mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Fix privilege check for SET SESSION AUTHORIZATION.
Presently, the privilege check for SET SESSION AUTHORIZATION checks whether the original authenticated role was a superuser at connection start time. Even if the role loses the superuser attribute, its existing sessions are permitted to change session authorization to any role. This commit modifies this privilege check to verify the original authenticated role currently has superuser. In the event that the authenticated role loses superuser within a session authorization change, the authorization change will remain in effect, which means the user can still take advantage of the target role's privileges. However, [RE]SET SESSION AUTHORIZATION will only permit switching to the original authenticated role. Author: Joseph Koshakow Discussion: https://postgr.es/m/CAAvxfHc-HHzONQ2oXdvhFF9ayRnidPwK%2BfVBhRzaBWYYLVQL-g%40mail.gmail.com
This commit is contained in:
@ -51,7 +51,7 @@ RESET SESSION AUTHORIZATION
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
The session user identifier can be changed only if the initial session
|
The session user identifier can be changed only if the initial session
|
||||||
user (the <firstterm>authenticated user</firstterm>) had the
|
user (the <firstterm>authenticated user</firstterm>) has the
|
||||||
superuser privilege. Otherwise, the command is accepted only if it
|
superuser privilege. Otherwise, the command is accepted only if it
|
||||||
specifies the authenticated user name.
|
specifies the authenticated user name.
|
||||||
</para>
|
</para>
|
||||||
|
@ -854,7 +854,7 @@ check_session_authorization(char **newval, void **extra, GucSource source)
|
|||||||
* authenticated user's superuserness is what matters.
|
* authenticated user's superuserness is what matters.
|
||||||
*/
|
*/
|
||||||
if (roleid != GetAuthenticatedUserId() &&
|
if (roleid != GetAuthenticatedUserId() &&
|
||||||
!GetAuthenticatedUserIsSuperuser())
|
!superuser_arg(GetAuthenticatedUserId()))
|
||||||
{
|
{
|
||||||
if (source == PGC_S_TEST)
|
if (source == PGC_S_TEST)
|
||||||
{
|
{
|
||||||
|
@ -467,8 +467,8 @@ ChangeToDataDir(void)
|
|||||||
* AuthenticatedUserId is determined at connection start and never changes.
|
* AuthenticatedUserId is determined at connection start and never changes.
|
||||||
*
|
*
|
||||||
* SessionUserId is initially the same as AuthenticatedUserId, but can be
|
* SessionUserId is initially the same as AuthenticatedUserId, but can be
|
||||||
* changed by SET SESSION AUTHORIZATION (if AuthenticatedUserIsSuperuser).
|
* changed by SET SESSION AUTHORIZATION (if AuthenticatedUserId is a
|
||||||
* This is the ID reported by the SESSION_USER SQL function.
|
* superuser). This is the ID reported by the SESSION_USER SQL function.
|
||||||
*
|
*
|
||||||
* OuterUserId is the current user ID in effect at the "outer level" (outside
|
* OuterUserId is the current user ID in effect at the "outer level" (outside
|
||||||
* any transaction or function). This is initially the same as SessionUserId,
|
* any transaction or function). This is initially the same as SessionUserId,
|
||||||
@ -492,8 +492,7 @@ static Oid OuterUserId = InvalidOid;
|
|||||||
static Oid CurrentUserId = InvalidOid;
|
static Oid CurrentUserId = InvalidOid;
|
||||||
static const char *SystemUser = NULL;
|
static const char *SystemUser = NULL;
|
||||||
|
|
||||||
/* We also have to remember the superuser state of some of these levels */
|
/* We also have to remember the superuser state of the session user */
|
||||||
static bool AuthenticatedUserIsSuperuser = false;
|
|
||||||
static bool SessionUserIsSuperuser = false;
|
static bool SessionUserIsSuperuser = false;
|
||||||
|
|
||||||
static int SecurityRestrictionContext = 0;
|
static int SecurityRestrictionContext = 0;
|
||||||
@ -582,16 +581,6 @@ 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
|
||||||
@ -741,6 +730,7 @@ InitializeSessionUserId(const char *rolename, Oid roleid)
|
|||||||
HeapTuple roleTup;
|
HeapTuple roleTup;
|
||||||
Form_pg_authid rform;
|
Form_pg_authid rform;
|
||||||
char *rname;
|
char *rname;
|
||||||
|
bool is_superuser;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't do scans if we're bootstrapping, none of the system catalogs
|
* Don't do scans if we're bootstrapping, none of the system catalogs
|
||||||
@ -780,10 +770,10 @@ InitializeSessionUserId(const char *rolename, Oid roleid)
|
|||||||
rname = NameStr(rform->rolname);
|
rname = NameStr(rform->rolname);
|
||||||
|
|
||||||
AuthenticatedUserId = roleid;
|
AuthenticatedUserId = roleid;
|
||||||
AuthenticatedUserIsSuperuser = rform->rolsuper;
|
is_superuser = rform->rolsuper;
|
||||||
|
|
||||||
/* This sets OuterUserId/CurrentUserId too */
|
/* This sets OuterUserId/CurrentUserId too */
|
||||||
SetSessionUserId(roleid, AuthenticatedUserIsSuperuser);
|
SetSessionUserId(roleid, is_superuser);
|
||||||
|
|
||||||
/* Also mark our PGPROC entry with the authenticated user id */
|
/* Also mark our PGPROC entry with the authenticated user id */
|
||||||
/* (We assume this is an atomic store so no lock is needed) */
|
/* (We assume this is an atomic store so no lock is needed) */
|
||||||
@ -816,7 +806,7 @@ InitializeSessionUserId(const char *rolename, Oid roleid)
|
|||||||
* just document that the connection limit is approximate.
|
* just document that the connection limit is approximate.
|
||||||
*/
|
*/
|
||||||
if (rform->rolconnlimit >= 0 &&
|
if (rform->rolconnlimit >= 0 &&
|
||||||
!AuthenticatedUserIsSuperuser &&
|
!is_superuser &&
|
||||||
CountUserBackends(roleid) > rform->rolconnlimit)
|
CountUserBackends(roleid) > rform->rolconnlimit)
|
||||||
ereport(FATAL,
|
ereport(FATAL,
|
||||||
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
|
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
|
||||||
@ -828,7 +818,7 @@ InitializeSessionUserId(const char *rolename, Oid roleid)
|
|||||||
SetConfigOption("session_authorization", rname,
|
SetConfigOption("session_authorization", rname,
|
||||||
PGC_BACKEND, PGC_S_OVERRIDE);
|
PGC_BACKEND, PGC_S_OVERRIDE);
|
||||||
SetConfigOption("is_superuser",
|
SetConfigOption("is_superuser",
|
||||||
AuthenticatedUserIsSuperuser ? "on" : "off",
|
is_superuser ? "on" : "off",
|
||||||
PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
|
PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
|
||||||
|
|
||||||
ReleaseSysCache(roleTup);
|
ReleaseSysCache(roleTup);
|
||||||
@ -851,8 +841,6 @@ InitializeSessionUserIdStandalone(void)
|
|||||||
Assert(!OidIsValid(AuthenticatedUserId));
|
Assert(!OidIsValid(AuthenticatedUserId));
|
||||||
|
|
||||||
AuthenticatedUserId = BOOTSTRAP_SUPERUSERID;
|
AuthenticatedUserId = BOOTSTRAP_SUPERUSERID;
|
||||||
AuthenticatedUserIsSuperuser = true;
|
|
||||||
|
|
||||||
SetSessionUserId(BOOTSTRAP_SUPERUSERID, true);
|
SetSessionUserId(BOOTSTRAP_SUPERUSERID, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,7 +357,6 @@ 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