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