1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-14 18:42:34 +03:00

Improve several permission-related error messages.

Mainly move some detail from errmsg to errdetail, remove explicit
mention of superuser where appropriate, since that is implied in most
permission checks, and make messages more uniform.

Author: Nathan Bossart <nathandbossart@gmail.com>
Discussion: https://www.postgresql.org/message-id/20230316234701.GA903298@nathanxps13
This commit is contained in:
Peter Eisentraut
2023-03-17 10:14:16 +01:00
parent 39a3bdc9eb
commit de4d456b40
18 changed files with 282 additions and 109 deletions

View File

@ -491,7 +491,8 @@ ALTER FOREIGN TABLE agg_text OWNER TO regress_file_fdw_user;
ALTER FOREIGN TABLE agg_text OPTIONS (SET format 'text'); ALTER FOREIGN TABLE agg_text OPTIONS (SET format 'text');
SET ROLE regress_file_fdw_user; SET ROLE regress_file_fdw_user;
ALTER FOREIGN TABLE agg_text OPTIONS (SET format 'text'); ALTER FOREIGN TABLE agg_text OPTIONS (SET format 'text');
ERROR: only superuser or a role with privileges of the pg_read_server_files role may specify the filename option of a file_fdw foreign table ERROR: permission denied to set the "filename" option of a file_fdw foreign table
DETAIL: Only roles with privileges of the "pg_read_server_files" role may set this option.
SET ROLE regress_file_fdw_superuser; SET ROLE regress_file_fdw_superuser;
-- cleanup -- cleanup
RESET ROLE; RESET ROLE;

View File

@ -279,13 +279,19 @@ file_fdw_validator(PG_FUNCTION_ARGS)
!has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES)) !has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("only superuser or a role with privileges of the pg_read_server_files role may specify the filename option of a file_fdw foreign table"))); errmsg("permission denied to set the \"%s\" option of a file_fdw foreign table",
"filename"),
errdetail("Only roles with privileges of the \"%s\" role may set this option.",
"pg_read_server_files")));
if (strcmp(def->defname, "program") == 0 && if (strcmp(def->defname, "program") == 0 &&
!has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM)) !has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("only superuser or a role with privileges of the pg_execute_server_program role may specify the program option of a file_fdw foreign table"))); errmsg("permission denied to set the \"%s\" option of a file_fdw foreign table",
"program"),
errdetail("Only roles with privileges of the \"%s\" role may set this option.",
"pg_execute_server_program")));
filename = defGetString(def); filename = defGetString(def);
} }

View File

@ -54,13 +54,16 @@ RESET ROLE;
-- plain user *can't* can control replication -- plain user *can't* can control replication
SET ROLE regress_lr_normal; SET ROLE regress_lr_normal;
SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding'); SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
ERROR: must be superuser or replication role to use replication slots ERROR: permission denied to use replication slots
DETAIL: Only roles with the REPLICATION attribute may use replication slots.
INSERT INTO lr_test VALUES('lr_superuser_init'); INSERT INTO lr_test VALUES('lr_superuser_init');
ERROR: permission denied for table lr_test ERROR: permission denied for table lr_test
SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
ERROR: must be superuser or replication role to use replication slots ERROR: permission denied to use replication slots
DETAIL: Only roles with the REPLICATION attribute may use replication slots.
SELECT pg_drop_replication_slot('regression_slot'); SELECT pg_drop_replication_slot('regression_slot');
ERROR: must be superuser or replication role to use replication slots ERROR: permission denied to use replication slots
DETAIL: Only roles with the REPLICATION attribute may use replication slots.
RESET ROLE; RESET ROLE;
-- replication users can drop superuser created slots -- replication users can drop superuser created slots
SET ROLE regress_lr_superuser; SET ROLE regress_lr_superuser;
@ -90,7 +93,8 @@ SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_d
RESET ROLE; RESET ROLE;
SET ROLE regress_lr_normal; SET ROLE regress_lr_normal;
SELECT pg_drop_replication_slot('regression_slot'); SELECT pg_drop_replication_slot('regression_slot');
ERROR: must be superuser or replication role to use replication slots ERROR: permission denied to use replication slots
DETAIL: Only roles with the REPLICATION attribute may use replication slots.
RESET ROLE; RESET ROLE;
-- all users can see existing slots -- all users can see existing slots
SET ROLE regress_lr_superuser; SET ROLE regress_lr_superuser;

View File

@ -72,7 +72,9 @@ bbsink_server_new(bbsink *next, char *pathname)
if (!has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES)) if (!has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or a role with privileges of the pg_write_server_files role to create backup stored on server"))); errmsg("permission denied to create backup stored on server"),
errdetail("Only roles with privileges of the \"%s\" role may create a backup stored on the server.",
"pg_write_server_files")));
CommitTransactionCommand(); CommitTransactionCommand();
/* /*

View File

@ -2547,18 +2547,24 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
if (!superuser_arg(roleid)) if (!superuser_arg(roleid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser"))); errmsg("permission denied"),
errdetail("The current user must have the %s attribute.",
"SUPERUSER")));
} }
else else
{ {
if (!has_createrole_privilege(roleid)) if (!has_createrole_privilege(roleid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have CREATEROLE privilege"))); errmsg("permission denied"),
errdetail("The current user must have the %s attribute.",
"CREATEROLE")));
if (!is_admin_of_role(roleid, address.objectId)) if (!is_admin_of_role(roleid, address.objectId))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have admin option on role \"%s\"", errmsg("permission denied"),
errdetail("The current user must have the %s option on role \"%s\".",
"ADMIN",
GetUserNameFromId(address.objectId, GetUserNameFromId(address.objectId,
true)))); true))));
} }

View File

@ -83,7 +83,9 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
if (!has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM)) if (!has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or have privileges of the pg_execute_server_program role to COPY to or from an external program"), errmsg("permission denied to COPY to or from an external program"),
errdetail("Only roles with privileges of the \"%s\" role may COPY to or from an external program.",
"pg_execute_server_program"),
errhint("Anyone can COPY to stdout or from stdin. " errhint("Anyone can COPY to stdout or from stdin. "
"psql's \\copy command also works for anyone."))); "psql's \\copy command also works for anyone.")));
} }
@ -92,14 +94,18 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
if (is_from && !has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES)) if (is_from && !has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or have privileges of the pg_read_server_files role to COPY from a file"), errmsg("permission denied to COPY from a file"),
errdetail("Only roles with privileges of the \"%s\" role may COPY from a file.",
"pg_read_server_files"),
errhint("Anyone can COPY to stdout or from stdin. " errhint("Anyone can COPY to stdout or from stdin. "
"psql's \\copy command also works for anyone."))); "psql's \\copy command also works for anyone.")));
if (!is_from && !has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES)) if (!is_from && !has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or have privileges of the pg_write_server_files role to COPY to a file"), errmsg("permission denied to COPY to a file"),
errdetail("Only roles with privileges of the \"%s\" role may COPY to a file.",
"pg_write_server_files"),
errhint("Anyone can COPY to stdout or from stdin. " errhint("Anyone can COPY to stdout or from stdin. "
"psql's \\copy command also works for anyone."))); "psql's \\copy command also works for anyone.")));
} }

View File

@ -316,23 +316,33 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (!has_createrole_privilege(currentUserId)) if (!has_createrole_privilege(currentUserId))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to create role"))); errmsg("permission denied to create role"),
errdetail("Only roles with the %s attribute may create roles.",
"CREATEROLE")));
if (issuper) if (issuper)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to create superusers"))); errmsg("permission denied to create role"),
errdetail("Only roles with the %s attribute may create roles with %s.",
"SUPERUSER", "SUPERUSER")));
if (createdb && !have_createdb_privilege()) if (createdb && !have_createdb_privilege())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have createdb permission to create createdb users"))); errmsg("permission denied to create role"),
errdetail("Only roles with the %s attribute may create roles with %s.",
"CREATEDB", "CREATEDB")));
if (isreplication && !has_rolreplication(currentUserId)) if (isreplication && !has_rolreplication(currentUserId))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have replication permission to create replication users"))); errmsg("permission denied to create role"),
errdetail("Only roles with the %s attribute may create roles with %s.",
"REPLICATION", "REPLICATION")));
if (bypassrls && !has_bypassrls_privilege(currentUserId)) if (bypassrls && !has_bypassrls_privilege(currentUserId))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have bypassrls to create bypassrls users"))); errmsg("permission denied to create role"),
errdetail("Only roles with the %s attribute may create roles with %s.",
"BYPASSRLS", "BYPASSRLS")));
} }
/* /*
@ -744,10 +754,18 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
roleid = authform->oid; roleid = authform->oid;
/* To mess with a superuser in any way you gotta be superuser. */ /* To mess with a superuser in any way you gotta be superuser. */
if (!superuser() && (authform->rolsuper || dissuper)) if (!superuser() && authform->rolsuper)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to alter superuser roles or change superuser attribute"))); errmsg("permission denied to alter role"),
errdetail("Only roles with the %s attribute may alter roles with %s.",
"SUPERUSER", "SUPERUSER")));
if (!superuser() && dissuper)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to alter role"),
errdetail("Only roles with the %s attribute may change the %s attribute.",
"SUPERUSER", "SUPERUSER")));
/* /*
* Most changes to a role require that you both have CREATEROLE privileges * Most changes to a role require that you both have CREATEROLE privileges
@ -761,13 +779,17 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
dvalidUntil || disreplication || dbypassRLS) dvalidUntil || disreplication || dbypassRLS)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied"))); errmsg("permission denied to alter role"),
errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may alter this role.",
"CREATEROLE", "ADMIN", rolename)));
/* an unprivileged user can change their own password */ /* an unprivileged user can change their own password */
if (dpassword && roleid != currentUserId) if (dpassword && roleid != currentUserId)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have CREATEROLE privilege to change another user's password"))); errmsg("permission denied to alter role"),
errdetail("To change another role's password, the current user must have the %s attribute and the %s option on the role.",
"CREATEROLE", "ADMIN")));
} }
else if (!superuser()) else if (!superuser())
{ {
@ -779,23 +801,30 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
if (dcreatedb && !have_createdb_privilege()) if (dcreatedb && !have_createdb_privilege())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have createdb privilege to change createdb attribute"))); errmsg("permission denied to alter role"),
errdetail("Only roles with the %s attribute may change the %s attribute.",
"CREATEDB", "CREATEDB")));
if (disreplication && !has_rolreplication(currentUserId)) if (disreplication && !has_rolreplication(currentUserId))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have replication privilege to change replication attribute"))); errmsg("permission denied to alter role"),
errdetail("Only roles with the %s attribute may change the %s attribute.",
"REPLICATION", "REPLICATION")));
if (dbypassRLS && !has_bypassrls_privilege(currentUserId)) if (dbypassRLS && !has_bypassrls_privilege(currentUserId))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have bypassrls privilege to change bypassrls attribute"))); errmsg("permission denied to alter role"),
errdetail("Only roles with the %s attribute may change the %s attribute.",
"BYPASSRLS", "BYPASSRLS")));
} }
/* To add members to a role, you need ADMIN OPTION. */ /* To add members to a role, you need ADMIN OPTION. */
if (drolemembers && !is_admin_of_role(currentUserId, roleid)) if (drolemembers && !is_admin_of_role(currentUserId, roleid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have admin option on role \"%s\" to add members", errmsg("permission denied to alter role"),
rolename))); errdetail("Only roles with the %s option on role \"%s\" may add members.",
"ADMIN", rolename)));
/* Convert validuntil to internal form */ /* Convert validuntil to internal form */
if (dvalidUntil) if (dvalidUntil)
@ -837,8 +866,10 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
if (!should_be_super && roleid == BOOTSTRAP_SUPERUSERID) if (!should_be_super && roleid == BOOTSTRAP_SUPERUSERID)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("permission denied: bootstrap user must be superuser"))); errmsg("permission denied to alter role"),
errdetail("The bootstrap user must have the %s attribute.",
"SUPERUSER")));
new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(should_be_super); new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(should_be_super);
new_record_repl[Anum_pg_authid_rolsuper - 1] = true; new_record_repl[Anum_pg_authid_rolsuper - 1] = true;
@ -999,7 +1030,9 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
if (!superuser()) if (!superuser())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to alter superusers"))); errmsg("permission denied to alter role"),
errdetail("Only roles with the %s attribute may alter roles with %s.",
"SUPERUSER", "SUPERUSER")));
} }
else else
{ {
@ -1008,7 +1041,9 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
&& roleid != GetUserId()) && roleid != GetUserId())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied"))); errmsg("permission denied to alter role"),
errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may alter this role.",
"CREATROLE", "ADMIN", NameStr(roleform->rolname))));
} }
ReleaseSysCache(roletuple); ReleaseSysCache(roletuple);
@ -1038,7 +1073,9 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
if (!superuser()) if (!superuser())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to alter settings globally"))); errmsg("permission denied to alter setting"),
errdetail("Only roles with the %s attribute may alter settings globally.",
"SUPERUSER")));
} }
AlterSetting(databaseid, roleid, stmt->setstmt); AlterSetting(databaseid, roleid, stmt->setstmt);
@ -1061,7 +1098,9 @@ DropRole(DropRoleStmt *stmt)
if (!have_createrole_privilege()) if (!have_createrole_privilege())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to drop role"))); errmsg("permission denied to drop role"),
errdetail("Only roles with the %s attribute and the %s option on the target roles may drop roles.",
"CREATEROLE", "ADMIN")));
/* /*
* Scan the pg_authid relation to find the Oid of the role(s) to be * Scan the pg_authid relation to find the Oid of the role(s) to be
@ -1131,12 +1170,15 @@ DropRole(DropRoleStmt *stmt)
if (roleform->rolsuper && !superuser()) if (roleform->rolsuper && !superuser())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to drop superusers"))); errmsg("permission denied to drop role"),
errdetail("Only roles with the %s attribute may drop roles with %s.",
"SUPERUSER", "SUPERUSER")));
if (!is_admin_of_role(GetUserId(), roleid)) if (!is_admin_of_role(GetUserId(), roleid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have admin option on role \"%s\"", errmsg("permission denied to drop role"),
role))); errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may drop this role.",
"CREATEROLE", "ADMIN", NameStr(roleform->rolname))));
/* DROP hook for the role being removed */ /* DROP hook for the role being removed */
InvokeObjectDropHook(AuthIdRelationId, roleid, 0); InvokeObjectDropHook(AuthIdRelationId, roleid, 0);
@ -1383,7 +1425,9 @@ RenameRole(const char *oldname, const char *newname)
if (!superuser()) if (!superuser())
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to rename superusers"))); errmsg("permission denied to rename role"),
errdetail("Only roles with the %s attribute may rename roles with %s.",
"SUPERUSER", "SUPERUSER")));
} }
else else
{ {
@ -1391,7 +1435,9 @@ RenameRole(const char *oldname, const char *newname)
!is_admin_of_role(GetUserId(), roleid)) !is_admin_of_role(GetUserId(), roleid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to rename role"))); errmsg("permission denied to rename role"),
errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may rename this role.",
"CREATEROLE", "ADMIN", NameStr(authform->rolname))));
} }
/* OK, construct the modified tuple */ /* OK, construct the modified tuple */
@ -1554,7 +1600,9 @@ DropOwnedObjects(DropOwnedStmt *stmt)
if (!has_privs_of_role(GetUserId(), roleid)) if (!has_privs_of_role(GetUserId(), roleid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to drop objects"))); errmsg("permission denied to drop objects"),
errdetail("Only roles with privileges of role \"%s\" may drop objects owned by it.",
GetUserNameFromId(roleid, false))));
} }
/* Ok, do it */ /* Ok, do it */
@ -1581,7 +1629,9 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt)
if (!has_privs_of_role(GetUserId(), roleid)) if (!has_privs_of_role(GetUserId(), roleid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to reassign objects"))); errmsg("permission denied to reassign objects"),
errdetail("Only roles with privileges of role \"%s\" may reassign objects owned by it.",
GetUserNameFromId(roleid, false))));
} }
/* Must have privileges on the receiving side too */ /* Must have privileges on the receiving side too */
@ -1590,7 +1640,9 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt)
if (!has_privs_of_role(GetUserId(), newrole)) if (!has_privs_of_role(GetUserId(), newrole))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to reassign objects"))); errmsg("permission denied to reassign objects"),
errdetail("Only roles with privileges of role \"%s\" may reassign objects to it.",
GetUserNameFromId(newrole, false))));
/* Ok, do it */ /* Ok, do it */
shdepReassignOwned(role_ids, newrole); shdepReassignOwned(role_ids, newrole);
@ -1738,7 +1790,8 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
if (memberid == BOOTSTRAP_SUPERUSERID) if (memberid == BOOTSTRAP_SUPERUSERID)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION), (errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("admin option cannot be granted back to your own grantor"))); errmsg("%s option cannot be granted back to your own grantor",
"ADMIN")));
plan_member_revoke(memlist, actions, memberid); plan_member_revoke(memlist, actions, memberid);
} }
@ -1763,7 +1816,8 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
if (i >= memlist->n_members) if (i >= memlist->n_members)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION), (errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("admin option cannot be granted back to your own grantor"))); errmsg("%s option cannot be granted back to your own grantor",
"ADMIN")));
ReleaseSysCacheList(memlist); ReleaseSysCacheList(memlist);
} }
@ -2081,9 +2135,22 @@ check_role_membership_authorization(Oid currentUserId, Oid roleid,
if (superuser_arg(roleid)) if (superuser_arg(roleid))
{ {
if (!superuser_arg(currentUserId)) if (!superuser_arg(currentUserId))
{
if (is_grant)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to alter superusers"))); errmsg("permission denied to grant role \"%s\"",
GetUserNameFromId(roleid, false)),
errdetail("Only roles with the %s attribute may grant roles with %s.",
"SUPERUSER", "SUPERUSER")));
else
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to revoke role \"%s\"",
GetUserNameFromId(roleid, false)),
errdetail("Only roles with the %s attribute may revoke roles with %s.",
"SUPERUSER", "SUPERUSER")));
}
} }
else else
{ {
@ -2091,10 +2158,22 @@ check_role_membership_authorization(Oid currentUserId, Oid roleid,
* Otherwise, must have admin option on the role to be changed. * Otherwise, must have admin option on the role to be changed.
*/ */
if (!is_admin_of_role(currentUserId, roleid)) if (!is_admin_of_role(currentUserId, roleid))
{
if (is_grant)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have admin option on role \"%s\"", errmsg("permission denied to grant role \"%s\"",
GetUserNameFromId(roleid, false)))); GetUserNameFromId(roleid, false)),
errdetail("Only roles with the %s option on role \"%s\" may grant this role.",
"ADMIN", GetUserNameFromId(roleid, false))));
else
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to revoke role \"%s\"",
GetUserNameFromId(roleid, false)),
errdetail("Only roles with the %s option on role \"%s\" may revoke this role.",
"ADMIN", GetUserNameFromId(roleid, false))));
}
} }
} }
@ -2173,14 +2252,18 @@ check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId, bool is_grant)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to grant privileges as role \"%s\"", errmsg("permission denied to grant privileges as role \"%s\"",
GetUserNameFromId(grantorId, false)),
errdetail("Only roles with privileges of role \"%s\" may grant privileges as this role.",
GetUserNameFromId(grantorId, false)))); GetUserNameFromId(grantorId, false))));
if (grantorId != BOOTSTRAP_SUPERUSERID && if (grantorId != BOOTSTRAP_SUPERUSERID &&
select_best_admin(grantorId, roleid) != grantorId) select_best_admin(grantorId, roleid) != grantorId)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("grantor must have ADMIN OPTION on \"%s\"", errmsg("permission denied to grant privileges as role \"%s\"",
GetUserNameFromId(roleid, false)))); GetUserNameFromId(grantorId, false)),
errdetail("The grantor must have the %s option on role \"%s\".",
"ADMIN", GetUserNameFromId(roleid, false))));
} }
else else
{ {
@ -2188,6 +2271,8 @@ check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId, bool is_grant)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to revoke privileges granted by role \"%s\"", errmsg("permission denied to revoke privileges granted by role \"%s\"",
GetUserNameFromId(grantorId, false)),
errdetail("Only roles with privileges of role \"%s\" may revoke privileges granted by this role.",
GetUserNameFromId(grantorId, false)))); GetUserNameFromId(grantorId, false))));
} }

View File

@ -1143,7 +1143,9 @@ CheckSlotPermissions(void)
if (!has_rolreplication(GetUserId())) if (!has_rolreplication(GetUserId()))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or replication role to use replication slots"))); errmsg("permission denied to use replication slots"),
errdetail("Only roles with the %s attribute may use replication slots.",
"REPLICATION")));
} }
/* /*

View File

@ -3883,7 +3883,9 @@ TerminateOtherDBBackends(Oid databaseId)
!has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND)) !has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be a member of the role whose process is being terminated or member of pg_signal_backend"))); errmsg("permission denied to terminate process"),
errdetail("Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process.",
"pg_signal_backend")));
} }
} }

View File

@ -121,12 +121,16 @@ pg_cancel_backend(PG_FUNCTION_ARGS)
if (r == SIGNAL_BACKEND_NOSUPERUSER) if (r == SIGNAL_BACKEND_NOSUPERUSER)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be a superuser to cancel superuser query"))); errmsg("permission denied to cancel query"),
errdetail("Only roles with the %s attribute may cancel queries of roles with %s.",
"SUPERUSER", "SUPERUSER")));
if (r == SIGNAL_BACKEND_NOPERMISSION) if (r == SIGNAL_BACKEND_NOPERMISSION)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be a member of the role whose query is being canceled or member of pg_signal_backend"))); errmsg("permission denied to cancel query"),
errdetail("Only roles with privileges of the role whose query is being canceled or with privileges of the \"%s\" role may cancel this query.",
"pg_signal_backend")));
PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS); PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);
} }
@ -223,12 +227,16 @@ pg_terminate_backend(PG_FUNCTION_ARGS)
if (r == SIGNAL_BACKEND_NOSUPERUSER) if (r == SIGNAL_BACKEND_NOSUPERUSER)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be a superuser to terminate superuser process"))); errmsg("permission denied to terminate process"),
errdetail("Only roles with the %s attribute may terminate processes of roles with %s.",
"SUPERUSER", "SUPERUSER")));
if (r == SIGNAL_BACKEND_NOPERMISSION) if (r == SIGNAL_BACKEND_NOPERMISSION)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be a member of the role whose process is being terminated or member of pg_signal_backend"))); errmsg("permission denied to terminate process"),
errdetail("Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process.",
"pg_signal_backend")));
/* Wait only on success and if actually requested */ /* Wait only on success and if actually requested */
if (r == SIGNAL_BACKEND_SUCCESS && timeout > 0) if (r == SIGNAL_BACKEND_SUCCESS && timeout > 0)

View File

@ -950,7 +950,10 @@ standard_ProcessUtility(PlannedStmt *pstmt,
if (!has_privs_of_role(GetUserId(), ROLE_PG_CHECKPOINT)) if (!has_privs_of_role(GetUserId(), ROLE_PG_CHECKPOINT))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or have privileges of pg_checkpoint to do CHECKPOINT"))); errmsg("permission denied to execute %s command",
"CHECKPOINT"),
errdetail("Only roles with privileges of the \"%s\" role may execute this command.",
"pg_checkpoint")));
RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_WAIT | RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_WAIT |
(RecoveryInProgress() ? 0 : CHECKPOINT_FORCE)); (RecoveryInProgress() ? 0 : CHECKPOINT_FORCE));

View File

@ -949,12 +949,14 @@ InitPostgres(const char *in_dbname, Oid dboid,
if (nfree < SuperuserReservedConnections) if (nfree < SuperuserReservedConnections)
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_TOO_MANY_CONNECTIONS), (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
errmsg("remaining connection slots are reserved for superusers"))); errmsg("remaining connection slots are reserved for roles with %s",
"SUPERUSER")));
if (!has_privs_of_role(GetUserId(), ROLE_PG_USE_RESERVED_CONNECTIONS)) if (!has_privs_of_role(GetUserId(), ROLE_PG_USE_RESERVED_CONNECTIONS))
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_TOO_MANY_CONNECTIONS), (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
errmsg("remaining connection slots are reserved for roles with privileges of pg_use_reserved_connections"))); errmsg("remaining connection slots are reserved for roles with privileges of the \"%s\" role",
"pg_use_reserved_connections")));
} }
/* Check replication permissions needed for walsender processes. */ /* Check replication permissions needed for walsender processes. */
@ -965,7 +967,9 @@ InitPostgres(const char *in_dbname, Oid dboid,
if (!has_rolreplication(GetUserId())) if (!has_rolreplication(GetUserId()))
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or replication role to start walsender"))); errmsg("permission denied to start WAL sender"),
errdetail("Only roles with the %s attribute may start a WAL sender process.",
"REPLICATION")));
} }
/* /*

View File

@ -4209,8 +4209,9 @@ GetConfigOption(const char *name, bool missing_ok, bool restrict_privileged)
!ConfigOptionIsVisible(record)) !ConfigOptionIsVisible(record))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or have privileges of pg_read_all_settings to examine \"%s\"", errmsg("permission denied to examine \"%s\"", name),
name))); errdetail("Only roles with privileges of the \"%s\" role may examine this parameter.",
"pg_read_all_settings")));
switch (record->vartype) switch (record->vartype)
{ {
@ -4255,8 +4256,9 @@ GetConfigOptionResetString(const char *name)
if (!ConfigOptionIsVisible(record)) if (!ConfigOptionIsVisible(record))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or have privileges of pg_read_all_settings to examine \"%s\"", errmsg("permission denied to examine \"%s\"", name),
name))); errdetail("Only roles with privileges of the \"%s\" role may examine this parameter.",
"pg_read_all_settings")));
switch (record->vartype) switch (record->vartype)
{ {
@ -5261,8 +5263,9 @@ GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
if (!ConfigOptionIsVisible(record)) if (!ConfigOptionIsVisible(record))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or have privileges of pg_read_all_settings to examine \"%s\"", errmsg("permission denied to examine \"%s\"", name),
name))); errdetail("Only roles with privileges of the \"%s\" role may examine this parameter.",
"pg_read_all_settings")));
if (varname) if (varname)
*varname = record->name; *varname = record->name;

View File

@ -59,7 +59,8 @@ SECURITY LABEL ON ROLE regress_dummy_seclabel_user4 IS 'unclassified'; -- fail (
ERROR: role "regress_dummy_seclabel_user4" does not exist ERROR: role "regress_dummy_seclabel_user4" does not exist
SET SESSION AUTHORIZATION regress_dummy_seclabel_user2; SET SESSION AUTHORIZATION regress_dummy_seclabel_user2;
SECURITY LABEL ON ROLE regress_dummy_seclabel_user2 IS 'unclassified'; -- fail (not privileged) SECURITY LABEL ON ROLE regress_dummy_seclabel_user2 IS 'unclassified'; -- fail (not privileged)
ERROR: must have CREATEROLE privilege ERROR: permission denied
DETAIL: The current user must have the CREATEROLE attribute.
RESET SESSION AUTHORIZATION; RESET SESSION AUTHORIZATION;
-- --
-- Test for various types of object -- Test for various types of object

View File

@ -1077,7 +1077,8 @@ SHOW session_preload_libraries;
SET SESSION AUTHORIZATION regress_role_nopriv; SET SESSION AUTHORIZATION regress_role_nopriv;
-- fails with role not member of pg_read_all_settings -- fails with role not member of pg_read_all_settings
SHOW session_preload_libraries; SHOW session_preload_libraries;
ERROR: must be superuser or have privileges of pg_read_all_settings to examine "session_preload_libraries" ERROR: permission denied to examine "session_preload_libraries"
DETAIL: Only roles with privileges of the "pg_read_all_settings" role may examine this parameter.
RESET SESSION AUTHORIZATION; RESET SESSION AUTHORIZATION;
ERROR: current transaction is aborted, commands ignored until end of transaction block ERROR: current transaction is aborted, commands ignored until end of transaction block
ROLLBACK; ROLLBACK;

View File

@ -7,26 +7,35 @@ CREATE ROLE regress_role_normal;
-- fail, CREATEROLE user can't give away role attributes without having them -- fail, CREATEROLE user can't give away role attributes without having them
SET SESSION AUTHORIZATION regress_role_limited_admin; SET SESSION AUTHORIZATION regress_role_limited_admin;
CREATE ROLE regress_nosuch_superuser SUPERUSER; CREATE ROLE regress_nosuch_superuser SUPERUSER;
ERROR: must be superuser to create superusers ERROR: permission denied to create role
DETAIL: Only roles with the SUPERUSER attribute may create roles with SUPERUSER.
CREATE ROLE regress_nosuch_replication_bypassrls REPLICATION BYPASSRLS; CREATE ROLE regress_nosuch_replication_bypassrls REPLICATION BYPASSRLS;
ERROR: must have replication permission to create replication users ERROR: permission denied to create role
DETAIL: Only roles with the REPLICATION attribute may create roles with REPLICATION.
CREATE ROLE regress_nosuch_replication REPLICATION; CREATE ROLE regress_nosuch_replication REPLICATION;
ERROR: must have replication permission to create replication users ERROR: permission denied to create role
DETAIL: Only roles with the REPLICATION attribute may create roles with REPLICATION.
CREATE ROLE regress_nosuch_bypassrls BYPASSRLS; CREATE ROLE regress_nosuch_bypassrls BYPASSRLS;
ERROR: must have bypassrls to create bypassrls users ERROR: permission denied to create role
DETAIL: Only roles with the BYPASSRLS attribute may create roles with BYPASSRLS.
CREATE ROLE regress_nosuch_createdb CREATEDB; CREATE ROLE regress_nosuch_createdb CREATEDB;
ERROR: must have createdb permission to create createdb users ERROR: permission denied to create role
DETAIL: Only roles with the CREATEDB attribute may create roles with CREATEDB.
-- ok, can create a role without any special attributes -- ok, can create a role without any special attributes
CREATE ROLE regress_role_limited; CREATE ROLE regress_role_limited;
-- fail, can't give it in any of the restricted attributes -- fail, can't give it in any of the restricted attributes
ALTER ROLE regress_role_limited SUPERUSER; ALTER ROLE regress_role_limited SUPERUSER;
ERROR: must be superuser to alter superuser roles or change superuser attribute ERROR: permission denied to alter role
DETAIL: Only roles with the SUPERUSER attribute may change the SUPERUSER attribute.
ALTER ROLE regress_role_limited REPLICATION; ALTER ROLE regress_role_limited REPLICATION;
ERROR: must have replication privilege to change replication attribute ERROR: permission denied to alter role
DETAIL: Only roles with the REPLICATION attribute may change the REPLICATION attribute.
ALTER ROLE regress_role_limited CREATEDB; ALTER ROLE regress_role_limited CREATEDB;
ERROR: must have createdb privilege to change createdb attribute ERROR: permission denied to alter role
DETAIL: Only roles with the CREATEDB attribute may change the CREATEDB attribute.
ALTER ROLE regress_role_limited BYPASSRLS; ALTER ROLE regress_role_limited BYPASSRLS;
ERROR: must have bypassrls privilege to change bypassrls attribute ERROR: permission denied to alter role
DETAIL: Only roles with the BYPASSRLS attribute may change the BYPASSRLS attribute.
DROP ROLE regress_role_limited; DROP ROLE regress_role_limited;
-- ok, can give away these role attributes if you have them -- ok, can give away these role attributes if you have them
SET SESSION AUTHORIZATION regress_role_admin; SET SESSION AUTHORIZATION regress_role_admin;
@ -43,9 +52,11 @@ ALTER ROLE regress_createdb NOCREATEDB;
ALTER ROLE regress_createdb CREATEDB; ALTER ROLE regress_createdb CREATEDB;
-- fail, can't toggle SUPERUSER -- fail, can't toggle SUPERUSER
ALTER ROLE regress_createdb SUPERUSER; ALTER ROLE regress_createdb SUPERUSER;
ERROR: must be superuser to alter superuser roles or change superuser attribute ERROR: permission denied to alter role
DETAIL: Only roles with the SUPERUSER attribute may change the SUPERUSER attribute.
ALTER ROLE regress_createdb NOSUPERUSER; ALTER ROLE regress_createdb NOSUPERUSER;
ERROR: must be superuser to alter superuser roles or change superuser attribute ERROR: permission denied to alter role
DETAIL: Only roles with the SUPERUSER attribute may change the SUPERUSER attribute.
-- ok, having CREATEROLE is enough to create users with these privileges -- ok, having CREATEROLE is enough to create users with these privileges
CREATE ROLE regress_createrole CREATEROLE NOINHERIT; CREATE ROLE regress_createrole CREATEROLE NOINHERIT;
GRANT CREATE ON DATABASE regression TO regress_createrole WITH GRANT OPTION; GRANT CREATE ON DATABASE regression TO regress_createrole WITH GRANT OPTION;
@ -59,7 +70,8 @@ CREATE ROLE regress_noiseword SYSID 12345;
NOTICE: SYSID can no longer be specified NOTICE: SYSID can no longer be specified
-- fail, cannot grant membership in superuser role -- fail, cannot grant membership in superuser role
CREATE ROLE regress_nosuch_super IN ROLE regress_role_super; CREATE ROLE regress_nosuch_super IN ROLE regress_role_super;
ERROR: must be superuser to alter superusers ERROR: permission denied to grant role "regress_role_super"
DETAIL: Only roles with the SUPERUSER attribute may grant roles with SUPERUSER.
-- fail, database owner cannot have members -- fail, database owner cannot have members
CREATE ROLE regress_nosuch_dbowner IN ROLE pg_database_owner; CREATE ROLE regress_nosuch_dbowner IN ROLE pg_database_owner;
ERROR: role "pg_database_owner" cannot have explicit members ERROR: role "pg_database_owner" cannot have explicit members
@ -94,11 +106,14 @@ ALTER ROLE regress_hasprivs RENAME TO regress_tenant;
ALTER ROLE regress_tenant NOINHERIT NOLOGIN CONNECTION LIMIT 7; ALTER ROLE regress_tenant NOINHERIT NOLOGIN CONNECTION LIMIT 7;
-- fail, we should be unable to modify a role we did not create -- fail, we should be unable to modify a role we did not create
COMMENT ON ROLE regress_role_normal IS 'some comment'; COMMENT ON ROLE regress_role_normal IS 'some comment';
ERROR: must have admin option on role "regress_role_normal" ERROR: permission denied
DETAIL: The current user must have the ADMIN option on role "regress_role_normal".
ALTER ROLE regress_role_normal RENAME TO regress_role_abnormal; ALTER ROLE regress_role_normal RENAME TO regress_role_abnormal;
ERROR: permission denied to rename role ERROR: permission denied to rename role
DETAIL: Only roles with the CREATEROLE attribute and the ADMIN option on role "regress_role_normal" may rename this role.
ALTER ROLE regress_role_normal NOINHERIT NOLOGIN CONNECTION LIMIT 7; ALTER ROLE regress_role_normal NOINHERIT NOLOGIN CONNECTION LIMIT 7;
ERROR: permission denied ERROR: permission denied to alter role
DETAIL: Only roles with the CREATEROLE attribute and the ADMIN option on role "regress_role_normal" may alter this role.
-- ok, regress_tenant can create objects within the database -- ok, regress_tenant can create objects within the database
SET SESSION AUTHORIZATION regress_tenant; SET SESSION AUTHORIZATION regress_tenant;
CREATE TABLE tenant_table (i integer); CREATE TABLE tenant_table (i integer);
@ -123,6 +138,7 @@ ERROR: must be able to SET ROLE "regress_tenant"
-- fail, we don't inherit permissions from regress_tenant -- fail, we don't inherit permissions from regress_tenant
REASSIGN OWNED BY regress_tenant TO regress_createrole; REASSIGN OWNED BY regress_tenant TO regress_createrole;
ERROR: permission denied to reassign objects ERROR: permission denied to reassign objects
DETAIL: Only roles with privileges of role "regress_tenant" may reassign objects owned by it.
-- ok, create a role with a value for createrole_self_grant -- ok, create a role with a value for createrole_self_grant
SET createrole_self_grant = 'set, inherit'; SET createrole_self_grant = 'set, inherit';
CREATE ROLE regress_tenant2; CREATE ROLE regress_tenant2;
@ -150,25 +166,35 @@ ERROR: must be able to SET ROLE "regress_tenant2"
DROP TABLE tenant2_table; DROP TABLE tenant2_table;
-- fail, CREATEROLE is not enough to create roles in privileged roles -- fail, CREATEROLE is not enough to create roles in privileged roles
CREATE ROLE regress_read_all_data IN ROLE pg_read_all_data; CREATE ROLE regress_read_all_data IN ROLE pg_read_all_data;
ERROR: must have admin option on role "pg_read_all_data" ERROR: permission denied to grant role "pg_read_all_data"
DETAIL: Only roles with the ADMIN option on role "pg_read_all_data" may grant this role.
CREATE ROLE regress_write_all_data IN ROLE pg_write_all_data; CREATE ROLE regress_write_all_data IN ROLE pg_write_all_data;
ERROR: must have admin option on role "pg_write_all_data" ERROR: permission denied to grant role "pg_write_all_data"
DETAIL: Only roles with the ADMIN option on role "pg_write_all_data" may grant this role.
CREATE ROLE regress_monitor IN ROLE pg_monitor; CREATE ROLE regress_monitor IN ROLE pg_monitor;
ERROR: must have admin option on role "pg_monitor" ERROR: permission denied to grant role "pg_monitor"
DETAIL: Only roles with the ADMIN option on role "pg_monitor" may grant this role.
CREATE ROLE regress_read_all_settings IN ROLE pg_read_all_settings; CREATE ROLE regress_read_all_settings IN ROLE pg_read_all_settings;
ERROR: must have admin option on role "pg_read_all_settings" ERROR: permission denied to grant role "pg_read_all_settings"
DETAIL: Only roles with the ADMIN option on role "pg_read_all_settings" may grant this role.
CREATE ROLE regress_read_all_stats IN ROLE pg_read_all_stats; CREATE ROLE regress_read_all_stats IN ROLE pg_read_all_stats;
ERROR: must have admin option on role "pg_read_all_stats" ERROR: permission denied to grant role "pg_read_all_stats"
DETAIL: Only roles with the ADMIN option on role "pg_read_all_stats" may grant this role.
CREATE ROLE regress_stat_scan_tables IN ROLE pg_stat_scan_tables; CREATE ROLE regress_stat_scan_tables IN ROLE pg_stat_scan_tables;
ERROR: must have admin option on role "pg_stat_scan_tables" ERROR: permission denied to grant role "pg_stat_scan_tables"
DETAIL: Only roles with the ADMIN option on role "pg_stat_scan_tables" may grant this role.
CREATE ROLE regress_read_server_files IN ROLE pg_read_server_files; CREATE ROLE regress_read_server_files IN ROLE pg_read_server_files;
ERROR: must have admin option on role "pg_read_server_files" ERROR: permission denied to grant role "pg_read_server_files"
DETAIL: Only roles with the ADMIN option on role "pg_read_server_files" may grant this role.
CREATE ROLE regress_write_server_files IN ROLE pg_write_server_files; CREATE ROLE regress_write_server_files IN ROLE pg_write_server_files;
ERROR: must have admin option on role "pg_write_server_files" ERROR: permission denied to grant role "pg_write_server_files"
DETAIL: Only roles with the ADMIN option on role "pg_write_server_files" may grant this role.
CREATE ROLE regress_execute_server_program IN ROLE pg_execute_server_program; CREATE ROLE regress_execute_server_program IN ROLE pg_execute_server_program;
ERROR: must have admin option on role "pg_execute_server_program" ERROR: permission denied to grant role "pg_execute_server_program"
DETAIL: Only roles with the ADMIN option on role "pg_execute_server_program" may grant this role.
CREATE ROLE regress_signal_backend IN ROLE pg_signal_backend; CREATE ROLE regress_signal_backend IN ROLE pg_signal_backend;
ERROR: must have admin option on role "pg_signal_backend" ERROR: permission denied to grant role "pg_signal_backend"
DETAIL: Only roles with the ADMIN option on role "pg_signal_backend" may grant this role.
-- fail, role still owns database objects -- fail, role still owns database objects
DROP ROLE regress_tenant; DROP ROLE regress_tenant;
ERROR: role "regress_tenant" cannot be dropped because some objects depend on it ERROR: role "regress_tenant" cannot be dropped because some objects depend on it
@ -211,11 +237,13 @@ DROP ROLE regress_inroles;
DROP ROLE regress_adminroles; DROP ROLE regress_adminroles;
-- fail, cannot drop ourself, nor superusers or roles we lack ADMIN for -- fail, cannot drop ourself, nor superusers or roles we lack ADMIN for
DROP ROLE regress_role_super; DROP ROLE regress_role_super;
ERROR: must be superuser to drop superusers ERROR: permission denied to drop role
DETAIL: Only roles with the SUPERUSER attribute may drop roles with SUPERUSER.
DROP ROLE regress_role_admin; DROP ROLE regress_role_admin;
ERROR: current user cannot be dropped ERROR: current user cannot be dropped
DROP ROLE regress_rolecreator; DROP ROLE regress_rolecreator;
ERROR: must have admin option on role "regress_rolecreator" ERROR: permission denied to drop role
DETAIL: Only roles with the CREATEROLE attribute and the ADMIN option on role "regress_rolecreator" may drop this role.
-- ok -- ok
RESET SESSION AUTHORIZATION; RESET SESSION AUTHORIZATION;
REVOKE CREATE ON DATABASE regression FROM regress_role_admin CASCADE; REVOKE CREATE ON DATABASE regression FROM regress_role_admin CASCADE;

View File

@ -48,12 +48,16 @@ SET SESSION AUTHORIZATION regress_dep_user0;
-- permission denied -- permission denied
DROP OWNED BY regress_dep_user1; DROP OWNED BY regress_dep_user1;
ERROR: permission denied to drop objects ERROR: permission denied to drop objects
DETAIL: Only roles with privileges of role "regress_dep_user1" may drop objects owned by it.
DROP OWNED BY regress_dep_user0, regress_dep_user2; DROP OWNED BY regress_dep_user0, regress_dep_user2;
ERROR: permission denied to drop objects ERROR: permission denied to drop objects
DETAIL: Only roles with privileges of role "regress_dep_user2" may drop objects owned by it.
REASSIGN OWNED BY regress_dep_user0 TO regress_dep_user1; REASSIGN OWNED BY regress_dep_user0 TO regress_dep_user1;
ERROR: permission denied to reassign objects ERROR: permission denied to reassign objects
DETAIL: Only roles with privileges of role "regress_dep_user1" may reassign objects to it.
REASSIGN OWNED BY regress_dep_user1 TO regress_dep_user0; REASSIGN OWNED BY regress_dep_user1 TO regress_dep_user0;
ERROR: permission denied to reassign objects ERROR: permission denied to reassign objects
DETAIL: Only roles with privileges of role "regress_dep_user1" may reassign objects owned by it.
-- this one is allowed -- this one is allowed
DROP OWNED BY regress_dep_user0; DROP OWNED BY regress_dep_user0;
CREATE TABLE deptest1 (f1 int unique); CREATE TABLE deptest1 (f1 int unique);

View File

@ -37,7 +37,7 @@ CREATE ROLE regress_priv_role;
GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION; GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION;
GRANT regress_priv_user1 TO regress_priv_user3 WITH ADMIN OPTION GRANTED BY regress_priv_user2; GRANT regress_priv_user1 TO regress_priv_user3 WITH ADMIN OPTION GRANTED BY regress_priv_user2;
GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION GRANTED BY regress_priv_user3; GRANT regress_priv_user1 TO regress_priv_user2 WITH ADMIN OPTION GRANTED BY regress_priv_user3;
ERROR: admin option cannot be granted back to your own grantor ERROR: ADMIN option cannot be granted back to your own grantor
-- need CASCADE to revoke grant or admin option if dependent grants exist -- need CASCADE to revoke grant or admin option if dependent grants exist
REVOKE ADMIN OPTION FOR regress_priv_user1 FROM regress_priv_user2; -- fail REVOKE ADMIN OPTION FOR regress_priv_user1 FROM regress_priv_user2; -- fail
ERROR: dependent privileges exist ERROR: dependent privileges exist
@ -156,7 +156,8 @@ ALTER GROUP regress_priv_group2 ADD USER regress_priv_user2; -- duplicate
NOTICE: role "regress_priv_user2" has already been granted membership in role "regress_priv_group2" by role "regress_priv_user1" NOTICE: role "regress_priv_user2" has already been granted membership in role "regress_priv_group2" by role "regress_priv_user1"
ALTER GROUP regress_priv_group2 DROP USER regress_priv_user2; ALTER GROUP regress_priv_group2 DROP USER regress_priv_user2;
ALTER USER regress_priv_user2 PASSWORD 'verysecret'; -- not permitted ALTER USER regress_priv_user2 PASSWORD 'verysecret'; -- not permitted
ERROR: must have CREATEROLE privilege to change another user's password ERROR: permission denied to alter role
DETAIL: To change another role's password, the current user must have the CREATEROLE attribute and the ADMIN option on the role.
RESET SESSION AUTHORIZATION; RESET SESSION AUTHORIZATION;
ALTER GROUP regress_priv_group2 DROP USER regress_priv_user2; ALTER GROUP regress_priv_group2 DROP USER regress_priv_user2;
REVOKE ADMIN OPTION FOR regress_priv_group2 FROM regress_priv_user1; REVOKE ADMIN OPTION FOR regress_priv_group2 FROM regress_priv_user1;
@ -168,7 +169,8 @@ CREATE FUNCTION leak(integer,integer) RETURNS boolean
ALTER FUNCTION leak(integer,integer) OWNER TO regress_priv_user1; ALTER FUNCTION leak(integer,integer) OWNER TO regress_priv_user1;
-- test owner privileges -- test owner privileges
GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY regress_priv_role; -- error, doesn't have ADMIN OPTION GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY regress_priv_role; -- error, doesn't have ADMIN OPTION
ERROR: grantor must have ADMIN OPTION on "regress_priv_role" ERROR: permission denied to grant privileges as role "regress_priv_role"
DETAIL: The grantor must have the ADMIN option on role "regress_priv_role".
GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY CURRENT_ROLE; GRANT regress_priv_role TO regress_priv_user1 WITH ADMIN OPTION GRANTED BY CURRENT_ROLE;
REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY foo; -- error REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY foo; -- error
ERROR: role "foo" does not exist ERROR: role "foo" does not exist
@ -1795,7 +1797,8 @@ REFRESH MATERIALIZED VIEW sro_mv;
ERROR: cannot fire deferred trigger within security-restricted operation ERROR: cannot fire deferred trigger within security-restricted operation
CONTEXT: SQL function "mv_action" statement 1 CONTEXT: SQL function "mv_action" statement 1
BEGIN; SET CONSTRAINTS ALL IMMEDIATE; REFRESH MATERIALIZED VIEW sro_mv; COMMIT; BEGIN; SET CONSTRAINTS ALL IMMEDIATE; REFRESH MATERIALIZED VIEW sro_mv; COMMIT;
ERROR: must have admin option on role "regress_priv_group2" ERROR: permission denied to grant role "regress_priv_group2"
DETAIL: Only roles with the ADMIN option on role "regress_priv_group2" may grant this role.
CONTEXT: SQL function "unwanted_grant" statement 1 CONTEXT: SQL function "unwanted_grant" statement 1
SQL statement "SELECT unwanted_grant()" SQL statement "SELECT unwanted_grant()"
PL/pgSQL function sro_trojan() line 1 at PERFORM PL/pgSQL function sro_trojan() line 1 at PERFORM
@ -1825,10 +1828,12 @@ CREATE FUNCTION dogrant_ok() RETURNS void LANGUAGE sql SECURITY DEFINER AS
GRANT regress_priv_group2 TO regress_priv_user5; -- ok: had ADMIN OPTION GRANT regress_priv_group2 TO regress_priv_user5; -- ok: had ADMIN OPTION
SET ROLE regress_priv_group2; SET ROLE regress_priv_group2;
GRANT regress_priv_group2 TO regress_priv_user5; -- fails: SET ROLE suspended privilege GRANT regress_priv_group2 TO regress_priv_user5; -- fails: SET ROLE suspended privilege
ERROR: must have admin option on role "regress_priv_group2" ERROR: permission denied to grant role "regress_priv_group2"
DETAIL: Only roles with the ADMIN option on role "regress_priv_group2" may grant this role.
SET SESSION AUTHORIZATION regress_priv_user1; SET SESSION AUTHORIZATION regress_priv_user1;
GRANT regress_priv_group2 TO regress_priv_user5; -- fails: no ADMIN OPTION GRANT regress_priv_group2 TO regress_priv_user5; -- fails: no ADMIN OPTION
ERROR: must have admin option on role "regress_priv_group2" ERROR: permission denied to grant role "regress_priv_group2"
DETAIL: Only roles with the ADMIN option on role "regress_priv_group2" may grant this role.
SELECT dogrant_ok(); -- ok: SECURITY DEFINER conveys ADMIN SELECT dogrant_ok(); -- ok: SECURITY DEFINER conveys ADMIN
NOTICE: role "regress_priv_user5" has already been granted membership in role "regress_priv_group2" by role "regress_priv_user4" NOTICE: role "regress_priv_user5" has already been granted membership in role "regress_priv_group2" by role "regress_priv_user4"
dogrant_ok dogrant_ok
@ -1838,10 +1843,12 @@ NOTICE: role "regress_priv_user5" has already been granted membership in role "
SET ROLE regress_priv_group2; SET ROLE regress_priv_group2;
GRANT regress_priv_group2 TO regress_priv_user5; -- fails: SET ROLE did not help GRANT regress_priv_group2 TO regress_priv_user5; -- fails: SET ROLE did not help
ERROR: must have admin option on role "regress_priv_group2" ERROR: permission denied to grant role "regress_priv_group2"
DETAIL: Only roles with the ADMIN option on role "regress_priv_group2" may grant this role.
SET SESSION AUTHORIZATION regress_priv_group2; SET SESSION AUTHORIZATION regress_priv_group2;
GRANT regress_priv_group2 TO regress_priv_user5; -- fails: no self-admin GRANT regress_priv_group2 TO regress_priv_user5; -- fails: no self-admin
ERROR: must have admin option on role "regress_priv_group2" ERROR: permission denied to grant role "regress_priv_group2"
DETAIL: Only roles with the ADMIN option on role "regress_priv_group2" may grant this role.
SET SESSION AUTHORIZATION regress_priv_user4; SET SESSION AUTHORIZATION regress_priv_user4;
DROP FUNCTION dogrant_ok(); DROP FUNCTION dogrant_ok();
REVOKE regress_priv_group2 FROM regress_priv_user5; REVOKE regress_priv_group2 FROM regress_priv_user5;