From ea886339b8406674ebceb456e5ef1b4fc7c170b4 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 27 Jun 2003 19:08:38 +0000
Subject: [PATCH] Add is_superuser parameter reporting, soon to be used by
 psql.

---
 doc/src/sgml/libpq.sgml           |  5 +++--
 doc/src/sgml/protocol.sgml        |  5 +++--
 doc/src/sgml/ref/show.sgml        | 12 +++++++++++-
 src/backend/commands/variable.c   | 27 +++++++++++++++++----------
 src/backend/utils/init/miscinit.c | 18 ++++++++++++++----
 src/backend/utils/misc/check_guc  |  9 ++++++---
 src/backend/utils/misc/guc.c      | 11 ++++++++++-
 src/include/miscadmin.h           |  4 ++--
 8 files changed, 66 insertions(+), 25 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index b41ba1e172c..ce70d6eb6be 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.126 2003/06/22 00:29:29 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.127 2003/06/27 19:08:37 tgl Exp $
 -->
 
  <chapter id="libpq">
@@ -812,7 +812,8 @@ is not known.
 Parameters reported as of the current release include
 <literal>server_version</> (cannot change after startup);
 <literal>server_encoding</> (also not presently changeable after start);
-<literal>client_encoding</>, and
+<literal>client_encoding</>,
+<literal>is_superuser</>, and
 <literal>DateStyle</>.
 </para>
 
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 2d5b5d8c222..75fe6b3982e 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1,4 +1,4 @@
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.38 2003/05/08 14:35:24 tgl Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.39 2003/06/27 19:08:37 tgl Exp $ -->
 
 <chapter id="protocol">
  <title>Frontend/Backend Protocol</title>
@@ -998,7 +998,8 @@
     <literal>server_version</> (a pseudo-parameter that cannot change after
     startup);
     <literal>server_encoding</> (also not presently changeable after start);
-    <literal>client_encoding</>, and
+    <literal>client_encoding</>,
+    <literal>is_superuser</>, and
     <literal>DateStyle</>.
     This set might change in the future, or even become configurable.
     Accordingly, a frontend should simply ignore ParameterStatus for
diff --git a/doc/src/sgml/ref/show.sgml b/doc/src/sgml/ref/show.sgml
index 0232d97dfce..09619bb4827 100644
--- a/doc/src/sgml/ref/show.sgml
+++ b/doc/src/sgml/ref/show.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/show.sgml,v 1.27 2003/05/14 03:26:00 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/show.sgml,v 1.28 2003/06/27 19:08:37 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -97,6 +97,16 @@ SHOW ALL
          </para>
         </listitem>
        </varlistentry>
+
+       <varlistentry>
+        <term><literal>IS_SUPERUSER</literal></term>
+        <listitem>
+         <para>
+          True if the current session authorization identifier has
+	  superuser privileges.
+         </para>
+        </listitem>
+       </varlistentry>
       </variablelist>
      </para>
     </listitem>
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 1b2f8477521..3dd4724f774 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.78 2003/06/06 16:25:35 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.79 2003/06/27 19:08:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -721,25 +721,29 @@ assign_client_encoding(const char *value, bool doit, bool interactive)
  * When resetting session auth after an error, we can't expect to do catalog
  * lookups.  Hence, the stored form of the value must provide a numeric userid
  * that can be re-used directly.  We store the string in the form of
- * NAMEDATALEN 'x's followed by the numeric userid --- this cannot conflict
- * with any valid user name, because of the NAMEDATALEN limit on names.
+ * NAMEDATALEN 'x's, followed by T or F to indicate superuserness, followed
+ * by the numeric userid --- this cannot conflict with any valid user name,
+ * because of the NAMEDATALEN limit on names.
  */
 const char *
 assign_session_authorization(const char *value, bool doit, bool interactive)
 {
 	AclId		usesysid = 0;
+	bool		is_superuser = false;
 	char	   *result;
 
-	if (strspn(value, "x") == NAMEDATALEN)
+	if (strspn(value, "x") == NAMEDATALEN &&
+		(value[NAMEDATALEN] == 'T' || value[NAMEDATALEN] == 'F'))
 	{
 		/* might be a saved numeric userid */
 		char	   *endptr;
 
-		usesysid = (AclId) strtoul(value + NAMEDATALEN, &endptr, 10);
+		usesysid = (AclId) strtoul(value + NAMEDATALEN + 1, &endptr, 10);
 
-		if (endptr != value + NAMEDATALEN && *endptr == '\0')
+		if (endptr != value + NAMEDATALEN + 1 && *endptr == '\0')
 		{
-			/* syntactically valid, so use the numeric user ID */
+			/* syntactically valid, so use the numeric user ID and flag */
+			is_superuser = (value[NAMEDATALEN] == 'T');
 		}
 		else
 			usesysid = 0;
@@ -771,12 +775,13 @@ assign_session_authorization(const char *value, bool doit, bool interactive)
 		}
 
 		usesysid = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
-
+		is_superuser = ((Form_pg_shadow) GETSTRUCT(userTup))->usesuper;
+		
 		ReleaseSysCache(userTup);
 	}
 
 	if (doit)
-		SetSessionAuthorization(usesysid);
+		SetSessionAuthorization(usesysid, is_superuser);
 
 	result = (char *) malloc(NAMEDATALEN + 32);
 	if (!result)
@@ -784,7 +789,9 @@ assign_session_authorization(const char *value, bool doit, bool interactive)
 
 	memset(result, 'x', NAMEDATALEN);
 
-	snprintf(result + NAMEDATALEN, 32, "%lu", (unsigned long) usesysid);
+	snprintf(result + NAMEDATALEN, 32, "%c%lu",
+			 is_superuser ? 'T' : 'F',
+			 (unsigned long) usesysid);
 
 	return result;
 }
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index c3dc38f387d..4d65f619be4 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.103 2003/06/27 14:45:30 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.104 2003/06/27 19:08:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -553,9 +553,12 @@ InitializeSessionUserId(const char *username)
 
 	SetSessionUserId(usesysid); /* sets CurrentUserId too */
 
-	/* Record username as a config option too */
+	/* Record username and superuser status as GUC settings too */
 	SetConfigOption("session_authorization", username,
 					PGC_BACKEND, PGC_S_OVERRIDE);
+	SetConfigOption("is_superuser",
+					AuthenticatedUserIsSuperuser ? "on" : "off",
+					PGC_INTERNAL, PGC_S_OVERRIDE);
 
 	/*
 	 * Set up user-specific configuration variables.  This is a good place
@@ -594,10 +597,13 @@ InitializeSessionUserIdStandalone(void)
 /*
  * Change session auth ID while running
  *
- * Only a superuser may set auth ID to something other than himself.
+ * Only a superuser may set auth ID to something other than himself.  Note
+ * that in case of multiple SETs in a single session, the original userid's
+ * superuserness is what matters.  But we set the GUC variable is_superuser
+ * to indicate whether the *current* session userid is a superuser.
  */
 void
-SetSessionAuthorization(AclId userid)
+SetSessionAuthorization(AclId userid, bool is_superuser)
 {
 	/* Must have authenticated already, else can't make permission check */
 	AssertState(AclIdIsValid(AuthenticatedUserId));
@@ -608,6 +614,10 @@ SetSessionAuthorization(AclId userid)
 
 	SetSessionUserId(userid);
 	SetUserId(userid);
+
+	SetConfigOption("is_superuser",
+					is_superuser ? "on" : "off",
+					PGC_INTERNAL, PGC_S_OVERRIDE);
 }
 
 
diff --git a/src/backend/utils/misc/check_guc b/src/backend/utils/misc/check_guc
index 7930d06f6e6..5b545d5f436 100755
--- a/src/backend/utils/misc/check_guc
+++ b/src/backend/utils/misc/check_guc
@@ -16,9 +16,12 @@
 ## if an option is valid but shows up in only one file (guc.c but not
 ## postgresql.conf.sample), it should be listed here so that it 
 ## can be ignored
-INTENTIONALLY_NOT_INCLUDED="pre_auth_delay lc_messages lc_monetary \
-lc_numeric lc_time seed server_encoding session_authorization \
-transaction_isolation transaction_read_only zero_damaged_pages"
+INTENTIONALLY_NOT_INCLUDED="autocommit debug_deadlocks exit_on_error \
+is_superuser lc_collate lc_ctype lc_messages lc_monetary lc_numeric lc_time \
+pre_auth_delay seed server_encoding server_version session_authorization \
+trace_lock_oidmin trace_lock_table trace_locks trace_lwlocks trace_notify \
+trace_userlocks transaction_isolation transaction_read_only \
+zero_damaged_pages"
 
 ### What options are listed in postgresql.conf.sample, but don't appear 
 ### in guc.c?
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index f1582b8c5b5..dfdc4f82e7f 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.131 2003/06/11 22:13:22 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.132 2003/06/27 19:08:38 tgl Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -138,6 +138,7 @@ static char *log_min_error_statement_str;
 static char *log_min_messages_str;
 static char *client_min_messages_str;
 static bool phony_autocommit;
+static bool session_auth_is_superuser;
 static double phony_random_seed;
 static char *client_encoding_string;
 static char *datestyle_string;
@@ -361,6 +362,13 @@ static struct config_bool
 		true, NULL, NULL
 	},
 
+	/* Not for general use --- used by SET SESSION AUTHORIZATION */
+	{
+		{"is_superuser", PGC_INTERNAL, GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL},
+		&session_auth_is_superuser,
+		false, NULL, NULL
+	},
+
 	{
 		{"tcpip_socket", PGC_POSTMASTER}, &NetServer,
 		false, NULL, NULL
@@ -894,6 +902,7 @@ static struct config_string
 		"SQL_ASCII", NULL, NULL
 	},
 
+	/* Can't be set in postgresql.conf */
 	{
 		{"server_version", PGC_INTERNAL, GUC_REPORT},
 		&server_version_string,
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index f88b9835045..213d2581333 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: miscadmin.h,v 1.124 2003/06/27 14:45:31 petere Exp $
+ * $Id: miscadmin.h,v 1.125 2003/06/27 19:08:38 tgl Exp $
  *
  * NOTES
  *	  some of the information in this file should be moved to
@@ -208,7 +208,7 @@ extern AclId GetSessionUserId(void);
 extern void SetSessionUserId(AclId userid);
 extern void InitializeSessionUserId(const char *username);
 extern void InitializeSessionUserIdStandalone(void);
-extern void SetSessionAuthorization(AclId userid);
+extern void SetSessionAuthorization(AclId userid, bool is_superuser);
 
 extern void SetDataDir(const char *dir);
 
-- 
GitLab