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,
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)
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
/*
* Change session auth ID while running
*
- * Only a superuser may set auth ID to something other than himself. Note
- * that in case of multiple SETs in a single session, the original userid's
- * 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.
+ * Note that we set the GUC variable is_superuser to indicate whether the
+ * current role is a superuser.
*/
void
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);
SetConfigOption("is_superuser",
extern Oid GetOuterUserId(void);
extern Oid GetSessionUserId(void);
extern Oid GetAuthenticatedUserId(void);
+extern bool GetAuthenticatedUserIsSuperuser(void);
extern void GetUserIdAndSecContext(Oid *userid, int *sec_context);
extern void SetUserIdAndSecContext(Oid userid, int sec_context);
extern bool InLocalUserIdChange(void);