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