summaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
authorAlvaro Herrera2014-12-23 18:35:49 +0000
committerAlvaro Herrera2014-12-23 18:35:49 +0000
commita609d96778c1714b9af916477b2c30891fbe578a (patch)
tree66b7073c9e67e708136d3c3450d7cbdd81b06a73 /src/backend/commands
parentd7ee82e50f624221db76023c17137661fe69ec61 (diff)
Revert "Use a bitmask to represent role attributes"
This reverts commit 1826987a46d079458007b7b6bbcbbd852353adbb. The overall design was deemed unacceptable, in discussion following the previous commit message; we might find some parts of it still salvageable, but I don't want to be on the hook for fixing it, so let's wait until we have a new patch.
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/dbcommands.c27
-rw-r--r--src/backend/commands/user.c244
-rw-r--r--src/backend/commands/variable.c8
3 files changed, 125 insertions, 154 deletions
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index c079168c83d..1a5244cade2 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -85,6 +85,7 @@ static bool get_db_info(const char *name, LOCKMODE lockmode,
Oid *dbLastSysOidP, TransactionId *dbFrozenXidP,
MultiXactId *dbMinMultiP,
Oid *dbTablespace, char **dbCollate, char **dbCtype);
+static bool have_createdb_privilege(void);
static void remove_dbtablespaces(Oid db_id);
static bool check_db_file_conflict(Oid db_id);
static int errdetail_busy_db(int notherbackends, int npreparedxacts);
@@ -290,7 +291,7 @@ createdb(const CreatedbStmt *stmt)
* "giveaway" attacks. Note that a superuser will always have both of
* these privileges a fortiori.
*/
- if (!have_role_attribute(ROLE_ATTR_CREATEDB))
+ if (!have_createdb_privilege())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to create database")));
@@ -964,7 +965,7 @@ RenameDatabase(const char *oldname, const char *newname)
oldname);
/* must have createdb rights */
- if (!have_role_attribute(ROLE_ATTR_CREATEDB))
+ if (!have_createdb_privilege())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to rename database")));
@@ -1622,7 +1623,7 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId)
* databases. Because superusers will always have this right, we need
* no special case for them.
*/
- if (!have_role_attribute(ROLE_ATTR_CREATEDB))
+ if (!have_createdb_privilege())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to change owner of database")));
@@ -1801,6 +1802,26 @@ get_db_info(const char *name, LOCKMODE lockmode,
return result;
}
+/* Check if current user has createdb privileges */
+static bool
+have_createdb_privilege(void)
+{
+ bool result = false;
+ HeapTuple utup;
+
+ /* Superusers can always do everything */
+ if (superuser())
+ return true;
+
+ utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(GetUserId()));
+ if (HeapTupleIsValid(utup))
+ {
+ result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreatedb;
+ ReleaseSysCache(utup);
+ }
+ return result;
+}
+
/*
* Remove tablespace directories
*
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 564f77a8695..1a73fd85582 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -56,6 +56,14 @@ static void DelRoleMems(const char *rolename, Oid roleid,
bool admin_opt);
+/* Check if current user has createrole privileges */
+static bool
+have_createrole_privilege(void)
+{
+ return has_createrole_privilege(GetUserId());
+}
+
+
/*
* CREATE ROLE
*/
@@ -73,7 +81,13 @@ CreateRole(CreateRoleStmt *stmt)
char *password = NULL; /* user password */
bool encrypt_password = Password_encryption; /* encrypt password? */
char encrypted_password[MD5_PASSWD_LEN + 1];
- RoleAttr attributes;
+ bool issuper = false; /* Make the user a superuser? */
+ bool inherit = true; /* Auto inherit privileges? */
+ bool createrole = false; /* Can this user create roles? */
+ bool createdb = false; /* Can the user create databases? */
+ bool canlogin = false; /* Can this user login? */
+ bool isreplication = false; /* Is this a replication role? */
+ bool bypassrls = false; /* Is this a row security enabled role? */
int connlimit = -1; /* maximum connections allowed */
List *addroleto = NIL; /* roles to make this a member of */
List *rolemembers = NIL; /* roles to be members of this role */
@@ -95,17 +109,13 @@ CreateRole(CreateRoleStmt *stmt)
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
- /*
- * Every role has INHERIT by default, and CANLOGIN depends on the statement
- * type.
- */
- attributes = ROLE_ATTR_INHERIT;
+ /* The defaults can vary depending on the original statement type */
switch (stmt->stmt_type)
{
case ROLESTMT_ROLE:
break;
case ROLESTMT_USER:
- attributes |= ROLE_ATTR_CANLOGIN;
+ canlogin = true;
/* may eventually want inherit to default to false here */
break;
case ROLESTMT_GROUP:
@@ -239,76 +249,18 @@ CreateRole(CreateRoleStmt *stmt)
if (dpassword && dpassword->arg)
password = strVal(dpassword->arg);
-
- /* Set up role attributes and check permissions to set each of them */
if (dissuper)
- {
- if (intVal(dissuper->arg) != 0)
- {
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to create superusers")));
- attributes |= ROLE_ATTR_SUPERUSER;
- }
- else
- attributes &= ~ROLE_ATTR_SUPERUSER;
- }
+ issuper = intVal(dissuper->arg) != 0;
if (dinherit)
- {
- if (intVal(dinherit->arg) != 0)
- attributes |= ROLE_ATTR_INHERIT;
- else
- attributes &= ~ROLE_ATTR_INHERIT;
- }
+ inherit = intVal(dinherit->arg) != 0;
if (dcreaterole)
- {
- if (intVal(dcreaterole->arg) != 0)
- attributes |= ROLE_ATTR_CREATEROLE;
- else
- attributes &= ~ROLE_ATTR_CREATEROLE;
- }
+ createrole = intVal(dcreaterole->arg) != 0;
if (dcreatedb)
- {
- if (intVal(dcreatedb->arg) != 0)
- attributes |= ROLE_ATTR_CREATEDB;
- else
- attributes &= ~ROLE_ATTR_CREATEDB;
- }
+ createdb = intVal(dcreatedb->arg) != 0;
if (dcanlogin)
- {
- if (intVal(dcanlogin->arg) != 0)
- attributes |= ROLE_ATTR_CANLOGIN;
- else
- attributes &= ~ROLE_ATTR_CANLOGIN;
- }
+ canlogin = intVal(dcanlogin->arg) != 0;
if (disreplication)
- {
- if (intVal(disreplication->arg) != 0)
- {
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to create replication users")));
- attributes |= ROLE_ATTR_REPLICATION;
- }
- else
- attributes &= ~ROLE_ATTR_REPLICATION;
- }
- if (dbypassRLS)
- {
- if (intVal(dbypassRLS->arg) != 0)
- {
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to change bypassrls attribute")));
- attributes |= ROLE_ATTR_BYPASSRLS;
- }
- else
- attributes &= ~ROLE_ATTR_BYPASSRLS;
- }
-
+ isreplication = intVal(disreplication->arg) != 0;
if (dconnlimit)
{
connlimit = intVal(dconnlimit->arg);
@@ -325,12 +277,38 @@ CreateRole(CreateRoleStmt *stmt)
adminmembers = (List *) dadminmembers->arg;
if (dvalidUntil)
validUntil = strVal(dvalidUntil->arg);
+ if (dbypassRLS)
+ bypassrls = intVal(dbypassRLS->arg) != 0;
- /* Check permissions */
- if (!have_role_attribute(ROLE_ATTR_CREATEROLE))
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("permission denied to create role")));
+ /* Check some permissions first */
+ if (issuper)
+ {
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to create superusers")));
+ }
+ else if (isreplication)
+ {
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to create replication users")));
+ }
+ else if (bypassrls)
+ {
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to change bypassrls attribute.")));
+ }
+ else
+ {
+ if (!have_createrole_privilege())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied to create role")));
+ }
if (strcmp(stmt->role, "public") == 0 ||
strcmp(stmt->role, "none") == 0)
@@ -386,8 +364,14 @@ CreateRole(CreateRoleStmt *stmt)
new_record[Anum_pg_authid_rolname - 1] =
DirectFunctionCall1(namein, CStringGetDatum(stmt->role));
- new_record[Anum_pg_authid_rolattr - 1] = Int64GetDatum(attributes);
-
+ new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper);
+ new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit);
+ new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole);
+ new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb);
+ /* superuser gets catupdate right by default */
+ new_record[Anum_pg_authid_rolcatupdate - 1] = BoolGetDatum(issuper);
+ new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin);
+ new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication);
new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
if (password)
@@ -410,6 +394,8 @@ CreateRole(CreateRoleStmt *stmt)
new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
+ new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls);
+
tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls);
/*
@@ -522,7 +508,6 @@ AlterRole(AlterRoleStmt *stmt)
DefElem *dvalidUntil = NULL;
DefElem *dbypassRLS = NULL;
Oid roleid;
- RoleAttr attributes;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
@@ -673,34 +658,31 @@ AlterRole(AlterRoleStmt *stmt)
roleid = HeapTupleGetOid(tuple);
/*
- * To mess with a superuser or a replication user you gotta be superuser;
- * else you need createrole, or just want to change your own password
+ * To mess with a superuser you gotta be superuser; else you need
+ * createrole, or just want to change your own password
*/
-
- attributes = ((Form_pg_authid) GETSTRUCT(tuple))->rolattr;
-
- if ((attributes & ROLE_ATTR_SUPERUSER) || issuper >= 0)
+ if (((Form_pg_authid) GETSTRUCT(tuple))->rolsuper || issuper >= 0)
{
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to alter superusers")));
}
- else if ((attributes & ROLE_ATTR_REPLICATION) || isreplication >= 0)
+ else if (((Form_pg_authid) GETSTRUCT(tuple))->rolreplication || isreplication >= 0)
{
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to alter replication users")));
}
- else if ((attributes & ROLE_ATTR_BYPASSRLS) || bypassrls >= 0)
+ else if (((Form_pg_authid) GETSTRUCT(tuple))->rolbypassrls || bypassrls >= 0)
{
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to change bypassrls attribute")));
}
- else if (!have_role_attribute(ROLE_ATTR_CREATEROLE))
+ else if (!have_createrole_privilege())
{
if (!(inherit < 0 &&
createrole < 0 &&
@@ -761,71 +743,43 @@ AlterRole(AlterRoleStmt *stmt)
*/
if (issuper >= 0)
{
- if (issuper > 0)
- attributes |= ROLE_ATTR_SUPERUSER | ROLE_ATTR_CATUPDATE;
- else
- attributes &= ~(ROLE_ATTR_SUPERUSER | ROLE_ATTR_CATUPDATE);
- new_record_repl[Anum_pg_authid_rolattr - 1] = true;
+ new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper > 0);
+ new_record_repl[Anum_pg_authid_rolsuper - 1] = true;
+
+ new_record[Anum_pg_authid_rolcatupdate - 1] = BoolGetDatum(issuper > 0);
+ new_record_repl[Anum_pg_authid_rolcatupdate - 1] = true;
}
if (inherit >= 0)
{
- if (inherit > 0)
- attributes |= ROLE_ATTR_INHERIT;
- else
- attributes &= ~ROLE_ATTR_INHERIT;
- new_record_repl[Anum_pg_authid_rolattr - 1] = true;
+ new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit > 0);
+ new_record_repl[Anum_pg_authid_rolinherit - 1] = true;
}
if (createrole >= 0)
{
- if (createrole > 0)
- attributes |= ROLE_ATTR_CREATEROLE;
- else
- attributes &= ~ROLE_ATTR_CREATEROLE;
- new_record_repl[Anum_pg_authid_rolattr - 1] = true;
+ new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole > 0);
+ new_record_repl[Anum_pg_authid_rolcreaterole - 1] = true;
}
if (createdb >= 0)
{
- if (createdb > 0)
- attributes |= ROLE_ATTR_CREATEDB;
- else
- attributes &= ~ROLE_ATTR_CREATEDB;
- new_record_repl[Anum_pg_authid_rolattr - 1] = true;
+ new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb > 0);
+ new_record_repl[Anum_pg_authid_rolcreatedb - 1] = true;
}
if (canlogin >= 0)
{
- if (canlogin > 0)
- attributes |= ROLE_ATTR_CANLOGIN;
- else
- attributes &= ~ROLE_ATTR_CANLOGIN;
- new_record_repl[Anum_pg_authid_rolattr - 1] = true;
+ new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin > 0);
+ new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true;
}
if (isreplication >= 0)
{
- if (isreplication > 0)
- attributes |= ROLE_ATTR_REPLICATION;
- else
- attributes &= ~ROLE_ATTR_REPLICATION;
- new_record_repl[Anum_pg_authid_rolattr - 1] = true;
+ new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication > 0);
+ new_record_repl[Anum_pg_authid_rolreplication - 1] = true;
}
- if (bypassrls >= 0)
- {
- if (bypassrls > 0)
- attributes |= ROLE_ATTR_BYPASSRLS;
- else
- attributes &= ~ROLE_ATTR_BYPASSRLS;
- new_record_repl[Anum_pg_authid_rolattr - 1] = true;
- }
-
- /* If any role attributes were set, then update. */
- if (new_record_repl[Anum_pg_authid_rolattr - 1])
- new_record[Anum_pg_authid_rolattr - 1] = Int64GetDatum(attributes);
-
if (dconnlimit)
{
new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
@@ -861,6 +815,11 @@ AlterRole(AlterRoleStmt *stmt)
new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
new_record_repl[Anum_pg_authid_rolvaliduntil - 1] = true;
+ if (bypassrls >= 0)
+ {
+ new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls > 0);
+ new_record_repl[Anum_pg_authid_rolbypassrls - 1] = true;
+ }
new_tuple = heap_modify_tuple(tuple, pg_authid_dsc, new_record,
new_record_nulls, new_record_repl);
@@ -908,7 +867,6 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
HeapTuple roletuple;
Oid databaseid = InvalidOid;
Oid roleid = InvalidOid;
- RoleAttr attributes;
if (stmt->role)
{
@@ -931,8 +889,7 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
* To mess with a superuser you gotta be superuser; else you need
* createrole, or just want to change your own settings
*/
- attributes = ((Form_pg_authid) GETSTRUCT(roletuple))->rolattr;
- if (attributes & ROLE_ATTR_SUPERUSER)
+ if (((Form_pg_authid) GETSTRUCT(roletuple))->rolsuper)
{
if (!superuser())
ereport(ERROR,
@@ -941,7 +898,7 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
}
else
{
- if (!have_role_attribute(ROLE_ATTR_CREATEROLE) &&
+ if (!have_createrole_privilege() &&
HeapTupleGetOid(roletuple) != GetUserId())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -994,7 +951,7 @@ DropRole(DropRoleStmt *stmt)
pg_auth_members_rel;
ListCell *item;
- if (!have_role_attribute(ROLE_ATTR_CREATEROLE))
+ if (!have_createrole_privilege())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to drop role")));
@@ -1016,7 +973,6 @@ DropRole(DropRoleStmt *stmt)
char *detail_log;
SysScanDesc sscan;
Oid roleid;
- RoleAttr attributes;
tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
if (!HeapTupleIsValid(tuple))
@@ -1057,8 +1013,8 @@ DropRole(DropRoleStmt *stmt)
* roles but not superuser roles. This is mainly to avoid the
* scenario where you accidentally drop the last superuser.
*/
- attributes = ((Form_pg_authid) GETSTRUCT(tuple))->rolattr;
- if ((attributes & ROLE_ATTR_SUPERUSER) && !superuser())
+ if (((Form_pg_authid) GETSTRUCT(tuple))->rolsuper &&
+ !superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to drop superusers")));
@@ -1172,7 +1128,6 @@ RenameRole(const char *oldname, const char *newname)
bool repl_repl[Natts_pg_authid];
int i;
Oid roleid;
- RoleAttr attributes;
rel = heap_open(AuthIdRelationId, RowExclusiveLock);
dsc = RelationGetDescr(rel);
@@ -1218,8 +1173,7 @@ RenameRole(const char *oldname, const char *newname)
/*
* createrole is enough privilege unless you want to mess with a superuser
*/
- attributes = ((Form_pg_authid) GETSTRUCT(oldtuple))->rolattr;
- if (attributes & ROLE_ATTR_SUPERUSER)
+ if (((Form_pg_authid) GETSTRUCT(oldtuple))->rolsuper)
{
if (!superuser())
ereport(ERROR,
@@ -1228,7 +1182,7 @@ RenameRole(const char *oldname, const char *newname)
}
else
{
- if (!have_role_attribute(ROLE_ATTR_CREATEROLE))
+ if (!have_createrole_privilege())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to rename role")));
@@ -1455,7 +1409,7 @@ AddRoleMems(const char *rolename, Oid roleid,
}
else
{
- if (!have_role_attribute(ROLE_ATTR_CREATEROLE) &&
+ if (!have_createrole_privilege() &&
!is_admin_of_role(grantorId, roleid))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -1601,7 +1555,7 @@ DelRoleMems(const char *rolename, Oid roleid,
}
else
{
- if (!have_role_attribute(ROLE_ATTR_CREATEROLE) &&
+ if (!have_createrole_privilege() &&
!is_admin_of_role(GetUserId(), roleid))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 491dc38caf3..6ce8daeb95a 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -776,7 +776,6 @@ check_session_authorization(char **newval, void **extra, GucSource source)
Oid roleid;
bool is_superuser;
role_auth_extra *myextra;
- RoleAttr attributes;
/* Do nothing for the boot_val default of NULL */
if (*newval == NULL)
@@ -801,8 +800,7 @@ check_session_authorization(char **newval, void **extra, GucSource source)
}
roleid = HeapTupleGetOid(roleTup);
- attributes = ((Form_pg_authid) GETSTRUCT(roleTup))->rolattr;
- is_superuser = (attributes & ROLE_ATTR_SUPERUSER);
+ is_superuser = ((Form_pg_authid) GETSTRUCT(roleTup))->rolsuper;
ReleaseSysCache(roleTup);
@@ -846,7 +844,6 @@ check_role(char **newval, void **extra, GucSource source)
Oid roleid;
bool is_superuser;
role_auth_extra *myextra;
- RoleAttr attributes;
if (strcmp(*newval, "none") == 0)
{
@@ -875,8 +872,7 @@ check_role(char **newval, void **extra, GucSource source)
}
roleid = HeapTupleGetOid(roleTup);
- attributes = ((Form_pg_authid) GETSTRUCT(roleTup))->rolattr;
- is_superuser = (attributes & ROLE_ATTR_SUPERUSER);
+ is_superuser = ((Form_pg_authid) GETSTRUCT(roleTup))->rolsuper;
ReleaseSysCache(roleTup);