#include "postgres.h"#include "access/genam.h"#include "access/heapam.h"#include "access/htup_details.h"#include "access/sysattr.h"#include "access/xact.h"#include "catalog/catalog.h"#include "catalog/dependency.h"#include "catalog/indexing.h"#include "catalog/objectaccess.h"#include "catalog/pg_authid.h"#include "catalog/pg_collation.h"#include "catalog/pg_conversion.h"#include "catalog/pg_database.h"#include "catalog/pg_default_acl.h"#include "catalog/pg_event_trigger.h"#include "catalog/pg_extension.h"#include "catalog/pg_foreign_data_wrapper.h"#include "catalog/pg_foreign_server.h"#include "catalog/pg_language.h"#include "catalog/pg_largeobject.h"#include "catalog/pg_largeobject_metadata.h"#include "catalog/pg_namespace.h"#include "catalog/pg_opclass.h"#include "catalog/pg_operator.h"#include "catalog/pg_opfamily.h"#include "catalog/pg_proc.h"#include "catalog/pg_tablespace.h"#include "catalog/pg_type.h"#include "catalog/pg_ts_config.h"#include "catalog/pg_ts_dict.h"#include "commands/dbcommands.h"#include "commands/proclang.h"#include "commands/tablespace.h"#include "foreign/foreign.h"#include "miscadmin.h"#include "nodes/makefuncs.h"#include "parser/parse_func.h"#include "parser/parse_type.h"#include "utils/acl.h"#include "utils/builtins.h"#include "utils/fmgroids.h"#include "utils/lsyscache.h"#include "utils/rel.h"#include "utils/syscache.h"#include "utils/tqual.h"
Go to the source code of this file.
| void aclcheck_error | ( | AclResult | aclerr, | |
| AclObjectKind | objectkind, | |||
| const char * | objectname | |||
| ) |
Definition at line 3362 of file aclchk.c.
References ACLCHECK_NO_PRIV, ACLCHECK_NOT_OWNER, ACLCHECK_OK, elog, ereport, errcode(), errmsg(), and ERROR.
Referenced by aclcheck_error_type(), AlterDatabase(), AlterDatabaseOwner(), AlterDatabaseSet(), AlterEventTrigger(), AlterEventTriggerOwner_internal(), AlterExtensionNamespace(), AlterForeignServer(), AlterForeignServerOwner_internal(), AlterFunction(), AlterObjectNamespace_internal(), AlterObjectOwner_internal(), AlterObjectRename_internal(), AlterOpFamilyAdd(), AlterRoleSet(), AlterSchemaOwner_internal(), AlterSequence(), AlterTableSpaceOptions(), AlterTSConfiguration(), AlterTSDictionary(), AlterTypeOwner(), ATExecChangeOwner(), ATPrepSetStatistics(), ATPrepSetTableSpace(), ATSimplePermissions(), calculate_database_size(), calculate_tablespace_size(), check_object_ownership(), check_temp_tablespaces(), checkFkeyPermissions(), CheckRelationOwnership(), compute_return_type(), create_proc_lang(), CreateConversionCommand(), createdb(), CreateForeignServer(), CreateForeignTable(), CreateFunction(), CreateProceduralLanguage(), CreateSchemaCommand(), CreateTrigger(), currtid_byrelname(), currtid_byreloid(), DefineAggregate(), DefineCollation(), DefineDomain(), DefineEnum(), DefineIndex(), DefineOpClass(), DefineOperator(), DefineOpFamily(), DefineQueryRewrite(), DefineRange(), DefineRelation(), DefineTSConfiguration(), DefineTSDictionary(), DefineType(), dropdb(), DropTableSpace(), EnableDisableRule(), ExecAlterExtensionContentsStmt(), ExecAlterExtensionStmt(), ExecCheckRTPerms(), ExecEvalArrayCoerceExpr(), ExecInitAgg(), ExecInitWindowAgg(), ExecuteDoStmt(), ExecuteTruncate(), findRangeCanonicalFunction(), findRangeSubtypeDiffFunction(), get_connect_string(), get_other_operator(), get_rel_from_relname(), HandleFunctionRequest(), init_fcache(), initialize_peragg(), LockTableRecurse(), lookup_agg_function(), LookupCreationNamespace(), LookupExplicitNamespace(), MergeAttributes(), movedb(), OperatorCreate(), pgrowlocks(), ProcedureCreate(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForLockTable(), RangeVarCallbackForReindexIndex(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackOwnsTable(), RangeVarGetAndCheckCreationNamespace(), ReindexDatabase(), renameatt_check(), RenameDatabase(), RenameSchema(), RenameTableSpace(), restrict_and_check_grant(), SetDefaultACLsInSchemas(), transformTableLikeClause(), truncate_check_rel(), TypeCreate(), and user_mapping_ddl_aclcheck().
{
switch (aclerr)
{
case ACLCHECK_OK:
/* no error, so return to caller */
break;
case ACLCHECK_NO_PRIV:
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg(no_priv_msg[objectkind], objectname)));
break;
case ACLCHECK_NOT_OWNER:
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg(not_owner_msg[objectkind], objectname)));
break;
default:
elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
break;
}
}
| void aclcheck_error_col | ( | AclResult | aclerr, | |
| AclObjectKind | objectkind, | |||
| const char * | objectname, | |||
| const char * | colname | |||
| ) |
Definition at line 3388 of file aclchk.c.
References ACLCHECK_NO_PRIV, ACLCHECK_NOT_OWNER, ACLCHECK_OK, elog, ereport, errcode(), errmsg(), and ERROR.
Referenced by restrict_and_check_grant().
{
switch (aclerr)
{
case ACLCHECK_OK:
/* no error, so return to caller */
break;
case ACLCHECK_NO_PRIV:
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for column \"%s\" of relation \"%s\"",
colname, objectname)));
break;
case ACLCHECK_NOT_OWNER:
/* relation msg is OK since columns don't have separate owners */
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg(not_owner_msg[objectkind], objectname)));
break;
default:
elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
break;
}
}
Definition at line 3420 of file aclchk.c.
References ACL_KIND_TYPE, aclcheck_error(), format_type_be(), and get_element_type().
Referenced by AggregateCreate(), AlterTypeNamespace_oid(), AlterTypeOwner(), ATExecAddColumn(), ATPrepAlterColumnType(), BuildDescForRelation(), check_object_ownership(), checkDomainOwner(), checkEnumOwner(), compute_return_type(), CreateCast(), DefineDomain(), DefineOpClass(), DefineOperator(), DefineRelation(), examine_parameter_list(), and RenameType().
{
Oid element_type = get_element_type(typeOid);
aclcheck_error(aclerr, ACL_KIND_TYPE, format_type_be(element_type ? element_type : typeOid));
}
| void ExecAlterDefaultPrivilegesStmt | ( | AlterDefaultPrivilegesStmt * | stmt | ) |
Definition at line 854 of file aclchk.c.
References ACL_ID_PUBLIC, ACL_OBJECT_FUNCTION, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TYPE, AlterDefaultPrivilegesStmt::action, InternalDefaultACL::all_privs, DefElem::arg, GrantStmt::behavior, InternalDefaultACL::behavior, check_is_member_of_role(), AccessPriv::cols, DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, get_role_oid(), gettext_noop, GetUserId(), GrantStmt::grant_option, InternalDefaultACL::grant_option, GrantStmt::grantees, InternalDefaultACL::grantees, GrantStmt::is_grant, InternalDefaultACL::is_grant, lappend_oid(), lfirst, NIL, NULL, GrantStmt::objtype, InternalDefaultACL::objtype, AlterDefaultPrivilegesStmt::options, AccessPriv::priv_name, privilege_to_string(), InternalDefaultACL::privileges, GrantStmt::privileges, InternalDefaultACL::roleid, PrivGrantee::rolname, SetDefaultACLsInSchemas(), string_to_privilege(), and strVal.
Referenced by ProcessUtilitySlow().
{
GrantStmt *action = stmt->action;
InternalDefaultACL iacls;
ListCell *cell;
List *rolenames = NIL;
List *nspnames = NIL;
DefElem *drolenames = NULL;
DefElem *dnspnames = NULL;
AclMode all_privileges;
const char *errormsg;
/* Deconstruct the "options" part of the statement */
foreach(cell, stmt->options)
{
DefElem *defel = (DefElem *) lfirst(cell);
if (strcmp(defel->defname, "schemas") == 0)
{
if (dnspnames)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
dnspnames = defel;
}
else if (strcmp(defel->defname, "roles") == 0)
{
if (drolenames)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
drolenames = defel;
}
else
elog(ERROR, "option \"%s\" not recognized", defel->defname);
}
if (dnspnames)
nspnames = (List *) dnspnames->arg;
if (drolenames)
rolenames = (List *) drolenames->arg;
/* Prepare the InternalDefaultACL representation of the statement */
/* roleid to be filled below */
/* nspid to be filled in SetDefaultACLsInSchemas */
iacls.is_grant = action->is_grant;
iacls.objtype = action->objtype;
/* all_privs to be filled below */
/* privileges to be filled below */
iacls.grantees = NIL; /* filled below */
iacls.grant_option = action->grant_option;
iacls.behavior = action->behavior;
/*
* Convert the PrivGrantee list into an Oid list. Note that at this point
* we insert an ACL_ID_PUBLIC into the list if an empty role name is
* detected (which is what the grammar uses if PUBLIC is found), so
* downstream there shouldn't be any additional work needed to support
* this case.
*/
foreach(cell, action->grantees)
{
PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);
if (grantee->rolname == NULL)
iacls.grantees = lappend_oid(iacls.grantees, ACL_ID_PUBLIC);
else
iacls.grantees =
lappend_oid(iacls.grantees,
get_role_oid(grantee->rolname, false));
}
/*
* Convert action->privileges, a list of privilege strings, into an
* AclMode bitmask.
*/
switch (action->objtype)
{
case ACL_OBJECT_RELATION:
all_privileges = ACL_ALL_RIGHTS_RELATION;
errormsg = gettext_noop("invalid privilege type %s for relation");
break;
case ACL_OBJECT_SEQUENCE:
all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
errormsg = gettext_noop("invalid privilege type %s for sequence");
break;
case ACL_OBJECT_FUNCTION:
all_privileges = ACL_ALL_RIGHTS_FUNCTION;
errormsg = gettext_noop("invalid privilege type %s for function");
break;
case ACL_OBJECT_TYPE:
all_privileges = ACL_ALL_RIGHTS_TYPE;
errormsg = gettext_noop("invalid privilege type %s for type");
break;
default:
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
(int) action->objtype);
/* keep compiler quiet */
all_privileges = ACL_NO_RIGHTS;
errormsg = NULL;
}
if (action->privileges == NIL)
{
iacls.all_privs = true;
/*
* will be turned into ACL_ALL_RIGHTS_* by the internal routines
* depending on the object type
*/
iacls.privileges = ACL_NO_RIGHTS;
}
else
{
iacls.all_privs = false;
iacls.privileges = ACL_NO_RIGHTS;
foreach(cell, action->privileges)
{
AccessPriv *privnode = (AccessPriv *) lfirst(cell);
AclMode priv;
if (privnode->cols)
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("default privileges cannot be set for columns")));
if (privnode->priv_name == NULL) /* parser mistake? */
elog(ERROR, "AccessPriv node must specify privilege");
priv = string_to_privilege(privnode->priv_name);
if (priv & ~((AclMode) all_privileges))
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg(errormsg, privilege_to_string(priv))));
iacls.privileges |= priv;
}
}
if (rolenames == NIL)
{
/* Set permissions for myself */
iacls.roleid = GetUserId();
SetDefaultACLsInSchemas(&iacls, nspnames);
}
else
{
/* Look up the role OIDs and do permissions checks */
ListCell *rolecell;
foreach(rolecell, rolenames)
{
char *rolename = strVal(lfirst(rolecell));
iacls.roleid = get_role_oid(rolename, false);
/*
* We insist that calling user be a member of each target role. If
* he has that, he could become that role anyway via SET ROLE, so
* FOR ROLE is just a syntactic convenience and doesn't give any
* special privileges.
*/
check_is_member_of_role(GetUserId(), iacls.roleid);
SetDefaultACLsInSchemas(&iacls, nspnames);
}
}
}
| static void ExecGrant_Attribute | ( | InternalGrant * | istmt, | |
| Oid | relOid, | |||
| const char * | relname, | |||
| AttrNumber | attnum, | |||
| Oid | ownerId, | |||
| AclMode | col_privileges, | |||
| Relation | attRelation, | |||
| const Acl * | old_rel_acl | |||
| ) | [static] |
Definition at line 1561 of file aclchk.c.
References ACL_ALL_RIGHTS_COLUMN, ACL_KIND_COLUMN, ACL_NUM, ACL_OBJECT_COLUMN, aclconcat(), acldefault(), aclmembers(), Anum_pg_attribute_attacl, ATTNUM, InternalGrant::behavior, CatalogUpdateIndexes(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum, InternalGrant::is_grant, MemSet, merge_acl_with_grant(), NameStr, ObjectIdGetDatum, pfree(), PointerGetDatum, RelationGetDescr, RelationRelationId, ReleaseSysCache(), restrict_and_check_grant(), SearchSysCache2, select_best_grantor(), simple_heap_update(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.
Referenced by ExecGrant_Relation().
{
HeapTuple attr_tuple;
Form_pg_attribute pg_attribute_tuple;
Acl *old_acl;
Acl *new_acl;
Acl *merged_acl;
Datum aclDatum;
bool isNull;
Oid grantorId;
AclMode avail_goptions;
bool need_update;
HeapTuple newtuple;
Datum values[Natts_pg_attribute];
bool nulls[Natts_pg_attribute];
bool replaces[Natts_pg_attribute];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
attr_tuple = SearchSysCache2(ATTNUM,
ObjectIdGetDatum(relOid),
Int16GetDatum(attnum));
if (!HeapTupleIsValid(attr_tuple))
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
attnum, relOid);
pg_attribute_tuple = (Form_pg_attribute) GETSTRUCT(attr_tuple);
/*
* Get working copy of existing ACL. If there's no ACL, substitute the
* proper default.
*/
aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
&isNull);
if (isNull)
{
old_acl = acldefault(ACL_OBJECT_COLUMN, ownerId);
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
}
else
{
old_acl = DatumGetAclPCopy(aclDatum);
/* Get the roles mentioned in the existing ACL */
noldmembers = aclmembers(old_acl, &oldmembers);
}
/*
* In select_best_grantor we should consider existing table-level ACL bits
* as well as the per-column ACL. Build a new ACL that is their
* concatenation. (This is a bit cheap and dirty compared to merging them
* properly with no duplications, but it's all we need here.)
*/
merged_acl = aclconcat(old_rel_acl, old_acl);
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), col_privileges,
merged_acl, ownerId,
&grantorId, &avail_goptions);
pfree(merged_acl);
/*
* Restrict the privileges to what we can actually grant, and emit the
* standards-mandated warning and error messages. Note: we don't track
* whether the user actually used the ALL PRIVILEGES(columns) syntax for
* each column; we just approximate it by whether all the possible
* privileges are specified now. Since the all_privs flag only determines
* whether a warning is issued, this seems close enough.
*/
col_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
(col_privileges == ACL_ALL_RIGHTS_COLUMN),
col_privileges,
relOid, grantorId, ACL_KIND_COLUMN,
relname, attnum,
NameStr(pg_attribute_tuple->attname));
/*
* Generate new ACL.
*/
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
istmt->grant_option,
istmt->behavior, istmt->grantees,
col_privileges, grantorId,
ownerId);
/*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information.
*/
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
/*
* If the updated ACL is empty, we can set attacl to null, and maybe even
* avoid an update of the pg_attribute row. This is worth testing because
* we'll come through here multiple times for any relation-level REVOKE,
* even if there were never any column GRANTs. Note we are assuming that
* the "default" ACL state for columns is empty.
*/
if (ACL_NUM(new_acl) > 0)
{
values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl);
need_update = true;
}
else
{
nulls[Anum_pg_attribute_attacl - 1] = true;
need_update = !isNull;
}
replaces[Anum_pg_attribute_attacl - 1] = true;
if (need_update)
{
newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
values, nulls, replaces);
simple_heap_update(attRelation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(attRelation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(RelationRelationId, relOid, attnum,
ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
}
pfree(new_acl);
ReleaseSysCache(attr_tuple);
}
| static void ExecGrant_Database | ( | InternalGrant * | grantStmt | ) | [static] |
Definition at line 2038 of file aclchk.c.
References ACL_KIND_DATABASE, ACL_NO_RIGHTS, ACL_OBJECT_DATABASE, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_database_datacl, InternalGrant::behavior, CatalogUpdateIndexes(), CommandCounterIncrement(), DATABASEOID, DatabaseRelationId, DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_close, heap_getattr, heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, NULL, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1, select_best_grantor(), simple_heap_update(), HeapTupleData::t_self, updateAclDependencies(), and values.
Referenced by ExecGrantStmt_oids().
{
Relation relation;
ListCell *cell;
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
istmt->privileges = ACL_ALL_RIGHTS_DATABASE;
relation = heap_open(DatabaseRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
{
Oid datId = lfirst_oid(cell);
Form_pg_database pg_database_tuple;
Datum aclDatum;
bool isNull;
AclMode avail_goptions;
AclMode this_privileges;
Acl *old_acl;
Acl *new_acl;
Oid grantorId;
Oid ownerId;
HeapTuple newtuple;
Datum values[Natts_pg_database];
bool nulls[Natts_pg_database];
bool replaces[Natts_pg_database];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
HeapTuple tuple;
tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(datId));
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for database %u", datId);
pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
*/
ownerId = pg_database_tuple->datdba;
aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
RelationGetDescr(relation), &isNull);
if (isNull)
{
old_acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
}
else
{
old_acl = DatumGetAclPCopy(aclDatum);
/* Get the roles mentioned in the existing ACL */
noldmembers = aclmembers(old_acl, &oldmembers);
}
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
/*
* Restrict the privileges to what we can actually grant, and emit the
* standards-mandated warning and error messages.
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, istmt->privileges,
datId, grantorId, ACL_KIND_DATABASE,
NameStr(pg_database_tuple->datname),
0, NULL);
/*
* Generate new ACL.
*/
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
/*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information.
*/
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
replaces[Anum_pg_database_datacl - 1] = true;
values[Anum_pg_database_datacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
simple_heap_update(relation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(DatabaseRelationId, HeapTupleGetOid(tuple), 0,
ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
ReleaseSysCache(tuple);
pfree(new_acl);
/* prevent error when processing duplicate objects */
CommandCounterIncrement();
}
heap_close(relation, RowExclusiveLock);
}
| static void ExecGrant_Fdw | ( | InternalGrant * | grantStmt | ) | [static] |
Definition at line 2161 of file aclchk.c.
References ACL_KIND_FDW, ACL_NO_RIGHTS, ACL_OBJECT_FDW, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_foreign_data_wrapper_fdwacl, InternalGrant::behavior, CatalogUpdateIndexes(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, FOREIGNDATAWRAPPEROID, ForeignDataWrapperRelationId, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_close, heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, NULL, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1, select_best_grantor(), simple_heap_update(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.
Referenced by ExecGrantStmt_oids().
{
Relation relation;
ListCell *cell;
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
istmt->privileges = ACL_ALL_RIGHTS_FDW;
relation = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
{
Oid fdwid = lfirst_oid(cell);
Form_pg_foreign_data_wrapper pg_fdw_tuple;
Datum aclDatum;
bool isNull;
AclMode avail_goptions;
AclMode this_privileges;
Acl *old_acl;
Acl *new_acl;
Oid grantorId;
Oid ownerId;
HeapTuple tuple;
HeapTuple newtuple;
Datum values[Natts_pg_foreign_data_wrapper];
bool nulls[Natts_pg_foreign_data_wrapper];
bool replaces[Natts_pg_foreign_data_wrapper];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID,
ObjectIdGetDatum(fdwid));
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
pg_fdw_tuple = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
*/
ownerId = pg_fdw_tuple->fdwowner;
aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
Anum_pg_foreign_data_wrapper_fdwacl,
&isNull);
if (isNull)
{
old_acl = acldefault(ACL_OBJECT_FDW, ownerId);
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
}
else
{
old_acl = DatumGetAclPCopy(aclDatum);
/* Get the roles mentioned in the existing ACL */
noldmembers = aclmembers(old_acl, &oldmembers);
}
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
/*
* Restrict the privileges to what we can actually grant, and emit the
* standards-mandated warning and error messages.
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, istmt->privileges,
fdwid, grantorId, ACL_KIND_FDW,
NameStr(pg_fdw_tuple->fdwname),
0, NULL);
/*
* Generate new ACL.
*/
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
/*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information.
*/
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
replaces[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
values[Anum_pg_foreign_data_wrapper_fdwacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
simple_heap_update(relation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(ForeignDataWrapperRelationId,
HeapTupleGetOid(tuple), 0,
ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
ReleaseSysCache(tuple);
pfree(new_acl);
/* prevent error when processing duplicate objects */
CommandCounterIncrement();
}
heap_close(relation, RowExclusiveLock);
}
| static void ExecGrant_ForeignServer | ( | InternalGrant * | grantStmt | ) | [static] |
Definition at line 2287 of file aclchk.c.
References ACL_KIND_FOREIGN_SERVER, ACL_NO_RIGHTS, ACL_OBJECT_FOREIGN_SERVER, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_foreign_server_srvacl, InternalGrant::behavior, CatalogUpdateIndexes(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, FOREIGNSERVEROID, ForeignServerRelationId, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_close, heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, NULL, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1, select_best_grantor(), simple_heap_update(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.
Referenced by ExecGrantStmt_oids().
{
Relation relation;
ListCell *cell;
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
istmt->privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
relation = heap_open(ForeignServerRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
{
Oid srvid = lfirst_oid(cell);
Form_pg_foreign_server pg_server_tuple;
Datum aclDatum;
bool isNull;
AclMode avail_goptions;
AclMode this_privileges;
Acl *old_acl;
Acl *new_acl;
Oid grantorId;
Oid ownerId;
HeapTuple tuple;
HeapTuple newtuple;
Datum values[Natts_pg_foreign_server];
bool nulls[Natts_pg_foreign_server];
bool replaces[Natts_pg_foreign_server];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srvid));
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for foreign server %u", srvid);
pg_server_tuple = (Form_pg_foreign_server) GETSTRUCT(tuple);
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
*/
ownerId = pg_server_tuple->srvowner;
aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
Anum_pg_foreign_server_srvacl,
&isNull);
if (isNull)
{
old_acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
}
else
{
old_acl = DatumGetAclPCopy(aclDatum);
/* Get the roles mentioned in the existing ACL */
noldmembers = aclmembers(old_acl, &oldmembers);
}
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
/*
* Restrict the privileges to what we can actually grant, and emit the
* standards-mandated warning and error messages.
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, istmt->privileges,
srvid, grantorId, ACL_KIND_FOREIGN_SERVER,
NameStr(pg_server_tuple->srvname),
0, NULL);
/*
* Generate new ACL.
*/
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
/*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information.
*/
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
replaces[Anum_pg_foreign_server_srvacl - 1] = true;
values[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
simple_heap_update(relation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(ForeignServerRelationId,
HeapTupleGetOid(tuple), 0,
ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
ReleaseSysCache(tuple);
pfree(new_acl);
/* prevent error when processing duplicate objects */
CommandCounterIncrement();
}
heap_close(relation, RowExclusiveLock);
}
| static void ExecGrant_Function | ( | InternalGrant * | grantStmt | ) | [static] |
Definition at line 2412 of file aclchk.c.
References ACL_KIND_PROC, ACL_NO_RIGHTS, ACL_OBJECT_FUNCTION, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_proc_proacl, InternalGrant::behavior, CatalogUpdateIndexes(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_close, heap_modify_tuple(), heap_open(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, NULL, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, ProcedureRelationId, PROCOID, RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1, select_best_grantor(), simple_heap_update(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.
Referenced by ExecGrantStmt_oids().
{
Relation relation;
ListCell *cell;
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
istmt->privileges = ACL_ALL_RIGHTS_FUNCTION;
relation = heap_open(ProcedureRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
{
Oid funcId = lfirst_oid(cell);
Form_pg_proc pg_proc_tuple;
Datum aclDatum;
bool isNull;
AclMode avail_goptions;
AclMode this_privileges;
Acl *old_acl;
Acl *new_acl;
Oid grantorId;
Oid ownerId;
HeapTuple tuple;
HeapTuple newtuple;
Datum values[Natts_pg_proc];
bool nulls[Natts_pg_proc];
bool replaces[Natts_pg_proc];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for function %u", funcId);
pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
*/
ownerId = pg_proc_tuple->proowner;
aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
&isNull);
if (isNull)
{
old_acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
}
else
{
old_acl = DatumGetAclPCopy(aclDatum);
/* Get the roles mentioned in the existing ACL */
noldmembers = aclmembers(old_acl, &oldmembers);
}
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
/*
* Restrict the privileges to what we can actually grant, and emit the
* standards-mandated warning and error messages.
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, istmt->privileges,
funcId, grantorId, ACL_KIND_PROC,
NameStr(pg_proc_tuple->proname),
0, NULL);
/*
* Generate new ACL.
*/
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
/*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information.
*/
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
replaces[Anum_pg_proc_proacl - 1] = true;
values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
simple_heap_update(relation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(ProcedureRelationId, funcId, 0,
ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
ReleaseSysCache(tuple);
pfree(new_acl);
/* prevent error when processing duplicate objects */
CommandCounterIncrement();
}
heap_close(relation, RowExclusiveLock);
}
| static void ExecGrant_Language | ( | InternalGrant * | grantStmt | ) | [static] |
Definition at line 2535 of file aclchk.c.
References ACL_KIND_LANGUAGE, ACL_NO_RIGHTS, ACL_OBJECT_LANGUAGE, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_language_lanacl, InternalGrant::behavior, CatalogUpdateIndexes(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ereport, errcode(), errhint(), errmsg(), ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_close, heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InternalGrant::is_grant, LANGNAME, LANGOID, LanguageRelationId, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, NULL, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1, select_best_grantor(), simple_heap_update(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.
Referenced by ExecGrantStmt_oids().
{
Relation relation;
ListCell *cell;
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
istmt->privileges = ACL_ALL_RIGHTS_LANGUAGE;
relation = heap_open(LanguageRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
{
Oid langId = lfirst_oid(cell);
Form_pg_language pg_language_tuple;
Datum aclDatum;
bool isNull;
AclMode avail_goptions;
AclMode this_privileges;
Acl *old_acl;
Acl *new_acl;
Oid grantorId;
Oid ownerId;
HeapTuple tuple;
HeapTuple newtuple;
Datum values[Natts_pg_language];
bool nulls[Natts_pg_language];
bool replaces[Natts_pg_language];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(langId));
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for language %u", langId);
pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
if (!pg_language_tuple->lanpltrusted)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("language \"%s\" is not trusted",
NameStr(pg_language_tuple->lanname)),
errhint("Only superusers can use untrusted languages.")));
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
*/
ownerId = pg_language_tuple->lanowner;
aclDatum = SysCacheGetAttr(LANGNAME, tuple, Anum_pg_language_lanacl,
&isNull);
if (isNull)
{
old_acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
}
else
{
old_acl = DatumGetAclPCopy(aclDatum);
/* Get the roles mentioned in the existing ACL */
noldmembers = aclmembers(old_acl, &oldmembers);
}
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
/*
* Restrict the privileges to what we can actually grant, and emit the
* standards-mandated warning and error messages.
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, istmt->privileges,
langId, grantorId, ACL_KIND_LANGUAGE,
NameStr(pg_language_tuple->lanname),
0, NULL);
/*
* Generate new ACL.
*/
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
/*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information.
*/
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
replaces[Anum_pg_language_lanacl - 1] = true;
values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
simple_heap_update(relation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple), 0,
ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
ReleaseSysCache(tuple);
pfree(new_acl);
/* prevent error when processing duplicate objects */
CommandCounterIncrement();
}
heap_close(relation, RowExclusiveLock);
}
| static void ExecGrant_Largeobject | ( | InternalGrant * | grantStmt | ) | [static] |
Definition at line 2665 of file aclchk.c.
References ACL_KIND_LARGEOBJECT, ACL_NO_RIGHTS, ACL_OBJECT_LARGEOBJECT, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_largeobject_metadata_lomacl, InternalGrant::behavior, BTEqualStrategyNumber, CatalogUpdateIndexes(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_close, heap_getattr, heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InternalGrant::is_grant, LargeObjectMetadataOidIndexId, LargeObjectMetadataRelationId, LargeObjectRelationId, lfirst_oid, MemSet, merge_acl_with_grant(), NULL, ObjectIdAttributeNumber, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, RelationGetDescr, restrict_and_check_grant(), RowExclusiveLock, ScanKeyInit(), select_best_grantor(), simple_heap_update(), SnapshotNow, snprintf(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, updateAclDependencies(), and values.
Referenced by ExecGrantStmt_oids().
{
Relation relation;
ListCell *cell;
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
istmt->privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
relation = heap_open(LargeObjectMetadataRelationId,
RowExclusiveLock);
foreach(cell, istmt->objects)
{
Oid loid = lfirst_oid(cell);
Form_pg_largeobject_metadata form_lo_meta;
char loname[NAMEDATALEN];
Datum aclDatum;
bool isNull;
AclMode avail_goptions;
AclMode this_privileges;
Acl *old_acl;
Acl *new_acl;
Oid grantorId;
Oid ownerId;
HeapTuple newtuple;
Datum values[Natts_pg_largeobject_metadata];
bool nulls[Natts_pg_largeobject_metadata];
bool replaces[Natts_pg_largeobject_metadata];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
ScanKeyData entry[1];
SysScanDesc scan;
HeapTuple tuple;
/* There's no syscache for pg_largeobject_metadata */
ScanKeyInit(&entry[0],
ObjectIdAttributeNumber,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(loid));
scan = systable_beginscan(relation,
LargeObjectMetadataOidIndexId, true,
SnapshotNow, 1, entry);
tuple = systable_getnext(scan);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for large object %u", loid);
form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
*/
ownerId = form_lo_meta->lomowner;
aclDatum = heap_getattr(tuple,
Anum_pg_largeobject_metadata_lomacl,
RelationGetDescr(relation), &isNull);
if (isNull)
{
old_acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
}
else
{
old_acl = DatumGetAclPCopy(aclDatum);
/* Get the roles mentioned in the existing ACL */
noldmembers = aclmembers(old_acl, &oldmembers);
}
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
/*
* Restrict the privileges to what we can actually grant, and emit the
* standards-mandated warning and error messages.
*/
snprintf(loname, sizeof(loname), "large object %u", loid);
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, istmt->privileges,
loid, grantorId, ACL_KIND_LARGEOBJECT,
loname, 0, NULL);
/*
* Generate new ACL.
*/
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
/*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information.
*/
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
values[Anum_pg_largeobject_metadata_lomacl - 1]
= PointerGetDatum(new_acl);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
values, nulls, replaces);
simple_heap_update(relation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(LargeObjectRelationId,
HeapTupleGetOid(tuple), 0,
ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
systable_endscan(scan);
pfree(new_acl);
/* prevent error when processing duplicate objects */
CommandCounterIncrement();
}
heap_close(relation, RowExclusiveLock);
}
| static void ExecGrant_Namespace | ( | InternalGrant * | grantStmt | ) | [static] |
Definition at line 2805 of file aclchk.c.
References ACL_KIND_NAMESPACE, ACL_NO_RIGHTS, ACL_OBJECT_NAMESPACE, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_namespace_nspacl, InternalGrant::behavior, CatalogUpdateIndexes(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_close, heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NAMESPACENAME, NAMESPACEOID, NamespaceRelationId, NameStr, NULL, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1, select_best_grantor(), simple_heap_update(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.
Referenced by ExecGrantStmt_oids().
{
Relation relation;
ListCell *cell;
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
istmt->privileges = ACL_ALL_RIGHTS_NAMESPACE;
relation = heap_open(NamespaceRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
{
Oid nspid = lfirst_oid(cell);
Form_pg_namespace pg_namespace_tuple;
Datum aclDatum;
bool isNull;
AclMode avail_goptions;
AclMode this_privileges;
Acl *old_acl;
Acl *new_acl;
Oid grantorId;
Oid ownerId;
HeapTuple tuple;
HeapTuple newtuple;
Datum values[Natts_pg_namespace];
bool nulls[Natts_pg_namespace];
bool replaces[Natts_pg_namespace];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for namespace %u", nspid);
pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
*/
ownerId = pg_namespace_tuple->nspowner;
aclDatum = SysCacheGetAttr(NAMESPACENAME, tuple,
Anum_pg_namespace_nspacl,
&isNull);
if (isNull)
{
old_acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
}
else
{
old_acl = DatumGetAclPCopy(aclDatum);
/* Get the roles mentioned in the existing ACL */
noldmembers = aclmembers(old_acl, &oldmembers);
}
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
/*
* Restrict the privileges to what we can actually grant, and emit the
* standards-mandated warning and error messages.
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, istmt->privileges,
nspid, grantorId, ACL_KIND_NAMESPACE,
NameStr(pg_namespace_tuple->nspname),
0, NULL);
/*
* Generate new ACL.
*/
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
/*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information.
*/
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
replaces[Anum_pg_namespace_nspacl - 1] = true;
values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
simple_heap_update(relation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple), 0,
ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
ReleaseSysCache(tuple);
pfree(new_acl);
/* prevent error when processing duplicate objects */
CommandCounterIncrement();
}
heap_close(relation, RowExclusiveLock);
}
| static void ExecGrant_Relation | ( | InternalGrant * | grantStmt | ) | [static] |
Definition at line 1708 of file aclchk.c.
References ACL_ALL_RIGHTS_COLUMN, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SEQUENCE, ACL_NO_RIGHTS, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_SELECT, aclcopy(), acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_class_relacl, AttributeRelationId, InternalGrant::behavior, CatalogUpdateIndexes(), InternalGrant::col_privs, AccessPriv::cols, CommandCounterIncrement(), DatumGetAclPCopy, elog, ereport, errcode(), errmsg(), ERROR, ExecGrant_Attribute(), expand_all_col_privileges(), expand_col_privileges(), FirstLowInvalidHeapAttributeNumber, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_close, heap_modify_tuple(), heap_open(), HeapTupleIsValid, InternalGrant::is_grant, lfirst, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, NULL, ObjectIdGetDatum, InternalGrant::objects, InternalGrant::objtype, palloc0(), pfree(), PointerGetDatum, AccessPriv::priv_name, privilege_to_string(), InternalGrant::privileges, RelationGetDescr, RelationRelationId, ReleaseSysCache(), RELKIND_COMPOSITE_TYPE, RELKIND_INDEX, RELKIND_SEQUENCE, RELOID, restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1, select_best_grantor(), simple_heap_update(), string_to_privilege(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), values, and WARNING.
Referenced by ExecGrantStmt_oids().
{
Relation relation;
Relation attRelation;
ListCell *cell;
relation = heap_open(RelationRelationId, RowExclusiveLock);
attRelation = heap_open(AttributeRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
{
Oid relOid = lfirst_oid(cell);
Datum aclDatum;
Form_pg_class pg_class_tuple;
bool isNull;
AclMode this_privileges;
AclMode *col_privileges;
int num_col_privileges;
bool have_col_privileges;
Acl *old_acl;
Acl *old_rel_acl;
int noldmembers;
Oid *oldmembers;
Oid ownerId;
HeapTuple tuple;
ListCell *cell_colprivs;
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for relation %u", relOid);
pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
/* Not sensible to grant on an index */
if (pg_class_tuple->relkind == RELKIND_INDEX)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is an index",
NameStr(pg_class_tuple->relname))));
/* Composite types aren't tables either */
if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is a composite type",
NameStr(pg_class_tuple->relname))));
/* Used GRANT SEQUENCE on a non-sequence? */
if (istmt->objtype == ACL_OBJECT_SEQUENCE &&
pg_class_tuple->relkind != RELKIND_SEQUENCE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a sequence",
NameStr(pg_class_tuple->relname))));
/* Adjust the default permissions based on object type */
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
{
if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
else
this_privileges = ACL_ALL_RIGHTS_RELATION;
}
else
this_privileges = istmt->privileges;
/*
* The GRANT TABLE syntax can be used for sequences and non-sequences,
* so we have to look at the relkind to determine the supported
* permissions. The OR of table and sequence permissions were already
* checked.
*/
if (istmt->objtype == ACL_OBJECT_RELATION)
{
if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
{
/*
* For backward compatibility, just throw a warning for
* invalid sequence permissions when using the non-sequence
* GRANT syntax.
*/
if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
{
/*
* Mention the object name because the user needs to know
* which operations succeeded. This is required because
* WARNING allows the command to continue.
*/
ereport(WARNING,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges",
NameStr(pg_class_tuple->relname))));
this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
}
}
else
{
if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
{
/*
* USAGE is the only permission supported by sequences but
* not by non-sequences. Don't mention the object name
* because we didn't in the combined TABLE | SEQUENCE
* check.
*/
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("invalid privilege type USAGE for table")));
}
}
}
/*
* Set up array in which we'll accumulate any column privilege bits
* that need modification. The array is indexed such that entry [0]
* corresponds to FirstLowInvalidHeapAttributeNumber.
*/
num_col_privileges = pg_class_tuple->relnatts - FirstLowInvalidHeapAttributeNumber + 1;
col_privileges = (AclMode *) palloc0(num_col_privileges * sizeof(AclMode));
have_col_privileges = false;
/*
* If we are revoking relation privileges that are also column
* privileges, we must implicitly revoke them from each column too,
* per SQL spec. (We don't need to implicitly add column privileges
* during GRANT because the permissions-checking code always checks
* both relation and per-column privileges.)
*/
if (!istmt->is_grant &&
(this_privileges & ACL_ALL_RIGHTS_COLUMN) != 0)
{
expand_all_col_privileges(relOid, pg_class_tuple,
this_privileges & ACL_ALL_RIGHTS_COLUMN,
col_privileges,
num_col_privileges);
have_col_privileges = true;
}
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
*/
ownerId = pg_class_tuple->relowner;
aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
&isNull);
if (isNull)
{
switch (pg_class_tuple->relkind)
{
case RELKIND_SEQUENCE:
old_acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
break;
default:
old_acl = acldefault(ACL_OBJECT_RELATION, ownerId);
break;
}
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
}
else
{
old_acl = DatumGetAclPCopy(aclDatum);
/* Get the roles mentioned in the existing ACL */
noldmembers = aclmembers(old_acl, &oldmembers);
}
/* Need an extra copy of original rel ACL for column handling */
old_rel_acl = aclcopy(old_acl);
/*
* Handle relation-level privileges, if any were specified
*/
if (this_privileges != ACL_NO_RIGHTS)
{
AclMode avail_goptions;
Acl *new_acl;
Oid grantorId;
HeapTuple newtuple;
Datum values[Natts_pg_class];
bool nulls[Natts_pg_class];
bool replaces[Natts_pg_class];
int nnewmembers;
Oid *newmembers;
AclObjectKind aclkind;
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), this_privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
switch (pg_class_tuple->relkind)
{
case RELKIND_SEQUENCE:
aclkind = ACL_KIND_SEQUENCE;
break;
default:
aclkind = ACL_KIND_CLASS;
break;
}
/*
* Restrict the privileges to what we can actually grant, and emit
* the standards-mandated warning and error messages.
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, this_privileges,
relOid, grantorId, aclkind,
NameStr(pg_class_tuple->relname),
0, NULL);
/*
* Generate new ACL.
*/
new_acl = merge_acl_with_grant(old_acl,
istmt->is_grant,
istmt->grant_option,
istmt->behavior,
istmt->grantees,
this_privileges,
grantorId,
ownerId);
/*
* We need the members of both old and new ACLs so we can correct
* the shared dependency information.
*/
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
replaces[Anum_pg_class_relacl - 1] = true;
values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
values, nulls, replaces);
simple_heap_update(relation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(RelationRelationId, relOid, 0,
ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
pfree(new_acl);
}
/*
* Handle column-level privileges, if any were specified or implied.
* We first expand the user-specified column privileges into the
* array, and then iterate over all nonempty array entries.
*/
foreach(cell_colprivs, istmt->col_privs)
{
AccessPriv *col_privs = (AccessPriv *) lfirst(cell_colprivs);
if (col_privs->priv_name == NULL)
this_privileges = ACL_ALL_RIGHTS_COLUMN;
else
this_privileges = string_to_privilege(col_privs->priv_name);
if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("invalid privilege type %s for column",
privilege_to_string(this_privileges))));
if (pg_class_tuple->relkind == RELKIND_SEQUENCE &&
this_privileges & ~((AclMode) ACL_SELECT))
{
/*
* The only column privilege allowed on sequences is SELECT.
* This is a warning not error because we do it that way for
* relation-level privileges.
*/
ereport(WARNING,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("sequence \"%s\" only supports SELECT column privileges",
NameStr(pg_class_tuple->relname))));
this_privileges &= (AclMode) ACL_SELECT;
}
expand_col_privileges(col_privs->cols, relOid,
this_privileges,
col_privileges,
num_col_privileges);
have_col_privileges = true;
}
if (have_col_privileges)
{
AttrNumber i;
for (i = 0; i < num_col_privileges; i++)
{
if (col_privileges[i] == ACL_NO_RIGHTS)
continue;
ExecGrant_Attribute(istmt,
relOid,
NameStr(pg_class_tuple->relname),
i + FirstLowInvalidHeapAttributeNumber,
ownerId,
col_privileges[i],
attRelation,
old_rel_acl);
}
}
pfree(old_rel_acl);
pfree(col_privileges);
ReleaseSysCache(tuple);
/* prevent error when processing duplicate objects */
CommandCounterIncrement();
}
heap_close(attRelation, RowExclusiveLock);
heap_close(relation, RowExclusiveLock);
}
| static void ExecGrant_Tablespace | ( | InternalGrant * | grantStmt | ) | [static] |
Definition at line 2929 of file aclchk.c.
References ACL_KIND_TABLESPACE, ACL_NO_RIGHTS, ACL_OBJECT_TABLESPACE, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_tablespace_spcacl, InternalGrant::behavior, CatalogUpdateIndexes(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_close, heap_getattr, heap_modify_tuple(), heap_open(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, NULL, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1, select_best_grantor(), simple_heap_update(), HeapTupleData::t_self, TABLESPACEOID, TableSpaceRelationId, updateAclDependencies(), and values.
Referenced by ExecGrantStmt_oids().
{
Relation relation;
ListCell *cell;
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
istmt->privileges = ACL_ALL_RIGHTS_TABLESPACE;
relation = heap_open(TableSpaceRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
{
Oid tblId = lfirst_oid(cell);
Form_pg_tablespace pg_tablespace_tuple;
Datum aclDatum;
bool isNull;
AclMode avail_goptions;
AclMode this_privileges;
Acl *old_acl;
Acl *new_acl;
Oid grantorId;
Oid ownerId;
HeapTuple newtuple;
Datum values[Natts_pg_tablespace];
bool nulls[Natts_pg_tablespace];
bool replaces[Natts_pg_tablespace];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
HeapTuple tuple;
/* Search syscache for pg_tablespace */
tuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(tblId));
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for tablespace %u", tblId);
pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
*/
ownerId = pg_tablespace_tuple->spcowner;
aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl,
RelationGetDescr(relation), &isNull);
if (isNull)
{
old_acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
}
else
{
old_acl = DatumGetAclPCopy(aclDatum);
/* Get the roles mentioned in the existing ACL */
noldmembers = aclmembers(old_acl, &oldmembers);
}
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
/*
* Restrict the privileges to what we can actually grant, and emit the
* standards-mandated warning and error messages.
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, istmt->privileges,
tblId, grantorId, ACL_KIND_TABLESPACE,
NameStr(pg_tablespace_tuple->spcname),
0, NULL);
/*
* Generate new ACL.
*/
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
/*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information.
*/
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
replaces[Anum_pg_tablespace_spcacl - 1] = true;
values[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
simple_heap_update(relation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(TableSpaceRelationId, tblId, 0,
ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
ReleaseSysCache(tuple);
pfree(new_acl);
/* prevent error when processing duplicate objects */
CommandCounterIncrement();
}
heap_close(relation, RowExclusiveLock);
}
| static void ExecGrant_Type | ( | InternalGrant * | grantStmt | ) | [static] |
Definition at line 3052 of file aclchk.c.
References ACL_KIND_TYPE, ACL_NO_RIGHTS, ACL_OBJECT_DOMAIN, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_type_typacl, InternalGrant::behavior, CatalogUpdateIndexes(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ereport, errcode(), errhint(), errmsg(), ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_close, heap_getattr, heap_modify_tuple(), heap_open(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, NULL, ObjectIdGetDatum, InternalGrant::objects, InternalGrant::objtype, pfree(), PointerGetDatum, InternalGrant::privileges, RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1, select_best_grantor(), simple_heap_update(), HeapTupleData::t_self, TYPEOID, TypeRelationId, TYPTYPE_DOMAIN, updateAclDependencies(), and values.
Referenced by ExecGrantStmt_oids().
{
Relation relation;
ListCell *cell;
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
istmt->privileges = ACL_ALL_RIGHTS_TYPE;
relation = heap_open(TypeRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
{
Oid typId = lfirst_oid(cell);
Form_pg_type pg_type_tuple;
Datum aclDatum;
bool isNull;
AclMode avail_goptions;
AclMode this_privileges;
Acl *old_acl;
Acl *new_acl;
Oid grantorId;
Oid ownerId;
HeapTuple newtuple;
Datum values[Natts_pg_type];
bool nulls[Natts_pg_type];
bool replaces[Natts_pg_type];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
HeapTuple tuple;
/* Search syscache for pg_type */
tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typId));
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for type %u", typId);
pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
if (pg_type_tuple->typelem != 0 && pg_type_tuple->typlen == -1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("cannot set privileges of array types"),
errhint("Set the privileges of the element type instead.")));
/* Used GRANT DOMAIN on a non-domain? */
if (istmt->objtype == ACL_OBJECT_DOMAIN &&
pg_type_tuple->typtype != TYPTYPE_DOMAIN)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a domain",
NameStr(pg_type_tuple->typname))));
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
*/
ownerId = pg_type_tuple->typowner;
aclDatum = heap_getattr(tuple, Anum_pg_type_typacl,
RelationGetDescr(relation), &isNull);
if (isNull)
{
old_acl = acldefault(istmt->objtype, ownerId);
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
}
else
{
old_acl = DatumGetAclPCopy(aclDatum);
/* Get the roles mentioned in the existing ACL */
noldmembers = aclmembers(old_acl, &oldmembers);
}
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
/*
* Restrict the privileges to what we can actually grant, and emit the
* standards-mandated warning and error messages.
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, istmt->privileges,
typId, grantorId, ACL_KIND_TYPE,
NameStr(pg_type_tuple->typname),
0, NULL);
/*
* Generate new ACL.
*/
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
/*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information.
*/
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
replaces[Anum_pg_type_typacl - 1] = true;
values[Anum_pg_type_typacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
simple_heap_update(relation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(TypeRelationId, typId, 0,
ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
ReleaseSysCache(tuple);
pfree(new_acl);
/* prevent error when processing duplicate objects */
CommandCounterIncrement();
}
heap_close(relation, RowExclusiveLock);
}
| static void ExecGrantStmt_oids | ( | InternalGrant * | istmt | ) | [static] |
Definition at line 565 of file aclchk.c.
References ACL_OBJECT_DATABASE, ACL_OBJECT_DOMAIN, ACL_OBJECT_FDW, ACL_OBJECT_FOREIGN_SERVER, ACL_OBJECT_FUNCTION, ACL_OBJECT_LANGUAGE, ACL_OBJECT_LARGEOBJECT, ACL_OBJECT_NAMESPACE, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TABLESPACE, ACL_OBJECT_TYPE, elog, ERROR, ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), and InternalGrant::objtype.
Referenced by ExecuteGrantStmt(), and RemoveRoleFromObjectACL().
{
switch (istmt->objtype)
{
case ACL_OBJECT_RELATION:
case ACL_OBJECT_SEQUENCE:
ExecGrant_Relation(istmt);
break;
case ACL_OBJECT_DATABASE:
ExecGrant_Database(istmt);
break;
case ACL_OBJECT_DOMAIN:
case ACL_OBJECT_TYPE:
ExecGrant_Type(istmt);
break;
case ACL_OBJECT_FDW:
ExecGrant_Fdw(istmt);
break;
case ACL_OBJECT_FOREIGN_SERVER:
ExecGrant_ForeignServer(istmt);
break;
case ACL_OBJECT_FUNCTION:
ExecGrant_Function(istmt);
break;
case ACL_OBJECT_LANGUAGE:
ExecGrant_Language(istmt);
break;
case ACL_OBJECT_LARGEOBJECT:
ExecGrant_Largeobject(istmt);
break;
case ACL_OBJECT_NAMESPACE:
ExecGrant_Namespace(istmt);
break;
case ACL_OBJECT_TABLESPACE:
ExecGrant_Tablespace(istmt);
break;
default:
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
(int) istmt->objtype);
}
}
| void ExecuteGrantStmt | ( | GrantStmt * | stmt | ) |
Definition at line 388 of file aclchk.c.
References ACL_ALL_RIGHTS_RELATION, ACL_ID_PUBLIC, ACL_OBJECT_DATABASE, ACL_OBJECT_DOMAIN, ACL_OBJECT_FDW, ACL_OBJECT_FOREIGN_SERVER, ACL_OBJECT_FUNCTION, ACL_OBJECT_LANGUAGE, ACL_OBJECT_LARGEOBJECT, ACL_OBJECT_NAMESPACE, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TABLESPACE, ACL_OBJECT_TYPE, ACL_TARGET_ALL_IN_SCHEMA, ACL_TARGET_OBJECT, InternalGrant::all_privs, GrantStmt::behavior, InternalGrant::behavior, InternalGrant::col_privs, AccessPriv::cols, elog, ereport, errcode(), errmsg(), ERROR, ExecGrantStmt_oids(), get_role_oid(), gettext_noop, GrantStmt::grant_option, InternalGrant::grant_option, GrantStmt::grantees, InternalGrant::grantees, GrantStmt::is_grant, InternalGrant::is_grant, lappend(), lappend_oid(), lfirst, NIL, NULL, objectNamesToOids(), GrantStmt::objects, InternalGrant::objects, objectsInSchemaToOids(), GrantStmt::objtype, InternalGrant::objtype, AccessPriv::priv_name, privilege_to_string(), InternalGrant::privileges, GrantStmt::privileges, PrivGrantee::rolname, string_to_privilege(), and GrantStmt::targtype.
Referenced by standard_ProcessUtility().
{
InternalGrant istmt;
ListCell *cell;
const char *errormsg;
AclMode all_privileges;
/*
* Turn the regular GrantStmt into the InternalGrant form.
*/
istmt.is_grant = stmt->is_grant;
istmt.objtype = stmt->objtype;
/* Collect the OIDs of the target objects */
switch (stmt->targtype)
{
case ACL_TARGET_OBJECT:
istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects);
break;
case ACL_TARGET_ALL_IN_SCHEMA:
istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
break;
/* ACL_TARGET_DEFAULTS should not be seen here */
default:
elog(ERROR, "unrecognized GrantStmt.targtype: %d",
(int) stmt->targtype);
}
/* all_privs to be filled below */
/* privileges to be filled below */
istmt.col_privs = NIL; /* may get filled below */
istmt.grantees = NIL; /* filled below */
istmt.grant_option = stmt->grant_option;
istmt.behavior = stmt->behavior;
/*
* Convert the PrivGrantee list into an Oid list. Note that at this point
* we insert an ACL_ID_PUBLIC into the list if an empty role name is
* detected (which is what the grammar uses if PUBLIC is found), so
* downstream there shouldn't be any additional work needed to support
* this case.
*/
foreach(cell, stmt->grantees)
{
PrivGrantee *grantee = (PrivGrantee *) lfirst(cell);
if (grantee->rolname == NULL)
istmt.grantees = lappend_oid(istmt.grantees, ACL_ID_PUBLIC);
else
istmt.grantees =
lappend_oid(istmt.grantees,
get_role_oid(grantee->rolname, false));
}
/*
* Convert stmt->privileges, a list of AccessPriv nodes, into an AclMode
* bitmask. Note: objtype can't be ACL_OBJECT_COLUMN.
*/
switch (stmt->objtype)
{
/*
* Because this might be a sequence, we test both relation and
* sequence bits, and later do a more limited test when we know
* the object type.
*/
case ACL_OBJECT_RELATION:
all_privileges = ACL_ALL_RIGHTS_RELATION | ACL_ALL_RIGHTS_SEQUENCE;
errormsg = gettext_noop("invalid privilege type %s for relation");
break;
case ACL_OBJECT_SEQUENCE:
all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
errormsg = gettext_noop("invalid privilege type %s for sequence");
break;
case ACL_OBJECT_DATABASE:
all_privileges = ACL_ALL_RIGHTS_DATABASE;
errormsg = gettext_noop("invalid privilege type %s for database");
break;
case ACL_OBJECT_DOMAIN:
all_privileges = ACL_ALL_RIGHTS_TYPE;
errormsg = gettext_noop("invalid privilege type %s for domain");
break;
case ACL_OBJECT_FUNCTION:
all_privileges = ACL_ALL_RIGHTS_FUNCTION;
errormsg = gettext_noop("invalid privilege type %s for function");
break;
case ACL_OBJECT_LANGUAGE:
all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
errormsg = gettext_noop("invalid privilege type %s for language");
break;
case ACL_OBJECT_LARGEOBJECT:
all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
errormsg = gettext_noop("invalid privilege type %s for large object");
break;
case ACL_OBJECT_NAMESPACE:
all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
errormsg = gettext_noop("invalid privilege type %s for schema");
break;
case ACL_OBJECT_TABLESPACE:
all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
errormsg = gettext_noop("invalid privilege type %s for tablespace");
break;
case ACL_OBJECT_TYPE:
all_privileges = ACL_ALL_RIGHTS_TYPE;
errormsg = gettext_noop("invalid privilege type %s for type");
break;
case ACL_OBJECT_FDW:
all_privileges = ACL_ALL_RIGHTS_FDW;
errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
break;
case ACL_OBJECT_FOREIGN_SERVER:
all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
errormsg = gettext_noop("invalid privilege type %s for foreign server");
break;
default:
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
(int) stmt->objtype);
/* keep compiler quiet */
all_privileges = ACL_NO_RIGHTS;
errormsg = NULL;
}
if (stmt->privileges == NIL)
{
istmt.all_privs = true;
/*
* will be turned into ACL_ALL_RIGHTS_* by the internal routines
* depending on the object type
*/
istmt.privileges = ACL_NO_RIGHTS;
}
else
{
istmt.all_privs = false;
istmt.privileges = ACL_NO_RIGHTS;
foreach(cell, stmt->privileges)
{
AccessPriv *privnode = (AccessPriv *) lfirst(cell);
AclMode priv;
/*
* If it's a column-level specification, we just set it aside in
* col_privs for the moment; but insist it's for a relation.
*/
if (privnode->cols)
{
if (stmt->objtype != ACL_OBJECT_RELATION)
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("column privileges are only valid for relations")));
istmt.col_privs = lappend(istmt.col_privs, privnode);
continue;
}
if (privnode->priv_name == NULL) /* parser mistake? */
elog(ERROR, "AccessPriv node must specify privilege or columns");
priv = string_to_privilege(privnode->priv_name);
if (priv & ~((AclMode) all_privileges))
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg(errormsg, privilege_to_string(priv))));
istmt.privileges |= priv;
}
}
ExecGrantStmt_oids(&istmt);
}
| static void expand_all_col_privileges | ( | Oid | table_oid, | |
| Form_pg_class | classForm, | |||
| AclMode | this_privileges, | |||
| AclMode * | col_privileges, | |||
| int | num_col_privileges | |||
| ) | [static] |
Definition at line 1511 of file aclchk.c.
References Assert, ATTNUM, elog, ERROR, FirstLowInvalidHeapAttributeNumber, GETSTRUCT, HeapTupleIsValid, Int16GetDatum, InvalidAttrNumber, ObjectIdAttributeNumber, ObjectIdGetDatum, ReleaseSysCache(), RELKIND_VIEW, and SearchSysCache2.
Referenced by ExecGrant_Relation().
{
AttrNumber curr_att;
Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
curr_att <= classForm->relnatts;
curr_att++)
{
HeapTuple attTuple;
bool isdropped;
if (curr_att == InvalidAttrNumber)
continue;
/* Skip OID column if it doesn't exist */
if (curr_att == ObjectIdAttributeNumber && !classForm->relhasoids)
continue;
/* Views don't have any system columns at all */
if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
continue;
attTuple = SearchSysCache2(ATTNUM,
ObjectIdGetDatum(table_oid),
Int16GetDatum(curr_att));
if (!HeapTupleIsValid(attTuple))
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
curr_att, table_oid);
isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
ReleaseSysCache(attTuple);
/* ignore dropped columns */
if (isdropped)
continue;
col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
}
}
| static void expand_col_privileges | ( | List * | colnames, | |
| Oid | table_oid, | |||
| AclMode | this_privileges, | |||
| AclMode * | col_privileges, | |||
| int | num_col_privileges | |||
| ) | [static] |
Definition at line 1478 of file aclchk.c.
References elog, ereport, errcode(), errmsg(), ERROR, get_attnum(), get_rel_name(), InvalidAttrNumber, lfirst, and strVal.
Referenced by ExecGrant_Relation().
{
ListCell *cell;
foreach(cell, colnames)
{
char *colname = strVal(lfirst(cell));
AttrNumber attnum;
attnum = get_attnum(table_oid, colname);
if (attnum == InvalidAttrNumber)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" of relation \"%s\" does not exist",
colname, get_rel_name(table_oid))));
attnum -= FirstLowInvalidHeapAttributeNumber;
if (attnum <= 0 || attnum >= num_col_privileges)
elog(ERROR, "column number out of range"); /* safety check */
col_privileges[attnum] |= this_privileges;
}
}
Definition at line 5088 of file aclchk.c.
References Anum_pg_default_acl_defaclacl, CharGetDatum, DatumGetAclPCopy, DEFACLROLENSPOBJ, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache3, and SysCacheGetAttr().
Referenced by get_user_default_acl().
{
Acl *result = NULL;
HeapTuple tuple;
tuple = SearchSysCache3(DEFACLROLENSPOBJ,
ObjectIdGetDatum(roleId),
ObjectIdGetDatum(nsp_oid),
CharGetDatum(objtype));
if (HeapTupleIsValid(tuple))
{
Datum aclDatum;
bool isNull;
aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
Anum_pg_default_acl_defaclacl,
&isNull);
if (!isNull)
result = DatumGetAclPCopy(aclDatum);
ReleaseSysCache(tuple);
}
return result;
}
| Acl* get_user_default_acl | ( | GrantObjectType | objtype, | |
| Oid | ownerId, | |||
| Oid | nsp_oid | |||
| ) |
Definition at line 5120 of file aclchk.c.
References ACL_OBJECT_FUNCTION, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TYPE, acldefault(), aclequal(), aclitemsort(), aclmerge(), get_default_acl_internal(), InvalidOid, IsBootstrapProcessingMode, and NULL.
Referenced by heap_create_with_catalog(), ProcedureCreate(), and TypeCreate().
{
Acl *result;
Acl *glob_acl;
Acl *schema_acl;
Acl *def_acl;
char defaclobjtype;
/*
* Use NULL during bootstrap, since pg_default_acl probably isn't there
* yet.
*/
if (IsBootstrapProcessingMode())
return NULL;
/* Check if object type is supported in pg_default_acl */
switch (objtype)
{
case ACL_OBJECT_RELATION:
defaclobjtype = DEFACLOBJ_RELATION;
break;
case ACL_OBJECT_SEQUENCE:
defaclobjtype = DEFACLOBJ_SEQUENCE;
break;
case ACL_OBJECT_FUNCTION:
defaclobjtype = DEFACLOBJ_FUNCTION;
break;
case ACL_OBJECT_TYPE:
defaclobjtype = DEFACLOBJ_TYPE;
break;
default:
return NULL;
}
/* Look up the relevant pg_default_acl entries */
glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
/* Quick out if neither entry exists */
if (glob_acl == NULL && schema_acl == NULL)
return NULL;
/* We need to know the hard-wired default value, too */
def_acl = acldefault(objtype, ownerId);
/* If there's no global entry, substitute the hard-wired default */
if (glob_acl == NULL)
glob_acl = def_acl;
/* Merge in any per-schema privileges */
result = aclmerge(glob_acl, schema_acl, ownerId);
/*
* For efficiency, we want to return NULL if the result equals default.
* This requires sorting both arrays to get an accurate comparison.
*/
aclitemsort(result);
aclitemsort(def_acl);
if (aclequal(result, def_acl))
result = NULL;
return result;
}
Definition at line 818 of file aclchk.c.
References AccessShareLock, Anum_pg_class_relkind, Anum_pg_class_relnamespace, BTEqualStrategyNumber, CharGetDatum, ForwardScanDirection, heap_beginscan(), heap_close, heap_endscan(), heap_getnext(), heap_open(), HeapTupleGetOid, lappend_oid(), NULL, ObjectIdGetDatum, RelationRelationId, ScanKeyInit(), and SnapshotNow.
Referenced by objectsInSchemaToOids().
{
List *relations = NIL;
ScanKeyData key[2];
Relation rel;
HeapScanDesc scan;
HeapTuple tuple;
ScanKeyInit(&key[0],
Anum_pg_class_relnamespace,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(namespaceId));
ScanKeyInit(&key[1],
Anum_pg_class_relkind,
BTEqualStrategyNumber, F_CHAREQ,
CharGetDatum(relkind));
rel = heap_open(RelationRelationId, AccessShareLock);
scan = heap_beginscan(rel, SnapshotNow, 2, key);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
relations = lappend_oid(relations, HeapTupleGetOid(tuple));
}
heap_endscan(scan);
heap_close(rel, AccessShareLock);
return relations;
}
Definition at line 5064 of file aclchk.c.
References AUTHOID, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by check_object_ownership(), and have_createrole_privilege().
{
bool result = false;
HeapTuple utup;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
if (HeapTupleIsValid(utup))
{
result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
ReleaseSysCache(utup);
}
return result;
}
Definition at line 3430 of file aclchk.c.
References AUTHOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), and SearchSysCache1.
Referenced by pg_class_aclmask().
{
bool rolcatupdate;
HeapTuple tuple;
tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("role with OID %u does not exist", roleid)));
rolcatupdate = ((Form_pg_authid) GETSTRUCT(tuple))->rolcatupdate;
ReleaseSysCache(tuple);
return rolcatupdate;
}
| static Acl* merge_acl_with_grant | ( | Acl * | old_acl, | |
| bool | is_grant, | |||
| bool | grant_option, | |||
| DropBehavior | behavior, | |||
| List * | grantees, | |||
| AclMode | privileges, | |||
| Oid | grantorId, | |||
| Oid | ownerId | |||
| ) | [static] |
Definition at line 174 of file aclchk.c.
References ACL_ID_PUBLIC, ACL_MODECHG_ADD, ACL_NO_RIGHTS, ACLITEM_SET_PRIVS_GOPTIONS, aclupdate(), AclItem::ai_grantee, AclItem::ai_grantor, ereport, errcode(), errmsg(), ERROR, lfirst_oid, and pfree().
Referenced by ExecGrant_Attribute(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), and SetDefaultACL().
{
unsigned modechg;
ListCell *j;
Acl *new_acl;
modechg = is_grant ? ACL_MODECHG_ADD : ACL_MODECHG_DEL;
#ifdef ACLDEBUG
dumpacl(old_acl);
#endif
new_acl = old_acl;
foreach(j, grantees)
{
AclItem aclitem;
Acl *newer_acl;
aclitem.ai_grantee = lfirst_oid(j);
/*
* Grant options can only be granted to individual roles, not PUBLIC.
* The reason is that if a user would re-grant a privilege that he
* held through PUBLIC, and later the user is removed, the situation
* is impossible to clean up.
*/
if (is_grant && grant_option && aclitem.ai_grantee == ACL_ID_PUBLIC)
ereport(ERROR,
(errcode(ERRCODE_INVALID_GRANT_OPERATION),
errmsg("grant options can only be granted to roles")));
aclitem.ai_grantor = grantorId;
/*
* The asymmetry in the conditions here comes from the spec. In
* GRANT, the grant_option flag signals WITH GRANT OPTION, which means
* to grant both the basic privilege and its grant option. But in
* REVOKE, plain revoke revokes both the basic privilege and its grant
* option, while REVOKE GRANT OPTION revokes only the option.
*/
ACLITEM_SET_PRIVS_GOPTIONS(aclitem,
(is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
(!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS);
newer_acl = aclupdate(new_acl, &aclitem, modechg, ownerId, behavior);
/* avoid memory leak when there are many grantees */
pfree(new_acl);
new_acl = newer_acl;
#ifdef ACLDEBUG
dumpacl(new_acl);
#endif
}
return new_acl;
}
| static List * objectNamesToOids | ( | GrantObjectType | objtype, | |
| List * | objnames | |||
| ) | [static] |
Definition at line 618 of file aclchk.c.
References ACL_OBJECT_DATABASE, ACL_OBJECT_DOMAIN, ACL_OBJECT_FDW, ACL_OBJECT_FOREIGN_SERVER, ACL_OBJECT_FUNCTION, ACL_OBJECT_LANGUAGE, ACL_OBJECT_LARGEOBJECT, ACL_OBJECT_NAMESPACE, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TABLESPACE, ACL_OBJECT_TYPE, Assert, elog, ereport, errcode(), errmsg(), ERROR, FuncWithArgs::funcargs, FuncWithArgs::funcname, get_database_oid(), get_foreign_data_wrapper_oid(), get_foreign_server_oid(), get_language_oid(), get_namespace_oid(), get_tablespace_oid(), lappend_oid(), LargeObjectExists(), lfirst, LookupFuncNameTypeNames(), makeTypeNameFromNameList(), NIL, NoLock, NULL, oidparse(), RangeVarGetRelid, strVal, and typenameTypeId().
Referenced by ExecuteGrantStmt().
{
List *objects = NIL;
ListCell *cell;
Assert(objnames != NIL);
switch (objtype)
{
case ACL_OBJECT_RELATION:
case ACL_OBJECT_SEQUENCE:
foreach(cell, objnames)
{
RangeVar *relvar = (RangeVar *) lfirst(cell);
Oid relOid;
relOid = RangeVarGetRelid(relvar, NoLock, false);
objects = lappend_oid(objects, relOid);
}
break;
case ACL_OBJECT_DATABASE:
foreach(cell, objnames)
{
char *dbname = strVal(lfirst(cell));
Oid dbid;
dbid = get_database_oid(dbname, false);
objects = lappend_oid(objects, dbid);
}
break;
case ACL_OBJECT_DOMAIN:
case ACL_OBJECT_TYPE:
foreach(cell, objnames)
{
List *typname = (List *) lfirst(cell);
Oid oid;
oid = typenameTypeId(NULL, makeTypeNameFromNameList(typname));
objects = lappend_oid(objects, oid);
}
break;
case ACL_OBJECT_FUNCTION:
foreach(cell, objnames)
{
FuncWithArgs *func = (FuncWithArgs *) lfirst(cell);
Oid funcid;
funcid = LookupFuncNameTypeNames(func->funcname,
func->funcargs, false);
objects = lappend_oid(objects, funcid);
}
break;
case ACL_OBJECT_LANGUAGE:
foreach(cell, objnames)
{
char *langname = strVal(lfirst(cell));
Oid oid;
oid = get_language_oid(langname, false);
objects = lappend_oid(objects, oid);
}
break;
case ACL_OBJECT_LARGEOBJECT:
foreach(cell, objnames)
{
Oid lobjOid = oidparse(lfirst(cell));
if (!LargeObjectExists(lobjOid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("large object %u does not exist",
lobjOid)));
objects = lappend_oid(objects, lobjOid);
}
break;
case ACL_OBJECT_NAMESPACE:
foreach(cell, objnames)
{
char *nspname = strVal(lfirst(cell));
Oid oid;
oid = get_namespace_oid(nspname, false);
objects = lappend_oid(objects, oid);
}
break;
case ACL_OBJECT_TABLESPACE:
foreach(cell, objnames)
{
char *spcname = strVal(lfirst(cell));
Oid spcoid;
spcoid = get_tablespace_oid(spcname, false);
objects = lappend_oid(objects, spcoid);
}
break;
case ACL_OBJECT_FDW:
foreach(cell, objnames)
{
char *fdwname = strVal(lfirst(cell));
Oid fdwid = get_foreign_data_wrapper_oid(fdwname, false);
objects = lappend_oid(objects, fdwid);
}
break;
case ACL_OBJECT_FOREIGN_SERVER:
foreach(cell, objnames)
{
char *srvname = strVal(lfirst(cell));
Oid srvid = get_foreign_server_oid(srvname, false);
objects = lappend_oid(objects, srvid);
}
break;
default:
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
(int) objtype);
}
return objects;
}
| static List * objectsInSchemaToOids | ( | GrantObjectType | objtype, | |
| List * | nspnames | |||
| ) | [static] |
Definition at line 748 of file aclchk.c.
References AccessShareLock, ACL_OBJECT_FUNCTION, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, Anum_pg_proc_pronamespace, BTEqualStrategyNumber, elog, ERROR, ForwardScanDirection, getRelationsInNamespace(), heap_beginscan(), heap_close, heap_endscan(), heap_getnext(), heap_open(), HeapTupleGetOid, lappend_oid(), lfirst, list_concat(), LookupExplicitNamespace(), NULL, ObjectIdGetDatum, ProcedureRelationId, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, ScanKeyInit(), SnapshotNow, and strVal.
Referenced by ExecuteGrantStmt().
{
List *objects = NIL;
ListCell *cell;
foreach(cell, nspnames)
{
char *nspname = strVal(lfirst(cell));
Oid namespaceId;
List *objs;
namespaceId = LookupExplicitNamespace(nspname, false);
switch (objtype)
{
case ACL_OBJECT_RELATION:
/* Process regular tables, views and foreign tables */
objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
objects = list_concat(objects, objs);
objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
objects = list_concat(objects, objs);
objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
objects = list_concat(objects, objs);
objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
objects = list_concat(objects, objs);
break;
case ACL_OBJECT_SEQUENCE:
objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
objects = list_concat(objects, objs);
break;
case ACL_OBJECT_FUNCTION:
{
ScanKeyData key[1];
Relation rel;
HeapScanDesc scan;
HeapTuple tuple;
ScanKeyInit(&key[0],
Anum_pg_proc_pronamespace,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(namespaceId));
rel = heap_open(ProcedureRelationId, AccessShareLock);
scan = heap_beginscan(rel, SnapshotNow, 1, key);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
objects = lappend_oid(objects, HeapTupleGetOid(tuple));
}
heap_endscan(scan);
heap_close(rel, AccessShareLock);
}
break;
default:
/* should not happen */
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
(int) objtype);
}
}
return objects;
}
| static AclMode pg_aclmask | ( | AclObjectKind | objkind, | |
| Oid | table_oid, | |||
| AttrNumber | attnum, | |||
| Oid | roleid, | |||
| AclMode | mask, | |||
| AclMaskHow | how | |||
| ) | [static] |
Definition at line 3452 of file aclchk.c.
References ACL_KIND_CLASS, ACL_KIND_COLUMN, ACL_KIND_DATABASE, ACL_KIND_EVENT_TRIGGER, ACL_KIND_FDW, ACL_KIND_FOREIGN_SERVER, ACL_KIND_LANGUAGE, ACL_KIND_LARGEOBJECT, ACL_KIND_NAMESPACE, ACL_KIND_PROC, ACL_KIND_SEQUENCE, ACL_KIND_TABLESPACE, ACL_KIND_TYPE, elog, ERROR, pg_attribute_aclmask(), pg_class_aclmask(), pg_database_aclmask(), pg_foreign_data_wrapper_aclmask(), pg_foreign_server_aclmask(), pg_language_aclmask(), pg_largeobject_aclmask_snapshot(), pg_namespace_aclmask(), pg_proc_aclmask(), pg_tablespace_aclmask(), pg_type_aclmask(), and SnapshotNow.
Referenced by restrict_and_check_grant().
{
switch (objkind)
{
case ACL_KIND_COLUMN:
return
pg_class_aclmask(table_oid, roleid, mask, how) |
pg_attribute_aclmask(table_oid, attnum, roleid, mask, how);
case ACL_KIND_CLASS:
case ACL_KIND_SEQUENCE:
return pg_class_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_DATABASE:
return pg_database_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_PROC:
return pg_proc_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_LANGUAGE:
return pg_language_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_LARGEOBJECT:
return pg_largeobject_aclmask_snapshot(table_oid, roleid,
mask, how, SnapshotNow);
case ACL_KIND_NAMESPACE:
return pg_namespace_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_TABLESPACE:
return pg_tablespace_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_FDW:
return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_FOREIGN_SERVER:
return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_EVENT_TRIGGER:
elog(ERROR, "grantable rights not supported for event triggers");
/* not reached, but keep compiler quiet */
return ACL_NO_RIGHTS;
case ACL_KIND_TYPE:
return pg_type_aclmask(table_oid, roleid, mask, how);
default:
elog(ERROR, "unrecognized objkind: %d",
(int) objkind);
/* not reached, but keep compiler quiet */
return ACL_NO_RIGHTS;
}
}
| AclResult pg_attribute_aclcheck | ( | Oid | table_oid, | |
| AttrNumber | attnum, | |||
| Oid | roleid, | |||
| AclMode | mode | |||
| ) |
Definition at line 4280 of file aclchk.c.
References ACLMASK_ANY, and pg_attribute_aclmask().
Referenced by checkFkeyPermissions(), column_privilege_check(), and ExecCheckRTEPerms().
{
if (pg_attribute_aclmask(table_oid, attnum, roleid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
| AclResult pg_attribute_aclcheck_all | ( | Oid | table_oid, | |
| Oid | roleid, | |||
| AclMode | mode, | |||
| AclMaskHow | how | |||
| ) |
Definition at line 4309 of file aclchk.c.
References ACLMASK_ALL, ACLMASK_ANY, Anum_pg_attribute_attacl, ATTNUM, GETSTRUCT, heap_attisnull(), HeapTupleIsValid, Int16GetDatum, ObjectIdGetDatum, pg_attribute_aclmask(), ReleaseSysCache(), RELOID, SearchSysCache1, and SearchSysCache2.
Referenced by ExecCheckRTEPerms(), has_any_column_privilege_id(), has_any_column_privilege_id_id(), has_any_column_privilege_id_name(), has_any_column_privilege_name(), has_any_column_privilege_name_id(), and has_any_column_privilege_name_name().
{
AclResult result;
HeapTuple classTuple;
Form_pg_class classForm;
AttrNumber nattrs;
AttrNumber curr_att;
/*
* Must fetch pg_class row to check number of attributes. As in
* pg_attribute_aclmask, we prefer to return "no privileges" instead of
* throwing an error if we get any unexpected lookup errors.
*/
classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
if (!HeapTupleIsValid(classTuple))
return ACLCHECK_NO_PRIV;
classForm = (Form_pg_class) GETSTRUCT(classTuple);
nattrs = classForm->relnatts;
ReleaseSysCache(classTuple);
/*
* Initialize result in case there are no non-dropped columns. We want to
* report failure in such cases for either value of 'how'.
*/
result = ACLCHECK_NO_PRIV;
for (curr_att = 1; curr_att <= nattrs; curr_att++)
{
HeapTuple attTuple;
AclMode attmask;
attTuple = SearchSysCache2(ATTNUM,
ObjectIdGetDatum(table_oid),
Int16GetDatum(curr_att));
if (!HeapTupleIsValid(attTuple))
continue;
/* ignore dropped columns */
if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
{
ReleaseSysCache(attTuple);
continue;
}
/*
* Here we hard-wire knowledge that the default ACL for a column
* grants no privileges, so that we can fall out quickly in the very
* common case where attacl is null.
*/
if (heap_attisnull(attTuple, Anum_pg_attribute_attacl))
attmask = 0;
else
attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
mode, ACLMASK_ANY);
ReleaseSysCache(attTuple);
if (attmask != 0)
{
result = ACLCHECK_OK;
if (how == ACLMASK_ANY)
break; /* succeed on any success */
}
else
{
result = ACLCHECK_NO_PRIV;
if (how == ACLMASK_ALL)
break; /* fail on any failure */
}
}
return result;
}
| AclMode pg_attribute_aclmask | ( | Oid | table_oid, | |
| AttrNumber | attnum, | |||
| Oid | roleid, | |||
| AclMode | mask, | |||
| AclMaskHow | how | |||
| ) |
Definition at line 3516 of file aclchk.c.
References aclmask(), Anum_pg_attribute_attacl, ATTNUM, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum, ObjectIdGetDatum, pfree(), ReleaseSysCache(), RELOID, SearchSysCache1, SearchSysCache2, and SysCacheGetAttr().
Referenced by pg_aclmask(), pg_attribute_aclcheck(), and pg_attribute_aclcheck_all().
{
AclMode result;
HeapTuple classTuple;
HeapTuple attTuple;
Form_pg_class classForm;
Form_pg_attribute attributeForm;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
/*
* First, get the column's ACL from its pg_attribute entry
*/
attTuple = SearchSysCache2(ATTNUM,
ObjectIdGetDatum(table_oid),
Int16GetDatum(attnum));
if (!HeapTupleIsValid(attTuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("attribute %d of relation with OID %u does not exist",
attnum, table_oid)));
attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
/* Throw error on dropped columns, too */
if (attributeForm->attisdropped)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("attribute %d of relation with OID %u does not exist",
attnum, table_oid)));
aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
&isNull);
/*
* Here we hard-wire knowledge that the default ACL for a column grants no
* privileges, so that we can fall out quickly in the very common case
* where attacl is null.
*/
if (isNull)
{
ReleaseSysCache(attTuple);
return 0;
}
/*
* Must get the relation's ownerId from pg_class. Since we already found
* a pg_attribute entry, the only likely reason for this to fail is that a
* concurrent DROP of the relation committed since then (which could only
* happen if we don't have lock on the relation). We prefer to report "no
* privileges" rather than failing in such a case, so as to avoid unwanted
* failures in has_column_privilege() tests.
*/
classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
if (!HeapTupleIsValid(classTuple))
{
ReleaseSysCache(attTuple);
return 0;
}
classForm = (Form_pg_class) GETSTRUCT(classTuple);
ownerId = classForm->relowner;
ReleaseSysCache(classTuple);
/* detoast column's ACL if necessary */
acl = DatumGetAclP(aclDatum);
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
ReleaseSysCache(attTuple);
return result;
}
Definition at line 4394 of file aclchk.c.
References ACLMASK_ANY, and pg_class_aclmask().
Referenced by checkFkeyPermissions(), column_privilege_check(), CreateTrigger(), currtid_byrelname(), currtid_byreloid(), currval_oid(), do_setval(), get_rel_from_relname(), has_any_column_privilege_id(), has_any_column_privilege_id_id(), has_any_column_privilege_id_name(), has_any_column_privilege_name(), has_any_column_privilege_name_id(), has_any_column_privilege_name_name(), has_sequence_privilege_id(), has_sequence_privilege_id_id(), has_sequence_privilege_id_name(), has_sequence_privilege_name(), has_sequence_privilege_name_id(), has_sequence_privilege_name_name(), has_table_privilege_id(), has_table_privilege_id_id(), has_table_privilege_id_name(), has_table_privilege_name(), has_table_privilege_name_id(), has_table_privilege_name_name(), lastval(), LockTableAclCheck(), nextval_internal(), pg_sequence_parameters(), pgrowlocks(), transformTableLikeClause(), and truncate_check_rel().
{
if (pg_class_aclmask(table_oid, roleid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
| AclMode pg_class_aclmask | ( | Oid | table_oid, | |
| Oid | roleid, | |||
| AclMode | mask, | |||
| AclMaskHow | how | |||
| ) |
Definition at line 3601 of file aclchk.c.
References ACL_DELETE, ACL_INSERT, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_TRUNCATE, ACL_UPDATE, ACL_USAGE, acldefault(), aclmask(), allowSystemTableMods, Anum_pg_class_relacl, DatumGetAclP, DatumGetPointer, DEBUG2, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_rolcatupdate(), HeapTupleIsValid, IsSystemClass(), ObjectIdGetDatum, pfree(), ReleaseSysCache(), RELKIND_SEQUENCE, RELKIND_VIEW, RELOID, SearchSysCache1, superuser_arg(), and SysCacheGetAttr().
Referenced by ExecCheckRTEPerms(), pg_aclmask(), and pg_class_aclcheck().
{
AclMode result;
HeapTuple tuple;
Form_pg_class classForm;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
/*
* Must get the relation's tuple from pg_class
*/
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("relation with OID %u does not exist",
table_oid)));
classForm = (Form_pg_class) GETSTRUCT(tuple);
/*
* Deny anyone permission to update a system catalog unless
* pg_authid.rolcatupdate is set. (This is to let superusers protect
* themselves from themselves.) Also allow it if allowSystemTableMods.
*
* As of 7.4 we have some updatable system views; those shouldn't be
* protected in this way. Assume the view rules can take care of
* themselves. ACL_USAGE is if we ever have system sequences.
*/
if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
IsSystemClass(classForm) &&
classForm->relkind != RELKIND_VIEW &&
!has_rolcatupdate(roleid) &&
!allowSystemTableMods)
{
#ifdef ACLDEBUG
elog(DEBUG2, "permission denied for system catalog update");
#endif
mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE);
}
/*
* Otherwise, superusers bypass all permission-checking.
*/
if (superuser_arg(roleid))
{
#ifdef ACLDEBUG
elog(DEBUG2, "OID %u is superuser, home free", roleid);
#endif
ReleaseSysCache(tuple);
return mask;
}
/*
* Normal case: get the relation's ACL from pg_class
*/
ownerId = classForm->relowner;
aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
&isNull);
if (isNull)
{
/* No ACL, so build default ACL */
switch (classForm->relkind)
{
case RELKIND_SEQUENCE:
acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
break;
default:
acl = acldefault(ACL_OBJECT_RELATION, ownerId);
break;
}
aclDatum = (Datum) 0;
}
else
{
/* detoast rel's ACL if necessary */
acl = DatumGetAclP(aclDatum);
}
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
ReleaseSysCache(tuple);
return result;
}
Definition at line 4518 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), RELOID, SearchSysCache1, and superuser_arg().
Referenced by AlterSequence(), analyze_rel(), ATExecChangeOwner(), ATPrepSetStatistics(), ATSimplePermissions(), check_object_ownership(), CheckRelationOwnership(), cluster_rel(), DefineQueryRewrite(), EnableDisableRule(), ExecuteTruncate(), get_tables_to_cluster(), MergeAttributes(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForReindexIndex(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackOwnsTable(), RangeVarGetAndCheckCreationNamespace(), renameatt_check(), and vacuum_rel().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(class_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("relation with OID %u does not exist", class_oid)));
ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4962 of file aclchk.c.
References COLLOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by check_object_ownership().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(coll_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("collation with OID %u does not exist", coll_oid)));
ownerId = ((Form_pg_collation) GETSTRUCT(tuple))->collowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4988 of file aclchk.c.
References CONVOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by check_object_ownership().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(conv_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("conversion with OID %u does not exist", conv_oid)));
ownerId = ((Form_pg_conversion) GETSTRUCT(tuple))->conowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4406 of file aclchk.c.
References ACLMASK_ANY, and pg_database_aclmask().
Referenced by AlterSchemaOwner_internal(), calculate_database_size(), CheckMyDatabase(), CreateSchemaCommand(), has_database_privilege_id(), has_database_privilege_id_id(), has_database_privilege_id_name(), has_database_privilege_name(), has_database_privilege_name_id(), has_database_privilege_name_name(), InitTempTableNamespace(), pg_namespace_aclmask(), and RenameSchema().
{
if (pg_database_aclmask(db_oid, roleid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
| AclMode pg_database_aclmask | ( | Oid | db_oid, | |
| Oid | roleid, | |||
| AclMode | mask, | |||
| AclMaskHow | how | |||
| ) |
Definition at line 3698 of file aclchk.c.
References ACL_OBJECT_DATABASE, acldefault(), aclmask(), Anum_pg_database_datacl, DATABASEOID, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), and SysCacheGetAttr().
Referenced by pg_aclmask(), and pg_database_aclcheck().
{
AclMode result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return mask;
/*
* Get the database's ACL from pg_database
*/
tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database with OID %u does not exist", db_oid)));
ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
aclDatum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datacl,
&isNull);
if (isNull)
{
/* No ACL, so build default ACL */
acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
aclDatum = (Datum) 0;
}
else
{
/* detoast ACL if necessary */
acl = DatumGetAclP(aclDatum);
}
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
ReleaseSysCache(tuple);
return result;
}
Definition at line 4936 of file aclchk.c.
References DATABASEOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by AlterDatabase(), AlterDatabaseOwner(), AlterDatabaseSet(), AlterRoleSet(), analyze_rel(), check_object_ownership(), createdb(), CreateProceduralLanguage(), dropdb(), movedb(), ReindexDatabase(), RenameDatabase(), and vacuum_rel().
{
HeapTuple tuple;
Oid dba;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database with OID %u does not exist", db_oid)));
dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, dba);
}
Definition at line 4909 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, EVENTTRIGGEROID, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by AlterEventTrigger(), AlterEventTriggerOwner_internal(), and check_object_ownership().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(EVENTTRIGGEROID, ObjectIdGetDatum(et_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("event trigger with OID %u does not exist",
et_oid)));
ownerId = ((Form_pg_event_trigger) GETSTRUCT(tuple))->evtowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 5014 of file aclchk.c.
References AccessShareLock, BTEqualStrategyNumber, ereport, errcode(), errmsg(), ERROR, ExtensionOidIndexId, ExtensionRelationId, GETSTRUCT, has_privs_of_role(), heap_close, heap_open(), HeapTupleIsValid, ObjectIdAttributeNumber, ObjectIdGetDatum, ScanKeyInit(), SnapshotNow, superuser_arg(), systable_beginscan(), systable_endscan(), and systable_getnext().
Referenced by AlterExtensionNamespace(), check_object_ownership(), ExecAlterExtensionContentsStmt(), and ExecAlterExtensionStmt().
{
Relation pg_extension;
ScanKeyData entry[1];
SysScanDesc scan;
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
/* There's no syscache for pg_extension, so do it the hard way */
pg_extension = heap_open(ExtensionRelationId, AccessShareLock);
ScanKeyInit(&entry[0],
ObjectIdAttributeNumber,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(ext_oid));
scan = systable_beginscan(pg_extension,
ExtensionOidIndexId, true,
SnapshotNow, 1, entry);
tuple = systable_getnext(scan);
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("extension with OID %u does not exist", ext_oid)));
ownerId = ((Form_pg_extension) GETSTRUCT(tuple))->extowner;
systable_endscan(scan);
heap_close(pg_extension, AccessShareLock);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4481 of file aclchk.c.
References ACLMASK_ANY, and pg_foreign_data_wrapper_aclmask().
Referenced by AlterForeignServerOwner_internal(), CreateForeignServer(), has_foreign_data_wrapper_privilege_id(), has_foreign_data_wrapper_privilege_id_id(), has_foreign_data_wrapper_privilege_id_name(), has_foreign_data_wrapper_privilege_name(), has_foreign_data_wrapper_privilege_name_id(), and has_foreign_data_wrapper_privilege_name_name().
{
if (pg_foreign_data_wrapper_aclmask(fdw_oid, roleid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
| AclMode pg_foreign_data_wrapper_aclmask | ( | Oid | fdw_oid, | |
| Oid | roleid, | |||
| AclMode | mask, | |||
| AclMaskHow | how | |||
| ) |
Definition at line 4078 of file aclchk.c.
References ACL_OBJECT_FDW, acldefault(), aclmask(), Anum_pg_foreign_data_wrapper_fdwacl, DatumGetAclP, DatumGetPointer, ereport, errmsg(), ERROR, FOREIGNDATAWRAPPEROID, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), and SysCacheGetAttr().
Referenced by pg_aclmask(), and pg_foreign_data_wrapper_aclcheck().
{
AclMode result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
Form_pg_foreign_data_wrapper fdwForm;
/* Bypass permission checks for superusers */
if (superuser_arg(roleid))
return mask;
/*
* Must get the FDW's tuple from pg_foreign_data_wrapper
*/
tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(fdw_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errmsg("foreign-data wrapper with OID %u does not exist",
fdw_oid)));
fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
/*
* Normal case: get the FDW's ACL from pg_foreign_data_wrapper
*/
ownerId = fdwForm->fdwowner;
aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
Anum_pg_foreign_data_wrapper_fdwacl, &isNull);
if (isNull)
{
/* No ACL, so build default ACL */
acl = acldefault(ACL_OBJECT_FDW, ownerId);
aclDatum = (Datum) 0;
}
else
{
/* detoast rel's ACL if necessary */
acl = DatumGetAclP(aclDatum);
}
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
ReleaseSysCache(tuple);
return result;
}
Definition at line 4855 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, FOREIGNDATAWRAPPEROID, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by check_object_ownership().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(srv_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("foreign-data wrapper with OID %u does not exist",
srv_oid)));
ownerId = ((Form_pg_foreign_data_wrapper) GETSTRUCT(tuple))->fdwowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4494 of file aclchk.c.
References ACLMASK_ANY, and pg_foreign_server_aclmask().
Referenced by CreateForeignTable(), get_connect_string(), has_server_privilege_id(), has_server_privilege_id_id(), has_server_privilege_id_name(), has_server_privilege_name(), has_server_privilege_name_id(), has_server_privilege_name_name(), and user_mapping_ddl_aclcheck().
{
if (pg_foreign_server_aclmask(srv_oid, roleid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
| AclMode pg_foreign_server_aclmask | ( | Oid | srv_oid, | |
| Oid | roleid, | |||
| AclMode | mask, | |||
| AclMaskHow | how | |||
| ) |
Definition at line 4139 of file aclchk.c.
References ACL_OBJECT_FOREIGN_SERVER, acldefault(), aclmask(), Anum_pg_foreign_server_srvacl, DatumGetAclP, DatumGetPointer, ereport, errmsg(), ERROR, FOREIGNSERVEROID, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), and SysCacheGetAttr().
Referenced by pg_aclmask(), and pg_foreign_server_aclcheck().
{
AclMode result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
Form_pg_foreign_server srvForm;
/* Bypass permission checks for superusers */
if (superuser_arg(roleid))
return mask;
/*
* Must get the FDW's tuple from pg_foreign_data_wrapper
*/
tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errmsg("foreign server with OID %u does not exist",
srv_oid)));
srvForm = (Form_pg_foreign_server) GETSTRUCT(tuple);
/*
* Normal case: get the foreign server's ACL from pg_foreign_server
*/
ownerId = srvForm->srvowner;
aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
Anum_pg_foreign_server_srvacl, &isNull);
if (isNull)
{
/* No ACL, so build default ACL */
acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
aclDatum = (Datum) 0;
}
else
{
/* detoast rel's ACL if necessary */
acl = DatumGetAclP(aclDatum);
}
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
ReleaseSysCache(tuple);
return result;
}
Definition at line 4882 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, FOREIGNSERVEROID, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by AlterForeignServer(), AlterForeignServerOwner_internal(), check_object_ownership(), and user_mapping_ddl_aclcheck().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("foreign server with OID %u does not exist",
srv_oid)));
ownerId = ((Form_pg_foreign_server) GETSTRUCT(tuple))->srvowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4430 of file aclchk.c.
References ACLMASK_ANY, and pg_language_aclmask().
Referenced by CreateFunction(), ExecuteDoStmt(), has_language_privilege_id(), has_language_privilege_id_id(), has_language_privilege_id_name(), has_language_privilege_name(), has_language_privilege_name_id(), and has_language_privilege_name_name().
{
if (pg_language_aclmask(lang_oid, roleid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
| AclMode pg_language_aclmask | ( | Oid | lang_oid, | |
| Oid | roleid, | |||
| AclMode | mask, | |||
| AclMaskHow | how | |||
| ) |
Definition at line 3806 of file aclchk.c.
References ACL_OBJECT_LANGUAGE, acldefault(), aclmask(), Anum_pg_language_lanacl, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, LANGOID, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), and SysCacheGetAttr().
Referenced by pg_aclmask(), and pg_language_aclcheck().
{
AclMode result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return mask;
/*
* Get the language's ACL from pg_language
*/
tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lang_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("language with OID %u does not exist", lang_oid)));
ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
&isNull);
if (isNull)
{
/* No ACL, so build default ACL */
acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
aclDatum = (Datum) 0;
}
else
{
/* detoast ACL if necessary */
acl = DatumGetAclP(aclDatum);
}
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
ReleaseSysCache(tuple);
return result;
}
Definition at line 4622 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, LANGOID, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by check_object_ownership(), and create_proc_lang().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lan_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("language with OID %u does not exist", lan_oid)));
ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
| AclResult pg_largeobject_aclcheck_snapshot | ( | Oid | lobj_oid, | |
| Oid | roleid, | |||
| AclMode | mode, | |||
| Snapshot | snapshot | |||
| ) |
Definition at line 4442 of file aclchk.c.
References ACLMASK_ANY, and pg_largeobject_aclmask_snapshot().
Referenced by lo_read(), lo_truncate_internal(), and lo_write().
{
if (pg_largeobject_aclmask_snapshot(lobj_oid, roleid, mode,
ACLMASK_ANY, snapshot) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
| AclMode pg_largeobject_aclmask_snapshot | ( | Oid | lobj_oid, | |
| Oid | roleid, | |||
| AclMode | mask, | |||
| AclMaskHow | how, | |||
| Snapshot | snapshot | |||
| ) |
Definition at line 3866 of file aclchk.c.
References AccessShareLock, ACL_OBJECT_LARGEOBJECT, acldefault(), aclmask(), Anum_pg_largeobject_metadata_lomacl, BTEqualStrategyNumber, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, heap_close, heap_getattr, heap_open(), HeapTupleIsValid, LargeObjectMetadataOidIndexId, LargeObjectMetadataRelationId, ObjectIdAttributeNumber, ObjectIdGetDatum, pfree(), RelationGetDescr, ScanKeyInit(), superuser_arg(), systable_beginscan(), systable_endscan(), and systable_getnext().
Referenced by pg_aclmask(), and pg_largeobject_aclcheck_snapshot().
{
AclMode result;
Relation pg_lo_meta;
ScanKeyData entry[1];
SysScanDesc scan;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return mask;
/*
* Get the largeobject's ACL from pg_language_metadata
*/
pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
AccessShareLock);
ScanKeyInit(&entry[0],
ObjectIdAttributeNumber,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(lobj_oid));
scan = systable_beginscan(pg_lo_meta,
LargeObjectMetadataOidIndexId, true,
snapshot, 1, entry);
tuple = systable_getnext(scan);
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("large object %u does not exist", lobj_oid)));
ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
aclDatum = heap_getattr(tuple, Anum_pg_largeobject_metadata_lomacl,
RelationGetDescr(pg_lo_meta), &isNull);
if (isNull)
{
/* No ACL, so build default ACL */
acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
aclDatum = (Datum) 0;
}
else
{
/* detoast ACL if necessary */
acl = DatumGetAclP(aclDatum);
}
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
systable_endscan(scan);
heap_close(pg_lo_meta, AccessShareLock);
return result;
}
Definition at line 4651 of file aclchk.c.
References AccessShareLock, BTEqualStrategyNumber, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), heap_close, heap_open(), HeapTupleIsValid, LargeObjectMetadataOidIndexId, LargeObjectMetadataRelationId, ObjectIdAttributeNumber, ObjectIdGetDatum, ScanKeyInit(), SnapshotNow, superuser_arg(), systable_beginscan(), systable_endscan(), and systable_getnext().
Referenced by check_object_ownership(), and lo_unlink().
{
Relation pg_lo_meta;
ScanKeyData entry[1];
SysScanDesc scan;
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
/* There's no syscache for pg_largeobject_metadata */
pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
AccessShareLock);
ScanKeyInit(&entry[0],
ObjectIdAttributeNumber,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(lobj_oid));
scan = systable_beginscan(pg_lo_meta,
LargeObjectMetadataOidIndexId, true,
SnapshotNow, 1, entry);
tuple = systable_getnext(scan);
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("large object %u does not exist", lobj_oid)));
ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
systable_endscan(scan);
heap_close(pg_lo_meta, AccessShareLock);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4456 of file aclchk.c.
References ACLMASK_ANY, and pg_namespace_aclmask().
Referenced by AlterExtensionNamespace(), AlterObjectNamespace_internal(), AlterObjectOwner_internal(), AlterObjectRename_internal(), AlterTypeOwner(), ATExecChangeOwner(), compute_return_type(), CreateConversionCommand(), CreateFunction(), DefineAggregate(), DefineCollation(), DefineDomain(), DefineEnum(), DefineIndex(), DefineOpClass(), DefineOperator(), DefineOpFamily(), DefineRange(), DefineTSConfiguration(), DefineTSDictionary(), DefineType(), get_other_operator(), HandleFunctionRequest(), has_schema_privilege_id(), has_schema_privilege_id_id(), has_schema_privilege_id_name(), has_schema_privilege_name(), has_schema_privilege_name_id(), has_schema_privilege_name_name(), LookupCreationNamespace(), LookupExplicitNamespace(), RangeVarCallbackForAlterRelation(), RangeVarGetAndCheckCreationNamespace(), recomputeNamespacePath(), and SetDefaultACLsInSchemas().
{
if (pg_namespace_aclmask(nsp_oid, roleid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
| AclMode pg_namespace_aclmask | ( | Oid | nsp_oid, | |
| Oid | roleid, | |||
| AclMode | mask, | |||
| AclMaskHow | how | |||
| ) |
Definition at line 3939 of file aclchk.c.
References ACL_CREATE_TEMP, ACL_OBJECT_NAMESPACE, ACLCHECK_OK, acldefault(), aclmask(), Anum_pg_namespace_nspacl, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, isTempNamespace(), MyDatabaseId, NAMESPACEOID, ObjectIdGetDatum, pfree(), pg_database_aclcheck(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), and SysCacheGetAttr().
Referenced by pg_aclmask(), and pg_namespace_aclcheck().
{
AclMode result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return mask;
/*
* If we have been assigned this namespace as a temp namespace, check to
* make sure we have CREATE TEMP permission on the database, and if so act
* as though we have all standard (but not GRANT OPTION) permissions on
* the namespace. If we don't have CREATE TEMP, act as though we have
* only USAGE (and not CREATE) rights.
*
* This may seem redundant given the check in InitTempTableNamespace, but
* it really isn't since current user ID may have changed since then. The
* upshot of this behavior is that a SECURITY DEFINER function can create
* temp tables that can then be accessed (if permission is granted) by
* code in the same session that doesn't have permissions to create temp
* tables.
*
* XXX Would it be safe to ereport a special error message as
* InitTempTableNamespace does? Returning zero here means we'll get a
* generic "permission denied for schema pg_temp_N" message, which is not
* remarkably user-friendly.
*/
if (isTempNamespace(nsp_oid))
{
if (pg_database_aclcheck(MyDatabaseId, roleid,
ACL_CREATE_TEMP) == ACLCHECK_OK)
return mask & ACL_ALL_RIGHTS_NAMESPACE;
else
return mask & ACL_USAGE;
}
/*
* Get the schema's ACL from pg_namespace
*/
tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_SCHEMA),
errmsg("schema with OID %u does not exist", nsp_oid)));
ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspacl,
&isNull);
if (isNull)
{
/* No ACL, so build default ACL */
acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
aclDatum = (Datum) 0;
}
else
{
/* detoast ACL if necessary */
acl = DatumGetAclP(aclDatum);
}
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
ReleaseSysCache(tuple);
return result;
}
Definition at line 4694 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, NAMESPACEOID, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by AlterSchemaOwner_internal(), check_object_ownership(), RangeVarCallbackForDropRelation(), RemoveObjects(), and RenameSchema().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_SCHEMA),
errmsg("schema with OID %u does not exist", nsp_oid)));
ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4747 of file aclchk.c.
References CLAOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by check_object_ownership().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opc_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("operator class with OID %u does not exist",
opc_oid)));
ownerId = ((Form_pg_opclass) GETSTRUCT(tuple))->opcowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4570 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, OPEROID, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by AlterOpFamilyAdd(), check_object_ownership(), DefineOpClass(), and OperatorCreate().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(oper_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("operator with OID %u does not exist", oper_oid)));
ownerId = ((Form_pg_operator) GETSTRUCT(tuple))->oprowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4774 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, OPFAMILYOID, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by check_object_ownership().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opf_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("operator family with OID %u does not exist",
opf_oid)));
ownerId = ((Form_pg_opfamily) GETSTRUCT(tuple))->opfowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4418 of file aclchk.c.
References ACLMASK_ANY, and pg_proc_aclmask().
Referenced by CreateConversionCommand(), CreateTrigger(), DefineOperator(), ExecEvalArrayCoerceExpr(), ExecInitAgg(), ExecInitWindowAgg(), findRangeCanonicalFunction(), findRangeSubtypeDiffFunction(), HandleFunctionRequest(), has_function_privilege_id(), has_function_privilege_id_id(), has_function_privilege_id_name(), has_function_privilege_name(), has_function_privilege_name_id(), has_function_privilege_name_name(), init_fcache(), initialize_peragg(), inline_function(), inline_set_returning_function(), and lookup_agg_function().
{
if (pg_proc_aclmask(proc_oid, roleid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
| AclMode pg_proc_aclmask | ( | Oid | proc_oid, | |
| Oid | roleid, | |||
| AclMode | mask, | |||
| AclMaskHow | how | |||
| ) |
Definition at line 3752 of file aclchk.c.
References ACL_OBJECT_FUNCTION, acldefault(), aclmask(), Anum_pg_proc_proacl, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, pfree(), PROCOID, ReleaseSysCache(), SearchSysCache1, superuser_arg(), and SysCacheGetAttr().
Referenced by pg_aclmask(), and pg_proc_aclcheck().
{
AclMode result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return mask;
/*
* Get the function's ACL from pg_proc
*/
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function with OID %u does not exist", proc_oid)));
ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
&isNull);
if (isNull)
{
/* No ACL, so build default ACL */
acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
aclDatum = (Datum) 0;
}
else
{
/* detoast ACL if necessary */
acl = DatumGetAclP(aclDatum);
}
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
ReleaseSysCache(tuple);
return result;
}
Definition at line 4596 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, PROCOID, ReleaseSysCache(), SearchSysCache1, and superuser_arg().
Referenced by AlterFunction(), AlterOpFamilyAdd(), check_object_ownership(), DefineOpClass(), DefineType(), and ProcedureCreate().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function with OID %u does not exist", proc_oid)));
ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4468 of file aclchk.c.
References ACLMASK_ANY, and pg_tablespace_aclmask().
Referenced by ATPrepSetTableSpace(), calculate_tablespace_size(), check_temp_tablespaces(), createdb(), DefineIndex(), DefineRelation(), has_tablespace_privilege_id(), has_tablespace_privilege_id_id(), has_tablespace_privilege_id_name(), has_tablespace_privilege_name(), has_tablespace_privilege_name_id(), has_tablespace_privilege_name_name(), movedb(), and PrepareTempTablespaces().
{
if (pg_tablespace_aclmask(spc_oid, roleid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
| AclMode pg_tablespace_aclmask | ( | Oid | spc_oid, | |
| Oid | roleid, | |||
| AclMode | mask, | |||
| AclMaskHow | how | |||
| ) |
Definition at line 4021 of file aclchk.c.
References ACL_OBJECT_TABLESPACE, acldefault(), aclmask(), Anum_pg_tablespace_spcacl, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), SysCacheGetAttr(), and TABLESPACEOID.
Referenced by pg_aclmask(), and pg_tablespace_aclcheck().
{
AclMode result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return mask;
/*
* Get the tablespace's ACL from pg_tablespace
*/
tuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("tablespace with OID %u does not exist", spc_oid)));
ownerId = ((Form_pg_tablespace) GETSTRUCT(tuple))->spcowner;
aclDatum = SysCacheGetAttr(TABLESPACEOID, tuple,
Anum_pg_tablespace_spcacl,
&isNull);
if (isNull)
{
/* No ACL, so build default ACL */
acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
aclDatum = (Datum) 0;
}
else
{
/* detoast ACL if necessary */
acl = DatumGetAclP(aclDatum);
}
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
ReleaseSysCache(tuple);
return result;
}
Definition at line 4720 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, superuser_arg(), and TABLESPACEOID.
Referenced by AlterTableSpaceOptions(), check_object_ownership(), DropTableSpace(), and RenameTableSpace().
{
HeapTuple spctuple;
Oid spcowner;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
/* Search syscache for pg_tablespace */
spctuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
if (!HeapTupleIsValid(spctuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("tablespace with OID %u does not exist", spc_oid)));
spcowner = ((Form_pg_tablespace) GETSTRUCT(spctuple))->spcowner;
ReleaseSysCache(spctuple);
return has_privs_of_role(roleid, spcowner);
}
Definition at line 4828 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, superuser_arg(), and TSCONFIGOID.
Referenced by AlterTSConfiguration(), and check_object_ownership().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfg_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("text search configuration with OID %u does not exist",
cfg_oid)));
ownerId = ((Form_pg_ts_config) GETSTRUCT(tuple))->cfgowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4801 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, superuser_arg(), and TSDICTOID.
Referenced by AlterTSDictionary(), and check_object_ownership().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dict_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("text search dictionary with OID %u does not exist",
dict_oid)));
ownerId = ((Form_pg_ts_dict) GETSTRUCT(tuple))->dictowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
Definition at line 4506 of file aclchk.c.
References ACLMASK_ANY, and pg_type_aclmask().
Referenced by AggregateCreate(), ATExecAddColumn(), ATPrepAlterColumnType(), BuildDescForRelation(), compute_return_type(), CreateCast(), DefineDomain(), DefineOperator(), DefineRelation(), examine_parameter_list(), has_type_privilege_id(), has_type_privilege_id_id(), has_type_privilege_id_name(), has_type_privilege_name(), has_type_privilege_name_id(), has_type_privilege_name_name(), and transformTableLikeClause().
{
if (pg_type_aclmask(type_oid, roleid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
| AclMode pg_type_aclmask | ( | Oid | type_oid, | |
| Oid | roleid, | |||
| AclMode | mask, | |||
| AclMaskHow | how | |||
| ) |
Definition at line 4199 of file aclchk.c.
References ACL_OBJECT_TYPE, acldefault(), aclmask(), Anum_pg_type_typacl, DatumGetAclP, DatumGetPointer, ereport, errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1, superuser_arg(), SysCacheGetAttr(), and TYPEOID.
Referenced by pg_aclmask(), and pg_type_aclcheck().
{
AclMode result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
Form_pg_type typeForm;
/* Bypass permission checks for superusers */
if (superuser_arg(roleid))
return mask;
/*
* Must get the type's tuple from pg_type
*/
tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errmsg("type with OID %u does not exist",
type_oid)));
typeForm = (Form_pg_type) GETSTRUCT(tuple);
/* "True" array types don't manage permissions of their own */
if (typeForm->typelem != 0 && typeForm->typlen == -1)
{
Oid elttype_oid = typeForm->typelem;
ReleaseSysCache(tuple);
tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(elttype_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errmsg("type with OID %u does not exist",
type_oid)));
typeForm = (Form_pg_type) GETSTRUCT(tuple);
}
/*
* Normal case: get the type's ACL from pg_type
*/
ownerId = typeForm->typowner;
aclDatum = SysCacheGetAttr(TYPEOID, tuple,
Anum_pg_type_typacl, &isNull);
if (isNull)
{
/* No ACL, so build default ACL */
acl = acldefault(ACL_OBJECT_TYPE, ownerId);
aclDatum = (Datum) 0;
}
else
{
/* detoast rel's ACL if necessary */
acl = DatumGetAclP(aclDatum);
}
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
ReleaseSysCache(tuple);
return result;
}
Definition at line 4544 of file aclchk.c.
References ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, superuser_arg(), and TYPEOID.
Referenced by AlterTypeNamespace_oid(), AlterTypeOwner(), check_object_ownership(), checkDomainOwner(), checkEnumOwner(), CreateCast(), DefineOpClass(), and RenameType().
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type with OID %u does not exist", type_oid)));
ownerId = ((Form_pg_type) GETSTRUCT(tuple))->typowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
| static const char * privilege_to_string | ( | AclMode | privilege | ) | [static] |
Definition at line 3227 of file aclchk.c.
References ACL_CONNECT, ACL_CREATE, ACL_CREATE_TEMP, ACL_DELETE, ACL_EXECUTE, ACL_INSERT, ACL_REFERENCES, ACL_SELECT, ACL_TRIGGER, ACL_TRUNCATE, ACL_UPDATE, ACL_USAGE, elog, and ERROR.
Referenced by ExecAlterDefaultPrivilegesStmt(), ExecGrant_Relation(), and ExecuteGrantStmt().
{
switch (privilege)
{
case ACL_INSERT:
return "INSERT";
case ACL_SELECT:
return "SELECT";
case ACL_UPDATE:
return "UPDATE";
case ACL_DELETE:
return "DELETE";
case ACL_TRUNCATE:
return "TRUNCATE";
case ACL_REFERENCES:
return "REFERENCES";
case ACL_TRIGGER:
return "TRIGGER";
case ACL_EXECUTE:
return "EXECUTE";
case ACL_USAGE:
return "USAGE";
case ACL_CREATE:
return "CREATE";
case ACL_CREATE_TEMP:
return "TEMP";
case ACL_CONNECT:
return "CONNECT";
default:
elog(ERROR, "unrecognized privilege: %d", (int) privilege);
}
return NULL; /* appease compiler */
}
| void RemoveDefaultACLById | ( | Oid | defaclOid | ) |
Definition at line 1441 of file aclchk.c.
References BTEqualStrategyNumber, DefaultAclOidIndexId, DefaultAclRelationId, elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, ObjectIdAttributeNumber, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), simple_heap_delete(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.
Referenced by doDeletion().
{
Relation rel;
ScanKeyData skey[1];
SysScanDesc scan;
HeapTuple tuple;
rel = heap_open(DefaultAclRelationId, RowExclusiveLock);
ScanKeyInit(&skey[0],
ObjectIdAttributeNumber,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(defaclOid));
scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
SnapshotNow, 1, skey);
tuple = systable_getnext(scan);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "could not find tuple for default ACL %u", defaclOid);
simple_heap_delete(rel, &tuple->t_self);
systable_endscan(scan);
heap_close(rel, RowExclusiveLock);
}
Definition at line 1316 of file aclchk.c.
References AccessShareLock, InternalGrant::all_privs, InternalDefaultACL::all_privs, InternalGrant::behavior, InternalDefaultACL::behavior, BTEqualStrategyNumber, InternalGrant::col_privs, DatabaseRelationId, DEFACLOBJ_FUNCTION, DEFACLOBJ_RELATION, DEFACLOBJ_SEQUENCE, DEFACLOBJ_TYPE, DefaultAclOidIndexId, DefaultAclRelationId, elog, ERROR, ExecGrantStmt_oids(), ForeignDataWrapperRelationId, ForeignServerRelationId, GETSTRUCT, InternalGrant::grant_option, InternalDefaultACL::grant_option, InternalGrant::grantees, InternalDefaultACL::grantees, heap_close, heap_open(), HeapTupleIsValid, InternalGrant::is_grant, InternalDefaultACL::is_grant, LanguageRelationId, LargeObjectRelationId, list_make1_oid, NamespaceRelationId, InternalDefaultACL::nspid, ObjectIdAttributeNumber, ObjectIdGetDatum, InternalGrant::objects, InternalGrant::objtype, InternalDefaultACL::objtype, InternalGrant::privileges, InternalDefaultACL::privileges, ProcedureRelationId, RelationRelationId, InternalDefaultACL::roleid, ScanKeyInit(), SetDefaultACL(), SnapshotNow, systable_beginscan(), systable_endscan(), systable_getnext(), TableSpaceRelationId, and TypeRelationId.
Referenced by shdepDropOwned().
{
if (classid == DefaultAclRelationId)
{
InternalDefaultACL iacls;
Form_pg_default_acl pg_default_acl_tuple;
Relation rel;
ScanKeyData skey[1];
SysScanDesc scan;
HeapTuple tuple;
/* first fetch info needed by SetDefaultACL */
rel = heap_open(DefaultAclRelationId, AccessShareLock);
ScanKeyInit(&skey[0],
ObjectIdAttributeNumber,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(objid));
scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
SnapshotNow, 1, skey);
tuple = systable_getnext(scan);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "could not find tuple for default ACL %u", objid);
pg_default_acl_tuple = (Form_pg_default_acl) GETSTRUCT(tuple);
iacls.roleid = pg_default_acl_tuple->defaclrole;
iacls.nspid = pg_default_acl_tuple->defaclnamespace;
switch (pg_default_acl_tuple->defaclobjtype)
{
case DEFACLOBJ_RELATION:
iacls.objtype = ACL_OBJECT_RELATION;
break;
case DEFACLOBJ_SEQUENCE:
iacls.objtype = ACL_OBJECT_SEQUENCE;
break;
case DEFACLOBJ_FUNCTION:
iacls.objtype = ACL_OBJECT_FUNCTION;
break;
case DEFACLOBJ_TYPE:
iacls.objtype = ACL_OBJECT_TYPE;
break;
default:
/* Shouldn't get here */
elog(ERROR, "unexpected default ACL type: %d",
(int) pg_default_acl_tuple->defaclobjtype);
break;
}
systable_endscan(scan);
heap_close(rel, AccessShareLock);
iacls.is_grant = false;
iacls.all_privs = true;
iacls.privileges = ACL_NO_RIGHTS;
iacls.grantees = list_make1_oid(roleid);
iacls.grant_option = false;
iacls.behavior = DROP_CASCADE;
/* Do it */
SetDefaultACL(&iacls);
}
else
{
InternalGrant istmt;
switch (classid)
{
case RelationRelationId:
/* it's OK to use RELATION for a sequence */
istmt.objtype = ACL_OBJECT_RELATION;
break;
case DatabaseRelationId:
istmt.objtype = ACL_OBJECT_DATABASE;
break;
case TypeRelationId:
istmt.objtype = ACL_OBJECT_TYPE;
break;
case ProcedureRelationId:
istmt.objtype = ACL_OBJECT_FUNCTION;
break;
case LanguageRelationId:
istmt.objtype = ACL_OBJECT_LANGUAGE;
break;
case LargeObjectRelationId:
istmt.objtype = ACL_OBJECT_LARGEOBJECT;
break;
case NamespaceRelationId:
istmt.objtype = ACL_OBJECT_NAMESPACE;
break;
case TableSpaceRelationId:
istmt.objtype = ACL_OBJECT_TABLESPACE;
break;
case ForeignServerRelationId:
istmt.objtype = ACL_OBJECT_FOREIGN_SERVER;
break;
case ForeignDataWrapperRelationId:
istmt.objtype = ACL_OBJECT_FDW;
break;
default:
elog(ERROR, "unexpected object class %u", classid);
break;
}
istmt.is_grant = false;
istmt.objects = list_make1_oid(objid);
istmt.all_privs = true;
istmt.privileges = ACL_NO_RIGHTS;
istmt.col_privs = NIL;
istmt.grantees = list_make1_oid(roleid);
istmt.grant_option = false;
istmt.behavior = DROP_CASCADE;
ExecGrantStmt_oids(&istmt);
}
}
| static AclMode restrict_and_check_grant | ( | bool | is_grant, | |
| AclMode | avail_goptions, | |||
| bool | all_privs, | |||
| AclMode | privileges, | |||
| Oid | objectId, | |||
| Oid | grantorId, | |||
| AclObjectKind | objkind, | |||
| const char * | objname, | |||
| AttrNumber | att_number, | |||
| const char * | colname | |||
| ) | [static] |
Definition at line 240 of file aclchk.c.
References ACL_GRANT_OPTION_FOR, ACL_KIND_CLASS, ACL_KIND_COLUMN, ACL_KIND_DATABASE, ACL_KIND_EVENT_TRIGGER, ACL_KIND_FDW, ACL_KIND_FOREIGN_SERVER, ACL_KIND_LANGUAGE, ACL_KIND_LARGEOBJECT, ACL_KIND_NAMESPACE, ACL_KIND_PROC, ACL_KIND_SEQUENCE, ACL_KIND_TABLESPACE, ACL_KIND_TYPE, ACL_NO_RIGHTS, ACL_OPTION_TO_PRIVS, aclcheck_error(), aclcheck_error_col(), ACLCHECK_NO_PRIV, ACLMASK_ANY, elog, ereport, errcode(), errmsg(), ERROR, pg_aclmask(), and WARNING.
Referenced by ExecGrant_Attribute(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), and ExecGrant_Type().
{
AclMode this_privileges;
AclMode whole_mask;
switch (objkind)
{
case ACL_KIND_COLUMN:
whole_mask = ACL_ALL_RIGHTS_COLUMN;
break;
case ACL_KIND_CLASS:
whole_mask = ACL_ALL_RIGHTS_RELATION;
break;
case ACL_KIND_SEQUENCE:
whole_mask = ACL_ALL_RIGHTS_SEQUENCE;
break;
case ACL_KIND_DATABASE:
whole_mask = ACL_ALL_RIGHTS_DATABASE;
break;
case ACL_KIND_PROC:
whole_mask = ACL_ALL_RIGHTS_FUNCTION;
break;
case ACL_KIND_LANGUAGE:
whole_mask = ACL_ALL_RIGHTS_LANGUAGE;
break;
case ACL_KIND_LARGEOBJECT:
whole_mask = ACL_ALL_RIGHTS_LARGEOBJECT;
break;
case ACL_KIND_NAMESPACE:
whole_mask = ACL_ALL_RIGHTS_NAMESPACE;
break;
case ACL_KIND_TABLESPACE:
whole_mask = ACL_ALL_RIGHTS_TABLESPACE;
break;
case ACL_KIND_FDW:
whole_mask = ACL_ALL_RIGHTS_FDW;
break;
case ACL_KIND_FOREIGN_SERVER:
whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
break;
case ACL_KIND_EVENT_TRIGGER:
elog(ERROR, "grantable rights not supported for event triggers");
/* not reached, but keep compiler quiet */
return ACL_NO_RIGHTS;
case ACL_KIND_TYPE:
whole_mask = ACL_ALL_RIGHTS_TYPE;
break;
default:
elog(ERROR, "unrecognized object kind: %d", objkind);
/* not reached, but keep compiler quiet */
return ACL_NO_RIGHTS;
}
/*
* If we found no grant options, consider whether to issue a hard error.
* Per spec, having any privilege at all on the object will get you by
* here.
*/
if (avail_goptions == ACL_NO_RIGHTS)
{
if (pg_aclmask(objkind, objectId, att_number, grantorId,
whole_mask | ACL_GRANT_OPTION_FOR(whole_mask),
ACLMASK_ANY) == ACL_NO_RIGHTS)
{
if (objkind == ACL_KIND_COLUMN && colname)
aclcheck_error_col(ACLCHECK_NO_PRIV, objkind, objname, colname);
else
aclcheck_error(ACLCHECK_NO_PRIV, objkind, objname);
}
}
/*
* Restrict the operation to what we can actually grant or revoke, and
* issue a warning if appropriate. (For REVOKE this isn't quite what the
* spec says to do: the spec seems to want a warning only if no privilege
* bits actually change in the ACL. In practice that behavior seems much
* too noisy, as well as inconsistent with the GRANT case.)
*/
this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
if (is_grant)
{
if (this_privileges == 0)
{
if (objkind == ACL_KIND_COLUMN && colname)
ereport(WARNING,
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
errmsg("no privileges were granted for column \"%s\" of relation \"%s\"",
colname, objname)));
else
ereport(WARNING,
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
errmsg("no privileges were granted for \"%s\"",
objname)));
}
else if (!all_privs && this_privileges != privileges)
{
if (objkind == ACL_KIND_COLUMN && colname)
ereport(WARNING,
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
errmsg("not all privileges were granted for column \"%s\" of relation \"%s\"",
colname, objname)));
else
ereport(WARNING,
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
errmsg("not all privileges were granted for \"%s\"",
objname)));
}
}
else
{
if (this_privileges == 0)
{
if (objkind == ACL_KIND_COLUMN && colname)
ereport(WARNING,
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
errmsg("no privileges could be revoked for column \"%s\" of relation \"%s\"",
colname, objname)));
else
ereport(WARNING,
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
errmsg("no privileges could be revoked for \"%s\"",
objname)));
}
else if (!all_privs && this_privileges != privileges)
{
if (objkind == ACL_KIND_COLUMN && colname)
ereport(WARNING,
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
errmsg("not all privileges could be revoked for column \"%s\" of relation \"%s\"",
colname, objname)));
else
ereport(WARNING,
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
errmsg("not all privileges could be revoked for \"%s\"",
objname)));
}
}
return this_privileges;
}
| static void SetDefaultACL | ( | InternalDefaultACL * | iacls | ) | [static] |
Definition at line 1074 of file aclchk.c.
References ACL_NO_RIGHTS, ACL_OBJECT_FUNCTION, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TYPE, aclcopy(), acldefault(), aclequal(), aclitemsort(), aclmembers(), InternalDefaultACL::all_privs, Anum_pg_default_acl_defaclacl, Anum_pg_default_acl_defaclnamespace, Anum_pg_default_acl_defaclobjtype, Anum_pg_default_acl_defaclrole, InternalDefaultACL::behavior, CatalogUpdateIndexes(), CharGetDatum, ObjectAddress::classId, DatumGetAclPCopy, DEFACLROLENSPOBJ, DefaultAclRelationId, DEPENDENCY_AUTO, DROP_RESTRICT, elog, ERROR, InternalDefaultACL::grant_option, InternalDefaultACL::grantees, heap_close, heap_form_tuple(), heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvokeObjectPostAlterHook, InvokeObjectPostCreateHook, InternalDefaultACL::is_grant, make_empty_acl(), MemSet, merge_acl_with_grant(), InternalDefaultACL::nspid, NULL, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, InternalDefaultACL::objtype, OidIsValid, performDeletion(), PointerGetDatum, InternalDefaultACL::privileges, recordDependencyOn(), recordDependencyOnOwner(), RelationGetDescr, ReleaseSysCache(), InternalDefaultACL::roleid, RowExclusiveLock, SearchSysCache3, simple_heap_insert(), simple_heap_update(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.
Referenced by RemoveRoleFromObjectACL(), and SetDefaultACLsInSchemas().
{
AclMode this_privileges = iacls->privileges;
char objtype;
Relation rel;
HeapTuple tuple;
bool isNew;
Acl *def_acl;
Acl *old_acl;
Acl *new_acl;
HeapTuple newtuple;
Datum values[Natts_pg_default_acl];
bool nulls[Natts_pg_default_acl];
bool replaces[Natts_pg_default_acl];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
rel = heap_open(DefaultAclRelationId, RowExclusiveLock);
/*
* The default for a global entry is the hard-wired default ACL for the
* particular object type. The default for non-global entries is an empty
* ACL. This must be so because global entries replace the hard-wired
* defaults, while others are added on.
*/
if (!OidIsValid(iacls->nspid))
def_acl = acldefault(iacls->objtype, iacls->roleid);
else
def_acl = make_empty_acl();
/*
* Convert ACL object type to pg_default_acl object type and handle
* all_privs option
*/
switch (iacls->objtype)
{
case ACL_OBJECT_RELATION:
objtype = DEFACLOBJ_RELATION;
if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
this_privileges = ACL_ALL_RIGHTS_RELATION;
break;
case ACL_OBJECT_SEQUENCE:
objtype = DEFACLOBJ_SEQUENCE;
if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
break;
case ACL_OBJECT_FUNCTION:
objtype = DEFACLOBJ_FUNCTION;
if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
this_privileges = ACL_ALL_RIGHTS_FUNCTION;
break;
case ACL_OBJECT_TYPE:
objtype = DEFACLOBJ_TYPE;
if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
this_privileges = ACL_ALL_RIGHTS_TYPE;
break;
default:
elog(ERROR, "unrecognized objtype: %d",
(int) iacls->objtype);
objtype = 0; /* keep compiler quiet */
break;
}
/* Search for existing row for this object type in catalog */
tuple = SearchSysCache3(DEFACLROLENSPOBJ,
ObjectIdGetDatum(iacls->roleid),
ObjectIdGetDatum(iacls->nspid),
CharGetDatum(objtype));
if (HeapTupleIsValid(tuple))
{
Datum aclDatum;
bool isNull;
aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
Anum_pg_default_acl_defaclacl,
&isNull);
if (!isNull)
old_acl = DatumGetAclPCopy(aclDatum);
else
old_acl = NULL; /* this case shouldn't happen, probably */
isNew = false;
}
else
{
old_acl = NULL;
isNew = true;
}
if (old_acl != NULL)
{
/*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information. Collect data before
* merge_acl_with_grant throws away old_acl.
*/
noldmembers = aclmembers(old_acl, &oldmembers);
}
else
{
/* If no or null entry, start with the default ACL value */
old_acl = aclcopy(def_acl);
/* There are no old member roles according to the catalogs */
noldmembers = 0;
oldmembers = NULL;
}
/*
* Generate new ACL. Grantor of rights is always the same as the target
* role.
*/
new_acl = merge_acl_with_grant(old_acl,
iacls->is_grant,
iacls->grant_option,
iacls->behavior,
iacls->grantees,
this_privileges,
iacls->roleid,
iacls->roleid);
/*
* If the result is the same as the default value, we do not need an
* explicit pg_default_acl entry, and should in fact remove the entry if
* it exists. Must sort both arrays to compare properly.
*/
aclitemsort(new_acl);
aclitemsort(def_acl);
if (aclequal(new_acl, def_acl))
{
/* delete old entry, if indeed there is one */
if (!isNew)
{
ObjectAddress myself;
/*
* The dependency machinery will take care of removing all
* associated dependency entries. We use DROP_RESTRICT since
* there shouldn't be anything depending on this entry.
*/
myself.classId = DefaultAclRelationId;
myself.objectId = HeapTupleGetOid(tuple);
myself.objectSubId = 0;
performDeletion(&myself, DROP_RESTRICT, 0);
}
}
else
{
/* Prepare to insert or update pg_default_acl entry */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
if (isNew)
{
/* insert new entry */
values[Anum_pg_default_acl_defaclrole - 1] = ObjectIdGetDatum(iacls->roleid);
values[Anum_pg_default_acl_defaclnamespace - 1] = ObjectIdGetDatum(iacls->nspid);
values[Anum_pg_default_acl_defaclobjtype - 1] = CharGetDatum(objtype);
values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
simple_heap_insert(rel, newtuple);
}
else
{
/* update existing entry */
values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
replaces[Anum_pg_default_acl_defaclacl - 1] = true;
newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
values, nulls, replaces);
simple_heap_update(rel, &newtuple->t_self, newtuple);
}
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(rel, newtuple);
/* these dependencies don't change in an update */
if (isNew)
{
/* dependency on role */
recordDependencyOnOwner(DefaultAclRelationId,
HeapTupleGetOid(newtuple),
iacls->roleid);
/* dependency on namespace */
if (OidIsValid(iacls->nspid))
{
ObjectAddress myself,
referenced;
myself.classId = DefaultAclRelationId;
myself.objectId = HeapTupleGetOid(newtuple);
myself.objectSubId = 0;
referenced.classId = NamespaceRelationId;
referenced.objectId = iacls->nspid;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
}
}
/*
* Update the shared dependency ACL info
*/
nnewmembers = aclmembers(new_acl, &newmembers);
updateAclDependencies(DefaultAclRelationId,
HeapTupleGetOid(newtuple), 0,
iacls->roleid,
noldmembers, oldmembers,
nnewmembers, newmembers);
if (isNew)
InvokeObjectPostCreateHook(DefaultAclRelationId,
HeapTupleGetOid(newtuple), 0);
else
InvokeObjectPostAlterHook(DefaultAclRelationId,
HeapTupleGetOid(newtuple), 0);
}
if (HeapTupleIsValid(tuple))
ReleaseSysCache(tuple);
heap_close(rel, RowExclusiveLock);
}
| static void SetDefaultACLsInSchemas | ( | InternalDefaultACL * | iacls, | |
| List * | nspnames | |||
| ) | [static] |
Definition at line 1031 of file aclchk.c.
References ACL_CREATE, ACL_KIND_NAMESPACE, aclcheck_error(), ACLCHECK_OK, get_namespace_oid(), lfirst, NIL, InternalDefaultACL::nspid, pg_namespace_aclcheck(), InternalDefaultACL::roleid, SetDefaultACL(), and strVal.
Referenced by ExecAlterDefaultPrivilegesStmt().
{
if (nspnames == NIL)
{
/* Set database-wide permissions if no schema was specified */
iacls->nspid = InvalidOid;
SetDefaultACL(iacls);
}
else
{
/* Look up the schema OIDs and do permissions checks */
ListCell *nspcell;
foreach(nspcell, nspnames)
{
char *nspname = strVal(lfirst(nspcell));
AclResult aclresult;
/*
* Note that we must do the permissions check against the target
* role not the calling user. We require CREATE privileges, since
* without CREATE you won't be able to do anything using the
* default privs anyway.
*/
iacls->nspid = get_namespace_oid(nspname, false);
aclresult = pg_namespace_aclcheck(iacls->nspid, iacls->roleid,
ACL_CREATE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
nspname);
SetDefaultACL(iacls);
}
}
}
| static AclMode string_to_privilege | ( | const char * | privname | ) | [static] |
Definition at line 3190 of file aclchk.c.
References ereport, errcode(), errmsg(), and ERROR.
Referenced by ExecAlterDefaultPrivilegesStmt(), ExecGrant_Relation(), and ExecuteGrantStmt().
{
if (strcmp(privname, "insert") == 0)
return ACL_INSERT;
if (strcmp(privname, "select") == 0)
return ACL_SELECT;
if (strcmp(privname, "update") == 0)
return ACL_UPDATE;
if (strcmp(privname, "delete") == 0)
return ACL_DELETE;
if (strcmp(privname, "truncate") == 0)
return ACL_TRUNCATE;
if (strcmp(privname, "references") == 0)
return ACL_REFERENCES;
if (strcmp(privname, "trigger") == 0)
return ACL_TRIGGER;
if (strcmp(privname, "execute") == 0)
return ACL_EXECUTE;
if (strcmp(privname, "usage") == 0)
return ACL_USAGE;
if (strcmp(privname, "create") == 0)
return ACL_CREATE;
if (strcmp(privname, "temporary") == 0)
return ACL_CREATE_TEMP;
if (strcmp(privname, "temp") == 0)
return ACL_CREATE_TEMP;
if (strcmp(privname, "connect") == 0)
return ACL_CONNECT;
if (strcmp(privname, "rule") == 0)
return 0; /* ignore old RULE privileges */
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unrecognized privilege type \"%s\"", privname)));
return 0; /* appease compiler */
}
const char* const no_priv_msg[MAX_ACL_KIND] [static] |
const char* const not_owner_msg[MAX_ACL_KIND] [static] |
1.7.1