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