1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-07 00:36:50 +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:
Stephen Frost
2016-04-08 16:56:27 -04:00
parent fa6075e551
commit 293007898d
21 changed files with 226 additions and 13 deletions

View File

@ -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);