00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "postgres.h"
00019
00020 #include "access/genam.h"
00021 #include "access/heapam.h"
00022 #include "access/htup_details.h"
00023 #include "access/sysattr.h"
00024 #include "access/xact.h"
00025 #include "catalog/catalog.h"
00026 #include "catalog/dependency.h"
00027 #include "catalog/indexing.h"
00028 #include "catalog/objectaccess.h"
00029 #include "catalog/pg_authid.h"
00030 #include "catalog/pg_collation.h"
00031 #include "catalog/pg_conversion.h"
00032 #include "catalog/pg_database.h"
00033 #include "catalog/pg_default_acl.h"
00034 #include "catalog/pg_event_trigger.h"
00035 #include "catalog/pg_extension.h"
00036 #include "catalog/pg_foreign_data_wrapper.h"
00037 #include "catalog/pg_foreign_server.h"
00038 #include "catalog/pg_language.h"
00039 #include "catalog/pg_largeobject.h"
00040 #include "catalog/pg_largeobject_metadata.h"
00041 #include "catalog/pg_namespace.h"
00042 #include "catalog/pg_opclass.h"
00043 #include "catalog/pg_operator.h"
00044 #include "catalog/pg_opfamily.h"
00045 #include "catalog/pg_proc.h"
00046 #include "catalog/pg_tablespace.h"
00047 #include "catalog/pg_type.h"
00048 #include "catalog/pg_ts_config.h"
00049 #include "catalog/pg_ts_dict.h"
00050 #include "commands/dbcommands.h"
00051 #include "commands/proclang.h"
00052 #include "commands/tablespace.h"
00053 #include "foreign/foreign.h"
00054 #include "miscadmin.h"
00055 #include "nodes/makefuncs.h"
00056 #include "parser/parse_func.h"
00057 #include "parser/parse_type.h"
00058 #include "utils/acl.h"
00059 #include "utils/builtins.h"
00060 #include "utils/fmgroids.h"
00061 #include "utils/lsyscache.h"
00062 #include "utils/rel.h"
00063 #include "utils/syscache.h"
00064 #include "utils/tqual.h"
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 typedef struct
00081 {
00082 bool is_grant;
00083 GrantObjectType objtype;
00084 List *objects;
00085 bool all_privs;
00086 AclMode privileges;
00087 List *col_privs;
00088 List *grantees;
00089 bool grant_option;
00090 DropBehavior behavior;
00091 } InternalGrant;
00092
00093
00094
00095
00096 typedef struct
00097 {
00098 Oid roleid;
00099 Oid nspid;
00100
00101 bool is_grant;
00102 GrantObjectType objtype;
00103 bool all_privs;
00104 AclMode privileges;
00105 List *grantees;
00106 bool grant_option;
00107 DropBehavior behavior;
00108 } InternalDefaultACL;
00109
00110
00111 static void ExecGrantStmt_oids(InternalGrant *istmt);
00112 static void ExecGrant_Relation(InternalGrant *grantStmt);
00113 static void ExecGrant_Database(InternalGrant *grantStmt);
00114 static void ExecGrant_Fdw(InternalGrant *grantStmt);
00115 static void ExecGrant_ForeignServer(InternalGrant *grantStmt);
00116 static void ExecGrant_Function(InternalGrant *grantStmt);
00117 static void ExecGrant_Language(InternalGrant *grantStmt);
00118 static void ExecGrant_Largeobject(InternalGrant *grantStmt);
00119 static void ExecGrant_Namespace(InternalGrant *grantStmt);
00120 static void ExecGrant_Tablespace(InternalGrant *grantStmt);
00121 static void ExecGrant_Type(InternalGrant *grantStmt);
00122
00123 static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames);
00124 static void SetDefaultACL(InternalDefaultACL *iacls);
00125
00126 static List *objectNamesToOids(GrantObjectType objtype, List *objnames);
00127 static List *objectsInSchemaToOids(GrantObjectType objtype, List *nspnames);
00128 static List *getRelationsInNamespace(Oid namespaceId, char relkind);
00129 static void expand_col_privileges(List *colnames, Oid table_oid,
00130 AclMode this_privileges,
00131 AclMode *col_privileges,
00132 int num_col_privileges);
00133 static void expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
00134 AclMode this_privileges,
00135 AclMode *col_privileges,
00136 int num_col_privileges);
00137 static AclMode string_to_privilege(const char *privname);
00138 static const char *privilege_to_string(AclMode privilege);
00139 static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions,
00140 bool all_privs, AclMode privileges,
00141 Oid objectId, Oid grantorId,
00142 AclObjectKind objkind, const char *objname,
00143 AttrNumber att_number, const char *colname);
00144 static AclMode pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum,
00145 Oid roleid, AclMode mask, AclMaskHow how);
00146
00147
00148 #ifdef ACLDEBUG
00149 static void
00150 dumpacl(Acl *acl)
00151 {
00152 int i;
00153 AclItem *aip;
00154
00155 elog(DEBUG2, "acl size = %d, # acls = %d",
00156 ACL_SIZE(acl), ACL_NUM(acl));
00157 aip = ACL_DAT(acl);
00158 for (i = 0; i < ACL_NUM(acl); ++i)
00159 elog(DEBUG2, " acl[%d]: %s", i,
00160 DatumGetCString(DirectFunctionCall1(aclitemout,
00161 PointerGetDatum(aip + i))));
00162 }
00163 #endif
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 static Acl *
00174 merge_acl_with_grant(Acl *old_acl, bool is_grant,
00175 bool grant_option, DropBehavior behavior,
00176 List *grantees, AclMode privileges,
00177 Oid grantorId, Oid ownerId)
00178 {
00179 unsigned modechg;
00180 ListCell *j;
00181 Acl *new_acl;
00182
00183 modechg = is_grant ? ACL_MODECHG_ADD : ACL_MODECHG_DEL;
00184
00185 #ifdef ACLDEBUG
00186 dumpacl(old_acl);
00187 #endif
00188 new_acl = old_acl;
00189
00190 foreach(j, grantees)
00191 {
00192 AclItem aclitem;
00193 Acl *newer_acl;
00194
00195 aclitem.ai_grantee = lfirst_oid(j);
00196
00197
00198
00199
00200
00201
00202
00203 if (is_grant && grant_option && aclitem.ai_grantee == ACL_ID_PUBLIC)
00204 ereport(ERROR,
00205 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
00206 errmsg("grant options can only be granted to roles")));
00207
00208 aclitem.ai_grantor = grantorId;
00209
00210
00211
00212
00213
00214
00215
00216
00217 ACLITEM_SET_PRIVS_GOPTIONS(aclitem,
00218 (is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
00219 (!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS);
00220
00221 newer_acl = aclupdate(new_acl, &aclitem, modechg, ownerId, behavior);
00222
00223
00224 pfree(new_acl);
00225 new_acl = newer_acl;
00226
00227 #ifdef ACLDEBUG
00228 dumpacl(new_acl);
00229 #endif
00230 }
00231
00232 return new_acl;
00233 }
00234
00235
00236
00237
00238
00239 static AclMode
00240 restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
00241 AclMode privileges, Oid objectId, Oid grantorId,
00242 AclObjectKind objkind, const char *objname,
00243 AttrNumber att_number, const char *colname)
00244 {
00245 AclMode this_privileges;
00246 AclMode whole_mask;
00247
00248 switch (objkind)
00249 {
00250 case ACL_KIND_COLUMN:
00251 whole_mask = ACL_ALL_RIGHTS_COLUMN;
00252 break;
00253 case ACL_KIND_CLASS:
00254 whole_mask = ACL_ALL_RIGHTS_RELATION;
00255 break;
00256 case ACL_KIND_SEQUENCE:
00257 whole_mask = ACL_ALL_RIGHTS_SEQUENCE;
00258 break;
00259 case ACL_KIND_DATABASE:
00260 whole_mask = ACL_ALL_RIGHTS_DATABASE;
00261 break;
00262 case ACL_KIND_PROC:
00263 whole_mask = ACL_ALL_RIGHTS_FUNCTION;
00264 break;
00265 case ACL_KIND_LANGUAGE:
00266 whole_mask = ACL_ALL_RIGHTS_LANGUAGE;
00267 break;
00268 case ACL_KIND_LARGEOBJECT:
00269 whole_mask = ACL_ALL_RIGHTS_LARGEOBJECT;
00270 break;
00271 case ACL_KIND_NAMESPACE:
00272 whole_mask = ACL_ALL_RIGHTS_NAMESPACE;
00273 break;
00274 case ACL_KIND_TABLESPACE:
00275 whole_mask = ACL_ALL_RIGHTS_TABLESPACE;
00276 break;
00277 case ACL_KIND_FDW:
00278 whole_mask = ACL_ALL_RIGHTS_FDW;
00279 break;
00280 case ACL_KIND_FOREIGN_SERVER:
00281 whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
00282 break;
00283 case ACL_KIND_EVENT_TRIGGER:
00284 elog(ERROR, "grantable rights not supported for event triggers");
00285
00286 return ACL_NO_RIGHTS;
00287 case ACL_KIND_TYPE:
00288 whole_mask = ACL_ALL_RIGHTS_TYPE;
00289 break;
00290 default:
00291 elog(ERROR, "unrecognized object kind: %d", objkind);
00292
00293 return ACL_NO_RIGHTS;
00294 }
00295
00296
00297
00298
00299
00300
00301 if (avail_goptions == ACL_NO_RIGHTS)
00302 {
00303 if (pg_aclmask(objkind, objectId, att_number, grantorId,
00304 whole_mask | ACL_GRANT_OPTION_FOR(whole_mask),
00305 ACLMASK_ANY) == ACL_NO_RIGHTS)
00306 {
00307 if (objkind == ACL_KIND_COLUMN && colname)
00308 aclcheck_error_col(ACLCHECK_NO_PRIV, objkind, objname, colname);
00309 else
00310 aclcheck_error(ACLCHECK_NO_PRIV, objkind, objname);
00311 }
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321 this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
00322 if (is_grant)
00323 {
00324 if (this_privileges == 0)
00325 {
00326 if (objkind == ACL_KIND_COLUMN && colname)
00327 ereport(WARNING,
00328 (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
00329 errmsg("no privileges were granted for column \"%s\" of relation \"%s\"",
00330 colname, objname)));
00331 else
00332 ereport(WARNING,
00333 (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
00334 errmsg("no privileges were granted for \"%s\"",
00335 objname)));
00336 }
00337 else if (!all_privs && this_privileges != privileges)
00338 {
00339 if (objkind == ACL_KIND_COLUMN && colname)
00340 ereport(WARNING,
00341 (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
00342 errmsg("not all privileges were granted for column \"%s\" of relation \"%s\"",
00343 colname, objname)));
00344 else
00345 ereport(WARNING,
00346 (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
00347 errmsg("not all privileges were granted for \"%s\"",
00348 objname)));
00349 }
00350 }
00351 else
00352 {
00353 if (this_privileges == 0)
00354 {
00355 if (objkind == ACL_KIND_COLUMN && colname)
00356 ereport(WARNING,
00357 (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
00358 errmsg("no privileges could be revoked for column \"%s\" of relation \"%s\"",
00359 colname, objname)));
00360 else
00361 ereport(WARNING,
00362 (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
00363 errmsg("no privileges could be revoked for \"%s\"",
00364 objname)));
00365 }
00366 else if (!all_privs && this_privileges != privileges)
00367 {
00368 if (objkind == ACL_KIND_COLUMN && colname)
00369 ereport(WARNING,
00370 (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
00371 errmsg("not all privileges could be revoked for column \"%s\" of relation \"%s\"",
00372 colname, objname)));
00373 else
00374 ereport(WARNING,
00375 (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
00376 errmsg("not all privileges could be revoked for \"%s\"",
00377 objname)));
00378 }
00379 }
00380
00381 return this_privileges;
00382 }
00383
00384
00385
00386
00387 void
00388 ExecuteGrantStmt(GrantStmt *stmt)
00389 {
00390 InternalGrant istmt;
00391 ListCell *cell;
00392 const char *errormsg;
00393 AclMode all_privileges;
00394
00395
00396
00397
00398 istmt.is_grant = stmt->is_grant;
00399 istmt.objtype = stmt->objtype;
00400
00401
00402 switch (stmt->targtype)
00403 {
00404 case ACL_TARGET_OBJECT:
00405 istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects);
00406 break;
00407 case ACL_TARGET_ALL_IN_SCHEMA:
00408 istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
00409 break;
00410
00411 default:
00412 elog(ERROR, "unrecognized GrantStmt.targtype: %d",
00413 (int) stmt->targtype);
00414 }
00415
00416
00417
00418 istmt.col_privs = NIL;
00419 istmt.grantees = NIL;
00420 istmt.grant_option = stmt->grant_option;
00421 istmt.behavior = stmt->behavior;
00422
00423
00424
00425
00426
00427
00428
00429
00430 foreach(cell, stmt->grantees)
00431 {
00432 PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);
00433
00434 if (grantee->rolname == NULL)
00435 istmt.grantees = lappend_oid(istmt.grantees, ACL_ID_PUBLIC);
00436 else
00437 istmt.grantees =
00438 lappend_oid(istmt.grantees,
00439 get_role_oid(grantee->rolname, false));
00440 }
00441
00442
00443
00444
00445
00446 switch (stmt->objtype)
00447 {
00448
00449
00450
00451
00452
00453 case ACL_OBJECT_RELATION:
00454 all_privileges = ACL_ALL_RIGHTS_RELATION | ACL_ALL_RIGHTS_SEQUENCE;
00455 errormsg = gettext_noop("invalid privilege type %s for relation");
00456 break;
00457 case ACL_OBJECT_SEQUENCE:
00458 all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
00459 errormsg = gettext_noop("invalid privilege type %s for sequence");
00460 break;
00461 case ACL_OBJECT_DATABASE:
00462 all_privileges = ACL_ALL_RIGHTS_DATABASE;
00463 errormsg = gettext_noop("invalid privilege type %s for database");
00464 break;
00465 case ACL_OBJECT_DOMAIN:
00466 all_privileges = ACL_ALL_RIGHTS_TYPE;
00467 errormsg = gettext_noop("invalid privilege type %s for domain");
00468 break;
00469 case ACL_OBJECT_FUNCTION:
00470 all_privileges = ACL_ALL_RIGHTS_FUNCTION;
00471 errormsg = gettext_noop("invalid privilege type %s for function");
00472 break;
00473 case ACL_OBJECT_LANGUAGE:
00474 all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
00475 errormsg = gettext_noop("invalid privilege type %s for language");
00476 break;
00477 case ACL_OBJECT_LARGEOBJECT:
00478 all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
00479 errormsg = gettext_noop("invalid privilege type %s for large object");
00480 break;
00481 case ACL_OBJECT_NAMESPACE:
00482 all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
00483 errormsg = gettext_noop("invalid privilege type %s for schema");
00484 break;
00485 case ACL_OBJECT_TABLESPACE:
00486 all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
00487 errormsg = gettext_noop("invalid privilege type %s for tablespace");
00488 break;
00489 case ACL_OBJECT_TYPE:
00490 all_privileges = ACL_ALL_RIGHTS_TYPE;
00491 errormsg = gettext_noop("invalid privilege type %s for type");
00492 break;
00493 case ACL_OBJECT_FDW:
00494 all_privileges = ACL_ALL_RIGHTS_FDW;
00495 errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
00496 break;
00497 case ACL_OBJECT_FOREIGN_SERVER:
00498 all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
00499 errormsg = gettext_noop("invalid privilege type %s for foreign server");
00500 break;
00501 default:
00502 elog(ERROR, "unrecognized GrantStmt.objtype: %d",
00503 (int) stmt->objtype);
00504
00505 all_privileges = ACL_NO_RIGHTS;
00506 errormsg = NULL;
00507 }
00508
00509 if (stmt->privileges == NIL)
00510 {
00511 istmt.all_privs = true;
00512
00513
00514
00515
00516
00517 istmt.privileges = ACL_NO_RIGHTS;
00518 }
00519 else
00520 {
00521 istmt.all_privs = false;
00522 istmt.privileges = ACL_NO_RIGHTS;
00523
00524 foreach(cell, stmt->privileges)
00525 {
00526 AccessPriv *privnode = (AccessPriv *) lfirst(cell);
00527 AclMode priv;
00528
00529
00530
00531
00532
00533 if (privnode->cols)
00534 {
00535 if (stmt->objtype != ACL_OBJECT_RELATION)
00536 ereport(ERROR,
00537 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
00538 errmsg("column privileges are only valid for relations")));
00539 istmt.col_privs = lappend(istmt.col_privs, privnode);
00540 continue;
00541 }
00542
00543 if (privnode->priv_name == NULL)
00544 elog(ERROR, "AccessPriv node must specify privilege or columns");
00545 priv = string_to_privilege(privnode->priv_name);
00546
00547 if (priv & ~((AclMode) all_privileges))
00548 ereport(ERROR,
00549 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
00550 errmsg(errormsg, privilege_to_string(priv))));
00551
00552 istmt.privileges |= priv;
00553 }
00554 }
00555
00556 ExecGrantStmt_oids(&istmt);
00557 }
00558
00559
00560
00561
00562
00563
00564 static void
00565 ExecGrantStmt_oids(InternalGrant *istmt)
00566 {
00567 switch (istmt->objtype)
00568 {
00569 case ACL_OBJECT_RELATION:
00570 case ACL_OBJECT_SEQUENCE:
00571 ExecGrant_Relation(istmt);
00572 break;
00573 case ACL_OBJECT_DATABASE:
00574 ExecGrant_Database(istmt);
00575 break;
00576 case ACL_OBJECT_DOMAIN:
00577 case ACL_OBJECT_TYPE:
00578 ExecGrant_Type(istmt);
00579 break;
00580 case ACL_OBJECT_FDW:
00581 ExecGrant_Fdw(istmt);
00582 break;
00583 case ACL_OBJECT_FOREIGN_SERVER:
00584 ExecGrant_ForeignServer(istmt);
00585 break;
00586 case ACL_OBJECT_FUNCTION:
00587 ExecGrant_Function(istmt);
00588 break;
00589 case ACL_OBJECT_LANGUAGE:
00590 ExecGrant_Language(istmt);
00591 break;
00592 case ACL_OBJECT_LARGEOBJECT:
00593 ExecGrant_Largeobject(istmt);
00594 break;
00595 case ACL_OBJECT_NAMESPACE:
00596 ExecGrant_Namespace(istmt);
00597 break;
00598 case ACL_OBJECT_TABLESPACE:
00599 ExecGrant_Tablespace(istmt);
00600 break;
00601 default:
00602 elog(ERROR, "unrecognized GrantStmt.objtype: %d",
00603 (int) istmt->objtype);
00604 }
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 static List *
00618 objectNamesToOids(GrantObjectType objtype, List *objnames)
00619 {
00620 List *objects = NIL;
00621 ListCell *cell;
00622
00623 Assert(objnames != NIL);
00624
00625 switch (objtype)
00626 {
00627 case ACL_OBJECT_RELATION:
00628 case ACL_OBJECT_SEQUENCE:
00629 foreach(cell, objnames)
00630 {
00631 RangeVar *relvar = (RangeVar *) lfirst(cell);
00632 Oid relOid;
00633
00634 relOid = RangeVarGetRelid(relvar, NoLock, false);
00635 objects = lappend_oid(objects, relOid);
00636 }
00637 break;
00638 case ACL_OBJECT_DATABASE:
00639 foreach(cell, objnames)
00640 {
00641 char *dbname = strVal(lfirst(cell));
00642 Oid dbid;
00643
00644 dbid = get_database_oid(dbname, false);
00645 objects = lappend_oid(objects, dbid);
00646 }
00647 break;
00648 case ACL_OBJECT_DOMAIN:
00649 case ACL_OBJECT_TYPE:
00650 foreach(cell, objnames)
00651 {
00652 List *typname = (List *) lfirst(cell);
00653 Oid oid;
00654
00655 oid = typenameTypeId(NULL, makeTypeNameFromNameList(typname));
00656 objects = lappend_oid(objects, oid);
00657 }
00658 break;
00659 case ACL_OBJECT_FUNCTION:
00660 foreach(cell, objnames)
00661 {
00662 FuncWithArgs *func = (FuncWithArgs *) lfirst(cell);
00663 Oid funcid;
00664
00665 funcid = LookupFuncNameTypeNames(func->funcname,
00666 func->funcargs, false);
00667 objects = lappend_oid(objects, funcid);
00668 }
00669 break;
00670 case ACL_OBJECT_LANGUAGE:
00671 foreach(cell, objnames)
00672 {
00673 char *langname = strVal(lfirst(cell));
00674 Oid oid;
00675
00676 oid = get_language_oid(langname, false);
00677 objects = lappend_oid(objects, oid);
00678 }
00679 break;
00680 case ACL_OBJECT_LARGEOBJECT:
00681 foreach(cell, objnames)
00682 {
00683 Oid lobjOid = oidparse(lfirst(cell));
00684
00685 if (!LargeObjectExists(lobjOid))
00686 ereport(ERROR,
00687 (errcode(ERRCODE_UNDEFINED_OBJECT),
00688 errmsg("large object %u does not exist",
00689 lobjOid)));
00690
00691 objects = lappend_oid(objects, lobjOid);
00692 }
00693 break;
00694 case ACL_OBJECT_NAMESPACE:
00695 foreach(cell, objnames)
00696 {
00697 char *nspname = strVal(lfirst(cell));
00698 Oid oid;
00699
00700 oid = get_namespace_oid(nspname, false);
00701 objects = lappend_oid(objects, oid);
00702 }
00703 break;
00704 case ACL_OBJECT_TABLESPACE:
00705 foreach(cell, objnames)
00706 {
00707 char *spcname = strVal(lfirst(cell));
00708 Oid spcoid;
00709
00710 spcoid = get_tablespace_oid(spcname, false);
00711 objects = lappend_oid(objects, spcoid);
00712 }
00713 break;
00714 case ACL_OBJECT_FDW:
00715 foreach(cell, objnames)
00716 {
00717 char *fdwname = strVal(lfirst(cell));
00718 Oid fdwid = get_foreign_data_wrapper_oid(fdwname, false);
00719
00720 objects = lappend_oid(objects, fdwid);
00721 }
00722 break;
00723 case ACL_OBJECT_FOREIGN_SERVER:
00724 foreach(cell, objnames)
00725 {
00726 char *srvname = strVal(lfirst(cell));
00727 Oid srvid = get_foreign_server_oid(srvname, false);
00728
00729 objects = lappend_oid(objects, srvid);
00730 }
00731 break;
00732 default:
00733 elog(ERROR, "unrecognized GrantStmt.objtype: %d",
00734 (int) objtype);
00735 }
00736
00737 return objects;
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747 static List *
00748 objectsInSchemaToOids(GrantObjectType objtype, List *nspnames)
00749 {
00750 List *objects = NIL;
00751 ListCell *cell;
00752
00753 foreach(cell, nspnames)
00754 {
00755 char *nspname = strVal(lfirst(cell));
00756 Oid namespaceId;
00757 List *objs;
00758
00759 namespaceId = LookupExplicitNamespace(nspname, false);
00760
00761 switch (objtype)
00762 {
00763 case ACL_OBJECT_RELATION:
00764
00765 objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
00766 objects = list_concat(objects, objs);
00767 objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
00768 objects = list_concat(objects, objs);
00769 objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
00770 objects = list_concat(objects, objs);
00771 objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
00772 objects = list_concat(objects, objs);
00773 break;
00774 case ACL_OBJECT_SEQUENCE:
00775 objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
00776 objects = list_concat(objects, objs);
00777 break;
00778 case ACL_OBJECT_FUNCTION:
00779 {
00780 ScanKeyData key[1];
00781 Relation rel;
00782 HeapScanDesc scan;
00783 HeapTuple tuple;
00784
00785 ScanKeyInit(&key[0],
00786 Anum_pg_proc_pronamespace,
00787 BTEqualStrategyNumber, F_OIDEQ,
00788 ObjectIdGetDatum(namespaceId));
00789
00790 rel = heap_open(ProcedureRelationId, AccessShareLock);
00791 scan = heap_beginscan(rel, SnapshotNow, 1, key);
00792
00793 while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
00794 {
00795 objects = lappend_oid(objects, HeapTupleGetOid(tuple));
00796 }
00797
00798 heap_endscan(scan);
00799 heap_close(rel, AccessShareLock);
00800 }
00801 break;
00802 default:
00803
00804 elog(ERROR, "unrecognized GrantStmt.objtype: %d",
00805 (int) objtype);
00806 }
00807 }
00808
00809 return objects;
00810 }
00811
00812
00813
00814
00815
00816
00817 static List *
00818 getRelationsInNamespace(Oid namespaceId, char relkind)
00819 {
00820 List *relations = NIL;
00821 ScanKeyData key[2];
00822 Relation rel;
00823 HeapScanDesc scan;
00824 HeapTuple tuple;
00825
00826 ScanKeyInit(&key[0],
00827 Anum_pg_class_relnamespace,
00828 BTEqualStrategyNumber, F_OIDEQ,
00829 ObjectIdGetDatum(namespaceId));
00830 ScanKeyInit(&key[1],
00831 Anum_pg_class_relkind,
00832 BTEqualStrategyNumber, F_CHAREQ,
00833 CharGetDatum(relkind));
00834
00835 rel = heap_open(RelationRelationId, AccessShareLock);
00836 scan = heap_beginscan(rel, SnapshotNow, 2, key);
00837
00838 while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
00839 {
00840 relations = lappend_oid(relations, HeapTupleGetOid(tuple));
00841 }
00842
00843 heap_endscan(scan);
00844 heap_close(rel, AccessShareLock);
00845
00846 return relations;
00847 }
00848
00849
00850
00851
00852
00853 void
00854 ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt)
00855 {
00856 GrantStmt *action = stmt->action;
00857 InternalDefaultACL iacls;
00858 ListCell *cell;
00859 List *rolenames = NIL;
00860 List *nspnames = NIL;
00861 DefElem *drolenames = NULL;
00862 DefElem *dnspnames = NULL;
00863 AclMode all_privileges;
00864 const char *errormsg;
00865
00866
00867 foreach(cell, stmt->options)
00868 {
00869 DefElem *defel = (DefElem *) lfirst(cell);
00870
00871 if (strcmp(defel->defname, "schemas") == 0)
00872 {
00873 if (dnspnames)
00874 ereport(ERROR,
00875 (errcode(ERRCODE_SYNTAX_ERROR),
00876 errmsg("conflicting or redundant options")));
00877 dnspnames = defel;
00878 }
00879 else if (strcmp(defel->defname, "roles") == 0)
00880 {
00881 if (drolenames)
00882 ereport(ERROR,
00883 (errcode(ERRCODE_SYNTAX_ERROR),
00884 errmsg("conflicting or redundant options")));
00885 drolenames = defel;
00886 }
00887 else
00888 elog(ERROR, "option \"%s\" not recognized", defel->defname);
00889 }
00890
00891 if (dnspnames)
00892 nspnames = (List *) dnspnames->arg;
00893 if (drolenames)
00894 rolenames = (List *) drolenames->arg;
00895
00896
00897
00898
00899 iacls.is_grant = action->is_grant;
00900 iacls.objtype = action->objtype;
00901
00902
00903 iacls.grantees = NIL;
00904 iacls.grant_option = action->grant_option;
00905 iacls.behavior = action->behavior;
00906
00907
00908
00909
00910
00911
00912
00913
00914 foreach(cell, action->grantees)
00915 {
00916 PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);
00917
00918 if (grantee->rolname == NULL)
00919 iacls.grantees = lappend_oid(iacls.grantees, ACL_ID_PUBLIC);
00920 else
00921 iacls.grantees =
00922 lappend_oid(iacls.grantees,
00923 get_role_oid(grantee->rolname, false));
00924 }
00925
00926
00927
00928
00929
00930 switch (action->objtype)
00931 {
00932 case ACL_OBJECT_RELATION:
00933 all_privileges = ACL_ALL_RIGHTS_RELATION;
00934 errormsg = gettext_noop("invalid privilege type %s for relation");
00935 break;
00936 case ACL_OBJECT_SEQUENCE:
00937 all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
00938 errormsg = gettext_noop("invalid privilege type %s for sequence");
00939 break;
00940 case ACL_OBJECT_FUNCTION:
00941 all_privileges = ACL_ALL_RIGHTS_FUNCTION;
00942 errormsg = gettext_noop("invalid privilege type %s for function");
00943 break;
00944 case ACL_OBJECT_TYPE:
00945 all_privileges = ACL_ALL_RIGHTS_TYPE;
00946 errormsg = gettext_noop("invalid privilege type %s for type");
00947 break;
00948 default:
00949 elog(ERROR, "unrecognized GrantStmt.objtype: %d",
00950 (int) action->objtype);
00951
00952 all_privileges = ACL_NO_RIGHTS;
00953 errormsg = NULL;
00954 }
00955
00956 if (action->privileges == NIL)
00957 {
00958 iacls.all_privs = true;
00959
00960
00961
00962
00963
00964 iacls.privileges = ACL_NO_RIGHTS;
00965 }
00966 else
00967 {
00968 iacls.all_privs = false;
00969 iacls.privileges = ACL_NO_RIGHTS;
00970
00971 foreach(cell, action->privileges)
00972 {
00973 AccessPriv *privnode = (AccessPriv *) lfirst(cell);
00974 AclMode priv;
00975
00976 if (privnode->cols)
00977 ereport(ERROR,
00978 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
00979 errmsg("default privileges cannot be set for columns")));
00980
00981 if (privnode->priv_name == NULL)
00982 elog(ERROR, "AccessPriv node must specify privilege");
00983 priv = string_to_privilege(privnode->priv_name);
00984
00985 if (priv & ~((AclMode) all_privileges))
00986 ereport(ERROR,
00987 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
00988 errmsg(errormsg, privilege_to_string(priv))));
00989
00990 iacls.privileges |= priv;
00991 }
00992 }
00993
00994 if (rolenames == NIL)
00995 {
00996
00997 iacls.roleid = GetUserId();
00998
00999 SetDefaultACLsInSchemas(&iacls, nspnames);
01000 }
01001 else
01002 {
01003
01004 ListCell *rolecell;
01005
01006 foreach(rolecell, rolenames)
01007 {
01008 char *rolename = strVal(lfirst(rolecell));
01009
01010 iacls.roleid = get_role_oid(rolename, false);
01011
01012
01013
01014
01015
01016
01017
01018 check_is_member_of_role(GetUserId(), iacls.roleid);
01019
01020 SetDefaultACLsInSchemas(&iacls, nspnames);
01021 }
01022 }
01023 }
01024
01025
01026
01027
01028
01029
01030 static void
01031 SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
01032 {
01033 if (nspnames == NIL)
01034 {
01035
01036 iacls->nspid = InvalidOid;
01037
01038 SetDefaultACL(iacls);
01039 }
01040 else
01041 {
01042
01043 ListCell *nspcell;
01044
01045 foreach(nspcell, nspnames)
01046 {
01047 char *nspname = strVal(lfirst(nspcell));
01048 AclResult aclresult;
01049
01050
01051
01052
01053
01054
01055
01056 iacls->nspid = get_namespace_oid(nspname, false);
01057
01058 aclresult = pg_namespace_aclcheck(iacls->nspid, iacls->roleid,
01059 ACL_CREATE);
01060 if (aclresult != ACLCHECK_OK)
01061 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
01062 nspname);
01063
01064 SetDefaultACL(iacls);
01065 }
01066 }
01067 }
01068
01069
01070
01071
01072
01073 static void
01074 SetDefaultACL(InternalDefaultACL *iacls)
01075 {
01076 AclMode this_privileges = iacls->privileges;
01077 char objtype;
01078 Relation rel;
01079 HeapTuple tuple;
01080 bool isNew;
01081 Acl *def_acl;
01082 Acl *old_acl;
01083 Acl *new_acl;
01084 HeapTuple newtuple;
01085 Datum values[Natts_pg_default_acl];
01086 bool nulls[Natts_pg_default_acl];
01087 bool replaces[Natts_pg_default_acl];
01088 int noldmembers;
01089 int nnewmembers;
01090 Oid *oldmembers;
01091 Oid *newmembers;
01092
01093 rel = heap_open(DefaultAclRelationId, RowExclusiveLock);
01094
01095
01096
01097
01098
01099
01100
01101 if (!OidIsValid(iacls->nspid))
01102 def_acl = acldefault(iacls->objtype, iacls->roleid);
01103 else
01104 def_acl = make_empty_acl();
01105
01106
01107
01108
01109
01110 switch (iacls->objtype)
01111 {
01112 case ACL_OBJECT_RELATION:
01113 objtype = DEFACLOBJ_RELATION;
01114 if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
01115 this_privileges = ACL_ALL_RIGHTS_RELATION;
01116 break;
01117
01118 case ACL_OBJECT_SEQUENCE:
01119 objtype = DEFACLOBJ_SEQUENCE;
01120 if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
01121 this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
01122 break;
01123
01124 case ACL_OBJECT_FUNCTION:
01125 objtype = DEFACLOBJ_FUNCTION;
01126 if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
01127 this_privileges = ACL_ALL_RIGHTS_FUNCTION;
01128 break;
01129
01130 case ACL_OBJECT_TYPE:
01131 objtype = DEFACLOBJ_TYPE;
01132 if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
01133 this_privileges = ACL_ALL_RIGHTS_TYPE;
01134 break;
01135
01136 default:
01137 elog(ERROR, "unrecognized objtype: %d",
01138 (int) iacls->objtype);
01139 objtype = 0;
01140 break;
01141 }
01142
01143
01144 tuple = SearchSysCache3(DEFACLROLENSPOBJ,
01145 ObjectIdGetDatum(iacls->roleid),
01146 ObjectIdGetDatum(iacls->nspid),
01147 CharGetDatum(objtype));
01148
01149 if (HeapTupleIsValid(tuple))
01150 {
01151 Datum aclDatum;
01152 bool isNull;
01153
01154 aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
01155 Anum_pg_default_acl_defaclacl,
01156 &isNull);
01157 if (!isNull)
01158 old_acl = DatumGetAclPCopy(aclDatum);
01159 else
01160 old_acl = NULL;
01161 isNew = false;
01162 }
01163 else
01164 {
01165 old_acl = NULL;
01166 isNew = true;
01167 }
01168
01169 if (old_acl != NULL)
01170 {
01171
01172
01173
01174
01175
01176 noldmembers = aclmembers(old_acl, &oldmembers);
01177 }
01178 else
01179 {
01180
01181 old_acl = aclcopy(def_acl);
01182
01183 noldmembers = 0;
01184 oldmembers = NULL;
01185 }
01186
01187
01188
01189
01190
01191 new_acl = merge_acl_with_grant(old_acl,
01192 iacls->is_grant,
01193 iacls->grant_option,
01194 iacls->behavior,
01195 iacls->grantees,
01196 this_privileges,
01197 iacls->roleid,
01198 iacls->roleid);
01199
01200
01201
01202
01203
01204
01205 aclitemsort(new_acl);
01206 aclitemsort(def_acl);
01207 if (aclequal(new_acl, def_acl))
01208 {
01209
01210 if (!isNew)
01211 {
01212 ObjectAddress myself;
01213
01214
01215
01216
01217
01218
01219 myself.classId = DefaultAclRelationId;
01220 myself.objectId = HeapTupleGetOid(tuple);
01221 myself.objectSubId = 0;
01222
01223 performDeletion(&myself, DROP_RESTRICT, 0);
01224 }
01225 }
01226 else
01227 {
01228
01229 MemSet(values, 0, sizeof(values));
01230 MemSet(nulls, false, sizeof(nulls));
01231 MemSet(replaces, false, sizeof(replaces));
01232
01233 if (isNew)
01234 {
01235
01236 values[Anum_pg_default_acl_defaclrole - 1] = ObjectIdGetDatum(iacls->roleid);
01237 values[Anum_pg_default_acl_defaclnamespace - 1] = ObjectIdGetDatum(iacls->nspid);
01238 values[Anum_pg_default_acl_defaclobjtype - 1] = CharGetDatum(objtype);
01239 values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
01240
01241 newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
01242 simple_heap_insert(rel, newtuple);
01243 }
01244 else
01245 {
01246
01247 values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
01248 replaces[Anum_pg_default_acl_defaclacl - 1] = true;
01249
01250 newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
01251 values, nulls, replaces);
01252 simple_heap_update(rel, &newtuple->t_self, newtuple);
01253 }
01254
01255
01256 CatalogUpdateIndexes(rel, newtuple);
01257
01258
01259 if (isNew)
01260 {
01261
01262 recordDependencyOnOwner(DefaultAclRelationId,
01263 HeapTupleGetOid(newtuple),
01264 iacls->roleid);
01265
01266
01267 if (OidIsValid(iacls->nspid))
01268 {
01269 ObjectAddress myself,
01270 referenced;
01271
01272 myself.classId = DefaultAclRelationId;
01273 myself.objectId = HeapTupleGetOid(newtuple);
01274 myself.objectSubId = 0;
01275
01276 referenced.classId = NamespaceRelationId;
01277 referenced.objectId = iacls->nspid;
01278 referenced.objectSubId = 0;
01279
01280 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
01281 }
01282 }
01283
01284
01285
01286
01287 nnewmembers = aclmembers(new_acl, &newmembers);
01288
01289 updateAclDependencies(DefaultAclRelationId,
01290 HeapTupleGetOid(newtuple), 0,
01291 iacls->roleid,
01292 noldmembers, oldmembers,
01293 nnewmembers, newmembers);
01294
01295 if (isNew)
01296 InvokeObjectPostCreateHook(DefaultAclRelationId,
01297 HeapTupleGetOid(newtuple), 0);
01298 else
01299 InvokeObjectPostAlterHook(DefaultAclRelationId,
01300 HeapTupleGetOid(newtuple), 0);
01301 }
01302
01303 if (HeapTupleIsValid(tuple))
01304 ReleaseSysCache(tuple);
01305
01306 heap_close(rel, RowExclusiveLock);
01307 }
01308
01309
01310
01311
01312
01313
01314
01315 void
01316 RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
01317 {
01318 if (classid == DefaultAclRelationId)
01319 {
01320 InternalDefaultACL iacls;
01321 Form_pg_default_acl pg_default_acl_tuple;
01322 Relation rel;
01323 ScanKeyData skey[1];
01324 SysScanDesc scan;
01325 HeapTuple tuple;
01326
01327
01328 rel = heap_open(DefaultAclRelationId, AccessShareLock);
01329
01330 ScanKeyInit(&skey[0],
01331 ObjectIdAttributeNumber,
01332 BTEqualStrategyNumber, F_OIDEQ,
01333 ObjectIdGetDatum(objid));
01334
01335 scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
01336 SnapshotNow, 1, skey);
01337
01338 tuple = systable_getnext(scan);
01339
01340 if (!HeapTupleIsValid(tuple))
01341 elog(ERROR, "could not find tuple for default ACL %u", objid);
01342
01343 pg_default_acl_tuple = (Form_pg_default_acl) GETSTRUCT(tuple);
01344
01345 iacls.roleid = pg_default_acl_tuple->defaclrole;
01346 iacls.nspid = pg_default_acl_tuple->defaclnamespace;
01347
01348 switch (pg_default_acl_tuple->defaclobjtype)
01349 {
01350 case DEFACLOBJ_RELATION:
01351 iacls.objtype = ACL_OBJECT_RELATION;
01352 break;
01353 case DEFACLOBJ_SEQUENCE:
01354 iacls.objtype = ACL_OBJECT_SEQUENCE;
01355 break;
01356 case DEFACLOBJ_FUNCTION:
01357 iacls.objtype = ACL_OBJECT_FUNCTION;
01358 break;
01359 case DEFACLOBJ_TYPE:
01360 iacls.objtype = ACL_OBJECT_TYPE;
01361 break;
01362 default:
01363
01364 elog(ERROR, "unexpected default ACL type: %d",
01365 (int) pg_default_acl_tuple->defaclobjtype);
01366 break;
01367 }
01368
01369 systable_endscan(scan);
01370 heap_close(rel, AccessShareLock);
01371
01372 iacls.is_grant = false;
01373 iacls.all_privs = true;
01374 iacls.privileges = ACL_NO_RIGHTS;
01375 iacls.grantees = list_make1_oid(roleid);
01376 iacls.grant_option = false;
01377 iacls.behavior = DROP_CASCADE;
01378
01379
01380 SetDefaultACL(&iacls);
01381 }
01382 else
01383 {
01384 InternalGrant istmt;
01385
01386 switch (classid)
01387 {
01388 case RelationRelationId:
01389
01390 istmt.objtype = ACL_OBJECT_RELATION;
01391 break;
01392 case DatabaseRelationId:
01393 istmt.objtype = ACL_OBJECT_DATABASE;
01394 break;
01395 case TypeRelationId:
01396 istmt.objtype = ACL_OBJECT_TYPE;
01397 break;
01398 case ProcedureRelationId:
01399 istmt.objtype = ACL_OBJECT_FUNCTION;
01400 break;
01401 case LanguageRelationId:
01402 istmt.objtype = ACL_OBJECT_LANGUAGE;
01403 break;
01404 case LargeObjectRelationId:
01405 istmt.objtype = ACL_OBJECT_LARGEOBJECT;
01406 break;
01407 case NamespaceRelationId:
01408 istmt.objtype = ACL_OBJECT_NAMESPACE;
01409 break;
01410 case TableSpaceRelationId:
01411 istmt.objtype = ACL_OBJECT_TABLESPACE;
01412 break;
01413 case ForeignServerRelationId:
01414 istmt.objtype = ACL_OBJECT_FOREIGN_SERVER;
01415 break;
01416 case ForeignDataWrapperRelationId:
01417 istmt.objtype = ACL_OBJECT_FDW;
01418 break;
01419 default:
01420 elog(ERROR, "unexpected object class %u", classid);
01421 break;
01422 }
01423 istmt.is_grant = false;
01424 istmt.objects = list_make1_oid(objid);
01425 istmt.all_privs = true;
01426 istmt.privileges = ACL_NO_RIGHTS;
01427 istmt.col_privs = NIL;
01428 istmt.grantees = list_make1_oid(roleid);
01429 istmt.grant_option = false;
01430 istmt.behavior = DROP_CASCADE;
01431
01432 ExecGrantStmt_oids(&istmt);
01433 }
01434 }
01435
01436
01437
01438
01439
01440 void
01441 RemoveDefaultACLById(Oid defaclOid)
01442 {
01443 Relation rel;
01444 ScanKeyData skey[1];
01445 SysScanDesc scan;
01446 HeapTuple tuple;
01447
01448 rel = heap_open(DefaultAclRelationId, RowExclusiveLock);
01449
01450 ScanKeyInit(&skey[0],
01451 ObjectIdAttributeNumber,
01452 BTEqualStrategyNumber, F_OIDEQ,
01453 ObjectIdGetDatum(defaclOid));
01454
01455 scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
01456 SnapshotNow, 1, skey);
01457
01458 tuple = systable_getnext(scan);
01459
01460 if (!HeapTupleIsValid(tuple))
01461 elog(ERROR, "could not find tuple for default ACL %u", defaclOid);
01462
01463 simple_heap_delete(rel, &tuple->t_self);
01464
01465 systable_endscan(scan);
01466 heap_close(rel, RowExclusiveLock);
01467 }
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477 static void
01478 expand_col_privileges(List *colnames, Oid table_oid,
01479 AclMode this_privileges,
01480 AclMode *col_privileges,
01481 int num_col_privileges)
01482 {
01483 ListCell *cell;
01484
01485 foreach(cell, colnames)
01486 {
01487 char *colname = strVal(lfirst(cell));
01488 AttrNumber attnum;
01489
01490 attnum = get_attnum(table_oid, colname);
01491 if (attnum == InvalidAttrNumber)
01492 ereport(ERROR,
01493 (errcode(ERRCODE_UNDEFINED_COLUMN),
01494 errmsg("column \"%s\" of relation \"%s\" does not exist",
01495 colname, get_rel_name(table_oid))));
01496 attnum -= FirstLowInvalidHeapAttributeNumber;
01497 if (attnum <= 0 || attnum >= num_col_privileges)
01498 elog(ERROR, "column number out of range");
01499 col_privileges[attnum] |= this_privileges;
01500 }
01501 }
01502
01503
01504
01505
01506
01507
01508
01509
01510 static void
01511 expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
01512 AclMode this_privileges,
01513 AclMode *col_privileges,
01514 int num_col_privileges)
01515 {
01516 AttrNumber curr_att;
01517
01518 Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
01519 for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
01520 curr_att <= classForm->relnatts;
01521 curr_att++)
01522 {
01523 HeapTuple attTuple;
01524 bool isdropped;
01525
01526 if (curr_att == InvalidAttrNumber)
01527 continue;
01528
01529
01530 if (curr_att == ObjectIdAttributeNumber && !classForm->relhasoids)
01531 continue;
01532
01533
01534 if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
01535 continue;
01536
01537 attTuple = SearchSysCache2(ATTNUM,
01538 ObjectIdGetDatum(table_oid),
01539 Int16GetDatum(curr_att));
01540 if (!HeapTupleIsValid(attTuple))
01541 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
01542 curr_att, table_oid);
01543
01544 isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
01545
01546 ReleaseSysCache(attTuple);
01547
01548
01549 if (isdropped)
01550 continue;
01551
01552 col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
01553 }
01554 }
01555
01556
01557
01558
01559
01560 static void
01561 ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
01562 AttrNumber attnum, Oid ownerId, AclMode col_privileges,
01563 Relation attRelation, const Acl *old_rel_acl)
01564 {
01565 HeapTuple attr_tuple;
01566 Form_pg_attribute pg_attribute_tuple;
01567 Acl *old_acl;
01568 Acl *new_acl;
01569 Acl *merged_acl;
01570 Datum aclDatum;
01571 bool isNull;
01572 Oid grantorId;
01573 AclMode avail_goptions;
01574 bool need_update;
01575 HeapTuple newtuple;
01576 Datum values[Natts_pg_attribute];
01577 bool nulls[Natts_pg_attribute];
01578 bool replaces[Natts_pg_attribute];
01579 int noldmembers;
01580 int nnewmembers;
01581 Oid *oldmembers;
01582 Oid *newmembers;
01583
01584 attr_tuple = SearchSysCache2(ATTNUM,
01585 ObjectIdGetDatum(relOid),
01586 Int16GetDatum(attnum));
01587 if (!HeapTupleIsValid(attr_tuple))
01588 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
01589 attnum, relOid);
01590 pg_attribute_tuple = (Form_pg_attribute) GETSTRUCT(attr_tuple);
01591
01592
01593
01594
01595
01596 aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
01597 &isNull);
01598 if (isNull)
01599 {
01600 old_acl = acldefault(ACL_OBJECT_COLUMN, ownerId);
01601
01602 noldmembers = 0;
01603 oldmembers = NULL;
01604 }
01605 else
01606 {
01607 old_acl = DatumGetAclPCopy(aclDatum);
01608
01609 noldmembers = aclmembers(old_acl, &oldmembers);
01610 }
01611
01612
01613
01614
01615
01616
01617
01618 merged_acl = aclconcat(old_rel_acl, old_acl);
01619
01620
01621 select_best_grantor(GetUserId(), col_privileges,
01622 merged_acl, ownerId,
01623 &grantorId, &avail_goptions);
01624
01625 pfree(merged_acl);
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635 col_privileges =
01636 restrict_and_check_grant(istmt->is_grant, avail_goptions,
01637 (col_privileges == ACL_ALL_RIGHTS_COLUMN),
01638 col_privileges,
01639 relOid, grantorId, ACL_KIND_COLUMN,
01640 relname, attnum,
01641 NameStr(pg_attribute_tuple->attname));
01642
01643
01644
01645
01646 new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
01647 istmt->grant_option,
01648 istmt->behavior, istmt->grantees,
01649 col_privileges, grantorId,
01650 ownerId);
01651
01652
01653
01654
01655
01656 nnewmembers = aclmembers(new_acl, &newmembers);
01657
01658
01659 MemSet(values, 0, sizeof(values));
01660 MemSet(nulls, false, sizeof(nulls));
01661 MemSet(replaces, false, sizeof(replaces));
01662
01663
01664
01665
01666
01667
01668
01669
01670 if (ACL_NUM(new_acl) > 0)
01671 {
01672 values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl);
01673 need_update = true;
01674 }
01675 else
01676 {
01677 nulls[Anum_pg_attribute_attacl - 1] = true;
01678 need_update = !isNull;
01679 }
01680 replaces[Anum_pg_attribute_attacl - 1] = true;
01681
01682 if (need_update)
01683 {
01684 newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
01685 values, nulls, replaces);
01686
01687 simple_heap_update(attRelation, &newtuple->t_self, newtuple);
01688
01689
01690 CatalogUpdateIndexes(attRelation, newtuple);
01691
01692
01693 updateAclDependencies(RelationRelationId, relOid, attnum,
01694 ownerId,
01695 noldmembers, oldmembers,
01696 nnewmembers, newmembers);
01697 }
01698
01699 pfree(new_acl);
01700
01701 ReleaseSysCache(attr_tuple);
01702 }
01703
01704
01705
01706
01707 static void
01708 ExecGrant_Relation(InternalGrant *istmt)
01709 {
01710 Relation relation;
01711 Relation attRelation;
01712 ListCell *cell;
01713
01714 relation = heap_open(RelationRelationId, RowExclusiveLock);
01715 attRelation = heap_open(AttributeRelationId, RowExclusiveLock);
01716
01717 foreach(cell, istmt->objects)
01718 {
01719 Oid relOid = lfirst_oid(cell);
01720 Datum aclDatum;
01721 Form_pg_class pg_class_tuple;
01722 bool isNull;
01723 AclMode this_privileges;
01724 AclMode *col_privileges;
01725 int num_col_privileges;
01726 bool have_col_privileges;
01727 Acl *old_acl;
01728 Acl *old_rel_acl;
01729 int noldmembers;
01730 Oid *oldmembers;
01731 Oid ownerId;
01732 HeapTuple tuple;
01733 ListCell *cell_colprivs;
01734
01735 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
01736 if (!HeapTupleIsValid(tuple))
01737 elog(ERROR, "cache lookup failed for relation %u", relOid);
01738 pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
01739
01740
01741 if (pg_class_tuple->relkind == RELKIND_INDEX)
01742 ereport(ERROR,
01743 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01744 errmsg("\"%s\" is an index",
01745 NameStr(pg_class_tuple->relname))));
01746
01747
01748 if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
01749 ereport(ERROR,
01750 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01751 errmsg("\"%s\" is a composite type",
01752 NameStr(pg_class_tuple->relname))));
01753
01754
01755 if (istmt->objtype == ACL_OBJECT_SEQUENCE &&
01756 pg_class_tuple->relkind != RELKIND_SEQUENCE)
01757 ereport(ERROR,
01758 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01759 errmsg("\"%s\" is not a sequence",
01760 NameStr(pg_class_tuple->relname))));
01761
01762
01763 if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
01764 {
01765 if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
01766 this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
01767 else
01768 this_privileges = ACL_ALL_RIGHTS_RELATION;
01769 }
01770 else
01771 this_privileges = istmt->privileges;
01772
01773
01774
01775
01776
01777
01778
01779 if (istmt->objtype == ACL_OBJECT_RELATION)
01780 {
01781 if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
01782 {
01783
01784
01785
01786
01787
01788 if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
01789 {
01790
01791
01792
01793
01794
01795 ereport(WARNING,
01796 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
01797 errmsg("sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges",
01798 NameStr(pg_class_tuple->relname))));
01799 this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
01800 }
01801 }
01802 else
01803 {
01804 if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
01805 {
01806
01807
01808
01809
01810
01811
01812 ereport(ERROR,
01813 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
01814 errmsg("invalid privilege type USAGE for table")));
01815 }
01816 }
01817 }
01818
01819
01820
01821
01822
01823
01824 num_col_privileges = pg_class_tuple->relnatts - FirstLowInvalidHeapAttributeNumber + 1;
01825 col_privileges = (AclMode *) palloc0(num_col_privileges * sizeof(AclMode));
01826 have_col_privileges = false;
01827
01828
01829
01830
01831
01832
01833
01834
01835 if (!istmt->is_grant &&
01836 (this_privileges & ACL_ALL_RIGHTS_COLUMN) != 0)
01837 {
01838 expand_all_col_privileges(relOid, pg_class_tuple,
01839 this_privileges & ACL_ALL_RIGHTS_COLUMN,
01840 col_privileges,
01841 num_col_privileges);
01842 have_col_privileges = true;
01843 }
01844
01845
01846
01847
01848
01849 ownerId = pg_class_tuple->relowner;
01850 aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
01851 &isNull);
01852 if (isNull)
01853 {
01854 switch (pg_class_tuple->relkind)
01855 {
01856 case RELKIND_SEQUENCE:
01857 old_acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
01858 break;
01859 default:
01860 old_acl = acldefault(ACL_OBJECT_RELATION, ownerId);
01861 break;
01862 }
01863
01864 noldmembers = 0;
01865 oldmembers = NULL;
01866 }
01867 else
01868 {
01869 old_acl = DatumGetAclPCopy(aclDatum);
01870
01871 noldmembers = aclmembers(old_acl, &oldmembers);
01872 }
01873
01874
01875 old_rel_acl = aclcopy(old_acl);
01876
01877
01878
01879
01880 if (this_privileges != ACL_NO_RIGHTS)
01881 {
01882 AclMode avail_goptions;
01883 Acl *new_acl;
01884 Oid grantorId;
01885 HeapTuple newtuple;
01886 Datum values[Natts_pg_class];
01887 bool nulls[Natts_pg_class];
01888 bool replaces[Natts_pg_class];
01889 int nnewmembers;
01890 Oid *newmembers;
01891 AclObjectKind aclkind;
01892
01893
01894 select_best_grantor(GetUserId(), this_privileges,
01895 old_acl, ownerId,
01896 &grantorId, &avail_goptions);
01897
01898 switch (pg_class_tuple->relkind)
01899 {
01900 case RELKIND_SEQUENCE:
01901 aclkind = ACL_KIND_SEQUENCE;
01902 break;
01903 default:
01904 aclkind = ACL_KIND_CLASS;
01905 break;
01906 }
01907
01908
01909
01910
01911
01912 this_privileges =
01913 restrict_and_check_grant(istmt->is_grant, avail_goptions,
01914 istmt->all_privs, this_privileges,
01915 relOid, grantorId, aclkind,
01916 NameStr(pg_class_tuple->relname),
01917 0, NULL);
01918
01919
01920
01921
01922 new_acl = merge_acl_with_grant(old_acl,
01923 istmt->is_grant,
01924 istmt->grant_option,
01925 istmt->behavior,
01926 istmt->grantees,
01927 this_privileges,
01928 grantorId,
01929 ownerId);
01930
01931
01932
01933
01934
01935 nnewmembers = aclmembers(new_acl, &newmembers);
01936
01937
01938 MemSet(values, 0, sizeof(values));
01939 MemSet(nulls, false, sizeof(nulls));
01940 MemSet(replaces, false, sizeof(replaces));
01941
01942 replaces[Anum_pg_class_relacl - 1] = true;
01943 values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
01944
01945 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
01946 values, nulls, replaces);
01947
01948 simple_heap_update(relation, &newtuple->t_self, newtuple);
01949
01950
01951 CatalogUpdateIndexes(relation, newtuple);
01952
01953
01954 updateAclDependencies(RelationRelationId, relOid, 0,
01955 ownerId,
01956 noldmembers, oldmembers,
01957 nnewmembers, newmembers);
01958
01959 pfree(new_acl);
01960 }
01961
01962
01963
01964
01965
01966
01967 foreach(cell_colprivs, istmt->col_privs)
01968 {
01969 AccessPriv *col_privs = (AccessPriv *) lfirst(cell_colprivs);
01970
01971 if (col_privs->priv_name == NULL)
01972 this_privileges = ACL_ALL_RIGHTS_COLUMN;
01973 else
01974 this_privileges = string_to_privilege(col_privs->priv_name);
01975
01976 if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
01977 ereport(ERROR,
01978 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
01979 errmsg("invalid privilege type %s for column",
01980 privilege_to_string(this_privileges))));
01981
01982 if (pg_class_tuple->relkind == RELKIND_SEQUENCE &&
01983 this_privileges & ~((AclMode) ACL_SELECT))
01984 {
01985
01986
01987
01988
01989
01990 ereport(WARNING,
01991 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
01992 errmsg("sequence \"%s\" only supports SELECT column privileges",
01993 NameStr(pg_class_tuple->relname))));
01994
01995 this_privileges &= (AclMode) ACL_SELECT;
01996 }
01997
01998 expand_col_privileges(col_privs->cols, relOid,
01999 this_privileges,
02000 col_privileges,
02001 num_col_privileges);
02002 have_col_privileges = true;
02003 }
02004
02005 if (have_col_privileges)
02006 {
02007 AttrNumber i;
02008
02009 for (i = 0; i < num_col_privileges; i++)
02010 {
02011 if (col_privileges[i] == ACL_NO_RIGHTS)
02012 continue;
02013 ExecGrant_Attribute(istmt,
02014 relOid,
02015 NameStr(pg_class_tuple->relname),
02016 i + FirstLowInvalidHeapAttributeNumber,
02017 ownerId,
02018 col_privileges[i],
02019 attRelation,
02020 old_rel_acl);
02021 }
02022 }
02023
02024 pfree(old_rel_acl);
02025 pfree(col_privileges);
02026
02027 ReleaseSysCache(tuple);
02028
02029
02030 CommandCounterIncrement();
02031 }
02032
02033 heap_close(attRelation, RowExclusiveLock);
02034 heap_close(relation, RowExclusiveLock);
02035 }
02036
02037 static void
02038 ExecGrant_Database(InternalGrant *istmt)
02039 {
02040 Relation relation;
02041 ListCell *cell;
02042
02043 if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
02044 istmt->privileges = ACL_ALL_RIGHTS_DATABASE;
02045
02046 relation = heap_open(DatabaseRelationId, RowExclusiveLock);
02047
02048 foreach(cell, istmt->objects)
02049 {
02050 Oid datId = lfirst_oid(cell);
02051 Form_pg_database pg_database_tuple;
02052 Datum aclDatum;
02053 bool isNull;
02054 AclMode avail_goptions;
02055 AclMode this_privileges;
02056 Acl *old_acl;
02057 Acl *new_acl;
02058 Oid grantorId;
02059 Oid ownerId;
02060 HeapTuple newtuple;
02061 Datum values[Natts_pg_database];
02062 bool nulls[Natts_pg_database];
02063 bool replaces[Natts_pg_database];
02064 int noldmembers;
02065 int nnewmembers;
02066 Oid *oldmembers;
02067 Oid *newmembers;
02068 HeapTuple tuple;
02069
02070 tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(datId));
02071 if (!HeapTupleIsValid(tuple))
02072 elog(ERROR, "cache lookup failed for database %u", datId);
02073
02074 pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
02075
02076
02077
02078
02079
02080 ownerId = pg_database_tuple->datdba;
02081 aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
02082 RelationGetDescr(relation), &isNull);
02083 if (isNull)
02084 {
02085 old_acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
02086
02087 noldmembers = 0;
02088 oldmembers = NULL;
02089 }
02090 else
02091 {
02092 old_acl = DatumGetAclPCopy(aclDatum);
02093
02094 noldmembers = aclmembers(old_acl, &oldmembers);
02095 }
02096
02097
02098 select_best_grantor(GetUserId(), istmt->privileges,
02099 old_acl, ownerId,
02100 &grantorId, &avail_goptions);
02101
02102
02103
02104
02105
02106 this_privileges =
02107 restrict_and_check_grant(istmt->is_grant, avail_goptions,
02108 istmt->all_privs, istmt->privileges,
02109 datId, grantorId, ACL_KIND_DATABASE,
02110 NameStr(pg_database_tuple->datname),
02111 0, NULL);
02112
02113
02114
02115
02116 new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
02117 istmt->grant_option, istmt->behavior,
02118 istmt->grantees, this_privileges,
02119 grantorId, ownerId);
02120
02121
02122
02123
02124
02125 nnewmembers = aclmembers(new_acl, &newmembers);
02126
02127
02128 MemSet(values, 0, sizeof(values));
02129 MemSet(nulls, false, sizeof(nulls));
02130 MemSet(replaces, false, sizeof(replaces));
02131
02132 replaces[Anum_pg_database_datacl - 1] = true;
02133 values[Anum_pg_database_datacl - 1] = PointerGetDatum(new_acl);
02134
02135 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
02136 nulls, replaces);
02137
02138 simple_heap_update(relation, &newtuple->t_self, newtuple);
02139
02140
02141 CatalogUpdateIndexes(relation, newtuple);
02142
02143
02144 updateAclDependencies(DatabaseRelationId, HeapTupleGetOid(tuple), 0,
02145 ownerId,
02146 noldmembers, oldmembers,
02147 nnewmembers, newmembers);
02148
02149 ReleaseSysCache(tuple);
02150
02151 pfree(new_acl);
02152
02153
02154 CommandCounterIncrement();
02155 }
02156
02157 heap_close(relation, RowExclusiveLock);
02158 }
02159
02160 static void
02161 ExecGrant_Fdw(InternalGrant *istmt)
02162 {
02163 Relation relation;
02164 ListCell *cell;
02165
02166 if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
02167 istmt->privileges = ACL_ALL_RIGHTS_FDW;
02168
02169 relation = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
02170
02171 foreach(cell, istmt->objects)
02172 {
02173 Oid fdwid = lfirst_oid(cell);
02174 Form_pg_foreign_data_wrapper pg_fdw_tuple;
02175 Datum aclDatum;
02176 bool isNull;
02177 AclMode avail_goptions;
02178 AclMode this_privileges;
02179 Acl *old_acl;
02180 Acl *new_acl;
02181 Oid grantorId;
02182 Oid ownerId;
02183 HeapTuple tuple;
02184 HeapTuple newtuple;
02185 Datum values[Natts_pg_foreign_data_wrapper];
02186 bool nulls[Natts_pg_foreign_data_wrapper];
02187 bool replaces[Natts_pg_foreign_data_wrapper];
02188 int noldmembers;
02189 int nnewmembers;
02190 Oid *oldmembers;
02191 Oid *newmembers;
02192
02193 tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID,
02194 ObjectIdGetDatum(fdwid));
02195 if (!HeapTupleIsValid(tuple))
02196 elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
02197
02198 pg_fdw_tuple = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
02199
02200
02201
02202
02203
02204 ownerId = pg_fdw_tuple->fdwowner;
02205 aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
02206 Anum_pg_foreign_data_wrapper_fdwacl,
02207 &isNull);
02208 if (isNull)
02209 {
02210 old_acl = acldefault(ACL_OBJECT_FDW, ownerId);
02211
02212 noldmembers = 0;
02213 oldmembers = NULL;
02214 }
02215 else
02216 {
02217 old_acl = DatumGetAclPCopy(aclDatum);
02218
02219 noldmembers = aclmembers(old_acl, &oldmembers);
02220 }
02221
02222
02223 select_best_grantor(GetUserId(), istmt->privileges,
02224 old_acl, ownerId,
02225 &grantorId, &avail_goptions);
02226
02227
02228
02229
02230
02231 this_privileges =
02232 restrict_and_check_grant(istmt->is_grant, avail_goptions,
02233 istmt->all_privs, istmt->privileges,
02234 fdwid, grantorId, ACL_KIND_FDW,
02235 NameStr(pg_fdw_tuple->fdwname),
02236 0, NULL);
02237
02238
02239
02240
02241 new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
02242 istmt->grant_option, istmt->behavior,
02243 istmt->grantees, this_privileges,
02244 grantorId, ownerId);
02245
02246
02247
02248
02249
02250 nnewmembers = aclmembers(new_acl, &newmembers);
02251
02252
02253 MemSet(values, 0, sizeof(values));
02254 MemSet(nulls, false, sizeof(nulls));
02255 MemSet(replaces, false, sizeof(replaces));
02256
02257 replaces[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
02258 values[Anum_pg_foreign_data_wrapper_fdwacl - 1] = PointerGetDatum(new_acl);
02259
02260 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
02261 nulls, replaces);
02262
02263 simple_heap_update(relation, &newtuple->t_self, newtuple);
02264
02265
02266 CatalogUpdateIndexes(relation, newtuple);
02267
02268
02269 updateAclDependencies(ForeignDataWrapperRelationId,
02270 HeapTupleGetOid(tuple), 0,
02271 ownerId,
02272 noldmembers, oldmembers,
02273 nnewmembers, newmembers);
02274
02275 ReleaseSysCache(tuple);
02276
02277 pfree(new_acl);
02278
02279
02280 CommandCounterIncrement();
02281 }
02282
02283 heap_close(relation, RowExclusiveLock);
02284 }
02285
02286 static void
02287 ExecGrant_ForeignServer(InternalGrant *istmt)
02288 {
02289 Relation relation;
02290 ListCell *cell;
02291
02292 if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
02293 istmt->privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
02294
02295 relation = heap_open(ForeignServerRelationId, RowExclusiveLock);
02296
02297 foreach(cell, istmt->objects)
02298 {
02299 Oid srvid = lfirst_oid(cell);
02300 Form_pg_foreign_server pg_server_tuple;
02301 Datum aclDatum;
02302 bool isNull;
02303 AclMode avail_goptions;
02304 AclMode this_privileges;
02305 Acl *old_acl;
02306 Acl *new_acl;
02307 Oid grantorId;
02308 Oid ownerId;
02309 HeapTuple tuple;
02310 HeapTuple newtuple;
02311 Datum values[Natts_pg_foreign_server];
02312 bool nulls[Natts_pg_foreign_server];
02313 bool replaces[Natts_pg_foreign_server];
02314 int noldmembers;
02315 int nnewmembers;
02316 Oid *oldmembers;
02317 Oid *newmembers;
02318
02319 tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srvid));
02320 if (!HeapTupleIsValid(tuple))
02321 elog(ERROR, "cache lookup failed for foreign server %u", srvid);
02322
02323 pg_server_tuple = (Form_pg_foreign_server) GETSTRUCT(tuple);
02324
02325
02326
02327
02328
02329 ownerId = pg_server_tuple->srvowner;
02330 aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
02331 Anum_pg_foreign_server_srvacl,
02332 &isNull);
02333 if (isNull)
02334 {
02335 old_acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
02336
02337 noldmembers = 0;
02338 oldmembers = NULL;
02339 }
02340 else
02341 {
02342 old_acl = DatumGetAclPCopy(aclDatum);
02343
02344 noldmembers = aclmembers(old_acl, &oldmembers);
02345 }
02346
02347
02348 select_best_grantor(GetUserId(), istmt->privileges,
02349 old_acl, ownerId,
02350 &grantorId, &avail_goptions);
02351
02352
02353
02354
02355
02356 this_privileges =
02357 restrict_and_check_grant(istmt->is_grant, avail_goptions,
02358 istmt->all_privs, istmt->privileges,
02359 srvid, grantorId, ACL_KIND_FOREIGN_SERVER,
02360 NameStr(pg_server_tuple->srvname),
02361 0, NULL);
02362
02363
02364
02365
02366 new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
02367 istmt->grant_option, istmt->behavior,
02368 istmt->grantees, this_privileges,
02369 grantorId, ownerId);
02370
02371
02372
02373
02374
02375 nnewmembers = aclmembers(new_acl, &newmembers);
02376
02377
02378 MemSet(values, 0, sizeof(values));
02379 MemSet(nulls, false, sizeof(nulls));
02380 MemSet(replaces, false, sizeof(replaces));
02381
02382 replaces[Anum_pg_foreign_server_srvacl - 1] = true;
02383 values[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(new_acl);
02384
02385 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
02386 nulls, replaces);
02387
02388 simple_heap_update(relation, &newtuple->t_self, newtuple);
02389
02390
02391 CatalogUpdateIndexes(relation, newtuple);
02392
02393
02394 updateAclDependencies(ForeignServerRelationId,
02395 HeapTupleGetOid(tuple), 0,
02396 ownerId,
02397 noldmembers, oldmembers,
02398 nnewmembers, newmembers);
02399
02400 ReleaseSysCache(tuple);
02401
02402 pfree(new_acl);
02403
02404
02405 CommandCounterIncrement();
02406 }
02407
02408 heap_close(relation, RowExclusiveLock);
02409 }
02410
02411 static void
02412 ExecGrant_Function(InternalGrant *istmt)
02413 {
02414 Relation relation;
02415 ListCell *cell;
02416
02417 if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
02418 istmt->privileges = ACL_ALL_RIGHTS_FUNCTION;
02419
02420 relation = heap_open(ProcedureRelationId, RowExclusiveLock);
02421
02422 foreach(cell, istmt->objects)
02423 {
02424 Oid funcId = lfirst_oid(cell);
02425 Form_pg_proc pg_proc_tuple;
02426 Datum aclDatum;
02427 bool isNull;
02428 AclMode avail_goptions;
02429 AclMode this_privileges;
02430 Acl *old_acl;
02431 Acl *new_acl;
02432 Oid grantorId;
02433 Oid ownerId;
02434 HeapTuple tuple;
02435 HeapTuple newtuple;
02436 Datum values[Natts_pg_proc];
02437 bool nulls[Natts_pg_proc];
02438 bool replaces[Natts_pg_proc];
02439 int noldmembers;
02440 int nnewmembers;
02441 Oid *oldmembers;
02442 Oid *newmembers;
02443
02444 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
02445 if (!HeapTupleIsValid(tuple))
02446 elog(ERROR, "cache lookup failed for function %u", funcId);
02447
02448 pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
02449
02450
02451
02452
02453
02454 ownerId = pg_proc_tuple->proowner;
02455 aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
02456 &isNull);
02457 if (isNull)
02458 {
02459 old_acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
02460
02461 noldmembers = 0;
02462 oldmembers = NULL;
02463 }
02464 else
02465 {
02466 old_acl = DatumGetAclPCopy(aclDatum);
02467
02468 noldmembers = aclmembers(old_acl, &oldmembers);
02469 }
02470
02471
02472 select_best_grantor(GetUserId(), istmt->privileges,
02473 old_acl, ownerId,
02474 &grantorId, &avail_goptions);
02475
02476
02477
02478
02479
02480 this_privileges =
02481 restrict_and_check_grant(istmt->is_grant, avail_goptions,
02482 istmt->all_privs, istmt->privileges,
02483 funcId, grantorId, ACL_KIND_PROC,
02484 NameStr(pg_proc_tuple->proname),
02485 0, NULL);
02486
02487
02488
02489
02490 new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
02491 istmt->grant_option, istmt->behavior,
02492 istmt->grantees, this_privileges,
02493 grantorId, ownerId);
02494
02495
02496
02497
02498
02499 nnewmembers = aclmembers(new_acl, &newmembers);
02500
02501
02502 MemSet(values, 0, sizeof(values));
02503 MemSet(nulls, false, sizeof(nulls));
02504 MemSet(replaces, false, sizeof(replaces));
02505
02506 replaces[Anum_pg_proc_proacl - 1] = true;
02507 values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
02508
02509 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
02510 nulls, replaces);
02511
02512 simple_heap_update(relation, &newtuple->t_self, newtuple);
02513
02514
02515 CatalogUpdateIndexes(relation, newtuple);
02516
02517
02518 updateAclDependencies(ProcedureRelationId, funcId, 0,
02519 ownerId,
02520 noldmembers, oldmembers,
02521 nnewmembers, newmembers);
02522
02523 ReleaseSysCache(tuple);
02524
02525 pfree(new_acl);
02526
02527
02528 CommandCounterIncrement();
02529 }
02530
02531 heap_close(relation, RowExclusiveLock);
02532 }
02533
02534 static void
02535 ExecGrant_Language(InternalGrant *istmt)
02536 {
02537 Relation relation;
02538 ListCell *cell;
02539
02540 if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
02541 istmt->privileges = ACL_ALL_RIGHTS_LANGUAGE;
02542
02543 relation = heap_open(LanguageRelationId, RowExclusiveLock);
02544
02545 foreach(cell, istmt->objects)
02546 {
02547 Oid langId = lfirst_oid(cell);
02548 Form_pg_language pg_language_tuple;
02549 Datum aclDatum;
02550 bool isNull;
02551 AclMode avail_goptions;
02552 AclMode this_privileges;
02553 Acl *old_acl;
02554 Acl *new_acl;
02555 Oid grantorId;
02556 Oid ownerId;
02557 HeapTuple tuple;
02558 HeapTuple newtuple;
02559 Datum values[Natts_pg_language];
02560 bool nulls[Natts_pg_language];
02561 bool replaces[Natts_pg_language];
02562 int noldmembers;
02563 int nnewmembers;
02564 Oid *oldmembers;
02565 Oid *newmembers;
02566
02567 tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(langId));
02568 if (!HeapTupleIsValid(tuple))
02569 elog(ERROR, "cache lookup failed for language %u", langId);
02570
02571 pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
02572
02573 if (!pg_language_tuple->lanpltrusted)
02574 ereport(ERROR,
02575 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
02576 errmsg("language \"%s\" is not trusted",
02577 NameStr(pg_language_tuple->lanname)),
02578 errhint("Only superusers can use untrusted languages.")));
02579
02580
02581
02582
02583
02584 ownerId = pg_language_tuple->lanowner;
02585 aclDatum = SysCacheGetAttr(LANGNAME, tuple, Anum_pg_language_lanacl,
02586 &isNull);
02587 if (isNull)
02588 {
02589 old_acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
02590
02591 noldmembers = 0;
02592 oldmembers = NULL;
02593 }
02594 else
02595 {
02596 old_acl = DatumGetAclPCopy(aclDatum);
02597
02598 noldmembers = aclmembers(old_acl, &oldmembers);
02599 }
02600
02601
02602 select_best_grantor(GetUserId(), istmt->privileges,
02603 old_acl, ownerId,
02604 &grantorId, &avail_goptions);
02605
02606
02607
02608
02609
02610 this_privileges =
02611 restrict_and_check_grant(istmt->is_grant, avail_goptions,
02612 istmt->all_privs, istmt->privileges,
02613 langId, grantorId, ACL_KIND_LANGUAGE,
02614 NameStr(pg_language_tuple->lanname),
02615 0, NULL);
02616
02617
02618
02619
02620 new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
02621 istmt->grant_option, istmt->behavior,
02622 istmt->grantees, this_privileges,
02623 grantorId, ownerId);
02624
02625
02626
02627
02628
02629 nnewmembers = aclmembers(new_acl, &newmembers);
02630
02631
02632 MemSet(values, 0, sizeof(values));
02633 MemSet(nulls, false, sizeof(nulls));
02634 MemSet(replaces, false, sizeof(replaces));
02635
02636 replaces[Anum_pg_language_lanacl - 1] = true;
02637 values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
02638
02639 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
02640 nulls, replaces);
02641
02642 simple_heap_update(relation, &newtuple->t_self, newtuple);
02643
02644
02645 CatalogUpdateIndexes(relation, newtuple);
02646
02647
02648 updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple), 0,
02649 ownerId,
02650 noldmembers, oldmembers,
02651 nnewmembers, newmembers);
02652
02653 ReleaseSysCache(tuple);
02654
02655 pfree(new_acl);
02656
02657
02658 CommandCounterIncrement();
02659 }
02660
02661 heap_close(relation, RowExclusiveLock);
02662 }
02663
02664 static void
02665 ExecGrant_Largeobject(InternalGrant *istmt)
02666 {
02667 Relation relation;
02668 ListCell *cell;
02669
02670 if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
02671 istmt->privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
02672
02673 relation = heap_open(LargeObjectMetadataRelationId,
02674 RowExclusiveLock);
02675
02676 foreach(cell, istmt->objects)
02677 {
02678 Oid loid = lfirst_oid(cell);
02679 Form_pg_largeobject_metadata form_lo_meta;
02680 char loname[NAMEDATALEN];
02681 Datum aclDatum;
02682 bool isNull;
02683 AclMode avail_goptions;
02684 AclMode this_privileges;
02685 Acl *old_acl;
02686 Acl *new_acl;
02687 Oid grantorId;
02688 Oid ownerId;
02689 HeapTuple newtuple;
02690 Datum values[Natts_pg_largeobject_metadata];
02691 bool nulls[Natts_pg_largeobject_metadata];
02692 bool replaces[Natts_pg_largeobject_metadata];
02693 int noldmembers;
02694 int nnewmembers;
02695 Oid *oldmembers;
02696 Oid *newmembers;
02697 ScanKeyData entry[1];
02698 SysScanDesc scan;
02699 HeapTuple tuple;
02700
02701
02702 ScanKeyInit(&entry[0],
02703 ObjectIdAttributeNumber,
02704 BTEqualStrategyNumber, F_OIDEQ,
02705 ObjectIdGetDatum(loid));
02706
02707 scan = systable_beginscan(relation,
02708 LargeObjectMetadataOidIndexId, true,
02709 SnapshotNow, 1, entry);
02710
02711 tuple = systable_getnext(scan);
02712 if (!HeapTupleIsValid(tuple))
02713 elog(ERROR, "cache lookup failed for large object %u", loid);
02714
02715 form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
02716
02717
02718
02719
02720
02721 ownerId = form_lo_meta->lomowner;
02722 aclDatum = heap_getattr(tuple,
02723 Anum_pg_largeobject_metadata_lomacl,
02724 RelationGetDescr(relation), &isNull);
02725 if (isNull)
02726 {
02727 old_acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
02728
02729 noldmembers = 0;
02730 oldmembers = NULL;
02731 }
02732 else
02733 {
02734 old_acl = DatumGetAclPCopy(aclDatum);
02735
02736 noldmembers = aclmembers(old_acl, &oldmembers);
02737 }
02738
02739
02740 select_best_grantor(GetUserId(), istmt->privileges,
02741 old_acl, ownerId,
02742 &grantorId, &avail_goptions);
02743
02744
02745
02746
02747
02748 snprintf(loname, sizeof(loname), "large object %u", loid);
02749 this_privileges =
02750 restrict_and_check_grant(istmt->is_grant, avail_goptions,
02751 istmt->all_privs, istmt->privileges,
02752 loid, grantorId, ACL_KIND_LARGEOBJECT,
02753 loname, 0, NULL);
02754
02755
02756
02757
02758 new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
02759 istmt->grant_option, istmt->behavior,
02760 istmt->grantees, this_privileges,
02761 grantorId, ownerId);
02762
02763
02764
02765
02766
02767 nnewmembers = aclmembers(new_acl, &newmembers);
02768
02769
02770 MemSet(values, 0, sizeof(values));
02771 MemSet(nulls, false, sizeof(nulls));
02772 MemSet(replaces, false, sizeof(replaces));
02773
02774 replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
02775 values[Anum_pg_largeobject_metadata_lomacl - 1]
02776 = PointerGetDatum(new_acl);
02777
02778 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
02779 values, nulls, replaces);
02780
02781 simple_heap_update(relation, &newtuple->t_self, newtuple);
02782
02783
02784 CatalogUpdateIndexes(relation, newtuple);
02785
02786
02787 updateAclDependencies(LargeObjectRelationId,
02788 HeapTupleGetOid(tuple), 0,
02789 ownerId,
02790 noldmembers, oldmembers,
02791 nnewmembers, newmembers);
02792
02793 systable_endscan(scan);
02794
02795 pfree(new_acl);
02796
02797
02798 CommandCounterIncrement();
02799 }
02800
02801 heap_close(relation, RowExclusiveLock);
02802 }
02803
02804 static void
02805 ExecGrant_Namespace(InternalGrant *istmt)
02806 {
02807 Relation relation;
02808 ListCell *cell;
02809
02810 if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
02811 istmt->privileges = ACL_ALL_RIGHTS_NAMESPACE;
02812
02813 relation = heap_open(NamespaceRelationId, RowExclusiveLock);
02814
02815 foreach(cell, istmt->objects)
02816 {
02817 Oid nspid = lfirst_oid(cell);
02818 Form_pg_namespace pg_namespace_tuple;
02819 Datum aclDatum;
02820 bool isNull;
02821 AclMode avail_goptions;
02822 AclMode this_privileges;
02823 Acl *old_acl;
02824 Acl *new_acl;
02825 Oid grantorId;
02826 Oid ownerId;
02827 HeapTuple tuple;
02828 HeapTuple newtuple;
02829 Datum values[Natts_pg_namespace];
02830 bool nulls[Natts_pg_namespace];
02831 bool replaces[Natts_pg_namespace];
02832 int noldmembers;
02833 int nnewmembers;
02834 Oid *oldmembers;
02835 Oid *newmembers;
02836
02837 tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
02838 if (!HeapTupleIsValid(tuple))
02839 elog(ERROR, "cache lookup failed for namespace %u", nspid);
02840
02841 pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
02842
02843
02844
02845
02846
02847 ownerId = pg_namespace_tuple->nspowner;
02848 aclDatum = SysCacheGetAttr(NAMESPACENAME, tuple,
02849 Anum_pg_namespace_nspacl,
02850 &isNull);
02851 if (isNull)
02852 {
02853 old_acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
02854
02855 noldmembers = 0;
02856 oldmembers = NULL;
02857 }
02858 else
02859 {
02860 old_acl = DatumGetAclPCopy(aclDatum);
02861
02862 noldmembers = aclmembers(old_acl, &oldmembers);
02863 }
02864
02865
02866 select_best_grantor(GetUserId(), istmt->privileges,
02867 old_acl, ownerId,
02868 &grantorId, &avail_goptions);
02869
02870
02871
02872
02873
02874 this_privileges =
02875 restrict_and_check_grant(istmt->is_grant, avail_goptions,
02876 istmt->all_privs, istmt->privileges,
02877 nspid, grantorId, ACL_KIND_NAMESPACE,
02878 NameStr(pg_namespace_tuple->nspname),
02879 0, NULL);
02880
02881
02882
02883
02884 new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
02885 istmt->grant_option, istmt->behavior,
02886 istmt->grantees, this_privileges,
02887 grantorId, ownerId);
02888
02889
02890
02891
02892
02893 nnewmembers = aclmembers(new_acl, &newmembers);
02894
02895
02896 MemSet(values, 0, sizeof(values));
02897 MemSet(nulls, false, sizeof(nulls));
02898 MemSet(replaces, false, sizeof(replaces));
02899
02900 replaces[Anum_pg_namespace_nspacl - 1] = true;
02901 values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(new_acl);
02902
02903 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
02904 nulls, replaces);
02905
02906 simple_heap_update(relation, &newtuple->t_self, newtuple);
02907
02908
02909 CatalogUpdateIndexes(relation, newtuple);
02910
02911
02912 updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple), 0,
02913 ownerId,
02914 noldmembers, oldmembers,
02915 nnewmembers, newmembers);
02916
02917 ReleaseSysCache(tuple);
02918
02919 pfree(new_acl);
02920
02921
02922 CommandCounterIncrement();
02923 }
02924
02925 heap_close(relation, RowExclusiveLock);
02926 }
02927
02928 static void
02929 ExecGrant_Tablespace(InternalGrant *istmt)
02930 {
02931 Relation relation;
02932 ListCell *cell;
02933
02934 if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
02935 istmt->privileges = ACL_ALL_RIGHTS_TABLESPACE;
02936
02937 relation = heap_open(TableSpaceRelationId, RowExclusiveLock);
02938
02939 foreach(cell, istmt->objects)
02940 {
02941 Oid tblId = lfirst_oid(cell);
02942 Form_pg_tablespace pg_tablespace_tuple;
02943 Datum aclDatum;
02944 bool isNull;
02945 AclMode avail_goptions;
02946 AclMode this_privileges;
02947 Acl *old_acl;
02948 Acl *new_acl;
02949 Oid grantorId;
02950 Oid ownerId;
02951 HeapTuple newtuple;
02952 Datum values[Natts_pg_tablespace];
02953 bool nulls[Natts_pg_tablespace];
02954 bool replaces[Natts_pg_tablespace];
02955 int noldmembers;
02956 int nnewmembers;
02957 Oid *oldmembers;
02958 Oid *newmembers;
02959 HeapTuple tuple;
02960
02961
02962 tuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(tblId));
02963 if (!HeapTupleIsValid(tuple))
02964 elog(ERROR, "cache lookup failed for tablespace %u", tblId);
02965
02966 pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);
02967
02968
02969
02970
02971
02972 ownerId = pg_tablespace_tuple->spcowner;
02973 aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl,
02974 RelationGetDescr(relation), &isNull);
02975 if (isNull)
02976 {
02977 old_acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
02978
02979 noldmembers = 0;
02980 oldmembers = NULL;
02981 }
02982 else
02983 {
02984 old_acl = DatumGetAclPCopy(aclDatum);
02985
02986 noldmembers = aclmembers(old_acl, &oldmembers);
02987 }
02988
02989
02990 select_best_grantor(GetUserId(), istmt->privileges,
02991 old_acl, ownerId,
02992 &grantorId, &avail_goptions);
02993
02994
02995
02996
02997
02998 this_privileges =
02999 restrict_and_check_grant(istmt->is_grant, avail_goptions,
03000 istmt->all_privs, istmt->privileges,
03001 tblId, grantorId, ACL_KIND_TABLESPACE,
03002 NameStr(pg_tablespace_tuple->spcname),
03003 0, NULL);
03004
03005
03006
03007
03008 new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
03009 istmt->grant_option, istmt->behavior,
03010 istmt->grantees, this_privileges,
03011 grantorId, ownerId);
03012
03013
03014
03015
03016
03017 nnewmembers = aclmembers(new_acl, &newmembers);
03018
03019
03020 MemSet(values, 0, sizeof(values));
03021 MemSet(nulls, false, sizeof(nulls));
03022 MemSet(replaces, false, sizeof(replaces));
03023
03024 replaces[Anum_pg_tablespace_spcacl - 1] = true;
03025 values[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(new_acl);
03026
03027 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
03028 nulls, replaces);
03029
03030 simple_heap_update(relation, &newtuple->t_self, newtuple);
03031
03032
03033 CatalogUpdateIndexes(relation, newtuple);
03034
03035
03036 updateAclDependencies(TableSpaceRelationId, tblId, 0,
03037 ownerId,
03038 noldmembers, oldmembers,
03039 nnewmembers, newmembers);
03040
03041 ReleaseSysCache(tuple);
03042 pfree(new_acl);
03043
03044
03045 CommandCounterIncrement();
03046 }
03047
03048 heap_close(relation, RowExclusiveLock);
03049 }
03050
03051 static void
03052 ExecGrant_Type(InternalGrant *istmt)
03053 {
03054 Relation relation;
03055 ListCell *cell;
03056
03057 if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
03058 istmt->privileges = ACL_ALL_RIGHTS_TYPE;
03059
03060 relation = heap_open(TypeRelationId, RowExclusiveLock);
03061
03062 foreach(cell, istmt->objects)
03063 {
03064 Oid typId = lfirst_oid(cell);
03065 Form_pg_type pg_type_tuple;
03066 Datum aclDatum;
03067 bool isNull;
03068 AclMode avail_goptions;
03069 AclMode this_privileges;
03070 Acl *old_acl;
03071 Acl *new_acl;
03072 Oid grantorId;
03073 Oid ownerId;
03074 HeapTuple newtuple;
03075 Datum values[Natts_pg_type];
03076 bool nulls[Natts_pg_type];
03077 bool replaces[Natts_pg_type];
03078 int noldmembers;
03079 int nnewmembers;
03080 Oid *oldmembers;
03081 Oid *newmembers;
03082 HeapTuple tuple;
03083
03084
03085 tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typId));
03086 if (!HeapTupleIsValid(tuple))
03087 elog(ERROR, "cache lookup failed for type %u", typId);
03088
03089 pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
03090
03091 if (pg_type_tuple->typelem != 0 && pg_type_tuple->typlen == -1)
03092 ereport(ERROR,
03093 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
03094 errmsg("cannot set privileges of array types"),
03095 errhint("Set the privileges of the element type instead.")));
03096
03097
03098 if (istmt->objtype == ACL_OBJECT_DOMAIN &&
03099 pg_type_tuple->typtype != TYPTYPE_DOMAIN)
03100 ereport(ERROR,
03101 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
03102 errmsg("\"%s\" is not a domain",
03103 NameStr(pg_type_tuple->typname))));
03104
03105
03106
03107
03108
03109 ownerId = pg_type_tuple->typowner;
03110 aclDatum = heap_getattr(tuple, Anum_pg_type_typacl,
03111 RelationGetDescr(relation), &isNull);
03112 if (isNull)
03113 {
03114 old_acl = acldefault(istmt->objtype, ownerId);
03115
03116 noldmembers = 0;
03117 oldmembers = NULL;
03118 }
03119 else
03120 {
03121 old_acl = DatumGetAclPCopy(aclDatum);
03122
03123 noldmembers = aclmembers(old_acl, &oldmembers);
03124 }
03125
03126
03127 select_best_grantor(GetUserId(), istmt->privileges,
03128 old_acl, ownerId,
03129 &grantorId, &avail_goptions);
03130
03131
03132
03133
03134
03135 this_privileges =
03136 restrict_and_check_grant(istmt->is_grant, avail_goptions,
03137 istmt->all_privs, istmt->privileges,
03138 typId, grantorId, ACL_KIND_TYPE,
03139 NameStr(pg_type_tuple->typname),
03140 0, NULL);
03141
03142
03143
03144
03145 new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
03146 istmt->grant_option, istmt->behavior,
03147 istmt->grantees, this_privileges,
03148 grantorId, ownerId);
03149
03150
03151
03152
03153
03154 nnewmembers = aclmembers(new_acl, &newmembers);
03155
03156
03157 MemSet(values, 0, sizeof(values));
03158 MemSet(nulls, false, sizeof(nulls));
03159 MemSet(replaces, false, sizeof(replaces));
03160
03161 replaces[Anum_pg_type_typacl - 1] = true;
03162 values[Anum_pg_type_typacl - 1] = PointerGetDatum(new_acl);
03163
03164 newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
03165 nulls, replaces);
03166
03167 simple_heap_update(relation, &newtuple->t_self, newtuple);
03168
03169
03170 CatalogUpdateIndexes(relation, newtuple);
03171
03172
03173 updateAclDependencies(TypeRelationId, typId, 0,
03174 ownerId,
03175 noldmembers, oldmembers,
03176 nnewmembers, newmembers);
03177
03178 ReleaseSysCache(tuple);
03179 pfree(new_acl);
03180
03181
03182 CommandCounterIncrement();
03183 }
03184
03185 heap_close(relation, RowExclusiveLock);
03186 }
03187
03188
03189 static AclMode
03190 string_to_privilege(const char *privname)
03191 {
03192 if (strcmp(privname, "insert") == 0)
03193 return ACL_INSERT;
03194 if (strcmp(privname, "select") == 0)
03195 return ACL_SELECT;
03196 if (strcmp(privname, "update") == 0)
03197 return ACL_UPDATE;
03198 if (strcmp(privname, "delete") == 0)
03199 return ACL_DELETE;
03200 if (strcmp(privname, "truncate") == 0)
03201 return ACL_TRUNCATE;
03202 if (strcmp(privname, "references") == 0)
03203 return ACL_REFERENCES;
03204 if (strcmp(privname, "trigger") == 0)
03205 return ACL_TRIGGER;
03206 if (strcmp(privname, "execute") == 0)
03207 return ACL_EXECUTE;
03208 if (strcmp(privname, "usage") == 0)
03209 return ACL_USAGE;
03210 if (strcmp(privname, "create") == 0)
03211 return ACL_CREATE;
03212 if (strcmp(privname, "temporary") == 0)
03213 return ACL_CREATE_TEMP;
03214 if (strcmp(privname, "temp") == 0)
03215 return ACL_CREATE_TEMP;
03216 if (strcmp(privname, "connect") == 0)
03217 return ACL_CONNECT;
03218 if (strcmp(privname, "rule") == 0)
03219 return 0;
03220 ereport(ERROR,
03221 (errcode(ERRCODE_SYNTAX_ERROR),
03222 errmsg("unrecognized privilege type \"%s\"", privname)));
03223 return 0;
03224 }
03225
03226 static const char *
03227 privilege_to_string(AclMode privilege)
03228 {
03229 switch (privilege)
03230 {
03231 case ACL_INSERT:
03232 return "INSERT";
03233 case ACL_SELECT:
03234 return "SELECT";
03235 case ACL_UPDATE:
03236 return "UPDATE";
03237 case ACL_DELETE:
03238 return "DELETE";
03239 case ACL_TRUNCATE:
03240 return "TRUNCATE";
03241 case ACL_REFERENCES:
03242 return "REFERENCES";
03243 case ACL_TRIGGER:
03244 return "TRIGGER";
03245 case ACL_EXECUTE:
03246 return "EXECUTE";
03247 case ACL_USAGE:
03248 return "USAGE";
03249 case ACL_CREATE:
03250 return "CREATE";
03251 case ACL_CREATE_TEMP:
03252 return "TEMP";
03253 case ACL_CONNECT:
03254 return "CONNECT";
03255 default:
03256 elog(ERROR, "unrecognized privilege: %d", (int) privilege);
03257 }
03258 return NULL;
03259 }
03260
03261
03262
03263
03264
03265
03266
03267
03268 static const char *const no_priv_msg[MAX_ACL_KIND] =
03269 {
03270
03271 gettext_noop("permission denied for column %s"),
03272
03273 gettext_noop("permission denied for relation %s"),
03274
03275 gettext_noop("permission denied for sequence %s"),
03276
03277 gettext_noop("permission denied for database %s"),
03278
03279 gettext_noop("permission denied for function %s"),
03280
03281 gettext_noop("permission denied for operator %s"),
03282
03283 gettext_noop("permission denied for type %s"),
03284
03285 gettext_noop("permission denied for language %s"),
03286
03287 gettext_noop("permission denied for large object %s"),
03288
03289 gettext_noop("permission denied for schema %s"),
03290
03291 gettext_noop("permission denied for operator class %s"),
03292
03293 gettext_noop("permission denied for operator family %s"),
03294
03295 gettext_noop("permission denied for collation %s"),
03296
03297 gettext_noop("permission denied for conversion %s"),
03298
03299 gettext_noop("permission denied for tablespace %s"),
03300
03301 gettext_noop("permission denied for text search dictionary %s"),
03302
03303 gettext_noop("permission denied for text search configuration %s"),
03304
03305 gettext_noop("permission denied for foreign-data wrapper %s"),
03306
03307 gettext_noop("permission denied for foreign server %s"),
03308
03309 gettext_noop("permission denied for event trigger %s"),
03310
03311 gettext_noop("permission denied for extension %s"),
03312 };
03313
03314 static const char *const not_owner_msg[MAX_ACL_KIND] =
03315 {
03316
03317 gettext_noop("must be owner of relation %s"),
03318
03319 gettext_noop("must be owner of relation %s"),
03320
03321 gettext_noop("must be owner of sequence %s"),
03322
03323 gettext_noop("must be owner of database %s"),
03324
03325 gettext_noop("must be owner of function %s"),
03326
03327 gettext_noop("must be owner of operator %s"),
03328
03329 gettext_noop("must be owner of type %s"),
03330
03331 gettext_noop("must be owner of language %s"),
03332
03333 gettext_noop("must be owner of large object %s"),
03334
03335 gettext_noop("must be owner of schema %s"),
03336
03337 gettext_noop("must be owner of operator class %s"),
03338
03339 gettext_noop("must be owner of operator family %s"),
03340
03341 gettext_noop("must be owner of collation %s"),
03342
03343 gettext_noop("must be owner of conversion %s"),
03344
03345 gettext_noop("must be owner of tablespace %s"),
03346
03347 gettext_noop("must be owner of text search dictionary %s"),
03348
03349 gettext_noop("must be owner of text search configuration %s"),
03350
03351 gettext_noop("must be owner of foreign-data wrapper %s"),
03352
03353 gettext_noop("must be owner of foreign server %s"),
03354
03355 gettext_noop("must be owner of event trigger %s"),
03356
03357 gettext_noop("must be owner of extension %s"),
03358 };
03359
03360
03361 void
03362 aclcheck_error(AclResult aclerr, AclObjectKind objectkind,
03363 const char *objectname)
03364 {
03365 switch (aclerr)
03366 {
03367 case ACLCHECK_OK:
03368
03369 break;
03370 case ACLCHECK_NO_PRIV:
03371 ereport(ERROR,
03372 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
03373 errmsg(no_priv_msg[objectkind], objectname)));
03374 break;
03375 case ACLCHECK_NOT_OWNER:
03376 ereport(ERROR,
03377 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
03378 errmsg(not_owner_msg[objectkind], objectname)));
03379 break;
03380 default:
03381 elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
03382 break;
03383 }
03384 }
03385
03386
03387 void
03388 aclcheck_error_col(AclResult aclerr, AclObjectKind objectkind,
03389 const char *objectname, const char *colname)
03390 {
03391 switch (aclerr)
03392 {
03393 case ACLCHECK_OK:
03394
03395 break;
03396 case ACLCHECK_NO_PRIV:
03397 ereport(ERROR,
03398 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
03399 errmsg("permission denied for column \"%s\" of relation \"%s\"",
03400 colname, objectname)));
03401 break;
03402 case ACLCHECK_NOT_OWNER:
03403
03404 ereport(ERROR,
03405 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
03406 errmsg(not_owner_msg[objectkind], objectname)));
03407 break;
03408 default:
03409 elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
03410 break;
03411 }
03412 }
03413
03414
03415
03416
03417
03418
03419 void
03420 aclcheck_error_type(AclResult aclerr, Oid typeOid)
03421 {
03422 Oid element_type = get_element_type(typeOid);
03423
03424 aclcheck_error(aclerr, ACL_KIND_TYPE, format_type_be(element_type ? element_type : typeOid));
03425 }
03426
03427
03428
03429 static bool
03430 has_rolcatupdate(Oid roleid)
03431 {
03432 bool rolcatupdate;
03433 HeapTuple tuple;
03434
03435 tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
03436 if (!HeapTupleIsValid(tuple))
03437 ereport(ERROR,
03438 (errcode(ERRCODE_UNDEFINED_OBJECT),
03439 errmsg("role with OID %u does not exist", roleid)));
03440
03441 rolcatupdate = ((Form_pg_authid) GETSTRUCT(tuple))->rolcatupdate;
03442
03443 ReleaseSysCache(tuple);
03444
03445 return rolcatupdate;
03446 }
03447
03448
03449
03450
03451 static AclMode
03452 pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum, Oid roleid,
03453 AclMode mask, AclMaskHow how)
03454 {
03455 switch (objkind)
03456 {
03457 case ACL_KIND_COLUMN:
03458 return
03459 pg_class_aclmask(table_oid, roleid, mask, how) |
03460 pg_attribute_aclmask(table_oid, attnum, roleid, mask, how);
03461 case ACL_KIND_CLASS:
03462 case ACL_KIND_SEQUENCE:
03463 return pg_class_aclmask(table_oid, roleid, mask, how);
03464 case ACL_KIND_DATABASE:
03465 return pg_database_aclmask(table_oid, roleid, mask, how);
03466 case ACL_KIND_PROC:
03467 return pg_proc_aclmask(table_oid, roleid, mask, how);
03468 case ACL_KIND_LANGUAGE:
03469 return pg_language_aclmask(table_oid, roleid, mask, how);
03470 case ACL_KIND_LARGEOBJECT:
03471 return pg_largeobject_aclmask_snapshot(table_oid, roleid,
03472 mask, how, SnapshotNow);
03473 case ACL_KIND_NAMESPACE:
03474 return pg_namespace_aclmask(table_oid, roleid, mask, how);
03475 case ACL_KIND_TABLESPACE:
03476 return pg_tablespace_aclmask(table_oid, roleid, mask, how);
03477 case ACL_KIND_FDW:
03478 return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
03479 case ACL_KIND_FOREIGN_SERVER:
03480 return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
03481 case ACL_KIND_EVENT_TRIGGER:
03482 elog(ERROR, "grantable rights not supported for event triggers");
03483
03484 return ACL_NO_RIGHTS;
03485 case ACL_KIND_TYPE:
03486 return pg_type_aclmask(table_oid, roleid, mask, how);
03487 default:
03488 elog(ERROR, "unrecognized objkind: %d",
03489 (int) objkind);
03490
03491 return ACL_NO_RIGHTS;
03492 }
03493 }
03494
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515 AclMode
03516 pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid,
03517 AclMode mask, AclMaskHow how)
03518 {
03519 AclMode result;
03520 HeapTuple classTuple;
03521 HeapTuple attTuple;
03522 Form_pg_class classForm;
03523 Form_pg_attribute attributeForm;
03524 Datum aclDatum;
03525 bool isNull;
03526 Acl *acl;
03527 Oid ownerId;
03528
03529
03530
03531
03532 attTuple = SearchSysCache2(ATTNUM,
03533 ObjectIdGetDatum(table_oid),
03534 Int16GetDatum(attnum));
03535 if (!HeapTupleIsValid(attTuple))
03536 ereport(ERROR,
03537 (errcode(ERRCODE_UNDEFINED_COLUMN),
03538 errmsg("attribute %d of relation with OID %u does not exist",
03539 attnum, table_oid)));
03540 attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
03541
03542
03543 if (attributeForm->attisdropped)
03544 ereport(ERROR,
03545 (errcode(ERRCODE_UNDEFINED_COLUMN),
03546 errmsg("attribute %d of relation with OID %u does not exist",
03547 attnum, table_oid)));
03548
03549 aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
03550 &isNull);
03551
03552
03553
03554
03555
03556
03557 if (isNull)
03558 {
03559 ReleaseSysCache(attTuple);
03560 return 0;
03561 }
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571 classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
03572 if (!HeapTupleIsValid(classTuple))
03573 {
03574 ReleaseSysCache(attTuple);
03575 return 0;
03576 }
03577 classForm = (Form_pg_class) GETSTRUCT(classTuple);
03578
03579 ownerId = classForm->relowner;
03580
03581 ReleaseSysCache(classTuple);
03582
03583
03584 acl = DatumGetAclP(aclDatum);
03585
03586 result = aclmask(acl, roleid, ownerId, mask, how);
03587
03588
03589 if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
03590 pfree(acl);
03591
03592 ReleaseSysCache(attTuple);
03593
03594 return result;
03595 }
03596
03597
03598
03599
03600 AclMode
03601 pg_class_aclmask(Oid table_oid, Oid roleid,
03602 AclMode mask, AclMaskHow how)
03603 {
03604 AclMode result;
03605 HeapTuple tuple;
03606 Form_pg_class classForm;
03607 Datum aclDatum;
03608 bool isNull;
03609 Acl *acl;
03610 Oid ownerId;
03611
03612
03613
03614
03615 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
03616 if (!HeapTupleIsValid(tuple))
03617 ereport(ERROR,
03618 (errcode(ERRCODE_UNDEFINED_TABLE),
03619 errmsg("relation with OID %u does not exist",
03620 table_oid)));
03621 classForm = (Form_pg_class) GETSTRUCT(tuple);
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632 if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
03633 IsSystemClass(classForm) &&
03634 classForm->relkind != RELKIND_VIEW &&
03635 !has_rolcatupdate(roleid) &&
03636 !allowSystemTableMods)
03637 {
03638 #ifdef ACLDEBUG
03639 elog(DEBUG2, "permission denied for system catalog update");
03640 #endif
03641 mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE);
03642 }
03643
03644
03645
03646
03647 if (superuser_arg(roleid))
03648 {
03649 #ifdef ACLDEBUG
03650 elog(DEBUG2, "OID %u is superuser, home free", roleid);
03651 #endif
03652 ReleaseSysCache(tuple);
03653 return mask;
03654 }
03655
03656
03657
03658
03659 ownerId = classForm->relowner;
03660
03661 aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
03662 &isNull);
03663 if (isNull)
03664 {
03665
03666 switch (classForm->relkind)
03667 {
03668 case RELKIND_SEQUENCE:
03669 acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
03670 break;
03671 default:
03672 acl = acldefault(ACL_OBJECT_RELATION, ownerId);
03673 break;
03674 }
03675 aclDatum = (Datum) 0;
03676 }
03677 else
03678 {
03679
03680 acl = DatumGetAclP(aclDatum);
03681 }
03682
03683 result = aclmask(acl, roleid, ownerId, mask, how);
03684
03685
03686 if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
03687 pfree(acl);
03688
03689 ReleaseSysCache(tuple);
03690
03691 return result;
03692 }
03693
03694
03695
03696
03697 AclMode
03698 pg_database_aclmask(Oid db_oid, Oid roleid,
03699 AclMode mask, AclMaskHow how)
03700 {
03701 AclMode result;
03702 HeapTuple tuple;
03703 Datum aclDatum;
03704 bool isNull;
03705 Acl *acl;
03706 Oid ownerId;
03707
03708
03709 if (superuser_arg(roleid))
03710 return mask;
03711
03712
03713
03714
03715 tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
03716 if (!HeapTupleIsValid(tuple))
03717 ereport(ERROR,
03718 (errcode(ERRCODE_UNDEFINED_DATABASE),
03719 errmsg("database with OID %u does not exist", db_oid)));
03720
03721 ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
03722
03723 aclDatum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datacl,
03724 &isNull);
03725 if (isNull)
03726 {
03727
03728 acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
03729 aclDatum = (Datum) 0;
03730 }
03731 else
03732 {
03733
03734 acl = DatumGetAclP(aclDatum);
03735 }
03736
03737 result = aclmask(acl, roleid, ownerId, mask, how);
03738
03739
03740 if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
03741 pfree(acl);
03742
03743 ReleaseSysCache(tuple);
03744
03745 return result;
03746 }
03747
03748
03749
03750
03751 AclMode
03752 pg_proc_aclmask(Oid proc_oid, Oid roleid,
03753 AclMode mask, AclMaskHow how)
03754 {
03755 AclMode result;
03756 HeapTuple tuple;
03757 Datum aclDatum;
03758 bool isNull;
03759 Acl *acl;
03760 Oid ownerId;
03761
03762
03763 if (superuser_arg(roleid))
03764 return mask;
03765
03766
03767
03768
03769 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
03770 if (!HeapTupleIsValid(tuple))
03771 ereport(ERROR,
03772 (errcode(ERRCODE_UNDEFINED_FUNCTION),
03773 errmsg("function with OID %u does not exist", proc_oid)));
03774
03775 ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
03776
03777 aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
03778 &isNull);
03779 if (isNull)
03780 {
03781
03782 acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
03783 aclDatum = (Datum) 0;
03784 }
03785 else
03786 {
03787
03788 acl = DatumGetAclP(aclDatum);
03789 }
03790
03791 result = aclmask(acl, roleid, ownerId, mask, how);
03792
03793
03794 if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
03795 pfree(acl);
03796
03797 ReleaseSysCache(tuple);
03798
03799 return result;
03800 }
03801
03802
03803
03804
03805 AclMode
03806 pg_language_aclmask(Oid lang_oid, Oid roleid,
03807 AclMode mask, AclMaskHow how)
03808 {
03809 AclMode result;
03810 HeapTuple tuple;
03811 Datum aclDatum;
03812 bool isNull;
03813 Acl *acl;
03814 Oid ownerId;
03815
03816
03817 if (superuser_arg(roleid))
03818 return mask;
03819
03820
03821
03822
03823 tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lang_oid));
03824 if (!HeapTupleIsValid(tuple))
03825 ereport(ERROR,
03826 (errcode(ERRCODE_UNDEFINED_OBJECT),
03827 errmsg("language with OID %u does not exist", lang_oid)));
03828
03829 ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
03830
03831 aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
03832 &isNull);
03833 if (isNull)
03834 {
03835
03836 acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
03837 aclDatum = (Datum) 0;
03838 }
03839 else
03840 {
03841
03842 acl = DatumGetAclP(aclDatum);
03843 }
03844
03845 result = aclmask(acl, roleid, ownerId, mask, how);
03846
03847
03848 if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
03849 pfree(acl);
03850
03851 ReleaseSysCache(tuple);
03852
03853 return result;
03854 }
03855
03856
03857
03858
03859
03860
03861
03862
03863
03864
03865 AclMode
03866 pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
03867 AclMode mask, AclMaskHow how,
03868 Snapshot snapshot)
03869 {
03870 AclMode result;
03871 Relation pg_lo_meta;
03872 ScanKeyData entry[1];
03873 SysScanDesc scan;
03874 HeapTuple tuple;
03875 Datum aclDatum;
03876 bool isNull;
03877 Acl *acl;
03878 Oid ownerId;
03879
03880
03881 if (superuser_arg(roleid))
03882 return mask;
03883
03884
03885
03886
03887 pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
03888 AccessShareLock);
03889
03890 ScanKeyInit(&entry[0],
03891 ObjectIdAttributeNumber,
03892 BTEqualStrategyNumber, F_OIDEQ,
03893 ObjectIdGetDatum(lobj_oid));
03894
03895 scan = systable_beginscan(pg_lo_meta,
03896 LargeObjectMetadataOidIndexId, true,
03897 snapshot, 1, entry);
03898
03899 tuple = systable_getnext(scan);
03900 if (!HeapTupleIsValid(tuple))
03901 ereport(ERROR,
03902 (errcode(ERRCODE_UNDEFINED_OBJECT),
03903 errmsg("large object %u does not exist", lobj_oid)));
03904
03905 ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
03906
03907 aclDatum = heap_getattr(tuple, Anum_pg_largeobject_metadata_lomacl,
03908 RelationGetDescr(pg_lo_meta), &isNull);
03909
03910 if (isNull)
03911 {
03912
03913 acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
03914 aclDatum = (Datum) 0;
03915 }
03916 else
03917 {
03918
03919 acl = DatumGetAclP(aclDatum);
03920 }
03921
03922 result = aclmask(acl, roleid, ownerId, mask, how);
03923
03924
03925 if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
03926 pfree(acl);
03927
03928 systable_endscan(scan);
03929
03930 heap_close(pg_lo_meta, AccessShareLock);
03931
03932 return result;
03933 }
03934
03935
03936
03937
03938 AclMode
03939 pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
03940 AclMode mask, AclMaskHow how)
03941 {
03942 AclMode result;
03943 HeapTuple tuple;
03944 Datum aclDatum;
03945 bool isNull;
03946 Acl *acl;
03947 Oid ownerId;
03948
03949
03950 if (superuser_arg(roleid))
03951 return mask;
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964
03965
03966
03967
03968
03969
03970
03971
03972 if (isTempNamespace(nsp_oid))
03973 {
03974 if (pg_database_aclcheck(MyDatabaseId, roleid,
03975 ACL_CREATE_TEMP) == ACLCHECK_OK)
03976 return mask & ACL_ALL_RIGHTS_NAMESPACE;
03977 else
03978 return mask & ACL_USAGE;
03979 }
03980
03981
03982
03983
03984 tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
03985 if (!HeapTupleIsValid(tuple))
03986 ereport(ERROR,
03987 (errcode(ERRCODE_UNDEFINED_SCHEMA),
03988 errmsg("schema with OID %u does not exist", nsp_oid)));
03989
03990 ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
03991
03992 aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspacl,
03993 &isNull);
03994 if (isNull)
03995 {
03996
03997 acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
03998 aclDatum = (Datum) 0;
03999 }
04000 else
04001 {
04002
04003 acl = DatumGetAclP(aclDatum);
04004 }
04005
04006 result = aclmask(acl, roleid, ownerId, mask, how);
04007
04008
04009 if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
04010 pfree(acl);
04011
04012 ReleaseSysCache(tuple);
04013
04014 return result;
04015 }
04016
04017
04018
04019
04020 AclMode
04021 pg_tablespace_aclmask(Oid spc_oid, Oid roleid,
04022 AclMode mask, AclMaskHow how)
04023 {
04024 AclMode result;
04025 HeapTuple tuple;
04026 Datum aclDatum;
04027 bool isNull;
04028 Acl *acl;
04029 Oid ownerId;
04030
04031
04032 if (superuser_arg(roleid))
04033 return mask;
04034
04035
04036
04037
04038 tuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
04039 if (!HeapTupleIsValid(tuple))
04040 ereport(ERROR,
04041 (errcode(ERRCODE_UNDEFINED_OBJECT),
04042 errmsg("tablespace with OID %u does not exist", spc_oid)));
04043
04044 ownerId = ((Form_pg_tablespace) GETSTRUCT(tuple))->spcowner;
04045
04046 aclDatum = SysCacheGetAttr(TABLESPACEOID, tuple,
04047 Anum_pg_tablespace_spcacl,
04048 &isNull);
04049
04050 if (isNull)
04051 {
04052
04053 acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
04054 aclDatum = (Datum) 0;
04055 }
04056 else
04057 {
04058
04059 acl = DatumGetAclP(aclDatum);
04060 }
04061
04062 result = aclmask(acl, roleid, ownerId, mask, how);
04063
04064
04065 if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
04066 pfree(acl);
04067
04068 ReleaseSysCache(tuple);
04069
04070 return result;
04071 }
04072
04073
04074
04075
04076
04077 AclMode
04078 pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid,
04079 AclMode mask, AclMaskHow how)
04080 {
04081 AclMode result;
04082 HeapTuple tuple;
04083 Datum aclDatum;
04084 bool isNull;
04085 Acl *acl;
04086 Oid ownerId;
04087
04088 Form_pg_foreign_data_wrapper fdwForm;
04089
04090
04091 if (superuser_arg(roleid))
04092 return mask;
04093
04094
04095
04096
04097 tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(fdw_oid));
04098 if (!HeapTupleIsValid(tuple))
04099 ereport(ERROR,
04100 (errmsg("foreign-data wrapper with OID %u does not exist",
04101 fdw_oid)));
04102 fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
04103
04104
04105
04106
04107 ownerId = fdwForm->fdwowner;
04108
04109 aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
04110 Anum_pg_foreign_data_wrapper_fdwacl, &isNull);
04111 if (isNull)
04112 {
04113
04114 acl = acldefault(ACL_OBJECT_FDW, ownerId);
04115 aclDatum = (Datum) 0;
04116 }
04117 else
04118 {
04119
04120 acl = DatumGetAclP(aclDatum);
04121 }
04122
04123 result = aclmask(acl, roleid, ownerId, mask, how);
04124
04125
04126 if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
04127 pfree(acl);
04128
04129 ReleaseSysCache(tuple);
04130
04131 return result;
04132 }
04133
04134
04135
04136
04137
04138 AclMode
04139 pg_foreign_server_aclmask(Oid srv_oid, Oid roleid,
04140 AclMode mask, AclMaskHow how)
04141 {
04142 AclMode result;
04143 HeapTuple tuple;
04144 Datum aclDatum;
04145 bool isNull;
04146 Acl *acl;
04147 Oid ownerId;
04148
04149 Form_pg_foreign_server srvForm;
04150
04151
04152 if (superuser_arg(roleid))
04153 return mask;
04154
04155
04156
04157
04158 tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid));
04159 if (!HeapTupleIsValid(tuple))
04160 ereport(ERROR,
04161 (errmsg("foreign server with OID %u does not exist",
04162 srv_oid)));
04163 srvForm = (Form_pg_foreign_server) GETSTRUCT(tuple);
04164
04165
04166
04167
04168 ownerId = srvForm->srvowner;
04169
04170 aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
04171 Anum_pg_foreign_server_srvacl, &isNull);
04172 if (isNull)
04173 {
04174
04175 acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
04176 aclDatum = (Datum) 0;
04177 }
04178 else
04179 {
04180
04181 acl = DatumGetAclP(aclDatum);
04182 }
04183
04184 result = aclmask(acl, roleid, ownerId, mask, how);
04185
04186
04187 if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
04188 pfree(acl);
04189
04190 ReleaseSysCache(tuple);
04191
04192 return result;
04193 }
04194
04195
04196
04197
04198 AclMode
04199 pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
04200 {
04201 AclMode result;
04202 HeapTuple tuple;
04203 Datum aclDatum;
04204 bool isNull;
04205 Acl *acl;
04206 Oid ownerId;
04207
04208 Form_pg_type typeForm;
04209
04210
04211 if (superuser_arg(roleid))
04212 return mask;
04213
04214
04215
04216
04217 tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
04218 if (!HeapTupleIsValid(tuple))
04219 ereport(ERROR,
04220 (errmsg("type with OID %u does not exist",
04221 type_oid)));
04222 typeForm = (Form_pg_type) GETSTRUCT(tuple);
04223
04224
04225 if (typeForm->typelem != 0 && typeForm->typlen == -1)
04226 {
04227 Oid elttype_oid = typeForm->typelem;
04228
04229 ReleaseSysCache(tuple);
04230
04231 tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(elttype_oid));
04232 if (!HeapTupleIsValid(tuple))
04233 ereport(ERROR,
04234 (errmsg("type with OID %u does not exist",
04235 type_oid)));
04236 typeForm = (Form_pg_type) GETSTRUCT(tuple);
04237 }
04238
04239
04240
04241
04242 ownerId = typeForm->typowner;
04243
04244 aclDatum = SysCacheGetAttr(TYPEOID, tuple,
04245 Anum_pg_type_typacl, &isNull);
04246 if (isNull)
04247 {
04248
04249 acl = acldefault(ACL_OBJECT_TYPE, ownerId);
04250 aclDatum = (Datum) 0;
04251 }
04252 else
04253 {
04254
04255 acl = DatumGetAclP(aclDatum);
04256 }
04257
04258 result = aclmask(acl, roleid, ownerId, mask, how);
04259
04260
04261 if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
04262 pfree(acl);
04263
04264 ReleaseSysCache(tuple);
04265
04266 return result;
04267 }
04268
04269
04270
04271
04272
04273
04274
04275
04276
04277
04278
04279 AclResult
04280 pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum,
04281 Oid roleid, AclMode mode)
04282 {
04283 if (pg_attribute_aclmask(table_oid, attnum, roleid, mode, ACLMASK_ANY) != 0)
04284 return ACLCHECK_OK;
04285 else
04286 return ACLCHECK_NO_PRIV;
04287 }
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308 AclResult
04309 pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode,
04310 AclMaskHow how)
04311 {
04312 AclResult result;
04313 HeapTuple classTuple;
04314 Form_pg_class classForm;
04315 AttrNumber nattrs;
04316 AttrNumber curr_att;
04317
04318
04319
04320
04321
04322
04323 classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
04324 if (!HeapTupleIsValid(classTuple))
04325 return ACLCHECK_NO_PRIV;
04326 classForm = (Form_pg_class) GETSTRUCT(classTuple);
04327
04328 nattrs = classForm->relnatts;
04329
04330 ReleaseSysCache(classTuple);
04331
04332
04333
04334
04335
04336 result = ACLCHECK_NO_PRIV;
04337
04338 for (curr_att = 1; curr_att <= nattrs; curr_att++)
04339 {
04340 HeapTuple attTuple;
04341 AclMode attmask;
04342
04343 attTuple = SearchSysCache2(ATTNUM,
04344 ObjectIdGetDatum(table_oid),
04345 Int16GetDatum(curr_att));
04346 if (!HeapTupleIsValid(attTuple))
04347 continue;
04348
04349
04350 if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
04351 {
04352 ReleaseSysCache(attTuple);
04353 continue;
04354 }
04355
04356
04357
04358
04359
04360
04361 if (heap_attisnull(attTuple, Anum_pg_attribute_attacl))
04362 attmask = 0;
04363 else
04364 attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
04365 mode, ACLMASK_ANY);
04366
04367 ReleaseSysCache(attTuple);
04368
04369 if (attmask != 0)
04370 {
04371 result = ACLCHECK_OK;
04372 if (how == ACLMASK_ANY)
04373 break;
04374 }
04375 else
04376 {
04377 result = ACLCHECK_NO_PRIV;
04378 if (how == ACLMASK_ALL)
04379 break;
04380 }
04381 }
04382
04383 return result;
04384 }
04385
04386
04387
04388
04389
04390
04391
04392
04393 AclResult
04394 pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
04395 {
04396 if (pg_class_aclmask(table_oid, roleid, mode, ACLMASK_ANY) != 0)
04397 return ACLCHECK_OK;
04398 else
04399 return ACLCHECK_NO_PRIV;
04400 }
04401
04402
04403
04404
04405 AclResult
04406 pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
04407 {
04408 if (pg_database_aclmask(db_oid, roleid, mode, ACLMASK_ANY) != 0)
04409 return ACLCHECK_OK;
04410 else
04411 return ACLCHECK_NO_PRIV;
04412 }
04413
04414
04415
04416
04417 AclResult
04418 pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
04419 {
04420 if (pg_proc_aclmask(proc_oid, roleid, mode, ACLMASK_ANY) != 0)
04421 return ACLCHECK_OK;
04422 else
04423 return ACLCHECK_NO_PRIV;
04424 }
04425
04426
04427
04428
04429 AclResult
04430 pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
04431 {
04432 if (pg_language_aclmask(lang_oid, roleid, mode, ACLMASK_ANY) != 0)
04433 return ACLCHECK_OK;
04434 else
04435 return ACLCHECK_NO_PRIV;
04436 }
04437
04438
04439
04440
04441 AclResult
04442 pg_largeobject_aclcheck_snapshot(Oid lobj_oid, Oid roleid, AclMode mode,
04443 Snapshot snapshot)
04444 {
04445 if (pg_largeobject_aclmask_snapshot(lobj_oid, roleid, mode,
04446 ACLMASK_ANY, snapshot) != 0)
04447 return ACLCHECK_OK;
04448 else
04449 return ACLCHECK_NO_PRIV;
04450 }
04451
04452
04453
04454
04455 AclResult
04456 pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
04457 {
04458 if (pg_namespace_aclmask(nsp_oid, roleid, mode, ACLMASK_ANY) != 0)
04459 return ACLCHECK_OK;
04460 else
04461 return ACLCHECK_NO_PRIV;
04462 }
04463
04464
04465
04466
04467 AclResult
04468 pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
04469 {
04470 if (pg_tablespace_aclmask(spc_oid, roleid, mode, ACLMASK_ANY) != 0)
04471 return ACLCHECK_OK;
04472 else
04473 return ACLCHECK_NO_PRIV;
04474 }
04475
04476
04477
04478
04479
04480 AclResult
04481 pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode)
04482 {
04483 if (pg_foreign_data_wrapper_aclmask(fdw_oid, roleid, mode, ACLMASK_ANY) != 0)
04484 return ACLCHECK_OK;
04485 else
04486 return ACLCHECK_NO_PRIV;
04487 }
04488
04489
04490
04491
04492
04493 AclResult
04494 pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
04495 {
04496 if (pg_foreign_server_aclmask(srv_oid, roleid, mode, ACLMASK_ANY) != 0)
04497 return ACLCHECK_OK;
04498 else
04499 return ACLCHECK_NO_PRIV;
04500 }
04501
04502
04503
04504
04505 AclResult
04506 pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
04507 {
04508 if (pg_type_aclmask(type_oid, roleid, mode, ACLMASK_ANY) != 0)
04509 return ACLCHECK_OK;
04510 else
04511 return ACLCHECK_NO_PRIV;
04512 }
04513
04514
04515
04516
04517 bool
04518 pg_class_ownercheck(Oid class_oid, Oid roleid)
04519 {
04520 HeapTuple tuple;
04521 Oid ownerId;
04522
04523
04524 if (superuser_arg(roleid))
04525 return true;
04526
04527 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(class_oid));
04528 if (!HeapTupleIsValid(tuple))
04529 ereport(ERROR,
04530 (errcode(ERRCODE_UNDEFINED_TABLE),
04531 errmsg("relation with OID %u does not exist", class_oid)));
04532
04533 ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
04534
04535 ReleaseSysCache(tuple);
04536
04537 return has_privs_of_role(roleid, ownerId);
04538 }
04539
04540
04541
04542
04543 bool
04544 pg_type_ownercheck(Oid type_oid, Oid roleid)
04545 {
04546 HeapTuple tuple;
04547 Oid ownerId;
04548
04549
04550 if (superuser_arg(roleid))
04551 return true;
04552
04553 tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
04554 if (!HeapTupleIsValid(tuple))
04555 ereport(ERROR,
04556 (errcode(ERRCODE_UNDEFINED_OBJECT),
04557 errmsg("type with OID %u does not exist", type_oid)));
04558
04559 ownerId = ((Form_pg_type) GETSTRUCT(tuple))->typowner;
04560
04561 ReleaseSysCache(tuple);
04562
04563 return has_privs_of_role(roleid, ownerId);
04564 }
04565
04566
04567
04568
04569 bool
04570 pg_oper_ownercheck(Oid oper_oid, Oid roleid)
04571 {
04572 HeapTuple tuple;
04573 Oid ownerId;
04574
04575
04576 if (superuser_arg(roleid))
04577 return true;
04578
04579 tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(oper_oid));
04580 if (!HeapTupleIsValid(tuple))
04581 ereport(ERROR,
04582 (errcode(ERRCODE_UNDEFINED_FUNCTION),
04583 errmsg("operator with OID %u does not exist", oper_oid)));
04584
04585 ownerId = ((Form_pg_operator) GETSTRUCT(tuple))->oprowner;
04586
04587 ReleaseSysCache(tuple);
04588
04589 return has_privs_of_role(roleid, ownerId);
04590 }
04591
04592
04593
04594
04595 bool
04596 pg_proc_ownercheck(Oid proc_oid, Oid roleid)
04597 {
04598 HeapTuple tuple;
04599 Oid ownerId;
04600
04601
04602 if (superuser_arg(roleid))
04603 return true;
04604
04605 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
04606 if (!HeapTupleIsValid(tuple))
04607 ereport(ERROR,
04608 (errcode(ERRCODE_UNDEFINED_FUNCTION),
04609 errmsg("function with OID %u does not exist", proc_oid)));
04610
04611 ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
04612
04613 ReleaseSysCache(tuple);
04614
04615 return has_privs_of_role(roleid, ownerId);
04616 }
04617
04618
04619
04620
04621 bool
04622 pg_language_ownercheck(Oid lan_oid, Oid roleid)
04623 {
04624 HeapTuple tuple;
04625 Oid ownerId;
04626
04627
04628 if (superuser_arg(roleid))
04629 return true;
04630
04631 tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lan_oid));
04632 if (!HeapTupleIsValid(tuple))
04633 ereport(ERROR,
04634 (errcode(ERRCODE_UNDEFINED_FUNCTION),
04635 errmsg("language with OID %u does not exist", lan_oid)));
04636
04637 ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
04638
04639 ReleaseSysCache(tuple);
04640
04641 return has_privs_of_role(roleid, ownerId);
04642 }
04643
04644
04645
04646
04647
04648
04649
04650 bool
04651 pg_largeobject_ownercheck(Oid lobj_oid, Oid roleid)
04652 {
04653 Relation pg_lo_meta;
04654 ScanKeyData entry[1];
04655 SysScanDesc scan;
04656 HeapTuple tuple;
04657 Oid ownerId;
04658
04659
04660 if (superuser_arg(roleid))
04661 return true;
04662
04663
04664 pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
04665 AccessShareLock);
04666
04667 ScanKeyInit(&entry[0],
04668 ObjectIdAttributeNumber,
04669 BTEqualStrategyNumber, F_OIDEQ,
04670 ObjectIdGetDatum(lobj_oid));
04671
04672 scan = systable_beginscan(pg_lo_meta,
04673 LargeObjectMetadataOidIndexId, true,
04674 SnapshotNow, 1, entry);
04675
04676 tuple = systable_getnext(scan);
04677 if (!HeapTupleIsValid(tuple))
04678 ereport(ERROR,
04679 (errcode(ERRCODE_UNDEFINED_OBJECT),
04680 errmsg("large object %u does not exist", lobj_oid)));
04681
04682 ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
04683
04684 systable_endscan(scan);
04685 heap_close(pg_lo_meta, AccessShareLock);
04686
04687 return has_privs_of_role(roleid, ownerId);
04688 }
04689
04690
04691
04692
04693 bool
04694 pg_namespace_ownercheck(Oid nsp_oid, Oid roleid)
04695 {
04696 HeapTuple tuple;
04697 Oid ownerId;
04698
04699
04700 if (superuser_arg(roleid))
04701 return true;
04702
04703 tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
04704 if (!HeapTupleIsValid(tuple))
04705 ereport(ERROR,
04706 (errcode(ERRCODE_UNDEFINED_SCHEMA),
04707 errmsg("schema with OID %u does not exist", nsp_oid)));
04708
04709 ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
04710
04711 ReleaseSysCache(tuple);
04712
04713 return has_privs_of_role(roleid, ownerId);
04714 }
04715
04716
04717
04718
04719 bool
04720 pg_tablespace_ownercheck(Oid spc_oid, Oid roleid)
04721 {
04722 HeapTuple spctuple;
04723 Oid spcowner;
04724
04725
04726 if (superuser_arg(roleid))
04727 return true;
04728
04729
04730 spctuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
04731 if (!HeapTupleIsValid(spctuple))
04732 ereport(ERROR,
04733 (errcode(ERRCODE_UNDEFINED_OBJECT),
04734 errmsg("tablespace with OID %u does not exist", spc_oid)));
04735
04736 spcowner = ((Form_pg_tablespace) GETSTRUCT(spctuple))->spcowner;
04737
04738 ReleaseSysCache(spctuple);
04739
04740 return has_privs_of_role(roleid, spcowner);
04741 }
04742
04743
04744
04745
04746 bool
04747 pg_opclass_ownercheck(Oid opc_oid, Oid roleid)
04748 {
04749 HeapTuple tuple;
04750 Oid ownerId;
04751
04752
04753 if (superuser_arg(roleid))
04754 return true;
04755
04756 tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opc_oid));
04757 if (!HeapTupleIsValid(tuple))
04758 ereport(ERROR,
04759 (errcode(ERRCODE_UNDEFINED_OBJECT),
04760 errmsg("operator class with OID %u does not exist",
04761 opc_oid)));
04762
04763 ownerId = ((Form_pg_opclass) GETSTRUCT(tuple))->opcowner;
04764
04765 ReleaseSysCache(tuple);
04766
04767 return has_privs_of_role(roleid, ownerId);
04768 }
04769
04770
04771
04772
04773 bool
04774 pg_opfamily_ownercheck(Oid opf_oid, Oid roleid)
04775 {
04776 HeapTuple tuple;
04777 Oid ownerId;
04778
04779
04780 if (superuser_arg(roleid))
04781 return true;
04782
04783 tuple = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opf_oid));
04784 if (!HeapTupleIsValid(tuple))
04785 ereport(ERROR,
04786 (errcode(ERRCODE_UNDEFINED_OBJECT),
04787 errmsg("operator family with OID %u does not exist",
04788 opf_oid)));
04789
04790 ownerId = ((Form_pg_opfamily) GETSTRUCT(tuple))->opfowner;
04791
04792 ReleaseSysCache(tuple);
04793
04794 return has_privs_of_role(roleid, ownerId);
04795 }
04796
04797
04798
04799
04800 bool
04801 pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid)
04802 {
04803 HeapTuple tuple;
04804 Oid ownerId;
04805
04806
04807 if (superuser_arg(roleid))
04808 return true;
04809
04810 tuple = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dict_oid));
04811 if (!HeapTupleIsValid(tuple))
04812 ereport(ERROR,
04813 (errcode(ERRCODE_UNDEFINED_OBJECT),
04814 errmsg("text search dictionary with OID %u does not exist",
04815 dict_oid)));
04816
04817 ownerId = ((Form_pg_ts_dict) GETSTRUCT(tuple))->dictowner;
04818
04819 ReleaseSysCache(tuple);
04820
04821 return has_privs_of_role(roleid, ownerId);
04822 }
04823
04824
04825
04826
04827 bool
04828 pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid)
04829 {
04830 HeapTuple tuple;
04831 Oid ownerId;
04832
04833
04834 if (superuser_arg(roleid))
04835 return true;
04836
04837 tuple = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfg_oid));
04838 if (!HeapTupleIsValid(tuple))
04839 ereport(ERROR,
04840 (errcode(ERRCODE_UNDEFINED_OBJECT),
04841 errmsg("text search configuration with OID %u does not exist",
04842 cfg_oid)));
04843
04844 ownerId = ((Form_pg_ts_config) GETSTRUCT(tuple))->cfgowner;
04845
04846 ReleaseSysCache(tuple);
04847
04848 return has_privs_of_role(roleid, ownerId);
04849 }
04850
04851
04852
04853
04854 bool
04855 pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid)
04856 {
04857 HeapTuple tuple;
04858 Oid ownerId;
04859
04860
04861 if (superuser_arg(roleid))
04862 return true;
04863
04864 tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(srv_oid));
04865 if (!HeapTupleIsValid(tuple))
04866 ereport(ERROR,
04867 (errcode(ERRCODE_UNDEFINED_OBJECT),
04868 errmsg("foreign-data wrapper with OID %u does not exist",
04869 srv_oid)));
04870
04871 ownerId = ((Form_pg_foreign_data_wrapper) GETSTRUCT(tuple))->fdwowner;
04872
04873 ReleaseSysCache(tuple);
04874
04875 return has_privs_of_role(roleid, ownerId);
04876 }
04877
04878
04879
04880
04881 bool
04882 pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
04883 {
04884 HeapTuple tuple;
04885 Oid ownerId;
04886
04887
04888 if (superuser_arg(roleid))
04889 return true;
04890
04891 tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid));
04892 if (!HeapTupleIsValid(tuple))
04893 ereport(ERROR,
04894 (errcode(ERRCODE_UNDEFINED_OBJECT),
04895 errmsg("foreign server with OID %u does not exist",
04896 srv_oid)));
04897
04898 ownerId = ((Form_pg_foreign_server) GETSTRUCT(tuple))->srvowner;
04899
04900 ReleaseSysCache(tuple);
04901
04902 return has_privs_of_role(roleid, ownerId);
04903 }
04904
04905
04906
04907
04908 bool
04909 pg_event_trigger_ownercheck(Oid et_oid, Oid roleid)
04910 {
04911 HeapTuple tuple;
04912 Oid ownerId;
04913
04914
04915 if (superuser_arg(roleid))
04916 return true;
04917
04918 tuple = SearchSysCache1(EVENTTRIGGEROID, ObjectIdGetDatum(et_oid));
04919 if (!HeapTupleIsValid(tuple))
04920 ereport(ERROR,
04921 (errcode(ERRCODE_UNDEFINED_OBJECT),
04922 errmsg("event trigger with OID %u does not exist",
04923 et_oid)));
04924
04925 ownerId = ((Form_pg_event_trigger) GETSTRUCT(tuple))->evtowner;
04926
04927 ReleaseSysCache(tuple);
04928
04929 return has_privs_of_role(roleid, ownerId);
04930 }
04931
04932
04933
04934
04935 bool
04936 pg_database_ownercheck(Oid db_oid, Oid roleid)
04937 {
04938 HeapTuple tuple;
04939 Oid dba;
04940
04941
04942 if (superuser_arg(roleid))
04943 return true;
04944
04945 tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
04946 if (!HeapTupleIsValid(tuple))
04947 ereport(ERROR,
04948 (errcode(ERRCODE_UNDEFINED_DATABASE),
04949 errmsg("database with OID %u does not exist", db_oid)));
04950
04951 dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
04952
04953 ReleaseSysCache(tuple);
04954
04955 return has_privs_of_role(roleid, dba);
04956 }
04957
04958
04959
04960
04961 bool
04962 pg_collation_ownercheck(Oid coll_oid, Oid roleid)
04963 {
04964 HeapTuple tuple;
04965 Oid ownerId;
04966
04967
04968 if (superuser_arg(roleid))
04969 return true;
04970
04971 tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(coll_oid));
04972 if (!HeapTupleIsValid(tuple))
04973 ereport(ERROR,
04974 (errcode(ERRCODE_UNDEFINED_OBJECT),
04975 errmsg("collation with OID %u does not exist", coll_oid)));
04976
04977 ownerId = ((Form_pg_collation) GETSTRUCT(tuple))->collowner;
04978
04979 ReleaseSysCache(tuple);
04980
04981 return has_privs_of_role(roleid, ownerId);
04982 }
04983
04984
04985
04986
04987 bool
04988 pg_conversion_ownercheck(Oid conv_oid, Oid roleid)
04989 {
04990 HeapTuple tuple;
04991 Oid ownerId;
04992
04993
04994 if (superuser_arg(roleid))
04995 return true;
04996
04997 tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(conv_oid));
04998 if (!HeapTupleIsValid(tuple))
04999 ereport(ERROR,
05000 (errcode(ERRCODE_UNDEFINED_OBJECT),
05001 errmsg("conversion with OID %u does not exist", conv_oid)));
05002
05003 ownerId = ((Form_pg_conversion) GETSTRUCT(tuple))->conowner;
05004
05005 ReleaseSysCache(tuple);
05006
05007 return has_privs_of_role(roleid, ownerId);
05008 }
05009
05010
05011
05012
05013 bool
05014 pg_extension_ownercheck(Oid ext_oid, Oid roleid)
05015 {
05016 Relation pg_extension;
05017 ScanKeyData entry[1];
05018 SysScanDesc scan;
05019 HeapTuple tuple;
05020 Oid ownerId;
05021
05022
05023 if (superuser_arg(roleid))
05024 return true;
05025
05026
05027 pg_extension = heap_open(ExtensionRelationId, AccessShareLock);
05028
05029 ScanKeyInit(&entry[0],
05030 ObjectIdAttributeNumber,
05031 BTEqualStrategyNumber, F_OIDEQ,
05032 ObjectIdGetDatum(ext_oid));
05033
05034 scan = systable_beginscan(pg_extension,
05035 ExtensionOidIndexId, true,
05036 SnapshotNow, 1, entry);
05037
05038 tuple = systable_getnext(scan);
05039 if (!HeapTupleIsValid(tuple))
05040 ereport(ERROR,
05041 (errcode(ERRCODE_UNDEFINED_OBJECT),
05042 errmsg("extension with OID %u does not exist", ext_oid)));
05043
05044 ownerId = ((Form_pg_extension) GETSTRUCT(tuple))->extowner;
05045
05046 systable_endscan(scan);
05047 heap_close(pg_extension, AccessShareLock);
05048
05049 return has_privs_of_role(roleid, ownerId);
05050 }
05051
05052
05053
05054
05055
05056
05057
05058
05059
05060
05061
05062
05063 bool
05064 has_createrole_privilege(Oid roleid)
05065 {
05066 bool result = false;
05067 HeapTuple utup;
05068
05069
05070 if (superuser_arg(roleid))
05071 return true;
05072
05073 utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
05074 if (HeapTupleIsValid(utup))
05075 {
05076 result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
05077 ReleaseSysCache(utup);
05078 }
05079 return result;
05080 }
05081
05082
05083
05084
05085
05086
05087 static Acl *
05088 get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
05089 {
05090 Acl *result = NULL;
05091 HeapTuple tuple;
05092
05093 tuple = SearchSysCache3(DEFACLROLENSPOBJ,
05094 ObjectIdGetDatum(roleId),
05095 ObjectIdGetDatum(nsp_oid),
05096 CharGetDatum(objtype));
05097
05098 if (HeapTupleIsValid(tuple))
05099 {
05100 Datum aclDatum;
05101 bool isNull;
05102
05103 aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
05104 Anum_pg_default_acl_defaclacl,
05105 &isNull);
05106 if (!isNull)
05107 result = DatumGetAclPCopy(aclDatum);
05108 ReleaseSysCache(tuple);
05109 }
05110
05111 return result;
05112 }
05113
05114
05115
05116
05117
05118
05119 Acl *
05120 get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
05121 {
05122 Acl *result;
05123 Acl *glob_acl;
05124 Acl *schema_acl;
05125 Acl *def_acl;
05126 char defaclobjtype;
05127
05128
05129
05130
05131
05132 if (IsBootstrapProcessingMode())
05133 return NULL;
05134
05135
05136 switch (objtype)
05137 {
05138 case ACL_OBJECT_RELATION:
05139 defaclobjtype = DEFACLOBJ_RELATION;
05140 break;
05141
05142 case ACL_OBJECT_SEQUENCE:
05143 defaclobjtype = DEFACLOBJ_SEQUENCE;
05144 break;
05145
05146 case ACL_OBJECT_FUNCTION:
05147 defaclobjtype = DEFACLOBJ_FUNCTION;
05148 break;
05149
05150 case ACL_OBJECT_TYPE:
05151 defaclobjtype = DEFACLOBJ_TYPE;
05152 break;
05153
05154 default:
05155 return NULL;
05156 }
05157
05158
05159 glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
05160 schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
05161
05162
05163 if (glob_acl == NULL && schema_acl == NULL)
05164 return NULL;
05165
05166
05167 def_acl = acldefault(objtype, ownerId);
05168
05169
05170 if (glob_acl == NULL)
05171 glob_acl = def_acl;
05172
05173
05174 result = aclmerge(glob_acl, schema_acl, ownerId);
05175
05176
05177
05178
05179
05180 aclitemsort(result);
05181 aclitemsort(def_acl);
05182 if (aclequal(result, def_acl))
05183 result = NULL;
05184
05185 return result;
05186 }