]> granicus.if.org Git - postgresql/blob - src/backend/utils/misc/superuser.c
Make all our flex and bison files use %option prefix or %name-prefix
[postgresql] / src / backend / utils / misc / superuser.c
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-2006, PostgreSQL Global Development Group
13  * Portions Copyright (c) 1994, Regents of the University of California
14  *
15  *
16  * IDENTIFICATION
17  *        $PostgreSQL: pgsql/src/backend/utils/misc/superuser.c,v 1.35 2006/03/05 15:58:49 momjian Exp $
18  *
19  *-------------------------------------------------------------------------
20  */
21 #include "postgres.h"
22
23 #include "catalog/pg_authid.h"
24 #include "utils/inval.h"
25 #include "utils/syscache.h"
26 #include "miscadmin.h"
27
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, Oid relid);
40
41
42 /*
43  * The Postgres user running this command has Postgres superuser privileges
44  */
45 bool
46 superuser(void)
47 {
48         return superuser_arg(GetUserId());
49 }
50
51
52 /*
53  * The specified role has Postgres superuser privileges
54  */
55 bool
56 superuser_arg(Oid roleid)
57 {
58         bool            result;
59         HeapTuple       rtup;
60
61         /* Quick out for cache hit */
62         if (OidIsValid(last_roleid) && last_roleid == roleid)
63                 return last_roleid_is_super;
64
65         /* Special escape path in case you deleted all your users. */
66         if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID)
67                 return true;
68
69         /* OK, look up the information in pg_authid */
70         rtup = SearchSysCache(AUTHOID,
71                                                   ObjectIdGetDatum(roleid),
72                                                   0, 0, 0);
73         if (HeapTupleIsValid(rtup))
74         {
75                 result = ((Form_pg_authid) GETSTRUCT(rtup))->rolsuper;
76                 ReleaseSysCache(rtup);
77         }
78         else
79         {
80                 /* Report "not superuser" for invalid roleids */
81                 result = false;
82         }
83
84         /* If first time through, set up callback for cache flushes */
85         if (!roleid_callback_registered)
86         {
87                 CacheRegisterSyscacheCallback(AUTHOID,
88                                                                           RoleidCallback,
89                                                                           (Datum) 0);
90                 roleid_callback_registered = true;
91         }
92
93         /* Cache the result for next time */
94         last_roleid = roleid;
95         last_roleid_is_super = result;
96
97         return result;
98 }
99
100 /*
101  * UseridCallback
102  *              Syscache inval callback function
103  */
104 static void
105 RoleidCallback(Datum arg, Oid relid)
106 {
107         /* Invalidate our local cache in case role's superuserness changed */
108         last_roleid = InvalidOid;
109 }