summaryrefslogtreecommitdiff
path: root/src/backend/commands/variable.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-07-25 22:12:34 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-07-25 22:12:34 +0000
commite5d6b91220d69c87f44e1ce0095516946abc6d6c (patch)
tree004dd158466d5b8e9322a8a78bd5f68d0253af4b /src/backend/commands/variable.c
parentf5df006a04bdaed8ca8e7595bdd5c7c037d65dab (diff)
downloadpostgresql-e5d6b91220d69c87f44e1ce0095516946abc6d6c.tar.gz
Add SET ROLE. This is a partial commit of Stephen Frost's recent patch;
I'm still working on the has_role function and information_schema changes.
Diffstat (limited to 'src/backend/commands/variable.c')
-rw-r--r--src/backend/commands/variable.c142
1 files changed, 141 insertions, 1 deletions
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 494ab6b491..9254d57e34 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/variable.c,v 1.111 2005/07/21 03:56:10 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/variable.c,v 1.112 2005/07/25 22:12:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,6 +24,7 @@
#include "miscadmin.h"
#include "parser/scansup.h"
#include "pgtime.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/syscache.h"
@@ -684,3 +685,142 @@ show_session_authorization(void)
return endptr + 1;
}
+
+
+/*
+ * SET ROLE
+ *
+ * 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 oid
+ * that can be re-used directly. We implement this exactly like SET
+ * SESSION AUTHORIZATION.
+ *
+ * The SQL spec requires "SET ROLE NONE" to unset the role, so we hardwire
+ * a translation of "none" to InvalidOid.
+ */
+extern char *role_string; /* in guc.c */
+
+const char *
+assign_role(const char *value, bool doit, GucSource source)
+{
+ Oid roleid = InvalidOid;
+ bool is_superuser = false;
+ const char *actual_rolename = value;
+ char *result;
+
+ if (strspn(value, "x") == NAMEDATALEN &&
+ (value[NAMEDATALEN] == 'T' || value[NAMEDATALEN] == 'F'))
+ {
+ /* might be a saved userid string */
+ Oid savedoid;
+ char *endptr;
+
+ savedoid = (Oid) strtoul(value + NAMEDATALEN + 1, &endptr, 10);
+
+ if (endptr != value + NAMEDATALEN + 1 && *endptr == ',')
+ {
+ /* syntactically valid, so break out the data */
+ roleid = savedoid;
+ is_superuser = (value[NAMEDATALEN] == 'T');
+ actual_rolename = endptr + 1;
+ }
+ }
+
+ if (roleid == InvalidOid &&
+ strcmp(actual_rolename, "none") != 0)
+ {
+ /* not a saved ID, so look it up */
+ HeapTuple roleTup;
+
+ if (!IsTransactionState())
+ {
+ /*
+ * Can't do catalog lookups, so fail. The upshot of this is
+ * that role cannot be set in postgresql.conf, which seems
+ * like a good thing anyway.
+ */
+ return NULL;
+ }
+
+ roleTup = SearchSysCache(AUTHNAME,
+ PointerGetDatum(value),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(roleTup))
+ {
+ if (source >= PGC_S_INTERACTIVE)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("role \"%s\" does not exist", value)));
+ return NULL;
+ }
+
+ roleid = HeapTupleGetOid(roleTup);
+ is_superuser = ((Form_pg_authid) GETSTRUCT(roleTup))->rolsuper;
+
+ ReleaseSysCache(roleTup);
+
+ /*
+ * Verify that session user is allowed to become this role
+ */
+ if (!is_member_of_role(GetSessionUserId(), roleid))
+ {
+ if (source >= PGC_S_INTERACTIVE)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied to set role \"%s\"",
+ value)));
+ return NULL;
+ }
+ }
+
+ if (doit)
+ SetCurrentRoleId(roleid, is_superuser);
+
+ result = (char *) malloc(NAMEDATALEN + 32 + strlen(actual_rolename));
+ if (!result)
+ return NULL;
+
+ memset(result, 'x', NAMEDATALEN);
+
+ sprintf(result + NAMEDATALEN, "%c%u,%s",
+ is_superuser ? 'T' : 'F',
+ roleid,
+ actual_rolename);
+
+ return result;
+}
+
+const char *
+show_role(void)
+{
+ /*
+ * Extract the role name from the stored string; see
+ * assign_role
+ */
+ const char *value = role_string;
+ Oid savedoid;
+ char *endptr;
+
+ /* This special case only applies if no SET ROLE has been done */
+ if (value == NULL || strcmp(value, "none") == 0)
+ return "none";
+
+ Assert(strspn(value, "x") == NAMEDATALEN &&
+ (value[NAMEDATALEN] == 'T' || value[NAMEDATALEN] == 'F'));
+
+ savedoid = (Oid) strtoul(value + NAMEDATALEN + 1, &endptr, 10);
+
+ Assert(endptr != value + NAMEDATALEN + 1 && *endptr == ',');
+
+ /*
+ * Check that the stored string still matches the effective setting,
+ * else return "none". This is a kluge to deal with the fact that
+ * SET SESSION AUTHORIZATION logically resets SET ROLE to NONE, but
+ * we cannot set the GUC role variable from assign_session_authorization
+ * (because we haven't got enough info to call set_config_option).
+ */
+ if (savedoid != GetCurrentRoleId())
+ return "none";
+
+ return endptr + 1;
+}