1
/*-------------------------------------------------------------------------
4
* Routines to check access control permissions.
6
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7
* Portions Copyright (c) 1994, Regents of the University of California
11
* src/backend/catalog/aclchk.c
16
*-------------------------------------------------------------------------
20
#include "access/genam.h"
21
#include "access/heapam.h"
22
#include "access/sysattr.h"
23
#include "access/xact.h"
24
#include "catalog/catalog.h"
25
#include "catalog/dependency.h"
26
#include "catalog/indexing.h"
27
#include "catalog/pg_authid.h"
28
#include "catalog/pg_collation.h"
29
#include "catalog/pg_conversion.h"
30
#include "catalog/pg_database.h"
31
#include "catalog/pg_default_acl.h"
32
#include "catalog/pg_extension.h"
33
#include "catalog/pg_foreign_data_wrapper.h"
34
#include "catalog/pg_foreign_server.h"
35
#include "catalog/pg_language.h"
36
#include "catalog/pg_largeobject.h"
37
#include "catalog/pg_largeobject_metadata.h"
38
#include "catalog/pg_namespace.h"
39
#include "catalog/pg_opclass.h"
40
#include "catalog/pg_operator.h"
41
#include "catalog/pg_opfamily.h"
42
#include "catalog/pg_proc.h"
43
#include "catalog/pg_tablespace.h"
44
#include "catalog/pg_type.h"
45
#include "catalog/pg_ts_config.h"
46
#include "catalog/pg_ts_dict.h"
47
#include "commands/dbcommands.h"
48
#include "commands/proclang.h"
49
#include "commands/tablespace.h"
50
#include "foreign/foreign.h"
51
#include "miscadmin.h"
52
#include "parser/parse_func.h"
53
#include "utils/acl.h"
54
#include "utils/builtins.h"
55
#include "utils/fmgroids.h"
56
#include "utils/lsyscache.h"
57
#include "utils/rel.h"
58
#include "utils/syscache.h"
59
#include "utils/tqual.h"
63
* The information about one Grant/Revoke statement, in internal format: object
64
* and grantees names have been turned into Oids, the privilege list is an
65
* AclMode bitmask. If 'privileges' is ACL_NO_RIGHTS (the 0 value) and
66
* all_privs is true, 'privileges' will be internally set to the right kind of
67
* ACL_ALL_RIGHTS_*, depending on the object type (NB - this will modify the
68
* InternalGrant struct!)
70
* Note: 'all_privs' and 'privileges' represent object-level privileges only.
71
* There might also be column-level privilege specifications, which are
72
* represented in col_privs (this is a list of untransformed AccessPriv nodes).
73
* Column privileges are only valid for objtype ACL_OBJECT_RELATION.
78
GrantObjectType objtype;
85
DropBehavior behavior;
89
* Internal format used by ALTER DEFAULT PRIVILEGES.
93
Oid roleid; /* owning role */
94
Oid nspid; /* namespace, or InvalidOid if none */
95
/* remaining fields are same as in InternalGrant: */
97
GrantObjectType objtype;
102
DropBehavior behavior;
103
} InternalDefaultACL;
106
static void ExecGrantStmt_oids(InternalGrant *istmt);
107
static void ExecGrant_Relation(InternalGrant *grantStmt);
108
static void ExecGrant_Database(InternalGrant *grantStmt);
109
static void ExecGrant_Fdw(InternalGrant *grantStmt);
110
static void ExecGrant_ForeignServer(InternalGrant *grantStmt);
111
static void ExecGrant_Function(InternalGrant *grantStmt);
112
static void ExecGrant_Language(InternalGrant *grantStmt);
113
static void ExecGrant_Largeobject(InternalGrant *grantStmt);
114
static void ExecGrant_Namespace(InternalGrant *grantStmt);
115
static void ExecGrant_Tablespace(InternalGrant *grantStmt);
117
static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames);
118
static void SetDefaultACL(InternalDefaultACL *iacls);
120
static List *objectNamesToOids(GrantObjectType objtype, List *objnames);
121
static List *objectsInSchemaToOids(GrantObjectType objtype, List *nspnames);
122
static List *getRelationsInNamespace(Oid namespaceId, char relkind);
123
static void expand_col_privileges(List *colnames, Oid table_oid,
124
AclMode this_privileges,
125
AclMode *col_privileges,
126
int num_col_privileges);
127
static void expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
128
AclMode this_privileges,
129
AclMode *col_privileges,
130
int num_col_privileges);
131
static AclMode string_to_privilege(const char *privname);
132
static const char *privilege_to_string(AclMode privilege);
133
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions,
134
bool all_privs, AclMode privileges,
135
Oid objectId, Oid grantorId,
136
AclObjectKind objkind, const char *objname,
137
AttrNumber att_number, const char *colname);
138
static AclMode pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum,
139
Oid roleid, AclMode mask, AclMaskHow how);
149
elog(DEBUG2, "acl size = %d, # acls = %d",
150
ACL_SIZE(acl), ACL_NUM(acl));
152
for (i = 0; i < ACL_NUM(acl); ++i)
153
elog(DEBUG2, " acl[%d]: %s", i,
154
DatumGetCString(DirectFunctionCall1(aclitemout,
155
PointerGetDatum(aip + i))));
157
#endif /* ACLDEBUG */
161
* If is_grant is true, adds the given privileges for the list of
162
* grantees to the existing old_acl. If is_grant is false, the
163
* privileges for the given grantees are removed from old_acl.
165
* NB: the original old_acl is pfree'd.
168
merge_acl_with_grant(Acl *old_acl, bool is_grant,
169
bool grant_option, DropBehavior behavior,
170
List *grantees, AclMode privileges,
171
Oid grantorId, Oid ownerId)
177
modechg = is_grant ? ACL_MODECHG_ADD : ACL_MODECHG_DEL;
189
aclitem. ai_grantee = lfirst_oid(j);
192
* Grant options can only be granted to individual roles, not PUBLIC.
193
* The reason is that if a user would re-grant a privilege that he
194
* held through PUBLIC, and later the user is removed, the situation
195
* is impossible to clean up.
197
if (is_grant && grant_option && aclitem.ai_grantee == ACL_ID_PUBLIC)
199
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
200
errmsg("grant options can only be granted to roles")));
202
aclitem. ai_grantor = grantorId;
205
* The asymmetry in the conditions here comes from the spec. In
206
* GRANT, the grant_option flag signals WITH GRANT OPTION, which means
207
* to grant both the basic privilege and its grant option. But in
208
* REVOKE, plain revoke revokes both the basic privilege and its grant
209
* option, while REVOKE GRANT OPTION revokes only the option.
211
ACLITEM_SET_PRIVS_GOPTIONS(aclitem,
212
(is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
213
(!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS);
215
newer_acl = aclupdate(new_acl, &aclitem, modechg, ownerId, behavior);
217
/* avoid memory leak when there are many grantees */
230
* Restrict the privileges to what we can actually grant, and emit
231
* the standards-mandated warning and error messages.
234
restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
235
AclMode privileges, Oid objectId, Oid grantorId,
236
AclObjectKind objkind, const char *objname,
237
AttrNumber att_number, const char *colname)
239
AclMode this_privileges;
244
case ACL_KIND_COLUMN:
245
whole_mask = ACL_ALL_RIGHTS_COLUMN;
248
whole_mask = ACL_ALL_RIGHTS_RELATION;
250
case ACL_KIND_SEQUENCE:
251
whole_mask = ACL_ALL_RIGHTS_SEQUENCE;
253
case ACL_KIND_DATABASE:
254
whole_mask = ACL_ALL_RIGHTS_DATABASE;
257
whole_mask = ACL_ALL_RIGHTS_FUNCTION;
259
case ACL_KIND_LANGUAGE:
260
whole_mask = ACL_ALL_RIGHTS_LANGUAGE;
262
case ACL_KIND_LARGEOBJECT:
263
whole_mask = ACL_ALL_RIGHTS_LARGEOBJECT;
265
case ACL_KIND_NAMESPACE:
266
whole_mask = ACL_ALL_RIGHTS_NAMESPACE;
268
case ACL_KIND_TABLESPACE:
269
whole_mask = ACL_ALL_RIGHTS_TABLESPACE;
272
whole_mask = ACL_ALL_RIGHTS_FDW;
274
case ACL_KIND_FOREIGN_SERVER:
275
whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
278
elog(ERROR, "unrecognized object kind: %d", objkind);
279
/* not reached, but keep compiler quiet */
280
return ACL_NO_RIGHTS;
284
* If we found no grant options, consider whether to issue a hard error.
285
* Per spec, having any privilege at all on the object will get you by
288
if (avail_goptions == ACL_NO_RIGHTS)
290
if (pg_aclmask(objkind, objectId, att_number, grantorId,
291
whole_mask | ACL_GRANT_OPTION_FOR(whole_mask),
292
ACLMASK_ANY) == ACL_NO_RIGHTS)
294
if (objkind == ACL_KIND_COLUMN && colname)
295
aclcheck_error_col(ACLCHECK_NO_PRIV, objkind, objname, colname);
297
aclcheck_error(ACLCHECK_NO_PRIV, objkind, objname);
302
* Restrict the operation to what we can actually grant or revoke, and
303
* issue a warning if appropriate. (For REVOKE this isn't quite what the
304
* spec says to do: the spec seems to want a warning only if no privilege
305
* bits actually change in the ACL. In practice that behavior seems much
306
* too noisy, as well as inconsistent with the GRANT case.)
308
this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
311
if (this_privileges == 0)
313
if (objkind == ACL_KIND_COLUMN && colname)
315
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
316
errmsg("no privileges were granted for column \"%s\" of relation \"%s\"",
320
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
321
errmsg("no privileges were granted for \"%s\"",
324
else if (!all_privs && this_privileges != privileges)
326
if (objkind == ACL_KIND_COLUMN && colname)
328
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
329
errmsg("not all privileges were granted for column \"%s\" of relation \"%s\"",
333
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
334
errmsg("not all privileges were granted for \"%s\"",
340
if (this_privileges == 0)
342
if (objkind == ACL_KIND_COLUMN && colname)
344
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
345
errmsg("no privileges could be revoked for column \"%s\" of relation \"%s\"",
349
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
350
errmsg("no privileges could be revoked for \"%s\"",
353
else if (!all_privs && this_privileges != privileges)
355
if (objkind == ACL_KIND_COLUMN && colname)
357
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
358
errmsg("not all privileges could be revoked for column \"%s\" of relation \"%s\"",
362
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
363
errmsg("not all privileges could be revoked for \"%s\"",
368
return this_privileges;
372
* Called to execute the utility commands GRANT and REVOKE
375
ExecuteGrantStmt(GrantStmt *stmt)
379
const char *errormsg;
380
AclMode all_privileges;
383
* Turn the regular GrantStmt into the InternalGrant form.
385
istmt.is_grant = stmt->is_grant;
386
istmt.objtype = stmt->objtype;
388
/* Collect the OIDs of the target objects */
389
switch (stmt->targtype)
391
case ACL_TARGET_OBJECT:
392
istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects);
394
case ACL_TARGET_ALL_IN_SCHEMA:
395
istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
397
/* ACL_TARGET_DEFAULTS should not be seen here */
399
elog(ERROR, "unrecognized GrantStmt.targtype: %d",
400
(int) stmt->targtype);
403
/* all_privs to be filled below */
404
/* privileges to be filled below */
405
istmt.col_privs = NIL; /* may get filled below */
406
istmt.grantees = NIL; /* filled below */
407
istmt.grant_option = stmt->grant_option;
408
istmt.behavior = stmt->behavior;
411
* Convert the PrivGrantee list into an Oid list. Note that at this point
412
* we insert an ACL_ID_PUBLIC into the list if an empty role name is
413
* detected (which is what the grammar uses if PUBLIC is found), so
414
* downstream there shouldn't be any additional work needed to support
417
foreach(cell, stmt->grantees)
419
PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);
421
if (grantee->rolname == NULL)
422
istmt.grantees = lappend_oid(istmt.grantees, ACL_ID_PUBLIC);
425
lappend_oid(istmt.grantees,
426
get_role_oid(grantee->rolname, false));
430
* Convert stmt->privileges, a list of AccessPriv nodes, into an AclMode
431
* bitmask. Note: objtype can't be ACL_OBJECT_COLUMN.
433
switch (stmt->objtype)
436
* Because this might be a sequence, we test both relation and
437
* sequence bits, and later do a more limited test when we know
440
case ACL_OBJECT_RELATION:
441
all_privileges = ACL_ALL_RIGHTS_RELATION | ACL_ALL_RIGHTS_SEQUENCE;
442
errormsg = gettext_noop("invalid privilege type %s for relation");
444
case ACL_OBJECT_SEQUENCE:
445
all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
446
errormsg = gettext_noop("invalid privilege type %s for sequence");
448
case ACL_OBJECT_DATABASE:
449
all_privileges = ACL_ALL_RIGHTS_DATABASE;
450
errormsg = gettext_noop("invalid privilege type %s for database");
452
case ACL_OBJECT_FUNCTION:
453
all_privileges = ACL_ALL_RIGHTS_FUNCTION;
454
errormsg = gettext_noop("invalid privilege type %s for function");
456
case ACL_OBJECT_LANGUAGE:
457
all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
458
errormsg = gettext_noop("invalid privilege type %s for language");
460
case ACL_OBJECT_LARGEOBJECT:
461
all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
462
errormsg = gettext_noop("invalid privilege type %s for large object");
464
case ACL_OBJECT_NAMESPACE:
465
all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
466
errormsg = gettext_noop("invalid privilege type %s for schema");
468
case ACL_OBJECT_TABLESPACE:
469
all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
470
errormsg = gettext_noop("invalid privilege type %s for tablespace");
473
all_privileges = ACL_ALL_RIGHTS_FDW;
474
errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
476
case ACL_OBJECT_FOREIGN_SERVER:
477
all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
478
errormsg = gettext_noop("invalid privilege type %s for foreign server");
481
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
482
(int) stmt->objtype);
483
/* keep compiler quiet */
484
all_privileges = ACL_NO_RIGHTS;
488
if (stmt->privileges == NIL)
490
istmt.all_privs = true;
493
* will be turned into ACL_ALL_RIGHTS_* by the internal routines
494
* depending on the object type
496
istmt.privileges = ACL_NO_RIGHTS;
500
istmt.all_privs = false;
501
istmt.privileges = ACL_NO_RIGHTS;
503
foreach(cell, stmt->privileges)
505
AccessPriv *privnode = (AccessPriv *) lfirst(cell);
509
* If it's a column-level specification, we just set it aside in
510
* col_privs for the moment; but insist it's for a relation.
514
if (stmt->objtype != ACL_OBJECT_RELATION)
516
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
517
errmsg("column privileges are only valid for relations")));
518
istmt.col_privs = lappend(istmt.col_privs, privnode);
522
if (privnode->priv_name == NULL) /* parser mistake? */
523
elog(ERROR, "AccessPriv node must specify privilege or columns");
524
priv = string_to_privilege(privnode->priv_name);
526
if (priv & ~((AclMode) all_privileges))
528
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
529
errmsg(errormsg, privilege_to_string(priv))));
531
istmt.privileges |= priv;
535
ExecGrantStmt_oids(&istmt);
541
* Internal entry point for granting and revoking privileges.
544
ExecGrantStmt_oids(InternalGrant *istmt)
546
switch (istmt->objtype)
548
case ACL_OBJECT_RELATION:
549
case ACL_OBJECT_SEQUENCE:
550
ExecGrant_Relation(istmt);
552
case ACL_OBJECT_DATABASE:
553
ExecGrant_Database(istmt);
556
ExecGrant_Fdw(istmt);
558
case ACL_OBJECT_FOREIGN_SERVER:
559
ExecGrant_ForeignServer(istmt);
561
case ACL_OBJECT_FUNCTION:
562
ExecGrant_Function(istmt);
564
case ACL_OBJECT_LANGUAGE:
565
ExecGrant_Language(istmt);
567
case ACL_OBJECT_LARGEOBJECT:
568
ExecGrant_Largeobject(istmt);
570
case ACL_OBJECT_NAMESPACE:
571
ExecGrant_Namespace(istmt);
573
case ACL_OBJECT_TABLESPACE:
574
ExecGrant_Tablespace(istmt);
577
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
578
(int) istmt->objtype);
585
* Turn a list of object names of a given type into an Oid list.
588
objectNamesToOids(GrantObjectType objtype, List *objnames)
593
Assert(objnames != NIL);
597
case ACL_OBJECT_RELATION:
598
case ACL_OBJECT_SEQUENCE:
599
foreach(cell, objnames)
601
RangeVar *relvar = (RangeVar *) lfirst(cell);
604
relOid = RangeVarGetRelid(relvar, false);
605
objects = lappend_oid(objects, relOid);
608
case ACL_OBJECT_DATABASE:
609
foreach(cell, objnames)
611
char *dbname = strVal(lfirst(cell));
614
dbid = get_database_oid(dbname, false);
615
objects = lappend_oid(objects, dbid);
618
case ACL_OBJECT_FUNCTION:
619
foreach(cell, objnames)
621
FuncWithArgs *func = (FuncWithArgs *) lfirst(cell);
624
funcid = LookupFuncNameTypeNames(func->funcname,
625
func->funcargs, false);
626
objects = lappend_oid(objects, funcid);
629
case ACL_OBJECT_LANGUAGE:
630
foreach(cell, objnames)
632
char *langname = strVal(lfirst(cell));
635
oid = get_language_oid(langname, false);
636
objects = lappend_oid(objects, oid);
639
case ACL_OBJECT_LARGEOBJECT:
640
foreach(cell, objnames)
642
Oid lobjOid = oidparse(lfirst(cell));
644
if (!LargeObjectExists(lobjOid))
646
(errcode(ERRCODE_UNDEFINED_OBJECT),
647
errmsg("large object %u does not exist",
650
objects = lappend_oid(objects, lobjOid);
653
case ACL_OBJECT_NAMESPACE:
654
foreach(cell, objnames)
656
char *nspname = strVal(lfirst(cell));
659
oid = get_namespace_oid(nspname, false);
660
objects = lappend_oid(objects, oid);
663
case ACL_OBJECT_TABLESPACE:
664
foreach(cell, objnames)
666
char *spcname = strVal(lfirst(cell));
669
spcoid = get_tablespace_oid(spcname, false);
670
objects = lappend_oid(objects, spcoid);
674
foreach(cell, objnames)
676
char *fdwname = strVal(lfirst(cell));
677
Oid fdwid = get_foreign_data_wrapper_oid(fdwname, false);
679
objects = lappend_oid(objects, fdwid);
682
case ACL_OBJECT_FOREIGN_SERVER:
683
foreach(cell, objnames)
685
char *srvname = strVal(lfirst(cell));
686
Oid srvid = get_foreign_server_oid(srvname, false);
688
objects = lappend_oid(objects, srvid);
692
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
700
* objectsInSchemaToOids
702
* Find all objects of a given type in specified schemas, and make a list
703
* of their Oids. We check USAGE privilege on the schemas, but there is
704
* no privilege checking on the individual objects here.
707
objectsInSchemaToOids(GrantObjectType objtype, List *nspnames)
712
foreach(cell, nspnames)
714
char *nspname = strVal(lfirst(cell));
718
namespaceId = LookupExplicitNamespace(nspname);
722
case ACL_OBJECT_RELATION:
723
/* Process regular tables, views and foreign tables */
724
objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
725
objects = list_concat(objects, objs);
726
objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
727
objects = list_concat(objects, objs);
728
objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
729
objects = list_concat(objects, objs);
731
case ACL_OBJECT_SEQUENCE:
732
objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
733
objects = list_concat(objects, objs);
735
case ACL_OBJECT_FUNCTION:
743
Anum_pg_proc_pronamespace,
744
BTEqualStrategyNumber, F_OIDEQ,
745
ObjectIdGetDatum(namespaceId));
747
rel = heap_open(ProcedureRelationId, AccessShareLock);
748
scan = heap_beginscan(rel, SnapshotNow, 1, key);
750
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
752
objects = lappend_oid(objects, HeapTupleGetOid(tuple));
756
heap_close(rel, AccessShareLock);
760
/* should not happen */
761
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
770
* getRelationsInNamespace
772
* Return Oid list of relations in given namespace filtered by relation kind
775
getRelationsInNamespace(Oid namespaceId, char relkind)
777
List *relations = NIL;
784
Anum_pg_class_relnamespace,
785
BTEqualStrategyNumber, F_OIDEQ,
786
ObjectIdGetDatum(namespaceId));
788
Anum_pg_class_relkind,
789
BTEqualStrategyNumber, F_CHAREQ,
790
CharGetDatum(relkind));
792
rel = heap_open(RelationRelationId, AccessShareLock);
793
scan = heap_beginscan(rel, SnapshotNow, 2, key);
795
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
797
relations = lappend_oid(relations, HeapTupleGetOid(tuple));
801
heap_close(rel, AccessShareLock);
808
* ALTER DEFAULT PRIVILEGES statement
811
ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt)
813
GrantStmt *action = stmt->action;
814
InternalDefaultACL iacls;
816
List *rolenames = NIL;
817
List *nspnames = NIL;
818
DefElem *drolenames = NULL;
819
DefElem *dnspnames = NULL;
820
AclMode all_privileges;
821
const char *errormsg;
823
/* Deconstruct the "options" part of the statement */
824
foreach(cell, stmt->options)
826
DefElem *defel = (DefElem *) lfirst(cell);
828
if (strcmp(defel->defname, "schemas") == 0)
832
(errcode(ERRCODE_SYNTAX_ERROR),
833
errmsg("conflicting or redundant options")));
836
else if (strcmp(defel->defname, "roles") == 0)
840
(errcode(ERRCODE_SYNTAX_ERROR),
841
errmsg("conflicting or redundant options")));
845
elog(ERROR, "option \"%s\" not recognized", defel->defname);
849
nspnames = (List *) dnspnames->arg;
851
rolenames = (List *) drolenames->arg;
853
/* Prepare the InternalDefaultACL representation of the statement */
854
/* roleid to be filled below */
855
/* nspid to be filled in SetDefaultACLsInSchemas */
856
iacls.is_grant = action->is_grant;
857
iacls.objtype = action->objtype;
858
/* all_privs to be filled below */
859
/* privileges to be filled below */
860
iacls.grantees = NIL; /* filled below */
861
iacls.grant_option = action->grant_option;
862
iacls.behavior = action->behavior;
865
* Convert the PrivGrantee list into an Oid list. Note that at this point
866
* we insert an ACL_ID_PUBLIC into the list if an empty role name is
867
* detected (which is what the grammar uses if PUBLIC is found), so
868
* downstream there shouldn't be any additional work needed to support
871
foreach(cell, action->grantees)
873
PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);
875
if (grantee->rolname == NULL)
876
iacls.grantees = lappend_oid(iacls.grantees, ACL_ID_PUBLIC);
879
lappend_oid(iacls.grantees,
880
get_role_oid(grantee->rolname, false));
884
* Convert action->privileges, a list of privilege strings, into an
887
switch (action->objtype)
889
case ACL_OBJECT_RELATION:
890
all_privileges = ACL_ALL_RIGHTS_RELATION;
891
errormsg = gettext_noop("invalid privilege type %s for relation");
893
case ACL_OBJECT_SEQUENCE:
894
all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
895
errormsg = gettext_noop("invalid privilege type %s for sequence");
897
case ACL_OBJECT_FUNCTION:
898
all_privileges = ACL_ALL_RIGHTS_FUNCTION;
899
errormsg = gettext_noop("invalid privilege type %s for function");
902
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
903
(int) action->objtype);
904
/* keep compiler quiet */
905
all_privileges = ACL_NO_RIGHTS;
909
if (action->privileges == NIL)
911
iacls.all_privs = true;
914
* will be turned into ACL_ALL_RIGHTS_* by the internal routines
915
* depending on the object type
917
iacls.privileges = ACL_NO_RIGHTS;
921
iacls.all_privs = false;
922
iacls.privileges = ACL_NO_RIGHTS;
924
foreach(cell, action->privileges)
926
AccessPriv *privnode = (AccessPriv *) lfirst(cell);
931
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
932
errmsg("default privileges cannot be set for columns")));
934
if (privnode->priv_name == NULL) /* parser mistake? */
935
elog(ERROR, "AccessPriv node must specify privilege");
936
priv = string_to_privilege(privnode->priv_name);
938
if (priv & ~((AclMode) all_privileges))
940
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
941
errmsg(errormsg, privilege_to_string(priv))));
943
iacls.privileges |= priv;
947
if (rolenames == NIL)
949
/* Set permissions for myself */
950
iacls.roleid = GetUserId();
952
SetDefaultACLsInSchemas(&iacls, nspnames);
956
/* Look up the role OIDs and do permissions checks */
959
foreach(rolecell, rolenames)
961
char *rolename = strVal(lfirst(rolecell));
963
iacls.roleid = get_role_oid(rolename, false);
966
* We insist that calling user be a member of each target role. If
967
* he has that, he could become that role anyway via SET ROLE, so
968
* FOR ROLE is just a syntactic convenience and doesn't give any
969
* special privileges.
971
check_is_member_of_role(GetUserId(), iacls.roleid);
973
SetDefaultACLsInSchemas(&iacls, nspnames);
979
* Process ALTER DEFAULT PRIVILEGES for a list of target schemas
981
* All fields of *iacls except nspid were filled already
984
SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
988
/* Set database-wide permissions if no schema was specified */
989
iacls->nspid = InvalidOid;
991
SetDefaultACL(iacls);
995
/* Look up the schema OIDs and do permissions checks */
998
foreach(nspcell, nspnames)
1000
char *nspname = strVal(lfirst(nspcell));
1001
AclResult aclresult;
1004
* Note that we must do the permissions check against the target
1005
* role not the calling user. We require CREATE privileges, since
1006
* without CREATE you won't be able to do anything using the
1007
* default privs anyway.
1009
iacls->nspid = get_namespace_oid(nspname, false);
1011
aclresult = pg_namespace_aclcheck(iacls->nspid, iacls->roleid,
1013
if (aclresult != ACLCHECK_OK)
1014
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
1017
SetDefaultACL(iacls);
1024
* Create or update a pg_default_acl entry
1027
SetDefaultACL(InternalDefaultACL *iacls)
1029
AclMode this_privileges = iacls->privileges;
1038
Datum values[Natts_pg_default_acl];
1039
bool nulls[Natts_pg_default_acl];
1040
bool replaces[Natts_pg_default_acl];
1046
rel = heap_open(DefaultAclRelationId, RowExclusiveLock);
1049
* The default for a global entry is the hard-wired default ACL for the
1050
* particular object type. The default for non-global entries is an empty
1051
* ACL. This must be so because global entries replace the hard-wired
1052
* defaults, while others are added on.
1054
if (!OidIsValid(iacls->nspid))
1055
def_acl = acldefault(iacls->objtype, iacls->roleid);
1057
def_acl = make_empty_acl();
1060
* Convert ACL object type to pg_default_acl object type and handle
1063
switch (iacls->objtype)
1065
case ACL_OBJECT_RELATION:
1066
objtype = DEFACLOBJ_RELATION;
1067
if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1068
this_privileges = ACL_ALL_RIGHTS_RELATION;
1071
case ACL_OBJECT_SEQUENCE:
1072
objtype = DEFACLOBJ_SEQUENCE;
1073
if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1074
this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1077
case ACL_OBJECT_FUNCTION:
1078
objtype = DEFACLOBJ_FUNCTION;
1079
if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1080
this_privileges = ACL_ALL_RIGHTS_FUNCTION;
1084
elog(ERROR, "unrecognized objtype: %d",
1085
(int) iacls->objtype);
1086
objtype = 0; /* keep compiler quiet */
1090
/* Search for existing row for this object type in catalog */
1091
tuple = SearchSysCache3(DEFACLROLENSPOBJ,
1092
ObjectIdGetDatum(iacls->roleid),
1093
ObjectIdGetDatum(iacls->nspid),
1094
CharGetDatum(objtype));
1096
if (HeapTupleIsValid(tuple))
1101
aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
1102
Anum_pg_default_acl_defaclacl,
1105
old_acl = DatumGetAclPCopy(aclDatum);
1107
old_acl = NULL; /* this case shouldn't happen, probably */
1116
if (old_acl != NULL)
1119
* We need the members of both old and new ACLs so we can correct the
1120
* shared dependency information. Collect data before
1121
* merge_acl_with_grant throws away old_acl.
1123
noldmembers = aclmembers(old_acl, &oldmembers);
1127
/* If no or null entry, start with the default ACL value */
1128
old_acl = aclcopy(def_acl);
1129
/* There are no old member roles according to the catalogs */
1135
* Generate new ACL. Grantor of rights is always the same as the target
1138
new_acl = merge_acl_with_grant(old_acl,
1140
iacls->grant_option,
1148
* If the result is the same as the default value, we do not need an
1149
* explicit pg_default_acl entry, and should in fact remove the entry if
1150
* it exists. Must sort both arrays to compare properly.
1152
aclitemsort(new_acl);
1153
aclitemsort(def_acl);
1154
if (aclequal(new_acl, def_acl))
1156
/* delete old entry, if indeed there is one */
1159
ObjectAddress myself;
1162
* The dependency machinery will take care of removing all
1163
* associated dependency entries. We use DROP_RESTRICT since
1164
* there shouldn't be anything depending on this entry.
1166
myself.classId = DefaultAclRelationId;
1167
myself.objectId = HeapTupleGetOid(tuple);
1168
myself.objectSubId = 0;
1170
performDeletion(&myself, DROP_RESTRICT);
1175
/* Prepare to insert or update pg_default_acl entry */
1176
MemSet(values, 0, sizeof(values));
1177
MemSet(nulls, false, sizeof(nulls));
1178
MemSet(replaces, false, sizeof(replaces));
1182
/* insert new entry */
1183
values[Anum_pg_default_acl_defaclrole - 1] = ObjectIdGetDatum(iacls->roleid);
1184
values[Anum_pg_default_acl_defaclnamespace - 1] = ObjectIdGetDatum(iacls->nspid);
1185
values[Anum_pg_default_acl_defaclobjtype - 1] = CharGetDatum(objtype);
1186
values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
1188
newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
1189
simple_heap_insert(rel, newtuple);
1193
/* update existing entry */
1194
values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
1195
replaces[Anum_pg_default_acl_defaclacl - 1] = true;
1197
newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
1198
values, nulls, replaces);
1199
simple_heap_update(rel, &newtuple->t_self, newtuple);
1202
/* keep the catalog indexes up to date */
1203
CatalogUpdateIndexes(rel, newtuple);
1205
/* these dependencies don't change in an update */
1208
/* dependency on role */
1209
recordDependencyOnOwner(DefaultAclRelationId,
1210
HeapTupleGetOid(newtuple),
1213
/* dependency on namespace */
1214
if (OidIsValid(iacls->nspid))
1216
ObjectAddress myself,
1219
myself.classId = DefaultAclRelationId;
1220
myself.objectId = HeapTupleGetOid(newtuple);
1221
myself.objectSubId = 0;
1223
referenced.classId = NamespaceRelationId;
1224
referenced.objectId = iacls->nspid;
1225
referenced.objectSubId = 0;
1227
recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1232
* Update the shared dependency ACL info
1234
nnewmembers = aclmembers(new_acl, &newmembers);
1236
updateAclDependencies(DefaultAclRelationId,
1237
HeapTupleGetOid(newtuple), 0,
1239
noldmembers, oldmembers,
1240
nnewmembers, newmembers);
1243
if (HeapTupleIsValid(tuple))
1244
ReleaseSysCache(tuple);
1246
heap_close(rel, RowExclusiveLock);
1251
* RemoveRoleFromObjectACL
1253
* Used by shdepDropOwned to remove mentions of a role in ACLs
1256
RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
1258
if (classid == DefaultAclRelationId)
1260
InternalDefaultACL iacls;
1261
Form_pg_default_acl pg_default_acl_tuple;
1263
ScanKeyData skey[1];
1267
/* first fetch info needed by SetDefaultACL */
1268
rel = heap_open(DefaultAclRelationId, AccessShareLock);
1270
ScanKeyInit(&skey[0],
1271
ObjectIdAttributeNumber,
1272
BTEqualStrategyNumber, F_OIDEQ,
1273
ObjectIdGetDatum(objid));
1275
scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
1276
SnapshotNow, 1, skey);
1278
tuple = systable_getnext(scan);
1280
if (!HeapTupleIsValid(tuple))
1281
elog(ERROR, "could not find tuple for default ACL %u", objid);
1283
pg_default_acl_tuple = (Form_pg_default_acl) GETSTRUCT(tuple);
1285
iacls.roleid = pg_default_acl_tuple->defaclrole;
1286
iacls.nspid = pg_default_acl_tuple->defaclnamespace;
1288
switch (pg_default_acl_tuple->defaclobjtype)
1290
case DEFACLOBJ_RELATION:
1291
iacls.objtype = ACL_OBJECT_RELATION;
1293
case DEFACLOBJ_SEQUENCE:
1294
iacls.objtype = ACL_OBJECT_SEQUENCE;
1296
case DEFACLOBJ_FUNCTION:
1297
iacls.objtype = ACL_OBJECT_FUNCTION;
1300
/* Shouldn't get here */
1301
elog(ERROR, "unexpected default ACL type %d",
1302
pg_default_acl_tuple->defaclobjtype);
1306
systable_endscan(scan);
1307
heap_close(rel, AccessShareLock);
1309
iacls.is_grant = false;
1310
iacls.all_privs = true;
1311
iacls.privileges = ACL_NO_RIGHTS;
1312
iacls.grantees = list_make1_oid(roleid);
1313
iacls.grant_option = false;
1314
iacls.behavior = DROP_CASCADE;
1317
SetDefaultACL(&iacls);
1321
InternalGrant istmt;
1325
case RelationRelationId:
1326
/* it's OK to use RELATION for a sequence */
1327
istmt.objtype = ACL_OBJECT_RELATION;
1329
case DatabaseRelationId:
1330
istmt.objtype = ACL_OBJECT_DATABASE;
1332
case ProcedureRelationId:
1333
istmt.objtype = ACL_OBJECT_FUNCTION;
1335
case LanguageRelationId:
1336
istmt.objtype = ACL_OBJECT_LANGUAGE;
1338
case LargeObjectRelationId:
1339
istmt.objtype = ACL_OBJECT_LARGEOBJECT;
1341
case NamespaceRelationId:
1342
istmt.objtype = ACL_OBJECT_NAMESPACE;
1344
case TableSpaceRelationId:
1345
istmt.objtype = ACL_OBJECT_TABLESPACE;
1347
case ForeignServerRelationId:
1348
istmt.objtype = ACL_OBJECT_FOREIGN_SERVER;
1350
case ForeignDataWrapperRelationId:
1351
istmt.objtype = ACL_OBJECT_FDW;
1354
elog(ERROR, "unexpected object class %u", classid);
1357
istmt.is_grant = false;
1358
istmt.objects = list_make1_oid(objid);
1359
istmt.all_privs = true;
1360
istmt.privileges = ACL_NO_RIGHTS;
1361
istmt.col_privs = NIL;
1362
istmt.grantees = list_make1_oid(roleid);
1363
istmt.grant_option = false;
1364
istmt.behavior = DROP_CASCADE;
1366
ExecGrantStmt_oids(&istmt);
1372
* Remove a pg_default_acl entry
1375
RemoveDefaultACLById(Oid defaclOid)
1378
ScanKeyData skey[1];
1382
rel = heap_open(DefaultAclRelationId, RowExclusiveLock);
1384
ScanKeyInit(&skey[0],
1385
ObjectIdAttributeNumber,
1386
BTEqualStrategyNumber, F_OIDEQ,
1387
ObjectIdGetDatum(defaclOid));
1389
scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
1390
SnapshotNow, 1, skey);
1392
tuple = systable_getnext(scan);
1394
if (!HeapTupleIsValid(tuple))
1395
elog(ERROR, "could not find tuple for default ACL %u", defaclOid);
1397
simple_heap_delete(rel, &tuple->t_self);
1399
systable_endscan(scan);
1400
heap_close(rel, RowExclusiveLock);
1405
* expand_col_privileges
1407
* OR the specified privilege(s) into per-column array entries for each
1408
* specified attribute. The per-column array is indexed starting at
1409
* FirstLowInvalidHeapAttributeNumber, up to relation's last attribute.
1412
expand_col_privileges(List *colnames, Oid table_oid,
1413
AclMode this_privileges,
1414
AclMode *col_privileges,
1415
int num_col_privileges)
1419
foreach(cell, colnames)
1421
char *colname = strVal(lfirst(cell));
1424
attnum = get_attnum(table_oid, colname);
1425
if (attnum == InvalidAttrNumber)
1427
(errcode(ERRCODE_UNDEFINED_COLUMN),
1428
errmsg("column \"%s\" of relation \"%s\" does not exist",
1429
colname, get_rel_name(table_oid))));
1430
attnum -= FirstLowInvalidHeapAttributeNumber;
1431
if (attnum <= 0 || attnum >= num_col_privileges)
1432
elog(ERROR, "column number out of range"); /* safety check */
1433
col_privileges[attnum] |= this_privileges;
1438
* expand_all_col_privileges
1440
* OR the specified privilege(s) into per-column array entries for each valid
1441
* attribute of a relation. The per-column array is indexed starting at
1442
* FirstLowInvalidHeapAttributeNumber, up to relation's last attribute.
1445
expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
1446
AclMode this_privileges,
1447
AclMode *col_privileges,
1448
int num_col_privileges)
1450
AttrNumber curr_att;
1452
Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
1453
for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
1454
curr_att <= classForm->relnatts;
1460
if (curr_att == InvalidAttrNumber)
1463
/* Skip OID column if it doesn't exist */
1464
if (curr_att == ObjectIdAttributeNumber && !classForm->relhasoids)
1467
/* Views don't have any system columns at all */
1468
if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
1471
attTuple = SearchSysCache2(ATTNUM,
1472
ObjectIdGetDatum(table_oid),
1473
Int16GetDatum(curr_att));
1474
if (!HeapTupleIsValid(attTuple))
1475
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1476
curr_att, table_oid);
1478
isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
1480
ReleaseSysCache(attTuple);
1482
/* ignore dropped columns */
1486
col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
1491
* This processes attributes, but expects to be called from
1492
* ExecGrant_Relation, not directly from ExecGrantStmt.
1495
ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
1496
AttrNumber attnum, Oid ownerId, AclMode col_privileges,
1497
Relation attRelation, const Acl *old_rel_acl)
1499
HeapTuple attr_tuple;
1500
Form_pg_attribute pg_attribute_tuple;
1507
AclMode avail_goptions;
1510
Datum values[Natts_pg_attribute];
1511
bool nulls[Natts_pg_attribute];
1512
bool replaces[Natts_pg_attribute];
1518
attr_tuple = SearchSysCache2(ATTNUM,
1519
ObjectIdGetDatum(relOid),
1520
Int16GetDatum(attnum));
1521
if (!HeapTupleIsValid(attr_tuple))
1522
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1524
pg_attribute_tuple = (Form_pg_attribute) GETSTRUCT(attr_tuple);
1527
* Get working copy of existing ACL. If there's no ACL, substitute the
1530
aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
1534
old_acl = acldefault(ACL_OBJECT_COLUMN, ownerId);
1535
/* There are no old member roles according to the catalogs */
1541
old_acl = DatumGetAclPCopy(aclDatum);
1542
/* Get the roles mentioned in the existing ACL */
1543
noldmembers = aclmembers(old_acl, &oldmembers);
1547
* In select_best_grantor we should consider existing table-level ACL bits
1548
* as well as the per-column ACL. Build a new ACL that is their
1549
* concatenation. (This is a bit cheap and dirty compared to merging them
1550
* properly with no duplications, but it's all we need here.)
1552
merged_acl = aclconcat(old_rel_acl, old_acl);
1554
/* Determine ID to do the grant as, and available grant options */
1555
select_best_grantor(GetUserId(), col_privileges,
1556
merged_acl, ownerId,
1557
&grantorId, &avail_goptions);
1562
* Restrict the privileges to what we can actually grant, and emit the
1563
* standards-mandated warning and error messages. Note: we don't track
1564
* whether the user actually used the ALL PRIVILEGES(columns) syntax for
1565
* each column; we just approximate it by whether all the possible
1566
* privileges are specified now. Since the all_privs flag only determines
1567
* whether a warning is issued, this seems close enough.
1570
restrict_and_check_grant(istmt->is_grant, avail_goptions,
1571
(col_privileges == ACL_ALL_RIGHTS_COLUMN),
1573
relOid, grantorId, ACL_KIND_COLUMN,
1575
NameStr(pg_attribute_tuple->attname));
1580
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
1581
istmt->grant_option,
1582
istmt->behavior, istmt->grantees,
1583
col_privileges, grantorId,
1587
* We need the members of both old and new ACLs so we can correct the
1588
* shared dependency information.
1590
nnewmembers = aclmembers(new_acl, &newmembers);
1592
/* finished building new ACL value, now insert it */
1593
MemSet(values, 0, sizeof(values));
1594
MemSet(nulls, false, sizeof(nulls));
1595
MemSet(replaces, false, sizeof(replaces));
1598
* If the updated ACL is empty, we can set attacl to null, and maybe even
1599
* avoid an update of the pg_attribute row. This is worth testing because
1600
* we'll come through here multiple times for any relation-level REVOKE,
1601
* even if there were never any column GRANTs. Note we are assuming that
1602
* the "default" ACL state for columns is empty.
1604
if (ACL_NUM(new_acl) > 0)
1606
values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl);
1611
nulls[Anum_pg_attribute_attacl - 1] = true;
1612
need_update = !isNull;
1614
replaces[Anum_pg_attribute_attacl - 1] = true;
1618
newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
1619
values, nulls, replaces);
1621
simple_heap_update(attRelation, &newtuple->t_self, newtuple);
1623
/* keep the catalog indexes up to date */
1624
CatalogUpdateIndexes(attRelation, newtuple);
1626
/* Update the shared dependency ACL info */
1627
updateAclDependencies(RelationRelationId, relOid, attnum,
1629
noldmembers, oldmembers,
1630
nnewmembers, newmembers);
1635
ReleaseSysCache(attr_tuple);
1639
* This processes both sequences and non-sequences.
1642
ExecGrant_Relation(InternalGrant *istmt)
1645
Relation attRelation;
1648
relation = heap_open(RelationRelationId, RowExclusiveLock);
1649
attRelation = heap_open(AttributeRelationId, RowExclusiveLock);
1651
foreach(cell, istmt->objects)
1653
Oid relOid = lfirst_oid(cell);
1655
Form_pg_class pg_class_tuple;
1657
AclMode this_privileges;
1658
AclMode *col_privileges;
1659
int num_col_privileges;
1660
bool have_col_privileges;
1667
ListCell *cell_colprivs;
1669
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
1670
if (!HeapTupleIsValid(tuple))
1671
elog(ERROR, "cache lookup failed for relation %u", relOid);
1672
pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
1674
/* Not sensible to grant on an index */
1675
if (pg_class_tuple->relkind == RELKIND_INDEX)
1677
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1678
errmsg("\"%s\" is an index",
1679
NameStr(pg_class_tuple->relname))));
1681
/* Composite types aren't tables either */
1682
if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
1684
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1685
errmsg("\"%s\" is a composite type",
1686
NameStr(pg_class_tuple->relname))));
1688
/* Used GRANT SEQUENCE on a non-sequence? */
1689
if (istmt->objtype == ACL_OBJECT_SEQUENCE &&
1690
pg_class_tuple->relkind != RELKIND_SEQUENCE)
1692
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1693
errmsg("\"%s\" is not a sequence",
1694
NameStr(pg_class_tuple->relname))));
1696
/* Adjust the default permissions based on object type */
1697
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
1699
if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
1700
this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1702
this_privileges = ACL_ALL_RIGHTS_RELATION;
1705
this_privileges = istmt->privileges;
1708
* The GRANT TABLE syntax can be used for sequences and non-sequences,
1709
* so we have to look at the relkind to determine the supported
1710
* permissions. The OR of table and sequence permissions were already
1713
if (istmt->objtype == ACL_OBJECT_RELATION)
1715
if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
1718
* For backward compatibility, just throw a warning for
1719
* invalid sequence permissions when using the non-sequence
1722
if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
1725
* Mention the object name because the user needs to know
1726
* which operations succeeded. This is required because
1727
* WARNING allows the command to continue.
1730
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
1731
errmsg("sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges",
1732
NameStr(pg_class_tuple->relname))));
1733
this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
1738
if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
1741
* USAGE is the only permission supported by sequences but
1742
* not by non-sequences. Don't mention the object name
1743
* because we didn't in the combined TABLE | SEQUENCE
1747
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
1748
errmsg("invalid privilege type USAGE for table")));
1754
* Set up array in which we'll accumulate any column privilege bits
1755
* that need modification. The array is indexed such that entry [0]
1756
* corresponds to FirstLowInvalidHeapAttributeNumber.
1758
num_col_privileges = pg_class_tuple->relnatts - FirstLowInvalidHeapAttributeNumber + 1;
1759
col_privileges = (AclMode *) palloc0(num_col_privileges * sizeof(AclMode));
1760
have_col_privileges = false;
1763
* If we are revoking relation privileges that are also column
1764
* privileges, we must implicitly revoke them from each column too,
1765
* per SQL spec. (We don't need to implicitly add column privileges
1766
* during GRANT because the permissions-checking code always checks
1767
* both relation and per-column privileges.)
1769
if (!istmt->is_grant &&
1770
(this_privileges & ACL_ALL_RIGHTS_COLUMN) != 0)
1772
expand_all_col_privileges(relOid, pg_class_tuple,
1773
this_privileges & ACL_ALL_RIGHTS_COLUMN,
1775
num_col_privileges);
1776
have_col_privileges = true;
1780
* Get owner ID and working copy of existing ACL. If there's no ACL,
1781
* substitute the proper default.
1783
ownerId = pg_class_tuple->relowner;
1784
aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
1788
switch (pg_class_tuple->relkind)
1790
case RELKIND_SEQUENCE:
1791
old_acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
1794
old_acl = acldefault(ACL_OBJECT_RELATION, ownerId);
1797
/* There are no old member roles according to the catalogs */
1803
old_acl = DatumGetAclPCopy(aclDatum);
1804
/* Get the roles mentioned in the existing ACL */
1805
noldmembers = aclmembers(old_acl, &oldmembers);
1808
/* Need an extra copy of original rel ACL for column handling */
1809
old_rel_acl = aclcopy(old_acl);
1812
* Handle relation-level privileges, if any were specified
1814
if (this_privileges != ACL_NO_RIGHTS)
1816
AclMode avail_goptions;
1820
Datum values[Natts_pg_class];
1821
bool nulls[Natts_pg_class];
1822
bool replaces[Natts_pg_class];
1825
AclObjectKind aclkind;
1827
/* Determine ID to do the grant as, and available grant options */
1828
select_best_grantor(GetUserId(), this_privileges,
1830
&grantorId, &avail_goptions);
1832
switch (pg_class_tuple->relkind)
1834
case RELKIND_SEQUENCE:
1835
aclkind = ACL_KIND_SEQUENCE;
1838
aclkind = ACL_KIND_CLASS;
1843
* Restrict the privileges to what we can actually grant, and emit
1844
* the standards-mandated warning and error messages.
1847
restrict_and_check_grant(istmt->is_grant, avail_goptions,
1848
istmt->all_privs, this_privileges,
1849
relOid, grantorId, aclkind,
1850
NameStr(pg_class_tuple->relname),
1856
new_acl = merge_acl_with_grant(old_acl,
1858
istmt->grant_option,
1866
* We need the members of both old and new ACLs so we can correct
1867
* the shared dependency information.
1869
nnewmembers = aclmembers(new_acl, &newmembers);
1871
/* finished building new ACL value, now insert it */
1872
MemSet(values, 0, sizeof(values));
1873
MemSet(nulls, false, sizeof(nulls));
1874
MemSet(replaces, false, sizeof(replaces));
1876
replaces[Anum_pg_class_relacl - 1] = true;
1877
values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
1879
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
1880
values, nulls, replaces);
1882
simple_heap_update(relation, &newtuple->t_self, newtuple);
1884
/* keep the catalog indexes up to date */
1885
CatalogUpdateIndexes(relation, newtuple);
1887
/* Update the shared dependency ACL info */
1888
updateAclDependencies(RelationRelationId, relOid, 0,
1890
noldmembers, oldmembers,
1891
nnewmembers, newmembers);
1897
* Handle column-level privileges, if any were specified or implied.
1898
* We first expand the user-specified column privileges into the
1899
* array, and then iterate over all nonempty array entries.
1901
foreach(cell_colprivs, istmt->col_privs)
1903
AccessPriv *col_privs = (AccessPriv *) lfirst(cell_colprivs);
1905
if (col_privs->priv_name == NULL)
1906
this_privileges = ACL_ALL_RIGHTS_COLUMN;
1908
this_privileges = string_to_privilege(col_privs->priv_name);
1910
if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
1912
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
1913
errmsg("invalid privilege type %s for column",
1914
privilege_to_string(this_privileges))));
1916
if (pg_class_tuple->relkind == RELKIND_SEQUENCE &&
1917
this_privileges & ~((AclMode) ACL_SELECT))
1920
* The only column privilege allowed on sequences is SELECT.
1921
* This is a warning not error because we do it that way for
1922
* relation-level privileges.
1925
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
1926
errmsg("sequence \"%s\" only supports SELECT column privileges",
1927
NameStr(pg_class_tuple->relname))));
1929
this_privileges &= (AclMode) ACL_SELECT;
1932
expand_col_privileges(col_privs->cols, relOid,
1935
num_col_privileges);
1936
have_col_privileges = true;
1939
if (have_col_privileges)
1943
for (i = 0; i < num_col_privileges; i++)
1945
if (col_privileges[i] == ACL_NO_RIGHTS)
1947
ExecGrant_Attribute(istmt,
1949
NameStr(pg_class_tuple->relname),
1950
i + FirstLowInvalidHeapAttributeNumber,
1959
pfree(col_privileges);
1961
ReleaseSysCache(tuple);
1963
/* prevent error when processing duplicate objects */
1964
CommandCounterIncrement();
1967
heap_close(attRelation, RowExclusiveLock);
1968
heap_close(relation, RowExclusiveLock);
1972
ExecGrant_Database(InternalGrant *istmt)
1977
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
1978
istmt->privileges = ACL_ALL_RIGHTS_DATABASE;
1980
relation = heap_open(DatabaseRelationId, RowExclusiveLock);
1982
foreach(cell, istmt->objects)
1984
Oid datId = lfirst_oid(cell);
1985
Form_pg_database pg_database_tuple;
1988
AclMode avail_goptions;
1989
AclMode this_privileges;
1995
Datum values[Natts_pg_database];
1996
bool nulls[Natts_pg_database];
1997
bool replaces[Natts_pg_database];
2004
tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(datId));
2005
if (!HeapTupleIsValid(tuple))
2006
elog(ERROR, "cache lookup failed for database %u", datId);
2008
pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
2011
* Get owner ID and working copy of existing ACL. If there's no ACL,
2012
* substitute the proper default.
2014
ownerId = pg_database_tuple->datdba;
2015
aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
2016
RelationGetDescr(relation), &isNull);
2019
old_acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
2020
/* There are no old member roles according to the catalogs */
2026
old_acl = DatumGetAclPCopy(aclDatum);
2027
/* Get the roles mentioned in the existing ACL */
2028
noldmembers = aclmembers(old_acl, &oldmembers);
2031
/* Determine ID to do the grant as, and available grant options */
2032
select_best_grantor(GetUserId(), istmt->privileges,
2034
&grantorId, &avail_goptions);
2037
* Restrict the privileges to what we can actually grant, and emit the
2038
* standards-mandated warning and error messages.
2041
restrict_and_check_grant(istmt->is_grant, avail_goptions,
2042
istmt->all_privs, istmt->privileges,
2043
datId, grantorId, ACL_KIND_DATABASE,
2044
NameStr(pg_database_tuple->datname),
2050
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2051
istmt->grant_option, istmt->behavior,
2052
istmt->grantees, this_privileges,
2053
grantorId, ownerId);
2056
* We need the members of both old and new ACLs so we can correct the
2057
* shared dependency information.
2059
nnewmembers = aclmembers(new_acl, &newmembers);
2061
/* finished building new ACL value, now insert it */
2062
MemSet(values, 0, sizeof(values));
2063
MemSet(nulls, false, sizeof(nulls));
2064
MemSet(replaces, false, sizeof(replaces));
2066
replaces[Anum_pg_database_datacl - 1] = true;
2067
values[Anum_pg_database_datacl - 1] = PointerGetDatum(new_acl);
2069
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2072
simple_heap_update(relation, &newtuple->t_self, newtuple);
2074
/* keep the catalog indexes up to date */
2075
CatalogUpdateIndexes(relation, newtuple);
2077
/* Update the shared dependency ACL info */
2078
updateAclDependencies(DatabaseRelationId, HeapTupleGetOid(tuple), 0,
2080
noldmembers, oldmembers,
2081
nnewmembers, newmembers);
2083
ReleaseSysCache(tuple);
2087
/* prevent error when processing duplicate objects */
2088
CommandCounterIncrement();
2091
heap_close(relation, RowExclusiveLock);
2095
ExecGrant_Fdw(InternalGrant *istmt)
2100
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2101
istmt->privileges = ACL_ALL_RIGHTS_FDW;
2103
relation = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
2105
foreach(cell, istmt->objects)
2107
Oid fdwid = lfirst_oid(cell);
2108
Form_pg_foreign_data_wrapper pg_fdw_tuple;
2111
AclMode avail_goptions;
2112
AclMode this_privileges;
2119
Datum values[Natts_pg_foreign_data_wrapper];
2120
bool nulls[Natts_pg_foreign_data_wrapper];
2121
bool replaces[Natts_pg_foreign_data_wrapper];
2127
tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID,
2128
ObjectIdGetDatum(fdwid));
2129
if (!HeapTupleIsValid(tuple))
2130
elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
2132
pg_fdw_tuple = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
2135
* Get owner ID and working copy of existing ACL. If there's no ACL,
2136
* substitute the proper default.
2138
ownerId = pg_fdw_tuple->fdwowner;
2139
aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
2140
Anum_pg_foreign_data_wrapper_fdwacl,
2144
old_acl = acldefault(ACL_OBJECT_FDW, ownerId);
2145
/* There are no old member roles according to the catalogs */
2151
old_acl = DatumGetAclPCopy(aclDatum);
2152
/* Get the roles mentioned in the existing ACL */
2153
noldmembers = aclmembers(old_acl, &oldmembers);
2156
/* Determine ID to do the grant as, and available grant options */
2157
select_best_grantor(GetUserId(), istmt->privileges,
2159
&grantorId, &avail_goptions);
2162
* Restrict the privileges to what we can actually grant, and emit the
2163
* standards-mandated warning and error messages.
2166
restrict_and_check_grant(istmt->is_grant, avail_goptions,
2167
istmt->all_privs, istmt->privileges,
2168
fdwid, grantorId, ACL_KIND_FDW,
2169
NameStr(pg_fdw_tuple->fdwname),
2175
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2176
istmt->grant_option, istmt->behavior,
2177
istmt->grantees, this_privileges,
2178
grantorId, ownerId);
2181
* We need the members of both old and new ACLs so we can correct the
2182
* shared dependency information.
2184
nnewmembers = aclmembers(new_acl, &newmembers);
2186
/* finished building new ACL value, now insert it */
2187
MemSet(values, 0, sizeof(values));
2188
MemSet(nulls, false, sizeof(nulls));
2189
MemSet(replaces, false, sizeof(replaces));
2191
replaces[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
2192
values[Anum_pg_foreign_data_wrapper_fdwacl - 1] = PointerGetDatum(new_acl);
2194
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2197
simple_heap_update(relation, &newtuple->t_self, newtuple);
2199
/* keep the catalog indexes up to date */
2200
CatalogUpdateIndexes(relation, newtuple);
2202
/* Update the shared dependency ACL info */
2203
updateAclDependencies(ForeignDataWrapperRelationId,
2204
HeapTupleGetOid(tuple), 0,
2206
noldmembers, oldmembers,
2207
nnewmembers, newmembers);
2209
ReleaseSysCache(tuple);
2213
/* prevent error when processing duplicate objects */
2214
CommandCounterIncrement();
2217
heap_close(relation, RowExclusiveLock);
2221
ExecGrant_ForeignServer(InternalGrant *istmt)
2226
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2227
istmt->privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
2229
relation = heap_open(ForeignServerRelationId, RowExclusiveLock);
2231
foreach(cell, istmt->objects)
2233
Oid srvid = lfirst_oid(cell);
2234
Form_pg_foreign_server pg_server_tuple;
2237
AclMode avail_goptions;
2238
AclMode this_privileges;
2245
Datum values[Natts_pg_foreign_server];
2246
bool nulls[Natts_pg_foreign_server];
2247
bool replaces[Natts_pg_foreign_server];
2253
tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srvid));
2254
if (!HeapTupleIsValid(tuple))
2255
elog(ERROR, "cache lookup failed for foreign server %u", srvid);
2257
pg_server_tuple = (Form_pg_foreign_server) GETSTRUCT(tuple);
2260
* Get owner ID and working copy of existing ACL. If there's no ACL,
2261
* substitute the proper default.
2263
ownerId = pg_server_tuple->srvowner;
2264
aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
2265
Anum_pg_foreign_server_srvacl,
2269
old_acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
2270
/* There are no old member roles according to the catalogs */
2276
old_acl = DatumGetAclPCopy(aclDatum);
2277
/* Get the roles mentioned in the existing ACL */
2278
noldmembers = aclmembers(old_acl, &oldmembers);
2281
/* Determine ID to do the grant as, and available grant options */
2282
select_best_grantor(GetUserId(), istmt->privileges,
2284
&grantorId, &avail_goptions);
2287
* Restrict the privileges to what we can actually grant, and emit the
2288
* standards-mandated warning and error messages.
2291
restrict_and_check_grant(istmt->is_grant, avail_goptions,
2292
istmt->all_privs, istmt->privileges,
2293
srvid, grantorId, ACL_KIND_FOREIGN_SERVER,
2294
NameStr(pg_server_tuple->srvname),
2300
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2301
istmt->grant_option, istmt->behavior,
2302
istmt->grantees, this_privileges,
2303
grantorId, ownerId);
2306
* We need the members of both old and new ACLs so we can correct the
2307
* shared dependency information.
2309
nnewmembers = aclmembers(new_acl, &newmembers);
2311
/* finished building new ACL value, now insert it */
2312
MemSet(values, 0, sizeof(values));
2313
MemSet(nulls, false, sizeof(nulls));
2314
MemSet(replaces, false, sizeof(replaces));
2316
replaces[Anum_pg_foreign_server_srvacl - 1] = true;
2317
values[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(new_acl);
2319
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2322
simple_heap_update(relation, &newtuple->t_self, newtuple);
2324
/* keep the catalog indexes up to date */
2325
CatalogUpdateIndexes(relation, newtuple);
2327
/* Update the shared dependency ACL info */
2328
updateAclDependencies(ForeignServerRelationId,
2329
HeapTupleGetOid(tuple), 0,
2331
noldmembers, oldmembers,
2332
nnewmembers, newmembers);
2334
ReleaseSysCache(tuple);
2338
/* prevent error when processing duplicate objects */
2339
CommandCounterIncrement();
2342
heap_close(relation, RowExclusiveLock);
2346
ExecGrant_Function(InternalGrant *istmt)
2351
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2352
istmt->privileges = ACL_ALL_RIGHTS_FUNCTION;
2354
relation = heap_open(ProcedureRelationId, RowExclusiveLock);
2356
foreach(cell, istmt->objects)
2358
Oid funcId = lfirst_oid(cell);
2359
Form_pg_proc pg_proc_tuple;
2362
AclMode avail_goptions;
2363
AclMode this_privileges;
2370
Datum values[Natts_pg_proc];
2371
bool nulls[Natts_pg_proc];
2372
bool replaces[Natts_pg_proc];
2378
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
2379
if (!HeapTupleIsValid(tuple))
2380
elog(ERROR, "cache lookup failed for function %u", funcId);
2382
pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
2385
* Get owner ID and working copy of existing ACL. If there's no ACL,
2386
* substitute the proper default.
2388
ownerId = pg_proc_tuple->proowner;
2389
aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
2393
old_acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
2394
/* There are no old member roles according to the catalogs */
2400
old_acl = DatumGetAclPCopy(aclDatum);
2401
/* Get the roles mentioned in the existing ACL */
2402
noldmembers = aclmembers(old_acl, &oldmembers);
2405
/* Determine ID to do the grant as, and available grant options */
2406
select_best_grantor(GetUserId(), istmt->privileges,
2408
&grantorId, &avail_goptions);
2411
* Restrict the privileges to what we can actually grant, and emit the
2412
* standards-mandated warning and error messages.
2415
restrict_and_check_grant(istmt->is_grant, avail_goptions,
2416
istmt->all_privs, istmt->privileges,
2417
funcId, grantorId, ACL_KIND_PROC,
2418
NameStr(pg_proc_tuple->proname),
2424
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2425
istmt->grant_option, istmt->behavior,
2426
istmt->grantees, this_privileges,
2427
grantorId, ownerId);
2430
* We need the members of both old and new ACLs so we can correct the
2431
* shared dependency information.
2433
nnewmembers = aclmembers(new_acl, &newmembers);
2435
/* finished building new ACL value, now insert it */
2436
MemSet(values, 0, sizeof(values));
2437
MemSet(nulls, false, sizeof(nulls));
2438
MemSet(replaces, false, sizeof(replaces));
2440
replaces[Anum_pg_proc_proacl - 1] = true;
2441
values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
2443
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2446
simple_heap_update(relation, &newtuple->t_self, newtuple);
2448
/* keep the catalog indexes up to date */
2449
CatalogUpdateIndexes(relation, newtuple);
2451
/* Update the shared dependency ACL info */
2452
updateAclDependencies(ProcedureRelationId, funcId, 0,
2454
noldmembers, oldmembers,
2455
nnewmembers, newmembers);
2457
ReleaseSysCache(tuple);
2461
/* prevent error when processing duplicate objects */
2462
CommandCounterIncrement();
2465
heap_close(relation, RowExclusiveLock);
2469
ExecGrant_Language(InternalGrant *istmt)
2474
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2475
istmt->privileges = ACL_ALL_RIGHTS_LANGUAGE;
2477
relation = heap_open(LanguageRelationId, RowExclusiveLock);
2479
foreach(cell, istmt->objects)
2481
Oid langId = lfirst_oid(cell);
2482
Form_pg_language pg_language_tuple;
2485
AclMode avail_goptions;
2486
AclMode this_privileges;
2493
Datum values[Natts_pg_language];
2494
bool nulls[Natts_pg_language];
2495
bool replaces[Natts_pg_language];
2501
tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(langId));
2502
if (!HeapTupleIsValid(tuple))
2503
elog(ERROR, "cache lookup failed for language %u", langId);
2505
pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
2507
if (!pg_language_tuple->lanpltrusted)
2509
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
2510
errmsg("language \"%s\" is not trusted",
2511
NameStr(pg_language_tuple->lanname)),
2512
errhint("Only superusers can use untrusted languages.")));
2515
* Get owner ID and working copy of existing ACL. If there's no ACL,
2516
* substitute the proper default.
2518
ownerId = pg_language_tuple->lanowner;
2519
aclDatum = SysCacheGetAttr(LANGNAME, tuple, Anum_pg_language_lanacl,
2523
old_acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
2524
/* There are no old member roles according to the catalogs */
2530
old_acl = DatumGetAclPCopy(aclDatum);
2531
/* Get the roles mentioned in the existing ACL */
2532
noldmembers = aclmembers(old_acl, &oldmembers);
2535
/* Determine ID to do the grant as, and available grant options */
2536
select_best_grantor(GetUserId(), istmt->privileges,
2538
&grantorId, &avail_goptions);
2541
* Restrict the privileges to what we can actually grant, and emit the
2542
* standards-mandated warning and error messages.
2545
restrict_and_check_grant(istmt->is_grant, avail_goptions,
2546
istmt->all_privs, istmt->privileges,
2547
langId, grantorId, ACL_KIND_LANGUAGE,
2548
NameStr(pg_language_tuple->lanname),
2554
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2555
istmt->grant_option, istmt->behavior,
2556
istmt->grantees, this_privileges,
2557
grantorId, ownerId);
2560
* We need the members of both old and new ACLs so we can correct the
2561
* shared dependency information.
2563
nnewmembers = aclmembers(new_acl, &newmembers);
2565
/* finished building new ACL value, now insert it */
2566
MemSet(values, 0, sizeof(values));
2567
MemSet(nulls, false, sizeof(nulls));
2568
MemSet(replaces, false, sizeof(replaces));
2570
replaces[Anum_pg_language_lanacl - 1] = true;
2571
values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
2573
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2576
simple_heap_update(relation, &newtuple->t_self, newtuple);
2578
/* keep the catalog indexes up to date */
2579
CatalogUpdateIndexes(relation, newtuple);
2581
/* Update the shared dependency ACL info */
2582
updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple), 0,
2584
noldmembers, oldmembers,
2585
nnewmembers, newmembers);
2587
ReleaseSysCache(tuple);
2591
/* prevent error when processing duplicate objects */
2592
CommandCounterIncrement();
2595
heap_close(relation, RowExclusiveLock);
2599
ExecGrant_Largeobject(InternalGrant *istmt)
2604
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2605
istmt->privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
2607
relation = heap_open(LargeObjectMetadataRelationId,
2610
foreach(cell, istmt->objects)
2612
Oid loid = lfirst_oid(cell);
2613
Form_pg_largeobject_metadata form_lo_meta;
2614
char loname[NAMEDATALEN];
2617
AclMode avail_goptions;
2618
AclMode this_privileges;
2624
Datum values[Natts_pg_largeobject_metadata];
2625
bool nulls[Natts_pg_largeobject_metadata];
2626
bool replaces[Natts_pg_largeobject_metadata];
2631
ScanKeyData entry[1];
2635
/* There's no syscache for pg_largeobject_metadata */
2636
ScanKeyInit(&entry[0],
2637
ObjectIdAttributeNumber,
2638
BTEqualStrategyNumber, F_OIDEQ,
2639
ObjectIdGetDatum(loid));
2641
scan = systable_beginscan(relation,
2642
LargeObjectMetadataOidIndexId, true,
2643
SnapshotNow, 1, entry);
2645
tuple = systable_getnext(scan);
2646
if (!HeapTupleIsValid(tuple))
2647
elog(ERROR, "cache lookup failed for large object %u", loid);
2649
form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
2652
* Get owner ID and working copy of existing ACL. If there's no ACL,
2653
* substitute the proper default.
2655
ownerId = form_lo_meta->lomowner;
2656
aclDatum = heap_getattr(tuple,
2657
Anum_pg_largeobject_metadata_lomacl,
2658
RelationGetDescr(relation), &isNull);
2661
old_acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
2662
/* There are no old member roles according to the catalogs */
2668
old_acl = DatumGetAclPCopy(aclDatum);
2669
/* Get the roles mentioned in the existing ACL */
2670
noldmembers = aclmembers(old_acl, &oldmembers);
2673
/* Determine ID to do the grant as, and available grant options */
2674
select_best_grantor(GetUserId(), istmt->privileges,
2676
&grantorId, &avail_goptions);
2679
* Restrict the privileges to what we can actually grant, and emit the
2680
* standards-mandated warning and error messages.
2682
snprintf(loname, sizeof(loname), "large object %u", loid);
2684
restrict_and_check_grant(istmt->is_grant, avail_goptions,
2685
istmt->all_privs, istmt->privileges,
2686
loid, grantorId, ACL_KIND_LARGEOBJECT,
2692
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2693
istmt->grant_option, istmt->behavior,
2694
istmt->grantees, this_privileges,
2695
grantorId, ownerId);
2698
* We need the members of both old and new ACLs so we can correct the
2699
* shared dependency information.
2701
nnewmembers = aclmembers(new_acl, &newmembers);
2703
/* finished building new ACL value, now insert it */
2704
MemSet(values, 0, sizeof(values));
2705
MemSet(nulls, false, sizeof(nulls));
2706
MemSet(replaces, false, sizeof(replaces));
2708
replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
2709
values[Anum_pg_largeobject_metadata_lomacl - 1]
2710
= PointerGetDatum(new_acl);
2712
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2713
values, nulls, replaces);
2715
simple_heap_update(relation, &newtuple->t_self, newtuple);
2717
/* keep the catalog indexes up to date */
2718
CatalogUpdateIndexes(relation, newtuple);
2720
/* Update the shared dependency ACL info */
2721
updateAclDependencies(LargeObjectRelationId,
2722
HeapTupleGetOid(tuple), 0,
2724
noldmembers, oldmembers,
2725
nnewmembers, newmembers);
2727
systable_endscan(scan);
2731
/* prevent error when processing duplicate objects */
2732
CommandCounterIncrement();
2735
heap_close(relation, RowExclusiveLock);
2739
ExecGrant_Namespace(InternalGrant *istmt)
2744
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2745
istmt->privileges = ACL_ALL_RIGHTS_NAMESPACE;
2747
relation = heap_open(NamespaceRelationId, RowExclusiveLock);
2749
foreach(cell, istmt->objects)
2751
Oid nspid = lfirst_oid(cell);
2752
Form_pg_namespace pg_namespace_tuple;
2755
AclMode avail_goptions;
2756
AclMode this_privileges;
2763
Datum values[Natts_pg_namespace];
2764
bool nulls[Natts_pg_namespace];
2765
bool replaces[Natts_pg_namespace];
2771
tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
2772
if (!HeapTupleIsValid(tuple))
2773
elog(ERROR, "cache lookup failed for namespace %u", nspid);
2775
pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
2778
* Get owner ID and working copy of existing ACL. If there's no ACL,
2779
* substitute the proper default.
2781
ownerId = pg_namespace_tuple->nspowner;
2782
aclDatum = SysCacheGetAttr(NAMESPACENAME, tuple,
2783
Anum_pg_namespace_nspacl,
2787
old_acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
2788
/* There are no old member roles according to the catalogs */
2794
old_acl = DatumGetAclPCopy(aclDatum);
2795
/* Get the roles mentioned in the existing ACL */
2796
noldmembers = aclmembers(old_acl, &oldmembers);
2799
/* Determine ID to do the grant as, and available grant options */
2800
select_best_grantor(GetUserId(), istmt->privileges,
2802
&grantorId, &avail_goptions);
2805
* Restrict the privileges to what we can actually grant, and emit the
2806
* standards-mandated warning and error messages.
2809
restrict_and_check_grant(istmt->is_grant, avail_goptions,
2810
istmt->all_privs, istmt->privileges,
2811
nspid, grantorId, ACL_KIND_NAMESPACE,
2812
NameStr(pg_namespace_tuple->nspname),
2818
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2819
istmt->grant_option, istmt->behavior,
2820
istmt->grantees, this_privileges,
2821
grantorId, ownerId);
2824
* We need the members of both old and new ACLs so we can correct the
2825
* shared dependency information.
2827
nnewmembers = aclmembers(new_acl, &newmembers);
2829
/* finished building new ACL value, now insert it */
2830
MemSet(values, 0, sizeof(values));
2831
MemSet(nulls, false, sizeof(nulls));
2832
MemSet(replaces, false, sizeof(replaces));
2834
replaces[Anum_pg_namespace_nspacl - 1] = true;
2835
values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(new_acl);
2837
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2840
simple_heap_update(relation, &newtuple->t_self, newtuple);
2842
/* keep the catalog indexes up to date */
2843
CatalogUpdateIndexes(relation, newtuple);
2845
/* Update the shared dependency ACL info */
2846
updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple), 0,
2848
noldmembers, oldmembers,
2849
nnewmembers, newmembers);
2851
ReleaseSysCache(tuple);
2855
/* prevent error when processing duplicate objects */
2856
CommandCounterIncrement();
2859
heap_close(relation, RowExclusiveLock);
2863
ExecGrant_Tablespace(InternalGrant *istmt)
2868
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2869
istmt->privileges = ACL_ALL_RIGHTS_TABLESPACE;
2871
relation = heap_open(TableSpaceRelationId, RowExclusiveLock);
2873
foreach(cell, istmt->objects)
2875
Oid tblId = lfirst_oid(cell);
2876
Form_pg_tablespace pg_tablespace_tuple;
2879
AclMode avail_goptions;
2880
AclMode this_privileges;
2886
Datum values[Natts_pg_tablespace];
2887
bool nulls[Natts_pg_tablespace];
2888
bool replaces[Natts_pg_tablespace];
2895
/* Search syscache for pg_tablespace */
2896
tuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(tblId));
2897
if (!HeapTupleIsValid(tuple))
2898
elog(ERROR, "cache lookup failed for tablespace %u", tblId);
2900
pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);
2903
* Get owner ID and working copy of existing ACL. If there's no ACL,
2904
* substitute the proper default.
2906
ownerId = pg_tablespace_tuple->spcowner;
2907
aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl,
2908
RelationGetDescr(relation), &isNull);
2911
old_acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
2912
/* There are no old member roles according to the catalogs */
2918
old_acl = DatumGetAclPCopy(aclDatum);
2919
/* Get the roles mentioned in the existing ACL */
2920
noldmembers = aclmembers(old_acl, &oldmembers);
2923
/* Determine ID to do the grant as, and available grant options */
2924
select_best_grantor(GetUserId(), istmt->privileges,
2926
&grantorId, &avail_goptions);
2929
* Restrict the privileges to what we can actually grant, and emit the
2930
* standards-mandated warning and error messages.
2933
restrict_and_check_grant(istmt->is_grant, avail_goptions,
2934
istmt->all_privs, istmt->privileges,
2935
tblId, grantorId, ACL_KIND_TABLESPACE,
2936
NameStr(pg_tablespace_tuple->spcname),
2942
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2943
istmt->grant_option, istmt->behavior,
2944
istmt->grantees, this_privileges,
2945
grantorId, ownerId);
2948
* We need the members of both old and new ACLs so we can correct the
2949
* shared dependency information.
2951
nnewmembers = aclmembers(new_acl, &newmembers);
2953
/* finished building new ACL value, now insert it */
2954
MemSet(values, 0, sizeof(values));
2955
MemSet(nulls, false, sizeof(nulls));
2956
MemSet(replaces, false, sizeof(replaces));
2958
replaces[Anum_pg_tablespace_spcacl - 1] = true;
2959
values[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(new_acl);
2961
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2964
simple_heap_update(relation, &newtuple->t_self, newtuple);
2966
/* keep the catalog indexes up to date */
2967
CatalogUpdateIndexes(relation, newtuple);
2969
/* Update the shared dependency ACL info */
2970
updateAclDependencies(TableSpaceRelationId, tblId, 0,
2972
noldmembers, oldmembers,
2973
nnewmembers, newmembers);
2975
ReleaseSysCache(tuple);
2978
/* prevent error when processing duplicate objects */
2979
CommandCounterIncrement();
2982
heap_close(relation, RowExclusiveLock);
2987
string_to_privilege(const char *privname)
2989
if (strcmp(privname, "insert") == 0)
2991
if (strcmp(privname, "select") == 0)
2993
if (strcmp(privname, "update") == 0)
2995
if (strcmp(privname, "delete") == 0)
2997
if (strcmp(privname, "truncate") == 0)
2998
return ACL_TRUNCATE;
2999
if (strcmp(privname, "references") == 0)
3000
return ACL_REFERENCES;
3001
if (strcmp(privname, "trigger") == 0)
3003
if (strcmp(privname, "execute") == 0)
3005
if (strcmp(privname, "usage") == 0)
3007
if (strcmp(privname, "create") == 0)
3009
if (strcmp(privname, "temporary") == 0)
3010
return ACL_CREATE_TEMP;
3011
if (strcmp(privname, "temp") == 0)
3012
return ACL_CREATE_TEMP;
3013
if (strcmp(privname, "connect") == 0)
3015
if (strcmp(privname, "rule") == 0)
3016
return 0; /* ignore old RULE privileges */
3018
(errcode(ERRCODE_SYNTAX_ERROR),
3019
errmsg("unrecognized privilege type \"%s\"", privname)));
3020
return 0; /* appease compiler */
3024
privilege_to_string(AclMode privilege)
3038
case ACL_REFERENCES:
3039
return "REFERENCES";
3048
case ACL_CREATE_TEMP:
3053
elog(ERROR, "unrecognized privilege: %d", (int) privilege);
3055
return NULL; /* appease compiler */
3059
* Standardized reporting of aclcheck permissions failures.
3061
* Note: we do not double-quote the %s's below, because many callers
3062
* supply strings that might be already quoted.
3065
static const char *const no_priv_msg[MAX_ACL_KIND] =
3067
/* ACL_KIND_COLUMN */
3068
gettext_noop("permission denied for column %s"),
3069
/* ACL_KIND_CLASS */
3070
gettext_noop("permission denied for relation %s"),
3071
/* ACL_KIND_SEQUENCE */
3072
gettext_noop("permission denied for sequence %s"),
3073
/* ACL_KIND_DATABASE */
3074
gettext_noop("permission denied for database %s"),
3076
gettext_noop("permission denied for function %s"),
3078
gettext_noop("permission denied for operator %s"),
3080
gettext_noop("permission denied for type %s"),
3081
/* ACL_KIND_LANGUAGE */
3082
gettext_noop("permission denied for language %s"),
3083
/* ACL_KIND_LARGEOBJECT */
3084
gettext_noop("permission denied for large object %s"),
3085
/* ACL_KIND_NAMESPACE */
3086
gettext_noop("permission denied for schema %s"),
3087
/* ACL_KIND_OPCLASS */
3088
gettext_noop("permission denied for operator class %s"),
3089
/* ACL_KIND_OPFAMILY */
3090
gettext_noop("permission denied for operator family %s"),
3091
/* ACL_KIND_COLLATION */
3092
gettext_noop("permission denied for collation %s"),
3093
/* ACL_KIND_CONVERSION */
3094
gettext_noop("permission denied for conversion %s"),
3095
/* ACL_KIND_TABLESPACE */
3096
gettext_noop("permission denied for tablespace %s"),
3097
/* ACL_KIND_TSDICTIONARY */
3098
gettext_noop("permission denied for text search dictionary %s"),
3099
/* ACL_KIND_TSCONFIGURATION */
3100
gettext_noop("permission denied for text search configuration %s"),
3102
gettext_noop("permission denied for foreign-data wrapper %s"),
3103
/* ACL_KIND_FOREIGN_SERVER */
3104
gettext_noop("permission denied for foreign server %s"),
3105
/* ACL_KIND_EXTENSION */
3106
gettext_noop("permission denied for extension %s"),
3109
static const char *const not_owner_msg[MAX_ACL_KIND] =
3111
/* ACL_KIND_COLUMN */
3112
gettext_noop("must be owner of relation %s"),
3113
/* ACL_KIND_CLASS */
3114
gettext_noop("must be owner of relation %s"),
3115
/* ACL_KIND_SEQUENCE */
3116
gettext_noop("must be owner of sequence %s"),
3117
/* ACL_KIND_DATABASE */
3118
gettext_noop("must be owner of database %s"),
3120
gettext_noop("must be owner of function %s"),
3122
gettext_noop("must be owner of operator %s"),
3124
gettext_noop("must be owner of type %s"),
3125
/* ACL_KIND_LANGUAGE */
3126
gettext_noop("must be owner of language %s"),
3127
/* ACL_KIND_LARGEOBJECT */
3128
gettext_noop("must be owner of large object %s"),
3129
/* ACL_KIND_NAMESPACE */
3130
gettext_noop("must be owner of schema %s"),
3131
/* ACL_KIND_OPCLASS */
3132
gettext_noop("must be owner of operator class %s"),
3133
/* ACL_KIND_OPFAMILY */
3134
gettext_noop("must be owner of operator family %s"),
3135
/* ACL_KIND_COLLATION */
3136
gettext_noop("must be owner of collation %s"),
3137
/* ACL_KIND_CONVERSION */
3138
gettext_noop("must be owner of conversion %s"),
3139
/* ACL_KIND_TABLESPACE */
3140
gettext_noop("must be owner of tablespace %s"),
3141
/* ACL_KIND_TSDICTIONARY */
3142
gettext_noop("must be owner of text search dictionary %s"),
3143
/* ACL_KIND_TSCONFIGURATION */
3144
gettext_noop("must be owner of text search configuration %s"),
3146
gettext_noop("must be owner of foreign-data wrapper %s"),
3147
/* ACL_KIND_FOREIGN_SERVER */
3148
gettext_noop("must be owner of foreign server %s"),
3149
/* ACL_KIND_EXTENSION */
3150
gettext_noop("must be owner of extension %s"),
3155
aclcheck_error(AclResult aclerr, AclObjectKind objectkind,
3156
const char *objectname)
3161
/* no error, so return to caller */
3163
case ACLCHECK_NO_PRIV:
3165
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3166
errmsg(no_priv_msg[objectkind], objectname)));
3168
case ACLCHECK_NOT_OWNER:
3170
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3171
errmsg(not_owner_msg[objectkind], objectname)));
3174
elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3181
aclcheck_error_col(AclResult aclerr, AclObjectKind objectkind,
3182
const char *objectname, const char *colname)
3187
/* no error, so return to caller */
3189
case ACLCHECK_NO_PRIV:
3191
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3192
errmsg("permission denied for column \"%s\" of relation \"%s\"",
3193
colname, objectname)));
3195
case ACLCHECK_NOT_OWNER:
3196
/* relation msg is OK since columns don't have separate owners */
3198
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3199
errmsg(not_owner_msg[objectkind], objectname)));
3202
elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3208
/* Check if given user has rolcatupdate privilege according to pg_authid */
3210
has_rolcatupdate(Oid roleid)
3215
tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
3216
if (!HeapTupleIsValid(tuple))
3218
(errcode(ERRCODE_UNDEFINED_OBJECT),
3219
errmsg("role with OID %u does not exist", roleid)));
3221
rolcatupdate = ((Form_pg_authid) GETSTRUCT(tuple))->rolcatupdate;
3223
ReleaseSysCache(tuple);
3225
return rolcatupdate;
3229
* Relay for the various pg_*_mask routines depending on object kind
3232
pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum, Oid roleid,
3233
AclMode mask, AclMaskHow how)
3237
case ACL_KIND_COLUMN:
3239
pg_class_aclmask(table_oid, roleid, mask, how) |
3240
pg_attribute_aclmask(table_oid, attnum, roleid, mask, how);
3241
case ACL_KIND_CLASS:
3242
case ACL_KIND_SEQUENCE:
3243
return pg_class_aclmask(table_oid, roleid, mask, how);
3244
case ACL_KIND_DATABASE:
3245
return pg_database_aclmask(table_oid, roleid, mask, how);
3247
return pg_proc_aclmask(table_oid, roleid, mask, how);
3248
case ACL_KIND_LANGUAGE:
3249
return pg_language_aclmask(table_oid, roleid, mask, how);
3250
case ACL_KIND_LARGEOBJECT:
3251
return pg_largeobject_aclmask_snapshot(table_oid, roleid,
3252
mask, how, SnapshotNow);
3253
case ACL_KIND_NAMESPACE:
3254
return pg_namespace_aclmask(table_oid, roleid, mask, how);
3255
case ACL_KIND_TABLESPACE:
3256
return pg_tablespace_aclmask(table_oid, roleid, mask, how);
3258
return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
3259
case ACL_KIND_FOREIGN_SERVER:
3260
return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
3262
elog(ERROR, "unrecognized objkind: %d",
3264
/* not reached, but keep compiler quiet */
3265
return ACL_NO_RIGHTS;
3270
/* ****************************************************************
3271
* Exported routines for examining a user's privileges for various objects
3273
* See aclmask() for a description of the common API for these functions.
3275
* Note: we give lookup failure the full ereport treatment because the
3276
* has_xxx_privilege() family of functions allow users to pass any random
3277
* OID to these functions.
3278
* ****************************************************************
3282
* Exported routine for examining a user's privileges for a column
3284
* Note: this considers only privileges granted specifically on the column.
3285
* It is caller's responsibility to take relation-level privileges into account
3286
* as appropriate. (For the same reason, we have no special case for
3287
* superuser-ness here.)
3290
pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid,
3291
AclMode mask, AclMaskHow how)
3294
HeapTuple classTuple;
3296
Form_pg_class classForm;
3297
Form_pg_attribute attributeForm;
3304
* First, get the column's ACL from its pg_attribute entry
3306
attTuple = SearchSysCache2(ATTNUM,
3307
ObjectIdGetDatum(table_oid),
3308
Int16GetDatum(attnum));
3309
if (!HeapTupleIsValid(attTuple))
3311
(errcode(ERRCODE_UNDEFINED_COLUMN),
3312
errmsg("attribute %d of relation with OID %u does not exist",
3313
attnum, table_oid)));
3314
attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
3316
/* Throw error on dropped columns, too */
3317
if (attributeForm->attisdropped)
3319
(errcode(ERRCODE_UNDEFINED_COLUMN),
3320
errmsg("attribute %d of relation with OID %u does not exist",
3321
attnum, table_oid)));
3323
aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
3327
* Here we hard-wire knowledge that the default ACL for a column grants no
3328
* privileges, so that we can fall out quickly in the very common case
3329
* where attacl is null.
3333
ReleaseSysCache(attTuple);
3338
* Must get the relation's ownerId from pg_class. Since we already found
3339
* a pg_attribute entry, the only likely reason for this to fail is that a
3340
* concurrent DROP of the relation committed since then (which could only
3341
* happen if we don't have lock on the relation). We prefer to report "no
3342
* privileges" rather than failing in such a case, so as to avoid unwanted
3343
* failures in has_column_privilege() tests.
3345
classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3346
if (!HeapTupleIsValid(classTuple))
3348
ReleaseSysCache(attTuple);
3351
classForm = (Form_pg_class) GETSTRUCT(classTuple);
3353
ownerId = classForm->relowner;
3355
ReleaseSysCache(classTuple);
3357
/* detoast column's ACL if necessary */
3358
acl = DatumGetAclP(aclDatum);
3360
result = aclmask(acl, roleid, ownerId, mask, how);
3362
/* if we have a detoasted copy, free it */
3363
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3366
ReleaseSysCache(attTuple);
3372
* Exported routine for examining a user's privileges for a table
3375
pg_class_aclmask(Oid table_oid, Oid roleid,
3376
AclMode mask, AclMaskHow how)
3380
Form_pg_class classForm;
3387
* Must get the relation's tuple from pg_class
3389
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3390
if (!HeapTupleIsValid(tuple))
3392
(errcode(ERRCODE_UNDEFINED_TABLE),
3393
errmsg("relation with OID %u does not exist",
3395
classForm = (Form_pg_class) GETSTRUCT(tuple);
3398
* Deny anyone permission to update a system catalog unless
3399
* pg_authid.rolcatupdate is set. (This is to let superusers protect
3400
* themselves from themselves.) Also allow it if allowSystemTableMods.
3402
* As of 7.4 we have some updatable system views; those shouldn't be
3403
* protected in this way. Assume the view rules can take care of
3404
* themselves. ACL_USAGE is if we ever have system sequences.
3406
if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
3407
IsSystemClass(classForm) &&
3408
classForm->relkind != RELKIND_VIEW &&
3409
!has_rolcatupdate(roleid) &&
3410
!allowSystemTableMods)
3413
elog(DEBUG2, "permission denied for system catalog update");
3415
mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE);
3419
* Otherwise, superusers bypass all permission-checking.
3421
if (superuser_arg(roleid))
3424
elog(DEBUG2, "OID %u is superuser, home free", roleid);
3426
ReleaseSysCache(tuple);
3431
* Normal case: get the relation's ACL from pg_class
3433
ownerId = classForm->relowner;
3435
aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
3439
/* No ACL, so build default ACL */
3440
switch (classForm->relkind)
3442
case RELKIND_SEQUENCE:
3443
acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
3446
acl = acldefault(ACL_OBJECT_RELATION, ownerId);
3449
aclDatum = (Datum) 0;
3453
/* detoast rel's ACL if necessary */
3454
acl = DatumGetAclP(aclDatum);
3457
result = aclmask(acl, roleid, ownerId, mask, how);
3459
/* if we have a detoasted copy, free it */
3460
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3463
ReleaseSysCache(tuple);
3469
* Exported routine for examining a user's privileges for a database
3472
pg_database_aclmask(Oid db_oid, Oid roleid,
3473
AclMode mask, AclMaskHow how)
3482
/* Superusers bypass all permission checking. */
3483
if (superuser_arg(roleid))
3487
* Get the database's ACL from pg_database
3489
tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
3490
if (!HeapTupleIsValid(tuple))
3492
(errcode(ERRCODE_UNDEFINED_DATABASE),
3493
errmsg("database with OID %u does not exist", db_oid)));
3495
ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
3497
aclDatum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datacl,
3501
/* No ACL, so build default ACL */
3502
acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
3503
aclDatum = (Datum) 0;
3507
/* detoast ACL if necessary */
3508
acl = DatumGetAclP(aclDatum);
3511
result = aclmask(acl, roleid, ownerId, mask, how);
3513
/* if we have a detoasted copy, free it */
3514
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3517
ReleaseSysCache(tuple);
3523
* Exported routine for examining a user's privileges for a function
3526
pg_proc_aclmask(Oid proc_oid, Oid roleid,
3527
AclMode mask, AclMaskHow how)
3536
/* Superusers bypass all permission checking. */
3537
if (superuser_arg(roleid))
3541
* Get the function's ACL from pg_proc
3543
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
3544
if (!HeapTupleIsValid(tuple))
3546
(errcode(ERRCODE_UNDEFINED_FUNCTION),
3547
errmsg("function with OID %u does not exist", proc_oid)));
3549
ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
3551
aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
3555
/* No ACL, so build default ACL */
3556
acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
3557
aclDatum = (Datum) 0;
3561
/* detoast ACL if necessary */
3562
acl = DatumGetAclP(aclDatum);
3565
result = aclmask(acl, roleid, ownerId, mask, how);
3567
/* if we have a detoasted copy, free it */
3568
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3571
ReleaseSysCache(tuple);
3577
* Exported routine for examining a user's privileges for a language
3580
pg_language_aclmask(Oid lang_oid, Oid roleid,
3581
AclMode mask, AclMaskHow how)
3590
/* Superusers bypass all permission checking. */
3591
if (superuser_arg(roleid))
3595
* Get the language's ACL from pg_language
3597
tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lang_oid));
3598
if (!HeapTupleIsValid(tuple))
3600
(errcode(ERRCODE_UNDEFINED_OBJECT),
3601
errmsg("language with OID %u does not exist", lang_oid)));
3603
ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
3605
aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
3609
/* No ACL, so build default ACL */
3610
acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
3611
aclDatum = (Datum) 0;
3615
/* detoast ACL if necessary */
3616
acl = DatumGetAclP(aclDatum);
3619
result = aclmask(acl, roleid, ownerId, mask, how);
3621
/* if we have a detoasted copy, free it */
3622
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3625
ReleaseSysCache(tuple);
3631
* Exported routine for examining a user's privileges for a largeobject
3633
* When a large object is opened for reading, it is opened relative to the
3634
* caller's snapshot, but when it is opened for writing, it is always relative
3635
* to SnapshotNow, as documented in doc/src/sgml/lobj.sgml. This function
3636
* takes a snapshot argument so that the permissions check can be made relative
3637
* to the same snapshot that will be used to read the underlying data.
3640
pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
3641
AclMode mask, AclMaskHow how,
3645
Relation pg_lo_meta;
3646
ScanKeyData entry[1];
3654
/* Superusers bypass all permission checking. */
3655
if (superuser_arg(roleid))
3659
* Get the largeobject's ACL from pg_language_metadata
3661
pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
3664
ScanKeyInit(&entry[0],
3665
ObjectIdAttributeNumber,
3666
BTEqualStrategyNumber, F_OIDEQ,
3667
ObjectIdGetDatum(lobj_oid));
3669
scan = systable_beginscan(pg_lo_meta,
3670
LargeObjectMetadataOidIndexId, true,
3671
snapshot, 1, entry);
3673
tuple = systable_getnext(scan);
3674
if (!HeapTupleIsValid(tuple))
3676
(errcode(ERRCODE_UNDEFINED_OBJECT),
3677
errmsg("large object %u does not exist", lobj_oid)));
3679
ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
3681
aclDatum = heap_getattr(tuple, Anum_pg_largeobject_metadata_lomacl,
3682
RelationGetDescr(pg_lo_meta), &isNull);
3686
/* No ACL, so build default ACL */
3687
acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
3688
aclDatum = (Datum) 0;
3692
/* detoast ACL if necessary */
3693
acl = DatumGetAclP(aclDatum);
3696
result = aclmask(acl, roleid, ownerId, mask, how);
3698
/* if we have a detoasted copy, free it */
3699
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3702
systable_endscan(scan);
3704
heap_close(pg_lo_meta, AccessShareLock);
3710
* Exported routine for examining a user's privileges for a namespace
3713
pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
3714
AclMode mask, AclMaskHow how)
3723
/* Superusers bypass all permission checking. */
3724
if (superuser_arg(roleid))
3728
* If we have been assigned this namespace as a temp namespace, check to
3729
* make sure we have CREATE TEMP permission on the database, and if so act
3730
* as though we have all standard (but not GRANT OPTION) permissions on
3731
* the namespace. If we don't have CREATE TEMP, act as though we have
3732
* only USAGE (and not CREATE) rights.
3734
* This may seem redundant given the check in InitTempTableNamespace, but
3735
* it really isn't since current user ID may have changed since then. The
3736
* upshot of this behavior is that a SECURITY DEFINER function can create
3737
* temp tables that can then be accessed (if permission is granted) by
3738
* code in the same session that doesn't have permissions to create temp
3741
* XXX Would it be safe to ereport a special error message as
3742
* InitTempTableNamespace does? Returning zero here means we'll get a
3743
* generic "permission denied for schema pg_temp_N" message, which is not
3744
* remarkably user-friendly.
3746
if (isTempNamespace(nsp_oid))
3748
if (pg_database_aclcheck(MyDatabaseId, roleid,
3749
ACL_CREATE_TEMP) == ACLCHECK_OK)
3750
return mask & ACL_ALL_RIGHTS_NAMESPACE;
3752
return mask & ACL_USAGE;
3756
* Get the schema's ACL from pg_namespace
3758
tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
3759
if (!HeapTupleIsValid(tuple))
3761
(errcode(ERRCODE_UNDEFINED_SCHEMA),
3762
errmsg("schema with OID %u does not exist", nsp_oid)));
3764
ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
3766
aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspacl,
3770
/* No ACL, so build default ACL */
3771
acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
3772
aclDatum = (Datum) 0;
3776
/* detoast ACL if necessary */
3777
acl = DatumGetAclP(aclDatum);
3780
result = aclmask(acl, roleid, ownerId, mask, how);
3782
/* if we have a detoasted copy, free it */
3783
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3786
ReleaseSysCache(tuple);
3792
* Exported routine for examining a user's privileges for a tablespace
3795
pg_tablespace_aclmask(Oid spc_oid, Oid roleid,
3796
AclMode mask, AclMaskHow how)
3805
/* Superusers bypass all permission checking. */
3806
if (superuser_arg(roleid))
3810
* Get the tablespace's ACL from pg_tablespace
3812
tuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
3813
if (!HeapTupleIsValid(tuple))
3815
(errcode(ERRCODE_UNDEFINED_OBJECT),
3816
errmsg("tablespace with OID %u does not exist", spc_oid)));
3818
ownerId = ((Form_pg_tablespace) GETSTRUCT(tuple))->spcowner;
3820
aclDatum = SysCacheGetAttr(TABLESPACEOID, tuple,
3821
Anum_pg_tablespace_spcacl,
3826
/* No ACL, so build default ACL */
3827
acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
3828
aclDatum = (Datum) 0;
3832
/* detoast ACL if necessary */
3833
acl = DatumGetAclP(aclDatum);
3836
result = aclmask(acl, roleid, ownerId, mask, how);
3838
/* if we have a detoasted copy, free it */
3839
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3842
ReleaseSysCache(tuple);
3848
* Exported routine for examining a user's privileges for a foreign
3852
pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid,
3853
AclMode mask, AclMaskHow how)
3862
Form_pg_foreign_data_wrapper fdwForm;
3864
/* Bypass permission checks for superusers */
3865
if (superuser_arg(roleid))
3869
* Must get the FDW's tuple from pg_foreign_data_wrapper
3871
tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(fdw_oid));
3872
if (!HeapTupleIsValid(tuple))
3874
(errmsg("foreign-data wrapper with OID %u does not exist",
3876
fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
3879
* Normal case: get the FDW's ACL from pg_foreign_data_wrapper
3881
ownerId = fdwForm->fdwowner;
3883
aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
3884
Anum_pg_foreign_data_wrapper_fdwacl, &isNull);
3887
/* No ACL, so build default ACL */
3888
acl = acldefault(ACL_OBJECT_FDW, ownerId);
3889
aclDatum = (Datum) 0;
3893
/* detoast rel's ACL if necessary */
3894
acl = DatumGetAclP(aclDatum);
3897
result = aclmask(acl, roleid, ownerId, mask, how);
3899
/* if we have a detoasted copy, free it */
3900
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3903
ReleaseSysCache(tuple);
3909
* Exported routine for examining a user's privileges for a foreign
3913
pg_foreign_server_aclmask(Oid srv_oid, Oid roleid,
3914
AclMode mask, AclMaskHow how)
3923
Form_pg_foreign_server srvForm;
3925
/* Bypass permission checks for superusers */
3926
if (superuser_arg(roleid))
3930
* Must get the FDW's tuple from pg_foreign_data_wrapper
3932
tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid));
3933
if (!HeapTupleIsValid(tuple))
3935
(errmsg("foreign server with OID %u does not exist",
3937
srvForm = (Form_pg_foreign_server) GETSTRUCT(tuple);
3940
* Normal case: get the foreign server's ACL from pg_foreign_server
3942
ownerId = srvForm->srvowner;
3944
aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
3945
Anum_pg_foreign_server_srvacl, &isNull);
3948
/* No ACL, so build default ACL */
3949
acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
3950
aclDatum = (Datum) 0;
3954
/* detoast rel's ACL if necessary */
3955
acl = DatumGetAclP(aclDatum);
3958
result = aclmask(acl, roleid, ownerId, mask, how);
3960
/* if we have a detoasted copy, free it */
3961
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3964
ReleaseSysCache(tuple);
3970
* Exported routine for checking a user's access privileges to a column
3972
* Returns ACLCHECK_OK if the user has any of the privileges identified by
3973
* 'mode'; otherwise returns a suitable error code (in practice, always
3974
* ACLCHECK_NO_PRIV).
3976
* As with pg_attribute_aclmask, only privileges granted directly on the
3977
* column are considered here.
3980
pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum,
3981
Oid roleid, AclMode mode)
3983
if (pg_attribute_aclmask(table_oid, attnum, roleid, mode, ACLMASK_ANY) != 0)
3986
return ACLCHECK_NO_PRIV;
3990
* Exported routine for checking a user's access privileges to any/all columns
3992
* If 'how' is ACLMASK_ANY, then returns ACLCHECK_OK if user has any of the
3993
* privileges identified by 'mode' on any non-dropped column in the relation;
3994
* otherwise returns a suitable error code (in practice, always
3995
* ACLCHECK_NO_PRIV).
3997
* If 'how' is ACLMASK_ALL, then returns ACLCHECK_OK if user has any of the
3998
* privileges identified by 'mode' on each non-dropped column in the relation
3999
* (and there must be at least one such column); otherwise returns a suitable
4000
* error code (in practice, always ACLCHECK_NO_PRIV).
4002
* As with pg_attribute_aclmask, only privileges granted directly on the
4003
* column(s) are considered here.
4005
* Note: system columns are not considered here; there are cases where that
4006
* might be appropriate but there are also cases where it wouldn't.
4009
pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode,
4013
HeapTuple classTuple;
4014
Form_pg_class classForm;
4016
AttrNumber curr_att;
4019
* Must fetch pg_class row to check number of attributes. As in
4020
* pg_attribute_aclmask, we prefer to return "no privileges" instead of
4021
* throwing an error if we get any unexpected lookup errors.
4023
classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
4024
if (!HeapTupleIsValid(classTuple))
4025
return ACLCHECK_NO_PRIV;
4026
classForm = (Form_pg_class) GETSTRUCT(classTuple);
4028
nattrs = classForm->relnatts;
4030
ReleaseSysCache(classTuple);
4033
* Initialize result in case there are no non-dropped columns. We want to
4034
* report failure in such cases for either value of 'how'.
4036
result = ACLCHECK_NO_PRIV;
4038
for (curr_att = 1; curr_att <= nattrs; curr_att++)
4043
attTuple = SearchSysCache2(ATTNUM,
4044
ObjectIdGetDatum(table_oid),
4045
Int16GetDatum(curr_att));
4046
if (!HeapTupleIsValid(attTuple))
4049
/* ignore dropped columns */
4050
if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4052
ReleaseSysCache(attTuple);
4057
* Here we hard-wire knowledge that the default ACL for a column
4058
* grants no privileges, so that we can fall out quickly in the very
4059
* common case where attacl is null.
4061
if (heap_attisnull(attTuple, Anum_pg_attribute_attacl))
4064
attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
4067
ReleaseSysCache(attTuple);
4071
result = ACLCHECK_OK;
4072
if (how == ACLMASK_ANY)
4073
break; /* succeed on any success */
4077
result = ACLCHECK_NO_PRIV;
4078
if (how == ACLMASK_ALL)
4079
break; /* fail on any failure */
4087
* Exported routine for checking a user's access privileges to a table
4089
* Returns ACLCHECK_OK if the user has any of the privileges identified by
4090
* 'mode'; otherwise returns a suitable error code (in practice, always
4091
* ACLCHECK_NO_PRIV).
4094
pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
4096
if (pg_class_aclmask(table_oid, roleid, mode, ACLMASK_ANY) != 0)
4099
return ACLCHECK_NO_PRIV;
4103
* Exported routine for checking a user's access privileges to a database
4106
pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
4108
if (pg_database_aclmask(db_oid, roleid, mode, ACLMASK_ANY) != 0)
4111
return ACLCHECK_NO_PRIV;
4115
* Exported routine for checking a user's access privileges to a function
4118
pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
4120
if (pg_proc_aclmask(proc_oid, roleid, mode, ACLMASK_ANY) != 0)
4123
return ACLCHECK_NO_PRIV;
4127
* Exported routine for checking a user's access privileges to a language
4130
pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
4132
if (pg_language_aclmask(lang_oid, roleid, mode, ACLMASK_ANY) != 0)
4135
return ACLCHECK_NO_PRIV;
4139
* Exported routine for checking a user's access privileges to a largeobject
4142
pg_largeobject_aclcheck_snapshot(Oid lobj_oid, Oid roleid, AclMode mode,
4145
if (pg_largeobject_aclmask_snapshot(lobj_oid, roleid, mode,
4146
ACLMASK_ANY, snapshot) != 0)
4149
return ACLCHECK_NO_PRIV;
4153
* Exported routine for checking a user's access privileges to a namespace
4156
pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
4158
if (pg_namespace_aclmask(nsp_oid, roleid, mode, ACLMASK_ANY) != 0)
4161
return ACLCHECK_NO_PRIV;
4165
* Exported routine for checking a user's access privileges to a tablespace
4168
pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
4170
if (pg_tablespace_aclmask(spc_oid, roleid, mode, ACLMASK_ANY) != 0)
4173
return ACLCHECK_NO_PRIV;
4177
* Exported routine for checking a user's access privileges to a foreign
4181
pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode)
4183
if (pg_foreign_data_wrapper_aclmask(fdw_oid, roleid, mode, ACLMASK_ANY) != 0)
4186
return ACLCHECK_NO_PRIV;
4190
* Exported routine for checking a user's access privileges to a foreign
4194
pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
4196
if (pg_foreign_server_aclmask(srv_oid, roleid, mode, ACLMASK_ANY) != 0)
4199
return ACLCHECK_NO_PRIV;
4203
* Ownership check for a relation (specified by OID).
4206
pg_class_ownercheck(Oid class_oid, Oid roleid)
4211
/* Superusers bypass all permission checking. */
4212
if (superuser_arg(roleid))
4215
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(class_oid));
4216
if (!HeapTupleIsValid(tuple))
4218
(errcode(ERRCODE_UNDEFINED_TABLE),
4219
errmsg("relation with OID %u does not exist", class_oid)));
4221
ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
4223
ReleaseSysCache(tuple);
4225
return has_privs_of_role(roleid, ownerId);
4229
* Ownership check for a type (specified by OID).
4232
pg_type_ownercheck(Oid type_oid, Oid roleid)
4237
/* Superusers bypass all permission checking. */
4238
if (superuser_arg(roleid))
4241
tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
4242
if (!HeapTupleIsValid(tuple))
4244
(errcode(ERRCODE_UNDEFINED_OBJECT),
4245
errmsg("type with OID %u does not exist", type_oid)));
4247
ownerId = ((Form_pg_type) GETSTRUCT(tuple))->typowner;
4249
ReleaseSysCache(tuple);
4251
return has_privs_of_role(roleid, ownerId);
4255
* Ownership check for an operator (specified by OID).
4258
pg_oper_ownercheck(Oid oper_oid, Oid roleid)
4263
/* Superusers bypass all permission checking. */
4264
if (superuser_arg(roleid))
4267
tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(oper_oid));
4268
if (!HeapTupleIsValid(tuple))
4270
(errcode(ERRCODE_UNDEFINED_FUNCTION),
4271
errmsg("operator with OID %u does not exist", oper_oid)));
4273
ownerId = ((Form_pg_operator) GETSTRUCT(tuple))->oprowner;
4275
ReleaseSysCache(tuple);
4277
return has_privs_of_role(roleid, ownerId);
4281
* Ownership check for a function (specified by OID).
4284
pg_proc_ownercheck(Oid proc_oid, Oid roleid)
4289
/* Superusers bypass all permission checking. */
4290
if (superuser_arg(roleid))
4293
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
4294
if (!HeapTupleIsValid(tuple))
4296
(errcode(ERRCODE_UNDEFINED_FUNCTION),
4297
errmsg("function with OID %u does not exist", proc_oid)));
4299
ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
4301
ReleaseSysCache(tuple);
4303
return has_privs_of_role(roleid, ownerId);
4307
* Ownership check for a procedural language (specified by OID)
4310
pg_language_ownercheck(Oid lan_oid, Oid roleid)
4315
/* Superusers bypass all permission checking. */
4316
if (superuser_arg(roleid))
4319
tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lan_oid));
4320
if (!HeapTupleIsValid(tuple))
4322
(errcode(ERRCODE_UNDEFINED_FUNCTION),
4323
errmsg("language with OID %u does not exist", lan_oid)));
4325
ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
4327
ReleaseSysCache(tuple);
4329
return has_privs_of_role(roleid, ownerId);
4333
* Ownership check for a largeobject (specified by OID)
4335
* This is only used for operations like ALTER LARGE OBJECT that are always
4336
* relative to SnapshotNow.
4339
pg_largeobject_ownercheck(Oid lobj_oid, Oid roleid)
4341
Relation pg_lo_meta;
4342
ScanKeyData entry[1];
4347
/* Superusers bypass all permission checking. */
4348
if (superuser_arg(roleid))
4351
/* There's no syscache for pg_largeobject_metadata */
4352
pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
4355
ScanKeyInit(&entry[0],
4356
ObjectIdAttributeNumber,
4357
BTEqualStrategyNumber, F_OIDEQ,
4358
ObjectIdGetDatum(lobj_oid));
4360
scan = systable_beginscan(pg_lo_meta,
4361
LargeObjectMetadataOidIndexId, true,
4362
SnapshotNow, 1, entry);
4364
tuple = systable_getnext(scan);
4365
if (!HeapTupleIsValid(tuple))
4367
(errcode(ERRCODE_UNDEFINED_OBJECT),
4368
errmsg("large object %u does not exist", lobj_oid)));
4370
ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
4372
systable_endscan(scan);
4373
heap_close(pg_lo_meta, AccessShareLock);
4375
return has_privs_of_role(roleid, ownerId);
4379
* Ownership check for a namespace (specified by OID).
4382
pg_namespace_ownercheck(Oid nsp_oid, Oid roleid)
4387
/* Superusers bypass all permission checking. */
4388
if (superuser_arg(roleid))
4391
tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
4392
if (!HeapTupleIsValid(tuple))
4394
(errcode(ERRCODE_UNDEFINED_SCHEMA),
4395
errmsg("schema with OID %u does not exist", nsp_oid)));
4397
ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
4399
ReleaseSysCache(tuple);
4401
return has_privs_of_role(roleid, ownerId);
4405
* Ownership check for a tablespace (specified by OID).
4408
pg_tablespace_ownercheck(Oid spc_oid, Oid roleid)
4413
/* Superusers bypass all permission checking. */
4414
if (superuser_arg(roleid))
4417
/* Search syscache for pg_tablespace */
4418
spctuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
4419
if (!HeapTupleIsValid(spctuple))
4421
(errcode(ERRCODE_UNDEFINED_OBJECT),
4422
errmsg("tablespace with OID %u does not exist", spc_oid)));
4424
spcowner = ((Form_pg_tablespace) GETSTRUCT(spctuple))->spcowner;
4426
ReleaseSysCache(spctuple);
4428
return has_privs_of_role(roleid, spcowner);
4432
* Ownership check for an operator class (specified by OID).
4435
pg_opclass_ownercheck(Oid opc_oid, Oid roleid)
4440
/* Superusers bypass all permission checking. */
4441
if (superuser_arg(roleid))
4444
tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opc_oid));
4445
if (!HeapTupleIsValid(tuple))
4447
(errcode(ERRCODE_UNDEFINED_OBJECT),
4448
errmsg("operator class with OID %u does not exist",
4451
ownerId = ((Form_pg_opclass) GETSTRUCT(tuple))->opcowner;
4453
ReleaseSysCache(tuple);
4455
return has_privs_of_role(roleid, ownerId);
4459
* Ownership check for an operator family (specified by OID).
4462
pg_opfamily_ownercheck(Oid opf_oid, Oid roleid)
4467
/* Superusers bypass all permission checking. */
4468
if (superuser_arg(roleid))
4471
tuple = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opf_oid));
4472
if (!HeapTupleIsValid(tuple))
4474
(errcode(ERRCODE_UNDEFINED_OBJECT),
4475
errmsg("operator family with OID %u does not exist",
4478
ownerId = ((Form_pg_opfamily) GETSTRUCT(tuple))->opfowner;
4480
ReleaseSysCache(tuple);
4482
return has_privs_of_role(roleid, ownerId);
4486
* Ownership check for a text search dictionary (specified by OID).
4489
pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid)
4494
/* Superusers bypass all permission checking. */
4495
if (superuser_arg(roleid))
4498
tuple = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dict_oid));
4499
if (!HeapTupleIsValid(tuple))
4501
(errcode(ERRCODE_UNDEFINED_OBJECT),
4502
errmsg("text search dictionary with OID %u does not exist",
4505
ownerId = ((Form_pg_ts_dict) GETSTRUCT(tuple))->dictowner;
4507
ReleaseSysCache(tuple);
4509
return has_privs_of_role(roleid, ownerId);
4513
* Ownership check for a text search configuration (specified by OID).
4516
pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid)
4521
/* Superusers bypass all permission checking. */
4522
if (superuser_arg(roleid))
4525
tuple = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfg_oid));
4526
if (!HeapTupleIsValid(tuple))
4528
(errcode(ERRCODE_UNDEFINED_OBJECT),
4529
errmsg("text search configuration with OID %u does not exist",
4532
ownerId = ((Form_pg_ts_config) GETSTRUCT(tuple))->cfgowner;
4534
ReleaseSysCache(tuple);
4536
return has_privs_of_role(roleid, ownerId);
4540
* Ownership check for a foreign-data wrapper (specified by OID).
4543
pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid)
4548
/* Superusers bypass all permission checking. */
4549
if (superuser_arg(roleid))
4552
tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(srv_oid));
4553
if (!HeapTupleIsValid(tuple))
4555
(errcode(ERRCODE_UNDEFINED_OBJECT),
4556
errmsg("foreign-data wrapper with OID %u does not exist",
4559
ownerId = ((Form_pg_foreign_data_wrapper) GETSTRUCT(tuple))->fdwowner;
4561
ReleaseSysCache(tuple);
4563
return has_privs_of_role(roleid, ownerId);
4567
* Ownership check for a foreign server (specified by OID).
4570
pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
4575
/* Superusers bypass all permission checking. */
4576
if (superuser_arg(roleid))
4579
tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid));
4580
if (!HeapTupleIsValid(tuple))
4582
(errcode(ERRCODE_UNDEFINED_OBJECT),
4583
errmsg("foreign server with OID %u does not exist",
4586
ownerId = ((Form_pg_foreign_server) GETSTRUCT(tuple))->srvowner;
4588
ReleaseSysCache(tuple);
4590
return has_privs_of_role(roleid, ownerId);
4594
* Ownership check for a database (specified by OID).
4597
pg_database_ownercheck(Oid db_oid, Oid roleid)
4602
/* Superusers bypass all permission checking. */
4603
if (superuser_arg(roleid))
4606
tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
4607
if (!HeapTupleIsValid(tuple))
4609
(errcode(ERRCODE_UNDEFINED_DATABASE),
4610
errmsg("database with OID %u does not exist", db_oid)));
4612
dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
4614
ReleaseSysCache(tuple);
4616
return has_privs_of_role(roleid, dba);
4620
* Ownership check for a collation (specified by OID).
4623
pg_collation_ownercheck(Oid coll_oid, Oid roleid)
4628
/* Superusers bypass all permission checking. */
4629
if (superuser_arg(roleid))
4632
tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(coll_oid));
4633
if (!HeapTupleIsValid(tuple))
4635
(errcode(ERRCODE_UNDEFINED_OBJECT),
4636
errmsg("collation with OID %u does not exist", coll_oid)));
4638
ownerId = ((Form_pg_collation) GETSTRUCT(tuple))->collowner;
4640
ReleaseSysCache(tuple);
4642
return has_privs_of_role(roleid, ownerId);
4646
* Ownership check for a conversion (specified by OID).
4649
pg_conversion_ownercheck(Oid conv_oid, Oid roleid)
4654
/* Superusers bypass all permission checking. */
4655
if (superuser_arg(roleid))
4658
tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(conv_oid));
4659
if (!HeapTupleIsValid(tuple))
4661
(errcode(ERRCODE_UNDEFINED_OBJECT),
4662
errmsg("conversion with OID %u does not exist", conv_oid)));
4664
ownerId = ((Form_pg_conversion) GETSTRUCT(tuple))->conowner;
4666
ReleaseSysCache(tuple);
4668
return has_privs_of_role(roleid, ownerId);
4672
* Ownership check for an extension (specified by OID).
4675
pg_extension_ownercheck(Oid ext_oid, Oid roleid)
4677
Relation pg_extension;
4678
ScanKeyData entry[1];
4683
/* Superusers bypass all permission checking. */
4684
if (superuser_arg(roleid))
4687
/* There's no syscache for pg_extension, so do it the hard way */
4688
pg_extension = heap_open(ExtensionRelationId, AccessShareLock);
4690
ScanKeyInit(&entry[0],
4691
ObjectIdAttributeNumber,
4692
BTEqualStrategyNumber, F_OIDEQ,
4693
ObjectIdGetDatum(ext_oid));
4695
scan = systable_beginscan(pg_extension,
4696
ExtensionOidIndexId, true,
4697
SnapshotNow, 1, entry);
4699
tuple = systable_getnext(scan);
4700
if (!HeapTupleIsValid(tuple))
4702
(errcode(ERRCODE_UNDEFINED_OBJECT),
4703
errmsg("extension with OID %u does not exist", ext_oid)));
4705
ownerId = ((Form_pg_extension) GETSTRUCT(tuple))->extowner;
4707
systable_endscan(scan);
4708
heap_close(pg_extension, AccessShareLock);
4710
return has_privs_of_role(roleid, ownerId);
4714
* Check whether specified role has CREATEROLE privilege (or is a superuser)
4716
* Note: roles do not have owners per se; instead we use this test in
4717
* places where an ownership-like permissions test is needed for a role.
4718
* Be sure to apply it to the role trying to do the operation, not the
4719
* role being operated on! Also note that this generally should not be
4720
* considered enough privilege if the target role is a superuser.
4721
* (We don't handle that consideration here because we want to give a
4722
* separate error message for such cases, so the caller has to deal with it.)
4725
has_createrole_privilege(Oid roleid)
4727
bool result = false;
4730
/* Superusers bypass all permission checking. */
4731
if (superuser_arg(roleid))
4734
utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4735
if (HeapTupleIsValid(utup))
4737
result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
4738
ReleaseSysCache(utup);
4744
* Fetch pg_default_acl entry for given role, namespace and object type
4745
* (object type must be given in pg_default_acl's encoding).
4746
* Returns NULL if no such entry.
4749
get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
4754
tuple = SearchSysCache3(DEFACLROLENSPOBJ,
4755
ObjectIdGetDatum(roleId),
4756
ObjectIdGetDatum(nsp_oid),
4757
CharGetDatum(objtype));
4759
if (HeapTupleIsValid(tuple))
4764
aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
4765
Anum_pg_default_acl_defaclacl,
4768
result = DatumGetAclPCopy(aclDatum);
4769
ReleaseSysCache(tuple);
4776
* Get default permissions for newly created object within given schema
4778
* Returns NULL if built-in system defaults should be used
4781
get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
4790
* Use NULL during bootstrap, since pg_default_acl probably isn't there
4793
if (IsBootstrapProcessingMode())
4796
/* Check if object type is supported in pg_default_acl */
4799
case ACL_OBJECT_RELATION:
4800
defaclobjtype = DEFACLOBJ_RELATION;
4803
case ACL_OBJECT_SEQUENCE:
4804
defaclobjtype = DEFACLOBJ_SEQUENCE;
4807
case ACL_OBJECT_FUNCTION:
4808
defaclobjtype = DEFACLOBJ_FUNCTION;
4815
/* Look up the relevant pg_default_acl entries */
4816
glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
4817
schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
4819
/* Quick out if neither entry exists */
4820
if (glob_acl == NULL && schema_acl == NULL)
4823
/* We need to know the hard-wired default value, too */
4824
def_acl = acldefault(objtype, ownerId);
4826
/* If there's no global entry, substitute the hard-wired default */
4827
if (glob_acl == NULL)
4830
/* Merge in any per-schema privileges */
4831
result = aclmerge(glob_acl, schema_acl, ownerId);
4834
* For efficiency, we want to return NULL if the result equals default.
4835
* This requires sorting both arrays to get an accurate comparison.
4837
aclitemsort(result);
4838
aclitemsort(def_acl);
4839
if (aclequal(result, def_acl))