aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/aggregatecmds.c8
-rw-r--r--src/backend/commands/alter.c16
-rw-r--r--src/backend/commands/conversioncmds.c8
-rw-r--r--src/backend/commands/copy.c3
-rw-r--r--src/backend/commands/dbcommands.c50
-rw-r--r--src/backend/commands/functioncmds.c10
-rw-r--r--src/backend/commands/opclasscmds.c10
-rw-r--r--src/backend/commands/operatorcmds.c8
-rw-r--r--src/backend/commands/schemacmds.c33
-rw-r--r--src/backend/commands/tablecmds.c28
-rw-r--r--src/backend/commands/tablespace.c30
-rw-r--r--src/backend/commands/typecmds.c8
-rw-r--r--src/backend/commands/user.c1335
-rw-r--r--src/backend/commands/variable.c56
14 files changed, 711 insertions, 892 deletions
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index 9833937b705..6335757981e 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.26 2005/04/14 20:03:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.27 2005/06/28 05:08:53 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -295,7 +295,7 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
* Change aggregate owner
*/
void
-AlterAggregateOwner(List *name, TypeName *basetype, AclId newOwnerSysId)
+AlterAggregateOwner(List *name, TypeName *basetype, Oid newOwnerId)
{
Oid basetypeOid;
Oid procOid;
@@ -329,7 +329,7 @@ AlterAggregateOwner(List *name, TypeName *basetype, AclId newOwnerSysId)
* If the new owner is the same as the existing owner, consider the
* command to have succeeded. This is for dump restoration purposes.
*/
- if (procForm->proowner != newOwnerSysId)
+ if (procForm->proowner != newOwnerId)
{
/* Otherwise, must be superuser to change object ownership */
if (!superuser())
@@ -341,7 +341,7 @@ AlterAggregateOwner(List *name, TypeName *basetype, AclId newOwnerSysId)
* Modify the owner --- okay to scribble on tup because it's a
* copy
*/
- procForm->proowner = newOwnerSysId;
+ procForm->proowner = newOwnerId;
simple_heap_update(rel, &tup->t_self, tup);
CatalogUpdateIndexes(rel, tup);
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 9bb40f35164..a19b500152d 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.12 2004/12/31 21:59:41 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.13 2005/06/28 05:08:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -64,10 +64,6 @@ ExecRenameStmt(RenameStmt *stmt)
RenameFunction(stmt->object, stmt->objarg, stmt->newname);
break;
- case OBJECT_GROUP:
- RenameGroup(stmt->subname, stmt->newname);
- break;
-
case OBJECT_LANGUAGE:
RenameLanguage(stmt->subname, stmt->newname);
break;
@@ -76,6 +72,10 @@ ExecRenameStmt(RenameStmt *stmt)
RenameOpClass(stmt->object, stmt->subname, stmt->newname);
break;
+ case OBJECT_ROLE:
+ RenameRole(stmt->subname, stmt->newname);
+ break;
+
case OBJECT_SCHEMA:
RenameSchema(stmt->subname, stmt->newname);
break;
@@ -84,10 +84,6 @@ ExecRenameStmt(RenameStmt *stmt)
RenameTableSpace(stmt->subname, stmt->newname);
break;
- case OBJECT_USER:
- RenameUser(stmt->subname, stmt->newname);
- break;
-
case OBJECT_TABLE:
case OBJECT_INDEX:
case OBJECT_COLUMN:
@@ -153,7 +149,7 @@ ExecRenameStmt(RenameStmt *stmt)
void
ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
{
- AclId newowner = get_usesysid(stmt->newowner);
+ Oid newowner = get_roleid_checked(stmt->newowner);
switch (stmt->objectType)
{
diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c
index fb71bf59f92..c2aa48614e6 100644
--- a/src/backend/commands/conversioncmds.c
+++ b/src/backend/commands/conversioncmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.18 2005/05/03 19:17:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.19 2005/06/28 05:08:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -175,7 +175,7 @@ RenameConversion(List *name, const char *newname)
* Change conversion owner
*/
void
-AlterConversionOwner(List *name, AclId newOwnerSysId)
+AlterConversionOwner(List *name, Oid newOwnerId)
{
Oid conversionOid;
HeapTuple tup;
@@ -203,7 +203,7 @@ AlterConversionOwner(List *name, AclId newOwnerSysId)
* If the new owner is the same as the existing owner, consider the
* command to have succeeded. This is for dump restoration purposes.
*/
- if (convForm->conowner != newOwnerSysId)
+ if (convForm->conowner != newOwnerId)
{
/* Otherwise, must be superuser to change object ownership */
if (!superuser())
@@ -215,7 +215,7 @@ AlterConversionOwner(List *name, AclId newOwnerSysId)
* Modify the owner --- okay to scribble on tup because it's a
* copy
*/
- convForm->conowner = newOwnerSysId;
+ convForm->conowner = newOwnerId;
simple_heap_update(rel, &tup->t_self, tup);
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 30eeefded8e..10e68684b8e 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.245 2005/06/02 01:21:22 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.246 2005/06/28 05:08:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -25,7 +25,6 @@
#include "catalog/index.h"
#include "catalog/namespace.h"
#include "catalog/pg_index.h"
-#include "catalog/pg_shadow.h"
#include "catalog/pg_type.h"
#include "commands/copy.h"
#include "commands/trigger.h"
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 6fa6aa5b44b..1dac14ead2e 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.161 2005/06/25 22:47:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.162 2005/06/28 05:08:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,10 +28,10 @@
#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/catalog.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
-#include "catalog/pg_shadow.h"
#include "catalog/pg_tablespace.h"
-#include "catalog/indexing.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "commands/tablespace.h"
@@ -52,7 +52,7 @@
/* non-export function prototypes */
-static bool get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
+static bool get_db_info(const char *name, Oid *dbIdP, Oid *ownerIdP,
int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,
Oid *dbLastSysOidP,
TransactionId *dbVacuumXidP, TransactionId *dbFrozenXidP,
@@ -70,7 +70,7 @@ createdb(const CreatedbStmt *stmt)
HeapScanDesc scan;
Relation rel;
Oid src_dboid;
- AclId src_owner;
+ Oid src_owner;
int src_encoding;
bool src_istemplate;
bool src_allowconn;
@@ -85,7 +85,7 @@ createdb(const CreatedbStmt *stmt)
Datum new_record[Natts_pg_database];
char new_record_nulls[Natts_pg_database];
Oid dboid;
- AclId datdba;
+ Oid datdba;
ListCell *option;
DefElem *dtablespacename = NULL;
DefElem *downer = NULL;
@@ -186,13 +186,13 @@ createdb(const CreatedbStmt *stmt)
nodeTag(dencoding->arg));
}
- /* obtain sysid of proposed owner */
+ /* obtain OID of proposed owner */
if (dbowner)
- datdba = get_usesysid(dbowner); /* will ereport if no such user */
+ datdba = get_roleid_checked(dbowner);
else
datdba = GetUserId();
- if (datdba == GetUserId())
+ if (is_member_of_role(GetUserId(), datdba))
{
/* creating database for self: can be superuser or createdb */
if (!superuser() && !have_createdb_privilege())
@@ -243,7 +243,7 @@ createdb(const CreatedbStmt *stmt)
*/
if (!src_istemplate)
{
- if (!superuser() && GetUserId() != src_owner)
+ if (!pg_database_ownercheck(src_dboid, GetUserId()))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to copy database \"%s\"",
@@ -483,7 +483,7 @@ createdb(const CreatedbStmt *stmt)
new_record[Anum_pg_database_datname - 1] =
DirectFunctionCall1(namein, CStringGetDatum(dbname));
- new_record[Anum_pg_database_datdba - 1] = Int32GetDatum(datdba);
+ new_record[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(datdba);
new_record[Anum_pg_database_encoding - 1] = Int32GetDatum(encoding);
new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(false);
new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(true);
@@ -557,9 +557,8 @@ createdb(const CreatedbStmt *stmt)
void
dropdb(const char *dbname)
{
- int4 db_owner;
- bool db_istemplate;
Oid db_id;
+ bool db_istemplate;
Relation pgdbrel;
SysScanDesc pgdbscan;
ScanKeyData key;
@@ -588,13 +587,13 @@ dropdb(const char *dbname)
*/
pgdbrel = heap_open(DatabaseRelationId, ExclusiveLock);
- if (!get_db_info(dbname, &db_id, &db_owner, NULL,
+ if (!get_db_info(dbname, &db_id, NULL, NULL,
&db_istemplate, NULL, NULL, NULL, NULL, NULL))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database \"%s\" does not exist", dbname)));
- if (GetUserId() != db_owner && !superuser())
+ if (!pg_database_ownercheck(db_id, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
dbname);
@@ -818,8 +817,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database \"%s\" does not exist", stmt->dbname)));
- if (!(superuser()
- || ((Form_pg_database) GETSTRUCT(tuple))->datdba == GetUserId()))
+ if (!pg_database_ownercheck(HeapTupleGetOid(tuple), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
stmt->dbname);
@@ -878,7 +876,7 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
* ALTER DATABASE name OWNER TO newowner
*/
void
-AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
+AlterDatabaseOwner(const char *dbname, Oid newOwnerId)
{
HeapTuple tuple;
Relation rel;
@@ -910,7 +908,7 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
* command to have succeeded. This is to be consistent with other
* objects.
*/
- if (datForm->datdba != newOwnerSysId)
+ if (datForm->datdba != newOwnerId)
{
Datum repl_val[Natts_pg_database];
char repl_null[Natts_pg_database];
@@ -930,7 +928,7 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
memset(repl_repl, ' ', sizeof(repl_repl));
repl_repl[Anum_pg_database_datdba - 1] = 'r';
- repl_val[Anum_pg_database_datdba - 1] = Int32GetDatum(newOwnerSysId);
+ repl_val[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(newOwnerId);
/*
* Determine the modified ACL for the new owner. This is only
@@ -943,7 +941,7 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
if (!isNull)
{
newAcl = aclnewowner(DatumGetAclP(aclDatum),
- datForm->datdba, newOwnerSysId);
+ datForm->datdba, newOwnerId);
repl_repl[Anum_pg_database_datacl - 1] = 'r';
repl_val[Anum_pg_database_datacl - 1] = PointerGetDatum(newAcl);
}
@@ -972,7 +970,7 @@ AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId)
*/
static bool
-get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
+get_db_info(const char *name, Oid *dbIdP, Oid *ownerIdP,
int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,
Oid *dbLastSysOidP,
TransactionId *dbVacuumXidP, TransactionId *dbFrozenXidP,
@@ -1007,7 +1005,7 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
/* oid of the database */
if (dbIdP)
*dbIdP = HeapTupleGetOid(tuple);
- /* sysid of the owner */
+ /* oid of the owner */
if (ownerIdP)
*ownerIdP = dbform->datdba;
/* character encoding */
@@ -1046,12 +1044,12 @@ have_createdb_privilege(void)
bool result = false;
HeapTuple utup;
- utup = SearchSysCache(SHADOWSYSID,
- Int32GetDatum(GetUserId()),
+ utup = SearchSysCache(AUTHOID,
+ ObjectIdGetDatum(GetUserId()),
0, 0, 0);
if (HeapTupleIsValid(utup))
{
- result = ((Form_pg_shadow) GETSTRUCT(utup))->usecreatedb;
+ result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreatedb;
ReleaseSysCache(utup);
}
return result;
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index ea3c3811837..3329822fe62 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.61 2005/04/14 20:03:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.62 2005/06/28 05:08:53 tgl Exp $
*
* DESCRIPTION
* These routines take the parse tree and pick out the
@@ -853,7 +853,7 @@ RenameFunction(List *name, List *argtypes, const char *newname)
* Change function owner
*/
void
-AlterFunctionOwner(List *name, List *argtypes, AclId newOwnerSysId)
+AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
{
Oid procOid;
HeapTuple tup;
@@ -882,7 +882,7 @@ AlterFunctionOwner(List *name, List *argtypes, AclId newOwnerSysId)
* If the new owner is the same as the existing owner, consider the
* command to have succeeded. This is for dump restoration purposes.
*/
- if (procForm->proowner != newOwnerSysId)
+ if (procForm->proowner != newOwnerId)
{
Datum repl_val[Natts_pg_proc];
char repl_null[Natts_pg_proc];
@@ -902,7 +902,7 @@ AlterFunctionOwner(List *name, List *argtypes, AclId newOwnerSysId)
memset(repl_repl, ' ', sizeof(repl_repl));
repl_repl[Anum_pg_proc_proowner - 1] = 'r';
- repl_val[Anum_pg_proc_proowner - 1] = Int32GetDatum(newOwnerSysId);
+ repl_val[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(newOwnerId);
/*
* Determine the modified ACL for the new owner. This is only
@@ -914,7 +914,7 @@ AlterFunctionOwner(List *name, List *argtypes, AclId newOwnerSysId)
if (!isNull)
{
newAcl = aclnewowner(DatumGetAclP(aclDatum),
- procForm->proowner, newOwnerSysId);
+ procForm->proowner, newOwnerId);
repl_repl[Anum_pg_proc_proacl - 1] = 'r';
repl_val[Anum_pg_proc_proacl - 1] = PointerGetDatum(newAcl);
}
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index e64924c43a7..3610269644a 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.32 2005/04/14 20:03:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.33 2005/06/28 05:08:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -321,7 +321,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
namestrcpy(&opcName, opcname);
values[i++] = NameGetDatum(&opcName); /* opcname */
values[i++] = ObjectIdGetDatum(namespaceoid); /* opcnamespace */
- values[i++] = Int32GetDatum(GetUserId()); /* opcowner */
+ values[i++] = ObjectIdGetDatum(GetUserId()); /* opcowner */
values[i++] = ObjectIdGetDatum(typeoid); /* opcintype */
values[i++] = BoolGetDatum(stmt->isDefault); /* opcdefault */
values[i++] = ObjectIdGetDatum(storageoid); /* opckeytype */
@@ -880,7 +880,7 @@ RenameOpClass(List *name, const char *access_method, const char *newname)
* Change opclass owner
*/
void
-AlterOpClassOwner(List *name, const char *access_method, AclId newOwnerSysId)
+AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
{
Oid opcOid;
Oid amOid;
@@ -945,7 +945,7 @@ AlterOpClassOwner(List *name, const char *access_method, AclId newOwnerSysId)
* If the new owner is the same as the existing owner, consider the
* command to have succeeded. This is for dump restoration purposes.
*/
- if (opcForm->opcowner != newOwnerSysId)
+ if (opcForm->opcowner != newOwnerId)
{
/* Otherwise, must be superuser to change object ownership */
if (!superuser())
@@ -957,7 +957,7 @@ AlterOpClassOwner(List *name, const char *access_method, AclId newOwnerSysId)
* Modify the owner --- okay to scribble on tup because it's a
* copy
*/
- opcForm->opcowner = newOwnerSysId;
+ opcForm->opcowner = newOwnerId;
simple_heap_update(rel, &tup->t_self, tup);
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
index 45dc1eafeaa..adea1b2b5d7 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.21 2005/04/14 20:03:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.22 2005/06/28 05:08:54 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -269,7 +269,7 @@ RemoveOperatorById(Oid operOid)
*/
void
AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
- AclId newOwnerSysId)
+ Oid newOwnerId)
{
Oid operOid;
HeapTuple tup;
@@ -293,7 +293,7 @@ AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
* If the new owner is the same as the existing owner, consider the
* command to have succeeded. This is for dump restoration purposes.
*/
- if (oprForm->oprowner != newOwnerSysId)
+ if (oprForm->oprowner != newOwnerId)
{
/* Otherwise, must be superuser to change object ownership */
if (!superuser())
@@ -305,7 +305,7 @@ AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
* Modify the owner --- okay to scribble on tup because it's a
* copy
*/
- oprForm->oprowner = newOwnerSysId;
+ oprForm->oprowner = newOwnerId;
simple_heap_update(rel, &tup->t_self, tup);
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 5754c1dfcb4..d92812f1fcf 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.30 2005/06/21 00:58:15 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.31 2005/06/28 05:08:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -42,11 +42,11 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
Oid namespaceId;
List *parsetree_list;
ListCell *parsetree_item;
- AclId owner_userid;
- AclId saved_userid;
+ Oid owner_uid;
+ Oid saved_uid;
AclResult aclresult;
- saved_userid = GetUserId();
+ saved_uid = GetUserId();
/*
* Figure out user identities.
@@ -54,12 +54,11 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
if (!authId)
{
- owner_userid = saved_userid;
+ owner_uid = saved_uid;
}
else if (superuser())
{
- /* The following will error out if user does not exist */
- owner_userid = get_usesysid(authId);
+ owner_uid = get_roleid_checked(authId);
/*
* Set the current user to the requested authorization so that
@@ -67,15 +66,15 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
* (This will revert to session user on error or at the end of
* this routine.)
*/
- SetUserId(owner_userid);
+ SetUserId(owner_uid);
}
else
{
const char *owner_name;
/* not superuser */
- owner_userid = saved_userid;
- owner_name = GetUserNameFromId(owner_userid);
+ owner_uid = saved_uid;
+ owner_name = GetUserNameFromId(owner_uid);
if (strcmp(authId, owner_name) != 0)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -87,7 +86,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
/*
* Permissions checks.
*/
- aclresult = pg_database_aclcheck(MyDatabaseId, saved_userid, ACL_CREATE);
+ aclresult = pg_database_aclcheck(MyDatabaseId, saved_uid, ACL_CREATE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_DATABASE,
get_database_name(MyDatabaseId));
@@ -99,7 +98,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
errdetail("The prefix \"pg_\" is reserved for system schemas.")));
/* Create the schema's namespace */
- namespaceId = NamespaceCreate(schemaName, owner_userid);
+ namespaceId = NamespaceCreate(schemaName, owner_uid);
/* Advance cmd counter to make the namespace visible */
CommandCounterIncrement();
@@ -149,7 +148,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
PopSpecialNamespace(namespaceId);
/* Reset current user */
- SetUserId(saved_userid);
+ SetUserId(saved_uid);
}
@@ -279,7 +278,7 @@ RenameSchema(const char *oldname, const char *newname)
* Change schema owner
*/
void
-AlterSchemaOwner(const char *name, AclId newOwnerSysId)
+AlterSchemaOwner(const char *name, Oid newOwnerId)
{
HeapTuple tup;
Relation rel;
@@ -300,7 +299,7 @@ AlterSchemaOwner(const char *name, AclId newOwnerSysId)
* If the new owner is the same as the existing owner, consider the
* command to have succeeded. This is for dump restoration purposes.
*/
- if (nspForm->nspowner != newOwnerSysId)
+ if (nspForm->nspowner != newOwnerId)
{
Datum repl_val[Natts_pg_namespace];
char repl_null[Natts_pg_namespace];
@@ -320,7 +319,7 @@ AlterSchemaOwner(const char *name, AclId newOwnerSysId)
memset(repl_repl, ' ', sizeof(repl_repl));
repl_repl[Anum_pg_namespace_nspowner - 1] = 'r';
- repl_val[Anum_pg_namespace_nspowner - 1] = Int32GetDatum(newOwnerSysId);
+ repl_val[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(newOwnerId);
/*
* Determine the modified ACL for the new owner. This is only
@@ -332,7 +331,7 @@ AlterSchemaOwner(const char *name, AclId newOwnerSysId)
if (!isNull)
{
newAcl = aclnewowner(DatumGetAclP(aclDatum),
- nspForm->nspowner, newOwnerSysId);
+ nspForm->nspowner, newOwnerId);
repl_repl[Anum_pg_namespace_nspacl - 1] = 'r';
repl_val[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(newAcl);
}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 9981129c0eb..dda9532baf8 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.161 2005/06/06 20:22:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.162 2005/06/28 05:08:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -231,9 +231,9 @@ static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
const char *colName, TypeName *typename);
static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab);
static void ATPostAlterTypeParse(char *cmd, List **wqueue);
-static void ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId);
+static void ATExecChangeOwner(Oid relationOid, Oid newOwnerId);
static void change_owner_recurse_to_sequences(Oid relationOid,
- int32 newOwnerSysId);
+ Oid newOwnerId);
static void ATExecClusterOn(Relation rel, const char *indexName);
static void ATExecDropCluster(Relation rel);
static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel,
@@ -2133,8 +2133,8 @@ ATExecCmd(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd)
AlterTableCreateToastTable(RelationGetRelid(rel), false);
break;
case AT_ChangeOwner: /* ALTER OWNER */
- /* get_usesysid raises an error if no such user */
- ATExecChangeOwner(RelationGetRelid(rel), get_usesysid(cmd->name));
+ ATExecChangeOwner(RelationGetRelid(rel),
+ get_roleid_checked(cmd->name));
break;
case AT_ClusterOn: /* CLUSTER ON */
ATExecClusterOn(rel, cmd->name);
@@ -5233,7 +5233,7 @@ ATPostAlterTypeParse(char *cmd, List **wqueue)
* ALTER TABLE OWNER
*/
static void
-ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
+ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
{
Relation target_rel;
Relation class_rel;
@@ -5277,7 +5277,7 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
* If the new owner is the same as the existing owner, consider the
* command to have succeeded. This is for dump restoration purposes.
*/
- if (tuple_class->relowner != newOwnerSysId)
+ if (tuple_class->relowner != newOwnerId)
{
Datum repl_val[Natts_pg_class];
char repl_null[Natts_pg_class];
@@ -5297,7 +5297,7 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
memset(repl_repl, ' ', sizeof(repl_repl));
repl_repl[Anum_pg_class_relowner - 1] = 'r';
- repl_val[Anum_pg_class_relowner - 1] = Int32GetDatum(newOwnerSysId);
+ repl_val[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(newOwnerId);
/*
* Determine the modified ACL for the new owner. This is only
@@ -5309,7 +5309,7 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
if (!isNull)
{
newAcl = aclnewowner(DatumGetAclP(aclDatum),
- tuple_class->relowner, newOwnerSysId);
+ tuple_class->relowner, newOwnerId);
repl_repl[Anum_pg_class_relacl - 1] = 'r';
repl_val[Anum_pg_class_relacl - 1] = PointerGetDatum(newAcl);
}
@@ -5337,7 +5337,7 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
/* For each index, recursively change its ownership */
foreach(i, index_oid_list)
- ATExecChangeOwner(lfirst_oid(i), newOwnerSysId);
+ ATExecChangeOwner(lfirst_oid(i), newOwnerId);
list_free(index_oid_list);
}
@@ -5346,10 +5346,10 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
{
/* If it has a toast table, recurse to change its ownership */
if (tuple_class->reltoastrelid != InvalidOid)
- ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerSysId);
+ ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerId);
/* If it has dependent sequences, recurse to change them too */
- change_owner_recurse_to_sequences(relationOid, newOwnerSysId);
+ change_owner_recurse_to_sequences(relationOid, newOwnerId);
}
}
@@ -5366,7 +5366,7 @@ ATExecChangeOwner(Oid relationOid, int32 newOwnerSysId)
* ownership.
*/
static void
-change_owner_recurse_to_sequences(Oid relationOid, int32 newOwnerSysId)
+change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId)
{
Relation depRel;
SysScanDesc scan;
@@ -5416,7 +5416,7 @@ change_owner_recurse_to_sequences(Oid relationOid, int32 newOwnerSysId)
}
/* We don't need to close the sequence while we alter it. */
- ATExecChangeOwner(depForm->objid, newOwnerSysId);
+ ATExecChangeOwner(depForm->objid, newOwnerId);
/* Now we can close it. Keep the lock till end of transaction. */
relation_close(seqRel, NoLock);
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index a469a8fa349..15a263b8efd 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.22 2005/06/19 21:34:01 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.23 2005/06/28 05:08:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -208,7 +208,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
Oid tablespaceoid;
char *location;
char *linkloc;
- AclId ownerid;
+ Oid ownerId;
/* validate */
@@ -225,12 +225,9 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
/* However, the eventual owner of the tablespace need not be */
if (stmt->owner)
- {
- /* No need to check result, get_usesysid() does that */
- ownerid = get_usesysid(stmt->owner);
- }
+ ownerId = get_roleid_checked(stmt->owner);
else
- ownerid = GetUserId();
+ ownerId = GetUserId();
/* Unix-ify the offered path, and strip any trailing slashes */
location = pstrdup(stmt->location);
@@ -297,7 +294,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
values[Anum_pg_tablespace_spcname - 1] =
DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename));
values[Anum_pg_tablespace_spcowner - 1] =
- Int32GetDatum(ownerid);
+ ObjectIdGetDatum(ownerId);
values[Anum_pg_tablespace_spclocation - 1] =
DirectFunctionCall1(textin, CStringGetDatum(location));
nulls[Anum_pg_tablespace_spcacl - 1] = 'n';
@@ -426,9 +423,8 @@ DropTableSpace(DropTableSpaceStmt *stmt)
tablespaceoid = HeapTupleGetOid(tuple);
- /* Must be superuser or owner */
- if (GetUserId() != ((Form_pg_tablespace) GETSTRUCT(tuple))->spcowner &&
- !superuser())
+ /* Must be tablespace owner */
+ if (!pg_tablespace_ownercheck(tablespaceoid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
tablespacename);
@@ -711,8 +707,8 @@ RenameTableSpace(const char *oldname, const char *newname)
heap_endscan(scan);
- /* Must be owner or superuser */
- if (newform->spcowner != GetUserId() && !superuser())
+ /* Must be owner */
+ if (!pg_tablespace_ownercheck(HeapTupleGetOid(newtuple), GetUserId()))
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE, oldname);
/* Validate new name */
@@ -750,7 +746,7 @@ RenameTableSpace(const char *oldname, const char *newname)
* Change tablespace owner
*/
void
-AlterTableSpaceOwner(const char *name, AclId newOwnerSysId)
+AlterTableSpaceOwner(const char *name, Oid newOwnerId)
{
Relation rel;
ScanKeyData entry[1];
@@ -778,7 +774,7 @@ AlterTableSpaceOwner(const char *name, AclId newOwnerSysId)
* If the new owner is the same as the existing owner, consider the
* command to have succeeded. This is for dump restoration purposes.
*/
- if (spcForm->spcowner != newOwnerSysId)
+ if (spcForm->spcowner != newOwnerId)
{
Datum repl_val[Natts_pg_tablespace];
char repl_null[Natts_pg_tablespace];
@@ -798,7 +794,7 @@ AlterTableSpaceOwner(const char *name, AclId newOwnerSysId)
memset(repl_repl, ' ', sizeof(repl_repl));
repl_repl[Anum_pg_tablespace_spcowner - 1] = 'r';
- repl_val[Anum_pg_tablespace_spcowner - 1] = Int32GetDatum(newOwnerSysId);
+ repl_val[Anum_pg_tablespace_spcowner - 1] = ObjectIdGetDatum(newOwnerId);
/*
* Determine the modified ACL for the new owner. This is only
@@ -811,7 +807,7 @@ AlterTableSpaceOwner(const char *name, AclId newOwnerSysId)
if (!isNull)
{
newAcl = aclnewowner(DatumGetAclP(aclDatum),
- spcForm->spcowner, newOwnerSysId);
+ spcForm->spcowner, newOwnerId);
repl_repl[Anum_pg_tablespace_spcacl - 1] = 'r';
repl_val[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(newAcl);
}
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 280022feaa1..53570c77409 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.72 2005/05/06 17:24:53 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.73 2005/06/28 05:08:54 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -2016,7 +2016,7 @@ GetDomainConstraints(Oid typeOid)
* Change the owner of a type.
*/
void
-AlterTypeOwner(List *names, AclId newOwnerSysId)
+AlterTypeOwner(List *names, Oid newOwnerId)
{
TypeName *typename;
Oid typeOid;
@@ -2063,7 +2063,7 @@ AlterTypeOwner(List *names, AclId newOwnerSysId)
* If the new owner is the same as the existing owner, consider the
* command to have succeeded. This is for dump restoration purposes.
*/
- if (typTup->typowner != newOwnerSysId)
+ if (typTup->typowner != newOwnerId)
{
/* Otherwise, must be superuser to change object ownership */
if (!superuser())
@@ -2075,7 +2075,7 @@ AlterTypeOwner(List *names, AclId newOwnerSysId)
* Modify the owner --- okay to scribble on typTup because it's a
* copy
*/
- typTup->typowner = newOwnerSysId;
+ typTup->typowner = newOwnerId;
simple_heap_update(rel, &tup->t_self, tup);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 3c70c579785..131f1896f92 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -1,12 +1,12 @@
/*-------------------------------------------------------------------------
*
* user.c
- * Commands for manipulating users and groups.
+ * Commands for manipulating roles (formerly called users).
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.151 2005/04/14 20:03:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.152 2005/06/28 05:08:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -14,15 +14,14 @@
#include "access/heapam.h"
#include "catalog/indexing.h"
+#include "catalog/pg_auth_members.h"
+#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
-#include "catalog/pg_group.h"
-#include "catalog/pg_shadow.h"
-#include "catalog/pg_type.h"
#include "commands/user.h"
#include "libpq/crypt.h"
#include "miscadmin.h"
-#include "utils/acl.h"
#include "utils/builtins.h"
+#include "utils/catcache.h"
#include "utils/flatfiles.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
@@ -32,46 +31,46 @@
extern bool Password_encryption;
-
-static void CheckPgUserAclNotNull(void);
-static void UpdateGroupMembership(Relation group_rel, HeapTuple group_tuple,
- List *members);
-static IdList *IdListToArray(List *members);
-static List *IdArrayToList(IdList *oldarray);
+static List *roleNamesToIds(List *memberNames);
+static void AddRoleMems(const char *rolename, Oid roleid,
+ List *memberNames, List *memberIds,
+ Oid grantorId, bool admin_opt);
+static void DelRoleMems(const char *rolename, Oid roleid,
+ List *memberNames, List *memberIds,
+ bool admin_opt);
/*
- * CREATE USER
+ * CREATE ROLE
*/
void
-CreateUser(CreateUserStmt *stmt)
+CreateRole(CreateRoleStmt *stmt)
{
- Relation pg_shadow_rel;
- TupleDesc pg_shadow_dsc;
- HeapScanDesc scan;
+ Relation pg_authid_rel;
+ TupleDesc pg_authid_dsc;
HeapTuple tuple;
- Datum new_record[Natts_pg_shadow];
- char new_record_nulls[Natts_pg_shadow];
- bool user_exists = false,
- sysid_exists = false,
- havesysid = false;
- int max_id;
+ Datum new_record[Natts_pg_authid];
+ char new_record_nulls[Natts_pg_authid];
+ Oid roleid;
ListCell *item;
ListCell *option;
- char *password = NULL; /* PostgreSQL user password */
+ char *password = NULL; /* user password */
bool encrypt_password = Password_encryption; /* encrypt password? */
char encrypted_password[MD5_PASSWD_LEN + 1];
- int sysid = 0; /* PgSQL system id (valid if havesysid) */
+ bool issuper = false; /* Make the user a superuser? */
+ bool createrole = false; /* Can this user create roles? */
bool createdb = false; /* Can the user create databases? */
- bool createuser = false; /* Can this user create users? */
- List *groupElts = NIL; /* The groups the user is a member of */
+ bool canlogin = false; /* Can this user login? */
+ List *roleElts = NIL; /* roles the user is a member of */
+ List *rolememElts = NIL; /* roles which will be members of this role */
char *validUntil = NULL; /* The time the login is valid
* until */
DefElem *dpassword = NULL;
- DefElem *dsysid = NULL;
DefElem *dcreatedb = NULL;
- DefElem *dcreateuser = NULL;
- DefElem *dgroupElts = NULL;
+ DefElem *dcreaterole = NULL;
+ DefElem *dcanlogin = NULL;
+ DefElem *droleElts = NULL;
+ DefElem *drolememElts = NULL;
DefElem *dvalidUntil = NULL;
/* Extract options from the statement node tree */
@@ -95,11 +94,16 @@ CreateUser(CreateUserStmt *stmt)
}
else if (strcmp(defel->defname, "sysid") == 0)
{
- if (dsysid)
+ ereport(WARNING,
+ (errmsg("SYSID can no longer be specified")));
+ }
+ else if (strcmp(defel->defname, "createrole") == 0)
+ {
+ if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- dsysid = defel;
+ dcreaterole = defel;
}
else if (strcmp(defel->defname, "createdb") == 0)
{
@@ -109,21 +113,29 @@ CreateUser(CreateUserStmt *stmt)
errmsg("conflicting or redundant options")));
dcreatedb = defel;
}
- else if (strcmp(defel->defname, "createuser") == 0)
+ else if (strcmp(defel->defname, "canlogin") == 0)
{
- if (dcreateuser)
+ if (dcanlogin)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- dcreateuser = defel;
+ dcanlogin = defel;
}
- else if (strcmp(defel->defname, "groupElts") == 0)
+ else if (strcmp(defel->defname, "roleElts") == 0)
{
- if (dgroupElts)
+ if (droleElts)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- dgroupElts = defel;
+ droleElts = defel;
+ }
+ else if (strcmp(defel->defname, "rolememElts") == 0)
+ {
+ if (drolememElts)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ drolememElts = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
@@ -140,83 +152,51 @@ CreateUser(CreateUserStmt *stmt)
if (dcreatedb)
createdb = intVal(dcreatedb->arg) != 0;
- if (dcreateuser)
- createuser = intVal(dcreateuser->arg) != 0;
- if (dsysid)
+ if (dcreaterole)
{
- sysid = intVal(dsysid->arg);
- if (sysid <= 0)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("user ID must be positive")));
- havesysid = true;
+ createrole = intVal(dcreaterole->arg) != 0;
+ /* XXX issuper is implied by createrole for now */
+ issuper = createrole;
}
+ if (dcanlogin)
+ canlogin = intVal(dcanlogin->arg) != 0;
if (dvalidUntil)
validUntil = strVal(dvalidUntil->arg);
if (dpassword)
password = strVal(dpassword->arg);
- if (dgroupElts)
- groupElts = (List *) dgroupElts->arg;
+ if (droleElts)
+ roleElts = (List *) droleElts->arg;
+ if (drolememElts)
+ rolememElts = (List *) drolememElts->arg;
/* Check some permissions first */
- if (password)
- CheckPgUserAclNotNull();
-
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to create users")));
+ errmsg("must be superuser to create roles")));
- if (strcmp(stmt->user, "public") == 0)
+ if (strcmp(stmt->role, "public") == 0)
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
- errmsg("user name \"%s\" is reserved",
- stmt->user)));
+ errmsg("role name \"%s\" is reserved",
+ stmt->role)));
/*
- * Scan the pg_shadow relation to be certain the user or id doesn't
- * already exist. Note we secure exclusive lock, because we also need
- * to be sure of what the next usesysid should be, and we need to
- * protect our eventual update of the flat password file.
+ * Check the pg_authid relation to be certain the role doesn't
+ * already exist. Note we secure exclusive lock because
+ * we need to protect our eventual update of the flat auth file.
*/
- pg_shadow_rel = heap_open(ShadowRelationId, ExclusiveLock);
- pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
-
- scan = heap_beginscan(pg_shadow_rel, SnapshotNow, 0, NULL);
- max_id = 99; /* start auto-assigned ids at 100 */
- while (!user_exists && !sysid_exists &&
- (tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
- {
- Form_pg_shadow shadow_form = (Form_pg_shadow) GETSTRUCT(tuple);
- int32 this_sysid;
-
- user_exists = (strcmp(NameStr(shadow_form->usename), stmt->user) == 0);
-
- this_sysid = shadow_form->usesysid;
- if (havesysid) /* customized id wanted */
- sysid_exists = (this_sysid == sysid);
- else
- {
- /* pick 1 + max */
- if (this_sysid > max_id)
- max_id = this_sysid;
- }
- }
- heap_endscan(scan);
+ pg_authid_rel = heap_open(AuthIdRelationId, ExclusiveLock);
+ pg_authid_dsc = RelationGetDescr(pg_authid_rel);
- if (user_exists)
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("user \"%s\" already exists",
- stmt->user)));
- if (sysid_exists)
+ tuple = SearchSysCache(AUTHNAME,
+ PointerGetDatum(stmt->role),
+ 0, 0, 0);
+ if (HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("user ID %d is already assigned", sysid)));
-
- /* If no sysid given, use max existing id + 1 */
- if (!havesysid)
- sysid = max_id + 1;
+ errmsg("role \"%s\" already exists",
+ stmt->role)));
/*
* Build a tuple to insert
@@ -224,105 +204,123 @@ CreateUser(CreateUserStmt *stmt)
MemSet(new_record, 0, sizeof(new_record));
MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));
- new_record[Anum_pg_shadow_usename - 1] =
- DirectFunctionCall1(namein, CStringGetDatum(stmt->user));
- new_record[Anum_pg_shadow_usesysid - 1] = Int32GetDatum(sysid);
- AssertState(BoolIsValid(createdb));
- new_record[Anum_pg_shadow_usecreatedb - 1] = BoolGetDatum(createdb);
- AssertState(BoolIsValid(createuser));
- new_record[Anum_pg_shadow_usesuper - 1] = BoolGetDatum(createuser);
- /* superuser gets catupd right by default */
- new_record[Anum_pg_shadow_usecatupd - 1] = BoolGetDatum(createuser);
+ new_record[Anum_pg_authid_rolname - 1] =
+ DirectFunctionCall1(namein, CStringGetDatum(stmt->role));
+
+ new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper);
+ 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);
if (password)
{
if (!encrypt_password || isMD5(password))
- new_record[Anum_pg_shadow_passwd - 1] =
+ new_record[Anum_pg_authid_rolpassword - 1] =
DirectFunctionCall1(textin, CStringGetDatum(password));
else
{
- if (!EncryptMD5(password, stmt->user, strlen(stmt->user),
+ if (!EncryptMD5(password, stmt->role, strlen(stmt->role),
encrypted_password))
elog(ERROR, "password encryption failed");
- new_record[Anum_pg_shadow_passwd - 1] =
+ new_record[Anum_pg_authid_rolpassword - 1] =
DirectFunctionCall1(textin, CStringGetDatum(encrypted_password));
}
}
else
- new_record_nulls[Anum_pg_shadow_passwd - 1] = 'n';
+ new_record_nulls[Anum_pg_authid_rolpassword - 1] = 'n';
if (validUntil)
- new_record[Anum_pg_shadow_valuntil - 1] =
- DirectFunctionCall1(abstimein, CStringGetDatum(validUntil));
+ new_record[Anum_pg_authid_rolvaliduntil - 1] =
+ DirectFunctionCall3(timestamptz_in,
+ CStringGetDatum(validUntil),
+ ObjectIdGetDatum(InvalidOid),
+ Int32GetDatum(-1));
+
else
- new_record_nulls[Anum_pg_shadow_valuntil - 1] = 'n';
+ new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = 'n';
- new_record_nulls[Anum_pg_shadow_useconfig - 1] = 'n';
+ new_record_nulls[Anum_pg_authid_rolconfig - 1] = 'n';
- tuple = heap_formtuple(pg_shadow_dsc, new_record, new_record_nulls);
+ tuple = heap_formtuple(pg_authid_dsc, new_record, new_record_nulls);
/*
- * Insert new record in the pg_shadow table
+ * Insert new record in the pg_authid table
*/
- simple_heap_insert(pg_shadow_rel, tuple);
+ roleid = simple_heap_insert(pg_authid_rel, tuple);
+ Assert(OidIsValid(roleid));
/* Update indexes */
- CatalogUpdateIndexes(pg_shadow_rel, tuple);
+ CatalogUpdateIndexes(pg_authid_rel, tuple);
/*
- * Add the user to the groups specified. We'll just call the below
- * AlterGroup for this.
+ * Add the new role to the specified existing roles.
*/
- foreach(item, groupElts)
+ foreach(item, roleElts)
{
- AlterGroupStmt ags;
+ char *oldrolename = strVal(lfirst(item));
+ Oid oldroleid = get_roleid_checked(oldrolename);
- ags.name = strVal(lfirst(item)); /* the group name to add
- * this in */
- ags.action = +1;
- ags.listUsers = list_make1(makeInteger(sysid));
- AlterGroup(&ags, "CREATE USER");
+ AddRoleMems(oldrolename, oldroleid,
+ list_make1(makeString(stmt->role)),
+ list_make1_oid(roleid),
+ GetUserId(), false);
}
/*
+ * Add the specified members to this new role.
+ */
+ AddRoleMems(stmt->role, roleid,
+ rolememElts, roleNamesToIds(rolememElts),
+ GetUserId(), false);
+
+ /*
* Now we can clean up; but keep lock until commit (to avoid possible
* deadlock when commit code tries to acquire lock).
*/
- heap_close(pg_shadow_rel, NoLock);
+ heap_close(pg_authid_rel, NoLock);
/*
- * Set flag to update flat password file at commit.
+ * Set flag to update flat auth file at commit.
*/
- user_file_update_needed();
+ auth_file_update_needed();
}
-
/*
- * ALTER USER
+ * ALTER ROLE
*/
void
-AlterUser(AlterUserStmt *stmt)
+AlterRole(AlterRoleStmt *stmt)
{
- Datum new_record[Natts_pg_shadow];
- char new_record_nulls[Natts_pg_shadow];
- char new_record_repl[Natts_pg_shadow];
- Relation pg_shadow_rel;
- TupleDesc pg_shadow_dsc;
+ Datum new_record[Natts_pg_authid];
+ char new_record_nulls[Natts_pg_authid];
+ char new_record_repl[Natts_pg_authid];
+ Relation pg_authid_rel;
+ TupleDesc pg_authid_dsc;
HeapTuple tuple,
new_tuple;
ListCell *option;
- char *password = NULL; /* PostgreSQL user password */
+ char *password = NULL; /* user password */
bool encrypt_password = Password_encryption; /* encrypt password? */
char encrypted_password[MD5_PASSWD_LEN + 1];
- int createdb = -1; /* Can the user create databases? */
- int createuser = -1; /* Can this user create users? */
+ int issuper = -1; /* Make the user a superuser? */
+ int createrole = -1; /* Can this user create roles? */
+ int createdb = -1; /* Can the user create databases? */
+ int canlogin = -1; /* Can this user login? */
+ int adminopt = 0; /* Can this user grant this role to others? */
+ List *rolememElts = NIL; /* The roles which will be added/removed to this role */
char *validUntil = NULL; /* The time the login is valid
* until */
DefElem *dpassword = NULL;
DefElem *dcreatedb = NULL;
- DefElem *dcreateuser = NULL;
+ DefElem *dcreaterole = NULL;
+ DefElem *dcanlogin = NULL;
+ DefElem *dadminopt = NULL;
DefElem *dvalidUntil = NULL;
+ DefElem *drolememElts = NULL;
+ Oid roleid;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
@@ -351,13 +349,29 @@ AlterUser(AlterUserStmt *stmt)
errmsg("conflicting or redundant options")));
dcreatedb = defel;
}
- else if (strcmp(defel->defname, "createuser") == 0)
+ else if (strcmp(defel->defname, "createrole") == 0)
{
- if (dcreateuser)
+ if (dcreaterole)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- dcreateuser = defel;
+ dcreaterole = defel;
+ }
+ else if (strcmp(defel->defname, "canlogin") == 0)
+ {
+ if (dcanlogin)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ dcanlogin = defel;
+ }
+ else if (strcmp(defel->defname, "adminopt") == 0)
+ {
+ if (dadminopt)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ dadminopt = defel;
}
else if (strcmp(defel->defname, "validUntil") == 0)
{
@@ -367,6 +381,14 @@ AlterUser(AlterUserStmt *stmt)
errmsg("conflicting or redundant options")));
dvalidUntil = defel;
}
+ else if (strcmp(defel->defname, "rolememElts") == 0 && stmt->action != 0)
+ {
+ if (drolememElts)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ drolememElts = defel;
+ }
else
elog(ERROR, "option \"%s\" not recognized",
defel->defname);
@@ -374,42 +396,54 @@ AlterUser(AlterUserStmt *stmt)
if (dcreatedb)
createdb = intVal(dcreatedb->arg);
- if (dcreateuser)
- createuser = intVal(dcreateuser->arg);
+ if (dcreaterole)
+ {
+ createrole = intVal(dcreaterole->arg);
+ /* XXX createrole implies issuper for now */
+ issuper = createrole;
+ }
+ if (dcanlogin)
+ canlogin = intVal(dcanlogin->arg);
+ if (dadminopt)
+ adminopt = intVal(dadminopt->arg);
if (dvalidUntil)
validUntil = strVal(dvalidUntil->arg);
if (dpassword)
password = strVal(dpassword->arg);
-
- if (password)
- CheckPgUserAclNotNull();
+ if (drolememElts)
+ rolememElts = (List *) drolememElts->arg;
/* must be superuser or just want to change your own password */
if (!superuser() &&
- !(createdb < 0 &&
- createuser < 0 &&
+ !(issuper < 0 &&
+ createrole < 0 &&
+ createdb < 0 &&
+ canlogin < 0 &&
!validUntil &&
+ !rolememElts &&
+ !adminopt &&
password &&
- strcmp(GetUserNameFromId(GetUserId()), stmt->user) == 0))
+ strcmp(GetUserNameFromId(GetUserId()), stmt->role) == 0))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied")));
/*
- * Scan the pg_shadow relation to be certain the user exists. Note we
- * secure exclusive lock to protect our update of the flat password
- * file.
+ * Scan the pg_authid relation to be certain the user exists. Note we
+ * secure exclusive lock to protect our update of the flat auth file.
*/
- pg_shadow_rel = heap_open(ShadowRelationId, ExclusiveLock);
- pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
+ pg_authid_rel = heap_open(AuthIdRelationId, ExclusiveLock);
+ pg_authid_dsc = RelationGetDescr(pg_authid_rel);
- tuple = SearchSysCache(SHADOWNAME,
- PointerGetDatum(stmt->user),
+ tuple = SearchSysCache(AUTHNAME,
+ PointerGetDatum(stmt->role),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user \"%s\" does not exist", stmt->user)));
+ errmsg("role \"%s\" does not exist", stmt->role)));
+
+ roleid = HeapTupleGetOid(tuple);
/*
* Build an updated tuple, perusing the information just obtained
@@ -418,65 +452,79 @@ AlterUser(AlterUserStmt *stmt)
MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));
MemSet(new_record_repl, ' ', sizeof(new_record_repl));
- new_record[Anum_pg_shadow_usename - 1] = DirectFunctionCall1(namein,
- CStringGetDatum(stmt->user));
- new_record_repl[Anum_pg_shadow_usename - 1] = 'r';
-
- /* createdb */
- if (createdb >= 0)
- {
- new_record[Anum_pg_shadow_usecreatedb - 1] = BoolGetDatum(createdb > 0);
- new_record_repl[Anum_pg_shadow_usecreatedb - 1] = 'r';
- }
+ new_record[Anum_pg_authid_rolname - 1] = DirectFunctionCall1(namein,
+ CStringGetDatum(stmt->role));
+ new_record_repl[Anum_pg_authid_rolname - 1] = 'r';
/*
- * createuser (superuser) and catupd
+ * issuper/createrole/catupdate/etc
*
- * XXX It's rather unclear how to handle catupd. It's probably best to
+ * XXX It's rather unclear how to handle catupdate. It's probably best to
* keep it equal to the superuser status, otherwise you could end up
* with a situation where no existing superuser can alter the
- * catalogs, including pg_shadow!
+ * catalogs, including pg_authid!
*/
- if (createuser >= 0)
+ if (issuper >= 0)
{
- new_record[Anum_pg_shadow_usesuper - 1] = BoolGetDatum(createuser > 0);
- new_record_repl[Anum_pg_shadow_usesuper - 1] = 'r';
+ new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper > 0);
+ new_record_repl[Anum_pg_authid_rolsuper - 1] = 'r';
- new_record[Anum_pg_shadow_usecatupd - 1] = BoolGetDatum(createuser > 0);
- new_record_repl[Anum_pg_shadow_usecatupd - 1] = 'r';
+ new_record[Anum_pg_authid_rolcatupdate - 1] = BoolGetDatum(issuper > 0);
+ new_record_repl[Anum_pg_authid_rolcatupdate - 1] = 'r';
+ }
+
+ if (createrole >= 0)
+ {
+ new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole > 0);
+ new_record_repl[Anum_pg_authid_rolcreaterole - 1] = 'r';
+ }
+
+ if (createdb >= 0)
+ {
+ new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb > 0);
+ new_record_repl[Anum_pg_authid_rolcreatedb - 1] = 'r';
+ }
+
+ if (canlogin >= 0)
+ {
+ new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin > 0);
+ new_record_repl[Anum_pg_authid_rolcanlogin - 1] = 'r';
}
/* password */
if (password)
{
if (!encrypt_password || isMD5(password))
- new_record[Anum_pg_shadow_passwd - 1] =
+ new_record[Anum_pg_authid_rolpassword - 1] =
DirectFunctionCall1(textin, CStringGetDatum(password));
else
{
- if (!EncryptMD5(password, stmt->user, strlen(stmt->user),
+ if (!EncryptMD5(password, stmt->role, strlen(stmt->role),
encrypted_password))
elog(ERROR, "password encryption failed");
- new_record[Anum_pg_shadow_passwd - 1] =
+ new_record[Anum_pg_authid_rolpassword - 1] =
DirectFunctionCall1(textin, CStringGetDatum(encrypted_password));
}
- new_record_repl[Anum_pg_shadow_passwd - 1] = 'r';
+ new_record_repl[Anum_pg_authid_rolpassword - 1] = 'r';
}
/* valid until */
if (validUntil)
{
- new_record[Anum_pg_shadow_valuntil - 1] =
- DirectFunctionCall1(abstimein, CStringGetDatum(validUntil));
- new_record_repl[Anum_pg_shadow_valuntil - 1] = 'r';
+ new_record[Anum_pg_authid_rolvaliduntil - 1] =
+ DirectFunctionCall3(timestamptz_in,
+ CStringGetDatum(validUntil),
+ ObjectIdGetDatum(InvalidOid),
+ Int32GetDatum(-1));
+ new_record_repl[Anum_pg_authid_rolvaliduntil - 1] = 'r';
}
- new_tuple = heap_modifytuple(tuple, pg_shadow_dsc, new_record,
+ new_tuple = heap_modifytuple(tuple, pg_authid_dsc, new_record,
new_record_nulls, new_record_repl);
- simple_heap_update(pg_shadow_rel, &tuple->t_self, new_tuple);
+ simple_heap_update(pg_authid_rel, &tuple->t_self, new_tuple);
/* Update indexes */
- CatalogUpdateIndexes(pg_shadow_rel, new_tuple);
+ CatalogUpdateIndexes(pg_authid_rel, new_tuple);
ReleaseSysCache(tuple);
heap_freetuple(new_tuple);
@@ -485,59 +533,68 @@ AlterUser(AlterUserStmt *stmt)
* Now we can clean up; but keep lock until commit (to avoid possible
* deadlock when commit code tries to acquire lock).
*/
- heap_close(pg_shadow_rel, NoLock);
+ heap_close(pg_authid_rel, NoLock);
+
+ if (stmt->action == +1) /* add members to role */
+ AddRoleMems(stmt->role, roleid,
+ rolememElts, roleNamesToIds(rolememElts),
+ GetUserId(), adminopt);
+ else if (stmt->action == -1) /* drop members from role */
+ DelRoleMems(stmt->role, roleid,
+ rolememElts, roleNamesToIds(rolememElts),
+ adminopt);
/*
- * Set flag to update flat password file at commit.
+ * Set flag to update flat auth file at commit.
*/
- user_file_update_needed();
+ auth_file_update_needed();
}
/*
- * ALTER USER ... SET
+ * ALTER ROLE ... SET
*/
void
-AlterUserSet(AlterUserSetStmt *stmt)
+AlterRoleSet(AlterRoleSetStmt *stmt)
{
char *valuestr;
HeapTuple oldtuple,
newtuple;
Relation rel;
- Datum repl_val[Natts_pg_shadow];
- char repl_null[Natts_pg_shadow];
- char repl_repl[Natts_pg_shadow];
+ Datum repl_val[Natts_pg_authid];
+ char repl_null[Natts_pg_authid];
+ char repl_repl[Natts_pg_authid];
int i;
valuestr = flatten_set_variable_args(stmt->variable, stmt->value);
/*
* RowExclusiveLock is sufficient, because we don't need to update the
- * flat password file.
+ * flat auth file.
*/
- rel = heap_open(ShadowRelationId, RowExclusiveLock);
- oldtuple = SearchSysCache(SHADOWNAME,
- PointerGetDatum(stmt->user),
+ rel = heap_open(AuthIdRelationId, RowExclusiveLock);
+ oldtuple = SearchSysCache(AUTHNAME,
+ PointerGetDatum(stmt->role),
0, 0, 0);
if (!HeapTupleIsValid(oldtuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user \"%s\" does not exist", stmt->user)));
+ errmsg("role \"%s\" does not exist", stmt->role)));
if (!(superuser() ||
- ((Form_pg_shadow) GETSTRUCT(oldtuple))->usesysid == GetUserId()))
+ (HeapTupleGetOid(oldtuple) == GetUserId())))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied")));
- for (i = 0; i < Natts_pg_shadow; i++)
+ for (i = 0; i < Natts_pg_authid; i++)
repl_repl[i] = ' ';
- repl_repl[Anum_pg_shadow_useconfig - 1] = 'r';
+ repl_repl[Anum_pg_authid_rolconfig - 1] = 'r';
if (strcmp(stmt->variable, "all") == 0 && valuestr == NULL)
{
/* RESET ALL */
- repl_null[Anum_pg_shadow_useconfig - 1] = 'n';
+ repl_null[Anum_pg_authid_rolconfig - 1] = 'n';
}
else
{
@@ -545,10 +602,10 @@ AlterUserSet(AlterUserSetStmt *stmt)
bool isnull;
ArrayType *array;
- repl_null[Anum_pg_shadow_useconfig - 1] = ' ';
+ repl_null[Anum_pg_authid_rolconfig - 1] = ' ';
- datum = SysCacheGetAttr(SHADOWNAME, oldtuple,
- Anum_pg_shadow_useconfig, &isnull);
+ datum = SysCacheGetAttr(AUTHNAME, oldtuple,
+ Anum_pg_authid_rolconfig, &isnull);
array = isnull ? NULL : DatumGetArrayTypeP(datum);
@@ -558,9 +615,9 @@ AlterUserSet(AlterUserSetStmt *stmt)
array = GUCArrayDelete(array, stmt->variable);
if (array)
- repl_val[Anum_pg_shadow_useconfig - 1] = PointerGetDatum(array);
+ repl_val[Anum_pg_authid_rolconfig - 1] = PointerGetDatum(array);
else
- repl_null[Anum_pg_shadow_useconfig - 1] = 'n';
+ repl_null[Anum_pg_authid_rolconfig - 1] = 'n';
}
newtuple = heap_modifytuple(oldtuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
@@ -574,60 +631,61 @@ AlterUserSet(AlterUserSetStmt *stmt)
/*
- * DROP USER
+ * DROP ROLE
*/
void
-DropUser(DropUserStmt *stmt)
+DropRole(DropRoleStmt *stmt)
{
- Relation pg_shadow_rel;
- TupleDesc pg_shadow_dsc;
+ Relation pg_authid_rel, pg_auth_members_rel;
ListCell *item;
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to drop users")));
+ errmsg("must be superuser to drop roles")));
/*
- * Scan the pg_shadow relation to find the usesysid of the user to be
+ * Scan the pg_authid relation to find the Oid of the role to be
* deleted. Note we secure exclusive lock, because we need to protect
- * our update of the flat password file.
+ * our update of the flat auth file.
*/
- pg_shadow_rel = heap_open(ShadowRelationId, ExclusiveLock);
- pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
+ pg_authid_rel = heap_open(AuthIdRelationId, ExclusiveLock);
+ pg_auth_members_rel = heap_open(AuthMemRelationId, ExclusiveLock);
- foreach(item, stmt->users)
+ foreach(item, stmt->roles)
{
- const char *user = strVal(lfirst(item));
+ const char *role = strVal(lfirst(item));
HeapTuple tuple,
tmp_tuple;
Relation pg_rel;
TupleDesc pg_dsc;
ScanKeyData scankey;
HeapScanDesc scan;
- AclId usesysid;
+ CatCList *auth_mem_list;
+ Oid roleid;
+ int i;
- tuple = SearchSysCache(SHADOWNAME,
- PointerGetDatum(user),
+ tuple = SearchSysCache(AUTHNAME,
+ PointerGetDatum(role),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user \"%s\" does not exist", user)));
+ errmsg("role \"%s\" does not exist", role)));
- usesysid = ((Form_pg_shadow) GETSTRUCT(tuple))->usesysid;
+ roleid = HeapTupleGetOid(tuple);
- if (usesysid == GetUserId())
+ if (roleid == GetUserId())
ereport(ERROR,
(errcode(ERRCODE_OBJECT_IN_USE),
- errmsg("current user cannot be dropped")));
- if (usesysid == GetSessionUserId())
+ errmsg("current role cannot be dropped")));
+ if (roleid == GetSessionUserId())
ereport(ERROR,
(errcode(ERRCODE_OBJECT_IN_USE),
- errmsg("session user cannot be dropped")));
+ errmsg("session role cannot be dropped")));
/*
- * Check if user still owns a database. If so, error out.
+ * Check if role still owns a database. If so, error out.
*
* (It used to be that this function would drop the database
* automatically. This is not only very dangerous for people that
@@ -639,8 +697,8 @@ DropUser(DropUserStmt *stmt)
ScanKeyInit(&scankey,
Anum_pg_database_datdba,
- BTEqualStrategyNumber, F_INT4EQ,
- Int32GetDatum(usesysid));
+ BTEqualStrategyNumber, F_OIDEQ,
+ roleid);
scan = heap_beginscan(pg_rel, SnapshotNow, 1, &scankey);
@@ -651,8 +709,8 @@ DropUser(DropUserStmt *stmt)
dbname = NameStr(((Form_pg_database) GETSTRUCT(tmp_tuple))->datname);
ereport(ERROR,
(errcode(ERRCODE_OBJECT_IN_USE),
- errmsg("user \"%s\" cannot be dropped", user),
- errdetail("The user owns database \"%s\".", dbname)));
+ errmsg("role \"%s\" cannot be dropped", role),
+ errdetail("The role owns database \"%s\".", dbname)));
}
heap_endscan(scan);
@@ -660,66 +718,64 @@ DropUser(DropUserStmt *stmt)
/*
* Somehow we'd have to check for tables, views, etc. owned by the
- * user as well, but those could be spread out over all sorts of
+ * role as well, but those could be spread out over all sorts of
* databases which we don't have access to (easily).
*/
/*
- * Remove the user from the pg_shadow table
+ * Remove the role from the pg_authid table
*/
- simple_heap_delete(pg_shadow_rel, &tuple->t_self);
+ simple_heap_delete(pg_authid_rel, &tuple->t_self);
ReleaseSysCache(tuple);
/*
- * Remove user from groups
+ * Remove role from roles
*
- * try calling alter group drop user for every group
+ * scan pg_auth_members and remove tuples which have
+ * roleid == member or roleid == role
*/
- pg_rel = heap_open(GroupRelationId, ExclusiveLock);
- pg_dsc = RelationGetDescr(pg_rel);
- scan = heap_beginscan(pg_rel, SnapshotNow, 0, NULL);
- while ((tmp_tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
- {
- AlterGroupStmt ags;
+ auth_mem_list = SearchSysCacheList(AUTHMEMROLEMEM, 1,
+ ObjectIdGetDatum(roleid),
+ 0, 0, 0);
- /* the group name from which to try to drop the user: */
- ags.name = pstrdup(NameStr(((Form_pg_group) GETSTRUCT(tmp_tuple))->groname));
- ags.action = -1;
- ags.listUsers = list_make1(makeInteger(usesysid));
- AlterGroup(&ags, "DROP USER");
+ for (i = 0; i < auth_mem_list->n_members; i++)
+ {
+ HeapTuple authmemtup = &auth_mem_list->members[i]->tuple;
+ simple_heap_delete(pg_auth_members_rel, &authmemtup->t_self);
}
- heap_endscan(scan);
- heap_close(pg_rel, ExclusiveLock);
+ ReleaseSysCacheList(auth_mem_list);
- /*
- * Advance command counter so that later iterations of this loop
- * will see the changes already made. This is essential if, for
- * example, we are trying to drop two users who are members of the
- * same group --- the AlterGroup for the second user had better
- * see the tuple updated from the first one.
- */
- CommandCounterIncrement();
+ auth_mem_list = SearchSysCacheList(AUTHMEMMEMROLE, 1,
+ ObjectIdGetDatum(roleid),
+ 0, 0, 0);
+
+ for (i = 0; i < auth_mem_list->n_members; i++)
+ {
+ HeapTuple authmemtup = &auth_mem_list->members[i]->tuple;
+ simple_heap_delete(pg_auth_members_rel, &authmemtup->t_self);
+ }
+ ReleaseSysCacheList(auth_mem_list);
}
/*
* Now we can clean up; but keep lock until commit (to avoid possible
* deadlock when commit code tries to acquire lock).
*/
- heap_close(pg_shadow_rel, NoLock);
+ heap_close(pg_auth_members_rel, NoLock);
+ heap_close(pg_authid_rel, NoLock);
/*
- * Set flag to update flat password file at commit.
+ * Set flag to update flat auth file at commit.
*/
- user_file_update_needed();
+ auth_file_update_needed();
}
-
/*
- * Rename user
+ * Rename role
*/
void
-RenameUser(const char *oldname, const char *newname)
+RenameRole(const char *oldname, const char *newname)
{
HeapTuple oldtuple,
newtuple;
@@ -727,22 +783,23 @@ RenameUser(const char *oldname, const char *newname)
Relation rel;
Datum datum;
bool isnull;
- Datum repl_val[Natts_pg_shadow];
- char repl_null[Natts_pg_shadow];
- char repl_repl[Natts_pg_shadow];
+ Datum repl_val[Natts_pg_authid];
+ char repl_null[Natts_pg_authid];
+ char repl_repl[Natts_pg_authid];
int i;
+ Oid roleid;
/* ExclusiveLock because we need to update the password file */
- rel = heap_open(ShadowRelationId, ExclusiveLock);
+ rel = heap_open(AuthIdRelationId, ExclusiveLock);
dsc = RelationGetDescr(rel);
- oldtuple = SearchSysCache(SHADOWNAME,
+ oldtuple = SearchSysCache(AUTHNAME,
CStringGetDatum(oldname),
0, 0, 0);
if (!HeapTupleIsValid(oldtuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user \"%s\" does not exist", oldname)));
+ errmsg("role \"%s\" does not exist", oldname)));
/*
* XXX Client applications probably store the session user somewhere,
@@ -750,43 +807,46 @@ RenameUser(const char *oldname, const char *newname)
* not be an actual problem besides a little confusion, so think about
* this and decide.
*/
- if (((Form_pg_shadow) GETSTRUCT(oldtuple))->usesysid == GetSessionUserId())
+
+ roleid = HeapTupleGetOid(oldtuple);
+
+ if (roleid == GetSessionUserId())
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("session user may not be renamed")));
+ errmsg("session role may not be renamed")));
/* make sure the new name doesn't exist */
- if (SearchSysCacheExists(SHADOWNAME,
+ if (SearchSysCacheExists(AUTHNAME,
CStringGetDatum(newname),
0, 0, 0))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("user \"%s\" already exists", newname)));
+ errmsg("role \"%s\" already exists", newname)));
/* must be superuser */
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to rename users")));
+ errmsg("must be superuser to rename roles")));
- for (i = 0; i < Natts_pg_shadow; i++)
+ for (i = 0; i < Natts_pg_authid; i++)
repl_repl[i] = ' ';
- repl_repl[Anum_pg_shadow_usename - 1] = 'r';
- repl_val[Anum_pg_shadow_usename - 1] = DirectFunctionCall1(namein,
+ repl_repl[Anum_pg_authid_rolname - 1] = 'r';
+ repl_val[Anum_pg_authid_rolname - 1] = DirectFunctionCall1(namein,
CStringGetDatum(newname));
- repl_null[Anum_pg_shadow_usename - 1] = ' ';
+ repl_null[Anum_pg_authid_rolname - 1] = ' ';
- datum = heap_getattr(oldtuple, Anum_pg_shadow_passwd, dsc, &isnull);
+ datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
if (!isnull && isMD5(DatumGetCString(DirectFunctionCall1(textout, datum))))
{
/* MD5 uses the username as salt, so just clear it on a rename */
- repl_repl[Anum_pg_shadow_passwd - 1] = 'r';
- repl_null[Anum_pg_shadow_passwd - 1] = 'n';
+ repl_repl[Anum_pg_authid_rolpassword - 1] = 'r';
+ repl_null[Anum_pg_authid_rolpassword - 1] = 'n';
ereport(NOTICE,
- (errmsg("MD5 password cleared because of user rename")));
+ (errmsg("MD5 password cleared because of role rename")));
}
newtuple = heap_modifytuple(oldtuple, dsc, repl_val, repl_null, repl_repl);
@@ -797,551 +857,322 @@ RenameUser(const char *oldname, const char *newname)
ReleaseSysCache(oldtuple);
heap_close(rel, NoLock);
- user_file_update_needed();
+ auth_file_update_needed();
}
-
/*
- * CheckPgUserAclNotNull
+ * GrantRoleStmt
*
- * check to see if there is an ACL on pg_shadow
- */
-static void
-CheckPgUserAclNotNull(void)
-{
- HeapTuple htup;
-
- htup = SearchSysCache(RELOID,
- ObjectIdGetDatum(ShadowRelationId),
- 0, 0, 0);
- if (!HeapTupleIsValid(htup)) /* should not happen, we hope */
- elog(ERROR, "cache lookup failed for relation %u", ShadowRelationId);
-
- if (heap_attisnull(htup, Anum_pg_class_relacl))
- {
- Form_pg_class classForm = (Form_pg_class) GETSTRUCT(htup);
-
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("before using passwords you must revoke privileges on %s",
- NameStr(classForm->relname)),
- errdetail("This restriction is to prevent unprivileged users from reading the passwords."),
- errhint("Try REVOKE ALL ON \"%s\" FROM PUBLIC.",
- NameStr(classForm->relname))));
- }
-
- ReleaseSysCache(htup);
-}
-
-
-/*
- * CREATE GROUP
+ * Grant/Revoke roles to/from roles
*/
void
-CreateGroup(CreateGroupStmt *stmt)
+GrantRole(GrantRoleStmt *stmt)
{
- Relation pg_group_rel;
- HeapScanDesc scan;
- HeapTuple tuple;
- TupleDesc pg_group_dsc;
- bool group_exists = false,
- sysid_exists = false,
- havesysid = false;
- int max_id;
- Datum new_record[Natts_pg_group];
- char new_record_nulls[Natts_pg_group];
+ Oid grantor;
+ List *grantee_ids;
ListCell *item;
- ListCell *option;
- List *newlist = NIL;
- IdList *grolist;
- int sysid = 0;
- List *userElts = NIL;
- DefElem *dsysid = NULL;
- DefElem *duserElts = NULL;
-
- foreach(option, stmt->options)
- {
- DefElem *defel = (DefElem *) lfirst(option);
- if (strcmp(defel->defname, "sysid") == 0)
- {
- if (dsysid)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
- dsysid = defel;
- }
- else if (strcmp(defel->defname, "userElts") == 0)
- {
- if (duserElts)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("conflicting or redundant options")));
- duserElts = defel;
- }
- else
- elog(ERROR, "option \"%s\" not recognized",
- defel->defname);
- }
-
- if (dsysid)
- {
- sysid = intVal(dsysid->arg);
- if (sysid <= 0)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("group ID must be positive")));
- havesysid = true;
- }
+ if (stmt->grantor)
+ grantor = get_roleid_checked(stmt->grantor);
+ else
+ grantor = GetUserId();
- if (duserElts)
- userElts = (List *) duserElts->arg;
+ grantee_ids = roleNamesToIds(stmt->grantee_roles);
/*
- * Make sure the user can do this.
- */
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to create groups")));
-
- if (strcmp(stmt->name, "public") == 0)
- ereport(ERROR,
- (errcode(ERRCODE_RESERVED_NAME),
- errmsg("group name \"%s\" is reserved",
- stmt->name)));
-
- /*
- * Scan the pg_group relation to be certain the group or id doesn't
- * already exist. Note we secure exclusive lock, because we also need
- * to be sure of what the next grosysid should be, and we need to
- * protect our eventual update of the flat group file.
+ * Step through all of the granted roles and add/remove
+ * entries for the grantees, or, if admin_opt is set, then
+ * just add/remove the admin option.
+ *
+ * Note: Permissions checking is done by AddRoleMems/DelRoleMems
*/
- pg_group_rel = heap_open(GroupRelationId, ExclusiveLock);
- pg_group_dsc = RelationGetDescr(pg_group_rel);
-
- scan = heap_beginscan(pg_group_rel, SnapshotNow, 0, NULL);
- max_id = 99; /* start auto-assigned ids at 100 */
- while (!group_exists && !sysid_exists &&
- (tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ foreach(item, stmt->granted_roles)
{
- Form_pg_group group_form = (Form_pg_group) GETSTRUCT(tuple);
- int32 this_sysid;
+ char *rolename = strVal(lfirst(item));
+ Oid roleid = get_roleid_checked(rolename);
- group_exists = (strcmp(NameStr(group_form->groname), stmt->name) == 0);
-
- this_sysid = group_form->grosysid;
- if (havesysid) /* customized id wanted */
- sysid_exists = (this_sysid == sysid);
+ if (stmt->is_grant)
+ AddRoleMems(rolename, roleid,
+ stmt->grantee_roles, grantee_ids,
+ grantor, stmt->admin_opt);
else
- {
- /* pick 1 + max */
- if (this_sysid > max_id)
- max_id = this_sysid;
- }
+ DelRoleMems(rolename, roleid,
+ stmt->grantee_roles, grantee_ids,
+ stmt->admin_opt);
}
- heap_endscan(scan);
-
- if (group_exists)
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("group \"%s\" already exists",
- stmt->name)));
- if (sysid_exists)
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("group ID %d is already assigned", sysid)));
+}
- /* If no sysid given, use max existing id + 1 */
- if (!havesysid)
- sysid = max_id + 1;
+/*
+ * roleNamesToIds
+ *
+ * Given a list of role names (as String nodes), generate a list of role OIDs
+ * in the same order.
+ */
+static List *
+roleNamesToIds(List *memberNames)
+{
+ List *result = NIL;
+ ListCell *l;
- /*
- * Translate the given user names to ids
- */
- foreach(item, userElts)
+ foreach(l, memberNames)
{
- const char *groupuser = strVal(lfirst(item));
- int32 userid = get_usesysid(groupuser);
+ char *rolename = strVal(lfirst(l));
+ Oid roleid = get_roleid_checked(rolename);
- if (!list_member_int(newlist, userid))
- newlist = lappend_int(newlist, userid);
+ result = lappend_oid(result, roleid);
}
-
- /* build an array to insert */
- if (newlist)
- grolist = IdListToArray(newlist);
- else
- grolist = NULL;
-
- /*
- * Form a tuple to insert
- */
- new_record[Anum_pg_group_groname - 1] =
- DirectFunctionCall1(namein, CStringGetDatum(stmt->name));
- new_record[Anum_pg_group_grosysid - 1] = Int32GetDatum(sysid);
- new_record[Anum_pg_group_grolist - 1] = PointerGetDatum(grolist);
-
- new_record_nulls[Anum_pg_group_groname - 1] = ' ';
- new_record_nulls[Anum_pg_group_grosysid - 1] = ' ';
- new_record_nulls[Anum_pg_group_grolist - 1] = grolist ? ' ' : 'n';
-
- tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls);
-
- /*
- * Insert a new record in the pg_group table
- */
- simple_heap_insert(pg_group_rel, tuple);
-
- /* Update indexes */
- CatalogUpdateIndexes(pg_group_rel, tuple);
-
- /*
- * Now we can clean up; but keep lock until commit (to avoid possible
- * deadlock when commit code tries to acquire lock).
- */
- heap_close(pg_group_rel, NoLock);
-
- /*
- * Set flag to update flat group file at commit.
- */
- group_file_update_needed();
+ return result;
}
-
/*
- * ALTER GROUP
+ * AddRoleMems -- Add given members to the specified role
+ *
+ * rolename: name of role to add to (used only for error messages)
+ * roleid: OID of role to add to
+ * memberNames: list of names of roles to add (used only for error messages)
+ * memberIds: OIDs of roles to add
+ * grantorId: who is granting the membership
+ * admin_opt: granting admin option?
*/
-void
-AlterGroup(AlterGroupStmt *stmt, const char *tag)
+static void
+AddRoleMems(const char *rolename, Oid roleid,
+ List *memberNames, List *memberIds,
+ Oid grantorId, bool admin_opt)
{
- Relation pg_group_rel;
- TupleDesc pg_group_dsc;
- HeapTuple group_tuple;
- IdList *oldarray;
- Datum datum;
- bool null;
- List *newlist;
- ListCell *item;
+ Relation pg_authmem_rel;
+ TupleDesc pg_authmem_dsc;
+ ListCell *nameitem;
+ ListCell *iditem;
- /*
- * Make sure the user can do this.
- */
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to alter groups")));
+ Assert(list_length(memberNames) == list_length(memberIds));
- /*
- * Secure exclusive lock to protect our update of the flat group file.
- */
- pg_group_rel = heap_open(GroupRelationId, ExclusiveLock);
- pg_group_dsc = RelationGetDescr(pg_group_rel);
+ /* Skip permission check if nothing to do */
+ if (!memberIds)
+ return;
/*
- * Fetch existing tuple for group.
+ * Check permissions: must be superuser or have admin option on the
+ * role to be changed.
+ *
+ * XXX: The admin option is not considered to be inherited through
+ * multiple roles, unlike normal 'is_member_of_role' privilege checks.
*/
- group_tuple = SearchSysCache(GRONAME,
- PointerGetDatum(stmt->name),
- 0, 0, 0);
- if (!HeapTupleIsValid(group_tuple))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("group \"%s\" does not exist", stmt->name)));
+ if (!superuser())
+ {
+ HeapTuple authmem_chk_tuple;
+ Form_pg_auth_members authmem_chk;
- /* Fetch old group membership. */
- datum = heap_getattr(group_tuple, Anum_pg_group_grolist,
- pg_group_dsc, &null);
- oldarray = null ? NULL : DatumGetIdListP(datum);
+ if (grantorId != GetUserId())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to set grantor ID")));
+
+ authmem_chk_tuple = SearchSysCache(AUTHMEMROLEMEM,
+ ObjectIdGetDatum(roleid),
+ ObjectIdGetDatum(grantorId),
+ 0, 0);
+ if (!HeapTupleIsValid(authmem_chk_tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser or have admin option on role \"%s\"",
+ rolename)));
- /* initialize list with old array contents */
- newlist = IdArrayToList(oldarray);
+ authmem_chk = (Form_pg_auth_members) GETSTRUCT(authmem_chk_tuple);
+ if (!authmem_chk->admin_option)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser or have admin option on role \"%s\"",
+ rolename)));
+ ReleaseSysCache(authmem_chk_tuple);
+ }
/*
- * Now decide what to do.
+ * Secure exclusive lock to protect our update of the flat auth file.
*/
- AssertState(stmt->action == +1 || stmt->action == -1);
+ pg_authmem_rel = heap_open(AuthMemRelationId, ExclusiveLock);
+ pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
- if (stmt->action == +1) /* add users, might also be invoked by
- * create user */
+ forboth(nameitem, memberNames, iditem, memberIds)
{
+ const char *membername = strVal(lfirst(nameitem));
+ Oid memberid = lfirst_oid(iditem);
+ HeapTuple authmem_tuple;
+ HeapTuple tuple;
+ Datum new_record[Natts_pg_auth_members];
+ char new_record_nulls[Natts_pg_auth_members];
+ char new_record_repl[Natts_pg_auth_members];
+
/*
- * convert the to be added usernames to sysids and add them to the
- * list
+ * Check if entry for this role/member already exists;
+ * if so, give warning unless we are adding admin option.
*/
- foreach(item, stmt->listUsers)
+ authmem_tuple = SearchSysCache(AUTHMEMROLEMEM,
+ ObjectIdGetDatum(roleid),
+ ObjectIdGetDatum(memberid),
+ 0, 0);
+ if (HeapTupleIsValid(authmem_tuple) && !admin_opt)
{
- int32 sysid;
-
- if (strcmp(tag, "ALTER GROUP") == 0)
- {
- /* Get the uid of the proposed user to add. */
- sysid = get_usesysid(strVal(lfirst(item)));
- }
- else if (strcmp(tag, "CREATE USER") == 0)
- {
- /*
- * in this case we already know the uid and it wouldn't be
- * in the cache anyway yet
- */
- sysid = intVal(lfirst(item));
- }
- else
- {
- elog(ERROR, "unexpected tag: \"%s\"", tag);
- sysid = 0; /* keep compiler quiet */
- }
-
- if (!list_member_int(newlist, sysid))
- newlist = lappend_int(newlist, sysid);
+ ereport(NOTICE,
+ (errmsg("role \"%s\" is already a member of role \"%s\"",
+ membername, rolename)));
+ ReleaseSysCache(authmem_tuple);
+ continue;
}
- /* Do the update */
- UpdateGroupMembership(pg_group_rel, group_tuple, newlist);
- } /* endif alter group add user */
+ /* Build a tuple to insert or update */
+ MemSet(new_record, 0, sizeof(new_record));
+ MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));
+ MemSet(new_record_repl, ' ', sizeof(new_record_repl));
- else if (stmt->action == -1) /* drop users from group */
- {
- bool is_dropuser = strcmp(tag, "DROP USER") == 0;
+ new_record[Anum_pg_auth_members_roleid - 1] = ObjectIdGetDatum(roleid);
+ new_record[Anum_pg_auth_members_member - 1] = ObjectIdGetDatum(memberid);
+ new_record[Anum_pg_auth_members_grantor - 1] = ObjectIdGetDatum(grantorId);
+ new_record[Anum_pg_auth_members_admin_option - 1] = BoolGetDatum(admin_opt);
- if (newlist == NIL)
+ if (HeapTupleIsValid(authmem_tuple))
{
- if (!is_dropuser)
- ereport(WARNING,
- (errcode(ERRCODE_WARNING),
- errmsg("group \"%s\" does not have any members",
- stmt->name)));
+ new_record_repl[Anum_pg_auth_members_grantor - 1] = 'r';
+ new_record_repl[Anum_pg_auth_members_admin_option - 1] = 'r';
+ tuple = heap_modifytuple(authmem_tuple, pg_authmem_dsc,
+ new_record,
+ new_record_nulls, new_record_repl);
+ simple_heap_update(pg_authmem_rel, &tuple->t_self, tuple);
+ CatalogUpdateIndexes(pg_authmem_rel, tuple);
+ ReleaseSysCache(authmem_tuple);
}
else
{
- /*
- * convert the to be dropped usernames to sysids and remove
- * them from the list
- */
- foreach(item, stmt->listUsers)
- {
- int32 sysid;
-
- if (!is_dropuser)
- {
- /* Get the uid of the proposed user to drop. */
- sysid = get_usesysid(strVal(lfirst(item)));
- }
- else
- {
- /* for dropuser we already know the uid */
- sysid = intVal(lfirst(item));
- }
- if (list_member_int(newlist, sysid))
- newlist = list_delete_int(newlist, sysid);
- else if (!is_dropuser)
- ereport(WARNING,
- (errcode(ERRCODE_WARNING),
- errmsg("user \"%s\" is not in group \"%s\"",
- strVal(lfirst(item)), stmt->name)));
- }
-
- /* Do the update */
- UpdateGroupMembership(pg_group_rel, group_tuple, newlist);
- } /* endif group not null */
- } /* endif alter group drop user */
-
- ReleaseSysCache(group_tuple);
+ tuple = heap_formtuple(pg_authmem_dsc,
+ new_record, new_record_nulls);
+ simple_heap_insert(pg_authmem_rel, tuple);
+ CatalogUpdateIndexes(pg_authmem_rel, tuple);
+ }
+ }
/*
* Now we can clean up; but keep lock until commit (to avoid possible
* deadlock when commit code tries to acquire lock).
*/
- heap_close(pg_group_rel, NoLock);
-
- /*
- * Set flag to update flat group file at commit.
- */
- group_file_update_needed();
+ heap_close(pg_authmem_rel, NoLock);
}
/*
- * Subroutine for AlterGroup: given a pg_group tuple and a desired new
- * membership (expressed as an integer list), form and write an updated tuple.
- * The pg_group relation must be open and locked already.
+ * DelRoleMems -- Remove given members from the specified role
+ *
+ * rolename: name of role to del from (used only for error messages)
+ * roleid: OID of role to del from
+ * memberNames: list of names of roles to del (used only for error messages)
+ * memberIds: OIDs of roles to del
+ * admin_opt: remove admin option only?
*/
static void
-UpdateGroupMembership(Relation group_rel, HeapTuple group_tuple,
- List *members)
+DelRoleMems(const char *rolename, Oid roleid,
+ List *memberNames, List *memberIds,
+ bool admin_opt)
{
- IdList *newarray;
- Datum new_record[Natts_pg_group];
- char new_record_nulls[Natts_pg_group];
- char new_record_repl[Natts_pg_group];
- HeapTuple tuple;
+ Relation pg_authmem_rel;
+ TupleDesc pg_authmem_dsc;
+ ListCell *nameitem;
+ ListCell *iditem;
- newarray = IdListToArray(members);
+ Assert(list_length(memberNames) == list_length(memberIds));
+
+ /* Skip permission check if nothing to do */
+ if (!memberIds)
+ return;
/*
- * Form an updated tuple with the new array and write it back.
+ * Check permissions: must be superuser or have admin option on the
+ * role to be changed.
+ *
+ * XXX: The admin option is not considered to be inherited through
+ * multiple roles, unlike normal 'is_member_of_role' privilege checks.
*/
- MemSet(new_record, 0, sizeof(new_record));
- MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));
- MemSet(new_record_repl, ' ', sizeof(new_record_repl));
-
- new_record[Anum_pg_group_grolist - 1] = PointerGetDatum(newarray);
- new_record_repl[Anum_pg_group_grolist - 1] = 'r';
-
- tuple = heap_modifytuple(group_tuple, RelationGetDescr(group_rel),
- new_record, new_record_nulls, new_record_repl);
-
- simple_heap_update(group_rel, &group_tuple->t_self, tuple);
-
- /* Update indexes */
- CatalogUpdateIndexes(group_rel, tuple);
-}
-
-
-/*
- * Convert an integer list of sysids to an array.
- */
-static IdList *
-IdListToArray(List *members)
-{
- int nmembers = list_length(members);
- IdList *newarray;
- ListCell *item;
- int i;
-
- newarray = palloc(ARR_OVERHEAD(1) + nmembers * sizeof(int32));
- newarray->size = ARR_OVERHEAD(1) + nmembers * sizeof(int32);
- newarray->flags = 0;
- newarray->elemtype = INT4OID;
- ARR_NDIM(newarray) = 1; /* one dimensional array */
- ARR_LBOUND(newarray)[0] = 1; /* axis starts at one */
- ARR_DIMS(newarray)[0] = nmembers; /* axis is this long */
- i = 0;
- foreach(item, members)
- ((int *) ARR_DATA_PTR(newarray))[i++] = lfirst_int(item);
-
- return newarray;
-}
-
-/*
- * Convert an array of sysids to an integer list.
- */
-static List *
-IdArrayToList(IdList *oldarray)
-{
- List *newlist = NIL;
- int hibound,
- i;
-
- if (oldarray == NULL)
- return NIL;
-
- Assert(ARR_NDIM(oldarray) == 1);
- Assert(ARR_ELEMTYPE(oldarray) == INT4OID);
-
- hibound = ARR_DIMS(oldarray)[0];
-
- for (i = 0; i < hibound; i++)
+ if (!superuser())
{
- int32 sysid;
+ HeapTuple authmem_chk_tuple;
+ Form_pg_auth_members authmem_chk;
+
+ authmem_chk_tuple = SearchSysCache(AUTHMEMROLEMEM,
+ ObjectIdGetDatum(roleid),
+ ObjectIdGetDatum(GetUserId()),
+ 0, 0);
+ if (!HeapTupleIsValid(authmem_chk_tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser or have admin option on role \"%s\"",
+ rolename)));
- sysid = ((int32 *) ARR_DATA_PTR(oldarray))[i];
- /* filter out any duplicates --- probably a waste of time */
- if (!list_member_int(newlist, sysid))
- newlist = lappend_int(newlist, sysid);
+ authmem_chk = (Form_pg_auth_members) GETSTRUCT(authmem_chk_tuple);
+ if (!authmem_chk->admin_option)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser or have admin option on role \"%s\"",
+ rolename)));
+ ReleaseSysCache(authmem_chk_tuple);
}
- return newlist;
-}
-
-
-/*
- * DROP GROUP
- */
-void
-DropGroup(DropGroupStmt *stmt)
-{
- Relation pg_group_rel;
- HeapTuple tuple;
-
/*
- * Make sure the user can do this.
+ * Secure exclusive lock to protect our update of the flat auth file.
*/
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to drop groups")));
+ pg_authmem_rel = heap_open(AuthMemRelationId, ExclusiveLock);
+ pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
- /*
- * Secure exclusive lock to protect our update of the flat group file.
- */
- pg_group_rel = heap_open(GroupRelationId, ExclusiveLock);
+ forboth(nameitem, memberNames, iditem, memberIds)
+ {
+ const char *membername = strVal(lfirst(nameitem));
+ Oid memberid = lfirst_oid(iditem);
+ HeapTuple authmem_tuple;
- /* Find and delete the group. */
+ /*
+ * Find entry for this role/member
+ */
+ authmem_tuple = SearchSysCache(AUTHMEMROLEMEM,
+ ObjectIdGetDatum(roleid),
+ ObjectIdGetDatum(memberid),
+ 0, 0);
+ if (!HeapTupleIsValid(authmem_tuple))
+ {
+ ereport(WARNING,
+ (errmsg("role \"%s\" is not a member of role \"%s\"",
+ membername, rolename)));
+ continue;
+ }
- tuple = SearchSysCacheCopy(GRONAME,
- PointerGetDatum(stmt->name),
- 0, 0, 0);
- if (!HeapTupleIsValid(tuple))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("group \"%s\" does not exist", stmt->name)));
+ if (!admin_opt)
+ {
+ /* Remove the entry altogether */
+ simple_heap_delete(pg_authmem_rel, &authmem_tuple->t_self);
+ }
+ else
+ {
+ /* Just turn off the admin option */
+ HeapTuple tuple;
+ Datum new_record[Natts_pg_auth_members];
+ char new_record_nulls[Natts_pg_auth_members];
+ char new_record_repl[Natts_pg_auth_members];
+
+ /* Build a tuple to update with */
+ MemSet(new_record, 0, sizeof(new_record));
+ MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));
+ MemSet(new_record_repl, ' ', sizeof(new_record_repl));
+
+ new_record[Anum_pg_auth_members_admin_option - 1] = BoolGetDatum(false);
+ new_record_repl[Anum_pg_auth_members_admin_option - 1] = 'r';
+
+ tuple = heap_modifytuple(authmem_tuple, pg_authmem_dsc,
+ new_record,
+ new_record_nulls, new_record_repl);
+ simple_heap_update(pg_authmem_rel, &tuple->t_self, tuple);
+ CatalogUpdateIndexes(pg_authmem_rel, tuple);
+ }
- simple_heap_delete(pg_group_rel, &tuple->t_self);
+ ReleaseSysCache(authmem_tuple);
+ }
/*
* Now we can clean up; but keep lock until commit (to avoid possible
* deadlock when commit code tries to acquire lock).
*/
- heap_close(pg_group_rel, NoLock);
-
- /*
- * Set flag to update flat group file at commit.
- */
- group_file_update_needed();
-}
-
-
-/*
- * Rename group
- */
-void
-RenameGroup(const char *oldname, const char *newname)
-{
- HeapTuple tup;
- Relation rel;
-
- /* ExclusiveLock because we need to update the flat group file */
- rel = heap_open(GroupRelationId, ExclusiveLock);
-
- tup = SearchSysCacheCopy(GRONAME,
- CStringGetDatum(oldname),
- 0, 0, 0);
- if (!HeapTupleIsValid(tup))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("group \"%s\" does not exist", oldname)));
-
- /* make sure the new name doesn't exist */
- if (SearchSysCacheExists(GRONAME,
- CStringGetDatum(newname),
- 0, 0, 0))
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("group \"%s\" already exists", newname)));
-
- /* must be superuser */
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to rename groups")));
-
- /* rename */
- namestrcpy(&(((Form_pg_group) GETSTRUCT(tup))->groname), newname);
- simple_heap_update(rel, &tup->t_self, tup);
- CatalogUpdateIndexes(rel, tup);
-
- heap_close(rel, NoLock);
- heap_freetuple(tup);
-
- group_file_update_needed();
+ heap_close(pg_authmem_rel, NoLock);
}
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 048a3e41562..7df2a92a6c6 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.108 2005/06/09 21:52:07 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/variable.c,v 1.109 2005/06/28 05:08:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -19,7 +19,7 @@
#include <ctype.h>
#include "access/xact.h"
-#include "catalog/pg_shadow.h"
+#include "catalog/pg_authid.h"
#include "commands/variable.h"
#include "miscadmin.h"
#include "parser/scansup.h"
@@ -567,46 +567,46 @@ assign_client_encoding(const char *value, bool doit, GucSource source)
* SET SESSION AUTHORIZATION
*
* 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 userid
+ * lookups. Hence, the stored form of the value must provide a numeric oid
* that can be re-used directly. We store the string in the form of
* NAMEDATALEN 'x's, followed by T or F to indicate superuserness, followed
- * by the numeric userid, followed by a comma, followed by the user name.
- * This cannot be confused with a plain user name because of the NAMEDATALEN
+ * by the numeric oid, followed by a comma, followed by the role name.
+ * This cannot be confused with a plain role name because of the NAMEDATALEN
* limit on names, so we can tell whether we're being passed an initial
- * username or a saved/restored value.
+ * role name or a saved/restored value.
*/
extern char *session_authorization_string; /* in guc.c */
const char *
assign_session_authorization(const char *value, bool doit, GucSource source)
{
- AclId usesysid = 0;
+ Oid roleid = InvalidOid;
bool is_superuser = false;
- const char *actual_username = NULL;
+ const char *actual_rolename = NULL;
char *result;
if (strspn(value, "x") == NAMEDATALEN &&
(value[NAMEDATALEN] == 'T' || value[NAMEDATALEN] == 'F'))
{
/* might be a saved userid string */
- AclId savedsysid;
+ Oid savedoid;
char *endptr;
- savedsysid = (AclId) strtoul(value + NAMEDATALEN + 1, &endptr, 10);
+ savedoid = (Oid) strtoul(value + NAMEDATALEN + 1, &endptr, 10);
if (endptr != value + NAMEDATALEN + 1 && *endptr == ',')
{
/* syntactically valid, so break out the data */
- usesysid = savedsysid;
+ roleid = savedoid;
is_superuser = (value[NAMEDATALEN] == 'T');
- actual_username = endptr + 1;
+ actual_rolename = endptr + 1;
}
}
- if (usesysid == 0)
+ if (roleid == InvalidOid)
{
/* not a saved ID, so look it up */
- HeapTuple userTup;
+ HeapTuple roleTup;
if (!IsTransactionState())
{
@@ -618,38 +618,38 @@ assign_session_authorization(const char *value, bool doit, GucSource source)
return NULL;
}
- userTup = SearchSysCache(SHADOWNAME,
+ roleTup = SearchSysCache(AUTHNAME,
PointerGetDatum(value),
0, 0, 0);
- if (!HeapTupleIsValid(userTup))
+ if (!HeapTupleIsValid(roleTup))
{
if (source >= PGC_S_INTERACTIVE)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user \"%s\" does not exist", value)));
+ errmsg("role \"%s\" does not exist", value)));
return NULL;
}
- usesysid = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
- is_superuser = ((Form_pg_shadow) GETSTRUCT(userTup))->usesuper;
- actual_username = value;
+ roleid = HeapTupleGetOid(roleTup);
+ is_superuser = ((Form_pg_authid) GETSTRUCT(roleTup))->rolsuper;
+ actual_rolename = value;
- ReleaseSysCache(userTup);
+ ReleaseSysCache(roleTup);
}
if (doit)
- SetSessionAuthorization(usesysid, is_superuser);
+ SetSessionAuthorization(roleid, is_superuser);
- result = (char *) malloc(NAMEDATALEN + 32 + strlen(actual_username));
+ result = (char *) malloc(NAMEDATALEN + 32 + strlen(actual_rolename));
if (!result)
return NULL;
memset(result, 'x', NAMEDATALEN);
- sprintf(result + NAMEDATALEN, "%c%lu,%s",
+ sprintf(result + NAMEDATALEN, "%c%u,%s",
is_superuser ? 'T' : 'F',
- (unsigned long) usesysid,
- actual_username);
+ roleid,
+ actual_rolename);
return result;
}
@@ -662,13 +662,13 @@ show_session_authorization(void)
* assign_session_authorization
*/
const char *value = session_authorization_string;
- AclId savedsysid;
+ Oid savedoid;
char *endptr;
Assert(strspn(value, "x") == NAMEDATALEN &&
(value[NAMEDATALEN] == 'T' || value[NAMEDATALEN] == 'F'));
- savedsysid = (AclId) strtoul(value + NAMEDATALEN + 1, &endptr, 10);
+ savedoid = (Oid) strtoul(value + NAMEDATALEN + 1, &endptr, 10);
Assert(endptr != value + NAMEDATALEN + 1 && *endptr == ',');