Header And Logo

PostgreSQL
| The world's most advanced open source database.

superuser.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * superuser.c
00004  *    The superuser() function.  Determines if user has superuser privilege.
00005  *
00006  * All code should use either of these two functions to find out
00007  * whether a given user is a superuser, rather than examining
00008  * pg_authid.rolsuper directly, so that the escape hatch built in for
00009  * the single-user case works.
00010  *
00011  *
00012  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00013  * Portions Copyright (c) 1994, Regents of the University of California
00014  *
00015  *
00016  * IDENTIFICATION
00017  *    src/backend/utils/misc/superuser.c
00018  *
00019  *-------------------------------------------------------------------------
00020  */
00021 #include "postgres.h"
00022 
00023 #include "access/htup_details.h"
00024 #include "catalog/pg_authid.h"
00025 #include "utils/inval.h"
00026 #include "utils/syscache.h"
00027 #include "miscadmin.h"
00028 
00029 
00030 /*
00031  * In common cases the same roleid (ie, the session or current ID) will
00032  * be queried repeatedly.  So we maintain a simple one-entry cache for
00033  * the status of the last requested roleid.  The cache can be flushed
00034  * at need by watching for cache update events on pg_authid.
00035  */
00036 static Oid  last_roleid = InvalidOid;   /* InvalidOid == cache not valid */
00037 static bool last_roleid_is_super = false;
00038 static bool roleid_callback_registered = false;
00039 
00040 static void RoleidCallback(Datum arg, int cacheid, uint32 hashvalue);
00041 
00042 
00043 /*
00044  * The Postgres user running this command has Postgres superuser privileges
00045  */
00046 bool
00047 superuser(void)
00048 {
00049     return superuser_arg(GetUserId());
00050 }
00051 
00052 
00053 /*
00054  * The specified role has Postgres superuser privileges
00055  */
00056 bool
00057 superuser_arg(Oid roleid)
00058 {
00059     bool        result;
00060     HeapTuple   rtup;
00061 
00062     /* Quick out for cache hit */
00063     if (OidIsValid(last_roleid) && last_roleid == roleid)
00064         return last_roleid_is_super;
00065 
00066     /* Special escape path in case you deleted all your users. */
00067     if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID)
00068         return true;
00069 
00070     /* OK, look up the information in pg_authid */
00071     rtup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
00072     if (HeapTupleIsValid(rtup))
00073     {
00074         result = ((Form_pg_authid) GETSTRUCT(rtup))->rolsuper;
00075         ReleaseSysCache(rtup);
00076     }
00077     else
00078     {
00079         /* Report "not superuser" for invalid roleids */
00080         result = false;
00081     }
00082 
00083     /* If first time through, set up callback for cache flushes */
00084     if (!roleid_callback_registered)
00085     {
00086         CacheRegisterSyscacheCallback(AUTHOID,
00087                                       RoleidCallback,
00088                                       (Datum) 0);
00089         roleid_callback_registered = true;
00090     }
00091 
00092     /* Cache the result for next time */
00093     last_roleid = roleid;
00094     last_roleid_is_super = result;
00095 
00096     return result;
00097 }
00098 
00099 /*
00100  * RoleidCallback
00101  *      Syscache inval callback function
00102  */
00103 static void
00104 RoleidCallback(Datum arg, int cacheid, uint32 hashvalue)
00105 {
00106     /* Invalidate our local cache in case role's superuserness changed */
00107     last_roleid = InvalidOid;
00108 }