PostgreSQL Source Code  git master
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-2023, 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/tableam.h"
25 #include "access/xact.h"
26 #include "catalog/binary_upgrade.h"
27 #include "catalog/catalog.h"
28 #include "catalog/dependency.h"
29 #include "catalog/indexing.h"
30 #include "catalog/objectaccess.h"
31 #include "catalog/pg_aggregate.h"
32 #include "catalog/pg_am.h"
33 #include "catalog/pg_authid.h"
34 #include "catalog/pg_cast.h"
35 #include "catalog/pg_class.h"
36 #include "catalog/pg_collation.h"
37 #include "catalog/pg_conversion.h"
38 #include "catalog/pg_database.h"
39 #include "catalog/pg_default_acl.h"
41 #include "catalog/pg_extension.h"
44 #include "catalog/pg_init_privs.h"
45 #include "catalog/pg_language.h"
46 #include "catalog/pg_largeobject.h"
48 #include "catalog/pg_namespace.h"
49 #include "catalog/pg_opclass.h"
50 #include "catalog/pg_operator.h"
51 #include "catalog/pg_opfamily.h"
53 #include "catalog/pg_proc.h"
56 #include "catalog/pg_tablespace.h"
57 #include "catalog/pg_transform.h"
58 #include "catalog/pg_ts_config.h"
59 #include "catalog/pg_ts_dict.h"
60 #include "catalog/pg_ts_parser.h"
61 #include "catalog/pg_ts_template.h"
62 #include "catalog/pg_type.h"
63 #include "commands/dbcommands.h"
64 #include "commands/defrem.h"
65 #include "commands/event_trigger.h"
66 #include "commands/extension.h"
67 #include "commands/proclang.h"
68 #include "commands/tablespace.h"
69 #include "foreign/foreign.h"
70 #include "miscadmin.h"
71 #include "nodes/makefuncs.h"
72 #include "parser/parse_func.h"
73 #include "parser/parse_type.h"
74 #include "utils/acl.h"
75 #include "utils/aclchk_internal.h"
76 #include "utils/builtins.h"
77 #include "utils/fmgroids.h"
78 #include "utils/guc.h"
79 #include "utils/lsyscache.h"
80 #include "utils/rel.h"
81 #include "utils/syscache.h"
82 
83 /*
84  * Internal format used by ALTER DEFAULT PRIVILEGES.
85  */
86 typedef struct
87 {
88  Oid roleid; /* owning role */
89  Oid nspid; /* namespace, or InvalidOid if none */
90  /* remaining fields are same as in InternalGrant: */
91  bool is_grant;
93  bool all_privs;
99 
100 /*
101  * When performing a binary-upgrade, pg_dump will call a function to set
102  * this variable to let us know that we need to populate the pg_init_privs
103  * table for the GRANT/REVOKE commands while this variable is set to true.
104  */
106 
107 static void ExecGrantStmt_oids(InternalGrant *istmt);
108 static void ExecGrant_Relation(InternalGrant *istmt);
109 static void ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs,
110  void (*object_check) (InternalGrant *istmt, HeapTuple tuple));
111 static void ExecGrant_Language_check(InternalGrant *istmt, HeapTuple tuple);
112 static void ExecGrant_Largeobject(InternalGrant *istmt);
113 static void ExecGrant_Type_check(InternalGrant *istmt, HeapTuple tuple);
114 static void ExecGrant_Parameter(InternalGrant *istmt);
115 
116 static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames);
117 static void SetDefaultACL(InternalDefaultACL *iacls);
118 
119 static List *objectNamesToOids(ObjectType objtype, List *objnames,
120  bool is_grant);
121 static List *objectsInSchemaToOids(ObjectType objtype, List *nspnames);
122 static List *getRelationsInNamespace(Oid namespaceId, char relkind);
123 static void expand_col_privileges(List *colnames, Oid table_oid,
124  AclMode this_privileges,
125  AclMode *col_privileges,
126  int num_col_privileges);
127 static void expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
128  AclMode this_privileges,
129  AclMode *col_privileges,
130  int num_col_privileges);
131 static AclMode string_to_privilege(const char *privname);
132 static const char *privilege_to_string(AclMode privilege);
133 static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions,
134  bool all_privs, AclMode privileges,
135  Oid objectId, Oid grantorId,
136  ObjectType objtype, const char *objname,
137  AttrNumber att_number, const char *colname);
138 static AclMode pg_aclmask(ObjectType objtype, Oid object_oid, AttrNumber attnum,
139  Oid roleid, AclMode mask, AclMaskHow how);
140 static AclMode object_aclmask(Oid classid, Oid objectid, Oid roleid,
141  AclMode mask, AclMaskHow how);
143  Oid roleid, AclMode mask, AclMaskHow how);
145  Oid roleid, AclMode mask,
146  AclMaskHow how, bool *is_missing);
147 static AclMode pg_class_aclmask_ext(Oid table_oid, Oid roleid,
148  AclMode mask, AclMaskHow how,
149  bool *is_missing);
150 static AclMode pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid,
151  AclMode mask, AclMaskHow how);
152 static AclMode pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
153  AclMode mask, AclMaskHow how, Snapshot snapshot);
154 static AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
155  AclMode mask, AclMaskHow how);
156 static AclMode pg_type_aclmask(Oid type_oid, Oid roleid,
157  AclMode mask, AclMaskHow how);
158 static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid,
159  Acl *new_acl);
160 static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
161  Acl *new_acl);
162 
163 
164 /*
165  * If is_grant is true, adds the given privileges for the list of
166  * grantees to the existing old_acl. If is_grant is false, the
167  * privileges for the given grantees are removed from old_acl.
168  *
169  * NB: the original old_acl is pfree'd.
170  */
171 static Acl *
172 merge_acl_with_grant(Acl *old_acl, bool is_grant,
173  bool grant_option, DropBehavior behavior,
174  List *grantees, AclMode privileges,
175  Oid grantorId, Oid ownerId)
176 {
177  unsigned modechg;
178  ListCell *j;
179  Acl *new_acl;
180 
181  modechg = is_grant ? ACL_MODECHG_ADD : ACL_MODECHG_DEL;
182 
183  new_acl = old_acl;
184 
185  foreach(j, grantees)
186  {
187  AclItem aclitem;
188  Acl *newer_acl;
189 
190  aclitem.ai_grantee = lfirst_oid(j);
191 
192  /*
193  * Grant options can only be granted to individual roles, not PUBLIC.
194  * The reason is that if a user would re-grant a privilege that he
195  * held through PUBLIC, and later the user is removed, the situation
196  * is impossible to clean up.
197  */
198  if (is_grant && grant_option && aclitem.ai_grantee == ACL_ID_PUBLIC)
199  ereport(ERROR,
200  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
201  errmsg("grant options can only be granted to roles")));
202 
203  aclitem.ai_grantor = grantorId;
204 
205  /*
206  * The asymmetry in the conditions here comes from the spec. In
207  * GRANT, the grant_option flag signals WITH GRANT OPTION, which means
208  * to grant both the basic privilege and its grant option. But in
209  * REVOKE, plain revoke revokes both the basic privilege and its grant
210  * option, while REVOKE GRANT OPTION revokes only the option.
211  */
213  (is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
214  (!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS);
215 
216  newer_acl = aclupdate(new_acl, &aclitem, modechg, ownerId, behavior);
217 
218  /* avoid memory leak when there are many grantees */
219  pfree(new_acl);
220  new_acl = newer_acl;
221  }
222 
223  return new_acl;
224 }
225 
226 /*
227  * Restrict the privileges to what we can actually grant, and emit
228  * the standards-mandated warning and error messages.
229  */
230 static AclMode
231 restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
232  AclMode privileges, Oid objectId, Oid grantorId,
233  ObjectType objtype, const char *objname,
234  AttrNumber att_number, const char *colname)
235 {
236  AclMode this_privileges;
237  AclMode whole_mask;
238 
239  switch (objtype)
240  {
241  case OBJECT_COLUMN:
242  whole_mask = ACL_ALL_RIGHTS_COLUMN;
243  break;
244  case OBJECT_TABLE:
245  whole_mask = ACL_ALL_RIGHTS_RELATION;
246  break;
247  case OBJECT_SEQUENCE:
248  whole_mask = ACL_ALL_RIGHTS_SEQUENCE;
249  break;
250  case OBJECT_DATABASE:
251  whole_mask = ACL_ALL_RIGHTS_DATABASE;
252  break;
253  case OBJECT_FUNCTION:
254  whole_mask = ACL_ALL_RIGHTS_FUNCTION;
255  break;
256  case OBJECT_LANGUAGE:
257  whole_mask = ACL_ALL_RIGHTS_LANGUAGE;
258  break;
259  case OBJECT_LARGEOBJECT:
260  whole_mask = ACL_ALL_RIGHTS_LARGEOBJECT;
261  break;
262  case OBJECT_SCHEMA:
263  whole_mask = ACL_ALL_RIGHTS_SCHEMA;
264  break;
265  case OBJECT_TABLESPACE:
266  whole_mask = ACL_ALL_RIGHTS_TABLESPACE;
267  break;
268  case OBJECT_FDW:
269  whole_mask = ACL_ALL_RIGHTS_FDW;
270  break;
272  whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
273  break;
275  elog(ERROR, "grantable rights not supported for event triggers");
276  /* not reached, but keep compiler quiet */
277  return ACL_NO_RIGHTS;
278  case OBJECT_TYPE:
279  whole_mask = ACL_ALL_RIGHTS_TYPE;
280  break;
282  whole_mask = ACL_ALL_RIGHTS_PARAMETER_ACL;
283  break;
284  default:
285  elog(ERROR, "unrecognized object type: %d", objtype);
286  /* not reached, but keep compiler quiet */
287  return ACL_NO_RIGHTS;
288  }
289 
290  /*
291  * If we found no grant options, consider whether to issue a hard error.
292  * Per spec, having any privilege at all on the object will get you by
293  * here.
294  */
295  if (avail_goptions == ACL_NO_RIGHTS)
296  {
297  if (pg_aclmask(objtype, objectId, att_number, grantorId,
298  whole_mask | ACL_GRANT_OPTION_FOR(whole_mask),
300  {
301  if (objtype == OBJECT_COLUMN && colname)
302  aclcheck_error_col(ACLCHECK_NO_PRIV, objtype, objname, colname);
303  else
304  aclcheck_error(ACLCHECK_NO_PRIV, objtype, objname);
305  }
306  }
307 
308  /*
309  * Restrict the operation to what we can actually grant or revoke, and
310  * issue a warning if appropriate. (For REVOKE this isn't quite what the
311  * spec says to do: the spec seems to want a warning only if no privilege
312  * bits actually change in the ACL. In practice that behavior seems much
313  * too noisy, as well as inconsistent with the GRANT case.)
314  */
315  this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
316  if (is_grant)
317  {
318  if (this_privileges == 0)
319  {
320  if (objtype == OBJECT_COLUMN && colname)
322  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
323  errmsg("no privileges were granted for column \"%s\" of relation \"%s\"",
324  colname, objname)));
325  else
327  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
328  errmsg("no privileges were granted for \"%s\"",
329  objname)));
330  }
331  else if (!all_privs && this_privileges != privileges)
332  {
333  if (objtype == OBJECT_COLUMN && colname)
335  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
336  errmsg("not all privileges were granted for column \"%s\" of relation \"%s\"",
337  colname, objname)));
338  else
340  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
341  errmsg("not all privileges were granted for \"%s\"",
342  objname)));
343  }
344  }
345  else
346  {
347  if (this_privileges == 0)
348  {
349  if (objtype == OBJECT_COLUMN && colname)
351  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
352  errmsg("no privileges could be revoked for column \"%s\" of relation \"%s\"",
353  colname, objname)));
354  else
356  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
357  errmsg("no privileges could be revoked for \"%s\"",
358  objname)));
359  }
360  else if (!all_privs && this_privileges != privileges)
361  {
362  if (objtype == OBJECT_COLUMN && colname)
364  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
365  errmsg("not all privileges could be revoked for column \"%s\" of relation \"%s\"",
366  colname, objname)));
367  else
369  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
370  errmsg("not all privileges could be revoked for \"%s\"",
371  objname)));
372  }
373  }
374 
375  return this_privileges;
376 }
377 
378 /*
379  * Called to execute the utility commands GRANT and REVOKE
380  */
381 void
383 {
384  InternalGrant istmt;
385  ListCell *cell;
386  const char *errormsg;
387  AclMode all_privileges;
388 
389  if (stmt->grantor)
390  {
391  Oid grantor;
392 
393  grantor = get_rolespec_oid(stmt->grantor, false);
394 
395  /*
396  * Currently, this clause is only for SQL compatibility, not very
397  * interesting otherwise.
398  */
399  if (grantor != GetUserId())
400  ereport(ERROR,
401  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
402  errmsg("grantor must be current user")));
403  }
404 
405  /*
406  * Turn the regular GrantStmt into the InternalGrant form.
407  */
408  istmt.is_grant = stmt->is_grant;
409  istmt.objtype = stmt->objtype;
410 
411  /* Collect the OIDs of the target objects */
412  switch (stmt->targtype)
413  {
414  case ACL_TARGET_OBJECT:
415  istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects,
416  stmt->is_grant);
417  break;
419  istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
420  break;
421  /* ACL_TARGET_DEFAULTS should not be seen here */
422  default:
423  elog(ERROR, "unrecognized GrantStmt.targtype: %d",
424  (int) stmt->targtype);
425  }
426 
427  /* all_privs to be filled below */
428  /* privileges to be filled below */
429  istmt.col_privs = NIL; /* may get filled below */
430  istmt.grantees = NIL; /* filled below */
431  istmt.grant_option = stmt->grant_option;
432  istmt.behavior = stmt->behavior;
433 
434  /*
435  * Convert the RoleSpec list into an Oid list. Note that at this point we
436  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
437  * there shouldn't be any additional work needed to support this case.
438  */
439  foreach(cell, stmt->grantees)
440  {
441  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
442  Oid grantee_uid;
443 
444  switch (grantee->roletype)
445  {
446  case ROLESPEC_PUBLIC:
447  grantee_uid = ACL_ID_PUBLIC;
448  break;
449  default:
450  grantee_uid = get_rolespec_oid(grantee, false);
451  break;
452  }
453  istmt.grantees = lappend_oid(istmt.grantees, grantee_uid);
454  }
455 
456  /*
457  * Convert stmt->privileges, a list of AccessPriv nodes, into an AclMode
458  * bitmask. Note: objtype can't be OBJECT_COLUMN.
459  */
460  switch (stmt->objtype)
461  {
462  case OBJECT_TABLE:
463 
464  /*
465  * Because this might be a sequence, we test both relation and
466  * sequence bits, and later do a more limited test when we know
467  * the object type.
468  */
470  errormsg = gettext_noop("invalid privilege type %s for relation");
471  break;
472  case OBJECT_SEQUENCE:
473  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
474  errormsg = gettext_noop("invalid privilege type %s for sequence");
475  break;
476  case OBJECT_DATABASE:
477  all_privileges = ACL_ALL_RIGHTS_DATABASE;
478  errormsg = gettext_noop("invalid privilege type %s for database");
479  break;
480  case OBJECT_DOMAIN:
481  all_privileges = ACL_ALL_RIGHTS_TYPE;
482  errormsg = gettext_noop("invalid privilege type %s for domain");
483  break;
484  case OBJECT_FUNCTION:
485  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
486  errormsg = gettext_noop("invalid privilege type %s for function");
487  break;
488  case OBJECT_LANGUAGE:
489  all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
490  errormsg = gettext_noop("invalid privilege type %s for language");
491  break;
492  case OBJECT_LARGEOBJECT:
493  all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
494  errormsg = gettext_noop("invalid privilege type %s for large object");
495  break;
496  case OBJECT_SCHEMA:
497  all_privileges = ACL_ALL_RIGHTS_SCHEMA;
498  errormsg = gettext_noop("invalid privilege type %s for schema");
499  break;
500  case OBJECT_PROCEDURE:
501  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
502  errormsg = gettext_noop("invalid privilege type %s for procedure");
503  break;
504  case OBJECT_ROUTINE:
505  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
506  errormsg = gettext_noop("invalid privilege type %s for routine");
507  break;
508  case OBJECT_TABLESPACE:
509  all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
510  errormsg = gettext_noop("invalid privilege type %s for tablespace");
511  break;
512  case OBJECT_TYPE:
513  all_privileges = ACL_ALL_RIGHTS_TYPE;
514  errormsg = gettext_noop("invalid privilege type %s for type");
515  break;
516  case OBJECT_FDW:
517  all_privileges = ACL_ALL_RIGHTS_FDW;
518  errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
519  break;
521  all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
522  errormsg = gettext_noop("invalid privilege type %s for foreign server");
523  break;
525  all_privileges = ACL_ALL_RIGHTS_PARAMETER_ACL;
526  errormsg = gettext_noop("invalid privilege type %s for parameter");
527  break;
528  default:
529  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
530  (int) stmt->objtype);
531  /* keep compiler quiet */
532  all_privileges = ACL_NO_RIGHTS;
533  errormsg = NULL;
534  }
535 
536  if (stmt->privileges == NIL)
537  {
538  istmt.all_privs = true;
539 
540  /*
541  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
542  * depending on the object type
543  */
544  istmt.privileges = ACL_NO_RIGHTS;
545  }
546  else
547  {
548  istmt.all_privs = false;
549  istmt.privileges = ACL_NO_RIGHTS;
550 
551  foreach(cell, stmt->privileges)
552  {
553  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
554  AclMode priv;
555 
556  /*
557  * If it's a column-level specification, we just set it aside in
558  * col_privs for the moment; but insist it's for a relation.
559  */
560  if (privnode->cols)
561  {
562  if (stmt->objtype != OBJECT_TABLE)
563  ereport(ERROR,
564  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
565  errmsg("column privileges are only valid for relations")));
566  istmt.col_privs = lappend(istmt.col_privs, privnode);
567  continue;
568  }
569 
570  if (privnode->priv_name == NULL) /* parser mistake? */
571  elog(ERROR, "AccessPriv node must specify privilege or columns");
572  priv = string_to_privilege(privnode->priv_name);
573 
574  if (priv & ~((AclMode) all_privileges))
575  ereport(ERROR,
576  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
577  errmsg(errormsg, privilege_to_string(priv))));
578 
579  istmt.privileges |= priv;
580  }
581  }
582 
583  ExecGrantStmt_oids(&istmt);
584 }
585 
586 /*
587  * ExecGrantStmt_oids
588  *
589  * Internal entry point for granting and revoking privileges.
590  */
591 static void
593 {
594  switch (istmt->objtype)
595  {
596  case OBJECT_TABLE:
597  case OBJECT_SEQUENCE:
598  ExecGrant_Relation(istmt);
599  break;
600  case OBJECT_DATABASE:
601  ExecGrant_common(istmt, DatabaseRelationId, ACL_ALL_RIGHTS_DATABASE, NULL);
602  break;
603  case OBJECT_DOMAIN:
604  case OBJECT_TYPE:
606  break;
607  case OBJECT_FDW:
608  ExecGrant_common(istmt, ForeignDataWrapperRelationId, ACL_ALL_RIGHTS_FDW, NULL);
609  break;
611  ExecGrant_common(istmt, ForeignServerRelationId, ACL_ALL_RIGHTS_FOREIGN_SERVER, NULL);
612  break;
613  case OBJECT_FUNCTION:
614  case OBJECT_PROCEDURE:
615  case OBJECT_ROUTINE:
616  ExecGrant_common(istmt, ProcedureRelationId, ACL_ALL_RIGHTS_FUNCTION, NULL);
617  break;
618  case OBJECT_LANGUAGE:
620  break;
621  case OBJECT_LARGEOBJECT:
622  ExecGrant_Largeobject(istmt);
623  break;
624  case OBJECT_SCHEMA:
625  ExecGrant_common(istmt, NamespaceRelationId, ACL_ALL_RIGHTS_SCHEMA, NULL);
626  break;
627  case OBJECT_TABLESPACE:
628  ExecGrant_common(istmt, TableSpaceRelationId, ACL_ALL_RIGHTS_TABLESPACE, NULL);
629  break;
631  ExecGrant_Parameter(istmt);
632  break;
633  default:
634  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
635  (int) istmt->objtype);
636  }
637 
638  /*
639  * Pass the info to event triggers about the just-executed GRANT. Note
640  * that we prefer to do it after actually executing it, because that gives
641  * the functions a chance to adjust the istmt with privileges actually
642  * granted.
643  */
646 }
647 
648 /*
649  * objectNamesToOids
650  *
651  * Turn a list of object names of a given type into an Oid list.
652  *
653  * XXX: This function doesn't take any sort of locks on the objects whose
654  * names it looks up. In the face of concurrent DDL, we might easily latch
655  * onto an old version of an object, causing the GRANT or REVOKE statement
656  * to fail.
657  */
658 static List *
659 objectNamesToOids(ObjectType objtype, List *objnames, bool is_grant)
660 {
661  List *objects = NIL;
662  ListCell *cell;
663 
664  Assert(objnames != NIL);
665 
666  switch (objtype)
667  {
668  case OBJECT_TABLE:
669  case OBJECT_SEQUENCE:
670  foreach(cell, objnames)
671  {
672  RangeVar *relvar = (RangeVar *) lfirst(cell);
673  Oid relOid;
674 
675  relOid = RangeVarGetRelid(relvar, NoLock, false);
676  objects = lappend_oid(objects, relOid);
677  }
678  break;
679  case OBJECT_DATABASE:
680  foreach(cell, objnames)
681  {
682  char *dbname = strVal(lfirst(cell));
683  Oid dbid;
684 
685  dbid = get_database_oid(dbname, false);
686  objects = lappend_oid(objects, dbid);
687  }
688  break;
689  case OBJECT_DOMAIN:
690  case OBJECT_TYPE:
691  foreach(cell, objnames)
692  {
693  List *typname = (List *) lfirst(cell);
694  Oid oid;
695 
697  objects = lappend_oid(objects, oid);
698  }
699  break;
700  case OBJECT_FUNCTION:
701  foreach(cell, objnames)
702  {
703  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
704  Oid funcid;
705 
706  funcid = LookupFuncWithArgs(OBJECT_FUNCTION, func, false);
707  objects = lappend_oid(objects, funcid);
708  }
709  break;
710  case OBJECT_LANGUAGE:
711  foreach(cell, objnames)
712  {
713  char *langname = strVal(lfirst(cell));
714  Oid oid;
715 
716  oid = get_language_oid(langname, false);
717  objects = lappend_oid(objects, oid);
718  }
719  break;
720  case OBJECT_LARGEOBJECT:
721  foreach(cell, objnames)
722  {
723  Oid lobjOid = oidparse(lfirst(cell));
724 
725  if (!LargeObjectExists(lobjOid))
726  ereport(ERROR,
727  (errcode(ERRCODE_UNDEFINED_OBJECT),
728  errmsg("large object %u does not exist",
729  lobjOid)));
730 
731  objects = lappend_oid(objects, lobjOid);
732  }
733  break;
734  case OBJECT_SCHEMA:
735  foreach(cell, objnames)
736  {
737  char *nspname = strVal(lfirst(cell));
738  Oid oid;
739 
740  oid = get_namespace_oid(nspname, false);
741  objects = lappend_oid(objects, oid);
742  }
743  break;
744  case OBJECT_PROCEDURE:
745  foreach(cell, objnames)
746  {
747  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
748  Oid procid;
749 
750  procid = LookupFuncWithArgs(OBJECT_PROCEDURE, func, false);
751  objects = lappend_oid(objects, procid);
752  }
753  break;
754  case OBJECT_ROUTINE:
755  foreach(cell, objnames)
756  {
757  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
758  Oid routid;
759 
760  routid = LookupFuncWithArgs(OBJECT_ROUTINE, func, false);
761  objects = lappend_oid(objects, routid);
762  }
763  break;
764  case OBJECT_TABLESPACE:
765  foreach(cell, objnames)
766  {
767  char *spcname = strVal(lfirst(cell));
768  Oid spcoid;
769 
770  spcoid = get_tablespace_oid(spcname, false);
771  objects = lappend_oid(objects, spcoid);
772  }
773  break;
774  case OBJECT_FDW:
775  foreach(cell, objnames)
776  {
777  char *fdwname = strVal(lfirst(cell));
778  Oid fdwid = get_foreign_data_wrapper_oid(fdwname, false);
779 
780  objects = lappend_oid(objects, fdwid);
781  }
782  break;
784  foreach(cell, objnames)
785  {
786  char *srvname = strVal(lfirst(cell));
787  Oid srvid = get_foreign_server_oid(srvname, false);
788 
789  objects = lappend_oid(objects, srvid);
790  }
791  break;
793  foreach(cell, objnames)
794  {
795  /*
796  * In this code we represent a GUC by the OID of its entry in
797  * pg_parameter_acl, which we have to manufacture here if it
798  * doesn't exist yet. (That's a hack for sure, but it avoids
799  * messing with all the GRANT/REVOKE infrastructure that
800  * expects to use OIDs for object identities.) However, if
801  * this is a REVOKE, we can instead just ignore any GUCs that
802  * don't have such an entry, as they must not have any
803  * privileges needing removal.
804  */
805  char *parameter = strVal(lfirst(cell));
806  Oid parameterId = ParameterAclLookup(parameter, true);
807 
808  if (!OidIsValid(parameterId) && is_grant)
809  {
810  parameterId = ParameterAclCreate(parameter);
811 
812  /*
813  * Prevent error when processing duplicate objects, and
814  * make this new entry visible so that ExecGrant_Parameter
815  * can update it.
816  */
818  }
819  if (OidIsValid(parameterId))
820  objects = lappend_oid(objects, parameterId);
821  }
822  break;
823  default:
824  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
825  (int) objtype);
826  }
827 
828  return objects;
829 }
830 
831 /*
832  * objectsInSchemaToOids
833  *
834  * Find all objects of a given type in specified schemas, and make a list
835  * of their Oids. We check USAGE privilege on the schemas, but there is
836  * no privilege checking on the individual objects here.
837  */
838 static List *
840 {
841  List *objects = NIL;
842  ListCell *cell;
843 
844  foreach(cell, nspnames)
845  {
846  char *nspname = strVal(lfirst(cell));
847  Oid namespaceId;
848  List *objs;
849 
850  namespaceId = LookupExplicitNamespace(nspname, false);
851 
852  switch (objtype)
853  {
854  case OBJECT_TABLE:
855  objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
856  objects = list_concat(objects, objs);
857  objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
858  objects = list_concat(objects, objs);
859  objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
860  objects = list_concat(objects, objs);
861  objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
862  objects = list_concat(objects, objs);
863  objs = getRelationsInNamespace(namespaceId, RELKIND_PARTITIONED_TABLE);
864  objects = list_concat(objects, objs);
865  break;
866  case OBJECT_SEQUENCE:
867  objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
868  objects = list_concat(objects, objs);
869  break;
870  case OBJECT_FUNCTION:
871  case OBJECT_PROCEDURE:
872  case OBJECT_ROUTINE:
873  {
874  ScanKeyData key[2];
875  int keycount;
876  Relation rel;
877  TableScanDesc scan;
878  HeapTuple tuple;
879 
880  keycount = 0;
881  ScanKeyInit(&key[keycount++],
882  Anum_pg_proc_pronamespace,
883  BTEqualStrategyNumber, F_OIDEQ,
884  ObjectIdGetDatum(namespaceId));
885 
886  if (objtype == OBJECT_FUNCTION)
887  /* includes aggregates and window functions */
888  ScanKeyInit(&key[keycount++],
889  Anum_pg_proc_prokind,
890  BTEqualStrategyNumber, F_CHARNE,
891  CharGetDatum(PROKIND_PROCEDURE));
892  else if (objtype == OBJECT_PROCEDURE)
893  ScanKeyInit(&key[keycount++],
894  Anum_pg_proc_prokind,
895  BTEqualStrategyNumber, F_CHAREQ,
896  CharGetDatum(PROKIND_PROCEDURE));
897 
898  rel = table_open(ProcedureRelationId, AccessShareLock);
899  scan = table_beginscan_catalog(rel, keycount, key);
900 
901  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
902  {
903  Oid oid = ((Form_pg_proc) GETSTRUCT(tuple))->oid;
904 
905  objects = lappend_oid(objects, oid);
906  }
907 
908  table_endscan(scan);
910  }
911  break;
912  default:
913  /* should not happen */
914  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
915  (int) objtype);
916  }
917  }
918 
919  return objects;
920 }
921 
922 /*
923  * getRelationsInNamespace
924  *
925  * Return Oid list of relations in given namespace filtered by relation kind
926  */
927 static List *
928 getRelationsInNamespace(Oid namespaceId, char relkind)
929 {
930  List *relations = NIL;
931  ScanKeyData key[2];
932  Relation rel;
933  TableScanDesc scan;
934  HeapTuple tuple;
935 
936  ScanKeyInit(&key[0],
937  Anum_pg_class_relnamespace,
938  BTEqualStrategyNumber, F_OIDEQ,
939  ObjectIdGetDatum(namespaceId));
940  ScanKeyInit(&key[1],
941  Anum_pg_class_relkind,
942  BTEqualStrategyNumber, F_CHAREQ,
943  CharGetDatum(relkind));
944 
945  rel = table_open(RelationRelationId, AccessShareLock);
946  scan = table_beginscan_catalog(rel, 2, key);
947 
948  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
949  {
950  Oid oid = ((Form_pg_class) GETSTRUCT(tuple))->oid;
951 
952  relations = lappend_oid(relations, oid);
953  }
954 
955  table_endscan(scan);
957 
958  return relations;
959 }
960 
961 
962 /*
963  * ALTER DEFAULT PRIVILEGES statement
964  */
965 void
967 {
968  GrantStmt *action = stmt->action;
969  InternalDefaultACL iacls;
970  ListCell *cell;
971  List *rolespecs = NIL;
972  List *nspnames = NIL;
973  DefElem *drolespecs = NULL;
974  DefElem *dnspnames = NULL;
975  AclMode all_privileges;
976  const char *errormsg;
977 
978  /* Deconstruct the "options" part of the statement */
979  foreach(cell, stmt->options)
980  {
981  DefElem *defel = (DefElem *) lfirst(cell);
982 
983  if (strcmp(defel->defname, "schemas") == 0)
984  {
985  if (dnspnames)
986  errorConflictingDefElem(defel, pstate);
987  dnspnames = defel;
988  }
989  else if (strcmp(defel->defname, "roles") == 0)
990  {
991  if (drolespecs)
992  errorConflictingDefElem(defel, pstate);
993  drolespecs = defel;
994  }
995  else
996  elog(ERROR, "option \"%s\" not recognized", defel->defname);
997  }
998 
999  if (dnspnames)
1000  nspnames = (List *) dnspnames->arg;
1001  if (drolespecs)
1002  rolespecs = (List *) drolespecs->arg;
1003 
1004  /* Prepare the InternalDefaultACL representation of the statement */
1005  /* roleid to be filled below */
1006  /* nspid to be filled in SetDefaultACLsInSchemas */
1007  iacls.is_grant = action->is_grant;
1008  iacls.objtype = action->objtype;
1009  /* all_privs to be filled below */
1010  /* privileges to be filled below */
1011  iacls.grantees = NIL; /* filled below */
1012  iacls.grant_option = action->grant_option;
1013  iacls.behavior = action->behavior;
1014 
1015  /*
1016  * Convert the RoleSpec list into an Oid list. Note that at this point we
1017  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
1018  * there shouldn't be any additional work needed to support this case.
1019  */
1020  foreach(cell, action->grantees)
1021  {
1022  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
1023  Oid grantee_uid;
1024 
1025  switch (grantee->roletype)
1026  {
1027  case ROLESPEC_PUBLIC:
1028  grantee_uid = ACL_ID_PUBLIC;
1029  break;
1030  default:
1031  grantee_uid = get_rolespec_oid(grantee, false);
1032  break;
1033  }
1034  iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
1035  }
1036 
1037  /*
1038  * Convert action->privileges, a list of privilege strings, into an
1039  * AclMode bitmask.
1040  */
1041  switch (action->objtype)
1042  {
1043  case OBJECT_TABLE:
1044  all_privileges = ACL_ALL_RIGHTS_RELATION;
1045  errormsg = gettext_noop("invalid privilege type %s for relation");
1046  break;
1047  case OBJECT_SEQUENCE:
1048  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1049  errormsg = gettext_noop("invalid privilege type %s for sequence");
1050  break;
1051  case OBJECT_FUNCTION:
1052  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1053  errormsg = gettext_noop("invalid privilege type %s for function");
1054  break;
1055  case OBJECT_PROCEDURE:
1056  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1057  errormsg = gettext_noop("invalid privilege type %s for procedure");
1058  break;
1059  case OBJECT_ROUTINE:
1060  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1061  errormsg = gettext_noop("invalid privilege type %s for routine");
1062  break;
1063  case OBJECT_TYPE:
1064  all_privileges = ACL_ALL_RIGHTS_TYPE;
1065  errormsg = gettext_noop("invalid privilege type %s for type");
1066  break;
1067  case OBJECT_SCHEMA:
1068  all_privileges = ACL_ALL_RIGHTS_SCHEMA;
1069  errormsg = gettext_noop("invalid privilege type %s for schema");
1070  break;
1071  default:
1072  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
1073  (int) action->objtype);
1074  /* keep compiler quiet */
1075  all_privileges = ACL_NO_RIGHTS;
1076  errormsg = NULL;
1077  }
1078 
1079  if (action->privileges == NIL)
1080  {
1081  iacls.all_privs = true;
1082 
1083  /*
1084  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
1085  * depending on the object type
1086  */
1087  iacls.privileges = ACL_NO_RIGHTS;
1088  }
1089  else
1090  {
1091  iacls.all_privs = false;
1092  iacls.privileges = ACL_NO_RIGHTS;
1093 
1094  foreach(cell, action->privileges)
1095  {
1096  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
1097  AclMode priv;
1098 
1099  if (privnode->cols)
1100  ereport(ERROR,
1101  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1102  errmsg("default privileges cannot be set for columns")));
1103 
1104  if (privnode->priv_name == NULL) /* parser mistake? */
1105  elog(ERROR, "AccessPriv node must specify privilege");
1106  priv = string_to_privilege(privnode->priv_name);
1107 
1108  if (priv & ~((AclMode) all_privileges))
1109  ereport(ERROR,
1110  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1111  errmsg(errormsg, privilege_to_string(priv))));
1112 
1113  iacls.privileges |= priv;
1114  }
1115  }
1116 
1117  if (rolespecs == NIL)
1118  {
1119  /* Set permissions for myself */
1120  iacls.roleid = GetUserId();
1121 
1122  SetDefaultACLsInSchemas(&iacls, nspnames);
1123  }
1124  else
1125  {
1126  /* Look up the role OIDs and do permissions checks */
1127  ListCell *rolecell;
1128 
1129  foreach(rolecell, rolespecs)
1130  {
1131  RoleSpec *rolespec = lfirst(rolecell);
1132 
1133  iacls.roleid = get_rolespec_oid(rolespec, false);
1134 
1135  if (!has_privs_of_role(GetUserId(), iacls.roleid))
1136  ereport(ERROR,
1137  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1138  errmsg("permission denied to change default privileges")));
1139 
1140  SetDefaultACLsInSchemas(&iacls, nspnames);
1141  }
1142  }
1143 }
1144 
1145 /*
1146  * Process ALTER DEFAULT PRIVILEGES for a list of target schemas
1147  *
1148  * All fields of *iacls except nspid were filled already
1149  */
1150 static void
1152 {
1153  if (nspnames == NIL)
1154  {
1155  /* Set database-wide permissions if no schema was specified */
1156  iacls->nspid = InvalidOid;
1157 
1158  SetDefaultACL(iacls);
1159  }
1160  else
1161  {
1162  /* Look up the schema OIDs and set permissions for each one */
1163  ListCell *nspcell;
1164 
1165  foreach(nspcell, nspnames)
1166  {
1167  char *nspname = strVal(lfirst(nspcell));
1168 
1169  iacls->nspid = get_namespace_oid(nspname, false);
1170 
1171  /*
1172  * We used to insist that the target role have CREATE privileges
1173  * on the schema, since without that it wouldn't be able to create
1174  * an object for which these default privileges would apply.
1175  * However, this check proved to be more confusing than helpful,
1176  * and it also caused certain database states to not be
1177  * dumpable/restorable, since revoking CREATE doesn't cause
1178  * default privileges for the schema to go away. So now, we just
1179  * allow the ALTER; if the user lacks CREATE he'll find out when
1180  * he tries to create an object.
1181  */
1182 
1183  SetDefaultACL(iacls);
1184  }
1185  }
1186 }
1187 
1188 
1189 /*
1190  * Create or update a pg_default_acl entry
1191  */
1192 static void
1194 {
1195  AclMode this_privileges = iacls->privileges;
1196  char objtype;
1197  Relation rel;
1198  HeapTuple tuple;
1199  bool isNew;
1200  Acl *def_acl;
1201  Acl *old_acl;
1202  Acl *new_acl;
1203  HeapTuple newtuple;
1204  int noldmembers;
1205  int nnewmembers;
1206  Oid *oldmembers;
1207  Oid *newmembers;
1208 
1209  rel = table_open(DefaultAclRelationId, RowExclusiveLock);
1210 
1211  /*
1212  * The default for a global entry is the hard-wired default ACL for the
1213  * particular object type. The default for non-global entries is an empty
1214  * ACL. This must be so because global entries replace the hard-wired
1215  * defaults, while others are added on.
1216  */
1217  if (!OidIsValid(iacls->nspid))
1218  def_acl = acldefault(iacls->objtype, iacls->roleid);
1219  else
1220  def_acl = make_empty_acl();
1221 
1222  /*
1223  * Convert ACL object type to pg_default_acl object type and handle
1224  * all_privs option
1225  */
1226  switch (iacls->objtype)
1227  {
1228  case OBJECT_TABLE:
1229  objtype = DEFACLOBJ_RELATION;
1230  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1231  this_privileges = ACL_ALL_RIGHTS_RELATION;
1232  break;
1233 
1234  case OBJECT_SEQUENCE:
1235  objtype = DEFACLOBJ_SEQUENCE;
1236  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1237  this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1238  break;
1239 
1240  case OBJECT_FUNCTION:
1241  objtype = DEFACLOBJ_FUNCTION;
1242  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1243  this_privileges = ACL_ALL_RIGHTS_FUNCTION;
1244  break;
1245 
1246  case OBJECT_TYPE:
1247  objtype = DEFACLOBJ_TYPE;
1248  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1249  this_privileges = ACL_ALL_RIGHTS_TYPE;
1250  break;
1251 
1252  case OBJECT_SCHEMA:
1253  if (OidIsValid(iacls->nspid))
1254  ereport(ERROR,
1255  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1256  errmsg("cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS")));
1257  objtype = DEFACLOBJ_NAMESPACE;
1258  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1259  this_privileges = ACL_ALL_RIGHTS_SCHEMA;
1260  break;
1261 
1262  default:
1263  elog(ERROR, "unrecognized object type: %d",
1264  (int) iacls->objtype);
1265  objtype = 0; /* keep compiler quiet */
1266  break;
1267  }
1268 
1269  /* Search for existing row for this object type in catalog */
1271  ObjectIdGetDatum(iacls->roleid),
1272  ObjectIdGetDatum(iacls->nspid),
1273  CharGetDatum(objtype));
1274 
1275  if (HeapTupleIsValid(tuple))
1276  {
1277  Datum aclDatum;
1278  bool isNull;
1279 
1280  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
1281  Anum_pg_default_acl_defaclacl,
1282  &isNull);
1283  if (!isNull)
1284  old_acl = DatumGetAclPCopy(aclDatum);
1285  else
1286  old_acl = NULL; /* this case shouldn't happen, probably */
1287  isNew = false;
1288  }
1289  else
1290  {
1291  old_acl = NULL;
1292  isNew = true;
1293  }
1294 
1295  if (old_acl != NULL)
1296  {
1297  /*
1298  * We need the members of both old and new ACLs so we can correct the
1299  * shared dependency information. Collect data before
1300  * merge_acl_with_grant throws away old_acl.
1301  */
1302  noldmembers = aclmembers(old_acl, &oldmembers);
1303  }
1304  else
1305  {
1306  /* If no or null entry, start with the default ACL value */
1307  old_acl = aclcopy(def_acl);
1308  /* There are no old member roles according to the catalogs */
1309  noldmembers = 0;
1310  oldmembers = NULL;
1311  }
1312 
1313  /*
1314  * Generate new ACL. Grantor of rights is always the same as the target
1315  * role.
1316  */
1317  new_acl = merge_acl_with_grant(old_acl,
1318  iacls->is_grant,
1319  iacls->grant_option,
1320  iacls->behavior,
1321  iacls->grantees,
1322  this_privileges,
1323  iacls->roleid,
1324  iacls->roleid);
1325 
1326  /*
1327  * If the result is the same as the default value, we do not need an
1328  * explicit pg_default_acl entry, and should in fact remove the entry if
1329  * it exists. Must sort both arrays to compare properly.
1330  */
1331  aclitemsort(new_acl);
1332  aclitemsort(def_acl);
1333  if (aclequal(new_acl, def_acl))
1334  {
1335  /* delete old entry, if indeed there is one */
1336  if (!isNew)
1337  {
1338  ObjectAddress myself;
1339 
1340  /*
1341  * The dependency machinery will take care of removing all
1342  * associated dependency entries. We use DROP_RESTRICT since
1343  * there shouldn't be anything depending on this entry.
1344  */
1345  myself.classId = DefaultAclRelationId;
1346  myself.objectId = ((Form_pg_default_acl) GETSTRUCT(tuple))->oid;
1347  myself.objectSubId = 0;
1348 
1349  performDeletion(&myself, DROP_RESTRICT, 0);
1350  }
1351  }
1352  else
1353  {
1354  Datum values[Natts_pg_default_acl] = {0};
1355  bool nulls[Natts_pg_default_acl] = {0};
1356  bool replaces[Natts_pg_default_acl] = {0};
1357  Oid defAclOid;
1358 
1359  if (isNew)
1360  {
1361  /* insert new entry */
1362  defAclOid = GetNewOidWithIndex(rel, DefaultAclOidIndexId,
1363  Anum_pg_default_acl_oid);
1364  values[Anum_pg_default_acl_oid - 1] = ObjectIdGetDatum(defAclOid);
1365  values[Anum_pg_default_acl_defaclrole - 1] = ObjectIdGetDatum(iacls->roleid);
1366  values[Anum_pg_default_acl_defaclnamespace - 1] = ObjectIdGetDatum(iacls->nspid);
1367  values[Anum_pg_default_acl_defaclobjtype - 1] = CharGetDatum(objtype);
1368  values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
1369 
1370  newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
1371  CatalogTupleInsert(rel, newtuple);
1372  }
1373  else
1374  {
1375  defAclOid = ((Form_pg_default_acl) GETSTRUCT(tuple))->oid;
1376 
1377  /* update existing entry */
1378  values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
1379  replaces[Anum_pg_default_acl_defaclacl - 1] = true;
1380 
1381  newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
1382  values, nulls, replaces);
1383  CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
1384  }
1385 
1386  /* these dependencies don't change in an update */
1387  if (isNew)
1388  {
1389  /* dependency on role */
1390  recordDependencyOnOwner(DefaultAclRelationId, defAclOid,
1391  iacls->roleid);
1392 
1393  /* dependency on namespace */
1394  if (OidIsValid(iacls->nspid))
1395  {
1396  ObjectAddress myself,
1397  referenced;
1398 
1399  myself.classId = DefaultAclRelationId;
1400  myself.objectId = defAclOid;
1401  myself.objectSubId = 0;
1402 
1403  referenced.classId = NamespaceRelationId;
1404  referenced.objectId = iacls->nspid;
1405  referenced.objectSubId = 0;
1406 
1407  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1408  }
1409  }
1410 
1411  /*
1412  * Update the shared dependency ACL info
1413  */
1414  nnewmembers = aclmembers(new_acl, &newmembers);
1415 
1416  updateAclDependencies(DefaultAclRelationId,
1417  defAclOid, 0,
1418  iacls->roleid,
1419  noldmembers, oldmembers,
1420  nnewmembers, newmembers);
1421 
1422  if (isNew)
1423  InvokeObjectPostCreateHook(DefaultAclRelationId, defAclOid, 0);
1424  else
1425  InvokeObjectPostAlterHook(DefaultAclRelationId, defAclOid, 0);
1426  }
1427 
1428  if (HeapTupleIsValid(tuple))
1429  ReleaseSysCache(tuple);
1430 
1432 
1433  /* prevent error when processing duplicate objects */
1435 }
1436 
1437 
1438 /*
1439  * RemoveRoleFromObjectACL
1440  *
1441  * Used by shdepDropOwned to remove mentions of a role in ACLs
1442  */
1443 void
1444 RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
1445 {
1446  if (classid == DefaultAclRelationId)
1447  {
1448  InternalDefaultACL iacls;
1449  Form_pg_default_acl pg_default_acl_tuple;
1450  Relation rel;
1451  ScanKeyData skey[1];
1452  SysScanDesc scan;
1453  HeapTuple tuple;
1454 
1455  /* first fetch info needed by SetDefaultACL */
1456  rel = table_open(DefaultAclRelationId, AccessShareLock);
1457 
1458  ScanKeyInit(&skey[0],
1459  Anum_pg_default_acl_oid,
1460  BTEqualStrategyNumber, F_OIDEQ,
1461  ObjectIdGetDatum(objid));
1462 
1463  scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
1464  NULL, 1, skey);
1465 
1466  tuple = systable_getnext(scan);
1467 
1468  if (!HeapTupleIsValid(tuple))
1469  elog(ERROR, "could not find tuple for default ACL %u", objid);
1470 
1471  pg_default_acl_tuple = (Form_pg_default_acl) GETSTRUCT(tuple);
1472 
1473  iacls.roleid = pg_default_acl_tuple->defaclrole;
1474  iacls.nspid = pg_default_acl_tuple->defaclnamespace;
1475 
1476  switch (pg_default_acl_tuple->defaclobjtype)
1477  {
1478  case DEFACLOBJ_RELATION:
1479  iacls.objtype = OBJECT_TABLE;
1480  break;
1481  case DEFACLOBJ_SEQUENCE:
1482  iacls.objtype = OBJECT_SEQUENCE;
1483  break;
1484  case DEFACLOBJ_FUNCTION:
1485  iacls.objtype = OBJECT_FUNCTION;
1486  break;
1487  case DEFACLOBJ_TYPE:
1488  iacls.objtype = OBJECT_TYPE;
1489  break;
1490  case DEFACLOBJ_NAMESPACE:
1491  iacls.objtype = OBJECT_SCHEMA;
1492  break;
1493  default:
1494  /* Shouldn't get here */
1495  elog(ERROR, "unexpected default ACL type: %d",
1496  (int) pg_default_acl_tuple->defaclobjtype);
1497  break;
1498  }
1499 
1500  systable_endscan(scan);
1502 
1503  iacls.is_grant = false;
1504  iacls.all_privs = true;
1505  iacls.privileges = ACL_NO_RIGHTS;
1506  iacls.grantees = list_make1_oid(roleid);
1507  iacls.grant_option = false;
1508  iacls.behavior = DROP_CASCADE;
1509 
1510  /* Do it */
1511  SetDefaultACL(&iacls);
1512  }
1513  else
1514  {
1515  InternalGrant istmt;
1516 
1517  switch (classid)
1518  {
1519  case RelationRelationId:
1520  /* it's OK to use TABLE for a sequence */
1521  istmt.objtype = OBJECT_TABLE;
1522  break;
1523  case DatabaseRelationId:
1524  istmt.objtype = OBJECT_DATABASE;
1525  break;
1526  case TypeRelationId:
1527  istmt.objtype = OBJECT_TYPE;
1528  break;
1529  case ProcedureRelationId:
1530  istmt.objtype = OBJECT_ROUTINE;
1531  break;
1532  case LanguageRelationId:
1533  istmt.objtype = OBJECT_LANGUAGE;
1534  break;
1535  case LargeObjectRelationId:
1536  istmt.objtype = OBJECT_LARGEOBJECT;
1537  break;
1538  case NamespaceRelationId:
1539  istmt.objtype = OBJECT_SCHEMA;
1540  break;
1541  case TableSpaceRelationId:
1542  istmt.objtype = OBJECT_TABLESPACE;
1543  break;
1544  case ForeignServerRelationId:
1546  break;
1547  case ForeignDataWrapperRelationId:
1548  istmt.objtype = OBJECT_FDW;
1549  break;
1550  case ParameterAclRelationId:
1551  istmt.objtype = OBJECT_PARAMETER_ACL;
1552  break;
1553  default:
1554  elog(ERROR, "unexpected object class %u", classid);
1555  break;
1556  }
1557  istmt.is_grant = false;
1558  istmt.objects = list_make1_oid(objid);
1559  istmt.all_privs = true;
1560  istmt.privileges = ACL_NO_RIGHTS;
1561  istmt.col_privs = NIL;
1562  istmt.grantees = list_make1_oid(roleid);
1563  istmt.grant_option = false;
1564  istmt.behavior = DROP_CASCADE;
1565 
1566  ExecGrantStmt_oids(&istmt);
1567  }
1568 }
1569 
1570 
1571 /*
1572  * expand_col_privileges
1573  *
1574  * OR the specified privilege(s) into per-column array entries for each
1575  * specified attribute. The per-column array is indexed starting at
1576  * FirstLowInvalidHeapAttributeNumber, up to relation's last attribute.
1577  */
1578 static void
1579 expand_col_privileges(List *colnames, Oid table_oid,
1580  AclMode this_privileges,
1581  AclMode *col_privileges,
1582  int num_col_privileges)
1583 {
1584  ListCell *cell;
1585 
1586  foreach(cell, colnames)
1587  {
1588  char *colname = strVal(lfirst(cell));
1590 
1591  attnum = get_attnum(table_oid, colname);
1592  if (attnum == InvalidAttrNumber)
1593  ereport(ERROR,
1594  (errcode(ERRCODE_UNDEFINED_COLUMN),
1595  errmsg("column \"%s\" of relation \"%s\" does not exist",
1596  colname, get_rel_name(table_oid))));
1598  if (attnum <= 0 || attnum >= num_col_privileges)
1599  elog(ERROR, "column number out of range"); /* safety check */
1600  col_privileges[attnum] |= this_privileges;
1601  }
1602 }
1603 
1604 /*
1605  * expand_all_col_privileges
1606  *
1607  * OR the specified privilege(s) into per-column array entries for each valid
1608  * attribute of a relation. The per-column array is indexed starting at
1609  * FirstLowInvalidHeapAttributeNumber, up to relation's last attribute.
1610  */
1611 static void
1613  AclMode this_privileges,
1614  AclMode *col_privileges,
1615  int num_col_privileges)
1616 {
1617  AttrNumber curr_att;
1618 
1619  Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
1620  for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
1621  curr_att <= classForm->relnatts;
1622  curr_att++)
1623  {
1624  HeapTuple attTuple;
1625  bool isdropped;
1626 
1627  if (curr_att == InvalidAttrNumber)
1628  continue;
1629 
1630  /* Views don't have any system columns at all */
1631  if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
1632  continue;
1633 
1634  attTuple = SearchSysCache2(ATTNUM,
1635  ObjectIdGetDatum(table_oid),
1636  Int16GetDatum(curr_att));
1637  if (!HeapTupleIsValid(attTuple))
1638  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1639  curr_att, table_oid);
1640 
1641  isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
1642 
1643  ReleaseSysCache(attTuple);
1644 
1645  /* ignore dropped columns */
1646  if (isdropped)
1647  continue;
1648 
1649  col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
1650  }
1651 }
1652 
1653 /*
1654  * This processes attributes, but expects to be called from
1655  * ExecGrant_Relation, not directly from ExecuteGrantStmt.
1656  */
1657 static void
1658 ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
1659  AttrNumber attnum, Oid ownerId, AclMode col_privileges,
1660  Relation attRelation, const Acl *old_rel_acl)
1661 {
1662  HeapTuple attr_tuple;
1663  Form_pg_attribute pg_attribute_tuple;
1664  Acl *old_acl;
1665  Acl *new_acl;
1666  Acl *merged_acl;
1667  Datum aclDatum;
1668  bool isNull;
1669  Oid grantorId;
1670  AclMode avail_goptions;
1671  bool need_update;
1672  HeapTuple newtuple;
1673  Datum values[Natts_pg_attribute] = {0};
1674  bool nulls[Natts_pg_attribute] = {0};
1675  bool replaces[Natts_pg_attribute] = {0};
1676  int noldmembers;
1677  int nnewmembers;
1678  Oid *oldmembers;
1679  Oid *newmembers;
1680 
1681  attr_tuple = SearchSysCache2(ATTNUM,
1682  ObjectIdGetDatum(relOid),
1684  if (!HeapTupleIsValid(attr_tuple))
1685  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1686  attnum, relOid);
1687  pg_attribute_tuple = (Form_pg_attribute) GETSTRUCT(attr_tuple);
1688 
1689  /*
1690  * Get working copy of existing ACL. If there's no ACL, substitute the
1691  * proper default.
1692  */
1693  aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
1694  &isNull);
1695  if (isNull)
1696  {
1697  old_acl = acldefault(OBJECT_COLUMN, ownerId);
1698  /* There are no old member roles according to the catalogs */
1699  noldmembers = 0;
1700  oldmembers = NULL;
1701  }
1702  else
1703  {
1704  old_acl = DatumGetAclPCopy(aclDatum);
1705  /* Get the roles mentioned in the existing ACL */
1706  noldmembers = aclmembers(old_acl, &oldmembers);
1707  }
1708 
1709  /*
1710  * In select_best_grantor we should consider existing table-level ACL bits
1711  * as well as the per-column ACL. Build a new ACL that is their
1712  * concatenation. (This is a bit cheap and dirty compared to merging them
1713  * properly with no duplications, but it's all we need here.)
1714  */
1715  merged_acl = aclconcat(old_rel_acl, old_acl);
1716 
1717  /* Determine ID to do the grant as, and available grant options */
1718  select_best_grantor(GetUserId(), col_privileges,
1719  merged_acl, ownerId,
1720  &grantorId, &avail_goptions);
1721 
1722  pfree(merged_acl);
1723 
1724  /*
1725  * Restrict the privileges to what we can actually grant, and emit the
1726  * standards-mandated warning and error messages. Note: we don't track
1727  * whether the user actually used the ALL PRIVILEGES(columns) syntax for
1728  * each column; we just approximate it by whether all the possible
1729  * privileges are specified now. Since the all_privs flag only determines
1730  * whether a warning is issued, this seems close enough.
1731  */
1732  col_privileges =
1733  restrict_and_check_grant(istmt->is_grant, avail_goptions,
1734  (col_privileges == ACL_ALL_RIGHTS_COLUMN),
1735  col_privileges,
1736  relOid, grantorId, OBJECT_COLUMN,
1737  relname, attnum,
1738  NameStr(pg_attribute_tuple->attname));
1739 
1740  /*
1741  * Generate new ACL.
1742  */
1743  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
1744  istmt->grant_option,
1745  istmt->behavior, istmt->grantees,
1746  col_privileges, grantorId,
1747  ownerId);
1748 
1749  /*
1750  * We need the members of both old and new ACLs so we can correct the
1751  * shared dependency information.
1752  */
1753  nnewmembers = aclmembers(new_acl, &newmembers);
1754 
1755  /* finished building new ACL value, now insert it */
1756 
1757  /*
1758  * If the updated ACL is empty, we can set attacl to null, and maybe even
1759  * avoid an update of the pg_attribute row. This is worth testing because
1760  * we'll come through here multiple times for any relation-level REVOKE,
1761  * even if there were never any column GRANTs. Note we are assuming that
1762  * the "default" ACL state for columns is empty.
1763  */
1764  if (ACL_NUM(new_acl) > 0)
1765  {
1766  values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl);
1767  need_update = true;
1768  }
1769  else
1770  {
1771  nulls[Anum_pg_attribute_attacl - 1] = true;
1772  need_update = !isNull;
1773  }
1774  replaces[Anum_pg_attribute_attacl - 1] = true;
1775 
1776  if (need_update)
1777  {
1778  newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
1779  values, nulls, replaces);
1780 
1781  CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
1782 
1783  /* Update initial privileges for extensions */
1784  recordExtensionInitPriv(relOid, RelationRelationId, attnum,
1785  ACL_NUM(new_acl) > 0 ? new_acl : NULL);
1786 
1787  /* Update the shared dependency ACL info */
1788  updateAclDependencies(RelationRelationId, relOid, attnum,
1789  ownerId,
1790  noldmembers, oldmembers,
1791  nnewmembers, newmembers);
1792  }
1793 
1794  pfree(new_acl);
1795 
1796  ReleaseSysCache(attr_tuple);
1797 }
1798 
1799 /*
1800  * This processes both sequences and non-sequences.
1801  */
1802 static void
1804 {
1805  Relation relation;
1806  Relation attRelation;
1807  ListCell *cell;
1808 
1809  relation = table_open(RelationRelationId, RowExclusiveLock);
1810  attRelation = table_open(AttributeRelationId, RowExclusiveLock);
1811 
1812  foreach(cell, istmt->objects)
1813  {
1814  Oid relOid = lfirst_oid(cell);
1815  Datum aclDatum;
1816  Form_pg_class pg_class_tuple;
1817  bool isNull;
1818  AclMode this_privileges;
1819  AclMode *col_privileges;
1820  int num_col_privileges;
1821  bool have_col_privileges;
1822  Acl *old_acl;
1823  Acl *old_rel_acl;
1824  int noldmembers;
1825  Oid *oldmembers;
1826  Oid ownerId;
1827  HeapTuple tuple;
1828  ListCell *cell_colprivs;
1829 
1830  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
1831  if (!HeapTupleIsValid(tuple))
1832  elog(ERROR, "cache lookup failed for relation %u", relOid);
1833  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
1834 
1835  /* Not sensible to grant on an index */
1836  if (pg_class_tuple->relkind == RELKIND_INDEX ||
1837  pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX)
1838  ereport(ERROR,
1839  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1840  errmsg("\"%s\" is an index",
1841  NameStr(pg_class_tuple->relname))));
1842 
1843  /* Composite types aren't tables either */
1844  if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
1845  ereport(ERROR,
1846  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1847  errmsg("\"%s\" is a composite type",
1848  NameStr(pg_class_tuple->relname))));
1849 
1850  /* Used GRANT SEQUENCE on a non-sequence? */
1851  if (istmt->objtype == OBJECT_SEQUENCE &&
1852  pg_class_tuple->relkind != RELKIND_SEQUENCE)
1853  ereport(ERROR,
1854  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1855  errmsg("\"%s\" is not a sequence",
1856  NameStr(pg_class_tuple->relname))));
1857 
1858  /* Adjust the default permissions based on object type */
1859  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
1860  {
1861  if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
1862  this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1863  else
1864  this_privileges = ACL_ALL_RIGHTS_RELATION;
1865  }
1866  else
1867  this_privileges = istmt->privileges;
1868 
1869  /*
1870  * The GRANT TABLE syntax can be used for sequences and non-sequences,
1871  * so we have to look at the relkind to determine the supported
1872  * permissions. The OR of table and sequence permissions were already
1873  * checked.
1874  */
1875  if (istmt->objtype == OBJECT_TABLE)
1876  {
1877  if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
1878  {
1879  /*
1880  * For backward compatibility, just throw a warning for
1881  * invalid sequence permissions when using the non-sequence
1882  * GRANT syntax.
1883  */
1884  if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
1885  {
1886  /*
1887  * Mention the object name because the user needs to know
1888  * which operations succeeded. This is required because
1889  * WARNING allows the command to continue.
1890  */
1891  ereport(WARNING,
1892  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1893  errmsg("sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges",
1894  NameStr(pg_class_tuple->relname))));
1895  this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
1896  }
1897  }
1898  else
1899  {
1900  if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
1901  {
1902  /*
1903  * USAGE is the only permission supported by sequences but
1904  * not by non-sequences. Don't mention the object name
1905  * because we didn't in the combined TABLE | SEQUENCE
1906  * check.
1907  */
1908  ereport(ERROR,
1909  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1910  errmsg("invalid privilege type %s for table",
1911  "USAGE")));
1912  }
1913  }
1914  }
1915 
1916  /*
1917  * Set up array in which we'll accumulate any column privilege bits
1918  * that need modification. The array is indexed such that entry [0]
1919  * corresponds to FirstLowInvalidHeapAttributeNumber.
1920  */
1921  num_col_privileges = pg_class_tuple->relnatts - FirstLowInvalidHeapAttributeNumber + 1;
1922  col_privileges = (AclMode *) palloc0(num_col_privileges * sizeof(AclMode));
1923  have_col_privileges = false;
1924 
1925  /*
1926  * If we are revoking relation privileges that are also column
1927  * privileges, we must implicitly revoke them from each column too,
1928  * per SQL spec. (We don't need to implicitly add column privileges
1929  * during GRANT because the permissions-checking code always checks
1930  * both relation and per-column privileges.)
1931  */
1932  if (!istmt->is_grant &&
1933  (this_privileges & ACL_ALL_RIGHTS_COLUMN) != 0)
1934  {
1935  expand_all_col_privileges(relOid, pg_class_tuple,
1936  this_privileges & ACL_ALL_RIGHTS_COLUMN,
1937  col_privileges,
1938  num_col_privileges);
1939  have_col_privileges = true;
1940  }
1941 
1942  /*
1943  * Get owner ID and working copy of existing ACL. If there's no ACL,
1944  * substitute the proper default.
1945  */
1946  ownerId = pg_class_tuple->relowner;
1947  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
1948  &isNull);
1949  if (isNull)
1950  {
1951  switch (pg_class_tuple->relkind)
1952  {
1953  case RELKIND_SEQUENCE:
1954  old_acl = acldefault(OBJECT_SEQUENCE, ownerId);
1955  break;
1956  default:
1957  old_acl = acldefault(OBJECT_TABLE, ownerId);
1958  break;
1959  }
1960  /* There are no old member roles according to the catalogs */
1961  noldmembers = 0;
1962  oldmembers = NULL;
1963  }
1964  else
1965  {
1966  old_acl = DatumGetAclPCopy(aclDatum);
1967  /* Get the roles mentioned in the existing ACL */
1968  noldmembers = aclmembers(old_acl, &oldmembers);
1969  }
1970 
1971  /* Need an extra copy of original rel ACL for column handling */
1972  old_rel_acl = aclcopy(old_acl);
1973 
1974  /*
1975  * Handle relation-level privileges, if any were specified
1976  */
1977  if (this_privileges != ACL_NO_RIGHTS)
1978  {
1979  AclMode avail_goptions;
1980  Acl *new_acl;
1981  Oid grantorId;
1982  HeapTuple newtuple;
1983  Datum values[Natts_pg_class] = {0};
1984  bool nulls[Natts_pg_class] = {0};
1985  bool replaces[Natts_pg_class] = {0};
1986  int nnewmembers;
1987  Oid *newmembers;
1988  ObjectType objtype;
1989 
1990  /* Determine ID to do the grant as, and available grant options */
1991  select_best_grantor(GetUserId(), this_privileges,
1992  old_acl, ownerId,
1993  &grantorId, &avail_goptions);
1994 
1995  switch (pg_class_tuple->relkind)
1996  {
1997  case RELKIND_SEQUENCE:
1998  objtype = OBJECT_SEQUENCE;
1999  break;
2000  default:
2001  objtype = OBJECT_TABLE;
2002  break;
2003  }
2004 
2005  /*
2006  * Restrict the privileges to what we can actually grant, and emit
2007  * the standards-mandated warning and error messages.
2008  */
2009  this_privileges =
2010  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2011  istmt->all_privs, this_privileges,
2012  relOid, grantorId, objtype,
2013  NameStr(pg_class_tuple->relname),
2014  0, NULL);
2015 
2016  /*
2017  * Generate new ACL.
2018  */
2019  new_acl = merge_acl_with_grant(old_acl,
2020  istmt->is_grant,
2021  istmt->grant_option,
2022  istmt->behavior,
2023  istmt->grantees,
2024  this_privileges,
2025  grantorId,
2026  ownerId);
2027 
2028  /*
2029  * We need the members of both old and new ACLs so we can correct
2030  * the shared dependency information.
2031  */
2032  nnewmembers = aclmembers(new_acl, &newmembers);
2033 
2034  /* finished building new ACL value, now insert it */
2035  replaces[Anum_pg_class_relacl - 1] = true;
2036  values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
2037 
2038  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2039  values, nulls, replaces);
2040 
2041  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2042 
2043  /* Update initial privileges for extensions */
2044  recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl);
2045 
2046  /* Update the shared dependency ACL info */
2047  updateAclDependencies(RelationRelationId, relOid, 0,
2048  ownerId,
2049  noldmembers, oldmembers,
2050  nnewmembers, newmembers);
2051 
2052  pfree(new_acl);
2053  }
2054 
2055  /*
2056  * Handle column-level privileges, if any were specified or implied.
2057  * We first expand the user-specified column privileges into the
2058  * array, and then iterate over all nonempty array entries.
2059  */
2060  foreach(cell_colprivs, istmt->col_privs)
2061  {
2062  AccessPriv *col_privs = (AccessPriv *) lfirst(cell_colprivs);
2063 
2064  if (col_privs->priv_name == NULL)
2065  this_privileges = ACL_ALL_RIGHTS_COLUMN;
2066  else
2067  this_privileges = string_to_privilege(col_privs->priv_name);
2068 
2069  if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
2070  ereport(ERROR,
2071  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
2072  errmsg("invalid privilege type %s for column",
2073  privilege_to_string(this_privileges))));
2074 
2075  if (pg_class_tuple->relkind == RELKIND_SEQUENCE &&
2076  this_privileges & ~((AclMode) ACL_SELECT))
2077  {
2078  /*
2079  * The only column privilege allowed on sequences is SELECT.
2080  * This is a warning not error because we do it that way for
2081  * relation-level privileges.
2082  */
2083  ereport(WARNING,
2084  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
2085  errmsg("sequence \"%s\" only supports SELECT column privileges",
2086  NameStr(pg_class_tuple->relname))));
2087 
2088  this_privileges &= (AclMode) ACL_SELECT;
2089  }
2090 
2091  expand_col_privileges(col_privs->cols, relOid,
2092  this_privileges,
2093  col_privileges,
2094  num_col_privileges);
2095  have_col_privileges = true;
2096  }
2097 
2098  if (have_col_privileges)
2099  {
2100  AttrNumber i;
2101 
2102  for (i = 0; i < num_col_privileges; i++)
2103  {
2104  if (col_privileges[i] == ACL_NO_RIGHTS)
2105  continue;
2106  ExecGrant_Attribute(istmt,
2107  relOid,
2108  NameStr(pg_class_tuple->relname),
2110  ownerId,
2111  col_privileges[i],
2112  attRelation,
2113  old_rel_acl);
2114  }
2115  }
2116 
2117  pfree(old_rel_acl);
2118  pfree(col_privileges);
2119 
2120  ReleaseSysCache(tuple);
2121 
2122  /* prevent error when processing duplicate objects */
2124  }
2125 
2126  table_close(attRelation, RowExclusiveLock);
2127  table_close(relation, RowExclusiveLock);
2128 }
2129 
2130 static void
2131 ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs,
2132  void (*object_check) (InternalGrant *istmt, HeapTuple tuple))
2133 {
2134  int cacheid;
2135  Relation relation;
2136  ListCell *cell;
2137 
2138  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2139  istmt->privileges = default_privs;
2140 
2141  cacheid = get_object_catcache_oid(classid);
2142 
2143  relation = table_open(classid, RowExclusiveLock);
2144 
2145  foreach(cell, istmt->objects)
2146  {
2147  Oid objectid = lfirst_oid(cell);
2148  Datum aclDatum;
2149  Datum nameDatum;
2150  bool isNull;
2151  AclMode avail_goptions;
2152  AclMode this_privileges;
2153  Acl *old_acl;
2154  Acl *new_acl;
2155  Oid grantorId;
2156  Oid ownerId;
2157  HeapTuple tuple;
2158  HeapTuple newtuple;
2159  Datum *values = palloc0_array(Datum, RelationGetDescr(relation)->natts);
2160  bool *nulls = palloc0_array(bool, RelationGetDescr(relation)->natts);
2161  bool *replaces = palloc0_array(bool, RelationGetDescr(relation)->natts);
2162  int noldmembers;
2163  int nnewmembers;
2164  Oid *oldmembers;
2165  Oid *newmembers;
2166 
2167  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
2168  if (!HeapTupleIsValid(tuple))
2169  elog(ERROR, "cache lookup failed for %s %u", get_object_class_descr(classid), objectid);
2170 
2171  /*
2172  * Additional object-type-specific checks
2173  */
2174  if (object_check)
2175  object_check(istmt, tuple);
2176 
2177  /*
2178  * Get owner ID and working copy of existing ACL. If there's no ACL,
2179  * substitute the proper default.
2180  */
2181  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
2182  tuple,
2183  get_object_attnum_owner(classid)));
2184  aclDatum = SysCacheGetAttr(cacheid,
2185  tuple,
2186  get_object_attnum_acl(classid),
2187  &isNull);
2188  if (isNull)
2189  {
2190  old_acl = acldefault(get_object_type(classid, objectid), ownerId);
2191  /* There are no old member roles according to the catalogs */
2192  noldmembers = 0;
2193  oldmembers = NULL;
2194  }
2195  else
2196  {
2197  old_acl = DatumGetAclPCopy(aclDatum);
2198  /* Get the roles mentioned in the existing ACL */
2199  noldmembers = aclmembers(old_acl, &oldmembers);
2200  }
2201 
2202  /* Determine ID to do the grant as, and available grant options */
2204  old_acl, ownerId,
2205  &grantorId, &avail_goptions);
2206 
2207  nameDatum = SysCacheGetAttrNotNull(cacheid, tuple,
2208  get_object_attnum_name(classid));
2209 
2210  /*
2211  * Restrict the privileges to what we can actually grant, and emit the
2212  * standards-mandated warning and error messages.
2213  */
2214  this_privileges =
2215  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2216  istmt->all_privs, istmt->privileges,
2217  objectid, grantorId, get_object_type(classid, objectid),
2218  NameStr(*DatumGetName(nameDatum)),
2219  0, NULL);
2220 
2221  /*
2222  * Generate new ACL.
2223  */
2224  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2225  istmt->grant_option, istmt->behavior,
2226  istmt->grantees, this_privileges,
2227  grantorId, ownerId);
2228 
2229  /*
2230  * We need the members of both old and new ACLs so we can correct the
2231  * shared dependency information.
2232  */
2233  nnewmembers = aclmembers(new_acl, &newmembers);
2234 
2235  /* finished building new ACL value, now insert it */
2236  replaces[get_object_attnum_acl(classid) - 1] = true;
2237  values[get_object_attnum_acl(classid) - 1] = PointerGetDatum(new_acl);
2238 
2239  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2240  nulls, replaces);
2241 
2242  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2243 
2244  /* Update initial privileges for extensions */
2245  recordExtensionInitPriv(objectid, classid, 0, new_acl);
2246 
2247  /* Update the shared dependency ACL info */
2248  updateAclDependencies(classid,
2249  objectid, 0,
2250  ownerId,
2251  noldmembers, oldmembers,
2252  nnewmembers, newmembers);
2253 
2254  ReleaseSysCache(tuple);
2255 
2256  pfree(new_acl);
2257 
2258  /* prevent error when processing duplicate objects */
2260  }
2261 
2262  table_close(relation, RowExclusiveLock);
2263 }
2264 
2265 static void
2267 {
2268  Form_pg_language pg_language_tuple;
2269 
2270  pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
2271 
2272  if (!pg_language_tuple->lanpltrusted)
2273  ereport(ERROR,
2274  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2275  errmsg("language \"%s\" is not trusted",
2276  NameStr(pg_language_tuple->lanname)),
2277  errdetail("GRANT and REVOKE are not allowed on untrusted languages, "
2278  "because only superusers can use untrusted languages.")));
2279 }
2280 
2281 static void
2283 {
2284  Relation relation;
2285  ListCell *cell;
2286 
2287  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2289 
2290  relation = table_open(LargeObjectMetadataRelationId,
2292 
2293  foreach(cell, istmt->objects)
2294  {
2295  Oid loid = lfirst_oid(cell);
2296  Form_pg_largeobject_metadata form_lo_meta;
2297  char loname[NAMEDATALEN];
2298  Datum aclDatum;
2299  bool isNull;
2300  AclMode avail_goptions;
2301  AclMode this_privileges;
2302  Acl *old_acl;
2303  Acl *new_acl;
2304  Oid grantorId;
2305  Oid ownerId;
2306  HeapTuple newtuple;
2307  Datum values[Natts_pg_largeobject_metadata] = {0};
2308  bool nulls[Natts_pg_largeobject_metadata] = {0};
2309  bool replaces[Natts_pg_largeobject_metadata] = {0};
2310  int noldmembers;
2311  int nnewmembers;
2312  Oid *oldmembers;
2313  Oid *newmembers;
2314  ScanKeyData entry[1];
2315  SysScanDesc scan;
2316  HeapTuple tuple;
2317 
2318  /* There's no syscache for pg_largeobject_metadata */
2319  ScanKeyInit(&entry[0],
2320  Anum_pg_largeobject_metadata_oid,
2321  BTEqualStrategyNumber, F_OIDEQ,
2322  ObjectIdGetDatum(loid));
2323 
2324  scan = systable_beginscan(relation,
2325  LargeObjectMetadataOidIndexId, true,
2326  NULL, 1, entry);
2327 
2328  tuple = systable_getnext(scan);
2329  if (!HeapTupleIsValid(tuple))
2330  elog(ERROR, "could not find tuple for large object %u", loid);
2331 
2332  form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
2333 
2334  /*
2335  * Get owner ID and working copy of existing ACL. If there's no ACL,
2336  * substitute the proper default.
2337  */
2338  ownerId = form_lo_meta->lomowner;
2339  aclDatum = heap_getattr(tuple,
2340  Anum_pg_largeobject_metadata_lomacl,
2341  RelationGetDescr(relation), &isNull);
2342  if (isNull)
2343  {
2344  old_acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
2345  /* There are no old member roles according to the catalogs */
2346  noldmembers = 0;
2347  oldmembers = NULL;
2348  }
2349  else
2350  {
2351  old_acl = DatumGetAclPCopy(aclDatum);
2352  /* Get the roles mentioned in the existing ACL */
2353  noldmembers = aclmembers(old_acl, &oldmembers);
2354  }
2355 
2356  /* Determine ID to do the grant as, and available grant options */
2358  old_acl, ownerId,
2359  &grantorId, &avail_goptions);
2360 
2361  /*
2362  * Restrict the privileges to what we can actually grant, and emit the
2363  * standards-mandated warning and error messages.
2364  */
2365  snprintf(loname, sizeof(loname), "large object %u", loid);
2366  this_privileges =
2367  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2368  istmt->all_privs, istmt->privileges,
2369  loid, grantorId, OBJECT_LARGEOBJECT,
2370  loname, 0, NULL);
2371 
2372  /*
2373  * Generate new ACL.
2374  */
2375  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2376  istmt->grant_option, istmt->behavior,
2377  istmt->grantees, this_privileges,
2378  grantorId, ownerId);
2379 
2380  /*
2381  * We need the members of both old and new ACLs so we can correct the
2382  * shared dependency information.
2383  */
2384  nnewmembers = aclmembers(new_acl, &newmembers);
2385 
2386  /* finished building new ACL value, now insert it */
2387  replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
2388  values[Anum_pg_largeobject_metadata_lomacl - 1]
2389  = PointerGetDatum(new_acl);
2390 
2391  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2392  values, nulls, replaces);
2393 
2394  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2395 
2396  /* Update initial privileges for extensions */
2397  recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
2398 
2399  /* Update the shared dependency ACL info */
2400  updateAclDependencies(LargeObjectRelationId,
2401  form_lo_meta->oid, 0,
2402  ownerId,
2403  noldmembers, oldmembers,
2404  nnewmembers, newmembers);
2405 
2406  systable_endscan(scan);
2407 
2408  pfree(new_acl);
2409 
2410  /* prevent error when processing duplicate objects */
2412  }
2413 
2414  table_close(relation, RowExclusiveLock);
2415 }
2416 
2417 static void
2419 {
2420  Form_pg_type pg_type_tuple;
2421 
2422  pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
2423 
2424  if (IsTrueArrayType(pg_type_tuple))
2425  ereport(ERROR,
2426  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
2427  errmsg("cannot set privileges of array types"),
2428  errhint("Set the privileges of the element type instead.")));
2429 
2430  /* Used GRANT DOMAIN on a non-domain? */
2431  if (istmt->objtype == OBJECT_DOMAIN &&
2432  pg_type_tuple->typtype != TYPTYPE_DOMAIN)
2433  ereport(ERROR,
2434  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2435  errmsg("\"%s\" is not a domain",
2436  NameStr(pg_type_tuple->typname))));
2437 }
2438 
2439 static void
2441 {
2442  Relation relation;
2443  ListCell *cell;
2444 
2445  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2447 
2448  relation = table_open(ParameterAclRelationId, RowExclusiveLock);
2449 
2450  foreach(cell, istmt->objects)
2451  {
2452  Oid parameterId = lfirst_oid(cell);
2453  Datum nameDatum;
2454  const char *parname;
2455  Datum aclDatum;
2456  bool isNull;
2457  AclMode avail_goptions;
2458  AclMode this_privileges;
2459  Acl *old_acl;
2460  Acl *new_acl;
2461  Oid grantorId;
2462  Oid ownerId;
2463  HeapTuple tuple;
2464  int noldmembers;
2465  int nnewmembers;
2466  Oid *oldmembers;
2467  Oid *newmembers;
2468 
2469  tuple = SearchSysCache1(PARAMETERACLOID, ObjectIdGetDatum(parameterId));
2470  if (!HeapTupleIsValid(tuple))
2471  elog(ERROR, "cache lookup failed for parameter ACL %u",
2472  parameterId);
2473 
2474  /* We'll need the GUC's name */
2475  nameDatum = SysCacheGetAttrNotNull(PARAMETERACLOID, tuple,
2476  Anum_pg_parameter_acl_parname);
2477  parname = TextDatumGetCString(nameDatum);
2478 
2479  /* Treat all parameters as belonging to the bootstrap superuser. */
2480  ownerId = BOOTSTRAP_SUPERUSERID;
2481 
2482  /*
2483  * Get working copy of existing ACL. If there's no ACL, substitute the
2484  * proper default.
2485  */
2486  aclDatum = SysCacheGetAttr(PARAMETERACLOID, tuple,
2487  Anum_pg_parameter_acl_paracl,
2488  &isNull);
2489 
2490  if (isNull)
2491  {
2492  old_acl = acldefault(istmt->objtype, ownerId);
2493  /* There are no old member roles according to the catalogs */
2494  noldmembers = 0;
2495  oldmembers = NULL;
2496  }
2497  else
2498  {
2499  old_acl = DatumGetAclPCopy(aclDatum);
2500  /* Get the roles mentioned in the existing ACL */
2501  noldmembers = aclmembers(old_acl, &oldmembers);
2502  }
2503 
2504  /* Determine ID to do the grant as, and available grant options */
2506  old_acl, ownerId,
2507  &grantorId, &avail_goptions);
2508 
2509  /*
2510  * Restrict the privileges to what we can actually grant, and emit the
2511  * standards-mandated warning and error messages.
2512  */
2513  this_privileges =
2514  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2515  istmt->all_privs, istmt->privileges,
2516  parameterId, grantorId,
2518  parname,
2519  0, NULL);
2520 
2521  /*
2522  * Generate new ACL.
2523  */
2524  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2525  istmt->grant_option, istmt->behavior,
2526  istmt->grantees, this_privileges,
2527  grantorId, ownerId);
2528 
2529  /*
2530  * We need the members of both old and new ACLs so we can correct the
2531  * shared dependency information.
2532  */
2533  nnewmembers = aclmembers(new_acl, &newmembers);
2534 
2535  /*
2536  * If the new ACL is equal to the default, we don't need the catalog
2537  * entry any longer. Delete it rather than updating it, to avoid
2538  * leaving a degenerate entry.
2539  */
2540  if (aclequal(new_acl, acldefault(istmt->objtype, ownerId)))
2541  {
2542  CatalogTupleDelete(relation, &tuple->t_self);
2543  }
2544  else
2545  {
2546  /* finished building new ACL value, now insert it */
2547  HeapTuple newtuple;
2548  Datum values[Natts_pg_parameter_acl] = {0};
2549  bool nulls[Natts_pg_parameter_acl] = {0};
2550  bool replaces[Natts_pg_parameter_acl] = {0};
2551 
2552  replaces[Anum_pg_parameter_acl_paracl - 1] = true;
2553  values[Anum_pg_parameter_acl_paracl - 1] = PointerGetDatum(new_acl);
2554 
2555  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2556  values, nulls, replaces);
2557 
2558  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2559  }
2560 
2561  /* Update initial privileges for extensions */
2562  recordExtensionInitPriv(parameterId, ParameterAclRelationId, 0,
2563  new_acl);
2564 
2565  /* Update the shared dependency ACL info */
2566  updateAclDependencies(ParameterAclRelationId, parameterId, 0,
2567  ownerId,
2568  noldmembers, oldmembers,
2569  nnewmembers, newmembers);
2570 
2571  ReleaseSysCache(tuple);
2572  pfree(new_acl);
2573 
2574  /* prevent error when processing duplicate objects */
2576  }
2577 
2578  table_close(relation, RowExclusiveLock);
2579 }
2580 
2581 
2582 static AclMode
2583 string_to_privilege(const char *privname)
2584 {
2585  if (strcmp(privname, "insert") == 0)
2586  return ACL_INSERT;
2587  if (strcmp(privname, "select") == 0)
2588  return ACL_SELECT;
2589  if (strcmp(privname, "update") == 0)
2590  return ACL_UPDATE;
2591  if (strcmp(privname, "delete") == 0)
2592  return ACL_DELETE;
2593  if (strcmp(privname, "truncate") == 0)
2594  return ACL_TRUNCATE;
2595  if (strcmp(privname, "references") == 0)
2596  return ACL_REFERENCES;
2597  if (strcmp(privname, "trigger") == 0)
2598  return ACL_TRIGGER;
2599  if (strcmp(privname, "execute") == 0)
2600  return ACL_EXECUTE;
2601  if (strcmp(privname, "usage") == 0)
2602  return ACL_USAGE;
2603  if (strcmp(privname, "create") == 0)
2604  return ACL_CREATE;
2605  if (strcmp(privname, "temporary") == 0)
2606  return ACL_CREATE_TEMP;
2607  if (strcmp(privname, "temp") == 0)
2608  return ACL_CREATE_TEMP;
2609  if (strcmp(privname, "connect") == 0)
2610  return ACL_CONNECT;
2611  if (strcmp(privname, "set") == 0)
2612  return ACL_SET;
2613  if (strcmp(privname, "alter system") == 0)
2614  return ACL_ALTER_SYSTEM;
2615  if (strcmp(privname, "rule") == 0)
2616  return 0; /* ignore old RULE privileges */
2617  ereport(ERROR,
2618  (errcode(ERRCODE_SYNTAX_ERROR),
2619  errmsg("unrecognized privilege type \"%s\"", privname)));
2620  return 0; /* appease compiler */
2621 }
2622 
2623 static const char *
2625 {
2626  switch (privilege)
2627  {
2628  case ACL_INSERT:
2629  return "INSERT";
2630  case ACL_SELECT:
2631  return "SELECT";
2632  case ACL_UPDATE:
2633  return "UPDATE";
2634  case ACL_DELETE:
2635  return "DELETE";
2636  case ACL_TRUNCATE:
2637  return "TRUNCATE";
2638  case ACL_REFERENCES:
2639  return "REFERENCES";
2640  case ACL_TRIGGER:
2641  return "TRIGGER";
2642  case ACL_EXECUTE:
2643  return "EXECUTE";
2644  case ACL_USAGE:
2645  return "USAGE";
2646  case ACL_CREATE:
2647  return "CREATE";
2648  case ACL_CREATE_TEMP:
2649  return "TEMP";
2650  case ACL_CONNECT:
2651  return "CONNECT";
2652  case ACL_SET:
2653  return "SET";
2654  case ACL_ALTER_SYSTEM:
2655  return "ALTER SYSTEM";
2656  default:
2657  elog(ERROR, "unrecognized privilege: %d", (int) privilege);
2658  }
2659  return NULL; /* appease compiler */
2660 }
2661 
2662 /*
2663  * Standardized reporting of aclcheck permissions failures.
2664  *
2665  * Note: we do not double-quote the %s's below, because many callers
2666  * supply strings that might be already quoted.
2667  */
2668 void
2670  const char *objectname)
2671 {
2672  switch (aclerr)
2673  {
2674  case ACLCHECK_OK:
2675  /* no error, so return to caller */
2676  break;
2677  case ACLCHECK_NO_PRIV:
2678  {
2679  const char *msg = "???";
2680 
2681  switch (objtype)
2682  {
2683  case OBJECT_AGGREGATE:
2684  msg = gettext_noop("permission denied for aggregate %s");
2685  break;
2686  case OBJECT_COLLATION:
2687  msg = gettext_noop("permission denied for collation %s");
2688  break;
2689  case OBJECT_COLUMN:
2690  msg = gettext_noop("permission denied for column %s");
2691  break;
2692  case OBJECT_CONVERSION:
2693  msg = gettext_noop("permission denied for conversion %s");
2694  break;
2695  case OBJECT_DATABASE:
2696  msg = gettext_noop("permission denied for database %s");
2697  break;
2698  case OBJECT_DOMAIN:
2699  msg = gettext_noop("permission denied for domain %s");
2700  break;
2701  case OBJECT_EVENT_TRIGGER:
2702  msg = gettext_noop("permission denied for event trigger %s");
2703  break;
2704  case OBJECT_EXTENSION:
2705  msg = gettext_noop("permission denied for extension %s");
2706  break;
2707  case OBJECT_FDW:
2708  msg = gettext_noop("permission denied for foreign-data wrapper %s");
2709  break;
2710  case OBJECT_FOREIGN_SERVER:
2711  msg = gettext_noop("permission denied for foreign server %s");
2712  break;
2713  case OBJECT_FOREIGN_TABLE:
2714  msg = gettext_noop("permission denied for foreign table %s");
2715  break;
2716  case OBJECT_FUNCTION:
2717  msg = gettext_noop("permission denied for function %s");
2718  break;
2719  case OBJECT_INDEX:
2720  msg = gettext_noop("permission denied for index %s");
2721  break;
2722  case OBJECT_LANGUAGE:
2723  msg = gettext_noop("permission denied for language %s");
2724  break;
2725  case OBJECT_LARGEOBJECT:
2726  msg = gettext_noop("permission denied for large object %s");
2727  break;
2728  case OBJECT_MATVIEW:
2729  msg = gettext_noop("permission denied for materialized view %s");
2730  break;
2731  case OBJECT_OPCLASS:
2732  msg = gettext_noop("permission denied for operator class %s");
2733  break;
2734  case OBJECT_OPERATOR:
2735  msg = gettext_noop("permission denied for operator %s");
2736  break;
2737  case OBJECT_OPFAMILY:
2738  msg = gettext_noop("permission denied for operator family %s");
2739  break;
2740  case OBJECT_PARAMETER_ACL:
2741  msg = gettext_noop("permission denied for parameter %s");
2742  break;
2743  case OBJECT_POLICY:
2744  msg = gettext_noop("permission denied for policy %s");
2745  break;
2746  case OBJECT_PROCEDURE:
2747  msg = gettext_noop("permission denied for procedure %s");
2748  break;
2749  case OBJECT_PUBLICATION:
2750  msg = gettext_noop("permission denied for publication %s");
2751  break;
2752  case OBJECT_ROUTINE:
2753  msg = gettext_noop("permission denied for routine %s");
2754  break;
2755  case OBJECT_SCHEMA:
2756  msg = gettext_noop("permission denied for schema %s");
2757  break;
2758  case OBJECT_SEQUENCE:
2759  msg = gettext_noop("permission denied for sequence %s");
2760  break;
2761  case OBJECT_STATISTIC_EXT:
2762  msg = gettext_noop("permission denied for statistics object %s");
2763  break;
2764  case OBJECT_SUBSCRIPTION:
2765  msg = gettext_noop("permission denied for subscription %s");
2766  break;
2767  case OBJECT_TABLE:
2768  msg = gettext_noop("permission denied for table %s");
2769  break;
2770  case OBJECT_TABLESPACE:
2771  msg = gettext_noop("permission denied for tablespace %s");
2772  break;
2774  msg = gettext_noop("permission denied for text search configuration %s");
2775  break;
2776  case OBJECT_TSDICTIONARY:
2777  msg = gettext_noop("permission denied for text search dictionary %s");
2778  break;
2779  case OBJECT_TYPE:
2780  msg = gettext_noop("permission denied for type %s");
2781  break;
2782  case OBJECT_VIEW:
2783  msg = gettext_noop("permission denied for view %s");
2784  break;
2785  /* these currently aren't used */
2786  case OBJECT_ACCESS_METHOD:
2787  case OBJECT_AMOP:
2788  case OBJECT_AMPROC:
2789  case OBJECT_ATTRIBUTE:
2790  case OBJECT_CAST:
2791  case OBJECT_DEFAULT:
2792  case OBJECT_DEFACL:
2793  case OBJECT_DOMCONSTRAINT:
2796  case OBJECT_ROLE:
2797  case OBJECT_RULE:
2798  case OBJECT_TABCONSTRAINT:
2799  case OBJECT_TRANSFORM:
2800  case OBJECT_TRIGGER:
2801  case OBJECT_TSPARSER:
2802  case OBJECT_TSTEMPLATE:
2803  case OBJECT_USER_MAPPING:
2804  elog(ERROR, "unsupported object type: %d", objtype);
2805  }
2806 
2807  ereport(ERROR,
2808  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2809  errmsg(msg, objectname)));
2810  break;
2811  }
2812  case ACLCHECK_NOT_OWNER:
2813  {
2814  const char *msg = "???";
2815 
2816  switch (objtype)
2817  {
2818  case OBJECT_AGGREGATE:
2819  msg = gettext_noop("must be owner of aggregate %s");
2820  break;
2821  case OBJECT_COLLATION:
2822  msg = gettext_noop("must be owner of collation %s");
2823  break;
2824  case OBJECT_CONVERSION:
2825  msg = gettext_noop("must be owner of conversion %s");
2826  break;
2827  case OBJECT_DATABASE:
2828  msg = gettext_noop("must be owner of database %s");
2829  break;
2830  case OBJECT_DOMAIN:
2831  msg = gettext_noop("must be owner of domain %s");
2832  break;
2833  case OBJECT_EVENT_TRIGGER:
2834  msg = gettext_noop("must be owner of event trigger %s");
2835  break;
2836  case OBJECT_EXTENSION:
2837  msg = gettext_noop("must be owner of extension %s");
2838  break;
2839  case OBJECT_FDW:
2840  msg = gettext_noop("must be owner of foreign-data wrapper %s");
2841  break;
2842  case OBJECT_FOREIGN_SERVER:
2843  msg = gettext_noop("must be owner of foreign server %s");
2844  break;
2845  case OBJECT_FOREIGN_TABLE:
2846  msg = gettext_noop("must be owner of foreign table %s");
2847  break;
2848  case OBJECT_FUNCTION:
2849  msg = gettext_noop("must be owner of function %s");
2850  break;
2851  case OBJECT_INDEX:
2852  msg = gettext_noop("must be owner of index %s");
2853  break;
2854  case OBJECT_LANGUAGE:
2855  msg = gettext_noop("must be owner of language %s");
2856  break;
2857  case OBJECT_LARGEOBJECT:
2858  msg = gettext_noop("must be owner of large object %s");
2859  break;
2860  case OBJECT_MATVIEW:
2861  msg = gettext_noop("must be owner of materialized view %s");
2862  break;
2863  case OBJECT_OPCLASS:
2864  msg = gettext_noop("must be owner of operator class %s");
2865  break;
2866  case OBJECT_OPERATOR:
2867  msg = gettext_noop("must be owner of operator %s");
2868  break;
2869  case OBJECT_OPFAMILY:
2870  msg = gettext_noop("must be owner of operator family %s");
2871  break;
2872  case OBJECT_PROCEDURE:
2873  msg = gettext_noop("must be owner of procedure %s");
2874  break;
2875  case OBJECT_PUBLICATION:
2876  msg = gettext_noop("must be owner of publication %s");
2877  break;
2878  case OBJECT_ROUTINE:
2879  msg = gettext_noop("must be owner of routine %s");
2880  break;
2881  case OBJECT_SEQUENCE:
2882  msg = gettext_noop("must be owner of sequence %s");
2883  break;
2884  case OBJECT_SUBSCRIPTION:
2885  msg = gettext_noop("must be owner of subscription %s");
2886  break;
2887  case OBJECT_TABLE:
2888  msg = gettext_noop("must be owner of table %s");
2889  break;
2890  case OBJECT_TYPE:
2891  msg = gettext_noop("must be owner of type %s");
2892  break;
2893  case OBJECT_VIEW:
2894  msg = gettext_noop("must be owner of view %s");
2895  break;
2896  case OBJECT_SCHEMA:
2897  msg = gettext_noop("must be owner of schema %s");
2898  break;
2899  case OBJECT_STATISTIC_EXT:
2900  msg = gettext_noop("must be owner of statistics object %s");
2901  break;
2902  case OBJECT_TABLESPACE:
2903  msg = gettext_noop("must be owner of tablespace %s");
2904  break;
2906  msg = gettext_noop("must be owner of text search configuration %s");
2907  break;
2908  case OBJECT_TSDICTIONARY:
2909  msg = gettext_noop("must be owner of text search dictionary %s");
2910  break;
2911 
2912  /*
2913  * Special cases: For these, the error message talks
2914  * about "relation", because that's where the
2915  * ownership is attached. See also
2916  * check_object_ownership().
2917  */
2918  case OBJECT_COLUMN:
2919  case OBJECT_POLICY:
2920  case OBJECT_RULE:
2921  case OBJECT_TABCONSTRAINT:
2922  case OBJECT_TRIGGER:
2923  msg = gettext_noop("must be owner of relation %s");
2924  break;
2925  /* these currently aren't used */
2926  case OBJECT_ACCESS_METHOD:
2927  case OBJECT_AMOP:
2928  case OBJECT_AMPROC:
2929  case OBJECT_ATTRIBUTE:
2930  case OBJECT_CAST:
2931  case OBJECT_DEFAULT:
2932  case OBJECT_DEFACL:
2933  case OBJECT_DOMCONSTRAINT:
2934  case OBJECT_PARAMETER_ACL:
2937  case OBJECT_ROLE:
2938  case OBJECT_TRANSFORM:
2939  case OBJECT_TSPARSER:
2940  case OBJECT_TSTEMPLATE:
2941  case OBJECT_USER_MAPPING:
2942  elog(ERROR, "unsupported object type: %d", objtype);
2943  }
2944 
2945  ereport(ERROR,
2946  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2947  errmsg(msg, objectname)));
2948  break;
2949  }
2950  default:
2951  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
2952  break;
2953  }
2954 }
2955 
2956 
2957 void
2959  const char *objectname, const char *colname)
2960 {
2961  switch (aclerr)
2962  {
2963  case ACLCHECK_OK:
2964  /* no error, so return to caller */
2965  break;
2966  case ACLCHECK_NO_PRIV:
2967  ereport(ERROR,
2968  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2969  errmsg("permission denied for column \"%s\" of relation \"%s\"",
2970  colname, objectname)));
2971  break;
2972  case ACLCHECK_NOT_OWNER:
2973  /* relation msg is OK since columns don't have separate owners */
2974  aclcheck_error(aclerr, objtype, objectname);
2975  break;
2976  default:
2977  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
2978  break;
2979  }
2980 }
2981 
2982 
2983 /*
2984  * Special common handling for types: use element type instead of array type,
2985  * and format nicely
2986  */
2987 void
2989 {
2990  Oid element_type = get_element_type(typeOid);
2991 
2992  aclcheck_error(aclerr, OBJECT_TYPE, format_type_be(element_type ? element_type : typeOid));
2993 }
2994 
2995 
2996 /*
2997  * Relay for the various pg_*_mask routines depending on object kind
2998  */
2999 static AclMode
3000 pg_aclmask(ObjectType objtype, Oid object_oid, AttrNumber attnum, Oid roleid,
3001  AclMode mask, AclMaskHow how)
3002 {
3003  switch (objtype)
3004  {
3005  case OBJECT_COLUMN:
3006  return
3007  pg_class_aclmask(object_oid, roleid, mask, how) |
3008  pg_attribute_aclmask(object_oid, attnum, roleid, mask, how);
3009  case OBJECT_TABLE:
3010  case OBJECT_SEQUENCE:
3011  return pg_class_aclmask(object_oid, roleid, mask, how);
3012  case OBJECT_DATABASE:
3013  return object_aclmask(DatabaseRelationId, object_oid, roleid, mask, how);
3014  case OBJECT_FUNCTION:
3015  return object_aclmask(ProcedureRelationId, object_oid, roleid, mask, how);
3016  case OBJECT_LANGUAGE:
3017  return object_aclmask(LanguageRelationId, object_oid, roleid, mask, how);
3018  case OBJECT_LARGEOBJECT:
3019  return pg_largeobject_aclmask_snapshot(object_oid, roleid,
3020  mask, how, NULL);
3021  case OBJECT_PARAMETER_ACL:
3022  return pg_parameter_acl_aclmask(object_oid, roleid, mask, how);
3023  case OBJECT_SCHEMA:
3024  return object_aclmask(NamespaceRelationId, object_oid, roleid, mask, how);
3025  case OBJECT_STATISTIC_EXT:
3026  elog(ERROR, "grantable rights not supported for statistics objects");
3027  /* not reached, but keep compiler quiet */
3028  return ACL_NO_RIGHTS;
3029  case OBJECT_TABLESPACE:
3030  return object_aclmask(TableSpaceRelationId, object_oid, roleid, mask, how);
3031  case OBJECT_FDW:
3032  return object_aclmask(ForeignDataWrapperRelationId, object_oid, roleid, mask, how);
3033  case OBJECT_FOREIGN_SERVER:
3034  return object_aclmask(ForeignServerRelationId, object_oid, roleid, mask, how);
3035  case OBJECT_EVENT_TRIGGER:
3036  elog(ERROR, "grantable rights not supported for event triggers");
3037  /* not reached, but keep compiler quiet */
3038  return ACL_NO_RIGHTS;
3039  case OBJECT_TYPE:
3040  return object_aclmask(TypeRelationId, object_oid, roleid, mask, how);
3041  default:
3042  elog(ERROR, "unrecognized object type: %d",
3043  (int) objtype);
3044  /* not reached, but keep compiler quiet */
3045  return ACL_NO_RIGHTS;
3046  }
3047 }
3048 
3049 
3050 /* ****************************************************************
3051  * Exported routines for examining a user's privileges for various objects
3052  *
3053  * See aclmask() for a description of the common API for these functions.
3054  *
3055  * Note: we give lookup failure the full ereport treatment because the
3056  * has_xxx_privilege() family of functions allow users to pass any random
3057  * OID to these functions.
3058  * ****************************************************************
3059  */
3060 
3061 /*
3062  * Generic routine for examining a user's privileges for an object
3063  */
3064 static AclMode
3065 object_aclmask(Oid classid, Oid objectid, Oid roleid,
3066  AclMode mask, AclMaskHow how)
3067 {
3068  int cacheid;
3069  AclMode result;
3070  HeapTuple tuple;
3071  Datum aclDatum;
3072  bool isNull;
3073  Acl *acl;
3074  Oid ownerId;
3075 
3076  /* Special cases */
3077  switch (classid)
3078  {
3079  case NamespaceRelationId:
3080  return pg_namespace_aclmask(objectid, roleid, mask, how);
3081  case TypeRelationId:
3082  return pg_type_aclmask(objectid, roleid, mask, how);
3083  }
3084 
3085  /* Even more special cases */
3086  Assert(classid != RelationRelationId); /* should use pg_class_acl* */
3087  Assert(classid != LargeObjectMetadataRelationId); /* should use
3088  * pg_largeobject_acl* */
3089 
3090  /* Superusers bypass all permission checking. */
3091  if (superuser_arg(roleid))
3092  return mask;
3093 
3094  /*
3095  * Get the objects's ACL from its catalog
3096  */
3097 
3098  cacheid = get_object_catcache_oid(classid);
3099 
3100  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
3101  if (!HeapTupleIsValid(tuple))
3102  ereport(ERROR,
3103  (errcode(ERRCODE_UNDEFINED_DATABASE),
3104  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
3105 
3106  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
3107  tuple,
3108  get_object_attnum_owner(classid)));
3109 
3110  aclDatum = SysCacheGetAttr(cacheid, tuple, get_object_attnum_acl(classid),
3111  &isNull);
3112  if (isNull)
3113  {
3114  /* No ACL, so build default ACL */
3115  acl = acldefault(get_object_type(classid, objectid), ownerId);
3116  aclDatum = (Datum) 0;
3117  }
3118  else
3119  {
3120  /* detoast ACL if necessary */
3121  acl = DatumGetAclP(aclDatum);
3122  }
3123 
3124  result = aclmask(acl, roleid, ownerId, mask, how);
3125 
3126  /* if we have a detoasted copy, free it */
3127  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3128  pfree(acl);
3129 
3130  ReleaseSysCache(tuple);
3131 
3132  return result;
3133 }
3134 
3135 /*
3136  * Routine for examining a user's privileges for a column
3137  *
3138  * Note: this considers only privileges granted specifically on the column.
3139  * It is caller's responsibility to take relation-level privileges into account
3140  * as appropriate. (For the same reason, we have no special case for
3141  * superuser-ness here.)
3142  */
3143 static AclMode
3145  AclMode mask, AclMaskHow how)
3146 {
3147  return pg_attribute_aclmask_ext(table_oid, attnum, roleid,
3148  mask, how, NULL);
3149 }
3150 
3151 /*
3152  * Routine for examining a user's privileges for a column
3153  *
3154  * Does the bulk of the work for pg_attribute_aclmask(), and allows other
3155  * callers to avoid the missing attribute ERROR when is_missing is non-NULL.
3156  */
3157 static AclMode
3159  AclMode mask, AclMaskHow how, bool *is_missing)
3160 {
3161  AclMode result;
3162  HeapTuple classTuple;
3163  HeapTuple attTuple;
3164  Form_pg_class classForm;
3165  Form_pg_attribute attributeForm;
3166  Datum aclDatum;
3167  bool isNull;
3168  Acl *acl;
3169  Oid ownerId;
3170 
3171  /*
3172  * First, get the column's ACL from its pg_attribute entry
3173  */
3174  attTuple = SearchSysCache2(ATTNUM,
3175  ObjectIdGetDatum(table_oid),
3177  if (!HeapTupleIsValid(attTuple))
3178  {
3179  if (is_missing != NULL)
3180  {
3181  /* return "no privileges" instead of throwing an error */
3182  *is_missing = true;
3183  return 0;
3184  }
3185  else
3186  ereport(ERROR,
3187  (errcode(ERRCODE_UNDEFINED_COLUMN),
3188  errmsg("attribute %d of relation with OID %u does not exist",
3189  attnum, table_oid)));
3190  }
3191 
3192  attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
3193 
3194  /* Check dropped columns, too */
3195  if (attributeForm->attisdropped)
3196  {
3197  if (is_missing != NULL)
3198  {
3199  /* return "no privileges" instead of throwing an error */
3200  *is_missing = true;
3201  ReleaseSysCache(attTuple);
3202  return 0;
3203  }
3204  else
3205  ereport(ERROR,
3206  (errcode(ERRCODE_UNDEFINED_COLUMN),
3207  errmsg("attribute %d of relation with OID %u does not exist",
3208  attnum, table_oid)));
3209  }
3210 
3211  aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
3212  &isNull);
3213 
3214  /*
3215  * Here we hard-wire knowledge that the default ACL for a column grants no
3216  * privileges, so that we can fall out quickly in the very common case
3217  * where attacl is null.
3218  */
3219  if (isNull)
3220  {
3221  ReleaseSysCache(attTuple);
3222  return 0;
3223  }
3224 
3225  /*
3226  * Must get the relation's ownerId from pg_class. Since we already found
3227  * a pg_attribute entry, the only likely reason for this to fail is that a
3228  * concurrent DROP of the relation committed since then (which could only
3229  * happen if we don't have lock on the relation). We prefer to report "no
3230  * privileges" rather than failing in such a case, so as to avoid unwanted
3231  * failures in has_column_privilege() tests.
3232  */
3233  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3234  if (!HeapTupleIsValid(classTuple))
3235  {
3236  ReleaseSysCache(attTuple);
3237  return 0;
3238  }
3239  classForm = (Form_pg_class) GETSTRUCT(classTuple);
3240 
3241  ownerId = classForm->relowner;
3242 
3243  ReleaseSysCache(classTuple);
3244 
3245  /* detoast column's ACL if necessary */
3246  acl = DatumGetAclP(aclDatum);
3247 
3248  result = aclmask(acl, roleid, ownerId, mask, how);
3249 
3250  /* if we have a detoasted copy, free it */
3251  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3252  pfree(acl);
3253 
3254  ReleaseSysCache(attTuple);
3255 
3256  return result;
3257 }
3258 
3259 /*
3260  * Exported routine for examining a user's privileges for a table
3261  */
3262 AclMode
3263 pg_class_aclmask(Oid table_oid, Oid roleid,
3264  AclMode mask, AclMaskHow how)
3265 {
3266  return pg_class_aclmask_ext(table_oid, roleid, mask, how, NULL);
3267 }
3268 
3269 /*
3270  * Routine for examining a user's privileges for a table
3271  *
3272  * Does the bulk of the work for pg_class_aclmask(), and allows other
3273  * callers to avoid the missing relation ERROR when is_missing is non-NULL.
3274  */
3275 static AclMode
3276 pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask,
3277  AclMaskHow how, bool *is_missing)
3278 {
3279  AclMode result;
3280  HeapTuple tuple;
3281  Form_pg_class classForm;
3282  Datum aclDatum;
3283  bool isNull;
3284  Acl *acl;
3285  Oid ownerId;
3286 
3287  /*
3288  * Must get the relation's tuple from pg_class
3289  */
3290  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3291  if (!HeapTupleIsValid(tuple))
3292  {
3293  if (is_missing != NULL)
3294  {
3295  /* return "no privileges" instead of throwing an error */
3296  *is_missing = true;
3297  return 0;
3298  }
3299  else
3300  ereport(ERROR,
3302  errmsg("relation with OID %u does not exist",
3303  table_oid)));
3304  }
3305 
3306  classForm = (Form_pg_class) GETSTRUCT(tuple);
3307 
3308  /*
3309  * Deny anyone permission to update a system catalog unless
3310  * pg_authid.rolsuper is set.
3311  *
3312  * As of 7.4 we have some updatable system views; those shouldn't be
3313  * protected in this way. Assume the view rules can take care of
3314  * themselves. ACL_USAGE is if we ever have system sequences.
3315  */
3316  if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
3317  IsSystemClass(table_oid, classForm) &&
3318  classForm->relkind != RELKIND_VIEW &&
3319  !superuser_arg(roleid))
3321 
3322  /*
3323  * Otherwise, superusers bypass all permission-checking.
3324  */
3325  if (superuser_arg(roleid))
3326  {
3327  ReleaseSysCache(tuple);
3328  return mask;
3329  }
3330 
3331  /*
3332  * Normal case: get the relation's ACL from pg_class
3333  */
3334  ownerId = classForm->relowner;
3335 
3336  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
3337  &isNull);
3338  if (isNull)
3339  {
3340  /* No ACL, so build default ACL */
3341  switch (classForm->relkind)
3342  {
3343  case RELKIND_SEQUENCE:
3344  acl = acldefault(OBJECT_SEQUENCE, ownerId);
3345  break;
3346  default:
3347  acl = acldefault(OBJECT_TABLE, ownerId);
3348  break;
3349  }
3350  aclDatum = (Datum) 0;
3351  }
3352  else
3353  {
3354  /* detoast rel's ACL if necessary */
3355  acl = DatumGetAclP(aclDatum);
3356  }
3357 
3358  result = aclmask(acl, roleid, ownerId, mask, how);
3359 
3360  /* if we have a detoasted copy, free it */
3361  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3362  pfree(acl);
3363 
3364  ReleaseSysCache(tuple);
3365 
3366  /*
3367  * Check if ACL_SELECT is being checked and, if so, and not set already as
3368  * part of the result, then check if the user is a member of the
3369  * pg_read_all_data role, which allows read access to all relations.
3370  */
3371  if (mask & ACL_SELECT && !(result & ACL_SELECT) &&
3372  has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA))
3373  result |= ACL_SELECT;
3374 
3375  /*
3376  * Check if ACL_INSERT, ACL_UPDATE, or ACL_DELETE is being checked and, if
3377  * so, and not set already as part of the result, then check if the user
3378  * is a member of the pg_write_all_data role, which allows
3379  * INSERT/UPDATE/DELETE access to all relations (except system catalogs,
3380  * which requires superuser, see above).
3381  */
3382  if (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE) &&
3383  !(result & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
3384  has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA))
3385  result |= (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE));
3386 
3387  return result;
3388 }
3389 
3390 /*
3391  * Routine for examining a user's privileges for a configuration
3392  * parameter (GUC), identified by GUC name.
3393  */
3394 static AclMode
3395 pg_parameter_aclmask(const char *name, Oid roleid, AclMode mask, AclMaskHow how)
3396 {
3397  AclMode result;
3398  char *parname;
3399  text *partext;
3400  HeapTuple tuple;
3401 
3402  /* Superusers bypass all permission checking. */
3403  if (superuser_arg(roleid))
3404  return mask;
3405 
3406  /* Convert name to the form it should have in pg_parameter_acl... */
3408  partext = cstring_to_text(parname);
3409 
3410  /* ... and look it up */
3412 
3413  if (!HeapTupleIsValid(tuple))
3414  {
3415  /* If no entry, GUC has no permissions for non-superusers */
3416  result = ACL_NO_RIGHTS;
3417  }
3418  else
3419  {
3420  Datum aclDatum;
3421  bool isNull;
3422  Acl *acl;
3423 
3424  aclDatum = SysCacheGetAttr(PARAMETERACLNAME, tuple,
3425  Anum_pg_parameter_acl_paracl,
3426  &isNull);
3427  if (isNull)
3428  {
3429  /* No ACL, so build default ACL */
3430  acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
3431  aclDatum = (Datum) 0;
3432  }
3433  else
3434  {
3435  /* detoast ACL if necessary */
3436  acl = DatumGetAclP(aclDatum);
3437  }
3438 
3439  result = aclmask(acl, roleid, BOOTSTRAP_SUPERUSERID, mask, how);
3440 
3441  /* if we have a detoasted copy, free it */
3442  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3443  pfree(acl);
3444 
3445  ReleaseSysCache(tuple);
3446  }
3447 
3448  pfree(parname);
3449  pfree(partext);
3450 
3451  return result;
3452 }
3453 
3454 /*
3455  * Routine for examining a user's privileges for a configuration
3456  * parameter (GUC), identified by the OID of its pg_parameter_acl entry.
3457  */
3458 static AclMode
3460 {
3461  AclMode result;
3462  HeapTuple tuple;
3463  Datum aclDatum;
3464  bool isNull;
3465  Acl *acl;
3466 
3467  /* Superusers bypass all permission checking. */
3468  if (superuser_arg(roleid))
3469  return mask;
3470 
3471  /* Get the ACL from pg_parameter_acl */
3473  if (!HeapTupleIsValid(tuple))
3474  ereport(ERROR,
3475  (errcode(ERRCODE_UNDEFINED_OBJECT),
3476  errmsg("parameter ACL with OID %u does not exist",
3477  acl_oid)));
3478 
3479  aclDatum = SysCacheGetAttr(PARAMETERACLOID, tuple,
3480  Anum_pg_parameter_acl_paracl,
3481  &isNull);
3482  if (isNull)
3483  {
3484  /* No ACL, so build default ACL */
3485  acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
3486  aclDatum = (Datum) 0;
3487  }
3488  else
3489  {
3490  /* detoast ACL if necessary */
3491  acl = DatumGetAclP(aclDatum);
3492  }
3493 
3494  result = aclmask(acl, roleid, BOOTSTRAP_SUPERUSERID, mask, how);
3495 
3496  /* if we have a detoasted copy, free it */
3497  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3498  pfree(acl);
3499 
3500  ReleaseSysCache(tuple);
3501 
3502  return result;
3503 }
3504 
3505 /*
3506  * Routine for examining a user's privileges for a largeobject
3507  *
3508  * When a large object is opened for reading, it is opened relative to the
3509  * caller's snapshot, but when it is opened for writing, a current
3510  * MVCC snapshot will be used. See doc/src/sgml/lobj.sgml. This function
3511  * takes a snapshot argument so that the permissions check can be made
3512  * relative to the same snapshot that will be used to read the underlying
3513  * data. The caller will actually pass NULL for an instantaneous MVCC
3514  * snapshot, since all we do with the snapshot argument is pass it through
3515  * to systable_beginscan().
3516  */
3517 static AclMode
3519  AclMode mask, AclMaskHow how,
3520  Snapshot snapshot)
3521 {
3522  AclMode result;
3523  Relation pg_lo_meta;
3524  ScanKeyData entry[1];
3525  SysScanDesc scan;
3526  HeapTuple tuple;
3527  Datum aclDatum;
3528  bool isNull;
3529  Acl *acl;
3530  Oid ownerId;
3531 
3532  /* Superusers bypass all permission checking. */
3533  if (superuser_arg(roleid))
3534  return mask;
3535 
3536  /*
3537  * Get the largeobject's ACL from pg_largeobject_metadata
3538  */
3539  pg_lo_meta = table_open(LargeObjectMetadataRelationId,
3540  AccessShareLock);
3541 
3542  ScanKeyInit(&entry[0],
3543  Anum_pg_largeobject_metadata_oid,
3544  BTEqualStrategyNumber, F_OIDEQ,
3545  ObjectIdGetDatum(lobj_oid));
3546 
3547  scan = systable_beginscan(pg_lo_meta,
3548  LargeObjectMetadataOidIndexId, true,
3549  snapshot, 1, entry);
3550 
3551  tuple = systable_getnext(scan);
3552  if (!HeapTupleIsValid(tuple))
3553  ereport(ERROR,
3554  (errcode(ERRCODE_UNDEFINED_OBJECT),
3555  errmsg("large object %u does not exist", lobj_oid)));
3556 
3557  ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
3558 
3559  aclDatum = heap_getattr(tuple, Anum_pg_largeobject_metadata_lomacl,
3560  RelationGetDescr(pg_lo_meta), &isNull);
3561 
3562  if (isNull)
3563  {
3564  /* No ACL, so build default ACL */
3565  acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
3566  aclDatum = (Datum) 0;
3567  }
3568  else
3569  {
3570  /* detoast ACL if necessary */
3571  acl = DatumGetAclP(aclDatum);
3572  }
3573 
3574  result = aclmask(acl, roleid, ownerId, mask, how);
3575 
3576  /* if we have a detoasted copy, free it */
3577  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3578  pfree(acl);
3579 
3580  systable_endscan(scan);
3581 
3582  table_close(pg_lo_meta, AccessShareLock);
3583 
3584  return result;
3585 }
3586 
3587 /*
3588  * Routine for examining a user's privileges for a namespace
3589  */
3590 static AclMode
3591 pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
3592  AclMode mask, AclMaskHow how)
3593 {
3594  AclMode result;
3595  HeapTuple tuple;
3596  Datum aclDatum;
3597  bool isNull;
3598  Acl *acl;
3599  Oid ownerId;
3600 
3601  /* Superusers bypass all permission checking. */
3602  if (superuser_arg(roleid))
3603  return mask;
3604 
3605  /*
3606  * If we have been assigned this namespace as a temp namespace, check to
3607  * make sure we have CREATE TEMP permission on the database, and if so act
3608  * as though we have all standard (but not GRANT OPTION) permissions on
3609  * the namespace. If we don't have CREATE TEMP, act as though we have
3610  * only USAGE (and not CREATE) rights.
3611  *
3612  * This may seem redundant given the check in InitTempTableNamespace, but
3613  * it really isn't since current user ID may have changed since then. The
3614  * upshot of this behavior is that a SECURITY DEFINER function can create
3615  * temp tables that can then be accessed (if permission is granted) by
3616  * code in the same session that doesn't have permissions to create temp
3617  * tables.
3618  *
3619  * XXX Would it be safe to ereport a special error message as
3620  * InitTempTableNamespace does? Returning zero here means we'll get a
3621  * generic "permission denied for schema pg_temp_N" message, which is not
3622  * remarkably user-friendly.
3623  */
3624  if (isTempNamespace(nsp_oid))
3625  {
3626  if (object_aclcheck(DatabaseRelationId, MyDatabaseId, roleid,
3628  return mask & ACL_ALL_RIGHTS_SCHEMA;
3629  else
3630  return mask & ACL_USAGE;
3631  }
3632 
3633  /*
3634  * Get the schema's ACL from pg_namespace
3635  */
3636  tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
3637  if (!HeapTupleIsValid(tuple))
3638  ereport(ERROR,
3639  (errcode(ERRCODE_UNDEFINED_SCHEMA),
3640  errmsg("schema with OID %u does not exist", nsp_oid)));
3641 
3642  ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
3643 
3644  aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspacl,
3645  &isNull);
3646  if (isNull)
3647  {
3648  /* No ACL, so build default ACL */
3649  acl = acldefault(OBJECT_SCHEMA, ownerId);
3650  aclDatum = (Datum) 0;
3651  }
3652  else
3653  {
3654  /* detoast ACL if necessary */
3655  acl = DatumGetAclP(aclDatum);
3656  }
3657 
3658  result = aclmask(acl, roleid, ownerId, mask, how);
3659 
3660  /* if we have a detoasted copy, free it */
3661  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3662  pfree(acl);
3663 
3664  ReleaseSysCache(tuple);
3665 
3666  /*
3667  * Check if ACL_USAGE is being checked and, if so, and not set already as
3668  * part of the result, then check if the user is a member of the
3669  * pg_read_all_data or pg_write_all_data roles, which allow usage access
3670  * to all schemas.
3671  */
3672  if (mask & ACL_USAGE && !(result & ACL_USAGE) &&
3673  (has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA) ||
3674  has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA)))
3675  result |= ACL_USAGE;
3676  return result;
3677 }
3678 
3679 /*
3680  * Routine for examining a user's privileges for a type.
3681  */
3682 static AclMode
3683 pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
3684 {
3685  AclMode result;
3686  HeapTuple tuple;
3687  Datum aclDatum;
3688  bool isNull;
3689  Acl *acl;
3690  Oid ownerId;
3691 
3692  Form_pg_type typeForm;
3693 
3694  /* Bypass permission checks for superusers */
3695  if (superuser_arg(roleid))
3696  return mask;
3697 
3698  /*
3699  * Must get the type's tuple from pg_type
3700  */
3701  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
3702  if (!HeapTupleIsValid(tuple))
3703  ereport(ERROR,
3704  (errcode(ERRCODE_UNDEFINED_OBJECT),
3705  errmsg("type with OID %u does not exist",
3706  type_oid)));
3707  typeForm = (Form_pg_type) GETSTRUCT(tuple);
3708 
3709  /*
3710  * "True" array types don't manage permissions of their own; consult the
3711  * element type instead.
3712  */
3713  if (IsTrueArrayType(typeForm))
3714  {
3715  Oid elttype_oid = typeForm->typelem;
3716 
3717  ReleaseSysCache(tuple);
3718 
3719  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(elttype_oid));
3720  /* this case is not a user-facing error, so elog not ereport */
3721  if (!HeapTupleIsValid(tuple))
3722  elog(ERROR, "cache lookup failed for type %u", elttype_oid);
3723  typeForm = (Form_pg_type) GETSTRUCT(tuple);
3724  }
3725 
3726  /*
3727  * Now get the type's owner and ACL from the tuple
3728  */
3729  ownerId = typeForm->typowner;
3730 
3731  aclDatum = SysCacheGetAttr(TYPEOID, tuple,
3732  Anum_pg_type_typacl, &isNull);
3733  if (isNull)
3734  {
3735  /* No ACL, so build default ACL */
3736  acl = acldefault(OBJECT_TYPE, ownerId);
3737  aclDatum = (Datum) 0;
3738  }
3739  else
3740  {
3741  /* detoast rel's ACL if necessary */
3742  acl = DatumGetAclP(aclDatum);
3743  }
3744 
3745  result = aclmask(acl, roleid, ownerId, mask, how);
3746 
3747  /* if we have a detoasted copy, free it */
3748  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3749  pfree(acl);
3750 
3751  ReleaseSysCache(tuple);
3752 
3753  return result;
3754 }
3755 
3756 /*
3757  * Exported generic routine for checking a user's access privileges to an object
3758  */
3759 AclResult
3760 object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
3761 {
3762  if (object_aclmask(classid, objectid, roleid, mode, ACLMASK_ANY) != 0)
3763  return ACLCHECK_OK;
3764  else
3765  return ACLCHECK_NO_PRIV;
3766 }
3767 
3768 /*
3769  * Exported routine for checking a user's access privileges to a column
3770  *
3771  * Returns ACLCHECK_OK if the user has any of the privileges identified by
3772  * 'mode'; otherwise returns a suitable error code (in practice, always
3773  * ACLCHECK_NO_PRIV).
3774  *
3775  * As with pg_attribute_aclmask, only privileges granted directly on the
3776  * column are considered here.
3777  */
3778 AclResult
3780  Oid roleid, AclMode mode)
3781 {
3782  return pg_attribute_aclcheck_ext(table_oid, attnum, roleid, mode, NULL);
3783 }
3784 
3785 
3786 /*
3787  * Exported routine for checking a user's access privileges to a column
3788  *
3789  * Does the bulk of the work for pg_attribute_aclcheck(), and allows other
3790  * callers to avoid the missing attribute ERROR when is_missing is non-NULL.
3791  */
3792 AclResult
3794  Oid roleid, AclMode mode, bool *is_missing)
3795 {
3796  if (pg_attribute_aclmask_ext(table_oid, attnum, roleid, mode,
3797  ACLMASK_ANY, is_missing) != 0)
3798  return ACLCHECK_OK;
3799  else
3800  return ACLCHECK_NO_PRIV;
3801 }
3802 
3803 /*
3804  * Exported routine for checking a user's access privileges to any/all columns
3805  *
3806  * If 'how' is ACLMASK_ANY, then returns ACLCHECK_OK if user has any of the
3807  * privileges identified by 'mode' on any non-dropped column in the relation;
3808  * otherwise returns a suitable error code (in practice, always
3809  * ACLCHECK_NO_PRIV).
3810  *
3811  * If 'how' is ACLMASK_ALL, then returns ACLCHECK_OK if user has any of the
3812  * privileges identified by 'mode' on each non-dropped column in the relation
3813  * (and there must be at least one such column); otherwise returns a suitable
3814  * error code (in practice, always ACLCHECK_NO_PRIV).
3815  *
3816  * As with pg_attribute_aclmask, only privileges granted directly on the
3817  * column(s) are considered here.
3818  *
3819  * Note: system columns are not considered here; there are cases where that
3820  * might be appropriate but there are also cases where it wouldn't.
3821  */
3822 AclResult
3824  AclMaskHow how)
3825 {
3826  AclResult result;
3827  HeapTuple classTuple;
3828  Form_pg_class classForm;
3829  AttrNumber nattrs;
3830  AttrNumber curr_att;
3831 
3832  /*
3833  * Must fetch pg_class row to check number of attributes. As in
3834  * pg_attribute_aclmask, we prefer to return "no privileges" instead of
3835  * throwing an error if we get any unexpected lookup errors.
3836  */
3837  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3838  if (!HeapTupleIsValid(classTuple))
3839  return ACLCHECK_NO_PRIV;
3840  classForm = (Form_pg_class) GETSTRUCT(classTuple);
3841 
3842  nattrs = classForm->relnatts;
3843 
3844  ReleaseSysCache(classTuple);
3845 
3846  /*
3847  * Initialize result in case there are no non-dropped columns. We want to
3848  * report failure in such cases for either value of 'how'.
3849  */
3850  result = ACLCHECK_NO_PRIV;
3851 
3852  for (curr_att = 1; curr_att <= nattrs; curr_att++)
3853  {
3854  HeapTuple attTuple;
3855  AclMode attmask;
3856 
3857  attTuple = SearchSysCache2(ATTNUM,
3858  ObjectIdGetDatum(table_oid),
3859  Int16GetDatum(curr_att));
3860  if (!HeapTupleIsValid(attTuple))
3861  continue;
3862 
3863  /* ignore dropped columns */
3864  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
3865  {
3866  ReleaseSysCache(attTuple);
3867  continue;
3868  }
3869 
3870  /*
3871  * Here we hard-wire knowledge that the default ACL for a column
3872  * grants no privileges, so that we can fall out quickly in the very
3873  * common case where attacl is null.
3874  */
3875  if (heap_attisnull(attTuple, Anum_pg_attribute_attacl, NULL))
3876  attmask = 0;
3877  else
3878  attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
3879  mode, ACLMASK_ANY);
3880 
3881  ReleaseSysCache(attTuple);
3882 
3883  if (attmask != 0)
3884  {
3885  result = ACLCHECK_OK;
3886  if (how == ACLMASK_ANY)
3887  break; /* succeed on any success */
3888  }
3889  else
3890  {
3891  result = ACLCHECK_NO_PRIV;
3892  if (how == ACLMASK_ALL)
3893  break; /* fail on any failure */
3894  }
3895  }
3896 
3897  return result;
3898 }
3899 
3900 /*
3901  * Exported routine for checking a user's access privileges to a table
3902  *
3903  * Returns ACLCHECK_OK if the user has any of the privileges identified by
3904  * 'mode'; otherwise returns a suitable error code (in practice, always
3905  * ACLCHECK_NO_PRIV).
3906  */
3907 AclResult
3908 pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
3909 {
3910  return pg_class_aclcheck_ext(table_oid, roleid, mode, NULL);
3911 }
3912 
3913 /*
3914  * Exported routine for checking a user's access privileges to a table
3915  *
3916  * Does the bulk of the work for pg_class_aclcheck(), and allows other
3917  * callers to avoid the missing relation ERROR when is_missing is non-NULL.
3918  */
3919 AclResult
3920 pg_class_aclcheck_ext(Oid table_oid, Oid roleid,
3921  AclMode mode, bool *is_missing)
3922 {
3923  if (pg_class_aclmask_ext(table_oid, roleid, mode,
3924  ACLMASK_ANY, is_missing) != 0)
3925  return ACLCHECK_OK;
3926  else
3927  return ACLCHECK_NO_PRIV;
3928 }
3929 
3930 /*
3931  * Exported routine for checking a user's access privileges to a configuration
3932  * parameter (GUC), identified by GUC name.
3933  */
3934 AclResult
3936 {
3937  if (pg_parameter_aclmask(name, roleid, mode, ACLMASK_ANY) != 0)
3938  return ACLCHECK_OK;
3939  else
3940  return ACLCHECK_NO_PRIV;
3941 }
3942 
3943 /*
3944  * Exported routine for checking a user's access privileges to a largeobject
3945  */
3946 AclResult
3948  Snapshot snapshot)
3949 {
3950  if (pg_largeobject_aclmask_snapshot(lobj_oid, roleid, mode,
3951  ACLMASK_ANY, snapshot) != 0)
3952  return ACLCHECK_OK;
3953  else
3954  return ACLCHECK_NO_PRIV;
3955 }
3956 
3957 /*
3958  * Generic ownership check for an object
3959  */
3960 bool
3961 object_ownercheck(Oid classid, Oid objectid, Oid roleid)
3962 {
3963  int cacheid;
3964  Oid ownerId;
3965 
3966  /* Superusers bypass all permission checking. */
3967  if (superuser_arg(roleid))
3968  return true;
3969 
3970  cacheid = get_object_catcache_oid(classid);
3971  if (cacheid != -1)
3972  {
3973  HeapTuple tuple;
3974 
3975  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
3976  if (!HeapTupleIsValid(tuple))
3977  ereport(ERROR,
3978  (errcode(ERRCODE_UNDEFINED_OBJECT),
3979  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
3980 
3981  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
3982  tuple,
3983  get_object_attnum_owner(classid)));
3984  ReleaseSysCache(tuple);
3985  }
3986  else
3987  {
3988  /* for catalogs without an appropriate syscache */
3989 
3990  Relation rel;
3991  ScanKeyData entry[1];
3992  SysScanDesc scan;
3993  HeapTuple tuple;
3994  bool isnull;
3995 
3996  rel = table_open(classid, AccessShareLock);
3997 
3998  ScanKeyInit(&entry[0],
3999  get_object_attnum_oid(classid),
4000  BTEqualStrategyNumber, F_OIDEQ,
4001  ObjectIdGetDatum(objectid));
4002 
4003  scan = systable_beginscan(rel,
4004  get_object_oid_index(classid), true,
4005  NULL, 1, entry);
4006 
4007  tuple = systable_getnext(scan);
4008  if (!HeapTupleIsValid(tuple))
4009  ereport(ERROR,
4010  (errcode(ERRCODE_UNDEFINED_OBJECT),
4011  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
4012 
4013  ownerId = DatumGetObjectId(heap_getattr(tuple,
4014  get_object_attnum_owner(classid),
4015  RelationGetDescr(rel),
4016  &isnull));
4017  Assert(!isnull);
4018 
4019  systable_endscan(scan);
4021  }
4022 
4023  return has_privs_of_role(roleid, ownerId);
4024 }
4025 
4026 /*
4027  * Check whether specified role has CREATEROLE privilege (or is a superuser)
4028  *
4029  * Note: roles do not have owners per se; instead we use this test in
4030  * places where an ownership-like permissions test is needed for a role.
4031  * Be sure to apply it to the role trying to do the operation, not the
4032  * role being operated on! Also note that this generally should not be
4033  * considered enough privilege if the target role is a superuser.
4034  * (We don't handle that consideration here because we want to give a
4035  * separate error message for such cases, so the caller has to deal with it.)
4036  */
4037 bool
4039 {
4040  bool result = false;
4041  HeapTuple utup;
4042 
4043  /* Superusers bypass all permission checking. */
4044  if (superuser_arg(roleid))
4045  return true;
4046 
4047  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4048  if (HeapTupleIsValid(utup))
4049  {
4050  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
4051  ReleaseSysCache(utup);
4052  }
4053  return result;
4054 }
4055 
4056 bool
4058 {
4059  bool result = false;
4060  HeapTuple utup;
4061 
4062  /* Superusers bypass all permission checking. */
4063  if (superuser_arg(roleid))
4064  return true;
4065 
4066  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4067  if (HeapTupleIsValid(utup))
4068  {
4069  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
4070  ReleaseSysCache(utup);
4071  }
4072  return result;
4073 }
4074 
4075 /*
4076  * Fetch pg_default_acl entry for given role, namespace and object type
4077  * (object type must be given in pg_default_acl's encoding).
4078  * Returns NULL if no such entry.
4079  */
4080 static Acl *
4081 get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
4082 {
4083  Acl *result = NULL;
4084  HeapTuple tuple;
4085 
4087  ObjectIdGetDatum(roleId),
4088  ObjectIdGetDatum(nsp_oid),
4089  CharGetDatum(objtype));
4090 
4091  if (HeapTupleIsValid(tuple))
4092  {
4093  Datum aclDatum;
4094  bool isNull;
4095 
4096  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
4097  Anum_pg_default_acl_defaclacl,
4098  &isNull);
4099  if (!isNull)
4100  result = DatumGetAclPCopy(aclDatum);
4101  ReleaseSysCache(tuple);
4102  }
4103 
4104  return result;
4105 }
4106 
4107 /*
4108  * Get default permissions for newly created object within given schema
4109  *
4110  * Returns NULL if built-in system defaults should be used.
4111  *
4112  * If the result is not NULL, caller must call recordDependencyOnNewAcl
4113  * once the OID of the new object is known.
4114  */
4115 Acl *
4116 get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
4117 {
4118  Acl *result;
4119  Acl *glob_acl;
4120  Acl *schema_acl;
4121  Acl *def_acl;
4122  char defaclobjtype;
4123 
4124  /*
4125  * Use NULL during bootstrap, since pg_default_acl probably isn't there
4126  * yet.
4127  */
4129  return NULL;
4130 
4131  /* Check if object type is supported in pg_default_acl */
4132  switch (objtype)
4133  {
4134  case OBJECT_TABLE:
4135  defaclobjtype = DEFACLOBJ_RELATION;
4136  break;
4137 
4138  case OBJECT_SEQUENCE:
4139  defaclobjtype = DEFACLOBJ_SEQUENCE;
4140  break;
4141 
4142  case OBJECT_FUNCTION:
4143  defaclobjtype = DEFACLOBJ_FUNCTION;
4144  break;
4145 
4146  case OBJECT_TYPE:
4147  defaclobjtype = DEFACLOBJ_TYPE;
4148  break;
4149 
4150  case OBJECT_SCHEMA:
4151  defaclobjtype = DEFACLOBJ_NAMESPACE;
4152  break;
4153 
4154  default:
4155  return NULL;
4156  }
4157 
4158  /* Look up the relevant pg_default_acl entries */
4159  glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
4160  schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
4161 
4162  /* Quick out if neither entry exists */
4163  if (glob_acl == NULL && schema_acl == NULL)
4164  return NULL;
4165 
4166  /* We need to know the hard-wired default value, too */
4167  def_acl = acldefault(objtype, ownerId);
4168 
4169  /* If there's no global entry, substitute the hard-wired default */
4170  if (glob_acl == NULL)
4171  glob_acl = def_acl;
4172 
4173  /* Merge in any per-schema privileges */
4174  result = aclmerge(glob_acl, schema_acl, ownerId);
4175 
4176  /*
4177  * For efficiency, we want to return NULL if the result equals default.
4178  * This requires sorting both arrays to get an accurate comparison.
4179  */
4180  aclitemsort(result);
4181  aclitemsort(def_acl);
4182  if (aclequal(result, def_acl))
4183  result = NULL;
4184 
4185  return result;
4186 }
4187 
4188 /*
4189  * Record dependencies on roles mentioned in a new object's ACL.
4190  */
4191 void
4192 recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId,
4193  Oid ownerId, Acl *acl)
4194 {
4195  int nmembers;
4196  Oid *members;
4197 
4198  /* Nothing to do if ACL is defaulted */
4199  if (acl == NULL)
4200  return;
4201 
4202  /* Extract roles mentioned in ACL */
4203  nmembers = aclmembers(acl, &members);
4204 
4205  /* Update the shared dependency ACL info */
4206  updateAclDependencies(classId, objectId, objsubId,
4207  ownerId,
4208  0, NULL,
4209  nmembers, members);
4210 }
4211 
4212 /*
4213  * Record initial privileges for the top-level object passed in.
4214  *
4215  * For the object passed in, this will record its ACL (if any) and the ACLs of
4216  * any sub-objects (eg: columns) into pg_init_privs.
4217  */
4218 void
4219 recordExtObjInitPriv(Oid objoid, Oid classoid)
4220 {
4221  /*
4222  * pg_class / pg_attribute
4223  *
4224  * If this is a relation then we need to see if there are any sub-objects
4225  * (eg: columns) for it and, if so, be sure to call
4226  * recordExtensionInitPrivWorker() for each one.
4227  */
4228  if (classoid == RelationRelationId)
4229  {
4230  Form_pg_class pg_class_tuple;
4231  Datum aclDatum;
4232  bool isNull;
4233  HeapTuple tuple;
4234 
4235  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
4236  if (!HeapTupleIsValid(tuple))
4237  elog(ERROR, "cache lookup failed for relation %u", objoid);
4238  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
4239 
4240  /*
4241  * Indexes don't have permissions, neither do the pg_class rows for
4242  * composite types. (These cases are unreachable given the
4243  * restrictions in ALTER EXTENSION ADD, but let's check anyway.)
4244  */
4245  if (pg_class_tuple->relkind == RELKIND_INDEX ||
4246  pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
4247  pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
4248  {
4249  ReleaseSysCache(tuple);
4250  return;
4251  }
4252 
4253  /*
4254  * If this isn't a sequence then it's possibly going to have
4255  * column-level ACLs associated with it.
4256  */
4257  if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
4258  {
4259  AttrNumber curr_att;
4260  AttrNumber nattrs = pg_class_tuple->relnatts;
4261 
4262  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4263  {
4264  HeapTuple attTuple;
4265  Datum attaclDatum;
4266 
4267  attTuple = SearchSysCache2(ATTNUM,
4268  ObjectIdGetDatum(objoid),
4269  Int16GetDatum(curr_att));
4270 
4271  if (!HeapTupleIsValid(attTuple))
4272  continue;
4273 
4274  /* ignore dropped columns */
4275  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4276  {
4277  ReleaseSysCache(attTuple);
4278  continue;
4279  }
4280 
4281  attaclDatum = SysCacheGetAttr(ATTNUM, attTuple,
4282  Anum_pg_attribute_attacl,
4283  &isNull);
4284 
4285  /* no need to do anything for a NULL ACL */
4286  if (isNull)
4287  {
4288  ReleaseSysCache(attTuple);
4289  continue;
4290  }
4291 
4292  recordExtensionInitPrivWorker(objoid, classoid, curr_att,
4293  DatumGetAclP(attaclDatum));
4294 
4295  ReleaseSysCache(attTuple);
4296  }
4297  }
4298 
4299  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
4300  &isNull);
4301 
4302  /* Add the record, if any, for the top-level object */
4303  if (!isNull)
4304  recordExtensionInitPrivWorker(objoid, classoid, 0,
4305  DatumGetAclP(aclDatum));
4306 
4307  ReleaseSysCache(tuple);
4308  }
4309  /* pg_largeobject_metadata */
4310  else if (classoid == LargeObjectMetadataRelationId)
4311  {
4312  Datum aclDatum;
4313  bool isNull;
4314  HeapTuple tuple;
4315  ScanKeyData entry[1];
4316  SysScanDesc scan;
4317  Relation relation;
4318 
4319  /*
4320  * Note: this is dead code, given that we don't allow large objects to
4321  * be made extension members. But it seems worth carrying in case
4322  * some future caller of this function has need for it.
4323  */
4324  relation = table_open(LargeObjectMetadataRelationId, RowExclusiveLock);
4325 
4326  /* There's no syscache for pg_largeobject_metadata */
4327  ScanKeyInit(&entry[0],
4328  Anum_pg_largeobject_metadata_oid,
4329  BTEqualStrategyNumber, F_OIDEQ,
4330  ObjectIdGetDatum(objoid));
4331 
4332  scan = systable_beginscan(relation,
4333  LargeObjectMetadataOidIndexId, true,
4334  NULL, 1, entry);
4335 
4336  tuple = systable_getnext(scan);
4337  if (!HeapTupleIsValid(tuple))
4338  elog(ERROR, "could not find tuple for large object %u", objoid);
4339 
4340  aclDatum = heap_getattr(tuple,
4341  Anum_pg_largeobject_metadata_lomacl,
4342  RelationGetDescr(relation), &isNull);
4343 
4344  /* Add the record, if any, for the top-level object */
4345  if (!isNull)
4346  recordExtensionInitPrivWorker(objoid, classoid, 0,
4347  DatumGetAclP(aclDatum));
4348 
4349  systable_endscan(scan);
4350  }
4351  /* This will error on unsupported classoid. */
4352  else if (get_object_attnum_acl(classoid) != InvalidAttrNumber)
4353  {
4354  Datum aclDatum;
4355  bool isNull;
4356  HeapTuple tuple;
4357 
4358  tuple = SearchSysCache1(get_object_catcache_oid(classoid),
4359  ObjectIdGetDatum(objoid));
4360  if (!HeapTupleIsValid(tuple))
4361  elog(ERROR, "cache lookup failed for %s %u",
4362  get_object_class_descr(classoid), objoid);
4363 
4364  aclDatum = SysCacheGetAttr(get_object_catcache_oid(classoid), tuple,
4365  get_object_attnum_acl(classoid),
4366  &isNull);
4367 
4368  /* Add the record, if any, for the top-level object */
4369  if (!isNull)
4370  recordExtensionInitPrivWorker(objoid, classoid, 0,
4371  DatumGetAclP(aclDatum));
4372 
4373  ReleaseSysCache(tuple);
4374  }
4375 }
4376 
4377 /*
4378  * For the object passed in, remove its ACL and the ACLs of any object subIds
4379  * from pg_init_privs (via recordExtensionInitPrivWorker()).
4380  */
4381 void
4382 removeExtObjInitPriv(Oid objoid, Oid classoid)
4383 {
4384  /*
4385  * If this is a relation then we need to see if there are any sub-objects
4386  * (eg: columns) for it and, if so, be sure to call
4387  * recordExtensionInitPrivWorker() for each one.
4388  */
4389  if (classoid == RelationRelationId)
4390  {
4391  Form_pg_class pg_class_tuple;
4392  HeapTuple tuple;
4393 
4394  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
4395  if (!HeapTupleIsValid(tuple))
4396  elog(ERROR, "cache lookup failed for relation %u", objoid);
4397  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
4398 
4399  /*
4400  * Indexes don't have permissions, neither do the pg_class rows for
4401  * composite types. (These cases are unreachable given the
4402  * restrictions in ALTER EXTENSION DROP, but let's check anyway.)
4403  */
4404  if (pg_class_tuple->relkind == RELKIND_INDEX ||
4405  pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
4406  pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
4407  {
4408  ReleaseSysCache(tuple);
4409  return;
4410  }
4411 
4412  /*
4413  * If this isn't a sequence then it's possibly going to have
4414  * column-level ACLs associated with it.
4415  */
4416  if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
4417  {
4418  AttrNumber curr_att;
4419  AttrNumber nattrs = pg_class_tuple->relnatts;
4420 
4421  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4422  {
4423  HeapTuple attTuple;
4424 
4425  attTuple = SearchSysCache2(ATTNUM,
4426  ObjectIdGetDatum(objoid),
4427  Int16GetDatum(curr_att));
4428 
4429  if (!HeapTupleIsValid(attTuple))
4430  continue;
4431 
4432  /* when removing, remove all entries, even dropped columns */
4433 
4434  recordExtensionInitPrivWorker(objoid, classoid, curr_att, NULL);
4435 
4436  ReleaseSysCache(attTuple);
4437  }
4438  }
4439 
4440  ReleaseSysCache(tuple);
4441  }
4442 
4443  /* Remove the record, if any, for the top-level object */
4444  recordExtensionInitPrivWorker(objoid, classoid, 0, NULL);
4445 }
4446 
4447 /*
4448  * Record initial ACL for an extension object
4449  *
4450  * Can be called at any time, we check if 'creating_extension' is set and, if
4451  * not, exit immediately.
4452  *
4453  * Pass in the object OID, the OID of the class (the OID of the table which
4454  * the object is defined in) and the 'sub' id of the object (objsubid), if
4455  * any. If there is no 'sub' id (they are currently only used for columns of
4456  * tables) then pass in '0'. Finally, pass in the complete ACL to store.
4457  *
4458  * If an ACL already exists for this object/sub-object then we will replace
4459  * it with what is passed in.
4460  *
4461  * Passing in NULL for 'new_acl' will result in the entry for the object being
4462  * removed, if one is found.
4463  */
4464 static void
4465 recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
4466 {
4467  /*
4468  * Generally, we only record the initial privileges when an extension is
4469  * being created, but because we don't actually use CREATE EXTENSION
4470  * during binary upgrades with pg_upgrade, there is a variable to let us
4471  * know that the GRANT and REVOKE statements being issued, while this
4472  * variable is true, are for the initial privileges of the extension
4473  * object and therefore we need to record them.
4474  */
4476  return;
4477 
4478  recordExtensionInitPrivWorker(objoid, classoid, objsubid, new_acl);
4479 }
4480 
4481 /*
4482  * Record initial ACL for an extension object, worker.
4483  *
4484  * This will perform a wholesale replacement of the entire ACL for the object
4485  * passed in, therefore be sure to pass in the complete new ACL to use.
4486  *
4487  * Generally speaking, do *not* use this function directly but instead use
4488  * recordExtensionInitPriv(), which checks if 'creating_extension' is set.
4489  * This function does *not* check if 'creating_extension' is set as it is also
4490  * used when an object is added to or removed from an extension via ALTER
4491  * EXTENSION ... ADD/DROP.
4492  */
4493 static void
4494 recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
4495 {
4496  Relation relation;
4497  ScanKeyData key[3];
4498  SysScanDesc scan;
4499  HeapTuple tuple;
4500  HeapTuple oldtuple;
4501 
4502  relation = table_open(InitPrivsRelationId, RowExclusiveLock);
4503 
4504  ScanKeyInit(&key[0],
4505  Anum_pg_init_privs_objoid,
4506  BTEqualStrategyNumber, F_OIDEQ,
4507  ObjectIdGetDatum(objoid));
4508  ScanKeyInit(&key[1],
4509  Anum_pg_init_privs_classoid,
4510  BTEqualStrategyNumber, F_OIDEQ,
4511  ObjectIdGetDatum(classoid));
4512  ScanKeyInit(&key[2],
4513  Anum_pg_init_privs_objsubid,
4514  BTEqualStrategyNumber, F_INT4EQ,
4515  Int32GetDatum(objsubid));
4516 
4517  scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
4518  NULL, 3, key);
4519 
4520  /* There should exist only one entry or none. */
4521  oldtuple = systable_getnext(scan);
4522 
4523  /* If we find an entry, update it with the latest ACL. */
4524  if (HeapTupleIsValid(oldtuple))
4525  {
4526  Datum values[Natts_pg_init_privs] = {0};
4527  bool nulls[Natts_pg_init_privs] = {0};
4528  bool replace[Natts_pg_init_privs] = {0};
4529 
4530  /* If we have a new ACL to set, then update the row with it. */
4531  if (new_acl)
4532  {
4533  values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
4534  replace[Anum_pg_init_privs_initprivs - 1] = true;
4535 
4536  oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation),
4537  values, nulls, replace);
4538 
4539  CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple);
4540  }
4541  else
4542  {
4543  /* new_acl is NULL, so delete the entry we found. */
4544  CatalogTupleDelete(relation, &oldtuple->t_self);
4545  }
4546  }
4547  else
4548  {
4549  Datum values[Natts_pg_init_privs] = {0};
4550  bool nulls[Natts_pg_init_privs] = {0};
4551 
4552  /*
4553  * Only add a new entry if the new ACL is non-NULL.
4554  *
4555  * If we are passed in a NULL ACL and no entry exists, we can just
4556  * fall through and do nothing.
4557  */
4558  if (new_acl)
4559  {
4560  /* No entry found, so add it. */
4561  values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
4562  values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
4563  values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
4564 
4565  /* This function only handles initial privileges of extensions */
4566  values[Anum_pg_init_privs_privtype - 1] =
4568 
4569  values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
4570 
4571  tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
4572 
4573  CatalogTupleInsert(relation, tuple);
4574  }
4575  }
4576 
4577  systable_endscan(scan);
4578 
4579  /* prevent error when processing objects multiple times */
4581 
4582  table_close(relation, RowExclusiveLock);
4583 }
Acl * aclupdate(const Acl *old_acl, const AclItem *mod_aip, int modechg, Oid ownerId, DropBehavior behavior)
Definition: acl.c:966
bool aclequal(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:533
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5171
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4961
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1508
Acl * aclconcat(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:451
Acl * aclcopy(const Acl *orig_acl)
Definition: acl.c:431
void aclitemsort(Acl *acl)
Definition: acl.c:519
AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
Definition: acl.c:1356
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:777
Acl * make_empty_acl(void)
Definition: acl.c:422
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5281
Acl * aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
Definition: acl.c:475
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:163
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:169
AclResult
Definition: acl.h:181
@ ACLCHECK_NO_PRIV
Definition: acl.h:183
@ ACLCHECK_OK
Definition: acl.h:182
@ ACLCHECK_NOT_OWNER
Definition: acl.h:184
#define ACL_ALL_RIGHTS_PARAMETER_ACL
Definition: acl.h:167
#define ACL_ALL_RIGHTS_SCHEMA
Definition: acl.h:168
#define DatumGetAclP(X)
Definition: acl.h:120
#define ACL_MODECHG_DEL
Definition: acl.h:130
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:160
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:161
#define ACL_MODECHG_ADD
Definition: acl.h:129
#define ACL_ALL_RIGHTS_COLUMN
Definition: acl.h:158
#define ACL_OPTION_TO_PRIVS(privs)
Definition: acl.h:71
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:164
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:165
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:170
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:162
#define ACLITEM_SET_PRIVS_GOPTIONS(item, privs, goptions)
Definition: acl.h:82
#define ACL_NUM(ACL)
Definition: acl.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:121
#define ACL_ALL_RIGHTS_RELATION
Definition: acl.h:159
#define ACL_ID_PUBLIC
Definition: acl.h:46
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:166
AclMaskHow
Definition: acl.h:174
@ ACLMASK_ANY
Definition: acl.h:176
@ ACLMASK_ALL
Definition: acl.h:175
#define ACL_GRANT_OPTION_FOR(privs)
Definition: acl.h:70
static AclMode pg_attribute_aclmask_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3158
void ExecuteGrantStmt(GrantStmt *stmt)
Definition: aclchk.c:382
AclResult pg_largeobject_aclcheck_snapshot(Oid lobj_oid, Oid roleid, AclMode mode, Snapshot snapshot)
Definition: aclchk.c:3947
static void expand_all_col_privileges(Oid table_oid, Form_pg_class classForm, AclMode this_privileges, AclMode *col_privileges, int num_col_privileges)
Definition: aclchk.c:1612
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:4465
static void expand_col_privileges(List *colnames, Oid table_oid, AclMode this_privileges, AclMode *col_privileges, int num_col_privileges)
Definition: aclchk.c:1579
bool has_bypassrls_privilege(Oid roleid)
Definition: aclchk.c:4057
AclResult pg_class_aclcheck_ext(Oid table_oid, Oid roleid, AclMode mode, bool *is_missing)
Definition: aclchk.c:3920
void aclcheck_error_col(AclResult aclerr, ObjectType objtype, const char *objectname, const char *colname)
Definition: aclchk.c:2958
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
Definition: aclchk.c:4192
static void ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname, AttrNumber attnum, Oid ownerId, AclMode col_privileges, Relation attRelation, const Acl *old_rel_acl)
Definition: aclchk.c:1658
static void ExecGrant_Type_check(InternalGrant *istmt, HeapTuple tuple)
Definition: aclchk.c:2418
void ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *stmt)
Definition: aclchk.c:966
static void ExecGrantStmt_oids(InternalGrant *istmt)
Definition: aclchk.c:592
static AclMode pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid, AclMode mask, AclMaskHow how, Snapshot snapshot)
Definition: aclchk.c:3518
static AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3144
static List * objectNamesToOids(ObjectType objtype, List *objnames, bool is_grant)
Definition: aclchk.c:659
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:172
static AclMode pg_parameter_aclmask(const char *name, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3395
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition: aclchk.c:3823
static AclMode pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3459
static void SetDefaultACL(InternalDefaultACL *iacls)
Definition: aclchk.c:1193
static List * objectsInSchemaToOids(ObjectType objtype, List *nspnames)
Definition: aclchk.c:839
AclResult pg_parameter_aclcheck(const char *name, Oid roleid, AclMode mode)
Definition: aclchk.c:3935
static void ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs, void(*object_check)(InternalGrant *istmt, HeapTuple tuple))
Definition: aclchk.c:2131
void recordExtObjInitPriv(Oid objoid, Oid classoid)
Definition: aclchk.c:4219
static List * getRelationsInNamespace(Oid namespaceId, char relkind)
Definition: aclchk.c:928
static AclMode pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3276
static AclMode string_to_privilege(const char *privname)
Definition: aclchk.c:2583
static AclMode pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3683
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2669
static AclMode object_aclmask(Oid classid, Oid objectid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3065
static void ExecGrant_Largeobject(InternalGrant *istmt)
Definition: aclchk.c:2282
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition: aclchk.c:3779
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:231
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3760
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition: aclchk.c:4116
static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:4494
static AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3591
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:3961
AclResult pg_attribute_aclcheck_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode, bool *is_missing)
Definition: aclchk.c:3793
static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
Definition: aclchk.c:1151
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3263
static void ExecGrant_Parameter(InternalGrant *istmt)
Definition: aclchk.c:2440
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:2624
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:2988
bool has_createrole_privilege(Oid roleid)
Definition: aclchk.c:4038
static Acl * get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
Definition: aclchk.c:4081
static void ExecGrant_Relation(InternalGrant *istmt)
Definition: aclchk.c:1803
bool binary_upgrade_record_init_privs
Definition: aclchk.c:105
void RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
Definition: aclchk.c:1444
static void ExecGrant_Language_check(InternalGrant *istmt, HeapTuple tuple)
Definition: aclchk.c:2266
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:3908
static AclMode pg_aclmask(ObjectType objtype, Oid object_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3000
void removeExtObjInitPriv(Oid objoid, Oid classoid)
Definition: aclchk.c:4382
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1432
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define TextDatumGetCString(d)
Definition: builtins.h:95
#define NameStr(name)
Definition: c.h:735
signed int int32
Definition: c.h:483
#define gettext_noop(x)
Definition: c.h:1209
char * Pointer
Definition: c.h:472
#define OidIsValid(objectId)
Definition: c.h:764
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:393
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:87
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:3037
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:385
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:328
@ DEPENDENCY_AUTO
Definition: dependency.h:34
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
bool EventTriggerSupportsObjectType(ObjectType obtype)
void EventTriggerCollectGrant(InternalGrant *istmt)
bool creating_extension
Definition: extension.c:73
#define palloc0_array(type, count)
Definition: fe_memutils.h:65
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition: foreign.c:691
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition: foreign.c:668
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:599
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:506
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
Oid MyDatabaseId
Definition: globals.c:89
char * convert_GUC_name_for_parameter_acl(const char *name)
Definition: guc.c:1339
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1086
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1108
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1201
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:447
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define stmt
Definition: indent_codes.h:59
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
int j
Definition: isn.c:74
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:338
List * lappend_oid(List *list, Oid datum)
Definition: list.c:374
List * list_concat(List *list1, const List *list2)
Definition: list.c:560
#define NoLock
Definition: lockdefs.h:34
#define AccessShareLock
Definition: lockdefs.h:36
#define RowExclusiveLock
Definition: lockdefs.h:38
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:857
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2741
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1932
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:459
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc0(Size size)
Definition: mcxt.c:1257
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:414
Oid GetUserId(void)
Definition: miscinit.c:509
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2918
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3182
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3068
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:79
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
AttrNumber get_object_attnum_owner(Oid class_id)
AttrNumber get_object_attnum_oid(Oid class_id)
AttrNumber get_object_attnum_name(Oid class_id)
AttrNumber get_object_attnum_acl(Oid class_id)
int get_object_catcache_oid(Oid class_id)
Oid get_object_oid_index(Oid class_id)
ObjectType get_object_type(Oid class_id, Oid object_id)
const char * get_object_class_descr(Oid class_id)
Oid oidparse(Node *node)
Definition: oid.c:234
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2205
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291
@ ROLESPEC_PUBLIC
Definition: parsenodes.h:395
#define ACL_CREATE_TEMP
Definition: parsenodes.h:93
#define ACL_SET
Definition: parsenodes.h:95
#define ACL_DELETE
Definition: parsenodes.h:86
uint64 AclMode
Definition: parsenodes.h:81
#define ACL_USAGE
Definition: parsenodes.h:91
#define ACL_INSERT
Definition: parsenodes.h:83
#define ACL_NO_RIGHTS
Definition: parsenodes.h:98
#define ACL_UPDATE
Definition: parsenodes.h:85
DropBehavior
Definition: parsenodes.h:2192
@ DROP_CASCADE
Definition: parsenodes.h:2194
@ DROP_RESTRICT
Definition: parsenodes.h:2193
ObjectType
Definition: parsenodes.h:2119
@ OBJECT_EVENT_TRIGGER
Definition: parsenodes.h:2134
@ OBJECT_FDW
Definition: parsenodes.h:2136
@ OBJECT_TSPARSER
Definition: parsenodes.h:2167
@ OBJECT_COLLATION
Definition: parsenodes.h:2127
@ OBJECT_USER_MAPPING
Definition: parsenodes.h:2170
@ OBJECT_ACCESS_METHOD
Definition: parsenodes.h:2120
@ OBJECT_OPCLASS
Definition: parsenodes.h:2144
@ OBJECT_DEFACL
Definition: parsenodes.h:2131
@ OBJECT_AGGREGATE
Definition: parsenodes.h:2121
@ OBJECT_MATVIEW
Definition: parsenodes.h:2143
@ OBJECT_SCHEMA
Definition: parsenodes.h:2156
@ OBJECT_POLICY
Definition: parsenodes.h:2148
@ OBJECT_OPERATOR
Definition: parsenodes.h:2145
@ OBJECT_FOREIGN_TABLE
Definition: parsenodes.h:2138
@ OBJECT_TSCONFIGURATION
Definition: parsenodes.h:2165
@ OBJECT_OPFAMILY
Definition: parsenodes.h:2146
@ OBJECT_DOMAIN
Definition: parsenodes.h:2132
@ OBJECT_COLUMN
Definition: parsenodes.h:2126
@ OBJECT_TABLESPACE
Definition: parsenodes.h:2162
@ OBJECT_ROLE
Definition: parsenodes.h:2153
@ OBJECT_ROUTINE
Definition: parsenodes.h:2154
@ OBJECT_LARGEOBJECT
Definition: parsenodes.h:2142
@ OBJECT_PUBLICATION_NAMESPACE
Definition: parsenodes.h:2151
@ OBJECT_PROCEDURE
Definition: parsenodes.h:2149
@ OBJECT_EXTENSION
Definition: parsenodes.h:2135
@ OBJECT_INDEX
Definition: parsenodes.h:2140
@ OBJECT_DEFAULT
Definition: parsenodes.h:2130
@ OBJECT_DATABASE
Definition: parsenodes.h:2129
@ OBJECT_SEQUENCE
Definition: parsenodes.h:2157
@ OBJECT_TSTEMPLATE
Definition: parsenodes.h:2168
@ OBJECT_LANGUAGE
Definition: parsenodes.h:2141
@ OBJECT_AMOP
Definition: parsenodes.h:2122
@ OBJECT_PUBLICATION_REL
Definition: parsenodes.h:2152
@ OBJECT_FOREIGN_SERVER
Definition: parsenodes.h:2137
@ OBJECT_TSDICTIONARY
Definition: parsenodes.h:2166
@ OBJECT_ATTRIBUTE
Definition: parsenodes.h:2124
@ OBJECT_PUBLICATION
Definition: parsenodes.h:2150
@ OBJECT_RULE
Definition: parsenodes.h:2155
@ OBJECT_CONVERSION
Definition: parsenodes.h:2128
@ OBJECT_AMPROC
Definition: parsenodes.h:2123
@ OBJECT_TABLE
Definition: parsenodes.h:2161
@ OBJECT_VIEW
Definition: parsenodes.h:2171
@ OBJECT_PARAMETER_ACL
Definition: parsenodes.h:2147
@ OBJECT_TYPE
Definition: parsenodes.h:2169
@ OBJECT_FUNCTION
Definition: parsenodes.h:2139
@ OBJECT_TABCONSTRAINT
Definition: parsenodes.h:2160
@ OBJECT_DOMCONSTRAINT
Definition: parsenodes.h:2133
@ OBJECT_SUBSCRIPTION
Definition: parsenodes.h:2158
@ OBJECT_STATISTIC_EXT
Definition: parsenodes.h:2159
@ OBJECT_CAST
Definition: parsenodes.h:2125
@ OBJECT_TRIGGER
Definition: parsenodes.h:2164
@ OBJECT_TRANSFORM
Definition: parsenodes.h:2163
@ ACL_TARGET_OBJECT
Definition: parsenodes.h:2347
@ ACL_TARGET_ALL_IN_SCHEMA
Definition: parsenodes.h:2348
#define ACL_CONNECT
Definition: parsenodes.h:94
#define ACL_ALTER_SYSTEM
Definition: parsenodes.h:96
#define ACL_REFERENCES
Definition: parsenodes.h:88
#define ACL_SELECT
Definition: parsenodes.h:84
#define ACL_TRUNCATE
Definition: parsenodes.h:87
#define ACL_EXECUTE
Definition: parsenodes.h:90
#define ACL_CREATE
Definition: parsenodes.h:92
#define ACL_TRIGGER
Definition: parsenodes.h:89
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
bool rolcreaterole
Definition: pg_authid.h:37
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
bool rolbypassrls
Definition: pg_authid.h:41
static PgChecksumMode mode
Definition: pg_checksums.c:56
NameData relname
Definition: pg_class.h:38
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define NAMEDATALEN
FormData_pg_default_acl * Form_pg_default_acl
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
@ INITPRIVS_EXTENSION
Definition: pg_init_privs.h:80
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
bool LargeObjectExists(Oid loid)
FormData_pg_largeobject_metadata * Form_pg_largeobject_metadata
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
#define list_make1_oid(x1)
Definition: pg_list.h:242
#define lfirst_oid(lc)
Definition: pg_list.h:174
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:52
Oid ParameterAclLookup(const char *parameter, bool missing_ok)
Oid ParameterAclCreate(const char *parameter)
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:482
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:165
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
NameData typname
Definition: pg_type.h:41
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:78
#define snprintf
Definition: port.h:238
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static Name DatumGetName(Datum X)
Definition: postgres.h:360
uintptr_t Datum
Definition: postgres.h:64
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
static Datum CharGetDatum(char X)
Definition: postgres.h:122
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:228
#define RelationGetDescr(relation)
Definition: rel.h:530
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
@ ForwardScanDirection
Definition: sdir.h:28
#define BTEqualStrategyNumber
Definition: stratnum.h:31
char * dbname
Definition: streamutil.c:51
char * priv_name
Definition: parsenodes.h:2404
List * cols
Definition: parsenodes.h:2405
Definition: acl.h:55
Oid ai_grantee
Definition: acl.h:56
Oid ai_grantor
Definition: acl.h:57
char * defname
Definition: parsenodes.h:809
Node * arg
Definition: parsenodes.h:810
ItemPointerData t_self
Definition: htup.h:65
bool grant_option
Definition: aclchk.c:96
AclMode privileges
Definition: aclchk.c:94
List * grantees
Definition: aclchk.c:95
DropBehavior behavior
Definition: aclchk.c:97
ObjectType objtype
Definition: aclchk.c:92
DropBehavior behavior
AclMode privileges
ObjectType objtype
Definition: pg_list.h:54
RoleSpecType roletype
Definition: parsenodes.h:401
Definition: c.h:676
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:868
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:842
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1081
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:831
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:1112
@ PARAMETERACLOID
Definition: syscache.h:76
@ TYPEOID
Definition: syscache.h:114
@ AUTHOID
Definition: syscache.h:45
@ ATTNUM
Definition: syscache.h:41
@ RELOID
Definition: syscache.h:89
@ PARAMETERACLNAME
Definition: syscache.h:75
@ DEFACLROLENSPOBJ
Definition: syscache.h:56
@ NAMESPACEOID
Definition: syscache.h:70
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1009
#define strVal(v)
Definition: value.h:82
text * cstring_to_text(const char *s)
Definition: varlena.c:182
const char * name
void CommandCounterIncrement(void)
Definition: xact.c:1078