Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * usercontext.c
4 : : * Convenience functions for running code as a different database user.
5 : : *
6 : : * Portions Copyright (c) 1996-2024, 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 : : */
32 : : void
376 rhaas@postgresql.org 33 :CBC 148222 : SwitchToUntrustedUser(Oid userid, UserContext *context)
34 : : {
35 : : /* Get the current user ID and security context. */
36 : 148222 : GetUserIdAndSecContext(&context->save_userid,
37 : : &context->save_sec_context);
38 : :
39 : : /* Check that we have sufficient privileges to assume the target role. */
40 [ + + ]: 148222 : if (!member_can_set_role(context->save_userid, userid))
41 [ + - ]: 1 : ereport(ERROR,
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 [ + + ]: 148221 : 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 : : */
59 : 148191 : SetUserIdAndSecContext(userid, context->save_sec_context);
60 : 148191 : context->save_nestlevel = -1;
61 : : }
62 : : else
63 : : {
331 tgl@sss.pgh.pa.us 64 : 30 : 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 : : */
376 rhaas@postgresql.org 74 : 30 : sec_context |= SECURITY_RESTRICTED_OPERATION;
75 : 30 : SetUserIdAndSecContext(userid, sec_context);
76 : 30 : context->save_nestlevel = NewGUCNestLevel();
77 : : }
78 : 148221 : }
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 : : */
86 : : void
87 : 148198 : RestoreUserContext(UserContext *context)
88 : : {
89 [ + + ]: 148198 : if (context->save_nestlevel != -1)
90 : 24 : AtEOXact_GUC(false, context->save_nestlevel);
91 : 148198 : SetUserIdAndSecContext(context->save_userid, context->save_sec_context);
92 : 148198 : }
|