From 22a2c4b576fe1423382e68b418d954208555ba34 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 6 May 2004 16:59:16 +0000 Subject: [PATCH] Erase MD5 user passwords when a user is renamed because the username is used as salt for the MD5 password. --- doc/src/sgml/ref/alter_user.sgml | 5 ++- src/backend/commands/user.c | 55 ++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/doc/src/sgml/ref/alter_user.sgml b/doc/src/sgml/ref/alter_user.sgml index 4af0888509..e74da13c87 100644 --- a/doc/src/sgml/ref/alter_user.sgml +++ b/doc/src/sgml/ref/alter_user.sgml @@ -1,5 +1,5 @@ @@ -57,6 +57,9 @@ ALTER USER name RESET The second variant changes the name of the user. Only a database superuser can rename user accounts. The session user cannot be renamed. (Connect as a different user if you need to do that.) + Because MD5-encrypted passwords use the username as + cryptographic salt, renaming a user clears their MD5 + password. diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index d646c8e14b..476e7e1865 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.139 2004/03/16 05:05:57 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.140 2004/05/06 16:59:16 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -959,8 +959,8 @@ AlterUserSet(AlterUserSetStmt *stmt) (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("user \"%s\" does not exist", stmt->user))); - if (!(superuser() - || ((Form_pg_shadow) GETSTRUCT(oldtuple))->usesysid == GetUserId())) + if (!(superuser() || + ((Form_pg_shadow) GETSTRUCT(oldtuple))->usesysid == GetUserId())) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied"))); @@ -1157,16 +1157,25 @@ DropUser(DropUserStmt *stmt) void RenameUser(const char *oldname, const char *newname) { - HeapTuple tup; + HeapTuple oldtuple, + newtuple; + TupleDesc dsc; Relation rel; - + Datum datum; + bool isnull; + Datum repl_val[Natts_pg_shadow]; + char repl_null[Natts_pg_shadow]; + char repl_repl[Natts_pg_shadow]; + int i; + /* ExclusiveLock because we need to update the password file */ rel = heap_openr(ShadowRelationName, ExclusiveLock); + dsc = RelationGetDescr(rel); - tup = SearchSysCacheCopy(SHADOWNAME, + oldtuple = SearchSysCache(SHADOWNAME, CStringGetDatum(oldname), 0, 0, 0); - if (!HeapTupleIsValid(tup)) + if (!HeapTupleIsValid(oldtuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("user \"%s\" does not exist", oldname))); @@ -1177,7 +1186,7 @@ RenameUser(const char *oldname, const char *newname) * not be an actual problem besides a little confusion, so think about * this and decide. */ - if (((Form_pg_shadow) GETSTRUCT(tup))->usesysid == GetSessionUserId()) + if (((Form_pg_shadow) GETSTRUCT(oldtuple))->usesysid == GetSessionUserId()) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("session user may not be renamed"))); @@ -1196,13 +1205,33 @@ RenameUser(const char *oldname, const char *newname) (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be superuser to rename users"))); - /* rename */ - namestrcpy(&(((Form_pg_shadow) GETSTRUCT(tup))->usename), newname); - simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); + for (i = 0; i < Natts_pg_shadow; i++) + repl_repl[i] = ' '; + repl_repl[Anum_pg_shadow_usename - 1] = 'r'; + repl_val[Anum_pg_shadow_usename - 1] = DirectFunctionCall1(namein, + CStringGetDatum(newname)); + repl_null[Anum_pg_shadow_usename - 1] = ' '; + + datum = heap_getattr(oldtuple, Anum_pg_shadow_passwd, dsc, &isnull); + + if (!isnull && isMD5(DatumGetCString(DirectFunctionCall1(textout, datum)))) + { + /* MD5 uses the username as salt, so just clear it on a rename */ + repl_repl[Anum_pg_shadow_passwd - 1] = 'r'; + repl_null[Anum_pg_shadow_passwd - 1] = 'n'; + + ereport(NOTICE, + (errmsg("MD5 password cleared because of user rename"))); + } + + newtuple = heap_modifytuple(oldtuple, rel, repl_val, repl_null, repl_repl); + simple_heap_update(rel, &oldtuple->t_self, newtuple); + + CatalogUpdateIndexes(rel, newtuple); + + ReleaseSysCache(oldtuple); heap_close(rel, NoLock); - heap_freetuple(tup); user_file_update_needed = true; }