1 /*-------------------------------------------------------------------------
4 * Basic access control list data structures manipulation routines.
6 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.100 2003/10/29 22:20:54 tgl Exp $
13 *-------------------------------------------------------------------------
19 #include "catalog/namespace.h"
20 #include "catalog/pg_shadow.h"
21 #include "catalog/pg_type.h"
22 #include "commands/dbcommands.h"
23 #include "miscadmin.h"
24 #include "utils/acl.h"
25 #include "utils/builtins.h"
26 #include "utils/lsyscache.h"
27 #include "utils/syscache.h"
30 #define ACL_IDTYPE_GID_KEYWORD "group"
31 #define ACL_IDTYPE_UID_KEYWORD "user"
33 static const char *getid(const char *s, char *n);
34 static void putid(char *p, const char *s);
35 static Acl *allocacl(int n);
36 static const char *aclparse(const char *s, AclItem *aip);
37 static bool aclitem_match(const AclItem *a1, const AclItem *a2);
38 static Acl *recursive_revoke(Acl *acl, AclId grantee,
39 AclMode revoke_privs, DropBehavior behavior);
41 static AclMode convert_priv_string(text *priv_type_text);
43 static Oid convert_table_name(text *tablename);
44 static AclMode convert_table_priv_string(text *priv_type_text);
45 static Oid convert_database_name(text *databasename);
46 static AclMode convert_database_priv_string(text *priv_type_text);
47 static Oid convert_function_name(text *functionname);
48 static AclMode convert_function_priv_string(text *priv_type_text);
49 static Oid convert_language_name(text *languagename);
50 static AclMode convert_language_priv_string(text *priv_type_text);
51 static Oid convert_schema_name(text *schemaname);
52 static AclMode convert_schema_priv_string(text *priv_type_text);
57 * Consumes the first alphanumeric string (identifier) found in string
58 * 's', ignoring any leading white space. If it finds a double quote
59 * it returns the word inside the quotes.
62 * the string position in 's' that points to the next non-space character
63 * in 's', after any quotes. Also:
64 * - loads the identifier into 'n'. (If no identifier is found, 'n'
65 * contains an empty string.) 'n' must be NAMEDATALEN bytes.
68 getid(const char *s, char *n)
71 bool in_quotes = false;
75 while (isspace((unsigned char) *s))
77 /* This code had better match what putid() does, below */
80 (isalnum((unsigned char) *s) ||
88 /* safe to look at next char (could be '\0' though) */
91 in_quotes = !in_quotes;
94 /* it's an escaped double quote; skip the escaping char */
98 /* Add the character to the string */
99 if (len >= NAMEDATALEN - 1)
101 (errcode(ERRCODE_NAME_TOO_LONG),
102 errmsg("identifier too long"),
103 errdetail("Identifier must be less than %d characters.",
109 while (isspace((unsigned char) *s))
115 * Write a user or group Name at *p, adding double quotes if needed.
116 * There must be at least (2*NAMEDATALEN)+2 bytes available at *p.
117 * This needs to be kept in sync with copyAclUserName in pg_dump/dumputils.c
120 putid(char *p, const char *s)
125 for (src = s; *src; src++)
127 /* This test had better match what getid() does, above */
128 if (!isalnum((unsigned char) *src) && *src != '_')
136 for (src = s; *src; src++)
138 /* A double quote character in a username is encoded as "" */
150 * Consumes and parses an ACL specification of the form:
151 * [group|user] [A-Za-z0-9]*=[rwaR]*
152 * from string 's', ignoring any leading white space or white space
153 * between the optional id type keyword (group|user) and the actual
156 * This routine is called by the parser as well as aclitemin(), hence
157 * the added generality.
160 * the string position in 's' immediately following the ACL
161 * specification. Also:
162 * - loads the structure pointed to by 'aip' with the appropriate
163 * UID/GID, id type identifier and mode type values.
166 aclparse(const char *s, AclItem *aip)
172 char name[NAMEDATALEN];
173 char name2[NAMEDATALEN];
178 elog(LOG, "aclparse: input = \"%s\"", s);
180 idtype = ACL_IDTYPE_UID;
184 /* we just read a keyword, not a name */
185 if (strcmp(name, ACL_IDTYPE_GID_KEYWORD) == 0)
186 idtype = ACL_IDTYPE_GID;
187 else if (strcmp(name, ACL_IDTYPE_UID_KEYWORD) != 0)
189 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
190 errmsg("unrecognized key word: \"%s\"", name),
191 errhint("ACL key word must be \"group\" or \"user\".")));
192 s = getid(s, name); /* move s to the name beyond the keyword */
195 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
196 errmsg("missing name"),
197 errhint("A name must follow the \"group\" or \"user\" key word.")));
200 idtype = ACL_IDTYPE_WORLD;
204 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
205 errmsg("missing \"=\" sign")));
207 privs = goption = ACL_NO_RIGHTS;
209 for (++s, read = 0; isalpha((unsigned char) *s) || *s == '*'; s++)
231 case ACL_REFERENCES_CHR:
232 read = ACL_REFERENCES;
234 case ACL_TRIGGER_CHR:
237 case ACL_EXECUTE_CHR:
246 case ACL_CREATE_TEMP_CHR:
247 read = ACL_CREATE_TEMP;
251 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
252 errmsg("invalid mode character: must be one of \"%s\"",
253 ACL_ALL_RIGHTS_STR)));
262 aip->ai_grantee = get_usesysid(name);
265 aip->ai_grantee = get_grosysid(name);
267 case ACL_IDTYPE_WORLD:
268 aip->ai_grantee = ACL_ID_WORLD;
273 * XXX Allow a degree of backward compatibility by defaulting the
274 * grantor to the superuser.
278 s = getid(s + 1, name2);
279 if (name2[0] == '\0')
281 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
282 errmsg("a name must follow the \"/\" sign")));
284 aip->ai_grantor = get_usesysid(name2);
288 aip->ai_grantor = BOOTSTRAP_USESYSID;
290 (errcode(ERRCODE_INVALID_GRANTOR),
291 errmsg("defaulting grantor to user ID %u", BOOTSTRAP_USESYSID)));
294 ACLITEM_SET_PRIVS_IDTYPE(*aip, privs, goption, idtype);
297 elog(LOG, "aclparse: correctly read [%x %d %x]",
298 idtype, aip->ai_grantee, privs);
305 * Allocates storage for a new Acl with 'n' entries.
317 elog(ERROR, "invalid size: %d", n);
318 size = ACL_N_SIZE(n);
319 new_acl = (Acl *) palloc0(size);
320 new_acl->size = size;
323 new_acl->elemtype = ACLITEMOID;
324 ARR_LBOUND(new_acl)[0] = 0;
325 ARR_DIMS(new_acl)[0] = n;
331 * Allocates storage for, and fills in, a new AclItem given a string
332 * 's' that contains an ACL specification. See aclparse for details.
338 aclitemin(PG_FUNCTION_ARGS)
340 const char *s = PG_GETARG_CSTRING(0);
343 aip = (AclItem *) palloc(sizeof(AclItem));
344 s = aclparse(s, aip);
345 while (isspace((unsigned char) *s))
349 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
350 errmsg("extra garbage at the end of the ACL specification")));
352 PG_RETURN_ACLITEM_P(aip);
357 * Allocates storage for, and fills in, a new null-delimited string
358 * containing a formatted ACL specification. See aclparse for details.
364 aclitemout(PG_FUNCTION_ARGS)
366 AclItem *aip = PG_GETARG_ACLITEM_P(0);
373 out = palloc(strlen("group =/") +
375 2 * (2 * NAMEDATALEN + 2) +
381 switch (ACLITEM_GET_IDTYPE(*aip))
384 htup = SearchSysCache(SHADOWSYSID,
385 ObjectIdGetDatum(aip->ai_grantee),
387 if (HeapTupleIsValid(htup))
389 putid(p, NameStr(((Form_pg_shadow) GETSTRUCT(htup))->usename));
390 ReleaseSysCache(htup);
394 /* Generate numeric UID if we don't find an entry */
395 sprintf(p, "%d", aip->ai_grantee);
401 tmpname = get_groname(aip->ai_grantee);
406 /* Generate numeric GID if we don't find an entry */
407 sprintf(p, "%d", aip->ai_grantee);
410 case ACL_IDTYPE_WORLD:
413 elog(ERROR, "unrecognized idtype: %d",
414 (int) ACLITEM_GET_IDTYPE(*aip));
422 for (i = 0; i < N_ACL_RIGHTS; ++i)
424 if (ACLITEM_GET_PRIVS(*aip) & (1 << i))
425 *p++ = ACL_ALL_RIGHTS_STR[i];
426 if (ACLITEM_GET_GOPTIONS(*aip) & (1 << i))
433 htup = SearchSysCache(SHADOWSYSID,
434 ObjectIdGetDatum(aip->ai_grantor),
436 if (HeapTupleIsValid(htup))
438 putid(p, NameStr(((Form_pg_shadow) GETSTRUCT(htup))->usename));
439 ReleaseSysCache(htup);
443 /* Generate numeric UID if we don't find an entry */
444 sprintf(p, "%d", aip->ai_grantor);
451 PG_RETURN_CSTRING(out);
456 * Two AclItems are considered to match iff they have the same
457 * grantee and grantor; the privileges are ignored.
460 aclitem_match(const AclItem *a1, const AclItem *a2)
462 return ACLITEM_GET_IDTYPE(*a1) == ACLITEM_GET_IDTYPE(*a2) &&
463 a1->ai_grantee == a2->ai_grantee &&
464 a1->ai_grantor == a2->ai_grantor;
468 * aclitem equality operator
471 aclitem_eq(PG_FUNCTION_ARGS)
473 AclItem *a1 = PG_GETARG_ACLITEM_P(0);
474 AclItem *a2 = PG_GETARG_ACLITEM_P(1);
477 result = a1->ai_privs == a2->ai_privs &&
478 a1->ai_grantee == a2->ai_grantee &&
479 a1->ai_grantor == a2->ai_grantor;
480 PG_RETURN_BOOL(result);
484 * aclitem hash function
486 * We make aclitems hashable not so much because anyone is likely to hash
487 * them, as because we want array equality to work on aclitem arrays, and
488 * with the typcache mechanism we must have a hash or btree opclass.
491 hash_aclitem(PG_FUNCTION_ARGS)
493 AclItem *a = PG_GETARG_ACLITEM_P(0);
495 /* not very bright, but avoids any issue of padding in struct */
496 PG_RETURN_UINT32((uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor));
501 * acldefault() --- create an ACL describing default access permissions
503 * Change this routine if you want to alter the default access policy for
504 * newly-created objects (or any object with a NULL acl entry).
507 acldefault(GrantObjectType objtype, AclId ownerid)
509 AclMode world_default;
510 AclMode owner_default;
516 case ACL_OBJECT_RELATION:
517 world_default = ACL_NO_RIGHTS;
518 owner_default = ACL_ALL_RIGHTS_RELATION;
520 case ACL_OBJECT_DATABASE:
521 world_default = ACL_CREATE_TEMP; /* not NO_RIGHTS! */
522 owner_default = ACL_ALL_RIGHTS_DATABASE;
524 case ACL_OBJECT_FUNCTION:
525 /* Grant EXECUTE by default, for now */
526 world_default = ACL_EXECUTE;
527 owner_default = ACL_ALL_RIGHTS_FUNCTION;
529 case ACL_OBJECT_LANGUAGE:
530 /* Grant USAGE by default, for now */
531 world_default = ACL_USAGE;
532 owner_default = ACL_ALL_RIGHTS_LANGUAGE;
534 case ACL_OBJECT_NAMESPACE:
535 world_default = ACL_NO_RIGHTS;
536 owner_default = ACL_ALL_RIGHTS_NAMESPACE;
539 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
540 world_default = ACL_NO_RIGHTS; /* keep compiler quiet */
541 owner_default = ACL_NO_RIGHTS;
545 acl = allocacl((world_default != ACL_NO_RIGHTS) ? 2 : 1);
548 if (world_default != ACL_NO_RIGHTS)
550 aip->ai_grantee = ACL_ID_WORLD;
551 aip->ai_grantor = ownerid;
552 ACLITEM_SET_PRIVS_IDTYPE(*aip, world_default, ACL_NO_RIGHTS,
557 aip->ai_grantee = ownerid;
558 aip->ai_grantor = ownerid;
559 /* owner gets default privileges with grant option */
560 ACLITEM_SET_PRIVS_IDTYPE(*aip, owner_default, owner_default,
568 * Add or replace an item in an ACL array. The result is a modified copy;
569 * the input object is not changed.
571 * NB: caller is responsible for having detoasted the input ACL, if needed.
574 aclinsert3(const Acl *old_acl, const AclItem *mod_aip,
575 unsigned modechg, DropBehavior behavior)
587 /* These checks for null input are probably dead code, but... */
588 if (!old_acl || ACL_NUM(old_acl) < 0)
589 old_acl = allocacl(0);
592 new_acl = allocacl(ACL_NUM(old_acl));
593 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
597 num = ACL_NUM(old_acl);
598 old_aip = ACL_DAT(old_acl);
601 * Search the ACL for an existing entry for this grantee and grantor.
602 * If one exists, just modify the entry in-place (well, in the same
603 * position, since we actually return a copy); otherwise, insert the
604 * new entry at the end.
607 for (dst = 0; dst < num; ++dst)
609 if (aclitem_match(mod_aip, old_aip + dst))
611 /* found a match, so modify existing item */
612 new_acl = allocacl(num);
613 new_aip = ACL_DAT(new_acl);
614 memcpy(new_acl, old_acl, ACL_SIZE(old_acl));
621 /* need to append a new item */
622 new_acl = allocacl(num + 1);
623 new_aip = ACL_DAT(new_acl);
624 memcpy(new_aip, old_aip, num * sizeof(AclItem));
626 /* initialize the new entry with no permissions */
627 new_aip[dst].ai_grantee = mod_aip->ai_grantee;
628 new_aip[dst].ai_grantor = mod_aip->ai_grantor;
629 ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst], ACL_NO_RIGHTS, ACL_NO_RIGHTS,
630 ACLITEM_GET_IDTYPE(*mod_aip));
631 num++; /* set num to the size of new_acl */
634 old_privs = ACLITEM_GET_PRIVS(new_aip[dst]);
635 old_goptions = ACLITEM_GET_GOPTIONS(new_aip[dst]);
637 /* apply the specified permissions change */
640 case ACL_MODECHG_ADD:
641 ACLITEM_SET_PRIVS(new_aip[dst],
642 old_privs | ACLITEM_GET_PRIVS(*mod_aip));
643 ACLITEM_SET_GOPTIONS(new_aip[dst],
644 old_goptions | ACLITEM_GET_GOPTIONS(*mod_aip));
646 case ACL_MODECHG_DEL:
647 ACLITEM_SET_PRIVS(new_aip[dst],
648 old_privs & ~ACLITEM_GET_PRIVS(*mod_aip));
649 ACLITEM_SET_GOPTIONS(new_aip[dst],
650 old_goptions & ~ACLITEM_GET_GOPTIONS(*mod_aip));
652 case ACL_MODECHG_EQL:
653 ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst],
654 ACLITEM_GET_PRIVS(*mod_aip),
655 ACLITEM_GET_GOPTIONS(*mod_aip),
656 ACLITEM_GET_IDTYPE(new_aip[dst]));
660 new_privs = ACLITEM_GET_PRIVS(new_aip[dst]);
661 new_goptions = ACLITEM_GET_GOPTIONS(new_aip[dst]);
664 * If the adjusted entry has no permissions, delete it from the list.
666 if (new_privs == ACL_NO_RIGHTS && new_goptions == ACL_NO_RIGHTS)
668 memmove(new_aip + dst,
670 (num - dst - 1) * sizeof(AclItem));
671 ARR_DIMS(new_acl)[0] = num - 1;
672 ARR_SIZE(new_acl) -= sizeof(AclItem);
676 * Remove abandoned privileges (cascading revoke). Currently we
677 * can only handle this when the grantee is a user.
679 if ((old_goptions & ~new_goptions) != 0
680 && ACLITEM_GET_IDTYPE(*mod_aip) == ACL_IDTYPE_UID)
681 new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee,
682 (old_goptions & ~new_goptions),
690 * Ensure that no privilege is "abandoned". A privilege is abandoned
691 * if the user that granted the privilege loses the grant option. (So
692 * the chain through which it was granted is broken.) Either the
693 * abandoned privileges are revoked as well, or an error message is
694 * printed, depending on the drop behavior option.
697 recursive_revoke(Acl *acl,
699 AclMode revoke_privs,
700 DropBehavior behavior)
705 for (i = 0; i < ACL_NUM(acl); i++)
707 AclItem *aip = ACL_DAT(acl);
709 if (aip[i].ai_grantor == grantee
710 && (ACLITEM_GET_PRIVS(aip[i]) & revoke_privs) != 0)
714 if (behavior == DROP_RESTRICT)
716 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
717 errmsg("dependent privileges exist"),
718 errhint("Use CASCADE to revoke them too.")));
720 mod_acl.ai_grantor = grantee;
721 mod_acl.ai_grantee = aip[i].ai_grantee;
722 ACLITEM_SET_PRIVS_IDTYPE(mod_acl,
725 ACLITEM_GET_IDTYPE(aip[i]));
727 acl = aclinsert3(acl, &mod_acl, ACL_MODECHG_DEL, behavior);
737 * aclinsert (exported function)
740 aclinsert(PG_FUNCTION_ARGS)
742 Acl *old_acl = PG_GETARG_ACL_P(0);
743 AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
745 PG_RETURN_ACL_P(aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL, DROP_CASCADE));
749 aclremove(PG_FUNCTION_ARGS)
751 Acl *old_acl = PG_GETARG_ACL_P(0);
752 AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
760 /* These checks for null input should be dead code, but... */
761 if (!old_acl || ACL_NUM(old_acl) < 0)
762 old_acl = allocacl(0);
765 new_acl = allocacl(ACL_NUM(old_acl));
766 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
767 PG_RETURN_ACL_P(new_acl);
770 old_num = ACL_NUM(old_acl);
771 old_aip = ACL_DAT(old_acl);
773 /* Search for the matching entry */
775 dst < old_num && !aclitem_match(mod_aip, old_aip + dst);
781 /* Not found, so return copy of source ACL */
782 new_acl = allocacl(old_num);
783 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
787 new_num = old_num - 1;
788 new_acl = allocacl(new_num);
789 new_aip = ACL_DAT(new_acl);
791 memcpy((char *) new_aip,
793 dst * sizeof(AclItem));
795 memcpy((char *) (new_aip + dst),
796 (char *) (old_aip + dst + 1),
797 (new_num - dst) * sizeof(AclItem));
800 PG_RETURN_ACL_P(new_acl);
804 aclcontains(PG_FUNCTION_ARGS)
806 Acl *acl = PG_GETARG_ACL_P(0);
807 AclItem *aip = PG_GETARG_ACLITEM_P(1);
813 aidat = ACL_DAT(acl);
814 for (i = 0; i < num; ++i)
816 if (aip->ai_grantee == aidat[i].ai_grantee
817 && ACLITEM_GET_IDTYPE(*aip) == ACLITEM_GET_IDTYPE(aidat[i])
818 && aip->ai_grantor == aidat[i].ai_grantor
819 && (ACLITEM_GET_PRIVS(*aip) & ACLITEM_GET_PRIVS(aidat[i])) == ACLITEM_GET_PRIVS(*aip)
820 && (ACLITEM_GET_GOPTIONS(*aip) & ACLITEM_GET_GOPTIONS(aidat[i])) == ACLITEM_GET_GOPTIONS(*aip))
821 PG_RETURN_BOOL(true);
823 PG_RETURN_BOOL(false);
827 makeaclitem(PG_FUNCTION_ARGS)
829 int32 u_grantee = PG_GETARG_INT32(0);
830 int32 g_grantee = PG_GETARG_INT32(1);
831 int32 grantor = PG_GETARG_INT32(2);
832 text *privtext = PG_GETARG_TEXT_P(3);
833 bool goption = PG_GETARG_BOOL(4);
837 priv = convert_priv_string(privtext);
839 aclitem = (AclItem *) palloc(sizeof(*aclitem));
841 if (u_grantee == 0 && g_grantee == 0)
843 aclitem->ai_grantee = ACL_ID_WORLD;
845 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_WORLD);
847 else if (u_grantee != 0 && g_grantee != 0)
850 (errcode(ERRCODE_DATA_EXCEPTION),
851 errmsg("cannot specify both user and group")));
853 else if (u_grantee != 0)
855 aclitem->ai_grantee = u_grantee;
857 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_UID);
859 else /* (g_grantee != 0) */
861 aclitem->ai_grantee = g_grantee;
863 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_GID);
866 aclitem->ai_grantor = grantor;
868 ACLITEM_SET_PRIVS(*aclitem, priv);
870 ACLITEM_SET_GOPTIONS(*aclitem, priv);
872 ACLITEM_SET_GOPTIONS(*aclitem, ACL_NO_RIGHTS);
874 PG_RETURN_ACLITEM_P(aclitem);
878 convert_priv_string(text *priv_type_text)
882 priv_type = DatumGetCString(DirectFunctionCall1(textout,
883 PointerGetDatum(priv_type_text)));
885 if (strcasecmp(priv_type, "SELECT") == 0)
887 if (strcasecmp(priv_type, "INSERT") == 0)
889 if (strcasecmp(priv_type, "UPDATE") == 0)
891 if (strcasecmp(priv_type, "DELETE") == 0)
893 if (strcasecmp(priv_type, "RULE") == 0)
895 if (strcasecmp(priv_type, "REFERENCES") == 0)
896 return ACL_REFERENCES;
897 if (strcasecmp(priv_type, "TRIGGER") == 0)
899 if (strcasecmp(priv_type, "EXECUTE") == 0)
901 if (strcasecmp(priv_type, "USAGE") == 0)
903 if (strcasecmp(priv_type, "CREATE") == 0)
905 if (strcasecmp(priv_type, "TEMP") == 0)
906 return ACL_CREATE_TEMP;
907 if (strcasecmp(priv_type, "TEMPORARY") == 0)
908 return ACL_CREATE_TEMP;
911 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
912 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
913 return ACL_NO_RIGHTS; /* keep compiler quiet */
918 * has_table_privilege variants
919 * These are all named "has_table_privilege" at the SQL level.
920 * They take various combinations of relation name, relation OID,
921 * user name, user sysid, or implicit user = current_user.
923 * The result is a boolean value: true if user has the indicated
924 * privilege, false if not.
928 * has_table_privilege_name_name
929 * Check user privileges on a table given
930 * name username, text tablename, and text priv name.
933 has_table_privilege_name_name(PG_FUNCTION_ARGS)
935 Name username = PG_GETARG_NAME(0);
936 text *tablename = PG_GETARG_TEXT_P(1);
937 text *priv_type_text = PG_GETARG_TEXT_P(2);
943 usesysid = get_usesysid(NameStr(*username));
944 tableoid = convert_table_name(tablename);
945 mode = convert_table_priv_string(priv_type_text);
947 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
949 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
953 * has_table_privilege_name
954 * Check user privileges on a table given
955 * text tablename and text priv name.
956 * current_user is assumed
959 has_table_privilege_name(PG_FUNCTION_ARGS)
961 text *tablename = PG_GETARG_TEXT_P(0);
962 text *priv_type_text = PG_GETARG_TEXT_P(1);
968 usesysid = GetUserId();
969 tableoid = convert_table_name(tablename);
970 mode = convert_table_priv_string(priv_type_text);
972 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
974 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
978 * has_table_privilege_name_id
979 * Check user privileges on a table given
980 * name usename, table oid, and text priv name.
983 has_table_privilege_name_id(PG_FUNCTION_ARGS)
985 Name username = PG_GETARG_NAME(0);
986 Oid tableoid = PG_GETARG_OID(1);
987 text *priv_type_text = PG_GETARG_TEXT_P(2);
992 usesysid = get_usesysid(NameStr(*username));
993 mode = convert_table_priv_string(priv_type_text);
995 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
997 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1001 * has_table_privilege_id
1002 * Check user privileges on a table given
1003 * table oid, and text priv name.
1004 * current_user is assumed
1007 has_table_privilege_id(PG_FUNCTION_ARGS)
1009 Oid tableoid = PG_GETARG_OID(0);
1010 text *priv_type_text = PG_GETARG_TEXT_P(1);
1013 AclResult aclresult;
1015 usesysid = GetUserId();
1016 mode = convert_table_priv_string(priv_type_text);
1018 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
1020 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1024 * has_table_privilege_id_name
1025 * Check user privileges on a table given
1026 * usesysid, text tablename, and text priv name.
1029 has_table_privilege_id_name(PG_FUNCTION_ARGS)
1031 int32 usesysid = PG_GETARG_INT32(0);
1032 text *tablename = PG_GETARG_TEXT_P(1);
1033 text *priv_type_text = PG_GETARG_TEXT_P(2);
1036 AclResult aclresult;
1038 tableoid = convert_table_name(tablename);
1039 mode = convert_table_priv_string(priv_type_text);
1041 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
1043 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1047 * has_table_privilege_id_id
1048 * Check user privileges on a table given
1049 * usesysid, table oid, and text priv name.
1052 has_table_privilege_id_id(PG_FUNCTION_ARGS)
1054 int32 usesysid = PG_GETARG_INT32(0);
1055 Oid tableoid = PG_GETARG_OID(1);
1056 text *priv_type_text = PG_GETARG_TEXT_P(2);
1058 AclResult aclresult;
1060 mode = convert_table_priv_string(priv_type_text);
1062 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
1064 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1068 * Support routines for has_table_privilege family.
1072 * Given a table name expressed as a string, look it up and return Oid
1075 convert_table_name(text *tablename)
1079 relrv = makeRangeVarFromNameList(textToQualifiedNameList(tablename,
1080 "has_table_privilege"));
1082 return RangeVarGetRelid(relrv, false);
1086 * convert_table_priv_string
1087 * Convert text string to AclMode value.
1090 convert_table_priv_string(text *priv_type_text)
1094 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1095 PointerGetDatum(priv_type_text)));
1098 * Return mode from priv_type string
1100 if (strcasecmp(priv_type, "SELECT") == 0)
1102 if (strcasecmp(priv_type, "SELECT WITH GRANT OPTION") == 0)
1103 return ACL_GRANT_OPTION_FOR(ACL_SELECT);
1105 if (strcasecmp(priv_type, "INSERT") == 0)
1107 if (strcasecmp(priv_type, "INSERT WITH GRANT OPTION") == 0)
1108 return ACL_GRANT_OPTION_FOR(ACL_INSERT);
1110 if (strcasecmp(priv_type, "UPDATE") == 0)
1112 if (strcasecmp(priv_type, "UPDATE WITH GRANT OPTION") == 0)
1113 return ACL_GRANT_OPTION_FOR(ACL_UPDATE);
1115 if (strcasecmp(priv_type, "DELETE") == 0)
1117 if (strcasecmp(priv_type, "DELETE WITH GRANT OPTION") == 0)
1118 return ACL_GRANT_OPTION_FOR(ACL_DELETE);
1120 if (strcasecmp(priv_type, "RULE") == 0)
1122 if (strcasecmp(priv_type, "RULE WITH GRANT OPTION") == 0)
1123 return ACL_GRANT_OPTION_FOR(ACL_RULE);
1125 if (strcasecmp(priv_type, "REFERENCES") == 0)
1126 return ACL_REFERENCES;
1127 if (strcasecmp(priv_type, "REFERENCES WITH GRANT OPTION") == 0)
1128 return ACL_GRANT_OPTION_FOR(ACL_REFERENCES);
1130 if (strcasecmp(priv_type, "TRIGGER") == 0)
1132 if (strcasecmp(priv_type, "TRIGGER WITH GRANT OPTION") == 0)
1133 return ACL_GRANT_OPTION_FOR(ACL_TRIGGER);
1136 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1137 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
1138 return ACL_NO_RIGHTS; /* keep compiler quiet */
1143 * has_database_privilege variants
1144 * These are all named "has_database_privilege" at the SQL level.
1145 * They take various combinations of database name, database OID,
1146 * user name, user sysid, or implicit user = current_user.
1148 * The result is a boolean value: true if user has the indicated
1149 * privilege, false if not.
1153 * has_database_privilege_name_name
1154 * Check user privileges on a database given
1155 * name username, text databasename, and text priv name.
1158 has_database_privilege_name_name(PG_FUNCTION_ARGS)
1160 Name username = PG_GETARG_NAME(0);
1161 text *databasename = PG_GETARG_TEXT_P(1);
1162 text *priv_type_text = PG_GETARG_TEXT_P(2);
1166 AclResult aclresult;
1168 usesysid = get_usesysid(NameStr(*username));
1169 databaseoid = convert_database_name(databasename);
1170 mode = convert_database_priv_string(priv_type_text);
1172 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1174 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1178 * has_database_privilege_name
1179 * Check user privileges on a database given
1180 * text databasename and text priv name.
1181 * current_user is assumed
1184 has_database_privilege_name(PG_FUNCTION_ARGS)
1186 text *databasename = PG_GETARG_TEXT_P(0);
1187 text *priv_type_text = PG_GETARG_TEXT_P(1);
1191 AclResult aclresult;
1193 usesysid = GetUserId();
1194 databaseoid = convert_database_name(databasename);
1195 mode = convert_database_priv_string(priv_type_text);
1197 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1199 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1203 * has_database_privilege_name_id
1204 * Check user privileges on a database given
1205 * name usename, database oid, and text priv name.
1208 has_database_privilege_name_id(PG_FUNCTION_ARGS)
1210 Name username = PG_GETARG_NAME(0);
1211 Oid databaseoid = PG_GETARG_OID(1);
1212 text *priv_type_text = PG_GETARG_TEXT_P(2);
1215 AclResult aclresult;
1217 usesysid = get_usesysid(NameStr(*username));
1218 mode = convert_database_priv_string(priv_type_text);
1220 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1222 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1226 * has_database_privilege_id
1227 * Check user privileges on a database given
1228 * database oid, and text priv name.
1229 * current_user is assumed
1232 has_database_privilege_id(PG_FUNCTION_ARGS)
1234 Oid databaseoid = PG_GETARG_OID(0);
1235 text *priv_type_text = PG_GETARG_TEXT_P(1);
1238 AclResult aclresult;
1240 usesysid = GetUserId();
1241 mode = convert_database_priv_string(priv_type_text);
1243 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1245 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1249 * has_database_privilege_id_name
1250 * Check user privileges on a database given
1251 * usesysid, text databasename, and text priv name.
1254 has_database_privilege_id_name(PG_FUNCTION_ARGS)
1256 int32 usesysid = PG_GETARG_INT32(0);
1257 text *databasename = PG_GETARG_TEXT_P(1);
1258 text *priv_type_text = PG_GETARG_TEXT_P(2);
1261 AclResult aclresult;
1263 databaseoid = convert_database_name(databasename);
1264 mode = convert_database_priv_string(priv_type_text);
1266 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1268 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1272 * has_database_privilege_id_id
1273 * Check user privileges on a database given
1274 * usesysid, database oid, and text priv name.
1277 has_database_privilege_id_id(PG_FUNCTION_ARGS)
1279 int32 usesysid = PG_GETARG_INT32(0);
1280 Oid databaseoid = PG_GETARG_OID(1);
1281 text *priv_type_text = PG_GETARG_TEXT_P(2);
1283 AclResult aclresult;
1285 mode = convert_database_priv_string(priv_type_text);
1287 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1289 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1293 * Support routines for has_database_privilege family.
1297 * Given a database name expressed as a string, look it up and return Oid
1300 convert_database_name(text *databasename)
1305 dbname = DatumGetCString(DirectFunctionCall1(textout,
1306 PointerGetDatum(databasename)));
1308 oid = get_database_oid(dbname);
1309 if (!OidIsValid(oid))
1311 (errcode(ERRCODE_UNDEFINED_DATABASE),
1312 errmsg("database \"%s\" does not exist", dbname)));
1318 * convert_database_priv_string
1319 * Convert text string to AclMode value.
1322 convert_database_priv_string(text *priv_type_text)
1326 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1327 PointerGetDatum(priv_type_text)));
1330 * Return mode from priv_type string
1332 if (strcasecmp(priv_type, "CREATE") == 0)
1334 if (strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0)
1335 return ACL_GRANT_OPTION_FOR(ACL_CREATE);
1337 if (strcasecmp(priv_type, "TEMPORARY") == 0)
1338 return ACL_CREATE_TEMP;
1339 if (strcasecmp(priv_type, "TEMPORARY WITH GRANT OPTION") == 0)
1340 return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP);
1342 if (strcasecmp(priv_type, "TEMP") == 0)
1343 return ACL_CREATE_TEMP;
1344 if (strcasecmp(priv_type, "TEMP WITH GRANT OPTION") == 0)
1345 return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP);
1348 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1349 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
1350 return ACL_NO_RIGHTS; /* keep compiler quiet */
1355 * has_function_privilege variants
1356 * These are all named "has_function_privilege" at the SQL level.
1357 * They take various combinations of function name, function OID,
1358 * user name, user sysid, or implicit user = current_user.
1360 * The result is a boolean value: true if user has the indicated
1361 * privilege, false if not.
1365 * has_function_privilege_name_name
1366 * Check user privileges on a function given
1367 * name username, text functionname, and text priv name.
1370 has_function_privilege_name_name(PG_FUNCTION_ARGS)
1372 Name username = PG_GETARG_NAME(0);
1373 text *functionname = PG_GETARG_TEXT_P(1);
1374 text *priv_type_text = PG_GETARG_TEXT_P(2);
1378 AclResult aclresult;
1380 usesysid = get_usesysid(NameStr(*username));
1381 functionoid = convert_function_name(functionname);
1382 mode = convert_function_priv_string(priv_type_text);
1384 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1386 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1390 * has_function_privilege_name
1391 * Check user privileges on a function given
1392 * text functionname and text priv name.
1393 * current_user is assumed
1396 has_function_privilege_name(PG_FUNCTION_ARGS)
1398 text *functionname = PG_GETARG_TEXT_P(0);
1399 text *priv_type_text = PG_GETARG_TEXT_P(1);
1403 AclResult aclresult;
1405 usesysid = GetUserId();
1406 functionoid = convert_function_name(functionname);
1407 mode = convert_function_priv_string(priv_type_text);
1409 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1411 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1415 * has_function_privilege_name_id
1416 * Check user privileges on a function given
1417 * name usename, function oid, and text priv name.
1420 has_function_privilege_name_id(PG_FUNCTION_ARGS)
1422 Name username = PG_GETARG_NAME(0);
1423 Oid functionoid = PG_GETARG_OID(1);
1424 text *priv_type_text = PG_GETARG_TEXT_P(2);
1427 AclResult aclresult;
1429 usesysid = get_usesysid(NameStr(*username));
1430 mode = convert_function_priv_string(priv_type_text);
1432 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1434 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1438 * has_function_privilege_id
1439 * Check user privileges on a function given
1440 * function oid, and text priv name.
1441 * current_user is assumed
1444 has_function_privilege_id(PG_FUNCTION_ARGS)
1446 Oid functionoid = PG_GETARG_OID(0);
1447 text *priv_type_text = PG_GETARG_TEXT_P(1);
1450 AclResult aclresult;
1452 usesysid = GetUserId();
1453 mode = convert_function_priv_string(priv_type_text);
1455 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1457 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1461 * has_function_privilege_id_name
1462 * Check user privileges on a function given
1463 * usesysid, text functionname, and text priv name.
1466 has_function_privilege_id_name(PG_FUNCTION_ARGS)
1468 int32 usesysid = PG_GETARG_INT32(0);
1469 text *functionname = PG_GETARG_TEXT_P(1);
1470 text *priv_type_text = PG_GETARG_TEXT_P(2);
1473 AclResult aclresult;
1475 functionoid = convert_function_name(functionname);
1476 mode = convert_function_priv_string(priv_type_text);
1478 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1480 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1484 * has_function_privilege_id_id
1485 * Check user privileges on a function given
1486 * usesysid, function oid, and text priv name.
1489 has_function_privilege_id_id(PG_FUNCTION_ARGS)
1491 int32 usesysid = PG_GETARG_INT32(0);
1492 Oid functionoid = PG_GETARG_OID(1);
1493 text *priv_type_text = PG_GETARG_TEXT_P(2);
1495 AclResult aclresult;
1497 mode = convert_function_priv_string(priv_type_text);
1499 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1501 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1505 * Support routines for has_function_privilege family.
1509 * Given a function name expressed as a string, look it up and return Oid
1512 convert_function_name(text *functionname)
1517 funcname = DatumGetCString(DirectFunctionCall1(textout,
1518 PointerGetDatum(functionname)));
1520 oid = DatumGetObjectId(DirectFunctionCall1(regprocedurein,
1521 CStringGetDatum(funcname)));
1523 if (!OidIsValid(oid))
1525 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1526 errmsg("function \"%s\" does not exist", funcname)));
1532 * convert_function_priv_string
1533 * Convert text string to AclMode value.
1536 convert_function_priv_string(text *priv_type_text)
1540 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1541 PointerGetDatum(priv_type_text)));
1544 * Return mode from priv_type string
1546 if (strcasecmp(priv_type, "EXECUTE") == 0)
1548 if (strcasecmp(priv_type, "EXECUTE WITH GRANT OPTION") == 0)
1549 return ACL_GRANT_OPTION_FOR(ACL_EXECUTE);
1552 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1553 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
1554 return ACL_NO_RIGHTS; /* keep compiler quiet */
1559 * has_language_privilege variants
1560 * These are all named "has_language_privilege" at the SQL level.
1561 * They take various combinations of language name, language OID,
1562 * user name, user sysid, or implicit user = current_user.
1564 * The result is a boolean value: true if user has the indicated
1565 * privilege, false if not.
1569 * has_language_privilege_name_name
1570 * Check user privileges on a language given
1571 * name username, text languagename, and text priv name.
1574 has_language_privilege_name_name(PG_FUNCTION_ARGS)
1576 Name username = PG_GETARG_NAME(0);
1577 text *languagename = PG_GETARG_TEXT_P(1);
1578 text *priv_type_text = PG_GETARG_TEXT_P(2);
1582 AclResult aclresult;
1584 usesysid = get_usesysid(NameStr(*username));
1585 languageoid = convert_language_name(languagename);
1586 mode = convert_language_priv_string(priv_type_text);
1588 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1590 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1594 * has_language_privilege_name
1595 * Check user privileges on a language given
1596 * text languagename and text priv name.
1597 * current_user is assumed
1600 has_language_privilege_name(PG_FUNCTION_ARGS)
1602 text *languagename = PG_GETARG_TEXT_P(0);
1603 text *priv_type_text = PG_GETARG_TEXT_P(1);
1607 AclResult aclresult;
1609 usesysid = GetUserId();
1610 languageoid = convert_language_name(languagename);
1611 mode = convert_language_priv_string(priv_type_text);
1613 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1615 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1619 * has_language_privilege_name_id
1620 * Check user privileges on a language given
1621 * name usename, language oid, and text priv name.
1624 has_language_privilege_name_id(PG_FUNCTION_ARGS)
1626 Name username = PG_GETARG_NAME(0);
1627 Oid languageoid = PG_GETARG_OID(1);
1628 text *priv_type_text = PG_GETARG_TEXT_P(2);
1631 AclResult aclresult;
1633 usesysid = get_usesysid(NameStr(*username));
1634 mode = convert_language_priv_string(priv_type_text);
1636 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1638 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1642 * has_language_privilege_id
1643 * Check user privileges on a language given
1644 * language oid, and text priv name.
1645 * current_user is assumed
1648 has_language_privilege_id(PG_FUNCTION_ARGS)
1650 Oid languageoid = PG_GETARG_OID(0);
1651 text *priv_type_text = PG_GETARG_TEXT_P(1);
1654 AclResult aclresult;
1656 usesysid = GetUserId();
1657 mode = convert_language_priv_string(priv_type_text);
1659 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1661 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1665 * has_language_privilege_id_name
1666 * Check user privileges on a language given
1667 * usesysid, text languagename, and text priv name.
1670 has_language_privilege_id_name(PG_FUNCTION_ARGS)
1672 int32 usesysid = PG_GETARG_INT32(0);
1673 text *languagename = PG_GETARG_TEXT_P(1);
1674 text *priv_type_text = PG_GETARG_TEXT_P(2);
1677 AclResult aclresult;
1679 languageoid = convert_language_name(languagename);
1680 mode = convert_language_priv_string(priv_type_text);
1682 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1684 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1688 * has_language_privilege_id_id
1689 * Check user privileges on a language given
1690 * usesysid, language oid, and text priv name.
1693 has_language_privilege_id_id(PG_FUNCTION_ARGS)
1695 int32 usesysid = PG_GETARG_INT32(0);
1696 Oid languageoid = PG_GETARG_OID(1);
1697 text *priv_type_text = PG_GETARG_TEXT_P(2);
1699 AclResult aclresult;
1701 mode = convert_language_priv_string(priv_type_text);
1703 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1705 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1709 * Support routines for has_language_privilege family.
1713 * Given a language name expressed as a string, look it up and return Oid
1716 convert_language_name(text *languagename)
1721 langname = DatumGetCString(DirectFunctionCall1(textout,
1722 PointerGetDatum(languagename)));
1724 oid = GetSysCacheOid(LANGNAME,
1725 CStringGetDatum(langname),
1727 if (!OidIsValid(oid))
1729 (errcode(ERRCODE_UNDEFINED_OBJECT),
1730 errmsg("language \"%s\" does not exist", langname)));
1736 * convert_language_priv_string
1737 * Convert text string to AclMode value.
1740 convert_language_priv_string(text *priv_type_text)
1744 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1745 PointerGetDatum(priv_type_text)));
1748 * Return mode from priv_type string
1750 if (strcasecmp(priv_type, "USAGE") == 0)
1752 if (strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0)
1753 return ACL_GRANT_OPTION_FOR(ACL_USAGE);
1756 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1757 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
1758 return ACL_NO_RIGHTS; /* keep compiler quiet */
1763 * has_schema_privilege variants
1764 * These are all named "has_schema_privilege" at the SQL level.
1765 * They take various combinations of schema name, schema OID,
1766 * user name, user sysid, or implicit user = current_user.
1768 * The result is a boolean value: true if user has the indicated
1769 * privilege, false if not.
1773 * has_schema_privilege_name_name
1774 * Check user privileges on a schema given
1775 * name username, text schemaname, and text priv name.
1778 has_schema_privilege_name_name(PG_FUNCTION_ARGS)
1780 Name username = PG_GETARG_NAME(0);
1781 text *schemaname = PG_GETARG_TEXT_P(1);
1782 text *priv_type_text = PG_GETARG_TEXT_P(2);
1786 AclResult aclresult;
1788 usesysid = get_usesysid(NameStr(*username));
1789 schemaoid = convert_schema_name(schemaname);
1790 mode = convert_schema_priv_string(priv_type_text);
1792 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1794 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1798 * has_schema_privilege_name
1799 * Check user privileges on a schema given
1800 * text schemaname and text priv name.
1801 * current_user is assumed
1804 has_schema_privilege_name(PG_FUNCTION_ARGS)
1806 text *schemaname = PG_GETARG_TEXT_P(0);
1807 text *priv_type_text = PG_GETARG_TEXT_P(1);
1811 AclResult aclresult;
1813 usesysid = GetUserId();
1814 schemaoid = convert_schema_name(schemaname);
1815 mode = convert_schema_priv_string(priv_type_text);
1817 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1819 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1823 * has_schema_privilege_name_id
1824 * Check user privileges on a schema given
1825 * name usename, schema oid, and text priv name.
1828 has_schema_privilege_name_id(PG_FUNCTION_ARGS)
1830 Name username = PG_GETARG_NAME(0);
1831 Oid schemaoid = PG_GETARG_OID(1);
1832 text *priv_type_text = PG_GETARG_TEXT_P(2);
1835 AclResult aclresult;
1837 usesysid = get_usesysid(NameStr(*username));
1838 mode = convert_schema_priv_string(priv_type_text);
1840 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1842 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1846 * has_schema_privilege_id
1847 * Check user privileges on a schema given
1848 * schema oid, and text priv name.
1849 * current_user is assumed
1852 has_schema_privilege_id(PG_FUNCTION_ARGS)
1854 Oid schemaoid = PG_GETARG_OID(0);
1855 text *priv_type_text = PG_GETARG_TEXT_P(1);
1858 AclResult aclresult;
1860 usesysid = GetUserId();
1861 mode = convert_schema_priv_string(priv_type_text);
1863 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1865 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1869 * has_schema_privilege_id_name
1870 * Check user privileges on a schema given
1871 * usesysid, text schemaname, and text priv name.
1874 has_schema_privilege_id_name(PG_FUNCTION_ARGS)
1876 int32 usesysid = PG_GETARG_INT32(0);
1877 text *schemaname = PG_GETARG_TEXT_P(1);
1878 text *priv_type_text = PG_GETARG_TEXT_P(2);
1881 AclResult aclresult;
1883 schemaoid = convert_schema_name(schemaname);
1884 mode = convert_schema_priv_string(priv_type_text);
1886 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1888 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1892 * has_schema_privilege_id_id
1893 * Check user privileges on a schema given
1894 * usesysid, schema oid, and text priv name.
1897 has_schema_privilege_id_id(PG_FUNCTION_ARGS)
1899 int32 usesysid = PG_GETARG_INT32(0);
1900 Oid schemaoid = PG_GETARG_OID(1);
1901 text *priv_type_text = PG_GETARG_TEXT_P(2);
1903 AclResult aclresult;
1905 mode = convert_schema_priv_string(priv_type_text);
1907 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1909 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1913 * Support routines for has_schema_privilege family.
1917 * Given a schema name expressed as a string, look it up and return Oid
1920 convert_schema_name(text *schemaname)
1925 nspname = DatumGetCString(DirectFunctionCall1(textout,
1926 PointerGetDatum(schemaname)));
1928 oid = GetSysCacheOid(NAMESPACENAME,
1929 CStringGetDatum(nspname),
1931 if (!OidIsValid(oid))
1933 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1934 errmsg("schema \"%s\" does not exist", nspname)));
1940 * convert_schema_priv_string
1941 * Convert text string to AclMode value.
1944 convert_schema_priv_string(text *priv_type_text)
1948 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1949 PointerGetDatum(priv_type_text)));
1952 * Return mode from priv_type string
1954 if (strcasecmp(priv_type, "CREATE") == 0)
1956 if (strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0)
1957 return ACL_GRANT_OPTION_FOR(ACL_CREATE);
1959 if (strcasecmp(priv_type, "USAGE") == 0)
1961 if (strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0)
1962 return ACL_GRANT_OPTION_FOR(ACL_USAGE);
1965 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1966 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
1967 return ACL_NO_RIGHTS; /* keep compiler quiet */