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-2024, 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
9716 bruce@momjian.us 46 :CBC 47817 : superuser(void)
47 : : {
8091 peter_e@gmx.net 48 : 47817 : return superuser_arg(GetUserId());
49 : : }
50 : :
51 : :
52 : : /*
53 : : * The specified role has Postgres superuser privileges
54 : : */
55 : : bool
6865 tgl@sss.pgh.pa.us 56 : 3224938 : superuser_arg(Oid roleid)
57 : : {
58 : : bool result;
59 : : HeapTuple rtup;
60 : :
61 : : /* Quick out for cache hit */
62 [ + + + + ]: 3224938 : if (OidIsValid(last_roleid) && last_roleid == roleid)
63 : 3045132 : return last_roleid_is_super;
64 : :
65 : : /* Special escape path in case you deleted all your users. */
66 [ + + + + ]: 179806 : if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID)
8254 peter_e@gmx.net 67 : 150002 : return true;
68 : :
69 : : /* OK, look up the information in pg_authid */
5173 rhaas@postgresql.org 70 : 29804 : rtup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
6865 tgl@sss.pgh.pa.us 71 [ + + ]: 29804 : if (HeapTupleIsValid(rtup))
72 : : {
3400 alvherre@alvh.no-ip. 73 : 29801 : result = ((Form_pg_authid) GETSTRUCT(rtup))->rolsuper;
6865 tgl@sss.pgh.pa.us 74 : 29801 : ReleaseSysCache(rtup);
75 : : }
76 : : else
77 : : {
78 : : /* Report "not superuser" for invalid roleids */
6895 79 : 3 : result = false;
80 : : }
81 : :
82 : : /* If first time through, set up callback for cache flushes */
6865 83 [ + + ]: 29804 : if (!roleid_callback_registered)
84 : : {
85 : 13653 : CacheRegisterSyscacheCallback(AUTHOID,
86 : : RoleidCallback,
87 : : (Datum) 0);
88 : 13653 : roleid_callback_registered = true;
89 : : }
90 : :
91 : : /* Cache the result for next time */
92 : 29804 : last_roleid = roleid;
93 : 29804 : last_roleid_is_super = result;
94 : :
8341 95 : 29804 : return result;
96 : : }
97 : :
98 : : /*
99 : : * RoleidCallback
100 : : * Syscache inval callback function
101 : : */
102 : : static void
4625 103 : 16010 : RoleidCallback(Datum arg, int cacheid, uint32 hashvalue)
104 : : {
105 : : /* Invalidate our local cache in case role's superuserness changed */
6865 106 : 16010 : last_roleid = InvalidOid;
6895 107 : 16010 : }
|