Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * superuser.c
4 : : * The superuser() function. Determines if user has superuser privilege.
5 : : *
6 : : * All code should use either of these two functions to find out
7 : : * whether a given user is a superuser, rather than examining
8 : : * pg_authid.rolsuper directly, so that the escape hatch built in for
9 : : * the single-user case works.
10 : : *
11 : : *
12 : : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
13 : : * Portions Copyright (c) 1994, Regents of the University of California
14 : : *
15 : : *
16 : : * IDENTIFICATION
17 : : * src/backend/utils/misc/superuser.c
18 : : *
19 : : *-------------------------------------------------------------------------
20 : : */
21 : : #include "postgres.h"
22 : :
23 : : #include "access/htup_details.h"
24 : : #include "catalog/pg_authid.h"
25 : : #include "miscadmin.h"
26 : : #include "utils/inval.h"
27 : : #include "utils/syscache.h"
28 : :
29 : : /*
30 : : * In common cases the same roleid (ie, the session or current ID) will
31 : : * be queried repeatedly. So we maintain a simple one-entry cache for
32 : : * the status of the last requested roleid. The cache can be flushed
33 : : * at need by watching for cache update events on pg_authid.
34 : : */
35 : : static Oid last_roleid = InvalidOid; /* InvalidOid == cache not valid */
36 : : static bool last_roleid_is_super = false;
37 : : static bool roleid_callback_registered = false;
38 : :
39 : : static void RoleidCallback(Datum arg, int cacheid, uint32 hashvalue);
40 : :
41 : :
42 : : /*
43 : : * The Postgres user running this command has Postgres superuser privileges
44 : : */
45 : : bool
10226 bruce@momjian.us 46 :CBC 54221 : superuser(void)
47 : : {
8601 peter_e@gmx.net 48 : 54221 : return superuser_arg(GetUserId());
49 : : }
50 : :
51 : :
52 : : /*
53 : : * The specified role has Postgres superuser privileges
54 : : */
55 : : bool
7375 tgl@sss.pgh.pa.us 56 : 3379807 : superuser_arg(Oid roleid)
57 : : {
58 : : bool result;
59 : : HeapTuple rtup;
60 : :
61 : : /* Quick out for cache hit */
62 [ + + + + ]: 3379807 : if (OidIsValid(last_roleid) && last_roleid == roleid)
63 : 3149256 : return last_roleid_is_super;
64 : :
65 : : /* Special escape path in case you deleted all your users. */
66 [ + + + + ]: 230551 : if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID)
8764 peter_e@gmx.net 67 : 198997 : return true;
68 : :
69 : : /* OK, look up the information in pg_authid */
5683 rhaas@postgresql.org 70 : 31554 : rtup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
7375 tgl@sss.pgh.pa.us 71 [ + + ]: 31554 : if (HeapTupleIsValid(rtup))
72 : : {
3910 alvherre@alvh.no-ip. 73 : 31548 : result = ((Form_pg_authid) GETSTRUCT(rtup))->rolsuper;
7375 tgl@sss.pgh.pa.us 74 : 31548 : ReleaseSysCache(rtup);
75 : : }
76 : : else
77 : : {
78 : : /* Report "not superuser" for invalid roleids */
7405 79 : 6 : result = false;
80 : : }
81 : :
82 : : /* If first time through, set up callback for cache flushes */
7375 83 [ + + ]: 31554 : if (!roleid_callback_registered)
84 : : {
85 : 13922 : CacheRegisterSyscacheCallback(AUTHOID,
86 : : RoleidCallback,
87 : : (Datum) 0);
88 : 13922 : roleid_callback_registered = true;
89 : : }
90 : :
91 : : /* Cache the result for next time */
92 : 31554 : last_roleid = roleid;
93 : 31554 : last_roleid_is_super = result;
94 : :
8851 95 : 31554 : return result;
96 : : }
97 : :
98 : : /*
99 : : * RoleidCallback
100 : : * Syscache inval callback function
101 : : */
102 : : static void
5135 103 : 16311 : RoleidCallback(Datum arg, int cacheid, uint32 hashvalue)
104 : : {
105 : : /* Invalidate our local cache in case role's superuserness changed */
7375 106 : 16311 : last_roleid = InvalidOid;
7405 107 : 16311 : }
|