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