aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/variable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/variable.c')
-rw-r--r--src/backend/commands/variable.c101
1 files changed, 72 insertions, 29 deletions
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index e5ddcda0b4a..f105e006c3f 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -753,40 +753,78 @@ check_session_authorization(char **newval, void **extra, GucSource source)
if (*newval == NULL)
return true;
- if (!IsTransactionState())
+ if (InitializingParallelWorker)
{
/*
- * Can't do catalog lookups, so fail. The result of this is that
- * session_authorization cannot be set in postgresql.conf, which seems
- * like a good thing anyway, so we don't work hard to avoid it.
+ * In parallel worker initialization, we want to copy the leader's
+ * state even if it no longer matches the catalogs. ParallelWorkerMain
+ * already installed the correct role OID and superuser state.
*/
- return false;
+ roleid = GetSessionUserId();
+ is_superuser = GetSessionUserIsSuperuser();
}
-
- /* Look up the username */
- roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
- if (!HeapTupleIsValid(roleTup))
+ else
{
+ if (!IsTransactionState())
+ {
+ /*
+ * Can't do catalog lookups, so fail. The result of this is that
+ * session_authorization cannot be set in postgresql.conf, which
+ * seems like a good thing anyway, so we don't work hard to avoid
+ * it.
+ */
+ return false;
+ }
+
/*
* When source == PGC_S_TEST, we don't throw a hard error for a
- * nonexistent user name, only a NOTICE. See comments in guc.h.
+ * nonexistent user name or insufficient privileges, only a NOTICE.
+ * See comments in guc.h.
*/
- if (source == PGC_S_TEST)
+
+ /* Look up the username */
+ roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
+ if (!HeapTupleIsValid(roleTup))
{
- ereport(NOTICE,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("role \"%s\" does not exist", *newval)));
- return true;
+ if (source == PGC_S_TEST)
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("role \"%s\" does not exist", *newval)));
+ return true;
+ }
+ GUC_check_errmsg("role \"%s\" does not exist", *newval);
+ return false;
}
- GUC_check_errmsg("role \"%s\" does not exist", *newval);
- return false;
- }
- roleform = (Form_pg_authid) GETSTRUCT(roleTup);
- roleid = roleform->oid;
- is_superuser = roleform->rolsuper;
+ roleform = (Form_pg_authid) GETSTRUCT(roleTup);
+ roleid = roleform->oid;
+ is_superuser = roleform->rolsuper;
- ReleaseSysCache(roleTup);
+ ReleaseSysCache(roleTup);
+
+ /*
+ * Only superusers may SET SESSION AUTHORIZATION a role other than
+ * itself. Note that in case of multiple SETs in a single session, the
+ * original authenticated user's superuserness is what matters.
+ */
+ if (roleid != GetAuthenticatedUserId() &&
+ !GetAuthenticatedUserIsSuperuser())
+ {
+ if (source == PGC_S_TEST)
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission will be denied to set session authorization \"%s\"",
+ *newval)));
+ return true;
+ }
+ GUC_check_errcode(ERRCODE_INSUFFICIENT_PRIVILEGE);
+ GUC_check_errmsg("permission denied to set session authorization \"%s\"",
+ *newval);
+ return false;
+ }
+ }
/* Set up "extra" struct for assign_session_authorization to use */
myextra = (role_auth_extra *) malloc(sizeof(role_auth_extra));
@@ -836,6 +874,16 @@ check_role(char **newval, void **extra, GucSource source)
roleid = InvalidOid;
is_superuser = false;
}
+ else if (InitializingParallelWorker)
+ {
+ /*
+ * In parallel worker initialization, we want to copy the leader's
+ * state even if it no longer matches the catalogs. ParallelWorkerMain
+ * already installed the correct role OID and superuser state.
+ */
+ roleid = GetCurrentRoleId();
+ is_superuser = session_auth_is_superuser;
+ }
else
{
if (!IsTransactionState())
@@ -875,13 +923,8 @@ check_role(char **newval, void **extra, GucSource source)
ReleaseSysCache(roleTup);
- /*
- * Verify that session user is allowed to become this role, but skip
- * this in parallel mode, where we must blindly recreate the parallel
- * leader's state.
- */
- if (!InitializingParallelWorker &&
- !is_member_of_role(GetSessionUserId(), roleid))
+ /* Verify that session user is allowed to become this role */
+ if (!is_member_of_role(GetSessionUserId(), roleid))
{
if (source == PGC_S_TEST)
{