summaryrefslogtreecommitdiffstats
path: root/src/backend/utils/misc/superuser.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 13:44:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 13:44:03 +0000
commit293913568e6a7a86fd1479e1cff8e2ecb58d6568 (patch)
treefc3b469a3ec5ab71b36ea97cc7aaddb838423a0c /src/backend/utils/misc/superuser.c
parentInitial commit. (diff)
downloadpostgresql-16-293913568e6a7a86fd1479e1cff8e2ecb58d6568.tar.xz
postgresql-16-293913568e6a7a86fd1479e1cff8e2ecb58d6568.zip
Adding upstream version 16.2.upstream/16.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/backend/utils/misc/superuser.c')
-rw-r--r--src/backend/utils/misc/superuser.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
new file mode 100644
index 0000000..71c0e72
--- /dev/null
+++ b/src/backend/utils/misc/superuser.c
@@ -0,0 +1,107 @@
+/*-------------------------------------------------------------------------
+ *
+ * superuser.c
+ * The superuser() function. Determines if user has superuser privilege.
+ *
+ * All code should use either of these two functions to find out
+ * whether a given user is a superuser, rather than examining
+ * pg_authid.rolsuper directly, so that the escape hatch built in for
+ * the single-user case works.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/utils/misc/superuser.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup_details.h"
+#include "catalog/pg_authid.h"
+#include "miscadmin.h"
+#include "utils/inval.h"
+#include "utils/syscache.h"
+
+/*
+ * In common cases the same roleid (ie, the session or current ID) will
+ * be queried repeatedly. So we maintain a simple one-entry cache for
+ * the status of the last requested roleid. The cache can be flushed
+ * at need by watching for cache update events on pg_authid.
+ */
+static Oid last_roleid = InvalidOid; /* InvalidOid == cache not valid */
+static bool last_roleid_is_super = false;
+static bool roleid_callback_registered = false;
+
+static void RoleidCallback(Datum arg, int cacheid, uint32 hashvalue);
+
+
+/*
+ * The Postgres user running this command has Postgres superuser privileges
+ */
+bool
+superuser(void)
+{
+ return superuser_arg(GetUserId());
+}
+
+
+/*
+ * The specified role has Postgres superuser privileges
+ */
+bool
+superuser_arg(Oid roleid)
+{
+ bool result;
+ HeapTuple rtup;
+
+ /* Quick out for cache hit */
+ if (OidIsValid(last_roleid) && last_roleid == roleid)
+ return last_roleid_is_super;
+
+ /* Special escape path in case you deleted all your users. */
+ if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID)
+ return true;
+
+ /* OK, look up the information in pg_authid */
+ rtup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
+ if (HeapTupleIsValid(rtup))
+ {
+ result = ((Form_pg_authid) GETSTRUCT(rtup))->rolsuper;
+ ReleaseSysCache(rtup);
+ }
+ else
+ {
+ /* Report "not superuser" for invalid roleids */
+ result = false;
+ }
+
+ /* If first time through, set up callback for cache flushes */
+ if (!roleid_callback_registered)
+ {
+ CacheRegisterSyscacheCallback(AUTHOID,
+ RoleidCallback,
+ (Datum) 0);
+ roleid_callback_registered = true;
+ }
+
+ /* Cache the result for next time */
+ last_roleid = roleid;
+ last_roleid_is_super = result;
+
+ return result;
+}
+
+/*
+ * RoleidCallback
+ * Syscache inval callback function
+ */
+static void
+RoleidCallback(Datum arg, int cacheid, uint32 hashvalue)
+{
+ /* Invalidate our local cache in case role's superuserness changed */
+ last_roleid = InvalidOid;
+}