1 /*-------------------------------------------------------------------------
4 * Basic access control list data structures manipulation routines.
6 * Portions Copyright (c) 1996-2002, 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.80 2002/09/24 23:14:25 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 Acl *makeacl(int n);
35 static const char *aclparse(const char *s, AclItem *aip, unsigned *modechg);
36 static bool aclitemeq(const AclItem *a1, const AclItem *a2);
37 static bool aclitemgt(const AclItem *a1, const AclItem *a2);
39 static Oid convert_table_name(text *tablename);
40 static AclMode convert_table_priv_string(text *priv_type_text);
41 static Oid convert_database_name(text *databasename);
42 static AclMode convert_database_priv_string(text *priv_type_text);
43 static Oid convert_function_name(text *functionname);
44 static AclMode convert_function_priv_string(text *priv_type_text);
45 static Oid convert_language_name(text *languagename);
46 static AclMode convert_language_priv_string(text *priv_type_text);
47 static Oid convert_schema_name(text *schemaname);
48 static AclMode convert_schema_priv_string(text *priv_type_text);
53 * Consumes the first alphanumeric string (identifier) found in string
54 * 's', ignoring any leading white space. If it finds a double quote
55 * it returns the word inside the quotes.
58 * the string position in 's' that points to the next non-space character
59 * in 's', after any quotes. Also:
60 * - loads the identifier into 'name'. (If no identifier is found, 'name'
61 * contains an empty string.) name must be NAMEDATALEN bytes.
64 getid(const char *s, char *n)
72 while (isspace((unsigned char) *s))
82 isalnum((unsigned char) *s) || *s == '_' || in_quotes;
85 if (in_quotes && *s == '"')
91 if (len >= NAMEDATALEN)
92 elog(ERROR, "getid: identifier must be <%d characters",
97 while (isspace((unsigned char) *s))
104 * Consumes and parses an ACL specification of the form:
105 * [group|user] [A-Za-z0-9]*[+-=][rwaR]*
106 * from string 's', ignoring any leading white space or white space
107 * between the optional id type keyword (group|user) and the actual
110 * This routine is called by the parser as well as aclitemin(), hence
111 * the added generality.
114 * the string position in 's' immediately following the ACL
115 * specification. Also:
116 * - loads the structure pointed to by 'aip' with the appropriate
117 * UID/GID, id type identifier and mode type values.
118 * - loads 'modechg' with the mode change flag.
121 aclparse(const char *s, AclItem *aip, unsigned *modechg)
125 char name[NAMEDATALEN];
127 Assert(s && aip && modechg);
130 elog(LOG, "aclparse: input = '%s'", s);
132 idtype = ACL_IDTYPE_UID;
134 if (*s != ACL_MODECHG_ADD_CHR &&
135 *s != ACL_MODECHG_DEL_CHR &&
136 *s != ACL_MODECHG_EQL_CHR)
138 /* we just read a keyword, not a name */
139 if (strncmp(name, ACL_IDTYPE_GID_KEYWORD, sizeof(name)) == 0)
140 idtype = ACL_IDTYPE_GID;
141 else if (strncmp(name, ACL_IDTYPE_UID_KEYWORD, sizeof(name)) != 0)
142 elog(ERROR, "aclparse: bad keyword, must be [group|user]");
143 s = getid(s, name); /* move s to the name beyond the keyword */
145 elog(ERROR, "aclparse: a name must follow the [group|user] keyword");
148 idtype = ACL_IDTYPE_WORLD;
152 case ACL_MODECHG_ADD_CHR:
153 *modechg = ACL_MODECHG_ADD;
155 case ACL_MODECHG_DEL_CHR:
156 *modechg = ACL_MODECHG_DEL;
158 case ACL_MODECHG_EQL_CHR:
159 *modechg = ACL_MODECHG_EQL;
162 elog(ERROR, "aclparse: mode change flag must use \"%c%c%c\"",
165 ACL_MODECHG_EQL_CHR);
168 privs = ACL_NO_RIGHTS;
170 while (isalpha((unsigned char) *++s))
189 case ACL_REFERENCES_CHR:
190 privs |= ACL_REFERENCES;
192 case ACL_TRIGGER_CHR:
193 privs |= ACL_TRIGGER;
195 case ACL_EXECUTE_CHR:
196 privs |= ACL_EXECUTE;
204 case ACL_CREATE_TEMP_CHR:
205 privs |= ACL_CREATE_TEMP;
208 elog(ERROR, "aclparse: mode flags must use \"%s\"",
216 aip->ai_id = get_usesysid(name);
219 aip->ai_id = get_grosysid(name);
221 case ACL_IDTYPE_WORLD:
222 aip->ai_id = ACL_ID_WORLD;
226 ACLITEM_SET_PRIVS_IDTYPE(*aip, privs, idtype);
229 elog(LOG, "aclparse: correctly read [%x %d %x], modechg=%x",
230 idtype, aip->ai_id, privs, *modechg);
237 * Allocates storage for a new Acl with 'n' entries.
249 elog(ERROR, "makeacl: invalid size: %d", n);
250 size = ACL_N_SIZE(n);
251 new_acl = (Acl *) palloc(size);
252 MemSet((char *) new_acl, 0, size);
253 new_acl->size = size;
256 new_acl->elemtype = ACLITEMOID;
257 ARR_LBOUND(new_acl)[0] = 0;
258 ARR_DIMS(new_acl)[0] = n;
264 * Allocates storage for, and fills in, a new AclItem given a string
265 * 's' that contains an ACL specification. See aclparse for details.
271 aclitemin(PG_FUNCTION_ARGS)
273 const char *s = PG_GETARG_CSTRING(0);
277 aip = (AclItem *) palloc(sizeof(AclItem));
278 s = aclparse(s, aip, &modechg);
279 if (modechg != ACL_MODECHG_EQL)
280 elog(ERROR, "aclitemin: cannot accept anything but = ACLs");
281 while (isspace((unsigned char) *s))
284 elog(ERROR, "aclitemin: extra garbage at end of specification");
285 PG_RETURN_ACLITEM_P(aip);
290 * Allocates storage for, and fills in, a new null-delimited string
291 * containing a formatted ACL specification. See aclparse for details.
297 aclitemout(PG_FUNCTION_ARGS)
299 AclItem *aip = PG_GETARG_ACLITEM_P(0);
306 p = out = palloc(strlen("group = ") + N_ACL_RIGHTS + NAMEDATALEN + 1);
309 switch (ACLITEM_GET_IDTYPE(*aip))
312 htup = SearchSysCache(SHADOWSYSID,
313 ObjectIdGetDatum(aip->ai_id),
315 if (HeapTupleIsValid(htup))
318 NameStr(((Form_pg_shadow) GETSTRUCT(htup))->usename),
320 ReleaseSysCache(htup);
324 /* Generate numeric UID if we don't find an entry */
327 tmp = DatumGetCString(DirectFunctionCall1(int4out,
328 Int32GetDatum((int32) aip->ai_id)));
335 tmpname = get_groname(aip->ai_id);
337 strncat(p, tmpname, NAMEDATALEN);
340 /* Generate numeric GID if we don't find an entry */
343 tmp = DatumGetCString(DirectFunctionCall1(int4out,
344 Int32GetDatum((int32) aip->ai_id)));
349 case ACL_IDTYPE_WORLD:
352 elog(ERROR, "aclitemout: bad idtype: %d",
353 ACLITEM_GET_IDTYPE(*aip));
359 for (i = 0; i < N_ACL_RIGHTS; ++i)
360 if (aip->ai_privs & (1 << i))
361 *p++ = ACL_ALL_RIGHTS_STR[i];
364 PG_RETURN_CSTRING(out);
370 * AclItem equality and greater-than comparison routines.
371 * Two AclItems are considered equal iff they have the same
372 * identifier (and identifier type); the privileges are ignored.
373 * Note that these routines are really only useful for sorting
374 * AclItems into identifier order.
377 * a boolean value indicating = or >
380 aclitemeq(const AclItem *a1, const AclItem *a2)
382 return ACLITEM_GET_IDTYPE(*a1) == ACLITEM_GET_IDTYPE(*a2) &&
383 a1->ai_id == a2->ai_id;
387 aclitemgt(const AclItem *a1, const AclItem *a2)
389 return ((ACLITEM_GET_IDTYPE(*a1) > ACLITEM_GET_IDTYPE(*a2)) ||
390 (ACLITEM_GET_IDTYPE(*a1) == ACLITEM_GET_IDTYPE(*a2) &&
391 a1->ai_id > a2->ai_id));
396 * acldefault() --- create an ACL describing default access permissions
398 * Change this routine if you want to alter the default access policy for
399 * newly-created objects (or any object with a NULL acl entry).
402 acldefault(GrantObjectType objtype, AclId ownerid)
404 AclMode world_default;
405 AclMode owner_default;
411 case ACL_OBJECT_RELATION:
412 world_default = ACL_NO_RIGHTS;
413 owner_default = ACL_ALL_RIGHTS_RELATION;
415 case ACL_OBJECT_DATABASE:
416 world_default = ACL_CREATE_TEMP; /* not NO_RIGHTS! */
417 owner_default = ACL_ALL_RIGHTS_DATABASE;
419 case ACL_OBJECT_FUNCTION:
420 /* Grant EXECUTE by default, for now */
421 world_default = ACL_EXECUTE;
422 owner_default = ACL_ALL_RIGHTS_FUNCTION;
424 case ACL_OBJECT_LANGUAGE:
425 /* Grant USAGE by default, for now */
426 world_default = ACL_USAGE;
427 owner_default = ACL_ALL_RIGHTS_LANGUAGE;
429 case ACL_OBJECT_NAMESPACE:
430 world_default = ACL_NO_RIGHTS;
431 owner_default = ACL_ALL_RIGHTS_NAMESPACE;
434 elog(ERROR, "acldefault: bogus objtype %d", (int) objtype);
435 world_default = ACL_NO_RIGHTS; /* keep compiler quiet */
436 owner_default = ACL_NO_RIGHTS;
440 acl = makeacl(ownerid ? 2 : 1);
443 aip[0].ai_id = ACL_ID_WORLD;
444 ACLITEM_SET_PRIVS_IDTYPE(aip[0], world_default, ACL_IDTYPE_WORLD);
447 aip[1].ai_id = ownerid;
448 ACLITEM_SET_PRIVS_IDTYPE(aip[1], owner_default, ACL_IDTYPE_UID);
456 * Add or replace an item in an ACL array. The result is a modified copy;
457 * the input object is not changed.
459 * NB: caller is responsible for having detoasted the input ACL, if needed.
462 aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg)
470 /* These checks for null input are probably dead code, but... */
471 if (!old_acl || ACL_NUM(old_acl) < 1)
472 old_acl = makeacl(1);
475 new_acl = makeacl(ACL_NUM(old_acl));
476 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
480 num = ACL_NUM(old_acl);
481 old_aip = ACL_DAT(old_acl);
484 * Search the ACL for an existing entry for 'id'. If one exists, just
485 * modify the entry in-place (well, in the same position, since we
486 * actually return a copy); otherwise, insert the new entry in
489 /* find the first element not less than the element to be inserted */
490 for (dst = 0; dst < num && aclitemgt(mod_aip, old_aip + dst); ++dst)
493 if (dst < num && aclitemeq(mod_aip, old_aip + dst))
495 /* found a match, so modify existing item */
496 new_acl = makeacl(num);
497 new_aip = ACL_DAT(new_acl);
498 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
502 /* need to insert a new item */
503 new_acl = makeacl(num + 1);
504 new_aip = ACL_DAT(new_acl);
507 elog(ERROR, "aclinsert3: insertion before world ACL??");
511 memcpy((char *) new_aip,
513 num * sizeof(AclItem));
517 memcpy((char *) new_aip,
519 dst * sizeof(AclItem));
520 memcpy((char *) (new_aip + dst + 1),
521 (char *) (old_aip + dst),
522 (num - dst) * sizeof(AclItem));
524 /* initialize the new entry with no permissions */
525 new_aip[dst].ai_id = mod_aip->ai_id;
526 ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst], ACL_NO_RIGHTS,
527 ACLITEM_GET_IDTYPE(*mod_aip));
528 num++; /* set num to the size of new_acl */
531 /* apply the permissions mod */
534 case ACL_MODECHG_ADD:
535 new_aip[dst].ai_privs |= ACLITEM_GET_PRIVS(*mod_aip);
537 case ACL_MODECHG_DEL:
538 new_aip[dst].ai_privs &= ~ACLITEM_GET_PRIVS(*mod_aip);
540 case ACL_MODECHG_EQL:
541 ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst],
542 ACLITEM_GET_PRIVS(*mod_aip),
543 ACLITEM_GET_IDTYPE(new_aip[dst]));
548 * if the adjusted entry has no permissions, delete it from the list.
549 * For example, this helps in removing entries for users who no longer
550 * exist. EXCEPTION: never remove the world entry.
552 if (ACLITEM_GET_PRIVS(new_aip[dst]) == ACL_NO_RIGHTS && dst > 0)
554 memmove((char *) (new_aip + dst),
555 (char *) (new_aip + dst + 1),
556 (num - dst - 1) * sizeof(AclItem));
557 ARR_DIMS(new_acl)[0] = num - 1;
558 ARR_SIZE(new_acl) -= sizeof(AclItem);
565 * aclinsert (exported function)
568 aclinsert(PG_FUNCTION_ARGS)
570 Acl *old_acl = PG_GETARG_ACL_P(0);
571 AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
573 PG_RETURN_ACL_P(aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL));
577 aclremove(PG_FUNCTION_ARGS)
579 Acl *old_acl = PG_GETARG_ACL_P(0);
580 AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
588 /* These checks for null input should be dead code, but... */
589 if (!old_acl || ACL_NUM(old_acl) < 1)
590 old_acl = makeacl(1);
593 new_acl = makeacl(ACL_NUM(old_acl));
594 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
595 PG_RETURN_ACL_P(new_acl);
598 old_num = ACL_NUM(old_acl);
599 old_aip = ACL_DAT(old_acl);
601 /* Search for the matching entry */
602 for (dst = 0; dst < old_num && !aclitemeq(mod_aip, old_aip + dst); ++dst)
607 /* Not found, so return copy of source ACL */
608 new_acl = makeacl(old_num);
609 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
613 new_num = old_num - 1;
614 new_acl = makeacl(new_num);
615 new_aip = ACL_DAT(new_acl);
618 elog(ERROR, "aclremove: removal of the world ACL??");
620 else if (dst == old_num - 1)
622 memcpy((char *) new_aip,
624 new_num * sizeof(AclItem));
628 memcpy((char *) new_aip,
630 dst * sizeof(AclItem));
631 memcpy((char *) (new_aip + dst),
632 (char *) (old_aip + dst + 1),
633 (new_num - dst) * sizeof(AclItem));
637 PG_RETURN_ACL_P(new_acl);
641 aclcontains(PG_FUNCTION_ARGS)
643 Acl *acl = PG_GETARG_ACL_P(0);
644 AclItem *aip = PG_GETARG_ACLITEM_P(1);
650 aidat = ACL_DAT(acl);
651 for (i = 0; i < num; ++i)
653 if (aip->ai_id == aidat[i].ai_id &&
654 aip->ai_privs == aidat[i].ai_privs)
655 PG_RETURN_BOOL(true);
657 PG_RETURN_BOOL(false);
662 * has_table_privilege variants
663 * These are all named "has_table_privilege" at the SQL level.
664 * They take various combinations of relation name, relation OID,
665 * user name, user sysid, or implicit user = current_user.
667 * The result is a boolean value: true if user has the indicated
668 * privilege, false if not.
672 * has_table_privilege_name_name
673 * Check user privileges on a table given
674 * name username, text tablename, and text priv name.
677 has_table_privilege_name_name(PG_FUNCTION_ARGS)
679 Name username = PG_GETARG_NAME(0);
680 text *tablename = PG_GETARG_TEXT_P(1);
681 text *priv_type_text = PG_GETARG_TEXT_P(2);
687 usesysid = get_usesysid(NameStr(*username));
688 tableoid = convert_table_name(tablename);
689 mode = convert_table_priv_string(priv_type_text);
691 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
693 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
697 * has_table_privilege_name
698 * Check user privileges on a table given
699 * text tablename and text priv name.
700 * current_user is assumed
703 has_table_privilege_name(PG_FUNCTION_ARGS)
705 text *tablename = PG_GETARG_TEXT_P(0);
706 text *priv_type_text = PG_GETARG_TEXT_P(1);
712 usesysid = GetUserId();
713 tableoid = convert_table_name(tablename);
714 mode = convert_table_priv_string(priv_type_text);
716 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
718 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
722 * has_table_privilege_name_id
723 * Check user privileges on a table given
724 * name usename, table oid, and text priv name.
727 has_table_privilege_name_id(PG_FUNCTION_ARGS)
729 Name username = PG_GETARG_NAME(0);
730 Oid tableoid = PG_GETARG_OID(1);
731 text *priv_type_text = PG_GETARG_TEXT_P(2);
736 usesysid = get_usesysid(NameStr(*username));
737 mode = convert_table_priv_string(priv_type_text);
739 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
741 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
745 * has_table_privilege_id
746 * Check user privileges on a table given
747 * table oid, and text priv name.
748 * current_user is assumed
751 has_table_privilege_id(PG_FUNCTION_ARGS)
753 Oid tableoid = PG_GETARG_OID(0);
754 text *priv_type_text = PG_GETARG_TEXT_P(1);
759 usesysid = GetUserId();
760 mode = convert_table_priv_string(priv_type_text);
762 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
764 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
768 * has_table_privilege_id_name
769 * Check user privileges on a table given
770 * usesysid, text tablename, and text priv name.
773 has_table_privilege_id_name(PG_FUNCTION_ARGS)
775 int32 usesysid = PG_GETARG_INT32(0);
776 text *tablename = PG_GETARG_TEXT_P(1);
777 text *priv_type_text = PG_GETARG_TEXT_P(2);
782 tableoid = convert_table_name(tablename);
783 mode = convert_table_priv_string(priv_type_text);
785 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
787 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
791 * has_table_privilege_id_id
792 * Check user privileges on a table given
793 * usesysid, table oid, and text priv name.
796 has_table_privilege_id_id(PG_FUNCTION_ARGS)
798 int32 usesysid = PG_GETARG_INT32(0);
799 Oid tableoid = PG_GETARG_OID(1);
800 text *priv_type_text = PG_GETARG_TEXT_P(2);
804 mode = convert_table_priv_string(priv_type_text);
806 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
808 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
812 * Support routines for has_table_privilege family.
816 * Given a table name expressed as a string, look it up and return Oid
819 convert_table_name(text *tablename)
823 relrv = makeRangeVarFromNameList(textToQualifiedNameList(tablename,
824 "has_table_privilege"));
826 return RangeVarGetRelid(relrv, false);
830 * convert_table_priv_string
831 * Convert text string to AclMode value.
834 convert_table_priv_string(text *priv_type_text)
838 priv_type = DatumGetCString(DirectFunctionCall1(textout,
839 PointerGetDatum(priv_type_text)));
842 * Return mode from priv_type string
844 if (strcasecmp(priv_type, "SELECT") == 0)
847 if (strcasecmp(priv_type, "INSERT") == 0)
850 if (strcasecmp(priv_type, "UPDATE") == 0)
853 if (strcasecmp(priv_type, "DELETE") == 0)
856 if (strcasecmp(priv_type, "RULE") == 0)
859 if (strcasecmp(priv_type, "REFERENCES") == 0)
860 return ACL_REFERENCES;
862 if (strcasecmp(priv_type, "TRIGGER") == 0)
865 elog(ERROR, "has_table_privilege: invalid privilege type %s",
867 return ACL_NO_RIGHTS; /* keep compiler quiet */
872 * has_database_privilege variants
873 * These are all named "has_database_privilege" at the SQL level.
874 * They take various combinations of database name, database OID,
875 * user name, user sysid, or implicit user = current_user.
877 * The result is a boolean value: true if user has the indicated
878 * privilege, false if not.
882 * has_database_privilege_name_name
883 * Check user privileges on a database given
884 * name username, text databasename, and text priv name.
887 has_database_privilege_name_name(PG_FUNCTION_ARGS)
889 Name username = PG_GETARG_NAME(0);
890 text *databasename = PG_GETARG_TEXT_P(1);
891 text *priv_type_text = PG_GETARG_TEXT_P(2);
897 usesysid = get_usesysid(NameStr(*username));
898 databaseoid = convert_database_name(databasename);
899 mode = convert_database_priv_string(priv_type_text);
901 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
903 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
907 * has_database_privilege_name
908 * Check user privileges on a database given
909 * text databasename and text priv name.
910 * current_user is assumed
913 has_database_privilege_name(PG_FUNCTION_ARGS)
915 text *databasename = PG_GETARG_TEXT_P(0);
916 text *priv_type_text = PG_GETARG_TEXT_P(1);
922 usesysid = GetUserId();
923 databaseoid = convert_database_name(databasename);
924 mode = convert_database_priv_string(priv_type_text);
926 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
928 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
932 * has_database_privilege_name_id
933 * Check user privileges on a database given
934 * name usename, database oid, and text priv name.
937 has_database_privilege_name_id(PG_FUNCTION_ARGS)
939 Name username = PG_GETARG_NAME(0);
940 Oid databaseoid = PG_GETARG_OID(1);
941 text *priv_type_text = PG_GETARG_TEXT_P(2);
946 usesysid = get_usesysid(NameStr(*username));
947 mode = convert_database_priv_string(priv_type_text);
949 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
951 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
955 * has_database_privilege_id
956 * Check user privileges on a database given
957 * database oid, and text priv name.
958 * current_user is assumed
961 has_database_privilege_id(PG_FUNCTION_ARGS)
963 Oid databaseoid = PG_GETARG_OID(0);
964 text *priv_type_text = PG_GETARG_TEXT_P(1);
969 usesysid = GetUserId();
970 mode = convert_database_priv_string(priv_type_text);
972 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
974 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
978 * has_database_privilege_id_name
979 * Check user privileges on a database given
980 * usesysid, text databasename, and text priv name.
983 has_database_privilege_id_name(PG_FUNCTION_ARGS)
985 int32 usesysid = PG_GETARG_INT32(0);
986 text *databasename = PG_GETARG_TEXT_P(1);
987 text *priv_type_text = PG_GETARG_TEXT_P(2);
992 databaseoid = convert_database_name(databasename);
993 mode = convert_database_priv_string(priv_type_text);
995 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
997 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1001 * has_database_privilege_id_id
1002 * Check user privileges on a database given
1003 * usesysid, database oid, and text priv name.
1006 has_database_privilege_id_id(PG_FUNCTION_ARGS)
1008 int32 usesysid = PG_GETARG_INT32(0);
1009 Oid databaseoid = PG_GETARG_OID(1);
1010 text *priv_type_text = PG_GETARG_TEXT_P(2);
1012 AclResult aclresult;
1014 mode = convert_database_priv_string(priv_type_text);
1016 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1018 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1022 * Support routines for has_database_privilege family.
1026 * Given a database name expressed as a string, look it up and return Oid
1029 convert_database_name(text *databasename)
1034 dbname = DatumGetCString(DirectFunctionCall1(textout,
1035 PointerGetDatum(databasename)));
1037 oid = get_database_oid(dbname);
1038 if (!OidIsValid(oid))
1039 elog(ERROR, "database \"%s\" does not exist", dbname);
1045 * convert_database_priv_string
1046 * Convert text string to AclMode value.
1049 convert_database_priv_string(text *priv_type_text)
1053 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1054 PointerGetDatum(priv_type_text)));
1057 * Return mode from priv_type string
1059 if (strcasecmp(priv_type, "CREATE") == 0)
1062 if (strcasecmp(priv_type, "TEMPORARY") == 0)
1063 return ACL_CREATE_TEMP;
1065 if (strcasecmp(priv_type, "TEMP") == 0)
1066 return ACL_CREATE_TEMP;
1068 elog(ERROR, "has_database_privilege: invalid privilege type %s",
1070 return ACL_NO_RIGHTS; /* keep compiler quiet */
1075 * has_function_privilege variants
1076 * These are all named "has_function_privilege" at the SQL level.
1077 * They take various combinations of function name, function OID,
1078 * user name, user sysid, or implicit user = current_user.
1080 * The result is a boolean value: true if user has the indicated
1081 * privilege, false if not.
1085 * has_function_privilege_name_name
1086 * Check user privileges on a function given
1087 * name username, text functionname, and text priv name.
1090 has_function_privilege_name_name(PG_FUNCTION_ARGS)
1092 Name username = PG_GETARG_NAME(0);
1093 text *functionname = PG_GETARG_TEXT_P(1);
1094 text *priv_type_text = PG_GETARG_TEXT_P(2);
1098 AclResult aclresult;
1100 usesysid = get_usesysid(NameStr(*username));
1101 functionoid = convert_function_name(functionname);
1102 mode = convert_function_priv_string(priv_type_text);
1104 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1106 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1110 * has_function_privilege_name
1111 * Check user privileges on a function given
1112 * text functionname and text priv name.
1113 * current_user is assumed
1116 has_function_privilege_name(PG_FUNCTION_ARGS)
1118 text *functionname = PG_GETARG_TEXT_P(0);
1119 text *priv_type_text = PG_GETARG_TEXT_P(1);
1123 AclResult aclresult;
1125 usesysid = GetUserId();
1126 functionoid = convert_function_name(functionname);
1127 mode = convert_function_priv_string(priv_type_text);
1129 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1131 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1135 * has_function_privilege_name_id
1136 * Check user privileges on a function given
1137 * name usename, function oid, and text priv name.
1140 has_function_privilege_name_id(PG_FUNCTION_ARGS)
1142 Name username = PG_GETARG_NAME(0);
1143 Oid functionoid = PG_GETARG_OID(1);
1144 text *priv_type_text = PG_GETARG_TEXT_P(2);
1147 AclResult aclresult;
1149 usesysid = get_usesysid(NameStr(*username));
1150 mode = convert_function_priv_string(priv_type_text);
1152 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1154 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1158 * has_function_privilege_id
1159 * Check user privileges on a function given
1160 * function oid, and text priv name.
1161 * current_user is assumed
1164 has_function_privilege_id(PG_FUNCTION_ARGS)
1166 Oid functionoid = PG_GETARG_OID(0);
1167 text *priv_type_text = PG_GETARG_TEXT_P(1);
1170 AclResult aclresult;
1172 usesysid = GetUserId();
1173 mode = convert_function_priv_string(priv_type_text);
1175 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1177 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1181 * has_function_privilege_id_name
1182 * Check user privileges on a function given
1183 * usesysid, text functionname, and text priv name.
1186 has_function_privilege_id_name(PG_FUNCTION_ARGS)
1188 int32 usesysid = PG_GETARG_INT32(0);
1189 text *functionname = PG_GETARG_TEXT_P(1);
1190 text *priv_type_text = PG_GETARG_TEXT_P(2);
1193 AclResult aclresult;
1195 functionoid = convert_function_name(functionname);
1196 mode = convert_function_priv_string(priv_type_text);
1198 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1200 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1204 * has_function_privilege_id_id
1205 * Check user privileges on a function given
1206 * usesysid, function oid, and text priv name.
1209 has_function_privilege_id_id(PG_FUNCTION_ARGS)
1211 int32 usesysid = PG_GETARG_INT32(0);
1212 Oid functionoid = PG_GETARG_OID(1);
1213 text *priv_type_text = PG_GETARG_TEXT_P(2);
1215 AclResult aclresult;
1217 mode = convert_function_priv_string(priv_type_text);
1219 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1221 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1225 * Support routines for has_function_privilege family.
1229 * Given a function name expressed as a string, look it up and return Oid
1232 convert_function_name(text *functionname)
1237 funcname = DatumGetCString(DirectFunctionCall1(textout,
1238 PointerGetDatum(functionname)));
1240 oid = DatumGetObjectId(DirectFunctionCall1(regprocedurein,
1241 CStringGetDatum(funcname)));
1243 if (!OidIsValid(oid))
1244 elog(ERROR, "function \"%s\" does not exist", funcname);
1250 * convert_function_priv_string
1251 * Convert text string to AclMode value.
1254 convert_function_priv_string(text *priv_type_text)
1258 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1259 PointerGetDatum(priv_type_text)));
1262 * Return mode from priv_type string
1264 if (strcasecmp(priv_type, "EXECUTE") == 0)
1267 elog(ERROR, "has_function_privilege: invalid privilege type %s",
1269 return ACL_NO_RIGHTS; /* keep compiler quiet */
1274 * has_language_privilege variants
1275 * These are all named "has_language_privilege" at the SQL level.
1276 * They take various combinations of language name, language OID,
1277 * user name, user sysid, or implicit user = current_user.
1279 * The result is a boolean value: true if user has the indicated
1280 * privilege, false if not.
1284 * has_language_privilege_name_name
1285 * Check user privileges on a language given
1286 * name username, text languagename, and text priv name.
1289 has_language_privilege_name_name(PG_FUNCTION_ARGS)
1291 Name username = PG_GETARG_NAME(0);
1292 text *languagename = PG_GETARG_TEXT_P(1);
1293 text *priv_type_text = PG_GETARG_TEXT_P(2);
1297 AclResult aclresult;
1299 usesysid = get_usesysid(NameStr(*username));
1300 languageoid = convert_language_name(languagename);
1301 mode = convert_language_priv_string(priv_type_text);
1303 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1305 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1309 * has_language_privilege_name
1310 * Check user privileges on a language given
1311 * text languagename and text priv name.
1312 * current_user is assumed
1315 has_language_privilege_name(PG_FUNCTION_ARGS)
1317 text *languagename = PG_GETARG_TEXT_P(0);
1318 text *priv_type_text = PG_GETARG_TEXT_P(1);
1322 AclResult aclresult;
1324 usesysid = GetUserId();
1325 languageoid = convert_language_name(languagename);
1326 mode = convert_language_priv_string(priv_type_text);
1328 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1330 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1334 * has_language_privilege_name_id
1335 * Check user privileges on a language given
1336 * name usename, language oid, and text priv name.
1339 has_language_privilege_name_id(PG_FUNCTION_ARGS)
1341 Name username = PG_GETARG_NAME(0);
1342 Oid languageoid = PG_GETARG_OID(1);
1343 text *priv_type_text = PG_GETARG_TEXT_P(2);
1346 AclResult aclresult;
1348 usesysid = get_usesysid(NameStr(*username));
1349 mode = convert_language_priv_string(priv_type_text);
1351 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1353 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1357 * has_language_privilege_id
1358 * Check user privileges on a language given
1359 * language oid, and text priv name.
1360 * current_user is assumed
1363 has_language_privilege_id(PG_FUNCTION_ARGS)
1365 Oid languageoid = PG_GETARG_OID(0);
1366 text *priv_type_text = PG_GETARG_TEXT_P(1);
1369 AclResult aclresult;
1371 usesysid = GetUserId();
1372 mode = convert_language_priv_string(priv_type_text);
1374 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1376 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1380 * has_language_privilege_id_name
1381 * Check user privileges on a language given
1382 * usesysid, text languagename, and text priv name.
1385 has_language_privilege_id_name(PG_FUNCTION_ARGS)
1387 int32 usesysid = PG_GETARG_INT32(0);
1388 text *languagename = PG_GETARG_TEXT_P(1);
1389 text *priv_type_text = PG_GETARG_TEXT_P(2);
1392 AclResult aclresult;
1394 languageoid = convert_language_name(languagename);
1395 mode = convert_language_priv_string(priv_type_text);
1397 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1399 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1403 * has_language_privilege_id_id
1404 * Check user privileges on a language given
1405 * usesysid, language oid, and text priv name.
1408 has_language_privilege_id_id(PG_FUNCTION_ARGS)
1410 int32 usesysid = PG_GETARG_INT32(0);
1411 Oid languageoid = PG_GETARG_OID(1);
1412 text *priv_type_text = PG_GETARG_TEXT_P(2);
1414 AclResult aclresult;
1416 mode = convert_language_priv_string(priv_type_text);
1418 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1420 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1424 * Support routines for has_language_privilege family.
1428 * Given a language name expressed as a string, look it up and return Oid
1431 convert_language_name(text *languagename)
1436 langname = DatumGetCString(DirectFunctionCall1(textout,
1437 PointerGetDatum(languagename)));
1439 oid = GetSysCacheOid(LANGNAME,
1440 CStringGetDatum(langname),
1442 if (!OidIsValid(oid))
1443 elog(ERROR, "language \"%s\" does not exist", langname);
1449 * convert_language_priv_string
1450 * Convert text string to AclMode value.
1453 convert_language_priv_string(text *priv_type_text)
1457 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1458 PointerGetDatum(priv_type_text)));
1461 * Return mode from priv_type string
1463 if (strcasecmp(priv_type, "USAGE") == 0)
1466 elog(ERROR, "has_language_privilege: invalid privilege type %s",
1468 return ACL_NO_RIGHTS; /* keep compiler quiet */
1473 * has_schema_privilege variants
1474 * These are all named "has_schema_privilege" at the SQL level.
1475 * They take various combinations of schema name, schema OID,
1476 * user name, user sysid, or implicit user = current_user.
1478 * The result is a boolean value: true if user has the indicated
1479 * privilege, false if not.
1483 * has_schema_privilege_name_name
1484 * Check user privileges on a schema given
1485 * name username, text schemaname, and text priv name.
1488 has_schema_privilege_name_name(PG_FUNCTION_ARGS)
1490 Name username = PG_GETARG_NAME(0);
1491 text *schemaname = PG_GETARG_TEXT_P(1);
1492 text *priv_type_text = PG_GETARG_TEXT_P(2);
1496 AclResult aclresult;
1498 usesysid = get_usesysid(NameStr(*username));
1499 schemaoid = convert_schema_name(schemaname);
1500 mode = convert_schema_priv_string(priv_type_text);
1502 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1504 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1508 * has_schema_privilege_name
1509 * Check user privileges on a schema given
1510 * text schemaname and text priv name.
1511 * current_user is assumed
1514 has_schema_privilege_name(PG_FUNCTION_ARGS)
1516 text *schemaname = PG_GETARG_TEXT_P(0);
1517 text *priv_type_text = PG_GETARG_TEXT_P(1);
1521 AclResult aclresult;
1523 usesysid = GetUserId();
1524 schemaoid = convert_schema_name(schemaname);
1525 mode = convert_schema_priv_string(priv_type_text);
1527 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1529 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1533 * has_schema_privilege_name_id
1534 * Check user privileges on a schema given
1535 * name usename, schema oid, and text priv name.
1538 has_schema_privilege_name_id(PG_FUNCTION_ARGS)
1540 Name username = PG_GETARG_NAME(0);
1541 Oid schemaoid = PG_GETARG_OID(1);
1542 text *priv_type_text = PG_GETARG_TEXT_P(2);
1545 AclResult aclresult;
1547 usesysid = get_usesysid(NameStr(*username));
1548 mode = convert_schema_priv_string(priv_type_text);
1550 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1552 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1556 * has_schema_privilege_id
1557 * Check user privileges on a schema given
1558 * schema oid, and text priv name.
1559 * current_user is assumed
1562 has_schema_privilege_id(PG_FUNCTION_ARGS)
1564 Oid schemaoid = PG_GETARG_OID(0);
1565 text *priv_type_text = PG_GETARG_TEXT_P(1);
1568 AclResult aclresult;
1570 usesysid = GetUserId();
1571 mode = convert_schema_priv_string(priv_type_text);
1573 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1575 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1579 * has_schema_privilege_id_name
1580 * Check user privileges on a schema given
1581 * usesysid, text schemaname, and text priv name.
1584 has_schema_privilege_id_name(PG_FUNCTION_ARGS)
1586 int32 usesysid = PG_GETARG_INT32(0);
1587 text *schemaname = PG_GETARG_TEXT_P(1);
1588 text *priv_type_text = PG_GETARG_TEXT_P(2);
1591 AclResult aclresult;
1593 schemaoid = convert_schema_name(schemaname);
1594 mode = convert_schema_priv_string(priv_type_text);
1596 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1598 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1602 * has_schema_privilege_id_id
1603 * Check user privileges on a schema given
1604 * usesysid, schema oid, and text priv name.
1607 has_schema_privilege_id_id(PG_FUNCTION_ARGS)
1609 int32 usesysid = PG_GETARG_INT32(0);
1610 Oid schemaoid = PG_GETARG_OID(1);
1611 text *priv_type_text = PG_GETARG_TEXT_P(2);
1613 AclResult aclresult;
1615 mode = convert_schema_priv_string(priv_type_text);
1617 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1619 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1623 * Support routines for has_schema_privilege family.
1627 * Given a schema name expressed as a string, look it up and return Oid
1630 convert_schema_name(text *schemaname)
1635 nspname = DatumGetCString(DirectFunctionCall1(textout,
1636 PointerGetDatum(schemaname)));
1638 oid = GetSysCacheOid(NAMESPACENAME,
1639 CStringGetDatum(nspname),
1641 if (!OidIsValid(oid))
1642 elog(ERROR, "schema \"%s\" does not exist", nspname);
1648 * convert_schema_priv_string
1649 * Convert text string to AclMode value.
1652 convert_schema_priv_string(text *priv_type_text)
1656 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1657 PointerGetDatum(priv_type_text)));
1660 * Return mode from priv_type string
1662 if (strcasecmp(priv_type, "CREATE") == 0)
1665 if (strcasecmp(priv_type, "USAGE") == 0)
1668 elog(ERROR, "has_schema_privilege: invalid privilege type %s",
1670 return ACL_NO_RIGHTS; /* keep compiler quiet */