mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
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
This commit is contained in:
@ -821,14 +821,16 @@ check_session_authorization(char **newval, void **extra, GucSource source)
|
|||||||
return false;
|
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 */
|
/* Look up the username */
|
||||||
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
|
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
|
||||||
if (!HeapTupleIsValid(roleTup))
|
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)
|
if (source == PGC_S_TEST)
|
||||||
{
|
{
|
||||||
ereport(NOTICE,
|
ereport(NOTICE,
|
||||||
@ -846,6 +848,28 @@ check_session_authorization(char **newval, void **extra, GucSource source)
|
|||||||
|
|
||||||
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 */
|
/* Set up "extra" struct for assign_session_authorization to use */
|
||||||
myextra = (role_auth_extra *) guc_malloc(LOG, sizeof(role_auth_extra));
|
myextra = (role_auth_extra *) guc_malloc(LOG, sizeof(role_auth_extra));
|
||||||
if (!myextra)
|
if (!myextra)
|
||||||
|
@ -582,6 +582,16 @@ GetAuthenticatedUserId(void)
|
|||||||
return AuthenticatedUserId;
|
return AuthenticatedUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return whether the authenticated user was superuser at connection start.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
GetAuthenticatedUserIsSuperuser(void)
|
||||||
|
{
|
||||||
|
Assert(OidIsValid(AuthenticatedUserId));
|
||||||
|
return AuthenticatedUserIsSuperuser;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GetUserIdAndSecContext/SetUserIdAndSecContext - get/set the current user ID
|
* GetUserIdAndSecContext/SetUserIdAndSecContext - get/set the current user ID
|
||||||
@ -889,28 +899,12 @@ system_user(PG_FUNCTION_ARGS)
|
|||||||
/*
|
/*
|
||||||
* Change session auth ID while running
|
* Change session auth ID while running
|
||||||
*
|
*
|
||||||
* Only a superuser may set auth ID to something other than himself. Note
|
* Note that we set the GUC variable is_superuser to indicate whether the
|
||||||
* that in case of multiple SETs in a single session, the original userid's
|
* current role is a superuser.
|
||||||
* superuserness is what matters. But we set the GUC variable is_superuser
|
|
||||||
* to indicate whether the *current* session userid is a superuser.
|
|
||||||
*
|
|
||||||
* Note: this is not an especially clean place to do the permission check.
|
|
||||||
* It's OK because the check does not require catalog access and can't
|
|
||||||
* fail during an end-of-transaction GUC reversion, but we may someday
|
|
||||||
* have to push it up into assign_session_authorization.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
SetSessionAuthorization(Oid userid, bool is_superuser)
|
SetSessionAuthorization(Oid userid, bool is_superuser)
|
||||||
{
|
{
|
||||||
/* Must have authenticated already, else can't make permission check */
|
|
||||||
Assert(OidIsValid(AuthenticatedUserId));
|
|
||||||
|
|
||||||
if (userid != AuthenticatedUserId &&
|
|
||||||
!AuthenticatedUserIsSuperuser)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
|
||||||
errmsg("permission denied to set session authorization")));
|
|
||||||
|
|
||||||
SetSessionUserId(userid, is_superuser);
|
SetSessionUserId(userid, is_superuser);
|
||||||
|
|
||||||
SetConfigOption("is_superuser",
|
SetConfigOption("is_superuser",
|
||||||
|
@ -357,6 +357,7 @@ extern Oid GetUserId(void);
|
|||||||
extern Oid GetOuterUserId(void);
|
extern Oid GetOuterUserId(void);
|
||||||
extern Oid GetSessionUserId(void);
|
extern Oid GetSessionUserId(void);
|
||||||
extern Oid GetAuthenticatedUserId(void);
|
extern Oid GetAuthenticatedUserId(void);
|
||||||
|
extern bool GetAuthenticatedUserIsSuperuser(void);
|
||||||
extern void GetUserIdAndSecContext(Oid *userid, int *sec_context);
|
extern void GetUserIdAndSecContext(Oid *userid, int *sec_context);
|
||||||
extern void SetUserIdAndSecContext(Oid userid, int sec_context);
|
extern void SetUserIdAndSecContext(Oid userid, int sec_context);
|
||||||
extern bool InLocalUserIdChange(void);
|
extern bool InLocalUserIdChange(void);
|
||||||
|
Reference in New Issue
Block a user