diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-06-28 05:09:14 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-06-28 05:09:14 +0000 |
commit | 7762619e95272974f90a38d8d85aafbe0e94add5 (patch) | |
tree | d7f756687beb883406489d59d13f722995fd7660 /src/backend/utils/adt/acl.c | |
parent | 977530d8da2683dff036c2994395ab518527b93e (diff) | |
download | postgresql-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/adt/acl.c')
-rw-r--r-- | src/backend/utils/adt/acl.c | 734 |
1 files changed, 369 insertions, 365 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); +} |