Accept SET SESSION AUTHORIZATION DEFAULT and RESET SESSION AUTHORIZATION
authorTom Lane
Mon, 6 May 2002 19:47:30 +0000 (19:47 +0000)
committerTom Lane
Mon, 6 May 2002 19:47:30 +0000 (19:47 +0000)
to reset session userid to the originally-authenticated name.  Also,
relax SET SESSION AUTHORIZATION to allow specifying one's own username
even if one is not superuser, so as to avoid unnecessary error messages
when loading a pg_dump file that uses this command.  Per discussion from
several months ago.

doc/src/sgml/ref/set_session_auth.sgml
src/backend/commands/variable.c
src/backend/parser/gram.y
src/backend/utils/init/miscinit.c

index fa427c10259e7735afffa9c73ba38bde1e958c8a..7cd0d7d1ec7195713e5f23ac9044d77fa710a7fd 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
  
   2001-04-21
@@ -16,7 +16,9 @@
 
  
 
-SET SESSION AUTHORIZATION 'username'
+SET SESSION AUTHORIZATION username
+SET SESSION AUTHORIZATION DEFAULT
+RESET SESSION AUTHORIZATION
 
  
 
@@ -26,7 +28,11 @@ SET SESSION AUTHORIZATION 'username'
   
    This command sets the session user identifier and the current user
    identifier of the current SQL-session context to be
-   username.
+   username.  The user name may be written as
+   either an identifier or a string literal.
+   The session user identifier is valid for the duration of a
+   connection; for example, it is possible to temporarily become an
+   unprivileged user and later switch back to become a superuser.
   
 
   
@@ -39,12 +45,18 @@ SET SESSION AUTHORIZATION 'username'
   
 
   
-   Execution of this command is only permitted if the initial session
+   The session user identifier may be changed only if the initial session
    user (the authenticated user) had the
-   superuser privilege.  This permission is kept for the duration of a
-   connection; for example, it is possible to temporarily become an
-   unprivileged user and later switch back to become a superuser.
+   superuser privilege.  Otherwise, the command is accepted only if it
+   specifies the authenticated username.
   
+
+  
+   The DEFAULT and RESET forms reset the session
+   and current user identifiers to be the originally authenticated user
+   name.  These forms are always accepted.
+  
+
  
 
  
index 301a3c86a7449f574edbd333f1ce0d3f91711ab5..de42538bd63107c41fe4bce5de70450f4c10c881 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.65 2002/04/22 15:13:53 thomas Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.66 2002/05/06 19:47:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -815,6 +815,15 @@ reset_server_encoding(void)
 }
 
 
+static bool
+show_session_authorization(void)
+{
+   elog(INFO, "Current session authorization is '%s'",
+        GetUserName(GetSessionUserId()));
+   return TRUE;
+}
+
+
 
 /* SetPGVariable()
  * Dispatcher for handling SET commands.
@@ -902,6 +911,8 @@ GetPGVariable(const char *name)
        show_server_encoding();
    else if (strcasecmp(name, "seed") == 0)
        show_random_seed();
+   else if (strcasecmp(name, "session_authorization") == 0)
+       show_session_authorization();
    else if (strcasecmp(name, "all") == 0)
    {
        ShowAllGUCConfig();
@@ -935,6 +946,8 @@ ResetPGVariable(const char *name)
        reset_server_encoding();
    else if (strcasecmp(name, "seed") == 0)
        reset_random_seed();
+   else if (strcasecmp(name, "session_authorization") == 0)
+       SetSessionAuthorization(NULL);
    else if (strcasecmp(name, "all") == 0)
    {
        reset_random_seed();
@@ -942,6 +955,7 @@ ResetPGVariable(const char *name)
        reset_client_encoding();
        reset_datestyle();
        reset_timezone();
+       /* should we reset session authorization here? */
 
        ResetAllOptions(false);
    }
index 1d1b7a78a29b9c79a742063150ce5fff922b0101..258a11c11832c2cec6ff72442b3367d826a65480 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.312 2002/05/03 00:32:16 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.313 2002/05/06 19:47:30 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -281,7 +281,7 @@ static void doNegateFloat(Value *v);
 %type    Iconst
 %type         Sconst, comment_text
 %type         UserId, opt_boolean, ColId_or_Sconst
-%type    var_list
+%type    var_list, var_list_or_default
 %type         ColId, ColLabel, type_name
 %type    var_value, zone_value
 
@@ -833,14 +833,14 @@ schema_stmt: CreateStmt
  *
  *****************************************************************************/
 
-VariableSetStmt:  SET ColId TO var_list
+VariableSetStmt:  SET ColId TO var_list_or_default
                {
                    VariableSetStmt *n = makeNode(VariableSetStmt);
                    n->name  = $2;
                    n->args = $4;
                    $$ = (Node *) n;
                }
-       | SET ColId '=' var_list
+       | SET ColId '=' var_list_or_default
                {
                    VariableSetStmt *n = makeNode(VariableSetStmt);
                    n->name  = $2;
@@ -884,14 +884,25 @@ VariableSetStmt:  SET ColId TO var_list
                    n->args = makeList1(makeStringConst($4, NULL));
                    $$ = (Node *) n;
                }
+       | SET SESSION AUTHORIZATION DEFAULT
+               {
+                   VariableSetStmt *n = makeNode(VariableSetStmt);
+                   n->name = "session_authorization";
+                   n->args = NIL;
+                   $$ = (Node *) n;
+               }
+       ;
+
+var_list_or_default:  var_list
+               { $$ = $1; }
+       | DEFAULT
+               { $$ = NIL; }
        ;
 
 var_list:  var_value
                {   $$ = makeList1($1); }
        | var_list ',' var_value
                {   $$ = lappend($1, $3); }
-       | DEFAULT
-               { $$ = NIL; }
        ;
 
 var_value:  opt_boolean
@@ -1017,6 +1028,12 @@ VariableResetStmt:   RESET ColId
                    n->name  = "XactIsoLevel";
                    $$ = (Node *) n;
                }
+       | RESET SESSION AUTHORIZATION
+               {
+                   VariableResetStmt *n = makeNode(VariableResetStmt);
+                   n->name = "session_authorization";
+                   $$ = (Node *) n;
+               }
        | RESET ALL
                {
                    VariableResetStmt *n = makeNode(VariableResetStmt);
index 91c5a3eb2f5240af4d613e74c042fe57d23a1955..4cc9d396c70b470a460396d3261dfea903fac9e7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.89 2002/05/05 00:03:29 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.90 2002/05/06 19:47:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -529,15 +529,17 @@ GetCharSetByHost(char *TableName, int host, const char *DataDir)
 /* ----------------------------------------------------------------
  * User ID things
  *
- * The session user is determined at connection start and never
- * changes.  The current user may change when "setuid" functions
+ * The authenticated user is determined at connection start and never
+ * changes.  The session user can be changed only by SET SESSION
+ * AUTHORIZATION.  The current user may change when "setuid" functions
  * are implemented.  Conceptually there is a stack, whose bottom
  * is the session user.  You are yourself responsible to save and
  * restore the current user id if you need to change it.
  * ----------------------------------------------------------------
  */
-static Oid CurrentUserId = InvalidOid;
+static Oid AuthenticatedUserId = InvalidOid;
 static Oid SessionUserId = InvalidOid;
+static Oid CurrentUserId = InvalidOid;
 
 static bool AuthenticatedUserIsSuperuser = false;
 
@@ -588,6 +590,7 @@ InitializeSessionUserId(const char *username)
    HeapTuple   userTup;
    Datum       datum;
    bool        isnull;
+   Oid         usesysid;
 
    /*
     * Don't do scans if we're bootstrapping, none of the system catalogs
@@ -596,7 +599,7 @@ InitializeSessionUserId(const char *username)
    AssertState(!IsBootstrapProcessingMode());
 
    /* call only once */
-   AssertState(!OidIsValid(SessionUserId));
+   AssertState(!OidIsValid(AuthenticatedUserId));
 
    userTup = SearchSysCache(SHADOWNAME,
                             PointerGetDatum(username),
@@ -604,10 +607,14 @@ InitializeSessionUserId(const char *username)
    if (!HeapTupleIsValid(userTup))
        elog(FATAL, "user \"%s\" does not exist", username);
 
-   SetSessionUserId(((Form_pg_shadow) GETSTRUCT(userTup))->usesysid);
+   usesysid = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
 
+   AuthenticatedUserId = usesysid;
    AuthenticatedUserIsSuperuser = ((Form_pg_shadow) GETSTRUCT(userTup))->usesuper;
 
+   SetSessionUserId(usesysid); /* sets CurrentUserId too */
+
+
    /*
     * Set up user-specific configuration variables.  This is a good
     * place to do it so we don't have to read pg_shadow twice during
@@ -633,25 +640,36 @@ InitializeSessionUserIdStandalone(void)
    AssertState(!IsUnderPostmaster);
 
    /* call only once */
-   AssertState(!OidIsValid(SessionUserId));
+   AssertState(!OidIsValid(AuthenticatedUserId));
 
-   SetSessionUserId(BOOTSTRAP_USESYSID);
+   AuthenticatedUserId = BOOTSTRAP_USESYSID;
    AuthenticatedUserIsSuperuser = true;
+
+   SetSessionUserId(BOOTSTRAP_USESYSID);
 }
 
 
 /*
  * Change session auth ID while running
+ *
+ * Only a superuser may set auth ID to something other than himself.
+ *
+ * username == NULL implies reset to default (AuthenticatedUserId).
  */
 void
 SetSessionAuthorization(const char *username)
 {
-   int32       userid;
-
-   if (!AuthenticatedUserIsSuperuser)
-       elog(ERROR, "permission denied");
+   Oid     userid;
 
-   userid = get_usesysid(username);
+   if (username == NULL)
+       userid = AuthenticatedUserId;
+   else
+   {
+       userid = get_usesysid(username);
+       if (userid != AuthenticatedUserId &&
+           !AuthenticatedUserIsSuperuser)
+           elog(ERROR, "permission denied");
+   }
 
    SetSessionUserId(userid);
    SetUserId(userid);