From 25f050d90d818b88d57e24b4be42cff3244d3881 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 11 Apr 2002 05:32:03 +0000 Subject: [PATCH] Make sure that usesuper is always accessed through superuser(), so that the single-user escape path always works. --- src/backend/catalog/aclchk.c | 8 +++---- src/backend/commands/dbcommands.c | 38 ++++++++++-------------------- src/backend/utils/misc/superuser.c | 7 +++++- src/include/catalog/pg_shadow.h | 4 ++-- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 07f49c75ab..04f98449bd 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.62 2002/04/09 20:35:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.63 2002/04/11 05:32:02 petere Exp $ * * NOTES * See acl.h. @@ -734,9 +734,6 @@ pg_class_aclcheck(Oid table_oid, Oid userid, AclMode mode) /* * Validate userid, find out if he is superuser - * - * We do not use superuser_arg() here because we also need to check - * usecatupd. */ tuple = SearchSysCache(SHADOWSYSID, ObjectIdGetDatum(userid), @@ -744,11 +741,12 @@ pg_class_aclcheck(Oid table_oid, Oid userid, AclMode mode) if (!HeapTupleIsValid(tuple)) elog(ERROR, "pg_class_aclcheck: invalid user id %u", userid); - usesuper = ((Form_pg_shadow) GETSTRUCT(tuple))->usesuper; usecatupd = ((Form_pg_shadow) GETSTRUCT(tuple))->usecatupd; ReleaseSysCache(tuple); + usesuper = superuser_arg(userid); + /* * Now get the relation's tuple from pg_class */ diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 9d40d6a11e..a6072be07a 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.85 2002/03/06 06:09:32 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.86 2002/04/11 05:32:03 petere Exp $ * *------------------------------------------------------------------------- */ @@ -49,7 +49,7 @@ static bool get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, int *encodingP, bool *dbIsTemplateP, Oid *dbLastSysOidP, TransactionId *dbVacuumXidP, TransactionId *dbFrozenXidP, char *dbpath); -static bool get_user_info(Oid use_sysid, bool *use_super, bool *use_createdb); +static bool have_createdb_privilege(void); static char *resolve_alt_dbpath(const char *dbpath, Oid dboid); static bool remove_dbdirs(const char *real_loc, const char *altloc); @@ -67,8 +67,6 @@ createdb(const char *dbname, const char *dbowner, char *target_dir; char src_loc[MAXPGPATH]; char buf[2 * MAXPGPATH + 100]; - bool use_super, - use_createdb; Oid src_dboid; int4 src_owner; int src_encoding; @@ -91,21 +89,17 @@ createdb(const char *dbname, const char *dbowner, else datdba = GetUserId(); - /* check permission to create database */ - if (!get_user_info(GetUserId(), &use_super, &use_createdb)) - elog(ERROR, "current user name is invalid"); - if (datdba == (int32) GetUserId()) { /* creating database for self: can be superuser or createdb */ - if (!use_createdb && !use_super) + if (!superuser() && !have_createdb_privilege()) elog(ERROR, "CREATE DATABASE: permission denied"); } else { /* creating database for someone else: must be superuser */ /* note that the someone else need not have any permissions */ - if (!use_super) + if (!superuser()) elog(ERROR, "CREATE DATABASE: permission denied"); } @@ -143,7 +137,7 @@ createdb(const char *dbname, const char *dbowner, */ if (!src_istemplate) { - if (!use_super && GetUserId() != src_owner) + if (!superuser() && GetUserId() != src_owner ) elog(ERROR, "CREATE DATABASE: permission to copy \"%s\" denied", dbtemplate); } @@ -332,7 +326,6 @@ dropdb(const char *dbname) { int4 db_owner; bool db_istemplate; - bool use_super; Oid db_id; char *alt_loc; char *nominal_loc; @@ -350,9 +343,6 @@ dropdb(const char *dbname) if (IsTransactionBlock()) elog(ERROR, "DROP DATABASE: may not be called in a transaction block"); - if (!get_user_info(GetUserId(), &use_super, NULL)) - elog(ERROR, "current user name is invalid"); - /* * Obtain exclusive lock on pg_database. We need this to ensure that * no new backend starts up in the target database while we are @@ -368,7 +358,7 @@ dropdb(const char *dbname) &db_istemplate, NULL, NULL, NULL, dbpath)) elog(ERROR, "DROP DATABASE: database \"%s\" does not exist", dbname); - if (!use_super && GetUserId() != db_owner) + if (GetUserId() != db_owner && !superuser()) elog(ERROR, "DROP DATABASE: permission denied"); /* @@ -605,25 +595,23 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, } static bool -get_user_info(Oid use_sysid, bool *use_super, bool *use_createdb) +have_createdb_privilege(void) { HeapTuple utup; + bool retval; utup = SearchSysCache(SHADOWSYSID, - ObjectIdGetDatum(use_sysid), + ObjectIdGetDatum(GetUserId()), 0, 0, 0); if (!HeapTupleIsValid(utup)) - return false; - - if (use_super) - *use_super = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper; - if (use_createdb) - *use_createdb = ((Form_pg_shadow) GETSTRUCT(utup))->usecreatedb; + retval = true; + else + retval = ((Form_pg_shadow) GETSTRUCT(utup))->usecreatedb; ReleaseSysCache(utup); - return true; + return retval; } diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c index f677d64fd3..4a3f3de1c5 100644 --- a/src/backend/utils/misc/superuser.c +++ b/src/backend/utils/misc/superuser.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.20 2002/02/18 23:11:26 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.21 2002/04/11 05:32:03 petere Exp $ * *------------------------------------------------------------------------- */ @@ -27,6 +27,11 @@ /* * The Postgres user running this command has Postgres superuser privileges + * + * All code should use either of these two functions to find out + * whether a given user is a superuser, rather than evaluating + * pg_shadow.usesuper directly, so that the escape hatch built in for + * the single-user case works. */ bool superuser(void) diff --git a/src/include/catalog/pg_shadow.h b/src/include/catalog/pg_shadow.h index 2e8d5b771c..fd372ae7bf 100644 --- a/src/include/catalog/pg_shadow.h +++ b/src/include/catalog/pg_shadow.h @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_shadow.h,v 1.18 2002/03/01 22:45:17 petere Exp $ + * $Id: pg_shadow.h,v 1.19 2002/04/11 05:32:03 petere Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -35,7 +35,7 @@ CATALOG(pg_shadow) BOOTSTRAP BKI_WITHOUT_OIDS int4 usesysid; bool usecreatedb; bool usetrace; - bool usesuper; + bool usesuper; /* read this field via superuser() only */ bool usecatupd; text passwd; int4 valuntil;