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