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