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