aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-06-28 05:09:14 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-06-28 05:09:14 +0000
commit7762619e95272974f90a38d8d85aafbe0e94add5 (patch)
treed7f756687beb883406489d59d13f722995fd7660 /src/backend/utils
parent977530d8da2683dff036c2994395ab518527b93e (diff)
downloadpostgresql-7762619e95272974f90a38d8d85aafbe0e94add5.tar.gz
postgresql-7762619e95272974f90a38d8d85aafbe0e94add5.zip
Replace pg_shadow and pg_group by new role-capable catalogs pg_authid
and pg_auth_members. There are still many loose ends to finish in this patch (no documentation, no regression tests, no pg_dump support for instance). But I'm going to commit it now anyway so that Alvaro can make some progress on shared dependencies. The catalog changes should be pretty much done.
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/adt/acl.c734
-rw-r--r--src/backend/utils/adt/pgstatfuncs.c5
-rw-r--r--src/backend/utils/adt/ri_triggers.c6
-rw-r--r--src/backend/utils/adt/ruleutils.c30
-rw-r--r--src/backend/utils/cache/lsyscache.c73
-rw-r--r--src/backend/utils/cache/syscache.c86
-rw-r--r--src/backend/utils/fmgr/fmgr.c6
-rw-r--r--src/backend/utils/init/flatfiles.c544
-rw-r--r--src/backend/utils/init/miscinit.c95
-rw-r--r--src/backend/utils/init/postinit.c32
-rw-r--r--src/backend/utils/misc/guc.c6
-rw-r--r--src/backend/utils/misc/superuser.c62
12 files changed, 817 insertions, 862 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 68b34f3dce5..4d5904b7690 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.114 2005/05/27 00:57:49 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.115 2005/06/28 05:09:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,20 +17,33 @@
#include <ctype.h>
#include "catalog/namespace.h"
-#include "catalog/pg_group.h"
-#include "catalog/pg_shadow.h"
+#include "catalog/pg_authid.h"
+#include "catalog/pg_auth_members.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
#include "commands/tablespace.h"
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/builtins.h"
+#include "utils/catcache.h"
+#include "utils/inval.h"
#include "utils/lsyscache.h"
+#include "utils/memutils.h"
#include "utils/syscache.h"
-#define ACL_IDTYPE_GID_KEYWORD "group"
-#define ACL_IDTYPE_UID_KEYWORD "user"
+#define ACL_IDTYPE_ROLE_KEYWORD "role"
+
+/* The rolmemcache is a possibly-empty list of role OIDs.
+ * rolmemRole is the Role for which the cache was generated.
+ * In the event of a Role change the cache will be regenerated.
+ */
+static List *rolmemcache = NIL;
+static Oid rolmemRole = InvalidOid;
+
+/* rolmemcache and rolmemRole only valid when
+ * rolmemcacheValid is true */
+static bool rolmemcacheValid = false;
static const char *getid(const char *s, char *n);
static void putid(char *p, const char *s);
@@ -38,10 +51,9 @@ static Acl *allocacl(int n);
static const char *aclparse(const char *s, AclItem *aip);
static bool aclitem_match(const AclItem *a1, const AclItem *a2);
static void check_circularity(const Acl *old_acl, const AclItem *mod_aip,
- AclId ownerid);
-static Acl *recursive_revoke(Acl *acl, AclId grantee, AclMode revoke_privs,
- AclId ownerid, DropBehavior behavior);
-static bool in_group(AclId uid, AclId gid);
+ Oid ownerId);
+static Acl *recursive_revoke(Acl *acl, Oid grantee, AclMode revoke_privs,
+ Oid ownerId, DropBehavior behavior);
static AclMode convert_priv_string(text *priv_type_text);
@@ -58,6 +70,9 @@ static AclMode convert_schema_priv_string(text *priv_type_text);
static Oid convert_tablespace_name(text *tablespacename);
static AclMode convert_tablespace_priv_string(text *priv_type_text);
+static void RolMemCacheCallback(Datum arg, Oid relid);
+static void recomputeRolMemCache(Oid roleid);
+
/*
* getid
@@ -175,7 +190,6 @@ aclparse(const char *s, AclItem *aip)
AclMode privs,
goption,
read;
- uint32 idtype;
char name[NAMEDATALEN];
char name2[NAMEDATALEN];
@@ -184,27 +198,22 @@ aclparse(const char *s, AclItem *aip)
#ifdef ACLDEBUG
elog(LOG, "aclparse: input = \"%s\"", s);
#endif
- idtype = ACL_IDTYPE_UID;
s = getid(s, name);
if (*s != '=')
{
/* we just read a keyword, not a name */
- if (strcmp(name, ACL_IDTYPE_GID_KEYWORD) == 0)
- idtype = ACL_IDTYPE_GID;
- else if (strcmp(name, ACL_IDTYPE_UID_KEYWORD) != 0)
+ if (strcmp(name, ACL_IDTYPE_ROLE_KEYWORD) != 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("unrecognized key word: \"%s\"", name),
- errhint("ACL key word must be \"group\" or \"user\".")));
+ errhint("ACL key word must be \"role\".")));
s = getid(s, name); /* move s to the name beyond the keyword */
if (name[0] == '\0')
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("missing name"),
- errhint("A name must follow the \"group\" or \"user\" key word.")));
+ errhint("A name must follow the \"role\" key word.")));
}
- if (name[0] == '\0')
- idtype = ACL_IDTYPE_WORLD;
if (*s != '=')
ereport(ERROR,
@@ -263,18 +272,10 @@ aclparse(const char *s, AclItem *aip)
privs |= read;
}
- switch (idtype)
- {
- case ACL_IDTYPE_UID:
- aip->ai_grantee = get_usesysid(name);
- break;
- case ACL_IDTYPE_GID:
- aip->ai_grantee = get_grosysid(name);
- break;
- case ACL_IDTYPE_WORLD:
- aip->ai_grantee = ACL_ID_WORLD;
- break;
- }
+ if (name[0] == '\0')
+ aip->ai_grantee = ACL_ID_PUBLIC;
+ else
+ aip->ai_grantee = get_roleid_checked(name);
/*
* XXX Allow a degree of backward compatibility by defaulting the
@@ -287,23 +288,24 @@ aclparse(const char *s, AclItem *aip)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("a name must follow the \"/\" sign")));
-
- aip->ai_grantor = get_usesysid(name2);
+ aip->ai_grantor = get_roleid_checked(name2);
}
else
{
- aip->ai_grantor = BOOTSTRAP_USESYSID;
+ aip->ai_grantor = BOOTSTRAP_SUPERUSERID;
ereport(WARNING,
(errcode(ERRCODE_INVALID_GRANTOR),
- errmsg("defaulting grantor to user ID %u", BOOTSTRAP_USESYSID)));
+ errmsg("defaulting grantor to user ID %u",
+ BOOTSTRAP_SUPERUSERID)));
}
- ACLITEM_SET_PRIVS_IDTYPE(*aip, privs, goption, idtype);
+ ACLITEM_SET_PRIVS_GOPTIONS(*aip, privs, goption);
#ifdef ACLDEBUG
- elog(LOG, "aclparse: correctly read [%x %d %x]",
- idtype, aip->ai_grantee, privs);
+ elog(LOG, "aclparse: correctly read [%u %x %x]",
+ aip->ai_grantee, privs, goption);
#endif
+
return s;
}
@@ -375,7 +377,6 @@ aclitemout(PG_FUNCTION_ARGS)
char *out;
HeapTuple htup;
unsigned i;
- char *tmpname;
out = palloc(strlen("group =/") +
2 * N_ACL_RIGHTS +
@@ -385,41 +386,21 @@ aclitemout(PG_FUNCTION_ARGS)
p = out;
*p = '\0';
- switch (ACLITEM_GET_IDTYPE(*aip))
+ if (aip->ai_grantee != ACL_ID_PUBLIC)
{
- case ACL_IDTYPE_UID:
- htup = SearchSysCache(SHADOWSYSID,
- ObjectIdGetDatum(aip->ai_grantee),
- 0, 0, 0);
- if (HeapTupleIsValid(htup))
- {
- putid(p, NameStr(((Form_pg_shadow) GETSTRUCT(htup))->usename));
- ReleaseSysCache(htup);
- }
- else
- {
- /* Generate numeric UID if we don't find an entry */
- sprintf(p, "%d", aip->ai_grantee);
- }
- break;
- case ACL_IDTYPE_GID:
- strcpy(p, "group ");
- p += strlen(p);
- tmpname = get_groname(aip->ai_grantee);
- if (tmpname != NULL)
- putid(p, tmpname);
- else
- {
- /* Generate numeric GID if we don't find an entry */
- sprintf(p, "%d", aip->ai_grantee);
- }
- break;
- case ACL_IDTYPE_WORLD:
- break;
- default:
- elog(ERROR, "unrecognized idtype: %d",
- (int) ACLITEM_GET_IDTYPE(*aip));
- break;
+ htup = SearchSysCache(AUTHOID,
+ ObjectIdGetDatum(aip->ai_grantee),
+ 0, 0, 0);
+ if (HeapTupleIsValid(htup))
+ {
+ putid(p, NameStr(((Form_pg_authid) GETSTRUCT(htup))->rolname));
+ ReleaseSysCache(htup);
+ }
+ else
+ {
+ /* Generate numeric OID if we don't find an entry */
+ sprintf(p, "%u", aip->ai_grantee);
+ }
}
while (*p)
++p;
@@ -437,18 +418,18 @@ aclitemout(PG_FUNCTION_ARGS)
*p++ = '/';
*p = '\0';
- htup = SearchSysCache(SHADOWSYSID,
+ htup = SearchSysCache(AUTHOID,
ObjectIdGetDatum(aip->ai_grantor),
0, 0, 0);
if (HeapTupleIsValid(htup))
{
- putid(p, NameStr(((Form_pg_shadow) GETSTRUCT(htup))->usename));
+ putid(p, NameStr(((Form_pg_authid) GETSTRUCT(htup))->rolname));
ReleaseSysCache(htup);
}
else
{
- /* Generate numeric UID if we don't find an entry */
- sprintf(p, "%d", aip->ai_grantor);
+ /* Generate numeric OID if we don't find an entry */
+ sprintf(p, "%u", aip->ai_grantor);
}
while (*p)
@@ -466,8 +447,7 @@ aclitemout(PG_FUNCTION_ARGS)
static bool
aclitem_match(const AclItem *a1, const AclItem *a2)
{
- return ACLITEM_GET_IDTYPE(*a1) == ACLITEM_GET_IDTYPE(*a2) &&
- a1->ai_grantee == a2->ai_grantee &&
+ return a1->ai_grantee == a2->ai_grantee &&
a1->ai_grantor == a2->ai_grantor;
}
@@ -511,7 +491,7 @@ hash_aclitem(PG_FUNCTION_ARGS)
* newly-created objects (or any object with a NULL acl entry).
*/
Acl *
-acldefault(GrantObjectType objtype, AclId ownerid)
+acldefault(GrantObjectType objtype, Oid ownerId)
{
AclMode world_default;
AclMode owner_default;
@@ -558,10 +538,9 @@ acldefault(GrantObjectType objtype, AclId ownerid)
if (world_default != ACL_NO_RIGHTS)
{
- aip->ai_grantee = ACL_ID_WORLD;
- aip->ai_grantor = ownerid;
- ACLITEM_SET_PRIVS_IDTYPE(*aip, world_default, ACL_NO_RIGHTS,
- ACL_IDTYPE_WORLD);
+ aip->ai_grantee = ACL_ID_PUBLIC;
+ aip->ai_grantor = ownerId;
+ ACLITEM_SET_PRIVS_GOPTIONS(*aip, world_default, ACL_NO_RIGHTS);
aip++;
}
@@ -575,10 +554,9 @@ acldefault(GrantObjectType objtype, AclId ownerid)
* without any explicit "_SYSTEM"-like ACL entry, by internally
* special-casing the owner whereever we are testing grant options.
*/
- aip->ai_grantee = ownerid;
- aip->ai_grantor = ownerid;
- ACLITEM_SET_PRIVS_IDTYPE(*aip, owner_default, ACL_NO_RIGHTS,
- ACL_IDTYPE_UID);
+ aip->ai_grantee = ownerId;
+ aip->ai_grantor = ownerId;
+ ACLITEM_SET_PRIVS_GOPTIONS(*aip, owner_default, ACL_NO_RIGHTS);
return acl;
}
@@ -590,7 +568,7 @@ acldefault(GrantObjectType objtype, AclId ownerid)
* old_acl: the input ACL array
* mod_aip: defines the privileges to be added, removed, or substituted
* modechg: ACL_MODECHG_ADD, ACL_MODECHG_DEL, or ACL_MODECHG_EQL
- * ownerid: AclId of object owner
+ * ownerId: Oid of object owner
* behavior: RESTRICT or CASCADE behavior for recursive removal
*
* ownerid and behavior are only relevant when the update operation specifies
@@ -602,7 +580,7 @@ acldefault(GrantObjectType objtype, AclId ownerid)
*/
Acl *
aclupdate(const Acl *old_acl, const AclItem *mod_aip,
- int modechg, AclId ownerid, DropBehavior behavior)
+ int modechg, Oid ownerId, DropBehavior behavior)
{
Acl *new_acl = NULL;
AclItem *old_aip,
@@ -627,7 +605,7 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
/* If granting grant options, check for circularity */
if (modechg != ACL_MODECHG_DEL &&
ACLITEM_GET_GOPTIONS(*mod_aip) != ACL_NO_RIGHTS)
- check_circularity(old_acl, mod_aip, ownerid);
+ check_circularity(old_acl, mod_aip, ownerId);
num = ACL_NUM(old_acl);
old_aip = ACL_DAT(old_acl);
@@ -661,9 +639,8 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
/* initialize the new entry with no permissions */
new_aip[dst].ai_grantee = mod_aip->ai_grantee;
new_aip[dst].ai_grantor = mod_aip->ai_grantor;
- ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst],
- ACL_NO_RIGHTS, ACL_NO_RIGHTS,
- ACLITEM_GET_IDTYPE(*mod_aip));
+ ACLITEM_SET_PRIVS_GOPTIONS(new_aip[dst],
+ ACL_NO_RIGHTS, ACL_NO_RIGHTS);
num++; /* set num to the size of new_acl */
}
@@ -704,14 +681,14 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
/*
* Remove abandoned privileges (cascading revoke). Currently we can
- * only handle this when the grantee is a user.
+ * only handle this when the grantee is not PUBLIC.
*/
if ((old_goptions & ~new_goptions) != 0)
{
- Assert(ACLITEM_GET_IDTYPE(*mod_aip) == ACL_IDTYPE_UID);
+ Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee,
(old_goptions & ~new_goptions),
- ownerid, behavior);
+ ownerId, behavior);
}
return new_acl;
@@ -721,15 +698,15 @@ aclupdate(const Acl *old_acl, const AclItem *mod_aip,
* Update an ACL array to reflect a change of owner to the parent object
*
* old_acl: the input ACL array (must not be NULL)
- * oldownerid: AclId of the old object owner
- * newownerid: AclId of the new object owner
+ * oldOwnerId: Oid of the old object owner
+ * newOwnerId: Oid of the new object owner
*
* The result is a modified copy; the input object is not changed.
*
* NB: caller is responsible for having detoasted the input ACL, if needed.
*/
Acl *
-aclnewowner(const Acl *old_acl, AclId oldownerid, AclId newownerid)
+aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
{
Acl *new_acl;
AclItem *new_aip;
@@ -755,18 +732,14 @@ aclnewowner(const Acl *old_acl, AclId oldownerid, AclId newownerid)
memcpy(new_aip, old_aip, num * sizeof(AclItem));
for (dst = 0, dst_aip = new_aip; dst < num; dst++, dst_aip++)
{
- /* grantor is always a UID, but grantee might not be */
- if (dst_aip->ai_grantor == oldownerid)
- dst_aip->ai_grantor = newownerid;
- else if (dst_aip->ai_grantor == newownerid)
+ if (dst_aip->ai_grantor == oldOwnerId)
+ dst_aip->ai_grantor = newOwnerId;
+ else if (dst_aip->ai_grantor == newOwnerId)
+ newpresent = true;
+ if (dst_aip->ai_grantee == oldOwnerId)
+ dst_aip->ai_grantee = newOwnerId;
+ else if (dst_aip->ai_grantee == newOwnerId)
newpresent = true;
- if (ACLITEM_GET_IDTYPE(*dst_aip) == ACL_IDTYPE_UID)
- {
- if (dst_aip->ai_grantee == oldownerid)
- dst_aip->ai_grantee = newownerid;
- else if (dst_aip->ai_grantee == newownerid)
- newpresent = true;
- }
}
/*
@@ -836,7 +809,7 @@ aclnewowner(const Acl *old_acl, AclId oldownerid, AclId newownerid)
*/
static void
check_circularity(const Acl *old_acl, const AclItem *mod_aip,
- AclId ownerid)
+ Oid ownerId)
{
Acl *acl;
AclItem *aip;
@@ -845,13 +818,13 @@ check_circularity(const Acl *old_acl, const AclItem *mod_aip,
AclMode own_privs;
/*
- * For now, grant options can only be granted to users, not groups or
- * PUBLIC. Otherwise we'd have to work a bit harder here.
+ * For now, grant options can only be granted to roles, not PUBLIC.
+ * Otherwise we'd have to work a bit harder here.
*/
- Assert(ACLITEM_GET_IDTYPE(*mod_aip) == ACL_IDTYPE_UID);
+ Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
/* The owner always has grant options, no need to check */
- if (mod_aip->ai_grantor == ownerid)
+ if (mod_aip->ai_grantor == ownerId)
return;
/* Make a working copy */
@@ -864,15 +837,14 @@ cc_restart:
aip = ACL_DAT(acl);
for (i = 0; i < num; i++)
{
- if (ACLITEM_GET_IDTYPE(aip[i]) == ACL_IDTYPE_UID &&
- aip[i].ai_grantee == mod_aip->ai_grantee &&
+ if (aip[i].ai_grantee == mod_aip->ai_grantee &&
ACLITEM_GET_GOPTIONS(aip[i]) != ACL_NO_RIGHTS)
{
Acl *new_acl;
/* We'll actually zap ordinary privs too, but no matter */
new_acl = aclupdate(acl, &aip[i], ACL_MODECHG_DEL,
- ownerid, DROP_CASCADE);
+ ownerId, DROP_CASCADE);
pfree(acl);
acl = new_acl;
@@ -884,7 +856,7 @@ cc_restart:
/* Now we can compute grantor's independently-derived privileges */
own_privs = aclmask(acl,
mod_aip->ai_grantor,
- ownerid,
+ ownerId,
ACL_GRANT_OPTION_FOR(ACLITEM_GET_GOPTIONS(*mod_aip)),
ACLMASK_ALL);
own_privs = ACL_OPTION_TO_PRIVS(own_privs);
@@ -908,16 +880,16 @@ cc_restart:
* acl: the input ACL list
* grantee: the user from whom some grant options have been revoked
* revoke_privs: the grant options being revoked
- * ownerid: AclId of object owner
+ * ownerId: Oid of object owner
* behavior: RESTRICT or CASCADE behavior for recursive removal
*
* The input Acl object is pfree'd if replaced.
*/
static Acl *
recursive_revoke(Acl *acl,
- AclId grantee,
+ Oid grantee,
AclMode revoke_privs,
- AclId ownerid,
+ Oid ownerId,
DropBehavior behavior)
{
AclMode still_has;
@@ -926,11 +898,11 @@ recursive_revoke(Acl *acl,
num;
/* The owner can never truly lose grant options, so short-circuit */
- if (grantee == ownerid)
+ if (grantee == ownerId)
return acl;
/* The grantee might still have the privileges via another grantor */
- still_has = aclmask(acl, grantee, ownerid,
+ still_has = aclmask(acl, grantee, ownerId,
ACL_GRANT_OPTION_FOR(revoke_privs),
ACLMASK_ALL);
revoke_privs &= ~still_has;
@@ -956,13 +928,12 @@ restart:
mod_acl.ai_grantor = grantee;
mod_acl.ai_grantee = aip[i].ai_grantee;
- ACLITEM_SET_PRIVS_IDTYPE(mod_acl,
- revoke_privs,
- revoke_privs,
- ACLITEM_GET_IDTYPE(aip[i]));
+ ACLITEM_SET_PRIVS_GOPTIONS(mod_acl,
+ revoke_privs,
+ revoke_privs);
new_acl = aclupdate(acl, &mod_acl, ACL_MODECHG_DEL,
- ownerid, behavior);
+ ownerId, behavior);
pfree(acl);
acl = new_acl;
@@ -976,10 +947,10 @@ restart:
/*
- * aclmask --- compute bitmask of all privileges held by userid.
+ * aclmask --- compute bitmask of all privileges held by roleid.
*
* When 'how' = ACLMASK_ALL, this simply returns the privilege bits
- * held by the given userid according to the given ACL list, ANDed
+ * held by the given roleid according to the given ACL list, ANDed
* with 'mask'. (The point of passing 'mask' is to let the routine
* exit early if all privileges of interest have been found.)
*
@@ -990,20 +961,20 @@ restart:
* Usage patterns:
*
* To see if any of a set of privileges are held:
- * if (aclmask(acl, userid, ownerid, privs, ACLMASK_ANY) != 0)
+ * if (aclmask(acl, roleid, ownerId, privs, ACLMASK_ANY) != 0)
*
* To see if all of a set of privileges are held:
- * if (aclmask(acl, userid, ownerid, privs, ACLMASK_ALL) == privs)
+ * if (aclmask(acl, roleid, ownerId, privs, ACLMASK_ALL) == privs)
*
* To determine exactly which of a set of privileges are held:
- * heldprivs = aclmask(acl, userid, ownerid, privs, ACLMASK_ALL);
+ * heldprivs = aclmask(acl, roleid, ownerId, privs, ACLMASK_ALL);
+ *
*/
AclMode
-aclmask(const Acl *acl, AclId userid, AclId ownerid,
+aclmask(const Acl *acl, Oid roleid, Oid ownerId,
AclMode mask, AclMaskHow how)
{
AclMode result;
- AclMode remaining;
AclItem *aidat;
int i,
num;
@@ -1022,7 +993,7 @@ aclmask(const Acl *acl, AclId userid, AclId ownerid,
result = 0;
/* Owner always implicitly has all grant options */
- if (userid == ownerid)
+ if (is_member_of_role(roleid,ownerId))
{
result = mask & ACLITEM_ALL_GOPTION_BITS;
if (result == mask)
@@ -1033,39 +1004,19 @@ aclmask(const Acl *acl, AclId userid, AclId ownerid,
aidat = ACL_DAT(acl);
/*
- * Check privileges granted directly to user or to public
- */
- for (i = 0; i < num; i++)
- {
- AclItem *aidata = &aidat[i];
-
- if (ACLITEM_GET_IDTYPE(*aidata) == ACL_IDTYPE_WORLD
- || (ACLITEM_GET_IDTYPE(*aidata) == ACL_IDTYPE_UID
- && aidata->ai_grantee == userid))
- {
- result |= (aidata->ai_privs & mask);
- if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
- return result;
- }
- }
-
- /*
- * Check privileges granted via groups. We do this in a separate pass
- * to minimize expensive lookups in pg_group.
+ * Check privileges granted directly to role, indirectly
+ * via role membership or to public
*/
- remaining = (mask & ~result);
for (i = 0; i < num; i++)
{
AclItem *aidata = &aidat[i];
- if (ACLITEM_GET_IDTYPE(*aidata) == ACL_IDTYPE_GID
- && (aidata->ai_privs & remaining)
- && in_group(userid, aidata->ai_grantee))
+ if (aidata->ai_grantee == ACL_ID_PUBLIC ||
+ is_member_of_role(roleid, aidata->ai_grantee))
{
result |= (aidata->ai_privs & mask);
if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
return result;
- remaining = (mask & ~result);
}
}
@@ -1074,55 +1025,19 @@ aclmask(const Acl *acl, AclId userid, AclId ownerid,
/*
- * Is user a member of group?
+ * Is member a member of role?
+ * relmemcache includes the role itself too
*/
-static bool
-in_group(AclId uid, AclId gid)
-{
- bool result = false;
- HeapTuple tuple;
- Datum att;
- bool isNull;
- IdList *glist;
- AclId *aidp;
- int i,
- num;
+bool
+is_member_of_role(Oid member, Oid role)
+{
+ /* Fast path for simple case */
+ if (member == role)
+ return true;
- tuple = SearchSysCache(GROSYSID,
- ObjectIdGetDatum(gid),
- 0, 0, 0);
- if (HeapTupleIsValid(tuple))
- {
- att = SysCacheGetAttr(GROSYSID,
- tuple,
- Anum_pg_group_grolist,
- &isNull);
- if (!isNull)
- {
- /* be sure the IdList is not toasted */
- glist = DatumGetIdListP(att);
- /* scan it */
- num = IDLIST_NUM(glist);
- aidp = IDLIST_DAT(glist);
- for (i = 0; i < num; ++i)
- {
- if (aidp[i] == uid)
- {
- result = true;
- break;
- }
- }
- /* if IdList was toasted, free detoasted copy */
- if ((Pointer) glist != DatumGetPointer(att))
- pfree(glist);
- }
- ReleaseSysCache(tuple);
- }
- else
- ereport(WARNING,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("group with ID %u does not exist", gid)));
- return result;
+ recomputeRolMemCache(member);
+
+ return list_member_oid(rolmemcache, role);
}
@@ -1162,10 +1077,9 @@ aclcontains(PG_FUNCTION_ARGS)
aidat = ACL_DAT(acl);
for (i = 0; i < num; ++i)
{
- if (aip->ai_grantee == aidat[i].ai_grantee
- && ACLITEM_GET_IDTYPE(*aip) == ACLITEM_GET_IDTYPE(aidat[i])
- && aip->ai_grantor == aidat[i].ai_grantor
- && (ACLITEM_GET_RIGHTS(*aip) & ACLITEM_GET_RIGHTS(aidat[i])) == ACLITEM_GET_RIGHTS(*aip))
+ if (aip->ai_grantee == aidat[i].ai_grantee &&
+ aip->ai_grantor == aidat[i].ai_grantor &&
+ (ACLITEM_GET_RIGHTS(*aip) & ACLITEM_GET_RIGHTS(aidat[i])) == ACLITEM_GET_RIGHTS(*aip))
PG_RETURN_BOOL(true);
}
PG_RETURN_BOOL(false);
@@ -1174,51 +1088,22 @@ aclcontains(PG_FUNCTION_ARGS)
Datum
makeaclitem(PG_FUNCTION_ARGS)
{
- int32 u_grantee = PG_GETARG_INT32(0);
- int32 g_grantee = PG_GETARG_INT32(1);
- int32 grantor = PG_GETARG_INT32(2);
- text *privtext = PG_GETARG_TEXT_P(3);
- bool goption = PG_GETARG_BOOL(4);
+ Oid grantee = PG_GETARG_OID(0);
+ Oid grantor = PG_GETARG_OID(1);
+ text *privtext = PG_GETARG_TEXT_P(2);
+ bool goption = PG_GETARG_BOOL(3);
AclItem *aclitem;
AclMode priv;
priv = convert_priv_string(privtext);
- aclitem = (AclItem *) palloc(sizeof(*aclitem));
+ aclitem = (AclItem *) palloc(sizeof(AclItem));
- if (u_grantee == 0 && g_grantee == 0)
- {
- aclitem ->ai_grantee = ACL_ID_WORLD;
+ aclitem->ai_grantee = grantee;
+ aclitem->ai_grantor = grantor;
- ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_WORLD);
- }
- else if (u_grantee != 0 && g_grantee != 0)
- {
- ereport(ERROR,
- (errcode(ERRCODE_DATA_EXCEPTION),
- errmsg("cannot specify both user and group")));
- }
- else if (u_grantee != 0)
- {
- aclitem ->ai_grantee = u_grantee;
-
- ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_UID);
- }
- else
- /* (g_grantee != 0) */
- {
- aclitem ->ai_grantee = g_grantee;
-
- ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_GID);
- }
-
- aclitem ->ai_grantor = grantor;
-
- ACLITEM_SET_PRIVS(*aclitem, priv);
- if (goption)
- ACLITEM_SET_GOPTIONS(*aclitem, priv);
- else
- ACLITEM_SET_GOPTIONS(*aclitem, ACL_NO_RIGHTS);
+ ACLITEM_SET_PRIVS_GOPTIONS(*aclitem, priv,
+ (goption ? priv : ACL_NO_RIGHTS));
PG_RETURN_ACLITEM_P(aclitem);
}
@@ -1267,7 +1152,7 @@ convert_priv_string(text *priv_type_text)
* has_table_privilege variants
* These are all named "has_table_privilege" at the SQL level.
* They take various combinations of relation name, relation OID,
- * user name, user sysid, or implicit user = current_user.
+ * user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
@@ -1281,19 +1166,20 @@ convert_priv_string(text *priv_type_text)
Datum
has_table_privilege_name_name(PG_FUNCTION_ARGS)
{
- Name username = PG_GETARG_NAME(0);
+ Name rolename = PG_GETARG_NAME(0);
text *tablename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
Oid tableoid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*rolename));
+
tableoid = convert_table_name(tablename);
mode = convert_table_priv_string(priv_type_text);
- aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1309,16 +1195,16 @@ has_table_privilege_name(PG_FUNCTION_ARGS)
{
text *tablename = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
Oid tableoid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
tableoid = convert_table_name(tablename);
mode = convert_table_priv_string(priv_type_text);
- aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1334,14 +1220,15 @@ has_table_privilege_name_id(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
Oid tableoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
mode = convert_table_priv_string(priv_type_text);
- aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1357,14 +1244,14 @@ has_table_privilege_id(PG_FUNCTION_ARGS)
{
Oid tableoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
mode = convert_table_priv_string(priv_type_text);
- aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1372,12 +1259,12 @@ has_table_privilege_id(PG_FUNCTION_ARGS)
/*
* has_table_privilege_id_name
* Check user privileges on a table given
- * usesysid, text tablename, and text priv name.
+ * roleid, text tablename, and text priv name.
*/
Datum
has_table_privilege_id_name(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
text *tablename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid tableoid;
@@ -1387,7 +1274,7 @@ has_table_privilege_id_name(PG_FUNCTION_ARGS)
tableoid = convert_table_name(tablename);
mode = convert_table_priv_string(priv_type_text);
- aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1395,12 +1282,12 @@ has_table_privilege_id_name(PG_FUNCTION_ARGS)
/*
* has_table_privilege_id_id
* Check user privileges on a table given
- * usesysid, table oid, and text priv name.
+ * roleid, table oid, and text priv name.
*/
Datum
has_table_privilege_id_id(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Oid tableoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
@@ -1408,7 +1295,7 @@ has_table_privilege_id_id(PG_FUNCTION_ARGS)
mode = convert_table_priv_string(priv_type_text);
- aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
+ aclresult = pg_class_aclcheck(tableoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1491,7 +1378,7 @@ convert_table_priv_string(text *priv_type_text)
* has_database_privilege variants
* These are all named "has_database_privilege" at the SQL level.
* They take various combinations of database name, database OID,
- * user name, user sysid, or implicit user = current_user.
+ * user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
@@ -1508,16 +1395,17 @@ has_database_privilege_name_name(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
text *databasename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
Oid databaseoid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
databaseoid = convert_database_name(databasename);
mode = convert_database_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1533,16 +1421,16 @@ has_database_privilege_name(PG_FUNCTION_ARGS)
{
text *databasename = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
Oid databaseoid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
databaseoid = convert_database_name(databasename);
mode = convert_database_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1558,14 +1446,15 @@ has_database_privilege_name_id(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
Oid databaseoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
mode = convert_database_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1581,14 +1470,14 @@ has_database_privilege_id(PG_FUNCTION_ARGS)
{
Oid databaseoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
mode = convert_database_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1596,12 +1485,12 @@ has_database_privilege_id(PG_FUNCTION_ARGS)
/*
* has_database_privilege_id_name
* Check user privileges on a database given
- * usesysid, text databasename, and text priv name.
+ * roleid, text databasename, and text priv name.
*/
Datum
has_database_privilege_id_name(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
text *databasename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid databaseoid;
@@ -1611,7 +1500,7 @@ has_database_privilege_id_name(PG_FUNCTION_ARGS)
databaseoid = convert_database_name(databasename);
mode = convert_database_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1619,12 +1508,12 @@ has_database_privilege_id_name(PG_FUNCTION_ARGS)
/*
* has_database_privilege_id_id
* Check user privileges on a database given
- * usesysid, database oid, and text priv name.
+ * roleid, database oid, and text priv name.
*/
Datum
has_database_privilege_id_id(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Oid databaseoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
@@ -1632,7 +1521,7 @@ has_database_privilege_id_id(PG_FUNCTION_ARGS)
mode = convert_database_priv_string(priv_type_text);
- aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
+ aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1703,7 +1592,7 @@ convert_database_priv_string(text *priv_type_text)
* has_function_privilege variants
* These are all named "has_function_privilege" at the SQL level.
* They take various combinations of function name, function OID,
- * user name, user sysid, or implicit user = current_user.
+ * user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
@@ -1720,16 +1609,17 @@ has_function_privilege_name_name(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
text *functionname = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
Oid functionoid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
functionoid = convert_function_name(functionname);
mode = convert_function_priv_string(priv_type_text);
- aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+ aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1745,16 +1635,16 @@ has_function_privilege_name(PG_FUNCTION_ARGS)
{
text *functionname = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
Oid functionoid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
functionoid = convert_function_name(functionname);
mode = convert_function_priv_string(priv_type_text);
- aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+ aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1770,14 +1660,15 @@ has_function_privilege_name_id(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
Oid functionoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
mode = convert_function_priv_string(priv_type_text);
- aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+ aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1793,14 +1684,14 @@ has_function_privilege_id(PG_FUNCTION_ARGS)
{
Oid functionoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
mode = convert_function_priv_string(priv_type_text);
- aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+ aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1808,12 +1699,12 @@ has_function_privilege_id(PG_FUNCTION_ARGS)
/*
* has_function_privilege_id_name
* Check user privileges on a function given
- * usesysid, text functionname, and text priv name.
+ * roleid, text functionname, and text priv name.
*/
Datum
has_function_privilege_id_name(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
text *functionname = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid functionoid;
@@ -1823,7 +1714,7 @@ has_function_privilege_id_name(PG_FUNCTION_ARGS)
functionoid = convert_function_name(functionname);
mode = convert_function_priv_string(priv_type_text);
- aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+ aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1831,12 +1722,12 @@ has_function_privilege_id_name(PG_FUNCTION_ARGS)
/*
* has_function_privilege_id_id
* Check user privileges on a function given
- * usesysid, function oid, and text priv name.
+ * roleid, function oid, and text priv name.
*/
Datum
has_function_privilege_id_id(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Oid functionoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
@@ -1844,7 +1735,7 @@ has_function_privilege_id_id(PG_FUNCTION_ARGS)
mode = convert_function_priv_string(priv_type_text);
- aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
+ aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1907,7 +1798,7 @@ convert_function_priv_string(text *priv_type_text)
* has_language_privilege variants
* These are all named "has_language_privilege" at the SQL level.
* They take various combinations of language name, language OID,
- * user name, user sysid, or implicit user = current_user.
+ * user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
@@ -1924,16 +1815,17 @@ has_language_privilege_name_name(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
text *languagename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
Oid languageoid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
languageoid = convert_language_name(languagename);
mode = convert_language_priv_string(priv_type_text);
- aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+ aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1949,16 +1841,16 @@ has_language_privilege_name(PG_FUNCTION_ARGS)
{
text *languagename = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
Oid languageoid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
languageoid = convert_language_name(languagename);
mode = convert_language_priv_string(priv_type_text);
- aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+ aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1974,14 +1866,15 @@ has_language_privilege_name_id(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
Oid languageoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
mode = convert_language_priv_string(priv_type_text);
- aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+ aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -1997,14 +1890,14 @@ has_language_privilege_id(PG_FUNCTION_ARGS)
{
Oid languageoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
mode = convert_language_priv_string(priv_type_text);
- aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+ aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2012,12 +1905,12 @@ has_language_privilege_id(PG_FUNCTION_ARGS)
/*
* has_language_privilege_id_name
* Check user privileges on a language given
- * usesysid, text languagename, and text priv name.
+ * roleid, text languagename, and text priv name.
*/
Datum
has_language_privilege_id_name(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
text *languagename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid languageoid;
@@ -2027,7 +1920,7 @@ has_language_privilege_id_name(PG_FUNCTION_ARGS)
languageoid = convert_language_name(languagename);
mode = convert_language_priv_string(priv_type_text);
- aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+ aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2035,12 +1928,12 @@ has_language_privilege_id_name(PG_FUNCTION_ARGS)
/*
* has_language_privilege_id_id
* Check user privileges on a language given
- * usesysid, language oid, and text priv name.
+ * roleid, language oid, and text priv name.
*/
Datum
has_language_privilege_id_id(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Oid languageoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
@@ -2048,7 +1941,7 @@ has_language_privilege_id_id(PG_FUNCTION_ARGS)
mode = convert_language_priv_string(priv_type_text);
- aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
+ aclresult = pg_language_aclcheck(languageoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2111,7 +2004,7 @@ convert_language_priv_string(text *priv_type_text)
* has_schema_privilege variants
* These are all named "has_schema_privilege" at the SQL level.
* They take various combinations of schema name, schema OID,
- * user name, user sysid, or implicit user = current_user.
+ * user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
@@ -2128,16 +2021,17 @@ has_schema_privilege_name_name(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
text *schemaname = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
Oid schemaoid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
schemaoid = convert_schema_name(schemaname);
mode = convert_schema_priv_string(priv_type_text);
- aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+ aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2153,16 +2047,16 @@ has_schema_privilege_name(PG_FUNCTION_ARGS)
{
text *schemaname = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
Oid schemaoid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
schemaoid = convert_schema_name(schemaname);
mode = convert_schema_priv_string(priv_type_text);
- aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+ aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2178,14 +2072,15 @@ has_schema_privilege_name_id(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
Oid schemaoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
mode = convert_schema_priv_string(priv_type_text);
- aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+ aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2201,14 +2096,14 @@ has_schema_privilege_id(PG_FUNCTION_ARGS)
{
Oid schemaoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
mode = convert_schema_priv_string(priv_type_text);
- aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+ aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2216,12 +2111,12 @@ has_schema_privilege_id(PG_FUNCTION_ARGS)
/*
* has_schema_privilege_id_name
* Check user privileges on a schema given
- * usesysid, text schemaname, and text priv name.
+ * roleid, text schemaname, and text priv name.
*/
Datum
has_schema_privilege_id_name(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
text *schemaname = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid schemaoid;
@@ -2231,7 +2126,7 @@ has_schema_privilege_id_name(PG_FUNCTION_ARGS)
schemaoid = convert_schema_name(schemaname);
mode = convert_schema_priv_string(priv_type_text);
- aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+ aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2239,12 +2134,12 @@ has_schema_privilege_id_name(PG_FUNCTION_ARGS)
/*
* has_schema_privilege_id_id
* Check user privileges on a schema given
- * usesysid, schema oid, and text priv name.
+ * roleid, schema oid, and text priv name.
*/
Datum
has_schema_privilege_id_id(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Oid schemaoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
@@ -2252,7 +2147,7 @@ has_schema_privilege_id_id(PG_FUNCTION_ARGS)
mode = convert_schema_priv_string(priv_type_text);
- aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
+ aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2319,7 +2214,7 @@ convert_schema_priv_string(text *priv_type_text)
* has_tablespace_privilege variants
* These are all named "has_tablespace_privilege" at the SQL level.
* They take various combinations of tablespace name, tablespace OID,
- * user name, user sysid, or implicit user = current_user.
+ * user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
@@ -2336,16 +2231,17 @@ has_tablespace_privilege_name_name(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
text *tablespacename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
Oid tablespaceoid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
tablespaceoid = convert_tablespace_name(tablespacename);
mode = convert_tablespace_priv_string(priv_type_text);
- aclresult = pg_tablespace_aclcheck(tablespaceoid, usesysid, mode);
+ aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2361,16 +2257,16 @@ has_tablespace_privilege_name(PG_FUNCTION_ARGS)
{
text *tablespacename = PG_GETARG_TEXT_P(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
Oid tablespaceoid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
tablespaceoid = convert_tablespace_name(tablespacename);
mode = convert_tablespace_priv_string(priv_type_text);
- aclresult = pg_tablespace_aclcheck(tablespaceoid, usesysid, mode);
+ aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2386,14 +2282,15 @@ has_tablespace_privilege_name_id(PG_FUNCTION_ARGS)
Name username = PG_GETARG_NAME(0);
Oid tablespaceoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
- int32 usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = get_usesysid(NameStr(*username));
+ roleid = get_roleid_checked(NameStr(*username));
+
mode = convert_tablespace_priv_string(priv_type_text);
- aclresult = pg_tablespace_aclcheck(tablespaceoid, usesysid, mode);
+ aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2409,14 +2306,14 @@ has_tablespace_privilege_id(PG_FUNCTION_ARGS)
{
Oid tablespaceoid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
- AclId usesysid;
+ Oid roleid;
AclMode mode;
AclResult aclresult;
- usesysid = GetUserId();
+ roleid = GetUserId();
mode = convert_tablespace_priv_string(priv_type_text);
- aclresult = pg_tablespace_aclcheck(tablespaceoid, usesysid, mode);
+ aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2424,12 +2321,12 @@ has_tablespace_privilege_id(PG_FUNCTION_ARGS)
/*
* has_tablespace_privilege_id_name
* Check user privileges on a tablespace given
- * usesysid, text tablespacename, and text priv name.
+ * roleid, text tablespacename, and text priv name.
*/
Datum
has_tablespace_privilege_id_name(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
text *tablespacename = PG_GETARG_TEXT_P(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid tablespaceoid;
@@ -2439,7 +2336,7 @@ has_tablespace_privilege_id_name(PG_FUNCTION_ARGS)
tablespaceoid = convert_tablespace_name(tablespacename);
mode = convert_tablespace_priv_string(priv_type_text);
- aclresult = pg_tablespace_aclcheck(tablespaceoid, usesysid, mode);
+ aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2447,12 +2344,12 @@ has_tablespace_privilege_id_name(PG_FUNCTION_ARGS)
/*
* has_tablespace_privilege_id_id
* Check user privileges on a tablespace given
- * usesysid, tablespace oid, and text priv name.
+ * roleid, tablespace oid, and text priv name.
*/
Datum
has_tablespace_privilege_id_id(PG_FUNCTION_ARGS)
{
- int32 usesysid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Oid tablespaceoid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
@@ -2460,7 +2357,7 @@ has_tablespace_privilege_id_id(PG_FUNCTION_ARGS)
mode = convert_tablespace_priv_string(priv_type_text);
- aclresult = pg_tablespace_aclcheck(tablespaceoid, usesysid, mode);
+ aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
@@ -2515,3 +2412,110 @@ convert_tablespace_priv_string(text *priv_type_text)
errmsg("unrecognized privilege type: \"%s\"", priv_type)));
return ACL_NO_RIGHTS; /* keep compiler quiet */
}
+
+void
+InitializeAcl(void)
+{
+ if (!IsBootstrapProcessingMode())
+ {
+ /*
+ * In normal mode, set a callback on any syscache
+ * invalidation of pg_auth_members rows
+ */
+ CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
+ RolMemCacheCallback,
+ (Datum) 0);
+
+ /* Force role/member cache to be recomputed on next use */
+ rolmemcacheValid = false;
+ }
+}
+
+/*
+ * RolMemCacheCallback
+ * Syscache inval callback function
+ */
+static void
+RolMemCacheCallback(Datum arg, Oid relid)
+{
+ /* Force role/member cache to be recomputed on next use */
+ rolmemcacheValid = false;
+}
+
+
+/*
+ * recomputeRolMemCache - recompute the role/member cache if needed
+ */
+static void
+recomputeRolMemCache(Oid roleid)
+{
+ int i;
+ Oid memberOid;
+ List *roles_list_hunt = NIL;
+ List *roles_list = NIL;
+ List *newrolmemcache;
+ CatCList *memlist;
+ MemoryContext oldctx;
+
+ /* Do nothing if rolmemcache is already valid */
+ if (rolmemcacheValid && rolmemRole == roleid)
+ return;
+
+ if (rolmemRole != roleid)
+ rolmemcacheValid = false;
+
+ /*
+ * Find all the roles which this role is a member of,
+ * including multi-level recursion
+ */
+
+ /*
+ * Include the current role itself to simplify checks
+ * later on, also should be at the head so lookup should
+ * be fast.
+ */
+ roles_list = lappend_oid(roles_list, roleid);
+ roles_list_hunt = lappend_oid(roles_list_hunt, roleid);
+
+ while (roles_list_hunt)
+ {
+ memberOid = linitial_oid(roles_list_hunt);
+ memlist = SearchSysCacheList(AUTHMEMMEMROLE, 1,
+ ObjectIdGetDatum(memberOid),
+ 0, 0, 0);
+ for (i = 0; i < memlist->n_members; i++) {
+ HeapTuple roletup = &memlist->members[i]->tuple;
+ Form_pg_auth_members rolemem = (Form_pg_auth_members) GETSTRUCT(roletup);
+
+ if (!list_member_oid(roles_list,rolemem->roleid)) {
+ roles_list = lappend_oid(roles_list,rolemem->roleid);
+ roles_list_hunt = lappend_oid(roles_list_hunt,rolemem->roleid);
+ }
+ }
+ roles_list_hunt = list_delete_oid(roles_list_hunt, memberOid);
+ ReleaseSysCacheList(memlist);
+ }
+
+ /*
+ * Now that we've built the list of role Oids this
+ * role is a member of, save it in permanent storage
+ */
+ oldctx = MemoryContextSwitchTo(TopMemoryContext);
+ newrolmemcache = list_copy(roles_list);
+ MemoryContextSwitchTo(oldctx);
+
+ /*
+ * Now safe to assign to state variable
+ */
+ list_free(rolmemcache);
+ rolmemcache = newrolmemcache;
+
+ /*
+ * Mark as valid
+ */
+ rolmemRole = roleid;
+ rolmemcacheValid = true;
+
+ /* Clean up */
+ list_free(roles_list);
+}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 90c8ea695bb..870513fb9d5 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -8,14 +8,13 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.22 2005/05/11 01:41:41 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.23 2005/06/28 05:09:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/xact.h"
-#include "catalog/pg_shadow.h"
#include "fmgr.h"
#include "funcapi.h"
#include "miscadmin.h"
@@ -306,7 +305,7 @@ pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
if (!OidIsValid(beentry->userid))
PG_RETURN_NULL();
- PG_RETURN_INT32(beentry->userid);
+ PG_RETURN_OID(beentry->userid);
}
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index a0d561f1f0f..8de31643a68 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -17,7 +17,7 @@
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.79 2005/05/30 07:20:58 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.80 2005/06/28 05:09:00 tgl Exp $
*
* ----------
*/
@@ -3036,7 +3036,7 @@ ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes,
{
void *qplan;
Relation query_rel;
- AclId save_uid;
+ Oid save_uid;
/*
* The query is always run against the FK table except when this is an
@@ -3089,7 +3089,7 @@ ri_PerformCheck(RI_QueryKey *qkey, void *qplan,
Snapshot crosscheck_snapshot;
int limit;
int spi_result;
- AclId save_uid;
+ Oid save_uid;
Datum vals[RI_MAX_NUMKEYS * 2];
char nulls[RI_MAX_NUMKEYS * 2];
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 0bd1d73eae1..cbebd5495c0 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.201 2005/06/26 22:05:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.202 2005/06/28 05:09:01 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -46,13 +46,13 @@
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
+#include "catalog/pg_authid.h"
#include "catalog/pg_cast.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_index.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
-#include "catalog/pg_shadow.h"
#include "catalog/pg_trigger.h"
#include "executor/spi.h"
#include "funcapi.h"
@@ -1194,17 +1194,17 @@ pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
/* ----------
- * get_userbyid - Get a user name by usesysid and
- * fallback to 'unknown (UID=n)'
+ * get_userbyid - Get a user name by roleid and
+ * fallback to 'unknown (OID=n)'
* ----------
*/
Datum
pg_get_userbyid(PG_FUNCTION_ARGS)
{
- int32 uid = PG_GETARG_INT32(0);
+ Oid roleid = PG_GETARG_OID(0);
Name result;
- HeapTuple usertup;
- Form_pg_shadow user_rec;
+ HeapTuple roletup;
+ Form_pg_authid role_rec;
/*
* Allocate space for the result
@@ -1213,19 +1213,19 @@ pg_get_userbyid(PG_FUNCTION_ARGS)
memset(NameStr(*result), 0, NAMEDATALEN);
/*
- * Get the pg_shadow entry and print the result
+ * Get the pg_authid entry and print the result
*/
- usertup = SearchSysCache(SHADOWSYSID,
- ObjectIdGetDatum(uid),
+ roletup = SearchSysCache(AUTHOID,
+ ObjectIdGetDatum(roleid),
0, 0, 0);
- if (HeapTupleIsValid(usertup))
+ if (HeapTupleIsValid(roletup))
{
- user_rec = (Form_pg_shadow) GETSTRUCT(usertup);
- StrNCpy(NameStr(*result), NameStr(user_rec->usename), NAMEDATALEN);
- ReleaseSysCache(usertup);
+ role_rec = (Form_pg_authid) GETSTRUCT(roletup);
+ StrNCpy(NameStr(*result), NameStr(role_rec->rolname), NAMEDATALEN);
+ ReleaseSysCache(roletup);
}
else
- sprintf(NameStr(*result), "unknown (UID=%d)", uid);
+ sprintf(NameStr(*result), "unknown (OID=%u)", roleid);
PG_RETURN_NAME(result);
}
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 5390d94462a..ea10f8c8cd3 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.125 2005/05/01 18:56:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.126 2005/06/28 05:09:01 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -24,8 +24,6 @@
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
-#include "catalog/pg_shadow.h"
-#include "catalog/pg_group.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
@@ -2010,66 +2008,35 @@ get_namespace_name(Oid nspid)
return NULL;
}
-/* ---------- PG_SHADOW CACHE ---------- */
+/* ---------- PG_AUTHID CACHE ---------- */
/*
- * get_usesysid
- *
- * Given a user name, look up the user's sysid.
- * Raises an error if no such user (rather than returning zero,
- * which might possibly be a valid usesysid).
- *
- * Note: the type of usesysid is currently int4, but may change to Oid
- * someday. It'd be reasonable to return zero on failure if we were
- * using Oid ...
+ * get_roleid
+ * Given a role name, look up the role's OID.
+ * Returns InvalidOid if no such role.
*/
-AclId
-get_usesysid(const char *username)
+Oid
+get_roleid(const char *rolname)
{
- AclId userId;
- HeapTuple userTup;
-
- userTup = SearchSysCache(SHADOWNAME,
- PointerGetDatum(username),
- 0, 0, 0);
- if (!HeapTupleIsValid(userTup))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user \"%s\" does not exist", username)));
-
- userId = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
-
- ReleaseSysCache(userTup);
-
- return userId;
+ return GetSysCacheOid(AUTHNAME,
+ PointerGetDatum(rolname),
+ 0, 0, 0);
}
/*
- * get_grosysid
- *
- * Given a group name, look up the group's sysid.
- * Raises an error if no such group (rather than returning zero,
- * which might possibly be a valid grosysid).
- *
+ * get_roleid_checked
+ * Given a role name, look up the role's OID.
+ * ereports if no such role.
*/
-AclId
-get_grosysid(char *groname)
+Oid
+get_roleid_checked(const char *rolname)
{
- AclId groupId;
- HeapTuple groupTup;
+ Oid roleid;
- groupTup = SearchSysCache(GRONAME,
- PointerGetDatum(groname),
- 0, 0, 0);
- if (!HeapTupleIsValid(groupTup))
+ roleid = get_roleid(rolname);
+ if (!OidIsValid(roleid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("group \"%s\" does not exist", groname)));
-
- groupId = ((Form_pg_group) GETSTRUCT(groupTup))->grosysid;
-
- ReleaseSysCache(groupTup);
-
- return groupId;
+ errmsg("role \"%s\" does not exist", rolname)));
+ return roleid;
}
-
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index c6cfbc5be24..cd24460857f 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.99 2005/05/11 01:26:02 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.100 2005/06/28 05:09:01 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
@@ -27,9 +27,10 @@
#include "catalog/pg_aggregate.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h"
+#include "catalog/pg_authid.h"
+#include "catalog/pg_auth_members.h"
#include "catalog/pg_cast.h"
#include "catalog/pg_conversion.h"
-#include "catalog/pg_group.h"
#include "catalog/pg_index.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_language.h"
@@ -38,7 +39,6 @@
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_rewrite.h"
-#include "catalog/pg_shadow.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
#include "utils/catcache.h"
@@ -172,6 +172,46 @@ static const struct cachedesc cacheinfo[] = {
0,
0
}},
+ {AuthMemRelationId, /* AUTHMEMMEMROLE */
+ AuthMemMemRoleIndexId,
+ 0,
+ 2,
+ {
+ Anum_pg_auth_members_member,
+ Anum_pg_auth_members_roleid,
+ 0,
+ 0
+ }},
+ {AuthMemRelationId, /* AUTHMEMROLEMEM */
+ AuthMemRoleMemIndexId,
+ 0,
+ 2,
+ {
+ Anum_pg_auth_members_roleid,
+ Anum_pg_auth_members_member,
+ 0,
+ 0
+ }},
+ {AuthIdRelationId, /* AUTHNAME */
+ AuthIdRolnameIndexId,
+ 0,
+ 1,
+ {
+ Anum_pg_authid_rolname,
+ 0,
+ 0,
+ 0
+ }},
+ {AuthIdRelationId, /* AUTHOID */
+ AuthIdOidIndexId,
+ 0,
+ 1,
+ {
+ ObjectIdAttributeNumber,
+ 0,
+ 0,
+ 0
+ }},
{
CastRelationId, /* CASTSOURCETARGET */
CastSourceTargetIndexId,
@@ -233,26 +273,6 @@ static const struct cachedesc cacheinfo[] = {
0,
0
}},
- {GroupRelationId, /* GRONAME */
- GroupNameIndexId,
- 0,
- 1,
- {
- Anum_pg_group_groname,
- 0,
- 0,
- 0
- }},
- {GroupRelationId, /* GROSYSID */
- GroupSysidIndexId,
- 0,
- 1,
- {
- Anum_pg_group_grosysid,
- 0,
- 0,
- 0
- }},
{IndexRelationId, /* INDEXRELID */
IndexRelidIndexId,
Anum_pg_index_indrelid,
@@ -383,26 +403,6 @@ static const struct cachedesc cacheinfo[] = {
0,
0
}},
- {ShadowRelationId, /* SHADOWNAME */
- ShadowNameIndexId,
- 0,
- 1,
- {
- Anum_pg_shadow_usename,
- 0,
- 0,
- 0
- }},
- {ShadowRelationId, /* SHADOWSYSID */
- ShadowSysidIndexId,
- 0,
- 1,
- {
- Anum_pg_shadow_usesysid,
- 0,
- 0,
- 0
- }},
{StatisticRelationId, /* STATRELATT */
StatisticRelidAttnumIndexId,
Anum_pg_statistic_starelid,
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 0733f190c2b..dd6134ccfd0 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.95 2005/05/29 04:23:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.96 2005/06/28 05:09:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -769,7 +769,7 @@ fmgr_oldstyle(PG_FUNCTION_ARGS)
struct fmgr_security_definer_cache
{
FmgrInfo flinfo;
- AclId userid;
+ Oid userid;
};
/*
@@ -786,7 +786,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
Datum result;
FmgrInfo *save_flinfo;
struct fmgr_security_definer_cache * volatile fcache;
- AclId save_userid;
+ Oid save_userid;
HeapTuple tuple;
if (!fcinfo->flinfo->fn_extra)
diff --git a/src/backend/utils/init/flatfiles.c b/src/backend/utils/init/flatfiles.c
index fcbc99189ff..8b129692f45 100644
--- a/src/backend/utils/init/flatfiles.c
+++ b/src/backend/utils/init/flatfiles.c
@@ -4,9 +4,10 @@
* Routines for maintaining "flat file" images of the shared catalogs.
*
* We use flat files so that the postmaster and not-yet-fully-started
- * backends can look at the contents of pg_database, pg_shadow, and pg_group
- * for authentication purposes. This module is responsible for keeping the
- * flat-file images as nearly in sync with database reality as possible.
+ * backends can look at the contents of pg_database, pg_authid, and
+ * pg_auth_members for authentication purposes. This module is
+ * responsible for keeping the flat-file images as nearly in sync with
+ * database reality as possible.
*
* The tricky part of the write_xxx_file() routines in this module is that
* they need to be able to operate in the context of the database startup
@@ -22,7 +23,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.8 2005/06/17 22:32:47 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.9 2005/06/28 05:09:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -31,12 +32,14 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "access/genam.h"
#include "access/heapam.h"
#include "access/twophase_rmgr.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_namespace.h"
-#include "catalog/pg_shadow.h"
#include "catalog/pg_tablespace.h"
#include "commands/trigger.h"
#include "miscadmin.h"
@@ -45,19 +48,18 @@
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/flatfiles.h"
+#include "utils/fmgroids.h"
#include "utils/resowner.h"
#include "utils/syscache.h"
/* Actual names of the flat files (within $PGDATA/global/) */
#define DATABASE_FLAT_FILE "pg_database"
-#define GROUP_FLAT_FILE "pg_group"
-#define USER_FLAT_FILE "pg_pwd"
+#define AUTH_FLAT_FILE "pg_auth"
/* Info bits in a flatfiles 2PC record */
#define FF_BIT_DATABASE 1
-#define FF_BIT_GROUP 2
-#define FF_BIT_USER 4
+#define FF_BIT_AUTH 2
/*
@@ -73,8 +75,7 @@
* SubTransactionId is seen at top-level commit.
*/
static SubTransactionId database_file_update_subid = InvalidSubTransactionId;
-static SubTransactionId group_file_update_subid = InvalidSubTransactionId;
-static SubTransactionId user_file_update_subid = InvalidSubTransactionId;
+static SubTransactionId auth_file_update_subid = InvalidSubTransactionId;
/*
@@ -88,23 +89,13 @@ database_file_update_needed(void)
}
/*
- * Mark flat group file as needing an update (because pg_group changed)
+ * Mark flat auth file as needing an update (because pg_auth changed)
*/
void
-group_file_update_needed(void)
+auth_file_update_needed(void)
{
- if (group_file_update_subid == InvalidSubTransactionId)
- group_file_update_subid = GetCurrentSubTransactionId();
-}
-
-/*
- * Mark flat user file as needing an update (because pg_shadow changed)
- */
-void
-user_file_update_needed(void)
-{
- if (user_file_update_subid == InvalidSubTransactionId)
- user_file_update_subid = GetCurrentSubTransactionId();
+ if (auth_file_update_subid == InvalidSubTransactionId)
+ auth_file_update_subid = GetCurrentSubTransactionId();
}
@@ -128,39 +119,20 @@ database_getflatfilename(void)
}
/*
- * group_getflatfilename --- get full pathname of group file
- *
- * Note that result string is palloc'd, and should be freed by the caller.
- */
-char *
-group_getflatfilename(void)
-{
- int bufsize;
- char *pfnam;
-
- bufsize = strlen(DataDir) + strlen("/global/") +
- strlen(GROUP_FLAT_FILE) + 1;
- pfnam = (char *) palloc(bufsize);
- snprintf(pfnam, bufsize, "%s/global/%s", DataDir, GROUP_FLAT_FILE);
-
- return pfnam;
-}
-
-/*
- * Get full pathname of password file.
+ * Get full pathname of auth file.
*
* Note that result string is palloc'd, and should be freed by the caller.
*/
char *
-user_getflatfilename(void)
+auth_getflatfilename(void)
{
int bufsize;
char *pfnam;
bufsize = strlen(DataDir) + strlen("/global/") +
- strlen(USER_FLAT_FILE) + 1;
+ strlen(AUTH_FLAT_FILE) + 1;
pfnam = (char *) palloc(bufsize);
- snprintf(pfnam, bufsize, "%s/global/%s", DataDir, USER_FLAT_FILE);
+ snprintf(pfnam, bufsize, "%s/global/%s", DataDir, AUTH_FLAT_FILE);
return pfnam;
}
@@ -189,7 +161,7 @@ fputs_quote(const char *str, FILE *fp)
/*
* name_okay
*
- * We must disallow newlines in user and group names because
+ * We must disallow newlines in role names because
* hba.c's parser won't handle fields split across lines, even if quoted.
*/
static bool
@@ -322,165 +294,81 @@ write_database_file(Relation drel)
/*
- * write_group_file: update the flat group file
+ * Support for write_auth_file
*/
-static void
-write_group_file(Relation grel)
-{
- char *filename,
- *tempname;
- int bufsize;
- FILE *fp;
- mode_t oumask;
- HeapScanDesc scan;
- HeapTuple tuple;
-
- /*
- * Create a temporary filename to be renamed later. This prevents the
- * backend from clobbering the flat file while the postmaster
- * might be reading from it.
- */
- filename = group_getflatfilename();
- bufsize = strlen(filename) + 12;
- tempname = (char *) palloc(bufsize);
- snprintf(tempname, bufsize, "%s.%d", filename, MyProcPid);
-
- oumask = umask((mode_t) 077);
- fp = AllocateFile(tempname, "w");
- umask(oumask);
- if (fp == NULL)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not write to temporary file \"%s\": %m",
- tempname)));
-
- /*
- * Read pg_group and write the file.
- */
- scan = heap_beginscan(grel, SnapshotNow, 0, NULL);
- while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
- {
- Form_pg_group grpform = (Form_pg_group) GETSTRUCT(tuple);
- HeapTupleHeader tup = tuple->t_data;
- char *tp; /* ptr to tuple data */
- long off; /* offset in tuple data */
- bits8 *bp = tup->t_bits; /* ptr to null bitmask in tuple */
- Datum datum;
- char *groname;
- IdList *grolist_p;
- AclId *aidp;
- int i,
- num;
-
- groname = NameStr(grpform->groname);
-
- /*
- * Check for illegal characters in the group name.
- */
- if (!name_okay(groname))
- {
- ereport(LOG,
- (errmsg("invalid group name \"%s\"", groname)));
- continue;
- }
-
- /*
- * We can't use heap_getattr() here because during startup we will
- * not have any tupdesc for pg_group. Fortunately it's not too
- * hard to work around this. grolist is the first possibly-null
- * field so we can compute its offset directly.
- */
- tp = (char *) tup + tup->t_hoff;
- off = offsetof(FormData_pg_group, grolist);
-
- if (HeapTupleHasNulls(tuple) &&
- att_isnull(Anum_pg_group_grolist - 1, bp))
- {
- /* grolist is null, so we can ignore this group */
- continue;
- }
-
- /* assume grolist is pass-by-ref */
- datum = PointerGetDatum(tp + off);
-
- /*
- * We can't currently support out-of-line toasted group lists in
- * startup mode (the tuptoaster won't work). This sucks, but it
- * should be something of a corner case. Live with it until we
- * can redesign pg_group.
- *
- * Detect startup mode by noting whether we got a tupdesc.
- */
- if (VARATT_IS_EXTERNAL(DatumGetPointer(datum)) &&
- RelationGetDescr(grel) == NULL)
- continue;
- /* be sure the IdList is not toasted */
- grolist_p = DatumGetIdListP(datum);
+typedef struct {
+ Oid roleid;
+ char* rolname;
+ char* rolpassword;
+ char* rolvaliduntil;
+ List* roles_names;
+} auth_entry;
+
+typedef struct {
+ Oid roleid;
+ Oid memberid;
+} authmem_entry;
+
+static int
+oid_compar(const void *a, const void *b)
+{
+ const auth_entry *a_auth = (const auth_entry*) a;
+ const auth_entry *b_auth = (const auth_entry*) b;
- /*
- * The file format is: "groupname" usesysid1 usesysid2 ...
- *
- * We ignore groups that have no members.
- */
- aidp = IDLIST_DAT(grolist_p);
- num = IDLIST_NUM(grolist_p);
- if (num > 0)
- {
- fputs_quote(groname, fp);
- fprintf(fp, "\t%u", aidp[0]);
- for (i = 1; i < num; ++i)
- fprintf(fp, " %u", aidp[i]);
- fputs("\n", fp);
- }
+ if (a_auth->roleid < b_auth->roleid) return -1;
+ if (a_auth->roleid > b_auth->roleid) return 1;
+ return 0;
+}
- /* if IdList was toasted, free detoasted copy */
- if ((Pointer) grolist_p != DatumGetPointer(datum))
- pfree(grolist_p);
- }
- heap_endscan(scan);
+static int
+name_compar(const void *a, const void *b)
+{
+ const auth_entry *a_auth = (const auth_entry*) a;
+ const auth_entry *b_auth = (const auth_entry*) b;
- if (FreeFile(fp))
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not write to temporary file \"%s\": %m",
- tempname)));
+ return strcmp(a_auth->rolname,b_auth->rolname);
+}
- /*
- * Rename the temp file to its final name, deleting the old flat file.
- * We expect that rename(2) is an atomic action.
- */
- if (rename(tempname, filename))
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not rename file \"%s\" to \"%s\": %m",
- tempname, filename)));
+static int
+mem_compar(const void *a, const void *b)
+{
+ const authmem_entry *a_auth = (const authmem_entry*) a;
+ const authmem_entry *b_auth = (const authmem_entry*) b;
- pfree(tempname);
- pfree(filename);
+ if (a_auth->memberid < b_auth->memberid) return -1;
+ if (a_auth->memberid > b_auth->memberid) return 1;
+ return 0;
}
-
/*
- * write_user_file: update the flat password file
+ * write_auth_file: update the flat auth file
*/
static void
-write_user_file(Relation urel)
+write_auth_file(Relation rel_auth, Relation rel_authmem, bool startup)
{
char *filename,
*tempname;
int bufsize;
+ BlockNumber totalblocks;
FILE *fp;
mode_t oumask;
HeapScanDesc scan;
HeapTuple tuple;
+ int curr_role = 0;
+ int total_roles = 0;
+ int curr_mem = 0;
+ int total_mem = 0;
+ int est_rows;
+ auth_entry *auth_info;
+ authmem_entry *authmem_info = NULL;
/*
* Create a temporary filename to be renamed later. This prevents the
- * backend from clobbering the flat file while the postmaster might
+ * backend from clobbering the pg_auth file while the postmaster might
* be reading from it.
*/
- filename = user_getflatfilename();
+ filename = auth_getflatfilename();
bufsize = strlen(filename) + 12;
tempname = (char *) palloc(bufsize);
snprintf(tempname, bufsize, "%s.%d", filename, MyProcPid);
@@ -495,39 +383,41 @@ write_user_file(Relation urel)
tempname)));
/*
- * Read pg_shadow and write the file.
+ * Read pg_authid and fill temporary data structures.
*/
- scan = heap_beginscan(urel, SnapshotNow, 0, NULL);
+ totalblocks = RelationGetNumberOfBlocks(rel_auth);
+ totalblocks = totalblocks ? totalblocks : 1;
+ est_rows = totalblocks * (BLCKSZ / (sizeof(HeapTupleHeaderData)+sizeof(FormData_pg_authid)));
+ auth_info = (auth_entry*) palloc(est_rows*sizeof(auth_entry));
+
+ scan = heap_beginscan(rel_auth, SnapshotNow, 0, NULL);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
- Form_pg_shadow pwform = (Form_pg_shadow) GETSTRUCT(tuple);
+ Form_pg_authid pwform = (Form_pg_authid) GETSTRUCT(tuple);
HeapTupleHeader tup = tuple->t_data;
char *tp; /* ptr to tuple data */
long off; /* offset in tuple data */
bits8 *bp = tup->t_bits; /* ptr to null bitmask in tuple */
Datum datum;
- char *usename,
- *passwd,
- *valuntil;
- AclId usesysid;
- usename = NameStr(pwform->usename);
- usesysid = pwform->usesysid;
+ auth_info[curr_role].roleid = HeapTupleGetOid(tuple);
+ auth_info[curr_role].rolname = pstrdup(NameStr(pwform->rolname));
+ auth_info[curr_role].roles_names = NIL;
/*
* We can't use heap_getattr() here because during startup we will
- * not have any tupdesc for pg_shadow. Fortunately it's not too
- * hard to work around this. passwd is the first possibly-null
+ * not have any tupdesc for pg_authid. Fortunately it's not too
+ * hard to work around this. rolpassword is the first possibly-null
* field so we can compute its offset directly.
*/
tp = (char *) tup + tup->t_hoff;
- off = offsetof(FormData_pg_shadow, passwd);
+ off = offsetof(FormData_pg_authid, rolpassword);
if (HeapTupleHasNulls(tuple) &&
- att_isnull(Anum_pg_shadow_passwd - 1, bp))
+ att_isnull(Anum_pg_authid_rolpassword - 1, bp))
{
/* passwd is null, emit as an empty string */
- passwd = pstrdup("");
+ auth_info[curr_role].rolpassword = pstrdup("");
}
else
{
@@ -539,59 +429,175 @@ write_user_file(Relation urel)
* if it is, ignore it, since we can't handle that in startup mode.
*/
if (VARATT_IS_EXTERNAL(DatumGetPointer(datum)))
- passwd = pstrdup("");
+ auth_info[curr_role].rolpassword = pstrdup("");
else
- passwd = DatumGetCString(DirectFunctionCall1(textout, datum));
+ auth_info[curr_role].rolpassword = DatumGetCString(DirectFunctionCall1(textout, datum));
/* assume passwd has attlen -1 */
off = att_addlength(off, -1, tp + off);
}
if (HeapTupleHasNulls(tuple) &&
- att_isnull(Anum_pg_shadow_valuntil - 1, bp))
+ att_isnull(Anum_pg_authid_rolvaliduntil - 1, bp))
{
- /* valuntil is null, emit as an empty string */
- valuntil = pstrdup("");
+ /* rolvaliduntil is null, emit as an empty string */
+ auth_info[curr_role].rolvaliduntil = pstrdup("");
}
else
{
- /* assume valuntil has attalign 'i' */
- off = att_align(off, 'i');
- /* assume valuntil is pass-by-value, integer size */
- datum = Int32GetDatum(*((int32 *) (tp + off)));
- valuntil = DatumGetCString(DirectFunctionCall1(abstimeout, datum));
+ /*
+ * rolvaliduntil is timestamptz, which we assume is double
+ * alignment and pass-by-reference.
+ */
+ off = att_align(off, 'd');
+ datum = PointerGetDatum(tp + off);
+ auth_info[curr_role].rolvaliduntil = DatumGetCString(DirectFunctionCall1(timestamptz_out, datum));
}
/*
* Check for illegal characters in the user name and password.
*/
- if (!name_okay(usename))
+ if (!name_okay(auth_info[curr_role].rolname))
{
ereport(LOG,
- (errmsg("invalid user name \"%s\"", usename)));
+ (errmsg("invalid role name \"%s\"",
+ auth_info[curr_role].rolname)));
+ pfree(auth_info[curr_role].rolname);
+ pfree(auth_info[curr_role].rolpassword);
+ pfree(auth_info[curr_role].rolvaliduntil);
continue;
}
- if (!name_okay(passwd))
+ if (!name_okay(auth_info[curr_role].rolpassword))
{
ereport(LOG,
- (errmsg("invalid user password \"%s\"", passwd)));
+ (errmsg("invalid role password \"%s\"",
+ auth_info[curr_role].rolpassword)));
+ pfree(auth_info[curr_role].rolname);
+ pfree(auth_info[curr_role].rolpassword);
+ pfree(auth_info[curr_role].rolvaliduntil);
continue;
}
- /*
- * The file format is: "usename" usesysid "passwd" "valuntil"
+ curr_role++;
+ total_roles++;
+ }
+ heap_endscan(scan);
+
+ Assert(total_roles <= est_rows);
+
+ qsort(auth_info, total_roles, sizeof(auth_entry), oid_compar);
+
+ /*
+ * Read pg_auth_members into temporary data structure, too
+ */
+ totalblocks = RelationGetNumberOfBlocks(rel_authmem);
+ totalblocks = totalblocks ? totalblocks : 1;
+ est_rows = totalblocks * (BLCKSZ / (sizeof(HeapTupleHeaderData)+sizeof(FormData_pg_auth_members)));
+ authmem_info = (authmem_entry*) palloc(est_rows*sizeof(authmem_entry));
+
+ scan = heap_beginscan(rel_authmem, SnapshotNow, 0, NULL);
+ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ Form_pg_auth_members memform = (Form_pg_auth_members) GETSTRUCT(tuple);
+
+ authmem_info[curr_mem].roleid = memform->roleid;
+ authmem_info[curr_mem].memberid = memform->member;
+ curr_mem++;
+ total_mem++;
+ }
+ heap_endscan(scan);
+
+ Assert(total_mem <= est_rows);
+
+ qsort(authmem_info, total_mem, sizeof(authmem_entry), mem_compar);
+
+ for (curr_role = 0; curr_role < total_roles; curr_role++)
+ {
+ int first_found, last_found, curr_mem;
+ List *roles_list_hunt = NIL;
+ List *roles_list = NIL;
+ ListCell *mem = NULL;
+ auth_entry *found_role = NULL, key_auth;
+ authmem_entry key;
+ authmem_entry *found_mem = NULL;
+
+ roles_list_hunt = lappend_oid(roles_list_hunt,
+ auth_info[curr_role].roleid);
+
+ while (roles_list_hunt)
+ {
+ key.memberid = linitial_oid(roles_list_hunt);
+ roles_list_hunt = list_delete_first(roles_list_hunt);
+ if (total_mem)
+ found_mem = bsearch(&key, authmem_info, total_mem,
+ sizeof(authmem_entry), mem_compar);
+ if (found_mem)
+ {
+ /*
+ * bsearch found a match for us; but if there were multiple
+ * matches it could have found any one of them.
+ */
+ first_found = last_found = (found_mem - authmem_info);
+ while (first_found > 0 &&
+ mem_compar(&key, &authmem_info[first_found - 1]) == 0)
+ first_found--;
+ while (last_found + 1 < total_mem &&
+ mem_compar(&key, &authmem_info[last_found + 1]) == 0)
+ last_found++;
+
+ for (curr_mem = first_found; curr_mem <= last_found; curr_mem++)
+ {
+ Oid otherrole = authmem_info[curr_mem].roleid;
+
+ if (!list_member_oid(roles_list, otherrole))
+ {
+ roles_list = lappend_oid(roles_list,
+ otherrole);
+ roles_list_hunt = lappend_oid(roles_list_hunt,
+ otherrole);
+ }
+ }
+ }
+ }
+
+ foreach(mem, roles_list)
+ {
+ key_auth.roleid = lfirst_oid(mem);
+ found_role = bsearch(&key_auth, auth_info, total_roles, sizeof(auth_entry), oid_compar);
+ auth_info[curr_role].roles_names = lappend(auth_info[curr_role].roles_names,found_role->rolname);
+ }
+ }
+
+ qsort(auth_info, total_roles, sizeof(auth_entry), name_compar);
+
+ for (curr_role = 0; curr_role < total_roles; curr_role++)
+ {
+ ListCell *mem = NULL;
+
+ /*----------
+ * The file format is:
+ * "rolename" "password" "validuntil" "member" "member" ...
+ * where lines are expected to be in order by rolename
+ *----------
*/
- fputs_quote(usename, fp);
- fprintf(fp, " %u ", usesysid);
- fputs_quote(passwd, fp);
+ fputs_quote(auth_info[curr_role].rolname, fp);
+ fputs(" ", fp);
+ fputs_quote(auth_info[curr_role].rolpassword, fp);
fputs(" ", fp);
- fputs_quote(valuntil, fp);
+ fputs_quote(auth_info[curr_role].rolvaliduntil, fp);
+
+ foreach(mem, auth_info[curr_role].roles_names)
+ {
+ fputs(" ", fp);
+ fputs_quote(lfirst(mem), fp);
+ }
+
fputs("\n", fp);
- pfree(passwd);
- pfree(valuntil);
+ pfree(auth_info[curr_role].rolname);
+ pfree(auth_info[curr_role].rolpassword);
+ pfree(auth_info[curr_role].rolvaliduntil);
}
- heap_endscan(scan);
if (FreeFile(fp))
ereport(ERROR,
@@ -609,6 +615,8 @@ write_user_file(Relation urel)
errmsg("could not rename file \"%s\" to \"%s\": %m",
tempname, filename)));
+ pfree(auth_info);
+ pfree(authmem_info);
pfree(tempname);
pfree(filename);
}
@@ -634,7 +642,7 @@ BuildFlatFiles(bool database_only)
{
ResourceOwner owner;
RelFileNode rnode;
- Relation rel;
+ Relation rel, rel_auth, rel_authmem;
/*
* We don't have any hope of running a real relcache, but we can use
@@ -657,21 +665,16 @@ BuildFlatFiles(bool database_only)
if (!database_only)
{
- /* hard-wired path to pg_group */
+ /* hard-wired path to pg_auth */
rnode.spcNode = GLOBALTABLESPACE_OID;
rnode.dbNode = 0;
- rnode.relNode = GroupRelationId;
+ rnode.relNode = AuthIdRelationId;
+ rel_auth = XLogOpenRelation(rnode);
- rel = XLogOpenRelation(rnode);
- write_group_file(rel);
-
- /* hard-wired path to pg_shadow */
rnode.spcNode = GLOBALTABLESPACE_OID;
rnode.dbNode = 0;
- rnode.relNode = ShadowRelationId;
-
- rel = XLogOpenRelation(rnode);
- write_user_file(rel);
+ rnode.relNode = AuthMemRelationId;
+ rel_authmem = XLogOpenRelation(rnode);
}
CurrentResourceOwner = NULL;
@@ -699,19 +702,17 @@ void
AtEOXact_UpdateFlatFiles(bool isCommit)
{
Relation drel = NULL;
- Relation grel = NULL;
- Relation urel = NULL;
+ Relation arel = NULL;
+ Relation mrel = NULL;
if (database_file_update_subid == InvalidSubTransactionId &&
- group_file_update_subid == InvalidSubTransactionId &&
- user_file_update_subid == InvalidSubTransactionId)
+ auth_file_update_subid == InvalidSubTransactionId)
return; /* nothing to do */
if (!isCommit)
{
database_file_update_subid = InvalidSubTransactionId;
- group_file_update_subid = InvalidSubTransactionId;
- user_file_update_subid = InvalidSubTransactionId;
+ auth_file_update_subid = InvalidSubTransactionId;
return;
}
@@ -731,10 +732,10 @@ AtEOXact_UpdateFlatFiles(bool isCommit)
*/
if (database_file_update_subid != InvalidSubTransactionId)
drel = heap_open(DatabaseRelationId, ExclusiveLock);
- if (group_file_update_subid != InvalidSubTransactionId)
- grel = heap_open(GroupRelationId, ExclusiveLock);
- if (user_file_update_subid != InvalidSubTransactionId)
- urel = heap_open(ShadowRelationId, ExclusiveLock);
+ if (auth_file_update_subid != InvalidSubTransactionId) {
+ arel = heap_open(AuthIdRelationId, ExclusiveLock);
+ mrel = heap_open(AuthMemRelationId, ExclusiveLock);
+ }
/* Okay to write the files */
if (database_file_update_subid != InvalidSubTransactionId)
@@ -744,18 +745,12 @@ AtEOXact_UpdateFlatFiles(bool isCommit)
heap_close(drel, NoLock);
}
- if (group_file_update_subid != InvalidSubTransactionId)
- {
- group_file_update_subid = InvalidSubTransactionId;
- write_group_file(grel);
- heap_close(grel, NoLock);
- }
-
- if (user_file_update_subid != InvalidSubTransactionId)
+ if (auth_file_update_subid != InvalidSubTransactionId)
{
- user_file_update_subid = InvalidSubTransactionId;
- write_user_file(urel);
- heap_close(urel, NoLock);
+ auth_file_update_subid = InvalidSubTransactionId;
+ write_auth_file(arel, mrel, false);
+ heap_close(arel, NoLock);
+ heap_close(mrel, NoLock);
}
/*
@@ -785,15 +780,10 @@ AtPrepare_UpdateFlatFiles(void)
database_file_update_subid = InvalidSubTransactionId;
info |= FF_BIT_DATABASE;
}
- if (group_file_update_subid != InvalidSubTransactionId)
- {
- group_file_update_subid = InvalidSubTransactionId;
- info |= FF_BIT_GROUP;
- }
- if (user_file_update_subid != InvalidSubTransactionId)
+ if (auth_file_update_subid != InvalidSubTransactionId)
{
- user_file_update_subid = InvalidSubTransactionId;
- info |= FF_BIT_USER;
+ auth_file_update_subid = InvalidSubTransactionId;
+ info |= FF_BIT_AUTH;
}
if (info != 0)
RegisterTwoPhaseRecord(TWOPHASE_RM_FLATFILES_ID, info,
@@ -817,29 +807,23 @@ AtEOSubXact_UpdateFlatFiles(bool isCommit,
if (database_file_update_subid == mySubid)
database_file_update_subid = parentSubid;
- if (group_file_update_subid == mySubid)
- group_file_update_subid = parentSubid;
-
- if (user_file_update_subid == mySubid)
- user_file_update_subid = parentSubid;
+ if (auth_file_update_subid == mySubid)
+ auth_file_update_subid = parentSubid;
}
else
{
if (database_file_update_subid == mySubid)
database_file_update_subid = InvalidSubTransactionId;
- if (group_file_update_subid == mySubid)
- group_file_update_subid = InvalidSubTransactionId;
-
- if (user_file_update_subid == mySubid)
- user_file_update_subid = InvalidSubTransactionId;
+ if (auth_file_update_subid == mySubid)
+ auth_file_update_subid = InvalidSubTransactionId;
}
}
/*
- * This trigger is fired whenever someone modifies pg_database, pg_shadow
- * or pg_group via general-purpose INSERT/UPDATE/DELETE commands.
+ * This trigger is fired whenever someone modifies pg_database, pg_authid
+ * or pg_auth_members via general-purpose INSERT/UPDATE/DELETE commands.
*
* It is sufficient for this to be a STATEMENT trigger since we don't
* care which individual rows changed. It doesn't much matter whether
@@ -862,11 +846,11 @@ flatfile_update_trigger(PG_FUNCTION_ARGS)
case DatabaseRelationId:
database_file_update_needed();
break;
- case GroupRelationId:
- group_file_update_needed();
+ case AuthIdRelationId:
+ auth_file_update_needed();
break;
- case ShadowRelationId:
- user_file_update_needed();
+ case AuthMemRelationId:
+ auth_file_update_needed();
break;
default:
elog(ERROR, "flatfile_update_trigger was called for wrong table");
@@ -895,8 +879,6 @@ flatfile_twophase_postcommit(TransactionId xid, uint16 info,
*/
if (info & FF_BIT_DATABASE)
database_file_update_needed();
- if (info & FF_BIT_GROUP)
- group_file_update_needed();
- if (info & FF_BIT_USER)
- user_file_update_needed();
+ if (info & FF_BIT_AUTH)
+ auth_file_update_needed();
}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 508c56e1e03..1db29928996 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.142 2005/06/20 02:17:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.143 2005/06/28 05:09:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -29,7 +29,7 @@
#include <utime.h>
#endif
-#include "catalog/pg_shadow.h"
+#include "catalog/pg_authid.h"
#include "libpq/libpq-be.h"
#include "miscadmin.h"
#include "storage/fd.h"
@@ -251,7 +251,7 @@ make_absolute_path(const char *path)
/* ----------------------------------------------------------------
- * User ID things
+ * Role ID things
*
* The authenticated user is determined at connection start and never
* changes. The session user can be changed only by SET SESSION
@@ -261,60 +261,60 @@ make_absolute_path(const char *path)
* restore the current user id if you need to change it.
* ----------------------------------------------------------------
*/
-static AclId AuthenticatedUserId = 0;
-static AclId SessionUserId = 0;
-static AclId CurrentUserId = 0;
+static Oid AuthenticatedUserId = InvalidOid;
+static Oid SessionUserId = InvalidOid;
+static Oid CurrentUserId = InvalidOid;
static bool AuthenticatedUserIsSuperuser = false;
/*
* This function is relevant for all privilege checks.
*/
-AclId
+Oid
GetUserId(void)
{
- AssertState(AclIdIsValid(CurrentUserId));
+ AssertState(OidIsValid(CurrentUserId));
return CurrentUserId;
}
void
-SetUserId(AclId newid)
+SetUserId(Oid roleid)
{
- AssertArg(AclIdIsValid(newid));
- CurrentUserId = newid;
+ AssertArg(OidIsValid(roleid));
+ CurrentUserId = roleid;
}
/*
* This value is only relevant for informational purposes.
*/
-AclId
+Oid
GetSessionUserId(void)
{
- AssertState(AclIdIsValid(SessionUserId));
+ AssertState(OidIsValid(SessionUserId));
return SessionUserId;
}
void
-SetSessionUserId(AclId newid)
+SetSessionUserId(Oid roleid)
{
- AssertArg(AclIdIsValid(newid));
- SessionUserId = newid;
+ AssertArg(OidIsValid(roleid));
+ SessionUserId = roleid;
/* Current user defaults to session user. */
- if (!AclIdIsValid(CurrentUserId))
- CurrentUserId = newid;
+ if (!OidIsValid(CurrentUserId))
+ CurrentUserId = roleid;
}
void
-InitializeSessionUserId(const char *username)
+InitializeSessionUserId(const char *rolename)
{
- HeapTuple userTup;
+ HeapTuple roleTup;
Datum datum;
bool isnull;
- AclId usesysid;
+ Oid roleid;
/*
* Don't do scans if we're bootstrapping, none of the system catalogs
@@ -325,23 +325,23 @@ InitializeSessionUserId(const char *username)
/* call only once */
AssertState(!OidIsValid(AuthenticatedUserId));
- userTup = SearchSysCache(SHADOWNAME,
- PointerGetDatum(username),
+ roleTup = SearchSysCache(AUTHNAME,
+ PointerGetDatum(rolename),
0, 0, 0);
- if (!HeapTupleIsValid(userTup))
+ if (!HeapTupleIsValid(roleTup))
ereport(FATAL,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user \"%s\" does not exist", username)));
+ errmsg("role \"%s\" does not exist", rolename)));
- usesysid = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
+ roleid = HeapTupleGetOid(roleTup);
- AuthenticatedUserId = usesysid;
- AuthenticatedUserIsSuperuser = ((Form_pg_shadow) GETSTRUCT(userTup))->usesuper;
+ AuthenticatedUserId = roleid;
+ AuthenticatedUserIsSuperuser = ((Form_pg_authid) GETSTRUCT(roleTup))->rolsuper;
- SetSessionUserId(usesysid); /* sets CurrentUserId too */
+ SetSessionUserId(roleid); /* sets CurrentUserId too */
/* Record username and superuser status as GUC settings too */
- SetConfigOption("session_authorization", username,
+ SetConfigOption("session_authorization", rolename,
PGC_BACKEND, PGC_S_OVERRIDE);
SetConfigOption("is_superuser",
AuthenticatedUserIsSuperuser ? "on" : "off",
@@ -349,11 +349,11 @@ InitializeSessionUserId(const char *username)
/*
* Set up user-specific configuration variables. This is a good place
- * to do it so we don't have to read pg_shadow twice during session
+ * to do it so we don't have to read pg_authid twice during session
* startup.
*/
- datum = SysCacheGetAttr(SHADOWNAME, userTup,
- Anum_pg_shadow_useconfig, &isnull);
+ datum = SysCacheGetAttr(AUTHNAME, roleTup,
+ Anum_pg_authid_rolconfig, &isnull);
if (!isnull)
{
ArrayType *a = DatumGetArrayTypeP(datum);
@@ -361,7 +361,7 @@ InitializeSessionUserId(const char *username)
ProcessGUCArray(a, PGC_S_USER);
}
- ReleaseSysCache(userTup);
+ ReleaseSysCache(roleTup);
}
@@ -374,10 +374,10 @@ InitializeSessionUserIdStandalone(void)
/* call only once */
AssertState(!OidIsValid(AuthenticatedUserId));
- AuthenticatedUserId = BOOTSTRAP_USESYSID;
+ AuthenticatedUserId = BOOTSTRAP_SUPERUSERID;
AuthenticatedUserIsSuperuser = true;
- SetSessionUserId(BOOTSTRAP_USESYSID);
+ SetSessionUserId(BOOTSTRAP_SUPERUSERID);
}
@@ -390,19 +390,19 @@ InitializeSessionUserIdStandalone(void)
* to indicate whether the *current* session userid is a superuser.
*/
void
-SetSessionAuthorization(AclId userid, bool is_superuser)
+SetSessionAuthorization(Oid roleid, bool is_superuser)
{
/* Must have authenticated already, else can't make permission check */
- AssertState(AclIdIsValid(AuthenticatedUserId));
+ AssertState(OidIsValid(AuthenticatedUserId));
- if (userid != AuthenticatedUserId &&
+ if (roleid != AuthenticatedUserId &&
!AuthenticatedUserIsSuperuser)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to set session authorization")));
- SetSessionUserId(userid);
- SetUserId(userid);
+ SetSessionUserId(roleid);
+ SetUserId(roleid);
SetConfigOption("is_superuser",
is_superuser ? "on" : "off",
@@ -411,30 +411,29 @@ SetSessionAuthorization(AclId userid, bool is_superuser)
/*
- * Get user name from user id
+ * Get user name from user oid
*/
char *
-GetUserNameFromId(AclId userid)
+GetUserNameFromId(Oid roleid)
{
HeapTuple tuple;
char *result;
- tuple = SearchSysCache(SHADOWSYSID,
- ObjectIdGetDatum(userid),
+ tuple = SearchSysCache(AUTHOID,
+ ObjectIdGetDatum(roleid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("invalid user ID: %d", userid)));
+ errmsg("invalid role OID: %u", roleid)));
- result = pstrdup(NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename));
+ result = pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname));
ReleaseSysCache(tuple);
return result;
}
-
/*-------------------------------------------------------------------------
* Interlock-file support
*
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 1836aee81d7..9baacacfffd 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.149 2005/06/24 01:06:26 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.150 2005/06/28 05:09:02 tgl Exp $
*
*
*-------------------------------------------------------------------------
@@ -20,11 +20,11 @@
#include <math.h>
#include <unistd.h>
-#include "catalog/catalog.h"
#include "access/heapam.h"
+#include "catalog/catalog.h"
#include "catalog/namespace.h"
+#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
-#include "catalog/pg_shadow.h"
#include "catalog/pg_tablespace.h"
#include "libpq/hba.h"
#include "mb/pg_wchar.h"
@@ -37,6 +37,7 @@
#include "storage/procarray.h"
#include "storage/sinval.h"
#include "storage/smgr.h"
+#include "utils/acl.h"
#include "utils/flatfiles.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
@@ -49,7 +50,7 @@ static bool FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace);
static void ReverifyMyDatabase(const char *name);
static void InitCommunication(void);
static void ShutdownPostgres(int code, Datum arg);
-static bool ThereIsAtLeastOneUser(void);
+static bool ThereIsAtLeastOneRole(void);
/*** InitPostgres support ***/
@@ -415,12 +416,12 @@ InitPostgres(const char *dbname, const char *username)
else if (!IsUnderPostmaster)
{
InitializeSessionUserIdStandalone();
- if (!ThereIsAtLeastOneUser())
+ if (!ThereIsAtLeastOneRole())
ereport(WARNING,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("no users are defined in this database system"),
- errhint("You should immediately run CREATE USER \"%s\" WITH SYSID %d CREATEUSER;.",
- username, BOOTSTRAP_USESYSID)));
+ errmsg("no roles are defined in this database system"),
+ errhint("You should immediately run CREATE USER \"%s\" CREATEUSER;.",
+ username)));
}
else
{
@@ -469,6 +470,9 @@ InitPostgres(const char *dbname, const char *username)
/* set default namespace search path */
InitializeSearchPath();
+ /* set up ACL framework (currently just sets RolMemCache callback) */
+ InitializeAcl();
+
/* initialize client encoding */
InitializeClientEncoding();
@@ -530,22 +534,22 @@ ShutdownPostgres(int code, Datum arg)
/*
- * Returns true if at least one user is defined in this database cluster.
+ * Returns true if at least one role is defined in this database cluster.
*/
static bool
-ThereIsAtLeastOneUser(void)
+ThereIsAtLeastOneRole(void)
{
- Relation pg_shadow_rel;
+ Relation pg_authid_rel;
HeapScanDesc scan;
bool result;
- pg_shadow_rel = heap_open(ShadowRelationId, AccessExclusiveLock);
+ pg_authid_rel = heap_open(AuthIdRelationId, AccessExclusiveLock);
- scan = heap_beginscan(pg_shadow_rel, SnapshotNow, 0, NULL);
+ scan = heap_beginscan(pg_authid_rel, SnapshotNow, 0, NULL);
result = (heap_getnext(scan, ForwardScanDirection) != NULL);
heap_endscan(scan);
- heap_close(pg_shadow_rel, AccessExclusiveLock);
+ heap_close(pg_authid_rel, AccessExclusiveLock);
return result;
}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 0ab8e742336..84d8085503a 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.270 2005/06/26 19:16:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.271 2005/06/28 05:09:02 tgl Exp $
*
*--------------------------------------------------------------------
*/
@@ -5108,7 +5108,7 @@ ParseLongOption(const char *string, char **name, char **value)
/*
- * Handle options fetched from pg_database.datconfig or pg_shadow.useconfig.
+ * Handle options fetched from pg_database.datconfig or pg_authid.rolconfig.
* The array parameter must be an array of TEXT (it must not be NULL).
*/
void
@@ -5154,7 +5154,7 @@ ProcessGUCArray(ArrayType *array, GucSource source)
/*
* We process all these options at SUSET level. We assume that
- * the right to insert an option into pg_database or pg_shadow was
+ * the right to insert an option into pg_database or pg_authid was
* checked when it was inserted.
*/
SetConfigOption(name, value, PGC_SUSET, source);
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
index 520dc470cdc..9e965b8107f 100644
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -14,29 +14,29 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/superuser.c,v 1.31 2005/05/29 20:38:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/superuser.c,v 1.32 2005/06/28 05:09:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
-#include "catalog/pg_shadow.h"
+#include "catalog/pg_authid.h"
#include "utils/inval.h"
#include "utils/syscache.h"
#include "miscadmin.h"
/*
- * In common cases the same userid (ie, the session or current ID) will
+ * In common cases the same roleid (ie, the session or current ID) will
* be queried repeatedly. So we maintain a simple one-entry cache for
- * the status of the last requested userid. The cache can be flushed
- * at need by watching for cache update events on pg_shadow.
+ * the status of the last requested roleid. The cache can be flushed
+ * at need by watching for cache update events on pg_authid.
*/
-static AclId last_userid = 0; /* 0 == cache not valid */
-static bool last_userid_is_super = false;
-static bool userid_callback_registered = false;
+static Oid last_roleid = InvalidOid; /* InvalidOid == cache not valid */
+static bool last_roleid_is_super = false;
+static bool roleid_callback_registered = false;
-static void UseridCallback(Datum arg, Oid relid);
+static void RoleidCallback(Datum arg, Oid relid);
/*
@@ -50,49 +50,49 @@ superuser(void)
/*
- * The specified userid has Postgres superuser privileges
+ * The specified role has Postgres superuser privileges
*/
bool
-superuser_arg(AclId userid)
+superuser_arg(Oid roleid)
{
bool result;
- HeapTuple utup;
+ HeapTuple rtup;
/* Quick out for cache hit */
- if (AclIdIsValid(last_userid) && last_userid == userid)
- return last_userid_is_super;
+ if (OidIsValid(last_roleid) && last_roleid == roleid)
+ return last_roleid_is_super;
/* Special escape path in case you deleted all your users. */
- if (!IsUnderPostmaster && userid == BOOTSTRAP_USESYSID)
+ if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID)
return true;
- /* OK, look up the information in pg_shadow */
- utup = SearchSysCache(SHADOWSYSID,
- Int32GetDatum(userid),
+ /* OK, look up the information in pg_authid */
+ rtup = SearchSysCache(AUTHOID,
+ ObjectIdGetDatum(roleid),
0, 0, 0);
- if (HeapTupleIsValid(utup))
+ if (HeapTupleIsValid(rtup))
{
- result = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
- ReleaseSysCache(utup);
+ result = ((Form_pg_authid) GETSTRUCT(rtup))->rolsuper;
+ ReleaseSysCache(rtup);
}
else
{
- /* Report "not superuser" for invalid userids */
+ /* Report "not superuser" for invalid roleids */
result = false;
}
/* If first time through, set up callback for cache flushes */
- if (!userid_callback_registered)
+ if (!roleid_callback_registered)
{
- CacheRegisterSyscacheCallback(SHADOWSYSID,
- UseridCallback,
+ CacheRegisterSyscacheCallback(AUTHOID,
+ RoleidCallback,
(Datum) 0);
- userid_callback_registered = true;
+ roleid_callback_registered = true;
}
/* Cache the result for next time */
- last_userid = userid;
- last_userid_is_super = result;
+ last_roleid = roleid;
+ last_roleid_is_super = result;
return result;
}
@@ -102,8 +102,8 @@ superuser_arg(AclId userid)
* Syscache inval callback function
*/
static void
-UseridCallback(Datum arg, Oid relid)
+RoleidCallback(Datum arg, Oid relid)
{
- /* Invalidate our local cache in case user's superuserness changed */
- last_userid = 0;
+ /* Invalidate our local cache in case role's superuserness changed */
+ last_roleid = InvalidOid;
}