PostgreSQL Source Code git master
usercontext.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * usercontext.c
4 * Convenience functions for running code as a different database user.
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/utils/init/usercontext.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include "miscadmin.h"
18#include "utils/acl.h"
19#include "utils/guc.h"
20#include "utils/usercontext.h"
21
22/*
23 * Temporarily switch to a new user ID.
24 *
25 * If the current user doesn't have permission to SET ROLE to the new user,
26 * an ERROR occurs.
27 *
28 * If the new user doesn't have permission to SET ROLE to the current user,
29 * SECURITY_RESTRICTED_OPERATION is imposed and a new GUC nest level is
30 * created so that any settings changes can be rolled back.
31 */
32void
34{
35 /* Get the current user ID and security context. */
37 &context->save_sec_context);
38
39 /* Check that we have sufficient privileges to assume the target role. */
40 if (!member_can_set_role(context->save_userid, userid))
42 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
43 errmsg("role \"%s\" cannot SET ROLE to \"%s\"",
44 GetUserNameFromId(context->save_userid, false),
45 GetUserNameFromId(userid, false))));
46
47 /*
48 * Try to prevent the user to which we're switching from assuming the
49 * privileges of the current user, unless they can SET ROLE to that user
50 * anyway.
51 */
52 if (member_can_set_role(userid, context->save_userid))
53 {
54 /*
55 * Each user can SET ROLE to the other, so there's no point in
56 * imposing any security restrictions. Just let the user do whatever
57 * they want.
58 */
60 context->save_nestlevel = -1;
61 }
62 else
63 {
64 int sec_context = context->save_sec_context;
65
66 /*
67 * This user can SET ROLE to the target user, but not the other way
68 * around, so protect ourselves against the target user by setting
69 * SECURITY_RESTRICTED_OPERATION to prevent certain changes to the
70 * session state. Also set up a new GUC nest level, so that we can
71 * roll back any GUC changes that may be made by code running as the
72 * target user, inasmuch as they could be malicious.
73 */
74 sec_context |= SECURITY_RESTRICTED_OPERATION;
75 SetUserIdAndSecContext(userid, sec_context);
77 }
78}
79
80/*
81 * Switch back to the original user ID.
82 *
83 * If we created a new GUC nest level, also roll back any changes that were
84 * made within it.
85 */
86void
88{
89 if (context->save_nestlevel != -1)
90 AtEOXact_GUC(false, context->save_nestlevel);
92}
bool member_can_set_role(Oid member, Oid role)
Definition: acl.c:5302
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int NewGUCNestLevel(void)
Definition: guc.c:2235
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:2262
#define SECURITY_RESTRICTED_OPERATION
Definition: miscadmin.h:318
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition: miscinit.c:660
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition: miscinit.c:1036
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition: miscinit.c:667
unsigned int Oid
Definition: postgres_ext.h:32
int save_sec_context
Definition: usercontext.h:18
Oid save_userid
Definition: usercontext.h:17
int save_nestlevel
Definition: usercontext.h:19
void SwitchToUntrustedUser(Oid userid, UserContext *context)
Definition: usercontext.c:33
void RestoreUserContext(UserContext *context)
Definition: usercontext.c:87