From 9987a7bf34061ed5cffc4e5113da056358976e94 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 13 Jul 2023 21:10:36 -0700 Subject: Move privilege check for SET SESSION AUTHORIZATION. Presently, the privilege check for SET SESSION AUTHORIZATION is performed in session_authorization's assign_hook. A relevant comment states, "It's OK because the check does not require catalog access and can't fail during an end-of-transaction GUC reversion..." However, we plan to add a catalog lookup to this privilege check in a follow-up commit. This commit moves this privilege check to the check_hook for session_authorization. Like check_role(), we do not throw a hard error for insufficient privileges when the source is PGC_S_TEST. Author: Joseph Koshakow Discussion: https://postgr.es/m/CAAvxfHc-HHzONQ2oXdvhFF9ayRnidPwK%2BfVBhRzaBWYYLVQL-g%40mail.gmail.com --- src/backend/commands/variable.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'src/backend/commands/variable.c') diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index f0f2e076552..071bef63754 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -821,14 +821,16 @@ check_session_authorization(char **newval, void **extra, GucSource source) return false; } + /* + * When source == PGC_S_TEST, we don't throw a hard error for a + * nonexistent user name or insufficient privileges, only a NOTICE. See + * comments in guc.h. + */ + /* Look up the username */ roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval)); if (!HeapTupleIsValid(roleTup)) { - /* - * 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. - */ if (source == PGC_S_TEST) { ereport(NOTICE, @@ -846,6 +848,28 @@ check_session_authorization(char **newval, void **extra, GucSource source) 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 *) guc_malloc(LOG, sizeof(role_auth_extra)); if (!myextra) -- cgit v1.2.3