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