mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
Adjust permissions checking for ALTER OWNER commands: instead of
requiring superuserness always, allow an owner to reassign ownership to any role he is a member of, if that role would have the right to create a similar object. These three requirements essentially state that the would-be alterer has enough privilege to DROP the existing object and then re-CREATE it as the new role; so we might as well let him do it in one step. The ALTER TABLESPACE case is a bit squirrely, but the whole concept of non-superuser tablespace owners is pretty dubious anyway. Stephen Frost, code review by Tom Lane.
This commit is contained in:
parent
bd15782164
commit
aa1110624c
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.27 2005/06/28 05:08:53 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.28 2005/07/14 21:46:29 tgl Exp $
|
||||||
*
|
*
|
||||||
* DESCRIPTION
|
* DESCRIPTION
|
||||||
* The "DefineFoo" routines take the parse tree and pick out the
|
* The "DefineFoo" routines take the parse tree and pick out the
|
||||||
@ -302,6 +302,7 @@ AlterAggregateOwner(List *name, TypeName *basetype, Oid newOwnerId)
|
|||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
Form_pg_proc procForm;
|
Form_pg_proc procForm;
|
||||||
Relation rel;
|
Relation rel;
|
||||||
|
AclResult aclresult;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if a basetype is passed in, then attempt to find an aggregate for
|
* if a basetype is passed in, then attempt to find an aggregate for
|
||||||
@ -331,11 +332,20 @@ AlterAggregateOwner(List *name, TypeName *basetype, Oid newOwnerId)
|
|||||||
*/
|
*/
|
||||||
if (procForm->proowner != newOwnerId)
|
if (procForm->proowner != newOwnerId)
|
||||||
{
|
{
|
||||||
/* Otherwise, must be superuser to change object ownership */
|
/* Otherwise, must be owner of the existing object */
|
||||||
if (!superuser())
|
if (!pg_proc_ownercheck(procOid, GetUserId()))
|
||||||
ereport(ERROR,
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
NameListToString(name));
|
||||||
errmsg("must be superuser to change owner")));
|
|
||||||
|
/* Must be able to become new owner */
|
||||||
|
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||||
|
|
||||||
|
/* New owner must have CREATE privilege on namespace */
|
||||||
|
aclresult = pg_namespace_aclcheck(procForm->pronamespace, newOwnerId,
|
||||||
|
ACL_CREATE);
|
||||||
|
if (aclresult != ACLCHECK_OK)
|
||||||
|
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||||
|
get_namespace_name(procForm->pronamespace));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Modify the owner --- okay to scribble on tup because it's a
|
* Modify the owner --- okay to scribble on tup because it's a
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.20 2005/07/07 20:39:58 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.21 2005/07/14 21:46:29 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -152,8 +152,7 @@ RenameConversion(List *name, const char *newname)
|
|||||||
newname, get_namespace_name(namespaceOid))));
|
newname, get_namespace_name(namespaceOid))));
|
||||||
|
|
||||||
/* must be owner */
|
/* must be owner */
|
||||||
if (!superuser() &&
|
if (!pg_conversion_ownercheck(conversionOid,GetUserId()))
|
||||||
((Form_pg_conversion) GETSTRUCT(tup))->conowner != GetUserId())
|
|
||||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
|
||||||
NameListToString(name));
|
NameListToString(name));
|
||||||
|
|
||||||
@ -182,6 +181,7 @@ AlterConversionOwner(List *name, Oid newOwnerId)
|
|||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
Relation rel;
|
Relation rel;
|
||||||
Form_pg_conversion convForm;
|
Form_pg_conversion convForm;
|
||||||
|
AclResult aclresult;
|
||||||
|
|
||||||
rel = heap_open(ConversionRelationId, RowExclusiveLock);
|
rel = heap_open(ConversionRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
@ -206,11 +206,20 @@ AlterConversionOwner(List *name, Oid newOwnerId)
|
|||||||
*/
|
*/
|
||||||
if (convForm->conowner != newOwnerId)
|
if (convForm->conowner != newOwnerId)
|
||||||
{
|
{
|
||||||
/* Otherwise, must be superuser to change object ownership */
|
/* Otherwise, must be owner of the existing object */
|
||||||
if (!superuser())
|
if (!pg_conversion_ownercheck(HeapTupleGetOid(tup),GetUserId()))
|
||||||
ereport(ERROR,
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
NameListToString(name));
|
||||||
errmsg("must be superuser to change owner")));
|
|
||||||
|
/* Must be able to become new owner */
|
||||||
|
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||||
|
|
||||||
|
/* New owner must have CREATE privilege on namespace */
|
||||||
|
aclresult = pg_namespace_aclcheck(convForm->connamespace, newOwnerId,
|
||||||
|
ACL_CREATE);
|
||||||
|
if (aclresult != ACLCHECK_OK)
|
||||||
|
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||||
|
get_namespace_name(convForm->connamespace));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Modify the owner --- okay to scribble on tup because it's a
|
* Modify the owner --- okay to scribble on tup because it's a
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.166 2005/07/08 04:12:24 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.167 2005/07/14 21:46:29 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -193,23 +193,19 @@ createdb(const CreatedbStmt *stmt)
|
|||||||
else
|
else
|
||||||
datdba = GetUserId();
|
datdba = GetUserId();
|
||||||
|
|
||||||
if (is_member_of_role(GetUserId(), datdba))
|
/*
|
||||||
{
|
* To create a database, must have createdb privilege and must be able
|
||||||
/* creating database for self: createdb is required */
|
* to become the target role (this does not imply that the target role
|
||||||
|
* itself must have createdb privilege). The latter provision guards
|
||||||
|
* against "giveaway" attacks. Note that a superuser will always have
|
||||||
|
* both of these privileges a fortiori.
|
||||||
|
*/
|
||||||
if (!have_createdb_privilege())
|
if (!have_createdb_privilege())
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||||
errmsg("permission denied to create database")));
|
errmsg("permission denied to create database")));
|
||||||
}
|
|
||||||
else
|
check_is_member_of_role(GetUserId(), datdba);
|
||||||
{
|
|
||||||
/* creating database for someone else: must be superuser */
|
|
||||||
/* note that the someone else need not have any permissions */
|
|
||||||
if (!superuser())
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
|
||||||
errmsg("must be superuser to create database for another user")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for db name conflict. There is a race condition here, since
|
* Check for db name conflict. There is a race condition here, since
|
||||||
@ -930,11 +926,26 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId)
|
|||||||
bool isNull;
|
bool isNull;
|
||||||
HeapTuple newtuple;
|
HeapTuple newtuple;
|
||||||
|
|
||||||
/* must be superuser to change ownership */
|
/* Otherwise, must be owner of the existing object */
|
||||||
if (!superuser())
|
if (!pg_database_ownercheck(HeapTupleGetOid(tuple),GetUserId()))
|
||||||
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
|
||||||
|
dbname);
|
||||||
|
|
||||||
|
/* Must be able to become new owner */
|
||||||
|
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* must have createdb rights
|
||||||
|
*
|
||||||
|
* NOTE: This is different from other alter-owner checks in
|
||||||
|
* that the current user is checked for createdb privileges
|
||||||
|
* instead of the destination owner. This is consistent
|
||||||
|
* with the CREATE case for databases.
|
||||||
|
*/
|
||||||
|
if (!have_createdb_privilege())
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||||
errmsg("must be superuser to change owner")));
|
errmsg("permission denied to change owner of database")));
|
||||||
|
|
||||||
memset(repl_null, ' ', sizeof(repl_null));
|
memset(repl_null, ' ', sizeof(repl_null));
|
||||||
memset(repl_repl, ' ', sizeof(repl_repl));
|
memset(repl_repl, ' ', sizeof(repl_repl));
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.63 2005/07/07 20:39:58 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.64 2005/07/14 21:46:29 tgl Exp $
|
||||||
*
|
*
|
||||||
* DESCRIPTION
|
* DESCRIPTION
|
||||||
* These routines take the parse tree and pick out the
|
* These routines take the parse tree and pick out the
|
||||||
@ -859,6 +859,7 @@ AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
|
|||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
Form_pg_proc procForm;
|
Form_pg_proc procForm;
|
||||||
Relation rel;
|
Relation rel;
|
||||||
|
AclResult aclresult;
|
||||||
|
|
||||||
rel = heap_open(ProcedureRelationId, RowExclusiveLock);
|
rel = heap_open(ProcedureRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
@ -892,11 +893,20 @@ AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
|
|||||||
bool isNull;
|
bool isNull;
|
||||||
HeapTuple newtuple;
|
HeapTuple newtuple;
|
||||||
|
|
||||||
/* Otherwise, must be superuser to change object ownership */
|
/* Otherwise, must be owner of the existing object */
|
||||||
if (!superuser())
|
if (!pg_proc_ownercheck(procOid,GetUserId()))
|
||||||
ereport(ERROR,
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
NameListToString(name));
|
||||||
errmsg("must be superuser to change owner")));
|
|
||||||
|
/* Must be able to become new owner */
|
||||||
|
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||||
|
|
||||||
|
/* New owner must have CREATE privilege on namespace */
|
||||||
|
aclresult = pg_namespace_aclcheck(procForm->pronamespace, newOwnerId,
|
||||||
|
ACL_CREATE);
|
||||||
|
if (aclresult != ACLCHECK_OK)
|
||||||
|
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||||
|
get_namespace_name(procForm->pronamespace));
|
||||||
|
|
||||||
memset(repl_null, ' ', sizeof(repl_null));
|
memset(repl_null, ' ', sizeof(repl_null));
|
||||||
memset(repl_repl, ' ', sizeof(repl_repl));
|
memset(repl_repl, ' ', sizeof(repl_repl));
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.34 2005/07/07 20:39:58 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.35 2005/07/14 21:46:29 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -892,6 +892,7 @@ AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
|
|||||||
char *opcname;
|
char *opcname;
|
||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
Relation rel;
|
Relation rel;
|
||||||
|
AclResult aclresult;
|
||||||
Form_pg_opclass opcForm;
|
Form_pg_opclass opcForm;
|
||||||
|
|
||||||
amOid = GetSysCacheOid(AMNAME,
|
amOid = GetSysCacheOid(AMNAME,
|
||||||
@ -950,11 +951,20 @@ AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
|
|||||||
*/
|
*/
|
||||||
if (opcForm->opcowner != newOwnerId)
|
if (opcForm->opcowner != newOwnerId)
|
||||||
{
|
{
|
||||||
/* Otherwise, must be superuser to change object ownership */
|
/* Otherwise, must be owner of the existing object */
|
||||||
if (!superuser())
|
if (!pg_opclass_ownercheck(HeapTupleGetOid(tup),GetUserId()))
|
||||||
ereport(ERROR,
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
NameListToString(name));
|
||||||
errmsg("must be superuser to change owner")));
|
|
||||||
|
/* Must be able to become new owner */
|
||||||
|
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||||
|
|
||||||
|
/* New owner must have CREATE privilege on namespace */
|
||||||
|
aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
|
||||||
|
ACL_CREATE);
|
||||||
|
if (aclresult != ACLCHECK_OK)
|
||||||
|
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||||
|
get_namespace_name(namespaceOid));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Modify the owner --- okay to scribble on tup because it's a
|
* Modify the owner --- okay to scribble on tup because it's a
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.23 2005/07/07 20:39:58 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.24 2005/07/14 21:46:29 tgl Exp $
|
||||||
*
|
*
|
||||||
* DESCRIPTION
|
* DESCRIPTION
|
||||||
* The "DefineFoo" routines take the parse tree and pick out the
|
* The "DefineFoo" routines take the parse tree and pick out the
|
||||||
@ -274,6 +274,7 @@ AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
|
|||||||
Oid operOid;
|
Oid operOid;
|
||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
Relation rel;
|
Relation rel;
|
||||||
|
AclResult aclresult;
|
||||||
Form_pg_operator oprForm;
|
Form_pg_operator oprForm;
|
||||||
|
|
||||||
rel = heap_open(OperatorRelationId, RowExclusiveLock);
|
rel = heap_open(OperatorRelationId, RowExclusiveLock);
|
||||||
@ -295,11 +296,20 @@ AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
|
|||||||
*/
|
*/
|
||||||
if (oprForm->oprowner != newOwnerId)
|
if (oprForm->oprowner != newOwnerId)
|
||||||
{
|
{
|
||||||
/* Otherwise, must be superuser to change object ownership */
|
/* Otherwise, must be owner of the existing object */
|
||||||
if (!superuser())
|
if (!pg_oper_ownercheck(operOid,GetUserId()))
|
||||||
ereport(ERROR,
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
NameListToString(name));
|
||||||
errmsg("must be superuser to change owner")));
|
|
||||||
|
/* Must be able to become new owner */
|
||||||
|
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||||
|
|
||||||
|
/* New owner must have CREATE privilege on namespace */
|
||||||
|
aclresult = pg_namespace_aclcheck(oprForm->oprnamespace, newOwnerId,
|
||||||
|
ACL_CREATE);
|
||||||
|
if (aclresult != ACLCHECK_OK)
|
||||||
|
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||||
|
get_namespace_name(oprForm->oprnamespace));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Modify the owner --- okay to scribble on tup because it's a
|
* Modify the owner --- okay to scribble on tup because it's a
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.32 2005/07/07 20:39:58 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.33 2005/07/14 21:46:29 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -49,54 +49,45 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
|
|||||||
saved_uid = GetUserId();
|
saved_uid = GetUserId();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Figure out user identities.
|
* Who is supposed to own the new schema?
|
||||||
*/
|
*/
|
||||||
|
if (authId)
|
||||||
if (!authId)
|
|
||||||
{
|
|
||||||
owner_uid = saved_uid;
|
|
||||||
}
|
|
||||||
else if (superuser())
|
|
||||||
{
|
|
||||||
owner_uid = get_roleid_checked(authId);
|
owner_uid = get_roleid_checked(authId);
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the current user to the requested authorization so that
|
|
||||||
* objects created in the statement have the requested owner.
|
|
||||||
* (This will revert to session user on error or at the end of
|
|
||||||
* this routine.)
|
|
||||||
*/
|
|
||||||
SetUserId(owner_uid);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
const char *owner_name;
|
|
||||||
|
|
||||||
/* not superuser */
|
|
||||||
owner_uid = saved_uid;
|
owner_uid = saved_uid;
|
||||||
owner_name = GetUserNameFromId(owner_uid);
|
|
||||||
if (strcmp(authId, owner_name) != 0)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
|
||||||
errmsg("permission denied"),
|
|
||||||
errdetail("\"%s\" is not a superuser, so cannot create a schema for \"%s\"",
|
|
||||||
owner_name, authId)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Permissions checks.
|
* To create a schema, must have schema-create privilege on the current
|
||||||
|
* database and must be able to become the target role (this does not
|
||||||
|
* imply that the target role itself must have create-schema privilege).
|
||||||
|
* The latter provision guards against "giveaway" attacks. Note that
|
||||||
|
* a superuser will always have both of these privileges a fortiori.
|
||||||
*/
|
*/
|
||||||
aclresult = pg_database_aclcheck(MyDatabaseId, saved_uid, ACL_CREATE);
|
aclresult = pg_database_aclcheck(MyDatabaseId, saved_uid, ACL_CREATE);
|
||||||
if (aclresult != ACLCHECK_OK)
|
if (aclresult != ACLCHECK_OK)
|
||||||
aclcheck_error(aclresult, ACL_KIND_DATABASE,
|
aclcheck_error(aclresult, ACL_KIND_DATABASE,
|
||||||
get_database_name(MyDatabaseId));
|
get_database_name(MyDatabaseId));
|
||||||
|
|
||||||
|
check_is_member_of_role(saved_uid, owner_uid);
|
||||||
|
|
||||||
|
/* Additional check to protect reserved schema names */
|
||||||
if (!allowSystemTableMods && IsReservedName(schemaName))
|
if (!allowSystemTableMods && IsReservedName(schemaName))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_RESERVED_NAME),
|
(errcode(ERRCODE_RESERVED_NAME),
|
||||||
errmsg("unacceptable schema name \"%s\"", schemaName),
|
errmsg("unacceptable schema name \"%s\"", schemaName),
|
||||||
errdetail("The prefix \"pg_\" is reserved for system schemas.")));
|
errdetail("The prefix \"pg_\" is reserved for system schemas.")));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the requested authorization is different from the current user,
|
||||||
|
* temporarily set the current user so that the object(s) will be
|
||||||
|
* created with the correct ownership.
|
||||||
|
*
|
||||||
|
* (The setting will revert to session user on error or at the end of
|
||||||
|
* this routine.)
|
||||||
|
*/
|
||||||
|
if (saved_uid != owner_uid)
|
||||||
|
SetUserId(owner_uid);
|
||||||
|
|
||||||
/* Create the schema's namespace */
|
/* Create the schema's namespace */
|
||||||
namespaceId = NamespaceCreate(schemaName, owner_uid);
|
namespaceId = NamespaceCreate(schemaName, owner_uid);
|
||||||
|
|
||||||
@ -308,12 +299,29 @@ AlterSchemaOwner(const char *name, Oid newOwnerId)
|
|||||||
Datum aclDatum;
|
Datum aclDatum;
|
||||||
bool isNull;
|
bool isNull;
|
||||||
HeapTuple newtuple;
|
HeapTuple newtuple;
|
||||||
|
AclResult aclresult;
|
||||||
|
|
||||||
/* Otherwise, must be superuser to change object ownership */
|
/* Otherwise, must be owner of the existing object */
|
||||||
if (!superuser())
|
if (!pg_namespace_ownercheck(HeapTupleGetOid(tup),GetUserId()))
|
||||||
ereport(ERROR,
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
name);
|
||||||
errmsg("must be superuser to change owner")));
|
|
||||||
|
/* Must be able to become new owner */
|
||||||
|
check_is_member_of_role(GetUserId(),newOwnerId);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* must have create-schema rights
|
||||||
|
*
|
||||||
|
* NOTE: This is different from other alter-owner checks in
|
||||||
|
* that the current user is checked for create privileges
|
||||||
|
* instead of the destination owner. This is consistent
|
||||||
|
* with the CREATE case for schemas.
|
||||||
|
*/
|
||||||
|
aclresult = pg_database_aclcheck(MyDatabaseId, GetUserId(),
|
||||||
|
ACL_CREATE);
|
||||||
|
if (aclresult != ACLCHECK_OK)
|
||||||
|
aclcheck_error(aclresult, ACL_KIND_DATABASE,
|
||||||
|
get_database_name(MyDatabaseId));
|
||||||
|
|
||||||
memset(repl_null, ' ', sizeof(repl_null));
|
memset(repl_null, ' ', sizeof(repl_null));
|
||||||
memset(repl_repl, ' ', sizeof(repl_repl));
|
memset(repl_repl, ' ', sizeof(repl_repl));
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.163 2005/07/07 20:39:58 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.164 2005/07/14 21:46:29 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -5286,12 +5286,23 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
|
|||||||
Datum aclDatum;
|
Datum aclDatum;
|
||||||
bool isNull;
|
bool isNull;
|
||||||
HeapTuple newtuple;
|
HeapTuple newtuple;
|
||||||
|
Oid namespaceOid = tuple_class->relnamespace;
|
||||||
|
AclResult aclresult;
|
||||||
|
|
||||||
/* Otherwise, check that we are the superuser */
|
/* Otherwise, must be owner of the existing object */
|
||||||
if (!superuser())
|
if (!pg_class_ownercheck(relationOid,GetUserId()))
|
||||||
ereport(ERROR,
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
RelationGetRelationName(target_rel));
|
||||||
errmsg("must be superuser to change owner")));
|
|
||||||
|
/* Must be able to become new owner */
|
||||||
|
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||||
|
|
||||||
|
/* New owner must have CREATE privilege on namespace */
|
||||||
|
aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
|
||||||
|
ACL_CREATE);
|
||||||
|
if (aclresult != ACLCHECK_OK)
|
||||||
|
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||||
|
get_namespace_name(namespaceOid));
|
||||||
|
|
||||||
memset(repl_null, ' ', sizeof(repl_null));
|
memset(repl_null, ' ', sizeof(repl_null));
|
||||||
memset(repl_repl, ' ', sizeof(repl_repl));
|
memset(repl_repl, ' ', sizeof(repl_repl));
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.25 2005/07/07 20:39:58 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.26 2005/07/14 21:46:29 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -788,11 +788,23 @@ AlterTableSpaceOwner(const char *name, Oid newOwnerId)
|
|||||||
bool isNull;
|
bool isNull;
|
||||||
HeapTuple newtuple;
|
HeapTuple newtuple;
|
||||||
|
|
||||||
/* Otherwise, must be superuser to change object ownership */
|
/* Otherwise, must be owner of the existing object */
|
||||||
if (!superuser())
|
if (!pg_tablespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
|
||||||
ereport(ERROR,
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
name);
|
||||||
errmsg("must be superuser to change owner")));
|
|
||||||
|
/* Must be able to become new owner */
|
||||||
|
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normally we would also check for create permissions here,
|
||||||
|
* but there are none for tablespaces so we follow what rename
|
||||||
|
* tablespace does and omit the create permissions check.
|
||||||
|
*
|
||||||
|
* NOTE: Only superusers may create tablespaces to begin with and
|
||||||
|
* so initially only a superuser would be able to change its
|
||||||
|
* ownership anyway.
|
||||||
|
*/
|
||||||
|
|
||||||
memset(repl_null, ' ', sizeof(repl_null));
|
memset(repl_null, ' ', sizeof(repl_null));
|
||||||
memset(repl_repl, ' ', sizeof(repl_repl));
|
memset(repl_repl, ' ', sizeof(repl_repl));
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.75 2005/07/10 21:13:58 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.76 2005/07/14 21:46:29 tgl Exp $
|
||||||
*
|
*
|
||||||
* DESCRIPTION
|
* DESCRIPTION
|
||||||
* The "DefineFoo" routines take the parse tree and pick out the
|
* The "DefineFoo" routines take the parse tree and pick out the
|
||||||
@ -2025,6 +2025,7 @@ AlterTypeOwner(List *names, Oid newOwnerId)
|
|||||||
Relation rel;
|
Relation rel;
|
||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
Form_pg_type typTup;
|
Form_pg_type typTup;
|
||||||
|
AclResult aclresult;
|
||||||
|
|
||||||
/* Make a TypeName so we can use standard type lookup machinery */
|
/* Make a TypeName so we can use standard type lookup machinery */
|
||||||
typename = makeNode(TypeName);
|
typename = makeNode(TypeName);
|
||||||
@ -2067,11 +2068,20 @@ AlterTypeOwner(List *names, Oid newOwnerId)
|
|||||||
*/
|
*/
|
||||||
if (typTup->typowner != newOwnerId)
|
if (typTup->typowner != newOwnerId)
|
||||||
{
|
{
|
||||||
/* Otherwise, must be superuser to change object ownership */
|
/* Otherwise, must be owner of the existing object */
|
||||||
if (!superuser())
|
if (!pg_type_ownercheck(HeapTupleGetOid(tup),GetUserId()))
|
||||||
ereport(ERROR,
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
TypeNameToString(typename));
|
||||||
errmsg("must be superuser to change owner")));
|
|
||||||
|
/* Must be able to become new owner */
|
||||||
|
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||||
|
|
||||||
|
/* New owner must have CREATE privilege on namespace */
|
||||||
|
aclresult = pg_namespace_aclcheck(typTup->typnamespace, newOwnerId,
|
||||||
|
ACL_CREATE);
|
||||||
|
if (aclresult != ACLCHECK_OK)
|
||||||
|
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||||
|
get_namespace_name(typTup->typnamespace));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Modify the owner --- okay to scribble on typTup because it's a
|
* Modify the owner --- okay to scribble on typTup because it's a
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.118 2005/07/07 20:39:58 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.119 2005/07/14 21:46:30 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -2541,6 +2541,10 @@ is_member_of_role(Oid member, Oid role)
|
|||||||
if (member == role)
|
if (member == role)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
/* Superusers have every privilege, so are part of every role */
|
||||||
|
if (superuser_arg(member))
|
||||||
|
return true;
|
||||||
|
|
||||||
/* If cache is already valid, just use the list */
|
/* If cache is already valid, just use the list */
|
||||||
if (OidIsValid(cached_role) && cached_role == member)
|
if (OidIsValid(cached_role) && cached_role == member)
|
||||||
return list_member_oid(cached_memberships, role);
|
return list_member_oid(cached_memberships, role);
|
||||||
@ -2604,6 +2608,20 @@ is_member_of_role(Oid member, Oid role)
|
|||||||
return list_member_oid(cached_memberships, role);
|
return list_member_oid(cached_memberships, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check_is_member_of_role
|
||||||
|
* is_member_of_role with a standard permission-violation error if not
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
check_is_member_of_role(Oid member, Oid role)
|
||||||
|
{
|
||||||
|
if (!is_member_of_role(member, role))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||||
|
errmsg("must be member of role \"%s\"",
|
||||||
|
GetUserNameFromId(role))));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is member an admin of role (directly or indirectly)? That is, is it
|
* Is member an admin of role (directly or indirectly)? That is, is it
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.81 2005/07/07 20:40:00 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.82 2005/07/14 21:46:30 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* An ACL array is simply an array of AclItems, representing the union
|
* An ACL array is simply an array of AclItems, representing the union
|
||||||
@ -212,6 +212,7 @@ extern int aclmembers(const Acl *acl, Oid **roleids);
|
|||||||
|
|
||||||
extern bool is_member_of_role(Oid member, Oid role);
|
extern bool is_member_of_role(Oid member, Oid role);
|
||||||
extern bool is_admin_of_role(Oid member, Oid role);
|
extern bool is_admin_of_role(Oid member, Oid role);
|
||||||
|
extern void check_is_member_of_role(Oid member, Oid role);
|
||||||
|
|
||||||
extern void initialize_acl(void);
|
extern void initialize_acl(void);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user