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