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, "maintain") == 0)
2616  return ACL_MAINTAIN;
2617  if (strcmp(privname, "rule") == 0)
2618  return 0; /* ignore old RULE privileges */
2619  ereport(ERROR,
2620  (errcode(ERRCODE_SYNTAX_ERROR),
2621  errmsg("unrecognized privilege type \"%s\"", privname)));
2622  return 0; /* appease compiler */
2623 }
2624 
2625 static const char *
2627 {
2628  switch (privilege)
2629  {
2630  case ACL_INSERT:
2631  return "INSERT";
2632  case ACL_SELECT:
2633  return "SELECT";
2634  case ACL_UPDATE:
2635  return "UPDATE";
2636  case ACL_DELETE:
2637  return "DELETE";
2638  case ACL_TRUNCATE:
2639  return "TRUNCATE";
2640  case ACL_REFERENCES:
2641  return "REFERENCES";
2642  case ACL_TRIGGER:
2643  return "TRIGGER";
2644  case ACL_EXECUTE:
2645  return "EXECUTE";
2646  case ACL_USAGE:
2647  return "USAGE";
2648  case ACL_CREATE:
2649  return "CREATE";
2650  case ACL_CREATE_TEMP:
2651  return "TEMP";
2652  case ACL_CONNECT:
2653  return "CONNECT";
2654  case ACL_SET:
2655  return "SET";
2656  case ACL_ALTER_SYSTEM:
2657  return "ALTER SYSTEM";
2658  case ACL_MAINTAIN:
2659  return "MAINTAIN";
2660  default:
2661  elog(ERROR, "unrecognized privilege: %d", (int) privilege);
2662  }
2663  return NULL; /* appease compiler */
2664 }
2665 
2666 /*
2667  * Standardized reporting of aclcheck permissions failures.
2668  *
2669  * Note: we do not double-quote the %s's below, because many callers
2670  * supply strings that might be already quoted.
2671  */
2672 void
2674  const char *objectname)
2675 {
2676  switch (aclerr)
2677  {
2678  case ACLCHECK_OK:
2679  /* no error, so return to caller */
2680  break;
2681  case ACLCHECK_NO_PRIV:
2682  {
2683  const char *msg = "???";
2684 
2685  switch (objtype)
2686  {
2687  case OBJECT_AGGREGATE:
2688  msg = gettext_noop("permission denied for aggregate %s");
2689  break;
2690  case OBJECT_COLLATION:
2691  msg = gettext_noop("permission denied for collation %s");
2692  break;
2693  case OBJECT_COLUMN:
2694  msg = gettext_noop("permission denied for column %s");
2695  break;
2696  case OBJECT_CONVERSION:
2697  msg = gettext_noop("permission denied for conversion %s");
2698  break;
2699  case OBJECT_DATABASE:
2700  msg = gettext_noop("permission denied for database %s");
2701  break;
2702  case OBJECT_DOMAIN:
2703  msg = gettext_noop("permission denied for domain %s");
2704  break;
2705  case OBJECT_EVENT_TRIGGER:
2706  msg = gettext_noop("permission denied for event trigger %s");
2707  break;
2708  case OBJECT_EXTENSION:
2709  msg = gettext_noop("permission denied for extension %s");
2710  break;
2711  case OBJECT_FDW:
2712  msg = gettext_noop("permission denied for foreign-data wrapper %s");
2713  break;
2714  case OBJECT_FOREIGN_SERVER:
2715  msg = gettext_noop("permission denied for foreign server %s");
2716  break;
2717  case OBJECT_FOREIGN_TABLE:
2718  msg = gettext_noop("permission denied for foreign table %s");
2719  break;
2720  case OBJECT_FUNCTION:
2721  msg = gettext_noop("permission denied for function %s");
2722  break;
2723  case OBJECT_INDEX:
2724  msg = gettext_noop("permission denied for index %s");
2725  break;
2726  case OBJECT_LANGUAGE:
2727  msg = gettext_noop("permission denied for language %s");
2728  break;
2729  case OBJECT_LARGEOBJECT:
2730  msg = gettext_noop("permission denied for large object %s");
2731  break;
2732  case OBJECT_MATVIEW:
2733  msg = gettext_noop("permission denied for materialized view %s");
2734  break;
2735  case OBJECT_OPCLASS:
2736  msg = gettext_noop("permission denied for operator class %s");
2737  break;
2738  case OBJECT_OPERATOR:
2739  msg = gettext_noop("permission denied for operator %s");
2740  break;
2741  case OBJECT_OPFAMILY:
2742  msg = gettext_noop("permission denied for operator family %s");
2743  break;
2744  case OBJECT_PARAMETER_ACL:
2745  msg = gettext_noop("permission denied for parameter %s");
2746  break;
2747  case OBJECT_POLICY:
2748  msg = gettext_noop("permission denied for policy %s");
2749  break;
2750  case OBJECT_PROCEDURE:
2751  msg = gettext_noop("permission denied for procedure %s");
2752  break;
2753  case OBJECT_PUBLICATION:
2754  msg = gettext_noop("permission denied for publication %s");
2755  break;
2756  case OBJECT_ROUTINE:
2757  msg = gettext_noop("permission denied for routine %s");
2758  break;
2759  case OBJECT_SCHEMA:
2760  msg = gettext_noop("permission denied for schema %s");
2761  break;
2762  case OBJECT_SEQUENCE:
2763  msg = gettext_noop("permission denied for sequence %s");
2764  break;
2765  case OBJECT_STATISTIC_EXT:
2766  msg = gettext_noop("permission denied for statistics object %s");
2767  break;
2768  case OBJECT_SUBSCRIPTION:
2769  msg = gettext_noop("permission denied for subscription %s");
2770  break;
2771  case OBJECT_TABLE:
2772  msg = gettext_noop("permission denied for table %s");
2773  break;
2774  case OBJECT_TABLESPACE:
2775  msg = gettext_noop("permission denied for tablespace %s");
2776  break;
2778  msg = gettext_noop("permission denied for text search configuration %s");
2779  break;
2780  case OBJECT_TSDICTIONARY:
2781  msg = gettext_noop("permission denied for text search dictionary %s");
2782  break;
2783  case OBJECT_TYPE:
2784  msg = gettext_noop("permission denied for type %s");
2785  break;
2786  case OBJECT_VIEW:
2787  msg = gettext_noop("permission denied for view %s");
2788  break;
2789  /* these currently aren't used */
2790  case OBJECT_ACCESS_METHOD:
2791  case OBJECT_AMOP:
2792  case OBJECT_AMPROC:
2793  case OBJECT_ATTRIBUTE:
2794  case OBJECT_CAST:
2795  case OBJECT_DEFAULT:
2796  case OBJECT_DEFACL:
2797  case OBJECT_DOMCONSTRAINT:
2800  case OBJECT_ROLE:
2801  case OBJECT_RULE:
2802  case OBJECT_TABCONSTRAINT:
2803  case OBJECT_TRANSFORM:
2804  case OBJECT_TRIGGER:
2805  case OBJECT_TSPARSER:
2806  case OBJECT_TSTEMPLATE:
2807  case OBJECT_USER_MAPPING:
2808  elog(ERROR, "unsupported object type: %d", objtype);
2809  }
2810 
2811  ereport(ERROR,
2812  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2813  errmsg(msg, objectname)));
2814  break;
2815  }
2816  case ACLCHECK_NOT_OWNER:
2817  {
2818  const char *msg = "???";
2819 
2820  switch (objtype)
2821  {
2822  case OBJECT_AGGREGATE:
2823  msg = gettext_noop("must be owner of aggregate %s");
2824  break;
2825  case OBJECT_COLLATION:
2826  msg = gettext_noop("must be owner of collation %s");
2827  break;
2828  case OBJECT_CONVERSION:
2829  msg = gettext_noop("must be owner of conversion %s");
2830  break;
2831  case OBJECT_DATABASE:
2832  msg = gettext_noop("must be owner of database %s");
2833  break;
2834  case OBJECT_DOMAIN:
2835  msg = gettext_noop("must be owner of domain %s");
2836  break;
2837  case OBJECT_EVENT_TRIGGER:
2838  msg = gettext_noop("must be owner of event trigger %s");
2839  break;
2840  case OBJECT_EXTENSION:
2841  msg = gettext_noop("must be owner of extension %s");
2842  break;
2843  case OBJECT_FDW:
2844  msg = gettext_noop("must be owner of foreign-data wrapper %s");
2845  break;
2846  case OBJECT_FOREIGN_SERVER:
2847  msg = gettext_noop("must be owner of foreign server %s");
2848  break;
2849  case OBJECT_FOREIGN_TABLE:
2850  msg = gettext_noop("must be owner of foreign table %s");
2851  break;
2852  case OBJECT_FUNCTION:
2853  msg = gettext_noop("must be owner of function %s");
2854  break;
2855  case OBJECT_INDEX:
2856  msg = gettext_noop("must be owner of index %s");
2857  break;
2858  case OBJECT_LANGUAGE:
2859  msg = gettext_noop("must be owner of language %s");
2860  break;
2861  case OBJECT_LARGEOBJECT:
2862  msg = gettext_noop("must be owner of large object %s");
2863  break;
2864  case OBJECT_MATVIEW:
2865  msg = gettext_noop("must be owner of materialized view %s");
2866  break;
2867  case OBJECT_OPCLASS:
2868  msg = gettext_noop("must be owner of operator class %s");
2869  break;
2870  case OBJECT_OPERATOR:
2871  msg = gettext_noop("must be owner of operator %s");
2872  break;
2873  case OBJECT_OPFAMILY:
2874  msg = gettext_noop("must be owner of operator family %s");
2875  break;
2876  case OBJECT_PROCEDURE:
2877  msg = gettext_noop("must be owner of procedure %s");
2878  break;
2879  case OBJECT_PUBLICATION:
2880  msg = gettext_noop("must be owner of publication %s");
2881  break;
2882  case OBJECT_ROUTINE:
2883  msg = gettext_noop("must be owner of routine %s");
2884  break;
2885  case OBJECT_SEQUENCE:
2886  msg = gettext_noop("must be owner of sequence %s");
2887  break;
2888  case OBJECT_SUBSCRIPTION:
2889  msg = gettext_noop("must be owner of subscription %s");
2890  break;
2891  case OBJECT_TABLE:
2892  msg = gettext_noop("must be owner of table %s");
2893  break;
2894  case OBJECT_TYPE:
2895  msg = gettext_noop("must be owner of type %s");
2896  break;
2897  case OBJECT_VIEW:
2898  msg = gettext_noop("must be owner of view %s");
2899  break;
2900  case OBJECT_SCHEMA:
2901  msg = gettext_noop("must be owner of schema %s");
2902  break;
2903  case OBJECT_STATISTIC_EXT:
2904  msg = gettext_noop("must be owner of statistics object %s");
2905  break;
2906  case OBJECT_TABLESPACE:
2907  msg = gettext_noop("must be owner of tablespace %s");
2908  break;
2910  msg = gettext_noop("must be owner of text search configuration %s");
2911  break;
2912  case OBJECT_TSDICTIONARY:
2913  msg = gettext_noop("must be owner of text search dictionary %s");
2914  break;
2915 
2916  /*
2917  * Special cases: For these, the error message talks
2918  * about "relation", because that's where the
2919  * ownership is attached. See also
2920  * check_object_ownership().
2921  */
2922  case OBJECT_COLUMN:
2923  case OBJECT_POLICY:
2924  case OBJECT_RULE:
2925  case OBJECT_TABCONSTRAINT:
2926  case OBJECT_TRIGGER:
2927  msg = gettext_noop("must be owner of relation %s");
2928  break;
2929  /* these currently aren't used */
2930  case OBJECT_ACCESS_METHOD:
2931  case OBJECT_AMOP:
2932  case OBJECT_AMPROC:
2933  case OBJECT_ATTRIBUTE:
2934  case OBJECT_CAST:
2935  case OBJECT_DEFAULT:
2936  case OBJECT_DEFACL:
2937  case OBJECT_DOMCONSTRAINT:
2938  case OBJECT_PARAMETER_ACL:
2941  case OBJECT_ROLE:
2942  case OBJECT_TRANSFORM:
2943  case OBJECT_TSPARSER:
2944  case OBJECT_TSTEMPLATE:
2945  case OBJECT_USER_MAPPING:
2946  elog(ERROR, "unsupported object type: %d", objtype);
2947  }
2948 
2949  ereport(ERROR,
2950  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2951  errmsg(msg, objectname)));
2952  break;
2953  }
2954  default:
2955  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
2956  break;
2957  }
2958 }
2959 
2960 
2961 void
2963  const char *objectname, const char *colname)
2964 {
2965  switch (aclerr)
2966  {
2967  case ACLCHECK_OK:
2968  /* no error, so return to caller */
2969  break;
2970  case ACLCHECK_NO_PRIV:
2971  ereport(ERROR,
2972  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2973  errmsg("permission denied for column \"%s\" of relation \"%s\"",
2974  colname, objectname)));
2975  break;
2976  case ACLCHECK_NOT_OWNER:
2977  /* relation msg is OK since columns don't have separate owners */
2978  aclcheck_error(aclerr, objtype, objectname);
2979  break;
2980  default:
2981  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
2982  break;
2983  }
2984 }
2985 
2986 
2987 /*
2988  * Special common handling for types: use element type instead of array type,
2989  * and format nicely
2990  */
2991 void
2993 {
2994  Oid element_type = get_element_type(typeOid);
2995 
2996  aclcheck_error(aclerr, OBJECT_TYPE, format_type_be(element_type ? element_type : typeOid));
2997 }
2998 
2999 
3000 /*
3001  * Relay for the various pg_*_mask routines depending on object kind
3002  */
3003 static AclMode
3004 pg_aclmask(ObjectType objtype, Oid object_oid, AttrNumber attnum, Oid roleid,
3005  AclMode mask, AclMaskHow how)
3006 {
3007  switch (objtype)
3008  {
3009  case OBJECT_COLUMN:
3010  return
3011  pg_class_aclmask(object_oid, roleid, mask, how) |
3012  pg_attribute_aclmask(object_oid, attnum, roleid, mask, how);
3013  case OBJECT_TABLE:
3014  case OBJECT_SEQUENCE:
3015  return pg_class_aclmask(object_oid, roleid, mask, how);
3016  case OBJECT_DATABASE:
3017  return object_aclmask(DatabaseRelationId, object_oid, roleid, mask, how);
3018  case OBJECT_FUNCTION:
3019  return object_aclmask(ProcedureRelationId, object_oid, roleid, mask, how);
3020  case OBJECT_LANGUAGE:
3021  return object_aclmask(LanguageRelationId, object_oid, roleid, mask, how);
3022  case OBJECT_LARGEOBJECT:
3023  return pg_largeobject_aclmask_snapshot(object_oid, roleid,
3024  mask, how, NULL);
3025  case OBJECT_PARAMETER_ACL:
3026  return pg_parameter_acl_aclmask(object_oid, roleid, mask, how);
3027  case OBJECT_SCHEMA:
3028  return object_aclmask(NamespaceRelationId, object_oid, roleid, mask, how);
3029  case OBJECT_STATISTIC_EXT:
3030  elog(ERROR, "grantable rights not supported for statistics objects");
3031  /* not reached, but keep compiler quiet */
3032  return ACL_NO_RIGHTS;
3033  case OBJECT_TABLESPACE:
3034  return object_aclmask(TableSpaceRelationId, object_oid, roleid, mask, how);
3035  case OBJECT_FDW:
3036  return object_aclmask(ForeignDataWrapperRelationId, object_oid, roleid, mask, how);
3037  case OBJECT_FOREIGN_SERVER:
3038  return object_aclmask(ForeignServerRelationId, object_oid, roleid, mask, how);
3039  case OBJECT_EVENT_TRIGGER:
3040  elog(ERROR, "grantable rights not supported for event triggers");
3041  /* not reached, but keep compiler quiet */
3042  return ACL_NO_RIGHTS;
3043  case OBJECT_TYPE:
3044  return object_aclmask(TypeRelationId, object_oid, roleid, mask, how);
3045  default:
3046  elog(ERROR, "unrecognized object type: %d",
3047  (int) objtype);
3048  /* not reached, but keep compiler quiet */
3049  return ACL_NO_RIGHTS;
3050  }
3051 }
3052 
3053 
3054 /* ****************************************************************
3055  * Exported routines for examining a user's privileges for various objects
3056  *
3057  * See aclmask() for a description of the common API for these functions.
3058  *
3059  * Note: we give lookup failure the full ereport treatment because the
3060  * has_xxx_privilege() family of functions allow users to pass any random
3061  * OID to these functions.
3062  * ****************************************************************
3063  */
3064 
3065 /*
3066  * Generic routine for examining a user's privileges for an object
3067  */
3068 static AclMode
3069 object_aclmask(Oid classid, Oid objectid, Oid roleid,
3070  AclMode mask, AclMaskHow how)
3071 {
3072  int cacheid;
3073  AclMode result;
3074  HeapTuple tuple;
3075  Datum aclDatum;
3076  bool isNull;
3077  Acl *acl;
3078  Oid ownerId;
3079 
3080  /* Special cases */
3081  switch (classid)
3082  {
3083  case NamespaceRelationId:
3084  return pg_namespace_aclmask(objectid, roleid, mask, how);
3085  case TypeRelationId:
3086  return pg_type_aclmask(objectid, roleid, mask, how);
3087  }
3088 
3089  /* Even more special cases */
3090  Assert(classid != RelationRelationId); /* should use pg_class_acl* */
3091  Assert(classid != LargeObjectMetadataRelationId); /* should use
3092  * pg_largeobject_acl* */
3093 
3094  /* Superusers bypass all permission checking. */
3095  if (superuser_arg(roleid))
3096  return mask;
3097 
3098  /*
3099  * Get the objects's ACL from its catalog
3100  */
3101 
3102  cacheid = get_object_catcache_oid(classid);
3103 
3104  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
3105  if (!HeapTupleIsValid(tuple))
3106  ereport(ERROR,
3107  (errcode(ERRCODE_UNDEFINED_DATABASE),
3108  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
3109 
3110  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
3111  tuple,
3112  get_object_attnum_owner(classid)));
3113 
3114  aclDatum = SysCacheGetAttr(cacheid, tuple, get_object_attnum_acl(classid),
3115  &isNull);
3116  if (isNull)
3117  {
3118  /* No ACL, so build default ACL */
3119  acl = acldefault(get_object_type(classid, objectid), ownerId);
3120  aclDatum = (Datum) 0;
3121  }
3122  else
3123  {
3124  /* detoast ACL if necessary */
3125  acl = DatumGetAclP(aclDatum);
3126  }
3127 
3128  result = aclmask(acl, roleid, ownerId, mask, how);
3129 
3130  /* if we have a detoasted copy, free it */
3131  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3132  pfree(acl);
3133 
3134  ReleaseSysCache(tuple);
3135 
3136  return result;
3137 }
3138 
3139 /*
3140  * Routine for examining a user's privileges for a column
3141  *
3142  * Note: this considers only privileges granted specifically on the column.
3143  * It is caller's responsibility to take relation-level privileges into account
3144  * as appropriate. (For the same reason, we have no special case for
3145  * superuser-ness here.)
3146  */
3147 static AclMode
3149  AclMode mask, AclMaskHow how)
3150 {
3151  return pg_attribute_aclmask_ext(table_oid, attnum, roleid,
3152  mask, how, NULL);
3153 }
3154 
3155 /*
3156  * Routine for examining a user's privileges for a column
3157  *
3158  * Does the bulk of the work for pg_attribute_aclmask(), and allows other
3159  * callers to avoid the missing attribute ERROR when is_missing is non-NULL.
3160  */
3161 static AclMode
3163  AclMode mask, AclMaskHow how, bool *is_missing)
3164 {
3165  AclMode result;
3166  HeapTuple classTuple;
3167  HeapTuple attTuple;
3168  Form_pg_class classForm;
3169  Form_pg_attribute attributeForm;
3170  Datum aclDatum;
3171  bool isNull;
3172  Acl *acl;
3173  Oid ownerId;
3174 
3175  /*
3176  * First, get the column's ACL from its pg_attribute entry
3177  */
3178  attTuple = SearchSysCache2(ATTNUM,
3179  ObjectIdGetDatum(table_oid),
3181  if (!HeapTupleIsValid(attTuple))
3182  {
3183  if (is_missing != NULL)
3184  {
3185  /* return "no privileges" instead of throwing an error */
3186  *is_missing = true;
3187  return 0;
3188  }
3189  else
3190  ereport(ERROR,
3191  (errcode(ERRCODE_UNDEFINED_COLUMN),
3192  errmsg("attribute %d of relation with OID %u does not exist",
3193  attnum, table_oid)));
3194  }
3195 
3196  attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
3197 
3198  /* Check dropped columns, too */
3199  if (attributeForm->attisdropped)
3200  {
3201  if (is_missing != NULL)
3202  {
3203  /* return "no privileges" instead of throwing an error */
3204  *is_missing = true;
3205  ReleaseSysCache(attTuple);
3206  return 0;
3207  }
3208  else
3209  ereport(ERROR,
3210  (errcode(ERRCODE_UNDEFINED_COLUMN),
3211  errmsg("attribute %d of relation with OID %u does not exist",
3212  attnum, table_oid)));
3213  }
3214 
3215  aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
3216  &isNull);
3217 
3218  /*
3219  * Here we hard-wire knowledge that the default ACL for a column grants no
3220  * privileges, so that we can fall out quickly in the very common case
3221  * where attacl is null.
3222  */
3223  if (isNull)
3224  {
3225  ReleaseSysCache(attTuple);
3226  return 0;
3227  }
3228 
3229  /*
3230  * Must get the relation's ownerId from pg_class. Since we already found
3231  * a pg_attribute entry, the only likely reason for this to fail is that a
3232  * concurrent DROP of the relation committed since then (which could only
3233  * happen if we don't have lock on the relation). We prefer to report "no
3234  * privileges" rather than failing in such a case, so as to avoid unwanted
3235  * failures in has_column_privilege() tests.
3236  */
3237  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3238  if (!HeapTupleIsValid(classTuple))
3239  {
3240  ReleaseSysCache(attTuple);
3241  return 0;
3242  }
3243  classForm = (Form_pg_class) GETSTRUCT(classTuple);
3244 
3245  ownerId = classForm->relowner;
3246 
3247  ReleaseSysCache(classTuple);
3248 
3249  /* detoast column's ACL if necessary */
3250  acl = DatumGetAclP(aclDatum);
3251 
3252  result = aclmask(acl, roleid, ownerId, mask, how);
3253 
3254  /* if we have a detoasted copy, free it */
3255  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3256  pfree(acl);
3257 
3258  ReleaseSysCache(attTuple);
3259 
3260  return result;
3261 }
3262 
3263 /*
3264  * Exported routine for examining a user's privileges for a table
3265  */
3266 AclMode
3267 pg_class_aclmask(Oid table_oid, Oid roleid,
3268  AclMode mask, AclMaskHow how)
3269 {
3270  return pg_class_aclmask_ext(table_oid, roleid, mask, how, NULL);
3271 }
3272 
3273 /*
3274  * Routine for examining a user's privileges for a table
3275  *
3276  * Does the bulk of the work for pg_class_aclmask(), and allows other
3277  * callers to avoid the missing relation ERROR when is_missing is non-NULL.
3278  */
3279 static AclMode
3280 pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask,
3281  AclMaskHow how, bool *is_missing)
3282 {
3283  AclMode result;
3284  HeapTuple tuple;
3285  Form_pg_class classForm;
3286  Datum aclDatum;
3287  bool isNull;
3288  Acl *acl;
3289  Oid ownerId;
3290 
3291  /*
3292  * Must get the relation's tuple from pg_class
3293  */
3294  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3295  if (!HeapTupleIsValid(tuple))
3296  {
3297  if (is_missing != NULL)
3298  {
3299  /* return "no privileges" instead of throwing an error */
3300  *is_missing = true;
3301  return 0;
3302  }
3303  else
3304  ereport(ERROR,
3306  errmsg("relation with OID %u does not exist",
3307  table_oid)));
3308  }
3309 
3310  classForm = (Form_pg_class) GETSTRUCT(tuple);
3311 
3312  /*
3313  * Deny anyone permission to update a system catalog unless
3314  * pg_authid.rolsuper is set.
3315  *
3316  * As of 7.4 we have some updatable system views; those shouldn't be
3317  * protected in this way. Assume the view rules can take care of
3318  * themselves. ACL_USAGE is if we ever have system sequences.
3319  */
3320  if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
3321  IsSystemClass(table_oid, classForm) &&
3322  classForm->relkind != RELKIND_VIEW &&
3323  !superuser_arg(roleid))
3325 
3326  /*
3327  * Otherwise, superusers bypass all permission-checking.
3328  */
3329  if (superuser_arg(roleid))
3330  {
3331  ReleaseSysCache(tuple);
3332  return mask;
3333  }
3334 
3335  /*
3336  * Normal case: get the relation's ACL from pg_class
3337  */
3338  ownerId = classForm->relowner;
3339 
3340  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
3341  &isNull);
3342  if (isNull)
3343  {
3344  /* No ACL, so build default ACL */
3345  switch (classForm->relkind)
3346  {
3347  case RELKIND_SEQUENCE:
3348  acl = acldefault(OBJECT_SEQUENCE, ownerId);
3349  break;
3350  default:
3351  acl = acldefault(OBJECT_TABLE, ownerId);
3352  break;
3353  }
3354  aclDatum = (Datum) 0;
3355  }
3356  else
3357  {
3358  /* detoast rel's ACL if necessary */
3359  acl = DatumGetAclP(aclDatum);
3360  }
3361 
3362  result = aclmask(acl, roleid, ownerId, mask, how);
3363 
3364  /* if we have a detoasted copy, free it */
3365  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3366  pfree(acl);
3367 
3368  ReleaseSysCache(tuple);
3369 
3370  /*
3371  * Check if ACL_SELECT is being checked and, if so, and not set already as
3372  * part of the result, then check if the user is a member of the
3373  * pg_read_all_data role, which allows read access to all relations.
3374  */
3375  if (mask & ACL_SELECT && !(result & ACL_SELECT) &&
3376  has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA))
3377  result |= ACL_SELECT;
3378 
3379  /*
3380  * Check if ACL_INSERT, ACL_UPDATE, or ACL_DELETE is being checked and, if
3381  * so, and not set already as part of the result, then check if the user
3382  * is a member of the pg_write_all_data role, which allows
3383  * INSERT/UPDATE/DELETE access to all relations (except system catalogs,
3384  * which requires superuser, see above).
3385  */
3386  if (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE) &&
3387  !(result & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
3388  has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA))
3389  result |= (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE));
3390 
3391  /*
3392  * Check if ACL_MAINTAIN is being checked and, if so, and not already set as
3393  * part of the result, then check if the user is a member of the
3394  * pg_maintain role, which allows VACUUM, ANALYZE, CLUSTER, REFRESH
3395  * MATERIALIZED VIEW, and REINDEX on all relations.
3396  */
3397  if (mask & ACL_MAINTAIN &&
3398  !(result & ACL_MAINTAIN) &&
3399  has_privs_of_role(roleid, ROLE_PG_MAINTAIN))
3400  result |= ACL_MAINTAIN;
3401 
3402  return result;
3403 }
3404 
3405 /*
3406  * Routine for examining a user's privileges for a configuration
3407  * parameter (GUC), identified by GUC name.
3408  */
3409 static AclMode
3410 pg_parameter_aclmask(const char *name, Oid roleid, AclMode mask, AclMaskHow how)
3411 {
3412  AclMode result;
3413  char *parname;
3414  text *partext;
3415  HeapTuple tuple;
3416 
3417  /* Superusers bypass all permission checking. */
3418  if (superuser_arg(roleid))
3419  return mask;
3420 
3421  /* Convert name to the form it should have in pg_parameter_acl... */
3423  partext = cstring_to_text(parname);
3424 
3425  /* ... and look it up */
3427 
3428  if (!HeapTupleIsValid(tuple))
3429  {
3430  /* If no entry, GUC has no permissions for non-superusers */
3431  result = ACL_NO_RIGHTS;
3432  }
3433  else
3434  {
3435  Datum aclDatum;
3436  bool isNull;
3437  Acl *acl;
3438 
3439  aclDatum = SysCacheGetAttr(PARAMETERACLNAME, tuple,
3440  Anum_pg_parameter_acl_paracl,
3441  &isNull);
3442  if (isNull)
3443  {
3444  /* No ACL, so build default ACL */
3445  acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
3446  aclDatum = (Datum) 0;
3447  }
3448  else
3449  {
3450  /* detoast ACL if necessary */
3451  acl = DatumGetAclP(aclDatum);
3452  }
3453 
3454  result = aclmask(acl, roleid, BOOTSTRAP_SUPERUSERID, mask, how);
3455 
3456  /* if we have a detoasted copy, free it */
3457  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3458  pfree(acl);
3459 
3460  ReleaseSysCache(tuple);
3461  }
3462 
3463  pfree(parname);
3464  pfree(partext);
3465 
3466  return result;
3467 }
3468 
3469 /*
3470  * Routine for examining a user's privileges for a configuration
3471  * parameter (GUC), identified by the OID of its pg_parameter_acl entry.
3472  */
3473 static AclMode
3475 {
3476  AclMode result;
3477  HeapTuple tuple;
3478  Datum aclDatum;
3479  bool isNull;
3480  Acl *acl;
3481 
3482  /* Superusers bypass all permission checking. */
3483  if (superuser_arg(roleid))
3484  return mask;
3485 
3486  /* Get the ACL from pg_parameter_acl */
3488  if (!HeapTupleIsValid(tuple))
3489  ereport(ERROR,
3490  (errcode(ERRCODE_UNDEFINED_OBJECT),
3491  errmsg("parameter ACL with OID %u does not exist",
3492  acl_oid)));
3493 
3494  aclDatum = SysCacheGetAttr(PARAMETERACLOID, tuple,
3495  Anum_pg_parameter_acl_paracl,
3496  &isNull);
3497  if (isNull)
3498  {
3499  /* No ACL, so build default ACL */
3500  acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
3501  aclDatum = (Datum) 0;
3502  }
3503  else
3504  {
3505  /* detoast ACL if necessary */
3506  acl = DatumGetAclP(aclDatum);
3507  }
3508 
3509  result = aclmask(acl, roleid, BOOTSTRAP_SUPERUSERID, mask, how);
3510 
3511  /* if we have a detoasted copy, free it */
3512  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3513  pfree(acl);
3514 
3515  ReleaseSysCache(tuple);
3516 
3517  return result;
3518 }
3519 
3520 /*
3521  * Routine for examining a user's privileges for a largeobject
3522  *
3523  * When a large object is opened for reading, it is opened relative to the
3524  * caller's snapshot, but when it is opened for writing, a current
3525  * MVCC snapshot will be used. See doc/src/sgml/lobj.sgml. This function
3526  * takes a snapshot argument so that the permissions check can be made
3527  * relative to the same snapshot that will be used to read the underlying
3528  * data. The caller will actually pass NULL for an instantaneous MVCC
3529  * snapshot, since all we do with the snapshot argument is pass it through
3530  * to systable_beginscan().
3531  */
3532 static AclMode
3534  AclMode mask, AclMaskHow how,
3535  Snapshot snapshot)
3536 {
3537  AclMode result;
3538  Relation pg_lo_meta;
3539  ScanKeyData entry[1];
3540  SysScanDesc scan;
3541  HeapTuple tuple;
3542  Datum aclDatum;
3543  bool isNull;
3544  Acl *acl;
3545  Oid ownerId;
3546 
3547  /* Superusers bypass all permission checking. */
3548  if (superuser_arg(roleid))
3549  return mask;
3550 
3551  /*
3552  * Get the largeobject's ACL from pg_largeobject_metadata
3553  */
3554  pg_lo_meta = table_open(LargeObjectMetadataRelationId,
3555  AccessShareLock);
3556 
3557  ScanKeyInit(&entry[0],
3558  Anum_pg_largeobject_metadata_oid,
3559  BTEqualStrategyNumber, F_OIDEQ,
3560  ObjectIdGetDatum(lobj_oid));
3561 
3562  scan = systable_beginscan(pg_lo_meta,
3563  LargeObjectMetadataOidIndexId, true,
3564  snapshot, 1, entry);
3565 
3566  tuple = systable_getnext(scan);
3567  if (!HeapTupleIsValid(tuple))
3568  ereport(ERROR,
3569  (errcode(ERRCODE_UNDEFINED_OBJECT),
3570  errmsg("large object %u does not exist", lobj_oid)));
3571 
3572  ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
3573 
3574  aclDatum = heap_getattr(tuple, Anum_pg_largeobject_metadata_lomacl,
3575  RelationGetDescr(pg_lo_meta), &isNull);
3576 
3577  if (isNull)
3578  {
3579  /* No ACL, so build default ACL */
3580  acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
3581  aclDatum = (Datum) 0;
3582  }
3583  else
3584  {
3585  /* detoast ACL if necessary */
3586  acl = DatumGetAclP(aclDatum);
3587  }
3588 
3589  result = aclmask(acl, roleid, ownerId, mask, how);
3590 
3591  /* if we have a detoasted copy, free it */
3592  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3593  pfree(acl);
3594 
3595  systable_endscan(scan);
3596 
3597  table_close(pg_lo_meta, AccessShareLock);
3598 
3599  return result;
3600 }
3601 
3602 /*
3603  * Routine for examining a user's privileges for a namespace
3604  */
3605 static AclMode
3606 pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
3607  AclMode mask, AclMaskHow how)
3608 {
3609  AclMode result;
3610  HeapTuple tuple;
3611  Datum aclDatum;
3612  bool isNull;
3613  Acl *acl;
3614  Oid ownerId;
3615 
3616  /* Superusers bypass all permission checking. */
3617  if (superuser_arg(roleid))
3618  return mask;
3619 
3620  /*
3621  * If we have been assigned this namespace as a temp namespace, check to
3622  * make sure we have CREATE TEMP permission on the database, and if so act
3623  * as though we have all standard (but not GRANT OPTION) permissions on
3624  * the namespace. If we don't have CREATE TEMP, act as though we have
3625  * only USAGE (and not CREATE) rights.
3626  *
3627  * This may seem redundant given the check in InitTempTableNamespace, but
3628  * it really isn't since current user ID may have changed since then. The
3629  * upshot of this behavior is that a SECURITY DEFINER function can create
3630  * temp tables that can then be accessed (if permission is granted) by
3631  * code in the same session that doesn't have permissions to create temp
3632  * tables.
3633  *
3634  * XXX Would it be safe to ereport a special error message as
3635  * InitTempTableNamespace does? Returning zero here means we'll get a
3636  * generic "permission denied for schema pg_temp_N" message, which is not
3637  * remarkably user-friendly.
3638  */
3639  if (isTempNamespace(nsp_oid))
3640  {
3641  if (object_aclcheck(DatabaseRelationId, MyDatabaseId, roleid,
3643  return mask & ACL_ALL_RIGHTS_SCHEMA;
3644  else
3645  return mask & ACL_USAGE;
3646  }
3647 
3648  /*
3649  * Get the schema's ACL from pg_namespace
3650  */
3651  tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
3652  if (!HeapTupleIsValid(tuple))
3653  ereport(ERROR,
3654  (errcode(ERRCODE_UNDEFINED_SCHEMA),
3655  errmsg("schema with OID %u does not exist", nsp_oid)));
3656 
3657  ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
3658 
3659  aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspacl,
3660  &isNull);
3661  if (isNull)
3662  {
3663  /* No ACL, so build default ACL */
3664  acl = acldefault(OBJECT_SCHEMA, ownerId);
3665  aclDatum = (Datum) 0;
3666  }
3667  else
3668  {
3669  /* detoast ACL if necessary */
3670  acl = DatumGetAclP(aclDatum);
3671  }
3672 
3673  result = aclmask(acl, roleid, ownerId, mask, how);
3674 
3675  /* if we have a detoasted copy, free it */
3676  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3677  pfree(acl);
3678 
3679  ReleaseSysCache(tuple);
3680 
3681  /*
3682  * Check if ACL_USAGE is being checked and, if so, and not set already as
3683  * part of the result, then check if the user is a member of the
3684  * pg_read_all_data or pg_write_all_data roles, which allow usage access
3685  * to all schemas.
3686  */
3687  if (mask & ACL_USAGE && !(result & ACL_USAGE) &&
3688  (has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA) ||
3689  has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA)))
3690  result |= ACL_USAGE;
3691  return result;
3692 }
3693 
3694 /*
3695  * Routine for examining a user's privileges for a type.
3696  */
3697 static AclMode
3698 pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
3699 {
3700  AclMode result;
3701  HeapTuple tuple;
3702  Datum aclDatum;
3703  bool isNull;
3704  Acl *acl;
3705  Oid ownerId;
3706 
3707  Form_pg_type typeForm;
3708 
3709  /* Bypass permission checks for superusers */
3710  if (superuser_arg(roleid))
3711  return mask;
3712 
3713  /*
3714  * Must get the type's tuple from pg_type
3715  */
3716  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
3717  if (!HeapTupleIsValid(tuple))
3718  ereport(ERROR,
3719  (errcode(ERRCODE_UNDEFINED_OBJECT),
3720  errmsg("type with OID %u does not exist",
3721  type_oid)));
3722  typeForm = (Form_pg_type) GETSTRUCT(tuple);
3723 
3724  /*
3725  * "True" array types don't manage permissions of their own; consult the
3726  * element type instead.
3727  */
3728  if (IsTrueArrayType(typeForm))
3729  {
3730  Oid elttype_oid = typeForm->typelem;
3731 
3732  ReleaseSysCache(tuple);
3733 
3734  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(elttype_oid));
3735  /* this case is not a user-facing error, so elog not ereport */
3736  if (!HeapTupleIsValid(tuple))
3737  elog(ERROR, "cache lookup failed for type %u", elttype_oid);
3738  typeForm = (Form_pg_type) GETSTRUCT(tuple);
3739  }
3740 
3741  /*
3742  * Now get the type's owner and ACL from the tuple
3743  */
3744  ownerId = typeForm->typowner;
3745 
3746  aclDatum = SysCacheGetAttr(TYPEOID, tuple,
3747  Anum_pg_type_typacl, &isNull);
3748  if (isNull)
3749  {
3750  /* No ACL, so build default ACL */
3751  acl = acldefault(OBJECT_TYPE, ownerId);
3752  aclDatum = (Datum) 0;
3753  }
3754  else
3755  {
3756  /* detoast rel's ACL if necessary */
3757  acl = DatumGetAclP(aclDatum);
3758  }
3759 
3760  result = aclmask(acl, roleid, ownerId, mask, how);
3761 
3762  /* if we have a detoasted copy, free it */
3763  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3764  pfree(acl);
3765 
3766  ReleaseSysCache(tuple);
3767 
3768  return result;
3769 }
3770 
3771 /*
3772  * Exported generic routine for checking a user's access privileges to an object
3773  */
3774 AclResult
3775 object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
3776 {
3777  if (object_aclmask(classid, objectid, roleid, mode, ACLMASK_ANY) != 0)
3778  return ACLCHECK_OK;
3779  else
3780  return ACLCHECK_NO_PRIV;
3781 }
3782 
3783 /*
3784  * Exported routine for checking a user's access privileges to a column
3785  *
3786  * Returns ACLCHECK_OK if the user has any of the privileges identified by
3787  * 'mode'; otherwise returns a suitable error code (in practice, always
3788  * ACLCHECK_NO_PRIV).
3789  *
3790  * As with pg_attribute_aclmask, only privileges granted directly on the
3791  * column are considered here.
3792  */
3793 AclResult
3795  Oid roleid, AclMode mode)
3796 {
3797  return pg_attribute_aclcheck_ext(table_oid, attnum, roleid, mode, NULL);
3798 }
3799 
3800 
3801 /*
3802  * Exported routine for checking a user's access privileges to a column
3803  *
3804  * Does the bulk of the work for pg_attribute_aclcheck(), and allows other
3805  * callers to avoid the missing attribute ERROR when is_missing is non-NULL.
3806  */
3807 AclResult
3809  Oid roleid, AclMode mode, bool *is_missing)
3810 {
3811  if (pg_attribute_aclmask_ext(table_oid, attnum, roleid, mode,
3812  ACLMASK_ANY, is_missing) != 0)
3813  return ACLCHECK_OK;
3814  else
3815  return ACLCHECK_NO_PRIV;
3816 }
3817 
3818 /*
3819  * Exported routine for checking a user's access privileges to any/all columns
3820  *
3821  * If 'how' is ACLMASK_ANY, then returns ACLCHECK_OK if user has any of the
3822  * privileges identified by 'mode' on any non-dropped column in the relation;
3823  * otherwise returns a suitable error code (in practice, always
3824  * ACLCHECK_NO_PRIV).
3825  *
3826  * If 'how' is ACLMASK_ALL, then returns ACLCHECK_OK if user has any of the
3827  * privileges identified by 'mode' on each non-dropped column in the relation
3828  * (and there must be at least one such column); otherwise returns a suitable
3829  * error code (in practice, always ACLCHECK_NO_PRIV).
3830  *
3831  * As with pg_attribute_aclmask, only privileges granted directly on the
3832  * column(s) are considered here.
3833  *
3834  * Note: system columns are not considered here; there are cases where that
3835  * might be appropriate but there are also cases where it wouldn't.
3836  */
3837 AclResult
3839  AclMaskHow how)
3840 {
3841  AclResult result;
3842  HeapTuple classTuple;
3843  Form_pg_class classForm;
3844  AttrNumber nattrs;
3845  AttrNumber curr_att;
3846 
3847  /*
3848  * Must fetch pg_class row to check number of attributes. As in
3849  * pg_attribute_aclmask, we prefer to return "no privileges" instead of
3850  * throwing an error if we get any unexpected lookup errors.
3851  */
3852  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3853  if (!HeapTupleIsValid(classTuple))
3854  return ACLCHECK_NO_PRIV;
3855  classForm = (Form_pg_class) GETSTRUCT(classTuple);
3856 
3857  nattrs = classForm->relnatts;
3858 
3859  ReleaseSysCache(classTuple);
3860 
3861  /*
3862  * Initialize result in case there are no non-dropped columns. We want to
3863  * report failure in such cases for either value of 'how'.
3864  */
3865  result = ACLCHECK_NO_PRIV;
3866 
3867  for (curr_att = 1; curr_att <= nattrs; curr_att++)
3868  {
3869  HeapTuple attTuple;
3870  AclMode attmask;
3871 
3872  attTuple = SearchSysCache2(ATTNUM,
3873  ObjectIdGetDatum(table_oid),
3874  Int16GetDatum(curr_att));
3875  if (!HeapTupleIsValid(attTuple))
3876  continue;
3877 
3878  /* ignore dropped columns */
3879  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
3880  {
3881  ReleaseSysCache(attTuple);
3882  continue;
3883  }
3884 
3885  /*
3886  * Here we hard-wire knowledge that the default ACL for a column
3887  * grants no privileges, so that we can fall out quickly in the very
3888  * common case where attacl is null.
3889  */
3890  if (heap_attisnull(attTuple, Anum_pg_attribute_attacl, NULL))
3891  attmask = 0;
3892  else
3893  attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
3894  mode, ACLMASK_ANY);
3895 
3896  ReleaseSysCache(attTuple);
3897 
3898  if (attmask != 0)
3899  {
3900  result = ACLCHECK_OK;
3901  if (how == ACLMASK_ANY)
3902  break; /* succeed on any success */
3903  }
3904  else
3905  {
3906  result = ACLCHECK_NO_PRIV;
3907  if (how == ACLMASK_ALL)
3908  break; /* fail on any failure */
3909  }
3910  }
3911 
3912  return result;
3913 }
3914 
3915 /*
3916  * Exported routine for checking a user's access privileges to a table
3917  *
3918  * Returns ACLCHECK_OK if the user has any of the privileges identified by
3919  * 'mode'; otherwise returns a suitable error code (in practice, always
3920  * ACLCHECK_NO_PRIV).
3921  */
3922 AclResult
3923 pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
3924 {
3925  return pg_class_aclcheck_ext(table_oid, roleid, mode, NULL);
3926 }
3927 
3928 /*
3929  * Exported routine for checking a user's access privileges to a table
3930  *
3931  * Does the bulk of the work for pg_class_aclcheck(), and allows other
3932  * callers to avoid the missing relation ERROR when is_missing is non-NULL.
3933  */
3934 AclResult
3935 pg_class_aclcheck_ext(Oid table_oid, Oid roleid,
3936  AclMode mode, bool *is_missing)
3937 {
3938  if (pg_class_aclmask_ext(table_oid, roleid, mode,
3939  ACLMASK_ANY, is_missing) != 0)
3940  return ACLCHECK_OK;
3941  else
3942  return ACLCHECK_NO_PRIV;
3943 }
3944 
3945 /*
3946  * Exported routine for checking a user's access privileges to a configuration
3947  * parameter (GUC), identified by GUC name.
3948  */
3949 AclResult
3951 {
3952  if (pg_parameter_aclmask(name, roleid, mode, ACLMASK_ANY) != 0)
3953  return ACLCHECK_OK;
3954  else
3955  return ACLCHECK_NO_PRIV;
3956 }
3957 
3958 /*
3959  * Exported routine for checking a user's access privileges to a largeobject
3960  */
3961 AclResult
3963  Snapshot snapshot)
3964 {
3965  if (pg_largeobject_aclmask_snapshot(lobj_oid, roleid, mode,
3966  ACLMASK_ANY, snapshot) != 0)
3967  return ACLCHECK_OK;
3968  else
3969  return ACLCHECK_NO_PRIV;
3970 }
3971 
3972 /*
3973  * Generic ownership check for an object
3974  */
3975 bool
3976 object_ownercheck(Oid classid, Oid objectid, Oid roleid)
3977 {
3978  int cacheid;
3979  Oid ownerId;
3980 
3981  /* Superusers bypass all permission checking. */
3982  if (superuser_arg(roleid))
3983  return true;
3984 
3985  cacheid = get_object_catcache_oid(classid);
3986  if (cacheid != -1)
3987  {
3988  HeapTuple tuple;
3989 
3990  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
3991  if (!HeapTupleIsValid(tuple))
3992  ereport(ERROR,
3993  (errcode(ERRCODE_UNDEFINED_OBJECT),
3994  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
3995 
3996  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
3997  tuple,
3998  get_object_attnum_owner(classid)));
3999  ReleaseSysCache(tuple);
4000  }
4001  else
4002  {
4003  /* for catalogs without an appropriate syscache */
4004 
4005  Relation rel;
4006  ScanKeyData entry[1];
4007  SysScanDesc scan;
4008  HeapTuple tuple;
4009  bool isnull;
4010 
4011  rel = table_open(classid, AccessShareLock);
4012 
4013  ScanKeyInit(&entry[0],
4014  get_object_attnum_oid(classid),
4015  BTEqualStrategyNumber, F_OIDEQ,
4016  ObjectIdGetDatum(objectid));
4017 
4018  scan = systable_beginscan(rel,
4019  get_object_oid_index(classid), true,
4020  NULL, 1, entry);
4021 
4022  tuple = systable_getnext(scan);
4023  if (!HeapTupleIsValid(tuple))
4024  ereport(ERROR,
4025  (errcode(ERRCODE_UNDEFINED_OBJECT),
4026  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
4027 
4028  ownerId = DatumGetObjectId(heap_getattr(tuple,
4029  get_object_attnum_owner(classid),
4030  RelationGetDescr(rel),
4031  &isnull));
4032  Assert(!isnull);
4033 
4034  systable_endscan(scan);
4036  }
4037 
4038  return has_privs_of_role(roleid, ownerId);
4039 }
4040 
4041 /*
4042  * Check whether specified role has CREATEROLE privilege (or is a superuser)
4043  *
4044  * Note: roles do not have owners per se; instead we use this test in
4045  * places where an ownership-like permissions test is needed for a role.
4046  * Be sure to apply it to the role trying to do the operation, not the
4047  * role being operated on! Also note that this generally should not be
4048  * considered enough privilege if the target role is a superuser.
4049  * (We don't handle that consideration here because we want to give a
4050  * separate error message for such cases, so the caller has to deal with it.)
4051  */
4052 bool
4054 {
4055  bool result = false;
4056  HeapTuple utup;
4057 
4058  /* Superusers bypass all permission checking. */
4059  if (superuser_arg(roleid))
4060  return true;
4061 
4062  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4063  if (HeapTupleIsValid(utup))
4064  {
4065  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
4066  ReleaseSysCache(utup);
4067  }
4068  return result;
4069 }
4070 
4071 bool
4073 {
4074  bool result = false;
4075  HeapTuple utup;
4076 
4077  /* Superusers bypass all permission checking. */
4078  if (superuser_arg(roleid))
4079  return true;
4080 
4081  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4082  if (HeapTupleIsValid(utup))
4083  {
4084  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
4085  ReleaseSysCache(utup);
4086  }
4087  return result;
4088 }
4089 
4090 /*
4091  * Fetch pg_default_acl entry for given role, namespace and object type
4092  * (object type must be given in pg_default_acl's encoding).
4093  * Returns NULL if no such entry.
4094  */
4095 static Acl *
4096 get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
4097 {
4098  Acl *result = NULL;
4099  HeapTuple tuple;
4100 
4102  ObjectIdGetDatum(roleId),
4103  ObjectIdGetDatum(nsp_oid),
4104  CharGetDatum(objtype));
4105 
4106  if (HeapTupleIsValid(tuple))
4107  {
4108  Datum aclDatum;
4109  bool isNull;
4110 
4111  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
4112  Anum_pg_default_acl_defaclacl,
4113  &isNull);
4114  if (!isNull)
4115  result = DatumGetAclPCopy(aclDatum);
4116  ReleaseSysCache(tuple);
4117  }
4118 
4119  return result;
4120 }
4121 
4122 /*
4123  * Get default permissions for newly created object within given schema
4124  *
4125  * Returns NULL if built-in system defaults should be used.
4126  *
4127  * If the result is not NULL, caller must call recordDependencyOnNewAcl
4128  * once the OID of the new object is known.
4129  */
4130 Acl *
4131 get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
4132 {
4133  Acl *result;
4134  Acl *glob_acl;
4135  Acl *schema_acl;
4136  Acl *def_acl;
4137  char defaclobjtype;
4138 
4139  /*
4140  * Use NULL during bootstrap, since pg_default_acl probably isn't there
4141  * yet.
4142  */
4144  return NULL;
4145 
4146  /* Check if object type is supported in pg_default_acl */
4147  switch (objtype)
4148  {
4149  case OBJECT_TABLE:
4150  defaclobjtype = DEFACLOBJ_RELATION;
4151  break;
4152 
4153  case OBJECT_SEQUENCE:
4154  defaclobjtype = DEFACLOBJ_SEQUENCE;
4155  break;
4156 
4157  case OBJECT_FUNCTION:
4158  defaclobjtype = DEFACLOBJ_FUNCTION;
4159  break;
4160 
4161  case OBJECT_TYPE:
4162  defaclobjtype = DEFACLOBJ_TYPE;
4163  break;
4164 
4165  case OBJECT_SCHEMA:
4166  defaclobjtype = DEFACLOBJ_NAMESPACE;
4167  break;
4168 
4169  default:
4170  return NULL;
4171  }
4172 
4173  /* Look up the relevant pg_default_acl entries */
4174  glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
4175  schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
4176 
4177  /* Quick out if neither entry exists */
4178  if (glob_acl == NULL && schema_acl == NULL)
4179  return NULL;
4180 
4181  /* We need to know the hard-wired default value, too */
4182  def_acl = acldefault(objtype, ownerId);
4183 
4184  /* If there's no global entry, substitute the hard-wired default */
4185  if (glob_acl == NULL)
4186  glob_acl = def_acl;
4187 
4188  /* Merge in any per-schema privileges */
4189  result = aclmerge(glob_acl, schema_acl, ownerId);
4190 
4191  /*
4192  * For efficiency, we want to return NULL if the result equals default.
4193  * This requires sorting both arrays to get an accurate comparison.
4194  */
4195  aclitemsort(result);
4196  aclitemsort(def_acl);
4197  if (aclequal(result, def_acl))
4198  result = NULL;
4199 
4200  return result;
4201 }
4202 
4203 /*
4204  * Record dependencies on roles mentioned in a new object's ACL.
4205  */
4206 void
4207 recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId,
4208  Oid ownerId, Acl *acl)
4209 {
4210  int nmembers;
4211  Oid *members;
4212 
4213  /* Nothing to do if ACL is defaulted */
4214  if (acl == NULL)
4215  return;
4216 
4217  /* Extract roles mentioned in ACL */
4218  nmembers = aclmembers(acl, &members);
4219 
4220  /* Update the shared dependency ACL info */
4221  updateAclDependencies(classId, objectId, objsubId,
4222  ownerId,
4223  0, NULL,
4224  nmembers, members);
4225 }
4226 
4227 /*
4228  * Record initial privileges for the top-level object passed in.
4229  *
4230  * For the object passed in, this will record its ACL (if any) and the ACLs of
4231  * any sub-objects (eg: columns) into pg_init_privs.
4232  */
4233 void
4234 recordExtObjInitPriv(Oid objoid, Oid classoid)
4235 {
4236  /*
4237  * pg_class / pg_attribute
4238  *
4239  * If this is a relation then we need to see if there are any sub-objects
4240  * (eg: columns) for it and, if so, be sure to call
4241  * recordExtensionInitPrivWorker() for each one.
4242  */
4243  if (classoid == RelationRelationId)
4244  {
4245  Form_pg_class pg_class_tuple;
4246  Datum aclDatum;
4247  bool isNull;
4248  HeapTuple tuple;
4249 
4250  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
4251  if (!HeapTupleIsValid(tuple))
4252  elog(ERROR, "cache lookup failed for relation %u", objoid);
4253  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
4254 
4255  /*
4256  * Indexes don't have permissions, neither do the pg_class rows for
4257  * composite types. (These cases are unreachable given the
4258  * restrictions in ALTER EXTENSION ADD, but let's check anyway.)
4259  */
4260  if (pg_class_tuple->relkind == RELKIND_INDEX ||
4261  pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
4262  pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
4263  {
4264  ReleaseSysCache(tuple);
4265  return;
4266  }
4267 
4268  /*
4269  * If this isn't a sequence then it's possibly going to have
4270  * column-level ACLs associated with it.
4271  */
4272  if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
4273  {
4274  AttrNumber curr_att;
4275  AttrNumber nattrs = pg_class_tuple->relnatts;
4276 
4277  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4278  {
4279  HeapTuple attTuple;
4280  Datum attaclDatum;
4281 
4282  attTuple = SearchSysCache2(ATTNUM,
4283  ObjectIdGetDatum(objoid),
4284  Int16GetDatum(curr_att));
4285 
4286  if (!HeapTupleIsValid(attTuple))
4287  continue;
4288 
4289  /* ignore dropped columns */
4290  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4291  {
4292  ReleaseSysCache(attTuple);
4293  continue;
4294  }
4295 
4296  attaclDatum = SysCacheGetAttr(ATTNUM, attTuple,
4297  Anum_pg_attribute_attacl,
4298  &isNull);
4299 
4300  /* no need to do anything for a NULL ACL */
4301  if (isNull)
4302  {
4303  ReleaseSysCache(attTuple);
4304  continue;
4305  }
4306 
4307  recordExtensionInitPrivWorker(objoid, classoid, curr_att,
4308  DatumGetAclP(attaclDatum));
4309 
4310  ReleaseSysCache(attTuple);
4311  }
4312  }
4313 
4314  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
4315  &isNull);
4316 
4317  /* Add the record, if any, for the top-level object */
4318  if (!isNull)
4319  recordExtensionInitPrivWorker(objoid, classoid, 0,
4320  DatumGetAclP(aclDatum));
4321 
4322  ReleaseSysCache(tuple);
4323  }
4324  /* pg_largeobject_metadata */
4325  else if (classoid == LargeObjectMetadataRelationId)
4326  {
4327  Datum aclDatum;
4328  bool isNull;
4329  HeapTuple tuple;
4330  ScanKeyData entry[1];
4331  SysScanDesc scan;
4332  Relation relation;
4333 
4334  /*
4335  * Note: this is dead code, given that we don't allow large objects to
4336  * be made extension members. But it seems worth carrying in case
4337  * some future caller of this function has need for it.
4338  */
4339  relation = table_open(LargeObjectMetadataRelationId, RowExclusiveLock);
4340 
4341  /* There's no syscache for pg_largeobject_metadata */
4342  ScanKeyInit(&entry[0],
4343  Anum_pg_largeobject_metadata_oid,
4344  BTEqualStrategyNumber, F_OIDEQ,
4345  ObjectIdGetDatum(objoid));
4346 
4347  scan = systable_beginscan(relation,
4348  LargeObjectMetadataOidIndexId, true,
4349  NULL, 1, entry);
4350 
4351  tuple = systable_getnext(scan);
4352  if (!HeapTupleIsValid(tuple))
4353  elog(ERROR, "could not find tuple for large object %u", objoid);
4354 
4355  aclDatum = heap_getattr(tuple,
4356  Anum_pg_largeobject_metadata_lomacl,
4357  RelationGetDescr(relation), &isNull);
4358 
4359  /* Add the record, if any, for the top-level object */
4360  if (!isNull)
4361  recordExtensionInitPrivWorker(objoid, classoid, 0,
4362  DatumGetAclP(aclDatum));
4363 
4364  systable_endscan(scan);
4365  }
4366  /* This will error on unsupported classoid. */
4367  else if (get_object_attnum_acl(classoid) != InvalidAttrNumber)
4368  {
4369  Datum aclDatum;
4370  bool isNull;
4371  HeapTuple tuple;
4372 
4373  tuple = SearchSysCache1(get_object_catcache_oid(classoid),
4374  ObjectIdGetDatum(objoid));
4375  if (!HeapTupleIsValid(tuple))
4376  elog(ERROR, "cache lookup failed for %s %u",
4377  get_object_class_descr(classoid), objoid);
4378 
4379  aclDatum = SysCacheGetAttr(get_object_catcache_oid(classoid), tuple,
4380  get_object_attnum_acl(classoid),
4381  &isNull);
4382 
4383  /* Add the record, if any, for the top-level object */
4384  if (!isNull)
4385  recordExtensionInitPrivWorker(objoid, classoid, 0,
4386  DatumGetAclP(aclDatum));
4387 
4388  ReleaseSysCache(tuple);
4389  }
4390 }
4391 
4392 /*
4393  * For the object passed in, remove its ACL and the ACLs of any object subIds
4394  * from pg_init_privs (via recordExtensionInitPrivWorker()).
4395  */
4396 void
4397 removeExtObjInitPriv(Oid objoid, Oid classoid)
4398 {
4399  /*
4400  * If this is a relation then we need to see if there are any sub-objects
4401  * (eg: columns) for it and, if so, be sure to call
4402  * recordExtensionInitPrivWorker() for each one.
4403  */
4404  if (classoid == RelationRelationId)
4405  {
4406  Form_pg_class pg_class_tuple;
4407  HeapTuple tuple;
4408 
4409  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
4410  if (!HeapTupleIsValid(tuple))
4411  elog(ERROR, "cache lookup failed for relation %u", objoid);
4412  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
4413 
4414  /*
4415  * Indexes don't have permissions, neither do the pg_class rows for
4416  * composite types. (These cases are unreachable given the
4417  * restrictions in ALTER EXTENSION DROP, but let's check anyway.)
4418  */
4419  if (pg_class_tuple->relkind == RELKIND_INDEX ||
4420  pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
4421  pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
4422  {
4423  ReleaseSysCache(tuple);
4424  return;
4425  }
4426 
4427  /*
4428  * If this isn't a sequence then it's possibly going to have
4429  * column-level ACLs associated with it.
4430  */
4431  if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
4432  {
4433  AttrNumber curr_att;
4434  AttrNumber nattrs = pg_class_tuple->relnatts;
4435 
4436  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4437  {
4438  HeapTuple attTuple;
4439 
4440  attTuple = SearchSysCache2(ATTNUM,
4441  ObjectIdGetDatum(objoid),
4442  Int16GetDatum(curr_att));
4443 
4444  if (!HeapTupleIsValid(attTuple))
4445  continue;
4446 
4447  /* when removing, remove all entries, even dropped columns */
4448 
4449  recordExtensionInitPrivWorker(objoid, classoid, curr_att, NULL);
4450 
4451  ReleaseSysCache(attTuple);
4452  }
4453  }
4454 
4455  ReleaseSysCache(tuple);
4456  }
4457 
4458  /* Remove the record, if any, for the top-level object */
4459  recordExtensionInitPrivWorker(objoid, classoid, 0, NULL);
4460 }
4461 
4462 /*
4463  * Record initial ACL for an extension object
4464  *
4465  * Can be called at any time, we check if 'creating_extension' is set and, if
4466  * not, exit immediately.
4467  *
4468  * Pass in the object OID, the OID of the class (the OID of the table which
4469  * the object is defined in) and the 'sub' id of the object (objsubid), if
4470  * any. If there is no 'sub' id (they are currently only used for columns of
4471  * tables) then pass in '0'. Finally, pass in the complete ACL to store.
4472  *
4473  * If an ACL already exists for this object/sub-object then we will replace
4474  * it with what is passed in.
4475  *
4476  * Passing in NULL for 'new_acl' will result in the entry for the object being
4477  * removed, if one is found.
4478  */
4479 static void
4480 recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
4481 {
4482  /*
4483  * Generally, we only record the initial privileges when an extension is
4484  * being created, but because we don't actually use CREATE EXTENSION
4485  * during binary upgrades with pg_upgrade, there is a variable to let us
4486  * know that the GRANT and REVOKE statements being issued, while this
4487  * variable is true, are for the initial privileges of the extension
4488  * object and therefore we need to record them.
4489  */
4491  return;
4492 
4493  recordExtensionInitPrivWorker(objoid, classoid, objsubid, new_acl);
4494 }
4495 
4496 /*
4497  * Record initial ACL for an extension object, worker.
4498  *
4499  * This will perform a wholesale replacement of the entire ACL for the object
4500  * passed in, therefore be sure to pass in the complete new ACL to use.
4501  *
4502  * Generally speaking, do *not* use this function directly but instead use
4503  * recordExtensionInitPriv(), which checks if 'creating_extension' is set.
4504  * This function does *not* check if 'creating_extension' is set as it is also
4505  * used when an object is added to or removed from an extension via ALTER
4506  * EXTENSION ... ADD/DROP.
4507  */
4508 static void
4509 recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
4510 {
4511  Relation relation;
4512  ScanKeyData key[3];
4513  SysScanDesc scan;
4514  HeapTuple tuple;
4515  HeapTuple oldtuple;
4516 
4517  relation = table_open(InitPrivsRelationId, RowExclusiveLock);
4518 
4519  ScanKeyInit(&key[0],
4520  Anum_pg_init_privs_objoid,
4521  BTEqualStrategyNumber, F_OIDEQ,
4522  ObjectIdGetDatum(objoid));
4523  ScanKeyInit(&key[1],
4524  Anum_pg_init_privs_classoid,
4525  BTEqualStrategyNumber, F_OIDEQ,
4526  ObjectIdGetDatum(classoid));
4527  ScanKeyInit(&key[2],
4528  Anum_pg_init_privs_objsubid,
4529  BTEqualStrategyNumber, F_INT4EQ,
4530  Int32GetDatum(objsubid));
4531 
4532  scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
4533  NULL, 3, key);
4534 
4535  /* There should exist only one entry or none. */
4536  oldtuple = systable_getnext(scan);
4537 
4538  /* If we find an entry, update it with the latest ACL. */
4539  if (HeapTupleIsValid(oldtuple))
4540  {
4541  Datum values[Natts_pg_init_privs] = {0};
4542  bool nulls[Natts_pg_init_privs] = {0};
4543  bool replace[Natts_pg_init_privs] = {0};
4544 
4545  /* If we have a new ACL to set, then update the row with it. */
4546  if (new_acl)
4547  {
4548  values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
4549  replace[Anum_pg_init_privs_initprivs - 1] = true;
4550 
4551  oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation),
4552  values, nulls, replace);
4553 
4554  CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple);
4555  }
4556  else
4557  {
4558  /* new_acl is NULL, so delete the entry we found. */
4559  CatalogTupleDelete(relation, &oldtuple->t_self);
4560  }
4561  }
4562  else
4563  {
4564  Datum values[Natts_pg_init_privs] = {0};
4565  bool nulls[Natts_pg_init_privs] = {0};
4566 
4567  /*
4568  * Only add a new entry if the new ACL is non-NULL.
4569  *
4570  * If we are passed in a NULL ACL and no entry exists, we can just
4571  * fall through and do nothing.
4572  */
4573  if (new_acl)
4574  {
4575  /* No entry found, so add it. */
4576  values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
4577  values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
4578  values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
4579 
4580  /* This function only handles initial privileges of extensions */
4581  values[Anum_pg_init_privs_privtype - 1] =
4583 
4584  values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
4585 
4586  tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
4587 
4588  CatalogTupleInsert(relation, tuple);
4589  }
4590  }
4591 
4592  systable_endscan(scan);
4593 
4594  /* prevent error when processing objects multiple times */
4596 
4597  table_close(relation, RowExclusiveLock);
4598 }
Acl * aclupdate(const Acl *old_acl, const AclItem *mod_aip, int modechg, Oid ownerId, DropBehavior behavior)
Definition: acl.c:969
bool aclequal(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:536
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5179
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4969
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1511
Acl * aclconcat(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:454
Acl * aclcopy(const Acl *orig_acl)
Definition: acl.c:434
void aclitemsort(Acl *acl)
Definition: acl.c:522
AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
Definition: acl.c:1359
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:780
Acl * make_empty_acl(void)
Definition: acl.c:425
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5289
Acl * aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
Definition: acl.c:478
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:164
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:170
AclResult
Definition: acl.h:182
@ ACLCHECK_NO_PRIV
Definition: acl.h:184
@ ACLCHECK_OK
Definition: acl.h:183
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
#define ACL_ALL_RIGHTS_PARAMETER_ACL
Definition: acl.h:168
#define ACL_ALL_RIGHTS_SCHEMA
Definition: acl.h:169
#define DatumGetAclP(X)
Definition: acl.h:120
#define ACL_MODECHG_DEL
Definition: acl.h:130
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:161
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:162
#define ACL_MODECHG_ADD
Definition: acl.h:129
#define ACL_ALL_RIGHTS_COLUMN
Definition: acl.h:159
#define ACL_OPTION_TO_PRIVS(privs)
Definition: acl.h:71
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:165
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:166
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:171
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:163
#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:160
#define ACL_ID_PUBLIC
Definition: acl.h:46
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:167
AclMaskHow
Definition: acl.h:175
@ ACLMASK_ANY
Definition: acl.h:177
@ ACLMASK_ALL
Definition: acl.h:176
#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:3162
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:3962
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:4480
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:4072
AclResult pg_class_aclcheck_ext(Oid table_oid, Oid roleid, AclMode mode, bool *is_missing)
Definition: aclchk.c:3935
void aclcheck_error_col(AclResult aclerr, ObjectType objtype, const char *objectname, const char *colname)
Definition: aclchk.c:2962
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
Definition: aclchk.c:4207
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:3533
static AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3148
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:3410
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition: aclchk.c:3838
static AclMode pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3474
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:3950
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:4234
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:3280
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:3698
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2673
static AclMode object_aclmask(Oid classid, Oid objectid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3069
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:3794
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:3775
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition: aclchk.c:4131
static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:4509
static AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3606
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:3976
AclResult pg_attribute_aclcheck_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode, bool *is_missing)
Definition: aclchk.c:3808
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:3267
static void ExecGrant_Parameter(InternalGrant *istmt)
Definition: aclchk.c:2440
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:2626
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:2992
bool has_createrole_privilege(Oid roleid)
Definition: aclchk.c:4053
static Acl * get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
Definition: aclchk.c:4096
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:3923
static AclMode pg_aclmask(ObjectType objtype, Oid object_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3004
void removeExtObjInitPriv(Oid objoid, Oid classoid)
Definition: aclchk.c:4397
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:730
signed int int32
Definition: c.h:478
#define gettext_noop(x)
Definition: c.h:1186
char * Pointer
Definition: c.h:467
#define OidIsValid(objectId)
Definition: c.h:759
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:2976
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
const char * name
Definition: encode.c:571
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:690
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition: foreign.c:667
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
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:1093
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
#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:2717
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1910
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:459
void pfree(void *pointer)
Definition: mcxt.c:1436
void * palloc0(Size size)
Definition: mcxt.c:1241
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:405
Oid GetUserId(void)
Definition: miscinit.c:510
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2936
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3200
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3086
#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:396
#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_MAINTAIN
Definition: parsenodes.h:97
#define ACL_USAGE
Definition: parsenodes.h:91
#define ACL_INSERT
Definition: parsenodes.h:83
#define ACL_NO_RIGHTS
Definition: parsenodes.h:99
#define ACL_UPDATE
Definition: parsenodes.h:85
DropBehavior
Definition: parsenodes.h:2154
@ DROP_CASCADE
Definition: parsenodes.h:2156
@ DROP_RESTRICT
Definition: parsenodes.h:2155
ObjectType
Definition: parsenodes.h:2081
@ OBJECT_EVENT_TRIGGER
Definition: parsenodes.h:2096
@ OBJECT_FDW
Definition: parsenodes.h:2098
@ OBJECT_TSPARSER
Definition: parsenodes.h:2129
@ OBJECT_COLLATION
Definition: parsenodes.h:2089
@ OBJECT_USER_MAPPING
Definition: parsenodes.h:2132
@ OBJECT_ACCESS_METHOD
Definition: parsenodes.h:2082
@ OBJECT_OPCLASS
Definition: parsenodes.h:2106
@ OBJECT_DEFACL
Definition: parsenodes.h:2093
@ OBJECT_AGGREGATE
Definition: parsenodes.h:2083
@ OBJECT_MATVIEW
Definition: parsenodes.h:2105
@ OBJECT_SCHEMA
Definition: parsenodes.h:2118
@ OBJECT_POLICY
Definition: parsenodes.h:2110
@ OBJECT_OPERATOR
Definition: parsenodes.h:2107
@ OBJECT_FOREIGN_TABLE
Definition: parsenodes.h:2100
@ OBJECT_TSCONFIGURATION
Definition: parsenodes.h:2127
@ OBJECT_OPFAMILY
Definition: parsenodes.h:2108
@ OBJECT_DOMAIN
Definition: parsenodes.h:2094
@ OBJECT_COLUMN
Definition: parsenodes.h:2088
@ OBJECT_TABLESPACE
Definition: parsenodes.h:2124
@ OBJECT_ROLE
Definition: parsenodes.h:2115
@ OBJECT_ROUTINE
Definition: parsenodes.h:2116
@ OBJECT_LARGEOBJECT
Definition: parsenodes.h:2104
@ OBJECT_PUBLICATION_NAMESPACE
Definition: parsenodes.h:2113
@ OBJECT_PROCEDURE
Definition: parsenodes.h:2111
@ OBJECT_EXTENSION
Definition: parsenodes.h:2097
@ OBJECT_INDEX
Definition: parsenodes.h:2102
@ OBJECT_DEFAULT
Definition: parsenodes.h:2092
@ OBJECT_DATABASE
Definition: parsenodes.h:2091
@ OBJECT_SEQUENCE
Definition: parsenodes.h:2119
@ OBJECT_TSTEMPLATE
Definition: parsenodes.h:2130
@ OBJECT_LANGUAGE
Definition: parsenodes.h:2103
@ OBJECT_AMOP
Definition: parsenodes.h:2084
@ OBJECT_PUBLICATION_REL
Definition: parsenodes.h:2114
@ OBJECT_FOREIGN_SERVER
Definition: parsenodes.h:2099
@ OBJECT_TSDICTIONARY
Definition: parsenodes.h:2128
@ OBJECT_ATTRIBUTE
Definition: parsenodes.h:2086
@ OBJECT_PUBLICATION
Definition: parsenodes.h:2112
@ OBJECT_RULE
Definition: parsenodes.h:2117
@ OBJECT_CONVERSION
Definition: parsenodes.h:2090
@ OBJECT_AMPROC
Definition: parsenodes.h:2085
@ OBJECT_TABLE
Definition: parsenodes.h:2123
@ OBJECT_VIEW
Definition: parsenodes.h:2133
@ OBJECT_PARAMETER_ACL
Definition: parsenodes.h:2109
@ OBJECT_TYPE
Definition: parsenodes.h:2131
@ OBJECT_FUNCTION
Definition: parsenodes.h:2101
@ OBJECT_TABCONSTRAINT
Definition: parsenodes.h:2122
@ OBJECT_DOMCONSTRAINT
Definition: parsenodes.h:2095
@ OBJECT_SUBSCRIPTION
Definition: parsenodes.h:2120
@ OBJECT_STATISTIC_EXT
Definition: parsenodes.h:2121
@ OBJECT_CAST
Definition: parsenodes.h:2087
@ OBJECT_TRIGGER
Definition: parsenodes.h:2126
@ OBJECT_TRANSFORM
Definition: parsenodes.h:2125
@ ACL_TARGET_OBJECT
Definition: parsenodes.h:2309
@ ACL_TARGET_ALL_IN_SCHEMA
Definition: parsenodes.h:2310
#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:65
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:529
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:2366
List * cols
Definition: parsenodes.h:2367
Definition: acl.h:55
Oid ai_grantee
Definition: acl.h:56
Oid ai_grantor
Definition: acl.h:57
char * defname
Definition: parsenodes.h:810
Node * arg
Definition: parsenodes.h:811
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:402
Definition: c.h:671
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:866
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:818
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:840
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1079
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:829
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:1110
@ 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:1011
#define strVal(v)
Definition: value.h:82
text * cstring_to_text(const char *s)
Definition: varlena.c:182
void CommandCounterIncrement(void)
Definition: xact.c:1078