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