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');
SET ROLE regress_file_fdw_user;
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;
-- cleanup
RESET ROLE;

View File

@ -279,13 +279,19 @@ file_fdw_validator(PG_FUNCTION_ARGS)
!has_privs_of_role(GetUserId(), ROLE_PG_READ_SERVER_FILES))
ereport(ERROR,
(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 &&
!has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
ereport(ERROR,
(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);
}

View File

@ -54,13 +54,16 @@ RESET ROLE;
-- plain user *can't* can control replication
SET ROLE regress_lr_normal;
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');
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');
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');
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;
-- replication users can drop superuser created slots
SET ROLE regress_lr_superuser;
@ -90,7 +93,8 @@ SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_d
RESET ROLE;
SET ROLE regress_lr_normal;
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;
-- all users can see existing slots
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))
ereport(ERROR,
(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();
/*

View File

@ -2547,20 +2547,26 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
if (!superuser_arg(roleid))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser")));
errmsg("permission denied"),
errdetail("The current user must have the %s attribute.",
"SUPERUSER")));
}
else
{
if (!has_createrole_privilege(roleid))
ereport(ERROR,
(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))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have admin option on role \"%s\"",
GetUserNameFromId(address.objectId,
true))));
errmsg("permission denied"),
errdetail("The current user must have the %s option on role \"%s\".",
"ADMIN",
GetUserNameFromId(address.objectId,
true))));
}
break;
case OBJECT_TSPARSER:

View File

@ -83,7 +83,9 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
if (!has_privs_of_role(GetUserId(), ROLE_PG_EXECUTE_SERVER_PROGRAM))
ereport(ERROR,
(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. "
"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))
ereport(ERROR,
(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. "
"psql's \\copy command also works for anyone.")));
if (!is_from && !has_privs_of_role(GetUserId(), ROLE_PG_WRITE_SERVER_FILES))
ereport(ERROR,
(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. "
"psql's \\copy command also works for anyone.")));
}

View File

@ -316,23 +316,33 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
if (!has_createrole_privilege(currentUserId))
ereport(ERROR,
(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)
ereport(ERROR,
(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())
ereport(ERROR,
(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))
ereport(ERROR,
(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))
ereport(ERROR,
(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;
/* To mess with a superuser in any way you gotta be superuser. */
if (!superuser() && (authform->rolsuper || dissuper))
if (!superuser() && authform->rolsuper)
ereport(ERROR,
(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
@ -761,13 +779,17 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
dvalidUntil || disreplication || dbypassRLS)
ereport(ERROR,
(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 */
if (dpassword && roleid != currentUserId)
ereport(ERROR,
(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())
{
@ -779,23 +801,30 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
if (dcreatedb && !have_createdb_privilege())
ereport(ERROR,
(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))
ereport(ERROR,
(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))
ereport(ERROR,
(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. */
if (drolemembers && !is_admin_of_role(currentUserId, roleid))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have admin option on role \"%s\" to add members",
rolename)));
errmsg("permission denied to alter role"),
errdetail("Only roles with the %s option on role \"%s\" may add members.",
"ADMIN", rolename)));
/* Convert validuntil to internal form */
if (dvalidUntil)
@ -837,8 +866,10 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
if (!should_be_super && roleid == BOOTSTRAP_SUPERUSERID)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied: bootstrap user must be superuser")));
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
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_repl[Anum_pg_authid_rolsuper - 1] = true;
@ -999,7 +1030,9 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
if (!superuser())
ereport(ERROR,
(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
{
@ -1008,7 +1041,9 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
&& roleid != GetUserId())
ereport(ERROR,
(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);
@ -1038,7 +1073,9 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
if (!superuser())
ereport(ERROR,
(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);
@ -1061,7 +1098,9 @@ DropRole(DropRoleStmt *stmt)
if (!have_createrole_privilege())
ereport(ERROR,
(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
@ -1131,12 +1170,15 @@ DropRole(DropRoleStmt *stmt)
if (roleform->rolsuper && !superuser())
ereport(ERROR,
(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))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have admin option on role \"%s\"",
role)));
errmsg("permission denied to drop 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 */
InvokeObjectDropHook(AuthIdRelationId, roleid, 0);
@ -1383,7 +1425,9 @@ RenameRole(const char *oldname, const char *newname)
if (!superuser())
ereport(ERROR,
(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
{
@ -1391,7 +1435,9 @@ RenameRole(const char *oldname, const char *newname)
!is_admin_of_role(GetUserId(), roleid))
ereport(ERROR,
(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 */
@ -1554,7 +1600,9 @@ DropOwnedObjects(DropOwnedStmt *stmt)
if (!has_privs_of_role(GetUserId(), roleid))
ereport(ERROR,
(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 */
@ -1581,7 +1629,9 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt)
if (!has_privs_of_role(GetUserId(), roleid))
ereport(ERROR,
(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 */
@ -1590,7 +1640,9 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt)
if (!has_privs_of_role(GetUserId(), newrole))
ereport(ERROR,
(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 */
shdepReassignOwned(role_ids, newrole);
@ -1738,7 +1790,8 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
if (memberid == BOOTSTRAP_SUPERUSERID)
ereport(ERROR,
(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);
}
@ -1763,7 +1816,8 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
if (i >= memlist->n_members)
ereport(ERROR,
(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);
}
@ -2081,9 +2135,22 @@ check_role_membership_authorization(Oid currentUserId, Oid roleid,
if (superuser_arg(roleid))
{
if (!superuser_arg(currentUserId))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to alter superusers")));
{
if (is_grant)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
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
{
@ -2091,10 +2158,22 @@ check_role_membership_authorization(Oid currentUserId, Oid roleid,
* Otherwise, must have admin option on the role to be changed.
*/
if (!is_admin_of_role(currentUserId, roleid))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must have admin option on role \"%s\"",
GetUserNameFromId(roleid, false))));
{
if (is_grant)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to grant role \"%s\"",
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,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to grant privileges as role \"%s\"",
GetUserNameFromId(grantorId, false))));
GetUserNameFromId(grantorId, false)),
errdetail("Only roles with privileges of role \"%s\" may grant privileges as this role.",
GetUserNameFromId(grantorId, false))));
if (grantorId != BOOTSTRAP_SUPERUSERID &&
select_best_admin(grantorId, roleid) != grantorId)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("grantor must have ADMIN OPTION on \"%s\"",
GetUserNameFromId(roleid, false))));
errmsg("permission denied to grant privileges as role \"%s\"",
GetUserNameFromId(grantorId, false)),
errdetail("The grantor must have the %s option on role \"%s\".",
"ADMIN", GetUserNameFromId(roleid, false))));
}
else
{
@ -2188,7 +2271,9 @@ check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId, bool is_grant)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to revoke privileges granted by role \"%s\"",
GetUserNameFromId(grantorId, false))));
GetUserNameFromId(grantorId, false)),
errdetail("Only roles with privileges of role \"%s\" may revoke privileges granted by this role.",
GetUserNameFromId(grantorId, false))));
}
/*

View File

@ -1143,7 +1143,9 @@ CheckSlotPermissions(void)
if (!has_rolreplication(GetUserId()))
ereport(ERROR,
(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))
ereport(ERROR,
(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)
ereport(ERROR,
(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)
ereport(ERROR,
(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);
}
@ -223,12 +227,16 @@ pg_terminate_backend(PG_FUNCTION_ARGS)
if (r == SIGNAL_BACKEND_NOSUPERUSER)
ereport(ERROR,
(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)
ereport(ERROR,
(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 */
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))
ereport(ERROR,
(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 |
(RecoveryInProgress() ? 0 : CHECKPOINT_FORCE));

View File

@ -949,12 +949,14 @@ InitPostgres(const char *in_dbname, Oid dboid,
if (nfree < SuperuserReservedConnections)
ereport(FATAL,
(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))
ereport(FATAL,
(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. */
@ -965,7 +967,9 @@ InitPostgres(const char *in_dbname, Oid dboid,
if (!has_rolreplication(GetUserId()))
ereport(FATAL,
(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))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or have privileges of pg_read_all_settings to examine \"%s\"",
name)));
errmsg("permission denied to examine \"%s\"", name),
errdetail("Only roles with privileges of the \"%s\" role may examine this parameter.",
"pg_read_all_settings")));
switch (record->vartype)
{
@ -4255,8 +4256,9 @@ GetConfigOptionResetString(const char *name)
if (!ConfigOptionIsVisible(record))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or have privileges of pg_read_all_settings to examine \"%s\"",
name)));
errmsg("permission denied to examine \"%s\"", name),
errdetail("Only roles with privileges of the \"%s\" role may examine this parameter.",
"pg_read_all_settings")));
switch (record->vartype)
{
@ -5261,8 +5263,9 @@ GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
if (!ConfigOptionIsVisible(record))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser or have privileges of pg_read_all_settings to examine \"%s\"",
name)));
errmsg("permission denied to examine \"%s\"", name),
errdetail("Only roles with privileges of the \"%s\" role may examine this parameter.",
"pg_read_all_settings")));
if (varname)
*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
SET SESSION AUTHORIZATION regress_dummy_seclabel_user2;
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;
--
-- Test for various types of object

View File

@ -1077,7 +1077,8 @@ SHOW session_preload_libraries;
SET SESSION AUTHORIZATION regress_role_nopriv;
-- fails with role not member of pg_read_all_settings
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;
ERROR: current transaction is aborted, commands ignored until end of transaction block
ROLLBACK;

View File

@ -7,26 +7,35 @@ CREATE ROLE regress_role_normal;
-- fail, CREATEROLE user can't give away role attributes without having them
SET SESSION AUTHORIZATION regress_role_limited_admin;
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;
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;
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;
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;
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
CREATE ROLE regress_role_limited;
-- fail, can't give it in any of the restricted attributes
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;
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;
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;
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;
-- ok, can give away these role attributes if you have them
SET SESSION AUTHORIZATION regress_role_admin;
@ -43,9 +52,11 @@ ALTER ROLE regress_createdb NOCREATEDB;
ALTER ROLE regress_createdb CREATEDB;
-- fail, can't toggle 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;
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
CREATE ROLE regress_createrole CREATEROLE NOINHERIT;
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
-- fail, cannot grant membership in superuser role
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
CREATE ROLE regress_nosuch_dbowner IN ROLE pg_database_owner;
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;
-- fail, we should be unable to modify a role we did not create
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;
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;
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
SET SESSION AUTHORIZATION regress_tenant;
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
REASSIGN OWNED BY regress_tenant TO regress_createrole;
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
SET createrole_self_grant = 'set, inherit';
CREATE ROLE regress_tenant2;
@ -150,25 +166,35 @@ ERROR: must be able to SET ROLE "regress_tenant2"
DROP TABLE tenant2_table;
-- fail, CREATEROLE is not enough to create roles in privileged roles
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;
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;
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;
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;
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;
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;
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;
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;
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;
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
DROP ROLE regress_tenant;
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;
-- fail, cannot drop ourself, nor superusers or roles we lack ADMIN for
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;
ERROR: current user cannot be dropped
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
RESET SESSION AUTHORIZATION;
REVOKE CREATE ON DATABASE regression FROM regress_role_admin CASCADE;

View File

@ -48,12 +48,16 @@ SET SESSION AUTHORIZATION regress_dep_user0;
-- permission denied
DROP OWNED BY regress_dep_user1;
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;
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;
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;
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
DROP OWNED BY regress_dep_user0;
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_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;
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
REVOKE ADMIN OPTION FOR regress_priv_user1 FROM regress_priv_user2; -- fail
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"
ALTER GROUP regress_priv_group2 DROP USER regress_priv_user2;
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;
ALTER GROUP regress_priv_group2 DROP USER regress_priv_user2;
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;
-- 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
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;
REVOKE ADMIN OPTION FOR regress_priv_role FROM regress_priv_user1 GRANTED BY foo; -- error
ERROR: role "foo" does not exist
@ -1795,7 +1797,8 @@ REFRESH MATERIALIZED VIEW sro_mv;
ERROR: cannot fire deferred trigger within security-restricted operation
CONTEXT: SQL function "mv_action" statement 1
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
SQL statement "SELECT unwanted_grant()"
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
SET ROLE regress_priv_group2;
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;
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
NOTICE: role "regress_priv_user5" has already been granted membership in role "regress_priv_group2" by role "regress_priv_user4"
dogrant_ok
@ -1838,10 +1843,12 @@ NOTICE: role "regress_priv_user5" has already been granted membership in role "
SET ROLE regress_priv_group2;
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;
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;
DROP FUNCTION dogrant_ok();
REVOKE regress_priv_group2 FROM regress_priv_user5;