mirror of
https://github.com/postgres/postgres.git
synced 2025-09-09 13:09:39 +03:00
Reserve the "pg_" namespace for roles
This will prevent users from creating roles which begin with "pg_" and will check for those roles before allowing an upgrade using pg_upgrade. This will allow for default roles to be provided at initdb time. Reviews by José Luis Tallón and Robert Haas
This commit is contained in:
@@ -747,6 +747,9 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
|
||||
{
|
||||
Oid newowner = get_rolespec_oid(stmt->newowner, false);
|
||||
|
||||
check_rolespec_name(stmt->newowner,
|
||||
"Cannot make reserved roles owners of objects.");
|
||||
|
||||
switch (stmt->objectType)
|
||||
{
|
||||
case OBJECT_DATABASE:
|
||||
|
@@ -1148,6 +1148,10 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
|
||||
else
|
||||
useId = get_rolespec_oid(stmt->user, false);
|
||||
|
||||
/* Additional check to protect reserved role names */
|
||||
check_rolespec_name(stmt->user,
|
||||
"Cannot specify reserved role as mapping user.");
|
||||
|
||||
/* Check that the server exists. */
|
||||
srv = GetForeignServerByName(stmt->servername, false);
|
||||
|
||||
@@ -1248,6 +1252,10 @@ AlterUserMapping(AlterUserMappingStmt *stmt)
|
||||
else
|
||||
useId = get_rolespec_oid(stmt->user, false);
|
||||
|
||||
/* Additional check to protect reserved role names */
|
||||
check_rolespec_name(stmt->user,
|
||||
"Cannot alter reserved role mapping user.");
|
||||
|
||||
srv = GetForeignServerByName(stmt->servername, false);
|
||||
|
||||
umId = GetSysCacheOid2(USERMAPPINGUSERSERVER,
|
||||
@@ -1337,6 +1345,11 @@ RemoveUserMapping(DropUserMappingStmt *stmt)
|
||||
else
|
||||
{
|
||||
useId = get_rolespec_oid(stmt->user, stmt->missing_ok);
|
||||
|
||||
/* Additional check to protect reserved role names */
|
||||
check_rolespec_name(stmt->user,
|
||||
"Cannot remove reserved role mapping user.");
|
||||
|
||||
if (!OidIsValid(useId))
|
||||
{
|
||||
/*
|
||||
|
@@ -176,8 +176,13 @@ policy_role_list_to_array(List *roles, int *num_roles)
|
||||
return role_oids;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Additional check to protect reserved role names */
|
||||
check_rolespec_name((Node *) spec,
|
||||
"Cannot specify reserved role as policy target");
|
||||
role_oids[i++] =
|
||||
ObjectIdGetDatum(get_rolespec_oid((Node *) spec, false));
|
||||
}
|
||||
}
|
||||
|
||||
return role_oids;
|
||||
|
@@ -65,6 +65,10 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
|
||||
else
|
||||
owner_uid = saved_uid;
|
||||
|
||||
/* Additional check to protect reserved role names */
|
||||
check_rolespec_name(stmt->authrole,
|
||||
"Cannot specify reserved role as owner.");
|
||||
|
||||
/* fill schema name with the user name if not specified */
|
||||
if (!schemaName)
|
||||
{
|
||||
|
@@ -3566,6 +3566,8 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
|
||||
(List *) cmd->def, lockmode);
|
||||
break;
|
||||
case AT_ChangeOwner: /* ALTER OWNER */
|
||||
check_rolespec_name(cmd->newowner,
|
||||
"Cannot specify reserved role as owner.");
|
||||
ATExecChangeOwner(RelationGetRelid(rel),
|
||||
get_rolespec_oid(cmd->newowner, false),
|
||||
false, lockmode);
|
||||
|
@@ -256,6 +256,10 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
|
||||
else
|
||||
ownerId = GetUserId();
|
||||
|
||||
/* Additional check to protect reserved role names */
|
||||
check_rolespec_name(stmt->owner,
|
||||
"Cannot specify reserved role as owner.");
|
||||
|
||||
/* Unix-ify the offered path, and strip any trailing slashes */
|
||||
location = pstrdup(stmt->location);
|
||||
canonicalize_path(location);
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include "access/htup_details.h"
|
||||
#include "access/xact.h"
|
||||
#include "catalog/binary_upgrade.h"
|
||||
#include "catalog/catalog.h"
|
||||
#include "catalog/dependency.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/objectaccess.h"
|
||||
@@ -311,6 +312,17 @@ CreateRole(CreateRoleStmt *stmt)
|
||||
errmsg("permission denied to create role")));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the user is not trying to create a role in the reserved
|
||||
* "pg_" namespace.
|
||||
*/
|
||||
if (IsReservedName(stmt->role))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_RESERVED_NAME),
|
||||
errmsg("role name \"%s\" is reserved",
|
||||
stmt->role),
|
||||
errdetail("Role names starting with \"pg_\" are reserved.")));
|
||||
|
||||
/*
|
||||
* Check the pg_authid relation to be certain the role doesn't already
|
||||
* exist.
|
||||
@@ -507,6 +519,9 @@ AlterRole(AlterRoleStmt *stmt)
|
||||
DefElem *dbypassRLS = NULL;
|
||||
Oid roleid;
|
||||
|
||||
check_rolespec_name(stmt->role,
|
||||
"Cannot alter reserved roles.");
|
||||
|
||||
/* Extract options from the statement node tree */
|
||||
foreach(option, stmt->options)
|
||||
{
|
||||
@@ -857,6 +872,9 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
|
||||
|
||||
if (stmt->role)
|
||||
{
|
||||
check_rolespec_name(stmt->role,
|
||||
"Cannot alter reserved roles.");
|
||||
|
||||
roletuple = get_rolespec_tuple(stmt->role);
|
||||
roleid = HeapTupleGetOid(roletuple);
|
||||
|
||||
@@ -1117,6 +1135,7 @@ RenameRole(const char *oldname, const char *newname)
|
||||
int i;
|
||||
Oid roleid;
|
||||
ObjectAddress address;
|
||||
Form_pg_authid authform;
|
||||
|
||||
rel = heap_open(AuthIdRelationId, RowExclusiveLock);
|
||||
dsc = RelationGetDescr(rel);
|
||||
@@ -1136,6 +1155,7 @@ RenameRole(const char *oldname, const char *newname)
|
||||
*/
|
||||
|
||||
roleid = HeapTupleGetOid(oldtuple);
|
||||
authform = (Form_pg_authid) GETSTRUCT(oldtuple);
|
||||
|
||||
if (roleid == GetSessionUserId())
|
||||
ereport(ERROR,
|
||||
@@ -1146,6 +1166,24 @@ RenameRole(const char *oldname, const char *newname)
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("current user cannot be renamed")));
|
||||
|
||||
/*
|
||||
* Check that the user is not trying to rename a system role and
|
||||
* not trying to rename a role into the reserved "pg_" namespace.
|
||||
*/
|
||||
if (IsReservedName(NameStr(authform->rolname)))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_RESERVED_NAME),
|
||||
errmsg("role name \"%s\" is reserved",
|
||||
NameStr(authform->rolname)),
|
||||
errdetail("Role names starting with \"pg_\" are reserved.")));
|
||||
|
||||
if (IsReservedName(newname))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_RESERVED_NAME),
|
||||
errmsg("role name \"%s\" is reserved",
|
||||
newname),
|
||||
errdetail("Role names starting with \"pg_\" are reserved.")));
|
||||
|
||||
/* make sure the new name doesn't exist */
|
||||
if (SearchSysCacheExists1(AUTHNAME, CStringGetDatum(newname)))
|
||||
ereport(ERROR,
|
||||
@@ -1224,10 +1262,18 @@ GrantRole(GrantRoleStmt *stmt)
|
||||
ListCell *item;
|
||||
|
||||
if (stmt->grantor)
|
||||
{
|
||||
check_rolespec_name(stmt->grantor,
|
||||
"Cannot specify reserved role as grantor.");
|
||||
grantor = get_rolespec_oid(stmt->grantor, false);
|
||||
}
|
||||
else
|
||||
grantor = GetUserId();
|
||||
|
||||
foreach(item, stmt->grantee_roles)
|
||||
check_rolespec_name(lfirst(item),
|
||||
"Cannot GRANT roles to a reserved role.");
|
||||
|
||||
grantee_ids = roleSpecsToIds(stmt->grantee_roles);
|
||||
|
||||
/* AccessShareLock is enough since we aren't modifying pg_authid */
|
||||
@@ -1318,6 +1364,9 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt)
|
||||
errmsg("permission denied to reassign objects")));
|
||||
}
|
||||
|
||||
check_rolespec_name(stmt->newrole,
|
||||
"Cannot specify reserved role as owner.");
|
||||
|
||||
/* Must have privileges on the receiving side too */
|
||||
newrole = get_rolespec_oid(stmt->newrole, false);
|
||||
|
||||
|
@@ -854,6 +854,9 @@ check_role(char **newval, void **extra, GucSource source)
|
||||
roleid = InvalidOid;
|
||||
is_superuser = false;
|
||||
}
|
||||
/* Do not allow setting role to a reserved role. */
|
||||
else if (strncmp(*newval, "pg_", 3) == 0)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
if (!IsTransactionState())
|
||||
|
Reference in New Issue
Block a user