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