PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
aclchk.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * aclchk.c
4  * Routines to check access control permissions.
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/catalog/aclchk.c
12  *
13  * NOTES
14  * See acl.h.
15  *
16  *-------------------------------------------------------------------------
17  */
18 #include "postgres.h"
19 
20 #include "access/genam.h"
21 #include "access/heapam.h"
22 #include "access/htup_details.h"
23 #include "access/sysattr.h"
24 #include "access/xact.h"
25 #include "catalog/binary_upgrade.h"
26 #include "catalog/catalog.h"
27 #include "catalog/dependency.h"
28 #include "catalog/indexing.h"
29 #include "catalog/objectaccess.h"
30 #include "catalog/pg_aggregate.h"
31 #include "catalog/pg_am.h"
32 #include "catalog/pg_authid.h"
33 #include "catalog/pg_cast.h"
34 #include "catalog/pg_collation.h"
35 #include "catalog/pg_conversion.h"
36 #include "catalog/pg_database.h"
37 #include "catalog/pg_default_acl.h"
39 #include "catalog/pg_extension.h"
42 #include "catalog/pg_init_privs.h"
43 #include "catalog/pg_language.h"
44 #include "catalog/pg_largeobject.h"
46 #include "catalog/pg_namespace.h"
47 #include "catalog/pg_opclass.h"
48 #include "catalog/pg_operator.h"
49 #include "catalog/pg_opfamily.h"
50 #include "catalog/pg_proc.h"
53 #include "catalog/pg_tablespace.h"
54 #include "catalog/pg_type.h"
55 #include "catalog/pg_ts_config.h"
56 #include "catalog/pg_ts_dict.h"
57 #include "catalog/pg_ts_parser.h"
58 #include "catalog/pg_ts_template.h"
59 #include "catalog/pg_transform.h"
60 #include "commands/dbcommands.h"
61 #include "commands/event_trigger.h"
62 #include "commands/extension.h"
63 #include "commands/proclang.h"
64 #include "commands/tablespace.h"
65 #include "foreign/foreign.h"
66 #include "miscadmin.h"
67 #include "nodes/makefuncs.h"
68 #include "parser/parse_func.h"
69 #include "parser/parse_type.h"
70 #include "utils/acl.h"
71 #include "utils/aclchk_internal.h"
72 #include "utils/builtins.h"
73 #include "utils/fmgroids.h"
74 #include "utils/lsyscache.h"
75 #include "utils/rel.h"
76 #include "utils/syscache.h"
77 #include "utils/tqual.h"
78 
79 
80 /*
81  * Internal format used by ALTER DEFAULT PRIVILEGES.
82  */
83 typedef struct
84 {
85  Oid roleid; /* owning role */
86  Oid nspid; /* namespace, or InvalidOid if none */
87  /* remaining fields are same as in InternalGrant: */
88  bool is_grant;
90  bool all_privs;
96 
97 /*
98  * When performing a binary-upgrade, pg_dump will call a function to set
99  * this variable to let us know that we need to populate the pg_init_privs
100  * table for the GRANT/REVOKE commands while this variable is set to true.
101  */
103 
104 static void ExecGrantStmt_oids(InternalGrant *istmt);
105 static void ExecGrant_Relation(InternalGrant *grantStmt);
106 static void ExecGrant_Database(InternalGrant *grantStmt);
107 static void ExecGrant_Fdw(InternalGrant *grantStmt);
108 static void ExecGrant_ForeignServer(InternalGrant *grantStmt);
109 static void ExecGrant_Function(InternalGrant *grantStmt);
110 static void ExecGrant_Language(InternalGrant *grantStmt);
111 static void ExecGrant_Largeobject(InternalGrant *grantStmt);
112 static void ExecGrant_Namespace(InternalGrant *grantStmt);
113 static void ExecGrant_Tablespace(InternalGrant *grantStmt);
114 static void ExecGrant_Type(InternalGrant *grantStmt);
115 
116 static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames);
117 static void SetDefaultACL(InternalDefaultACL *iacls);
118 
119 static List *objectNamesToOids(GrantObjectType objtype, List *objnames);
120 static List *objectsInSchemaToOids(GrantObjectType objtype, List *nspnames);
121 static List *getRelationsInNamespace(Oid namespaceId, char relkind);
122 static void expand_col_privileges(List *colnames, Oid table_oid,
123  AclMode this_privileges,
124  AclMode *col_privileges,
125  int num_col_privileges);
126 static void expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
127  AclMode this_privileges,
128  AclMode *col_privileges,
129  int num_col_privileges);
130 static AclMode string_to_privilege(const char *privname);
131 static const char *privilege_to_string(AclMode privilege);
132 static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions,
133  bool all_privs, AclMode privileges,
134  Oid objectId, Oid grantorId,
135  AclObjectKind objkind, const char *objname,
136  AttrNumber att_number, const char *colname);
137 static AclMode pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum,
138  Oid roleid, AclMode mask, AclMaskHow how);
139 static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid,
140  Acl *new_acl);
141 static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
142  Acl *new_acl);
143 
144 
145 #ifdef ACLDEBUG
146 static void
147 dumpacl(Acl *acl)
148 {
149  int i;
150  AclItem *aip;
151 
152  elog(DEBUG2, "acl size = %d, # acls = %d",
153  ACL_SIZE(acl), ACL_NUM(acl));
154  aip = ACL_DAT(acl);
155  for (i = 0; i < ACL_NUM(acl); ++i)
156  elog(DEBUG2, " acl[%d]: %s", i,
158  PointerGetDatum(aip + i))));
159 }
160 #endif /* ACLDEBUG */
161 
162 
163 /*
164  * If is_grant is true, adds the given privileges for the list of
165  * grantees to the existing old_acl. If is_grant is false, the
166  * privileges for the given grantees are removed from old_acl.
167  *
168  * NB: the original old_acl is pfree'd.
169  */
170 static Acl *
171 merge_acl_with_grant(Acl *old_acl, bool is_grant,
172  bool grant_option, DropBehavior behavior,
173  List *grantees, AclMode privileges,
174  Oid grantorId, Oid ownerId)
175 {
176  unsigned modechg;
177  ListCell *j;
178  Acl *new_acl;
179 
180  modechg = is_grant ? ACL_MODECHG_ADD : ACL_MODECHG_DEL;
181 
182 #ifdef ACLDEBUG
183  dumpacl(old_acl);
184 #endif
185  new_acl = old_acl;
186 
187  foreach(j, grantees)
188  {
189  AclItem aclitem;
190  Acl *newer_acl;
191 
192  aclitem.ai_grantee = lfirst_oid(j);
193 
194  /*
195  * Grant options can only be granted to individual roles, not PUBLIC.
196  * The reason is that if a user would re-grant a privilege that he
197  * held through PUBLIC, and later the user is removed, the situation
198  * is impossible to clean up.
199  */
200  if (is_grant && grant_option && aclitem.ai_grantee == ACL_ID_PUBLIC)
201  ereport(ERROR,
202  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
203  errmsg("grant options can only be granted to roles")));
204 
205  aclitem.ai_grantor = grantorId;
206 
207  /*
208  * The asymmetry in the conditions here comes from the spec. In
209  * GRANT, the grant_option flag signals WITH GRANT OPTION, which means
210  * to grant both the basic privilege and its grant option. But in
211  * REVOKE, plain revoke revokes both the basic privilege and its grant
212  * option, while REVOKE GRANT OPTION revokes only the option.
213  */
215  (is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
216  (!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS);
217 
218  newer_acl = aclupdate(new_acl, &aclitem, modechg, ownerId, behavior);
219 
220  /* avoid memory leak when there are many grantees */
221  pfree(new_acl);
222  new_acl = newer_acl;
223 
224 #ifdef ACLDEBUG
225  dumpacl(new_acl);
226 #endif
227  }
228 
229  return new_acl;
230 }
231 
232 /*
233  * Restrict the privileges to what we can actually grant, and emit
234  * the standards-mandated warning and error messages.
235  */
236 static AclMode
237 restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
238  AclMode privileges, Oid objectId, Oid grantorId,
239  AclObjectKind objkind, const char *objname,
240  AttrNumber att_number, const char *colname)
241 {
242  AclMode this_privileges;
243  AclMode whole_mask;
244 
245  switch (objkind)
246  {
247  case ACL_KIND_COLUMN:
248  whole_mask = ACL_ALL_RIGHTS_COLUMN;
249  break;
250  case ACL_KIND_CLASS:
251  whole_mask = ACL_ALL_RIGHTS_RELATION;
252  break;
253  case ACL_KIND_SEQUENCE:
254  whole_mask = ACL_ALL_RIGHTS_SEQUENCE;
255  break;
256  case ACL_KIND_DATABASE:
257  whole_mask = ACL_ALL_RIGHTS_DATABASE;
258  break;
259  case ACL_KIND_PROC:
260  whole_mask = ACL_ALL_RIGHTS_FUNCTION;
261  break;
262  case ACL_KIND_LANGUAGE:
263  whole_mask = ACL_ALL_RIGHTS_LANGUAGE;
264  break;
266  whole_mask = ACL_ALL_RIGHTS_LARGEOBJECT;
267  break;
268  case ACL_KIND_NAMESPACE:
269  whole_mask = ACL_ALL_RIGHTS_NAMESPACE;
270  break;
271  case ACL_KIND_TABLESPACE:
272  whole_mask = ACL_ALL_RIGHTS_TABLESPACE;
273  break;
274  case ACL_KIND_FDW:
275  whole_mask = ACL_ALL_RIGHTS_FDW;
276  break;
278  whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
279  break;
281  elog(ERROR, "grantable rights not supported for event triggers");
282  /* not reached, but keep compiler quiet */
283  return ACL_NO_RIGHTS;
284  case ACL_KIND_TYPE:
285  whole_mask = ACL_ALL_RIGHTS_TYPE;
286  break;
287  default:
288  elog(ERROR, "unrecognized object kind: %d", objkind);
289  /* not reached, but keep compiler quiet */
290  return ACL_NO_RIGHTS;
291  }
292 
293  /*
294  * If we found no grant options, consider whether to issue a hard error.
295  * Per spec, having any privilege at all on the object will get you by
296  * here.
297  */
298  if (avail_goptions == ACL_NO_RIGHTS)
299  {
300  if (pg_aclmask(objkind, objectId, att_number, grantorId,
301  whole_mask | ACL_GRANT_OPTION_FOR(whole_mask),
303  {
304  if (objkind == ACL_KIND_COLUMN && colname)
305  aclcheck_error_col(ACLCHECK_NO_PRIV, objkind, objname, colname);
306  else
307  aclcheck_error(ACLCHECK_NO_PRIV, objkind, objname);
308  }
309  }
310 
311  /*
312  * Restrict the operation to what we can actually grant or revoke, and
313  * issue a warning if appropriate. (For REVOKE this isn't quite what the
314  * spec says to do: the spec seems to want a warning only if no privilege
315  * bits actually change in the ACL. In practice that behavior seems much
316  * too noisy, as well as inconsistent with the GRANT case.)
317  */
318  this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
319  if (is_grant)
320  {
321  if (this_privileges == 0)
322  {
323  if (objkind == ACL_KIND_COLUMN && colname)
325  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
326  errmsg("no privileges were granted for column \"%s\" of relation \"%s\"",
327  colname, objname)));
328  else
330  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
331  errmsg("no privileges were granted for \"%s\"",
332  objname)));
333  }
334  else if (!all_privs && this_privileges != privileges)
335  {
336  if (objkind == ACL_KIND_COLUMN && colname)
338  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
339  errmsg("not all privileges were granted for column \"%s\" of relation \"%s\"",
340  colname, objname)));
341  else
343  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
344  errmsg("not all privileges were granted for \"%s\"",
345  objname)));
346  }
347  }
348  else
349  {
350  if (this_privileges == 0)
351  {
352  if (objkind == ACL_KIND_COLUMN && colname)
354  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
355  errmsg("no privileges could be revoked for column \"%s\" of relation \"%s\"",
356  colname, objname)));
357  else
359  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
360  errmsg("no privileges could be revoked for \"%s\"",
361  objname)));
362  }
363  else if (!all_privs && this_privileges != privileges)
364  {
365  if (objkind == ACL_KIND_COLUMN && colname)
367  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
368  errmsg("not all privileges could be revoked for column \"%s\" of relation \"%s\"",
369  colname, objname)));
370  else
372  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
373  errmsg("not all privileges could be revoked for \"%s\"",
374  objname)));
375  }
376  }
377 
378  return this_privileges;
379 }
380 
381 /*
382  * Called to execute the utility commands GRANT and REVOKE
383  */
384 void
386 {
387  InternalGrant istmt;
388  ListCell *cell;
389  const char *errormsg;
390  AclMode all_privileges;
391 
392  /*
393  * Turn the regular GrantStmt into the InternalGrant form.
394  */
395  istmt.is_grant = stmt->is_grant;
396  istmt.objtype = stmt->objtype;
397 
398  /* Collect the OIDs of the target objects */
399  switch (stmt->targtype)
400  {
401  case ACL_TARGET_OBJECT:
402  istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects);
403  break;
405  istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
406  break;
407  /* ACL_TARGET_DEFAULTS should not be seen here */
408  default:
409  elog(ERROR, "unrecognized GrantStmt.targtype: %d",
410  (int) stmt->targtype);
411  }
412 
413  /* all_privs to be filled below */
414  /* privileges to be filled below */
415  istmt.col_privs = NIL; /* may get filled below */
416  istmt.grantees = NIL; /* filled below */
417  istmt.grant_option = stmt->grant_option;
418  istmt.behavior = stmt->behavior;
419 
420  /*
421  * Convert the RoleSpec list into an Oid list. Note that at this point we
422  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
423  * there shouldn't be any additional work needed to support this case.
424  */
425  foreach(cell, stmt->grantees)
426  {
427  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
428  Oid grantee_uid;
429 
430  switch (grantee->roletype)
431  {
432  case ROLESPEC_PUBLIC:
433  grantee_uid = ACL_ID_PUBLIC;
434  break;
435  default:
436  grantee_uid = get_rolespec_oid(grantee, false);
437  break;
438  }
439  istmt.grantees = lappend_oid(istmt.grantees, grantee_uid);
440  }
441 
442  /*
443  * Convert stmt->privileges, a list of AccessPriv nodes, into an AclMode
444  * bitmask. Note: objtype can't be ACL_OBJECT_COLUMN.
445  */
446  switch (stmt->objtype)
447  {
448  /*
449  * Because this might be a sequence, we test both relation and
450  * sequence bits, and later do a more limited test when we know
451  * the object type.
452  */
453  case ACL_OBJECT_RELATION:
455  errormsg = gettext_noop("invalid privilege type %s for relation");
456  break;
457  case ACL_OBJECT_SEQUENCE:
458  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
459  errormsg = gettext_noop("invalid privilege type %s for sequence");
460  break;
461  case ACL_OBJECT_DATABASE:
462  all_privileges = ACL_ALL_RIGHTS_DATABASE;
463  errormsg = gettext_noop("invalid privilege type %s for database");
464  break;
465  case ACL_OBJECT_DOMAIN:
466  all_privileges = ACL_ALL_RIGHTS_TYPE;
467  errormsg = gettext_noop("invalid privilege type %s for domain");
468  break;
469  case ACL_OBJECT_FUNCTION:
470  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
471  errormsg = gettext_noop("invalid privilege type %s for function");
472  break;
473  case ACL_OBJECT_LANGUAGE:
474  all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
475  errormsg = gettext_noop("invalid privilege type %s for language");
476  break;
478  all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
479  errormsg = gettext_noop("invalid privilege type %s for large object");
480  break;
482  all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
483  errormsg = gettext_noop("invalid privilege type %s for schema");
484  break;
486  all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
487  errormsg = gettext_noop("invalid privilege type %s for tablespace");
488  break;
489  case ACL_OBJECT_TYPE:
490  all_privileges = ACL_ALL_RIGHTS_TYPE;
491  errormsg = gettext_noop("invalid privilege type %s for type");
492  break;
493  case ACL_OBJECT_FDW:
494  all_privileges = ACL_ALL_RIGHTS_FDW;
495  errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
496  break;
498  all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
499  errormsg = gettext_noop("invalid privilege type %s for foreign server");
500  break;
501  default:
502  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
503  (int) stmt->objtype);
504  /* keep compiler quiet */
505  all_privileges = ACL_NO_RIGHTS;
506  errormsg = NULL;
507  }
508 
509  if (stmt->privileges == NIL)
510  {
511  istmt.all_privs = true;
512 
513  /*
514  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
515  * depending on the object type
516  */
517  istmt.privileges = ACL_NO_RIGHTS;
518  }
519  else
520  {
521  istmt.all_privs = false;
522  istmt.privileges = ACL_NO_RIGHTS;
523 
524  foreach(cell, stmt->privileges)
525  {
526  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
527  AclMode priv;
528 
529  /*
530  * If it's a column-level specification, we just set it aside in
531  * col_privs for the moment; but insist it's for a relation.
532  */
533  if (privnode->cols)
534  {
535  if (stmt->objtype != ACL_OBJECT_RELATION)
536  ereport(ERROR,
537  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
538  errmsg("column privileges are only valid for relations")));
539  istmt.col_privs = lappend(istmt.col_privs, privnode);
540  continue;
541  }
542 
543  if (privnode->priv_name == NULL) /* parser mistake? */
544  elog(ERROR, "AccessPriv node must specify privilege or columns");
545  priv = string_to_privilege(privnode->priv_name);
546 
547  if (priv & ~((AclMode) all_privileges))
548  ereport(ERROR,
549  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
550  errmsg(errormsg, privilege_to_string(priv))));
551 
552  istmt.privileges |= priv;
553  }
554  }
555 
556  ExecGrantStmt_oids(&istmt);
557 }
558 
559 /*
560  * ExecGrantStmt_oids
561  *
562  * Internal entry point for granting and revoking privileges.
563  */
564 static void
566 {
567  switch (istmt->objtype)
568  {
569  case ACL_OBJECT_RELATION:
570  case ACL_OBJECT_SEQUENCE:
571  ExecGrant_Relation(istmt);
572  break;
573  case ACL_OBJECT_DATABASE:
574  ExecGrant_Database(istmt);
575  break;
576  case ACL_OBJECT_DOMAIN:
577  case ACL_OBJECT_TYPE:
578  ExecGrant_Type(istmt);
579  break;
580  case ACL_OBJECT_FDW:
581  ExecGrant_Fdw(istmt);
582  break;
585  break;
586  case ACL_OBJECT_FUNCTION:
587  ExecGrant_Function(istmt);
588  break;
589  case ACL_OBJECT_LANGUAGE:
590  ExecGrant_Language(istmt);
591  break;
593  ExecGrant_Largeobject(istmt);
594  break;
596  ExecGrant_Namespace(istmt);
597  break;
599  ExecGrant_Tablespace(istmt);
600  break;
601  default:
602  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
603  (int) istmt->objtype);
604  }
605 
606  /*
607  * Pass the info to event triggers about the just-executed GRANT. Note
608  * that we prefer to do it after actually executing it, because that gives
609  * the functions a chance to adjust the istmt with privileges actually
610  * granted.
611  */
614 }
615 
616 /*
617  * objectNamesToOids
618  *
619  * Turn a list of object names of a given type into an Oid list.
620  *
621  * XXX: This function doesn't take any sort of locks on the objects whose
622  * names it looks up. In the face of concurrent DDL, we might easily latch
623  * onto an old version of an object, causing the GRANT or REVOKE statement
624  * to fail.
625  */
626 static List *
628 {
629  List *objects = NIL;
630  ListCell *cell;
631 
632  Assert(objnames != NIL);
633 
634  switch (objtype)
635  {
636  case ACL_OBJECT_RELATION:
637  case ACL_OBJECT_SEQUENCE:
638  foreach(cell, objnames)
639  {
640  RangeVar *relvar = (RangeVar *) lfirst(cell);
641  Oid relOid;
642 
643  relOid = RangeVarGetRelid(relvar, NoLock, false);
644  objects = lappend_oid(objects, relOid);
645  }
646  break;
647  case ACL_OBJECT_DATABASE:
648  foreach(cell, objnames)
649  {
650  char *dbname = strVal(lfirst(cell));
651  Oid dbid;
652 
653  dbid = get_database_oid(dbname, false);
654  objects = lappend_oid(objects, dbid);
655  }
656  break;
657  case ACL_OBJECT_DOMAIN:
658  case ACL_OBJECT_TYPE:
659  foreach(cell, objnames)
660  {
661  List *typname = (List *) lfirst(cell);
662  Oid oid;
663 
665  objects = lappend_oid(objects, oid);
666  }
667  break;
668  case ACL_OBJECT_FUNCTION:
669  foreach(cell, objnames)
670  {
671  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
672  Oid funcid;
673 
674  funcid = LookupFuncWithArgs(func, false);
675  objects = lappend_oid(objects, funcid);
676  }
677  break;
678  case ACL_OBJECT_LANGUAGE:
679  foreach(cell, objnames)
680  {
681  char *langname = strVal(lfirst(cell));
682  Oid oid;
683 
684  oid = get_language_oid(langname, false);
685  objects = lappend_oid(objects, oid);
686  }
687  break;
689  foreach(cell, objnames)
690  {
691  Oid lobjOid = oidparse(lfirst(cell));
692 
693  if (!LargeObjectExists(lobjOid))
694  ereport(ERROR,
695  (errcode(ERRCODE_UNDEFINED_OBJECT),
696  errmsg("large object %u does not exist",
697  lobjOid)));
698 
699  objects = lappend_oid(objects, lobjOid);
700  }
701  break;
703  foreach(cell, objnames)
704  {
705  char *nspname = strVal(lfirst(cell));
706  Oid oid;
707 
708  oid = get_namespace_oid(nspname, false);
709  objects = lappend_oid(objects, oid);
710  }
711  break;
713  foreach(cell, objnames)
714  {
715  char *spcname = strVal(lfirst(cell));
716  Oid spcoid;
717 
718  spcoid = get_tablespace_oid(spcname, false);
719  objects = lappend_oid(objects, spcoid);
720  }
721  break;
722  case ACL_OBJECT_FDW:
723  foreach(cell, objnames)
724  {
725  char *fdwname = strVal(lfirst(cell));
726  Oid fdwid = get_foreign_data_wrapper_oid(fdwname, false);
727 
728  objects = lappend_oid(objects, fdwid);
729  }
730  break;
732  foreach(cell, objnames)
733  {
734  char *srvname = strVal(lfirst(cell));
735  Oid srvid = get_foreign_server_oid(srvname, false);
736 
737  objects = lappend_oid(objects, srvid);
738  }
739  break;
740  default:
741  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
742  (int) objtype);
743  }
744 
745  return objects;
746 }
747 
748 /*
749  * objectsInSchemaToOids
750  *
751  * Find all objects of a given type in specified schemas, and make a list
752  * of their Oids. We check USAGE privilege on the schemas, but there is
753  * no privilege checking on the individual objects here.
754  */
755 static List *
757 {
758  List *objects = NIL;
759  ListCell *cell;
760 
761  foreach(cell, nspnames)
762  {
763  char *nspname = strVal(lfirst(cell));
764  Oid namespaceId;
765  List *objs;
766 
767  namespaceId = LookupExplicitNamespace(nspname, false);
768 
769  switch (objtype)
770  {
771  case ACL_OBJECT_RELATION:
772  objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
773  objects = list_concat(objects, objs);
774  objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
775  objects = list_concat(objects, objs);
776  objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
777  objects = list_concat(objects, objs);
778  objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
779  objects = list_concat(objects, objs);
781  objects = list_concat(objects, objs);
782  break;
783  case ACL_OBJECT_SEQUENCE:
784  objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
785  objects = list_concat(objects, objs);
786  break;
787  case ACL_OBJECT_FUNCTION:
788  {
789  ScanKeyData key[1];
790  Relation rel;
791  HeapScanDesc scan;
792  HeapTuple tuple;
793 
794  ScanKeyInit(&key[0],
796  BTEqualStrategyNumber, F_OIDEQ,
797  ObjectIdGetDatum(namespaceId));
798 
800  scan = heap_beginscan_catalog(rel, 1, key);
801 
802  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
803  {
804  objects = lappend_oid(objects, HeapTupleGetOid(tuple));
805  }
806 
807  heap_endscan(scan);
809  }
810  break;
811  default:
812  /* should not happen */
813  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
814  (int) objtype);
815  }
816  }
817 
818  return objects;
819 }
820 
821 /*
822  * getRelationsInNamespace
823  *
824  * Return Oid list of relations in given namespace filtered by relation kind
825  */
826 static List *
827 getRelationsInNamespace(Oid namespaceId, char relkind)
828 {
829  List *relations = NIL;
830  ScanKeyData key[2];
831  Relation rel;
832  HeapScanDesc scan;
833  HeapTuple tuple;
834 
835  ScanKeyInit(&key[0],
837  BTEqualStrategyNumber, F_OIDEQ,
838  ObjectIdGetDatum(namespaceId));
839  ScanKeyInit(&key[1],
841  BTEqualStrategyNumber, F_CHAREQ,
842  CharGetDatum(relkind));
843 
845  scan = heap_beginscan_catalog(rel, 2, key);
846 
847  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
848  {
849  relations = lappend_oid(relations, HeapTupleGetOid(tuple));
850  }
851 
852  heap_endscan(scan);
854 
855  return relations;
856 }
857 
858 
859 /*
860  * ALTER DEFAULT PRIVILEGES statement
861  */
862 void
864 {
865  GrantStmt *action = stmt->action;
866  InternalDefaultACL iacls;
867  ListCell *cell;
868  List *rolespecs = NIL;
869  List *nspnames = NIL;
870  DefElem *drolespecs = NULL;
871  DefElem *dnspnames = NULL;
872  AclMode all_privileges;
873  const char *errormsg;
874 
875  /* Deconstruct the "options" part of the statement */
876  foreach(cell, stmt->options)
877  {
878  DefElem *defel = (DefElem *) lfirst(cell);
879 
880  if (strcmp(defel->defname, "schemas") == 0)
881  {
882  if (dnspnames)
883  ereport(ERROR,
884  (errcode(ERRCODE_SYNTAX_ERROR),
885  errmsg("conflicting or redundant options"),
886  parser_errposition(pstate, defel->location)));
887  dnspnames = defel;
888  }
889  else if (strcmp(defel->defname, "roles") == 0)
890  {
891  if (drolespecs)
892  ereport(ERROR,
893  (errcode(ERRCODE_SYNTAX_ERROR),
894  errmsg("conflicting or redundant options"),
895  parser_errposition(pstate, defel->location)));
896  drolespecs = defel;
897  }
898  else
899  elog(ERROR, "option \"%s\" not recognized", defel->defname);
900  }
901 
902  if (dnspnames)
903  nspnames = (List *) dnspnames->arg;
904  if (drolespecs)
905  rolespecs = (List *) drolespecs->arg;
906 
907  /* Prepare the InternalDefaultACL representation of the statement */
908  /* roleid to be filled below */
909  /* nspid to be filled in SetDefaultACLsInSchemas */
910  iacls.is_grant = action->is_grant;
911  iacls.objtype = action->objtype;
912  /* all_privs to be filled below */
913  /* privileges to be filled below */
914  iacls.grantees = NIL; /* filled below */
915  iacls.grant_option = action->grant_option;
916  iacls.behavior = action->behavior;
917 
918  /*
919  * Convert the RoleSpec list into an Oid list. Note that at this point we
920  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
921  * there shouldn't be any additional work needed to support this case.
922  */
923  foreach(cell, action->grantees)
924  {
925  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
926  Oid grantee_uid;
927 
928  switch (grantee->roletype)
929  {
930  case ROLESPEC_PUBLIC:
931  grantee_uid = ACL_ID_PUBLIC;
932  break;
933  default:
934  grantee_uid = get_rolespec_oid(grantee, false);
935  break;
936  }
937  iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
938  }
939 
940  /*
941  * Convert action->privileges, a list of privilege strings, into an
942  * AclMode bitmask.
943  */
944  switch (action->objtype)
945  {
946  case ACL_OBJECT_RELATION:
947  all_privileges = ACL_ALL_RIGHTS_RELATION;
948  errormsg = gettext_noop("invalid privilege type %s for relation");
949  break;
950  case ACL_OBJECT_SEQUENCE:
951  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
952  errormsg = gettext_noop("invalid privilege type %s for sequence");
953  break;
954  case ACL_OBJECT_FUNCTION:
955  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
956  errormsg = gettext_noop("invalid privilege type %s for function");
957  break;
958  case ACL_OBJECT_TYPE:
959  all_privileges = ACL_ALL_RIGHTS_TYPE;
960  errormsg = gettext_noop("invalid privilege type %s for type");
961  break;
963  all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
964  errormsg = gettext_noop("invalid privilege type %s for schema");
965  break;
966  default:
967  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
968  (int) action->objtype);
969  /* keep compiler quiet */
970  all_privileges = ACL_NO_RIGHTS;
971  errormsg = NULL;
972  }
973 
974  if (action->privileges == NIL)
975  {
976  iacls.all_privs = true;
977 
978  /*
979  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
980  * depending on the object type
981  */
982  iacls.privileges = ACL_NO_RIGHTS;
983  }
984  else
985  {
986  iacls.all_privs = false;
987  iacls.privileges = ACL_NO_RIGHTS;
988 
989  foreach(cell, action->privileges)
990  {
991  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
992  AclMode priv;
993 
994  if (privnode->cols)
995  ereport(ERROR,
996  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
997  errmsg("default privileges cannot be set for columns")));
998 
999  if (privnode->priv_name == NULL) /* parser mistake? */
1000  elog(ERROR, "AccessPriv node must specify privilege");
1001  priv = string_to_privilege(privnode->priv_name);
1002 
1003  if (priv & ~((AclMode) all_privileges))
1004  ereport(ERROR,
1005  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1006  errmsg(errormsg, privilege_to_string(priv))));
1007 
1008  iacls.privileges |= priv;
1009  }
1010  }
1011 
1012  if (rolespecs == NIL)
1013  {
1014  /* Set permissions for myself */
1015  iacls.roleid = GetUserId();
1016 
1017  SetDefaultACLsInSchemas(&iacls, nspnames);
1018  }
1019  else
1020  {
1021  /* Look up the role OIDs and do permissions checks */
1022  ListCell *rolecell;
1023 
1024  foreach(rolecell, rolespecs)
1025  {
1026  RoleSpec *rolespec = lfirst(rolecell);
1027 
1028  iacls.roleid = get_rolespec_oid(rolespec, false);
1029 
1030  /*
1031  * We insist that calling user be a member of each target role. If
1032  * he has that, he could become that role anyway via SET ROLE, so
1033  * FOR ROLE is just a syntactic convenience and doesn't give any
1034  * special privileges.
1035  */
1037 
1038  SetDefaultACLsInSchemas(&iacls, nspnames);
1039  }
1040  }
1041 }
1042 
1043 /*
1044  * Process ALTER DEFAULT PRIVILEGES for a list of target schemas
1045  *
1046  * All fields of *iacls except nspid were filled already
1047  */
1048 static void
1050 {
1051  if (nspnames == NIL)
1052  {
1053  /* Set database-wide permissions if no schema was specified */
1054  iacls->nspid = InvalidOid;
1055 
1056  SetDefaultACL(iacls);
1057  }
1058  else
1059  {
1060  /* Look up the schema OIDs and set permissions for each one */
1061  ListCell *nspcell;
1062 
1063  foreach(nspcell, nspnames)
1064  {
1065  char *nspname = strVal(lfirst(nspcell));
1066 
1067  iacls->nspid = get_namespace_oid(nspname, false);
1068 
1069  /*
1070  * We used to insist that the target role have CREATE privileges
1071  * on the schema, since without that it wouldn't be able to create
1072  * an object for which these default privileges would apply.
1073  * However, this check proved to be more confusing than helpful,
1074  * and it also caused certain database states to not be
1075  * dumpable/restorable, since revoking CREATE doesn't cause
1076  * default privileges for the schema to go away. So now, we just
1077  * allow the ALTER; if the user lacks CREATE he'll find out when
1078  * he tries to create an object.
1079  */
1080 
1081  SetDefaultACL(iacls);
1082  }
1083  }
1084 }
1085 
1086 
1087 /*
1088  * Create or update a pg_default_acl entry
1089  */
1090 static void
1092 {
1093  AclMode this_privileges = iacls->privileges;
1094  char objtype;
1095  Relation rel;
1096  HeapTuple tuple;
1097  bool isNew;
1098  Acl *def_acl;
1099  Acl *old_acl;
1100  Acl *new_acl;
1101  HeapTuple newtuple;
1103  bool nulls[Natts_pg_default_acl];
1104  bool replaces[Natts_pg_default_acl];
1105  int noldmembers;
1106  int nnewmembers;
1107  Oid *oldmembers;
1108  Oid *newmembers;
1109 
1111 
1112  /*
1113  * The default for a global entry is the hard-wired default ACL for the
1114  * particular object type. The default for non-global entries is an empty
1115  * ACL. This must be so because global entries replace the hard-wired
1116  * defaults, while others are added on.
1117  */
1118  if (!OidIsValid(iacls->nspid))
1119  def_acl = acldefault(iacls->objtype, iacls->roleid);
1120  else
1121  def_acl = make_empty_acl();
1122 
1123  /*
1124  * Convert ACL object type to pg_default_acl object type and handle
1125  * all_privs option
1126  */
1127  switch (iacls->objtype)
1128  {
1129  case ACL_OBJECT_RELATION:
1130  objtype = DEFACLOBJ_RELATION;
1131  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1132  this_privileges = ACL_ALL_RIGHTS_RELATION;
1133  break;
1134 
1135  case ACL_OBJECT_SEQUENCE:
1136  objtype = DEFACLOBJ_SEQUENCE;
1137  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1138  this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1139  break;
1140 
1141  case ACL_OBJECT_FUNCTION:
1142  objtype = DEFACLOBJ_FUNCTION;
1143  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1144  this_privileges = ACL_ALL_RIGHTS_FUNCTION;
1145  break;
1146 
1147  case ACL_OBJECT_TYPE:
1148  objtype = DEFACLOBJ_TYPE;
1149  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1150  this_privileges = ACL_ALL_RIGHTS_TYPE;
1151  break;
1152 
1153  case ACL_OBJECT_NAMESPACE:
1154  if (OidIsValid(iacls->nspid))
1155  ereport(ERROR,
1156  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1157  errmsg("cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS")));
1158  objtype = DEFACLOBJ_NAMESPACE;
1159  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1160  this_privileges = ACL_ALL_RIGHTS_NAMESPACE;
1161  break;
1162 
1163  default:
1164  elog(ERROR, "unrecognized objtype: %d",
1165  (int) iacls->objtype);
1166  objtype = 0; /* keep compiler quiet */
1167  break;
1168  }
1169 
1170  /* Search for existing row for this object type in catalog */
1172  ObjectIdGetDatum(iacls->roleid),
1173  ObjectIdGetDatum(iacls->nspid),
1174  CharGetDatum(objtype));
1175 
1176  if (HeapTupleIsValid(tuple))
1177  {
1178  Datum aclDatum;
1179  bool isNull;
1180 
1181  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
1183  &isNull);
1184  if (!isNull)
1185  old_acl = DatumGetAclPCopy(aclDatum);
1186  else
1187  old_acl = NULL; /* this case shouldn't happen, probably */
1188  isNew = false;
1189  }
1190  else
1191  {
1192  old_acl = NULL;
1193  isNew = true;
1194  }
1195 
1196  if (old_acl != NULL)
1197  {
1198  /*
1199  * We need the members of both old and new ACLs so we can correct the
1200  * shared dependency information. Collect data before
1201  * merge_acl_with_grant throws away old_acl.
1202  */
1203  noldmembers = aclmembers(old_acl, &oldmembers);
1204  }
1205  else
1206  {
1207  /* If no or null entry, start with the default ACL value */
1208  old_acl = aclcopy(def_acl);
1209  /* There are no old member roles according to the catalogs */
1210  noldmembers = 0;
1211  oldmembers = NULL;
1212  }
1213 
1214  /*
1215  * Generate new ACL. Grantor of rights is always the same as the target
1216  * role.
1217  */
1218  new_acl = merge_acl_with_grant(old_acl,
1219  iacls->is_grant,
1220  iacls->grant_option,
1221  iacls->behavior,
1222  iacls->grantees,
1223  this_privileges,
1224  iacls->roleid,
1225  iacls->roleid);
1226 
1227  /*
1228  * If the result is the same as the default value, we do not need an
1229  * explicit pg_default_acl entry, and should in fact remove the entry if
1230  * it exists. Must sort both arrays to compare properly.
1231  */
1232  aclitemsort(new_acl);
1233  aclitemsort(def_acl);
1234  if (aclequal(new_acl, def_acl))
1235  {
1236  /* delete old entry, if indeed there is one */
1237  if (!isNew)
1238  {
1239  ObjectAddress myself;
1240 
1241  /*
1242  * The dependency machinery will take care of removing all
1243  * associated dependency entries. We use DROP_RESTRICT since
1244  * there shouldn't be anything depending on this entry.
1245  */
1246  myself.classId = DefaultAclRelationId;
1247  myself.objectId = HeapTupleGetOid(tuple);
1248  myself.objectSubId = 0;
1249 
1250  performDeletion(&myself, DROP_RESTRICT, 0);
1251  }
1252  }
1253  else
1254  {
1255  /* Prepare to insert or update pg_default_acl entry */
1256  MemSet(values, 0, sizeof(values));
1257  MemSet(nulls, false, sizeof(nulls));
1258  MemSet(replaces, false, sizeof(replaces));
1259 
1260  if (isNew)
1261  {
1262  /* insert new entry */
1265  values[Anum_pg_default_acl_defaclobjtype - 1] = CharGetDatum(objtype);
1266  values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
1267 
1268  newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
1269  CatalogTupleInsert(rel, newtuple);
1270  }
1271  else
1272  {
1273  /* update existing entry */
1274  values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
1275  replaces[Anum_pg_default_acl_defaclacl - 1] = true;
1276 
1277  newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
1278  values, nulls, replaces);
1279  CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
1280  }
1281 
1282  /* these dependencies don't change in an update */
1283  if (isNew)
1284  {
1285  /* dependency on role */
1287  HeapTupleGetOid(newtuple),
1288  iacls->roleid);
1289 
1290  /* dependency on namespace */
1291  if (OidIsValid(iacls->nspid))
1292  {
1293  ObjectAddress myself,
1294  referenced;
1295 
1296  myself.classId = DefaultAclRelationId;
1297  myself.objectId = HeapTupleGetOid(newtuple);
1298  myself.objectSubId = 0;
1299 
1300  referenced.classId = NamespaceRelationId;
1301  referenced.objectId = iacls->nspid;
1302  referenced.objectSubId = 0;
1303 
1304  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1305  }
1306  }
1307 
1308  /*
1309  * Update the shared dependency ACL info
1310  */
1311  nnewmembers = aclmembers(new_acl, &newmembers);
1312 
1314  HeapTupleGetOid(newtuple), 0,
1315  iacls->roleid,
1316  noldmembers, oldmembers,
1317  nnewmembers, newmembers);
1318 
1319  if (isNew)
1321  HeapTupleGetOid(newtuple), 0);
1322  else
1324  HeapTupleGetOid(newtuple), 0);
1325  }
1326 
1327  if (HeapTupleIsValid(tuple))
1328  ReleaseSysCache(tuple);
1329 
1331 }
1332 
1333 
1334 /*
1335  * RemoveRoleFromObjectACL
1336  *
1337  * Used by shdepDropOwned to remove mentions of a role in ACLs
1338  */
1339 void
1340 RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
1341 {
1342  if (classid == DefaultAclRelationId)
1343  {
1344  InternalDefaultACL iacls;
1345  Form_pg_default_acl pg_default_acl_tuple;
1346  Relation rel;
1347  ScanKeyData skey[1];
1348  SysScanDesc scan;
1349  HeapTuple tuple;
1350 
1351  /* first fetch info needed by SetDefaultACL */
1353 
1354  ScanKeyInit(&skey[0],
1356  BTEqualStrategyNumber, F_OIDEQ,
1357  ObjectIdGetDatum(objid));
1358 
1359  scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
1360  NULL, 1, skey);
1361 
1362  tuple = systable_getnext(scan);
1363 
1364  if (!HeapTupleIsValid(tuple))
1365  elog(ERROR, "could not find tuple for default ACL %u", objid);
1366 
1367  pg_default_acl_tuple = (Form_pg_default_acl) GETSTRUCT(tuple);
1368 
1369  iacls.roleid = pg_default_acl_tuple->defaclrole;
1370  iacls.nspid = pg_default_acl_tuple->defaclnamespace;
1371 
1372  switch (pg_default_acl_tuple->defaclobjtype)
1373  {
1374  case DEFACLOBJ_RELATION:
1375  iacls.objtype = ACL_OBJECT_RELATION;
1376  break;
1377  case DEFACLOBJ_SEQUENCE:
1378  iacls.objtype = ACL_OBJECT_SEQUENCE;
1379  break;
1380  case DEFACLOBJ_FUNCTION:
1381  iacls.objtype = ACL_OBJECT_FUNCTION;
1382  break;
1383  case DEFACLOBJ_TYPE:
1384  iacls.objtype = ACL_OBJECT_TYPE;
1385  break;
1386  case DEFACLOBJ_NAMESPACE:
1387  iacls.objtype = ACL_OBJECT_NAMESPACE;
1388  break;
1389  default:
1390  /* Shouldn't get here */
1391  elog(ERROR, "unexpected default ACL type: %d",
1392  (int) pg_default_acl_tuple->defaclobjtype);
1393  break;
1394  }
1395 
1396  systable_endscan(scan);
1398 
1399  iacls.is_grant = false;
1400  iacls.all_privs = true;
1401  iacls.privileges = ACL_NO_RIGHTS;
1402  iacls.grantees = list_make1_oid(roleid);
1403  iacls.grant_option = false;
1404  iacls.behavior = DROP_CASCADE;
1405 
1406  /* Do it */
1407  SetDefaultACL(&iacls);
1408  }
1409  else
1410  {
1411  InternalGrant istmt;
1412 
1413  switch (classid)
1414  {
1415  case RelationRelationId:
1416  /* it's OK to use RELATION for a sequence */
1417  istmt.objtype = ACL_OBJECT_RELATION;
1418  break;
1419  case DatabaseRelationId:
1420  istmt.objtype = ACL_OBJECT_DATABASE;
1421  break;
1422  case TypeRelationId:
1423  istmt.objtype = ACL_OBJECT_TYPE;
1424  break;
1425  case ProcedureRelationId:
1426  istmt.objtype = ACL_OBJECT_FUNCTION;
1427  break;
1428  case LanguageRelationId:
1429  istmt.objtype = ACL_OBJECT_LANGUAGE;
1430  break;
1431  case LargeObjectRelationId:
1433  break;
1434  case NamespaceRelationId:
1435  istmt.objtype = ACL_OBJECT_NAMESPACE;
1436  break;
1437  case TableSpaceRelationId:
1439  break;
1442  break;
1444  istmt.objtype = ACL_OBJECT_FDW;
1445  break;
1446  default:
1447  elog(ERROR, "unexpected object class %u", classid);
1448  break;
1449  }
1450  istmt.is_grant = false;
1451  istmt.objects = list_make1_oid(objid);
1452  istmt.all_privs = true;
1453  istmt.privileges = ACL_NO_RIGHTS;
1454  istmt.col_privs = NIL;
1455  istmt.grantees = list_make1_oid(roleid);
1456  istmt.grant_option = false;
1457  istmt.behavior = DROP_CASCADE;
1458 
1459  ExecGrantStmt_oids(&istmt);
1460  }
1461 }
1462 
1463 
1464 /*
1465  * Remove a pg_default_acl entry
1466  */
1467 void
1469 {
1470  Relation rel;
1471  ScanKeyData skey[1];
1472  SysScanDesc scan;
1473  HeapTuple tuple;
1474 
1476 
1477  ScanKeyInit(&skey[0],
1479  BTEqualStrategyNumber, F_OIDEQ,
1480  ObjectIdGetDatum(defaclOid));
1481 
1482  scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
1483  NULL, 1, skey);
1484 
1485  tuple = systable_getnext(scan);
1486 
1487  if (!HeapTupleIsValid(tuple))
1488  elog(ERROR, "could not find tuple for default ACL %u", defaclOid);
1489 
1490  CatalogTupleDelete(rel, &tuple->t_self);
1491 
1492  systable_endscan(scan);
1494 }
1495 
1496 
1497 /*
1498  * expand_col_privileges
1499  *
1500  * OR the specified privilege(s) into per-column array entries for each
1501  * specified attribute. The per-column array is indexed starting at
1502  * FirstLowInvalidHeapAttributeNumber, up to relation's last attribute.
1503  */
1504 static void
1505 expand_col_privileges(List *colnames, Oid table_oid,
1506  AclMode this_privileges,
1507  AclMode *col_privileges,
1508  int num_col_privileges)
1509 {
1510  ListCell *cell;
1511 
1512  foreach(cell, colnames)
1513  {
1514  char *colname = strVal(lfirst(cell));
1515  AttrNumber attnum;
1516 
1517  attnum = get_attnum(table_oid, colname);
1518  if (attnum == InvalidAttrNumber)
1519  ereport(ERROR,
1520  (errcode(ERRCODE_UNDEFINED_COLUMN),
1521  errmsg("column \"%s\" of relation \"%s\" does not exist",
1522  colname, get_rel_name(table_oid))));
1524  if (attnum <= 0 || attnum >= num_col_privileges)
1525  elog(ERROR, "column number out of range"); /* safety check */
1526  col_privileges[attnum] |= this_privileges;
1527  }
1528 }
1529 
1530 /*
1531  * expand_all_col_privileges
1532  *
1533  * OR the specified privilege(s) into per-column array entries for each valid
1534  * attribute of a relation. The per-column array is indexed starting at
1535  * FirstLowInvalidHeapAttributeNumber, up to relation's last attribute.
1536  */
1537 static void
1539  AclMode this_privileges,
1540  AclMode *col_privileges,
1541  int num_col_privileges)
1542 {
1543  AttrNumber curr_att;
1544 
1545  Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
1546  for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
1547  curr_att <= classForm->relnatts;
1548  curr_att++)
1549  {
1550  HeapTuple attTuple;
1551  bool isdropped;
1552 
1553  if (curr_att == InvalidAttrNumber)
1554  continue;
1555 
1556  /* Skip OID column if it doesn't exist */
1557  if (curr_att == ObjectIdAttributeNumber && !classForm->relhasoids)
1558  continue;
1559 
1560  /* Views don't have any system columns at all */
1561  if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
1562  continue;
1563 
1564  attTuple = SearchSysCache2(ATTNUM,
1565  ObjectIdGetDatum(table_oid),
1566  Int16GetDatum(curr_att));
1567  if (!HeapTupleIsValid(attTuple))
1568  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1569  curr_att, table_oid);
1570 
1571  isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
1572 
1573  ReleaseSysCache(attTuple);
1574 
1575  /* ignore dropped columns */
1576  if (isdropped)
1577  continue;
1578 
1579  col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
1580  }
1581 }
1582 
1583 /*
1584  * This processes attributes, but expects to be called from
1585  * ExecGrant_Relation, not directly from ExecGrantStmt.
1586  */
1587 static void
1588 ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
1589  AttrNumber attnum, Oid ownerId, AclMode col_privileges,
1590  Relation attRelation, const Acl *old_rel_acl)
1591 {
1592  HeapTuple attr_tuple;
1593  Form_pg_attribute pg_attribute_tuple;
1594  Acl *old_acl;
1595  Acl *new_acl;
1596  Acl *merged_acl;
1597  Datum aclDatum;
1598  bool isNull;
1599  Oid grantorId;
1600  AclMode avail_goptions;
1601  bool need_update;
1602  HeapTuple newtuple;
1604  bool nulls[Natts_pg_attribute];
1605  bool replaces[Natts_pg_attribute];
1606  int noldmembers;
1607  int nnewmembers;
1608  Oid *oldmembers;
1609  Oid *newmembers;
1610 
1611  attr_tuple = SearchSysCache2(ATTNUM,
1612  ObjectIdGetDatum(relOid),
1613  Int16GetDatum(attnum));
1614  if (!HeapTupleIsValid(attr_tuple))
1615  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1616  attnum, relOid);
1617  pg_attribute_tuple = (Form_pg_attribute) GETSTRUCT(attr_tuple);
1618 
1619  /*
1620  * Get working copy of existing ACL. If there's no ACL, substitute the
1621  * proper default.
1622  */
1623  aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
1624  &isNull);
1625  if (isNull)
1626  {
1627  old_acl = acldefault(ACL_OBJECT_COLUMN, ownerId);
1628  /* There are no old member roles according to the catalogs */
1629  noldmembers = 0;
1630  oldmembers = NULL;
1631  }
1632  else
1633  {
1634  old_acl = DatumGetAclPCopy(aclDatum);
1635  /* Get the roles mentioned in the existing ACL */
1636  noldmembers = aclmembers(old_acl, &oldmembers);
1637  }
1638 
1639  /*
1640  * In select_best_grantor we should consider existing table-level ACL bits
1641  * as well as the per-column ACL. Build a new ACL that is their
1642  * concatenation. (This is a bit cheap and dirty compared to merging them
1643  * properly with no duplications, but it's all we need here.)
1644  */
1645  merged_acl = aclconcat(old_rel_acl, old_acl);
1646 
1647  /* Determine ID to do the grant as, and available grant options */
1648  select_best_grantor(GetUserId(), col_privileges,
1649  merged_acl, ownerId,
1650  &grantorId, &avail_goptions);
1651 
1652  pfree(merged_acl);
1653 
1654  /*
1655  * Restrict the privileges to what we can actually grant, and emit the
1656  * standards-mandated warning and error messages. Note: we don't track
1657  * whether the user actually used the ALL PRIVILEGES(columns) syntax for
1658  * each column; we just approximate it by whether all the possible
1659  * privileges are specified now. Since the all_privs flag only determines
1660  * whether a warning is issued, this seems close enough.
1661  */
1662  col_privileges =
1663  restrict_and_check_grant(istmt->is_grant, avail_goptions,
1664  (col_privileges == ACL_ALL_RIGHTS_COLUMN),
1665  col_privileges,
1666  relOid, grantorId, ACL_KIND_COLUMN,
1667  relname, attnum,
1668  NameStr(pg_attribute_tuple->attname));
1669 
1670  /*
1671  * Generate new ACL.
1672  */
1673  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
1674  istmt->grant_option,
1675  istmt->behavior, istmt->grantees,
1676  col_privileges, grantorId,
1677  ownerId);
1678 
1679  /*
1680  * We need the members of both old and new ACLs so we can correct the
1681  * shared dependency information.
1682  */
1683  nnewmembers = aclmembers(new_acl, &newmembers);
1684 
1685  /* finished building new ACL value, now insert it */
1686  MemSet(values, 0, sizeof(values));
1687  MemSet(nulls, false, sizeof(nulls));
1688  MemSet(replaces, false, sizeof(replaces));
1689 
1690  /*
1691  * If the updated ACL is empty, we can set attacl to null, and maybe even
1692  * avoid an update of the pg_attribute row. This is worth testing because
1693  * we'll come through here multiple times for any relation-level REVOKE,
1694  * even if there were never any column GRANTs. Note we are assuming that
1695  * the "default" ACL state for columns is empty.
1696  */
1697  if (ACL_NUM(new_acl) > 0)
1698  {
1699  values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl);
1700  need_update = true;
1701  }
1702  else
1703  {
1704  nulls[Anum_pg_attribute_attacl - 1] = true;
1705  need_update = !isNull;
1706  }
1707  replaces[Anum_pg_attribute_attacl - 1] = true;
1708 
1709  if (need_update)
1710  {
1711  newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
1712  values, nulls, replaces);
1713 
1714  CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
1715 
1716  /* Update initial privileges for extensions */
1718  ACL_NUM(new_acl) > 0 ? new_acl : NULL);
1719 
1720  /* Update the shared dependency ACL info */
1721  updateAclDependencies(RelationRelationId, relOid, attnum,
1722  ownerId,
1723  noldmembers, oldmembers,
1724  nnewmembers, newmembers);
1725  }
1726 
1727  pfree(new_acl);
1728 
1729  ReleaseSysCache(attr_tuple);
1730 }
1731 
1732 /*
1733  * This processes both sequences and non-sequences.
1734  */
1735 static void
1737 {
1738  Relation relation;
1739  Relation attRelation;
1740  ListCell *cell;
1741 
1744 
1745  foreach(cell, istmt->objects)
1746  {
1747  Oid relOid = lfirst_oid(cell);
1748  Datum aclDatum;
1749  Form_pg_class pg_class_tuple;
1750  bool isNull;
1751  AclMode this_privileges;
1752  AclMode *col_privileges;
1753  int num_col_privileges;
1754  bool have_col_privileges;
1755  Acl *old_acl;
1756  Acl *old_rel_acl;
1757  int noldmembers;
1758  Oid *oldmembers;
1759  Oid ownerId;
1760  HeapTuple tuple;
1761  ListCell *cell_colprivs;
1762 
1763  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
1764  if (!HeapTupleIsValid(tuple))
1765  elog(ERROR, "cache lookup failed for relation %u", relOid);
1766  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
1767 
1768  /* Not sensible to grant on an index */
1769  if (pg_class_tuple->relkind == RELKIND_INDEX)
1770  ereport(ERROR,
1771  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1772  errmsg("\"%s\" is an index",
1773  NameStr(pg_class_tuple->relname))));
1774 
1775  /* Composite types aren't tables either */
1776  if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
1777  ereport(ERROR,
1778  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1779  errmsg("\"%s\" is a composite type",
1780  NameStr(pg_class_tuple->relname))));
1781 
1782  /* Used GRANT SEQUENCE on a non-sequence? */
1783  if (istmt->objtype == ACL_OBJECT_SEQUENCE &&
1784  pg_class_tuple->relkind != RELKIND_SEQUENCE)
1785  ereport(ERROR,
1786  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1787  errmsg("\"%s\" is not a sequence",
1788  NameStr(pg_class_tuple->relname))));
1789 
1790  /* Adjust the default permissions based on object type */
1791  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
1792  {
1793  if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
1794  this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1795  else
1796  this_privileges = ACL_ALL_RIGHTS_RELATION;
1797  }
1798  else
1799  this_privileges = istmt->privileges;
1800 
1801  /*
1802  * The GRANT TABLE syntax can be used for sequences and non-sequences,
1803  * so we have to look at the relkind to determine the supported
1804  * permissions. The OR of table and sequence permissions were already
1805  * checked.
1806  */
1807  if (istmt->objtype == ACL_OBJECT_RELATION)
1808  {
1809  if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
1810  {
1811  /*
1812  * For backward compatibility, just throw a warning for
1813  * invalid sequence permissions when using the non-sequence
1814  * GRANT syntax.
1815  */
1816  if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
1817  {
1818  /*
1819  * Mention the object name because the user needs to know
1820  * which operations succeeded. This is required because
1821  * WARNING allows the command to continue.
1822  */
1823  ereport(WARNING,
1824  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1825  errmsg("sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges",
1826  NameStr(pg_class_tuple->relname))));
1827  this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
1828  }
1829  }
1830  else
1831  {
1832  if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
1833  {
1834  /*
1835  * USAGE is the only permission supported by sequences but
1836  * not by non-sequences. Don't mention the object name
1837  * because we didn't in the combined TABLE | SEQUENCE
1838  * check.
1839  */
1840  ereport(ERROR,
1841  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1842  errmsg("invalid privilege type %s for table",
1843  "USAGE")));
1844  }
1845  }
1846  }
1847 
1848  /*
1849  * Set up array in which we'll accumulate any column privilege bits
1850  * that need modification. The array is indexed such that entry [0]
1851  * corresponds to FirstLowInvalidHeapAttributeNumber.
1852  */
1853  num_col_privileges = pg_class_tuple->relnatts - FirstLowInvalidHeapAttributeNumber + 1;
1854  col_privileges = (AclMode *) palloc0(num_col_privileges * sizeof(AclMode));
1855  have_col_privileges = false;
1856 
1857  /*
1858  * If we are revoking relation privileges that are also column
1859  * privileges, we must implicitly revoke them from each column too,
1860  * per SQL spec. (We don't need to implicitly add column privileges
1861  * during GRANT because the permissions-checking code always checks
1862  * both relation and per-column privileges.)
1863  */
1864  if (!istmt->is_grant &&
1865  (this_privileges & ACL_ALL_RIGHTS_COLUMN) != 0)
1866  {
1867  expand_all_col_privileges(relOid, pg_class_tuple,
1868  this_privileges & ACL_ALL_RIGHTS_COLUMN,
1869  col_privileges,
1870  num_col_privileges);
1871  have_col_privileges = true;
1872  }
1873 
1874  /*
1875  * Get owner ID and working copy of existing ACL. If there's no ACL,
1876  * substitute the proper default.
1877  */
1878  ownerId = pg_class_tuple->relowner;
1879  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
1880  &isNull);
1881  if (isNull)
1882  {
1883  switch (pg_class_tuple->relkind)
1884  {
1885  case RELKIND_SEQUENCE:
1886  old_acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
1887  break;
1888  default:
1889  old_acl = acldefault(ACL_OBJECT_RELATION, ownerId);
1890  break;
1891  }
1892  /* There are no old member roles according to the catalogs */
1893  noldmembers = 0;
1894  oldmembers = NULL;
1895  }
1896  else
1897  {
1898  old_acl = DatumGetAclPCopy(aclDatum);
1899  /* Get the roles mentioned in the existing ACL */
1900  noldmembers = aclmembers(old_acl, &oldmembers);
1901  }
1902 
1903  /* Need an extra copy of original rel ACL for column handling */
1904  old_rel_acl = aclcopy(old_acl);
1905 
1906  /*
1907  * Handle relation-level privileges, if any were specified
1908  */
1909  if (this_privileges != ACL_NO_RIGHTS)
1910  {
1911  AclMode avail_goptions;
1912  Acl *new_acl;
1913  Oid grantorId;
1914  HeapTuple newtuple;
1916  bool nulls[Natts_pg_class];
1917  bool replaces[Natts_pg_class];
1918  int nnewmembers;
1919  Oid *newmembers;
1920  AclObjectKind aclkind;
1921 
1922  /* Determine ID to do the grant as, and available grant options */
1923  select_best_grantor(GetUserId(), this_privileges,
1924  old_acl, ownerId,
1925  &grantorId, &avail_goptions);
1926 
1927  switch (pg_class_tuple->relkind)
1928  {
1929  case RELKIND_SEQUENCE:
1930  aclkind = ACL_KIND_SEQUENCE;
1931  break;
1932  default:
1933  aclkind = ACL_KIND_CLASS;
1934  break;
1935  }
1936 
1937  /*
1938  * Restrict the privileges to what we can actually grant, and emit
1939  * the standards-mandated warning and error messages.
1940  */
1941  this_privileges =
1942  restrict_and_check_grant(istmt->is_grant, avail_goptions,
1943  istmt->all_privs, this_privileges,
1944  relOid, grantorId, aclkind,
1945  NameStr(pg_class_tuple->relname),
1946  0, NULL);
1947 
1948  /*
1949  * Generate new ACL.
1950  */
1951  new_acl = merge_acl_with_grant(old_acl,
1952  istmt->is_grant,
1953  istmt->grant_option,
1954  istmt->behavior,
1955  istmt->grantees,
1956  this_privileges,
1957  grantorId,
1958  ownerId);
1959 
1960  /*
1961  * We need the members of both old and new ACLs so we can correct
1962  * the shared dependency information.
1963  */
1964  nnewmembers = aclmembers(new_acl, &newmembers);
1965 
1966  /* finished building new ACL value, now insert it */
1967  MemSet(values, 0, sizeof(values));
1968  MemSet(nulls, false, sizeof(nulls));
1969  MemSet(replaces, false, sizeof(replaces));
1970 
1971  replaces[Anum_pg_class_relacl - 1] = true;
1972  values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
1973 
1974  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
1975  values, nulls, replaces);
1976 
1977  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1978 
1979  /* Update initial privileges for extensions */
1980  recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl);
1981 
1982  /* Update the shared dependency ACL info */
1984  ownerId,
1985  noldmembers, oldmembers,
1986  nnewmembers, newmembers);
1987 
1988  pfree(new_acl);
1989  }
1990 
1991  /*
1992  * Handle column-level privileges, if any were specified or implied.
1993  * We first expand the user-specified column privileges into the
1994  * array, and then iterate over all nonempty array entries.
1995  */
1996  foreach(cell_colprivs, istmt->col_privs)
1997  {
1998  AccessPriv *col_privs = (AccessPriv *) lfirst(cell_colprivs);
1999 
2000  if (col_privs->priv_name == NULL)
2001  this_privileges = ACL_ALL_RIGHTS_COLUMN;
2002  else
2003  this_privileges = string_to_privilege(col_privs->priv_name);
2004 
2005  if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
2006  ereport(ERROR,
2007  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
2008  errmsg("invalid privilege type %s for column",
2009  privilege_to_string(this_privileges))));
2010 
2011  if (pg_class_tuple->relkind == RELKIND_SEQUENCE &&
2012  this_privileges & ~((AclMode) ACL_SELECT))
2013  {
2014  /*
2015  * The only column privilege allowed on sequences is SELECT.
2016  * This is a warning not error because we do it that way for
2017  * relation-level privileges.
2018  */
2019  ereport(WARNING,
2020  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
2021  errmsg("sequence \"%s\" only supports SELECT column privileges",
2022  NameStr(pg_class_tuple->relname))));
2023 
2024  this_privileges &= (AclMode) ACL_SELECT;
2025  }
2026 
2027  expand_col_privileges(col_privs->cols, relOid,
2028  this_privileges,
2029  col_privileges,
2030  num_col_privileges);
2031  have_col_privileges = true;
2032  }
2033 
2034  if (have_col_privileges)
2035  {
2036  AttrNumber i;
2037 
2038  for (i = 0; i < num_col_privileges; i++)
2039  {
2040  if (col_privileges[i] == ACL_NO_RIGHTS)
2041  continue;
2042  ExecGrant_Attribute(istmt,
2043  relOid,
2044  NameStr(pg_class_tuple->relname),
2046  ownerId,
2047  col_privileges[i],
2048  attRelation,
2049  old_rel_acl);
2050  }
2051  }
2052 
2053  pfree(old_rel_acl);
2054  pfree(col_privileges);
2055 
2056  ReleaseSysCache(tuple);
2057 
2058  /* prevent error when processing duplicate objects */
2060  }
2061 
2062  heap_close(attRelation, RowExclusiveLock);
2063  heap_close(relation, RowExclusiveLock);
2064 }
2065 
2066 static void
2068 {
2069  Relation relation;
2070  ListCell *cell;
2071 
2072  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2074 
2076 
2077  foreach(cell, istmt->objects)
2078  {
2079  Oid datId = lfirst_oid(cell);
2080  Form_pg_database pg_database_tuple;
2081  Datum aclDatum;
2082  bool isNull;
2083  AclMode avail_goptions;
2084  AclMode this_privileges;
2085  Acl *old_acl;
2086  Acl *new_acl;
2087  Oid grantorId;
2088  Oid ownerId;
2089  HeapTuple newtuple;
2091  bool nulls[Natts_pg_database];
2092  bool replaces[Natts_pg_database];
2093  int noldmembers;
2094  int nnewmembers;
2095  Oid *oldmembers;
2096  Oid *newmembers;
2097  HeapTuple tuple;
2098 
2099  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(datId));
2100  if (!HeapTupleIsValid(tuple))
2101  elog(ERROR, "cache lookup failed for database %u", datId);
2102 
2103  pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
2104 
2105  /*
2106  * Get owner ID and working copy of existing ACL. If there's no ACL,
2107  * substitute the proper default.
2108  */
2109  ownerId = pg_database_tuple->datdba;
2110  aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
2111  RelationGetDescr(relation), &isNull);
2112  if (isNull)
2113  {
2114  old_acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
2115  /* There are no old member roles according to the catalogs */
2116  noldmembers = 0;
2117  oldmembers = NULL;
2118  }
2119  else
2120  {
2121  old_acl = DatumGetAclPCopy(aclDatum);
2122  /* Get the roles mentioned in the existing ACL */
2123  noldmembers = aclmembers(old_acl, &oldmembers);
2124  }
2125 
2126  /* Determine ID to do the grant as, and available grant options */
2128  old_acl, ownerId,
2129  &grantorId, &avail_goptions);
2130 
2131  /*
2132  * Restrict the privileges to what we can actually grant, and emit the
2133  * standards-mandated warning and error messages.
2134  */
2135  this_privileges =
2136  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2137  istmt->all_privs, istmt->privileges,
2138  datId, grantorId, ACL_KIND_DATABASE,
2139  NameStr(pg_database_tuple->datname),
2140  0, NULL);
2141 
2142  /*
2143  * Generate new ACL.
2144  */
2145  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2146  istmt->grant_option, istmt->behavior,
2147  istmt->grantees, this_privileges,
2148  grantorId, ownerId);
2149 
2150  /*
2151  * We need the members of both old and new ACLs so we can correct the
2152  * shared dependency information.
2153  */
2154  nnewmembers = aclmembers(new_acl, &newmembers);
2155 
2156  /* finished building new ACL value, now insert it */
2157  MemSet(values, 0, sizeof(values));
2158  MemSet(nulls, false, sizeof(nulls));
2159  MemSet(replaces, false, sizeof(replaces));
2160 
2161  replaces[Anum_pg_database_datacl - 1] = true;
2162  values[Anum_pg_database_datacl - 1] = PointerGetDatum(new_acl);
2163 
2164  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2165  nulls, replaces);
2166 
2167  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2168 
2169  /* Update the shared dependency ACL info */
2171  ownerId,
2172  noldmembers, oldmembers,
2173  nnewmembers, newmembers);
2174 
2175  ReleaseSysCache(tuple);
2176 
2177  pfree(new_acl);
2178 
2179  /* prevent error when processing duplicate objects */
2181  }
2182 
2183  heap_close(relation, RowExclusiveLock);
2184 }
2185 
2186 static void
2188 {
2189  Relation relation;
2190  ListCell *cell;
2191 
2192  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2193  istmt->privileges = ACL_ALL_RIGHTS_FDW;
2194 
2196 
2197  foreach(cell, istmt->objects)
2198  {
2199  Oid fdwid = lfirst_oid(cell);
2200  Form_pg_foreign_data_wrapper pg_fdw_tuple;
2201  Datum aclDatum;
2202  bool isNull;
2203  AclMode avail_goptions;
2204  AclMode this_privileges;
2205  Acl *old_acl;
2206  Acl *new_acl;
2207  Oid grantorId;
2208  Oid ownerId;
2209  HeapTuple tuple;
2210  HeapTuple newtuple;
2212  bool nulls[Natts_pg_foreign_data_wrapper];
2213  bool replaces[Natts_pg_foreign_data_wrapper];
2214  int noldmembers;
2215  int nnewmembers;
2216  Oid *oldmembers;
2217  Oid *newmembers;
2218 
2220  ObjectIdGetDatum(fdwid));
2221  if (!HeapTupleIsValid(tuple))
2222  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
2223 
2224  pg_fdw_tuple = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
2225 
2226  /*
2227  * Get owner ID and working copy of existing ACL. If there's no ACL,
2228  * substitute the proper default.
2229  */
2230  ownerId = pg_fdw_tuple->fdwowner;
2231  aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
2233  &isNull);
2234  if (isNull)
2235  {
2236  old_acl = acldefault(ACL_OBJECT_FDW, ownerId);
2237  /* There are no old member roles according to the catalogs */
2238  noldmembers = 0;
2239  oldmembers = NULL;
2240  }
2241  else
2242  {
2243  old_acl = DatumGetAclPCopy(aclDatum);
2244  /* Get the roles mentioned in the existing ACL */
2245  noldmembers = aclmembers(old_acl, &oldmembers);
2246  }
2247 
2248  /* Determine ID to do the grant as, and available grant options */
2250  old_acl, ownerId,
2251  &grantorId, &avail_goptions);
2252 
2253  /*
2254  * Restrict the privileges to what we can actually grant, and emit the
2255  * standards-mandated warning and error messages.
2256  */
2257  this_privileges =
2258  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2259  istmt->all_privs, istmt->privileges,
2260  fdwid, grantorId, ACL_KIND_FDW,
2261  NameStr(pg_fdw_tuple->fdwname),
2262  0, NULL);
2263 
2264  /*
2265  * Generate new ACL.
2266  */
2267  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2268  istmt->grant_option, istmt->behavior,
2269  istmt->grantees, this_privileges,
2270  grantorId, ownerId);
2271 
2272  /*
2273  * We need the members of both old and new ACLs so we can correct the
2274  * shared dependency information.
2275  */
2276  nnewmembers = aclmembers(new_acl, &newmembers);
2277 
2278  /* finished building new ACL value, now insert it */
2279  MemSet(values, 0, sizeof(values));
2280  MemSet(nulls, false, sizeof(nulls));
2281  MemSet(replaces, false, sizeof(replaces));
2282 
2283  replaces[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
2285 
2286  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2287  nulls, replaces);
2288 
2289  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2290 
2291  /* Update initial privileges for extensions */
2293  new_acl);
2294 
2295  /* Update the shared dependency ACL info */
2297  HeapTupleGetOid(tuple), 0,
2298  ownerId,
2299  noldmembers, oldmembers,
2300  nnewmembers, newmembers);
2301 
2302  ReleaseSysCache(tuple);
2303 
2304  pfree(new_acl);
2305 
2306  /* prevent error when processing duplicate objects */
2308  }
2309 
2310  heap_close(relation, RowExclusiveLock);
2311 }
2312 
2313 static void
2315 {
2316  Relation relation;
2317  ListCell *cell;
2318 
2319  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2321 
2323 
2324  foreach(cell, istmt->objects)
2325  {
2326  Oid srvid = lfirst_oid(cell);
2327  Form_pg_foreign_server pg_server_tuple;
2328  Datum aclDatum;
2329  bool isNull;
2330  AclMode avail_goptions;
2331  AclMode this_privileges;
2332  Acl *old_acl;
2333  Acl *new_acl;
2334  Oid grantorId;
2335  Oid ownerId;
2336  HeapTuple tuple;
2337  HeapTuple newtuple;
2339  bool nulls[Natts_pg_foreign_server];
2340  bool replaces[Natts_pg_foreign_server];
2341  int noldmembers;
2342  int nnewmembers;
2343  Oid *oldmembers;
2344  Oid *newmembers;
2345 
2347  if (!HeapTupleIsValid(tuple))
2348  elog(ERROR, "cache lookup failed for foreign server %u", srvid);
2349 
2350  pg_server_tuple = (Form_pg_foreign_server) GETSTRUCT(tuple);
2351 
2352  /*
2353  * Get owner ID and working copy of existing ACL. If there's no ACL,
2354  * substitute the proper default.
2355  */
2356  ownerId = pg_server_tuple->srvowner;
2357  aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
2359  &isNull);
2360  if (isNull)
2361  {
2362  old_acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
2363  /* There are no old member roles according to the catalogs */
2364  noldmembers = 0;
2365  oldmembers = NULL;
2366  }
2367  else
2368  {
2369  old_acl = DatumGetAclPCopy(aclDatum);
2370  /* Get the roles mentioned in the existing ACL */
2371  noldmembers = aclmembers(old_acl, &oldmembers);
2372  }
2373 
2374  /* Determine ID to do the grant as, and available grant options */
2376  old_acl, ownerId,
2377  &grantorId, &avail_goptions);
2378 
2379  /*
2380  * Restrict the privileges to what we can actually grant, and emit the
2381  * standards-mandated warning and error messages.
2382  */
2383  this_privileges =
2384  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2385  istmt->all_privs, istmt->privileges,
2386  srvid, grantorId, ACL_KIND_FOREIGN_SERVER,
2387  NameStr(pg_server_tuple->srvname),
2388  0, NULL);
2389 
2390  /*
2391  * Generate new ACL.
2392  */
2393  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2394  istmt->grant_option, istmt->behavior,
2395  istmt->grantees, this_privileges,
2396  grantorId, ownerId);
2397 
2398  /*
2399  * We need the members of both old and new ACLs so we can correct the
2400  * shared dependency information.
2401  */
2402  nnewmembers = aclmembers(new_acl, &newmembers);
2403 
2404  /* finished building new ACL value, now insert it */
2405  MemSet(values, 0, sizeof(values));
2406  MemSet(nulls, false, sizeof(nulls));
2407  MemSet(replaces, false, sizeof(replaces));
2408 
2409  replaces[Anum_pg_foreign_server_srvacl - 1] = true;
2410  values[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(new_acl);
2411 
2412  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2413  nulls, replaces);
2414 
2415  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2416 
2417  /* Update initial privileges for extensions */
2419 
2420  /* Update the shared dependency ACL info */
2422  HeapTupleGetOid(tuple), 0,
2423  ownerId,
2424  noldmembers, oldmembers,
2425  nnewmembers, newmembers);
2426 
2427  ReleaseSysCache(tuple);
2428 
2429  pfree(new_acl);
2430 
2431  /* prevent error when processing duplicate objects */
2433  }
2434 
2435  heap_close(relation, RowExclusiveLock);
2436 }
2437 
2438 static void
2440 {
2441  Relation relation;
2442  ListCell *cell;
2443 
2444  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2446 
2448 
2449  foreach(cell, istmt->objects)
2450  {
2451  Oid funcId = lfirst_oid(cell);
2452  Form_pg_proc pg_proc_tuple;
2453  Datum aclDatum;
2454  bool isNull;
2455  AclMode avail_goptions;
2456  AclMode this_privileges;
2457  Acl *old_acl;
2458  Acl *new_acl;
2459  Oid grantorId;
2460  Oid ownerId;
2461  HeapTuple tuple;
2462  HeapTuple newtuple;
2464  bool nulls[Natts_pg_proc];
2465  bool replaces[Natts_pg_proc];
2466  int noldmembers;
2467  int nnewmembers;
2468  Oid *oldmembers;
2469  Oid *newmembers;
2470 
2471  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
2472  if (!HeapTupleIsValid(tuple))
2473  elog(ERROR, "cache lookup failed for function %u", funcId);
2474 
2475  pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
2476 
2477  /*
2478  * Get owner ID and working copy of existing ACL. If there's no ACL,
2479  * substitute the proper default.
2480  */
2481  ownerId = pg_proc_tuple->proowner;
2482  aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
2483  &isNull);
2484  if (isNull)
2485  {
2486  old_acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
2487  /* There are no old member roles according to the catalogs */
2488  noldmembers = 0;
2489  oldmembers = NULL;
2490  }
2491  else
2492  {
2493  old_acl = DatumGetAclPCopy(aclDatum);
2494  /* Get the roles mentioned in the existing ACL */
2495  noldmembers = aclmembers(old_acl, &oldmembers);
2496  }
2497 
2498  /* Determine ID to do the grant as, and available grant options */
2500  old_acl, ownerId,
2501  &grantorId, &avail_goptions);
2502 
2503  /*
2504  * Restrict the privileges to what we can actually grant, and emit the
2505  * standards-mandated warning and error messages.
2506  */
2507  this_privileges =
2508  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2509  istmt->all_privs, istmt->privileges,
2510  funcId, grantorId, ACL_KIND_PROC,
2511  NameStr(pg_proc_tuple->proname),
2512  0, NULL);
2513 
2514  /*
2515  * Generate new ACL.
2516  */
2517  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2518  istmt->grant_option, istmt->behavior,
2519  istmt->grantees, this_privileges,
2520  grantorId, ownerId);
2521 
2522  /*
2523  * We need the members of both old and new ACLs so we can correct the
2524  * shared dependency information.
2525  */
2526  nnewmembers = aclmembers(new_acl, &newmembers);
2527 
2528  /* finished building new ACL value, now insert it */
2529  MemSet(values, 0, sizeof(values));
2530  MemSet(nulls, false, sizeof(nulls));
2531  MemSet(replaces, false, sizeof(replaces));
2532 
2533  replaces[Anum_pg_proc_proacl - 1] = true;
2534  values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
2535 
2536  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2537  nulls, replaces);
2538 
2539  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2540 
2541  /* Update initial privileges for extensions */
2542  recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
2543 
2544  /* Update the shared dependency ACL info */
2546  ownerId,
2547  noldmembers, oldmembers,
2548  nnewmembers, newmembers);
2549 
2550  ReleaseSysCache(tuple);
2551 
2552  pfree(new_acl);
2553 
2554  /* prevent error when processing duplicate objects */
2556  }
2557 
2558  heap_close(relation, RowExclusiveLock);
2559 }
2560 
2561 static void
2563 {
2564  Relation relation;
2565  ListCell *cell;
2566 
2567  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2569 
2571 
2572  foreach(cell, istmt->objects)
2573  {
2574  Oid langId = lfirst_oid(cell);
2575  Form_pg_language pg_language_tuple;
2576  Datum aclDatum;
2577  bool isNull;
2578  AclMode avail_goptions;
2579  AclMode this_privileges;
2580  Acl *old_acl;
2581  Acl *new_acl;
2582  Oid grantorId;
2583  Oid ownerId;
2584  HeapTuple tuple;
2585  HeapTuple newtuple;
2587  bool nulls[Natts_pg_language];
2588  bool replaces[Natts_pg_language];
2589  int noldmembers;
2590  int nnewmembers;
2591  Oid *oldmembers;
2592  Oid *newmembers;
2593 
2594  tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(langId));
2595  if (!HeapTupleIsValid(tuple))
2596  elog(ERROR, "cache lookup failed for language %u", langId);
2597 
2598  pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
2599 
2600  if (!pg_language_tuple->lanpltrusted)
2601  ereport(ERROR,
2602  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2603  errmsg("language \"%s\" is not trusted",
2604  NameStr(pg_language_tuple->lanname)),
2605  errdetail("GRANT and REVOKE are not allowed on untrusted languages, "
2606  "because only superusers can use untrusted languages.")));
2607 
2608  /*
2609  * Get owner ID and working copy of existing ACL. If there's no ACL,
2610  * substitute the proper default.
2611  */
2612  ownerId = pg_language_tuple->lanowner;
2614  &isNull);
2615  if (isNull)
2616  {
2617  old_acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
2618  /* There are no old member roles according to the catalogs */
2619  noldmembers = 0;
2620  oldmembers = NULL;
2621  }
2622  else
2623  {
2624  old_acl = DatumGetAclPCopy(aclDatum);
2625  /* Get the roles mentioned in the existing ACL */
2626  noldmembers = aclmembers(old_acl, &oldmembers);
2627  }
2628 
2629  /* Determine ID to do the grant as, and available grant options */
2631  old_acl, ownerId,
2632  &grantorId, &avail_goptions);
2633 
2634  /*
2635  * Restrict the privileges to what we can actually grant, and emit the
2636  * standards-mandated warning and error messages.
2637  */
2638  this_privileges =
2639  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2640  istmt->all_privs, istmt->privileges,
2641  langId, grantorId, ACL_KIND_LANGUAGE,
2642  NameStr(pg_language_tuple->lanname),
2643  0, NULL);
2644 
2645  /*
2646  * Generate new ACL.
2647  */
2648  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2649  istmt->grant_option, istmt->behavior,
2650  istmt->grantees, this_privileges,
2651  grantorId, ownerId);
2652 
2653  /*
2654  * We need the members of both old and new ACLs so we can correct the
2655  * shared dependency information.
2656  */
2657  nnewmembers = aclmembers(new_acl, &newmembers);
2658 
2659  /* finished building new ACL value, now insert it */
2660  MemSet(values, 0, sizeof(values));
2661  MemSet(nulls, false, sizeof(nulls));
2662  MemSet(replaces, false, sizeof(replaces));
2663 
2664  replaces[Anum_pg_language_lanacl - 1] = true;
2665  values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
2666 
2667  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2668  nulls, replaces);
2669 
2670  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2671 
2672  /* Update initial privileges for extensions */
2673  recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
2674 
2675  /* Update the shared dependency ACL info */
2677  ownerId,
2678  noldmembers, oldmembers,
2679  nnewmembers, newmembers);
2680 
2681  ReleaseSysCache(tuple);
2682 
2683  pfree(new_acl);
2684 
2685  /* prevent error when processing duplicate objects */
2687  }
2688 
2689  heap_close(relation, RowExclusiveLock);
2690 }
2691 
2692 static void
2694 {
2695  Relation relation;
2696  ListCell *cell;
2697 
2698  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2700 
2703 
2704  foreach(cell, istmt->objects)
2705  {
2706  Oid loid = lfirst_oid(cell);
2707  Form_pg_largeobject_metadata form_lo_meta;
2708  char loname[NAMEDATALEN];
2709  Datum aclDatum;
2710  bool isNull;
2711  AclMode avail_goptions;
2712  AclMode this_privileges;
2713  Acl *old_acl;
2714  Acl *new_acl;
2715  Oid grantorId;
2716  Oid ownerId;
2717  HeapTuple newtuple;
2719  bool nulls[Natts_pg_largeobject_metadata];
2720  bool replaces[Natts_pg_largeobject_metadata];
2721  int noldmembers;
2722  int nnewmembers;
2723  Oid *oldmembers;
2724  Oid *newmembers;
2725  ScanKeyData entry[1];
2726  SysScanDesc scan;
2727  HeapTuple tuple;
2728 
2729  /* There's no syscache for pg_largeobject_metadata */
2730  ScanKeyInit(&entry[0],
2732  BTEqualStrategyNumber, F_OIDEQ,
2733  ObjectIdGetDatum(loid));
2734 
2735  scan = systable_beginscan(relation,
2737  NULL, 1, entry);
2738 
2739  tuple = systable_getnext(scan);
2740  if (!HeapTupleIsValid(tuple))
2741  elog(ERROR, "could not find tuple for large object %u", loid);
2742 
2743  form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
2744 
2745  /*
2746  * Get owner ID and working copy of existing ACL. If there's no ACL,
2747  * substitute the proper default.
2748  */
2749  ownerId = form_lo_meta->lomowner;
2750  aclDatum = heap_getattr(tuple,
2752  RelationGetDescr(relation), &isNull);
2753  if (isNull)
2754  {
2755  old_acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
2756  /* There are no old member roles according to the catalogs */
2757  noldmembers = 0;
2758  oldmembers = NULL;
2759  }
2760  else
2761  {
2762  old_acl = DatumGetAclPCopy(aclDatum);
2763  /* Get the roles mentioned in the existing ACL */
2764  noldmembers = aclmembers(old_acl, &oldmembers);
2765  }
2766 
2767  /* Determine ID to do the grant as, and available grant options */
2769  old_acl, ownerId,
2770  &grantorId, &avail_goptions);
2771 
2772  /*
2773  * Restrict the privileges to what we can actually grant, and emit the
2774  * standards-mandated warning and error messages.
2775  */
2776  snprintf(loname, sizeof(loname), "large object %u", loid);
2777  this_privileges =
2778  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2779  istmt->all_privs, istmt->privileges,
2780  loid, grantorId, ACL_KIND_LARGEOBJECT,
2781  loname, 0, NULL);
2782 
2783  /*
2784  * Generate new ACL.
2785  */
2786  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2787  istmt->grant_option, istmt->behavior,
2788  istmt->grantees, this_privileges,
2789  grantorId, ownerId);
2790 
2791  /*
2792  * We need the members of both old and new ACLs so we can correct the
2793  * shared dependency information.
2794  */
2795  nnewmembers = aclmembers(new_acl, &newmembers);
2796 
2797  /* finished building new ACL value, now insert it */
2798  MemSet(values, 0, sizeof(values));
2799  MemSet(nulls, false, sizeof(nulls));
2800  MemSet(replaces, false, sizeof(replaces));
2801 
2802  replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
2804  = PointerGetDatum(new_acl);
2805 
2806  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2807  values, nulls, replaces);
2808 
2809  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2810 
2811  /* Update initial privileges for extensions */
2813 
2814  /* Update the shared dependency ACL info */
2816  HeapTupleGetOid(tuple), 0,
2817  ownerId,
2818  noldmembers, oldmembers,
2819  nnewmembers, newmembers);
2820 
2821  systable_endscan(scan);
2822 
2823  pfree(new_acl);
2824 
2825  /* prevent error when processing duplicate objects */
2827  }
2828 
2829  heap_close(relation, RowExclusiveLock);
2830 }
2831 
2832 static void
2834 {
2835  Relation relation;
2836  ListCell *cell;
2837 
2838  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2840 
2842 
2843  foreach(cell, istmt->objects)
2844  {
2845  Oid nspid = lfirst_oid(cell);
2846  Form_pg_namespace pg_namespace_tuple;
2847  Datum aclDatum;
2848  bool isNull;
2849  AclMode avail_goptions;
2850  AclMode this_privileges;
2851  Acl *old_acl;
2852  Acl *new_acl;
2853  Oid grantorId;
2854  Oid ownerId;
2855  HeapTuple tuple;
2856  HeapTuple newtuple;
2858  bool nulls[Natts_pg_namespace];
2859  bool replaces[Natts_pg_namespace];
2860  int noldmembers;
2861  int nnewmembers;
2862  Oid *oldmembers;
2863  Oid *newmembers;
2864 
2866  if (!HeapTupleIsValid(tuple))
2867  elog(ERROR, "cache lookup failed for namespace %u", nspid);
2868 
2869  pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
2870 
2871  /*
2872  * Get owner ID and working copy of existing ACL. If there's no ACL,
2873  * substitute the proper default.
2874  */
2875  ownerId = pg_namespace_tuple->nspowner;
2876  aclDatum = SysCacheGetAttr(NAMESPACENAME, tuple,
2878  &isNull);
2879  if (isNull)
2880  {
2881  old_acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
2882  /* There are no old member roles according to the catalogs */
2883  noldmembers = 0;
2884  oldmembers = NULL;
2885  }
2886  else
2887  {
2888  old_acl = DatumGetAclPCopy(aclDatum);
2889  /* Get the roles mentioned in the existing ACL */
2890  noldmembers = aclmembers(old_acl, &oldmembers);
2891  }
2892 
2893  /* Determine ID to do the grant as, and available grant options */
2895  old_acl, ownerId,
2896  &grantorId, &avail_goptions);
2897 
2898  /*
2899  * Restrict the privileges to what we can actually grant, and emit the
2900  * standards-mandated warning and error messages.
2901  */
2902  this_privileges =
2903  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2904  istmt->all_privs, istmt->privileges,
2905  nspid, grantorId, ACL_KIND_NAMESPACE,
2906  NameStr(pg_namespace_tuple->nspname),
2907  0, NULL);
2908 
2909  /*
2910  * Generate new ACL.
2911  */
2912  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2913  istmt->grant_option, istmt->behavior,
2914  istmt->grantees, this_privileges,
2915  grantorId, ownerId);
2916 
2917  /*
2918  * We need the members of both old and new ACLs so we can correct the
2919  * shared dependency information.
2920  */
2921  nnewmembers = aclmembers(new_acl, &newmembers);
2922 
2923  /* finished building new ACL value, now insert it */
2924  MemSet(values, 0, sizeof(values));
2925  MemSet(nulls, false, sizeof(nulls));
2926  MemSet(replaces, false, sizeof(replaces));
2927 
2928  replaces[Anum_pg_namespace_nspacl - 1] = true;
2929  values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(new_acl);
2930 
2931  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2932  nulls, replaces);
2933 
2934  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2935 
2936  /* Update initial privileges for extensions */
2937  recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
2938 
2939  /* Update the shared dependency ACL info */
2941  ownerId,
2942  noldmembers, oldmembers,
2943  nnewmembers, newmembers);
2944 
2945  ReleaseSysCache(tuple);
2946 
2947  pfree(new_acl);
2948 
2949  /* prevent error when processing duplicate objects */
2951  }
2952 
2953  heap_close(relation, RowExclusiveLock);
2954 }
2955 
2956 static void
2958 {
2959  Relation relation;
2960  ListCell *cell;
2961 
2962  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2964 
2966 
2967  foreach(cell, istmt->objects)
2968  {
2969  Oid tblId = lfirst_oid(cell);
2970  Form_pg_tablespace pg_tablespace_tuple;
2971  Datum aclDatum;
2972  bool isNull;
2973  AclMode avail_goptions;
2974  AclMode this_privileges;
2975  Acl *old_acl;
2976  Acl *new_acl;
2977  Oid grantorId;
2978  Oid ownerId;
2979  HeapTuple newtuple;
2981  bool nulls[Natts_pg_tablespace];
2982  bool replaces[Natts_pg_tablespace];
2983  int noldmembers;
2984  int nnewmembers;
2985  Oid *oldmembers;
2986  Oid *newmembers;
2987  HeapTuple tuple;
2988 
2989  /* Search syscache for pg_tablespace */
2991  if (!HeapTupleIsValid(tuple))
2992  elog(ERROR, "cache lookup failed for tablespace %u", tblId);
2993 
2994  pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);
2995 
2996  /*
2997  * Get owner ID and working copy of existing ACL. If there's no ACL,
2998  * substitute the proper default.
2999  */
3000  ownerId = pg_tablespace_tuple->spcowner;
3001  aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl,
3002  RelationGetDescr(relation), &isNull);
3003  if (isNull)
3004  {
3005  old_acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
3006  /* There are no old member roles according to the catalogs */
3007  noldmembers = 0;
3008  oldmembers = NULL;
3009  }
3010  else
3011  {
3012  old_acl = DatumGetAclPCopy(aclDatum);
3013  /* Get the roles mentioned in the existing ACL */
3014  noldmembers = aclmembers(old_acl, &oldmembers);
3015  }
3016 
3017  /* Determine ID to do the grant as, and available grant options */
3019  old_acl, ownerId,
3020  &grantorId, &avail_goptions);
3021 
3022  /*
3023  * Restrict the privileges to what we can actually grant, and emit the
3024  * standards-mandated warning and error messages.
3025  */
3026  this_privileges =
3027  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3028  istmt->all_privs, istmt->privileges,
3029  tblId, grantorId, ACL_KIND_TABLESPACE,
3030  NameStr(pg_tablespace_tuple->spcname),
3031  0, NULL);
3032 
3033  /*
3034  * Generate new ACL.
3035  */
3036  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3037  istmt->grant_option, istmt->behavior,
3038  istmt->grantees, this_privileges,
3039  grantorId, ownerId);
3040 
3041  /*
3042  * We need the members of both old and new ACLs so we can correct the
3043  * shared dependency information.
3044  */
3045  nnewmembers = aclmembers(new_acl, &newmembers);
3046 
3047  /* finished building new ACL value, now insert it */
3048  MemSet(values, 0, sizeof(values));
3049  MemSet(nulls, false, sizeof(nulls));
3050  MemSet(replaces, false, sizeof(replaces));
3051 
3052  replaces[Anum_pg_tablespace_spcacl - 1] = true;
3053  values[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(new_acl);
3054 
3055  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3056  nulls, replaces);
3057 
3058  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3059 
3060  /* Update the shared dependency ACL info */
3062  ownerId,
3063  noldmembers, oldmembers,
3064  nnewmembers, newmembers);
3065 
3066  ReleaseSysCache(tuple);
3067  pfree(new_acl);
3068 
3069  /* prevent error when processing duplicate objects */
3071  }
3072 
3073  heap_close(relation, RowExclusiveLock);
3074 }
3075 
3076 static void
3078 {
3079  Relation relation;
3080  ListCell *cell;
3081 
3082  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
3084 
3086 
3087  foreach(cell, istmt->objects)
3088  {
3089  Oid typId = lfirst_oid(cell);
3090  Form_pg_type pg_type_tuple;
3091  Datum aclDatum;
3092  bool isNull;
3093  AclMode avail_goptions;
3094  AclMode this_privileges;
3095  Acl *old_acl;
3096  Acl *new_acl;
3097  Oid grantorId;
3098  Oid ownerId;
3099  HeapTuple newtuple;
3101  bool nulls[Natts_pg_type];
3102  bool replaces[Natts_pg_type];
3103  int noldmembers;
3104  int nnewmembers;
3105  Oid *oldmembers;
3106  Oid *newmembers;
3107  HeapTuple tuple;
3108 
3109  /* Search syscache for pg_type */
3110  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typId));
3111  if (!HeapTupleIsValid(tuple))
3112  elog(ERROR, "cache lookup failed for type %u", typId);
3113 
3114  pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
3115 
3116  if (pg_type_tuple->typelem != 0 && pg_type_tuple->typlen == -1)
3117  ereport(ERROR,
3118  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
3119  errmsg("cannot set privileges of array types"),
3120  errhint("Set the privileges of the element type instead.")));
3121 
3122  /* Used GRANT DOMAIN on a non-domain? */
3123  if (istmt->objtype == ACL_OBJECT_DOMAIN &&
3124  pg_type_tuple->typtype != TYPTYPE_DOMAIN)
3125  ereport(ERROR,
3126  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3127  errmsg("\"%s\" is not a domain",
3128  NameStr(pg_type_tuple->typname))));
3129 
3130  /*
3131  * Get owner ID and working copy of existing ACL. If there's no ACL,
3132  * substitute the proper default.
3133  */
3134  ownerId = pg_type_tuple->typowner;
3135  aclDatum = heap_getattr(tuple, Anum_pg_type_typacl,
3136  RelationGetDescr(relation), &isNull);
3137  if (isNull)
3138  {
3139  old_acl = acldefault(istmt->objtype, ownerId);
3140  /* There are no old member roles according to the catalogs */
3141  noldmembers = 0;
3142  oldmembers = NULL;
3143  }
3144  else
3145  {
3146  old_acl = DatumGetAclPCopy(aclDatum);
3147  /* Get the roles mentioned in the existing ACL */
3148  noldmembers = aclmembers(old_acl, &oldmembers);
3149  }
3150 
3151  /* Determine ID to do the grant as, and available grant options */
3153  old_acl, ownerId,
3154  &grantorId, &avail_goptions);
3155 
3156  /*
3157  * Restrict the privileges to what we can actually grant, and emit the
3158  * standards-mandated warning and error messages.
3159  */
3160  this_privileges =
3161  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3162  istmt->all_privs, istmt->privileges,
3163  typId, grantorId, ACL_KIND_TYPE,
3164  NameStr(pg_type_tuple->typname),
3165  0, NULL);
3166 
3167  /*
3168  * Generate new ACL.
3169  */
3170  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3171  istmt->grant_option, istmt->behavior,
3172  istmt->grantees, this_privileges,
3173  grantorId, ownerId);
3174 
3175  /*
3176  * We need the members of both old and new ACLs so we can correct the
3177  * shared dependency information.
3178  */
3179  nnewmembers = aclmembers(new_acl, &newmembers);
3180 
3181  /* finished building new ACL value, now insert it */
3182  MemSet(values, 0, sizeof(values));
3183  MemSet(nulls, false, sizeof(nulls));
3184  MemSet(replaces, false, sizeof(replaces));
3185 
3186  replaces[Anum_pg_type_typacl - 1] = true;
3187  values[Anum_pg_type_typacl - 1] = PointerGetDatum(new_acl);
3188 
3189  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3190  nulls, replaces);
3191 
3192  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3193 
3194  /* Update initial privileges for extensions */
3195  recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
3196 
3197  /* Update the shared dependency ACL info */
3199  ownerId,
3200  noldmembers, oldmembers,
3201  nnewmembers, newmembers);
3202 
3203  ReleaseSysCache(tuple);
3204  pfree(new_acl);
3205 
3206  /* prevent error when processing duplicate objects */
3208  }
3209 
3210  heap_close(relation, RowExclusiveLock);
3211 }
3212 
3213 
3214 static AclMode
3215 string_to_privilege(const char *privname)
3216 {
3217  if (strcmp(privname, "insert") == 0)
3218  return ACL_INSERT;
3219  if (strcmp(privname, "select") == 0)
3220  return ACL_SELECT;
3221  if (strcmp(privname, "update") == 0)
3222  return ACL_UPDATE;
3223  if (strcmp(privname, "delete") == 0)
3224  return ACL_DELETE;
3225  if (strcmp(privname, "truncate") == 0)
3226  return ACL_TRUNCATE;
3227  if (strcmp(privname, "references") == 0)
3228  return ACL_REFERENCES;
3229  if (strcmp(privname, "trigger") == 0)
3230  return ACL_TRIGGER;
3231  if (strcmp(privname, "execute") == 0)
3232  return ACL_EXECUTE;
3233  if (strcmp(privname, "usage") == 0)
3234  return ACL_USAGE;
3235  if (strcmp(privname, "create") == 0)
3236  return ACL_CREATE;
3237  if (strcmp(privname, "temporary") == 0)
3238  return ACL_CREATE_TEMP;
3239  if (strcmp(privname, "temp") == 0)
3240  return ACL_CREATE_TEMP;
3241  if (strcmp(privname, "connect") == 0)
3242  return ACL_CONNECT;
3243  if (strcmp(privname, "rule") == 0)
3244  return 0; /* ignore old RULE privileges */
3245  ereport(ERROR,
3246  (errcode(ERRCODE_SYNTAX_ERROR),
3247  errmsg("unrecognized privilege type \"%s\"", privname)));
3248  return 0; /* appease compiler */
3249 }
3250 
3251 static const char *
3253 {
3254  switch (privilege)
3255  {
3256  case ACL_INSERT:
3257  return "INSERT";
3258  case ACL_SELECT:
3259  return "SELECT";
3260  case ACL_UPDATE:
3261  return "UPDATE";
3262  case ACL_DELETE:
3263  return "DELETE";
3264  case ACL_TRUNCATE:
3265  return "TRUNCATE";
3266  case ACL_REFERENCES:
3267  return "REFERENCES";
3268  case ACL_TRIGGER:
3269  return "TRIGGER";
3270  case ACL_EXECUTE:
3271  return "EXECUTE";
3272  case ACL_USAGE:
3273  return "USAGE";
3274  case ACL_CREATE:
3275  return "CREATE";
3276  case ACL_CREATE_TEMP:
3277  return "TEMP";
3278  case ACL_CONNECT:
3279  return "CONNECT";
3280  default:
3281  elog(ERROR, "unrecognized privilege: %d", (int) privilege);
3282  }
3283  return NULL; /* appease compiler */
3284 }
3285 
3286 /*
3287  * Standardized reporting of aclcheck permissions failures.
3288  *
3289  * Note: we do not double-quote the %s's below, because many callers
3290  * supply strings that might be already quoted.
3291  */
3292 
3293 static const char *const no_priv_msg[MAX_ACL_KIND] =
3294 {
3295  /* ACL_KIND_COLUMN */
3296  gettext_noop("permission denied for column %s"),
3297  /* ACL_KIND_CLASS */
3298  gettext_noop("permission denied for relation %s"),
3299  /* ACL_KIND_SEQUENCE */
3300  gettext_noop("permission denied for sequence %s"),
3301  /* ACL_KIND_DATABASE */
3302  gettext_noop("permission denied for database %s"),
3303  /* ACL_KIND_PROC */
3304  gettext_noop("permission denied for function %s"),
3305  /* ACL_KIND_OPER */
3306  gettext_noop("permission denied for operator %s"),
3307  /* ACL_KIND_TYPE */
3308  gettext_noop("permission denied for type %s"),
3309  /* ACL_KIND_LANGUAGE */
3310  gettext_noop("permission denied for language %s"),
3311  /* ACL_KIND_LARGEOBJECT */
3312  gettext_noop("permission denied for large object %s"),
3313  /* ACL_KIND_NAMESPACE */
3314  gettext_noop("permission denied for schema %s"),
3315  /* ACL_KIND_OPCLASS */
3316  gettext_noop("permission denied for operator class %s"),
3317  /* ACL_KIND_OPFAMILY */
3318  gettext_noop("permission denied for operator family %s"),
3319  /* ACL_KIND_COLLATION */
3320  gettext_noop("permission denied for collation %s"),
3321  /* ACL_KIND_CONVERSION */
3322  gettext_noop("permission denied for conversion %s"),
3323  /* ACL_KIND_STATISTICS */
3324  gettext_noop("permission denied for statistics object %s"),
3325  /* ACL_KIND_TABLESPACE */
3326  gettext_noop("permission denied for tablespace %s"),
3327  /* ACL_KIND_TSDICTIONARY */
3328  gettext_noop("permission denied for text search dictionary %s"),
3329  /* ACL_KIND_TSCONFIGURATION */
3330  gettext_noop("permission denied for text search configuration %s"),
3331  /* ACL_KIND_FDW */
3332  gettext_noop("permission denied for foreign-data wrapper %s"),
3333  /* ACL_KIND_FOREIGN_SERVER */
3334  gettext_noop("permission denied for foreign server %s"),
3335  /* ACL_KIND_EVENT_TRIGGER */
3336  gettext_noop("permission denied for event trigger %s"),
3337  /* ACL_KIND_EXTENSION */
3338  gettext_noop("permission denied for extension %s"),
3339  /* ACL_KIND_PUBLICATION */
3340  gettext_noop("permission denied for publication %s"),
3341  /* ACL_KIND_SUBSCRIPTION */
3342  gettext_noop("permission denied for subscription %s"),
3343 };
3344 
3345 static const char *const not_owner_msg[MAX_ACL_KIND] =
3346 {
3347  /* ACL_KIND_COLUMN */
3348  gettext_noop("must be owner of relation %s"),
3349  /* ACL_KIND_CLASS */
3350  gettext_noop("must be owner of relation %s"),
3351  /* ACL_KIND_SEQUENCE */
3352  gettext_noop("must be owner of sequence %s"),
3353  /* ACL_KIND_DATABASE */
3354  gettext_noop("must be owner of database %s"),
3355  /* ACL_KIND_PROC */
3356  gettext_noop("must be owner of function %s"),
3357  /* ACL_KIND_OPER */
3358  gettext_noop("must be owner of operator %s"),
3359  /* ACL_KIND_TYPE */
3360  gettext_noop("must be owner of type %s"),
3361  /* ACL_KIND_LANGUAGE */
3362  gettext_noop("must be owner of language %s"),
3363  /* ACL_KIND_LARGEOBJECT */
3364  gettext_noop("must be owner of large object %s"),
3365  /* ACL_KIND_NAMESPACE */
3366  gettext_noop("must be owner of schema %s"),
3367  /* ACL_KIND_OPCLASS */
3368  gettext_noop("must be owner of operator class %s"),
3369  /* ACL_KIND_OPFAMILY */
3370  gettext_noop("must be owner of operator family %s"),
3371  /* ACL_KIND_COLLATION */
3372  gettext_noop("must be owner of collation %s"),
3373  /* ACL_KIND_CONVERSION */
3374  gettext_noop("must be owner of conversion %s"),
3375  /* ACL_KIND_STATISTICS */
3376  gettext_noop("must be owner of statistics object %s"),
3377  /* ACL_KIND_TABLESPACE */
3378  gettext_noop("must be owner of tablespace %s"),
3379  /* ACL_KIND_TSDICTIONARY */
3380  gettext_noop("must be owner of text search dictionary %s"),
3381  /* ACL_KIND_TSCONFIGURATION */
3382  gettext_noop("must be owner of text search configuration %s"),
3383  /* ACL_KIND_FDW */
3384  gettext_noop("must be owner of foreign-data wrapper %s"),
3385  /* ACL_KIND_FOREIGN_SERVER */
3386  gettext_noop("must be owner of foreign server %s"),
3387  /* ACL_KIND_EVENT_TRIGGER */
3388  gettext_noop("must be owner of event trigger %s"),
3389  /* ACL_KIND_EXTENSION */
3390  gettext_noop("must be owner of extension %s"),
3391  /* ACL_KIND_PUBLICATION */
3392  gettext_noop("must be owner of publication %s"),
3393  /* ACL_KIND_SUBSCRIPTION */
3394  gettext_noop("must be owner of subscription %s"),
3395 };
3396 
3397 
3398 void
3400  const char *objectname)
3401 {
3402  switch (aclerr)
3403  {
3404  case ACLCHECK_OK:
3405  /* no error, so return to caller */
3406  break;
3407  case ACLCHECK_NO_PRIV:
3408  ereport(ERROR,
3409  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3410  errmsg(no_priv_msg[objectkind], objectname)));
3411  break;
3412  case ACLCHECK_NOT_OWNER:
3413  ereport(ERROR,
3414  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3415  errmsg(not_owner_msg[objectkind], objectname)));
3416  break;
3417  default:
3418  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3419  break;
3420  }
3421 }
3422 
3423 
3424 void
3426  const char *objectname, const char *colname)
3427 {
3428  switch (aclerr)
3429  {
3430  case ACLCHECK_OK:
3431  /* no error, so return to caller */
3432  break;
3433  case ACLCHECK_NO_PRIV:
3434  ereport(ERROR,
3435  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3436  errmsg("permission denied for column \"%s\" of relation \"%s\"",
3437  colname, objectname)));
3438  break;
3439  case ACLCHECK_NOT_OWNER:
3440  /* relation msg is OK since columns don't have separate owners */
3441  ereport(ERROR,
3442  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3443  errmsg(not_owner_msg[objectkind], objectname)));
3444  break;
3445  default:
3446  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3447  break;
3448  }
3449 }
3450 
3451 
3452 /*
3453  * Special common handling for types: use element type instead of array type,
3454  * and format nicely
3455  */
3456 void
3458 {
3459  Oid element_type = get_element_type(typeOid);
3460 
3461  aclcheck_error(aclerr, ACL_KIND_TYPE, format_type_be(element_type ? element_type : typeOid));
3462 }
3463 
3464 
3465 /*
3466  * Relay for the various pg_*_mask routines depending on object kind
3467  */
3468 static AclMode
3469 pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum, Oid roleid,
3470  AclMode mask, AclMaskHow how)
3471 {
3472  switch (objkind)
3473  {
3474  case ACL_KIND_COLUMN:
3475  return
3476  pg_class_aclmask(table_oid, roleid, mask, how) |
3477  pg_attribute_aclmask(table_oid, attnum, roleid, mask, how);
3478  case ACL_KIND_CLASS:
3479  case ACL_KIND_SEQUENCE:
3480  return pg_class_aclmask(table_oid, roleid, mask, how);
3481  case ACL_KIND_DATABASE:
3482  return pg_database_aclmask(table_oid, roleid, mask, how);
3483  case ACL_KIND_PROC:
3484  return pg_proc_aclmask(table_oid, roleid, mask, how);
3485  case ACL_KIND_LANGUAGE:
3486  return pg_language_aclmask(table_oid, roleid, mask, how);
3487  case ACL_KIND_LARGEOBJECT:
3488  return pg_largeobject_aclmask_snapshot(table_oid, roleid,
3489  mask, how, NULL);
3490  case ACL_KIND_NAMESPACE:
3491  return pg_namespace_aclmask(table_oid, roleid, mask, how);
3492  case ACL_KIND_STATISTICS:
3493  elog(ERROR, "grantable rights not supported for statistics objects");
3494  /* not reached, but keep compiler quiet */
3495  return ACL_NO_RIGHTS;
3496  case ACL_KIND_TABLESPACE:
3497  return pg_tablespace_aclmask(table_oid, roleid, mask, how);
3498  case ACL_KIND_FDW:
3499  return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
3501  return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
3503  elog(ERROR, "grantable rights not supported for event triggers");
3504  /* not reached, but keep compiler quiet */
3505  return ACL_NO_RIGHTS;
3506  case ACL_KIND_TYPE:
3507  return pg_type_aclmask(table_oid, roleid, mask, how);
3508  default:
3509  elog(ERROR, "unrecognized objkind: %d",
3510  (int) objkind);
3511  /* not reached, but keep compiler quiet */
3512  return ACL_NO_RIGHTS;
3513  }
3514 }
3515 
3516 
3517 /* ****************************************************************
3518  * Exported routines for examining a user's privileges for various objects
3519  *
3520  * See aclmask() for a description of the common API for these functions.
3521  *
3522  * Note: we give lookup failure the full ereport treatment because the
3523  * has_xxx_privilege() family of functions allow users to pass any random
3524  * OID to these functions.
3525  * ****************************************************************
3526  */
3527 
3528 /*
3529  * Exported routine for examining a user's privileges for a column
3530  *
3531  * Note: this considers only privileges granted specifically on the column.
3532  * It is caller's responsibility to take relation-level privileges into account
3533  * as appropriate. (For the same reason, we have no special case for
3534  * superuser-ness here.)
3535  */
3536 AclMode
3537 pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid,
3538  AclMode mask, AclMaskHow how)
3539 {
3540  AclMode result;
3541  HeapTuple classTuple;
3542  HeapTuple attTuple;
3543  Form_pg_class classForm;
3544  Form_pg_attribute attributeForm;
3545  Datum aclDatum;
3546  bool isNull;
3547  Acl *acl;
3548  Oid ownerId;
3549 
3550  /*
3551  * First, get the column's ACL from its pg_attribute entry
3552  */
3553  attTuple = SearchSysCache2(ATTNUM,
3554  ObjectIdGetDatum(table_oid),
3555  Int16GetDatum(attnum));
3556  if (!HeapTupleIsValid(attTuple))
3557  ereport(ERROR,
3558  (errcode(ERRCODE_UNDEFINED_COLUMN),
3559  errmsg("attribute %d of relation with OID %u does not exist",
3560  attnum, table_oid)));
3561  attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
3562 
3563  /* Throw error on dropped columns, too */
3564  if (attributeForm->attisdropped)
3565  ereport(ERROR,
3566  (errcode(ERRCODE_UNDEFINED_COLUMN),
3567  errmsg("attribute %d of relation with OID %u does not exist",
3568  attnum, table_oid)));
3569 
3570  aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
3571  &isNull);
3572 
3573  /*
3574  * Here we hard-wire knowledge that the default ACL for a column grants no
3575  * privileges, so that we can fall out quickly in the very common case
3576  * where attacl is null.
3577  */
3578  if (isNull)
3579  {
3580  ReleaseSysCache(attTuple);
3581  return 0;
3582  }
3583 
3584  /*
3585  * Must get the relation's ownerId from pg_class. Since we already found
3586  * a pg_attribute entry, the only likely reason for this to fail is that a
3587  * concurrent DROP of the relation committed since then (which could only
3588  * happen if we don't have lock on the relation). We prefer to report "no
3589  * privileges" rather than failing in such a case, so as to avoid unwanted
3590  * failures in has_column_privilege() tests.
3591  */
3592  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3593  if (!HeapTupleIsValid(classTuple))
3594  {
3595  ReleaseSysCache(attTuple);
3596  return 0;
3597  }
3598  classForm = (Form_pg_class) GETSTRUCT(classTuple);
3599 
3600  ownerId = classForm->relowner;
3601 
3602  ReleaseSysCache(classTuple);
3603 
3604  /* detoast column's ACL if necessary */
3605  acl = DatumGetAclP(aclDatum);
3606 
3607  result = aclmask(acl, roleid, ownerId, mask, how);
3608 
3609  /* if we have a detoasted copy, free it */
3610  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3611  pfree(acl);
3612 
3613  ReleaseSysCache(attTuple);
3614 
3615  return result;
3616 }
3617 
3618 /*
3619  * Exported routine for examining a user's privileges for a table
3620  */
3621 AclMode
3622 pg_class_aclmask(Oid table_oid, Oid roleid,
3623  AclMode mask, AclMaskHow how)
3624 {
3625  AclMode result;
3626  HeapTuple tuple;
3627  Form_pg_class classForm;
3628  Datum aclDatum;
3629  bool isNull;
3630  Acl *acl;
3631  Oid ownerId;
3632 
3633  /*
3634  * Must get the relation's tuple from pg_class
3635  */
3636  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3637  if (!HeapTupleIsValid(tuple))
3638  ereport(ERROR,
3640  errmsg("relation with OID %u does not exist",
3641  table_oid)));
3642  classForm = (Form_pg_class) GETSTRUCT(tuple);
3643 
3644  /*
3645  * Deny anyone permission to update a system catalog unless
3646  * pg_authid.rolsuper is set. Also allow it if allowSystemTableMods.
3647  *
3648  * As of 7.4 we have some updatable system views; those shouldn't be
3649  * protected in this way. Assume the view rules can take care of
3650  * themselves. ACL_USAGE is if we ever have system sequences.
3651  */
3652  if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
3653  IsSystemClass(table_oid, classForm) &&
3654  classForm->relkind != RELKIND_VIEW &&
3655  !superuser_arg(roleid) &&
3657  {
3658 #ifdef ACLDEBUG
3659  elog(DEBUG2, "permission denied for system catalog update");
3660 #endif
3662  }
3663 
3664  /*
3665  * Otherwise, superusers bypass all permission-checking.
3666  */
3667  if (superuser_arg(roleid))
3668  {
3669 #ifdef ACLDEBUG
3670  elog(DEBUG2, "OID %u is superuser, home free", roleid);
3671 #endif
3672  ReleaseSysCache(tuple);
3673  return mask;
3674  }
3675 
3676  /*
3677  * Normal case: get the relation's ACL from pg_class
3678  */
3679  ownerId = classForm->relowner;
3680 
3681  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
3682  &isNull);
3683  if (isNull)
3684  {
3685  /* No ACL, so build default ACL */
3686  switch (classForm->relkind)
3687  {
3688  case RELKIND_SEQUENCE:
3689  acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
3690  break;
3691  default:
3692  acl = acldefault(ACL_OBJECT_RELATION, ownerId);
3693  break;
3694  }
3695  aclDatum = (Datum) 0;
3696  }
3697  else
3698  {
3699  /* detoast rel's ACL if necessary */
3700  acl = DatumGetAclP(aclDatum);
3701  }
3702 
3703  result = aclmask(acl, roleid, ownerId, mask, how);
3704 
3705  /* if we have a detoasted copy, free it */
3706  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3707  pfree(acl);
3708 
3709  ReleaseSysCache(tuple);
3710 
3711  return result;
3712 }
3713 
3714 /*
3715  * Exported routine for examining a user's privileges for a database
3716  */
3717 AclMode
3718 pg_database_aclmask(Oid db_oid, Oid roleid,
3719  AclMode mask, AclMaskHow how)
3720 {
3721  AclMode result;
3722  HeapTuple tuple;
3723  Datum aclDatum;
3724  bool isNull;
3725  Acl *acl;
3726  Oid ownerId;
3727 
3728  /* Superusers bypass all permission checking. */
3729  if (superuser_arg(roleid))
3730  return mask;
3731 
3732  /*
3733  * Get the database's ACL from pg_database
3734  */
3735  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
3736  if (!HeapTupleIsValid(tuple))
3737  ereport(ERROR,
3738  (errcode(ERRCODE_UNDEFINED_DATABASE),
3739  errmsg("database with OID %u does not exist", db_oid)));
3740 
3741  ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
3742 
3744  &isNull);
3745  if (isNull)
3746  {
3747  /* No ACL, so build default ACL */
3748  acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
3749  aclDatum = (Datum) 0;
3750  }
3751  else
3752  {
3753  /* detoast ACL if necessary */
3754  acl = DatumGetAclP(aclDatum);
3755  }
3756 
3757  result = aclmask(acl, roleid, ownerId, mask, how);
3758 
3759  /* if we have a detoasted copy, free it */
3760  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3761  pfree(acl);
3762 
3763  ReleaseSysCache(tuple);
3764 
3765  return result;
3766 }
3767 
3768 /*
3769  * Exported routine for examining a user's privileges for a function
3770  */
3771 AclMode
3772 pg_proc_aclmask(Oid proc_oid, Oid roleid,
3773  AclMode mask, AclMaskHow how)
3774 {
3775  AclMode result;
3776  HeapTuple tuple;
3777  Datum aclDatum;
3778  bool isNull;
3779  Acl *acl;
3780  Oid ownerId;
3781 
3782  /* Superusers bypass all permission checking. */
3783  if (superuser_arg(roleid))
3784  return mask;
3785 
3786  /*
3787  * Get the function's ACL from pg_proc
3788  */
3789  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
3790  if (!HeapTupleIsValid(tuple))
3791  ereport(ERROR,
3792  (errcode(ERRCODE_UNDEFINED_FUNCTION),
3793  errmsg("function with OID %u does not exist", proc_oid)));
3794 
3795  ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
3796 
3797  aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
3798  &isNull);
3799  if (isNull)
3800  {
3801  /* No ACL, so build default ACL */
3802  acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
3803  aclDatum = (Datum) 0;
3804  }
3805  else
3806  {
3807  /* detoast ACL if necessary */
3808  acl = DatumGetAclP(aclDatum);
3809  }
3810 
3811  result = aclmask(acl, roleid, ownerId, mask, how);
3812 
3813  /* if we have a detoasted copy, free it */
3814  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3815  pfree(acl);
3816 
3817  ReleaseSysCache(tuple);
3818 
3819  return result;
3820 }
3821 
3822 /*
3823  * Exported routine for examining a user's privileges for a language
3824  */
3825 AclMode
3826 pg_language_aclmask(Oid lang_oid, Oid roleid,
3827  AclMode mask, AclMaskHow how)
3828 {
3829  AclMode result;
3830  HeapTuple tuple;
3831  Datum aclDatum;
3832  bool isNull;
3833  Acl *acl;
3834  Oid ownerId;
3835 
3836  /* Superusers bypass all permission checking. */
3837  if (superuser_arg(roleid))
3838  return mask;
3839 
3840  /*
3841  * Get the language's ACL from pg_language
3842  */
3843  tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lang_oid));
3844  if (!HeapTupleIsValid(tuple))
3845  ereport(ERROR,
3846  (errcode(ERRCODE_UNDEFINED_OBJECT),
3847  errmsg("language with OID %u does not exist", lang_oid)));
3848 
3849  ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
3850 
3851  aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
3852  &isNull);
3853  if (isNull)
3854  {
3855  /* No ACL, so build default ACL */
3856  acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
3857  aclDatum = (Datum) 0;
3858  }
3859  else
3860  {
3861  /* detoast ACL if necessary */
3862  acl = DatumGetAclP(aclDatum);
3863  }
3864 
3865  result = aclmask(acl, roleid, ownerId, mask, how);
3866 
3867  /* if we have a detoasted copy, free it */
3868  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3869  pfree(acl);
3870 
3871  ReleaseSysCache(tuple);
3872 
3873  return result;
3874 }
3875 
3876 /*
3877  * Exported routine for examining a user's privileges for a largeobject
3878  *
3879  * When a large object is opened for reading, it is opened relative to the
3880  * caller's snapshot, but when it is opened for writing, a current
3881  * MVCC snapshot will be used. See doc/src/sgml/lobj.sgml. This function
3882  * takes a snapshot argument so that the permissions check can be made
3883  * relative to the same snapshot that will be used to read the underlying
3884  * data. The caller will actually pass NULL for an instantaneous MVCC
3885  * snapshot, since all we do with the snapshot argument is pass it through
3886  * to systable_beginscan().
3887  */
3888 AclMode
3890  AclMode mask, AclMaskHow how,
3891  Snapshot snapshot)
3892 {
3893  AclMode result;
3894  Relation pg_lo_meta;
3895  ScanKeyData entry[1];
3896  SysScanDesc scan;
3897  HeapTuple tuple;
3898  Datum aclDatum;
3899  bool isNull;
3900  Acl *acl;
3901  Oid ownerId;
3902 
3903  /* Superusers bypass all permission checking. */
3904  if (superuser_arg(roleid))
3905  return mask;
3906 
3907  /*
3908  * Get the largeobject's ACL from pg_language_metadata
3909  */
3911  AccessShareLock);
3912 
3913  ScanKeyInit(&entry[0],
3915  BTEqualStrategyNumber, F_OIDEQ,
3916  ObjectIdGetDatum(lobj_oid));
3917 
3918  scan = systable_beginscan(pg_lo_meta,
3920  snapshot, 1, entry);
3921 
3922  tuple = systable_getnext(scan);
3923  if (!HeapTupleIsValid(tuple))
3924  ereport(ERROR,
3925  (errcode(ERRCODE_UNDEFINED_OBJECT),
3926  errmsg("large object %u does not exist", lobj_oid)));
3927 
3928  ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
3929 
3931  RelationGetDescr(pg_lo_meta), &isNull);
3932 
3933  if (isNull)
3934  {
3935  /* No ACL, so build default ACL */
3936  acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
3937  aclDatum = (Datum) 0;
3938  }
3939  else
3940  {
3941  /* detoast ACL if necessary */
3942  acl = DatumGetAclP(aclDatum);
3943  }
3944 
3945  result = aclmask(acl, roleid, ownerId, mask, how);
3946 
3947  /* if we have a detoasted copy, free it */
3948  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3949  pfree(acl);
3950 
3951  systable_endscan(scan);
3952 
3953  heap_close(pg_lo_meta, AccessShareLock);
3954 
3955  return result;
3956 }
3957 
3958 /*
3959  * Exported routine for examining a user's privileges for a namespace
3960  */
3961 AclMode
3962 pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
3963  AclMode mask, AclMaskHow how)
3964 {
3965  AclMode result;
3966  HeapTuple tuple;
3967  Datum aclDatum;
3968  bool isNull;
3969  Acl *acl;
3970  Oid ownerId;
3971 
3972  /* Superusers bypass all permission checking. */
3973  if (superuser_arg(roleid))
3974  return mask;
3975 
3976  /*
3977  * If we have been assigned this namespace as a temp namespace, check to
3978  * make sure we have CREATE TEMP permission on the database, and if so act
3979  * as though we have all standard (but not GRANT OPTION) permissions on
3980  * the namespace. If we don't have CREATE TEMP, act as though we have
3981  * only USAGE (and not CREATE) rights.
3982  *
3983  * This may seem redundant given the check in InitTempTableNamespace, but
3984  * it really isn't since current user ID may have changed since then. The
3985  * upshot of this behavior is that a SECURITY DEFINER function can create
3986  * temp tables that can then be accessed (if permission is granted) by
3987  * code in the same session that doesn't have permissions to create temp
3988  * tables.
3989  *
3990  * XXX Would it be safe to ereport a special error message as
3991  * InitTempTableNamespace does? Returning zero here means we'll get a
3992  * generic "permission denied for schema pg_temp_N" message, which is not
3993  * remarkably user-friendly.
3994  */
3995  if (isTempNamespace(nsp_oid))
3996  {
3997  if (pg_database_aclcheck(MyDatabaseId, roleid,
3999  return mask & ACL_ALL_RIGHTS_NAMESPACE;
4000  else
4001  return mask & ACL_USAGE;
4002  }
4003 
4004  /*
4005  * Get the schema's ACL from pg_namespace
4006  */
4007  tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
4008  if (!HeapTupleIsValid(tuple))
4009  ereport(ERROR,
4010  (errcode(ERRCODE_UNDEFINED_SCHEMA),
4011  errmsg("schema with OID %u does not exist", nsp_oid)));
4012 
4013  ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
4014 
4016  &isNull);
4017  if (isNull)
4018  {
4019  /* No ACL, so build default ACL */
4020  acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
4021  aclDatum = (Datum) 0;
4022  }
4023  else
4024  {
4025  /* detoast ACL if necessary */
4026  acl = DatumGetAclP(aclDatum);
4027  }
4028 
4029  result = aclmask(acl, roleid, ownerId, mask, how);
4030 
4031  /* if we have a detoasted copy, free it */
4032  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
4033  pfree(acl);
4034 
4035  ReleaseSysCache(tuple);
4036 
4037  return result;
4038 }
4039 
4040 /*
4041  * Exported routine for examining a user's privileges for a tablespace
4042  */
4043 AclMode
4045  AclMode mask, AclMaskHow how)
4046 {
4047  AclMode result;
4048  HeapTuple tuple;
4049  Datum aclDatum;
4050  bool isNull;
4051  Acl *acl;
4052  Oid ownerId;
4053 
4054  /* Superusers bypass all permission checking. */
4055  if (superuser_arg(roleid))
4056  return mask;
4057 
4058  /*
4059  * Get the tablespace's ACL from pg_tablespace
4060  */
4061  tuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
4062  if (!HeapTupleIsValid(tuple))
4063  ereport(ERROR,
4064  (errcode(ERRCODE_UNDEFINED_OBJECT),
4065  errmsg("tablespace with OID %u does not exist", spc_oid)));
4066 
4067  ownerId = ((Form_pg_tablespace) GETSTRUCT(tuple))->spcowner;
4068 
4069  aclDatum = SysCacheGetAttr(TABLESPACEOID, tuple,
4071  &isNull);
4072 
4073  if (isNull)
4074  {
4075  /* No ACL, so build default ACL */
4076  acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
4077  aclDatum = (Datum) 0;
4078  }
4079  else
4080  {
4081  /* detoast ACL if necessary */
4082  acl = DatumGetAclP(aclDatum);
4083  }
4084 
4085  result = aclmask(acl, roleid, ownerId, mask, how);
4086 
4087  /* if we have a detoasted copy, free it */
4088  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
4089  pfree(acl);
4090 
4091  ReleaseSysCache(tuple);
4092 
4093  return result;
4094 }
4095 
4096 /*
4097  * Exported routine for examining a user's privileges for a foreign
4098  * data wrapper
4099  */
4100 AclMode
4102  AclMode mask, AclMaskHow how)
4103 {
4104  AclMode result;
4105  HeapTuple tuple;
4106  Datum aclDatum;
4107  bool isNull;
4108  Acl *acl;
4109  Oid ownerId;
4110 
4112 
4113  /* Bypass permission checks for superusers */
4114  if (superuser_arg(roleid))
4115  return mask;
4116 
4117  /*
4118  * Must get the FDW's tuple from pg_foreign_data_wrapper
4119  */
4121  if (!HeapTupleIsValid(tuple))
4122  ereport(ERROR,
4123  (errcode(ERRCODE_UNDEFINED_OBJECT),
4124  errmsg("foreign-data wrapper with OID %u does not exist",
4125  fdw_oid)));
4126  fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
4127 
4128  /*
4129  * Normal case: get the FDW's ACL from pg_foreign_data_wrapper
4130  */
4131  ownerId = fdwForm->fdwowner;
4132 
4133  aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
4135  if (isNull)
4136  {
4137  /* No ACL, so build default ACL */
4138  acl = acldefault(ACL_OBJECT_FDW, ownerId);
4139  aclDatum = (Datum) 0;
4140  }
4141  else
4142  {
4143  /* detoast rel's ACL if necessary */
4144  acl = DatumGetAclP(aclDatum);
4145  }
4146 
4147  result = aclmask(acl, roleid, ownerId, mask, how);
4148 
4149  /* if we have a detoasted copy, free it */
4150  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
4151  pfree(acl);
4152 
4153  ReleaseSysCache(tuple);
4154 
4155  return result;
4156 }
4157 
4158 /*
4159  * Exported routine for examining a user's privileges for a foreign
4160  * server.
4161  */
4162 AclMode
4164  AclMode mask, AclMaskHow how)
4165 {
4166  AclMode result;
4167  HeapTuple tuple;
4168  Datum aclDatum;
4169  bool isNull;
4170  Acl *acl;
4171  Oid ownerId;
4172 
4173  Form_pg_foreign_server srvForm;
4174 
4175  /* Bypass permission checks for superusers */
4176  if (superuser_arg(roleid))
4177  return mask;
4178 
4179  /*
4180  * Must get the FDW's tuple from pg_foreign_data_wrapper
4181  */
4183  if (!HeapTupleIsValid(tuple))
4184  ereport(ERROR,
4185  (errcode(ERRCODE_UNDEFINED_OBJECT),
4186  errmsg("foreign server with OID %u does not exist",
4187  srv_oid)));
4188  srvForm = (Form_pg_foreign_server) GETSTRUCT(tuple);
4189 
4190  /*
4191  * Normal case: get the foreign server's ACL from pg_foreign_server
4192  */
4193  ownerId = srvForm->srvowner;
4194 
4195  aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
4197  if (isNull)
4198  {
4199  /* No ACL, so build default ACL */
4200  acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
4201  aclDatum = (Datum) 0;
4202  }
4203  else
4204  {
4205  /* detoast rel's ACL if necessary */
4206  acl = DatumGetAclP(aclDatum);
4207  }
4208 
4209  result = aclmask(acl, roleid, ownerId, mask, how);
4210 
4211  /* if we have a detoasted copy, free it */
4212  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
4213  pfree(acl);
4214 
4215  ReleaseSysCache(tuple);
4216 
4217  return result;
4218 }
4219 
4220 /*
4221  * Exported routine for examining a user's privileges for a type.
4222  */
4223 AclMode
4224 pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
4225 {
4226  AclMode result;
4227  HeapTuple tuple;
4228  Datum aclDatum;
4229  bool isNull;
4230  Acl *acl;
4231  Oid ownerId;
4232 
4233  Form_pg_type typeForm;
4234 
4235  /* Bypass permission checks for superusers */
4236  if (superuser_arg(roleid))
4237  return mask;
4238 
4239  /*
4240  * Must get the type's tuple from pg_type
4241  */
4242  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
4243  if (!HeapTupleIsValid(tuple))
4244  ereport(ERROR,
4245  (errcode(ERRCODE_UNDEFINED_OBJECT),
4246  errmsg("type with OID %u does not exist",
4247  type_oid)));
4248  typeForm = (Form_pg_type) GETSTRUCT(tuple);
4249 
4250  /*
4251  * "True" array types don't manage permissions of their own; consult the
4252  * element type instead.
4253  */
4254  if (OidIsValid(typeForm->typelem) && typeForm->typlen == -1)
4255  {
4256  Oid elttype_oid = typeForm->typelem;
4257 
4258  ReleaseSysCache(tuple);
4259 
4260  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(elttype_oid));
4261  /* this case is not a user-facing error, so elog not ereport */
4262  if (!HeapTupleIsValid(tuple))
4263  elog(ERROR, "cache lookup failed for type %u", elttype_oid);
4264  typeForm = (Form_pg_type) GETSTRUCT(tuple);
4265  }
4266 
4267  /*
4268  * Now get the type's owner and ACL from the tuple
4269  */
4270  ownerId = typeForm->typowner;
4271 
4272  aclDatum = SysCacheGetAttr(TYPEOID, tuple,
4273  Anum_pg_type_typacl, &isNull);
4274  if (isNull)
4275  {
4276  /* No ACL, so build default ACL */
4277  acl = acldefault(ACL_OBJECT_TYPE, ownerId);
4278  aclDatum = (Datum) 0;
4279  }
4280  else
4281  {
4282  /* detoast rel's ACL if necessary */
4283  acl = DatumGetAclP(aclDatum);
4284  }
4285 
4286  result = aclmask(acl, roleid, ownerId, mask, how);
4287 
4288  /* if we have a detoasted copy, free it */
4289  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
4290  pfree(acl);
4291 
4292  ReleaseSysCache(tuple);
4293 
4294  return result;
4295 }
4296 
4297 /*
4298  * Exported routine for checking a user's access privileges to a column
4299  *
4300  * Returns ACLCHECK_OK if the user has any of the privileges identified by
4301  * 'mode'; otherwise returns a suitable error code (in practice, always
4302  * ACLCHECK_NO_PRIV).
4303  *
4304  * As with pg_attribute_aclmask, only privileges granted directly on the
4305  * column are considered here.
4306  */
4307 AclResult
4309  Oid roleid, AclMode mode)
4310 {
4311  if (pg_attribute_aclmask(table_oid, attnum, roleid, mode, ACLMASK_ANY) != 0)
4312  return ACLCHECK_OK;
4313  else
4314  return ACLCHECK_NO_PRIV;
4315 }
4316 
4317 /*
4318  * Exported routine for checking a user's access privileges to any/all columns
4319  *
4320  * If 'how' is ACLMASK_ANY, then returns ACLCHECK_OK if user has any of the
4321  * privileges identified by 'mode' on any non-dropped column in the relation;
4322  * otherwise returns a suitable error code (in practice, always
4323  * ACLCHECK_NO_PRIV).
4324  *
4325  * If 'how' is ACLMASK_ALL, then returns ACLCHECK_OK if user has any of the
4326  * privileges identified by 'mode' on each non-dropped column in the relation
4327  * (and there must be at least one such column); otherwise returns a suitable
4328  * error code (in practice, always ACLCHECK_NO_PRIV).
4329  *
4330  * As with pg_attribute_aclmask, only privileges granted directly on the
4331  * column(s) are considered here.
4332  *
4333  * Note: system columns are not considered here; there are cases where that
4334  * might be appropriate but there are also cases where it wouldn't.
4335  */
4336 AclResult
4337 pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode,
4338  AclMaskHow how)
4339 {
4340  AclResult result;
4341  HeapTuple classTuple;
4342  Form_pg_class classForm;
4343  AttrNumber nattrs;
4344  AttrNumber curr_att;
4345 
4346  /*
4347  * Must fetch pg_class row to check number of attributes. As in
4348  * pg_attribute_aclmask, we prefer to return "no privileges" instead of
4349  * throwing an error if we get any unexpected lookup errors.
4350  */
4351  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
4352  if (!HeapTupleIsValid(classTuple))
4353  return ACLCHECK_NO_PRIV;
4354  classForm = (Form_pg_class) GETSTRUCT(classTuple);
4355 
4356  nattrs = classForm->relnatts;
4357 
4358  ReleaseSysCache(classTuple);
4359 
4360  /*
4361  * Initialize result in case there are no non-dropped columns. We want to
4362  * report failure in such cases for either value of 'how'.
4363  */
4364  result = ACLCHECK_NO_PRIV;
4365 
4366  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4367  {
4368  HeapTuple attTuple;
4369  AclMode attmask;
4370 
4371  attTuple = SearchSysCache2(ATTNUM,
4372  ObjectIdGetDatum(table_oid),
4373  Int16GetDatum(curr_att));
4374  if (!HeapTupleIsValid(attTuple))
4375  continue;
4376 
4377  /* ignore dropped columns */
4378  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4379  {
4380  ReleaseSysCache(attTuple);
4381  continue;
4382  }
4383 
4384  /*
4385  * Here we hard-wire knowledge that the default ACL for a column
4386  * grants no privileges, so that we can fall out quickly in the very
4387  * common case where attacl is null.
4388  */
4390  attmask = 0;
4391  else
4392  attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
4393  mode, ACLMASK_ANY);
4394 
4395  ReleaseSysCache(attTuple);
4396 
4397  if (attmask != 0)
4398  {
4399  result = ACLCHECK_OK;
4400  if (how == ACLMASK_ANY)
4401  break; /* succeed on any success */
4402  }
4403  else
4404  {
4405  result = ACLCHECK_NO_PRIV;
4406  if (how == ACLMASK_ALL)
4407  break; /* fail on any failure */
4408  }
4409  }
4410 
4411  return result;
4412 }
4413 
4414 /*
4415  * Exported routine for checking a user's access privileges to a table
4416  *
4417  * Returns ACLCHECK_OK if the user has any of the privileges identified by
4418  * 'mode'; otherwise returns a suitable error code (in practice, always
4419  * ACLCHECK_NO_PRIV).
4420  */
4421 AclResult
4422 pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
4423 {
4424  if (pg_class_aclmask(table_oid, roleid, mode, ACLMASK_ANY) != 0)
4425  return ACLCHECK_OK;
4426  else
4427  return ACLCHECK_NO_PRIV;
4428 }
4429 
4430 /*
4431  * Exported routine for checking a user's access privileges to a database
4432  */
4433 AclResult
4434 pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
4435 {
4436  if (pg_database_aclmask(db_oid, roleid, mode, ACLMASK_ANY) != 0)
4437  return ACLCHECK_OK;
4438  else
4439  return ACLCHECK_NO_PRIV;
4440 }
4441 
4442 /*
4443  * Exported routine for checking a user's access privileges to a function
4444  */
4445 AclResult
4446 pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
4447 {
4448  if (pg_proc_aclmask(proc_oid, roleid, mode, ACLMASK_ANY) != 0)
4449  return ACLCHECK_OK;
4450  else
4451  return ACLCHECK_NO_PRIV;
4452 }
4453 
4454 /*
4455  * Exported routine for checking a user's access privileges to a language
4456  */
4457 AclResult
4458 pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
4459 {
4460  if (pg_language_aclmask(lang_oid, roleid, mode, ACLMASK_ANY) != 0)
4461  return ACLCHECK_OK;
4462  else
4463  return ACLCHECK_NO_PRIV;
4464 }
4465 
4466 /*
4467  * Exported routine for checking a user's access privileges to a largeobject
4468  */
4469 AclResult
4471  Snapshot snapshot)
4472 {
4473  if (pg_largeobject_aclmask_snapshot(lobj_oid, roleid, mode,
4474  ACLMASK_ANY, snapshot) != 0)
4475  return ACLCHECK_OK;
4476  else
4477  return ACLCHECK_NO_PRIV;
4478 }
4479 
4480 /*
4481  * Exported routine for checking a user's access privileges to a namespace
4482  */
4483 AclResult
4484 pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
4485 {
4486  if (pg_namespace_aclmask(nsp_oid, roleid, mode, ACLMASK_ANY) != 0)
4487  return ACLCHECK_OK;
4488  else
4489  return ACLCHECK_NO_PRIV;
4490 }
4491 
4492 /*
4493  * Exported routine for checking a user's access privileges to a tablespace
4494  */
4495 AclResult
4496 pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
4497 {
4498  if (pg_tablespace_aclmask(spc_oid, roleid, mode, ACLMASK_ANY) != 0)
4499  return ACLCHECK_OK;
4500  else
4501  return ACLCHECK_NO_PRIV;
4502 }
4503 
4504 /*
4505  * Exported routine for checking a user's access privileges to a foreign
4506  * data wrapper
4507  */
4508 AclResult
4510 {
4511  if (pg_foreign_data_wrapper_aclmask(fdw_oid, roleid, mode, ACLMASK_ANY) != 0)
4512  return ACLCHECK_OK;
4513  else
4514  return ACLCHECK_NO_PRIV;
4515 }
4516 
4517 /*
4518  * Exported routine for checking a user's access privileges to a foreign
4519  * server
4520  */
4521 AclResult
4523 {
4524  if (pg_foreign_server_aclmask(srv_oid, roleid, mode, ACLMASK_ANY) != 0)
4525  return ACLCHECK_OK;
4526  else
4527  return ACLCHECK_NO_PRIV;
4528 }
4529 
4530 /*
4531  * Exported routine for checking a user's access privileges to a type
4532  */
4533 AclResult
4534 pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
4535 {
4536  if (pg_type_aclmask(type_oid, roleid, mode, ACLMASK_ANY) != 0)
4537  return ACLCHECK_OK;
4538  else
4539  return ACLCHECK_NO_PRIV;
4540 }
4541 
4542 /*
4543  * Ownership check for a relation (specified by OID).
4544  */
4545 bool
4546 pg_class_ownercheck(Oid class_oid, Oid roleid)
4547 {
4548  HeapTuple tuple;
4549  Oid ownerId;
4550 
4551  /* Superusers bypass all permission checking. */
4552  if (superuser_arg(roleid))
4553  return true;
4554 
4555  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(class_oid));
4556  if (!HeapTupleIsValid(tuple))
4557  ereport(ERROR,
4559  errmsg("relation with OID %u does not exist", class_oid)));
4560 
4561  ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
4562 
4563  ReleaseSysCache(tuple);
4564 
4565  return has_privs_of_role(roleid, ownerId);
4566 }
4567 
4568 /*
4569  * Ownership check for a type (specified by OID).
4570  */
4571 bool
4572 pg_type_ownercheck(Oid type_oid, Oid roleid)
4573 {
4574  HeapTuple tuple;
4575  Oid ownerId;
4576 
4577  /* Superusers bypass all permission checking. */
4578  if (superuser_arg(roleid))
4579  return true;
4580 
4581  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
4582  if (!HeapTupleIsValid(tuple))
4583  ereport(ERROR,
4584  (errcode(ERRCODE_UNDEFINED_OBJECT),
4585  errmsg("type with OID %u does not exist", type_oid)));
4586 
4587  ownerId = ((Form_pg_type) GETSTRUCT(tuple))->typowner;
4588 
4589  ReleaseSysCache(tuple);
4590 
4591  return has_privs_of_role(roleid, ownerId);
4592 }
4593 
4594 /*
4595  * Ownership check for an operator (specified by OID).
4596  */
4597 bool
4598 pg_oper_ownercheck(Oid oper_oid, Oid roleid)
4599 {
4600  HeapTuple tuple;
4601  Oid ownerId;
4602 
4603  /* Superusers bypass all permission checking. */
4604  if (superuser_arg(roleid))
4605  return true;
4606 
4607  tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(oper_oid));
4608  if (!HeapTupleIsValid(tuple))
4609  ereport(ERROR,
4610  (errcode(ERRCODE_UNDEFINED_FUNCTION),
4611  errmsg("operator with OID %u does not exist", oper_oid)));
4612 
4613  ownerId = ((Form_pg_operator) GETSTRUCT(tuple))->oprowner;
4614 
4615  ReleaseSysCache(tuple);
4616 
4617  return has_privs_of_role(roleid, ownerId);
4618 }
4619 
4620 /*
4621  * Ownership check for a function (specified by OID).
4622  */
4623 bool
4624 pg_proc_ownercheck(Oid proc_oid, Oid roleid)
4625 {
4626  HeapTuple tuple;
4627  Oid ownerId;
4628 
4629  /* Superusers bypass all permission checking. */
4630  if (superuser_arg(roleid))
4631  return true;
4632 
4633  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
4634  if (!HeapTupleIsValid(tuple))
4635  ereport(ERROR,
4636  (errcode(ERRCODE_UNDEFINED_FUNCTION),
4637  errmsg("function with OID %u does not exist", proc_oid)));
4638 
4639  ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
4640 
4641  ReleaseSysCache(tuple);
4642 
4643  return has_privs_of_role(roleid, ownerId);
4644 }
4645 
4646 /*
4647  * Ownership check for a procedural language (specified by OID)
4648  */
4649 bool
4651 {
4652  HeapTuple tuple;
4653  Oid ownerId;
4654 
4655  /* Superusers bypass all permission checking. */
4656  if (superuser_arg(roleid))
4657  return true;
4658 
4659  tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lan_oid));
4660  if (!HeapTupleIsValid(tuple))
4661  ereport(ERROR,
4662  (errcode(ERRCODE_UNDEFINED_FUNCTION),
4663  errmsg("language with OID %u does not exist", lan_oid)));
4664 
4665  ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
4666 
4667  ReleaseSysCache(tuple);
4668 
4669  return has_privs_of_role(roleid, ownerId);
4670 }
4671 
4672 /*
4673  * Ownership check for a largeobject (specified by OID)
4674  *
4675  * This is only used for operations like ALTER LARGE OBJECT that are always
4676  * relative to an up-to-date snapshot.
4677  */
4678 bool
4680 {
4681  Relation pg_lo_meta;
4682  ScanKeyData entry[1];
4683  SysScanDesc scan;
4684  HeapTuple tuple;
4685  Oid ownerId;
4686 
4687  /* Superusers bypass all permission checking. */
4688  if (superuser_arg(roleid))
4689  return true;
4690 
4691  /* There's no syscache for pg_largeobject_metadata */
4693  AccessShareLock);
4694 
4695  ScanKeyInit(&entry[0],
4697  BTEqualStrategyNumber, F_OIDEQ,
4698  ObjectIdGetDatum(lobj_oid));
4699 
4700  scan = systable_beginscan(pg_lo_meta,
4702  NULL, 1, entry);
4703 
4704  tuple = systable_getnext(scan);
4705  if (!HeapTupleIsValid(tuple))
4706  ereport(ERROR,
4707  (errcode(ERRCODE_UNDEFINED_OBJECT),
4708  errmsg("large object %u does not exist", lobj_oid)));
4709 
4710  ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
4711 
4712  systable_endscan(scan);
4713  heap_close(pg_lo_meta, AccessShareLock);
4714 
4715  return has_privs_of_role(roleid, ownerId);
4716 }
4717 
4718 /*
4719  * Ownership check for a namespace (specified by OID).
4720  */
4721 bool
4723 {
4724  HeapTuple tuple;
4725  Oid ownerId;
4726 
4727  /* Superusers bypass all permission checking. */
4728  if (superuser_arg(roleid))
4729  return true;
4730 
4731  tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
4732  if (!HeapTupleIsValid(tuple))
4733  ereport(ERROR,
4734  (errcode(ERRCODE_UNDEFINED_SCHEMA),
4735  errmsg("schema with OID %u does not exist", nsp_oid)));
4736 
4737  ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
4738 
4739  ReleaseSysCache(tuple);
4740 
4741  return has_privs_of_role(roleid, ownerId);
4742 }
4743 
4744 /*
4745  * Ownership check for a tablespace (specified by OID).
4746  */
4747 bool
4749 {
4750  HeapTuple spctuple;
4751  Oid spcowner;
4752 
4753  /* Superusers bypass all permission checking. */
4754  if (superuser_arg(roleid))
4755  return true;
4756 
4757  /* Search syscache for pg_tablespace */
4758  spctuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
4759  if (!HeapTupleIsValid(spctuple))
4760  ereport(ERROR,
4761  (errcode(ERRCODE_UNDEFINED_OBJECT),
4762  errmsg("tablespace with OID %u does not exist", spc_oid)));
4763 
4764  spcowner = ((Form_pg_tablespace) GETSTRUCT(spctuple))->spcowner;
4765 
4766  ReleaseSysCache(spctuple);
4767 
4768  return has_privs_of_role(roleid, spcowner);
4769 }
4770 
4771 /*
4772  * Ownership check for an operator class (specified by OID).
4773  */
4774 bool
4776 {
4777  HeapTuple tuple;
4778  Oid ownerId;
4779 
4780  /* Superusers bypass all permission checking. */
4781  if (superuser_arg(roleid))
4782  return true;
4783 
4784  tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opc_oid));
4785  if (!HeapTupleIsValid(tuple))
4786  ereport(ERROR,
4787  (errcode(ERRCODE_UNDEFINED_OBJECT),
4788  errmsg("operator class with OID %u does not exist",
4789  opc_oid)));
4790 
4791  ownerId = ((Form_pg_opclass) GETSTRUCT(tuple))->opcowner;
4792 
4793  ReleaseSysCache(tuple);
4794 
4795  return has_privs_of_role(roleid, ownerId);
4796 }
4797 
4798 /*
4799  * Ownership check for an operator family (specified by OID).
4800  */
4801 bool
4803 {
4804  HeapTuple tuple;
4805  Oid ownerId;
4806 
4807  /* Superusers bypass all permission checking. */
4808  if (superuser_arg(roleid))
4809  return true;
4810 
4811  tuple = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opf_oid));
4812  if (!HeapTupleIsValid(tuple))
4813  ereport(ERROR,
4814  (errcode(ERRCODE_UNDEFINED_OBJECT),
4815  errmsg("operator family with OID %u does not exist",
4816  opf_oid)));
4817 
4818  ownerId = ((Form_pg_opfamily) GETSTRUCT(tuple))->opfowner;
4819 
4820  ReleaseSysCache(tuple);
4821 
4822  return has_privs_of_role(roleid, ownerId);
4823 }
4824 
4825 /*
4826  * Ownership check for a text search dictionary (specified by OID).
4827  */
4828 bool
4829 pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid)
4830 {
4831  HeapTuple tuple;
4832  Oid ownerId;
4833 
4834  /* Superusers bypass all permission checking. */
4835  if (superuser_arg(roleid))
4836  return true;
4837 
4838  tuple = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dict_oid));
4839  if (!HeapTupleIsValid(tuple))
4840  ereport(ERROR,
4841  (errcode(ERRCODE_UNDEFINED_OBJECT),
4842  errmsg("text search dictionary with OID %u does not exist",
4843  dict_oid)));
4844 
4845  ownerId = ((Form_pg_ts_dict) GETSTRUCT(tuple))->dictowner;
4846 
4847  ReleaseSysCache(tuple);
4848 
4849  return has_privs_of_role(roleid, ownerId);
4850 }
4851 
4852 /*
4853  * Ownership check for a text search configuration (specified by OID).
4854  */
4855 bool
4857 {
4858  HeapTuple tuple;
4859  Oid ownerId;
4860 
4861  /* Superusers bypass all permission checking. */
4862  if (superuser_arg(roleid))
4863  return true;
4864 
4865  tuple = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfg_oid));
4866  if (!HeapTupleIsValid(tuple))
4867  ereport(ERROR,
4868  (errcode(ERRCODE_UNDEFINED_OBJECT),
4869  errmsg("text search configuration with OID %u does not exist",
4870  cfg_oid)));
4871 
4872  ownerId = ((Form_pg_ts_config) GETSTRUCT(tuple))->cfgowner;
4873 
4874  ReleaseSysCache(tuple);
4875 
4876  return has_privs_of_role(roleid, ownerId);
4877 }
4878 
4879 /*
4880  * Ownership check for a foreign-data wrapper (specified by OID).
4881  */
4882 bool
4884 {
4885  HeapTuple tuple;
4886  Oid ownerId;
4887 
4888  /* Superusers bypass all permission checking. */
4889  if (superuser_arg(roleid))
4890  return true;
4891 
4893  if (!HeapTupleIsValid(tuple))
4894  ereport(ERROR,
4895  (errcode(ERRCODE_UNDEFINED_OBJECT),
4896  errmsg("foreign-data wrapper with OID %u does not exist",
4897  srv_oid)));
4898 
4899  ownerId = ((Form_pg_foreign_data_wrapper) GETSTRUCT(tuple))->fdwowner;
4900 
4901  ReleaseSysCache(tuple);
4902 
4903  return has_privs_of_role(roleid, ownerId);
4904 }
4905 
4906 /*
4907  * Ownership check for a foreign server (specified by OID).
4908  */
4909 bool
4911 {
4912  HeapTuple tuple;
4913  Oid ownerId;
4914 
4915  /* Superusers bypass all permission checking. */
4916  if (superuser_arg(roleid))
4917  return true;
4918 
4920  if (!HeapTupleIsValid(tuple))
4921  ereport(ERROR,
4922  (errcode(ERRCODE_UNDEFINED_OBJECT),
4923  errmsg("foreign server with OID %u does not exist",
4924  srv_oid)));
4925 
4926  ownerId = ((Form_pg_foreign_server) GETSTRUCT(tuple))->srvowner;
4927 
4928  ReleaseSysCache(tuple);
4929 
4930  return has_privs_of_role(roleid, ownerId);
4931 }
4932 
4933 /*
4934  * Ownership check for an event trigger (specified by OID).
4935  */
4936 bool
4938 {
4939  HeapTuple tuple;
4940  Oid ownerId;
4941 
4942  /* Superusers bypass all permission checking. */
4943  if (superuser_arg(roleid))
4944  return true;
4945 
4947  if (!HeapTupleIsValid(tuple))
4948  ereport(ERROR,
4949  (errcode(ERRCODE_UNDEFINED_OBJECT),
4950  errmsg("event trigger with OID %u does not exist",
4951  et_oid)));
4952 
4953  ownerId = ((Form_pg_event_trigger) GETSTRUCT(tuple))->evtowner;
4954 
4955  ReleaseSysCache(tuple);
4956 
4957  return has_privs_of_role(roleid, ownerId);
4958 }
4959 
4960 /*
4961  * Ownership check for a database (specified by OID).
4962  */
4963 bool
4965 {
4966  HeapTuple tuple;
4967  Oid dba;
4968 
4969  /* Superusers bypass all permission checking. */
4970  if (superuser_arg(roleid))
4971  return true;
4972 
4973  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
4974  if (!HeapTupleIsValid(tuple))
4975  ereport(ERROR,
4976  (errcode(ERRCODE_UNDEFINED_DATABASE),
4977  errmsg("database with OID %u does not exist", db_oid)));
4978 
4979  dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
4980 
4981  ReleaseSysCache(tuple);
4982 
4983  return has_privs_of_role(roleid, dba);
4984 }
4985 
4986 /*
4987  * Ownership check for a collation (specified by OID).
4988  */
4989 bool
4991 {
4992  HeapTuple tuple;
4993  Oid ownerId;
4994 
4995  /* Superusers bypass all permission checking. */
4996  if (superuser_arg(roleid))
4997  return true;
4998 
4999  tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(coll_oid));
5000  if (!HeapTupleIsValid(tuple))
5001  ereport(ERROR,
5002  (errcode(ERRCODE_UNDEFINED_OBJECT),
5003  errmsg("collation with OID %u does not exist", coll_oid)));
5004 
5005  ownerId = ((Form_pg_collation) GETSTRUCT(tuple))->collowner;
5006 
5007  ReleaseSysCache(tuple);
5008 
5009  return has_privs_of_role(roleid, ownerId);
5010 }
5011 
5012 /*
5013  * Ownership check for a conversion (specified by OID).
5014  */
5015 bool
5017 {
5018  HeapTuple tuple;
5019  Oid ownerId;
5020 
5021  /* Superusers bypass all permission checking. */
5022  if (superuser_arg(roleid))
5023  return true;
5024 
5025  tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(conv_oid));
5026  if (!HeapTupleIsValid(tuple))
5027  ereport(ERROR,
5028  (errcode(ERRCODE_UNDEFINED_OBJECT),
5029  errmsg("conversion with OID %u does not exist", conv_oid)));
5030 
5031  ownerId = ((Form_pg_conversion) GETSTRUCT(tuple))->conowner;
5032 
5033  ReleaseSysCache(tuple);
5034 
5035  return has_privs_of_role(roleid, ownerId);
5036 }
5037 
5038 /*
5039  * Ownership check for an extension (specified by OID).
5040  */
5041 bool
5043 {
5044  Relation pg_extension;
5045  ScanKeyData entry[1];
5046  SysScanDesc scan;
5047  HeapTuple tuple;
5048  Oid ownerId;
5049 
5050  /* Superusers bypass all permission checking. */
5051  if (superuser_arg(roleid))
5052  return true;
5053 
5054  /* There's no syscache for pg_extension, so do it the hard way */
5056 
5057  ScanKeyInit(&entry[0],
5059  BTEqualStrategyNumber, F_OIDEQ,
5060  ObjectIdGetDatum(ext_oid));
5061 
5062  scan = systable_beginscan(pg_extension,
5063  ExtensionOidIndexId, true,
5064  NULL, 1, entry);
5065 
5066  tuple = systable_getnext(scan);
5067  if (!HeapTupleIsValid(tuple))
5068  ereport(ERROR,
5069  (errcode(ERRCODE_UNDEFINED_OBJECT),
5070  errmsg("extension with OID %u does not exist", ext_oid)));
5071 
5072  ownerId = ((Form_pg_extension) GETSTRUCT(tuple))->extowner;
5073 
5074  systable_endscan(scan);
5075  heap_close(pg_extension, AccessShareLock);
5076 
5077  return has_privs_of_role(roleid, ownerId);
5078 }
5079 
5080 /*
5081  * Ownership check for an publication (specified by OID).
5082  */
5083 bool
5085 {
5086  HeapTuple tuple;
5087  Oid ownerId;
5088 
5089  /* Superusers bypass all permission checking. */
5090  if (superuser_arg(roleid))
5091  return true;
5092 
5093  tuple = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pub_oid));
5094  if (!HeapTupleIsValid(tuple))
5095  ereport(ERROR,
5096  (errcode(ERRCODE_UNDEFINED_OBJECT),
5097  errmsg("publication with OID %u does not exist", pub_oid)));
5098 
5099  ownerId = ((Form_pg_publication) GETSTRUCT(tuple))->pubowner;
5100 
5101  ReleaseSysCache(tuple);
5102 
5103  return has_privs_of_role(roleid, ownerId);
5104 }
5105 
5106 /*
5107  * Ownership check for a subscription (specified by OID).
5108  */
5109 bool
5111 {
5112  HeapTuple tuple;
5113  Oid ownerId;
5114 
5115  /* Superusers bypass all permission checking. */
5116  if (superuser_arg(roleid))
5117  return true;
5118 
5120  if (!HeapTupleIsValid(tuple))
5121  ereport(ERROR,
5122  (errcode(ERRCODE_UNDEFINED_OBJECT),
5123  errmsg("subscription with OID %u does not exist", sub_oid)));
5124 
5125  ownerId = ((Form_pg_subscription) GETSTRUCT(tuple))->subowner;
5126 
5127  ReleaseSysCache(tuple);
5128 
5129  return has_privs_of_role(roleid, ownerId);
5130 }
5131 
5132 /*
5133  * Ownership check for a statistics object (specified by OID).
5134  */
5135 bool
5137 {
5138  HeapTuple tuple;
5139  Oid ownerId;
5140 
5141  /* Superusers bypass all permission checking. */
5142  if (superuser_arg(roleid))
5143  return true;
5144 
5145  tuple = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(stat_oid));
5146  if (!HeapTupleIsValid(tuple))
5147  ereport(ERROR,
5148  (errcode(ERRCODE_UNDEFINED_OBJECT),
5149  errmsg("statistics object with OID %u does not exist",
5150  stat_oid)));
5151 
5152  ownerId = ((Form_pg_statistic_ext) GETSTRUCT(tuple))->stxowner;
5153 
5154  ReleaseSysCache(tuple);
5155 
5156  return has_privs_of_role(roleid, ownerId);
5157 }
5158 
5159 /*
5160  * Check whether specified role has CREATEROLE privilege (or is a superuser)
5161  *
5162  * Note: roles do not have owners per se; instead we use this test in
5163  * places where an ownership-like permissions test is needed for a role.
5164  * Be sure to apply it to the role trying to do the operation, not the
5165  * role being operated on! Also note that this generally should not be
5166  * considered enough privilege if the target role is a superuser.
5167  * (We don't handle that consideration here because we want to give a
5168  * separate error message for such cases, so the caller has to deal with it.)
5169  */
5170 bool
5172 {
5173  bool result = false;
5174  HeapTuple utup;
5175 
5176  /* Superusers bypass all permission checking. */
5177  if (superuser_arg(roleid))
5178  return true;
5179 
5180  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5181  if (HeapTupleIsValid(utup))
5182  {
5183  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
5184  ReleaseSysCache(utup);
5185  }
5186  return result;
5187 }
5188 
5189 bool
5191 {
5192  bool result = false;
5193  HeapTuple utup;
5194 
5195  /* Superusers bypass all permission checking. */
5196  if (superuser_arg(roleid))
5197  return true;
5198 
5199  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5200  if (HeapTupleIsValid(utup))
5201  {
5202  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
5203  ReleaseSysCache(utup);
5204  }
5205  return result;
5206 }
5207 
5208 /*
5209  * Fetch pg_default_acl entry for given role, namespace and object type
5210  * (object type must be given in pg_default_acl's encoding).
5211  * Returns NULL if no such entry.
5212  */
5213 static Acl *
5214 get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
5215 {
5216  Acl *result = NULL;
5217  HeapTuple tuple;
5218 
5220  ObjectIdGetDatum(roleId),
5221  ObjectIdGetDatum(nsp_oid),
5222  CharGetDatum(objtype));
5223 
5224  if (HeapTupleIsValid(tuple))
5225  {
5226  Datum aclDatum;
5227  bool isNull;
5228 
5229  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
5231  &isNull);
5232  if (!isNull)
5233  result = DatumGetAclPCopy(aclDatum);
5234  ReleaseSysCache(tuple);
5235  }
5236 
5237  return result;
5238 }
5239 
5240 /*
5241  * Get default permissions for newly created object within given schema
5242  *
5243  * Returns NULL if built-in system defaults should be used
5244  */
5245 Acl *
5246 get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
5247 {
5248  Acl *result;
5249  Acl *glob_acl;
5250  Acl *schema_acl;
5251  Acl *def_acl;
5252  char defaclobjtype;
5253 
5254  /*
5255  * Use NULL during bootstrap, since pg_default_acl probably isn't there
5256  * yet.
5257  */
5259  return NULL;
5260 
5261  /* Check if object type is supported in pg_default_acl */
5262  switch (objtype)
5263  {
5264  case ACL_OBJECT_RELATION:
5265  defaclobjtype = DEFACLOBJ_RELATION;
5266  break;
5267 
5268  case ACL_OBJECT_SEQUENCE:
5269  defaclobjtype = DEFACLOBJ_SEQUENCE;
5270  break;
5271 
5272  case ACL_OBJECT_FUNCTION:
5273  defaclobjtype = DEFACLOBJ_FUNCTION;
5274  break;
5275 
5276  case ACL_OBJECT_TYPE:
5277  defaclobjtype = DEFACLOBJ_TYPE;
5278  break;
5279 
5280  case ACL_OBJECT_NAMESPACE:
5281  defaclobjtype = DEFACLOBJ_NAMESPACE;
5282  break;
5283 
5284  default:
5285  return NULL;
5286  }
5287 
5288  /* Look up the relevant pg_default_acl entries */
5289  glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
5290  schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
5291 
5292  /* Quick out if neither entry exists */
5293  if (glob_acl == NULL && schema_acl == NULL)
5294  return NULL;
5295 
5296  /* We need to know the hard-wired default value, too */
5297  def_acl = acldefault(objtype, ownerId);
5298 
5299  /* If there's no global entry, substitute the hard-wired default */
5300  if (glob_acl == NULL)
5301  glob_acl = def_acl;
5302 
5303  /* Merge in any per-schema privileges */
5304  result = aclmerge(glob_acl, schema_acl, ownerId);
5305 
5306  /*
5307  * For efficiency, we want to return NULL if the result equals default.
5308  * This requires sorting both arrays to get an accurate comparison.
5309  */
5310  aclitemsort(result);
5311  aclitemsort(def_acl);
5312  if (aclequal(result, def_acl))
5313  result = NULL;
5314 
5315  return result;
5316 }
5317 
5318 /*
5319  * Record initial privileges for the top-level object passed in.
5320  *
5321  * For the object passed in, this will record its ACL (if any) and the ACLs of
5322  * any sub-objects (eg: columns) into pg_init_privs.
5323  *
5324  * Any new kinds of objects which have ACLs associated with them and can be
5325  * added to an extension should be added to the if-else tree below.
5326  */
5327 void
5328 recordExtObjInitPriv(Oid objoid, Oid classoid)
5329 {
5330  /*
5331  * pg_class / pg_attribute
5332  *
5333  * If this is a relation then we need to see if there are any sub-objects
5334  * (eg: columns) for it and, if so, be sure to call
5335  * recordExtensionInitPrivWorker() for each one.
5336  */
5337  if (classoid == RelationRelationId)
5338  {
5339  Form_pg_class pg_class_tuple;
5340  Datum aclDatum;
5341  bool isNull;
5342  HeapTuple tuple;
5343 
5344  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
5345  if (!HeapTupleIsValid(tuple))
5346  elog(ERROR, "cache lookup failed for relation %u", objoid);
5347  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
5348 
5349  /* Indexes don't have permissions */
5350  if (pg_class_tuple->relkind == RELKIND_INDEX)
5351  return;
5352 
5353  /* Composite types don't have permissions either */
5354  if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
5355  return;
5356 
5357  /*
5358  * If this isn't a sequence, index, or composite type then it's
5359  * possibly going to have columns associated with it that might have
5360  * ACLs.
5361  */
5362  if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
5363  {
5364  AttrNumber curr_att;
5365  AttrNumber nattrs = pg_class_tuple->relnatts;
5366 
5367  for (curr_att = 1; curr_att <= nattrs; curr_att++)
5368  {
5369  HeapTuple attTuple;
5370  Datum attaclDatum;
5371 
5372  attTuple = SearchSysCache2(ATTNUM,
5373  ObjectIdGetDatum(objoid),
5374  Int16GetDatum(curr_att));
5375 
5376  if (!HeapTupleIsValid(attTuple))
5377  continue;
5378 
5379  /* ignore dropped columns */
5380  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
5381  {
5382  ReleaseSysCache(attTuple);
5383  continue;
5384  }
5385 
5386  attaclDatum = SysCacheGetAttr(ATTNUM, attTuple,
5388  &isNull);
5389 
5390  /* no need to do anything for a NULL ACL */
5391  if (isNull)
5392  {
5393  ReleaseSysCache(attTuple);
5394  continue;
5395  }
5396 
5397  recordExtensionInitPrivWorker(objoid, classoid, curr_att,
5398  DatumGetAclP(attaclDatum));
5399 
5400  ReleaseSysCache(attTuple);
5401  }
5402  }
5403 
5404  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
5405  &isNull);
5406 
5407  /* Add the record, if any, for the top-level object */
5408  if (!isNull)
5409  recordExtensionInitPrivWorker(objoid, classoid, 0,
5410  DatumGetAclP(aclDatum));
5411 
5412  ReleaseSysCache(tuple);
5413  }
5414  /* pg_foreign_data_wrapper */
5415  else if (classoid == ForeignDataWrapperRelationId)
5416  {
5417  Datum aclDatum;
5418  bool isNull;
5419  HeapTuple tuple;
5420 
5422  ObjectIdGetDatum(objoid));
5423  if (!HeapTupleIsValid(tuple))
5424  elog(ERROR, "cache lookup failed for foreign data wrapper %u",
5425  objoid);
5426 
5427  aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
5429  &isNull);
5430 
5431  /* Add the record, if any, for the top-level object */
5432  if (!isNull)
5433  recordExtensionInitPrivWorker(objoid, classoid, 0,
5434  DatumGetAclP(aclDatum));
5435 
5436  ReleaseSysCache(tuple);
5437  }
5438  /* pg_foreign_server */
5439  else if (classoid == ForeignServerRelationId)
5440  {
5441  Datum aclDatum;
5442  bool isNull;
5443  HeapTuple tuple;
5444 
5446  if (!HeapTupleIsValid(tuple))
5447  elog(ERROR, "cache lookup failed for foreign data wrapper %u",
5448  objoid);
5449 
5450  aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
5452  &isNull);
5453 
5454  /* Add the record, if any, for the top-level object */
5455  if (!isNull)
5456  recordExtensionInitPrivWorker(objoid, classoid, 0,
5457  DatumGetAclP(aclDatum));
5458 
5459  ReleaseSysCache(tuple);
5460  }
5461  /* pg_language */
5462  else if (classoid == LanguageRelationId)
5463  {
5464  Datum aclDatum;
5465  bool isNull;
5466  HeapTuple tuple;
5467 
5468  tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(objoid));
5469  if (!HeapTupleIsValid(tuple))
5470  elog(ERROR, "cache lookup failed for language %u", objoid);
5471 
5472  aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
5473  &isNull);
5474 
5475  /* Add the record, if any, for the top-level object */
5476  if (!isNull)
5477  recordExtensionInitPrivWorker(objoid, classoid, 0,
5478  DatumGetAclP(aclDatum));
5479 
5480  ReleaseSysCache(tuple);
5481  }
5482  /* pg_largeobject_metadata */
5483  else if (classoid == LargeObjectMetadataRelationId)
5484  {
5485  Datum aclDatum;
5486  bool isNull;
5487  HeapTuple tuple;
5488  ScanKeyData entry[1];
5489  SysScanDesc scan;
5490  Relation relation;
5491 
5493 
5494  /* There's no syscache for pg_largeobject_metadata */
5495  ScanKeyInit(&entry[0],
5497  BTEqualStrategyNumber, F_OIDEQ,
5498  ObjectIdGetDatum(objoid));
5499 
5500  scan = systable_beginscan(relation,
5502  NULL, 1, entry);
5503 
5504  tuple = systable_getnext(scan);
5505  if (!HeapTupleIsValid(tuple))
5506  elog(ERROR, "could not find tuple for large object %u", objoid);
5507 
5508  aclDatum = heap_getattr(tuple,
5510  RelationGetDescr(relation), &isNull);
5511 
5512  /* Add the record, if any, for the top-level object */
5513  if (!isNull)
5514  recordExtensionInitPrivWorker(objoid, classoid, 0,
5515  DatumGetAclP(aclDatum));
5516 
5517  systable_endscan(scan);
5518  }
5519  /* pg_namespace */
5520  else if (classoid == NamespaceRelationId)
5521  {
5522  Datum aclDatum;
5523  bool isNull;
5524  HeapTuple tuple;
5525 
5526  tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(objoid));
5527  if (!HeapTupleIsValid(tuple))
5528  elog(ERROR, "cache lookup failed for function %u", objoid);
5529 
5530  aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple,
5531  Anum_pg_namespace_nspacl, &isNull);
5532 
5533  /* Add the record, if any, for the top-level object */
5534  if (!isNull)
5535  recordExtensionInitPrivWorker(objoid, classoid, 0,
5536  DatumGetAclP(aclDatum));
5537 
5538  ReleaseSysCache(tuple);
5539  }
5540  /* pg_proc */
5541  else if (classoid == ProcedureRelationId)
5542  {
5543  Datum aclDatum;
5544  bool isNull;
5545  HeapTuple tuple;
5546 
5547  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(objoid));
5548  if (!HeapTupleIsValid(tuple))
5549  elog(ERROR, "cache lookup failed for function %u", objoid);
5550 
5551  aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
5552  &isNull);
5553 
5554  /* Add the record, if any, for the top-level object */
5555  if (!isNull)
5556  recordExtensionInitPrivWorker(objoid, classoid, 0,
5557  DatumGetAclP(aclDatum));
5558 
5559  ReleaseSysCache(tuple);
5560  }
5561  /* pg_type */
5562  else if (classoid == TypeRelationId)
5563  {
5564  Datum aclDatum;
5565  bool isNull;
5566  HeapTuple tuple;
5567 
5568  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(objoid));
5569  if (!HeapTupleIsValid(tuple))
5570  elog(ERROR, "cache lookup failed for function %u", objoid);
5571 
5572  aclDatum = SysCacheGetAttr(TYPEOID, tuple, Anum_pg_type_typacl,
5573  &isNull);
5574 
5575  /* Add the record, if any, for the top-level object */
5576  if (!isNull)
5577  recordExtensionInitPrivWorker(objoid, classoid, 0,
5578  DatumGetAclP(aclDatum));
5579 
5580  ReleaseSysCache(tuple);
5581  }
5582  else if (classoid == AccessMethodRelationId ||
5583  classoid == AggregateRelationId ||
5584  classoid == CastRelationId ||
5585  classoid == CollationRelationId ||
5586  classoid == ConversionRelationId ||
5587  classoid == EventTriggerRelationId ||
5588  classoid == OperatorRelationId ||
5589  classoid == OperatorClassRelationId ||
5590  classoid == OperatorFamilyRelationId ||
5591  classoid == NamespaceRelationId ||
5592  classoid == TSConfigRelationId ||
5593  classoid == TSDictionaryRelationId ||
5594  classoid == TSParserRelationId ||
5595  classoid == TSTemplateRelationId ||
5596  classoid == TransformRelationId
5597  )
5598  {
5599  /* no ACL for these object types, so do nothing. */
5600  }
5601 
5602  /*
5603  * complain if we are given a class OID for a class that extensions don't
5604  * support or that we don't recognize.
5605  */
5606  else
5607  {
5608  elog(ERROR, "unrecognized or unsupported class OID: %u", classoid);
5609  }
5610 }
5611 
5612 /*
5613  * For the object passed in, remove its ACL and the ACLs of any object subIds
5614  * from pg_init_privs (via recordExtensionInitPrivWorker()).
5615  */
5616 void
5617 removeExtObjInitPriv(Oid objoid, Oid classoid)
5618 {
5619  /*
5620  * If this is a relation then we need to see if there are any sub-objects
5621  * (eg: columns) for it and, if so, be sure to call
5622  * recordExtensionInitPrivWorker() for each one.
5623  */
5624  if (classoid == RelationRelationId)
5625  {
5626  Form_pg_class pg_class_tuple;
5627  HeapTuple tuple;
5628 
5629  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
5630  if (!HeapTupleIsValid(tuple))
5631  elog(ERROR, "cache lookup failed for relation %u", objoid);
5632  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
5633 
5634  /* Indexes don't have permissions */
5635  if (pg_class_tuple->relkind == RELKIND_INDEX)
5636  return;
5637 
5638  /* Composite types don't have permissions either */
5639  if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
5640  return;
5641 
5642  /*
5643  * If this isn't a sequence, index, or composite type then it's
5644  * possibly going to have columns associated with it that might have
5645  * ACLs.
5646  */
5647  if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
5648  {
5649  AttrNumber curr_att;
5650  AttrNumber nattrs = pg_class_tuple->relnatts;
5651 
5652  for (curr_att = 1; curr_att <= nattrs; curr_att++)
5653  {
5654  HeapTuple attTuple;
5655 
5656  attTuple = SearchSysCache2(ATTNUM,
5657  ObjectIdGetDatum(objoid),
5658  Int16GetDatum(curr_att));
5659 
5660  if (!HeapTupleIsValid(attTuple))
5661  continue;
5662 
5663  /* when removing, remove all entries, even dropped columns */
5664 
5665  recordExtensionInitPrivWorker(objoid, classoid, curr_att, NULL);
5666 
5667  ReleaseSysCache(attTuple);
5668  }
5669  }
5670 
5671  ReleaseSysCache(tuple);
5672  }
5673 
5674  /* Remove the record, if any, for the top-level object */
5675  recordExtensionInitPrivWorker(objoid, classoid, 0, NULL);
5676 }
5677 
5678 /*
5679  * Record initial ACL for an extension object
5680  *
5681  * Can be called at any ti