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