PostgreSQL Source Code  git master
acl.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * acl.c
4  * Basic access control list data structures manipulation routines.
5  *
6  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/utils/adt/acl.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include <ctype.h>
18 
19 #include "access/htup_details.h"
20 #include "catalog/catalog.h"
21 #include "catalog/namespace.h"
23 #include "catalog/pg_authid.h"
24 #include "catalog/pg_class.h"
25 #include "catalog/pg_type.h"
26 #include "commands/dbcommands.h"
27 #include "commands/proclang.h"
28 #include "commands/tablespace.h"
29 #include "foreign/foreign.h"
30 #include "funcapi.h"
31 #include "lib/qunique.h"
32 #include "miscadmin.h"
33 #include "utils/acl.h"
34 #include "utils/array.h"
35 #include "utils/builtins.h"
36 #include "utils/catcache.h"
37 #include "utils/hashutils.h"
38 #include "utils/inval.h"
39 #include "utils/lsyscache.h"
40 #include "utils/memutils.h"
41 #include "utils/syscache.h"
42 #include "utils/varlena.h"
43 
44 typedef struct
45 {
46  const char *name;
48 } priv_map;
49 
50 /*
51  * We frequently need to test whether a given role is a member of some other
52  * role. In most of these tests the "given role" is the same, namely the
53  * active current user. So we can optimize it by keeping a cached list of
54  * all the roles the "given role" is a member of, directly or indirectly.
55  * The cache is flushed whenever we detect a change in pg_auth_members.
56  *
57  * There are actually two caches, one computed under "has_privs" rules
58  * (do not recurse where rolinherit isn't true) and one computed under
59  * "is_member" rules (recurse regardless of rolinherit).
60  *
61  * Possibly this mechanism should be generalized to allow caching membership
62  * info for multiple roles?
63  *
64  * The has_privs cache is:
65  * cached_privs_role is the role OID the cache is for.
66  * cached_privs_roles is an OID list of roles that cached_privs_role
67  * has the privileges of (always including itself).
68  * The cache is valid if cached_privs_role is not InvalidOid.
69  *
70  * The is_member cache is similarly:
71  * cached_member_role is the role OID the cache is for.
72  * cached_membership_roles is an OID list of roles that cached_member_role
73  * is a member of (always including itself).
74  * The cache is valid if cached_member_role is not InvalidOid.
75  */
80 
81 
82 static const char *getid(const char *s, char *n);
83 static void putid(char *p, const char *s);
84 static Acl *allocacl(int n);
85 static void check_acl(const Acl *acl);
86 static const char *aclparse(const char *s, AclItem *aip);
87 static bool aclitem_match(const AclItem *a1, const AclItem *a2);
88 static int aclitemComparator(const void *arg1, const void *arg2);
89 static void check_circularity(const Acl *old_acl, const AclItem *mod_aip,
90  Oid ownerId);
91 static Acl *recursive_revoke(Acl *acl, Oid grantee, AclMode revoke_privs,
92  Oid ownerId, DropBehavior behavior);
93 
94 static AclMode convert_priv_string(text *priv_type_text);
95 static AclMode convert_any_priv_string(text *priv_type_text,
96  const priv_map *privileges);
97 
98 static Oid convert_table_name(text *tablename);
99 static AclMode convert_table_priv_string(text *priv_type_text);
100 static AclMode convert_sequence_priv_string(text *priv_type_text);
101 static AttrNumber convert_column_name(Oid tableoid, text *column);
102 static AclMode convert_column_priv_string(text *priv_type_text);
103 static Oid convert_database_name(text *databasename);
104 static AclMode convert_database_priv_string(text *priv_type_text);
107 static Oid convert_function_name(text *functionname);
108 static AclMode convert_function_priv_string(text *priv_type_text);
109 static Oid convert_language_name(text *languagename);
110 static AclMode convert_language_priv_string(text *priv_type_text);
111 static Oid convert_schema_name(text *schemaname);
112 static AclMode convert_schema_priv_string(text *priv_type_text);
113 static Oid convert_server_name(text *servername);
114 static AclMode convert_server_priv_string(text *priv_type_text);
115 static Oid convert_tablespace_name(text *tablespacename);
116 static AclMode convert_tablespace_priv_string(text *priv_type_text);
117 static Oid convert_type_name(text *typename);
118 static AclMode convert_type_priv_string(text *priv_type_text);
119 static AclMode convert_role_priv_string(text *priv_type_text);
120 static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode);
121 
122 static void RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue);
123 
124 
125 /*
126  * getid
127  * Consumes the first alphanumeric string (identifier) found in string
128  * 's', ignoring any leading white space. If it finds a double quote
129  * it returns the word inside the quotes.
130  *
131  * RETURNS:
132  * the string position in 's' that points to the next non-space character
133  * in 's', after any quotes. Also:
134  * - loads the identifier into 'n'. (If no identifier is found, 'n'
135  * contains an empty string.) 'n' must be NAMEDATALEN bytes.
136  */
137 static const char *
138 getid(const char *s, char *n)
139 {
140  int len = 0;
141  bool in_quotes = false;
142 
143  Assert(s && n);
144 
145  while (isspace((unsigned char) *s))
146  s++;
147  /* This code had better match what putid() does, below */
148  for (;
149  *s != '\0' &&
150  (isalnum((unsigned char) *s) ||
151  *s == '_' ||
152  *s == '"' ||
153  in_quotes);
154  s++)
155  {
156  if (*s == '"')
157  {
158  /* safe to look at next char (could be '\0' though) */
159  if (*(s + 1) != '"')
160  {
161  in_quotes = !in_quotes;
162  continue;
163  }
164  /* it's an escaped double quote; skip the escaping char */
165  s++;
166  }
167 
168  /* Add the character to the string */
169  if (len >= NAMEDATALEN - 1)
170  ereport(ERROR,
171  (errcode(ERRCODE_NAME_TOO_LONG),
172  errmsg("identifier too long"),
173  errdetail("Identifier must be less than %d characters.",
174  NAMEDATALEN)));
175 
176  n[len++] = *s;
177  }
178  n[len] = '\0';
179  while (isspace((unsigned char) *s))
180  s++;
181  return s;
182 }
183 
184 /*
185  * Write a role name at *p, adding double quotes if needed.
186  * There must be at least (2*NAMEDATALEN)+2 bytes available at *p.
187  * This needs to be kept in sync with copyAclUserName in pg_dump/dumputils.c
188  */
189 static void
190 putid(char *p, const char *s)
191 {
192  const char *src;
193  bool safe = true;
194 
195  for (src = s; *src; src++)
196  {
197  /* This test had better match what getid() does, above */
198  if (!isalnum((unsigned char) *src) && *src != '_')
199  {
200  safe = false;
201  break;
202  }
203  }
204  if (!safe)
205  *p++ = '"';
206  for (src = s; *src; src++)
207  {
208  /* A double quote character in a username is encoded as "" */
209  if (*src == '"')
210  *p++ = '"';
211  *p++ = *src;
212  }
213  if (!safe)
214  *p++ = '"';
215  *p = '\0';
216 }
217 
218 /*
219  * aclparse
220  * Consumes and parses an ACL specification of the form:
221  * [group|user] [A-Za-z0-9]*=[rwaR]*
222  * from string 's', ignoring any leading white space or white space
223  * between the optional id type keyword (group|user) and the actual
224  * ACL specification.
225  *
226  * The group|user decoration is unnecessary in the roles world,
227  * but we still accept it for backward compatibility.
228  *
229  * This routine is called by the parser as well as aclitemin(), hence
230  * the added generality.
231  *
232  * RETURNS:
233  * the string position in 's' immediately following the ACL
234  * specification. Also:
235  * - loads the structure pointed to by 'aip' with the appropriate
236  * UID/GID, id type identifier and mode type values.
237  */
238 static const char *
239 aclparse(const char *s, AclItem *aip)
240 {
241  AclMode privs,
242  goption,
243  read;
244  char name[NAMEDATALEN];
245  char name2[NAMEDATALEN];
246 
247  Assert(s && aip);
248 
249 #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 
1480  if (acl == NULL || ACL_NUM(acl) == 0)
1481  {
1482  *roleids = NULL;
1483  return 0;
1484  }
1485 
1486  check_acl(acl);
1487 
1488  /* Allocate the worst-case space requirement */
1489  list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
1490  acldat = ACL_DAT(acl);
1491 
1492  /*
1493  * Walk the ACL collecting mentioned RoleIds.
1494  */
1495  j = 0;
1496  for (i = 0; i < ACL_NUM(acl); i++)
1497  {
1498  const AclItem *ai = &acldat[i];
1499 
1500  if (ai->ai_grantee != ACL_ID_PUBLIC)
1501  list[j++] = ai->ai_grantee;
1502  /* grantor is currently never PUBLIC, but let's check anyway */
1503  if (ai->ai_grantor != ACL_ID_PUBLIC)
1504  list[j++] = ai->ai_grantor;
1505  }
1506 
1507  /* Sort the array */
1508  qsort(list, j, sizeof(Oid), oid_cmp);
1509 
1510  /*
1511  * We could repalloc the array down to minimum size, but it's hardly worth
1512  * it since it's only transient memory.
1513  */
1514  *roleids = list;
1515 
1516  /* Remove duplicates from the array */
1517  return qunique(list, j, sizeof(Oid), oid_cmp);
1518 }
1519 
1520 
1521 /*
1522  * aclinsert (exported function)
1523  */
1524 Datum
1526 {
1527  ereport(ERROR,
1528  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1529  errmsg("aclinsert is no longer supported")));
1530 
1531  PG_RETURN_NULL(); /* keep compiler quiet */
1532 }
1533 
1534 Datum
1536 {
1537  ereport(ERROR,
1538  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1539  errmsg("aclremove is no longer supported")));
1540 
1541  PG_RETURN_NULL(); /* keep compiler quiet */
1542 }
1543 
1544 Datum
1546 {
1547  Acl *acl = PG_GETARG_ACL_P(0);
1548  AclItem *aip = PG_GETARG_ACLITEM_P(1);
1549  AclItem *aidat;
1550  int i,
1551  num;
1552 
1553  check_acl(acl);
1554  num = ACL_NUM(acl);
1555  aidat = ACL_DAT(acl);
1556  for (i = 0; i < num; ++i)
1557  {
1558  if (aip->ai_grantee == aidat[i].ai_grantee &&
1559  aip->ai_grantor == aidat[i].ai_grantor &&
1560  (ACLITEM_GET_RIGHTS(*aip) & ACLITEM_GET_RIGHTS(aidat[i])) == ACLITEM_GET_RIGHTS(*aip))
1561  PG_RETURN_BOOL(true);
1562  }
1563  PG_RETURN_BOOL(false);
1564 }
1565 
1566 Datum
1568 {
1569  Oid grantee = PG_GETARG_OID(0);
1570  Oid grantor = PG_GETARG_OID(1);
1571  text *privtext = PG_GETARG_TEXT_PP(2);
1572  bool goption = PG_GETARG_BOOL(3);
1573  AclItem *result;
1574  AclMode priv;
1575 
1576  priv = convert_priv_string(privtext);
1577 
1578  result = (AclItem *) palloc(sizeof(AclItem));
1579 
1580  result->ai_grantee = grantee;
1581  result->ai_grantor = grantor;
1582 
1583  ACLITEM_SET_PRIVS_GOPTIONS(*result, priv,
1584  (goption ? priv : ACL_NO_RIGHTS));
1585 
1586  PG_RETURN_ACLITEM_P(result);
1587 }
1588 
1589 static AclMode
1590 convert_priv_string(text *priv_type_text)
1591 {
1592  char *priv_type = text_to_cstring(priv_type_text);
1593 
1594  if (pg_strcasecmp(priv_type, "SELECT") == 0)
1595  return ACL_SELECT;
1596  if (pg_strcasecmp(priv_type, "INSERT") == 0)
1597  return ACL_INSERT;
1598  if (pg_strcasecmp(priv_type, "UPDATE") == 0)
1599  return ACL_UPDATE;
1600  if (pg_strcasecmp(priv_type, "DELETE") == 0)
1601  return ACL_DELETE;
1602  if (pg_strcasecmp(priv_type, "TRUNCATE") == 0)
1603  return ACL_TRUNCATE;
1604  if (pg_strcasecmp(priv_type, "REFERENCES") == 0)
1605  return ACL_REFERENCES;
1606  if (pg_strcasecmp(priv_type, "TRIGGER") == 0)
1607  return ACL_TRIGGER;
1608  if (pg_strcasecmp(priv_type, "EXECUTE") == 0)
1609  return ACL_EXECUTE;
1610  if (pg_strcasecmp(priv_type, "USAGE") == 0)
1611  return ACL_USAGE;
1612  if (pg_strcasecmp(priv_type, "CREATE") == 0)
1613  return ACL_CREATE;
1614  if (pg_strcasecmp(priv_type, "TEMP") == 0)
1615  return ACL_CREATE_TEMP;
1616  if (pg_strcasecmp(priv_type, "TEMPORARY") == 0)
1617  return ACL_CREATE_TEMP;
1618  if (pg_strcasecmp(priv_type, "CONNECT") == 0)
1619  return ACL_CONNECT;
1620  if (pg_strcasecmp(priv_type, "RULE") == 0)
1621  return 0; /* ignore old RULE privileges */
1622 
1623  ereport(ERROR,
1624  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1625  errmsg("unrecognized privilege type: \"%s\"", priv_type)));
1626  return ACL_NO_RIGHTS; /* keep compiler quiet */
1627 }
1628 
1629 
1630 /*
1631  * convert_any_priv_string: recognize privilege strings for has_foo_privilege
1632  *
1633  * We accept a comma-separated list of case-insensitive privilege names,
1634  * producing a bitmask of the OR'd privilege bits. We are liberal about
1635  * whitespace between items, not so much about whitespace within items.
1636  * The allowed privilege names are given as an array of priv_map structs,
1637  * terminated by one with a NULL name pointer.
1638  */
1639 static AclMode
1641  const priv_map *privileges)
1642 {
1643  AclMode result = 0;
1644  char *priv_type = text_to_cstring(priv_type_text);
1645  char *chunk;
1646  char *next_chunk;
1647 
1648  /* We rely on priv_type being a private, modifiable string */
1649  for (chunk = priv_type; chunk; chunk = next_chunk)
1650  {
1651  int chunk_len;
1652  const priv_map *this_priv;
1653 
1654  /* Split string at commas */
1655  next_chunk = strchr(chunk, ',');
1656  if (next_chunk)
1657  *next_chunk++ = '\0';
1658 
1659  /* Drop leading/trailing whitespace in this chunk */
1660  while (*chunk && isspace((unsigned char) *chunk))
1661  chunk++;
1662  chunk_len = strlen(chunk);
1663  while (chunk_len > 0 && isspace((unsigned char) chunk[chunk_len - 1]))
1664  chunk_len--;
1665  chunk[chunk_len] = '\0';
1666 
1667  /* Match to the privileges list */
1668  for (this_priv = privileges; this_priv->name; this_priv++)
1669  {
1670  if (pg_strcasecmp(this_priv->name, chunk) == 0)
1671  {
1672  result |= this_priv->value;
1673  break;
1674  }
1675  }
1676  if (!this_priv->name)
1677  ereport(ERROR,
1678  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1679  errmsg("unrecognized privilege type: \"%s\"", chunk)));
1680  }
1681 
1682  pfree(priv_type);
1683  return result;
1684 }
1685 
1686 
1687 static const char *
1689 {
1690  switch (aclright)
1691  {
1692  case ACL_INSERT:
1693  return "INSERT";
1694  case ACL_SELECT:
1695  return "SELECT";
1696  case ACL_UPDATE:
1697  return "UPDATE";
1698  case ACL_DELETE:
1699  return "DELETE";
1700  case ACL_TRUNCATE:
1701  return "TRUNCATE";
1702  case ACL_REFERENCES:
1703  return "REFERENCES";
1704  case ACL_TRIGGER:
1705  return "TRIGGER";
1706  case ACL_EXECUTE:
1707  return "EXECUTE";
1708  case ACL_USAGE:
1709  return "USAGE";
1710  case ACL_CREATE:
1711  return "CREATE";
1712  case ACL_CREATE_TEMP:
1713  return "TEMPORARY";
1714  case ACL_CONNECT:
1715  return "CONNECT";
1716  default:
1717  elog(ERROR, "unrecognized aclright: %d", aclright);
1718  return NULL;
1719  }
1720 }
1721 
1722 
1723 /*----------
1724  * Convert an aclitem[] to a table.
1725  *
1726  * Example:
1727  *
1728  * aclexplode('{=r/joe,foo=a*w/joe}'::aclitem[])
1729  *
1730  * returns the table
1731  *
1732  * {{ OID(joe), 0::OID, 'SELECT', false },
1733  * { OID(joe), OID(foo), 'INSERT', true },
1734  * { OID(joe), OID(foo), 'UPDATE', false }}
1735  *----------
1736  */
1737 Datum
1739 {
1740  Acl *acl = PG_GETARG_ACL_P(0);
1741  FuncCallContext *funcctx;
1742  int *idx;
1743  AclItem *aidat;
1744 
1745  if (SRF_IS_FIRSTCALL())
1746  {
1747  TupleDesc tupdesc;
1748  MemoryContext oldcontext;
1749 
1750  check_acl(acl);
1751 
1752  funcctx = SRF_FIRSTCALL_INIT();
1753  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1754 
1755  /*
1756  * build tupdesc for result tuples (matches out parameters in pg_proc
1757  * entry)
1758  */
1759  tupdesc = CreateTemplateTupleDesc(4);
1760  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "grantor",
1761  OIDOID, -1, 0);
1762  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "grantee",
1763  OIDOID, -1, 0);
1764  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "privilege_type",
1765  TEXTOID, -1, 0);
1766  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "is_grantable",
1767  BOOLOID, -1, 0);
1768 
1769  funcctx->tuple_desc = BlessTupleDesc(tupdesc);
1770 
1771  /* allocate memory for user context */
1772  idx = (int *) palloc(sizeof(int[2]));
1773  idx[0] = 0; /* ACL array item index */
1774  idx[1] = -1; /* privilege type counter */
1775  funcctx->user_fctx = (void *) idx;
1776 
1777  MemoryContextSwitchTo(oldcontext);
1778  }
1779 
1780  funcctx = SRF_PERCALL_SETUP();
1781  idx = (int *) funcctx->user_fctx;
1782  aidat = ACL_DAT(acl);
1783 
1784  /* need test here in case acl has no items */
1785  while (idx[0] < ACL_NUM(acl))
1786  {
1787  AclItem *aidata;
1788  AclMode priv_bit;
1789 
1790  idx[1]++;
1791  if (idx[1] == N_ACL_RIGHTS)
1792  {
1793  idx[1] = 0;
1794  idx[0]++;
1795  if (idx[0] >= ACL_NUM(acl)) /* done */
1796  break;
1797  }
1798  aidata = &aidat[idx[0]];
1799  priv_bit = 1 << idx[1];
1800 
1801  if (ACLITEM_GET_PRIVS(*aidata) & priv_bit)
1802  {
1803  Datum result;
1804  Datum values[4];
1805  bool nulls[4];
1806  HeapTuple tuple;
1807 
1808  values[0] = ObjectIdGetDatum(aidata->ai_grantor);
1809  values[1] = ObjectIdGetDatum(aidata->ai_grantee);
1810  values[2] = CStringGetTextDatum(convert_aclright_to_string(priv_bit));
1811  values[3] = BoolGetDatum((ACLITEM_GET_GOPTIONS(*aidata) & priv_bit) != 0);
1812 
1813  MemSet(nulls, 0, sizeof(nulls));
1814 
1815  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
1816  result = HeapTupleGetDatum(tuple);
1817 
1818  SRF_RETURN_NEXT(funcctx, result);
1819  }
1820  }
1821 
1822  SRF_RETURN_DONE(funcctx);
1823 }
1824 
1825 
1826 /*
1827  * has_table_privilege variants
1828  * These are all named "has_table_privilege" at the SQL level.
1829  * They take various combinations of relation name, relation OID,
1830  * user name, user OID, or implicit user = current_user.
1831  *
1832  * The result is a boolean value: true if user has the indicated
1833  * privilege, false if not. The variants that take a relation OID
1834  * return NULL if the OID doesn't exist (rather than failing, as
1835  * they did before Postgres 8.4).
1836  */
1837 
1838 /*
1839  * has_table_privilege_name_name
1840  * Check user privileges on a table given
1841  * name username, text tablename, and text priv name.
1842  */
1843 Datum
1845 {
1846  Name rolename = PG_GETARG_NAME(0);
1847  text *tablename = PG_GETARG_TEXT_PP(1);
1848  text *priv_type_text = PG_GETARG_TEXT_PP(2);
1849  Oid roleid;
1850  Oid tableoid;
1851  AclMode mode;
1852  AclResult aclresult;
1853 
1854  roleid = get_role_oid_or_public(NameStr(*rolename));
1855  tableoid = convert_table_name(tablename);
1856  mode = convert_table_priv_string(priv_type_text);
1857 
1858  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1859 
1860  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1861 }
1862 
1863 /*
1864  * has_table_privilege_name
1865  * Check user privileges on a table given
1866  * text tablename and text priv name.
1867  * current_user is assumed
1868  */
1869 Datum
1871 {
1872  text *tablename = PG_GETARG_TEXT_PP(0);
1873  text *priv_type_text = PG_GETARG_TEXT_PP(1);
1874  Oid roleid;
1875  Oid tableoid;
1876  AclMode mode;
1877  AclResult aclresult;
1878 
1879  roleid = GetUserId();
1880  tableoid = convert_table_name(tablename);
1881  mode = convert_table_priv_string(priv_type_text);
1882 
1883  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1884 
1885  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1886 }
1887 
1888 /*
1889  * has_table_privilege_name_id
1890  * Check user privileges on a table given
1891  * name usename, table oid, and text priv name.
1892  */
1893 Datum
1895 {
1897  Oid tableoid = PG_GETARG_OID(1);
1898  text *priv_type_text = PG_GETARG_TEXT_PP(2);
1899  Oid roleid;
1900  AclMode mode;
1901  AclResult aclresult;
1902 
1903  roleid = get_role_oid_or_public(NameStr(*username));
1904  mode = convert_table_priv_string(priv_type_text);
1905 
1907  PG_RETURN_NULL();
1908 
1909  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1910 
1911  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1912 }
1913 
1914 /*
1915  * has_table_privilege_id
1916  * Check user privileges on a table given
1917  * table oid, and text priv name.
1918  * current_user is assumed
1919  */
1920 Datum
1922 {
1923  Oid tableoid = PG_GETARG_OID(0);
1924  text *priv_type_text = PG_GETARG_TEXT_PP(1);
1925  Oid roleid;
1926  AclMode mode;
1927  AclResult aclresult;
1928 
1929  roleid = GetUserId();
1930  mode = convert_table_priv_string(priv_type_text);
1931 
1933  PG_RETURN_NULL();
1934 
1935  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1936 
1937  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1938 }
1939 
1940 /*
1941  * has_table_privilege_id_name
1942  * Check user privileges on a table given
1943  * roleid, text tablename, and text priv name.
1944  */
1945 Datum
1947 {
1948  Oid roleid = PG_GETARG_OID(0);
1949  text *tablename = PG_GETARG_TEXT_PP(1);
1950  text *priv_type_text = PG_GETARG_TEXT_PP(2);
1951  Oid tableoid;
1952  AclMode mode;
1953  AclResult aclresult;
1954 
1955  tableoid = convert_table_name(tablename);
1956  mode = convert_table_priv_string(priv_type_text);
1957 
1958  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1959 
1960  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1961 }
1962 
1963 /*
1964  * has_table_privilege_id_id
1965  * Check user privileges on a table given
1966  * roleid, table oid, and text priv name.
1967  */
1968 Datum
1970 {
1971  Oid roleid = PG_GETARG_OID(0);
1972  Oid tableoid = PG_GETARG_OID(1);
1973  text *priv_type_text = PG_GETARG_TEXT_PP(2);
1974  AclMode mode;
1975  AclResult aclresult;
1976 
1977  mode = convert_table_priv_string(priv_type_text);
1978 
1980  PG_RETURN_NULL();
1981 
1982  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1983 
1984  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1985 }
1986 
1987 /*
1988  * Support routines for has_table_privilege family.
1989  */
1990 
1991 /*
1992  * Given a table name expressed as a string, look it up and return Oid
1993  */
1994 static Oid
1996 {
1997  RangeVar *relrv;
1998 
2000 
2001  /* We might not even have permissions on this relation; don't lock it. */
2002  return RangeVarGetRelid(relrv, NoLock, false);
2003 }
2004 
2005 /*
2006  * convert_table_priv_string
2007  * Convert text string to AclMode value.
2008  */
2009 static AclMode
2011 {
2012  static const priv_map table_priv_map[] = {
2013  {"SELECT", ACL_SELECT},
2014  {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
2015  {"INSERT", ACL_INSERT},
2016  {"INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT)},
2017  {"UPDATE", ACL_UPDATE},
2018  {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
2019  {"DELETE", ACL_DELETE},
2020  {"DELETE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_DELETE)},
2021  {"TRUNCATE", ACL_TRUNCATE},
2022  {"TRUNCATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRUNCATE)},
2023  {"REFERENCES", ACL_REFERENCES},
2024  {"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
2025  {"TRIGGER", ACL_TRIGGER},
2026  {"TRIGGER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRIGGER)},
2027  {"RULE", 0}, /* ignore old RULE privileges */
2028  {"RULE WITH GRANT OPTION", 0},
2029  {NULL, 0}
2030  };
2031 
2032  return convert_any_priv_string(priv_type_text, table_priv_map);
2033 }
2034 
2035 /*
2036  * has_sequence_privilege variants
2037  * These are all named "has_sequence_privilege" at the SQL level.
2038  * They take various combinations of relation name, relation OID,
2039  * user name, user OID, or implicit user = current_user.
2040  *
2041  * The result is a boolean value: true if user has the indicated
2042  * privilege, false if not. The variants that take a relation OID
2043  * return NULL if the OID doesn't exist.
2044  */
2045 
2046 /*
2047  * has_sequence_privilege_name_name
2048  * Check user privileges on a sequence given
2049  * name username, text sequencename, and text priv name.
2050  */
2051 Datum
2053 {
2054  Name rolename = PG_GETARG_NAME(0);
2055  text *sequencename = PG_GETARG_TEXT_PP(1);
2056  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2057  Oid roleid;
2058  Oid sequenceoid;
2059  AclMode mode;
2060  AclResult aclresult;
2061 
2062  roleid = get_role_oid_or_public(NameStr(*rolename));
2063  mode = convert_sequence_priv_string(priv_type_text);
2064  sequenceoid = convert_table_name(sequencename);
2065  if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
2066  ereport(ERROR,
2067  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2068  errmsg("\"%s\" is not a sequence",
2069  text_to_cstring(sequencename))));
2070 
2071  aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
2072 
2073  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2074 }
2075 
2076 /*
2077  * has_sequence_privilege_name
2078  * Check user privileges on a sequence given
2079  * text sequencename and text priv name.
2080  * current_user is assumed
2081  */
2082 Datum
2084 {
2085  text *sequencename = PG_GETARG_TEXT_PP(0);
2086  text *priv_type_text = PG_GETARG_TEXT_PP(1);
2087  Oid roleid;
2088  Oid sequenceoid;
2089  AclMode mode;
2090  AclResult aclresult;
2091 
2092  roleid = GetUserId();
2093  mode = convert_sequence_priv_string(priv_type_text);
2094  sequenceoid = convert_table_name(sequencename);
2095  if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
2096  ereport(ERROR,
2097  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2098  errmsg("\"%s\" is not a sequence",
2099  text_to_cstring(sequencename))));
2100 
2101  aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
2102 
2103  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2104 }
2105 
2106 /*
2107  * has_sequence_privilege_name_id
2108  * Check user privileges on a sequence given
2109  * name usename, sequence oid, and text priv name.
2110  */
2111 Datum
2113 {
2115  Oid sequenceoid = PG_GETARG_OID(1);
2116  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2117  Oid roleid;
2118  AclMode mode;
2119  AclResult aclresult;
2120  char relkind;
2121 
2122  roleid = get_role_oid_or_public(NameStr(*username));
2123  mode = convert_sequence_priv_string(priv_type_text);
2124  relkind = get_rel_relkind(sequenceoid);
2125  if (relkind == '\0')
2126  PG_RETURN_NULL();
2127  else if (relkind != RELKIND_SEQUENCE)
2128  ereport(ERROR,
2129  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2130  errmsg("\"%s\" is not a sequence",
2131  get_rel_name(sequenceoid))));
2132 
2133  aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
2134 
2135  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2136 }
2137 
2138 /*
2139  * has_sequence_privilege_id
2140  * Check user privileges on a sequence given
2141  * sequence oid, and text priv name.
2142  * current_user is assumed
2143  */
2144 Datum
2146 {
2147  Oid sequenceoid = PG_GETARG_OID(0);
2148  text *priv_type_text = PG_GETARG_TEXT_PP(1);
2149  Oid roleid;
2150  AclMode mode;
2151  AclResult aclresult;
2152  char relkind;
2153 
2154  roleid = GetUserId();
2155  mode = convert_sequence_priv_string(priv_type_text);
2156  relkind = get_rel_relkind(sequenceoid);
2157  if (relkind == '\0')
2158  PG_RETURN_NULL();
2159  else if (relkind != RELKIND_SEQUENCE)
2160  ereport(ERROR,
2161  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2162  errmsg("\"%s\" is not a sequence",
2163  get_rel_name(sequenceoid))));
2164 
2165  aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
2166 
2167  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2168 }
2169 
2170 /*
2171  * has_sequence_privilege_id_name
2172  * Check user privileges on a sequence given
2173  * roleid, text sequencename, and text priv name.
2174  */
2175 Datum
2177 {
2178  Oid roleid = PG_GETARG_OID(0);
2179  text *sequencename = PG_GETARG_TEXT_PP(1);
2180  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2181  Oid sequenceoid;
2182  AclMode mode;
2183  AclResult aclresult;
2184 
2185  mode = convert_sequence_priv_string(priv_type_text);
2186  sequenceoid = convert_table_name(sequencename);
2187  if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
2188  ereport(ERROR,
2189  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2190  errmsg("\"%s\" is not a sequence",
2191  text_to_cstring(sequencename))));
2192 
2193  aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
2194 
2195  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2196 }
2197 
2198 /*
2199  * has_sequence_privilege_id_id
2200  * Check user privileges on a sequence given
2201  * roleid, sequence oid, and text priv name.
2202  */
2203 Datum
2205 {
2206  Oid roleid = PG_GETARG_OID(0);
2207  Oid sequenceoid = PG_GETARG_OID(1);
2208  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2209  AclMode mode;
2210  AclResult aclresult;
2211  char relkind;
2212 
2213  mode = convert_sequence_priv_string(priv_type_text);
2214  relkind = get_rel_relkind(sequenceoid);
2215  if (relkind == '\0')
2216  PG_RETURN_NULL();
2217  else if (relkind != RELKIND_SEQUENCE)
2218  ereport(ERROR,
2219  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2220  errmsg("\"%s\" is not a sequence",
2221  get_rel_name(sequenceoid))));
2222 
2223  aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
2224 
2225  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2226 }
2227 
2228 /*
2229  * convert_sequence_priv_string
2230  * Convert text string to AclMode value.
2231  */
2232 static AclMode
2234 {
2235  static const priv_map sequence_priv_map[] = {
2236  {"USAGE", ACL_USAGE},
2237  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
2238  {"SELECT", ACL_SELECT},
2239  {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
2240  {"UPDATE", ACL_UPDATE},
2241  {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
2242  {NULL, 0}
2243  };
2244 
2245  return convert_any_priv_string(priv_type_text, sequence_priv_map);
2246 }
2247 
2248 
2249 /*
2250  * has_any_column_privilege variants
2251  * These are all named "has_any_column_privilege" at the SQL level.
2252  * They take various combinations of relation name, relation OID,
2253  * user name, user OID, or implicit user = current_user.
2254  *
2255  * The result is a boolean value: true if user has the indicated
2256  * privilege for any column of the table, false if not. The variants
2257  * that take a relation OID return NULL if the OID doesn't exist.
2258  */
2259 
2260 /*
2261  * has_any_column_privilege_name_name
2262  * Check user privileges on any column of a table given
2263  * name username, text tablename, and text priv name.
2264  */
2265 Datum
2267 {
2268  Name rolename = PG_GETARG_NAME(0);
2269  text *tablename = PG_GETARG_TEXT_PP(1);
2270  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2271  Oid roleid;
2272  Oid tableoid;
2273  AclMode mode;
2274  AclResult aclresult;
2275 
2276  roleid = get_role_oid_or_public(NameStr(*rolename));
2277  tableoid = convert_table_name(tablename);
2278  mode = convert_column_priv_string(priv_type_text);
2279 
2280  /* First check at table level, then examine each column if needed */
2281  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2282  if (aclresult != ACLCHECK_OK)
2283  aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2284  ACLMASK_ANY);
2285 
2286  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2287 }
2288 
2289 /*
2290  * has_any_column_privilege_name
2291  * Check user privileges on any column of a table given
2292  * text tablename and text priv name.
2293  * current_user is assumed
2294  */
2295 Datum
2297 {
2298  text *tablename = PG_GETARG_TEXT_PP(0);
2299  text *priv_type_text = PG_GETARG_TEXT_PP(1);
2300  Oid roleid;
2301  Oid tableoid;
2302  AclMode mode;
2303  AclResult aclresult;
2304 
2305  roleid = GetUserId();
2306  tableoid = convert_table_name(tablename);
2307  mode = convert_column_priv_string(priv_type_text);
2308 
2309  /* First check at table level, then examine each column if needed */
2310  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2311  if (aclresult != ACLCHECK_OK)
2312  aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2313  ACLMASK_ANY);
2314 
2315  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2316 }
2317 
2318 /*
2319  * has_any_column_privilege_name_id
2320  * Check user privileges on any column of a table given
2321  * name usename, table oid, and text priv name.
2322  */
2323 Datum
2325 {
2327  Oid tableoid = PG_GETARG_OID(1);
2328  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2329  Oid roleid;
2330  AclMode mode;
2331  AclResult aclresult;
2332 
2333  roleid = get_role_oid_or_public(NameStr(*username));
2334  mode = convert_column_priv_string(priv_type_text);
2335 
2337  PG_RETURN_NULL();
2338 
2339  /* First check at table level, then examine each column if needed */
2340  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2341  if (aclresult != ACLCHECK_OK)
2342  aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2343  ACLMASK_ANY);
2344 
2345  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2346 }
2347 
2348 /*
2349  * has_any_column_privilege_id
2350  * Check user privileges on any column of a table given
2351  * table oid, and text priv name.
2352  * current_user is assumed
2353  */
2354 Datum
2356 {
2357  Oid tableoid = PG_GETARG_OID(0);
2358  text *priv_type_text = PG_GETARG_TEXT_PP(1);
2359  Oid roleid;
2360  AclMode mode;
2361  AclResult aclresult;
2362 
2363  roleid = GetUserId();
2364  mode = convert_column_priv_string(priv_type_text);
2365 
2367  PG_RETURN_NULL();
2368 
2369  /* First check at table level, then examine each column if needed */
2370  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2371  if (aclresult != ACLCHECK_OK)
2372  aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2373  ACLMASK_ANY);
2374 
2375  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2376 }
2377 
2378 /*
2379  * has_any_column_privilege_id_name
2380  * Check user privileges on any column of a table given
2381  * roleid, text tablename, and text priv name.
2382  */
2383 Datum
2385 {
2386  Oid roleid = PG_GETARG_OID(0);
2387  text *tablename = PG_GETARG_TEXT_PP(1);
2388  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2389  Oid tableoid;
2390  AclMode mode;
2391  AclResult aclresult;
2392 
2393  tableoid = convert_table_name(tablename);
2394  mode = convert_column_priv_string(priv_type_text);
2395 
2396  /* First check at table level, then examine each column if needed */
2397  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2398  if (aclresult != ACLCHECK_OK)
2399  aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2400  ACLMASK_ANY);
2401 
2402  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2403 }
2404 
2405 /*
2406  * has_any_column_privilege_id_id
2407  * Check user privileges on any column of a table given
2408  * roleid, table oid, and text priv name.
2409  */
2410 Datum
2412 {
2413  Oid roleid = PG_GETARG_OID(0);
2414  Oid tableoid = PG_GETARG_OID(1);
2415  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2416  AclMode mode;
2417  AclResult aclresult;
2418 
2419  mode = convert_column_priv_string(priv_type_text);
2420 
2422  PG_RETURN_NULL();
2423 
2424  /* First check at table level, then examine each column if needed */
2425  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2426  if (aclresult != ACLCHECK_OK)
2427  aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2428  ACLMASK_ANY);
2429 
2430  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2431 }
2432 
2433 
2434 /*
2435  * has_column_privilege variants
2436  * These are all named "has_column_privilege" at the SQL level.
2437  * They take various combinations of relation name, relation OID,
2438  * column name, column attnum, user name, user OID, or
2439  * implicit user = current_user.
2440  *
2441  * The result is a boolean value: true if user has the indicated
2442  * privilege, false if not. The variants that take a relation OID
2443  * return NULL (rather than throwing an error) if that relation OID
2444  * doesn't exist. Likewise, the variants that take an integer attnum
2445  * return NULL (rather than throwing an error) if there is no such
2446  * pg_attribute entry. All variants return NULL if an attisdropped
2447  * column is selected. These rules are meant to avoid unnecessary
2448  * failures in queries that scan pg_attribute.
2449  */
2450 
2451 /*
2452  * column_privilege_check: check column privileges, but don't throw an error
2453  * for dropped column or table
2454  *
2455  * Returns 1 if have the privilege, 0 if not, -1 if dropped column/table.
2456  */
2457 static int
2459  Oid roleid, AclMode mode)
2460 {
2461  AclResult aclresult;
2462  HeapTuple attTuple;
2463  Form_pg_attribute attributeForm;
2464 
2465  /*
2466  * If convert_column_name failed, we can just return -1 immediately.
2467  */
2468  if (attnum == InvalidAttrNumber)
2469  return -1;
2470 
2471  /*
2472  * First check if we have the privilege at the table level. We check
2473  * existence of the pg_class row before risking calling pg_class_aclcheck.
2474  * Note: it might seem there's a race condition against concurrent DROP,
2475  * but really it's safe because there will be no syscache flush between
2476  * here and there. So if we see the row in the syscache, so will
2477  * pg_class_aclcheck.
2478  */
2480  return -1;
2481 
2482  aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2483 
2484  if (aclresult == ACLCHECK_OK)
2485  return true;
2486 
2487  /*
2488  * No table privilege, so try per-column privileges. Again, we have to
2489  * check for dropped attribute first, and we rely on the syscache not to
2490  * notice a concurrent drop before pg_attribute_aclcheck fetches the row.
2491  */
2492  attTuple = SearchSysCache2(ATTNUM,
2493  ObjectIdGetDatum(tableoid),
2494  Int16GetDatum(attnum));
2495  if (!HeapTupleIsValid(attTuple))
2496  return -1;
2497  attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
2498  if (attributeForm->attisdropped)
2499  {
2500  ReleaseSysCache(attTuple);
2501  return -1;
2502  }
2503  ReleaseSysCache(attTuple);
2504 
2505  aclresult = pg_attribute_aclcheck(tableoid, attnum, roleid, mode);
2506 
2507  return (aclresult == ACLCHECK_OK);
2508 }
2509 
2510 /*
2511  * has_column_privilege_name_name_name
2512  * Check user privileges on a column given
2513  * name username, text tablename, text colname, and text priv name.
2514  */
2515 Datum
2517 {
2518  Name rolename = PG_GETARG_NAME(0);
2519  text *tablename = PG_GETARG_TEXT_PP(1);
2520  text *column = PG_GETARG_TEXT_PP(2);
2521  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2522  Oid roleid;
2523  Oid tableoid;
2524  AttrNumber colattnum;
2525  AclMode mode;
2526  int privresult;
2527 
2528  roleid = get_role_oid_or_public(NameStr(*rolename));
2529  tableoid = convert_table_name(tablename);
2530  colattnum = convert_column_name(tableoid, column);
2531  mode = convert_column_priv_string(priv_type_text);
2532 
2533  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2534  if (privresult < 0)
2535  PG_RETURN_NULL();
2536  PG_RETURN_BOOL(privresult);
2537 }
2538 
2539 /*
2540  * has_column_privilege_name_name_attnum
2541  * Check user privileges on a column given
2542  * name username, text tablename, int attnum, and text priv name.
2543  */
2544 Datum
2546 {
2547  Name rolename = PG_GETARG_NAME(0);
2548  text *tablename = PG_GETARG_TEXT_PP(1);
2549  AttrNumber colattnum = PG_GETARG_INT16(2);
2550  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2551  Oid roleid;
2552  Oid tableoid;
2553  AclMode mode;
2554  int privresult;
2555 
2556  roleid = get_role_oid_or_public(NameStr(*rolename));
2557  tableoid = convert_table_name(tablename);
2558  mode = convert_column_priv_string(priv_type_text);
2559 
2560  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2561  if (privresult < 0)
2562  PG_RETURN_NULL();
2563  PG_RETURN_BOOL(privresult);
2564 }
2565 
2566 /*
2567  * has_column_privilege_name_id_name
2568  * Check user privileges on a column given
2569  * name username, table oid, text colname, and text priv name.
2570  */
2571 Datum
2573 {
2575  Oid tableoid = PG_GETARG_OID(1);
2576  text *column = PG_GETARG_TEXT_PP(2);
2577  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2578  Oid roleid;
2579  AttrNumber colattnum;
2580  AclMode mode;
2581  int privresult;
2582 
2583  roleid = get_role_oid_or_public(NameStr(*username));
2584  colattnum = convert_column_name(tableoid, column);
2585  mode = convert_column_priv_string(priv_type_text);
2586 
2587  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2588  if (privresult < 0)
2589  PG_RETURN_NULL();
2590  PG_RETURN_BOOL(privresult);
2591 }
2592 
2593 /*
2594  * has_column_privilege_name_id_attnum
2595  * Check user privileges on a column given
2596  * name username, table oid, int attnum, and text priv name.
2597  */
2598 Datum
2600 {
2602  Oid tableoid = PG_GETARG_OID(1);
2603  AttrNumber colattnum = PG_GETARG_INT16(2);
2604  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2605  Oid roleid;
2606  AclMode mode;
2607  int privresult;
2608 
2609  roleid = get_role_oid_or_public(NameStr(*username));
2610  mode = convert_column_priv_string(priv_type_text);
2611 
2612  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2613  if (privresult < 0)
2614  PG_RETURN_NULL();
2615  PG_RETURN_BOOL(privresult);
2616 }
2617 
2618 /*
2619  * has_column_privilege_id_name_name
2620  * Check user privileges on a column given
2621  * oid roleid, text tablename, text colname, and text priv name.
2622  */
2623 Datum
2625 {
2626  Oid roleid = PG_GETARG_OID(0);
2627  text *tablename = PG_GETARG_TEXT_PP(1);
2628  text *column = PG_GETARG_TEXT_PP(2);
2629  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2630  Oid tableoid;
2631  AttrNumber colattnum;
2632  AclMode mode;
2633  int privresult;
2634 
2635  tableoid = convert_table_name(tablename);
2636  colattnum = convert_column_name(tableoid, column);
2637  mode = convert_column_priv_string(priv_type_text);
2638 
2639  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2640  if (privresult < 0)
2641  PG_RETURN_NULL();
2642  PG_RETURN_BOOL(privresult);
2643 }
2644 
2645 /*
2646  * has_column_privilege_id_name_attnum
2647  * Check user privileges on a column given
2648  * oid roleid, text tablename, int attnum, and text priv name.
2649  */
2650 Datum
2652 {
2653  Oid roleid = PG_GETARG_OID(0);
2654  text *tablename = PG_GETARG_TEXT_PP(1);
2655  AttrNumber colattnum = PG_GETARG_INT16(2);
2656  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2657  Oid tableoid;
2658  AclMode mode;
2659  int privresult;
2660 
2661  tableoid = convert_table_name(tablename);
2662  mode = convert_column_priv_string(priv_type_text);
2663 
2664  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2665  if (privresult < 0)
2666  PG_RETURN_NULL();
2667  PG_RETURN_BOOL(privresult);
2668 }
2669 
2670 /*
2671  * has_column_privilege_id_id_name
2672  * Check user privileges on a column given
2673  * oid roleid, table oid, text colname, and text priv name.
2674  */
2675 Datum
2677 {
2678  Oid roleid = PG_GETARG_OID(0);
2679  Oid tableoid = PG_GETARG_OID(1);
2680  text *column = PG_GETARG_TEXT_PP(2);
2681  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2682  AttrNumber colattnum;
2683  AclMode mode;
2684  int privresult;
2685 
2686  colattnum = convert_column_name(tableoid, column);
2687  mode = convert_column_priv_string(priv_type_text);
2688 
2689  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2690  if (privresult < 0)
2691  PG_RETURN_NULL();
2692  PG_RETURN_BOOL(privresult);
2693 }
2694 
2695 /*
2696  * has_column_privilege_id_id_attnum
2697  * Check user privileges on a column given
2698  * oid roleid, table oid, int attnum, and text priv name.
2699  */
2700 Datum
2702 {
2703  Oid roleid = PG_GETARG_OID(0);
2704  Oid tableoid = PG_GETARG_OID(1);
2705  AttrNumber colattnum = PG_GETARG_INT16(2);
2706  text *priv_type_text = PG_GETARG_TEXT_PP(3);
2707  AclMode mode;
2708  int privresult;
2709 
2710  mode = convert_column_priv_string(priv_type_text);
2711 
2712  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2713  if (privresult < 0)
2714  PG_RETURN_NULL();
2715  PG_RETURN_BOOL(privresult);
2716 }
2717 
2718 /*
2719  * has_column_privilege_name_name
2720  * Check user privileges on a column given
2721  * text tablename, text colname, and text priv name.
2722  * current_user is assumed
2723  */
2724 Datum
2726 {
2727  text *tablename = PG_GETARG_TEXT_PP(0);
2728  text *column = PG_GETARG_TEXT_PP(1);
2729  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2730  Oid roleid;
2731  Oid tableoid;
2732  AttrNumber colattnum;
2733  AclMode mode;
2734  int privresult;
2735 
2736  roleid = GetUserId();
2737  tableoid = convert_table_name(tablename);
2738  colattnum = convert_column_name(tableoid, column);
2739  mode = convert_column_priv_string(priv_type_text);
2740 
2741  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2742  if (privresult < 0)
2743  PG_RETURN_NULL();
2744  PG_RETURN_BOOL(privresult);
2745 }
2746 
2747 /*
2748  * has_column_privilege_name_attnum
2749  * Check user privileges on a column given
2750  * text tablename, int attnum, and text priv name.
2751  * current_user is assumed
2752  */
2753 Datum
2755 {
2756  text *tablename = PG_GETARG_TEXT_PP(0);
2757  AttrNumber colattnum = PG_GETARG_INT16(1);
2758  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2759  Oid roleid;
2760  Oid tableoid;
2761  AclMode mode;
2762  int privresult;
2763 
2764  roleid = GetUserId();
2765  tableoid = convert_table_name(tablename);
2766  mode = convert_column_priv_string(priv_type_text);
2767 
2768  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2769  if (privresult < 0)
2770  PG_RETURN_NULL();
2771  PG_RETURN_BOOL(privresult);
2772 }
2773 
2774 /*
2775  * has_column_privilege_id_name
2776  * Check user privileges on a column given
2777  * table oid, text colname, and text priv name.
2778  * current_user is assumed
2779  */
2780 Datum
2782 {
2783  Oid tableoid = PG_GETARG_OID(0);
2784  text *column = PG_GETARG_TEXT_PP(1);
2785  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2786  Oid roleid;
2787  AttrNumber colattnum;
2788  AclMode mode;
2789  int privresult;
2790 
2791  roleid = GetUserId();
2792  colattnum = convert_column_name(tableoid, column);
2793  mode = convert_column_priv_string(priv_type_text);
2794 
2795  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2796  if (privresult < 0)
2797  PG_RETURN_NULL();
2798  PG_RETURN_BOOL(privresult);
2799 }
2800 
2801 /*
2802  * has_column_privilege_id_attnum
2803  * Check user privileges on a column given
2804  * table oid, int attnum, and text priv name.
2805  * current_user is assumed
2806  */
2807 Datum
2809 {
2810  Oid tableoid = PG_GETARG_OID(0);
2811  AttrNumber colattnum = PG_GETARG_INT16(1);
2812  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2813  Oid roleid;
2814  AclMode mode;
2815  int privresult;
2816 
2817  roleid = GetUserId();
2818  mode = convert_column_priv_string(priv_type_text);
2819 
2820  privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2821  if (privresult < 0)
2822  PG_RETURN_NULL();
2823  PG_RETURN_BOOL(privresult);
2824 }
2825 
2826 /*
2827  * Support routines for has_column_privilege family.
2828  */
2829 
2830 /*
2831  * Given a table OID and a column name expressed as a string, look it up
2832  * and return the column number. Returns InvalidAttrNumber in cases
2833  * where caller should return NULL instead of failing.
2834  */
2835 static AttrNumber
2836 convert_column_name(Oid tableoid, text *column)
2837 {
2838  char *colname;
2839  HeapTuple attTuple;
2841 
2842  colname = text_to_cstring(column);
2843 
2844  /*
2845  * We don't use get_attnum() here because it will report that dropped
2846  * columns don't exist. We need to treat dropped columns differently from
2847  * nonexistent columns.
2848  */
2849  attTuple = SearchSysCache2(ATTNAME,
2850  ObjectIdGetDatum(tableoid),
2851  CStringGetDatum(colname));
2852  if (HeapTupleIsValid(attTuple))
2853  {
2854  Form_pg_attribute attributeForm;
2855 
2856  attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
2857  /* We want to return NULL for dropped columns */
2858  if (attributeForm->attisdropped)
2859  attnum = InvalidAttrNumber;
2860  else
2861  attnum = attributeForm->attnum;
2862  ReleaseSysCache(attTuple);
2863  }
2864  else
2865  {
2866  char *tablename = get_rel_name(tableoid);
2867 
2868  /*
2869  * If the table OID is bogus, or it's just been dropped, we'll get
2870  * NULL back. In such cases we want has_column_privilege to return
2871  * NULL too, so just return InvalidAttrNumber.
2872  */
2873  if (tablename != NULL)
2874  {
2875  /* tableoid exists, colname does not, so throw error */
2876  ereport(ERROR,
2877  (errcode(ERRCODE_UNDEFINED_COLUMN),
2878  errmsg("column \"%s\" of relation \"%s\" does not exist",
2879  colname, tablename)));
2880  }
2881  /* tableoid doesn't exist, so act like attisdropped case */
2882  attnum = InvalidAttrNumber;
2883  }
2884 
2885  pfree(colname);
2886  return attnum;
2887 }
2888 
2889 /*
2890  * convert_column_priv_string
2891  * Convert text string to AclMode value.
2892  */
2893 static AclMode
2895 {
2896  static const priv_map column_priv_map[] = {
2897  {"SELECT", ACL_SELECT},
2898  {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
2899  {"INSERT", ACL_INSERT},
2900  {"INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT)},
2901  {"UPDATE", ACL_UPDATE},
2902  {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
2903  {"REFERENCES", ACL_REFERENCES},
2904  {"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
2905  {NULL, 0}
2906  };
2907 
2908  return convert_any_priv_string(priv_type_text, column_priv_map);
2909 }
2910 
2911 
2912 /*
2913  * has_database_privilege variants
2914  * These are all named "has_database_privilege" at the SQL level.
2915  * They take various combinations of database name, database OID,
2916  * user name, user OID, or implicit user = current_user.
2917  *
2918  * The result is a boolean value: true if user has the indicated
2919  * privilege, false if not, or NULL if object doesn't exist.
2920  */
2921 
2922 /*
2923  * has_database_privilege_name_name
2924  * Check user privileges on a database given
2925  * name username, text databasename, and text priv name.
2926  */
2927 Datum
2929 {
2931  text *databasename = PG_GETARG_TEXT_PP(1);
2932  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2933  Oid roleid;
2934  Oid databaseoid;
2935  AclMode mode;
2936  AclResult aclresult;
2937 
2938  roleid = get_role_oid_or_public(NameStr(*username));
2939  databaseoid = convert_database_name(databasename);
2940  mode = convert_database_priv_string(priv_type_text);
2941 
2942  aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
2943 
2944  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2945 }
2946 
2947 /*
2948  * has_database_privilege_name
2949  * Check user privileges on a database given
2950  * text databasename and text priv name.
2951  * current_user is assumed
2952  */
2953 Datum
2955 {
2956  text *databasename = PG_GETARG_TEXT_PP(0);
2957  text *priv_type_text = PG_GETARG_TEXT_PP(1);
2958  Oid roleid;
2959  Oid databaseoid;
2960  AclMode mode;
2961  AclResult aclresult;
2962 
2963  roleid = GetUserId();
2964  databaseoid = convert_database_name(databasename);
2965  mode = convert_database_priv_string(priv_type_text);
2966 
2967  aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
2968 
2969  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2970 }
2971 
2972 /*
2973  * has_database_privilege_name_id
2974  * Check user privileges on a database given
2975  * name usename, database oid, and text priv name.
2976  */
2977 Datum
2979 {
2981  Oid databaseoid = PG_GETARG_OID(1);
2982  text *priv_type_text = PG_GETARG_TEXT_PP(2);
2983  Oid roleid;
2984  AclMode mode;
2985  AclResult aclresult;
2986 
2987  roleid = get_role_oid_or_public(NameStr(*username));
2988  mode = convert_database_priv_string(priv_type_text);
2989 
2991  PG_RETURN_NULL();
2992 
2993  aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
2994 
2995  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
2996 }
2997 
2998 /*
2999  * has_database_privilege_id
3000  * Check user privileges on a database given
3001  * database oid, and text priv name.
3002  * current_user is assumed
3003  */
3004 Datum
3006 {
3007  Oid databaseoid = PG_GETARG_OID(0);
3008  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3009  Oid roleid;
3010  AclMode mode;
3011  AclResult aclresult;
3012 
3013  roleid = GetUserId();
3014  mode = convert_database_priv_string(priv_type_text);
3015 
3017  PG_RETURN_NULL();
3018 
3019  aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
3020 
3021  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3022 }
3023 
3024 /*
3025  * has_database_privilege_id_name
3026  * Check user privileges on a database given
3027  * roleid, text databasename, and text priv name.
3028  */
3029 Datum
3031 {
3032  Oid roleid = PG_GETARG_OID(0);
3033  text *databasename = PG_GETARG_TEXT_PP(1);
3034  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3035  Oid databaseoid;
3036  AclMode mode;
3037  AclResult aclresult;
3038 
3039  databaseoid = convert_database_name(databasename);
3040  mode = convert_database_priv_string(priv_type_text);
3041 
3042  aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
3043 
3044  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3045 }
3046 
3047 /*
3048  * has_database_privilege_id_id
3049  * Check user privileges on a database given
3050  * roleid, database oid, and text priv name.
3051  */
3052 Datum
3054 {
3055  Oid roleid = PG_GETARG_OID(0);
3056  Oid databaseoid = PG_GETARG_OID(1);
3057  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3058  AclMode mode;
3059  AclResult aclresult;
3060 
3061  mode = convert_database_priv_string(priv_type_text);
3062 
3064  PG_RETURN_NULL();
3065 
3066  aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
3067 
3068  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3069 }
3070 
3071 /*
3072  * Support routines for has_database_privilege family.
3073  */
3074 
3075 /*
3076  * Given a database name expressed as a string, look it up and return Oid
3077  */
3078 static Oid
3080 {
3081  char *dbname = text_to_cstring(databasename);
3082 
3083  return get_database_oid(dbname, false);
3084 }
3085 
3086 /*
3087  * convert_database_priv_string
3088  * Convert text string to AclMode value.
3089  */
3090 static AclMode
3092 {
3093  static const priv_map database_priv_map[] = {
3094  {"CREATE", ACL_CREATE},
3095  {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
3096  {"TEMPORARY", ACL_CREATE_TEMP},
3097  {"TEMPORARY WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP)},
3098  {"TEMP", ACL_CREATE_TEMP},
3099  {"TEMP WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP)},
3100  {"CONNECT", ACL_CONNECT},
3101  {"CONNECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CONNECT)},
3102  {NULL, 0}
3103  };
3104 
3105  return convert_any_priv_string(priv_type_text, database_priv_map);
3106 
3107 }
3108 
3109 
3110 /*
3111  * has_foreign_data_wrapper_privilege variants
3112  * These are all named "has_foreign_data_wrapper_privilege" at the SQL level.
3113  * They take various combinations of foreign-data wrapper name,
3114  * fdw OID, user name, user OID, or implicit user = current_user.
3115  *
3116  * The result is a boolean value: true if user has the indicated
3117  * privilege, false if not.
3118  */
3119 
3120 /*
3121  * has_foreign_data_wrapper_privilege_name_name
3122  * Check user privileges on a foreign-data wrapper given
3123  * name username, text fdwname, and text priv name.
3124  */
3125 Datum
3127 {
3129  text *fdwname = PG_GETARG_TEXT_PP(1);
3130  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3131  Oid roleid;
3132  Oid fdwid;
3133  AclMode mode;
3134  AclResult aclresult;
3135 
3136  roleid = get_role_oid_or_public(NameStr(*username));
3137  fdwid = convert_foreign_data_wrapper_name(fdwname);
3138  mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
3139 
3140  aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
3141 
3142  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3143 }
3144 
3145 /*
3146  * has_foreign_data_wrapper_privilege_name
3147  * Check user privileges on a foreign-data wrapper given
3148  * text fdwname and text priv name.
3149  * current_user is assumed
3150  */
3151 Datum
3153 {
3154  text *fdwname = PG_GETARG_TEXT_PP(0);
3155  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3156  Oid roleid;
3157  Oid fdwid;
3158  AclMode mode;
3159  AclResult aclresult;
3160 
3161  roleid = GetUserId();
3162  fdwid = convert_foreign_data_wrapper_name(fdwname);
3163  mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
3164 
3165  aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
3166 
3167  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3168 }
3169 
3170 /*
3171  * has_foreign_data_wrapper_privilege_name_id
3172  * Check user privileges on a foreign-data wrapper given
3173  * name usename, foreign-data wrapper oid, and text priv name.
3174  */
3175 Datum
3177 {
3179  Oid fdwid = PG_GETARG_OID(1);
3180  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3181  Oid roleid;
3182  AclMode mode;
3183  AclResult aclresult;
3184 
3185  roleid = get_role_oid_or_public(NameStr(*username));
3186  mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
3187 
3189  PG_RETURN_NULL();
3190 
3191  aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
3192 
3193  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3194 }
3195 
3196 /*
3197  * has_foreign_data_wrapper_privilege_id
3198  * Check user privileges on a foreign-data wrapper given
3199  * foreign-data wrapper oid, and text priv name.
3200  * current_user is assumed
3201  */
3202 Datum
3204 {
3205  Oid fdwid = PG_GETARG_OID(0);
3206  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3207  Oid roleid;
3208  AclMode mode;
3209  AclResult aclresult;
3210 
3211  roleid = GetUserId();
3212  mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
3213 
3215  PG_RETURN_NULL();
3216 
3217  aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
3218 
3219  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3220 }
3221 
3222 /*
3223  * has_foreign_data_wrapper_privilege_id_name
3224  * Check user privileges on a foreign-data wrapper given
3225  * roleid, text fdwname, and text priv name.
3226  */
3227 Datum
3229 {
3230  Oid roleid = PG_GETARG_OID(0);
3231  text *fdwname = PG_GETARG_TEXT_PP(1);
3232  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3233  Oid fdwid;
3234  AclMode mode;
3235  AclResult aclresult;
3236 
3237  fdwid = convert_foreign_data_wrapper_name(fdwname);
3238  mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
3239 
3240  aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
3241 
3242  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3243 }
3244 
3245 /*
3246  * has_foreign_data_wrapper_privilege_id_id
3247  * Check user privileges on a foreign-data wrapper given
3248  * roleid, fdw oid, and text priv name.
3249  */
3250 Datum
3252 {
3253  Oid roleid = PG_GETARG_OID(0);
3254  Oid fdwid = PG_GETARG_OID(1);
3255  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3256  AclMode mode;
3257  AclResult aclresult;
3258 
3259  mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
3260 
3262  PG_RETURN_NULL();
3263 
3264  aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
3265 
3266  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3267 }
3268 
3269 /*
3270  * Support routines for has_foreign_data_wrapper_privilege family.
3271  */
3272 
3273 /*
3274  * Given a FDW name expressed as a string, look it up and return Oid
3275  */
3276 static Oid
3278 {
3279  char *fdwstr = text_to_cstring(fdwname);
3280 
3281  return get_foreign_data_wrapper_oid(fdwstr, false);
3282 }
3283 
3284 /*
3285  * convert_foreign_data_wrapper_priv_string
3286  * Convert text string to AclMode value.
3287  */
3288 static AclMode
3290 {
3291  static const priv_map foreign_data_wrapper_priv_map[] = {
3292  {"USAGE", ACL_USAGE},
3293  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
3294  {NULL, 0}
3295  };
3296 
3297  return convert_any_priv_string(priv_type_text, foreign_data_wrapper_priv_map);
3298 }
3299 
3300 
3301 /*
3302  * has_function_privilege variants
3303  * These are all named "has_function_privilege" at the SQL level.
3304  * They take various combinations of function name, function OID,
3305  * user name, user OID, or implicit user = current_user.
3306  *
3307  * The result is a boolean value: true if user has the indicated
3308  * privilege, false if not, or NULL if object doesn't exist.
3309  */
3310 
3311 /*
3312  * has_function_privilege_name_name
3313  * Check user privileges on a function given
3314  * name username, text functionname, and text priv name.
3315  */
3316 Datum
3318 {
3320  text *functionname = PG_GETARG_TEXT_PP(1);
3321  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3322  Oid roleid;
3323  Oid functionoid;
3324  AclMode mode;
3325  AclResult aclresult;
3326 
3327  roleid = get_role_oid_or_public(NameStr(*username));
3328  functionoid = convert_function_name(functionname);
3329  mode = convert_function_priv_string(priv_type_text);
3330 
3331  aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
3332 
3333  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3334 }
3335 
3336 /*
3337  * has_function_privilege_name
3338  * Check user privileges on a function given
3339  * text functionname and text priv name.
3340  * current_user is assumed
3341  */
3342 Datum
3344 {
3345  text *functionname = PG_GETARG_TEXT_PP(0);
3346  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3347  Oid roleid;
3348  Oid functionoid;
3349  AclMode mode;
3350  AclResult aclresult;
3351 
3352  roleid = GetUserId();
3353  functionoid = convert_function_name(functionname);
3354  mode = convert_function_priv_string(priv_type_text);
3355 
3356  aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
3357 
3358  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3359 }
3360 
3361 /*
3362  * has_function_privilege_name_id
3363  * Check user privileges on a function given
3364  * name usename, function oid, and text priv name.
3365  */
3366 Datum
3368 {
3370  Oid functionoid = PG_GETARG_OID(1);
3371  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3372  Oid roleid;
3373  AclMode mode;
3374  AclResult aclresult;
3375 
3376  roleid = get_role_oid_or_public(NameStr(*username));
3377  mode = convert_function_priv_string(priv_type_text);
3378 
3379  if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(functionoid)))
3380  PG_RETURN_NULL();
3381 
3382  aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
3383 
3384  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3385 }
3386 
3387 /*
3388  * has_function_privilege_id
3389  * Check user privileges on a function given
3390  * function oid, and text priv name.
3391  * current_user is assumed
3392  */
3393 Datum
3395 {
3396  Oid functionoid = PG_GETARG_OID(0);
3397  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3398  Oid roleid;
3399  AclMode mode;
3400  AclResult aclresult;
3401 
3402  roleid = GetUserId();
3403  mode = convert_function_priv_string(priv_type_text);
3404 
3405  if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(functionoid)))
3406  PG_RETURN_NULL();
3407 
3408  aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
3409 
3410  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3411 }
3412 
3413 /*
3414  * has_function_privilege_id_name
3415  * Check user privileges on a function given
3416  * roleid, text functionname, and text priv name.
3417  */
3418 Datum
3420 {
3421  Oid roleid = PG_GETARG_OID(0);
3422  text *functionname = PG_GETARG_TEXT_PP(1);
3423  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3424  Oid functionoid;
3425  AclMode mode;
3426  AclResult aclresult;
3427 
3428  functionoid = convert_function_name(functionname);
3429  mode = convert_function_priv_string(priv_type_text);
3430 
3431  aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
3432 
3433  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3434 }
3435 
3436 /*
3437  * has_function_privilege_id_id
3438  * Check user privileges on a function given
3439  * roleid, function oid, and text priv name.
3440  */
3441 Datum
3443 {
3444  Oid roleid = PG_GETARG_OID(0);
3445  Oid functionoid = PG_GETARG_OID(1);
3446  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3447  AclMode mode;
3448  AclResult aclresult;
3449 
3450  mode = convert_function_priv_string(priv_type_text);
3451 
3452  if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(functionoid)))
3453  PG_RETURN_NULL();
3454 
3455  aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
3456 
3457  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3458 }
3459 
3460 /*
3461  * Support routines for has_function_privilege family.
3462  */
3463 
3464 /*
3465  * Given a function name expressed as a string, look it up and return Oid
3466  */
3467 static Oid
3469 {
3470  char *funcname = text_to_cstring(functionname);
3471  Oid oid;
3472 
3474  CStringGetDatum(funcname)));
3475 
3476  if (!OidIsValid(oid))
3477  ereport(ERROR,
3478  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3479  errmsg("function \"%s\" does not exist", funcname)));
3480 
3481  return oid;
3482 }
3483 
3484 /*
3485  * convert_function_priv_string
3486  * Convert text string to AclMode value.
3487  */
3488 static AclMode
3490 {
3491  static const priv_map function_priv_map[] = {
3492  {"EXECUTE", ACL_EXECUTE},
3493  {"EXECUTE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_EXECUTE)},
3494  {NULL, 0}
3495  };
3496 
3497  return convert_any_priv_string(priv_type_text, function_priv_map);
3498 }
3499 
3500 
3501 /*
3502  * has_language_privilege variants
3503  * These are all named "has_language_privilege" at the SQL level.
3504  * They take various combinations of language name, language OID,
3505  * user name, user OID, or implicit user = current_user.
3506  *
3507  * The result is a boolean value: true if user has the indicated
3508  * privilege, false if not, or NULL if object doesn't exist.
3509  */
3510 
3511 /*
3512  * has_language_privilege_name_name
3513  * Check user privileges on a language given
3514  * name username, text languagename, and text priv name.
3515  */
3516 Datum
3518 {
3520  text *languagename = PG_GETARG_TEXT_PP(1);
3521  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3522  Oid roleid;
3523  Oid languageoid;
3524  AclMode mode;
3525  AclResult aclresult;
3526 
3527  roleid = get_role_oid_or_public(NameStr(*username));
3528  languageoid = convert_language_name(languagename);
3529  mode = convert_language_priv_string(priv_type_text);
3530 
3531  aclresult = pg_language_aclcheck(languageoid, roleid, mode);
3532 
3533  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3534 }
3535 
3536 /*
3537  * has_language_privilege_name
3538  * Check user privileges on a language given
3539  * text languagename and text priv name.
3540  * current_user is assumed
3541  */
3542 Datum
3544 {
3545  text *languagename = PG_GETARG_TEXT_PP(0);
3546  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3547  Oid roleid;
3548  Oid languageoid;
3549  AclMode mode;
3550  AclResult aclresult;
3551 
3552  roleid = GetUserId();
3553  languageoid = convert_language_name(languagename);
3554  mode = convert_language_priv_string(priv_type_text);
3555 
3556  aclresult = pg_language_aclcheck(languageoid, roleid, mode);
3557 
3558  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3559 }
3560 
3561 /*
3562  * has_language_privilege_name_id
3563  * Check user privileges on a language given
3564  * name usename, language oid, and text priv name.
3565  */
3566 Datum
3568 {
3570  Oid languageoid = PG_GETARG_OID(1);
3571  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3572  Oid roleid;
3573  AclMode mode;
3574  AclResult aclresult;
3575 
3576  roleid = get_role_oid_or_public(NameStr(*username));
3577  mode = convert_language_priv_string(priv_type_text);
3578 
3579  if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
3580  PG_RETURN_NULL();
3581 
3582  aclresult = pg_language_aclcheck(languageoid, roleid, mode);
3583 
3584  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3585 }
3586 
3587 /*
3588  * has_language_privilege_id
3589  * Check user privileges on a language given
3590  * language oid, and text priv name.
3591  * current_user is assumed
3592  */
3593 Datum
3595 {
3596  Oid languageoid = PG_GETARG_OID(0);
3597  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3598  Oid roleid;
3599  AclMode mode;
3600  AclResult aclresult;
3601 
3602  roleid = GetUserId();
3603  mode = convert_language_priv_string(priv_type_text);
3604 
3605  if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
3606  PG_RETURN_NULL();
3607 
3608  aclresult = pg_language_aclcheck(languageoid, roleid, mode);
3609 
3610  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3611 }
3612 
3613 /*
3614  * has_language_privilege_id_name
3615  * Check user privileges on a language given
3616  * roleid, text languagename, and text priv name.
3617  */
3618 Datum
3620 {
3621  Oid roleid = PG_GETARG_OID(0);
3622  text *languagename = PG_GETARG_TEXT_PP(1);
3623  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3624  Oid languageoid;
3625  AclMode mode;
3626  AclResult aclresult;
3627 
3628  languageoid = convert_language_name(languagename);
3629  mode = convert_language_priv_string(priv_type_text);
3630 
3631  aclresult = pg_language_aclcheck(languageoid, roleid, mode);
3632 
3633  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3634 }
3635 
3636 /*
3637  * has_language_privilege_id_id
3638  * Check user privileges on a language given
3639  * roleid, language oid, and text priv name.
3640  */
3641 Datum
3643 {
3644  Oid roleid = PG_GETARG_OID(0);
3645  Oid languageoid = PG_GETARG_OID(1);
3646  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3647  AclMode mode;
3648  AclResult aclresult;
3649 
3650  mode = convert_language_priv_string(priv_type_text);
3651 
3652  if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
3653  PG_RETURN_NULL();
3654 
3655  aclresult = pg_language_aclcheck(languageoid, roleid, mode);
3656 
3657  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3658 }
3659 
3660 /*
3661  * Support routines for has_language_privilege family.
3662  */
3663 
3664 /*
3665  * Given a language name expressed as a string, look it up and return Oid
3666  */
3667 static Oid
3669 {
3670  char *langname = text_to_cstring(languagename);
3671 
3672  return get_language_oid(langname, false);
3673 }
3674 
3675 /*
3676  * convert_language_priv_string
3677  * Convert text string to AclMode value.
3678  */
3679 static AclMode
3681 {
3682  static const priv_map language_priv_map[] = {
3683  {"USAGE", ACL_USAGE},
3684  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
3685  {NULL, 0}
3686  };
3687 
3688  return convert_any_priv_string(priv_type_text, language_priv_map);
3689 }
3690 
3691 
3692 /*
3693  * has_schema_privilege variants
3694  * These are all named "has_schema_privilege" at the SQL level.
3695  * They take various combinations of schema name, schema OID,
3696  * user name, user OID, or implicit user = current_user.
3697  *
3698  * The result is a boolean value: true if user has the indicated
3699  * privilege, false if not, or NULL if object doesn't exist.
3700  */
3701 
3702 /*
3703  * has_schema_privilege_name_name
3704  * Check user privileges on a schema given
3705  * name username, text schemaname, and text priv name.
3706  */
3707 Datum
3709 {
3711  text *schemaname = PG_GETARG_TEXT_PP(1);
3712  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3713  Oid roleid;
3714  Oid schemaoid;
3715  AclMode mode;
3716  AclResult aclresult;
3717 
3718  roleid = get_role_oid_or_public(NameStr(*username));
3719  schemaoid = convert_schema_name(schemaname);
3720  mode = convert_schema_priv_string(priv_type_text);
3721 
3722  aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
3723 
3724  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3725 }
3726 
3727 /*
3728  * has_schema_privilege_name
3729  * Check user privileges on a schema given
3730  * text schemaname and text priv name.
3731  * current_user is assumed
3732  */
3733 Datum
3735 {
3736  text *schemaname = PG_GETARG_TEXT_PP(0);
3737  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3738  Oid roleid;
3739  Oid schemaoid;
3740  AclMode mode;
3741  AclResult aclresult;
3742 
3743  roleid = GetUserId();
3744  schemaoid = convert_schema_name(schemaname);
3745  mode = convert_schema_priv_string(priv_type_text);
3746 
3747  aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
3748 
3749  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3750 }
3751 
3752 /*
3753  * has_schema_privilege_name_id
3754  * Check user privileges on a schema given
3755  * name usename, schema oid, and text priv name.
3756  */
3757 Datum
3759 {
3761  Oid schemaoid = PG_GETARG_OID(1);
3762  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3763  Oid roleid;
3764  AclMode mode;
3765  AclResult aclresult;
3766 
3767  roleid = get_role_oid_or_public(NameStr(*username));
3768  mode = convert_schema_priv_string(priv_type_text);
3769 
3771  PG_RETURN_NULL();
3772 
3773  aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
3774 
3775  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3776 }
3777 
3778 /*
3779  * has_schema_privilege_id
3780  * Check user privileges on a schema given
3781  * schema oid, and text priv name.
3782  * current_user is assumed
3783  */
3784 Datum
3786 {
3787  Oid schemaoid = PG_GETARG_OID(0);
3788  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3789  Oid roleid;
3790  AclMode mode;
3791  AclResult aclresult;
3792 
3793  roleid = GetUserId();
3794  mode = convert_schema_priv_string(priv_type_text);
3795 
3797  PG_RETURN_NULL();
3798 
3799  aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
3800 
3801  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3802 }
3803 
3804 /*
3805  * has_schema_privilege_id_name
3806  * Check user privileges on a schema given
3807  * roleid, text schemaname, and text priv name.
3808  */
3809 Datum
3811 {
3812  Oid roleid = PG_GETARG_OID(0);
3813  text *schemaname = PG_GETARG_TEXT_PP(1);
3814  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3815  Oid schemaoid;
3816  AclMode mode;
3817  AclResult aclresult;
3818 
3819  schemaoid = convert_schema_name(schemaname);
3820  mode = convert_schema_priv_string(priv_type_text);
3821 
3822  aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
3823 
3824  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3825 }
3826 
3827 /*
3828  * has_schema_privilege_id_id
3829  * Check user privileges on a schema given
3830  * roleid, schema oid, and text priv name.
3831  */
3832 Datum
3834 {
3835  Oid roleid = PG_GETARG_OID(0);
3836  Oid schemaoid = PG_GETARG_OID(1);
3837  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3838  AclMode mode;
3839  AclResult aclresult;
3840 
3841  mode = convert_schema_priv_string(priv_type_text);
3842 
3844  PG_RETURN_NULL();
3845 
3846  aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
3847 
3848  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3849 }
3850 
3851 /*
3852  * Support routines for has_schema_privilege family.
3853  */
3854 
3855 /*
3856  * Given a schema name expressed as a string, look it up and return Oid
3857  */
3858 static Oid
3860 {
3861  char *nspname = text_to_cstring(schemaname);
3862 
3863  return get_namespace_oid(nspname, false);
3864 }
3865 
3866 /*
3867  * convert_schema_priv_string
3868  * Convert text string to AclMode value.
3869  */
3870 static AclMode
3872 {
3873  static const priv_map schema_priv_map[] = {
3874  {"CREATE", ACL_CREATE},
3875  {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
3876  {"USAGE", ACL_USAGE},
3877  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
3878  {NULL, 0}
3879  };
3880 
3881  return convert_any_priv_string(priv_type_text, schema_priv_map);
3882 }
3883 
3884 
3885 /*
3886  * has_server_privilege variants
3887  * These are all named "has_server_privilege" at the SQL level.
3888  * They take various combinations of foreign server name,
3889  * server OID, user name, user OID, or implicit user = current_user.
3890  *
3891  * The result is a boolean value: true if user has the indicated
3892  * privilege, false if not.
3893  */
3894 
3895 /*
3896  * has_server_privilege_name_name
3897  * Check user privileges on a foreign server given
3898  * name username, text servername, and text priv name.
3899  */
3900 Datum
3902 {
3904  text *servername = PG_GETARG_TEXT_PP(1);
3905  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3906  Oid roleid;
3907  Oid serverid;
3908  AclMode mode;
3909  AclResult aclresult;
3910 
3911  roleid = get_role_oid_or_public(NameStr(*username));
3912  serverid = convert_server_name(servername);
3913  mode = convert_server_priv_string(priv_type_text);
3914 
3915  aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
3916 
3917  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3918 }
3919 
3920 /*
3921  * has_server_privilege_name
3922  * Check user privileges on a foreign server given
3923  * text servername and text priv name.
3924  * current_user is assumed
3925  */
3926 Datum
3928 {
3929  text *servername = PG_GETARG_TEXT_PP(0);
3930  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3931  Oid roleid;
3932  Oid serverid;
3933  AclMode mode;
3934  AclResult aclresult;
3935 
3936  roleid = GetUserId();
3937  serverid = convert_server_name(servername);
3938  mode = convert_server_priv_string(priv_type_text);
3939 
3940  aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
3941 
3942  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3943 }
3944 
3945 /*
3946  * has_server_privilege_name_id
3947  * Check user privileges on a foreign server given
3948  * name usename, foreign server oid, and text priv name.
3949  */
3950 Datum
3952 {
3954  Oid serverid = PG_GETARG_OID(1);
3955  text *priv_type_text = PG_GETARG_TEXT_PP(2);
3956  Oid roleid;
3957  AclMode mode;
3958  AclResult aclresult;
3959 
3960  roleid = get_role_oid_or_public(NameStr(*username));
3961  mode = convert_server_priv_string(priv_type_text);
3962 
3964  PG_RETURN_NULL();
3965 
3966  aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
3967 
3968  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3969 }
3970 
3971 /*
3972  * has_server_privilege_id
3973  * Check user privileges on a foreign server given
3974  * server oid, and text priv name.
3975  * current_user is assumed
3976  */
3977 Datum
3979 {
3980  Oid serverid = PG_GETARG_OID(0);
3981  text *priv_type_text = PG_GETARG_TEXT_PP(1);
3982  Oid roleid;
3983  AclMode mode;
3984  AclResult aclresult;
3985 
3986  roleid = GetUserId();
3987  mode = convert_server_priv_string(priv_type_text);
3988 
3990  PG_RETURN_NULL();
3991 
3992  aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
3993 
3994  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
3995 }
3996 
3997 /*
3998  * has_server_privilege_id_name
3999  * Check user privileges on a foreign server given
4000  * roleid, text servername, and text priv name.
4001  */
4002 Datum
4004 {
4005  Oid roleid = PG_GETARG_OID(0);
4006  text *servername = PG_GETARG_TEXT_PP(1);
4007  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4008  Oid serverid;
4009  AclMode mode;
4010  AclResult aclresult;
4011 
4012  serverid = convert_server_name(servername);
4013  mode = convert_server_priv_string(priv_type_text);
4014 
4015  aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
4016 
4017  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4018 }
4019 
4020 /*
4021  * has_server_privilege_id_id
4022  * Check user privileges on a foreign server given
4023  * roleid, server oid, and text priv name.
4024  */
4025 Datum
4027 {
4028  Oid roleid = PG_GETARG_OID(0);
4029  Oid serverid = PG_GETARG_OID(1);
4030  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4031  AclMode mode;
4032  AclResult aclresult;
4033 
4034  mode = convert_server_priv_string(priv_type_text);
4035 
4037  PG_RETURN_NULL();
4038 
4039  aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
4040 
4041  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4042 }
4043 
4044 /*
4045  * Support routines for has_server_privilege family.
4046  */
4047 
4048 /*
4049  * Given a server name expressed as a string, look it up and return Oid
4050  */
4051 static Oid
4053 {
4054  char *serverstr = text_to_cstring(servername);
4055 
4056  return get_foreign_server_oid(serverstr, false);
4057 }
4058 
4059 /*
4060  * convert_server_priv_string
4061  * Convert text string to AclMode value.
4062  */
4063 static AclMode
4065 {
4066  static const priv_map server_priv_map[] = {
4067  {"USAGE", ACL_USAGE},
4068  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
4069  {NULL, 0}
4070  };
4071 
4072  return convert_any_priv_string(priv_type_text, server_priv_map);
4073 }
4074 
4075 
4076 /*
4077  * has_tablespace_privilege variants
4078  * These are all named "has_tablespace_privilege" at the SQL level.
4079  * They take various combinations of tablespace name, tablespace OID,
4080  * user name, user OID, or implicit user = current_user.
4081  *
4082  * The result is a boolean value: true if user has the indicated
4083  * privilege, false if not.
4084  */
4085 
4086 /*
4087  * has_tablespace_privilege_name_name
4088  * Check user privileges on a tablespace given
4089  * name username, text tablespacename, and text priv name.
4090  */
4091 Datum
4093 {
4095  text *tablespacename = PG_GETARG_TEXT_PP(1);
4096  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4097  Oid roleid;
4098  Oid tablespaceoid;
4099  AclMode mode;
4100  AclResult aclresult;
4101 
4102  roleid = get_role_oid_or_public(NameStr(*username));
4103  tablespaceoid = convert_tablespace_name(tablespacename);
4104  mode = convert_tablespace_priv_string(priv_type_text);
4105 
4106  aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
4107 
4108  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4109 }
4110 
4111 /*
4112  * has_tablespace_privilege_name
4113  * Check user privileges on a tablespace given
4114  * text tablespacename and text priv name.
4115  * current_user is assumed
4116  */
4117 Datum
4119 {
4120  text *tablespacename = PG_GETARG_TEXT_PP(0);
4121  text *priv_type_text = PG_GETARG_TEXT_PP(1);
4122  Oid roleid;
4123  Oid tablespaceoid;
4124  AclMode mode;
4125  AclResult aclresult;
4126 
4127  roleid = GetUserId();
4128  tablespaceoid = convert_tablespace_name(tablespacename);
4129  mode = convert_tablespace_priv_string(priv_type_text);
4130 
4131  aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
4132 
4133  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4134 }
4135 
4136 /*
4137  * has_tablespace_privilege_name_id
4138  * Check user privileges on a tablespace given
4139  * name usename, tablespace oid, and text priv name.
4140  */
4141 Datum
4143 {
4145  Oid tablespaceoid = PG_GETARG_OID(1);
4146  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4147  Oid roleid;
4148  AclMode mode;
4149  AclResult aclresult;
4150 
4151  roleid = get_role_oid_or_public(NameStr(*username));
4152  mode = convert_tablespace_priv_string(priv_type_text);
4153 
4155  PG_RETURN_NULL();
4156 
4157  aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
4158 
4159  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4160 }
4161 
4162 /*
4163  * has_tablespace_privilege_id
4164  * Check user privileges on a tablespace given
4165  * tablespace oid, and text priv name.
4166  * current_user is assumed
4167  */
4168 Datum
4170 {
4171  Oid tablespaceoid = PG_GETARG_OID(0);
4172  text *priv_type_text = PG_GETARG_TEXT_PP(1);
4173  Oid roleid;
4174  AclMode mode;
4175  AclResult aclresult;
4176 
4177  roleid = GetUserId();
4178  mode = convert_tablespace_priv_string(priv_type_text);
4179 
4181  PG_RETURN_NULL();
4182 
4183  aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
4184 
4185  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4186 }
4187 
4188 /*
4189  * has_tablespace_privilege_id_name
4190  * Check user privileges on a tablespace given
4191  * roleid, text tablespacename, and text priv name.
4192  */
4193 Datum
4195 {
4196  Oid roleid = PG_GETARG_OID(0);
4197  text *tablespacename = PG_GETARG_TEXT_PP(1);
4198  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4199  Oid tablespaceoid;
4200  AclMode mode;
4201  AclResult aclresult;
4202 
4203  tablespaceoid = convert_tablespace_name(tablespacename);
4204  mode = convert_tablespace_priv_string(priv_type_text);
4205 
4206  aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
4207 
4208  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4209 }
4210 
4211 /*
4212  * has_tablespace_privilege_id_id
4213  * Check user privileges on a tablespace given
4214  * roleid, tablespace oid, and text priv name.
4215  */
4216 Datum
4218 {
4219  Oid roleid = PG_GETARG_OID(0);
4220  Oid tablespaceoid = PG_GETARG_OID(1);
4221  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4222  AclMode mode;
4223  AclResult aclresult;
4224 
4225  mode = convert_tablespace_priv_string(priv_type_text);
4226 
4228  PG_RETURN_NULL();
4229 
4230  aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
4231 
4232  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4233 }
4234 
4235 /*
4236  * Support routines for has_tablespace_privilege family.
4237  */
4238 
4239 /*
4240  * Given a tablespace name expressed as a string, look it up and return Oid
4241  */
4242 static Oid
4244 {
4245  char *spcname = text_to_cstring(tablespacename);
4246 
4247  return get_tablespace_oid(spcname, false);
4248 }
4249 
4250 /*
4251  * convert_tablespace_priv_string
4252  * Convert text string to AclMode value.
4253  */
4254 static AclMode
4256 {
4257  static const priv_map tablespace_priv_map[] = {
4258  {"CREATE", ACL_CREATE},
4259  {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4260  {NULL, 0}
4261  };
4262 
4263  return convert_any_priv_string(priv_type_text, tablespace_priv_map);
4264 }
4265 
4266 /*
4267  * has_type_privilege variants
4268  * These are all named "has_type_privilege" at the SQL level.
4269  * They take various combinations of type name, type OID,
4270  * user name, user OID, or implicit user = current_user.
4271  *
4272  * The result is a boolean value: true if user has the indicated
4273  * privilege, false if not, or NULL if object doesn't exist.
4274  */
4275 
4276 /*
4277  * has_type_privilege_name_name
4278  * Check user privileges on a type given
4279  * name username, text typename, and text priv name.
4280  */
4281 Datum
4283 {
4285  text *typename = PG_GETARG_TEXT_PP(1);
4286  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4287  Oid roleid;
4288  Oid typeoid;
4289  AclMode mode;
4290  AclResult aclresult;
4291 
4292  roleid = get_role_oid_or_public(NameStr(*username));
4293  typeoid = convert_type_name(typename);
4294  mode = convert_type_priv_string(priv_type_text);
4295 
4296  aclresult = pg_type_aclcheck(typeoid, roleid, mode);
4297 
4298  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4299 }
4300 
4301 /*
4302  * has_type_privilege_name
4303  * Check user privileges on a type given
4304  * text typename and text priv name.
4305  * current_user is assumed
4306  */
4307 Datum
4309 {
4310  text *typename = PG_GETARG_TEXT_PP(0);
4311  text *priv_type_text = PG_GETARG_TEXT_PP(1);
4312  Oid roleid;
4313  Oid typeoid;
4314  AclMode mode;
4315  AclResult aclresult;
4316 
4317  roleid = GetUserId();
4318  typeoid = convert_type_name(typename);
4319  mode = convert_type_priv_string(priv_type_text);
4320 
4321  aclresult = pg_type_aclcheck(typeoid, roleid, mode);
4322 
4323  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4324 }
4325 
4326 /*
4327  * has_type_privilege_name_id
4328  * Check user privileges on a type given
4329  * name usename, type oid, and text priv name.
4330  */
4331 Datum
4333 {
4335  Oid typeoid = PG_GETARG_OID(1);
4336  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4337  Oid roleid;
4338  AclMode mode;
4339  AclResult aclresult;
4340 
4341  roleid = get_role_oid_or_public(NameStr(*username));
4342  mode = convert_type_priv_string(priv_type_text);
4343 
4345  PG_RETURN_NULL();
4346 
4347  aclresult = pg_type_aclcheck(typeoid, roleid, mode);
4348 
4349  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4350 }
4351 
4352 /*
4353  * has_type_privilege_id
4354  * Check user privileges on a type given
4355  * type oid, and text priv name.
4356  * current_user is assumed
4357  */
4358 Datum
4360 {
4361  Oid typeoid = PG_GETARG_OID(0);
4362  text *priv_type_text = PG_GETARG_TEXT_PP(1);
4363  Oid roleid;
4364  AclMode mode;
4365  AclResult aclresult;
4366 
4367  roleid = GetUserId();
4368  mode = convert_type_priv_string(priv_type_text);
4369 
4371  PG_RETURN_NULL();
4372 
4373  aclresult = pg_type_aclcheck(typeoid, roleid, mode);
4374 
4375  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4376 }
4377 
4378 /*
4379  * has_type_privilege_id_name
4380  * Check user privileges on a type given
4381  * roleid, text typename, and text priv name.
4382  */
4383 Datum
4385 {
4386  Oid roleid = PG_GETARG_OID(0);
4387  text *typename = PG_GETARG_TEXT_PP(1);
4388  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4389  Oid typeoid;
4390  AclMode mode;
4391  AclResult aclresult;
4392 
4393  typeoid = convert_type_name(typename);
4394  mode = convert_type_priv_string(priv_type_text);
4395 
4396  aclresult = pg_type_aclcheck(typeoid, roleid, mode);
4397 
4398  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4399 }
4400 
4401 /*
4402  * has_type_privilege_id_id
4403  * Check user privileges on a type given
4404  * roleid, type oid, and text priv name.
4405  */
4406 Datum
4408 {
4409  Oid roleid = PG_GETARG_OID(0);
4410  Oid typeoid = PG_GETARG_OID(1);
4411  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4412  AclMode mode;
4413  AclResult aclresult;
4414 
4415  mode = convert_type_priv_string(priv_type_text);
4416 
4418  PG_RETURN_NULL();
4419 
4420  aclresult = pg_type_aclcheck(typeoid, roleid, mode);
4421 
4422  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4423 }
4424 
4425 /*
4426  * Support routines for has_type_privilege family.
4427  */
4428 
4429 /*
4430  * Given a type name expressed as a string, look it up and return Oid
4431  */
4432 static Oid
4434 {
4435  char *typname = text_to_cstring(typename);
4436  Oid oid;
4437 
4439  CStringGetDatum(typname)));
4440 
4441  if (!OidIsValid(oid))
4442  ereport(ERROR,
4443  (errcode(ERRCODE_UNDEFINED_OBJECT),
4444  errmsg("type \"%s\" does not exist", typname)));
4445 
4446  return oid;
4447 }
4448 
4449 /*
4450  * convert_type_priv_string
4451  * Convert text string to AclMode value.
4452  */
4453 static AclMode
4455 {
4456  static const priv_map type_priv_map[] = {
4457  {"USAGE", ACL_USAGE},
4458  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
4459  {NULL, 0}
4460  };
4461 
4462  return convert_any_priv_string(priv_type_text, type_priv_map);
4463 }
4464 
4465 
4466 /*
4467  * pg_has_role variants
4468  * These are all named "pg_has_role" at the SQL level.
4469  * They take various combinations of role name, role OID,
4470  * user name, user OID, or implicit user = current_user.
4471  *
4472  * The result is a boolean value: true if user has the indicated
4473  * privilege, false if not.
4474  */
4475 
4476 /*
4477  * pg_has_role_name_name
4478  * Check user privileges on a role given
4479  * name username, name rolename, and text priv name.
4480  */
4481 Datum
4483 {
4485  Name rolename = PG_GETARG_NAME(1);
4486  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4487  Oid roleid;
4488  Oid roleoid;
4489  AclMode mode;
4490  AclResult aclresult;
4491 
4492  roleid = get_role_oid(NameStr(*username), false);
4493  roleoid = get_role_oid(NameStr(*rolename), false);
4494  mode = convert_role_priv_string(priv_type_text);
4495 
4496  aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4497 
4498  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4499 }
4500 
4501 /*
4502  * pg_has_role_name
4503  * Check user privileges on a role given
4504  * name rolename and text priv name.
4505  * current_user is assumed
4506  */
4507 Datum
4509 {
4510  Name rolename = PG_GETARG_NAME(0);
4511  text *priv_type_text = PG_GETARG_TEXT_PP(1);
4512  Oid roleid;
4513  Oid roleoid;
4514  AclMode mode;
4515  AclResult aclresult;
4516 
4517  roleid = GetUserId();
4518  roleoid = get_role_oid(NameStr(*rolename), false);
4519  mode = convert_role_priv_string(priv_type_text);
4520 
4521  aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4522 
4523  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4524 }
4525 
4526 /*
4527  * pg_has_role_name_id
4528  * Check user privileges on a role given
4529  * name usename, role oid, and text priv name.
4530  */
4531 Datum
4533 {
4535  Oid roleoid = PG_GETARG_OID(1);
4536  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4537  Oid roleid;
4538  AclMode mode;
4539  AclResult aclresult;
4540 
4541  roleid = get_role_oid(NameStr(*username), false);
4542  mode = convert_role_priv_string(priv_type_text);
4543 
4544  aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4545 
4546  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4547 }
4548 
4549 /*
4550  * pg_has_role_id
4551  * Check user privileges on a role given
4552  * role oid, and text priv name.
4553  * current_user is assumed
4554  */
4555 Datum
4557 {
4558  Oid roleoid = PG_GETARG_OID(0);
4559  text *priv_type_text = PG_GETARG_TEXT_PP(1);
4560  Oid roleid;
4561  AclMode mode;
4562  AclResult aclresult;
4563 
4564  roleid = GetUserId();
4565  mode = convert_role_priv_string(priv_type_text);
4566 
4567  aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4568 
4569  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4570 }
4571 
4572 /*
4573  * pg_has_role_id_name
4574  * Check user privileges on a role given
4575  * roleid, name rolename, and text priv name.
4576  */
4577 Datum
4579 {
4580  Oid roleid = PG_GETARG_OID(0);
4581  Name rolename = PG_GETARG_NAME(1);
4582  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4583  Oid roleoid;
4584  AclMode mode;
4585  AclResult aclresult;
4586 
4587  roleoid = get_role_oid(NameStr(*rolename), false);
4588  mode = convert_role_priv_string(priv_type_text);
4589 
4590  aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4591 
4592  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4593 }
4594 
4595 /*
4596  * pg_has_role_id_id
4597  * Check user privileges on a role given
4598  * roleid, role oid, and text priv name.
4599  */
4600 Datum
4602 {
4603  Oid roleid = PG_GETARG_OID(0);
4604  Oid roleoid = PG_GETARG_OID(1);
4605  text *priv_type_text = PG_GETARG_TEXT_PP(2);
4606  AclMode mode;
4607  AclResult aclresult;
4608 
4609  mode = convert_role_priv_string(priv_type_text);
4610 
4611  aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4612 
4613  PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
4614 }
4615 
4616 /*
4617  * Support routines for pg_has_role family.
4618  */
4619 
4620 /*
4621  * convert_role_priv_string
4622  * Convert text string to AclMode value.
4623  *
4624  * We use USAGE to denote whether the privileges of the role are accessible
4625  * (has_privs), MEMBER to denote is_member, and MEMBER WITH GRANT OPTION
4626  * (or ADMIN OPTION) to denote is_admin. There is no ACL bit corresponding
4627  * to MEMBER so we cheat and use ACL_CREATE for that. This convention
4628  * is shared only with pg_role_aclcheck, below.
4629  */
4630 static AclMode
4632 {
4633  static const priv_map role_priv_map[] = {
4634  {"USAGE", ACL_USAGE},
4635  {"MEMBER", ACL_CREATE},
4636  {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4637  {"USAGE WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4638  {"MEMBER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4639  {"MEMBER WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4640  {NULL, 0}
4641  };
4642 
4643  return convert_any_priv_string(priv_type_text, role_priv_map);
4644 }
4645 
4646 /*
4647  * pg_role_aclcheck
4648  * Quick-and-dirty support for pg_has_role
4649  */
4650 static AclResult
4652 {
4653  if (mode & ACL_GRANT_OPTION_FOR(ACL_CREATE))
4654  {
4655  /*
4656  * XXX For roleid == role_oid, is_admin_of_role() also examines the
4657  * session and call stack. That suits two-argument pg_has_role(), but
4658  * it gives the three-argument version a lamentable whimsy.
4659  */
4660  if (is_admin_of_role(roleid, role_oid))
4661  return ACLCHECK_OK;
4662  }
4663  if (mode & ACL_CREATE)
4664  {
4665  if (is_member_of_role(roleid, role_oid))
4666  return ACLCHECK_OK;
4667  }
4668  if (mode & ACL_USAGE)
4669  {
4670  if (has_privs_of_role(roleid, role_oid))
4671  return ACLCHECK_OK;
4672  }
4673  return ACLCHECK_NO_PRIV;
4674 }
4675 
4676 
4677 /*
4678  * initialization function (called by InitPostgres)
4679  */
4680 void
4682 {
4684  {
4685  /*
4686  * In normal mode, set a callback on any syscache invalidation of
4687  * pg_auth_members rows
4688  */
4691  (Datum) 0);
4692  }
4693 }
4694 
4695 /*
4696  * RoleMembershipCacheCallback
4697  * Syscache inval callback function
4698  */
4699 static void
4701 {
4702  /* Force membership caches to be recomputed on next use */
4705 }
4706 
4707 
4708 /* Check if specified role has rolinherit set */
4709 static bool
4711 {
4712  bool result = false;
4713  HeapTuple utup;
4714 
4715  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4716  if (HeapTupleIsValid(utup))
4717  {
4718  result = ((Form_pg_authid) GETSTRUCT(utup))->rolinherit;
4719  ReleaseSysCache(utup);
4720  }
4721  return result;
4722 }
4723 
4724 
4725 /*
4726  * Get a list of roles that the specified roleid has the privileges of
4727  *
4728  * This is defined not to recurse through roles that don't have rolinherit
4729  * set; for such roles, membership implies the ability to do SET ROLE, but
4730  * the privileges are not available until you've done so.
4731  *
4732  * Since indirect membership testing is relatively expensive, we cache
4733  * a list of memberships. Hence, the result is only guaranteed good until
4734  * the next call of roles_has_privs_of()!
4735  *
4736  * For the benefit of select_best_grantor, the result is defined to be
4737  * in breadth-first order, ie, closer relationships earlier.
4738  */
4739 static List *
4741 {
4742  List *roles_list;
4743  ListCell *l;
4744  List *new_cached_privs_roles;
4745  MemoryContext oldctx;
4746 
4747  /* If cache is already valid, just return the list */
4749  return cached_privs_roles;
4750 
4751  /*
4752  * Find all the roles that roleid is a member of, including multi-level
4753  * recursion. The role itself will always be the first element of the
4754  * resulting list.
4755  *
4756  * Each element of the list is scanned to see if it adds any indirect
4757  * memberships. We can use a single list as both the record of
4758  * already-found memberships and the agenda of roles yet to be scanned.
4759  * This is a bit tricky but works because the foreach() macro doesn't
4760  * fetch the next list element until the bottom of the loop.
4761  */
4762  roles_list = list_make1_oid(roleid);
4763 
4764  foreach(l, roles_list)
4765  {
4766  Oid memberid = lfirst_oid(l);
4767  CatCList *memlist;
4768  int i;
4769 
4770  /* Ignore non-inheriting roles */
4771  if (!has_rolinherit(memberid))
4772  continue;
4773 
4774  /* Find roles that memberid is directly a member of */
4776  ObjectIdGetDatum(memberid));
4777  for (i = 0; i < memlist->n_members; i++)
4778  {
4779  HeapTuple tup = &memlist->members[i]->tuple;
4780  Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
4781 
4782  /*
4783  * Even though there shouldn't be any loops in the membership
4784  * graph, we must test for having already seen this role. It is
4785  * legal for instance to have both A->B and A->C->B.
4786  */
4787  roles_list = list_append_unique_oid(roles_list, otherid);
4788  }
4789  ReleaseSysCacheList(memlist);
4790  }
4791 
4792  /*
4793  * Copy the completed list into TopMemoryContext so it will persist.
4794  */
4796  new_cached_privs_roles = list_copy(roles_list);
4797  MemoryContextSwitchTo(oldctx);
4798  list_free(roles_list);
4799 
4800  /*
4801  * Now safe to assign to state variable
4802  */
4803  cached_privs_role = InvalidOid; /* just paranoia */
4804  list_free(cached_privs_roles);
4805  cached_privs_roles = new_cached_privs_roles;
4806  cached_privs_role = roleid;
4807 
4808  /* And now we can return the answer */
4809  return cached_privs_roles;
4810 }
4811 
4812 
4813 /*
4814  * Get a list of roles that the specified roleid is a member of
4815  *
4816  * This is defined to recurse through roles regardless of rolinherit.
4817  *
4818  * Since indirect membership testing is relatively expensive, we cache
4819  * a list of memberships. Hence, the result is only guaranteed good until
4820  * the next call of roles_is_member_of()!
4821  */
4822 static List *
4824 {
4825  List *roles_list;
4826  ListCell *l;
4827  List *new_cached_membership_roles;
4828  MemoryContext oldctx;
4829 
4830  /* If cache is already valid, just return the list */
4832  return cached_membership_roles;
4833 
4834  /*
4835  * Find all the roles that roleid is a member of, including multi-level
4836  * recursion. The role itself will always be the first element of the
4837  * resulting list.
4838  *
4839  * Each element of the list is scanned to see if it adds any indirect
4840  * memberships. We can use a single list as both the record of
4841  * already-found memberships and the agenda of roles yet to be scanned.
4842  * This is a bit tricky but works because the foreach() macro doesn't
4843  * fetch the next list element until the bottom of the loop.
4844  */
4845  roles_list = list_make1_oid(roleid);
4846 
4847  foreach(l, roles_list)
4848  {
4849  Oid memberid = lfirst_oid(l);
4850  CatCList *memlist;
4851  int i;
4852 
4853  /* Find roles that memberid is directly a member of */
4855  ObjectIdGetDatum(memberid));
4856  for (i = 0; i < memlist->n_members; i++)
4857  {
4858  HeapTuple tup = &memlist->members[i]->tuple;
4859  Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
4860 
4861  /*
4862  * Even though there shouldn't be any loops in the membership
4863  * graph, we must test for having already seen this role. It is
4864  * legal for instance to have both A->B and A->C->B.
4865  */
4866  roles_list = list_append_unique_oid(roles_list, otherid);
4867  }
4868  ReleaseSysCacheList(memlist);
4869  }
4870 
4871  /*
4872  * Copy the completed list into TopMemoryContext so it will persist.
4873  */
4875  new_cached_membership_roles = list_copy(roles_list);
4876  MemoryContextSwitchTo(oldctx);
4877  list_free(roles_list);
4878 
4879  /*
4880  * Now safe to assign to state variable
4881  */
4882  cached_member_role = InvalidOid; /* just paranoia */
4883  list_free(cached_membership_roles);
4884  cached_membership_roles = new_cached_membership_roles;
4885  cached_member_role = roleid;
4886 
4887  /* And now we can return the answer */
4888  return cached_membership_roles;
4889 }
4890 
4891 
4892 /*
4893  * Does member have the privileges of role (directly or indirectly)?
4894  *
4895  * This is defined not to recurse through roles that don't have rolinherit
4896  * set; for such roles, membership implies the ability to do SET ROLE, but
4897  * the privileges are not available until you've done so.
4898  */
4899 bool
4901 {
4902  /* Fast path for simple case */
4903  if (member == role)
4904  return true;
4905 
4906  /* Superusers have every privilege, so are part of every role */
4907  if (superuser_arg(member))
4908  return true;
4909 
4910  /*
4911  * Find all the roles that member has the privileges of, including
4912  * multi-level recursion, then see if target role is any one of them.
4913  */
4914  return list_member_oid(roles_has_privs_of(member), role);
4915 }
4916 
4917 
4918 /*
4919  * Is member a member of role (directly or indirectly)?
4920  *
4921  * This is defined to recurse through roles regardless of rolinherit.
4922  */
4923 bool
4925 {
4926  /* Fast path for simple case */
4927  if (member == role)
4928  return true;
4929 
4930  /* Superusers have every privilege, so are part of every role */
4931  if (superuser_arg(member))
4932  return true;
4933 
4934  /*
4935  * Find all the roles that member is a member of, including multi-level
4936  * recursion, then see if target role is any one of them.
4937  */
4938  return list_member_oid(roles_is_member_of(member), role);
4939 }
4940 
4941 /*
4942  * check_is_member_of_role
4943  * is_member_of_role with a standard permission-violation error if not
4944  */
4945 void
4947 {
4948  if (!is_member_of_role(member, role))
4949  ereport(ERROR,
4950  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4951  errmsg("must be member of role \"%s\"",
4952  GetUserNameFromId(role, false))));
4953 }
4954 
4955 /*
4956  * Is member a member of role, not considering superuserness?
4957  *
4958  * This is identical to is_member_of_role except we ignore superuser
4959  * status.
4960  */
4961 bool
4963 {
4964  /* Fast path for simple case */
4965  if (member == role)
4966  return true;
4967 
4968  /*
4969  * Find all the roles that member is a member of, including multi-level
4970  * recursion, then see if target role is any one of them.
4971  */
4972  return list_member_oid(roles_is_member_of(member), role);
4973 }
4974 
4975 
4976 /*
4977  * Is member an admin of role? That is, is member the role itself (subject to
4978  * restrictions below), a member (directly or indirectly) WITH ADMIN OPTION,
4979  * or a superuser?
4980  */
4981 bool
4983 {
4984  bool result = false;
4985  List *roles_list;
4986  ListCell *l;
4987 
4988  if (superuser_arg(member))
4989  return true;
4990 
4991  if (member == role)
4992 
4993  /*
4994  * A role can admin itself when it matches the session user and we're
4995  * outside any security-restricted operation, SECURITY DEFINER or
4996  * similar context. SQL-standard roles cannot self-admin. However,
4997  * SQL-standard users are distinct from roles, and they are not
4998  * grantable like roles: PostgreSQL's role-user duality extends the
4999  * standard. Checking for a session user match has the effect of
5000  * letting a role self-admin only when it's conspicuously behaving
5001  * like a user. Note that allowing self-admin under a mere SET ROLE
5002  * would make WITH ADMIN OPTION largely irrelevant; any member could
5003  * SET ROLE to issue the otherwise-forbidden command.
5004  *
5005  * Withholding self-admin in a security-restricted operation prevents
5006  * object owners from harnessing the session user identity during
5007  * administrative maintenance. Suppose Alice owns a database, has
5008  * issued "GRANT alice TO bob", and runs a daily ANALYZE. Bob creates
5009  * an alice-owned SECURITY DEFINER function that issues "REVOKE alice
5010  * FROM carol". If he creates an expression index calling that
5011  * function, Alice will attempt the REVOKE during each ANALYZE.
5012  * Checking InSecurityRestrictedOperation() thwarts that attack.
5013  *
5014  * Withholding self-admin in SECURITY DEFINER functions makes their
5015  * behavior independent of the calling user. There's no security or
5016  * SQL-standard-conformance need for that restriction, though.
5017  *
5018  * A role cannot have actual WITH ADMIN OPTION on itself, because that
5019  * would imply a membership loop. Therefore, we're done either way.
5020  */
5021  return member == GetSessionUserId() &&
5023 
5024  /*
5025  * Find all the roles that member is a member of, including multi-level
5026  * recursion. We build a list in the same way that is_member_of_role does
5027  * to track visited and unvisited roles.
5028  */
5029  roles_list = list_make1_oid(member);
5030 
5031  foreach(l, roles_list)
5032  {
5033  Oid memberid = lfirst_oid(l);
5034  CatCList *memlist;
5035  int i;
5036 
5037  /* Find roles that memberid is directly a member of */
5039  ObjectIdGetDatum(memberid));
5040  for (i = 0; i < memlist->n_members; i++)
5041  {
5042  HeapTuple tup = &memlist->members[i]->tuple;
5043  Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
5044 
5045  if (otherid == role &&
5047  {
5048  /* Found what we came for, so can stop searching */
5049  result = true;
5050  break;
5051  }
5052 
5053  roles_list = list_append_unique_oid(roles_list, otherid);
5054  }
5055  ReleaseSysCacheList(memlist);
5056  if (result)
5057  break;
5058  }
5059 
5060  list_free(roles_list);
5061 
5062  return result;
5063 }
5064 
5065 
5066 /* does what it says ... */
5067 static int
5069 {
5070  int nbits = 0;
5071 
5072  /* this code relies on AclMode being an unsigned type */
5073  while (mask)
5074  {
5075  if (mask & 1)
5076  nbits++;
5077  mask >>= 1;
5078  }
5079  return nbits;
5080 }
5081 
5082 
5083 /*
5084  * Select the effective grantor ID for a GRANT or REVOKE operation.
5085  *
5086  * The grantor must always be either the object owner or some role that has
5087  * been explicitly granted grant options. This ensures that all granted
5088  * privileges appear to flow from the object owner, and there are never
5089  * multiple "original sources" of a privilege. Therefore, if the would-be
5090  * grantor is a member of a role that has the needed grant options, we have
5091  * to do the grant as that role instead.
5092  *
5093  * It is possible that the would-be grantor is a member of several roles
5094  * that have different subsets of the desired grant options, but no one
5095  * role has 'em all. In this case we pick a role with the largest number
5096  * of desired options. Ties are broken in favor of closer ancestors.
5097  *
5098  * roleId: the role attempting to do the GRANT/REVOKE
5099  * privileges: the privileges to be granted/revoked
5100  * acl: the ACL of the object in question
5101  * ownerId: the role owning the object in question
5102  * *grantorId: receives the OID of the role to do the grant as
5103  * *grantOptions: receives the grant options actually held by grantorId
5104  *
5105  * If no grant options exist, we set grantorId to roleId, grantOptions to 0.
5106  */
5107 void
5108 select_best_grantor(Oid roleId, AclMode privileges,
5109  const Acl *acl, Oid ownerId,
5110  Oid *grantorId, AclMode *grantOptions)
5111 {
5112  AclMode needed_goptions = ACL_GRANT_OPTION_FOR(privileges);
5113  List *roles_list;
5114  int nrights;
5115  ListCell *l;
5116 
5117  /*
5118  * The object owner is always treated as having all grant options, so if
5119  * roleId is the owner it's easy. Also, if roleId is a superuser it's
5120  * easy: superusers are implicitly members of every role, so they act as
5121  * the object owner.
5122  */
5123  if (roleId == ownerId || superuser_arg(roleId))
5124  {
5125  *grantorId = ownerId;
5126  *grantOptions = needed_goptions;
5127  return;
5128  }
5129 
5130  /*
5131  * Otherwise we have to do a careful search to see if roleId has the
5132  * privileges of any suitable role. Note: we can hang onto the result of
5133  * roles_has_privs_of() throughout this loop, because aclmask_direct()
5134  * doesn't query any role memberships.
5135  */
5136  roles_list = roles_has_privs_of(roleId);
5137 
5138  /* initialize candidate result as default */
5139  *grantorId = roleId;
5140  *grantOptions = ACL_NO_RIGHTS;
5141  nrights = 0;
5142 
5143  foreach(l, roles_list)
5144  {
5145  Oid otherrole = lfirst_oid(l);
5146  AclMode otherprivs;
5147 
5148  otherprivs = aclmask_direct(acl, otherrole, ownerId,
5149  needed_goptions, ACLMASK_ALL);
5150  if (otherprivs == needed_goptions)
5151  {
5152  /* Found a suitable grantor */
5153  *grantorId = otherrole;
5154  *grantOptions = otherprivs;
5155  return;
5156  }
5157 
5158  /*
5159  * If it has just some of the needed privileges, remember best
5160  * candidate.
5161  */
5162  if (otherprivs != ACL_NO_RIGHTS)
5163  {
5164  int nnewrights = count_one_bits(otherprivs);
5165 
5166  if (nnewrights > nrights)
5167  {
5168  *grantorId = otherrole;
5169  *grantOptions = otherprivs;
5170  nrights = nnewrights;
5171  }
5172  }
5173  }
5174 }
5175 
5176 /*
5177  * get_role_oid - Given a role name, look up the role's OID.
5178  *
5179  * If missing_ok is false, throw an error if role name not found. If
5180  * true, just return InvalidOid.
5181  */
5182 Oid
5183 get_role_oid(const char *rolname, bool missing_ok)
5184 {
5185  Oid oid;
5186 
5187  oid = GetSysCacheOid1(AUTHNAME, Anum_pg_authid_oid,
5188  CStringGetDatum(rolname));
5189  if (!OidIsValid(oid) && !missing_ok)
5190  ereport(ERROR,
5191  (errcode(ERRCODE_UNDEFINED_OBJECT),
5192  errmsg("role \"%s\" does not exist", rolname)));
5193  return oid;
5194 }
5195 
5196 /*
5197  * get_role_oid_or_public - As above, but return ACL_ID_PUBLIC if the
5198  * role name is "public".
5199  */
5200 Oid
5202 {
5203  if (strcmp(rolname, "public") == 0)
5204  return ACL_ID_PUBLIC;
5205 
5206  return get_role_oid(rolname, false);
5207 }
5208 
5209 /*
5210  * Given a RoleSpec node, return the OID it corresponds to. If missing_ok is
5211  * true, return InvalidOid if the role does not exist.
5212  *
5213  * PUBLIC is always disallowed here. Routines wanting to handle the PUBLIC
5214  * case must check the case separately.
5215  */
5216 Oid
5217 get_rolespec_oid(const RoleSpec *role, bool missing_ok)
5218 {
5219  Oid oid;
5220 
5221  switch (role->roletype)
5222  {
5223  case ROLESPEC_CSTRING:
5224  Assert(role->rolename);
5225  oid = get_role_oid(role->rolename, missing_ok);
5226  break;
5227 
5228  case ROLESPEC_CURRENT_USER:
5229  oid = GetUserId();
5230  break;
5231 
5232  case ROLESPEC_SESSION_USER:
5233  oid = GetSessionUserId();
5234  break;
5235 
5236  case ROLESPEC_PUBLIC:
5237  ereport(ERROR,
5238  (errcode(ERRCODE_UNDEFINED_OBJECT),
5239  errmsg("role \"%s\" does not exist", "public")));
5240  oid = InvalidOid; /* make compiler happy */
5241  break;
5242 
5243  default:
5244  elog(ERROR, "unexpected role type %d", role->roletype);
5245  }
5246 
5247  return oid;
5248 }
5249 
5250 /*
5251  * Given a RoleSpec node, return the pg_authid HeapTuple it corresponds to.
5252  * Caller must ReleaseSysCache when done with the result tuple.
5253  */
5254 HeapTuple
5256 {
5257  HeapTuple tuple;
5258 
5259  switch (role->roletype)
5260  {
5261  case ROLESPEC_CSTRING:
5262  Assert(role->rolename);
5264  if (!HeapTupleIsValid(tuple))
5265  ereport(ERROR,
5266  (errcode(ERRCODE_UNDEFINED_OBJECT),
5267  errmsg("role \"%s\" does not exist", role->rolename)));
5268  break;
5269 
5270  case ROLESPEC_CURRENT_USER:
5271  tuple = SearchSysCache1(AUTHOID, GetUserId());
5272  if (!HeapTupleIsValid(tuple))
5273  elog(ERROR, "cache lookup failed for role %u", GetUserId());
5274  break;
5275 
5276  case ROLESPEC_SESSION_USER:
5278  if (!HeapTupleIsValid(tuple))
5279  elog(ERROR, "cache lookup failed for role %u", GetSessionUserId());
5280  break;
5281 
5282  case ROLESPEC_PUBLIC:
5283  ereport(ERROR,
5284  (errcode(ERRCODE_UNDEFINED_OBJECT),
5285  errmsg("role \"%s\" does not exist", "public")));
5286  tuple = NULL; /* make compiler happy */
5287  break;
5288 
5289  default:
5290  elog(ERROR, "unexpected role type %d", role->roletype);
5291  }
5292 
5293  return tuple;
5294 }
5295 
5296 /*
5297  * Given a RoleSpec, returns a palloc'ed copy of the corresponding role's name.
5298  */
5299 char *
5301 {
5302  HeapTuple tp;
5303  Form_pg_authid authForm;
5304  char *rolename;
5305 
5306  tp = get_rolespec_tuple(role);
5307  authForm = (Form_pg_authid) GETSTRUCT(tp);
5308  rolename = pstrdup(NameStr(authForm->rolname));
5309  ReleaseSysCache(tp);
5310 
5311  return rolename;
5312 }
5313 
5314 /*
5315  * Given a RoleSpec, throw an error if the name is reserved, using detail_msg,
5316  * if provided.
5317  *
5318  * If node is NULL, no error is thrown. If detail_msg is NULL then no detail
5319  * message is provided.
5320  */
5321 void
5322 check_rolespec_name(const RoleSpec *role, const char *detail_msg)
5323 {
5324  if (!role)
5325  return;
5326 
5327  if (role->roletype != ROLESPEC_CSTRING)
5328  return;
5329 
5330  if (IsReservedName(role->rolename))
5331  {
5332  if (detail_msg)
5333  ereport(ERROR,
5334  (errcode(ERRCODE_RESERVED_NAME),
5335  errmsg("role name \"%s\" is reserved",
5336  role->rolename),
5337  errdetail("%s", detail_msg)));
5338  else
5339  ereport(ERROR,
5340  (errcode(ERRCODE_RESERVED_NAME),
5341  errmsg("role name \"%s\" is reserved",
5342  role->rolename)));
5343  }
5344 }
int remaining
Definition: informix.c:667
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:2516
static void putid(char *p, const char *s)
Definition: acl.c:190
Definition: acl.c:44
#define NIL
Definition: pg_list.h:65
#define ACL_MODECHG_EQL
Definition: acl.h:131
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1416
Datum has_column_privilege_id_id_attnum(PG_FUNCTION_ARGS)
Definition: acl.c:2701
static PgChecksumMode mode
Definition: pg_checksums.c:61
static const char * convert_aclright_to_string(int aclright)
Definition: acl.c:1688
#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:2296
static Oid convert_language_name(text *languagename)
Definition: acl.c:3668
Datum has_tablespace_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:4142
Datum has_column_privilege_name_name_attnum(PG_FUNCTION_ARGS)
Definition: acl.c:2545
static Oid cached_member_role
Definition: acl.c:78
Datum has_foreign_data_wrapper_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:3228
int n_members
Definition: catcache.h:176
Datum has_database_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:2978
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4703
Datum has_server_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:3901
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:3343
int errhint(const char *fmt,...)
Definition: elog.c:1069
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:2176
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Datum has_schema_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:3708
#define PG_RETURN_ACL_P(x)
Definition: acl.h:124
Datum has_sequence_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:2052
static AttrNumber convert_column_name(Oid tableoid, text *column)
Definition: acl.c:2836
Datum aclcontains(PG_FUNCTION_ARGS)
Definition: acl.c:1545
Datum has_database_privilege_name(PG_FUNCTION_ARGS)
Definition: acl.c:2954
static Oid convert_schema_name(text *schemaname)
Definition: acl.c:3859
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition: aclchk.c:4515
static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode)
Definition: acl.c:4651
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
Oid GetUserId(void)
Definition: miscinit.c:380
Datum aclexplode(PG_FUNCTION_ARGS)
Definition: acl.c:1738
Datum has_type_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:4359
#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:282
#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:4508
AclResult pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4716
static AclMode convert_function_priv_string(text *priv_type_text)
Definition: acl.c:3489
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:4900
static Oid convert_foreign_data_wrapper_name(text *fdwname)
Definition: acl.c:3277
#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:4982
#define ACL_DELETE_CHR
Definition: acl.h:140
static bool has_rolinherit(Oid roleid)
Definition: acl.c:4710
Datum aclinsert(PG_FUNCTION_ARGS)
Definition: acl.c:1525
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:5201
int errcode(int sqlerrcode)
Definition: elog.c:608
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:749
#define MemSet(start, val, len)
Definition: c.h:962
#define ACL_DELETE
Definition: parsenodes.h:77
Datum has_function_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:3419
Datum aclitemin(PG_FUNCTION_ARGS)
Definition: acl.c:566
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:263
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:166
static Oid convert_tablespace_name(text *tablespacename)
Definition: acl.c:4243
#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:615
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:269
Datum has_table_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:1894
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
void initialize_acl(void)
Definition: acl.c:4681
#define LOG
Definition: elog.h:26
unsigned int Oid
Definition: postgres_ext.h:31
bool IsReservedName(const char *name)
Definition: catalog.c:213
Datum pg_has_role_id(PG_FUNCTION_ARGS)
Definition: acl.c:4556
Datum has_server_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:3951
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:2083
Datum has_type_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:4332
#define OidIsValid(objectId)
Definition: c.h:645
Datum has_server_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:3978
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4691
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:286
Acl * make_empty_acl(void)
Definition: acl.c:399
Datum has_function_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:3367
Oid GetSessionUserId(void)
Definition: miscinit.c:414
AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4665
Datum has_any_column_privilege_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:2411
Oid ai_grantor
Definition: acl.h:57
char relkind
Definition: pg_class.h:81
TupleDesc tuple_desc
Definition: funcapi.h:112
#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:1640
Datum has_any_column_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:2266
Datum pg_has_role_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:4482
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5183
Datum has_schema_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:3810
#define ARR_LBOUND(a)
Definition: array.h:284
Datum has_foreign_data_wrapper_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:3203
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:178
#define NAMEDATALEN
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:288
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:3543
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:165
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition: foreign.c:691
Datum pg_has_role_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:4578
static List * roles_has_privs_of(Oid roleid)
Definition: acl.c:4740
#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:5068
Datum has_type_privilege_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:4407
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:3394
#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:2572
Datum has_tablespace_privilege_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:4217
#define ARR_DIMS(a)
Definition: array.h:282
Datum has_foreign_data_wrapper_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:3176
#define ACL_NUM(ACL)
Definition: acl.h:108
static List * roles_is_member_of(Oid roleid)
Definition: acl.c:4823
#define ACL_NO_RIGHTS
Definition: parsenodes.h:88
Datum pg_has_role_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:4601
#define ACL_ALL_RIGHTS_SCHEMA
Definition: acl.h:165
Datum has_table_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:1946
Datum has_column_privilege_id_attnum(PG_FUNCTION_ARGS)
Definition: acl.c:2808
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2052
Definition: c.h:610
#define ACL_TRIGGER
Definition: parsenodes.h:80
AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4729
#define ACL_TRUNCATE_CHR
Definition: acl.h:141
static AclMode convert_type_priv_string(text *priv_type_text)
Definition: acl.c:4454
#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:2010
#define memmove(d, s, c)
Definition: c.h:1266
#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:2651
int errdetail(const char *fmt,...)
Definition: elog.c:955
#define CStringGetDatum(X)
Definition: postgres.h:578
static AclMode convert_tablespace_priv_string(text *priv_type_text)
Definition: acl.c:4255
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:167
Datum has_tablespace_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:4194
Datum has_column_privilege_id_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:2676
Datum has_column_privilege_name_id_attnum(PG_FUNCTION_ARGS)
Definition: acl.c:2599
static Oid convert_database_name(text *databasename)
Definition: acl.c:3079
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
unsigned int uint32
Definition: c.h:359
Datum has_database_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:3005
static AclMode convert_database_priv_string(text *priv_type_text)
Definition: acl.c:3091
#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:4946
static AclMode convert_language_priv_string(text *priv_type_text)
Definition: acl.c:3680
#define ereport(elevel, rest)
Definition: elog.h:141
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
Datum has_tablespace_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:4092
Datum has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:3126
MemoryContext TopMemoryContext
Definition: mcxt.c:44
#define ACL_CONNECT
Definition: parsenodes.h:86
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3594
char * get_rolespec_name(const RoleSpec *role)
Definition: acl.c:5300
ObjectType
Definition: parsenodes.h:1690
Datum aclitemout(PG_FUNCTION_ARGS)
Definition: acl.c:592
Datum has_schema_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:3758
NameData typname
Definition: pg_type.h:41
Datum has_type_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:4282
Datum has_server_privilege_name(PG_FUNCTION_ARGS)
Definition: acl.c:3927
static Oid convert_server_name(text *servername)
Definition: acl.c:4052
Datum has_language_privilege_name_id(PG_FUNCTION_ARGS)
Definition: acl.c:3567
Datum has_language_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:3594
static AclMode convert_server_priv_string(text *priv_type_text)
Definition: acl.c:4064
Datum has_table_privilege_name_name(PG_FUNCTION_ARGS)
Definition: acl.c:1844
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:4308
Datum has_server_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:4003
Datum has_schema_privilege_id(PG_FUNCTION_ARGS)
Definition: acl.c:3785
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
Datum has_database_privilege_id_name(PG_FUNCTION_ARGS)
Definition: acl.c:3030
#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:1761
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:2928
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:5322
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define ACL_MODECHG_ADD
Definition: acl.h:129
#define ACL_SELECT
Definition: parsenodes.h:75
RoleSpecType roletype
Definition: parsenodes.h: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:5217
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:1535
Datum has_language_privilege_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:3642
AclMode value
Definition: acl.c:47
Datum has_sequence_privilege_id_id(PG_FUNCTION_ARGS)
Definition: acl.c:2204
bool admin_option
static AclMode convert_priv_string(text *priv_type_text)
Definition: acl.c:1590
#define BoolGetDatum(X)
Definition: postgres.h:402
#define ACL_ALL_RIGHTS_STR
Definition: acl.h:151
#define ACL_USAGE_CHR
Definition: acl.h:145
static char * username
Definition: initdb.c:133
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2108
#define InvalidOid
Definition: postgres_ext.h:36
int16 attnum
Definition: pg_attribute.h:79
Definition: acl.h:54
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:164