diff options
author | Peter Eisentraut | 2023-03-17 09:14:16 +0000 |
---|---|---|
committer | Peter Eisentraut | 2023-03-17 09:33:09 +0000 |
commit | de4d456b406bf502341ef526710d3f764b41e2c8 (patch) | |
tree | 9a5ae6a1fb699d41d38b430dab4d2b6dfa716419 /src/backend | |
parent | 39a3bdc9eba50628cecb7e3cada95271180c8744 (diff) |
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
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/backup/basebackup_server.c | 4 | ||||
-rw-r--r-- | src/backend/catalog/objectaddress.c | 16 | ||||
-rw-r--r-- | src/backend/commands/copy.c | 12 | ||||
-rw-r--r-- | src/backend/commands/user.c | 167 | ||||
-rw-r--r-- | src/backend/replication/slot.c | 4 | ||||
-rw-r--r-- | src/backend/storage/ipc/procarray.c | 4 | ||||
-rw-r--r-- | src/backend/storage/ipc/signalfuncs.c | 16 | ||||
-rw-r--r-- | src/backend/tcop/utility.c | 5 | ||||
-rw-r--r-- | src/backend/utils/init/postinit.c | 10 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 15 |
10 files changed, 187 insertions, 66 deletions
diff --git a/src/backend/backup/basebackup_server.c b/src/backend/backup/basebackup_server.c index 0258d7a03b3..2b9d9d29324 100644 --- a/src/backend/backup/basebackup_server.c +++ b/src/backend/backup/basebackup_server.c @@ -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(); /* diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 2f688166e14..d59492934cb 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -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: diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 167d31a2d99..f14fae33083 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -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."))); } diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 43fe530a96d..52796e95487 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -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)))); } /* diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 3506b77cc7c..2293c0c6fc3 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -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"))); } /* diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index a9fb97460d8..ea91ce355f2 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -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"))); } } diff --git a/src/backend/storage/ipc/signalfuncs.c b/src/backend/storage/ipc/signalfuncs.c index bc93ab5b520..eabb68a9e17 100644 --- a/src/backend/storage/ipc/signalfuncs.c +++ b/src/backend/storage/ipc/signalfuncs.c @@ -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) diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index c7d9d96b45d..eada7353639 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -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)); diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 3026317bfc9..92bac8b63f5 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -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"))); } /* diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 51e07d55825..ea67cfa5e51 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -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; |