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