PostgreSQL Source Code  git master
acl.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * acl.c
4  * Basic access control list data structures manipulation routines.
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/utils/adt/acl.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include <ctype.h>
18 
19 #include "access/htup_details.h"
20 #include "catalog/catalog.h"
21 #include "catalog/namespace.h"
23 #include "catalog/pg_authid.h"
24 #include "catalog/pg_class.h"
25 #include "catalog/pg_database.h"
26 #include "catalog/pg_type.h"
27 #include "commands/dbcommands.h"
28 #include "commands/proclang.h"
29 #include "commands/tablespace.h"
30 #include "common/hashfn.h"
31 #include "foreign/foreign.h"
32 #include "funcapi.h"
33 #include "lib/qunique.h"
34 #include "miscadmin.h"
35 #include "utils/acl.h"
36 #include "utils/array.h"
37 #include "utils/builtins.h"
38 #include "utils/catcache.h"
39 #include "utils/inval.h"
40 #include "utils/lsyscache.h"
41 #include "utils/memutils.h"
42 #include "utils/syscache.h"
43 #include "utils/varlena.h"
44 
45 typedef struct
46 {
47  const char *name;
49 } priv_map;
50 
51 /*
52  * We frequently need to test whether a given role is a member of some other
53  * role. In most of these tests the "given role" is the same, namely the
54  * active current user. So we can optimize it by keeping cached lists of all
55  * the roles the "given role" is a member of, directly or indirectly.
56  *
57  * Possibly this mechanism should be generalized to allow caching membership
58  * info for multiple roles?
59  *
60  * Each element of cached_roles is an OID list of constituent roles for the
61  * corresponding element of cached_role (always including the cached_role
62  * itself). One cache has ROLERECURSE_PRIVS semantics, and the other has
63  * ROLERECURSE_MEMBERS semantics.
64  */
66 {
67  ROLERECURSE_PRIVS = 0, /* recurse if rolinherit */
68  ROLERECURSE_MEMBERS = 1 /* recurse unconditionally */
69 };
71 static List *cached_roles[] = {NIL, NIL};
73 
74 
75 static const char *getid(const char *s, char *n);
76 static void putid(char *p, const char *s);
77 static Acl *allocacl(int n);
78 static void check_acl(const Acl *acl);
79 static const char *aclparse(const char *s, AclItem *aip);
80 static bool aclitem_match(const AclItem *a1, const AclItem *a2);
81 static int aclitemComparator(const void *arg1, const void *arg2);
82 static void check_circularity(const Acl *old_acl, const AclItem *mod_aip,
83  Oid ownerId);
84 static Acl *recursive_revoke(Acl *acl, Oid grantee, AclMode revoke_privs,
85  Oid ownerId, DropBehavior behavior);
86 
87 static AclMode convert_priv_string(text *priv_type_text);
88 static AclMode convert_any_priv_string(text *priv_type_text,
89  const priv_map *privileges);
90 
91 static Oid convert_table_name(text *tablename);
92 static AclMode convert_table_priv_string(text *priv_type_text);
93 static AclMode convert_sequence_priv_string(text *priv_type_text);
94 static AttrNumber convert_column_name(Oid tableoid, text *column);
95 static AclMode convert_column_priv_string(text *priv_type_text);
96 static Oid convert_database_name(text *databasename);
97 static AclMode convert_database_priv_string(text *priv_type_text);
100 static Oid convert_function_name(text *functionname);
101 static AclMode convert_function_priv_string(text *priv_type_text);
102 static Oid convert_language_name(text *languagename);
103 static AclMode convert_language_priv_string(text *priv_type_text);
104 static Oid convert_schema_name(text *schemaname);
105 static AclMode convert_schema_priv_string(text *priv_type_text);
106 static Oid convert_server_name(text *servername);
107 static AclMode convert_server_priv_string(text *priv_type_text);
108 static Oid convert_tablespace_name(text *tablespacename);
109 static AclMode convert_tablespace_priv_string(text *priv_type_text);
110 static Oid convert_type_name(text *typename);
111 static AclMode convert_type_priv_string(text *priv_type_text);
112 static AclMode convert_role_priv_string(text *priv_type_text);
113 static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode);
114 
115 static void RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue);
116 
117 
118 /*
119  * getid
120  * Consumes the first alphanumeric string (identifier) found in string
121  * 's', ignoring any leading white space. If it finds a double quote
122  * it returns the word inside the quotes.
123  *
124  * RETURNS:
125  * the string position in 's' that points to the next non-space character
126  * in 's', after any quotes. Also:
127  * - loads the identifier into 'n'. (If no identifier is found, 'n'
128  * contains an empty string.) 'n' must be NAMEDATALEN bytes.
129  */
130 static const char *
131 getid(const char *s, char *n)
132 {
133  int len = 0;
134  bool in_quotes = false;
135 
136  Assert(s && n);
137 
138  while (isspace((unsigned char) *s))
139  s++;
140  /* This code had better match what putid() does, below */
141  for (;
142  *s != '\0' &&
143  (isalnum((unsigned char) *s) ||
144  *s == '_' ||
145  *s == '"' ||
146  in_quotes);
147  s++)
148  {
149  if (*s == '"')
150  {
151  /* safe to look at next char (could be '\0' though) */
152  if (*(s + 1) != '"')
153  {
154  in_quotes = !in_quotes;
155  continue;
156  }
157  /* it's an escaped double quote; skip the escaping char */
158  s++;
159  }
160 
161  /* Add the character to the string */
162  if (len >= NAMEDATALEN - 1)
163  ereport(ERROR,
164  (errcode(ERRCODE_NAME_TOO_LONG),
165  errmsg("identifier too long"),
166  errdetail("Identifier must be less than %d characters.",
167  NAMEDATALEN)));
168 
169  n[len++] = *s;
170  }
171  n[len] = '\0';
172  while (isspace((unsigned char) *s))
173  s++;
174  return s;
175 }
176 
177 /*
178  * Write a role name at *p, adding double quotes if needed.
179  * There must be at least (2*NAMEDATALEN)+2 bytes available at *p.
180  * This needs to be kept in sync with copyAclUserName in pg_dump/dumputils.c
181  */
182 static void
183 putid(char *p, const char *s)
184 {
185  const char *src;
186  bool safe = true;
187 
188  for (src = s; *src; src++)
189  {
190  /* This test had better match what getid() does, above */
191  if (!isalnum((unsigned char) *src) && *src != '_')
192  {
193  safe = false;
194  break;
195  }
196  }
197  if (!safe)
198  *p++ = '"';
199  for (src = s; *src; src++)
200  {
201  /* A double quote character in a username is encoded as "" */
202  if (*src == '"')
203  *p++ = '"';
204  *p++ = *src;
205  }
206  if (!safe)
207  *p++ = '"';
208  *p = '\0';
209 }
210 
211 /*
212  * aclparse
213  * Consumes and parses an ACL specification of the form:
214  * [group|user] [A-Za-z0-9]*=[rwaR]*
215  * from string 's', ignoring any leading white space or white space
216  * between the optional id type keyword (group|user) and the actual
217  * ACL specification.
218  *
219  * The group|user decoration is unnecessary in the roles world,
220  * but we still accept it for backward compatibility.
221  *
222  * This routine is called by the parser as well as aclitemin(), hence
223  * the added generality.
224  *
225  * RETURNS:
226  * the string position in 's' immediately following the ACL
227  * specification. Also:
228  * - loads the structure pointed to by 'aip' with the appropriate
229  * UID/GID, id type identifier and mode type values.
230  */
231 static const char *
232 aclparse(const char *s, AclItem *aip)
233 {
234  AclMode privs,
235  goption,
236  read;
237  char name[NAMEDATALEN];
238  char name2[NAMEDATALEN];
239 
240  Assert(s && aip);
241 
242  s = getid(s, name);
243  if (*s != '=')
244  {
245  /* we just read a keyword, not a name */
246  if (strcmp(name, "group") != 0 && strcmp(name, "user") != 0)
247  ereport(ERROR,
248  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
249  errmsg("unrecognized key word: \"%s\"", name),
250  errhint("ACL key word must be \"group\" or \"user\".")));
251  s = getid(s, name); /* move s to the name beyond the keyword */
252  if (name[0] == '\0')
253  ereport(ERROR,
254  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
255  errmsg("missing name"),
256  errhint("A name must follow the \"group\" or \"user\" key word.")));
257  }
258 
259  if (*s != '=')
260  ereport(ERROR,
261  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
262  errmsg("missing \"=\" sign")));
263 
264  privs = goption = ACL_NO_RIGHTS;
265 
266  for (++s, read = 0; isalpha((unsigned char) *s) || *s == '*'; s++)
267  {
268  switch (*s)
269  {
270  case '*':
271  goption |= read;
272  break;
273  case ACL_INSERT_CHR:
274  read = ACL_INSERT;
275  break;
276  case ACL_SELECT_CHR:
277  read = ACL_SELECT;
278  break;
279  case ACL_UPDATE_CHR:
280  read = ACL_UPDATE;
281  break;
282  case ACL_DELETE_CHR:
283  read = ACL_DELETE;
284  break;
285  case ACL_TRUNCATE_CHR:
286  read = ACL_TRUNCATE;
287  break;
288  case ACL_REFERENCES_CHR:
289  read = ACL_REFERENCES;
290  break;
291  case ACL_TRIGGER_CHR:
292  read = ACL_TRIGGER;
293  break;
294  case ACL_EXECUTE_CHR:
295  read = ACL_EXECUTE;
296  break;
297  case ACL_USAGE_CHR:
298  read = ACL_USAGE;
299  break;
300  case ACL_CREATE_CHR:
301  read = ACL_CREATE;
302  break;
303  case ACL_CREATE_TEMP_CHR:
304  read = ACL_CREATE_TEMP;
305  break;
306  case ACL_CONNECT_CHR:
307  read = ACL_CONNECT;
308  break;
309  case 'R': /* ignore old RULE privileges */
310  read = 0;
311  break;
312  default:
313  ereport(ERROR,
314  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
315  errmsg("invalid mode character: must be one of \"%s\"",
317  }
318 
319  privs |= read;
320  }
321 
322  if (name[0] == '\0')
323  aip->ai_grantee = ACL_ID_PUBLIC;
324  else
325  aip->ai_grantee = get_role_oid(name, false);
326 
327  /*
328  * XXX Allow a degree of backward compatibility by defaulting the grantor
329  * to the superuser.
330  */
331  if (*s == '/')
332  {
333  s = getid(s + 1, name2);
334  if (name2[0] == '\0')
335  ereport(ERROR,
336  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
337  errmsg("a name must follow the \"/\" sign")));
338  aip->ai_grantor = get_role_oid(name2, false);
339  }
340  else
341  {
342  aip->ai_grantor = BOOTSTRAP_SUPERUSERID;
344  (errcode(ERRCODE_INVALID_GRANTOR),
345  errmsg("defaulting grantor to user ID %u",
346  BOOTSTRAP_SUPERUSERID)));
347  }
348 
349  ACLITEM_SET_PRIVS_GOPTIONS(*aip, privs, goption);
350 
351  return s;
352 }
353 
354 /*
355  * allocacl
356  * Allocates storage for a new Acl with 'n' entries.
357  *
358  * RETURNS:
359  * the new Acl
360  */
361 static Acl *
362 allocacl(int n)
363 {
364  Acl *new_acl;
365  Size size;
366 
367  if (n < 0)
368  elog(ERROR, "invalid size: %d", n);
369  size = ACL_N_SIZE(n);
370  new_acl = (Acl *) palloc0(size);
371  SET_VARSIZE(new_acl, size);
372  new_acl->ndim = 1;
373  new_acl->dataoffset = 0; /* we never put in any nulls */
374  new_acl->elemtype = ACLITEMOID;
375  ARR_LBOUND(new_acl)[0] = 1;
376  ARR_DIMS(new_acl)[0] = n;
377  return new_acl;
378 }
379 
380 /*
381  * Create a zero-entry ACL
382  */
383 Acl *
385 {
386  return allocacl(0);
387 }
388 
389 /*
390  * Copy an ACL
391  */
392 Acl *
393 aclcopy(const Acl *orig_acl)
394 {
395  Acl *result_acl;
396 
397  result_acl = allocacl(ACL_NUM(orig_acl));
398 
399  memcpy(ACL_DAT(result_acl),
400  ACL_DAT(orig_acl),
401  ACL_NUM(orig_acl) * sizeof(AclItem));
402 
403  return result_acl;
404 }
405 
406 /*
407  * Concatenate two ACLs
408  *
409  * This is a bit cheesy, since we may produce an ACL with redundant entries.
410  * Be careful what the result is used for!
411  */
412 Acl *
413 aclconcat(const Acl *left_acl, const Acl *right_acl)
414 {
415  Acl *result_acl;
416 
417  result_acl = allocacl(ACL_NUM(left_acl) + ACL_NUM(right_acl));
418 
419  memcpy(ACL_DAT(result_acl),
420  ACL_DAT(left_acl),
421  ACL_NUM(left_acl) * sizeof(AclItem));
422 
423  memcpy(ACL_DAT(result_acl) + ACL_NUM(left_acl),
424  ACL_DAT(right_acl),
425  ACL_NUM(right_acl) * sizeof(AclItem));
426 
427  return result_acl;
428 }
429 
430 /*
431  * Merge two ACLs
432  *
433  * This produces a properly merged ACL with no redundant entries.
434  * Returns NULL on NULL input.
435  */
436 Acl *
437 aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
438 {
439  Acl *result_acl;
440  AclItem *aip;
441  int i,
442  num;
443 
444  /* Check for cases where one or both are empty/null */
445  if (left_acl == NULL || ACL_NUM(left_acl) == 0)
446  {
447  if (right_acl == NULL || ACL_NUM(right_acl) == 0)
448  return NULL;
449  else
450  return aclcopy(right_acl);
451  }
452  else
453  {
454  if (right_acl == NULL || ACL_NUM(right_acl) == 0)
455  return aclcopy(left_acl);
456  }
457 
458  /* Merge them the hard way, one item at a time */
459  result_acl = aclcopy(left_acl);
460 
461  aip = ACL_DAT(right_acl);
462  num = ACL_NUM(right_acl);
463 
464  for (i = 0; i < num; i++, aip++)
465  {
466  Acl *tmp_acl;
467 
468  tmp_acl = aclupdate(result_acl, aip, ACL_MODECHG_ADD,
469  ownerId, DROP_RESTRICT);
470  pfree(result_acl);
471  result_acl = tmp_acl;
472  }
473 
474  return result_acl;
475 }
476 
477 /*
478  * Sort the items in an ACL (into an arbitrary but consistent order)
479  */
480 void
482 {
483  if (acl != NULL && ACL_NUM(acl) > 1)
484  qsort(ACL_DAT(acl), ACL_NUM(acl), sizeof(AclItem), aclitemComparator);
485 }
486 
487 /*
488  * Check if two ACLs are exactly equal
489  *
490  * This will not detect equality if the two arrays contain the same items
491  * in different orders. To handle that case, sort both inputs first,
492  * using aclitemsort().
493  */
494 bool
495 aclequal(const Acl *left_acl, const Acl *right_acl)
496 {
497  /* Check for cases where one or both are empty/null */
498  if (left_acl == NULL || ACL_NUM(left_acl) == 0)
499  {
500  if (right_acl == NULL || ACL_NUM(right_acl) == 0)
501  return true;
502  else
503  return false;
504  }
505  else
506  {
507  if (right_acl == NULL || ACL_NUM(right_acl) == 0)
508  return false;
509  }
510 
511  if (ACL_NUM(left_acl) != ACL_NUM(right_acl))
512  return false;
513 
514  if (memcmp(ACL_DAT(left_acl),
515  ACL_DAT(right_acl),
516  ACL_NUM(left_acl) * sizeof(AclItem)) == 0)
517  return true;
518 
519  return false;
520 }
521 
522 /*
523  * Verify that an ACL array is acceptable (one-dimensional and has no nulls)
524  */
525 static void
526 check_acl(const Acl *acl)
527 {
528  if (ARR_ELEMTYPE(acl) != ACLITEMOID)
529  ereport(ERROR,
530  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
531  errmsg("ACL array contains wrong data type")));
532  if (ARR_NDIM(acl) != 1)
533  ereport(ERROR,
534  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
535  errmsg("ACL arrays must be one-dimensional")));
536  if (ARR_HASNULL(acl))
537  ereport(ERROR,
538  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
539  errmsg("ACL arrays must not contain null values")));
540 }
541 
542 /*
543  * aclitemin
544  * Allocates storage for, and fills in, a new AclItem given a string
545  * 's' that contains an ACL specification. See aclparse for details.
546  *
547  * RETURNS:
548  * the new AclItem
549  */
550 Datum
552 {
553  const char *s = PG_GETARG_CSTRING(0);
554  AclItem *aip;
555 
556  aip = (AclItem *) palloc(sizeof(AclItem));
557  s = aclparse(s, aip);
558  while (isspace((unsigned char) *s))
559  ++s;
560  if (*s)
561  ereport(ERROR,
562  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
563  errmsg("extra garbage at the end of the ACL specification")));
564 
565  PG_RETURN_ACLITEM_P(aip);
566 }
567 
568 /*
569  * aclitemout
570  * Allocates storage for, and fills in, a new null-delimited string
571  * containing a formatted ACL specification. See aclparse for details.
572  *
573  * RETURNS:
574  * the new string
575  */
576 Datum
578 {
579  AclItem *aip = PG_GETARG_ACLITEM_P(0);
580  char *p;
581  char *out;
582  HeapTuple htup;
583  unsigned i;
584 
585  out = palloc(strlen("=/") +
586  2 * N_ACL_RIGHTS +
587  2 * (2 * NAMEDATALEN + 2) +
588  1);
589 
590  p = out;
591  *p = '\0';
592 
593  if (aip->ai_grantee != ACL_ID_PUBLIC)
594  {
596  if (HeapTupleIsValid(htup))
597  {
598  putid(p, NameStr(((Form_pg_authid) GETSTRUCT(htup))->rolname));
599  ReleaseSysCache(htup);
600  }
601  else
602  {
603  /* Generate numeric OID if we don't find an entry */
604  sprintf(p, "%u", aip->ai_grantee);
605  }
606  }
607  while (*p)
608  ++p;
609 
610  *p++ = '=';
611 
612  for (i = 0; i < N_ACL_RIGHTS; ++i)
613  {
614  if (ACLITEM_GET_PRIVS(*aip) & (1 << i))
615  *p++ = ACL_ALL_RIGHTS_STR[i];
616  if (ACLITEM_GET_GOPTIONS(*aip) & (1 << i))
617  *p++ = '*';
618  }
619 
620  *p++ = '/';
621  *p = '\0';
622 
624  if (HeapTupleIsValid(htup))
625  {
626  putid(p, NameStr(((Form_pg_authid) GETSTRUCT(htup))->rolname));
627  ReleaseSysCache(htup);
628  }
629  else
630  {
631  /* Generate numeric OID if we don't find an entry */
632  sprintf(p, "%u", aip->ai_grantor);
633  }
634 
635  PG_RETURN_CSTRING(out);
636 }
637 
638 /*
639  * aclitem_match
640  * Two AclItems are considered to match iff they have the same
641  * grantee and grantor; the privileges are ignored.
642  */
643 static bool
645 {
646  return a1->ai_grantee == a2->ai_grantee &&
647  a1->ai_grantor == a2->ai_grantor;
648 }
649 
650 /*
651  * aclitemComparator
652  * qsort comparison function for AclItems
653  */
654 static int
655 aclitemComparator(const void *arg1, const void *arg2)
656 {
657  const AclItem *a1 = (const AclItem *) arg1;
658  const AclItem *a2 = (const AclItem *) arg2;
659 
660  if (a1->ai_grantee > a2->ai_grantee)
661  return 1;
662  if (a1->ai_grantee < a2->ai_grantee)
663  return -1;
664  if (a1->ai_grantor > a2->ai_grantor)
665  return 1;
666  if (a1->ai_grantor < a2->ai_grantor)
667  return -1;
668  if (a1->ai_privs > a2->ai_privs)
669  return 1;
670  if (a1->ai_privs < a2->ai_privs)
671  return -1;
672  return 0;
673 }
674 
675 /*
676  * aclitem equality operator
677  */
678 Datum
680 {
683  bool result;
684 
685  result = a1->ai_privs == a2->ai_privs &&
686  a1->ai_grantee == a2->ai_grantee &&
687  a1->ai_grantor == a2->ai_grantor;
688  PG_RETURN_BOOL(result);
689 }
690 
691 /*
692  * aclitem hash function
693  *
694  * We make aclitems hashable not so much because anyone is likely to hash
695  * them, as because we want array equality to work on aclitem arrays, and
696  * with the typcache mechanism we must have a hash or btree opclass.
697  */
698 Datum
700 {
702 
703  /* not very bright, but avoids any issue of padding in struct */
705 }
706 
707 /*
708  * 64-bit hash function for aclitem.
709  *
710  * Similar to hash_aclitem, but accepts a seed and returns a uint64 value.
711  */
712 Datum
714 {
716  uint64 seed = PG_GETARG_INT64(1);
717  uint32 sum = (uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor);
718 
719  return (seed == 0) ? UInt64GetDatum(sum) : hash_uint32_extended(sum, seed);
720 }
721 
722 /*
723  * acldefault() --- create an ACL describing default access permissions
724  *
725  * Change this routine if you want to alter the default access policy for
726  * newly-created objects (or any object with a NULL acl entry). When
727  * you make a change here, don't forget to update the GRANT man page,
728  * which explains all the default permissions.
729  *
730  * Note that these are the hard-wired "defaults" that are used in the
731  * absence of any pg_default_acl entry.
732  */
733 Acl *
734 acldefault(ObjectType objtype, Oid ownerId)
735 {
736  AclMode world_default;
737  AclMode owner_default;
738  int nacl;
739  Acl *acl;
740  AclItem *aip;
741 
742  switch (objtype)
743  {
744  case OBJECT_COLUMN:
745  /* by default, columns have no extra privileges */
746  world_default = ACL_NO_RIGHTS;
747  owner_default = ACL_NO_RIGHTS;
748  break;
749  case OBJECT_TABLE:
750  world_default = ACL_NO_RIGHTS;
751  owner_default = ACL_ALL_RIGHTS_RELATION;
752  break;
753  case OBJECT_SEQUENCE:
754  world_default = ACL_NO_RIGHTS;
755  owner_default = ACL_ALL_RIGHTS_SEQUENCE;
756  break;
757  case OBJECT_DATABASE:
758  /* for backwards compatibility, grant some rights by default */
759  world_default = ACL_CREATE_TEMP | ACL_CONNECT;
760  owner_default = ACL_ALL_RIGHTS_DATABASE;
761  break;
762  case OBJECT_FUNCTION:
763  /* Grant EXECUTE by default, for now */
764  world_default = ACL_EXECUTE;
765  owner_default = ACL_ALL_RIGHTS_FUNCTION;
766  break;
767  case OBJECT_LANGUAGE:
768  /* Grant USAGE by default, for now */
769  world_default = ACL_USAGE;
770  owner_default = ACL_ALL_RIGHTS_LANGUAGE;
771  break;
772  case OBJECT_LARGEOBJECT:
773  world_default = ACL_NO_RIGHTS;
774  owner_default = ACL_ALL_RIGHTS_LARGEOBJECT;
775  break;
776  case OBJECT_SCHEMA:
777  world_default = ACL_NO_RIGHTS;
778  owner_default = ACL_ALL_RIGHTS_SCHEMA;
779  break;
780  case OBJECT_TABLESPACE:
781  world_default = ACL_NO_RIGHTS;
782  owner_default = ACL_ALL_RIGHTS_TABLESPACE;
783  break;
784  case OBJECT_FDW:
785  world_default = ACL_NO_RIGHTS;
786  owner_default = ACL_ALL_RIGHTS_FDW;
787  break;
789  world_default = ACL_NO_RIGHTS;
790  owner_default = ACL_ALL_RIGHTS_FOREIGN_SERVER;
791  break;
792  case OBJECT_DOMAIN:
793  case OBJECT_TYPE:
794  world_default = ACL_USAGE;
795  owner_default = ACL_ALL_RIGHTS_TYPE;
796  break;
797  default:
798  elog(ERROR, "unrecognized objtype: %d", (int) objtype);
799  world_default = ACL_NO_RIGHTS; /* keep compiler quiet */
800  owner_default = ACL_NO_RIGHTS;
801  break;
802  }
803 
804  nacl = 0;
805  if (world_default != ACL_NO_RIGHTS)
806  nacl++;
807  if (owner_default != ACL_NO_RIGHTS)
808  nacl++;
809 
810  acl = allocacl(nacl);
811  aip = ACL_DAT(acl);
812 
813  if (world_default != ACL_NO_RIGHTS)
814  {
815  aip->ai_grantee = ACL_ID_PUBLIC;
816  aip->ai_grantor = ownerId;
817  ACLITEM_SET_PRIVS_GOPTIONS(*aip, world_default, ACL_NO_RIGHTS);
818  aip++;
819  }
820 
821  /*
822  * Note that the owner's entry shows all ordinary privileges but no grant
823  * options. This is because his grant options come "from the system" and
824  * not from his own efforts. (The SQL spec says that the owner's rights
825  * come from a "_SYSTEM" authid.) However, we do consider that the
826  * owner's ordinary privileges are self-granted; this lets him revoke
827  * them. We implement the owner's grant options without any explicit
828  * "_SYSTEM"-like ACL entry, by internally special-casing the owner
829  * wherever we are testing grant options.
830  */
831  if (owner_default != ACL_NO_RIGHTS)
832  {
833  aip->ai_grantee = ownerId;
834  aip->ai_grantor = ownerId;
835  ACLITEM_SET_PRIVS_GOPTIONS(*aip, owner_default, ACL_NO_RIGHTS);
836  }
837 
838  return acl;
839 }
840 
841 
842 /*
843  * SQL-accessible version of acldefault(). Hackish mapping from "char" type to
844  * OBJECT_* values.
845  */
846 Datum
848 {
849  char objtypec = PG_GETARG_CHAR(0);
850  Oid owner = PG_GETARG_OID(1);
851  ObjectType objtype = 0;
852 
853  switch (objtypec)
854  {
855  case 'c':
856  objtype = OBJECT_COLUMN;
857  break;
858  case 'r':
859  objtype = OBJECT_TABLE;
860  break;
861  case 's':
862  objtype = OBJECT_SEQUENCE;
863  break;
864  case 'd':
865  objtype = OBJECT_DATABASE;
866  break;
867  case 'f':
868  objtype = OBJECT_FUNCTION;
869  break;
870  case 'l':
871  objtype = OBJECT_LANGUAGE;
872  break;
873  case 'L':
874  objtype = OBJECT_LARGEOBJECT;
875  break;
876  case 'n':
877  objtype = OBJECT_SCHEMA;
878  break;
879  case 't':
880  objtype = OBJECT_TABLESPACE;
881  break;
882  case 'F':
883  objtype = OBJECT_FDW;
884  break;
885  case 'S':
886  objtype = OBJECT_FOREIGN_SERVER;
887  break;
888  case 'T':
889  objtype = OBJECT_TYPE;
890  break;
891  default:
892  elog(ERROR, "unrecognized objtype abbreviation: %c", objtypec);
893  }
894 
895  PG_RETURN_ACL_P(acldefault(objtype, owner));
896 }
897 
898 
899 /*
900  * Update an ACL array to add or remove specified privileges.
901  *
902  * old_acl: the input ACL array
903  * mod_aip: defines the privileges to be added, removed, or substituted
904  * modechg: ACL_MODECHG_ADD, ACL_MODECHG_DEL, or ACL_MODECHG_EQL
905  * ownerId: Oid of object owner
906  * behavior: RESTRICT or CASCADE behavior for recursive removal
907  *
908  * ownerid and behavior are only relevant when the update operation specifies
909  * deletion of grant options.
910  *
911  * The result is a modified copy; the input object is not changed.
912  *
913  * NB: caller is responsible for having detoasted the input ACL, if needed.
914  */
915 Acl *
916 aclupdate(const Acl *old_acl, const AclItem *mod_aip,
917  int modechg, Oid ownerId, DropBehavior behavior)
918 {
919  Acl *new_acl = NULL;
920  AclItem *old_aip,
921  *new_aip = NULL;
922  AclMode old_rights,
923  old_goptions,
924  new_rights,
925  new_goptions;
926  int dst,
927  num;
928 
929  /* Caller probably already checked old_acl, but be safe */
930  check_acl(old_acl);
931 
932  /* If granting grant options, check for circularity */
933  if (modechg != ACL_MODECHG_DEL &&
934  ACLITEM_GET_GOPTIONS(*mod_aip) != ACL_NO_RIGHTS)
935  check_circularity(old_acl, mod_aip, ownerId);
936 
937  num = ACL_NUM(old_acl);
938  old_aip = ACL_DAT(old_acl);
939 
940  /*
941  * Search the ACL for an existing entry for this grantee and grantor. If
942  * one exists, just modify the entry in-place (well, in the same position,
943  * since we actually return a copy); otherwise, insert the new entry at
944  * the end.
945  */
946 
947  for (dst = 0; dst < num; ++dst)
948  {
949  if (aclitem_match(mod_aip, old_aip + dst))
950  {
951  /* found a match, so modify existing item */
952  new_acl = allocacl(num);
953  new_aip = ACL_DAT(new_acl);
954  memcpy(new_acl, old_acl, ACL_SIZE(old_acl));
955  break;
956  }
957  }
958 
959  if (dst == num)
960  {
961  /* need to append a new item */
962  new_acl = allocacl(num + 1);
963  new_aip = ACL_DAT(new_acl);
964  memcpy(new_aip, old_aip, num * sizeof(AclItem));
965 
966  /* initialize the new entry with no permissions */
967  new_aip[dst].ai_grantee = mod_aip->ai_grantee;
968  new_aip[dst].ai_grantor = mod_aip->ai_grantor;
969  ACLITEM_SET_PRIVS_GOPTIONS(new_aip[dst],
971  num++; /* set num to the size of new_acl */
972  }
973 
974  old_rights = ACLITEM_GET_RIGHTS(new_aip[dst]);
975  old_goptions = ACLITEM_GET_GOPTIONS(new_aip[dst]);
976 
977  /* apply the specified permissions change */
978  switch (modechg)
979  {
980  case ACL_MODECHG_ADD:
981  ACLITEM_SET_RIGHTS(new_aip[dst],
982  old_rights | ACLITEM_GET_RIGHTS(*mod_aip));
983  break;
984  case ACL_MODECHG_DEL:
985  ACLITEM_SET_RIGHTS(new_aip[dst],
986  old_rights & ~ACLITEM_GET_RIGHTS(*mod_aip));
987  break;
988  case ACL_MODECHG_EQL:
989  ACLITEM_SET_RIGHTS(new_aip[dst],
990  ACLITEM_GET_RIGHTS(*mod_aip));
991  break;
992  }
993 
994  new_rights = ACLITEM_GET_RIGHTS(new_aip[dst]);
995  new_goptions = ACLITEM_GET_GOPTIONS(new_aip[dst]);
996 
997  /*
998  * If the adjusted entry has no permissions, delete it from the list.
999  */
1000  if (new_rights == ACL_NO_RIGHTS)
1001  {
1002  memmove(new_aip + dst,
1003  new_aip + dst + 1,
1004  (num - dst - 1) * sizeof(AclItem));
1005  /* Adjust array size to be 'num - 1' items */
1006  ARR_DIMS(new_acl)[0] = num - 1;
1007  SET_VARSIZE(new_acl, ACL_N_SIZE(num - 1));
1008  }
1009 
1010  /*
1011  * Remove abandoned privileges (cascading revoke). Currently we can only
1012  * handle this when the grantee is not PUBLIC.
1013  */
1014  if ((old_goptions & ~new_goptions) != 0)
1015  {
1016  Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
1017  new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee,
1018  (old_goptions & ~new_goptions),
1019  ownerId, behavior);
1020  }
1021 
1022  return new_acl;
1023 }
1024 
1025 /*
1026  * Update an ACL array to reflect a change of owner to the parent object
1027  *
1028  * old_acl: the input ACL array (must not be NULL)
1029  * oldOwnerId: Oid of the old object owner
1030  * newOwnerId: Oid of the new object owner
1031  *
1032  * The result is a modified copy; the input object is not changed.
1033  *
1034  * NB: caller is responsible for having detoasted the input ACL, if needed.
1035  */
1036 Acl *
1037 aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
1038 {
1039  Acl *new_acl;
1040  AclItem *new_aip;
1041  AclItem *old_aip;
1042  AclItem *dst_aip;
1043  AclItem *src_aip;
1044  AclItem *targ_aip;
1045  bool newpresent = false;
1046  int dst,
1047  src,
1048  targ,
1049  num;
1050 
1051  check_acl(old_acl);
1052 
1053  /*
1054  * Make a copy of the given ACL, substituting new owner ID for old
1055  * wherever it appears as either grantor or grantee. Also note if the new
1056  * owner ID is already present.
1057  */
1058  num = ACL_NUM(old_acl);
1059  old_aip = ACL_DAT(old_acl);
1060  new_acl = allocacl(num);
1061  new_aip = ACL_DAT(new_acl);
1062  memcpy(new_aip, old_aip, num * sizeof(AclItem));
1063  for (dst = 0, dst_aip = new_aip; dst < num; dst++, dst_aip++)
1064  {
1065  if (dst_aip->ai_grantor == oldOwnerId)
1066  dst_aip->ai_grantor = newOwnerId;
1067  else if (dst_aip->ai_grantor == newOwnerId)
1068  newpresent = true;
1069  if (dst_aip->ai_grantee == oldOwnerId)
1070  dst_aip->ai_grantee = newOwnerId;
1071  else if (dst_aip->ai_grantee == newOwnerId)
1072  newpresent = true;
1073  }
1074 
1075  /*
1076  * If the old ACL contained any references to the new owner, then we may
1077  * now have generated an ACL containing duplicate entries. Find them and
1078  * merge them so that there are not duplicates. (This is relatively
1079  * expensive since we use a stupid O(N^2) algorithm, but it's unlikely to
1080  * be the normal case.)
1081  *
1082  * To simplify deletion of duplicate entries, we temporarily leave them in
1083  * the array but set their privilege masks to zero; when we reach such an
1084  * entry it's just skipped. (Thus, a side effect of this code will be to
1085  * remove privilege-free entries, should there be any in the input.) dst
1086  * is the next output slot, targ is the currently considered input slot
1087  * (always >= dst), and src scans entries to the right of targ looking for
1088  * duplicates. Once an entry has been emitted to dst it is known
1089  * duplicate-free and need not be considered anymore.
1090  */
1091  if (newpresent)
1092  {
1093  dst = 0;
1094  for (targ = 0, targ_aip = new_aip; targ < num; targ++, targ_aip++)
1095  {
1096  /* ignore if deleted in an earlier pass */
1097  if (ACLITEM_GET_RIGHTS(*targ_aip) == ACL_NO_RIGHTS)
1098  continue;
1099  /* find and merge any duplicates */
1100  for (src = targ + 1, src_aip = targ_aip + 1; src < num;
1101  src++, src_aip++)
1102  {
1103  if (ACLITEM_GET_RIGHTS(*src_aip) == ACL_NO_RIGHTS)
1104  continue;
1105  if (aclitem_match(targ_aip, src_aip))
1106  {
1107  ACLITEM_SET_RIGHTS(*targ_aip,
1108  ACLITEM_GET_RIGHTS(*targ_aip) |
1109  ACLITEM_GET_RIGHTS(*src_aip));
1110  /* mark the duplicate deleted */
1111  ACLITEM_SET_RIGHTS(*src_aip, ACL_NO_RIGHTS);
1112  }
1113  }
1114  /* and emit to output */
1115  new_aip[dst] = *targ_aip;
1116  dst++;
1117  }
1118  /* Adjust array size to be 'dst' items */
1119  ARR_DIMS(new_acl)[0] = dst;
1120  SET_VARSIZE(new_acl, ACL_N_SIZE(dst));
1121  }
1122 
1123  return new_acl;
1124 }
1125 
1126 
1127 /*
1128  * When granting grant options, we must disallow attempts to set up circular
1129  * chains of grant options. Suppose A (the object owner) grants B some
1130  * privileges with grant option, and B re-grants them to C. If C could
1131  * grant the privileges to B as well, then A would be unable to effectively
1132  * revoke the privileges from B, since recursive_revoke would consider that
1133  * B still has 'em from C.
1134  *
1135  * We check for this by recursively deleting all grant options belonging to
1136  * the target grantee, and then seeing if the would-be grantor still has the
1137  * grant option or not.
1138  */
1139 static void
1140 check_circularity(const Acl *old_acl, const AclItem *mod_aip,
1141  Oid ownerId)
1142 {
1143  Acl *acl;
1144  AclItem *aip;
1145  int i,
1146  num;
1147  AclMode own_privs;
1148 
1149  check_acl(old_acl);
1150 
1151  /*
1152  * For now, grant options can only be granted to roles, not PUBLIC.
1153  * Otherwise we'd have to work a bit harder here.
1154  */
1155  Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
1156 
1157  /* The owner always has grant options, no need to check */
1158  if (mod_aip->ai_grantor == ownerId)
1159  return;
1160 
1161  /* Make a working copy */
1162  acl = allocacl(ACL_NUM(old_acl));
1163  memcpy(acl, old_acl, ACL_SIZE(old_acl));
1164 
1165  /* Zap all grant options of target grantee, plus what depends on 'em */
1166 cc_restart:
1167  num = ACL_NUM(acl);
1168  aip = ACL_DAT(acl);
1169  for (i = 0; i < num; i++)
1170  {
1171  if (aip[i].ai_grantee == mod_aip->ai_grantee &&
1173  {
1174  Acl *new_acl;
1175 
1176  /* We'll actually zap ordinary privs too, but no matter */
1177  new_acl = aclupdate(acl, &aip[i], ACL_MODECHG_DEL,
1178  ownerId, DROP_CASCADE);
1179 
1180  pfree(acl);
1181  acl = new_acl;
1182 
1183  goto cc_restart;
1184  }
1185  }
1186 
1187  /* Now we can compute grantor's independently-derived privileges */
1188  own_privs = aclmask(acl,
1189  mod_aip->ai_grantor,
1190  ownerId,
1192  ACLMASK_ALL);
1193  own_privs = ACL_OPTION_TO_PRIVS(own_privs);
1194 
1195  if ((ACLITEM_GET_GOPTIONS(*mod_aip) & ~own_privs) != 0)
1196  ereport(ERROR,
1197  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1198  errmsg("grant options cannot be granted back to your own grantor")));
1199 
1200  pfree(acl);
1201 }
1202 
1203 
1204 /*
1205  * Ensure that no privilege is "abandoned". A privilege is abandoned
1206  * if the user that granted the privilege loses the grant option. (So
1207  * the chain through which it was granted is broken.) Either the
1208  * abandoned privileges are revoked as well, or an error message is
1209  * printed, depending on the drop behavior option.
1210  *
1211  * acl: the input ACL list
1212  * grantee: the user from whom some grant options have been revoked
1213  * revoke_privs: the grant options being revoked
1214  * ownerId: Oid of object owner
1215  * behavior: RESTRICT or CASCADE behavior for recursive removal
1216  *
1217  * The input Acl object is pfree'd if replaced.
1218  */
1219 static Acl *
1221  Oid grantee,
1222  AclMode revoke_privs,
1223  Oid ownerId,
1224  DropBehavior behavior)
1225 {
1226  AclMode still_has;
1227  AclItem *aip;
1228  int i,
1229  num;
1230 
1231  check_acl(acl);
1232 
1233  /* The owner can never truly lose grant options, so short-circuit */
1234  if (grantee == ownerId)
1235  return acl;
1236 
1237  /* The grantee might still have some grant options via another grantor */
1238  still_has = aclmask(acl, grantee, ownerId,
1239  ACL_GRANT_OPTION_FOR(revoke_privs),
1240  ACLMASK_ALL);
1241  revoke_privs &= ~ACL_OPTION_TO_PRIVS(still_has);
1242  if (revoke_privs == ACL_NO_RIGHTS)
1243  return acl;
1244 
1245 restart:
1246  num = ACL_NUM(acl);
1247  aip = ACL_DAT(acl);
1248  for (i = 0; i < num; i++)
1249  {
1250  if (aip[i].ai_grantor == grantee
1251  && (ACLITEM_GET_PRIVS(aip[i]) & revoke_privs) != 0)
1252  {
1253  AclItem mod_acl;
1254  Acl *new_acl;
1255 
1256  if (behavior == DROP_RESTRICT)
1257  ereport(ERROR,
1258  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1259  errmsg("dependent privileges exist"),
1260  errhint("Use CASCADE to revoke them too.")));
1261 
1262  mod_acl.ai_grantor = grantee;
1263  mod_acl.ai_grantee = aip[i].ai_grantee;
1265  revoke_privs,
1266  revoke_privs);
1267 
1268  new_acl = aclupdate(acl, &mod_acl, ACL_MODECHG_DEL,
1269  ownerId, behavior);
1270 
1271  pfree(acl);
1272  acl = new_acl;
1273 
1274  goto restart;
1275  }
1276  }
1277 
1278  return acl;
1279 }
1280 
1281 
1282 /*
1283  * aclmask --- compute bitmask of all privileges held by roleid.
1284  *
1285  * When 'how' = ACLMASK_ALL, this simply returns the privilege bits
1286  * held by the given roleid according to the given ACL list, ANDed
1287  * with 'mask'. (The point of passing 'mask' is to let the routine
1288  * exit early if all privileges of interest have been found.)
1289  *
1290  * When 'how' = ACLMASK_ANY, returns as soon as any bit in the mask
1291  * is known true. (This lets us exit soonest in cases where the
1292  * caller is only going to test for zero or nonzero result.)
1293  *
1294  * Usage patterns:
1295  *
1296  * To see if any of a set of privileges are held:
1297  * if (aclmask(acl, roleid, ownerId, privs, ACLMASK_ANY) != 0)
1298  *
1299  * To see if all of a set of privileges are held:
1300  * if (aclmask(acl, roleid, ownerId, privs, ACLMASK_ALL) == privs)
1301  *
1302  * To determine exactly which of a set of privileges are held:
1303  * heldprivs = aclmask(acl, roleid, ownerId, privs, ACLMASK_ALL);
1304  */
1305 AclMode
1306 aclmask(const Acl *acl, Oid roleid, Oid ownerId,
1307  AclMode mask, AclMaskHow how)
1308 {
1309  AclMode result;
1311  AclItem *aidat;
1312  int i,
1313  num;
1314 
1315  /*
1316  * Null ACL should not happen, since caller should have inserted
1317  * appropriate default
1318  */
1319  if (acl == NULL)
1320  elog(ERROR, "null ACL");
1321 
1322  check_acl(acl);
1323 
1324  /* Quick exit for mask == 0 */
1325  if (mask == 0)
1326  return 0;
1327 
1328  result = 0;
1329 
1330  /* Owner always implicitly has all grant options */
1331  if ((mask & ACLITEM_ALL_GOPTION_BITS) &&
1332  has_privs_of_role(roleid, ownerId))
1333  {
1334  result = mask & ACLITEM_ALL_GOPTION_BITS;
1335  if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1336  return result;
1337  }
1338 
1339  num = ACL_NUM(acl);
1340  aidat = ACL_DAT(acl);
1341 
1342  /*
1343  * Check privileges granted directly to roleid or to public
1344  */
1345  for (i = 0; i < num; i++)
1346  {
1347  AclItem *aidata = &aidat[i];
1348 
1349  if (aidata->ai_grantee == ACL_ID_PUBLIC ||
1350  aidata->ai_grantee == roleid)
1351  {
1352  result |= aidata->ai_privs & mask;
1353  if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1354  return result;
1355  }
1356  }
1357 
1358  /*
1359  * Check privileges granted indirectly via role memberships. We do this in
1360  * a separate pass to minimize expensive indirect membership tests. In
1361  * particular, it's worth testing whether a given ACL entry grants any
1362  * privileges still of interest before we perform the has_privs_of_role
1363  * test.
1364  */
1365  remaining = mask & ~result;
1366  for (i = 0; i < num; i++)
1367  {
1368  AclItem *aidata = &aidat[i];
1369 
1370  if (aidata->ai_grantee == ACL_ID_PUBLIC ||
1371  aidata->ai_grantee == roleid)
1372  continue; /* already checked it */
1373 
1374  if ((aidata->ai_privs & remaining) &&
1375  has_privs_of_role(roleid, aidata->ai_grantee))
1376  {
1377  result |= aidata->ai_privs & mask;
1378  if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1379  return result;
1380  remaining = mask & ~result;
1381  }
1382  }
1383 
1384  return result;
1385 }
1386 
1387 
1388 /*
1389  * aclmask_direct --- compute bitmask of all privileges held by roleid.
1390  *
1391  * This is exactly like aclmask() except that we consider only privileges
1392  * held *directly* by roleid, not those inherited via role membership.
1393  */
1394 static AclMode
1395 aclmask_direct(const Acl *acl, Oid roleid, Oid ownerId,
1396  AclMode mask, AclMaskHow how)
1397 {
1398  AclMode result;
1399  AclItem *aidat;
1400  int i,
1401  num;
1402 
1403  /*
1404  * Null ACL should not happen, since caller should have inserted
1405  * appropriate default
1406  */
1407  if (acl == NULL)
1408  elog(ERROR, "null ACL");
1409 
1410  check_acl(acl);
1411 
1412  /* Quick exit for mask == 0 */
1413  if (mask == 0)
1414  return 0;
1415 
1416  result = 0;
1417 
1418  /* Owner always implicitly has all grant options */
1419  if ((mask & ACLITEM_ALL_GOPTION_BITS) &&
1420  roleid == ownerId)
1421  {
1422  result = mask & ACLITEM_ALL_GOPTION_BITS;
1423  if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1424  return result;
1425  }
1426 
1427  num = ACL_NUM(acl);
1428  aidat = ACL_DAT(acl);
1429 
1430  /*
1431  * Check privileges granted directly to roleid (and not to public)
1432  */
1433  for (i = 0; i < num; i++)
1434  {
1435  AclItem *aidata = &aidat[i];
1436 
1437  if (aidata->ai_grantee == roleid)
1438  {
1439  result |= aidata->ai_privs & mask;
1440  if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1441  return result;
1442  }
1443  }
1444 
1445  return result;
1446 }
1447 
1448 
1449 /*
1450  * aclmembers
1451  * Find out all the roleids mentioned in an Acl.
1452  * Note that we do not distinguish grantors from grantees.
1453  *
1454  * *roleids is set to point to a palloc'd array containing distinct OIDs
1455  * in sorted order. The length of the array is the function result.
1456  */
1457 int
1458 aclmembers(const Acl *acl, Oid **roleids)
1459 {
1460  Oid *list;
1461  const AclItem *acldat;
1462  int i,
1463  j;
1464 
1465  if (acl == NULL || ACL_NUM(acl) == 0)
1466  {
1467  *roleids = NULL;
1468  return 0;
1469  }
1470 
1471  check_acl(acl);
1472 
1473  /* Allocate the worst-case space requirement */
1474  list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
1475  acldat = ACL_DAT(acl);
1476 
1477  /*
1478  * Walk the ACL collecting mentioned RoleIds.
1479  */
1480  j = 0;
1481  for (i = 0; i < ACL_NUM(acl); i++)
1482  {
1483  const AclItem *ai = &acldat[i];
1484 
1485  if (ai->ai_grantee != ACL_ID_PUBLIC)
1486  list[j++] = ai->ai_grantee;
1487  /* grantor is currently never PUBLIC, but let's check anyway */
1488  if (ai->ai_grantor != ACL_ID_PUBLIC)
1489  list[j++] = ai->ai_grantor;
1490  }
1491 
1492  /* Sort the array */
1493  qsort(list, j, sizeof(Oid), oid_cmp);
1494 
1495  /*
1496  * We could repalloc the array down to minimum size, but it's hardly worth
1497  * it since it's only transient memory.
1498  */
1499  *roleids = list;
1500 
1501  /* Remove duplicates from the array */
1502  return qunique(list, j, sizeof(Oid), oid_cmp);
1503 }
1504 
1505 
1506 /*
1507  * aclinsert (exported function)
1508  */
1509 Datum
1511 {
1512  ereport(ERROR,
1513  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1514  errmsg("aclinsert is no longer supported")));
1515 
1516  PG_RETURN_NULL(); /* keep compiler quiet */
1517 }
1518 
1519 Datum
1521 {
1522  ereport(ERROR,
1523  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1524  errmsg("aclremove is no longer supported")));
1525 
1526  PG_RETURN_NULL(); /* keep compiler quiet */
1527 }
1528 
1529 Datum
1531 {
1532  Acl *acl = PG_GETARG_ACL_P(0);
1533  AclItem *aip = PG_GETARG_ACLITEM_P(1);
1534  AclItem *aidat;
1535  int i,
1536  num;
1537 
1538  check_acl(acl);
1539  num = ACL_NUM(acl);
1540  aidat = ACL_DAT(acl);
1541  for (i = 0; i < num; ++i)
1542  {
1543  if (aip->ai_grantee == aidat[i].ai_grantee &&
1544  aip->ai_grantor == aidat[i].ai_grantor &&
1545  (ACLITEM_GET_RIGHTS(*aip) & ACLITEM_GET_RIGHTS(aidat[i])) == ACLITEM_GET_RIGHTS(*aip))
1546  PG_RETURN_BOOL(true);
1547  }
1548  PG_RETURN_BOOL(false);
1549 }
1550 
1551 Datum
1553 {
1554  Oid grantee = PG_GETARG_OID(0);
1555  Oid grantor = PG_GETARG_OID(1);
1556  text *privtext = PG_GETARG_TEXT_PP(2);
1557  bool goption = PG_GETARG_BOOL(3);
1558  AclItem *result;
1559  AclMode priv;
1560 
1561  priv = convert_priv_string(privtext);
1562 
1563  result = (AclItem *) palloc(sizeof(AclItem));
1564 
1565  result->ai_grantee = grantee;
1566  result->ai_grantor = grantor;
1567 
1568  ACLITEM_SET_PRIVS_GOPTIONS(*result, priv,
1569  (goption ? priv : ACL_NO_RIGHTS));
1570 
1571  PG_RETURN_ACLITEM_P(result);
1572 }
1573 
1574 static AclMode
1575 convert_priv_string(text *priv_type_text)
1576 {
1577  char *priv_type = text_to_cstring(priv_type_text);
1578 
1579  if (pg_strcasecmp(priv_type, "SELECT") == 0)
1580  return ACL_SELECT;
1581  if (pg_strcasecmp(priv_type, "INSERT") == 0)
1582  return ACL_INSERT;
1583  if (pg_strcasecmp(priv_type, "UPDATE") == 0)
1584  return ACL_UPDATE;
1585  if (pg_strcasecmp(priv_type, "DELETE") == 0)
1586  return ACL_DELETE;
1587  if (pg_strcasecmp(priv_type, "TRUNCATE") == 0)
1588  return ACL_TRUNCATE;
1589  if (pg_strcasecmp(priv_type, "REFERENCES") == 0)
1590  return ACL_REFERENCES;
1591  if (pg_strcasecmp(priv_type, "TRIGGER") == 0)
1592  return ACL_TRIGGER;
1593  if (pg_strcasecmp(priv_type, "EXECUTE") == 0)
1594  return ACL_EXECUTE;
1595  if (pg_strcasecmp(priv_type, "USAGE") == 0)
1596  return ACL_USAGE;
1597  if (pg_strcasecmp(priv_type, "CREATE") == 0)
1598  return ACL_CREATE;
1599  if (pg_strcasecmp(priv_type, "TEMP") == 0)
1600  return ACL_CREATE_TEMP;
1601  if (pg_strcasecmp(priv_type, "TEMPORARY") == 0)
1602  return ACL_CREATE_TEMP;
1603  if (pg_strcasecmp(priv_type, "CONNECT") == 0)
1604  return ACL_CONNECT;
1605  if (pg_strcasecmp(priv_type, "RULE") == 0)
1606  return 0; /* ignore old RULE privileges */
1607 
1608  ereport(ERROR,
1609  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1610  errmsg("unrecognized privilege type: \"%s\"", priv_type)));
1611  return ACL_NO_RIGHTS; /* keep compiler quiet */
1612 }
1613 
1614 
1615 /*
1616  * convert_any_priv_string: recognize privilege strings for has_foo_privilege
1617  *
1618  * We accept a comma-separated list of case-insensitive privilege names,
1619  * producing a bitmask of the OR'd privilege bits. We are liberal about
1620  * whitespace between items, not so much about whitespace within items.
1621  * The allowed privilege names are given as an array of priv_map structs,
1622  * terminated by one with a NULL name pointer.
1623  */
1624 static AclMode
1626  const priv_map *privileges)
1627 {
1628  AclMode result = 0;
1629  char *priv_type = text_to_cstring(priv_type_text);
1630  char *chunk;
1631  char *next_chunk;
1632 
1633  /* We rely on priv_type being a private, modifiable string */
1634  for (chunk = priv_type; chunk; chunk = next_chunk)
1635  {
1636  int chunk_len;
1637  const priv_map *this_priv;
1638 
1639  /* Split string at commas */
1640  next_chunk = strchr(chunk, ',');
1641  if (next_chunk)
1642  *next_chunk++ = '\0';
1643 
1644  /* Drop leading/trailing whitespace in this chunk */
1645  while (*chunk && isspace((unsigned char) *chunk))
1646  chunk++;
1647  chunk_len = strlen(chunk);
1648  while (chunk_len > 0 && isspace((unsigned char) chunk[chunk_len - 1]))
1649  chunk_len--;
1650  chunk[chunk_len] = '\0';
1651 
1652  /* Match to the privileges list */
1653  for (this_priv = privileges; this_priv->name; this_priv++)
1654  {
1655  if (pg_strcasecmp(this_priv->name, chunk) == 0)
1656  {
1657  result |= this_priv->value;
1658  break;
1659  }
1660  }
1661  if (!this_priv->name)
1662  ereport(ERROR,
1663  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1664  errmsg("unrecognized privilege type: \"%s\"", chunk)));
1665  }
1666 
1667  pfree(priv_type);
1668  return result;
1669 }
1670 
1671 
1672 static const char *
1674 {
1675  switch (aclright)
1676  {
1677  case ACL_INSERT:
1678  return "INSERT";
1679  case ACL_SELECT:
1680  return "SELECT";
1681  case ACL_UPDATE:
1682  return "UPDATE";
1683  case ACL_DELETE:
1684  return "DELETE";
1685  case ACL_TRUNCATE:
1686  return "TRUNCATE";
1687  case ACL_REFERENCES:
1688  return "REFERENCES";
1689  case ACL_TRIGGER:
1690  return "TRIGGER";
1691  case ACL_EXECUTE:
1692  return "EXECUTE";
1693  case ACL_USAGE:
1694  return "USAGE";
1695  case ACL_CREATE:
1696  return "CREATE";
1697  case ACL_CREATE_TEMP:
1698  return "TEMPORARY";
1699  case ACL_CONNECT:
1700  return "CONNECT";
1701  default:
1702  elog(ERROR, "unrecognized aclright: %d", aclright);
1703  return NULL;
1704  }
1705 }
1706 
1707 
1708 /*----------
1709  * Convert an aclitem[] to a table.
1710  *
1711  * Example:
1712  *
1713  * aclexplode('{=r/joe,foo=a*w/joe}'::aclitem[])
1714  *
1715  * returns the table
1716  *
1717  * {{ OID(joe), 0::OID, 'SELECT', false },
1718  * { OID(joe), OID(foo), 'INSERT', true },
1719  * { OID(joe), OID(foo), 'UPDATE', false }}
1720  *----------
1721  */
1722 Datum
1724 {
1725  Acl *acl = PG_GETARG_ACL_P(0);
1726  FuncCallContext *funcctx;
1727  int *idx;
1728  AclItem *aidat;
1729 
1730  if (SRF_IS_FIRSTCALL())
1731  {
1732  TupleDesc tupdesc;
1733  MemoryContext oldcontext;
1734 
1735  check_acl(acl);
1736 
1737  funcctx = SRF_FIRSTCALL_INIT();
1738  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1739 
1740  /*
1741  * build tupdesc for result tuples (matches out parameters in pg_proc
1742  * entry)
1743  */
1744  tupdesc = CreateTemplateTupleDesc(4);
1745  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "grantor",
1746  OIDOID, -1, 0);
1747  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "grantee",
1748  OIDOID, -1, 0);
1749  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "privilege_type",
1750  TEXTOID, -1, 0);
1751  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "is_grantable",
1752  BOOLOID, -1, 0);
1753 
1754  funcctx->tuple_desc = BlessTupleDesc(tupdesc);
1755 
1756  /* allocate memory for user context */
1757  idx = (int *) palloc(sizeof(int[2]));
1758  idx[0] = 0; /* ACL array item index */
1759  idx[1] = -1; /* privilege type counter */
1760  funcctx->user_fctx = (void *) idx;
1761 
1762  MemoryContextSwitchTo(oldcontext);
1763  }
1764 
1765  funcctx = SRF_PERCALL_SETUP();
1766  idx = (int *) funcctx->user_fctx;
1767  aidat = ACL_DAT(acl);
1768 
1769  /* need test here in case acl has no items */
1770  while (idx[0] < ACL_NUM(acl))
1771  {
1772  AclItem *aidata;
1773  AclMode priv_bit;
1774 
1775  idx[1]++;
1776  if (idx[1] == N_ACL_RIGHTS)
1777  {
1778  idx[1] = 0;
1779  idx[0]++;
1780  if (idx[0] >= ACL_NUM(acl)) /* done */
1781  break;
1782  }
1783  aidata = &aidat[idx[0]];
1784  priv_bit = 1 << idx[1];
1785 
1786  if (ACLITEM_GET_PRIVS(*aidata) & priv_bit)
1787  {
1788  Datum result;
1789  Datum values[4];
1790  bool nulls[4];
1791  HeapTuple tuple;
1792 
1793  values[0] = ObjectIdGetDatum(aidata->ai_grantor);
1794  values[1] = ObjectIdGetDatum(aidata->ai_grantee);
1795  values[2] = CStringGetTextDatum(convert_aclright_to_string(priv_bit));
1796  values[3] = BoolGetDatum((ACLITEM_GET_GOPTIONS(*aidata) & priv_bit) != 0);
1797 
1798  MemSet(nulls, 0, sizeof(nulls));
1799 
1800  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
1801  result = HeapTupleGetDatum(tuple);
1802 
1803  SRF_RETURN_NEXT(funcctx, result);
1804  }
1805  }
1806 
1807  SRF_RETURN_DONE(funcctx);
1808 }
1809 
1810 
1811 /*
1812  * has_table_privilege variants
1813  * These are all named "has_table_privilege" at the SQL level.
1814  * They take various combinations of relation name, relation OID,
1815  * user name, user OID, or implicit user = current_user.
1816  *
1817  * The result is a boolean value: true if user has the indicated
1818  * privilege, false if not. The variants that take a relation OID
1819  * return NULL if the OID doesn't exist (rather than failing, as
1820  * they did before Postgres 8.4).
1821  */
1822 
1823 /*
1824  * has_table_privilege_name_name
1825  * Check user privileges on a table given
1826  * name username, text tablename, and text priv name.
1827  */
1828 Datum
1830 {
1831  Name rolename = PG_GETARG_NAME(0);
1832  text *tablename = PG_GETARG_TEXT_PP(1);
1833  text *priv_type_text = PG_GETARG_TEXT_PP(2);
1834  Oid roleid;
1835  Oid tableoid;
1836  AclMode mode;
1837  AclResult aclresult;
1838 
1839  roleid = get_role_oid_or_public(NameStr(*rolename));
1840  tableoid = convert_table_name(tablename);
1841  mode = convert_table_priv_string(priv_type_text);
1842 
1843  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1844 
1845  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1846 }
1847 
1848 /*
1849  * has_table_privilege_name
1850  * Check user privileges on a table given
1851  * text tablename and text priv name.
1852  * current_user is assumed
1853  */
1854 Datum
1856 {
1857  text *tablename = PG_GETARG_TEXT_PP(0);
1858  text *priv_type_text = PG_GETARG_TEXT_PP(1);
1859  Oid roleid;
1860  Oid tableoid;
1861  AclMode mode;
1862  AclResult aclresult;
1863 
1864  roleid = GetUserId();
1865  tableoid = convert_table_name(tablename);
1866  mode = convert_table_priv_string(priv_type_text);
1867 
1868  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1869 
1870  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1871 }
1872 
1873 /*
1874  * has_table_privilege_name_id
1875  * Check user privileges on a table given
1876  * name usename, table oid, and text priv name.
1877  */
1878 Datum
1880 {
1882  Oid tableoid = PG_GETARG_OID(1);
1883  text *priv_type_text = PG_GETARG_TEXT_PP(2);
1884  Oid roleid;
1885  AclMode mode;
1886  AclResult aclresult;
1887 
1888  roleid = get_role_oid_or_public(NameStr(*username));
1889  mode = convert_table_priv_string(priv_type_text);
1890 
1892  PG_RETURN_NULL();
1893 
1894  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1895 
1896  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1897 }
1898 
1899 /*
1900  * has_table_privilege_id
1901  * Check user privileges on a table given
1902  * table oid, and text priv name.
1903  * current_user is assumed
1904  */
1905 Datum
1907 {
1908  Oid tableoid = PG_GETARG_OID(0);
1909  text *priv_type_text = PG_GETARG_TEXT_PP(1);
1910  Oid roleid;
1911  AclMode mode;
1912  AclResult aclresult;
1913 
1914  roleid = GetUserId();
1915  mode = convert_table_priv_string(priv_type_text);
1916 
1918  PG_RETURN_NULL();
1919 
1920  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1921 
1922  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1923 }
1924 
1925 /*
1926  * has_table_privilege_id_name
1927  * Check user privileges on a table given
1928  * roleid, text tablename, and text priv name.
1929  */
1930 Datum
1932 {
1933  Oid roleid = PG_GETARG_OID(0);
1934  text *tablename = PG_GETARG_TEXT_PP(1);
1935  text *priv_type_text = PG_GETARG_TEXT_PP(2);
1936  Oid tableoid;
1937  AclMode mode;
1938  AclResult aclresult;
1939 
1940  tableoid = convert_table_name(tablename);
1941  mode = convert_table_priv_string(priv_type_text);
1942 
1943  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1944 
1945  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1946 }
1947 
1948 /*
1949  * has_table_privilege_id_id
1950  * Check user privileges on a table given
1951  * roleid, table oid, and text priv name.
1952  */
1953 Datum
1955 {
1956  Oid roleid = PG_GETARG_OID(0);
1957  Oid tableoid = PG_GETARG_OID(1);
1958  text *priv_type_text = PG_GETARG_TEXT_PP(2);
1959  AclMode mode;
1960  AclResult aclresult;
1961 
1962  mode = convert_table_priv_string(priv_type_text);
1963 
1965  PG_RETURN_NULL();
1966 
1967  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1968 
1969  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1970 }
1971 
1972 /*
1973  * Support routines for has_table_privilege family.
1974  */
1975 
1976 /*
1977  * Given a table name expressed as a string, look it up and return Oid
1978  */
1979 static Oid
1981 {
1982  RangeVar *relrv;
1983 
1985 
1986  /* We might not even have permissions on this relation; don't lock it. */
1987  return RangeVarGetRelid(relrv, NoLock, false);
1988 }
1989 
1990 /*
1991  * convert_table_priv_string
1992  * Convert text string to AclMode value.
1993  */
1994 static AclMode
1996 {
1997  static const priv_map table_priv_map[] = {
1998  {"SELECT", ACL_SELECT},
1999  {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
2000  {"INSERT", ACL_INSERT},
2001  {"INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT)},
2002  {"UPDATE", ACL_UPDATE},
2003  {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
2004  {"DELETE", ACL_DELETE},
2005  {"DELETE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_DELETE)},
2006  {"TRUNCATE", ACL_TRUNCATE},
2007  {"TRUNCATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRUNCATE)},
2008  {"REFERENCES", ACL_REFERENCES},
2009  {"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
2010  {"TRIGGER", ACL_TRIGGER},
2011  {"TRIGGER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRIGGER)},
2012  {"RULE", 0}, /* ignore old RULE privileges */
2013  {"RULE WITH GRANT OPTION", 0},
2014  {NULL, 0}
2015  };
2016 
2017  return convert_any_priv_string(priv_type_text, table_priv_map);
2018 }
2019 
2020 /*
2021  * has_sequence_privilege variants
2022  * These are all named "has_sequence_privilege" at the SQL level.
2023  * They take various combinations of relation name, relation OID,
2024  * user name, user OID, or implicit user = current_user.
2025  *
2026  * The result is a boolean value: true if user has the indicated
2027  * privilege, false if not. The variants that take a relation OID
2028  * return NULL if the OID doesn't exist.
2029  */
2030 
2031 /*
2032  * has_sequence_privilege_name_name
2033  * Check user privileges on a sequence given
2034  * name username, text sequencename, and text priv name.
2035  */
2036 Datum
2038 {
2039  Name rolename = PG_GETARG_NAME(0);
2040  text *sequencename = PG_GETARG_TEXT_PP(1);
2041  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2042  Oid roleid;
2043  Oid sequenceoid;
2044  AclMode mode;
2045  AclResult aclresult;
2046 
2047  roleid = get_role_oid_or_public(NameStr(*rolename));
2048  mode = convert_sequence_priv_string(priv_type_text);
2049  sequenceoid = convert_table_name(sequencename);
2050  if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
2051  ereport(ERROR,
2052  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2053  errmsg("\"%s\" is not a sequence",
2054  text_to_cstring(sequencename))));
2055 
2056  aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
2057 
2058  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2059 }
2060 
2061 /*
2062  * has_sequence_privilege_name
2063  * Check user privileges on a sequence given
2064  * text sequencename and text priv name.
2065  * current_user is assumed
2066  */
2067 Datum
2069 {
2070  text *sequencename = PG_GETARG_TEXT_PP(0);
2071  text *priv_type_text = PG_GETARG_TEXT_PP(1);
2072  Oid roleid;
2073  Oid sequenceoid;
2074  AclMode mode;
2075  AclResult aclresult;
2076 
2077  roleid = GetUserId();
2078  mode = convert_sequence_priv_string(priv_type_text);
2079  sequenceoid = convert_table_name(sequencename);
2080  if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
2081  ereport(ERROR,
2082  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2083  errmsg("\"%s\" is not a sequence",
2084  text_to_cstring(sequencename))));
2085 
2086  aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
2087 
2088  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2089 }
2090 
2091 /*
2092  * has_sequence_privilege_name_id
2093  * Check user privileges on a sequence given
2094  * name usename, sequence oid, and text priv name.
2095  */
2096 Datum
2098 {
2100  Oid sequenceoid = PG_GETARG_OID(1);
2101  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2102  Oid roleid;
2103  AclMode mode;
2104  AclResult aclresult;
2105  char relkind;
2106 
2107  roleid = get_role_oid_or_public(NameStr(*username));
2108  mode = convert_sequence_priv_string(priv_type_text);
2109  relkind = get_rel_relkind(sequenceoid);
2110  if (relkind == '\0')
2111  PG_RETURN_NULL();
2112  else if (relkind != RELKIND_SEQUENCE)
2113  ereport(ERROR,
2114  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2115  errmsg("\"%s\" is not a sequence",
2116  get_rel_name(sequenceoid))));
2117 
2118  aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
2119 
2120  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2121 }
2122 
2123 /*
2124  * has_sequence_privilege_id
2125  * Check user privileges on a sequence given
2126  * sequence oid, and text priv name.
2127  * current_user is assumed
2128  */
2129 Datum
2131 {
2132  Oid sequenceoid = PG_GETARG_OID(0);
2133  text *priv_type_text = PG_GETARG_TEXT_PP(1);
2134  Oid roleid;
2135  AclMode mode;
2136  AclResult aclresult;
2137  char relkind;
2138 
2139  roleid = GetUserId();
2140  mode = convert_sequence_priv_string(priv_type_text);
2141  relkind = get_rel_relkind(sequenceoid);
2142  if (relkind == '\0')
2143  PG_RETURN_NULL();
2144  else if (relkind != RELKIND_SEQUENCE)
2145  ereport(ERROR,
2146  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2147  errmsg("\"%s\" is not a sequence",
2148  get_rel_name(sequenceoid))));
2149 
2150  aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
2151 
2152  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2153 }
2154 
2155 /*
2156  * has_sequence_privilege_id_name
2157  * Check user privileges on a sequence given
2158  * roleid, text sequencename, and text priv name.
2159  */
2160 Datum
2162 {
2163  Oid roleid = PG_GETARG_OID(0);
2164  text *sequencename = PG_GETARG_TEXT_PP(1);
2165  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2166  Oid sequenceoid;
2167  AclMode mode;
2168  AclResult aclresult;
2169 
2170  mode = convert_sequence_priv_string(priv_type_text);
2171  sequenceoid = convert_table_name(sequencename);
2172  if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
2173  ereport(ERROR,
2174  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2175  errmsg("\"%s\" is not a sequence",
2176  text_to_cstring(sequencename))));
2177 
2178  aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
2179 
2180  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2181 }
2182 
2183 /*
2184  * has_sequence_privilege_id_id
2185  * Check user privileges on a sequence given
2186  * roleid, sequence oid, and text priv name.
2187  */
2188 Datum
2190 {
2191  Oid roleid = PG_GETARG_OID(0);
2192  Oid sequenceoid = PG_GETARG_OID(1);
2193  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2194  AclMode mode;
2195  AclResult aclresult;
2196  char relkind;
2197 
2198  mode = convert_sequence_priv_string(priv_type_text);
2199  relkind = get_rel_relkind(sequenceoid);
2200  if (relkind == '\0')
2201  PG_RETURN_NULL();
2202  else if (relkind != RELKIND_SEQUENCE)
2203  ereport(ERROR,
2204  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2205  errmsg("\"%s\" is not a sequence",
2206  get_rel_name(sequenceoid))));
2207 
2208  aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
2209 
2210  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2211 }
2212 
2213 /*
2214  * convert_sequence_priv_string
2215  * Convert text string to AclMode value.
2216  */
2217 static AclMode
2219 {
2220  static const priv_map sequence_priv_map[] = {
2221  {"USAGE", ACL_USAGE},
2222  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
2223  {"SELECT", ACL_SELECT},
2224  {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
2225  {"UPDATE", ACL_UPDATE},
2226  {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
2227  {NULL, 0}
2228  };
2229 
2230  return convert_any_priv_string(priv_type_text, sequence_priv_map);
2231 }
2232 
2233 
2234 /*
2235  * has_any_column_privilege variants
2236  * These are all named "has_any_column_privilege" at the SQL level.
2237  * They take various combinations of relation name, relation OID,
2238  * user name, user OID, or implicit user = current_user.
2239  *
2240  * The result is a boolean value: true if user has the indicated
2241  * privilege for any column of the table, false if not. The variants
2242  * that take a relation OID return NULL if the OID doesn't exist.
2243  */
2244 
2245 /*
2246  * has_any_column_privilege_name_name
2247  * Check user privileges on any column of a table given
2248  * name username, text tablename, and text priv name.
2249  */
2250 Datum
2252 {
2253  Name rolename = PG_GETARG_NAME(0);
2254  text *tablename = PG_GETARG_TEXT_PP(1);
2255  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2256  Oid roleid;
2257  Oid tableoid;
2258  AclMode mode;
2259  AclResult aclresult;
2260 
2261  roleid = get_role_oid_or_public(NameStr(*rolename));
2262  tableoid = convert_table_name(tablename);
2263  mode = convert_column_priv_string(priv_type_text);
2264 
2265  /* First check at table level, then examine each column if needed */
2266  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2267  if (aclresult != ACLCHECK_OK)
2268  aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2269  ACLMASK_ANY);
2270 
2271  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2272 }
2273 
2274 /*
2275  * has_any_column_privilege_name
2276  * Check user privileges on any column of a table given
2277  * text tablename and text priv name.
2278  * current_user is assumed
2279  */
2280 Datum
2282 {
2283  text *tablename = PG_GETARG_TEXT_PP(0);
2284  text *priv_type_text = PG_GETARG_TEXT_PP(1);
2285  Oid roleid;
2286  Oid tableoid;
2287  AclMode mode;
2288  AclResult aclresult;
2289 
2290  roleid = GetUserId();
2291  tableoid = convert_table_name(tablename);
2292  mode = convert_column_priv_string(priv_type_text);
2293 
2294  /* First check at table level, then examine each column if needed */
2295  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2296  if (aclresult != ACLCHECK_OK)
2297  aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2298  ACLMASK_ANY);
2299 
2300  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2301 }
2302 
2303 /*
2304  * has_any_column_privilege_name_id
2305  * Check user privileges on any column of a table given
2306  * name usename, table oid, and text priv name.
2307  */
2308 Datum
2310 {
2312  Oid tableoid = PG_GETARG_OID(1);
2313  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2314  Oid roleid;
2315  AclMode mode;
2316  AclResult aclresult;
2317 
2318  roleid = get_role_oid_or_public(NameStr(*username));
2319  mode = convert_column_priv_string(priv_type_text);
2320 
2322  PG_RETURN_NULL();
2323 
2324  /* First check at table level, then examine each column if needed */
2325  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2326  if (aclresult != ACLCHECK_OK)
2327  aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2328  ACLMASK_ANY);
2329 
2330  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2331 }
2332 
2333 /*
2334  * has_any_column_privilege_id
2335  * Check user privileges on any column of a table given
2336  * table oid, and text priv name.
2337  * current_user is assumed
2338  */
2339 Datum
2341 {
2342  Oid tableoid = PG_GETARG_OID(0);
2343  text *priv_type_text = PG_GETARG_TEXT_PP(1);
2344  Oid roleid;
2345  AclMode mode;
2346  AclResult aclresult;
2347 
2348  roleid = GetUserId();
2349  mode = convert_column_priv_string(priv_type_text);
2350 
2352  PG_RETURN_NULL();
2353 
2354  /* First check at table level, then examine each column if needed */
2355  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2356  if (aclresult != ACLCHECK_OK)
2357  aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2358  ACLMASK_ANY);
2359 
2360  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2361 }
2362 
2363 /*
2364  * has_any_column_privilege_id_name
2365  * Check user privileges on any column of a table given
2366  * roleid, text tablename, and text priv name.
2367  */
2368 Datum
2370 {
2371  Oid roleid = PG_GETARG_OID(0);
2372  text *tablename = PG_GETARG_TEXT_PP(1);
2373  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2374  Oid tableoid;
2375  AclMode mode;
2376  AclResult aclresult;
2377 
2378  tableoid = convert_table_name(tablename);
2379  mode = convert_column_priv_string(priv_type_text);
2380 
2381  /* First check at table level, then examine each column if needed */
2382  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2383  if (aclresult != ACLCHECK_OK)
2384  aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2385  ACLMASK_ANY);
2386 
2387  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2388 }
2389 
2390 /*
2391  * has_any_column_privilege_id_id
2392  * Check user privileges on any column of a table given
2393  * roleid, table oid, and text priv name.
2394  */
2395 Datum
2397 {
2398  Oid roleid = PG_GETARG_OID(0);
2399  Oid tableoid = PG_GETARG_OID(1);
2400  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2401  AclMode mode;
2402  AclResult aclresult;
2403 
2404  mode = convert_column_priv_string(priv_type_text);
2405 
2407  PG_RETURN_NULL();
2408 
2409  /* First check at table level, then examine each column if needed */
2410  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2411  if (aclresult != ACLCHECK_OK)
2412  aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2413  ACLMASK_ANY);
2414 
2415  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2416 }
2417 
2418 
2419 /*
2420  * has_column_privilege variants
2421  * These are all named "has_column_privilege" at the SQL level.
2422  * They take various combinations of relation name, relation OID,
2423  * column name, column attnum, user name, user OID, or
2424  * implicit user = current_user.
2425  *
2426  * The result is a boolean value: true if user has the indicated
2427  * privilege, false if not. The variants that take a relation OID
2428  * return NULL (rather than throwing an error) if that relation OID
2429  * doesn't exist. Likewise, the variants that take an integer attnum
2430  * return NULL (rather than throwing an error) if there is no such
2431  * pg_attribute entry. All variants return NULL if an attisdropped
2432  * column is selected. These rules are meant to avoid unnecessary
2433  * failures in queries that scan pg_attribute.
2434  */
2435 
2436 /*
2437  * column_privilege_check: check column privileges, but don't throw an error
2438  * for dropped column or table
2439  *
2440  * Returns 1 if have the privilege, 0 if not, -1 if dropped column/table.
2441  */
2442 static int
2444  Oid roleid, AclMode mode)
2445 {
2446  AclResult aclresult;
2447  bool is_missing = false;
2448 
2449  /*
2450  * If convert_column_name failed, we can just return -1 immediately.
2451  */
2452  if (attnum == InvalidAttrNumber)
2453  return -1;
2454 
2455  /*
2456  * Check for column-level privileges first. This serves in part as a check
2457  * on whether the column even exists, so we need to do it before checking
2458  * table-level privilege.
2459  */
2460  aclresult = pg_attribute_aclcheck_ext(tableoid, attnum, roleid,
2461  mode, &is_missing);
2462  if (aclresult == ACLCHECK_OK)
2463  return 1;
2464  else if (is_missing)
2465  return -1;
2466 
2467  /* Next check if we have the privilege at the table level */
2468  aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
2469  if (aclresult == ACLCHECK_OK)
2470  return 1;
2471  else if (is_missing)
2472  return -1;
2473  else
2474  return 0;
2475 }
2476 
2477 /*
2478  * has_column_privilege_name_name_name
2479  * Check user privileges on a column given
2480  * name username, text tablename, text colname, and text priv name.
2481  */
2482 Datum
2484 {
2485  Name rolename = PG_GETARG_NAME(0);
2486  text *tablename = PG_GETARG_TEXT_PP(1);
2487  text *column = PG_GETARG_TEXT_PP(2);
2488  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2489  Oid roleid;
2490  Oid tableoid;
2491  AttrNumber colattnum;
2492  AclMode mode;
2493  int privresult;
2494 
2495  roleid = get_role_oid_or_public(NameStr(*rolename));
2496  tableoid = convert_table_name(tablename);
2497  colattnum = convert_column_name(tableoid, column);
2498  mode = convert_column_priv_string(priv_type_text);
2499 
2500  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2501  if (privresult < 0)
2502  PG_RETURN_NULL();
2503  PG_RETURN_BOOL(privresult);
2504 }
2505 
2506 /*
2507  * has_column_privilege_name_name_attnum
2508  * Check user privileges on a column given
2509  * name username, text tablename, int attnum, and text priv name.
2510  */
2511 Datum
2513 {
2514  Name rolename = PG_GETARG_NAME(0);
2515  text *tablename = PG_GETARG_TEXT_PP(1);
2516  AttrNumber colattnum = PG_GETARG_INT16(2);
2517  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2518  Oid roleid;
2519  Oid tableoid;
2520  AclMode mode;
2521  int privresult;
2522 
2523  roleid = get_role_oid_or_public(NameStr(*rolename));
2524  tableoid = convert_table_name(tablename);
2525  mode = convert_column_priv_string(priv_type_text);
2526 
2527  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2528  if (privresult < 0)
2529  PG_RETURN_NULL();
2530  PG_RETURN_BOOL(privresult);
2531 }
2532 
2533 /*
2534  * has_column_privilege_name_id_name
2535  * Check user privileges on a column given
2536  * name username, table oid, text colname, and text priv name.
2537  */
2538 Datum
2540 {
2542  Oid tableoid = PG_GETARG_OID(1);
2543  text *column = PG_GETARG_TEXT_PP(2);
2544  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2545  Oid roleid;
2546  AttrNumber colattnum;
2547  AclMode mode;
2548  int privresult;
2549 
2550  roleid = get_role_oid_or_public(NameStr(*username));
2551  colattnum = convert_column_name(tableoid, column);
2552  mode = convert_column_priv_string(priv_type_text);
2553 
2554  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2555  if (privresult < 0)
2556  PG_RETURN_NULL();
2557  PG_RETURN_BOOL(privresult);
2558 }
2559 
2560 /*
2561  * has_column_privilege_name_id_attnum
2562  * Check user privileges on a column given
2563  * name username, table oid, int attnum, and text priv name.
2564  */
2565 Datum
2567 {
2569  Oid tableoid = PG_GETARG_OID(1);
2570  AttrNumber colattnum = PG_GETARG_INT16(2);
2571  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2572  Oid roleid;
2573  AclMode mode;
2574  int privresult;
2575 
2576  roleid = get_role_oid_or_public(NameStr(*username));
2577  mode = convert_column_priv_string(priv_type_text);
2578 
2579  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2580  if (privresult < 0)
2581  PG_RETURN_NULL();
2582  PG_RETURN_BOOL(privresult);
2583 }
2584 
2585 /*
2586  * has_column_privilege_id_name_name
2587  * Check user privileges on a column given
2588  * oid roleid, text tablename, text colname, and text priv name.
2589  */
2590 Datum
2592 {
2593  Oid roleid = PG_GETARG_OID(0);
2594  text *tablename = PG_GETARG_TEXT_PP(1);
2595  text *column = PG_GETARG_TEXT_PP(2);
2596  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2597  Oid tableoid;
2598  AttrNumber colattnum;
2599  AclMode mode;
2600  int privresult;
2601 
2602  tableoid = convert_table_name(tablename);
2603  colattnum = convert_column_name(tableoid, column);
2604  mode = convert_column_priv_string(priv_type_text);
2605 
2606  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2607  if (privresult < 0)
2608  PG_RETURN_NULL();
2609  PG_RETURN_BOOL(privresult);
2610 }
2611 
2612 /*
2613  * has_column_privilege_id_name_attnum
2614  * Check user privileges on a column given
2615  * oid roleid, text tablename, int attnum, and text priv name.
2616  */
2617 Datum
2619 {
2620  Oid roleid = PG_GETARG_OID(0);
2621  text *tablename = PG_GETARG_TEXT_PP(1);
2622  AttrNumber colattnum = PG_GETARG_INT16(2);
2623  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2624  Oid tableoid;
2625  AclMode mode;
2626  int privresult;
2627 
2628  tableoid = convert_table_name(tablename);
2629  mode = convert_column_priv_string(priv_type_text);
2630 
2631  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2632  if (privresult < 0)
2633  PG_RETURN_NULL();
2634  PG_RETURN_BOOL(privresult);
2635 }
2636 
2637 /*
2638  * has_column_privilege_id_id_name
2639  * Check user privileges on a column given
2640  * oid roleid, table oid, text colname, and text priv name.
2641  */
2642 Datum
2644 {
2645  Oid roleid = PG_GETARG_OID(0);
2646  Oid tableoid = PG_GETARG_OID(1);
2647  text *column = PG_GETARG_TEXT_PP(2);
2648  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2649  AttrNumber colattnum;
2650  AclMode mode;
2651  int privresult;
2652 
2653  colattnum = convert_column_name(tableoid, column);
2654  mode = convert_column_priv_string(priv_type_text);
2655 
2656  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2657  if (privresult < 0)
2658  PG_RETURN_NULL();
2659  PG_RETURN_BOOL(privresult);
2660 }
2661 
2662 /*
2663  * has_column_privilege_id_id_attnum
2664  * Check user privileges on a column given
2665  * oid roleid, table oid, int attnum, and text priv name.
2666  */
2667 Datum
2669 {
2670  Oid roleid = PG_GETARG_OID(0);
2671  Oid tableoid = PG_GETARG_OID(1);
2672  AttrNumber colattnum = PG_GETARG_INT16(2);
2673  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2674  AclMode mode;
2675  int privresult;
2676 
2677  mode = convert_column_priv_string(priv_type_text);
2678 
2679  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2680  if (privresult < 0)
2681  PG_RETURN_NULL();
2682  PG_RETURN_BOOL(privresult);
2683 }
2684 
2685 /*
2686  * has_column_privilege_name_name
2687  * Check user privileges on a column given
2688  * text tablename, text colname, and text priv name.
2689  * current_user is assumed
2690  */
2691 Datum
2693 {
2694  text *tablename = PG_GETARG_TEXT_PP(0);
2695  text *column = PG_GETARG_TEXT_PP(1);
2696  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2697  Oid roleid;
2698  Oid tableoid;
2699  AttrNumber colattnum;
2700  AclMode mode;
2701  int privresult;
2702 
2703  roleid = GetUserId();
2704  tableoid = convert_table_name(tablename);
2705  colattnum = convert_column_name(tableoid, column);
2706  mode = convert_column_priv_string(priv_type_text);
2707 
2708  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2709  if (privresult < 0)
2710  PG_RETURN_NULL();
2711  PG_RETURN_BOOL(privresult);
2712 }
2713 
2714 /*
2715  * has_column_privilege_name_attnum
2716  * Check user privileges on a column given
2717  * text tablename, int attnum, and text priv name.
2718  * current_user is assumed
2719  */
2720 Datum
2722 {
2723  text *tablename = PG_GETARG_TEXT_PP(0);
2724  AttrNumber colattnum = PG_GETARG_INT16(1);
2725  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2726  Oid roleid;
2727  Oid tableoid;
2728  AclMode mode;
2729  int privresult;
2730 
2731  roleid = GetUserId();
2732  tableoid = convert_table_name(tablename);
2733  mode = convert_column_priv_string(priv_type_text);
2734 
2735  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2736  if (privresult < 0)
2737  PG_RETURN_NULL();
2738  PG_RETURN_BOOL(privresult);
2739 }
2740 
2741 /*
2742  * has_column_privilege_id_name
2743  * Check user privileges on a column given
2744  * table oid, text colname, and text priv name.
2745  * current_user is assumed
2746  */
2747 Datum
2749 {
2750  Oid tableoid = PG_GETARG_OID(0);
2751  text *column = PG_GETARG_TEXT_PP(1);
2752  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2753  Oid roleid;
2754  AttrNumber colattnum;
2755  AclMode mode;
2756  int privresult;
2757 
2758  roleid = GetUserId();
2759  colattnum = convert_column_name(tableoid, column);
2760  mode = convert_column_priv_string(priv_type_text);
2761 
2762  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2763  if (privresult < 0)
2764  PG_RETURN_NULL();
2765  PG_RETURN_BOOL(privresult);
2766 }
2767 
2768 /*
2769  * has_column_privilege_id_attnum
2770  * Check user privileges on a column given
2771  * table oid, int attnum, and text priv name.
2772  * current_user is assumed
2773  */
2774 Datum
2776 {
2777  Oid tableoid = PG_GETARG_OID(0);
2778  AttrNumber colattnum = PG_GETARG_INT16(1);
2779  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2780  Oid roleid;
2781  AclMode mode;
2782  int privresult;
2783 
2784  roleid = GetUserId();
2785  mode = convert_column_priv_string(priv_type_text);
2786 
2787  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2788  if (privresult < 0)
2789  PG_RETURN_NULL();
2790  PG_RETURN_BOOL(privresult);
2791 }
2792 
2793 /*
2794  * Support routines for has_column_privilege family.
2795  */
2796 
2797 /*
2798  * Given a table OID and a column name expressed as a string, look it up
2799  * and return the column number. Returns InvalidAttrNumber in cases
2800  * where caller should return NULL instead of failing.
2801  */
2802 static AttrNumber
2803 convert_column_name(Oid tableoid, text *column)
2804 {
2805  char *colname;
2806  HeapTuple attTuple;
2808 
2809  colname = text_to_cstring(column);
2810 
2811  /*
2812  * We don't use get_attnum() here because it will report that dropped
2813  * columns don't exist. We need to treat dropped columns differently from
2814  * nonexistent columns.
2815  */
2816  attTuple = SearchSysCache2(ATTNAME,
2817  ObjectIdGetDatum(tableoid),
2818  CStringGetDatum(colname));
2819  if (HeapTupleIsValid(attTuple))
2820  {
2821  Form_pg_attribute attributeForm;
2822 
2823  attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
2824  /* We want to return NULL for dropped columns */
2825  if (attributeForm->attisdropped)
2826  attnum = InvalidAttrNumber;
2827  else
2828  attnum = attributeForm->attnum;
2829  ReleaseSysCache(attTuple);
2830  }
2831  else
2832  {
2833  char *tablename = get_rel_name(tableoid);
2834 
2835  /*
2836  * If the table OID is bogus, or it's just been dropped, we'll get
2837  * NULL back. In such cases we want has_column_privilege to return
2838  * NULL too, so just return InvalidAttrNumber.
2839  */
2840  if (tablename != NULL)
2841  {
2842  /* tableoid exists, colname does not, so throw error */
2843  ereport(ERROR,
2844  (errcode(ERRCODE_UNDEFINED_COLUMN),
2845  errmsg("column \"%s\" of relation \"%s\" does not exist",
2846  colname, tablename)));
2847  }
2848  /* tableoid doesn't exist, so act like attisdropped case */
2849  attnum = InvalidAttrNumber;
2850  }
2851 
2852  pfree(colname);
2853  return attnum;
2854 }
2855 
2856 /*
2857  * convert_column_priv_string
2858  * Convert text string to AclMode value.
2859  */
2860 static AclMode
2862 {
2863  static const priv_map column_priv_map[] = {
2864  {"SELECT", ACL_SELECT},
2865  {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
2866  {"INSERT", ACL_INSERT},
2867  {"INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT)},
2868  {"UPDATE", ACL_UPDATE},
2869  {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
2870  {"REFERENCES", ACL_REFERENCES},
2871  {"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
2872  {NULL, 0}
2873  };
2874 
2875  return convert_any_priv_string(priv_type_text, column_priv_map);
2876 }
2877 
2878 
2879 /*
2880  * has_database_privilege variants
2881  * These are all named "has_database_privilege" at the SQL level.
2882  * They take various combinations of database name, database OID,
2883  * user name, user OID, or implicit user = current_user.
2884  *
2885  * The result is a boolean value: true if user has the indicated
2886  * privilege, false if not, or NULL if object doesn't exist.
2887  */
2888 
2889 /*
2890  * has_database_privilege_name_name
2891  * Check user privileges on a database given
2892  * name username, text databasename, and text priv name.
2893  */
2894 Datum
2896 {
2898  text *databasename = PG_GETARG_TEXT_PP(1);
2899  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2900  Oid roleid;
2901  Oid databaseoid;
2902  AclMode mode;
2903  AclResult aclresult;
2904 
2905  roleid = get_role_oid_or_public(NameStr(*username));
2906  databaseoid = convert_database_name(databasename);
2907  mode = convert_database_priv_string(priv_type_text);
2908 
2909  aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
2910 
2911  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2912 }
2913 
2914 /*
2915  * has_database_privilege_name
2916  * Check user privileges on a database given
2917  * text databasename and text priv name.
2918  * current_user is assumed
2919  */
2920 Datum
2922 {
2923  text *databasename = PG_GETARG_TEXT_PP(0);
2924  text *priv_type_text = PG_GETARG_TEXT_PP(1);
2925  Oid roleid;
2926  Oid databaseoid;
2927  AclMode mode;
2928  AclResult aclresult;
2929 
2930  roleid = GetUserId();
2931  databaseoid = convert_database_name(databasename);
2932  mode = convert_database_priv_string(priv_type_text);
2933 
2934  aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
2935 
2936  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2937 }
2938 
2939 /*
2940  * has_database_privilege_name_id
2941  * Check user privileges on a database given
2942  * name usename, database oid, and text priv name.
2943  */
2944 Datum
2946 {
2948  Oid databaseoid = PG_GETARG_OID(1);
2949  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2950  Oid roleid;
2951  AclMode mode;
2952  AclResult aclresult;
2953 
2954  roleid = get_role_oid_or_public(NameStr(*username));
2955  mode = convert_database_priv_string(priv_type_text);
2956 
2958  PG_RETURN_NULL();
2959 
2960  aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
2961 
2962  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2963 }
2964 
2965 /*
2966  * has_database_privilege_id
2967  * Check user privileges on a database given
2968  * database oid, and text priv name.
2969  * current_user is assumed
2970  */
2971 Datum
2973 {
2974  Oid databaseoid = PG_GETARG_OID(0);
2975  text *priv_type_text = PG_GETARG_TEXT_PP(1);
2976  Oid roleid;
2977  AclMode mode;
2978  AclResult aclresult;
2979 
2980  roleid = GetUserId();
2981  mode = convert_database_priv_string(priv_type_text);
2982 
2984  PG_RETURN_NULL();
2985 
2986  aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
2987 
2988  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2989 }
2990 
2991 /*
2992  * has_database_privilege_id_name
2993  * Check user privileges on a database given
2994  * roleid, text databasename, and text priv name.
2995  */
2996 Datum
2998 {
2999  Oid roleid = PG_GETARG_OID(0);
3000  text *databasename = PG_GETARG_TEXT_PP(1);
3001  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3002  Oid databaseoid;
3003  AclMode mode;
3004  AclResult aclresult;
3005 
3006  databaseoid = convert_database_name(databasename);
3007  mode = convert_database_priv_string(priv_type_text);
3008 
3009  aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
3010 
3011  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3012 }
3013 
3014 /*
3015  * has_database_privilege_id_id
3016  * Check user privileges on a database given
3017  * roleid, database oid, and text priv name.
3018  */
3019 Datum
3021 {
3022  Oid roleid = PG_GETARG_OID(0);
3023  Oid databaseoid = PG_GETARG_OID(1);
3024  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3025  AclMode mode;
3026  AclResult aclresult;
3027 
3028  mode = convert_database_priv_string(priv_type_text);
3029 
3031  PG_RETURN_NULL();
3032 
3033  aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
3034 
3035  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3036 }
3037 
3038 /*
3039  * Support routines for has_database_privilege family.
3040  */
3041 
3042 /*
3043  * Given a database name expressed as a string, look it up and return Oid
3044  */
3045 static Oid
3047 {
3048  char *dbname = text_to_cstring(databasename);
3049 
3050  return get_database_oid(dbname, false);
3051 }
3052 
3053 /*
3054  * convert_database_priv_string
3055  * Convert text string to AclMode value.
3056  */
3057 static AclMode
3059 {
3060  static const priv_map database_priv_map[] = {
3061  {"CREATE", ACL_CREATE},
3062  {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
3063  {"TEMPORARY", ACL_CREATE_TEMP},
3064  {"TEMPORARY WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP)},
3065  {"TEMP", ACL_CREATE_TEMP},
3066  {"TEMP WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP)},
3067  {"CONNECT", ACL_CONNECT},
3068  {"CONNECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CONNECT)},
3069  {NULL, 0}
3070  };
3071 
3072  return convert_any_priv_string(priv_type_text, database_priv_map);
3073 
3074 }
3075 
3076 
3077 /*
3078  * has_foreign_data_wrapper_privilege variants
3079  * These are all named "has_foreign_data_wrapper_privilege" at the SQL level.
3080  * They take various combinations of foreign-data wrapper name,
3081  * fdw OID, user name, user OID, or implicit user = current_user.
3082  *
3083  * The result is a boolean value: true if user has the indicated
3084  * privilege, false if not.
3085  */
3086 
3087 /*
3088  * has_foreign_data_wrapper_privilege_name_name
3089  * Check user privileges on a foreign-data wrapper given
3090  * name username, text fdwname, and text priv name.
3091  */
3092 Datum
3094 {
3096  text *fdwname = PG_GETARG_TEXT_PP(1);
3097  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3098  Oid roleid;
3099  Oid fdwid;
3100  AclMode mode;
3101  AclResult aclresult;
3102 
3103  roleid = get_role_oid_or_public(NameStr(*username));
3104  fdwid = convert_foreign_data_wrapper_name(fdwname);
3105  mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
3106 
3107  aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
3108 
3109  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3110 }
3111 
3112 /*
3113  * has_foreign_data_wrapper_privilege_name
3114  * Check user privileges on a foreign-data wrapper given
3115  * text fdwname and text priv name.
3116  * current_user is assumed
3117  */
3118 Datum
3120 {
3121  text *fdwname = PG_GETARG_TEXT_PP(0);
3122  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3123  Oid roleid;
3124  Oid fdwid;
3125  AclMode mode;
3126  AclResult aclresult;
3127 
3128  roleid = GetUserId();
3129  fdwid = convert_foreign_data_wrapper_name(fdwname);
3130  mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
3131 
3132  aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
3133 
3134  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3135 }
3136 
3137 /*
3138  * has_foreign_data_wrapper_privilege_name_id
3139  * Check user privileges on a foreign-data wrapper given
3140  * name usename, foreign-data wrapper oid, and text priv name.
3141  */
3142 Datum
3144 {
3146  Oid fdwid = PG_GETARG_OID(1);
3147  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3148  Oid roleid;
3149  AclMode mode;
3150  AclResult aclresult;
3151 
3152  roleid = get_role_oid_or_public(NameStr(*username));
3153  mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
3154 
3156  PG_RETURN_NULL();
3157 
3158  aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
3159 
3160  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3161 }
3162 
3163 /*
3164  * has_foreign_data_wrapper_privilege_id
3165  * Check user privileges on a foreign-data wrapper given
3166  * foreign-data wrapper oid, and text priv name.
3167  * current_user is assumed
3168  */
3169 Datum
3171 {
3172  Oid fdwid = PG_GETARG_OID(0);
3173  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3174  Oid roleid;
3175  AclMode mode;
3176  AclResult aclresult;
3177 
3178  roleid = GetUserId();
3179  mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
3180 
3182  PG_RETURN_NULL();
3183 
3184  aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
3185 
3186  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3187 }
3188 
3189 /*
3190  * has_foreign_data_wrapper_privilege_id_name
3191  * Check user privileges on a foreign-data wrapper given
3192  * roleid, text fdwname, and text priv name.
3193  */
3194 Datum
3196 {
3197  Oid roleid = PG_GETARG_OID(0);
3198  text *fdwname = PG_GETARG_TEXT_PP(1);
3199  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3200  Oid fdwid;
3201  AclMode mode;
3202  AclResult aclresult;
3203 
3204  fdwid = convert_foreign_data_wrapper_name(fdwname);
3205  mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
3206 
3207  aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
3208 
3209  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3210 }
3211 
3212 /*
3213  * has_foreign_data_wrapper_privilege_id_id
3214  * Check user privileges on a foreign-data wrapper given
3215  * roleid, fdw oid, and text priv name.
3216  */
3217 Datum
3219 {
3220  Oid roleid = PG_GETARG_OID(0);
3221  Oid fdwid = PG_GETARG_OID(1);
3222  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3223  AclMode mode;
3224  AclResult aclresult;
3225 
3226  mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
3227 
3229  PG_RETURN_NULL();
3230 
3231  aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
3232 
3233  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3234 }
3235 
3236 /*
3237  * Support routines for has_foreign_data_wrapper_privilege family.
3238  */
3239 
3240 /*
3241  * Given a FDW name expressed as a string, look it up and return Oid
3242  */
3243 static Oid
3245 {
3246  char *fdwstr = text_to_cstring(fdwname);
3247 
3248  return get_foreign_data_wrapper_oid(fdwstr, false);
3249 }
3250 
3251 /*
3252  * convert_foreign_data_wrapper_priv_string
3253  * Convert text string to AclMode value.
3254  */
3255 static AclMode
3257 {
3258  static const priv_map foreign_data_wrapper_priv_map[] = {
3259  {"USAGE", ACL_USAGE},
3260  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
3261  {NULL, 0}
3262  };
3263 
3264  return convert_any_priv_string(priv_type_text, foreign_data_wrapper_priv_map);
3265 }
3266 
3267 
3268 /*
3269  * has_function_privilege variants
3270  * These are all named "has_function_privilege" at the SQL level.
3271  * They take various combinations of function name, function OID,
3272  * user name, user OID, or implicit user = current_user.
3273  *
3274  * The result is a boolean value: true if user has the indicated
3275  * privilege, false if not, or NULL if object doesn't exist.
3276  */
3277 
3278 /*
3279  * has_function_privilege_name_name
3280  * Check user privileges on a function given
3281  * name username, text functionname, and text priv name.
3282  */
3283 Datum
3285 {
3287  text *functionname = PG_GETARG_TEXT_PP(1);
3288  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3289  Oid roleid;
3290  Oid functionoid;
3291  AclMode mode;
3292  AclResult aclresult;
3293 
3294  roleid = get_role_oid_or_public(NameStr(*username));
3295  functionoid = convert_function_name(functionname);
3296  mode = convert_function_priv_string(priv_type_text);
3297 
3298  aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
3299 
3300  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3301 }
3302 
3303 /*
3304  * has_function_privilege_name
3305  * Check user privileges on a function given
3306  * text functionname and text priv name.
3307  * current_user is assumed
3308  */
3309 Datum
3311 {
3312  text *functionname = PG_GETARG_TEXT_PP(0);
3313  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3314  Oid roleid;
3315  Oid functionoid;
3316  AclMode mode;
3317  AclResult aclresult;
3318 
3319  roleid = GetUserId();
3320  functionoid = convert_function_name(functionname);
3321  mode = convert_function_priv_string(priv_type_text);
3322 
3323  aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
3324 
3325  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3326 }
3327 
3328 /*
3329  * has_function_privilege_name_id
3330  * Check user privileges on a function given
3331  * name usename, function oid, and text priv name.
3332  */
3333 Datum
3335 {
3337  Oid functionoid = PG_GETARG_OID(1);
3338  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3339  Oid roleid;
3340  AclMode mode;
3341  AclResult aclresult;
3342 
3343  roleid = get_role_oid_or_public(NameStr(*username));
3344  mode = convert_function_priv_string(priv_type_text);
3345 
3346  if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(functionoid)))
3347  PG_RETURN_NULL();
3348 
3349  aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
3350 
3351  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3352 }
3353 
3354 /*
3355  * has_function_privilege_id
3356  * Check user privileges on a function given
3357  * function oid, and text priv name.
3358  * current_user is assumed
3359  */
3360 Datum
3362 {
3363  Oid functionoid = PG_GETARG_OID(0);
3364  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3365  Oid roleid;
3366  AclMode mode;
3367  AclResult aclresult;
3368 
3369  roleid = GetUserId();
3370  mode = convert_function_priv_string(priv_type_text);
3371 
3372  if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(functionoid)))
3373  PG_RETURN_NULL();
3374 
3375  aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
3376 
3377  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3378 }
3379 
3380 /*
3381  * has_function_privilege_id_name
3382  * Check user privileges on a function given
3383  * roleid, text functionname, and text priv name.
3384  */
3385 Datum
3387 {
3388  Oid roleid = PG_GETARG_OID(0);
3389  text *functionname = PG_GETARG_TEXT_PP(1);
3390  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3391  Oid functionoid;
3392  AclMode mode;
3393  AclResult aclresult;
3394 
3395  functionoid = convert_function_name(functionname);
3396  mode = convert_function_priv_string(priv_type_text);
3397 
3398  aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
3399 
3400  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3401 }
3402 
3403 /*
3404  * has_function_privilege_id_id
3405  * Check user privileges on a function given
3406  * roleid, function oid, and text priv name.
3407  */
3408 Datum
3410 {
3411  Oid roleid = PG_GETARG_OID(0);
3412  Oid functionoid = PG_GETARG_OID(1);
3413  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3414  AclMode mode;
3415  AclResult aclresult;
3416 
3417  mode = convert_function_priv_string(priv_type_text);
3418 
3419  if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(functionoid)))
3420  PG_RETURN_NULL();
3421 
3422  aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
3423 
3424  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3425 }
3426 
3427 /*
3428  * Support routines for has_function_privilege family.
3429  */
3430 
3431 /*
3432  * Given a function name expressed as a string, look it up and return Oid
3433  */
3434 static Oid
3436 {
3437  char *funcname = text_to_cstring(functionname);
3438  Oid oid;
3439 
3441  CStringGetDatum(funcname)));
3442 
3443  if (!OidIsValid(oid))
3444  ereport(ERROR,
3445  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3446  errmsg("function \"%s\" does not exist", funcname)));
3447 
3448  return oid;
3449 }
3450 
3451 /*
3452  * convert_function_priv_string
3453  * Convert text string to AclMode value.
3454  */
3455 static AclMode
3457 {
3458  static const priv_map function_priv_map[] = {
3459  {"EXECUTE", ACL_EXECUTE},
3460  {"EXECUTE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_EXECUTE)},
3461  {NULL, 0}
3462  };
3463 
3464  return convert_any_priv_string(priv_type_text, function_priv_map);
3465 }
3466 
3467 
3468 /*
3469  * has_language_privilege variants
3470  * These are all named "has_language_privilege" at the SQL level.
3471  * They take various combinations of language name, language OID,
3472  * user name, user OID, or implicit user = current_user.
3473  *
3474  * The result is a boolean value: true if user has the indicated
3475  * privilege, false if not, or NULL if object doesn't exist.
3476  */
3477 
3478 /*
3479  * has_language_privilege_name_name
3480  * Check user privileges on a language given
3481  * name username, text languagename, and text priv name.
3482  */
3483 Datum
3485 {
3487  text *languagename = PG_GETARG_TEXT_PP(1);
3488  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3489  Oid roleid;
3490  Oid languageoid;
3491  AclMode mode;
3492  AclResult aclresult;
3493 
3494  roleid = get_role_oid_or_public(NameStr(*username));
3495  languageoid = convert_language_name(languagename);
3496  mode = convert_language_priv_string(priv_type_text);
3497 
3498  aclresult = pg_language_aclcheck(languageoid, roleid, mode);
3499 
3500  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3501 }
3502 
3503 /*
3504  * has_language_privilege_name
3505  * Check user privileges on a language given
3506  * text languagename and text priv name.
3507  * current_user is assumed
3508  */
3509 Datum
3511 {
3512  text *languagename = PG_GETARG_TEXT_PP(0);
3513  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3514  Oid roleid;
3515  Oid languageoid;
3516  AclMode mode;
3517  AclResult aclresult;
3518 
3519  roleid = GetUserId();
3520  languageoid = convert_language_name(languagename);
3521  mode = convert_language_priv_string(priv_type_text);
3522 
3523  aclresult = pg_language_aclcheck(languageoid, roleid, mode);
3524 
3525  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3526 }
3527 
3528 /*
3529  * has_language_privilege_name_id
3530  * Check user privileges on a language given
3531  * name usename, language oid, and text priv name.
3532  */
3533 Datum
3535 {
3537  Oid languageoid = PG_GETARG_OID(1);
3538  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3539  Oid roleid;
3540  AclMode mode;
3541  AclResult aclresult;
3542 
3543  roleid = get_role_oid_or_public(NameStr(*username));
3544  mode = convert_language_priv_string(priv_type_text);
3545 
3546  if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
3547  PG_RETURN_NULL();
3548 
3549  aclresult = pg_language_aclcheck(languageoid, roleid, mode);
3550 
3551  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3552 }
3553 
3554 /*
3555  * has_language_privilege_id
3556  * Check user privileges on a language given
3557  * language oid, and text priv name.
3558  * current_user is assumed
3559  */
3560 Datum
3562 {
3563  Oid languageoid = PG_GETARG_OID(0);
3564  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3565  Oid roleid;
3566  AclMode mode;
3567  AclResult aclresult;
3568 
3569  roleid = GetUserId();
3570  mode = convert_language_priv_string(priv_type_text);
3571 
3572  if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
3573  PG_RETURN_NULL();
3574 
3575  aclresult = pg_language_aclcheck(languageoid, roleid, mode);
3576 
3577  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3578 }
3579 
3580 /*
3581  * has_language_privilege_id_name
3582  * Check user privileges on a language given
3583  * roleid, text languagename, and text priv name.
3584  */
3585 Datum
3587 {
3588  Oid roleid = PG_GETARG_OID(0);
3589  text *languagename = PG_GETARG_TEXT_PP(1);
3590  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3591  Oid languageoid;
3592  AclMode mode;
3593  AclResult aclresult;
3594 
3595  languageoid = convert_language_name(languagename);
3596  mode = convert_language_priv_string(priv_type_text);
3597 
3598  aclresult = pg_language_aclcheck(languageoid, roleid, mode);
3599 
3600  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3601 }
3602 
3603 /*
3604  * has_language_privilege_id_id
3605  * Check user privileges on a language given
3606  * roleid, language oid, and text priv name.
3607  */
3608 Datum
3610 {
3611  Oid roleid = PG_GETARG_OID(0);
3612  Oid languageoid = PG_GETARG_OID(1);
3613  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3614  AclMode mode;
3615  AclResult aclresult;
3616 
3617  mode = convert_language_priv_string(priv_type_text);
3618 
3619  if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
3620  PG_RETURN_NULL();
3621 
3622  aclresult = pg_language_aclcheck(languageoid, roleid, mode);
3623 
3624  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3625 }
3626 
3627 /*
3628  * Support routines for has_language_privilege family.
3629  */
3630 
3631 /*
3632  * Given a language name expressed as a string, look it up and return Oid
3633  */
3634 static Oid
3636 {
3637  char *langname = text_to_cstring(languagename);
3638 
3639  return get_language_oid(langname, false);
3640 }
3641 
3642 /*
3643  * convert_language_priv_string
3644  * Convert text string to AclMode value.
3645  */
3646 static AclMode
3648 {
3649  static const priv_map language_priv_map[] = {
3650  {"USAGE", ACL_USAGE},
3651  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
3652  {NULL, 0}
3653  };
3654 
3655  return convert_any_priv_string(priv_type_text, language_priv_map);
3656 }
3657 
3658 
3659 /*
3660  * has_schema_privilege variants
3661  * These are all named "has_schema_privilege" at the SQL level.
3662  * They take various combinations of schema name, schema OID,
3663  * user name, user OID, or implicit user = current_user.
3664  *
3665  * The result is a boolean value: true if user has the indicated
3666  * privilege, false if not, or NULL if object doesn't exist.
3667  */
3668 
3669 /*
3670  * has_schema_privilege_name_name
3671  * Check user privileges on a schema given
3672  * name username, text schemaname, and text priv name.
3673  */
3674 Datum
3676 {
3678  text *schemaname = PG_GETARG_TEXT_PP(1);
3679  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3680  Oid roleid;
3681  Oid schemaoid;
3682  AclMode mode;
3683  AclResult aclresult;
3684 
3685  roleid = get_role_oid_or_public(NameStr(*username));
3686  schemaoid = convert_schema_name(schemaname);
3687  mode = convert_schema_priv_string(priv_type_text);
3688 
3689  aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
3690 
3691  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3692 }
3693 
3694 /*
3695  * has_schema_privilege_name
3696  * Check user privileges on a schema given
3697  * text schemaname and text priv name.
3698  * current_user is assumed
3699  */
3700 Datum
3702 {
3703  text *schemaname = PG_GETARG_TEXT_PP(0);
3704  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3705  Oid roleid;
3706  Oid schemaoid;
3707  AclMode mode;
3708  AclResult aclresult;
3709 
3710  roleid = GetUserId();
3711  schemaoid = convert_schema_name(schemaname);
3712  mode = convert_schema_priv_string(priv_type_text);
3713 
3714  aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
3715 
3716  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3717 }
3718 
3719 /*
3720  * has_schema_privilege_name_id
3721  * Check user privileges on a schema given
3722  * name usename, schema oid, and text priv name.
3723  */
3724 Datum
3726 {
3728  Oid schemaoid = PG_GETARG_OID(1);
3729  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3730  Oid roleid;
3731  AclMode mode;
3732  AclResult aclresult;
3733 
3734  roleid = get_role_oid_or_public(NameStr(*username));
3735  mode = convert_schema_priv_string(priv_type_text);
3736 
3738  PG_RETURN_NULL();
3739 
3740  aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
3741 
3742  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3743 }
3744 
3745 /*
3746  * has_schema_privilege_id
3747  * Check user privileges on a schema given
3748  * schema oid, and text priv name.
3749  * current_user is assumed
3750  */
3751 Datum
3753 {
3754  Oid schemaoid = PG_GETARG_OID(0);
3755  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3756  Oid roleid;
3757  AclMode mode;
3758  AclResult aclresult;
3759 
3760  roleid = GetUserId();
3761  mode = convert_schema_priv_string(priv_type_text);
3762 
3764  PG_RETURN_NULL();
3765 
3766  aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
3767 
3768  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3769 }
3770 
3771 /*
3772  * has_schema_privilege_id_name
3773  * Check user privileges on a schema given
3774  * roleid, text schemaname, and text priv name.
3775  */
3776 Datum
3778 {
3779  Oid roleid = PG_GETARG_OID(0);
3780  text *schemaname = PG_GETARG_TEXT_PP(1);
3781  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3782  Oid schemaoid;
3783  AclMode mode;
3784  AclResult aclresult;
3785 
3786  schemaoid = convert_schema_name(schemaname);
3787  mode = convert_schema_priv_string(priv_type_text);
3788 
3789  aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
3790 
3791  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3792 }
3793 
3794 /*
3795  * has_schema_privilege_id_id
3796  * Check user privileges on a schema given
3797  * roleid, schema oid, and text priv name.
3798  */
3799 Datum
3801 {
3802  Oid roleid = PG_GETARG_OID(0);
3803  Oid schemaoid = PG_GETARG_OID(1);
3804  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3805  AclMode mode;
3806  AclResult aclresult;
3807 
3808  mode = convert_schema_priv_string(priv_type_text);
3809 
3811  PG_RETURN_NULL();
3812 
3813  aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
3814 
3815  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3816 }
3817 
3818 /*
3819  * Support routines for has_schema_privilege family.
3820  */
3821 
3822 /*
3823  * Given a schema name expressed as a string, look it up and return Oid
3824  */
3825 static Oid
3827 {
3828  char *nspname = text_to_cstring(schemaname);
3829 
3830  return get_namespace_oid(nspname, false);
3831 }
3832 
3833 /*
3834  * convert_schema_priv_string
3835  * Convert text string to AclMode value.
3836  */
3837 static AclMode
3839 {
3840  static const priv_map schema_priv_map[] = {
3841  {"CREATE", ACL_CREATE},
3842  {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
3843  {"USAGE", ACL_USAGE},
3844  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
3845  {NULL, 0}
3846  };
3847 
3848  return convert_any_priv_string(priv_type_text, schema_priv_map);
3849 }
3850 
3851 
3852 /*
3853  * has_server_privilege variants
3854  * These are all named "has_server_privilege" at the SQL level.
3855  * They take various combinations of foreign server name,
3856  * server OID, user name, user OID, or implicit user = current_user.
3857  *
3858  * The result is a boolean value: true if user has the indicated
3859  * privilege, false if not.
3860  */
3861 
3862 /*
3863  * has_server_privilege_name_name
3864  * Check user privileges on a foreign server given
3865  * name username, text servername, and text priv name.
3866  */
3867 Datum
3869 {
3871  text *servername = PG_GETARG_TEXT_PP(1);
3872  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3873  Oid roleid;
3874  Oid serverid;
3875  AclMode mode;
3876  AclResult aclresult;
3877 
3878  roleid = get_role_oid_or_public(NameStr(*username));
3879  serverid = convert_server_name(servername);
3880  mode = convert_server_priv_string(priv_type_text);
3881 
3882  aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
3883 
3884  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3885 }
3886 
3887 /*
3888  * has_server_privilege_name
3889  * Check user privileges on a foreign server given
3890  * text servername and text priv name.
3891  * current_user is assumed
3892  */
3893 Datum
3895 {
3896  text *servername = PG_GETARG_TEXT_PP(0);
3897  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3898  Oid roleid;
3899  Oid serverid;
3900  AclMode mode;
3901  AclResult aclresult;
3902 
3903  roleid = GetUserId();
3904  serverid = convert_server_name(servername);
3905  mode = convert_server_priv_string(priv_type_text);
3906 
3907  aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
3908 
3909  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3910 }
3911 
3912 /*
3913  * has_server_privilege_name_id
3914  * Check user privileges on a foreign server given
3915  * name usename, foreign server oid, and text priv name.
3916  */
3917 Datum
3919 {
3921  Oid serverid = PG_GETARG_OID(1);
3922  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3923  Oid roleid;
3924  AclMode mode;
3925  AclResult aclresult;
3926 
3927  roleid = get_role_oid_or_public(NameStr(*username));
3928  mode = convert_server_priv_string(priv_type_text);
3929 
3931  PG_RETURN_NULL();
3932 
3933  aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
3934 
3935  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3936 }
3937 
3938 /*
3939  * has_server_privilege_id
3940  * Check user privileges on a foreign server given
3941  * server oid, and text priv name.
3942  * current_user is assumed
3943  */
3944 Datum
3946 {
3947  Oid serverid = PG_GETARG_OID(0);
3948  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3949  Oid roleid;
3950  AclMode mode;
3951  AclResult aclresult;
3952 
3953  roleid = GetUserId();
3954  mode = convert_server_priv_string(priv_type_text);
3955 
3957  PG_RETURN_NULL();
3958 
3959  aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
3960 
3961  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3962 }
3963 
3964 /*
3965  * has_server_privilege_id_name
3966  * Check user privileges on a foreign server given
3967  * roleid, text servername, and text priv name.
3968  */
3969 Datum
3971 {
3972  Oid roleid = PG_GETARG_OID(0);
3973  text *servername = PG_GETARG_TEXT_PP(1);
3974  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3975  Oid serverid;
3976  AclMode mode;
3977  AclResult aclresult;
3978 
3979  serverid = convert_server_name(servername);
3980  mode = convert_server_priv_string(priv_type_text);
3981 
3982  aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
3983 
3984  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3985 }
3986 
3987 /*
3988  * has_server_privilege_id_id
3989  * Check user privileges on a foreign server given
3990  * roleid, server oid, and text priv name.
3991  */
3992 Datum
3994 {
3995  Oid roleid = PG_GETARG_OID(0);
3996  Oid serverid = PG_GETARG_OID(1);
3997  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3998  AclMode mode;
3999  AclResult aclresult;
4000 
4001  mode = convert_server_priv_string(priv_type_text);
4002 
4004  PG_RETURN_NULL();
4005 
4006  aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
4007 
4008  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4009 }
4010 
4011 /*
4012  * Support routines for has_server_privilege family.
4013  */
4014 
4015 /*
4016  * Given a server name expressed as a string, look it up and return Oid
4017  */
4018 static Oid
4020 {
4021  char *serverstr = text_to_cstring(servername);
4022 
4023  return get_foreign_server_oid(serverstr, false);
4024 }
4025 
4026 /*
4027  * convert_server_priv_string
4028  * Convert text string to AclMode value.
4029  */
4030 static AclMode
4032 {
4033  static const priv_map server_priv_map[] = {
4034  {"USAGE", ACL_USAGE},
4035  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
4036  {NULL, 0}
4037  };
4038 
4039  return convert_any_priv_string(priv_type_text, server_priv_map);
4040 }
4041 
4042 
4043 /*
4044  * has_tablespace_privilege variants
4045  * These are all named "has_tablespace_privilege" at the SQL level.
4046  * They take various combinations of tablespace name, tablespace OID,
4047  * user name, user OID, or implicit user = current_user.
4048  *
4049  * The result is a boolean value: true if user has the indicated
4050  * privilege, false if not.
4051  */
4052 
4053 /*
4054  * has_tablespace_privilege_name_name
4055  * Check user privileges on a tablespace given
4056  * name username, text tablespacename, and text priv name.
4057  */
4058 Datum
4060 {
4062  text *tablespacename = PG_GETARG_TEXT_PP(1);
4063  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4064  Oid roleid;
4065  Oid tablespaceoid;
4066  AclMode mode;
4067  AclResult aclresult;
4068 
4069  roleid = get_role_oid_or_public(NameStr(*username));
4070  tablespaceoid = convert_tablespace_name(tablespacename);
4071  mode = convert_tablespace_priv_string(priv_type_text);
4072 
4073  aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
4074 
4075  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4076 }
4077 
4078 /*
4079  * has_tablespace_privilege_name
4080  * Check user privileges on a tablespace given
4081  * text tablespacename and text priv name.
4082  * current_user is assumed
4083  */
4084 Datum
4086 {
4087  text *tablespacename = PG_GETARG_TEXT_PP(0);
4088  text *priv_type_text = PG_GETARG_TEXT_PP(1);
4089  Oid roleid;
4090  Oid tablespaceoid;
4091  AclMode mode;
4092  AclResult aclresult;
4093 
4094  roleid = GetUserId();
4095  tablespaceoid = convert_tablespace_name(tablespacename);
4096  mode = convert_tablespace_priv_string(priv_type_text);
4097 
4098  aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
4099 
4100  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4101 }
4102 
4103 /*
4104  * has_tablespace_privilege_name_id
4105  * Check user privileges on a tablespace given
4106  * name usename, tablespace oid, and text priv name.
4107  */
4108 Datum
4110 {
4112  Oid tablespaceoid = PG_GETARG_OID(1);
4113  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4114  Oid roleid;
4115  AclMode mode;
4116  AclResult aclresult;
4117 
4118  roleid = get_role_oid_or_public(NameStr(*username));
4119  mode = convert_tablespace_priv_string(priv_type_text);
4120 
4122  PG_RETURN_NULL();
4123 
4124  aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
4125 
4126  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4127 }
4128 
4129 /*
4130  * has_tablespace_privilege_id
4131  * Check user privileges on a tablespace given
4132  * tablespace oid, and text priv name.
4133  * current_user is assumed
4134  */
4135 Datum
4137 {
4138  Oid tablespaceoid = PG_GETARG_OID(0);
4139  text *priv_type_text = PG_GETARG_TEXT_PP(1);
4140  Oid roleid;
4141  AclMode mode;
4142  AclResult aclresult;
4143 
4144  roleid = GetUserId();
4145  mode = convert_tablespace_priv_string(priv_type_text);
4146 
4148  PG_RETURN_NULL();
4149 
4150  aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
4151 
4152  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4153 }
4154 
4155 /*
4156  * has_tablespace_privilege_id_name
4157  * Check user privileges on a tablespace given
4158  * roleid, text tablespacename, and text priv name.
4159  */
4160 Datum
4162 {
4163  Oid roleid = PG_GETARG_OID(0);
4164  text *tablespacename = PG_GETARG_TEXT_PP(1);
4165  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4166  Oid tablespaceoid;
4167  AclMode mode;
4168  AclResult aclresult;
4169 
4170  tablespaceoid = convert_tablespace_name(tablespacename);
4171  mode = convert_tablespace_priv_string(priv_type_text);
4172 
4173  aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
4174 
4175  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4176 }
4177 
4178 /*
4179  * has_tablespace_privilege_id_id
4180  * Check user privileges on a tablespace given
4181  * roleid, tablespace oid, and text priv name.
4182  */
4183 Datum
4185 {
4186  Oid roleid = PG_GETARG_OID(0);
4187  Oid tablespaceoid = PG_GETARG_OID(1);
4188  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4189  AclMode mode;
4190  AclResult aclresult;
4191 
4192  mode = convert_tablespace_priv_string(priv_type_text);
4193 
4195  PG_RETURN_NULL();
4196 
4197  aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
4198 
4199  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4200 }
4201 
4202 /*
4203  * Support routines for has_tablespace_privilege family.
4204  */
4205 
4206 /*
4207  * Given a tablespace name expressed as a string, look it up and return Oid
4208  */
4209 static Oid
4211 {
4212  char *spcname = text_to_cstring(tablespacename);
4213 
4214  return get_tablespace_oid(spcname, false);
4215 }
4216 
4217 /*
4218  * convert_tablespace_priv_string
4219  * Convert text string to AclMode value.
4220  */
4221 static AclMode
4223 {
4224  static const priv_map tablespace_priv_map[] = {
4225  {"CREATE", ACL_CREATE},
4226  {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4227  {NULL, 0}
4228  };
4229 
4230  return convert_any_priv_string(priv_type_text, tablespace_priv_map);
4231 }
4232 
4233 /*
4234  * has_type_privilege variants
4235  * These are all named "has_type_privilege" at the SQL level.
4236  * They take various combinations of type name, type OID,
4237  * user name, user OID, or implicit user = current_user.
4238  *
4239  * The result is a boolean value: true if user has the indicated
4240  * privilege, false if not, or NULL if object doesn't exist.
4241  */
4242 
4243 /*
4244  * has_type_privilege_name_name
4245  * Check user privileges on a type given
4246  * name username, text typename, and text priv name.
4247  */
4248 Datum
4250 {
4252  text *typename = PG_GETARG_TEXT_PP(1);
4253  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4254  Oid roleid;
4255  Oid typeoid;
4256  AclMode mode;
4257  AclResult aclresult;
4258 
4259  roleid = get_role_oid_or_public(NameStr(*username));
4260  typeoid = convert_type_name(typename);
4261  mode = convert_type_priv_string(priv_type_text);
4262 
4263  aclresult = pg_type_aclcheck(typeoid, roleid, mode);
4264 
4265  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4266 }
4267 
4268 /*
4269  * has_type_privilege_name
4270  * Check user privileges on a type given
4271  * text typename and text priv name.
4272  * current_user is assumed
4273  */
4274 Datum
4276 {
4277  text *typename = PG_GETARG_TEXT_PP(0);
4278  text *priv_type_text = PG_GETARG_TEXT_PP(1);
4279  Oid roleid;
4280  Oid typeoid;
4281  AclMode mode;
4282  AclResult aclresult;
4283 
4284  roleid = GetUserId();
4285  typeoid = convert_type_name(typename);
4286  mode = convert_type_priv_string(priv_type_text);
4287 
4288  aclresult = pg_type_aclcheck(typeoid, roleid, mode);
4289 
4290  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4291 }
4292 
4293 /*
4294  * has_type_privilege_name_id
4295  * Check user privileges on a type given
4296  * name usename, type oid, and text priv name.
4297  */
4298 Datum
4300 {
4302  Oid typeoid = PG_GETARG_OID(1);
4303  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4304  Oid roleid;
4305  AclMode mode;
4306  AclResult aclresult;
4307 
4308  roleid = get_role_oid_or_public(NameStr(*username));
4309  mode = convert_type_priv_string(priv_type_text);
4310 
4312  PG_RETURN_NULL();
4313 
4314  aclresult = pg_type_aclcheck(typeoid, roleid, mode);
4315 
4316  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4317 }
4318 
4319 /*
4320  * has_type_privilege_id
4321  * Check user privileges on a type given
4322  * type oid, and text priv name.
4323  * current_user is assumed
4324  */
4325 Datum
4327 {
4328  Oid typeoid = PG_GETARG_OID(0);
4329  text *priv_type_text = PG_GETARG_TEXT_PP(1);
4330  Oid roleid;
4331  AclMode mode;
4332  AclResult aclresult;
4333 
4334  roleid = GetUserId();
4335  mode = convert_type_priv_string(priv_type_text);
4336 
4338  PG_RETURN_NULL();
4339 
4340  aclresult = pg_type_aclcheck(typeoid, roleid, mode);
4341 
4342  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4343 }
4344 
4345 /*
4346  * has_type_privilege_id_name
4347  * Check user privileges on a type given
4348  * roleid, text typename, and text priv name.
4349  */
4350 Datum
4352 {
4353  Oid roleid = PG_GETARG_OID(0);
4354  text *typename = PG_GETARG_TEXT_PP(1);
4355  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4356  Oid typeoid;
4357  AclMode mode;
4358  AclResult aclresult;
4359 
4360  typeoid = convert_type_name(typename);
4361  mode = convert_type_priv_string(priv_type_text);
4362 
4363  aclresult = pg_type_aclcheck(typeoid, roleid, mode);
4364 
4365  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4366 }
4367 
4368 /*
4369  * has_type_privilege_id_id
4370  * Check user privileges on a type given
4371  * roleid, type oid, and text priv name.
4372  */
4373 Datum
4375 {
4376  Oid roleid = PG_GETARG_OID(0);
4377  Oid typeoid = PG_GETARG_OID(1);
4378  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4379  AclMode mode;
4380  AclResult aclresult;
4381 
4382  mode = convert_type_priv_string(priv_type_text);
4383 
4385  PG_RETURN_NULL();
4386 
4387  aclresult = pg_type_aclcheck(typeoid, roleid, mode);
4388 
4389  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4390 }
4391 
4392 /*
4393  * Support routines for has_type_privilege family.
4394  */
4395 
4396 /*
4397  * Given a type name expressed as a string, look it up and return Oid
4398  */
4399 static Oid
4401 {
4402  char *typname = text_to_cstring(typename);
4403  Oid oid;
4404 
4406  CStringGetDatum(typname)));
4407 
4408  if (!OidIsValid(oid))
4409  ereport(ERROR,
4410  (errcode(ERRCODE_UNDEFINED_OBJECT),
4411  errmsg("type \"%s\" does not exist", typname)));
4412 
4413  return oid;
4414 }
4415 
4416 /*
4417  * convert_type_priv_string
4418  * Convert text string to AclMode value.
4419  */
4420 static AclMode
4422 {
4423  static const priv_map type_priv_map[] = {
4424  {"USAGE", ACL_USAGE},
4425  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
4426  {NULL, 0}
4427  };
4428 
4429  return convert_any_priv_string(priv_type_text, type_priv_map);
4430 }
4431 
4432 
4433 /*
4434  * pg_has_role variants
4435  * These are all named "pg_has_role" at the SQL level.
4436  * They take various combinations of role name, role OID,
4437  * user name, user OID, or implicit user = current_user.
4438  *
4439  * The result is a boolean value: true if user has the indicated
4440  * privilege, false if not.
4441  */
4442 
4443 /*
4444  * pg_has_role_name_name
4445  * Check user privileges on a role given
4446  * name username, name rolename, and text priv name.
4447  */
4448 Datum
4450 {
4452  Name rolename = PG_GETARG_NAME(1);
4453  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4454  Oid roleid;
4455  Oid roleoid;
4456  AclMode mode;
4457  AclResult aclresult;
4458 
4459  roleid = get_role_oid(NameStr(*username), false);
4460  roleoid = get_role_oid(NameStr(*rolename), false);
4461  mode = convert_role_priv_string(priv_type_text);
4462 
4463  aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4464 
4465  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4466 }
4467 
4468 /*
4469  * pg_has_role_name
4470  * Check user privileges on a role given
4471  * name rolename and text priv name.
4472  * current_user is assumed
4473  */
4474 Datum
4476 {
4477  Name rolename = PG_GETARG_NAME(0);
4478  text *priv_type_text = PG_GETARG_TEXT_PP(1);
4479  Oid roleid;
4480  Oid roleoid;
4481  AclMode mode;
4482  AclResult aclresult;
4483 
4484  roleid = GetUserId();
4485  roleoid = get_role_oid(NameStr(*rolename), false);
4486  mode = convert_role_priv_string(priv_type_text);
4487 
4488  aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4489 
4490  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4491 }
4492 
4493 /*
4494  * pg_has_role_name_id
4495  * Check user privileges on a role given
4496  * name usename, role oid, and text priv name.
4497  */
4498 Datum
4500 {
4502  Oid roleoid = PG_GETARG_OID(1);
4503  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4504  Oid roleid;
4505  AclMode mode;
4506  AclResult aclresult;
4507 
4508  roleid = get_role_oid(NameStr(*username), false);
4509  mode = convert_role_priv_string(priv_type_text);
4510 
4511  aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4512 
4513  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4514 }
4515 
4516 /*
4517  * pg_has_role_id
4518  * Check user privileges on a role given
4519  * role oid, and text priv name.
4520  * current_user is assumed
4521  */
4522 Datum
4524 {
4525  Oid roleoid = PG_GETARG_OID(0);
4526  text *priv_type_text = PG_GETARG_TEXT_PP(1);
4527  Oid roleid;
4528  AclMode mode;
4529  AclResult aclresult;
4530 
4531  roleid = GetUserId();
4532  mode = convert_role_priv_string(priv_type_text);
4533 
4534  aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4535 
4536  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4537 }
4538 
4539 /*
4540  * pg_has_role_id_name
4541  * Check user privileges on a role given
4542  * roleid, name rolename, and text priv name.
4543  */
4544 Datum
4546 {
4547  Oid roleid = PG_GETARG_OID(0);
4548  Name rolename = PG_GETARG_NAME(1);
4549  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4550  Oid roleoid;
4551  AclMode mode;
4552  AclResult aclresult;
4553 
4554  roleoid = get_role_oid(NameStr(*rolename), false);
4555  mode = convert_role_priv_string(priv_type_text);
4556 
4557  aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4558 
4559  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4560 }
4561 
4562 /*
4563  * pg_has_role_id_id
4564  * Check user privileges on a role given
4565  * roleid, role oid, and text priv name.
4566  */
4567 Datum
4569 {
4570  Oid roleid = PG_GETARG_OID(0);
4571  Oid roleoid = PG_GETARG_OID(1);
4572  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4573  AclMode mode;
4574  AclResult aclresult;
4575 
4576  mode = convert_role_priv_string(priv_type_text);
4577 
4578  aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4579 
4580  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4581 }
4582 
4583 /*
4584  * Support routines for pg_has_role family.
4585  */
4586 
4587 /*
4588  * convert_role_priv_string
4589  * Convert text string to AclMode value.
4590  *
4591  * We use USAGE to denote whether the privileges of the role are accessible
4592  * (has_privs), MEMBER to denote is_member, and MEMBER WITH GRANT OPTION
4593  * (or ADMIN OPTION) to denote is_admin. There is no ACL bit corresponding
4594  * to MEMBER so we cheat and use ACL_CREATE for that. This convention
4595  * is shared only with pg_role_aclcheck, below.
4596  */
4597 static AclMode
4599 {
4600  static const priv_map role_priv_map[] = {
4601  {"USAGE", ACL_USAGE},
4602  {"MEMBER", ACL_CREATE},
4603  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4604  {"USAGE WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4605  {"MEMBER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4606  {"MEMBER WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4607  {NULL, 0}
4608  };
4609 
4610  return convert_any_priv_string(priv_type_text, role_priv_map);
4611 }
4612 
4613 /*
4614  * pg_role_aclcheck
4615  * Quick-and-dirty support for pg_has_role
4616  */
4617 static AclResult
4619 {
4620  if (mode & ACL_GRANT_OPTION_FOR(ACL_CREATE))
4621  {
4622  /*
4623  * XXX For roleid == role_oid, is_admin_of_role() also examines the
4624  * session and call stack. That suits two-argument pg_has_role(), but
4625  * it gives the three-argument version a lamentable whimsy.
4626  */
4627  if (is_admin_of_role(roleid, role_oid))
4628  return ACLCHECK_OK;
4629  }
4630  if (mode & ACL_CREATE)
4631  {
4632  if (is_member_of_role(roleid, role_oid))
4633  return ACLCHECK_OK;
4634  }
4635  if (mode & ACL_USAGE)
4636  {
4637  if (has_privs_of_role(roleid, role_oid))
4638  return ACLCHECK_OK;
4639  }
4640  return ACLCHECK_NO_PRIV;
4641 }
4642 
4643 
4644 /*
4645  * initialization function (called by InitPostgres)
4646  */
4647 void
4649 {
4651  {
4652  cached_db_hash =
4655 
4656  /*
4657  * In normal mode, set a callback on any syscache invalidation of rows
4658  * of pg_auth_members (for roles_is_member_of()), pg_authid (for
4659  * has_rolinherit()), or pg_database (for roles_is_member_of())
4660  */
4663  (Datum) 0);
4666  (Datum) 0);
4669  (Datum) 0);
4670  }
4671 }
4672 
4673 /*
4674  * RoleMembershipCacheCallback
4675  * Syscache inval callback function
4676  */
4677 static void
4679 {
4680  if (cacheid == DATABASEOID &&
4681  hashvalue != cached_db_hash &&
4682  hashvalue != 0)
4683  {
4684  return; /* ignore pg_database changes for other DBs */
4685  }
4686 
4687  /* Force membership caches to be recomputed on next use */
4690 }
4691 
4692 
4693 /* Check if specified role has rolinherit set */
4694 static bool
4696 {
4697  bool result = false;
4698  HeapTuple utup;
4699 
4700  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4701  if (HeapTupleIsValid(utup))
4702  {
4703  result = ((Form_pg_authid) GETSTRUCT(utup))->rolinherit;
4704  ReleaseSysCache(utup);
4705  }
4706  return result;
4707 }
4708 
4709 
4710 /*
4711  * Get a list of roles that the specified roleid is a member of
4712  *
4713  * Type ROLERECURSE_PRIVS recurses only through roles that have rolinherit
4714  * set, while ROLERECURSE_MEMBERS recurses through all roles. This sets
4715  * *is_admin==true if and only if role "roleid" has an ADMIN OPTION membership
4716  * in role "admin_of".
4717  *
4718  * Since indirect membership testing is relatively expensive, we cache
4719  * a list of memberships. Hence, the result is only guaranteed good until
4720  * the next call of roles_is_member_of()!
4721  *
4722  * For the benefit of select_best_grantor, the result is defined to be
4723  * in breadth-first order, ie, closer relationships earlier.
4724  */
4725 static List *
4727  Oid admin_of, bool *is_admin)
4728 {
4729  Oid dba;
4730  List *roles_list;
4731  ListCell *l;
4732  List *new_cached_roles;
4733  MemoryContext oldctx;
4734 
4735  Assert(OidIsValid(admin_of) == PointerIsValid(is_admin));
4736 
4737  /* If cache is valid and ADMIN OPTION not sought, just return the list */
4738  if (cached_role[type] == roleid && !OidIsValid(admin_of) &&
4739  OidIsValid(cached_role[type]))
4740  return cached_roles[type];
4741 
4742  /*
4743  * Role expansion happens in a non-database backend when guc.c checks
4744  * ROLE_PG_READ_ALL_SETTINGS for a physical walsender SHOW command. In
4745  * that case, no role gets pg_database_owner.
4746  */
4747  if (!OidIsValid(MyDatabaseId))
4748  dba = InvalidOid;
4749  else
4750  {
4751  HeapTuple dbtup;
4752 
4754  if (!HeapTupleIsValid(dbtup))
4755  elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
4756  dba = ((Form_pg_database) GETSTRUCT(dbtup))->datdba;
4757  ReleaseSysCache(dbtup);
4758  }
4759 
4760  /*
4761  * Find all the roles that roleid is a member of, including multi-level
4762  * recursion. The role itself will always be the first element of the
4763  * resulting list.
4764  *
4765  * Each element of the list is scanned to see if it adds any indirect
4766  * memberships. We can use a single list as both the record of
4767  * already-found memberships and the agenda of roles yet to be scanned.
4768  * This is a bit tricky but works because the foreach() macro doesn't
4769  * fetch the next list element until the bottom of the loop.
4770  */
4771  roles_list = list_make1_oid(roleid);
4772 
4773  foreach(l, roles_list)
4774  {
4775  Oid memberid = lfirst_oid(l);
4776  CatCList *memlist;
4777  int i;
4778 
4779  if (type == ROLERECURSE_PRIVS && !has_rolinherit(memberid))
4780  continue; /* ignore non-inheriting roles */
4781 
4782  /* Find roles that memberid is directly a member of */
4784  ObjectIdGetDatum(memberid));
4785  for (i = 0; i < memlist->n_members; i++)
4786  {
4787  HeapTuple tup = &memlist->members[i]->tuple;
4788  Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
4789 
4790  /*
4791  * While otherid==InvalidOid shouldn't appear in the catalog, the
4792  * OidIsValid() avoids crashing if that arises.
4793  */
4794  if (otherid == admin_of &&
4796  OidIsValid(admin_of))
4797  *is_admin = true;
4798 
4799  /*
4800  * Even though there shouldn't be any loops in the membership
4801  * graph, we must test for having already seen this role. It is
4802  * legal for instance to have both A->B and A->C->B.
4803  */
4804  roles_list = list_append_unique_oid(roles_list, otherid);
4805  }
4806  ReleaseSysCacheList(memlist);
4807 
4808  /* implement pg_database_owner implicit membership */
4809  if (memberid == dba && OidIsValid(dba))
4810  roles_list = list_append_unique_oid(roles_list,
4811  ROLE_PG_DATABASE_OWNER);
4812  }
4813 
4814  /*
4815  * Copy the completed list into TopMemoryContext so it will persist.
4816  */
4818  new_cached_roles = list_copy(roles_list);
4819  MemoryContextSwitchTo(oldctx);
4820  list_free(roles_list);
4821 
4822  /*
4823  * Now safe to assign to state variable
4824  */
4825  cached_role[type] = InvalidOid; /* just paranoia */
4826  list_free(cached_roles[type]);
4827  cached_roles[type] = new_cached_roles;
4828  cached_role[type] = roleid;
4829 
4830  /* And now we can return the answer */
4831  return cached_roles[type];
4832 }
4833 
4834 
4835 /*
4836  * Does member have the privileges of role (directly or indirectly)?
4837  *
4838  * This is defined not to recurse through roles that don't have rolinherit
4839  * set; for such roles, membership implies the ability to do SET ROLE, but
4840  * the privileges are not available until you've done so.
4841  */
4842 bool
4844 {
4845  /* Fast path for simple case */
4846  if (member == role)
4847  return true;
4848 
4849  /* Superusers have every privilege, so are part of every role */
4850  if (superuser_arg(member))
4851  return true;
4852 
4853  /*
4854  * Find all the roles that member has the privileges of, including
4855  * multi-level recursion, then see if target role is any one of them.
4856  */
4858  InvalidOid, NULL),
4859  role);
4860 }
4861 
4862 
4863 /*
4864  * Is member a member of role (directly or indirectly)?
4865  *
4866  * This is defined to recurse through roles regardless of rolinherit.
4867  */
4868 bool
4870 {
4871  /* Fast path for simple case */
4872  if (member == role)
4873  return true;
4874 
4875  /* Superusers have every privilege, so are part of every role */
4876  if (superuser_arg(member))
4877  return true;
4878 
4879  /*
4880  * Find all the roles that member is a member of, including multi-level
4881  * recursion, then see if target role is any one of them.
4882  */
4884  InvalidOid, NULL),
4885  role);
4886 }
4887 
4888 /*
4889  * check_is_member_of_role
4890  * is_member_of_role with a standard permission-violation error if not
4891  */
4892 void
4894 {
4895  if (!is_member_of_role(member, role))
4896  ereport(ERROR,
4897  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4898  errmsg("must be member of role \"%s\"",
4899  GetUserNameFromId(role, false))));
4900 }
4901 
4902 /*
4903  * Is member a member of role, not considering superuserness?
4904  *
4905  * This is identical to is_member_of_role except we ignore superuser
4906  * status.
4907  */
4908 bool
4910 {
4911  /* Fast path for simple case */
4912  if (member == role)
4913  return true;
4914 
4915  /*
4916  * Find all the roles that member is a member of, including multi-level
4917  * recursion, then see if target role is any one of them.
4918  */
4920  InvalidOid, NULL),
4921  role);
4922 }
4923 
4924 
4925 /*
4926  * Is member an admin of role? That is, is member the role itself (subject to
4927  * restrictions below), a member (directly or indirectly) WITH ADMIN OPTION,
4928  * or a superuser?
4929  */
4930 bool
4931 is_admin_of_role(Oid member, Oid role)
4932 {
4933  bool result = false;
4934 
4935  if (superuser_arg(member))
4936  return true;
4937 
4938  if (member == role)
4939 
4940  /*
4941  * A role can admin itself when it matches the session user and we're
4942  * outside any security-restricted operation, SECURITY DEFINER or
4943  * similar context. SQL-standard roles cannot self-admin. However,
4944  * SQL-standard users are distinct from roles, and they are not
4945  * grantable like roles: PostgreSQL's role-user duality extends the
4946  * standard. Checking for a session user match has the effect of
4947  * letting a role self-admin only when it's conspicuously behaving
4948  * like a user. Note that allowing self-admin under a mere SET ROLE
4949  * would make WITH ADMIN OPTION largely irrelevant; any member could
4950  * SET ROLE to issue the otherwise-forbidden command.
4951  *
4952  * Withholding self-admin in a security-restricted operation prevents
4953  * object owners from harnessing the session user identity during
4954  * administrative maintenance. Suppose Alice owns a database, has
4955  * issued "GRANT alice TO bob", and runs a daily ANALYZE. Bob creates
4956  * an alice-owned SECURITY DEFINER function that issues "REVOKE alice
4957  * FROM carol". If he creates an expression index calling that
4958  * function, Alice will attempt the REVOKE during each ANALYZE.
4959  * Checking InSecurityRestrictedOperation() thwarts that attack.
4960  *
4961  * Withholding self-admin in SECURITY DEFINER functions makes their
4962  * behavior independent of the calling user. There's no security or
4963  * SQL-standard-conformance need for that restriction, though.
4964  *
4965  * A role cannot have actual WITH ADMIN OPTION on itself, because that
4966  * would imply a membership loop. Therefore, we're done either way.
4967  */
4968  return member == GetSessionUserId() &&
4970 
4971  (void) roles_is_member_of(member, ROLERECURSE_MEMBERS, role, &result);
4972  return result;
4973 }
4974 
4975 
4976 /* does what it says ... */
4977 static int
4979 {
4980  int nbits = 0;
4981 
4982  /* this code relies on AclMode being an unsigned type */
4983  while (mask)
4984  {
4985  if (mask & 1)
4986  nbits++;
4987  mask >>= 1;
4988  }
4989  return nbits;
4990 }
4991 
4992 
4993 /*
4994  * Select the effective grantor ID for a GRANT or REVOKE operation.
4995  *
4996  * The grantor must always be either the object owner or some role that has
4997  * been explicitly granted grant options. This ensures that all granted
4998  * privileges appear to flow from the object owner, and there are never
4999  * multiple "original sources" of a privilege. Therefore, if the would-be
5000  * grantor is a member of a role that has the needed grant options, we have
5001  * to do the grant as that role instead.
5002  *
5003  * It is possible that the would-be grantor is a member of several roles
5004  * that have different subsets of the desired grant options, but no one
5005  * role has 'em all. In this case we pick a role with the largest number
5006  * of desired options. Ties are broken in favor of closer ancestors.
5007  *
5008  * roleId: the role attempting to do the GRANT/REVOKE
5009  * privileges: the privileges to be granted/revoked
5010  * acl: the ACL of the object in question
5011  * ownerId: the role owning the object in question
5012  * *grantorId: receives the OID of the role to do the grant as
5013  * *grantOptions: receives the grant options actually held by grantorId
5014  *
5015  * If no grant options exist, we set grantorId to roleId, grantOptions to 0.
5016  */
5017 void
5018 select_best_grantor(Oid roleId, AclMode privileges,
5019  const Acl *acl, Oid ownerId,
5020  Oid *grantorId, AclMode *grantOptions)
5021 {
5022  AclMode needed_goptions = ACL_GRANT_OPTION_FOR(privileges);
5023  List *roles_list;
5024  int nrights;
5025  ListCell *l;
5026 
5027  /*
5028  * The object owner is always treated as having all grant options, so if
5029  * roleId is the owner it's easy. Also, if roleId is a superuser it's
5030  * easy: superusers are implicitly members of every role, so they act as
5031  * the object owner.
5032  */
5033  if (roleId == ownerId || superuser_arg(roleId))
5034  {
5035  *grantorId = ownerId;
5036  *grantOptions = needed_goptions;
5037  return;
5038  }
5039 
5040  /*
5041  * Otherwise we have to do a careful search to see if roleId has the
5042  * privileges of any suitable role. Note: we can hang onto the result of
5043  * roles_is_member_of() throughout this loop, because aclmask_direct()
5044  * doesn't query any role memberships.
5045  */
5046  roles_list = roles_is_member_of(roleId, ROLERECURSE_PRIVS,
5047  InvalidOid, NULL);
5048 
5049  /* initialize candidate result as default */
5050  *grantorId = roleId;
5051  *grantOptions = ACL_NO_RIGHTS;
5052  nrights = 0;
5053 
5054  foreach(l, roles_list)
5055  {
5056  Oid otherrole = lfirst_oid(l);
5057  AclMode otherprivs;
5058 
5059  otherprivs = aclmask_direct(acl, otherrole, ownerId,
5060  needed_goptions, ACLMASK_ALL);
5061  if (otherprivs == needed_goptions)
5062  {
5063  /* Found a suitable grantor */
5064  *grantorId = otherrole;
5065  *grantOptions = otherprivs;
5066  return;
5067  }
5068 
5069  /*
5070  * If it has just some of the needed privileges, remember best
5071  * candidate.
5072  */
5073  if (otherprivs != ACL_NO_RIGHTS)
5074  {
5075  int nnewrights = count_one_bits(otherprivs);
5076 
5077  if (nnewrights > nrights)
5078  {
5079  *grantorId = otherrole;
5080  *grantOptions = otherprivs;
5081  nrights = nnewrights;
5082  }
5083  }
5084  }
5085 }
5086 
5087 /*
5088  * get_role_oid - Given a role name, look up the role's OID.
5089  *
5090  * If missing_ok is false, throw an error if role name not found. If
5091  * true, just return InvalidOid.
5092  */
5093 Oid
5094 get_role_oid(const char *rolname, bool missing_ok)
5095 {
5096  Oid oid;
5097 
5098  oid = GetSysCacheOid1(AUTHNAME, Anum_pg_authid_oid,
5099  CStringGetDatum(rolname));
5100  if (!OidIsValid(oid) && !missing_ok)
5101  ereport(ERROR,
5102  (errcode(ERRCODE_UNDEFINED_OBJECT),
5103  errmsg("role \"%s\" does not exist", rolname)));
5104  return oid;
5105 }
5106 
5107 /*
5108  * get_role_oid_or_public - As above, but return ACL_ID_PUBLIC if the
5109  * role name is "public".
5110  */
5111 Oid
5113 {
5114  if (strcmp(rolname, "public") == 0)
5115  return ACL_ID_PUBLIC;
5116 
5117  return get_role_oid(rolname, false);
5118 }
5119 
5120 /*
5121  * Given a RoleSpec node, return the OID it corresponds to. If missing_ok is
5122  * true, return InvalidOid if the role does not exist.
5123  *
5124  * PUBLIC is always disallowed here. Routines wanting to handle the PUBLIC
5125  * case must check the case separately.
5126  */
5127 Oid
5128 get_rolespec_oid(const RoleSpec *role, bool missing_ok)
5129 {
5130  Oid oid;
5131 
5132  switch (role->roletype)
5133  {
5134  case ROLESPEC_CSTRING:
5135  Assert(role->rolename);
5136  oid = get_role_oid(role->rolename, missing_ok);
5137  break;
5138 
5139  case ROLESPEC_CURRENT_ROLE:
5140  case ROLESPEC_CURRENT_USER:
5141  oid = GetUserId();
5142  break;
5143 
5144  case ROLESPEC_SESSION_USER:
5145  oid = GetSessionUserId();
5146  break;
5147 
5148  case ROLESPEC_PUBLIC:
5149  ereport(ERROR,
5150  (errcode(ERRCODE_UNDEFINED_OBJECT),
5151  errmsg("role \"%s\" does not exist", "public")));
5152  oid = InvalidOid; /* make compiler happy */
5153  break;
5154 
5155  default:
5156  elog(ERROR, "unexpected role type %d", role->roletype);
5157  }
5158 
5159  return oid;
5160 }
5161 
5162 /*
5163  * Given a RoleSpec node, return the pg_authid HeapTuple it corresponds to.
5164  * Caller must ReleaseSysCache when done with the result tuple.
5165  */
5166 HeapTuple
5168 {
5169  HeapTuple tuple;
5170 
5171  switch (role->roletype)
5172  {
5173  case ROLESPEC_CSTRING:
5174  Assert(role->rolename);
5176  if (!HeapTupleIsValid(tuple))
5177  ereport(ERROR,
5178  (errcode(ERRCODE_UNDEFINED_OBJECT),
5179  errmsg("role \"%s\" does not exist", role->rolename)));
5180  break;
5181 
5182  case ROLESPEC_CURRENT_ROLE:
5183  case ROLESPEC_CURRENT_USER:
5184  tuple = SearchSysCache1(AUTHOID, GetUserId());
5185  if (!HeapTupleIsValid(tuple))
5186  elog(ERROR, "cache lookup failed for role %u", GetUserId());
5187  break;
5188 
5189  case ROLESPEC_SESSION_USER:
5191  if (!HeapTupleIsValid(tuple))
5192  elog(ERROR, "cache lookup failed for role %u", GetSessionUserId());
5193  break;
5194 
5195  case ROLESPEC_PUBLIC:
5196  ereport(ERROR,
5197  (errcode(ERRCODE_UNDEFINED_OBJECT),
5198  errmsg("role \"%s\" does not exist", "public")));
5199  tuple = NULL; /* make compiler happy */
5200  break;
5201 
5202  default:
5203  elog(ERROR, "unexpected role type %d", role->roletype);
5204  }
5205 
5206  return tuple;
5207 }
5208 
5209 /*
5210  * Given a RoleSpec, returns a palloc'ed copy of the corresponding role's name.
5211  */
5212 char *
5214 {
5215  HeapTuple tp;
5216  Form_pg_authid authForm;
5217  char *rolename;
5218 
5219  tp = get_rolespec_tuple(role);
5220  authForm = (Form_pg_authid) GETSTRUCT(tp);
5221  rolename = pstrdup(NameStr(authForm->rolname));
5222  ReleaseSysCache(tp);
5223 
5224  return rolename;
5225 }
5226 
5227 /*
5228  * Given a RoleSpec, throw an error if the name is reserved, using detail_msg,
5229  * if provided.
5230  *
5231  * If node is NULL, no error is thrown. If detail_msg is NULL then no detail
5232  * message is provided.
5233  */
5234 void
5235 check_rolespec_name(const RoleSpec *role, const char *detail_msg)
5236 {
5237  if (!role)
5238  return;
5239 
5240  if (role->roletype != ROLESPEC_CSTRING)
5241  return;
5242 
5243  if (IsReservedName(role->rolename))
5244  {
5245  if (detail_msg)
5246  ereport(ERROR,
5247  (errcode(ERRCODE_RESERVED_NAME),
5248  errmsg("role name \"%s\" is reserved",
5249  role->rolename),
5250  errdetail("%s", detail_msg)));
5251  else
5252  ereport(ERROR,
5253  (errcode(ERRCODE_RESERVED_NAME),
5254  errmsg("role name \"%s\" is reserved",
5255  role->rolename)));
5256  }
5257 }
int remaining
Definition: informix.c:667
bool InLocalUserIdChange(void)
Definition: miscinit.c:618
Oid ai_grantee
Definition: acl.h:56
Datum has_column_privilege_name_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:2483
static void putid(char *p, const char *s)
Definition: acl.c:183
Definition: acl.c:45
#define NIL
Definition: pg_list.h:65
#define ACL_MODECHG_EQL
Definition: acl.h:131
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1427
Datum has_column_privilege_id_id_attnum(PG_FUNCTION_ARGS)
Definition: acl.c:2668
static PgChecksumMode mode
Definition: pg_checksums.c:65
static const char * convert_aclright_to_string(int aclright)
Definition: acl.c:1673
#define ACL_INSERT_CHR
Definition: acl.h:137
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:162
Datum has_any_column_privilege_name(PG_FUNCTION_ARGS)
Definition: acl.c:2281
static Oid convert_language_name(text *languagename)
Definition: acl.c:3635
Datum has_tablespace_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:4109
Datum has_column_privilege_name_name_attnum(PG_FUNCTION_ARGS)
Definition: acl.c:2512
Datum has_foreign_data_wrapper_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:3195
int n_members
Definition: catcache.h:176
Datum has_database_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:2945
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4768
Datum has_server_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:3868
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3088
#define ACLITEM_GET_GOPTIONS(item)
Definition: acl.h:67
Datum has_function_privilege_name(PG_FUNCTION_ARGS)
Definition: acl.c:3310
int errhint(const char *fmt,...)
Definition: elog.c:1156
List * list_append_unique_oid(List *list, Oid datum)
Definition: list.c:1232
Datum has_sequence_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:2161
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Datum has_schema_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:3675
#define PG_RETURN_ACL_P(x)
Definition: acl.h:124
Datum has_sequence_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:2037
static AttrNumber convert_column_name(Oid tableoid, text *column)
Definition: acl.c:2803
Datum aclcontains(PG_FUNCTION_ARGS)
Definition: acl.c:1530
Datum has_database_privilege_name(PG_FUNCTION_ARGS)
Definition: acl.c:2921
static Oid convert_schema_name(text *schemaname)
Definition: acl.c:3826
RoleRecurseType
Definition: acl.c:65
static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode)
Definition: acl.c:4618
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
Oid GetUserId(void)
Definition: miscinit.c:495
Datum aclexplode(PG_FUNCTION_ARGS)
Definition: acl.c:1723
Datum has_type_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:4326
#define ACL_CONNECT_CHR
Definition: acl.h:148
#define ACLITEM_ALL_GOPTION_BITS
Definition: acl.h:88
NameData rolname
Definition: pg_authid.h:34
FormData_pg_database * Form_pg_database
Definition: pg_database.h:81
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:293
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:79
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:193
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1974
#define UInt64GetDatum(X)
Definition: postgres.h:692
Datum hash_aclitem_extended(PG_FUNCTION_ARGS)
Definition: acl.c:713
#define DatumGetObjectId(X)
Definition: postgres.h:544
char * pstrdup(const char *in)
Definition: mcxt.c:1299
Datum pg_has_role_name(PG_FUNCTION_ARGS)
Definition: acl.c:4475
AclResult pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4781
static AclMode convert_function_priv_string(text *priv_type_text)
Definition: acl.c:3456
int32 dataoffset
Definition: array.h:89
static Acl * allocacl(int n)
Definition: acl.c:362
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4843
static Oid convert_foreign_data_wrapper_name(text *fdwname)
Definition: acl.c:3244
#define ACL_MODECHG_DEL
Definition: acl.h:130
AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
Definition: acl.c:1306
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:228
bool is_admin_of_role(Oid member, Oid role)
Definition: acl.c:4931
#define ACL_DELETE_CHR
Definition: acl.h:140
static bool has_rolinherit(Oid roleid)
Definition: acl.c:4695
Datum aclinsert(PG_FUNCTION_ARGS)
Definition: acl.c:1510
List * list_copy(const List *oldlist)
Definition: list.c:1418
#define ACL_SIZE(ACL)
Definition: acl.h:111
Oid get_role_oid_or_public(const char *rolname)
Definition: acl.c:5112
int errcode(int sqlerrcode)
Definition: elog.c:698
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:734
#define MemSet(start, val, len)
Definition: c.h:1008
#define ACL_DELETE
Definition: parsenodes.h:85
Datum has_function_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:3386
Datum aclitemin(PG_FUNCTION_ARGS)
Definition: acl.c:551
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:166
static Oid convert_tablespace_name(text *tablespacename)
Definition: acl.c:4210
#define PG_GETARG_ACLITEM_P(n)
Definition: acl.h:117
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:202
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:3107
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
Datum has_table_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:1879
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
static uint32 cached_db_hash
Definition: acl.c:72
void initialize_acl(void)
Definition: acl.c:4648
unsigned int Oid
Definition: postgres_ext.h:31
bool IsReservedName(const char *name)
Definition: catalog.c:218
Datum pg_has_role_id(PG_FUNCTION_ARGS)
Definition: acl.c:4523
Datum has_server_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:3918
bool aclequal(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:495
const char * name
Definition: acl.c:47
Datum has_sequence_privilege_name(PG_FUNCTION_ARGS)
Definition: acl.c:2068
Datum has_type_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:4299
#define OidIsValid(objectId)
Definition: c.h:710
Datum has_server_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:3945
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4756
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:297
Acl * make_empty_acl(void)
Definition: acl.c:384
Datum has_function_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:3334
Oid GetSessionUserId(void)
Definition: miscinit.c:529
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4730
Datum has_any_column_privilege_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:2396
Oid ai_grantor
Definition: acl.h:57
TupleDesc tuple_desc
Definition: funcapi.h:112
AclResult pg_class_aclcheck_ext(Oid table_oid, Oid roleid, AclMode mode, bool *is_missing)
Definition: aclchk.c:4692
#define PG_RETURN_UINT32(x)
Definition: fmgr.h:355
static AclMode convert_any_priv_string(text *priv_type_text, const priv_map *privileges)
Definition: acl.c:1625
Datum has_any_column_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:2251
Datum pg_has_role_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:4449
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5094
Datum has_schema_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:3777
#define ARR_LBOUND(a)
Definition: array.h:289
Datum has_foreign_data_wrapper_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:3170
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:178
#define NAMEDATALEN
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:299
AclMode ai_privs
Definition: acl.h:58
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:163
Datum has_language_privilege_name(PG_FUNCTION_ARGS)
Definition: acl.c:3510
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
#define sprintf
Definition: port.h:219
uint32 AclMode
Definition: parsenodes.h:80
static const FormData_pg_attribute a2
Definition: heap.c:167
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition: foreign.c:691
Datum pg_has_role_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:4545
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:184
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ACL_CREATE_TEMP_CHR
Definition: acl.h:147
static int count_one_bits(AclMode mask)
Definition: acl.c:4978
Datum has_type_privilege_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:4374
static void check_circularity(const Acl *old_acl, const AclItem *mod_aip, Oid ownerId)
Definition: acl.c:1140
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
Datum regprocedurein(PG_FUNCTION_ARGS)
Definition: regproc.c:230
Datum has_function_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:3361
#define ACL_CREATE
Definition: parsenodes.h:92
static const char * getid(const char *s, char *n)
Definition: acl.c:131
Oid elemtype
Definition: array.h:90
Datum has_column_privilege_name_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:2539
Datum has_tablespace_privilege_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:4184
#define ARR_DIMS(a)
Definition: array.h:287
Datum has_foreign_data_wrapper_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:3143
#define ACL_NUM(ACL)
Definition: acl.h:108
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
Datum pg_has_role_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:4568
#define ACL_ALL_RIGHTS_SCHEMA
Definition: acl.h:165
Datum has_table_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:1931
Datum has_column_privilege_id_attnum(PG_FUNCTION_ARGS)
Definition: acl.c:2775
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2082
Definition: c.h:675
#define ACL_TRIGGER
Definition: parsenodes.h:88
AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4794
#define ACL_TRUNCATE_CHR
Definition: acl.h:141
static AclMode convert_type_priv_string(text *priv_type_text)
Definition: acl.c:4421
#define NoLock
Definition: lockdefs.h:34
#define ACL_REFERENCES_CHR
Definition: acl.h:142
static AclMode convert_table_priv_string(text *priv_type_text)
Definition: acl.c:1995
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define N_ACL_RIGHTS
Definition: parsenodes.h:95
Datum has_column_privilege_id_name_attnum(PG_FUNCTION_ARGS)
Definition: acl.c:2618
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define CStringGetDatum(X)
Definition: postgres.h:622
static AclMode convert_tablespace_priv_string(text *priv_type_text)
Definition: acl.c:4222
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:167
Datum has_tablespace_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:4161
Datum has_column_privilege_id_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:2643
Datum has_column_privilege_name_id_attnum(PG_FUNCTION_ARGS)
Definition: acl.c:2566
static Oid convert_database_name(text *databasename)
Definition: acl.c:3046
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
unsigned int uint32
Definition: c.h:441
Datum has_database_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:2972
static AclMode convert_database_priv_string(text *priv_type_text)
Definition: acl.c:3058
#define ARR_HASNULL(a)
Definition: array.h:284
#define ACL_USAGE
Definition: parsenodes.h:90
#define SearchSysCacheList1(cacheId, key1)
Definition: syscache.h:211
static Oid cached_role[]
Definition: acl.c:70
#define ACLITEM_GET_RIGHTS(item)
Definition: acl.h:68
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:583
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4893
static AclMode convert_language_priv_string(text *priv_type_text)
Definition: acl.c:3647
const char * username
Definition: pgbench.c:282
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
Datum has_tablespace_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:4059
Datum has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:3093
MemoryContext TopMemoryContext
Definition: mcxt.c:48
#define ACL_CONNECT
Definition: parsenodes.h:94
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3688
char * get_rolespec_name(const RoleSpec *role)
Definition: acl.c:5213
ObjectType
Definition: parsenodes.h:1787
Datum aclitemout(PG_FUNCTION_ARGS)
Definition: acl.c:577
Datum has_schema_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:3725
NameData typname
Definition: pg_type.h:41
Datum has_type_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:4249
Datum has_server_privilege_name(PG_FUNCTION_ARGS)
Definition: acl.c:3894
static Oid convert_server_name(text *servername)
Definition: acl.c:4019
Datum has_language_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:3534
Datum has_language_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:3561
static AclMode convert_server_priv_string(text *priv_type_text)
Definition: acl.c:4031
Datum has_table_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:1829
Acl * aclconcat(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:413
Datum has_type_privilege_name(PG_FUNCTION_ARGS)
Definition: acl.c:4275
Datum has_server_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:3970
Datum has_schema_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:3752
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
Datum has_database_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:2997
#define ACLITEM_SET_RIGHTS(item, rights)
Definition: acl.h:79
#define ACL_SELECT_CHR
Definition: acl.h:138
#define ACL_UPDATE
Definition: parsenodes.h:84
#define ReleaseSysCacheList(x)
Definition: syscache.h:218
Datum regtypein(PG_FUNCTION_ARGS)
Definition: regproc.c:1251
DropBehavior
Definition: parsenodes.h:1858
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1498
#define ACL_GRANT_OPTION_FOR(privs)
Definition: acl.h:70
void * palloc0(Size size)
Definition: mcxt.c:1093
Datum has_database_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:2895
AclResult
Definition: acl.h:177
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
uintptr_t Datum
Definition: postgres.h:411
void check_rolespec_name(const RoleSpec *role, const char *detail_msg)
Definition: acl.c:5235
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define ACL_MODECHG_ADD
Definition: acl.h:129
#define ACL_SELECT
Definition: parsenodes.h:83
RoleSpecType roletype
Definition: parsenodes.h:351
#define ACL_DAT(ACL)
Definition: acl.h:109
#define list_make1_oid(x1)
Definition: pg_list.h:236
Oid MyDatabaseId
Definition: globals.c:88
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5128
static const char * aclparse(const char *s, AclItem *aip)
Definition: acl.c:232
Datum hash_aclitem(PG_FUNCTION_ARGS)
Definition: acl.c:699
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:158
FormData_pg_auth_members * Form_pg_auth_members
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
Datum aclremove(PG_FUNCTION_ARGS)
Definition: acl.c:1520
Datum has_language_privilege_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:3609
AclMode value
Definition: acl.c:48
Datum has_sequence_privilege_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:2189
bool admin_option
static AclMode convert_priv_string(text *priv_type_text)
Definition: acl.c:1575
#define BoolGetDatum(X)
Definition: postgres.h:446
#define ACL_ALL_RIGHTS_STR
Definition: acl.h:151
#define ACL_USAGE_CHR
Definition: acl.h:145
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2066
#define InvalidOid
Definition: postgres_ext.h:36
int16 attnum
Definition: pg_attribute.h:83
#define ereport(elevel,...)
Definition: elog.h:157
Definition: acl.h:54
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:164
bool is_member_of_role(Oid member, Oid role)
Definition: acl.c:4869
Acl * aclcopy(const Acl *orig_acl)
Definition: acl.c:393
#define ACL_OPTION_TO_PRIVS(privs)
Definition: acl.h:71
#define ACL_REFERENCES
Definition: parsenodes.h:87
Acl * aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
Definition: acl.c:437
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:689
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1458
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4706
static AclMode convert_foreign_data_wrapper_priv_string(text *priv_type_text)
Definition: acl.c:3256
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition: miscinit.c:910
#define Assert(condition)
Definition: c.h:804
Datum has_any_column_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:2369
static Oid convert_table_name(text *tablename)
Definition: acl.c:1980
bool InSecurityRestrictedOperation(void)
Definition: miscinit.c:627
Datum has_sequence_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:2130
static Oid convert_function_name(text *functionname)
Definition: acl.c:3435
Datum has_tablespace_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:4136
#define ACL_INSERT
Definition: parsenodes.h:82
Datum has_function_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:3284
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
HeapTuple get_rolespec_tuple(const RoleSpec *role)
Definition: acl.c:5167
Datum acldefault_sql(PG_FUNCTION_ARGS)
Definition: acl.c:847
int oid_cmp(const void *p1, const void *p2)
Definition: oid.c:336
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition: aclchk.c:4595
static bool aclitem_match(const AclItem *a1, const AclItem *a2)
Definition: acl.c:644
size_t Size
Definition: c.h:540
char * dbname
Definition: streamutil.c:51
Datum has_foreign_data_wrapper_privilege_name(PG_FUNCTION_ARGS)
Definition: acl.c:3119
Datum has_table_privilege_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:1954
Datum makeaclitem(PG_FUNCTION_ARGS)
Definition: acl.c:1552
AclResult pg_attribute_aclcheck_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode, bool *is_missing)
Definition: