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