From 282278899379a3a57fbc734bda6a4dc9cec3ce60 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 6 May 2002 19:47:30 +0000 Subject: [PATCH] Accept SET SESSION AUTHORIZATION DEFAULT and RESET SESSION AUTHORIZATION 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 | 26 ++++++++++++++------ src/backend/commands/variable.c | 16 ++++++++++++- src/backend/parser/gram.y | 29 +++++++++++++++++----- src/backend/utils/init/miscinit.c | 44 ++++++++++++++++++++++++---------- 4 files changed, 88 insertions(+), 27 deletions(-) diff --git a/doc/src/sgml/ref/set_session_auth.sgml b/doc/src/sgml/ref/set_session_auth.sgml index fa427c1025..7cd0d7d1ec 100644 --- a/doc/src/sgml/ref/set_session_auth.sgml +++ b/doc/src/sgml/ref/set_session_auth.sgml @@ -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. + + diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index 301a3c86a7..de42538bd6 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.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); } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 1d1b7a78a2..258a11c118 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -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); diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 91c5a3eb2f..4cc9d396c7 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.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); -- 2.11.0