Make sure that usesuper is always accessed through superuser(), so that the
single-user escape path always works.
This commit is contained in:
parent
a62f43ae6e
commit
25f050d90d
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user