Skip to content

Commit 9987a7b

Browse files
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
1 parent edca342 commit 9987a7b

File tree

3 files changed

+41
-22
lines changed

3 files changed

+41
-22
lines changed

src/backend/commands/variable.c

+28-4
Original file line numberDiff line numberDiff line change
@@ -821,14 +821,16 @@ check_session_authorization(char **newval, void **extra, GucSource source)
821821
return false;
822822
}
823823

824+
/*
825+
* When source == PGC_S_TEST, we don't throw a hard error for a
826+
* nonexistent user name or insufficient privileges, only a NOTICE. See
827+
* comments in guc.h.
828+
*/
829+
824830
/* Look up the username */
825831
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
826832
if (!HeapTupleIsValid(roleTup))
827833
{
828-
/*
829-
* When source == PGC_S_TEST, we don't throw a hard error for a
830-
* nonexistent user name, only a NOTICE. See comments in guc.h.
831-
*/
832834
if (source == PGC_S_TEST)
833835
{
834836
ereport(NOTICE,
@@ -846,6 +848,28 @@ check_session_authorization(char **newval, void **extra, GucSource source)
846848

847849
ReleaseSysCache(roleTup);
848850

851+
/*
852+
* Only superusers may SET SESSION AUTHORIZATION a role other than itself.
853+
* Note that in case of multiple SETs in a single session, the original
854+
* authenticated user's superuserness is what matters.
855+
*/
856+
if (roleid != GetAuthenticatedUserId() &&
857+
!GetAuthenticatedUserIsSuperuser())
858+
{
859+
if (source == PGC_S_TEST)
860+
{
861+
ereport(NOTICE,
862+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
863+
errmsg("permission will be denied to set session authorization \"%s\"",
864+
*newval)));
865+
return true;
866+
}
867+
GUC_check_errcode(ERRCODE_INSUFFICIENT_PRIVILEGE);
868+
GUC_check_errmsg("permission denied to set session authorization \"%s\"",
869+
*newval);
870+
return false;
871+
}
872+
849873
/* Set up "extra" struct for assign_session_authorization to use */
850874
myextra = (role_auth_extra *) guc_malloc(LOG, sizeof(role_auth_extra));
851875
if (!myextra)

src/backend/utils/init/miscinit.c

+12-18
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,16 @@ GetAuthenticatedUserId(void)
582582
return AuthenticatedUserId;
583583
}
584584

585+
/*
586+
* Return whether the authenticated user was superuser at connection start.
587+
*/
588+
bool
589+
GetAuthenticatedUserIsSuperuser(void)
590+
{
591+
Assert(OidIsValid(AuthenticatedUserId));
592+
return AuthenticatedUserIsSuperuser;
593+
}
594+
585595

586596
/*
587597
* GetUserIdAndSecContext/SetUserIdAndSecContext - get/set the current user ID
@@ -889,28 +899,12 @@ system_user(PG_FUNCTION_ARGS)
889899
/*
890900
* Change session auth ID while running
891901
*
892-
* Only a superuser may set auth ID to something other than himself. Note
893-
* that in case of multiple SETs in a single session, the original userid's
894-
* superuserness is what matters. But we set the GUC variable is_superuser
895-
* to indicate whether the *current* session userid is a superuser.
896-
*
897-
* Note: this is not an especially clean place to do the permission check.
898-
* It's OK because the check does not require catalog access and can't
899-
* fail during an end-of-transaction GUC reversion, but we may someday
900-
* have to push it up into assign_session_authorization.
902+
* Note that we set the GUC variable is_superuser to indicate whether the
903+
* current role is a superuser.
901904
*/
902905
void
903906
SetSessionAuthorization(Oid userid, bool is_superuser)
904907
{
905-
/* Must have authenticated already, else can't make permission check */
906-
Assert(OidIsValid(AuthenticatedUserId));
907-
908-
if (userid != AuthenticatedUserId &&
909-
!AuthenticatedUserIsSuperuser)
910-
ereport(ERROR,
911-
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
912-
errmsg("permission denied to set session authorization")));
913-
914908
SetSessionUserId(userid, is_superuser);
915909

916910
SetConfigOption("is_superuser",

src/include/miscadmin.h

+1
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ extern Oid GetUserId(void);
357357
extern Oid GetOuterUserId(void);
358358
extern Oid GetSessionUserId(void);
359359
extern Oid GetAuthenticatedUserId(void);
360+
extern bool GetAuthenticatedUserIsSuperuser(void);
360361
extern void GetUserIdAndSecContext(Oid *userid, int *sec_context);
361362
extern void SetUserIdAndSecContext(Oid userid, int sec_context);
362363
extern bool InLocalUserIdChange(void);

0 commit comments

Comments
 (0)