From: Peter Eisentraut Date: Tue, 19 Sep 2000 18:18:04 +0000 (+0000) Subject: Implement differentiation between CURRENT_USER and SESSION_USER as per SQL. X-Git-Tag: REL7_1_BETA~652 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=457ac0331cd3e28ecc5d783e7504645837c41a1d;p=postgresql Implement differentiation between CURRENT_USER and SESSION_USER as per SQL. There is still no effective difference but it will kick in once setuid functions exist (not included here). Make old getpgusername() alias for current_user. --- diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 593041a587..3e3266cf5f 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -1,5 +1,5 @@ @@ -211,11 +211,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.35 2000/08/29 20:02:07 mo - - getpgusername() - current_user - user name in current session - date('now') current_date diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 9f8fdd8932..0306f7cf05 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1509,6 +1509,61 @@ Not defined by this name. Implements the intersection operator '#' + + Miscellaneous Functions</> + + <table> + <title>Miscellaneous Functions</> + <tgroup cols="3"> + <thead> + <row><entry>Name</> <entry>Return type</> <entry>Description</></row> + </thead> + + <tbody> + <row> + <entry>current_user</> + <entry>name</> + <entry>user name of current execution context</> + </row> + <row> + <entry>user</> + <entry>name</> + <entry>equivalent to <function>current_user</></> + </row> + <row> + <entry>session_user</> + <entry>name</> + <entry>session user name</> + </row> + </tbody> + </tgroup> + </table> + + <para> + The <function>session_user</> is the user that initiated a database + connection and is fixed for the duration of that connection. The + <function>current_user</> is the user identifier that is applicable + for permission checking. Currently it is always equal to the session + user, but in the future there might be <quote>setuid</> functions and + other facilities to allow the current user to change temporarily. + In Unix parlance, the session user is the <quote>real user</> + and the current user is the <quote>effective user</>. + </para> + + <para> + Note that these functions have special syntactic status in <acronym>SQL</>; + they must be called without trailing parentheses. + </para> + + <note> + <title>Deprecated</> + <para> + The function <function>getpgusername()</> is an obsolete equivalent + of <function>current_user</>. + </para> + </note> + </sect1> + <sect1> <title id="aggregate-funcs">Aggregate Functions diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 25150818a7..cc57eb7068 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.67 2000/08/27 21:50:17 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.68 2000/09/19 18:17:54 petere Exp $ * *------------------------------------------------------------------------- */ @@ -348,7 +348,7 @@ AlterUser(AlterUserStmt *stmt) /* must be superuser or just want to change your own password */ if (!superuser() && !(stmt->createdb == 0 && stmt->createuser == 0 && !stmt->validUntil - && stmt->password && strcmp(GetPgUserName(), stmt->user) == 0)) + && stmt->password && strcmp(GetUserName(GetUserId()), stmt->user) == 0)) elog(ERROR, "ALTER USER: permission denied"); /* changes to the flat password file cannot be rolled back */ diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index c12cf997b7..a422bf705a 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.190 2000/09/15 18:45:30 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.191 2000/09/19 18:17:55 petere Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -4993,7 +4993,7 @@ c_expr: attr | CURRENT_USER { FuncCall *n = makeNode(FuncCall); - n->funcname = "getpgusername"; + n->funcname = "current_user"; n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; @@ -5002,7 +5002,7 @@ c_expr: attr | SESSION_USER { FuncCall *n = makeNode(FuncCall); - n->funcname = "getpgusername"; + n->funcname = "session_user"; n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; @@ -5011,7 +5011,7 @@ c_expr: attr | USER { FuncCall *n = makeNode(FuncCall); - n->funcname = "getpgusername"; + n->funcname = "current_user"; n->args = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; diff --git a/src/backend/utils/adt/name.c b/src/backend/utils/adt/name.c index 3acf40e0d4..edc14303d4 100644 --- a/src/backend/utils/adt/name.c +++ b/src/backend/utils/adt/name.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/name.c,v 1.29 2000/08/03 16:34:22 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/name.c,v 1.30 2000/09/19 18:17:56 petere Exp $ * *------------------------------------------------------------------------- */ @@ -136,13 +136,6 @@ namege(PG_FUNCTION_ARGS) PG_RETURN_BOOL(strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN) >= 0); } -/* SQL-function interface to GetPgUserName() */ -Datum -getpgusername(PG_FUNCTION_ARGS) -{ - PG_RETURN_DATUM(DirectFunctionCall1(namein, - CStringGetDatum(GetPgUserName()))); -} /* (see char.c for comparison/operation routines) */ @@ -218,6 +211,21 @@ namestrcmp(Name name, const char *str) return strncmp(NameStr(*name), str, NAMEDATALEN); } + +/* SQL-functions CURRENT_USER and SESSION_USER */ +Datum +current_user(PG_FUNCTION_ARGS) +{ + PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserName(GetUserId())))); +} + +Datum +session_user(PG_FUNCTION_ARGS) +{ + PG_RETURN_DATUM(DirectFunctionCall1(namein, CStringGetDatum(GetUserName(GetSessionUserId())))); +} + + /***************************************************************************** * PRIVATE ROUTINES * *****************************************************************************/ diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 20babcc616..0974a05715 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.54 2000/09/06 14:15:22 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.55 2000/09/19 18:17:57 petere Exp $ * *------------------------------------------------------------------------- */ @@ -272,50 +272,65 @@ convertstr(unsigned char *buff, int len, int dest) #endif -/* ---------------- - * GetPgUserName - * ---------------- - */ -char * -GetPgUserName(void) -{ - HeapTuple tuple; - Oid userid; - - userid = GetUserId(); - - tuple = SearchSysCacheTuple(SHADOWSYSID, ObjectIdGetDatum(userid), 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "invalid user id %u", (unsigned) userid); - - return pstrdup( NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename) ); -} /* ---------------------------------------------------------------- - * GetUserId and SetUserId + * User ID things + * + * The session user is determined at connection start and never + * changes. 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 UserId = InvalidOid; +static Oid CurrentUserId = InvalidOid; +static Oid SessionUserId = InvalidOid; +/* + * This function is relevant for all privilege checks. + */ Oid -GetUserId() +GetUserId(void) { - AssertState(OidIsValid(UserId)); - return UserId; + AssertState(OidIsValid(CurrentUserId)); + return CurrentUserId; } void SetUserId(Oid newid) { - UserId = newid; + AssertArg(OidIsValid(newid)); + CurrentUserId = newid; +} + + +/* + * This value is only relevant for informational purposes. + */ +Oid +GetSessionUserId(void) +{ + AssertState(OidIsValid(SessionUserId)); + return SessionUserId; +} + + +void +SetSessionUserId(Oid newid) +{ + AssertArg(OidIsValid(newid)); + SessionUserId = newid; + /* Current user defaults to session user. */ + if (!OidIsValid(CurrentUserId)) + CurrentUserId = newid; } void -SetUserIdFromUserName(const char *username) +SetSessionUserIdFromUserName(const char *username) { HeapTuple userTup; @@ -330,13 +345,30 @@ SetUserIdFromUserName(const char *username) 0, 0, 0); if (!HeapTupleIsValid(userTup)) elog(FATAL, "user \"%s\" does not exist", username); - SetUserId( ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid ); + SetSessionUserId( ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid ); } +/* + * Get user name from user id + */ +char * +GetUserName(Oid userid) +{ + HeapTuple tuple; + + tuple = SearchSysCacheTuple(SHADOWSYSID, ObjectIdGetDatum(userid), 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "invalid user id %u", (unsigned) userid); + + return pstrdup( NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename) ); +} + + + /*------------------------------------------------------------------------- * - * posmaster pid file stuffs. $DATADIR/postmaster.pid is created when: + * postmaster pid file stuffs. $DATADIR/postmaster.pid is created when: * * (1) postmaster starts. In this case pid > 0. * (2) postgres starts in standalone mode. In this case diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index a9e083557e..c0502d99ab 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.65 2000/09/06 14:15:22 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.66 2000/09/19 18:17:57 petere Exp $ * * *------------------------------------------------------------------------- @@ -374,9 +374,9 @@ InitPostgres(const char *dbname, const char *username) * user id. */ if (bootstrap) - SetUserId(geteuid()); + SetSessionUserId(geteuid()); else - SetUserIdFromUserName(username); + SetSessionUserIdFromUserName(username); setuid(geteuid()); diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index e23b8b9cb5..ab9ee67703 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catversion.h,v 1.46 2000/09/15 18:45:27 tgl Exp $ + * $Id: catversion.h,v 1.47 2000/09/19 18:18:01 petere Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200009151 +#define CATALOG_VERSION_NO 200009191 #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index ac1dbabef1..4f2043fb02 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_proc.h,v 1.166 2000/09/15 18:45:27 tgl Exp $ + * $Id: pg_proc.h,v 1.167 2000/09/19 18:18:01 petere Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -928,8 +928,8 @@ DATA(insert OID = 681 ( oidvectorgt PGUID 12 f t t t 2 f 16 "30 30" 100 0 0 DESCR("greater-than"); /* OIDS 700 - 799 */ -DATA(insert OID = 710 ( getpgusername PGUID 12 f t f t 0 f 19 "0" 100 0 0 100 getpgusername - )); -DESCR("Return username"); +DATA(insert OID = 710 ( getpgusername PGUID 12 f t f t 0 f 19 "0" 100 0 0 100 current_user - )); +DESCR("deprecated -- use current_user"); DATA(insert OID = 711 ( userfntest PGUID 12 f t t t 1 f 23 "23" 100 0 0 100 userfntest - )); DESCR(""); DATA(insert OID = 713 ( oidrand PGUID 12 f t f t 2 f 16 "26 23" 100 0 0 100 oidrand - )); @@ -974,6 +974,12 @@ DESCR("greater-than-or-equal"); DATA(insert OID = 744 ( array_eq PGUID 12 f t t t 2 f 16 "0 0" 100 0 0 100 array_eq -)); DESCR("array equal"); + +DATA(insert OID = 745 ( current_user PGUID 12 f t f t 0 f 19 "0" 100 0 0 100 current_user - )); +DESCR("current user name"); +DATA(insert OID = 746 ( session_user PGUID 12 f t f t 0 f 19 "0" 100 0 0 100 session_user - )); +DESCR("session user name"); + DATA(insert OID = 747 ( array_dims PGUID 12 f t t t 1 f 25 "0" 100 0 0 100 array_dims -)); DESCR("array dimensions"); DATA(insert OID = 750 ( array_in PGUID 12 f t t t 3 f 23 "0 26 23" 100 0 0 100 array_in - )); diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 540b726668..2132b3bb28 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: miscadmin.h,v 1.66 2000/09/06 19:54:52 petere Exp $ + * $Id: miscadmin.h,v 1.67 2000/09/19 18:17:58 petere Exp $ * * NOTES * some of the information in this file will be moved to @@ -128,10 +128,14 @@ extern char *ExpandDatabasePath(const char *path); extern void SetDatabaseName(const char *name); extern void SetDatabasePath(const char *path); -extern char *GetPgUserName(void); -extern Oid GetUserId(void); +extern char *GetUserName(Oid userid); + +extern Oid GetUserId(void); extern void SetUserId(Oid userid); -extern void SetUserIdFromUserName(const char *username); +extern Oid GetSessionUserId(void); +extern void SetSessionUserId(Oid userid); +extern void SetSessionUserIdFromUserName(const char *username); + extern int FindExec(char *full_path, const char *argv0, const char *binary_name); extern int CheckPathAccess(char *path, char *name, int open_mode); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 054f3d5a7a..c0528bcecd 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: builtins.h,v 1.137 2000/09/15 18:45:29 tgl Exp $ + * $Id: builtins.h,v 1.138 2000/09/19 18:18:02 petere Exp $ * *------------------------------------------------------------------------- */ @@ -136,10 +136,11 @@ extern Datum namelt(PG_FUNCTION_ARGS); extern Datum namele(PG_FUNCTION_ARGS); extern Datum namegt(PG_FUNCTION_ARGS); extern Datum namege(PG_FUNCTION_ARGS); -extern Datum getpgusername(PG_FUNCTION_ARGS); extern int namecpy(Name n1, Name n2); extern int namestrcpy(Name name, const char *str); extern int namestrcmp(Name name, const char *str); +extern Datum current_user(PG_FUNCTION_ARGS); +extern Datum session_user(PG_FUNCTION_ARGS); /* numutils.c */ extern int32 pg_atoi(char *s, int size, int c); diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index eb19122cbc..11e1539778 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1231,9 +1231,9 @@ SELECT tablename, rulename, definition FROM pg_rules ORDER BY tablename, rulename; tablename | rulename | definition ---------------+-----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - rtest_emp | rtest_emp_del | CREATE RULE rtest_emp_del AS ON DELETE TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (old.ename, getpgusername(), 'fired '::bpchar, '$0.00'::money, old.salary); - rtest_emp | rtest_emp_ins | CREATE RULE rtest_emp_ins AS ON INSERT TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (new.ename, getpgusername(), 'hired '::bpchar, new.salary, '$0.00'::money); - rtest_emp | rtest_emp_upd | CREATE RULE rtest_emp_upd AS ON UPDATE TO rtest_emp WHERE (new.salary <> old.salary) DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (new.ename, getpgusername(), 'honored '::bpchar, new.salary, old.salary); + rtest_emp | rtest_emp_del | CREATE RULE rtest_emp_del AS ON DELETE TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (old.ename, "current_user"(), 'fired '::bpchar, '$0.00'::money, old.salary); + rtest_emp | rtest_emp_ins | CREATE RULE rtest_emp_ins AS ON INSERT TO rtest_emp DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (new.ename, "current_user"(), 'hired '::bpchar, new.salary, '$0.00'::money); + rtest_emp | rtest_emp_upd | CREATE RULE rtest_emp_upd AS ON UPDATE TO rtest_emp WHERE (new.salary <> old.salary) DO INSERT INTO rtest_emplog (ename, who, "action", newsal, oldsal) VALUES (new.ename, "current_user"(), 'honored '::bpchar, new.salary, old.salary); rtest_nothn1 | rtest_nothn_r1 | CREATE RULE rtest_nothn_r1 AS ON INSERT TO rtest_nothn1 WHERE ((new.a >= 10) AND (new.a < 20)) DO INSTEAD SELECT 1; rtest_nothn1 | rtest_nothn_r2 | CREATE RULE rtest_nothn_r2 AS ON INSERT TO rtest_nothn1 WHERE ((new.a >= 30) AND (new.a < 40)) DO INSTEAD NOTHING; rtest_nothn2 | rtest_nothn_r3 | CREATE RULE rtest_nothn_r3 AS ON INSERT TO rtest_nothn2 WHERE (new.a >= 100) DO INSTEAD INSERT INTO rtest_nothn3 (a, b) VALUES (new.a, new.b);