PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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_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

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

Definition at line 3399 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(), AlterSequence(), 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(), 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(), 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().

3401 {
3402  switch (aclerr)
3403  {
3404  case ACLCHECK_OK:
3405  /* no error, so return to caller */
3406  break;
3407  case ACLCHECK_NO_PRIV:
3408  ereport(ERROR,
3409  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3410  errmsg(no_priv_msg[objectkind], objectname)));
3411  break;
3412  case ACLCHECK_NOT_OWNER:
3413  ereport(ERROR,
3414  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3415  errmsg(not_owner_msg[objectkind], objectname)));
3416  break;
3417  default:
3418  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3419  break;
3420  }
3421 }
static const char *const no_priv_msg[MAX_ACL_KIND]
Definition: aclchk.c:3293
static const char *const not_owner_msg[MAX_ACL_KIND]
Definition: aclchk.c:3345
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
void aclcheck_error_col ( AclResult  aclerr,
AclObjectKind  objectkind,
const char *  objectname,
const char *  colname 
)

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

3427 {
3428  switch (aclerr)
3429  {
3430  case ACLCHECK_OK:
3431  /* no error, so return to caller */
3432  break;
3433  case ACLCHECK_NO_PRIV:
3434  ereport(ERROR,
3435  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3436  errmsg("permission denied for column \"%s\" of relation \"%s\"",
3437  colname, objectname)));
3438  break;
3439  case ACLCHECK_NOT_OWNER:
3440  /* relation msg is OK since columns don't have separate owners */
3441  ereport(ERROR,
3442  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3443  errmsg(not_owner_msg[objectkind], objectname)));
3444  break;
3445  default:
3446  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3447  break;
3448  }
3449 }
static const char *const not_owner_msg[MAX_ACL_KIND]
Definition: aclchk.c:3345
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
void aclcheck_error_type ( AclResult  aclerr,
Oid  typeOid 
)

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

3458 {
3459  Oid element_type = get_element_type(typeOid);
3460 
3461  aclcheck_error(aclerr, ACL_KIND_TYPE, format_type_be(element_type ? element_type : typeOid));
3462 }
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2484
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:3399
void ExecAlterDefaultPrivilegesStmt ( ParseState pstate,
AlterDefaultPrivilegesStmt stmt 
)

Definition at line 863 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_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TYPE, 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, NULL, 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().

864 {
865  GrantStmt *action = stmt->action;
866  InternalDefaultACL iacls;
867  ListCell *cell;
868  List *rolespecs = NIL;
869  List *nspnames = NIL;
870  DefElem *drolespecs = NULL;
871  DefElem *dnspnames = NULL;
872  AclMode all_privileges;
873  const char *errormsg;
874 
875  /* Deconstruct the "options" part of the statement */
876  foreach(cell, stmt->options)
877  {
878  DefElem *defel = (DefElem *) lfirst(cell);
879 
880  if (strcmp(defel->defname, "schemas") == 0)
881  {
882  if (dnspnames)
883  ereport(ERROR,
884  (errcode(ERRCODE_SYNTAX_ERROR),
885  errmsg("conflicting or redundant options"),
886  parser_errposition(pstate, defel->location)));
887  dnspnames = defel;
888  }
889  else if (strcmp(defel->defname, "roles") == 0)
890  {
891  if (drolespecs)
892  ereport(ERROR,
893  (errcode(ERRCODE_SYNTAX_ERROR),
894  errmsg("conflicting or redundant options"),
895  parser_errposition(pstate, defel->location)));
896  drolespecs = defel;
897  }
898  else
899  elog(ERROR, "option \"%s\" not recognized", defel->defname);
900  }
901 
902  if (dnspnames)
903  nspnames = (List *) dnspnames->arg;
904  if (drolespecs)
905  rolespecs = (List *) drolespecs->arg;
906 
907  /* Prepare the InternalDefaultACL representation of the statement */
908  /* roleid to be filled below */
909  /* nspid to be filled in SetDefaultACLsInSchemas */
910  iacls.is_grant = action->is_grant;
911  iacls.objtype = action->objtype;
912  /* all_privs to be filled below */
913  /* privileges to be filled below */
914  iacls.grantees = NIL; /* filled below */
915  iacls.grant_option = action->grant_option;
916  iacls.behavior = action->behavior;
917 
918  /*
919  * Convert the RoleSpec list into an Oid list. Note that at this point we
920  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
921  * there shouldn't be any additional work needed to support this case.
922  */
923  foreach(cell, action->grantees)
924  {
925  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
926  Oid grantee_uid;
927 
928  switch (grantee->roletype)
929  {
930  case ROLESPEC_PUBLIC:
931  grantee_uid = ACL_ID_PUBLIC;
932  break;
933  default:
934  grantee_uid = get_rolespec_oid(grantee, false);
935  break;
936  }
937  iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
938  }
939 
940  /*
941  * Convert action->privileges, a list of privilege strings, into an
942  * AclMode bitmask.
943  */
944  switch (action->objtype)
945  {
946  case ACL_OBJECT_RELATION:
947  all_privileges = ACL_ALL_RIGHTS_RELATION;
948  errormsg = gettext_noop("invalid privilege type %s for relation");
949  break;
950  case ACL_OBJECT_SEQUENCE:
951  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
952  errormsg = gettext_noop("invalid privilege type %s for sequence");
953  break;
954  case ACL_OBJECT_FUNCTION:
955  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
956  errormsg = gettext_noop("invalid privilege type %s for function");
957  break;
958  case ACL_OBJECT_TYPE:
959  all_privileges = ACL_ALL_RIGHTS_TYPE;
960  errormsg = gettext_noop("invalid privilege type %s for type");
961  break;
963  all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
964  errormsg = gettext_noop("invalid privilege type %s for schema");
965  break;
966  default:
967  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
968  (int) action->objtype);
969  /* keep compiler quiet */
970  all_privileges = ACL_NO_RIGHTS;
971  errormsg = NULL;
972  }
973 
974  if (action->privileges == NIL)
975  {
976  iacls.all_privs = true;
977 
978  /*
979  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
980  * depending on the object type
981  */
982  iacls.privileges = ACL_NO_RIGHTS;
983  }
984  else
985  {
986  iacls.all_privs = false;
987  iacls.privileges = ACL_NO_RIGHTS;
988 
989  foreach(cell, action->privileges)
990  {
991  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
992  AclMode priv;
993 
994  if (privnode->cols)
995  ereport(ERROR,
996  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
997  errmsg("default privileges cannot be set for columns")));
998 
999  if (privnode->priv_name == NULL) /* parser mistake? */
1000  elog(ERROR, "AccessPriv node must specify privilege");
1001  priv = string_to_privilege(privnode->priv_name);
1002 
1003  if (priv & ~((AclMode) all_privileges))
1004  ereport(ERROR,
1005  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1006  errmsg(errormsg, privilege_to_string(priv))));
1007 
1008  iacls.privileges |= priv;
1009  }
1010  }
1011 
1012  if (rolespecs == NIL)
1013  {
1014  /* Set permissions for myself */
1015  iacls.roleid = GetUserId();
1016 
1017  SetDefaultACLsInSchemas(&iacls, nspnames);
1018  }
1019  else
1020  {
1021  /* Look up the role OIDs and do permissions checks */
1022  ListCell *rolecell;
1023 
1024  foreach(rolecell, rolespecs)
1025  {
1026  RoleSpec *rolespec = lfirst(rolecell);
1027 
1028  iacls.roleid = get_rolespec_oid(rolespec, false);
1029 
1030  /*
1031  * We insist that calling user be a member of each target role. If
1032  * he has that, he could become that role anyway via SET ROLE, so
1033  * FOR ROLE is just a syntactic convenience and doesn't give any
1034  * special privileges.
1035  */
1037 
1038  SetDefaultACLsInSchemas(&iacls, nspnames);
1039  }
1040  }
1041 }
#define NIL
Definition: pg_list.h:69
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:155
bool grant_option
Definition: aclchk.c:93
Oid GetUserId(void)
Definition: miscinit.c:283
static AclMode string_to_privilege(const char *privname)
Definition: aclchk.c:3215
bool grant_option
Definition: parsenodes.h:1831
#define gettext_noop(x)
Definition: c.h:139
int errcode(int sqlerrcode)
Definition: elog.c:575
List * cols
Definition: parsenodes.h:1861
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:160
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4859
#define ereport(elevel, rest)
Definition: elog.h:122
Node * arg
Definition: parsenodes.h:720
#define ACL_ALL_RIGHTS_NAMESPACE
Definition: acl.h:158
bool is_grant
Definition: parsenodes.h:1823
RoleSpecType roletype
Definition: parsenodes.h:328
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5129
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:151
DropBehavior behavior
Definition: aclchk.c:94
List * privileges
Definition: parsenodes.h:1828
DropBehavior behavior
Definition: parsenodes.h:1832
#define NULL
Definition: c.h:229
#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:1049
GrantObjectType objtype
Definition: parsenodes.h:1825
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_ALL_RIGHTS_RELATION
Definition: acl.h:150
#define ACL_ID_PUBLIC
Definition: acl.h:39
char * defname
Definition: parsenodes.h:719
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:3252
List * grantees
Definition: parsenodes.h:1830
#define elog
Definition: elog.h:219
AclMode privileges
Definition: aclchk.c:91
Definition: pg_list.h:45
char * priv_name
Definition: parsenodes.h:1860
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 1588 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, NULL, 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().

1591 {
1592  HeapTuple attr_tuple;
1593  Form_pg_attribute pg_attribute_tuple;
1594  Acl *old_acl;
1595  Acl *new_acl;
1596  Acl *merged_acl;
1597  Datum aclDatum;
1598  bool isNull;
1599  Oid grantorId;
1600  AclMode avail_goptions;
1601  bool need_update;
1602  HeapTuple newtuple;
1604  bool nulls[Natts_pg_attribute];
1605  bool replaces[Natts_pg_attribute];
1606  int noldmembers;
1607  int nnewmembers;
1608  Oid *oldmembers;
1609  Oid *newmembers;
1610 
1611  attr_tuple = SearchSysCache2(ATTNUM,
1612  ObjectIdGetDatum(relOid),
1613  Int16GetDatum(attnum));
1614  if (!HeapTupleIsValid(attr_tuple))
1615  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1616  attnum, relOid);
1617  pg_attribute_tuple = (Form_pg_attribute) GETSTRUCT(attr_tuple);
1618 
1619  /*
1620  * Get working copy of existing ACL. If there's no ACL, substitute the
1621  * proper default.
1622  */
1623  aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
1624  &isNull);
1625  if (isNull)
1626  {
1627  old_acl = acldefault(ACL_OBJECT_COLUMN, ownerId);
1628  /* There are no old member roles according to the catalogs */
1629  noldmembers = 0;
1630  oldmembers = NULL;
1631  }
1632  else
1633  {
1634  old_acl = DatumGetAclPCopy(aclDatum);
1635  /* Get the roles mentioned in the existing ACL */
1636  noldmembers = aclmembers(old_acl, &oldmembers);
1637  }
1638 
1639  /*
1640  * In select_best_grantor we should consider existing table-level ACL bits
1641  * as well as the per-column ACL. Build a new ACL that is their
1642  * concatenation. (This is a bit cheap and dirty compared to merging them
1643  * properly with no duplications, but it's all we need here.)
1644  */
1645  merged_acl = aclconcat(old_rel_acl, old_acl);
1646 
1647  /* Determine ID to do the grant as, and available grant options */
1648  select_best_grantor(GetUserId(), col_privileges,
1649  merged_acl, ownerId,
1650  &grantorId, &avail_goptions);
1651 
1652  pfree(merged_acl);
1653 
1654  /*
1655  * Restrict the privileges to what we can actually grant, and emit the
1656  * standards-mandated warning and error messages. Note: we don't track
1657  * whether the user actually used the ALL PRIVILEGES(columns) syntax for
1658  * each column; we just approximate it by whether all the possible
1659  * privileges are specified now. Since the all_privs flag only determines
1660  * whether a warning is issued, this seems close enough.
1661  */
1662  col_privileges =
1663  restrict_and_check_grant(istmt->is_grant, avail_goptions,
1664  (col_privileges == ACL_ALL_RIGHTS_COLUMN),
1665  col_privileges,
1666  relOid, grantorId, ACL_KIND_COLUMN,
1667  relname, attnum,
1668  NameStr(pg_attribute_tuple->attname));
1669 
1670  /*
1671  * Generate new ACL.
1672  */
1673  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
1674  istmt->grant_option,
1675  istmt->behavior, istmt->grantees,
1676  col_privileges, grantorId,
1677  ownerId);
1678 
1679  /*
1680  * We need the members of both old and new ACLs so we can correct the
1681  * shared dependency information.
1682  */
1683  nnewmembers = aclmembers(new_acl, &newmembers);
1684 
1685  /* finished building new ACL value, now insert it */
1686  MemSet(values, 0, sizeof(values));
1687  MemSet(nulls, false, sizeof(nulls));
1688  MemSet(replaces, false, sizeof(replaces));
1689 
1690  /*
1691  * If the updated ACL is empty, we can set attacl to null, and maybe even
1692  * avoid an update of the pg_attribute row. This is worth testing because
1693  * we'll come through here multiple times for any relation-level REVOKE,
1694  * even if there were never any column GRANTs. Note we are assuming that
1695  * the "default" ACL state for columns is empty.
1696  */
1697  if (ACL_NUM(new_acl) > 0)
1698  {
1699  values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl);
1700  need_update = true;
1701  }
1702  else
1703  {
1704  nulls[Anum_pg_attribute_attacl - 1] = true;
1705  need_update = !isNull;
1706  }
1707  replaces[Anum_pg_attribute_attacl - 1] = true;
1708 
1709  if (need_update)
1710  {
1711  newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
1712  values, nulls, replaces);
1713 
1714  CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
1715 
1716  /* Update initial privileges for extensions */
1718  ACL_NUM(new_acl) > 0 ? new_acl : NULL);
1719 
1720  /* Update the shared dependency ACL info */
1721  updateAclDependencies(RelationRelationId, relOid, attnum,
1722  ownerId,
1723  noldmembers, oldmembers,
1724  nnewmembers, newmembers);
1725  }
1726 
1727  pfree(new_acl);
1728 
1729  ReleaseSysCache(attr_tuple);
1730 }
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:656
#define ACL_ALL_RIGHTS_COLUMN
Definition: acl.h:149
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
#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:731
#define Anum_pg_attribute_attacl
Definition: pg_attribute.h:214
#define MemSet(start, val, len)
Definition: c.h:857
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:950
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_NUM(ACL)
Definition: acl.h:101
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:5695
Acl * aclconcat(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:426
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:1116
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
DropBehavior behavior
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1456
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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:5021
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#define NameStr(name)
Definition: c.h:499
#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:793
#define DatumGetAclPCopy(X)
Definition: acl.h:114
#define SearchSysCache2(cacheId, key1, key2)
Definition: syscache.h:154
static void ExecGrant_Database ( InternalGrant grantStmt)
static

Definition at line 2067 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, NULL, 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().

2068 {
2069  Relation relation;
2070  ListCell *cell;
2071 
2072  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2073  istmt->privileges = ACL_ALL_RIGHTS_DATABASE;
2074 
2076 
2077  foreach(cell, istmt->objects)
2078  {
2079  Oid datId = lfirst_oid(cell);
2080  Form_pg_database pg_database_tuple;
2081  Datum aclDatum;
2082  bool isNull;
2083  AclMode avail_goptions;
2084  AclMode this_privileges;
2085  Acl *old_acl;
2086  Acl *new_acl;
2087  Oid grantorId;
2088  Oid ownerId;
2089  HeapTuple newtuple;
2091  bool nulls[Natts_pg_database];
2092  bool replaces[Natts_pg_database];
2093  int noldmembers;
2094  int nnewmembers;
2095  Oid *oldmembers;
2096  Oid *newmembers;
2097  HeapTuple tuple;
2098 
2099  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(datId));
2100  if (!HeapTupleIsValid(tuple))
2101  elog(ERROR, "cache lookup failed for database %u", datId);
2102 
2103  pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
2104 
2105  /*
2106  * Get owner ID and working copy of existing ACL. If there's no ACL,
2107  * substitute the proper default.
2108  */
2109  ownerId = pg_database_tuple->datdba;
2110  aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
2111  RelationGetDescr(relation), &isNull);
2112  if (isNull)
2113  {
2114  old_acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
2115  /* There are no old member roles according to the catalogs */
2116  noldmembers = 0;
2117  oldmembers = NULL;
2118  }
2119  else
2120  {
2121  old_acl = DatumGetAclPCopy(aclDatum);
2122  /* Get the roles mentioned in the existing ACL */
2123  noldmembers = aclmembers(old_acl, &oldmembers);
2124  }
2125 
2126  /* Determine ID to do the grant as, and available grant options */
2127  select_best_grantor(GetUserId(), istmt->privileges,
2128  old_acl, ownerId,
2129  &grantorId, &avail_goptions);
2130 
2131  /*
2132  * Restrict the privileges to what we can actually grant, and emit the
2133  * standards-mandated warning and error messages.
2134  */
2135  this_privileges =
2136  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2137  istmt->all_privs, istmt->privileges,
2138  datId, grantorId, ACL_KIND_DATABASE,
2139  NameStr(pg_database_tuple->datname),
2140  0, NULL);
2141 
2142  /*
2143  * Generate new ACL.
2144  */
2145  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2146  istmt->grant_option, istmt->behavior,
2147  istmt->grantees, this_privileges,
2148  grantorId, ownerId);
2149 
2150  /*
2151  * We need the members of both old and new ACLs so we can correct the
2152  * shared dependency information.
2153  */
2154  nnewmembers = aclmembers(new_acl, &newmembers);
2155 
2156  /* finished building new ACL value, now insert it */
2157  MemSet(values, 0, sizeof(values));
2158  MemSet(nulls, false, sizeof(nulls));
2159  MemSet(replaces, false, sizeof(replaces));
2160 
2161  replaces[Anum_pg_database_datacl - 1] = true;
2162  values[Anum_pg_database_datacl - 1] = PointerGetDatum(new_acl);
2163 
2164  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2165  nulls, replaces);
2166 
2167  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2168 
2169  /* Update the shared dependency ACL info */
2171  ownerId,
2172  noldmembers, oldmembers,
2173  nnewmembers, newmembers);
2174 
2175  ReleaseSysCache(tuple);
2176 
2177  pfree(new_acl);
2178 
2179  /* prevent error when processing duplicate objects */
2181  }
2182 
2183  heap_close(relation, RowExclusiveLock);
2184 }
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:656
#define Natts_pg_database
Definition: pg_database.h:63
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
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:731
#define MemSet(start, val, len)
Definition: c.h:857
#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 SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:950
#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:769
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:922
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1456
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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:5021
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:152
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:114
static void ExecGrant_Fdw ( InternalGrant grantStmt)
static

Definition at line 2187 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, NULL, 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().

2188 {
2189  Relation relation;
2190  ListCell *cell;
2191 
2192  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2193  istmt->privileges = ACL_ALL_RIGHTS_FDW;
2194 
2196 
2197  foreach(cell, istmt->objects)
2198  {
2199  Oid fdwid = lfirst_oid(cell);
2200  Form_pg_foreign_data_wrapper pg_fdw_tuple;
2201  Datum aclDatum;
2202  bool isNull;
2203  AclMode avail_goptions;
2204  AclMode this_privileges;
2205  Acl *old_acl;
2206  Acl *new_acl;
2207  Oid grantorId;
2208  Oid ownerId;
2209  HeapTuple tuple;
2210  HeapTuple newtuple;
2212  bool nulls[Natts_pg_foreign_data_wrapper];
2213  bool replaces[Natts_pg_foreign_data_wrapper];
2214  int noldmembers;
2215  int nnewmembers;
2216  Oid *oldmembers;
2217  Oid *newmembers;
2218 
2220  ObjectIdGetDatum(fdwid));
2221  if (!HeapTupleIsValid(tuple))
2222  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
2223 
2224  pg_fdw_tuple = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
2225 
2226  /*
2227  * Get owner ID and working copy of existing ACL. If there's no ACL,
2228  * substitute the proper default.
2229  */
2230  ownerId = pg_fdw_tuple->fdwowner;
2231  aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
2233  &isNull);
2234  if (isNull)
2235  {
2236  old_acl = acldefault(ACL_OBJECT_FDW, ownerId);
2237  /* There are no old member roles according to the catalogs */
2238  noldmembers = 0;
2239  oldmembers = NULL;
2240  }
2241  else
2242  {
2243  old_acl = DatumGetAclPCopy(aclDatum);
2244  /* Get the roles mentioned in the existing ACL */
2245  noldmembers = aclmembers(old_acl, &oldmembers);
2246  }
2247 
2248  /* Determine ID to do the grant as, and available grant options */
2249  select_best_grantor(GetUserId(), istmt->privileges,
2250  old_acl, ownerId,
2251  &grantorId, &avail_goptions);
2252 
2253  /*
2254  * Restrict the privileges to what we can actually grant, and emit the
2255  * standards-mandated warning and error messages.
2256  */
2257  this_privileges =
2258  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2259  istmt->all_privs, istmt->privileges,
2260  fdwid, grantorId, ACL_KIND_FDW,
2261  NameStr(pg_fdw_tuple->fdwname),
2262  0, NULL);
2263 
2264  /*
2265  * Generate new ACL.
2266  */
2267  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2268  istmt->grant_option, istmt->behavior,
2269  istmt->grantees, this_privileges,
2270  grantorId, ownerId);
2271 
2272  /*
2273  * We need the members of both old and new ACLs so we can correct the
2274  * shared dependency information.
2275  */
2276  nnewmembers = aclmembers(new_acl, &newmembers);
2277 
2278  /* finished building new ACL value, now insert it */
2279  MemSet(values, 0, sizeof(values));
2280  MemSet(nulls, false, sizeof(nulls));
2281  MemSet(replaces, false, sizeof(replaces));
2282 
2283  replaces[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
2285 
2286  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2287  nulls, replaces);
2288 
2289  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2290 
2291  /* Update initial privileges for extensions */
2293  new_acl);
2294 
2295  /* Update the shared dependency ACL info */
2297  HeapTupleGetOid(tuple), 0,
2298  ownerId,
2299  noldmembers, oldmembers,
2300  nnewmembers, newmembers);
2301 
2302  ReleaseSysCache(tuple);
2303 
2304  pfree(new_acl);
2305 
2306  /* prevent error when processing duplicate objects */
2308  }
2309 
2310  heap_close(relation, RowExclusiveLock);
2311 }
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:656
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
#define PointerGetDatum(X)
Definition: postgres.h:562
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:731
#define MemSet(start, val, len)
Definition: c.h:857
#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 SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define Anum_pg_foreign_data_wrapper_fdwacl
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:950
#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:5695
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:922
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define Natts_pg_foreign_data_wrapper
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1456
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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:5021
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#define NameStr(name)
Definition: c.h:499
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:153
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:114
static void ExecGrant_ForeignServer ( InternalGrant grantStmt)
static

Definition at line 2314 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, NULL, 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().

2315 {
2316  Relation relation;
2317  ListCell *cell;
2318 
2319  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2320  istmt->privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
2321 
2323 
2324  foreach(cell, istmt->objects)
2325  {
2326  Oid srvid = lfirst_oid(cell);
2327  Form_pg_foreign_server pg_server_tuple;
2328  Datum aclDatum;
2329  bool isNull;
2330  AclMode avail_goptions;
2331  AclMode this_privileges;
2332  Acl *old_acl;
2333  Acl *new_acl;
2334  Oid grantorId;
2335  Oid ownerId;
2336  HeapTuple tuple;
2337  HeapTuple newtuple;
2339  bool nulls[Natts_pg_foreign_server];
2340  bool replaces[Natts_pg_foreign_server];
2341  int noldmembers;
2342  int nnewmembers;
2343  Oid *oldmembers;
2344  Oid *newmembers;
2345 
2347  if (!HeapTupleIsValid(tuple))
2348  elog(ERROR, "cache lookup failed for foreign server %u", srvid);
2349 
2350  pg_server_tuple = (Form_pg_foreign_server) GETSTRUCT(tuple);
2351 
2352  /*
2353  * Get owner ID and working copy of existing ACL. If there's no ACL,
2354  * substitute the proper default.
2355  */
2356  ownerId = pg_server_tuple->srvowner;
2357  aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
2359  &isNull);
2360  if (isNull)
2361  {
2362  old_acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
2363  /* There are no old member roles according to the catalogs */
2364  noldmembers = 0;
2365  oldmembers = NULL;
2366  }
2367  else
2368  {
2369  old_acl = DatumGetAclPCopy(aclDatum);
2370  /* Get the roles mentioned in the existing ACL */
2371  noldmembers = aclmembers(old_acl, &oldmembers);
2372  }
2373 
2374  /* Determine ID to do the grant as, and available grant options */
2375  select_best_grantor(GetUserId(), istmt->privileges,
2376  old_acl, ownerId,
2377  &grantorId, &avail_goptions);
2378 
2379  /*
2380  * Restrict the privileges to what we can actually grant, and emit the
2381  * standards-mandated warning and error messages.
2382  */
2383  this_privileges =
2384  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2385  istmt->all_privs, istmt->privileges,
2386  srvid, grantorId, ACL_KIND_FOREIGN_SERVER,
2387  NameStr(pg_server_tuple->srvname),
2388  0, NULL);
2389 
2390  /*
2391  * Generate new ACL.
2392  */
2393  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2394  istmt->grant_option, istmt->behavior,
2395  istmt->grantees, this_privileges,
2396  grantorId, ownerId);
2397 
2398  /*
2399  * We need the members of both old and new ACLs so we can correct the
2400  * shared dependency information.
2401  */
2402  nnewmembers = aclmembers(new_acl, &newmembers);
2403 
2404  /* finished building new ACL value, now insert it */
2405  MemSet(values, 0, sizeof(values));
2406  MemSet(nulls, false, sizeof(nulls));
2407  MemSet(replaces, false, sizeof(replaces));
2408 
2409  replaces[Anum_pg_foreign_server_srvacl - 1] = true;
2410  values[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(new_acl);
2411 
2412  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2413  nulls, replaces);
2414 
2415  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2416 
2417  /* Update initial privileges for extensions */
2419 
2420  /* Update the shared dependency ACL info */
2422  HeapTupleGetOid(tuple), 0,
2423  ownerId,
2424  noldmembers, oldmembers,
2425  nnewmembers, newmembers);
2426 
2427  ReleaseSysCache(tuple);
2428 
2429  pfree(new_acl);
2430 
2431  /* prevent error when processing duplicate objects */
2433  }
2434 
2435  heap_close(relation, RowExclusiveLock);
2436 }
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:656
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
#define PointerGetDatum(X)
Definition: postgres.h:562
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:731
#define MemSet(start, val, len)
Definition: c.h:857
#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 SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:950
#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:5695
#define Anum_pg_foreign_server_srvacl
#define Natts_pg_foreign_server
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:922
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
FormData_pg_foreign_server * Form_pg_foreign_server
#define ForeignServerRelationId
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1456
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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:5021
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:154
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:114
static void ExecGrant_Function ( InternalGrant grantStmt)
static

Definition at line 2439 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, NULL, 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().

2440 {
2441  Relation relation;
2442  ListCell *cell;
2443 
2444  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2445  istmt->privileges = ACL_ALL_RIGHTS_FUNCTION;
2446 
2448 
2449  foreach(cell, istmt->objects)
2450  {
2451  Oid funcId = lfirst_oid(cell);
2452  Form_pg_proc pg_proc_tuple;
2453  Datum aclDatum;
2454  bool isNull;
2455  AclMode avail_goptions;
2456  AclMode this_privileges;
2457  Acl *old_acl;
2458  Acl *new_acl;
2459  Oid grantorId;
2460  Oid ownerId;
2461  HeapTuple tuple;
2462  HeapTuple newtuple;
2464  bool nulls[Natts_pg_proc];
2465  bool replaces[Natts_pg_proc];
2466  int noldmembers;
2467  int nnewmembers;
2468  Oid *oldmembers;
2469  Oid *newmembers;
2470 
2471  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
2472  if (!HeapTupleIsValid(tuple))
2473  elog(ERROR, "cache lookup failed for function %u", funcId);
2474 
2475  pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
2476 
2477  /*
2478  * Get owner ID and working copy of existing ACL. If there's no ACL,
2479  * substitute the proper default.
2480  */
2481  ownerId = pg_proc_tuple->proowner;
2482  aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
2483  &isNull);
2484  if (isNull)
2485  {
2486  old_acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
2487  /* There are no old member roles according to the catalogs */
2488  noldmembers = 0;
2489  oldmembers = NULL;
2490  }
2491  else
2492  {
2493  old_acl = DatumGetAclPCopy(aclDatum);
2494  /* Get the roles mentioned in the existing ACL */
2495  noldmembers = aclmembers(old_acl, &oldmembers);
2496  }
2497 
2498  /* Determine ID to do the grant as, and available grant options */
2499  select_best_grantor(GetUserId(), istmt->privileges,
2500  old_acl, ownerId,
2501  &grantorId, &avail_goptions);
2502 
2503  /*
2504  * Restrict the privileges to what we can actually grant, and emit the
2505  * standards-mandated warning and error messages.
2506  */
2507  this_privileges =
2508  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2509  istmt->all_privs, istmt->privileges,
2510  funcId, grantorId, ACL_KIND_PROC,
2511  NameStr(pg_proc_tuple->proname),
2512  0, NULL);
2513 
2514  /*
2515  * Generate new ACL.
2516  */
2517  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2518  istmt->grant_option, istmt->behavior,
2519  istmt->grantees, this_privileges,
2520  grantorId, ownerId);
2521 
2522  /*
2523  * We need the members of both old and new ACLs so we can correct the
2524  * shared dependency information.
2525  */
2526  nnewmembers = aclmembers(new_acl, &newmembers);
2527 
2528  /* finished building new ACL value, now insert it */
2529  MemSet(values, 0, sizeof(values));
2530  MemSet(nulls, false, sizeof(nulls));
2531  MemSet(replaces, false, sizeof(replaces));
2532 
2533  replaces[Anum_pg_proc_proacl - 1] = true;
2534  values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
2535 
2536  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2537  nulls, replaces);
2538 
2539  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2540 
2541  /* Update initial privileges for extensions */
2542  recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
2543 
2544  /* Update the shared dependency ACL info */
2546  ownerId,
2547  noldmembers, oldmembers,
2548  nnewmembers, newmembers);
2549 
2550  ReleaseSysCache(tuple);
2551 
2552  pfree(new_acl);
2553 
2554  /* prevent error when processing duplicate objects */
2556  }
2557 
2558  heap_close(relation, RowExclusiveLock);
2559 }
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:155
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
#define PointerGetDatum(X)
Definition: postgres.h:562
#define ProcedureRelationId
Definition: pg_proc.h:33
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:731
#define Anum_pg_proc_proacl
Definition: pg_proc.h:118
#define MemSet(start, val, len)
Definition: c.h:857
#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 SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:950
#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:5695
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:922
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1456
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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:5021
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:114
static void ExecGrant_Language ( InternalGrant grantStmt)
static

Definition at line 2562 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, NULL, 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().

2563 {
2564  Relation relation;
2565  ListCell *cell;
2566 
2567  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2568  istmt->privileges = ACL_ALL_RIGHTS_LANGUAGE;
2569 
2571 
2572  foreach(cell, istmt->objects)
2573  {
2574  Oid langId = lfirst_oid(cell);
2575  Form_pg_language pg_language_tuple;
2576  Datum aclDatum;
2577  bool isNull;
2578  AclMode avail_goptions;
2579  AclMode this_privileges;
2580  Acl *old_acl;
2581  Acl *new_acl;
2582  Oid grantorId;
2583  Oid ownerId;
2584  HeapTuple tuple;
2585  HeapTuple newtuple;
2587  bool nulls[Natts_pg_language];
2588  bool replaces[Natts_pg_language];
2589  int noldmembers;
2590  int nnewmembers;
2591  Oid *oldmembers;
2592  Oid *newmembers;
2593 
2594  tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(langId));
2595  if (!HeapTupleIsValid(tuple))
2596  elog(ERROR, "cache lookup failed for language %u", langId);
2597 
2598  pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
2599 
2600  if (!pg_language_tuple->lanpltrusted)
2601  ereport(ERROR,
2602  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2603  errmsg("language \"%s\" is not trusted",
2604  NameStr(pg_language_tuple->lanname)),
2605  errdetail("GRANT and REVOKE are not allowed on untrusted languages, "
2606  "because only superusers can use untrusted languages.")));
2607 
2608  /*
2609  * Get owner ID and working copy of existing ACL. If there's no ACL,
2610  * substitute the proper default.
2611  */
2612  ownerId = pg_language_tuple->lanowner;
2614  &isNull);
2615  if (isNull)
2616  {
2617  old_acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
2618  /* There are no old member roles according to the catalogs */
2619  noldmembers = 0;
2620  oldmembers = NULL;
2621  }
2622  else
2623  {
2624  old_acl = DatumGetAclPCopy(aclDatum);
2625  /* Get the roles mentioned in the existing ACL */
2626  noldmembers = aclmembers(old_acl, &oldmembers);
2627  }
2628 
2629  /* Determine ID to do the grant as, and available grant options */
2630  select_best_grantor(GetUserId(), istmt->privileges,
2631  old_acl, ownerId,
2632  &grantorId, &avail_goptions);
2633 
2634  /*
2635  * Restrict the privileges to what we can actually grant, and emit the
2636  * standards-mandated warning and error messages.
2637  */
2638  this_privileges =
2639  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2640  istmt->all_privs, istmt->privileges,
2641  langId, grantorId, ACL_KIND_LANGUAGE,
2642  NameStr(pg_language_tuple->lanname),
2643  0, NULL);
2644 
2645  /*
2646  * Generate new ACL.
2647  */
2648  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2649  istmt->grant_option, istmt->behavior,
2650  istmt->grantees, this_privileges,
2651  grantorId, ownerId);
2652 
2653  /*
2654  * We need the members of both old and new ACLs so we can correct the
2655  * shared dependency information.
2656  */
2657  nnewmembers = aclmembers(new_acl, &newmembers);
2658 
2659  /* finished building new ACL value, now insert it */
2660  MemSet(values, 0, sizeof(values));
2661  MemSet(nulls, false, sizeof(nulls));
2662  MemSet(replaces, false, sizeof(replaces));
2663 
2664  replaces[Anum_pg_language_lanacl - 1] = true;
2665  values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
2666 
2667  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2668  nulls, replaces);
2669 
2670  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2671 
2672  /* Update initial privileges for extensions */
2673  recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
2674 
2675  /* Update the shared dependency ACL info */
2677  ownerId,
2678  noldmembers, oldmembers,
2679  nnewmembers, newmembers);
2680 
2681  ReleaseSysCache(tuple);
2682 
2683  pfree(new_acl);
2684 
2685  /* prevent error when processing duplicate objects */
2687  }
2688 
2689  heap_close(relation, RowExclusiveLock);
2690 }
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:656
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
#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:731
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:857
#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 SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:156
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:950
#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:5695
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:922
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1456
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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:5021
static Datum values[MAXATTR]
Definition: bootstrap.c:163
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:499
#define LanguageRelationId
Definition: pg_language.h:29
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:114
static void ExecGrant_Largeobject ( InternalGrant grantStmt)
static

Definition at line 2693 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, NULL, 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().

2694 {
2695  Relation relation;
2696  ListCell *cell;
2697 
2698  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2699  istmt->privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
2700 
2703 
2704  foreach(cell, istmt->objects)
2705  {
2706  Oid loid = lfirst_oid(cell);
2707  Form_pg_largeobject_metadata form_lo_meta;
2708  char loname[NAMEDATALEN];
2709  Datum aclDatum;
2710  bool isNull;
2711  AclMode avail_goptions;
2712  AclMode this_privileges;
2713  Acl *old_acl;
2714  Acl *new_acl;
2715  Oid grantorId;
2716  Oid ownerId;
2717  HeapTuple newtuple;
2719  bool nulls[Natts_pg_largeobject_metadata];
2720  bool replaces[Natts_pg_largeobject_metadata];
2721  int noldmembers;
2722  int nnewmembers;
2723  Oid *oldmembers;
2724  Oid *newmembers;
2725  ScanKeyData entry[1];
2726  SysScanDesc scan;
2727  HeapTuple tuple;
2728 
2729  /* There's no syscache for pg_largeobject_metadata */
2730  ScanKeyInit(&entry[0],
2732  BTEqualStrategyNumber, F_OIDEQ,
2733  ObjectIdGetDatum(loid));
2734 
2735  scan = systable_beginscan(relation,
2737  NULL, 1, entry);
2738 
2739  tuple = systable_getnext(scan);
2740  if (!HeapTupleIsValid(tuple))
2741  elog(ERROR, "cache lookup failed for large object %u", loid);
2742 
2743  form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
2744 
2745  /*
2746  * Get owner ID and working copy of existing ACL. If there's no ACL,
2747  * substitute the proper default.
2748  */
2749  ownerId = form_lo_meta->lomowner;
2750  aclDatum = heap_getattr(tuple,
2752  RelationGetDescr(relation), &isNull);
2753  if (isNull)
2754  {
2755  old_acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
2756  /* There are no old member roles according to the catalogs */
2757  noldmembers = 0;
2758  oldmembers = NULL;
2759  }
2760  else
2761  {
2762  old_acl = DatumGetAclPCopy(aclDatum);
2763  /* Get the roles mentioned in the existing ACL */
2764  noldmembers = aclmembers(old_acl, &oldmembers);
2765  }
2766 
2767  /* Determine ID to do the grant as, and available grant options */
2768  select_best_grantor(GetUserId(), istmt->privileges,
2769  old_acl, ownerId,
2770  &grantorId, &avail_goptions);
2771 
2772  /*
2773  * Restrict the privileges to what we can actually grant, and emit the
2774  * standards-mandated warning and error messages.
2775  */
2776  snprintf(loname, sizeof(loname), "large object %u", loid);
2777  this_privileges =
2778  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2779  istmt->all_privs, istmt->privileges,
2780  loid, grantorId, ACL_KIND_LARGEOBJECT,
2781  loname, 0, NULL);
2782 
2783  /*
2784  * Generate new ACL.
2785  */
2786  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2787  istmt->grant_option, istmt->behavior,
2788  istmt->grantees, this_privileges,
2789  grantorId, ownerId);
2790 
2791  /*
2792  * We need the members of both old and new ACLs so we can correct the
2793  * shared dependency information.
2794  */
2795  nnewmembers = aclmembers(new_acl, &newmembers);
2796 
2797  /* finished building new ACL value, now insert it */
2798  MemSet(values, 0, sizeof(values));
2799  MemSet(nulls, false, sizeof(nulls));
2800  MemSet(replaces, false, sizeof(replaces));
2801 
2802  replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
2804  = PointerGetDatum(new_acl);
2805 
2806  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2807  values, nulls, replaces);
2808 
2809  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2810 
2811  /* Update initial privileges for extensions */
2813 
2814  /* Update the shared dependency ACL info */
2816  HeapTupleGetOid(tuple), 0,
2817  ownerId,
2818  noldmembers, oldmembers,
2819  nnewmembers, newmembers);
2820 
2821  systable_endscan(scan);
2822 
2823  pfree(new_acl);
2824 
2825  /* prevent error when processing duplicate objects */
2827  }
2828 
2829  heap_close(relation, RowExclusiveLock);
2830 }
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:656
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define PointerGetDatum(X)
Definition: postgres.h:562
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:731
#define MemSet(start, val, len)
Definition: c.h:857
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:950
#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:5695
#define LargeObjectMetadataOidIndexId
Definition: indexing.h:183
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
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:922
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:157
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1456
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#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:5021
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#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:695
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#define LargeObjectRelationId
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:114
static void ExecGrant_Namespace ( InternalGrant grantStmt)
static

Definition at line 2833 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, NULL, 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().

2834 {
2835  Relation relation;
2836  ListCell *cell;
2837 
2838  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2839  istmt->privileges = ACL_ALL_RIGHTS_NAMESPACE;
2840 
2842 
2843  foreach(cell, istmt->objects)
2844  {
2845  Oid nspid = lfirst_oid(cell);
2846  Form_pg_namespace pg_namespace_tuple;
2847  Datum aclDatum;
2848  bool isNull;
2849  AclMode avail_goptions;
2850  AclMode this_privileges;
2851  Acl *old_acl;
2852  Acl *new_acl;
2853  Oid grantorId;
2854  Oid ownerId;
2855  HeapTuple tuple;
2856  HeapTuple newtuple;
2858  bool nulls[Natts_pg_namespace];
2859  bool replaces[Natts_pg_namespace];
2860  int noldmembers;
2861  int nnewmembers;
2862  Oid *oldmembers;
2863  Oid *newmembers;
2864 
2866  if (!HeapTupleIsValid(tuple))
2867  elog(ERROR, "cache lookup failed for namespace %u", nspid);
2868 
2869  pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
2870 
2871  /*
2872  * Get owner ID and working copy of existing ACL. If there's no ACL,
2873  * substitute the proper default.
2874  */
2875  ownerId = pg_namespace_tuple->nspowner;
2876  aclDatum = SysCacheGetAttr(NAMESPACENAME, tuple,
2878  &isNull);
2879  if (isNull)
2880  {
2881  old_acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
2882  /* There are no old member roles according to the catalogs */
2883  noldmembers = 0;
2884  oldmembers = NULL;
2885  }
2886  else
2887  {
2888  old_acl = DatumGetAclPCopy(aclDatum);
2889  /* Get the roles mentioned in the existing ACL */
2890  noldmembers = aclmembers(old_acl, &oldmembers);
2891  }
2892 
2893  /* Determine ID to do the grant as, and available grant options */
2894  select_best_grantor(GetUserId(), istmt->privileges,
2895  old_acl, ownerId,
2896  &grantorId, &avail_goptions);
2897 
2898  /*
2899  * Restrict the privileges to what we can actually grant, and emit the
2900  * standards-mandated warning and error messages.
2901  */
2902  this_privileges =
2903  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2904  istmt->all_privs, istmt->privileges,
2905  nspid, grantorId, ACL_KIND_NAMESPACE,
2906  NameStr(pg_namespace_tuple->nspname),
2907  0, NULL);
2908 
2909  /*
2910  * Generate new ACL.
2911  */
2912  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2913  istmt->grant_option, istmt->behavior,
2914  istmt->grantees, this_privileges,
2915  grantorId, ownerId);
2916 
2917  /*
2918  * We need the members of both old and new ACLs so we can correct the
2919  * shared dependency information.
2920  */
2921  nnewmembers = aclmembers(new_acl, &newmembers);
2922 
2923  /* finished building new ACL value, now insert it */
2924  MemSet(values, 0, sizeof(values));
2925  MemSet(nulls, false, sizeof(nulls));
2926  MemSet(replaces, false, sizeof(replaces));
2927 
2928  replaces[Anum_pg_namespace_nspacl - 1] = true;
2929  values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(new_acl);
2930 
2931  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2932  nulls, replaces);
2933 
2934  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2935 
2936  /* Update initial privileges for extensions */
2937  recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
2938 
2939  /* Update the shared dependency ACL info */
2941  ownerId,
2942  noldmembers, oldmembers,
2943  nnewmembers, newmembers);
2944 
2945  ReleaseSysCache(tuple);
2946 
2947  pfree(new_acl);
2948 
2949  /* prevent error when processing duplicate objects */
2951  }
2952 
2953  heap_close(relation, RowExclusiveLock);
2954 }
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:656
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:51
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
#define PointerGetDatum(X)
Definition: postgres.h:562
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:731
#define MemSet(start, val, len)
Definition: c.h:857
#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 SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:950
#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:5695
#define ACL_ALL_RIGHTS_NAMESPACE
Definition: acl.h:158
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:922
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#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:1456
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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:5021
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:114
static void ExecGrant_Relation ( InternalGrant grantStmt)
static

Definition at line 1736 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, NULL, 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().

1737 {
1738  Relation relation;
1739  Relation attRelation;
1740  ListCell *cell;
1741 
1744 
1745  foreach(cell, istmt->objects)
1746  {
1747  Oid relOid = lfirst_oid(cell);
1748  Datum aclDatum;
1749  Form_pg_class pg_class_tuple;
1750  bool isNull;
1751  AclMode this_privileges;
1752  AclMode *col_privileges;
1753  int num_col_privileges;
1754  bool have_col_privileges;
1755  Acl *old_acl;
1756  Acl *old_rel_acl;
1757  int noldmembers;
1758  Oid *oldmembers;
1759  Oid ownerId;
1760  HeapTuple tuple;
1761  ListCell *cell_colprivs;
1762 
1763  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
1764  if (!HeapTupleIsValid(tuple))
1765  elog(ERROR, "cache lookup failed for relation %u", relOid);
1766  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
1767 
1768  /* Not sensible to grant on an index */
1769  if (pg_class_tuple->relkind == RELKIND_INDEX)
1770  ereport(ERROR,
1771  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1772  errmsg("\"%s\" is an index",
1773  NameStr(pg_class_tuple->relname))));
1774 
1775  /* Composite types aren't tables either */
1776  if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
1777  ereport(ERROR,
1778  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1779  errmsg("\"%s\" is a composite type",
1780  NameStr(pg_class_tuple->relname))));
1781 
1782  /* Used GRANT SEQUENCE on a non-sequence? */
1783  if (istmt->objtype == ACL_OBJECT_SEQUENCE &&
1784  pg_class_tuple->relkind != RELKIND_SEQUENCE)
1785  ereport(ERROR,
1786  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1787  errmsg("\"%s\" is not a sequence",
1788  NameStr(pg_class_tuple->relname))));
1789 
1790  /* Adjust the default permissions based on object type */
1791  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
1792  {
1793  if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
1794  this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1795  else
1796  this_privileges = ACL_ALL_RIGHTS_RELATION;
1797  }
1798  else
1799  this_privileges = istmt->privileges;
1800 
1801  /*
1802  * The GRANT TABLE syntax can be used for sequences and non-sequences,
1803  * so we have to look at the relkind to determine the supported
1804  * permissions. The OR of table and sequence permissions were already
1805  * checked.
1806  */
1807  if (istmt->objtype == ACL_OBJECT_RELATION)
1808  {
1809  if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
1810  {
1811  /*
1812  * For backward compatibility, just throw a warning for
1813  * invalid sequence permissions when using the non-sequence
1814  * GRANT syntax.
1815  */
1816  if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
1817  {
1818  /*
1819  * Mention the object name because the user needs to know
1820  * which operations succeeded. This is required because
1821  * WARNING allows the command to continue.
1822  */
1823  ereport(WARNING,
1824  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1825  errmsg("sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges",
1826  NameStr(pg_class_tuple->relname))));
1827  this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
1828  }
1829  }
1830  else
1831  {
1832  if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
1833  {
1834  /*
1835  * USAGE is the only permission supported by sequences but
1836  * not by non-sequences. Don't mention the object name
1837  * because we didn't in the combined TABLE | SEQUENCE
1838  * check.
1839  */
1840  ereport(ERROR,
1841  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1842  errmsg("invalid privilege type %s for table",
1843  "USAGE")));
1844  }
1845  }
1846  }
1847 
1848  /*
1849  * Set up array in which we'll accumulate any column privilege bits
1850  * that need modification. The array is indexed such that entry [0]
1851  * corresponds to FirstLowInvalidHeapAttributeNumber.
1852  */
1853  num_col_privileges = pg_class_tuple->relnatts - FirstLowInvalidHeapAttributeNumber + 1;
1854  col_privileges = (AclMode *) palloc0(num_col_privileges * sizeof(AclMode));
1855  have_col_privileges = false;
1856 
1857  /*
1858  * If we are revoking relation privileges that are also column
1859  * privileges, we must implicitly revoke them from each column too,
1860  * per SQL spec. (We don't need to implicitly add column privileges
1861  * during GRANT because the permissions-checking code always checks
1862  * both relation and per-column privileges.)
1863  */
1864  if (!istmt->is_grant &&
1865  (this_privileges & ACL_ALL_RIGHTS_COLUMN) != 0)
1866  {
1867  expand_all_col_privileges(relOid, pg_class_tuple,
1868  this_privileges & ACL_ALL_RIGHTS_COLUMN,
1869  col_privileges,
1870  num_col_privileges);
1871  have_col_privileges = true;
1872  }
1873 
1874  /*
1875  * Get owner ID and working copy of existing ACL. If there's no ACL,
1876  * substitute the proper default.
1877  */
1878  ownerId = pg_class_tuple->relowner;
1879  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
1880  &isNull);
1881  if (isNull)
1882  {
1883  switch (pg_class_tuple->relkind)
1884  {
1885  case RELKIND_SEQUENCE:
1886  old_acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
1887  break;
1888  default:
1889  old_acl = acldefault(ACL_OBJECT_RELATION, ownerId);
1890  break;
1891  }
1892  /* There are no old member roles according to the catalogs */
1893  noldmembers = 0;
1894  oldmembers = NULL;
1895  }
1896  else
1897  {
1898  old_acl = DatumGetAclPCopy(aclDatum);
1899  /* Get the roles mentioned in the existing ACL */
1900  noldmembers = aclmembers(old_acl, &oldmembers);
1901  }
1902 
1903  /* Need an extra copy of original rel ACL for column handling */
1904  old_rel_acl = aclcopy(old_acl);
1905 
1906  /*
1907  * Handle relation-level privileges, if any were specified
1908  */
1909  if (this_privileges != ACL_NO_RIGHTS)
1910  {
1911  AclMode avail_goptions;
1912  Acl *new_acl;
1913  Oid grantorId;
1914  HeapTuple newtuple;
1916  bool nulls[Natts_pg_class];
1917  bool replaces[Natts_pg_class];
1918  int nnewmembers;
1919  Oid *newmembers;
1920  AclObjectKind aclkind;
1921 
1922  /* Determine ID to do the grant as, and available grant options */
1923  select_best_grantor(GetUserId(), this_privileges,
1924  old_acl, ownerId,
1925  &grantorId, &avail_goptions);
1926 
1927  switch (pg_class_tuple->relkind)
1928  {
1929  case RELKIND_SEQUENCE:
1930  aclkind = ACL_KIND_SEQUENCE;
1931  break;
1932  default:
1933  aclkind = ACL_KIND_CLASS;
1934  break;
1935  }
1936 
1937  /*
1938  * Restrict the privileges to what we can actually grant, and emit
1939  * the standards-mandated warning and error messages.
1940  */
1941  this_privileges =
1942  restrict_and_check_grant(istmt->is_grant, avail_goptions,
1943  istmt->all_privs, this_privileges,
1944  relOid, grantorId, aclkind,
1945  NameStr(pg_class_tuple->relname),
1946  0, NULL);
1947 
1948  /*
1949  * Generate new ACL.
1950  */
1951  new_acl = merge_acl_with_grant(old_acl,
1952  istmt->is_grant,
1953  istmt->grant_option,
1954  istmt->behavior,
1955  istmt->grantees,
1956  this_privileges,
1957  grantorId,
1958  ownerId);
1959 
1960  /*
1961  * We need the members of both old and new ACLs so we can correct
1962  * the shared dependency information.
1963  */
1964  nnewmembers = aclmembers(new_acl, &newmembers);
1965 
1966  /* finished building new ACL value, now insert it */
1967  MemSet(values, 0, sizeof(values));
1968  MemSet(nulls, false, sizeof(nulls));
1969  MemSet(replaces, false, sizeof(replaces));
1970 
1971  replaces[Anum_pg_class_relacl - 1] = true;
1972  values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
1973 
1974  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
1975  values, nulls, replaces);
1976 
1977  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
1978 
1979  /* Update initial privileges for extensions */
1980  recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl);
1981 
1982  /* Update the shared dependency ACL info */
1984  ownerId,
1985  noldmembers, oldmembers,
1986  nnewmembers, newmembers);
1987 
1988  pfree(new_acl);
1989  }
1990 
1991  /*
1992  * Handle column-level privileges, if any were specified or implied.
1993  * We first expand the user-specified column privileges into the
1994  * array, and then iterate over all nonempty array entries.
1995  */
1996  foreach(cell_colprivs, istmt->col_privs)
1997  {
1998  AccessPriv *col_privs = (AccessPriv *) lfirst(cell_colprivs);
1999 
2000  if (col_privs->priv_name == NULL)
2001  this_privileges = ACL_ALL_RIGHTS_COLUMN;
2002  else
2003  this_privileges = string_to_privilege(col_privs->priv_name);
2004 
2005  if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
2006  ereport(ERROR,
2007  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
2008  errmsg("invalid privilege type %s for column",
2009  privilege_to_string(this_privileges))));
2010 
2011  if (pg_class_tuple->relkind == RELKIND_SEQUENCE &&
2012  this_privileges & ~((AclMode) ACL_SELECT))
2013  {
2014  /*
2015  * The only column privilege allowed on sequences is SELECT.
2016  * This is a warning not error because we do it that way for
2017  * relation-level privileges.
2018  */
2019  ereport(WARNING,
2020  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
2021  errmsg("sequence \"%s\" only supports SELECT column privileges",
2022  NameStr(pg_class_tuple->relname))));
2023 
2024  this_privileges &= (AclMode) ACL_SELECT;
2025  }
2026 
2027  expand_col_privileges(col_privs->cols, relOid,
2028  this_privileges,
2029  col_privileges,
2030  num_col_privileges);
2031  have_col_privileges = true;
2032  }
2033 
2034  if (have_col_privileges)
2035  {
2036  AttrNumber i;
2037 
2038  for (i = 0; i < num_col_privileges; i++)
2039  {
2040  if (col_privileges[i] == ACL_NO_RIGHTS)
2041  continue;
2042  ExecGrant_Attribute(istmt,
2043  relOid,
2044  NameStr(pg_class_tuple->relname),
2046  ownerId,
2047  col_privileges[i],
2048  attRelation,
2049  old_rel_acl);
2050  }
2051  }
2052 
2053  pfree(old_rel_acl);
2054  pfree(col_privileges);
2055 
2056  ReleaseSysCache(tuple);
2057 
2058  /* prevent error when processing duplicate objects */
2060  }
2061 
2062  heap_close(attRelation, RowExclusiveLock);
2063  heap_close(relation, RowExclusiveLock);
2064 }
#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:656
#define Anum_pg_class_relacl
Definition: pg_class.h:133
#define ACL_ALL_RIGHTS_COLUMN
Definition: acl.h:149
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
#define PointerGetDatum(X)
Definition: postgres.h:562
static AclMode string_to_privilege(const char *privname)
Definition: aclchk.c:3215
#define RelationRelationId
Definition: pg_class.h:29
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:731
#define AttributeRelationId
Definition: pg_attribute.h:33
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:857
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
#define heap_close(r, l)
Definition: heapam.h:97
List * cols
Definition: parsenodes.h:1861
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
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
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:1505
void pfree(void *pointer)
Definition: mcxt.c:950
#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:5695
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:1538
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:1588
#define WARNING
Definition: elog.h:40
void * palloc0(Size size)
Definition: mcxt.c:878
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:922
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
#define ACL_SELECT
Definition: parsenodes.h:73
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:151
Acl * aclcopy(const Acl *orig_acl)
Definition: acl.c:406
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1456
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#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:5021
static Datum values[MAXATTR]
Definition: bootstrap.c:163
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:150
#define NameStr(name)
Definition: c.h:499
#define RELKIND_INDEX
Definition: pg_class.h:161
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:3252
#define elog
Definition: elog.h:219
AclObjectKind
Definition: acl.h:179
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
int16 AttrNumber
Definition: attnum.h:21
char * priv_name
Definition: parsenodes.h:1860
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:114
static void ExecGrant_Tablespace ( InternalGrant grantStmt)
static

Definition at line 2957 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, NULL, 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().

2958 {
2959  Relation relation;
2960  ListCell *cell;
2961 
2962  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2963  istmt->privileges = ACL_ALL_RIGHTS_TABLESPACE;
2964 
2966 
2967  foreach(cell, istmt->objects)
2968  {
2969  Oid tblId = lfirst_oid(cell);
2970  Form_pg_tablespace pg_tablespace_tuple;
2971  Datum aclDatum;
2972  bool isNull;
2973  AclMode avail_goptions;
2974  AclMode this_privileges;
2975  Acl *old_acl;
2976  Acl *new_acl;
2977  Oid grantorId;
2978  Oid ownerId;
2979  HeapTuple newtuple;
2981  bool nulls[Natts_pg_tablespace];
2982  bool replaces[Natts_pg_tablespace];
2983  int noldmembers;
2984  int nnewmembers;
2985  Oid *oldmembers;
2986  Oid *newmembers;
2987  HeapTuple tuple;
2988 
2989  /* Search syscache for pg_tablespace */
2991  if (!HeapTupleIsValid(tuple))
2992  elog(ERROR, "cache lookup failed for tablespace %u", tblId);
2993 
2994  pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);
2995 
2996  /*
2997  * Get owner ID and working copy of existing ACL. If there's no ACL,
2998  * substitute the proper default.
2999  */
3000  ownerId = pg_tablespace_tuple->spcowner;
3001  aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl,
3002  RelationGetDescr(relation), &isNull);
3003  if (isNull)
3004  {
3005  old_acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
3006  /* There are no old member roles according to the catalogs */
3007  noldmembers = 0;
3008  oldmembers = NULL;
3009  }
3010  else
3011  {
3012  old_acl = DatumGetAclPCopy(aclDatum);
3013  /* Get the roles mentioned in the existing ACL */
3014  noldmembers = aclmembers(old_acl, &oldmembers);
3015  }
3016 
3017  /* Determine ID to do the grant as, and available grant options */
3018  select_best_grantor(GetUserId(), istmt->privileges,
3019  old_acl, ownerId,
3020  &grantorId, &avail_goptions);
3021 
3022  /*
3023  * Restrict the privileges to what we can actually grant, and emit the
3024  * standards-mandated warning and error messages.
3025  */
3026  this_privileges =
3027  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3028  istmt->all_privs, istmt->privileges,
3029  tblId, grantorId, ACL_KIND_TABLESPACE,
3030  NameStr(pg_tablespace_tuple->spcname),
3031  0, NULL);
3032 
3033  /*
3034  * Generate new ACL.
3035  */
3036  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3037  istmt->grant_option, istmt->behavior,
3038  istmt->grantees, this_privileges,
3039  grantorId, ownerId);
3040 
3041  /*
3042  * We need the members of both old and new ACLs so we can correct the
3043  * shared dependency information.
3044  */
3045  nnewmembers = aclmembers(new_acl, &newmembers);
3046 
3047  /* finished building new ACL value, now insert it */
3048  MemSet(values, 0, sizeof(values));
3049  MemSet(nulls, false, sizeof(nulls));
3050  MemSet(replaces, false, sizeof(replaces));
3051 
3052  replaces[Anum_pg_tablespace_spcacl - 1] = true;
3053  values[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(new_acl);
3054 
3055  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3056  nulls, replaces);
3057 
3058  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3059 
3060  /* Update the shared dependency ACL info */
3062  ownerId,
3063  noldmembers, oldmembers,
3064  nnewmembers, newmembers);
3065 
3066  ReleaseSysCache(tuple);
3067  pfree(new_acl);
3068 
3069  /* prevent error when processing duplicate objects */
3071  }
3072 
3073  heap_close(relation, RowExclusiveLock);
3074 }
#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:656
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
#define PointerGetDatum(X)
Definition: postgres.h:562
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:731
#define MemSet(start, val, len)
Definition: c.h:857
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:159
#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 SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:950
#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:769
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:922
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1456
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
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:5021
#define TableSpaceRelationId
Definition: pg_tablespace.h:29
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:114
#define Natts_pg_tablespace
Definition: pg_tablespace.h:54
static void ExecGrant_Type ( InternalGrant grantStmt)
static

Definition at line 3077 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, NULL, 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().

3078 {
3079  Relation relation;
3080  ListCell *cell;
3081 
3082  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
3083  istmt->privileges = ACL_ALL_RIGHTS_TYPE;
3084 
3086 
3087  foreach(cell, istmt->objects)
3088  {
3089  Oid typId = lfirst_oid(cell);
3090  Form_pg_type pg_type_tuple;
3091  Datum aclDatum;
3092  bool isNull;
3093  AclMode avail_goptions;
3094  AclMode this_privileges;
3095  Acl *old_acl;
3096  Acl *new_acl;
3097  Oid grantorId;
3098  Oid ownerId;
3099  HeapTuple newtuple;
3101  bool nulls[Natts_pg_type];
3102  bool replaces[Natts_pg_type];
3103  int noldmembers;
3104  int nnewmembers;
3105  Oid *oldmembers;
3106  Oid *newmembers;
3107  HeapTuple tuple;
3108 
3109  /* Search syscache for pg_type */
3110  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typId));
3111  if (!HeapTupleIsValid(tuple))
3112  elog(ERROR, "cache lookup failed for type %u", typId);
3113 
3114  pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
3115 
3116  if (pg_type_tuple->typelem != 0 && pg_type_tuple->typlen == -1)
3117  ereport(ERROR,
3118  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
3119  errmsg("cannot set privileges of array types"),
3120  errhint("Set the privileges of the element type instead.")));
3121 
3122  /* Used GRANT DOMAIN on a non-domain? */
3123  if (istmt->objtype == ACL_OBJECT_DOMAIN &&
3124  pg_type_tuple->typtype != TYPTYPE_DOMAIN)
3125  ereport(ERROR,
3126  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3127  errmsg("\"%s\" is not a domain",
3128  NameStr(pg_type_tuple->typname))));
3129 
3130  /*
3131  * Get owner ID and working copy of existing ACL. If there's no ACL,
3132  * substitute the proper default.
3133  */
3134  ownerId = pg_type_tuple->typowner;
3135  aclDatum = heap_getattr(tuple, Anum_pg_type_typacl,
3136  RelationGetDescr(relation), &isNull);
3137  if (isNull)
3138  {
3139  old_acl = acldefault(istmt->objtype, ownerId);
3140  /* There are no old member roles according to the catalogs */
3141  noldmembers = 0;
3142  oldmembers = NULL;
3143  }
3144  else
3145  {
3146  old_acl = DatumGetAclPCopy(aclDatum);
3147  /* Get the roles mentioned in the existing ACL */
3148  noldmembers = aclmembers(old_acl, &oldmembers);
3149  }
3150 
3151  /* Determine ID to do the grant as, and available grant options */
3152  select_best_grantor(GetUserId(), istmt->privileges,
3153  old_acl, ownerId,
3154  &grantorId, &avail_goptions);
3155 
3156  /*
3157  * Restrict the privileges to what we can actually grant, and emit the
3158  * standards-mandated warning and error messages.
3159  */
3160  this_privileges =
3161  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3162  istmt->all_privs, istmt->privileges,
3163  typId, grantorId, ACL_KIND_TYPE,
3164  NameStr(pg_type_tuple->typname),
3165  0, NULL);
3166 
3167  /*
3168  * Generate new ACL.
3169  */
3170  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3171  istmt->grant_option, istmt->behavior,
3172  istmt->grantees, this_privileges,
3173  grantorId, ownerId);
3174 
3175  /*
3176  * We need the members of both old and new ACLs so we can correct the
3177  * shared dependency information.
3178  */
3179  nnewmembers = aclmembers(new_acl, &newmembers);
3180 
3181  /* finished building new ACL value, now insert it */
3182  MemSet(values, 0, sizeof(values));
3183  MemSet(nulls, false, sizeof(nulls));
3184  MemSet(replaces, false, sizeof(replaces));
3185 
3186  replaces[Anum_pg_type_typacl - 1] = true;
3187  values[Anum_pg_type_typacl - 1] = PointerGetDatum(new_acl);
3188 
3189  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3190  nulls, replaces);
3191 
3192  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3193 
3194  /* Update initial privileges for extensions */
3195  recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
3196 
3197  /* Update the shared dependency ACL info */
3199  ownerId,
3200  noldmembers, oldmembers,
3201  nnewmembers, newmembers);
3202 
3203  ReleaseSysCache(tuple);
3204  pfree(new_acl);
3205 
3206  /* prevent error when processing duplicate objects */
3208  }
3209 
3210  heap_close(relation, RowExclusiveLock);
3211 }
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:656
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
#define PointerGetDatum(X)
Definition: postgres.h:562
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:731
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:857
#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
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
uint32 AclMode
Definition: parsenodes.h:70
void pfree(void *pointer)
Definition: mcxt.c:950
#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:160
#define ereport(elevel, rest)
Definition: elog.h:122
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5695
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
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:922
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define Natts_pg_type
Definition: pg_type.h:239
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1456
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#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:5021
static Datum values[MAXATTR]
Definition: bootstrap.c:163
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define DatumGetAclPCopy(X)
Definition: acl.h:114
static void ExecGrantStmt_oids ( InternalGrant istmt)
static

Definition at line 565 of file aclchk.c.

References ACL_OBJECT_DATABASE, ACL_OBJECT_DOMAIN, ACL_OBJECT_FDW, ACL_OBJECT_FOREIGN_SERVER, ACL_OBJECT_FUNCTION, ACL_OBJECT_LANGUAGE, ACL_OBJECT_LARGEOBJECT, ACL_OBJECT_NAMESPACE, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TABLESPACE, ACL_OBJECT_TYPE, elog, ERROR, 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().

566 {
567  switch (istmt->objtype)
568  {
569  case ACL_OBJECT_RELATION:
570  case ACL_OBJECT_SEQUENCE:
571  ExecGrant_Relation(istmt);
572  break;
573  case ACL_OBJECT_DATABASE:
574  ExecGrant_Database(istmt);
575  break;
576  case ACL_OBJECT_DOMAIN:
577  case ACL_OBJECT_TYPE:
578  ExecGrant_Type(istmt);
579  break;
580  case ACL_OBJECT_FDW:
581  ExecGrant_Fdw(istmt);
582  break;
585  break;
586  case ACL_OBJECT_FUNCTION:
587  ExecGrant_Function(istmt);
588  break;
589  case ACL_OBJECT_LANGUAGE:
590  ExecGrant_Language(istmt);
591  break;
593  ExecGrant_Largeobject(istmt);
594  break;
596  ExecGrant_Namespace(istmt);
597  break;
599  ExecGrant_Tablespace(istmt);
600  break;
601  default:
602  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
603  (int) istmt->objtype);
604  }
605 
606  /*
607  * Pass the info to event triggers about the just-executed GRANT. Note
608  * that we prefer to do it after actually executing it, because that gives
609  * the functions a chance to adjust the istmt with privileges actually
610  * granted.
611  */
614 }
static void ExecGrant_Language(InternalGrant *grantStmt)
Definition: aclchk.c:2562
static void ExecGrant_Function(InternalGrant *grantStmt)
Definition: aclchk.c:2439
static void ExecGrant_Tablespace(InternalGrant *grantStmt)
Definition: aclchk.c:2957
static void ExecGrant_Namespace(InternalGrant *grantStmt)
Definition: aclchk.c:2833
static void ExecGrant_Type(InternalGrant *grantStmt)
Definition: aclchk.c:3077
static void ExecGrant_Database(InternalGrant *grantStmt)
Definition: aclchk.c:2067
GrantObjectType objtype
#define ERROR
Definition: elog.h:43
static void ExecGrant_Fdw(InternalGrant *grantStmt)
Definition: aclchk.c:2187
static void ExecGrant_Largeobject(InternalGrant *grantStmt)
Definition: aclchk.c:2693
static void ExecGrant_Relation(InternalGrant *grantStmt)
Definition: aclchk.c:1736
bool EventTriggerSupportsGrantObjectType(GrantObjectType objtype)
void EventTriggerCollectGrant(InternalGrant *istmt)
#define elog
Definition: elog.h:219
static void ExecGrant_ForeignServer(InternalGrant *grantStmt)
Definition: aclchk.c:2314
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_RELATION, 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, NULL, 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_TABLESPACE;
487  errormsg = gettext_noop("invalid privilege type %s for tablespace");
488  break;
489  case ACL_OBJECT_TYPE:
490  all_privileges = ACL_ALL_RIGHTS_TYPE;
491  errormsg = gettext_noop("invalid privilege type %s for type");
492  break;
493  case ACL_OBJECT_FDW:
494  all_privileges = ACL_ALL_RIGHTS_FDW;
495  errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
496  break;
498  all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
499  errormsg = gettext_noop("invalid privilege type %s for foreign server");
500  break;
501  default:
502  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
503  (int) stmt->objtype);
504  /* keep compiler quiet */
505  all_privileges = ACL_NO_RIGHTS;
506  errormsg = NULL;
507  }
508 
509  if (stmt->privileges == NIL)
510  {
511  istmt.all_privs = true;
512 
513  /*
514  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
515  * depending on the object type
516  */
517  istmt.privileges = ACL_NO_RIGHTS;
518  }
519  else
520  {
521  istmt.all_privs = false;
522  istmt.privileges = ACL_NO_RIGHTS;
523 
524  foreach(cell, stmt->privileges)
525  {
526  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
527  AclMode priv;
528 
529  /*
530  * If it's a column-level specification, we just set it aside in
531  * col_privs for the moment; but insist it's for a relation.
532  */
533  if (privnode->cols)
534  {
535  if (stmt->objtype != ACL_OBJECT_RELATION)
536  ereport(ERROR,
537  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
538  errmsg("column privileges are only valid for relations")));
539  istmt.col_privs = lappend(istmt.col_privs, privnode);
540  continue;
541  }
542 
543  if (privnode->priv_name == NULL) /* parser mistake? */
544  elog(ERROR, "AccessPriv node must specify privilege or columns");
545  priv = string_to_privilege(privnode->priv_name);
546 
547  if (priv & ~((AclMode) all_privileges))
548  ereport(ERROR,
549  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
550  errmsg(errormsg, privilege_to_string(priv))));
551 
552  istmt.privileges |= priv;
553  }
554  }
555 
556  ExecGrantStmt_oids(&istmt);
557 }
#define NIL
Definition: pg_list.h:69
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:155
static AclMode string_to_privilege(const char *privname)
Definition: aclchk.c:3215
AclMode privileges
bool grant_option
Definition: parsenodes.h:1831
#define gettext_noop(x)
Definition: c.h:139
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:159
List * cols
Definition: parsenodes.h:1861
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:756
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:156
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:160
#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:158
bool is_grant
Definition: parsenodes.h:1823
static void ExecGrantStmt_oids(InternalGrant *istmt)
Definition: aclchk.c:565
RoleSpecType roletype
Definition: parsenodes.h:328
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5129
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:151
List * privileges
Definition: parsenodes.h:1828
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:157
DropBehavior behavior
DropBehavior behavior
Definition: parsenodes.h:1832
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
List * objects
Definition: parsenodes.h:1826
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:152
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:154
GrantObjectType objtype
Definition: parsenodes.h:1825
static List * objectNamesToOids(GrantObjectType objtype, List *objnames)
Definition: aclchk.c:627
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_ALL_RIGHTS_RELATION
Definition: acl.h:150
#define ACL_ID_PUBLIC
Definition: acl.h:39
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:153
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:3252
List * grantees
Definition: parsenodes.h:1830
#define elog
Definition: elog.h:219
GrantTargetType targtype
Definition: parsenodes.h:1824
char * priv_name
Definition: parsenodes.h:1860
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 1538 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().

1542 {
1543  AttrNumber curr_att;
1544 
1545  Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
1546  for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
1547  curr_att <= classForm->relnatts;
1548  curr_att++)
1549  {
1550  HeapTuple attTuple;
1551  bool isdropped;
1552 
1553  if (curr_att == InvalidAttrNumber)
1554  continue;
1555 
1556  /* Skip OID column if it doesn't exist */
1557  if (curr_att == ObjectIdAttributeNumber && !classForm->relhasoids)
1558  continue;
1559 
1560  /* Views don't have any system columns at all */
1561  if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
1562  continue;
1563 
1564  attTuple = SearchSysCache2(ATTNUM,
1565  ObjectIdGetDatum(table_oid),
1566  Int16GetDatum(curr_att));
1567  if (!HeapTupleIsValid(attTuple))
1568  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1569  curr_att, table_oid);
1570 
1571  isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
1572 
1573  ReleaseSysCache(attTuple);
1574 
1575  /* ignore dropped columns */
1576  if (isdropped)
1577  continue;
1578 
1579  col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
1580  }
1581 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#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:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:675
#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
#define SearchSysCache2(cacheId, key1, key2)
Definition: syscache.h:154
static void expand_col_privileges ( List colnames,
Oid  table_oid,
AclMode  this_privileges,
AclMode col_privileges,
int  num_col_privileges 
)
static

Definition at line 1505 of file aclchk.c.

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

Referenced by ExecGrant_Relation().

1509 {
1510  ListCell *cell;
1511 
1512  foreach(cell, colnames)
1513  {
1514  char *colname = strVal(lfirst(cell));
1515  AttrNumber attnum;
1516 
1517  attnum = get_attnum(table_oid, colname);
1518  if (attnum == InvalidAttrNumber)
1519  ereport(ERROR,
1520  (errcode(ERRCODE_UNDEFINED_COLUMN),
1521  errmsg("column \"%s\" of relation \"%s\" does not exist",
1522  colname, get_rel_name(table_oid))));
1524  if (attnum <= 0 || attnum >= num_col_privileges)
1525  elog(ERROR, "column number out of range"); /* safety check */
1526  col_privileges[attnum] |= this_privileges;
1527  }
1528 }
#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:1726
int16 AttrNumber
Definition: attnum.h:21
static Acl* get_default_acl_internal ( Oid  roleId,
Oid  nsp_oid,
char  objtype 
)
static

Definition at line 5213 of file aclchk.c.

References Anum_pg_default_acl_defaclacl, CharGetDatum, DatumGetAclPCopy, DEFACLROLENSPOBJ, HeapTupleIsValid, NULL, ObjectIdGetDatum, ReleaseSysCache(), result, SearchSysCache3, and SysCacheGetAttr().

Referenced by get_user_default_acl().

5214 {
5215  Acl *result = NULL;
5216  HeapTuple tuple;
5217 
5219  ObjectIdGetDatum(roleId),
5220  ObjectIdGetDatum(nsp_oid),
5221  CharGetDatum(objtype));
5222 
5223  if (HeapTupleIsValid(tuple))
5224  {
5225  Datum aclDatum;
5226  bool isNull;
5227 
5228  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
5230  &isNull);
5231  if (!isNull)
5232  result = DatumGetAclPCopy(aclDatum);
5233  ReleaseSysCache(tuple);
5234  }
5235 
5236  return result;
5237 }
return result
Definition: formatting.c:1618
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define Anum_pg_default_acl_defaclacl
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define CharGetDatum(X)
Definition: postgres.h:422
#define SearchSysCache3(cacheId, key1, key2, key3)
Definition: syscache.h:156
#define DatumGetAclPCopy(X)
Definition: acl.h:114
Acl* get_user_default_acl ( GrantObjectType  objtype,
Oid  ownerId,
Oid  nsp_oid 
)

Definition at line 5245 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, IsBootstrapProcessingMode, NULL, and result.

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

5246 {
5247  Acl *result;
5248  Acl *glob_acl;
5249  Acl *schema_acl;
5250  Acl *def_acl;
5251  char defaclobjtype;
5252 
5253  /*
5254  * Use NULL during bootstrap, since pg_default_acl probably isn't there
5255  * yet.
5256  */
5258  return NULL;
5259 
5260  /* Check if object type is supported in pg_default_acl */
5261  switch (objtype)
5262  {
5263  case ACL_OBJECT_RELATION:
5264  defaclobjtype = DEFACLOBJ_RELATION;
5265  break;
5266 
5267  case ACL_OBJECT_SEQUENCE:
5268  defaclobjtype = DEFACLOBJ_SEQUENCE;
5269  break;
5270 
5271  case ACL_OBJECT_FUNCTION:
5272  defaclobjtype = DEFACLOBJ_FUNCTION;
5273  break;
5274 
5275  case ACL_OBJECT_TYPE:
5276  defaclobjtype = DEFACLOBJ_TYPE;
5277  break;
5278 
5279  case ACL_OBJECT_NAMESPACE:
5280  defaclobjtype = DEFACLOBJ_NAMESPACE;
5281  break;
5282 
5283  default:
5284  return NULL;
5285  }
5286 
5287  /* Look up the relevant pg_default_acl entries */
5288  glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
5289  schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
5290 
5291  /* Quick out if neither entry exists */
5292  if (glob_acl == NULL && schema_acl == NULL)
5293  return NULL;
5294 
5295  /* We need to know the hard-wired default value, too */
5296  def_acl = acldefault(objtype, ownerId);
5297 
5298  /* If there's no global entry, substitute the hard-wired default */
5299  if (glob_acl == NULL)
5300  glob_acl = def_acl;
5301 
5302  /* Merge in any per-schema privileges */
5303  result = aclmerge(glob_acl, schema_acl, ownerId);
5304 
5305  /*
5306  * For efficiency, we want to return NULL if the result equals default.
5307  * This requires sorting both arrays to get an accurate comparison.
5308  */
5309  aclitemsort(result);
5310  aclitemsort(def_acl);
5311  if (aclequal(result, def_acl))
5312  result = NULL;
5313 
5314  return result;
5315 }
Acl * acldefault(GrantObjectType objtype, Oid ownerId)
Definition: acl.c:731
static Acl * get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
Definition: aclchk.c:5213
return result
Definition: formatting.c:1618
bool aclequal(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:508
#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:450
#define NULL
Definition: c.h:229
#define DEFACLOBJ_FUNCTION
void aclitemsort(Acl *acl)
Definition: acl.c:494
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:365
static List * getRelationsInNamespace ( Oid  namespaceId,
char  relkind 
)
static

Definition at line 827 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, NULL, ObjectIdGetDatum, RelationRelationId, and ScanKeyInit().

Referenced by objectsInSchemaToOids().

828 {
829  List *relations = NIL;
830  ScanKeyData key[2];
831  Relation rel;
832  HeapScanDesc scan;
833  HeapTuple tuple;
834 
835  ScanKeyInit(&key[0],
837  BTEqualStrategyNumber, F_OIDEQ,
838  ObjectIdGetDatum(namespaceId));
839  ScanKeyInit(&key[1],
841  BTEqualStrategyNumber, F_CHAREQ,
842  CharGetDatum(relkind));
843 
845  scan = heap_beginscan_catalog(rel, 2, key);
846 
847  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
848  {
849  relations = lappend_oid(relations, HeapTupleGetOid(tuple));
850  }
851 
852  heap_endscan(scan);
854 
855  return relations;
856 }
#define NIL
Definition: pg_list.h:69
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1578
#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:1399
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1794
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define NULL
Definition: c.h:229
#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:695
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31
bool has_bypassrls_privilege ( Oid  roleid)

Definition at line 5189 of file aclchk.c.

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

Referenced by check_enable_rls(), and RI_Initial_Check().

5190 {
5191  bool result = false;
5192  HeapTuple utup;
5193 
5194  /* Superusers bypass all permission checking. */
5195  if (superuser_arg(roleid))
5196  return true;
5197 
5198  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5199  if (HeapTupleIsValid(utup))
5200  {
5201  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
5202  ReleaseSysCache(utup);
5203  }
5204  return result;
5205 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
return result
Definition: formatting.c:1618
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
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
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool has_createrole_privilege ( Oid  roleid)

Definition at line 5170 of file aclchk.c.

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

Referenced by check_object_ownership(), and have_createrole_privilege().

5171 {
5172  bool result = false;
5173  HeapTuple utup;
5174 
5175  /* Superusers bypass all permission checking. */
5176  if (superuser_arg(roleid))
5177  return true;
5178 
5179  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5180  if (HeapTupleIsValid(utup))
5181  {
5182  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
5183  ReleaseSysCache(utup);
5184  }
5185  return result;
5186 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
return result
Definition: formatting.c:1618
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
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
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
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:49
#define ACL_MODECHG_DEL
Definition: acl.h:123
int errcode(int sqlerrcode)
Definition: elog.c:575
Oid ai_grantor
Definition: acl.h:50
void pfree(void *pointer)
Definition: mcxt.c:950
#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:122
Definition: acl.h:47
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_ID_PUBLIC
Definition: acl.h:39
Acl * aclupdate(const Acl *old_acl, const AclItem *mod_aip, int modechg, Oid ownerId, DropBehavior behavior)
Definition: acl.c:914
#define ACLITEM_SET_PRIVS_GOPTIONS(item, privs, goptions)
Definition: acl.h:75
#define lfirst_oid(lc)
Definition: pg_list.h:108
static List * objectNamesToOids ( GrantObjectType  objtype,
List objnames 
)
static

Definition at line 627 of file aclchk.c.

References ACL_OBJECT_DATABASE, ACL_OBJECT_DOMAIN, ACL_OBJECT_FDW, ACL_OBJECT_FOREIGN_SERVER, ACL_OBJECT_FUNCTION, ACL_OBJECT_LANGUAGE, ACL_OBJECT_LARGEOBJECT, ACL_OBJECT_NAMESPACE, ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, ACL_OBJECT_TABLESPACE, ACL_OBJECT_TYPE, Assert, 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, NULL, oidparse(), RangeVarGetRelid, strVal, and typenameTypeId().

Referenced by ExecuteGrantStmt().

628 {
629  List *objects = NIL;
630  ListCell *cell;
631 
632  Assert(objnames != NIL);
633 
634  switch (objtype)
635  {
636  case ACL_OBJECT_RELATION:
637  case ACL_OBJECT_SEQUENCE:
638  foreach(cell, objnames)
639  {
640  RangeVar *relvar = (RangeVar *) lfirst(cell);
641  Oid relOid;
642 
643  relOid = RangeVarGetRelid(relvar, NoLock, false);
644  objects = lappend_oid(objects, relOid);
645  }
646  break;
647  case ACL_OBJECT_DATABASE:
648  foreach(cell, objnames)
649  {
650  char *dbname = strVal(lfirst(cell));
651  Oid dbid;
652 
653  dbid = get_database_oid(dbname, false);
654  objects = lappend_oid(objects, dbid);
655  }
656  break;
657  case ACL_OBJECT_DOMAIN:
658  case ACL_OBJECT_TYPE:
659  foreach(cell, objnames)
660  {
661  List *typname = (List *) lfirst(cell);
662  Oid oid;
663 
665  objects = lappend_oid(objects, oid);
666  }
667  break;
668  case ACL_OBJECT_FUNCTION:
669  foreach(cell, objnames)
670  {
671  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
672  Oid funcid;
673 
674  funcid = LookupFuncWithArgs(func, false);
675  objects = lappend_oid(objects, funcid);
676  }
677  break;
678  case ACL_OBJECT_LANGUAGE:
679  foreach(cell, objnames)
680  {
681  char *langname = strVal(lfirst(cell));
682  Oid oid;
683 
684  oid = get_language_oid(langname, false);
685  objects = lappend_oid(objects, oid);
686  }
687  break;
689  foreach(cell, objnames)
690  {
691  Oid lobjOid = oidparse(lfirst(cell));
692 
693  if (!LargeObjectExists(lobjOid))
694  ereport(ERROR,
695  (errcode(ERRCODE_UNDEFINED_OBJECT),
696  errmsg("large object %u does not exist",
697  lobjOid)));
698 
699  objects = lappend_oid(objects, lobjOid);
700  }
701  break;
703  foreach(cell, objnames)
704  {
705  char *nspname = strVal(lfirst(cell));
706  Oid oid;
707 
708  oid = get_namespace_oid(nspname, false);
709  objects = lappend_oid(objects, oid);
710  }
711  break;
713  foreach(cell, objnames)
714  {
715  char *spcname = strVal(lfirst(cell));
716  Oid spcoid;
717 
718  spcoid = get_tablespace_oid(spcname, false);
719  objects = lappend_oid(objects, spcoid);
720  }
721  break;
722  case ACL_OBJECT_FDW:
723  foreach(cell, objnames)
724  {
725  char *fdwname = strVal(lfirst(cell));
726  Oid fdwid = get_foreign_data_wrapper_oid(fdwname, false);
727 
728  objects = lappend_oid(objects, fdwid);
729  }
730  break;
732  foreach(cell, objnames)
733  {
734  char *srvname = strVal(lfirst(cell));
735  Oid srvid = get_foreign_server_oid(srvname, false);
736 
737  objects = lappend_oid(objects, srvid);
738  }
739  break;
740  default:
741  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
742  (int) objtype);
743  }
744 
745  return objects;
746 }
#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:2895
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
#define ereport(elevel, rest)
Definition: elog.h:122
Oid LookupFuncWithArgs(ObjectWithArgs *func, bool noError)
Definition: parse_func.c:1971
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2009
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
char * dbname
Definition: streamutil.c:38
bool LargeObjectExists(Oid loid)
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:453
#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
static List * objectsInSchemaToOids ( GrantObjectType  objtype,
List nspnames 
)
static

Definition at line 756 of file aclchk.c.

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

Referenced by ExecuteGrantStmt().

757 {
758  List *objects = NIL;
759  ListCell *cell;
760 
761  foreach(cell, nspnames)
762  {
763  char *nspname = strVal(lfirst(cell));
764  Oid namespaceId;
765  List *objs;
766 
767  namespaceId = LookupExplicitNamespace(nspname, false);
768 
769  switch (objtype)
770  {
771  case ACL_OBJECT_RELATION:
772  objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
773  objects = list_concat(objects, objs);
774  objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
775  objects = list_concat(objects, objs);
776  objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
777  objects = list_concat(objects, objs);
778  objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
779  objects = list_concat(objects, objs);
781  objects = list_concat(objects, objs);
782  break;
783  case ACL_OBJECT_SEQUENCE:
784  objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
785  objects = list_concat(objects, objs);
786  break;
787  case ACL_OBJECT_FUNCTION:
788  {
789  ScanKeyData key[1];
790  Relation rel;
791  HeapScanDesc scan;
792  HeapTuple tuple;
793 
794  ScanKeyInit(&key[0],
796  BTEqualStrategyNumber, F_OIDEQ,
797  ObjectIdGetDatum(namespaceId));
798 
800  scan = heap_beginscan_catalog(rel, 1, key);
801 
802  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
803  {
804  objects = lappend_oid(objects, HeapTupleGetOid(tuple));
805  }
806 
807  heap_endscan(scan);
809  }
810  break;
811  default:
812  /* should not happen */
813  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
814  (int) objtype);
815  }
816  }
817 
818  return objects;
819 }
#define NIL
Definition: pg_list.h:69
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2743
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1578
#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:1399
static List * getRelationsInNamespace(Oid namespaceId, char relkind)
Definition: aclchk.c:827
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1794
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define NULL
Definition: c.h:229
#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:695
#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
static AclMode pg_aclmask ( AclObjectKind  objkind,
Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)
static

Definition at line 3469 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, NULL, 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().

3471 {
3472  switch (objkind)
3473  {
3474  case ACL_KIND_COLUMN:
3475  return
3476  pg_class_aclmask(table_oid, roleid, mask, how) |
3477  pg_attribute_aclmask(table_oid, attnum, roleid, mask, how);
3478  case ACL_KIND_CLASS:
3479  case ACL_KIND_SEQUENCE:
3480  return pg_class_aclmask(table_oid, roleid, mask, how);
3481  case ACL_KIND_DATABASE:
3482  return pg_database_aclmask(table_oid, roleid, mask, how);
3483  case ACL_KIND_PROC:
3484  return pg_proc_aclmask(table_oid, roleid, mask, how);
3485  case ACL_KIND_LANGUAGE:
3486  return pg_language_aclmask(table_oid, roleid, mask, how);
3487  case ACL_KIND_LARGEOBJECT:
3488  return pg_largeobject_aclmask_snapshot(table_oid, roleid,
3489  mask, how, NULL);
3490  case ACL_KIND_NAMESPACE:
3491  return pg_namespace_aclmask(table_oid, roleid, mask, how);
3492  case ACL_KIND_STATISTICS:
3493  elog(ERROR, "grantable rights not supported for statistics");
3494  /* not reached, but keep compiler quiet */
3495  return ACL_NO_RIGHTS;
3496  case ACL_KIND_TABLESPACE:
3497  return pg_tablespace_aclmask(table_oid, roleid, mask, how);
3498  case ACL_KIND_FDW:
3499  return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
3501  return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
3503  elog(ERROR, "grantable rights not supported for event triggers");
3504  /* not reached, but keep compiler quiet */
3505  return ACL_NO_RIGHTS;
3506  case ACL_KIND_TYPE:
3507  return pg_type_aclmask(table_oid, roleid, mask, how);
3508  default:
3509  elog(ERROR, "unrecognized objkind: %d",
3510  (int) objkind);
3511  /* not reached, but keep compiler quiet */
3512  return ACL_NO_RIGHTS;
3513  }
3514 }
AclMode pg_foreign_server_aclmask(Oid srv_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4163
AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3537
AclMode pg_tablespace_aclmask(Oid spc_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4044
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3622
AclMode pg_database_aclmask(Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3718
#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:3962
AclMode pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4224
#define NULL
Definition: c.h:229
AclMode pg_language_aclmask(Oid lang_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3826
AclMode pg_proc_aclmask(Oid proc_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3772
AclMode pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4101
#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:3889
AclResult pg_attribute_aclcheck ( Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mode 
)

Definition at line 4308 of file aclchk.c.

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

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

4310 {
4311  if (pg_attribute_aclmask(table_oid, attnum, roleid, mode, ACLMASK_ANY) != 0)
4312  return ACLCHECK_OK;
4313  else
4314  return ACLCHECK_NO_PRIV;
4315 }
AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3537
AclResult pg_attribute_aclcheck_all ( Oid  table_oid,
Oid  roleid,
AclMode  mode,
AclMaskHow  how 
)

Definition at line 4337 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, result, 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().

4339 {
4340  AclResult result;
4341  HeapTuple classTuple;
4342  Form_pg_class classForm;
4343  AttrNumber nattrs;
4344  AttrNumber curr_att;
4345 
4346  /*
4347  * Must fetch pg_class row to check number of attributes. As in
4348  * pg_attribute_aclmask, we prefer to return "no privileges" instead of
4349  * throwing an error if we get any unexpected lookup errors.
4350  */
4351  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
4352  if (!HeapTupleIsValid(classTuple))
4353  return ACLCHECK_NO_PRIV;
4354  classForm = (Form_pg_class) GETSTRUCT(classTuple);
4355 
4356  nattrs = classForm->relnatts;
4357 
4358  ReleaseSysCache(classTuple);
4359 
4360  /*
4361  * Initialize result in case there are no non-dropped columns. We want to
4362  * report failure in such cases for either value of 'how'.
4363  */
4364  result = ACLCHECK_NO_PRIV;
4365 
4366  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4367  {
4368  HeapTuple attTuple;
4369  AclMode attmask;
4370 
4371  attTuple = SearchSysCache2(ATTNUM,
4372  ObjectIdGetDatum(table_oid),
4373  Int16GetDatum(curr_att));
4374  if (!HeapTupleIsValid(attTuple))
4375  continue;
4376 
4377  /* ignore dropped columns */
4378  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4379  {
4380  ReleaseSysCache(attTuple);
4381  continue;
4382  }
4383 
4384  /*
4385  * Here we hard-wire knowledge that the default ACL for a column
4386  * grants no privileges, so that we can fall out quickly in the very
4387  * common case where attacl is null.
4388  */
4390  attmask = 0;
4391  else
4392  attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
4393  mode, ACLMASK_ANY);
4394 
4395  ReleaseSysCache(attTuple);
4396 
4397  if (attmask != 0)
4398  {
4399  result = ACLCHECK_OK;
4400  if (how == ACLMASK_ANY)
4401  break; /* succeed on any success */
4402  }
4403  else
4404  {
4405  result = ACLCHECK_NO_PRIV;
4406  if (how == ACLMASK_ALL)
4407  break; /* fail on any failure */
4408  }
4409  }
4410 
4411  return result;
4412 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3537
#define Int16GetDatum(X)
Definition: postgres.h:457
#define Anum_pg_attribute_attacl
Definition: pg_attribute.h:214
return result
Definition: formatting.c:1618
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
uint32 AclMode
Definition: parsenodes.h:70
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:297
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
AclResult
Definition: acl.h:170
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
int16 AttrNumber
Definition: attnum.h:21
#define SearchSysCache2(cacheId, key1, key2)
Definition: syscache.h:154
AclMode pg_attribute_aclmask ( Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 3537 of file aclchk.c.

References aclmask(), Anum_pg_attribute_attacl, ATTNUM, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum, ObjectIdGetDatum, pfree(), ReleaseSysCache(), RELOID, result, SearchSysCache1, SearchSysCache2, and SysCacheGetAttr().

Referenced by pg_aclmask(), pg_attribute_aclcheck(), and pg_attribute_aclcheck_all().

3539 {
3540  AclMode result;
3541  HeapTuple classTuple;
3542  HeapTuple attTuple;
3543  Form_pg_class classForm;
3544  Form_pg_attribute attributeForm;
3545  Datum aclDatum;
3546  bool isNull;
3547  Acl *acl;
3548  Oid ownerId;
3549 
3550  /*
3551  * First, get the column's ACL from its pg_attribute entry
3552  */
3553  attTuple = SearchSysCache2(ATTNUM,
3554  ObjectIdGetDatum(table_oid),
3555  Int16GetDatum(attnum));
3556  if (!HeapTupleIsValid(attTuple))
3557  ereport(ERROR,
3558  (errcode(ERRCODE_UNDEFINED_COLUMN),
3559  errmsg("attribute %d of relation with OID %u does not exist",
3560  attnum, table_oid)));
3561  attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
3562 
3563  /* Throw error on dropped columns, too */
3564  if (attributeForm->attisdropped)
3565  ereport(ERROR,
3566  (errcode(ERRCODE_UNDEFINED_COLUMN),
3567  errmsg("attribute %d of relation with OID %u does not exist",
3568  attnum, table_oid)));
3569 
3570  aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
3571  &isNull);
3572 
3573  /*
3574  * Here we hard-wire knowledge that the default ACL for a column grants no
3575  * privileges, so that we can fall out quickly in the very common case
3576  * where attacl is null.
3577  */
3578  if (isNull)
3579  {
3580  ReleaseSysCache(attTuple);
3581  return 0;
3582  }
3583 
3584  /*
3585  * Must get the relation's ownerId from pg_class. Since we already found
3586  * a pg_attribute entry, the only likely reason for this to fail is that a
3587  * concurrent DROP of the relation committed since then (which could only
3588  * happen if we don't have lock on the relation). We prefer to report "no
3589  * privileges" rather than failing in such a case, so as to avoid unwanted
3590  * failures in has_column_privilege() tests.
3591  */
3592  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3593  if (!HeapTupleIsValid(classTuple))
3594  {
3595  ReleaseSysCache(attTuple);
3596  return 0;
3597  }
3598  classForm = (Form_pg_class) GETSTRUCT(classTuple);
3599 
3600  ownerId = classForm->relowner;
3601 
3602  ReleaseSysCache(classTuple);
3603 
3604  /* detoast column's ACL if necessary */
3605  acl = DatumGetAclP(aclDatum);
3606 
3607  result = aclmask(acl, roleid, ownerId, mask, how);
3608 
3609  /* if we have a detoasted copy, free it */
3610  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3611  pfree(acl);
3612 
3613  ReleaseSysCache(attTuple);
3614 
3615  return result;
3616 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define DatumGetAclP(X)
Definition: acl.h:113
AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, Ac