PostgreSQL Source Code  git master
aclchk.c File Reference
#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/binary_upgrade.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_am.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_cast.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_init_privs.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_statistic_ext.h"
#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_ts_parser.h"
#include "catalog/pg_ts_template.h"
#include "catalog/pg_transform.h"
#include "commands/dbcommands.h"
#include "commands/event_trigger.h"
#include "commands/extension.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/aclchk_internal.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"
Include dependency graph for aclchk.c:

Go to the source code of this file.

Data Structures

struct  InternalDefaultACL
 

Functions

static void ExecGrantStmt_oids (InternalGrant *istmt)
 
static void ExecGrant_Relation (InternalGrant *grantStmt)
 
static void ExecGrant_Database (InternalGrant *grantStmt)
 
static void ExecGrant_Fdw (InternalGrant *grantStmt)
 
static void ExecGrant_ForeignServer (InternalGrant *grantStmt)
 
static void ExecGrant_Function (InternalGrant *grantStmt)
 
static void ExecGrant_Language (InternalGrant *grantStmt)
 
static void ExecGrant_Largeobject (InternalGrant *grantStmt)
 
static void ExecGrant_Namespace (InternalGrant *grantStmt)
 
static void ExecGrant_Tablespace (InternalGrant *grantStmt)
 
static void ExecGrant_Type (InternalGrant *grantStmt)
 
static void SetDefaultACLsInSchemas (InternalDefaultACL *iacls, List *nspnames)
 
static void SetDefaultACL (InternalDefaultACL *iacls)
 
static ListobjectNamesToOids (GrantObjectType objtype, List *objnames)
 
static ListobjectsInSchemaToOids (GrantObjectType objtype, List *nspnames)
 
static ListgetRelationsInNamespace (Oid namespaceId, char relkind)
 
static void expand_col_privileges (List *colnames, Oid table_oid, AclMode this_privileges, AclMode *col_privileges, int num_col_privileges)
 
static void expand_all_col_privileges (Oid table_oid, Form_pg_class classForm, AclMode this_privileges, AclMode *col_privileges, int num_col_privileges)
 
static AclMode string_to_privilege (const char *privname)
 
static const char * privilege_to_string (AclMode privilege)
 
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 AclMode pg_aclmask (AclObjectKind objkind, Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
 
static void recordExtensionInitPriv (Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
 
static void recordExtensionInitPrivWorker (Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
 
static Aclmerge_acl_with_grant (Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
 
void ExecuteGrantStmt (GrantStmt *stmt)
 
void ExecAlterDefaultPrivilegesStmt (ParseState *pstate, AlterDefaultPrivilegesStmt *stmt)
 
void RemoveRoleFromObjectACL (Oid roleid, Oid classid, Oid objid)
 
void RemoveDefaultACLById (Oid defaclOid)
 
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)
 
void aclcheck_error (AclResult aclerr, AclObjectKind objectkind, const char *objectname)
 
void aclcheck_error_col (AclResult aclerr, AclObjectKind objectkind, const char *objectname, const char *colname)
 
void aclcheck_error_type (AclResult aclerr, Oid typeOid)
 
AclMode pg_attribute_aclmask (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_class_aclmask (Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_database_aclmask (Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_proc_aclmask (Oid proc_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_language_aclmask (Oid lang_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_largeobject_aclmask_snapshot (Oid lobj_oid, Oid roleid, AclMode mask, AclMaskHow how, Snapshot snapshot)
 
AclMode pg_namespace_aclmask (Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_tablespace_aclmask (Oid spc_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_foreign_data_wrapper_aclmask (Oid fdw_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_foreign_server_aclmask (Oid srv_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_type_aclmask (Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclResult pg_attribute_aclcheck (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
 
AclResult pg_attribute_aclcheck_all (Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
 
AclResult pg_class_aclcheck (Oid table_oid, Oid roleid, AclMode mode)
 
AclResult pg_database_aclcheck (Oid db_oid, Oid roleid, AclMode mode)
 
AclResult pg_proc_aclcheck (Oid proc_oid, Oid roleid, AclMode mode)
 
AclResult pg_language_aclcheck (Oid lang_oid, Oid roleid, AclMode mode)
 
AclResult pg_largeobject_aclcheck_snapshot (Oid lobj_oid, Oid roleid, AclMode mode, Snapshot snapshot)
 
AclResult pg_namespace_aclcheck (Oid nsp_oid, Oid roleid, AclMode mode)
 
AclResult pg_tablespace_aclcheck (Oid spc_oid, Oid roleid, AclMode mode)
 
AclResult pg_foreign_data_wrapper_aclcheck (Oid fdw_oid, Oid roleid, AclMode mode)
 
AclResult pg_foreign_server_aclcheck (Oid srv_oid, Oid roleid, AclMode mode)
 
AclResult pg_type_aclcheck (Oid type_oid, Oid roleid, AclMode mode)
 
bool pg_class_ownercheck (Oid class_oid, Oid roleid)
 
bool pg_type_ownercheck (Oid type_oid, Oid roleid)
 
bool pg_oper_ownercheck (Oid oper_oid, Oid roleid)
 
bool pg_proc_ownercheck (Oid proc_oid, Oid roleid)
 
bool pg_language_ownercheck (Oid lan_oid, Oid roleid)
 
bool pg_largeobject_ownercheck (Oid lobj_oid, Oid roleid)
 
bool pg_namespace_ownercheck (Oid nsp_oid, Oid roleid)
 
bool pg_tablespace_ownercheck (Oid spc_oid, Oid roleid)
 
bool pg_opclass_ownercheck (Oid opc_oid, Oid roleid)
 
bool pg_opfamily_ownercheck (Oid opf_oid, Oid roleid)
 
bool pg_ts_dict_ownercheck (Oid dict_oid, Oid roleid)
 
bool pg_ts_config_ownercheck (Oid cfg_oid, Oid roleid)
 
bool pg_foreign_data_wrapper_ownercheck (Oid srv_oid, Oid roleid)
 
bool pg_foreign_server_ownercheck (Oid srv_oid, Oid roleid)
 
bool pg_event_trigger_ownercheck (Oid et_oid, Oid roleid)
 
bool pg_database_ownercheck (Oid db_oid, Oid roleid)
 
bool pg_collation_ownercheck (Oid coll_oid, Oid roleid)
 
bool pg_conversion_ownercheck (Oid conv_oid, Oid roleid)
 
bool pg_extension_ownercheck (Oid ext_oid, Oid roleid)
 
bool pg_publication_ownercheck (Oid pub_oid, Oid roleid)
 
bool pg_subscription_ownercheck (Oid sub_oid, Oid roleid)
 
bool pg_statistics_object_ownercheck (Oid stat_oid, Oid roleid)
 
bool has_createrole_privilege (Oid roleid)
 
bool has_bypassrls_privilege (Oid roleid)
 
static Aclget_default_acl_internal (Oid roleId, Oid nsp_oid, char objtype)
 
Aclget_user_default_acl (GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
 
void recordExtObjInitPriv (Oid objoid, Oid classoid)
 
void removeExtObjInitPriv (Oid objoid, Oid classoid)
 

Variables

bool binary_upgrade_record_init_privs = false
 
static const char *const no_priv_msg [MAX_ACL_KIND]
 
static const char *const not_owner_msg [MAX_ACL_KIND]
 

Function Documentation

◆ aclcheck_error()

void aclcheck_error ( AclResult  aclerr,
AclObjectKind  objectkind,
const char *  objectname 
)

Definition at line 3457 of file aclchk.c.

References ACLCHECK_NO_PRIV, ACLCHECK_NOT_OWNER, ACLCHECK_OK, elog, ereport, errcode(), errmsg(), and ERROR.

Referenced by aclcheck_error_type(), AlterCollation(), AlterDatabase(), AlterDatabaseOwner(), AlterDatabaseSet(), AlterEventTrigger(), AlterEventTriggerOwner_internal(), AlterExtensionNamespace(), AlterForeignServer(), AlterForeignServerOwner_internal(), AlterFunction(), AlterObjectNamespace_internal(), AlterObjectOwner_internal(), AlterObjectRename_internal(), AlterOperator(), AlterOpFamilyAdd(), AlterPublication(), AlterPublicationOwner_internal(), AlterRoleSet(), AlterSchemaOwner_internal(), AlterSubscription(), AlterSubscriptionOwner_internal(), AlterTableMoveAll(), AlterTableSpaceOptions(), AlterTSConfiguration(), AlterTSDictionary(), AlterTypeOwner(), ATExecChangeOwner(), ATPrepSetStatistics(), ATPrepSetTableSpace(), ATSimplePermissions(), brin_desummarize_range(), brin_summarize_range(), calculate_database_size(), calculate_tablespace_size(), call_pltcl_start_proc(), check_object_ownership(), check_temp_tablespaces(), checkFkeyPermissions(), CheckFunctionValidatorAccess(), compute_return_type(), create_proc_lang(), CreateConversionCommand(), createdb(), CreateForeignServer(), CreateForeignTable(), CreateFunction(), CreateProceduralLanguage(), CreatePublication(), CreateSchemaCommand(), CreateStatistics(), CreateTransform(), CreateTrigger(), currtid_byrelname(), currtid_byreloid(), DefineAggregate(), DefineCollation(), DefineDomain(), DefineEnum(), DefineIndex(), DefineOpClass(), DefineOperator(), DefineOpFamily(), DefineQueryRewrite(), DefineRange(), DefineRelation(), DefineTSConfiguration(), DefineTSDictionary(), DefineType(), dropdb(), DropSubscription(), DropTableSpace(), EnableDisableRule(), ExecAlterExtensionContentsStmt(), ExecAlterExtensionStmt(), ExecCheckRTPerms(), ExecInitAgg(), ExecInitExprRec(), ExecInitFunc(), ExecInitWindowAgg(), ExecuteCallStmt(), ExecuteDoStmt(), ExecuteTruncate(), findRangeCanonicalFunction(), findRangeSubtypeDiffFunction(), get_connect_string(), get_other_operator(), get_rel_from_relname(), gin_clean_pending_list(), HandleFunctionRequest(), ImportForeignSchema(), init_sexpr(), initialize_peragg(), LockTableRecurse(), lookup_agg_function(), LookupCreationNamespace(), LookupExplicitNamespace(), MergeAttributes(), movedb(), OperatorCreate(), pg_prewarm(), pgrowlocks(), ProcedureCreate(), PublicationAddTables(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForLockTable(), RangeVarCallbackForPolicy(), RangeVarCallbackForReindexIndex(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackOwnsRelation(), RangeVarCallbackOwnsTable(), RangeVarGetAndCheckCreationNamespace(), ReindexMultipleTables(), renameatt_check(), RenameDatabase(), RenameSchema(), RenameTableSpace(), restrict_and_check_grant(), transformTableLikeClause(), truncate_check_rel(), TypeCreate(), user_mapping_ddl_aclcheck(), ValidateJoinEstimator(), and ValidateRestrictionEstimator().

3459 {
3460  switch (aclerr)
3461  {
3462  case ACLCHECK_OK:
3463  /* no error, so return to caller */
3464  break;
3465  case ACLCHECK_NO_PRIV:
3466  ereport(ERROR,
3467  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3468  errmsg(no_priv_msg[objectkind], objectname)));
3469  break;
3470  case ACLCHECK_NOT_OWNER:
3471  ereport(ERROR,
3472  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3473  errmsg(not_owner_msg[objectkind], objectname)));
3474  break;
3475  default:
3476  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3477  break;
3478  }
3479 }
static const char *const no_priv_msg[MAX_ACL_KIND]
Definition: aclchk.c:3351
static const char *const not_owner_msg[MAX_ACL_KIND]
Definition: aclchk.c:3403
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219

◆ aclcheck_error_col()

void aclcheck_error_col ( AclResult  aclerr,
AclObjectKind  objectkind,
const char *  objectname,
const char *  colname 
)

Definition at line 3483 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().

3485 {
3486  switch (aclerr)
3487  {
3488  case ACLCHECK_OK:
3489  /* no error, so return to caller */
3490  break;
3491  case ACLCHECK_NO_PRIV:
3492  ereport(ERROR,
3493  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3494  errmsg("permission denied for column \"%s\" of relation \"%s\"",
3495  colname, objectname)));
3496  break;
3497  case ACLCHECK_NOT_OWNER:
3498  /* relation msg is OK since columns don't have separate owners */
3499  ereport(ERROR,
3500  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3501  errmsg(not_owner_msg[objectkind], objectname)));
3502  break;
3503  default:
3504  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3505  break;
3506  }
3507 }
static const char *const not_owner_msg[MAX_ACL_KIND]
Definition: aclchk.c:3403
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219

◆ aclcheck_error_type()

void aclcheck_error_type ( AclResult  aclerr,
Oid  typeOid 
)

Definition at line 3515 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(), CreateTransform(), DefineDomain(), DefineOpClass(), DefineOperator(), DefineRelation(), interpret_function_parameter_list(), and RenameType().

3516 {
3517  Oid element_type = get_element_type(typeOid);
3518 
3519  aclcheck_error(aclerr, ACL_KIND_TYPE, format_type_be(element_type ? element_type : typeOid));
3520 }
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2517
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457

◆ ExecAlterDefaultPrivilegesStmt()

void ExecAlterDefaultPrivilegesStmt ( ParseState pstate,
AlterDefaultPrivilegesStmt stmt 
)

Definition at line 913 of file aclchk.c.

References ACL_ALL_RIGHTS_FUNCTION, ACL_ALL_RIGHTS_NAMESPACE, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SEQUENCE, ACL_ALL_RIGHTS_TYPE, ACL_ID_PUBLIC, ACL_NO_RIGHTS, ACL_OBJECT_FUNCTION, ACL_OBJECT_NAMESPACE, ACL_OBJECT_PROCEDURE, ACL_OBJECT_RELATION, ACL_OBJECT_ROUTINE, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TYPE, generate_unaccent_rules::action, AlterDefaultPrivilegesStmt::action, InternalDefaultACL::all_privs, DefElem::arg, InternalDefaultACL::behavior, GrantStmt::behavior, check_is_member_of_role(), AccessPriv::cols, DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, get_rolespec_oid(), gettext_noop, GetUserId(), InternalDefaultACL::grant_option, GrantStmt::grant_option, InternalDefaultACL::grantees, GrantStmt::grantees, InternalDefaultACL::is_grant, GrantStmt::is_grant, lappend_oid(), lfirst, DefElem::location, NIL, InternalDefaultACL::objtype, GrantStmt::objtype, AlterDefaultPrivilegesStmt::options, parser_errposition(), AccessPriv::priv_name, privilege_to_string(), InternalDefaultACL::privileges, GrantStmt::privileges, InternalDefaultACL::roleid, ROLESPEC_PUBLIC, RoleSpec::roletype, SetDefaultACLsInSchemas(), and string_to_privilege().

Referenced by ProcessUtilitySlow().

914 {
915  GrantStmt *action = stmt->action;
916  InternalDefaultACL iacls;
917  ListCell *cell;
918  List *rolespecs = NIL;
919  List *nspnames = NIL;
920  DefElem *drolespecs = NULL;
921  DefElem *dnspnames = NULL;
922  AclMode all_privileges;
923  const char *errormsg;
924 
925  /* Deconstruct the "options" part of the statement */
926  foreach(cell, stmt->options)
927  {
928  DefElem *defel = (DefElem *) lfirst(cell);
929 
930  if (strcmp(defel->defname, "schemas") == 0)
931  {
932  if (dnspnames)
933  ereport(ERROR,
934  (errcode(ERRCODE_SYNTAX_ERROR),
935  errmsg("conflicting or redundant options"),
936  parser_errposition(pstate, defel->location)));
937  dnspnames = defel;
938  }
939  else if (strcmp(defel->defname, "roles") == 0)
940  {
941  if (drolespecs)
942  ereport(ERROR,
943  (errcode(ERRCODE_SYNTAX_ERROR),
944  errmsg("conflicting or redundant options"),
945  parser_errposition(pstate, defel->location)));
946  drolespecs = defel;
947  }
948  else
949  elog(ERROR, "option \"%s\" not recognized", defel->defname);
950  }
951 
952  if (dnspnames)
953  nspnames = (List *) dnspnames->arg;
954  if (drolespecs)
955  rolespecs = (List *) drolespecs->arg;
956 
957  /* Prepare the InternalDefaultACL representation of the statement */
958  /* roleid to be filled below */
959  /* nspid to be filled in SetDefaultACLsInSchemas */
960  iacls.is_grant = action->is_grant;
961  iacls.objtype = action->objtype;
962  /* all_privs to be filled below */
963  /* privileges to be filled below */
964  iacls.grantees = NIL; /* filled below */
965  iacls.grant_option = action->grant_option;
966  iacls.behavior = action->behavior;
967 
968  /*
969  * Convert the RoleSpec list into an Oid list. Note that at this point we
970  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
971  * there shouldn't be any additional work needed to support this case.
972  */
973  foreach(cell, action->grantees)
974  {
975  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
976  Oid grantee_uid;
977 
978  switch (grantee->roletype)
979  {
980  case ROLESPEC_PUBLIC:
981  grantee_uid = ACL_ID_PUBLIC;
982  break;
983  default:
984  grantee_uid = get_rolespec_oid(grantee, false);
985  break;
986  }
987  iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
988  }
989 
990  /*
991  * Convert action->privileges, a list of privilege strings, into an
992  * AclMode bitmask.
993  */
994  switch (action->objtype)
995  {
996  case ACL_OBJECT_RELATION:
997  all_privileges = ACL_ALL_RIGHTS_RELATION;
998  errormsg = gettext_noop("invalid privilege type %s for relation");
999  break;
1000  case ACL_OBJECT_SEQUENCE:
1001  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1002  errormsg = gettext_noop("invalid privilege type %s for sequence");
1003  break;
1004  case ACL_OBJECT_FUNCTION:
1005  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1006  errormsg = gettext_noop("invalid privilege type %s for function");
1007  break;
1008  case ACL_OBJECT_PROCEDURE:
1009  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1010  errormsg = gettext_noop("invalid privilege type %s for procedure");
1011  break;
1012  case ACL_OBJECT_ROUTINE:
1013  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1014  errormsg = gettext_noop("invalid privilege type %s for routine");
1015  break;
1016  case ACL_OBJECT_TYPE:
1017  all_privileges = ACL_ALL_RIGHTS_TYPE;
1018  errormsg = gettext_noop("invalid privilege type %s for type");
1019  break;
1020  case ACL_OBJECT_NAMESPACE:
1021  all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
1022  errormsg = gettext_noop("invalid privilege type %s for schema");
1023  break;
1024  default:
1025  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
1026  (int) action->objtype);
1027  /* keep compiler quiet */
1028  all_privileges = ACL_NO_RIGHTS;
1029  errormsg = NULL;
1030  }
1031 
1032  if (action->privileges == NIL)
1033  {
1034  iacls.all_privs = true;
1035 
1036  /*
1037  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
1038  * depending on the object type
1039  */
1040  iacls.privileges = ACL_NO_RIGHTS;
1041  }
1042  else
1043  {
1044  iacls.all_privs = false;
1045  iacls.privileges = ACL_NO_RIGHTS;
1046 
1047  foreach(cell, action->privileges)
1048  {
1049  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
1050  AclMode priv;
1051 
1052  if (privnode->cols)
1053  ereport(ERROR,
1054  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1055  errmsg("default privileges cannot be set for columns")));
1056 
1057  if (privnode->priv_name == NULL) /* parser mistake? */
1058  elog(ERROR, "AccessPriv node must specify privilege");
1059  priv = string_to_privilege(privnode->priv_name);
1060 
1061  if (priv & ~((AclMode) all_privileges))
1062  ereport(ERROR,
1063  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1064  errmsg(errormsg, privilege_to_string(priv))));
1065 
1066  iacls.privileges |= priv;
1067  }
1068  }
1069 
1070  if (rolespecs == NIL)
1071  {
1072  /* Set permissions for myself */
1073  iacls.roleid = GetUserId();
1074 
1075  SetDefaultACLsInSchemas(&iacls, nspnames);
1076  }
1077  else
1078  {
1079  /* Look up the role OIDs and do permissions checks */
1080  ListCell *rolecell;
1081 
1082  foreach(rolecell, rolespecs)
1083  {
1084  RoleSpec *rolespec = lfirst(rolecell);
1085 
1086  iacls.roleid = get_rolespec_oid(rolespec, false);
1087 
1088  /*
1089  * We insist that calling user be a member of each target role. If
1090  * he has that, he could become that role anyway via SET ROLE, so
1091  * FOR ROLE is just a syntactic convenience and doesn't give any
1092  * special privileges.
1093  */
1095 
1096  SetDefaultACLsInSchemas(&iacls, nspnames);
1097  }
1098  }
1099 }
#define NIL
Definition: pg_list.h:69
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:163
bool grant_option
Definition: aclchk.c:93
Oid GetUserId(void)
Definition: miscinit.c:284
static AclMode string_to_privilege(const char *privname)
Definition: aclchk.c:3273
bool grant_option
Definition: parsenodes.h:1878
#define gettext_noop(x)
Definition: c.h:981
int errcode(int sqlerrcode)
Definition: elog.c:575
List * cols
Definition: parsenodes.h:1908
unsigned int Oid
Definition: postgres_ext.h:31
GrantObjectType objtype
Definition: aclchk.c:89
List * grantees
Definition: aclchk.c:92
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
uint32 AclMode
Definition: parsenodes.h:70
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
int location
Definition: parsenodes.h:722
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:168
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4879
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:720
#define ACL_ALL_RIGHTS_NAMESPACE
Definition: acl.h:166
bool is_grant
Definition: parsenodes.h:1870
RoleSpecType roletype
Definition: parsenodes.h:327
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5149
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:159
DropBehavior behavior
Definition: aclchk.c:94
List * privileges
Definition: parsenodes.h:1875
DropBehavior behavior
Definition: parsenodes.h:1879
#define lfirst(lc)
Definition: pg_list.h:106
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
Definition: aclchk.c:1107
GrantObjectType objtype
Definition: parsenodes.h:1872
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_ALL_RIGHTS_RELATION
Definition: acl.h:158
#define ACL_ID_PUBLIC
Definition: acl.h:47
char * defname
Definition: parsenodes.h:719
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:3310
List * grantees
Definition: parsenodes.h:1877
#define elog
Definition: elog.h:219
AclMode privileges
Definition: aclchk.c:91
Definition: pg_list.h:45
char * priv_name
Definition: parsenodes.h:1907

◆ ExecGrant_Attribute()

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 1646 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, CatalogTupleUpdate(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum, InternalGrant::is_grant, MemSet, merge_acl_with_grant(), NameStr, Natts_pg_attribute, ObjectIdGetDatum, pfree(), PointerGetDatum, recordExtensionInitPriv(), RelationGetDescr, RelationRelationId, ReleaseSysCache(), restrict_and_check_grant(), SearchSysCache2(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.

Referenced by ExecGrant_Relation().

1649 {
1650  HeapTuple attr_tuple;
1651  Form_pg_attribute pg_attribute_tuple;
1652  Acl *old_acl;
1653  Acl *new_acl;
1654  Acl *merged_acl;
1655  Datum aclDatum;
1656  bool isNull;
1657  Oid grantorId;
1658  AclMode avail_goptions;
1659  bool need_update;
1660  HeapTuple newtuple;
1662  bool nulls[Natts_pg_attribute];
1663  bool replaces[Natts_pg_attribute];
1664  int noldmembers;
1665  int nnewmembers;
1666  Oid *oldmembers;
1667  Oid *newmembers;
1668 
1669  attr_tuple = SearchSysCache2(ATTNUM,
1670  ObjectIdGetDatum(relOid),
1671  Int16GetDatum(attnum));
1672  if (!HeapTupleIsValid(attr_tuple))
1673  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1674  attnum, relOid);
1675  pg_attribute_tuple = (Form_pg_attribute) GETSTRUCT(attr_tuple);
1676 
1677  /*
1678  * Get working copy of existing ACL. If there's no ACL, substitute the
1679  * proper default.
1680  */
1681  aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
1682  &isNull);
1683  if (isNull)
1684  {
1685  old_acl = acldefault(ACL_OBJECT_COLUMN, ownerId);
1686  /* There are no old member roles according to the catalogs */
1687  noldmembers = 0;
1688  oldmembers = NULL;
1689  }
1690  else
1691  {
1692  old_acl = DatumGetAclPCopy(aclDatum);
1693  /* Get the roles mentioned in the existing ACL */
1694  noldmembers = aclmembers(old_acl, &oldmembers);
1695  }
1696 
1697  /*
1698  * In select_best_grantor we should consider existing table-level ACL bits
1699  * as well as the per-column ACL. Build a new ACL that is their
1700  * concatenation. (This is a bit cheap and dirty compared to merging them
1701  * properly with no duplications, but it's all we need here.)
1702  */
1703  merged_acl = aclconcat(old_rel_acl, old_acl);
1704 
1705  /* Determine ID to do the grant as, and available grant options */
1706  select_best_grantor(GetUserId(), col_privileges,
1707  merged_acl, ownerId,
1708  &grantorId, &avail_goptions);
1709 
1710  pfree(merged_acl);
1711 
1712  /*
1713  * Restrict the privileges to what we can actually grant, and emit the
1714  * standards-mandated warning and error messages. Note: we don't track
1715  * whether the user actually used the ALL PRIVILEGES(columns) syntax for
1716  * each column; we just approximate it by whether all the possible
1717  * privileges are specified now. Since the all_privs flag only determines
1718  * whether a warning is issued, this seems close enough.
1719  */
1720  col_privileges =
1721  restrict_and_check_grant(istmt->is_grant, avail_goptions,
1722  (col_privileges == ACL_ALL_RIGHTS_COLUMN),
1723  col_privileges,
1724  relOid, grantorId, ACL_KIND_COLUMN,
1725  relname, attnum,
1726  NameStr(pg_attribute_tuple->attname));
1727 
1728  /*
1729  * Generate new ACL.
1730  */
1731  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
1732  istmt->grant_option,
1733  istmt->behavior, istmt->grantees,
1734  col_privileges, grantorId,
1735  ownerId);
1736 
1737  /*
1738  * We need the members of both old and new ACLs so we can correct the
1739  * shared dependency information.
1740  */
1741  nnewmembers = aclmembers(new_acl, &newmembers);
1742 
1743  /* finished building new ACL value, now insert it */
1744  MemSet(values, 0, sizeof(values));
1745  MemSet(nulls, false, sizeof(nulls));
1746  MemSet(replaces, false, sizeof(replaces));
1747 
1748  /*
1749  * If the updated ACL is empty, we can set attacl to null, and maybe even
1750  * avoid an update of the pg_attribute row. This is worth testing because
1751  * we'll come through here multiple times for any relation-level REVOKE,
1752  * even if there were never any column GRANTs. Note we are assuming that
1753  * the "default" ACL state for columns is empty.
1754  */
1755  if (ACL_NUM(new_acl) > 0)
1756  {
1757  values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl);
1758  need_update = true;
1759  }
1760  else
1761  {
1762  nulls[Anum_pg_attribute_attacl - 1] = true;
1763  need_update = !isNull;
1764  }
1765  replaces[Anum_pg_attribute_attacl - 1] = true;
1766 
1767  if (need_update)
1768  {
1769  newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
1770  values, nulls, replaces);
1771 
1772  CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
1773 
1774  /* Update initial privileges for extensions */
1776  ACL_NUM(new_acl) > 0 ? new_acl : NULL);
1777 
1778  /* Update the shared dependency ACL info */
1779  updateAclDependencies(RelationRelationId, relOid, attnum,
1780  ownerId,
1781  noldmembers, oldmembers,
1782  nnewmembers, newmembers);
1783  }
1784 
1785  pfree(new_acl);
1786 
1787  ReleaseSysCache(attr_tuple);
1788 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define ACL_ALL_RIGHTS_COLUMN
Definition: acl.h:157
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define PointerGetDatum(X)
Definition: postgres.h:562
#define RelationRelationId
Definition: pg_class.h:29
#define Int16GetDatum(X)
Definition: postgres.h:457
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:748
#define Anum_pg_attribute_attacl
Definition: pg_attribute.h:214
#define MemSet(start, val, len)
Definition: c.h:853
unsigned int Oid
Definition: postgres_ext.h:31
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:171
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_NUM(ACL)
Definition: acl.h:109
ItemPointerData t_self
Definition: htup.h:65
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5754
Acl * aclconcat(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:427
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)
Definition: aclchk.c:237
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
DropBehavior behavior
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1123
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5041
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define NameStr(name)
Definition: c.h:547
#define Natts_pg_attribute
Definition: pg_attribute.h:194
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define DatumGetAclPCopy(X)
Definition: acl.h:122

◆ ExecGrant_Database()

static void ExecGrant_Database ( InternalGrant grantStmt)
static

Definition at line 2125 of file aclchk.c.

References ACL_ALL_RIGHTS_DATABASE, ACL_KIND_DATABASE, ACL_NO_RIGHTS, ACL_OBJECT_DATABASE, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_database_datacl, InternalGrant::behavior, CatalogTupleUpdate(), 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, Natts_pg_database, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), HeapTupleData::t_self, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2126 {
2127  Relation relation;
2128  ListCell *cell;
2129 
2130  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2131  istmt->privileges = ACL_ALL_RIGHTS_DATABASE;
2132 
2134 
2135  foreach(cell, istmt->objects)
2136  {
2137  Oid datId = lfirst_oid(cell);
2138  Form_pg_database pg_database_tuple;
2139  Datum aclDatum;
2140  bool isNull;
2141  AclMode avail_goptions;
2142  AclMode this_privileges;
2143  Acl *old_acl;
2144  Acl *new_acl;
2145  Oid grantorId;
2146  Oid ownerId;
2147  HeapTuple newtuple;
2149  bool nulls[Natts_pg_database];
2150  bool replaces[Natts_pg_database];
2151  int noldmembers;
2152  int nnewmembers;
2153  Oid *oldmembers;
2154  Oid *newmembers;
2155  HeapTuple tuple;
2156 
2157  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(datId));
2158  if (!HeapTupleIsValid(tuple))
2159  elog(ERROR, "cache lookup failed for database %u", datId);
2160 
2161  pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
2162 
2163  /*
2164  * Get owner ID and working copy of existing ACL. If there's no ACL,
2165  * substitute the proper default.
2166  */
2167  ownerId = pg_database_tuple->datdba;
2168  aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
2169  RelationGetDescr(relation), &isNull);
2170  if (isNull)
2171  {
2172  old_acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
2173  /* There are no old member roles according to the catalogs */
2174  noldmembers = 0;
2175  oldmembers = NULL;
2176  }
2177  else
2178  {
2179  old_acl = DatumGetAclPCopy(aclDatum);
2180  /* Get the roles mentioned in the existing ACL */
2181  noldmembers = aclmembers(old_acl, &oldmembers);
2182  }
2183 
2184  /* Determine ID to do the grant as, and available grant options */
2185  select_best_grantor(GetUserId(), istmt->privileges,
2186  old_acl, ownerId,
2187  &grantorId, &avail_goptions);
2188 
2189  /*
2190  * Restrict the privileges to what we can actually grant, and emit the
2191  * standards-mandated warning and error messages.
2192  */
2193  this_privileges =
2194  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2195  istmt->all_privs, istmt->privileges,
2196  datId, grantorId, ACL_KIND_DATABASE,
2197  NameStr(pg_database_tuple->datname),
2198  0, NULL);
2199 
2200  /*
2201  * Generate new ACL.
2202  */
2203  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2204  istmt->grant_option, istmt->behavior,
2205  istmt->grantees, this_privileges,
2206  grantorId, ownerId);
2207 
2208  /*
2209  * We need the members of both old and new ACLs so we can correct the
2210  * shared dependency information.
2211  */
2212  nnewmembers = aclmembers(new_acl, &newmembers);
2213 
2214  /* finished building new ACL value, now insert it */
2215  MemSet(values, 0, sizeof(values));
2216  MemSet(nulls, false, sizeof(nulls));
2217  MemSet(replaces, false, sizeof(replaces));
2218 
2219  replaces[Anum_pg_database_datacl - 1] = true;
2220  values[Anum_pg_database_datacl - 1] = PointerGetDatum(new_acl);
2221 
2222  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2223  nulls, replaces);
2224 
2225  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2226 
2227  /* Update the shared dependency ACL info */
2229  ownerId,
2230  noldmembers, oldmembers,
2231  nnewmembers, newmembers);
2232 
2233  ReleaseSysCache(tuple);
2234 
2235  pfree(new_acl);
2236 
2237  /* prevent error when processing duplicate objects */
2239  }
2240 
2241  heap_close(relation, RowExclusiveLock);
2242 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define Natts_pg_database
Definition: pg_database.h:63
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
FormData_pg_database * Form_pg_database
Definition: pg_database.h:57
#define PointerGetDatum(X)
Definition: postgres.h:562
#define DatabaseRelationId
Definition: pg_database.h:29
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:748
#define MemSet(start, val, len)
Definition: c.h:853
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:171
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define Anum_pg_database_datacl
Definition: pg_database.h:76
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:774
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
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)
Definition: aclchk.c:237
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5041
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:160
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define NameStr(name)
Definition: c.h:547
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:122

◆ ExecGrant_Fdw()

static void ExecGrant_Fdw ( InternalGrant grantStmt)
static

Definition at line 2245 of file aclchk.c.

References ACL_ALL_RIGHTS_FDW, ACL_KIND_FDW, ACL_NO_RIGHTS, ACL_OBJECT_FDW, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_foreign_data_wrapper_fdwacl, InternalGrant::behavior, CatalogTupleUpdate(), 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, Natts_pg_foreign_data_wrapper, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2246 {
2247  Relation relation;
2248  ListCell *cell;
2249 
2250  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2251  istmt->privileges = ACL_ALL_RIGHTS_FDW;
2252 
2254 
2255  foreach(cell, istmt->objects)
2256  {
2257  Oid fdwid = lfirst_oid(cell);
2258  Form_pg_foreign_data_wrapper pg_fdw_tuple;
2259  Datum aclDatum;
2260  bool isNull;
2261  AclMode avail_goptions;
2262  AclMode this_privileges;
2263  Acl *old_acl;
2264  Acl *new_acl;
2265  Oid grantorId;
2266  Oid ownerId;
2267  HeapTuple tuple;
2268  HeapTuple newtuple;
2270  bool nulls[Natts_pg_foreign_data_wrapper];
2271  bool replaces[Natts_pg_foreign_data_wrapper];
2272  int noldmembers;
2273  int nnewmembers;
2274  Oid *oldmembers;
2275  Oid *newmembers;
2276 
2278  ObjectIdGetDatum(fdwid));
2279  if (!HeapTupleIsValid(tuple))
2280  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
2281 
2282  pg_fdw_tuple = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
2283 
2284  /*
2285  * Get owner ID and working copy of existing ACL. If there's no ACL,
2286  * substitute the proper default.
2287  */
2288  ownerId = pg_fdw_tuple->fdwowner;
2289  aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
2291  &isNull);
2292  if (isNull)
2293  {
2294  old_acl = acldefault(ACL_OBJECT_FDW, ownerId);
2295  /* There are no old member roles according to the catalogs */
2296  noldmembers = 0;
2297  oldmembers = NULL;
2298  }
2299  else
2300  {
2301  old_acl = DatumGetAclPCopy(aclDatum);
2302  /* Get the roles mentioned in the existing ACL */
2303  noldmembers = aclmembers(old_acl, &oldmembers);
2304  }
2305 
2306  /* Determine ID to do the grant as, and available grant options */
2307  select_best_grantor(GetUserId(), istmt->privileges,
2308  old_acl, ownerId,
2309  &grantorId, &avail_goptions);
2310 
2311  /*
2312  * Restrict the privileges to what we can actually grant, and emit the
2313  * standards-mandated warning and error messages.
2314  */
2315  this_privileges =
2316  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2317  istmt->all_privs, istmt->privileges,
2318  fdwid, grantorId, ACL_KIND_FDW,
2319  NameStr(pg_fdw_tuple->fdwname),
2320  0, NULL);
2321 
2322  /*
2323  * Generate new ACL.
2324  */
2325  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2326  istmt->grant_option, istmt->behavior,
2327  istmt->grantees, this_privileges,
2328  grantorId, ownerId);
2329 
2330  /*
2331  * We need the members of both old and new ACLs so we can correct the
2332  * shared dependency information.
2333  */
2334  nnewmembers = aclmembers(new_acl, &newmembers);
2335 
2336  /* finished building new ACL value, now insert it */
2337  MemSet(values, 0, sizeof(values));
2338  MemSet(nulls, false, sizeof(nulls));
2339  MemSet(replaces, false, sizeof(replaces));
2340 
2341  replaces[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
2343 
2344  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2345  nulls, replaces);
2346 
2347  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2348 
2349  /* Update initial privileges for extensions */
2351  new_acl);
2352 
2353  /* Update the shared dependency ACL info */
2355  HeapTupleGetOid(tuple), 0,
2356  ownerId,
2357  noldmembers, oldmembers,
2358  nnewmembers, newmembers);
2359 
2360  ReleaseSysCache(tuple);
2361 
2362  pfree(new_acl);
2363 
2364  /* prevent error when processing duplicate objects */
2366  }
2367 
2368  heap_close(relation, RowExclusiveLock);
2369 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define PointerGetDatum(X)
Definition: postgres.h:562
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:748
#define MemSet(start, val, len)
Definition: c.h:853
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:171
#define Anum_pg_foreign_data_wrapper_fdwacl
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5754
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
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)
Definition: aclchk.c:237
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define Natts_pg_foreign_data_wrapper
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define ForeignDataWrapperRelationId
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5041
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define NameStr(name)
Definition: c.h:547
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:161
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:122

◆ ExecGrant_ForeignServer()

static void ExecGrant_ForeignServer ( InternalGrant grantStmt)
static

Definition at line 2372 of file aclchk.c.

References ACL_ALL_RIGHTS_FOREIGN_SERVER, ACL_KIND_FOREIGN_SERVER, ACL_NO_RIGHTS, ACL_OBJECT_FOREIGN_SERVER, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_foreign_server_srvacl, InternalGrant::behavior, CatalogTupleUpdate(), 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, Natts_pg_foreign_server, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2373 {
2374  Relation relation;
2375  ListCell *cell;
2376 
2377  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2378  istmt->privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
2379 
2381 
2382  foreach(cell, istmt->objects)
2383  {
2384  Oid srvid = lfirst_oid(cell);
2385  Form_pg_foreign_server pg_server_tuple;
2386  Datum aclDatum;
2387  bool isNull;
2388  AclMode avail_goptions;
2389  AclMode this_privileges;
2390  Acl *old_acl;
2391  Acl *new_acl;
2392  Oid grantorId;
2393  Oid ownerId;
2394  HeapTuple tuple;
2395  HeapTuple newtuple;
2397  bool nulls[Natts_pg_foreign_server];
2398  bool replaces[Natts_pg_foreign_server];
2399  int noldmembers;
2400  int nnewmembers;
2401  Oid *oldmembers;
2402  Oid *newmembers;
2403 
2405  if (!HeapTupleIsValid(tuple))
2406  elog(ERROR, "cache lookup failed for foreign server %u", srvid);
2407 
2408  pg_server_tuple = (Form_pg_foreign_server) GETSTRUCT(tuple);
2409 
2410  /*
2411  * Get owner ID and working copy of existing ACL. If there's no ACL,
2412  * substitute the proper default.
2413  */
2414  ownerId = pg_server_tuple->srvowner;
2415  aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
2417  &isNull);
2418  if (isNull)
2419  {
2420  old_acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
2421  /* There are no old member roles according to the catalogs */
2422  noldmembers = 0;
2423  oldmembers = NULL;
2424  }
2425  else
2426  {
2427  old_acl = DatumGetAclPCopy(aclDatum);
2428  /* Get the roles mentioned in the existing ACL */
2429  noldmembers = aclmembers(old_acl, &oldmembers);
2430  }
2431 
2432  /* Determine ID to do the grant as, and available grant options */
2433  select_best_grantor(GetUserId(), istmt->privileges,
2434  old_acl, ownerId,
2435  &grantorId, &avail_goptions);
2436 
2437  /*
2438  * Restrict the privileges to what we can actually grant, and emit the
2439  * standards-mandated warning and error messages.
2440  */
2441  this_privileges =
2442  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2443  istmt->all_privs, istmt->privileges,
2444  srvid, grantorId, ACL_KIND_FOREIGN_SERVER,
2445  NameStr(pg_server_tuple->srvname),
2446  0, NULL);
2447 
2448  /*
2449  * Generate new ACL.
2450  */
2451  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2452  istmt->grant_option, istmt->behavior,
2453  istmt->grantees, this_privileges,
2454  grantorId, ownerId);
2455 
2456  /*
2457  * We need the members of both old and new ACLs so we can correct the
2458  * shared dependency information.
2459  */
2460  nnewmembers = aclmembers(new_acl, &newmembers);
2461 
2462  /* finished building new ACL value, now insert it */
2463  MemSet(values, 0, sizeof(values));
2464  MemSet(nulls, false, sizeof(nulls));
2465  MemSet(replaces, false, sizeof(replaces));
2466 
2467  replaces[Anum_pg_foreign_server_srvacl - 1] = true;
2468  values[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(new_acl);
2469 
2470  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2471  nulls, replaces);
2472 
2473  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2474 
2475  /* Update initial privileges for extensions */
2477 
2478  /* Update the shared dependency ACL info */
2480  HeapTupleGetOid(tuple), 0,
2481  ownerId,
2482  noldmembers, oldmembers,
2483  nnewmembers, newmembers);
2484 
2485  ReleaseSysCache(tuple);
2486 
2487  pfree(new_acl);
2488 
2489  /* prevent error when processing duplicate objects */
2491  }
2492 
2493  heap_close(relation, RowExclusiveLock);
2494 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define PointerGetDatum(X)
Definition: postgres.h:562
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:748
#define MemSet(start, val, len)
Definition: c.h:853
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:171
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5754
#define Anum_pg_foreign_server_srvacl
#define Natts_pg_foreign_server
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
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)
Definition: aclchk.c:237
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
FormData_pg_foreign_server * Form_pg_foreign_server
#define ForeignServerRelationId
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5041
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:162
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define NameStr(name)
Definition: c.h:547
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:122

◆ ExecGrant_Function()

static void ExecGrant_Function ( InternalGrant grantStmt)
static

Definition at line 2497 of file aclchk.c.

References ACL_ALL_RIGHTS_FUNCTION, ACL_KIND_PROC, ACL_NO_RIGHTS, ACL_OBJECT_FUNCTION, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_proc_proacl, InternalGrant::behavior, CatalogTupleUpdate(), 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, Natts_pg_proc, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, ProcedureRelationId, PROCOID, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2498 {
2499  Relation relation;
2500  ListCell *cell;
2501 
2502  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2503  istmt->privileges = ACL_ALL_RIGHTS_FUNCTION;
2504 
2506 
2507  foreach(cell, istmt->objects)
2508  {
2509  Oid funcId = lfirst_oid(cell);
2510  Form_pg_proc pg_proc_tuple;
2511  Datum aclDatum;
2512  bool isNull;
2513  AclMode avail_goptions;
2514  AclMode this_privileges;
2515  Acl *old_acl;
2516  Acl *new_acl;
2517  Oid grantorId;
2518  Oid ownerId;
2519  HeapTuple tuple;
2520  HeapTuple newtuple;
2522  bool nulls[Natts_pg_proc];
2523  bool replaces[Natts_pg_proc];
2524  int noldmembers;
2525  int nnewmembers;
2526  Oid *oldmembers;
2527  Oid *newmembers;
2528 
2529  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
2530  if (!HeapTupleIsValid(tuple))
2531  elog(ERROR, "cache lookup failed for function %u", funcId);
2532 
2533  pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
2534 
2535  /*
2536  * Get owner ID and working copy of existing ACL. If there's no ACL,
2537  * substitute the proper default.
2538  */
2539  ownerId = pg_proc_tuple->proowner;
2540  aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
2541  &isNull);
2542  if (isNull)
2543  {
2544  old_acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
2545  /* There are no old member roles according to the catalogs */
2546  noldmembers = 0;
2547  oldmembers = NULL;
2548  }
2549  else
2550  {
2551  old_acl = DatumGetAclPCopy(aclDatum);
2552  /* Get the roles mentioned in the existing ACL */
2553  noldmembers = aclmembers(old_acl, &oldmembers);
2554  }
2555 
2556  /* Determine ID to do the grant as, and available grant options */
2557  select_best_grantor(GetUserId(), istmt->privileges,
2558  old_acl, ownerId,
2559  &grantorId, &avail_goptions);
2560 
2561  /*
2562  * Restrict the privileges to what we can actually grant, and emit the
2563  * standards-mandated warning and error messages.
2564  */
2565  this_privileges =
2566  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2567  istmt->all_privs, istmt->privileges,
2568  funcId, grantorId, ACL_KIND_PROC,
2569  NameStr(pg_proc_tuple->proname),
2570  0, NULL);
2571 
2572  /*
2573  * Generate new ACL.
2574  */
2575  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2576  istmt->grant_option, istmt->behavior,
2577  istmt->grantees, this_privileges,
2578  grantorId, ownerId);
2579 
2580  /*
2581  * We need the members of both old and new ACLs so we can correct the
2582  * shared dependency information.
2583  */
2584  nnewmembers = aclmembers(new_acl, &newmembers);
2585 
2586  /* finished building new ACL value, now insert it */
2587  MemSet(values, 0, sizeof(values));
2588  MemSet(nulls, false, sizeof(nulls));
2589  MemSet(replaces, false, sizeof(replaces));
2590 
2591  replaces[Anum_pg_proc_proacl - 1] = true;
2592  values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
2593 
2594  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2595  nulls, replaces);
2596 
2597  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2598 
2599  /* Update initial privileges for extensions */
2600  recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
2601 
2602  /* Update the shared dependency ACL info */
2604  ownerId,
2605  noldmembers, oldmembers,
2606  nnewmembers, newmembers);
2607 
2608  ReleaseSysCache(tuple);
2609 
2610  pfree(new_acl);
2611 
2612  /* prevent error when processing duplicate objects */
2614  }
2615 
2616  heap_close(relation, RowExclusiveLock);
2617 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:163
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define PointerGetDatum(X)
Definition: postgres.h:562
#define ProcedureRelationId
Definition: pg_proc.h:33
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:748
#define Anum_pg_proc_proacl
Definition: pg_proc.h:118
#define MemSet(start, val, len)
Definition: c.h:853
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:171
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:949
#define Natts_pg_proc
Definition: pg_proc.h:89
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5754
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
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)
Definition: aclchk.c:237
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5041
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define NameStr(name)
Definition: c.h:547
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:122

◆ ExecGrant_Language()

static void ExecGrant_Language ( InternalGrant grantStmt)
static

Definition at line 2620 of file aclchk.c.

References ACL_ALL_RIGHTS_LANGUAGE, ACL_KIND_LANGUAGE, ACL_NO_RIGHTS, ACL_OBJECT_LANGUAGE, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_language_lanacl, InternalGrant::behavior, CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ereport, errcode(), errdetail(), 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, Natts_pg_language, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2621 {
2622  Relation relation;
2623  ListCell *cell;
2624 
2625  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2626  istmt->privileges = ACL_ALL_RIGHTS_LANGUAGE;
2627 
2629 
2630  foreach(cell, istmt->objects)
2631  {
2632  Oid langId = lfirst_oid(cell);
2633  Form_pg_language pg_language_tuple;
2634  Datum aclDatum;
2635  bool isNull;
2636  AclMode avail_goptions;
2637  AclMode this_privileges;
2638  Acl *old_acl;
2639  Acl *new_acl;
2640  Oid grantorId;
2641  Oid ownerId;
2642  HeapTuple tuple;
2643  HeapTuple newtuple;
2645  bool nulls[Natts_pg_language];
2646  bool replaces[Natts_pg_language];
2647  int noldmembers;
2648  int nnewmembers;
2649  Oid *oldmembers;
2650  Oid *newmembers;
2651 
2652  tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(langId));
2653  if (!HeapTupleIsValid(tuple))
2654  elog(ERROR, "cache lookup failed for language %u", langId);
2655 
2656  pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
2657 
2658  if (!pg_language_tuple->lanpltrusted)
2659  ereport(ERROR,
2660  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2661  errmsg("language \"%s\" is not trusted",
2662  NameStr(pg_language_tuple->lanname)),
2663  errdetail("GRANT and REVOKE are not allowed on untrusted languages, "
2664  "because only superusers can use untrusted languages.")));
2665 
2666  /*
2667  * Get owner ID and working copy of existing ACL. If there's no ACL,
2668  * substitute the proper default.
2669  */
2670  ownerId = pg_language_tuple->lanowner;
2672  &isNull);
2673  if (isNull)
2674  {
2675  old_acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
2676  /* There are no old member roles according to the catalogs */
2677  noldmembers = 0;
2678  oldmembers = NULL;
2679  }
2680  else
2681  {
2682  old_acl = DatumGetAclPCopy(aclDatum);
2683  /* Get the roles mentioned in the existing ACL */
2684  noldmembers = aclmembers(old_acl, &oldmembers);
2685  }
2686 
2687  /* Determine ID to do the grant as, and available grant options */
2688  select_best_grantor(GetUserId(), istmt->privileges,
2689  old_acl, ownerId,
2690  &grantorId, &avail_goptions);
2691 
2692  /*
2693  * Restrict the privileges to what we can actually grant, and emit the
2694  * standards-mandated warning and error messages.
2695  */
2696  this_privileges =
2697  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2698  istmt->all_privs, istmt->privileges,
2699  langId, grantorId, ACL_KIND_LANGUAGE,
2700  NameStr(pg_language_tuple->lanname),
2701  0, NULL);
2702 
2703  /*
2704  * Generate new ACL.
2705  */
2706  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2707  istmt->grant_option, istmt->behavior,
2708  istmt->grantees, this_privileges,
2709  grantorId, ownerId);
2710 
2711  /*
2712  * We need the members of both old and new ACLs so we can correct the
2713  * shared dependency information.
2714  */
2715  nnewmembers = aclmembers(new_acl, &newmembers);
2716 
2717  /* finished building new ACL value, now insert it */
2718  MemSet(values, 0, sizeof(values));
2719  MemSet(nulls, false, sizeof(nulls));
2720  MemSet(replaces, false, sizeof(replaces));
2721 
2722  replaces[Anum_pg_language_lanacl - 1] = true;
2723  values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
2724 
2725  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2726  nulls, replaces);
2727 
2728  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2729 
2730  /* Update initial privileges for extensions */
2731  recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
2732 
2733  /* Update the shared dependency ACL info */
2735  ownerId,
2736  noldmembers, oldmembers,
2737  nnewmembers, newmembers);
2738 
2739  ReleaseSysCache(tuple);
2740 
2741  pfree(new_acl);
2742 
2743  /* prevent error when processing duplicate objects */
2745  }
2746 
2747  heap_close(relation, RowExclusiveLock);
2748 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define PointerGetDatum(X)
Definition: postgres.h:562
#define Anum_pg_language_lanacl
Definition: pg_language.h:65
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:748
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:853
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:171
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:164
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5754
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
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)
Definition: aclchk.c:237
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define Natts_pg_language
Definition: pg_language.h:57
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5041
static Datum values[MAXATTR]
Definition: bootstrap.c:164
FormData_pg_language * Form_pg_language
Definition: pg_language.h:51
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:547
#define LanguageRelationId
Definition: pg_language.h:29
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:122

◆ ExecGrant_Largeobject()

static void ExecGrant_Largeobject ( InternalGrant grantStmt)
static

Definition at line 2751 of file aclchk.c.

References ACL_ALL_RIGHTS_LARGEOBJECT, ACL_KIND_LARGEOBJECT, ACL_NO_RIGHTS, ACL_OBJECT_LARGEOBJECT, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_largeobject_metadata_lomacl, InternalGrant::behavior, BTEqualStrategyNumber, CatalogTupleUpdate(), 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(), NAMEDATALEN, Natts_pg_largeobject_metadata, ObjectIdAttributeNumber, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, restrict_and_check_grant(), RowExclusiveLock, ScanKeyInit(), select_best_grantor(), snprintf(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2752 {
2753  Relation relation;
2754  ListCell *cell;
2755 
2756  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2757  istmt->privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
2758 
2761 
2762  foreach(cell, istmt->objects)
2763  {
2764  Oid loid = lfirst_oid(cell);
2765  Form_pg_largeobject_metadata form_lo_meta;
2766  char loname[NAMEDATALEN];
2767  Datum aclDatum;
2768  bool isNull;
2769  AclMode avail_goptions;
2770  AclMode this_privileges;
2771  Acl *old_acl;
2772  Acl *new_acl;
2773  Oid grantorId;
2774  Oid ownerId;
2775  HeapTuple newtuple;
2777  bool nulls[Natts_pg_largeobject_metadata];
2778  bool replaces[Natts_pg_largeobject_metadata];
2779  int noldmembers;
2780  int nnewmembers;
2781  Oid *oldmembers;
2782  Oid *newmembers;
2783  ScanKeyData entry[1];
2784  SysScanDesc scan;
2785  HeapTuple tuple;
2786 
2787  /* There's no syscache for pg_largeobject_metadata */
2788  ScanKeyInit(&entry[0],
2790  BTEqualStrategyNumber, F_OIDEQ,
2791  ObjectIdGetDatum(loid));
2792 
2793  scan = systable_beginscan(relation,
2795  NULL, 1, entry);
2796 
2797  tuple = systable_getnext(scan);
2798  if (!HeapTupleIsValid(tuple))
2799  elog(ERROR, "could not find tuple for large object %u", loid);
2800 
2801  form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
2802 
2803  /*
2804  * Get owner ID and working copy of existing ACL. If there's no ACL,
2805  * substitute the proper default.
2806  */
2807  ownerId = form_lo_meta->lomowner;
2808  aclDatum = heap_getattr(tuple,
2810  RelationGetDescr(relation), &isNull);
2811  if (isNull)
2812  {
2813  old_acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
2814  /* There are no old member roles according to the catalogs */
2815  noldmembers = 0;
2816  oldmembers = NULL;
2817  }
2818  else
2819  {
2820  old_acl = DatumGetAclPCopy(aclDatum);
2821  /* Get the roles mentioned in the existing ACL */
2822  noldmembers = aclmembers(old_acl, &oldmembers);
2823  }
2824 
2825  /* Determine ID to do the grant as, and available grant options */
2826  select_best_grantor(GetUserId(), istmt->privileges,
2827  old_acl, ownerId,
2828  &grantorId, &avail_goptions);
2829 
2830  /*
2831  * Restrict the privileges to what we can actually grant, and emit the
2832  * standards-mandated warning and error messages.
2833  */
2834  snprintf(loname, sizeof(loname), "large object %u", loid);
2835  this_privileges =
2836  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2837  istmt->all_privs, istmt->privileges,
2838  loid, grantorId, ACL_KIND_LARGEOBJECT,
2839  loname, 0, NULL);
2840 
2841  /*
2842  * Generate new ACL.
2843  */
2844  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2845  istmt->grant_option, istmt->behavior,
2846  istmt->grantees, this_privileges,
2847  grantorId, ownerId);
2848 
2849  /*
2850  * We need the members of both old and new ACLs so we can correct the
2851  * shared dependency information.
2852  */
2853  nnewmembers = aclmembers(new_acl, &newmembers);
2854 
2855  /* finished building new ACL value, now insert it */
2856  MemSet(values, 0, sizeof(values));
2857  MemSet(nulls, false, sizeof(nulls));
2858  MemSet(replaces, false, sizeof(replaces));
2859 
2860  replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
2862  = PointerGetDatum(new_acl);
2863 
2864  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2865  values, nulls, replaces);
2866 
2867  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2868 
2869  /* Update initial privileges for extensions */
2871 
2872  /* Update the shared dependency ACL info */
2874  HeapTupleGetOid(tuple), 0,
2875  ownerId,
2876  noldmembers, oldmembers,
2877  nnewmembers, newmembers);
2878 
2879  systable_endscan(scan);
2880 
2881  pfree(new_acl);
2882 
2883  /* prevent error when processing duplicate objects */
2885  }
2886 
2887  heap_close(relation, RowExclusiveLock);
2888 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define PointerGetDatum(X)
Definition: postgres.h:562
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:748
#define MemSet(start, val, len)
Definition: c.h:853
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:171
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
#define Natts_pg_largeobject_metadata
#define NAMEDATALEN
uint32 AclMode
Definition: parsenodes.h:70
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5754
#define LargeObjectMetadataOidIndexId
Definition: indexing.h:183
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:774
FormData_pg_largeobject_metadata * Form_pg_largeobject_metadata
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)
Definition: aclchk.c:237
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:165
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define LargeObjectMetadataRelationId
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5041
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define Anum_pg_largeobject_metadata_lomacl
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define LargeObjectRelationId
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:122

◆ ExecGrant_Namespace()

static void ExecGrant_Namespace ( InternalGrant grantStmt)
static

Definition at line 2891 of file aclchk.c.

References ACL_ALL_RIGHTS_NAMESPACE, ACL_KIND_NAMESPACE, ACL_NO_RIGHTS, ACL_OBJECT_NAMESPACE, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_namespace_nspacl, InternalGrant::behavior, CatalogTupleUpdate(), 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, Natts_pg_namespace, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2892 {
2893  Relation relation;
2894  ListCell *cell;
2895 
2896  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2897  istmt->privileges = ACL_ALL_RIGHTS_NAMESPACE;
2898 
2900 
2901  foreach(cell, istmt->objects)
2902  {
2903  Oid nspid = lfirst_oid(cell);
2904  Form_pg_namespace pg_namespace_tuple;
2905  Datum aclDatum;
2906  bool isNull;
2907  AclMode avail_goptions;
2908  AclMode this_privileges;
2909  Acl *old_acl;
2910  Acl *new_acl;
2911  Oid grantorId;
2912  Oid ownerId;
2913  HeapTuple tuple;
2914  HeapTuple newtuple;
2916  bool nulls[Natts_pg_namespace];
2917  bool replaces[Natts_pg_namespace];
2918  int noldmembers;
2919  int nnewmembers;
2920  Oid *oldmembers;
2921  Oid *newmembers;
2922 
2924  if (!HeapTupleIsValid(tuple))
2925  elog(ERROR, "cache lookup failed for namespace %u", nspid);
2926 
2927  pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
2928 
2929  /*
2930  * Get owner ID and working copy of existing ACL. If there's no ACL,
2931  * substitute the proper default.
2932  */
2933  ownerId = pg_namespace_tuple->nspowner;
2934  aclDatum = SysCacheGetAttr(NAMESPACENAME, tuple,
2936  &isNull);
2937  if (isNull)
2938  {
2939  old_acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
2940  /* There are no old member roles according to the catalogs */
2941  noldmembers = 0;
2942  oldmembers = NULL;
2943  }
2944  else
2945  {
2946  old_acl = DatumGetAclPCopy(aclDatum);
2947  /* Get the roles mentioned in the existing ACL */
2948  noldmembers = aclmembers(old_acl, &oldmembers);
2949  }
2950 
2951  /* Determine ID to do the grant as, and available grant options */
2952  select_best_grantor(GetUserId(), istmt->privileges,
2953  old_acl, ownerId,
2954  &grantorId, &avail_goptions);
2955 
2956  /*
2957  * Restrict the privileges to what we can actually grant, and emit the
2958  * standards-mandated warning and error messages.
2959  */
2960  this_privileges =
2961  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2962  istmt->all_privs, istmt->privileges,
2963  nspid, grantorId, ACL_KIND_NAMESPACE,
2964  NameStr(pg_namespace_tuple->nspname),
2965  0, NULL);
2966 
2967  /*
2968  * Generate new ACL.
2969  */
2970  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2971  istmt->grant_option, istmt->behavior,
2972  istmt->grantees, this_privileges,
2973  grantorId, ownerId);
2974 
2975  /*
2976  * We need the members of both old and new ACLs so we can correct the
2977  * shared dependency information.
2978  */
2979  nnewmembers = aclmembers(new_acl, &newmembers);
2980 
2981  /* finished building new ACL value, now insert it */
2982  MemSet(values, 0, sizeof(values));
2983  MemSet(nulls, false, sizeof(nulls));
2984  MemSet(replaces, false, sizeof(replaces));
2985 
2986  replaces[Anum_pg_namespace_nspacl - 1] = true;
2987  values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(new_acl);
2988 
2989  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2990  nulls, replaces);
2991 
2992  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2993 
2994  /* Update initial privileges for extensions */
2995  recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
2996 
2997  /* Update the shared dependency ACL info */
2999  ownerId,
3000  noldmembers, oldmembers,
3001  nnewmembers, newmembers);
3002 
3003  ReleaseSysCache(tuple);
3004 
3005  pfree(new_acl);
3006 
3007  /* prevent error when processing duplicate objects */
3009  }
3010 
3011  heap_close(relation, RowExclusiveLock);
3012 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
#define NamespaceRelationId
Definition: pg_namespace.h:34
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:51
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define PointerGetDatum(X)
Definition: postgres.h:562
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:748
#define MemSet(start, val, len)
Definition: c.h:853
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:171
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5754
#define ACL_ALL_RIGHTS_NAMESPACE
Definition: acl.h:166
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
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)
Definition: aclchk.c:237
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define Natts_pg_namespace
Definition: pg_namespace.h:58
#define Anum_pg_namespace_nspacl
Definition: pg_namespace.h:61
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5041
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define NameStr(name)
Definition: c.h:547
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:122

◆ ExecGrant_Relation()

static void ExecGrant_Relation ( InternalGrant grantStmt)
static

Definition at line 1794 of file aclchk.c.

References ACL_ALL_RIGHTS_COLUMN, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SEQUENCE, ACL_KIND_CLASS, ACL_KIND_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, CatalogTupleUpdate(), 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, i, InternalGrant::is_grant, lfirst, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, Natts_pg_class, ObjectIdGetDatum, InternalGrant::objects, InternalGrant::objtype, palloc0(), pfree(), PointerGetDatum, AccessPriv::priv_name, privilege_to_string(), InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, RelationRelationId, ReleaseSysCache(), RELKIND_COMPOSITE_TYPE, RELKIND_INDEX, RELKIND_SEQUENCE, RELOID, restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), string_to_privilege(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), values, and WARNING.

Referenced by ExecGrantStmt_oids().

1795 {
1796  Relation relation;
1797  Relation attRelation;
1798  ListCell *cell;
1799 
1802 
1803  foreach(cell, istmt->objects)
1804  {
1805  Oid relOid = lfirst_oid(cell);
1806  Datum aclDatum;
1807  Form_pg_class pg_class_tuple;
1808  bool isNull;
1809  AclMode this_privileges;
1810  AclMode *col_privileges;
1811  int num_col_privileges;
1812  bool have_col_privileges;
1813  Acl *old_acl;
1814  Acl *old_rel_acl;
1815  int noldmembers;
1816  Oid *oldmembers;
1817  Oid ownerId;
1818  HeapTuple tuple;
1819  ListCell *cell_colprivs;
1820 
1821  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
1822  if (!HeapTupleIsValid(tuple))
1823  elog(ERROR, "cache lookup failed for relation %u", relOid);
1824  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
1825 
1826  /* Not sensible to grant on an index */
1827  if (pg_class_tuple->relkind == RELKIND_INDEX)
1828  ereport(ERROR,
1829  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1830  errmsg("\"%s\" is an index",
1831  NameStr(pg_class_tuple->relname))));
1832 
1833  /* Composite types aren't tables either */
1834  if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
1835  ereport(ERROR,
1836  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1837  errmsg("\"%s\" is a composite type",
1838  NameStr(pg_class_tuple->relname))));
1839 
1840  /* Used GRANT SEQUENCE on a non-sequence? */
1841  if (istmt->objtype == ACL_OBJECT_SEQUENCE &&
1842  pg_class_tuple->relkind != RELKIND_SEQUENCE)
1843  ereport(ERROR,
1844  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1845  errmsg("\"%s\" is not a sequence",
1846  NameStr(pg_class_tuple->relname))));
1847 
1848  /* Adjust the default permissions based on object type */
1849  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
1850  {
1851  if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
1852  this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1853  else
1854  this_privileges = ACL_ALL_RIGHTS_RELATION;
1855  }
1856  else
1857  this_privileges = istmt->privileges;
1858 
1859  /*
1860  * The GRANT TABLE syntax can be used for sequences and non-sequences,
1861  * so we have to look at the relkind to determine the supported
1862  * permissions. The OR of table and sequence permissions were already
1863  * checked.
1864  */
1865  if (istmt->objtype == ACL_OBJECT_RELATION)
1866  {
1867  if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
1868  {
1869  /*
1870  * For backward compatibility, just throw a warning for
1871  * invalid sequence permissions when using the non-sequence
1872  * GRANT syntax.
1873  */
1874  if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
1875  {
1876  /*
1877  * Mention the object name because the user needs to know
1878  * which operations succeeded. This is required because
1879  * WARNING allows the command to continue.
1880  */
1881  ereport(WARNING,
1882  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1883  errmsg("sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges",
1884  NameStr(pg_class_tuple->relname))));
1885  this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
1886  }
1887  }
1888  else
1889  {
1890  if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
1891  {
1892  /*
1893  * USAGE is the only permission supported by sequences but
1894  * not by non-sequences. Don't mention the object name
1895  * because we didn't in the combined TABLE | SEQUENCE
1896  * check.
1897  */
1898  ereport(ERROR,
1899  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1900  errmsg("invalid privilege type %s for table",
1901  "USAGE")));
1902  }
1903  }
1904  }
1905 
1906  /*
1907  * Set up array in which we'll accumulate any column privilege bits
1908  * that need modification. The array is indexed such that entry [0]
1909  * corresponds to FirstLowInvalidHeapAttributeNumber.
1910  */
1911  num_col_privileges = pg_class_tuple->relnatts - FirstLowInvalidHeapAttributeNumber + 1;
1912  col_privileges = (AclMode *) palloc0(num_col_privileges * sizeof(AclMode));
1913  have_col_privileges = false;
1914 
1915  /*
1916  * If we are revoking relation privileges that are also column
1917  * privileges, we must implicitly revoke them from each column too,
1918  * per SQL spec. (We don't need to implicitly add column privileges
1919  * during GRANT because the permissions-checking code always checks
1920  * both relation and per-column privileges.)
1921  */
1922  if (!istmt->is_grant &&
1923  (this_privileges & ACL_ALL_RIGHTS_COLUMN) != 0)
1924  {
1925  expand_all_col_privileges(relOid, pg_class_tuple,
1926  this_privileges & ACL_ALL_RIGHTS_COLUMN,
1927  col_privileges,
1928  num_col_privileges);
1929  have_col_privileges = true;
1930  }
1931 
1932  /*
1933  * Get owner ID and working copy of existing ACL. If there's no ACL,
1934  * substitute the proper default.
1935  */
1936  ownerId = pg_class_tuple->relowner;
1937  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
1938  &isNull);
1939  if (isNull)
1940  {
1941  switch (pg_class_tuple->relkind)
1942  {
1943  case RELKIND_SEQUENCE:
1944  old_acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
1945  break;
1946  default:
1947  old_acl = acldefault(ACL_OBJECT_RELATION, ownerId);
1948  break;
1949  }
1950  /* There are no old member roles according to the catalogs */
1951  noldmembers = 0;
1952  oldmembers = NULL;
1953  }
1954  else
1955  {
1956  old_acl = DatumGetAclPCopy(aclDatum);
1957  /* Get the roles mentioned in the existing ACL */
1958  noldmembers = aclmembers(old_acl, &oldmembers);
1959  }
1960 
1961  /* Need an extra copy of original rel ACL for column handling */
1962  old_rel_acl = aclcopy(old_acl);
1963 
1964  /*
1965  * Handle relation-level privileges, if any were specified
1966  */
1967  if (this_privileges != ACL_NO_RIGHTS)
1968  {
1969  AclMode avail_goptions;
1970  Acl *new_acl;
1971  Oid grantorId;
1972  HeapTuple newtuple;
1974  bool nulls[Natts_pg_class];
1975  bool replaces[Natts_pg_class];
1976  int nnewmembers;
1977  Oid *newmembers;
1978  AclObjectKind aclkind;
1979 
1980  /* Determine ID to do the grant as, and available grant options */
1981  select_best_grantor(GetUserId(), this_privileges,
1982  old_acl, ownerId,
1983  &grantorId, &avail_goptions);
1984 
1985  switch (pg_class_tuple->relkind)
1986  {
1987  case RELKIND_SEQUENCE:
1988  aclkind = ACL_KIND_SEQUENCE;
1989  break;
1990  default:
1991  aclkind = ACL_KIND_CLASS;
1992  break;
1993  }
1994 
1995  /*
1996  * Restrict the privileges to what we can actually grant, and emit
1997  * the standards-mandated warning and error messages.
1998  */
1999  this_privileges =
2000  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2001  istmt->all_privs, this_privileges,
2002  relOid, grantorId, aclkind,
2003  NameStr(pg_class_tuple->relname),
2004  0, NULL);
2005 
2006  /*
2007  * Generate new ACL.
2008  */
2009  new_acl = merge_acl_with_grant(old_acl,
2010  istmt->is_grant,
2011  istmt->grant_option,
2012  istmt->behavior,
2013  istmt->grantees,
2014  this_privileges,
2015  grantorId,
2016  ownerId);
2017 
2018  /*
2019  * We need the members of both old and new ACLs so we can correct
2020  * the shared dependency information.
2021  */
2022  nnewmembers = aclmembers(new_acl, &newmembers);
2023 
2024  /* finished building new ACL value, now insert it */
2025  MemSet(values, 0, sizeof(values));
2026  MemSet(nulls, false, sizeof(nulls));
2027  MemSet(replaces, false, sizeof(replaces));
2028 
2029  replaces[Anum_pg_class_relacl - 1] = true;
2030  values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
2031 
2032  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2033  values, nulls, replaces);
2034 
2035  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2036 
2037  /* Update initial privileges for extensions */
2038  recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl);
2039 
2040  /* Update the shared dependency ACL info */
2042  ownerId,
2043  noldmembers, oldmembers,
2044  nnewmembers, newmembers);
2045 
2046  pfree(new_acl);
2047  }
2048 
2049  /*
2050  * Handle column-level privileges, if any were specified or implied.
2051  * We first expand the user-specified column privileges into the
2052  * array, and then iterate over all nonempty array entries.
2053  */
2054  foreach(cell_colprivs, istmt->col_privs)
2055  {
2056  AccessPriv *col_privs = (AccessPriv *) lfirst(cell_colprivs);
2057 
2058  if (col_privs->priv_name == NULL)
2059  this_privileges = ACL_ALL_RIGHTS_COLUMN;
2060  else
2061  this_privileges = string_to_privilege(col_privs->priv_name);
2062 
2063  if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
2064  ereport(ERROR,
2065  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
2066  errmsg("invalid privilege type %s for column",
2067  privilege_to_string(this_privileges))));
2068 
2069  if (pg_class_tuple->relkind == RELKIND_SEQUENCE &&
2070  this_privileges & ~((AclMode) ACL_SELECT))
2071  {
2072  /*
2073  * The only column privilege allowed on sequences is SELECT.
2074  * This is a warning not error because we do it that way for
2075  * relation-level privileges.
2076  */
2077  ereport(WARNING,
2078  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
2079  errmsg("sequence \"%s\" only supports SELECT column privileges",
2080  NameStr(pg_class_tuple->relname))));
2081 
2082  this_privileges &= (AclMode) ACL_SELECT;
2083  }
2084 
2085  expand_col_privileges(col_privs->cols, relOid,
2086  this_privileges,
2087  col_privileges,
2088  num_col_privileges);
2089  have_col_privileges = true;
2090  }
2091 
2092  if (have_col_privileges)
2093  {
2094  AttrNumber i;
2095 
2096  for (i = 0; i < num_col_privileges; i++)
2097  {
2098  if (col_privileges[i] == ACL_NO_RIGHTS)
2099  continue;
2100  ExecGrant_Attribute(istmt,
2101  relOid,
2102  NameStr(pg_class_tuple->relname),
2104  ownerId,
2105  col_privileges[i],
2106  attRelation,
2107  old_rel_acl);
2108  }
2109  }
2110 
2111  pfree(old_rel_acl);
2112  pfree(col_privileges);
2113 
2114  ReleaseSysCache(tuple);
2115 
2116  /* prevent error when processing duplicate objects */
2118  }
2119 
2120  heap_close(attRelation, RowExclusiveLock);
2121  heap_close(relation, RowExclusiveLock);
2122 }
#define Natts_pg_class
Definition: pg_class.h:102
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define Anum_pg_class_relacl
Definition: pg_class.h:133
#define ACL_ALL_RIGHTS_COLUMN
Definition: acl.h:157
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define PointerGetDatum(X)
Definition: postgres.h:562
static AclMode string_to_privilege(const char *privname)
Definition: aclchk.c:3273
#define RelationRelationId
Definition: pg_class.h:29
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:748
#define AttributeRelationId
Definition: pg_attribute.h:33
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:853
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
#define heap_close(r, l)
Definition: heapam.h:97
List * cols
Definition: parsenodes.h:1908
unsigned int Oid
Definition: postgres_ext.h:31
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:171
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
uint32 AclMode
Definition: parsenodes.h:70
static void expand_col_privileges(List *colnames, Oid table_oid, AclMode this_privileges, AclMode *col_privileges, int num_col_privileges)
Definition: aclchk.c:1563
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5754
static void expand_all_col_privileges(Oid table_oid, Form_pg_class classForm, AclMode this_privileges, AclMode *col_privileges, int num_col_privileges)
Definition: aclchk.c:1596
static void ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname, AttrNumber attnum, Oid ownerId, AclMode col_privileges, Relation attRelation, const Acl *old_rel_acl)
Definition: aclchk.c:1646
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void * palloc0(Size size)
Definition: mcxt.c:877
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)
Definition: aclchk.c:237
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define ACL_SELECT
Definition: parsenodes.h:73
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:159
Acl * aclcopy(const Acl *orig_acl)
Definition: acl.c:407
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define lfirst(lc)
Definition: pg_list.h:106
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5041
static Datum values[MAXATTR]
Definition: bootstrap.c:164
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define ACL_ALL_RIGHTS_RELATION
Definition: acl.h:158
#define NameStr(name)
Definition: c.h:547
#define RELKIND_INDEX
Definition: pg_class.h:161
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:3310
#define elog
Definition: elog.h:219
AclObjectKind
Definition: acl.h:187
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
int16 AttrNumber
Definition: attnum.h:21
char * priv_name
Definition: parsenodes.h:1907
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:122

◆ ExecGrant_Tablespace()

static void ExecGrant_Tablespace ( InternalGrant grantStmt)
static

Definition at line 3015 of file aclchk.c.

References ACL_ALL_RIGHTS_TABLESPACE, ACL_KIND_TABLESPACE, ACL_NO_RIGHTS, ACL_OBJECT_TABLESPACE, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_tablespace_spcacl, InternalGrant::behavior, CatalogTupleUpdate(), 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, Natts_pg_tablespace, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), HeapTupleData::t_self, TABLESPACEOID, TableSpaceRelationId, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

3016 {
3017  Relation relation;
3018  ListCell *cell;
3019 
3020  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
3021  istmt->privileges = ACL_ALL_RIGHTS_TABLESPACE;
3022 
3024 
3025  foreach(cell, istmt->objects)
3026  {
3027  Oid tblId = lfirst_oid(cell);
3028  Form_pg_tablespace pg_tablespace_tuple;
3029  Datum aclDatum;
3030  bool isNull;
3031  AclMode avail_goptions;
3032  AclMode this_privileges;
3033  Acl *old_acl;
3034  Acl *new_acl;
3035  Oid grantorId;
3036  Oid ownerId;
3037  HeapTuple newtuple;
3039  bool nulls[Natts_pg_tablespace];
3040  bool replaces[Natts_pg_tablespace];
3041  int noldmembers;
3042  int nnewmembers;
3043  Oid *oldmembers;
3044  Oid *newmembers;
3045  HeapTuple tuple;
3046 
3047  /* Search syscache for pg_tablespace */
3049  if (!HeapTupleIsValid(tuple))
3050  elog(ERROR, "cache lookup failed for tablespace %u", tblId);
3051 
3052  pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);
3053 
3054  /*
3055  * Get owner ID and working copy of existing ACL. If there's no ACL,
3056  * substitute the proper default.
3057  */
3058  ownerId = pg_tablespace_tuple->spcowner;
3059  aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl,
3060  RelationGetDescr(relation), &isNull);
3061  if (isNull)
3062  {
3063  old_acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
3064  /* There are no old member roles according to the catalogs */
3065  noldmembers = 0;
3066  oldmembers = NULL;
3067  }
3068  else
3069  {
3070  old_acl = DatumGetAclPCopy(aclDatum);
3071  /* Get the roles mentioned in the existing ACL */
3072  noldmembers = aclmembers(old_acl, &oldmembers);
3073  }
3074 
3075  /* Determine ID to do the grant as, and available grant options */
3076  select_best_grantor(GetUserId(), istmt->privileges,
3077  old_acl, ownerId,
3078  &grantorId, &avail_goptions);
3079 
3080  /*
3081  * Restrict the privileges to what we can actually grant, and emit the
3082  * standards-mandated warning and error messages.
3083  */
3084  this_privileges =
3085  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3086  istmt->all_privs, istmt->privileges,
3087  tblId, grantorId, ACL_KIND_TABLESPACE,
3088  NameStr(pg_tablespace_tuple->spcname),
3089  0, NULL);
3090 
3091  /*
3092  * Generate new ACL.
3093  */
3094  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3095  istmt->grant_option, istmt->behavior,
3096  istmt->grantees, this_privileges,
3097  grantorId, ownerId);
3098 
3099  /*
3100  * We need the members of both old and new ACLs so we can correct the
3101  * shared dependency information.
3102  */
3103  nnewmembers = aclmembers(new_acl, &newmembers);
3104 
3105  /* finished building new ACL value, now insert it */
3106  MemSet(values, 0, sizeof(values));
3107  MemSet(nulls, false, sizeof(nulls));
3108  MemSet(replaces, false, sizeof(replaces));
3109 
3110  replaces[Anum_pg_tablespace_spcacl - 1] = true;
3111  values[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(new_acl);
3112 
3113  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3114  nulls, replaces);
3115 
3116  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3117 
3118  /* Update the shared dependency ACL info */
3120  ownerId,
3121  noldmembers, oldmembers,
3122  nnewmembers, newmembers);
3123 
3124  ReleaseSysCache(tuple);
3125  pfree(new_acl);
3126 
3127  /* prevent error when processing duplicate objects */
3129  }
3130 
3131  heap_close(relation, RowExclusiveLock);
3132 }
#define Anum_pg_tablespace_spcacl
Definition: pg_tablespace.h:57
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define PointerGetDatum(X)
Definition: postgres.h:562
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:748
#define MemSet(start, val, len)
Definition: c.h:853
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:167
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:171
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_tablespace * Form_pg_tablespace
Definition: pg_tablespace.h:47
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:774
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
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)
Definition: aclchk.c:237
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5041
#define TableSpaceRelationId
Definition: pg_tablespace.h:29
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define NameStr(name)
Definition: c.h:547
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:122
#define Natts_pg_tablespace
Definition: pg_tablespace.h:54

◆ ExecGrant_Type()

static void ExecGrant_Type ( InternalGrant grantStmt)
static

Definition at line 3135 of file aclchk.c.

References ACL_ALL_RIGHTS_TYPE, ACL_KIND_TYPE, ACL_NO_RIGHTS, ACL_OBJECT_DOMAIN, acldefault(), aclmembers(), InternalGrant::all_privs, Anum_pg_type_typacl, InternalGrant::behavior, CatalogTupleUpdate(), 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, Natts_pg_type, ObjectIdGetDatum, InternalGrant::objects, InternalGrant::objtype, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), HeapTupleData::t_self, TYPEOID, TypeRelationId, TYPTYPE_DOMAIN, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

3136 {
3137  Relation relation;
3138  ListCell *cell;
3139 
3140  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
3141  istmt->privileges = ACL_ALL_RIGHTS_TYPE;
3142 
3144 
3145  foreach(cell, istmt->objects)
3146  {
3147  Oid typId = lfirst_oid(cell);
3148  Form_pg_type pg_type_tuple;
3149  Datum aclDatum;
3150  bool isNull;
3151  AclMode avail_goptions;
3152  AclMode this_privileges;
3153  Acl *old_acl;
3154  Acl *new_acl;
3155  Oid grantorId;
3156  Oid ownerId;
3157  HeapTuple newtuple;
3159  bool nulls[Natts_pg_type];
3160  bool replaces[Natts_pg_type];
3161  int noldmembers;
3162  int nnewmembers;
3163  Oid *oldmembers;
3164  Oid *newmembers;
3165  HeapTuple tuple;
3166 
3167  /* Search syscache for pg_type */
3168  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typId));
3169  if (!HeapTupleIsValid(tuple))
3170  elog(ERROR, "cache lookup failed for type %u", typId);
3171 
3172  pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
3173 
3174  if (pg_type_tuple->typelem != 0 && pg_type_tuple->typlen == -1)
3175  ereport(ERROR,
3176  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
3177  errmsg("cannot set privileges of array types"),
3178  errhint("Set the privileges of the element type instead.")));
3179 
3180  /* Used GRANT DOMAIN on a non-domain? */
3181  if (istmt->objtype == ACL_OBJECT_DOMAIN &&
3182  pg_type_tuple->typtype != TYPTYPE_DOMAIN)
3183  ereport(ERROR,
3184  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3185  errmsg("\"%s\" is not a domain",
3186  NameStr(pg_type_tuple->typname))));
3187 
3188  /*
3189  * Get owner ID and working copy of existing ACL. If there's no ACL,
3190  * substitute the proper default.
3191  */
3192  ownerId = pg_type_tuple->typowner;
3193  aclDatum = heap_getattr(tuple, Anum_pg_type_typacl,
3194  RelationGetDescr(relation), &isNull);
3195  if (isNull)
3196  {
3197  old_acl = acldefault(istmt->objtype, ownerId);
3198  /* There are no old member roles according to the catalogs */
3199  noldmembers = 0;
3200  oldmembers = NULL;
3201  }
3202  else
3203  {
3204  old_acl = DatumGetAclPCopy(aclDatum);
3205  /* Get the roles mentioned in the existing ACL */
3206  noldmembers = aclmembers(old_acl, &oldmembers);
3207  }
3208 
3209  /* Determine ID to do the grant as, and available grant options */
3210  select_best_grantor(GetUserId(), istmt->privileges,
3211  old_acl, ownerId,
3212  &grantorId, &avail_goptions);
3213 
3214  /*
3215  * Restrict the privileges to what we can actually grant, and emit the
3216  * standards-mandated warning and error messages.
3217  */
3218  this_privileges =
3219  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3220  istmt->all_privs, istmt->privileges,
3221  typId, grantorId, ACL_KIND_TYPE,
3222  NameStr(pg_type_tuple->typname),
3223  0, NULL);
3224 
3225  /*
3226  * Generate new ACL.
3227  */
3228  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3229  istmt->grant_option, istmt->behavior,
3230  istmt->grantees, this_privileges,
3231  grantorId, ownerId);
3232 
3233  /*
3234  * We need the members of both old and new ACLs so we can correct the
3235  * shared dependency information.
3236  */
3237  nnewmembers = aclmembers(new_acl, &newmembers);
3238 
3239  /* finished building new ACL value, now insert it */
3240  MemSet(values, 0, sizeof(values));
3241  MemSet(nulls, false, sizeof(nulls));
3242  MemSet(replaces, false, sizeof(replaces));
3243 
3244  replaces[Anum_pg_type_typacl - 1] = true;
3245  values[Anum_pg_type_typacl - 1] = PointerGetDatum(new_acl);
3246 
3247  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3248  nulls, replaces);
3249 
3250  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3251 
3252  /* Update initial privileges for extensions */
3253  recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
3254 
3255  /* Update the shared dependency ACL info */
3257  ownerId,
3258  noldmembers, oldmembers,
3259  nnewmembers, newmembers);
3260 
3261  ReleaseSysCache(tuple);
3262  pfree(new_acl);
3263 
3264  /* prevent error when processing duplicate objects */
3266  }
3267 
3268  heap_close(relation, RowExclusiveLock);
3269 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
Oid GetUserId(void)
Definition: miscinit.c:284
#define PointerGetDatum(X)
Definition: postgres.h:562
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:748
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:853
#define heap_close(r, l)
Definition: heapam.h:97
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
static Acl * merge_acl_with_grant(Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
Definition: aclchk.c:171
#define TypeRelationId
Definition: pg_type.h:34
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:168
#define ereport(elevel, rest)
Definition: elog.h:122
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5754
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:774
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
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)
Definition: aclchk.c:237
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define Natts_pg_type
Definition: pg_type.h:239
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Anum_pg_type_typacl
Definition: pg_type.h:269
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5041
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:547
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:122

◆ ExecGrantStmt_oids()

static void ExecGrantStmt_oids ( InternalGrant istmt)
static

Definition at line 573 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_PROCEDURE, ACL_OBJECT_RELATION, ACL_OBJECT_ROUTINE, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TABLESPACE, ACL_OBJECT_TYPE, elog, ERROR, EventTriggerCollectGrant(), EventTriggerSupportsGrantObjectType(), 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().

574 {
575  switch (istmt->objtype)
576  {
577  case ACL_OBJECT_RELATION:
578  case ACL_OBJECT_SEQUENCE:
579  ExecGrant_Relation(istmt);
580  break;
581  case ACL_OBJECT_DATABASE:
582  ExecGrant_Database(istmt);
583  break;
584  case ACL_OBJECT_DOMAIN:
585  case ACL_OBJECT_TYPE:
586  ExecGrant_Type(istmt);
587  break;
588  case ACL_OBJECT_FDW:
589  ExecGrant_Fdw(istmt);
590  break;
593  break;
594  case ACL_OBJECT_FUNCTION:
596  case ACL_OBJECT_ROUTINE:
597  ExecGrant_Function(istmt);
598  break;
599  case ACL_OBJECT_LANGUAGE:
600  ExecGrant_Language(istmt);
601  break;
603  ExecGrant_Largeobject(istmt);
604  break;
606  ExecGrant_Namespace(istmt);
607  break;
609  ExecGrant_Tablespace(istmt);
610  break;
611  default:
612  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
613  (int) istmt->objtype);
614  }
615 
616  /*
617  * Pass the info to event triggers about the just-executed GRANT. Note
618  * that we prefer to do it after actually executing it, because that gives
619  * the functions a chance to adjust the istmt with privileges actually
620  * granted.
621  */
624 }
static void ExecGrant_Language(InternalGrant *grantStmt)
Definition: aclchk.c:2620
static void ExecGrant_Function(InternalGrant *grantStmt)
Definition: aclchk.c:2497
static void ExecGrant_Tablespace(InternalGrant *grantStmt)
Definition: aclchk.c:3015
static void ExecGrant_Namespace(InternalGrant *grantStmt)
Definition: aclchk.c:2891
static void ExecGrant_Type(InternalGrant *grantStmt)
Definition: aclchk.c:3135
static void ExecGrant_Database(InternalGrant *grantStmt)
Definition: aclchk.c:2125
GrantObjectType objtype
#define ERROR
Definition: elog.h:43
static void ExecGrant_Fdw(InternalGrant *grantStmt)
Definition: aclchk.c:2245
static void ExecGrant_Largeobject(InternalGrant *grantStmt)
Definition: aclchk.c:2751
static void ExecGrant_Relation(InternalGrant *grantStmt)
Definition: aclchk.c:1794
bool EventTriggerSupportsGrantObjectType(GrantObjectType objtype)
void EventTriggerCollectGrant(InternalGrant *istmt)
#define elog
Definition: elog.h:219
static void ExecGrant_ForeignServer(InternalGrant *grantStmt)
Definition: aclchk.c:2372

◆ ExecuteGrantStmt()

void ExecuteGrantStmt ( GrantStmt stmt)

Definition at line 385 of file aclchk.c.

References ACL_ALL_RIGHTS_DATABASE, ACL_ALL_RIGHTS_FDW, ACL_ALL_RIGHTS_FOREIGN_SERVER, ACL_ALL_RIGHTS_FUNCTION, ACL_ALL_RIGHTS_LANGUAGE, ACL_ALL_RIGHTS_LARGEOBJECT, ACL_ALL_RIGHTS_NAMESPACE, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SEQUENCE, ACL_ALL_RIGHTS_TABLESPACE, ACL_ALL_RIGHTS_TYPE, ACL_ID_PUBLIC, ACL_NO_RIGHTS, 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_PROCEDURE, ACL_OBJECT_RELATION, ACL_OBJECT_ROUTINE, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TABLESPACE, ACL_OBJECT_TYPE, ACL_TARGET_ALL_IN_SCHEMA, ACL_TARGET_OBJECT, InternalGrant::all_privs, InternalGrant::behavior, GrantStmt::behavior, InternalGrant::col_privs, AccessPriv::cols, elog, ereport, errcode(), errmsg(), ERROR, ExecGrantStmt_oids(), get_rolespec_oid(), gettext_noop, InternalGrant::grant_option, GrantStmt::grant_option, InternalGrant::grantees, GrantStmt::grantees, InternalGrant::is_grant, GrantStmt::is_grant, lappend(), lappend_oid(), lfirst, NIL, objectNamesToOids(), InternalGrant::objects, GrantStmt::objects, objectsInSchemaToOids(), InternalGrant::objtype, GrantStmt::objtype, AccessPriv::priv_name, privilege_to_string(), InternalGrant::privileges, GrantStmt::privileges, ROLESPEC_PUBLIC, RoleSpec::roletype, string_to_privilege(), and GrantStmt::targtype.

Referenced by ProcessUtilitySlow(), and standard_ProcessUtility().

386 {
387  InternalGrant istmt;
388  ListCell *cell;
389  const char *errormsg;
390  AclMode all_privileges;
391 
392  /*
393  * Turn the regular GrantStmt into the InternalGrant form.
394  */
395  istmt.is_grant = stmt->is_grant;
396  istmt.objtype = stmt->objtype;
397 
398  /* Collect the OIDs of the target objects */
399  switch (stmt->targtype)
400  {
401  case ACL_TARGET_OBJECT:
402  istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects);
403  break;
405  istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
406  break;
407  /* ACL_TARGET_DEFAULTS should not be seen here */
408  default:
409  elog(ERROR, "unrecognized GrantStmt.targtype: %d",
410  (int) stmt->targtype);
411  }
412 
413  /* all_privs to be filled below */
414  /* privileges to be filled below */
415  istmt.col_privs = NIL; /* may get filled below */
416  istmt.grantees = NIL; /* filled below */
417  istmt.grant_option = stmt->grant_option;
418  istmt.behavior = stmt->behavior;
419 
420  /*
421  * Convert the RoleSpec list into an Oid list. Note that at this point we
422  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
423  * there shouldn't be any additional work needed to support this case.
424  */
425  foreach(cell, stmt->grantees)
426  {
427  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
428  Oid grantee_uid;
429 
430  switch (grantee->roletype)
431  {
432  case ROLESPEC_PUBLIC:
433  grantee_uid = ACL_ID_PUBLIC;
434  break;
435  default:
436  grantee_uid = get_rolespec_oid(grantee, false);
437  break;
438  }
439  istmt.grantees = lappend_oid(istmt.grantees, grantee_uid);
440  }
441 
442  /*
443  * Convert stmt->privileges, a list of AccessPriv nodes, into an AclMode
444  * bitmask. Note: objtype can't be ACL_OBJECT_COLUMN.
445  */
446  switch (stmt->objtype)
447  {
448  /*
449  * Because this might be a sequence, we test both relation and
450  * sequence bits, and later do a more limited test when we know
451  * the object type.
452  */
453  case ACL_OBJECT_RELATION:
455  errormsg = gettext_noop("invalid privilege type %s for relation");
456  break;
457  case ACL_OBJECT_SEQUENCE:
458  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
459  errormsg = gettext_noop("invalid privilege type %s for sequence");
460  break;
461  case ACL_OBJECT_DATABASE:
462  all_privileges = ACL_ALL_RIGHTS_DATABASE;
463  errormsg = gettext_noop("invalid privilege type %s for database");
464  break;
465  case ACL_OBJECT_DOMAIN:
466  all_privileges = ACL_ALL_RIGHTS_TYPE;
467  errormsg = gettext_noop("invalid privilege type %s for domain");
468  break;
469  case ACL_OBJECT_FUNCTION:
470  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
471  errormsg = gettext_noop("invalid privilege type %s for function");
472  break;
473  case ACL_OBJECT_LANGUAGE:
474  all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
475  errormsg = gettext_noop("invalid privilege type %s for language");
476  break;
478  all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
479  errormsg = gettext_noop("invalid privilege type %s for large object");
480  break;
482  all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
483  errormsg = gettext_noop("invalid privilege type %s for schema");
484  break;
486  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
487  errormsg = gettext_noop("invalid privilege type %s for procedure");
488  break;
489  case ACL_OBJECT_ROUTINE:
490  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
491  errormsg = gettext_noop("invalid privilege type %s for routine");
492  break;
494  all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
495  errormsg = gettext_noop("invalid privilege type %s for tablespace");
496  break;
497  case ACL_OBJECT_TYPE:
498  all_privileges = ACL_ALL_RIGHTS_TYPE;
499  errormsg = gettext_noop("invalid privilege type %s for type");
500  break;
501  case ACL_OBJECT_FDW:
502  all_privileges = ACL_ALL_RIGHTS_FDW;
503  errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
504  break;
506  all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
507  errormsg = gettext_noop("invalid privilege type %s for foreign server");
508  break;
509  default:
510  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
511  (int) stmt->objtype);
512  /* keep compiler quiet */
513  all_privileges = ACL_NO_RIGHTS;
514  errormsg = NULL;
515  }
516 
517  if (stmt->privileges == NIL)
518  {
519  istmt.all_privs = true;
520 
521  /*
522  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
523  * depending on the object type
524  */
525  istmt.privileges = ACL_NO_RIGHTS;
526  }
527  else
528  {
529  istmt.all_privs = false;
530  istmt.privileges = ACL_NO_RIGHTS;
531 
532  foreach(cell, stmt->privileges)
533  {
534  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
535  AclMode priv;
536 
537  /*
538  * If it's a column-level specification, we just set it aside in
539  * col_privs for the moment; but insist it's for a relation.
540  */
541  if (privnode->cols)
542  {
543  if (stmt->objtype != ACL_OBJECT_RELATION)
544  ereport(ERROR,
545  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
546  errmsg("column privileges are only valid for relations")));
547  istmt.col_privs = lappend(istmt.col_privs, privnode);
548  continue;
549  }
550 
551  if (privnode->priv_name == NULL) /* parser mistake? */
552  elog(ERROR, "AccessPriv node must specify privilege or columns");
553  priv = string_to_privilege(privnode->priv_name);
554 
555  if (priv & ~((AclMode) all_privileges))
556  ereport(ERROR,
557  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
558  errmsg(errormsg, privilege_to_string(priv))));
559 
560  istmt.privileges |= priv;
561  }
562  }
563 
564  ExecGrantStmt_oids(&istmt);
565 }
#define NIL
Definition: pg_list.h:69
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:163
static AclMode string_to_privilege(const char *privname)
Definition: aclchk.c:3273
AclMode privileges
bool grant_option
Definition: parsenodes.h:1878
#define gettext_noop(x)
Definition: c.h:981
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:167
List * cols
Definition: parsenodes.h:1908
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
static List * objectsInSchemaToOids(GrantObjectType objtype, List *nspnames)
Definition: aclchk.c:786
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:164
GrantObjectType objtype
uint32 AclMode
Definition: parsenodes.h:70
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:168
#define ereport(elevel, rest)
Definition: elog.h:122
List * lappend(List *list, void *datum)
Definition: list.c:128
#define ACL_ALL_RIGHTS_NAMESPACE
Definition: acl.h:166
bool is_grant
Definition: parsenodes.h:1870
static void ExecGrantStmt_oids(InternalGrant *istmt)
Definition: aclchk.c:573
RoleSpecType roletype
Definition: parsenodes.h:327
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5149
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:159
List * privileges
Definition: parsenodes.h:1875
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:165
DropBehavior behavior
DropBehavior behavior
Definition: parsenodes.h:1879
#define lfirst(lc)
Definition: pg_list.h:106
List * objects
Definition: parsenodes.h:1873
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:160
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:162
GrantObjectType objtype
Definition: parsenodes.h:1872
static List * objectNamesToOids(GrantObjectType objtype, List *objnames)
Definition: aclchk.c:637
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_ALL_RIGHTS_RELATION
Definition: acl.h:158
#define ACL_ID_PUBLIC
Definition: acl.h:47
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:161
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:3310
List * grantees
Definition: parsenodes.h:1877
#define elog
Definition: elog.h:219
GrantTargetType targtype
Definition: parsenodes.h:1871
char * priv_name
Definition: parsenodes.h:1907

◆ expand_all_col_privileges()

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 1596 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().

1600 {
1601  AttrNumber curr_att;
1602 
1603  Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
1604  for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
1605  curr_att <= classForm->relnatts;
1606  curr_att++)
1607  {
1608  HeapTuple attTuple;
1609  bool isdropped;
1610 
1611  if (curr_att == InvalidAttrNumber)
1612  continue;
1613 
1614  /* Skip OID column if it doesn't exist */
1615  if (curr_att == ObjectIdAttributeNumber && !classForm->relhasoids)
1616  continue;
1617 
1618  /* Views don't have any system columns at all */
1619  if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
1620  continue;
1621 
1622  attTuple = SearchSysCache2(ATTNUM,
1623  ObjectIdGetDatum(table_oid),
1624  Int16GetDatum(curr_att));
1625  if (!HeapTupleIsValid(attTuple))
1626  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1627  curr_att, table_oid);
1628 
1629  isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
1630 
1631  ReleaseSysCache(attTuple);
1632 
1633  /* ignore dropped columns */
1634  if (isdropped)
1635  continue;
1636 
1637  col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
1638  }
1639 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define Int16GetDatum(X)
Definition: postgres.h:457
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:670
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1123
#define InvalidAttrNumber
Definition: attnum.h:23
#define RELKIND_VIEW
Definition: pg_class.h:164
#define elog
Definition: elog.h:219
int16 AttrNumber
Definition: attnum.h:21

◆ expand_col_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 1563 of file aclchk.c.

References elog, ereport, errcode(), errmsg(), ERROR, FirstLowInvalidHeapAttributeNumber, get_attnum(), get_rel_name(), InvalidAttrNumber, lfirst, and strVal.

Referenced by ExecGrant_Relation().

1567 {
1568  ListCell *cell;
1569 
1570  foreach(cell, colnames)
1571  {
1572  char *colname = strVal(lfirst(cell));
1573  AttrNumber attnum;
1574 
1575  attnum = get_attnum(table_oid, colname);
1576  if (attnum == InvalidAttrNumber)
1577  ereport(ERROR,
1578  (errcode(ERRCODE_UNDEFINED_COLUMN),
1579  errmsg("column \"%s\" of relation \"%s\" does not exist",
1580  colname, get_rel_name(table_oid))));
1582  if (attnum <= 0 || attnum >= num_col_privileges)
1583  elog(ERROR, "column number out of range"); /* safety check */
1584  col_privileges[attnum] |= this_privileges;
1585  }
1586 }
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
#define ERROR
Definition: elog.h:43
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:821
#define ereport(elevel, rest)
Definition: elog.h:122
#define lfirst(lc)
Definition: pg_list.h:106
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1745
int16 AttrNumber
Definition: attnum.h:21

◆ get_default_acl_internal()

static Acl* get_default_acl_internal ( Oid  roleId,
Oid  nsp_oid,
char  objtype 
)
static

Definition at line 5272 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().

5273 {
5274  Acl *result = NULL;
5275  HeapTuple tuple;
5276 
5278  ObjectIdGetDatum(roleId),
5279  ObjectIdGetDatum(nsp_oid),
5280  CharGetDatum(objtype));
5281 
5282  if (HeapTupleIsValid(tuple))
5283  {
5284  Datum aclDatum;
5285  bool isNull;
5286 
5287  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
5289  &isNull);
5290  if (!isNull)
5291  result = DatumGetAclPCopy(aclDatum);
5292  ReleaseSysCache(tuple);
5293  }
5294 
5295  return result;
5296 }
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define Anum_pg_default_acl_defaclacl
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1134
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define CharGetDatum(X)
Definition: postgres.h:422
#define DatumGetAclPCopy(X)
Definition: acl.h:122

◆ get_user_default_acl()

Acl* get_user_default_acl ( GrantObjectType  objtype,
Oid  ownerId,
Oid  nsp_oid 
)

Definition at line 5304 of file aclchk.c.

References ACL_OBJECT_FUNCTION, ACL_OBJECT_NAMESPACE, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TYPE, acldefault(), aclequal(), aclitemsort(), aclmerge(), DEFACLOBJ_FUNCTION, DEFACLOBJ_NAMESPACE, DEFACLOBJ_RELATION, DEFACLOBJ_SEQUENCE, DEFACLOBJ_TYPE, get_default_acl_internal(), InvalidOid, and IsBootstrapProcessingMode.

Referenced by heap_create_with_catalog(), NamespaceCreate(), ProcedureCreate(), and TypeCreate().

5305 {
5306  Acl *result;
5307  Acl *glob_acl;
5308  Acl *schema_acl;
5309  Acl *def_acl;
5310  char defaclobjtype;
5311 
5312  /*
5313  * Use NULL during bootstrap, since pg_default_acl probably isn't there
5314  * yet.
5315  */
5317  return NULL;
5318 
5319  /* Check if object type is supported in pg_default_acl */
5320  switch (objtype)
5321  {
5322  case ACL_OBJECT_RELATION:
5323  defaclobjtype = DEFACLOBJ_RELATION;
5324  break;
5325 
5326  case ACL_OBJECT_SEQUENCE:
5327  defaclobjtype = DEFACLOBJ_SEQUENCE;
5328  break;
5329 
5330  case ACL_OBJECT_FUNCTION:
5331  defaclobjtype = DEFACLOBJ_FUNCTION;
5332  break;
5333 
5334  case ACL_OBJECT_TYPE:
5335  defaclobjtype = DEFACLOBJ_TYPE;
5336  break;
5337 
5338  case ACL_OBJECT_NAMESPACE:
5339  defaclobjtype = DEFACLOBJ_NAMESPACE;
5340  break;
5341 
5342  default:
5343  return NULL;
5344  }
5345 
5346  /* Look up the relevant pg_default_acl entries */
5347  glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
5348  schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
5349 
5350  /* Quick out if neither entry exists */
5351  if (glob_acl == NULL && schema_acl == NULL)
5352  return NULL;
5353 
5354  /* We need to know the hard-wired default value, too */
5355  def_acl = acldefault(objtype, ownerId);
5356 
5357  /* If there's no global entry, substitute the hard-wired default */
5358  if (glob_acl == NULL)
5359  glob_acl = def_acl;
5360 
5361  /* Merge in any per-schema privileges */
5362  result = aclmerge(glob_acl, schema_acl, ownerId);
5363 
5364  /*
5365  * For efficiency, we want to return NULL if the result equals default.
5366  * This requires sorting both arrays to get an accurate comparison.
5367  */
5368  aclitemsort(result);
5369  aclitemsort(def_acl);
5370  if (aclequal(result, def_acl))
5371  result = NULL;
5372 
5373  return result;
5374 }
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:748
static Acl * get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
Definition: aclchk.c:5272
bool aclequal(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:509
#define DEFACLOBJ_SEQUENCE
#define DEFACLOBJ_TYPE
#define InvalidOid
Definition: postgres_ext.h:36
#define DEFACLOBJ_NAMESPACE
#define DEFACLOBJ_RELATION
Acl * aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
Definition: acl.c:451
#define DEFACLOBJ_FUNCTION
void aclitemsort(Acl *acl)
Definition: acl.c:495
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:367

◆ getRelationsInNamespace()

static List * getRelationsInNamespace ( Oid  namespaceId,
char  relkind 
)
static

Definition at line 877 of file aclchk.c.

References AccessShareLock, Anum_pg_class_relkind, Anum_pg_class_relnamespace, BTEqualStrategyNumber, CharGetDatum, ForwardScanDirection, heap_beginscan_catalog(), heap_close, heap_endscan(), heap_getnext(), heap_open(), HeapTupleGetOid, lappend_oid(), NIL, ObjectIdGetDatum, RelationRelationId, and ScanKeyInit().

Referenced by objectsInSchemaToOids().

878 {
879  List *relations = NIL;
880  ScanKeyData key[2];
881  Relation rel;
882  HeapScanDesc scan;
883  HeapTuple tuple;
884 
885  ScanKeyInit(&key[0],
887  BTEqualStrategyNumber, F_OIDEQ,
888  ObjectIdGetDatum(namespaceId));
889  ScanKeyInit(&key[1],
891  BTEqualStrategyNumber, F_CHAREQ,
892  CharGetDatum(relkind));
893 
895  scan = heap_beginscan_catalog(rel, 2, key);
896 
897  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
898  {
899  relations = lappend_oid(relations, HeapTupleGetOid(tuple));
900  }
901 
902  heap_endscan(scan);
904 
905  return relations;
906 }
#define NIL
Definition: pg_list.h:69
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1565
#define RelationRelationId
Definition: pg_class.h:29
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define Anum_pg_class_relnamespace
Definition: pg_class.h:104
#define Anum_pg_class_relkind
Definition: pg_class.h:118
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1405
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1808
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define CharGetDatum(X)
Definition: postgres.h:422
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ has_bypassrls_privilege()

bool has_bypassrls_privilege ( Oid  roleid)

Definition at line 5248 of file aclchk.c.

References AUTHOID, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1(), and superuser_arg().

Referenced by check_enable_rls(), and RI_Initial_Check().

5249 {
5250  bool result = false;
5251  HeapTuple utup;
5252 
5253  /* Superusers bypass all permission checking. */
5254  if (superuser_arg(roleid))
5255  return true;
5256 
5257  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5258  if (HeapTupleIsValid(utup))
5259  {
5260  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
5261  ReleaseSysCache(utup);
5262  }
5263  return result;
5264 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:72
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
bool superuser_arg(Oid roleid)
Definition: superuser.c:57
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77

◆ has_createrole_privilege()

bool has_createrole_privilege ( Oid  roleid)

Definition at line 5229 of file aclchk.c.

References AUTHOID, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1(), and superuser_arg().

Referenced by check_object_ownership(), and have_createrole_privilege().

5230 {
5231  bool result = false;
5232  HeapTuple utup;
5233 
5234  /* Superusers bypass all permission checking. */
5235  if (superuser_arg(roleid))
5236  return true;
5237 
5238  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5239  if (HeapTupleIsValid(utup))
5240  {
5241  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
5242  ReleaseSysCache(utup);
5243  }
5244  return result;
5245 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:72
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
bool superuser_arg(Oid roleid)
Definition: superuser.c:57
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77

◆ merge_acl_with_grant()

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 171 of file aclchk.c.

References ACL_ID_PUBLIC, ACL_MODECHG_ADD, ACL_MODECHG_DEL, 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().

175 {
176  unsigned modechg;
177  ListCell *j;
178  Acl *new_acl;
179 
180  modechg = is_grant ? ACL_MODECHG_ADD : ACL_MODECHG_DEL;
181 
182 #ifdef ACLDEBUG
183  dumpacl(old_acl);
184 #endif
185  new_acl = old_acl;
186 
187  foreach(j, grantees)
188  {
189  AclItem aclitem;
190  Acl *newer_acl;
191 
192  aclitem.ai_grantee = lfirst_oid(j);
193 
194  /*
195  * Grant options can only be granted to individual roles, not PUBLIC.
196  * The reason is that if a user would re-grant a privilege that he
197  * held through PUBLIC, and later the user is removed, the situation
198  * is impossible to clean up.
199  */
200  if (is_grant && grant_option && aclitem.ai_grantee == ACL_ID_PUBLIC)
201  ereport(ERROR,
202  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
203  errmsg("grant options can only be granted to roles")));
204 
205  aclitem.ai_grantor = grantorId;
206 
207  /*
208  * The asymmetry in the conditions here comes from the spec. In
209  * GRANT, the grant_option flag signals WITH GRANT OPTION, which means
210  * to grant both the basic privilege and its grant option. But in
211  * REVOKE, plain revoke revokes both the basic privilege and its grant
212  * option, while REVOKE GRANT OPTION revokes only the option.
213  */
215  (is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
216  (!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS);
217 
218  newer_acl = aclupdate(new_acl, &aclitem, modechg, ownerId, behavior);
219 
220  /* avoid memory leak when there are many grantees */
221  pfree(new_acl);
222  new_acl = newer_acl;
223 
224 #ifdef ACLDEBUG
225  dumpacl(new_acl);
226 #endif
227  }
228 
229  return new_acl;
230 }
Oid ai_grantee
Definition: acl.h:57
#define ACL_MODECHG_DEL
Definition: acl.h:131
int errcode(int sqlerrcode)
Definition: elog.c:575
Oid ai_grantor
Definition: acl.h:58
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
#define ereport(elevel, rest)
Definition: elog.h:122
#define ACL_MODECHG_ADD
Definition: acl.h:130
Definition: acl.h:55
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_ID_PUBLIC
Definition: acl.h:47
Acl * aclupdate(const Acl *old_acl, const AclItem *mod_aip, int modechg, Oid ownerId, DropBehavior behavior)
Definition: acl.c:931
#define ACLITEM_SET_PRIVS_GOPTIONS(item, privs, goptions)
Definition: acl.h:83
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ objectNamesToOids()

static List * objectNamesToOids ( GrantObjectType  objtype,
List objnames 
)
static

Definition at line 637 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_PROCEDURE, ACL_OBJECT_RELATION, ACL_OBJECT_ROUTINE, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TABLESPACE, ACL_OBJECT_TYPE, Assert, dbname, elog, ereport, errcode(), errmsg(), ERROR, 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, LookupFuncWithArgs(), makeTypeNameFromNameList(), NIL, NoLock, OBJECT_FUNCTION, OBJECT_PROCEDURE, OBJECT_ROUTINE, oidparse(), RangeVarGetRelid, strVal, and typenameTypeId().

Referenced by ExecuteGrantStmt().

638 {
639  List *objects = NIL;
640  ListCell *cell;
641 
642  Assert(objnames != NIL);
643 
644  switch (objtype)
645  {
646  case ACL_OBJECT_RELATION:
647  case ACL_OBJECT_SEQUENCE:
648  foreach(cell, objnames)
649  {
650  RangeVar *relvar = (RangeVar *) lfirst(cell);
651  Oid relOid;
652 
653  relOid = RangeVarGetRelid(relvar, NoLock, false);
654  objects = lappend_oid(objects, relOid);
655  }
656  break;
657  case ACL_OBJECT_DATABASE:
658  foreach(cell, objnames)
659  {
660  char *dbname = strVal(lfirst(cell));
661  Oid dbid;
662 
663  dbid = get_database_oid(dbname, false);
664  objects = lappend_oid(objects, dbid);
665  }
666  break;
667  case ACL_OBJECT_DOMAIN:
668  case ACL_OBJECT_TYPE:
669  foreach(cell, objnames)
670  {
671  List *typname = (List *) lfirst(cell);
672  Oid oid;
673 
674  oid = typenameTypeId(NULL, makeTypeNameFromNameList(typname));
675  objects = lappend_oid(objects, oid);
676  }
677  break;
678  case ACL_OBJECT_FUNCTION:
679  foreach(cell, objnames)
680  {
681  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
682  Oid funcid;
683 
684  funcid = LookupFuncWithArgs(OBJECT_FUNCTION, func, false);
685  objects = lappend_oid(objects, funcid);
686  }
687  break;
688  case ACL_OBJECT_LANGUAGE:
689  foreach(cell, objnames)
690  {
691  char *langname = strVal(lfirst(cell));
692  Oid oid;
693 
694  oid = get_language_oid(langname, false);
695  objects = lappend_oid(objects, oid);
696  }
697  break;
699  foreach(cell, objnames)
700  {
701  Oid lobjOid = oidparse(lfirst(cell));
702 
703  if (!LargeObjectExists(lobjOid))
704  ereport(ERROR,
705  (errcode(ERRCODE_UNDEFINED_OBJECT),
706  errmsg("large object %u does not exist",
707  lobjOid)));
708 
709  objects = lappend_oid(objects, lobjOid);
710  }
711  break;
713  foreach(cell, objnames)
714  {
715  char *nspname = strVal(lfirst(cell));
716  Oid oid;
717 
718  oid = get_namespace_oid(nspname, false);
719  objects = lappend_oid(objects, oid);
720  }
721  break;
723  foreach(cell, objnames)
724  {
725  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
726  Oid procid;
727 
728  procid = LookupFuncWithArgs(OBJECT_PROCEDURE, func, false);
729  objects = lappend_oid(objects, procid);
730  }
731  break;
732  case ACL_OBJECT_ROUTINE:
733  foreach(cell, objnames)
734  {
735  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
736  Oid routid;
737 
738  routid = LookupFuncWithArgs(OBJECT_ROUTINE, func, false);
739  objects = lappend_oid(objects, routid);
740  }
741  break;
743  foreach(cell, objnames)
744  {
745  char *spcname = strVal(lfirst(cell));
746  Oid spcoid;
747 
748  spcoid = get_tablespace_oid(spcname, false);
749  objects = lappend_oid(objects, spcoid);
750  }
751  break;
752  case ACL_OBJECT_FDW:
753  foreach(cell, objnames)
754  {
755  char *fdwname = strVal(lfirst(cell));
756  Oid fdwid = get_foreign_data_wrapper_oid(fdwname, false);
757 
758  objects = lappend_oid(objects, fdwid);
759  }
760  break;
762  foreach(cell, objnames)
763  {
764  char *srvname = strVal(lfirst(cell));
765  Oid srvid = get_foreign_server_oid(srvname, false);
766 
767  objects = lappend_oid(objects, srvid);
768  }
769  break;
770  default:
771  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
772  (int) objtype);
773  }
774 
775  return objects;
776 }
#define NIL
Definition: pg_list.h:69
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1380
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3005
Oid oidparse(Node *node)
Definition: oid.c:314
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:553
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition: foreign.c:659
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool noError)
Definition: parse_func.c:2019
#define ereport(elevel, rest)
Definition: elog.h:122
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2009
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
char * dbname
Definition: streamutil.c:42
bool LargeObjectExists(Oid loid)
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:455
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition: foreign.c:680
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274

◆ objectsInSchemaToOids()

static List * objectsInSchemaToOids ( GrantObjectType  objtype,
List nspnames 
)
static

Definition at line 786 of file aclchk.c.

References AccessShareLock, ACL_OBJECT_FUNCTION, ACL_OBJECT_PROCEDURE, ACL_OBJECT_RELATION, ACL_OBJECT_ROUTINE, ACL_OBJECT_SEQUENCE, Anum_pg_proc_pronamespace, Anum_pg_proc_prorettype, BTEqualStrategyNumber, elog, ERROR, ForwardScanDirection, getRelationsInNamespace(), heap_beginscan_catalog(), heap_close, heap_endscan(), heap_getnext(), heap_open(), HeapTupleGetOid, InvalidOid, lappend_oid(), lfirst, list_concat(), LookupExplicitNamespace(), NIL, ObjectIdGetDatum, ProcedureRelationId, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, ScanKeyInit(), and strVal.

Referenced by ExecuteGrantStmt().

787 {
788  List *objects = NIL;
789  ListCell *cell;
790 
791  foreach(cell, nspnames)
792  {
793  char *nspname = strVal(lfirst(cell));
794  Oid namespaceId;
795  List *objs;
796 
797  namespaceId = LookupExplicitNamespace(nspname, false);
798 
799  switch (objtype)
800  {
801  case ACL_OBJECT_RELATION:
802  objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
803  objects = list_concat(objects, objs);
804  objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
805  objects = list_concat(objects, objs);
806  objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
807  objects = list_concat(objects, objs);
808  objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
809  objects = list_concat(objects, objs);
811  objects = list_concat(objects, objs);
812  break;
813  case ACL_OBJECT_SEQUENCE:
814  objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
815  objects = list_concat(objects, objs);
816  break;
817  case ACL_OBJECT_FUNCTION:
819  case ACL_OBJECT_ROUTINE:
820  {
821  ScanKeyData key[2];
822  int keycount;
823  Relation rel;
824  HeapScanDesc scan;
825  HeapTuple tuple;
826 
827  keycount = 0;
828  ScanKeyInit(&key[keycount++],
830  BTEqualStrategyNumber, F_OIDEQ,
831  ObjectIdGetDatum(namespaceId));
832 
833  /*
834  * When looking for functions, check for return type <>0.
835  * When looking for procedures, check for return type ==0.
836  * When looking for routines, don't check the return type.
837  */
838  if (objtype == ACL_OBJECT_FUNCTION)
839  ScanKeyInit(&key[keycount++],
841  BTEqualStrategyNumber, F_OIDNE,
842  InvalidOid);
843  else if (objtype == ACL_OBJECT_PROCEDURE)
844  ScanKeyInit(&key[keycount++],
846  BTEqualStrategyNumber, F_OIDEQ,
847  InvalidOid);
848 
850  scan = heap_beginscan_catalog(rel, keycount, key);
851 
852  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
853  {
854  objects = lappend_oid(objects, HeapTupleGetOid(tuple));
855  }
856 
857  heap_endscan(scan);
859  }
860  break;
861  default:
862  /* should not happen */
863  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
864  (int) objtype);
865  }
866  }
867 
868  return objects;
869 }
#define NIL
Definition: pg_list.h:69
#define Anum_pg_proc_prorettype
Definition: pg_proc.h:108
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2853
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1565
#define ProcedureRelationId
Definition: pg_proc.h:33
#define RELKIND_MATVIEW
Definition: pg_class.h:165
#define AccessShareLock
Definition: lockdefs.h:36
#define strVal(v)
Definition: value.h:54
List * list_concat(List *list1, List *list2)
Definition: list.c:321
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1405
static List * getRelationsInNamespace(Oid namespaceId, char relkind)
Definition: aclchk.c:877
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1808
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
#define lfirst(lc)
Definition: pg_list.h:106
#define Anum_pg_proc_pronamespace
Definition: pg_proc.h:91
#define RELKIND_VIEW
Definition: pg_class.h:164
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ pg_aclmask()

static AclMode pg_aclmask ( AclObjectKind  objkind,
Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)
static

Definition at line 3527 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_STATISTICS, ACL_KIND_TABLESPACE, ACL_KIND_TYPE, ACL_NO_RIGHTS, 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(), and pg_type_aclmask().

Referenced by restrict_and_check_grant().

3529 {
3530  switch (objkind)
3531  {
3532  case ACL_KIND_COLUMN:
3533  return
3534  pg_class_aclmask(table_oid, roleid, mask, how) |
3535  pg_attribute_aclmask(table_oid, attnum, roleid, mask, how);
3536  case ACL_KIND_CLASS:
3537  case ACL_KIND_SEQUENCE:
3538  return pg_class_aclmask(table_oid, roleid, mask, how);
3539  case ACL_KIND_DATABASE:
3540  return pg_database_aclmask(table_oid, roleid, mask, how);
3541  case ACL_KIND_PROC:
3542  return pg_proc_aclmask(table_oid, roleid, mask, how);
3543  case ACL_KIND_LANGUAGE:
3544  return pg_language_aclmask(table_oid, roleid, mask, how);
3545  case ACL_KIND_LARGEOBJECT:
3546  return pg_largeobject_aclmask_snapshot(table_oid, roleid,
3547  mask, how, NULL);
3548  case ACL_KIND_NAMESPACE:
3549  return pg_namespace_aclmask(table_oid, roleid, mask, how);
3550  case ACL_KIND_STATISTICS:
3551  elog(ERROR, "grantable rights not supported for statistics objects");
3552  /* not reached, but keep compiler quiet */
3553  return ACL_NO_RIGHTS;
3554  case ACL_KIND_TABLESPACE:
3555  return pg_tablespace_aclmask(table_oid, roleid, mask, how);
3556  case ACL_KIND_FDW:
3557  return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
3559  return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
3561  elog(ERROR, "grantable rights not supported for event triggers");
3562  /* not reached, but keep compiler quiet */
3563  return ACL_NO_RIGHTS;
3564  case ACL_KIND_TYPE:
3565  return pg_type_aclmask(table_oid, roleid, mask, how);
3566  default:
3567  elog(ERROR, "unrecognized objkind: %d",
3568  (int) objkind);
3569  /* not reached, but keep compiler quiet */
3570  return ACL_NO_RIGHTS;
3571  }
3572 }
AclMode pg_foreign_server_aclmask(Oid srv_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4221
AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3595
AclMode pg_tablespace_aclmask(Oid spc_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4102
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3680
AclMode pg_database_aclmask(Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3776
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:86
AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4020
AclMode pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4282
AclMode pg_language_aclmask(Oid lang_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3884
AclMode pg_proc_aclmask(Oid proc_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3830
AclMode pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4159
#define elog
Definition: elog.h:219
AclMode pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid, AclMode mask, AclMaskHow how, Snapshot snapshot)
Definition: aclchk.c:3947

◆ pg_attribute_aclcheck()

AclResult pg_attribute_aclcheck ( Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mode 
)

Definition at line 4366 of file aclchk.c.

References ACLCHECK_NO_PRIV, ACLCHECK_OK, ACLMASK_ANY, and pg_attribute_aclmask().

Referenced by BuildIndexValueDescription(), checkFkeyPermissions(), column_privilege_check(), examine_simple_variable(), ExecBuildSlotPartitionKeyDescription(), ExecBuildSlotValueDescription(), ExecCheckRTEPerms(), ExecCheckRTEPermsModified(), and ri_ReportViolation().

4368 {
4369  if (pg_attribute_aclmask(table_oid, attnum, roleid, mode, ACLMASK_ANY) != 0)
4370  return ACLCHECK_OK;
4371  else
4372  return ACLCHECK_NO_PRIV;
4373 }
AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3595

◆ pg_attribute_aclcheck_all()

AclResult pg_attribute_aclcheck_all ( Oid  table_oid,
Oid  roleid,
AclMode  mode,
AclMaskHow  how 
)

Definition at line 4395 of file aclchk.c.

References ACLCHECK_NO_PRIV, ACLCHECK_OK, 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(), ExecCheckRTEPermsModified(), 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().

4397 {
4398  AclResult result;
4399  HeapTuple classTuple;
4400  Form_pg_class classForm;
4401  AttrNumber nattrs;
4402  AttrNumber curr_att;
4403 
4404  /*
4405  * Must fetch pg_class row to check number of attributes. As in
4406  * pg_attribute_aclmask, we prefer to return "no privileges" instead of
4407  * throwing an error if we get any unexpected lookup errors.
4408  */
4409  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
4410  if (!HeapTupleIsValid(classTuple))
4411  return ACLCHECK_NO_PRIV;
4412  classForm = (Form_pg_class) GETSTRUCT(classTuple);
4413 
4414  nattrs = classForm->relnatts;
4415 
4416  ReleaseSysCache(classTuple);
4417 
4418  /*
4419  * Initialize result in case there are no non-dropped columns. We want to
4420  * report failure in such cases for either value of 'how'.
4421  */
4422  result = ACLCHECK_NO_PRIV;
4423 
4424  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4425  {
4426  HeapTuple attTuple;
4427  AclMode attmask;
4428 
4429  attTuple = SearchSysCache2(ATTNUM,
4430  ObjectIdGetDatum(table_oid),
4431  Int16GetDatum(curr_att));
4432  if (!HeapTupleIsValid(attTuple))
4433  continue;
4434 
4435  /* ignore dropped columns */
4436  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4437  {
4438  ReleaseSysCache(attTuple);
4439  continue;
4440  }
4441 
4442  /*
4443  * Here we hard-wire knowledge that the default ACL for a column
4444  * grants no privileges, so that we can fall out quickly in the very
4445  * common case where attacl is null.
4446  */
4448  attmask = 0;
4449  else
4450  attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
4451  mode, ACLMASK_ANY);
4452 
4453  ReleaseSysCache(attTuple);
4454 
4455  if (attmask != 0)
4456  {
4457  result = ACLCHECK_OK;
4458  if (how == ACLMASK_ANY)
4459  break; /* succeed on any success */
4460  }
4461  else
4462  {
4463  result = ACLCHECK_NO_PRIV;
4464  if (how == ACLMASK_ALL)
4465  break; /* fail on any failure */
4466  }
4467  }
4468 
4469  return result;
4470 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3595
#define Int16GetDatum(X)
Definition: postgres.h:457
#define Anum_pg_attribute_attacl
Definition: pg_attribute.h:214
uint32 AclMode
Definition: parsenodes.h:70
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:296
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
AclResult
Definition: acl.h:178
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1123
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
int16 AttrNumber
Definition: attnum.h:21

◆ pg_attribute_aclmask()

AclMode pg_attribute_aclmask ( Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 3595 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().

3597 {
3598  AclMode result;
3599  HeapTuple classTuple;
3600  HeapTuple attTuple;
3601  Form_pg_class classForm;
3602  Form_pg_attribute attributeForm;
3603  Datum aclDatum;
3604  bool isNull;
3605  Acl *acl;
3606  Oid ownerId;
3607 
3608  /*
3609  * First, get the column's ACL from its pg_attribute entry
3610  */
3611  attTuple = SearchSysCache2(ATTNUM,
3612  ObjectIdGetDatum(table_oid),
3613  Int16GetDatum(attnum));
3614  if (!HeapTupleIsValid(attTuple))
3615  ereport(ERROR,
3616  (errcode(ERRCODE_UNDEFINED_COLUMN),
3617  errmsg("attribute %d of relation with OID %u does not exist",
3618  attnum, table_oid)));
3619  attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
3620 
3621  /* Throw error on dropped columns, too */
3622  if (attributeForm->attisdropped)
3623  ereport(ERROR,
3624  (errcode(ERRCODE_UNDEFINED_COLUMN),
3625  errmsg("attribute %d of relation with OID %u does not exist",
3626  attnum, table_oid)));
3627 
3628  aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,