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