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 3382 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_summarize_new_values(), 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().

3384 {
3385  switch (aclerr)
3386  {
3387  case ACLCHECK_OK:
3388  /* no error, so return to caller */
3389  break;
3390  case ACLCHECK_NO_PRIV:
3391  ereport(ERROR,
3392  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3393  errmsg(no_priv_msg[objectkind], objectname)));
3394  break;
3395  case ACLCHECK_NOT_OWNER:
3396  ereport(ERROR,
3397  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3398  errmsg(not_owner_msg[objectkind], objectname)));
3399  break;
3400  default:
3401  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3402  break;
3403  }
3404 }
static const char *const no_priv_msg[MAX_ACL_KIND]
Definition: aclchk.c:3276
static const char *const not_owner_msg[MAX_ACL_KIND]
Definition: aclchk.c:3328
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 3408 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().

3410 {
3411  switch (aclerr)
3412  {
3413  case ACLCHECK_OK:
3414  /* no error, so return to caller */
3415  break;
3416  case ACLCHECK_NO_PRIV:
3417  ereport(ERROR,
3418  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3419  errmsg("permission denied for column \"%s\" of relation \"%s\"",
3420  colname, objectname)));
3421  break;
3422  case ACLCHECK_NOT_OWNER:
3423  /* relation msg is OK since columns don't have separate owners */
3424  ereport(ERROR,
3425  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3426  errmsg(not_owner_msg[objectkind], objectname)));
3427  break;
3428  default:
3429  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3430  break;
3431  }
3432 }
static const char *const not_owner_msg[MAX_ACL_KIND]
Definition: aclchk.c:3328
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 3440 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().

3441 {
3442  Oid element_type = get_element_type(typeOid);
3443 
3444  aclcheck_error(aclerr, ACL_KIND_TYPE, format_type_be(element_type ? element_type : typeOid));
3445 }
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2452
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:3382
void ExecAlterDefaultPrivilegesStmt ( ParseState pstate,
AlterDefaultPrivilegesStmt stmt 
)

Definition at line 863 of file aclchk.c.

References ACL_ALL_RIGHTS_FUNCTION, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SEQUENCE, ACL_ALL_RIGHTS_TYPE, ACL_ID_PUBLIC, ACL_NO_RIGHTS, ACL_OBJECT_FUNCTION, 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;
962  default:
963  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
964  (int) action->objtype);
965  /* keep compiler quiet */
966  all_privileges = ACL_NO_RIGHTS;
967  errormsg = NULL;
968  }
969 
970  if (action->privileges == NIL)
971  {
972  iacls.all_privs = true;
973 
974  /*
975  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
976  * depending on the object type
977  */
978  iacls.privileges = ACL_NO_RIGHTS;
979  }
980  else
981  {
982  iacls.all_privs = false;
983  iacls.privileges = ACL_NO_RIGHTS;
984 
985  foreach(cell, action->privileges)
986  {
987  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
988  AclMode priv;
989 
990  if (privnode->cols)
991  ereport(ERROR,
992  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
993  errmsg("default privileges cannot be set for columns")));
994 
995  if (privnode->priv_name == NULL) /* parser mistake? */
996  elog(ERROR, "AccessPriv node must specify privilege");
997  priv = string_to_privilege(privnode->priv_name);
998 
999  if (priv & ~((AclMode) all_privileges))
1000  ereport(ERROR,
1001  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1002  errmsg(errormsg, privilege_to_string(priv))));
1003 
1004  iacls.privileges |= priv;
1005  }
1006  }
1007 
1008  if (rolespecs == NIL)
1009  {
1010  /* Set permissions for myself */
1011  iacls.roleid = GetUserId();
1012 
1013  SetDefaultACLsInSchemas(&iacls, nspnames);
1014  }
1015  else
1016  {
1017  /* Look up the role OIDs and do permissions checks */
1018  ListCell *rolecell;
1019 
1020  foreach(rolecell, rolespecs)
1021  {
1022  RoleSpec *rolespec = lfirst(rolecell);
1023 
1024  iacls.roleid = get_rolespec_oid(rolespec, false);
1025 
1026  /*
1027  * We insist that calling user be a member of each target role. If
1028  * he has that, he could become that role anyway via SET ROLE, so
1029  * FOR ROLE is just a syntactic convenience and doesn't give any
1030  * special privileges.
1031  */
1033 
1034  SetDefaultACLsInSchemas(&iacls, nspnames);
1035  }
1036  }
1037 }
#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:3198
bool grant_option
Definition: parsenodes.h:1812
#define gettext_noop(x)
Definition: c.h:139
int errcode(int sqlerrcode)
Definition: elog.c:575
List * cols
Definition: parsenodes.h:1842
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:63
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:79
int location
Definition: parsenodes.h:711
#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:709
bool is_grant
Definition: parsenodes.h:1804
RoleSpecType roletype
Definition: parsenodes.h:319
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:1809
DropBehavior behavior
Definition: parsenodes.h:1813
#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:109
static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
Definition: aclchk.c:1045
GrantObjectType objtype
Definition: parsenodes.h:1806
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:708
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:3235
List * grantees
Definition: parsenodes.h:1811
#define elog
Definition: elog.h:219
AclMode privileges
Definition: aclchk.c:91
Definition: pg_list.h:45
char * priv_name
Definition: parsenodes.h:1841
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 1571 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().

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

2051 {
2052  Relation relation;
2053  ListCell *cell;
2054 
2055  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2056  istmt->privileges = ACL_ALL_RIGHTS_DATABASE;
2057 
2059 
2060  foreach(cell, istmt->objects)
2061  {
2062  Oid datId = lfirst_oid(cell);
2063  Form_pg_database pg_database_tuple;
2064  Datum aclDatum;
2065  bool isNull;
2066  AclMode avail_goptions;
2067  AclMode this_privileges;
2068  Acl *old_acl;
2069  Acl *new_acl;
2070  Oid grantorId;
2071  Oid ownerId;
2072  HeapTuple newtuple;
2074  bool nulls[Natts_pg_database];
2075  bool replaces[Natts_pg_database];
2076  int noldmembers;
2077  int nnewmembers;
2078  Oid *oldmembers;
2079  Oid *newmembers;
2080  HeapTuple tuple;
2081 
2082  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(datId));
2083  if (!HeapTupleIsValid(tuple))
2084  elog(ERROR, "cache lookup failed for database %u", datId);
2085 
2086  pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
2087 
2088  /*
2089  * Get owner ID and working copy of existing ACL. If there's no ACL,
2090  * substitute the proper default.
2091  */
2092  ownerId = pg_database_tuple->datdba;
2093  aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
2094  RelationGetDescr(relation), &isNull);
2095  if (isNull)
2096  {
2097  old_acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
2098  /* There are no old member roles according to the catalogs */
2099  noldmembers = 0;
2100  oldmembers = NULL;
2101  }
2102  else
2103  {
2104  old_acl = DatumGetAclPCopy(aclDatum);
2105  /* Get the roles mentioned in the existing ACL */
2106  noldmembers = aclmembers(old_acl, &oldmembers);
2107  }
2108 
2109  /* Determine ID to do the grant as, and available grant options */
2110  select_best_grantor(GetUserId(), istmt->privileges,
2111  old_acl, ownerId,
2112  &grantorId, &avail_goptions);
2113 
2114  /*
2115  * Restrict the privileges to what we can actually grant, and emit the
2116  * standards-mandated warning and error messages.
2117  */
2118  this_privileges =
2119  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2120  istmt->all_privs, istmt->privileges,
2121  datId, grantorId, ACL_KIND_DATABASE,
2122  NameStr(pg_database_tuple->datname),
2123  0, NULL);
2124 
2125  /*
2126  * Generate new ACL.
2127  */
2128  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2129  istmt->grant_option, istmt->behavior,
2130  istmt->grantees, this_privileges,
2131  grantorId, ownerId);
2132 
2133  /*
2134  * We need the members of both old and new ACLs so we can correct the
2135  * shared dependency information.
2136  */
2137  nnewmembers = aclmembers(new_acl, &newmembers);
2138 
2139  /* finished building new ACL value, now insert it */
2140  MemSet(values, 0, sizeof(values));
2141  MemSet(nulls, false, sizeof(nulls));
2142  MemSet(replaces, false, sizeof(replaces));
2143 
2144  replaces[Anum_pg_database_datacl - 1] = true;
2145  values[Anum_pg_database_datacl - 1] = PointerGetDatum(new_acl);
2146 
2147  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2148  nulls, replaces);
2149 
2150  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2151 
2152  /* Update the shared dependency ACL info */
2154  ownerId,
2155  noldmembers, oldmembers,
2156  nnewmembers, newmembers);
2157 
2158  ReleaseSysCache(tuple);
2159 
2160  pfree(new_acl);
2161 
2162  /* prevent error when processing duplicate objects */
2164  }
2165 
2166  heap_close(relation, RowExclusiveLock);
2167 }
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:63
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:79
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:1287
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:162
#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 2170 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().

2171 {
2172  Relation relation;
2173  ListCell *cell;
2174 
2175  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2176  istmt->privileges = ACL_ALL_RIGHTS_FDW;
2177 
2179 
2180  foreach(cell, istmt->objects)
2181  {
2182  Oid fdwid = lfirst_oid(cell);
2183  Form_pg_foreign_data_wrapper pg_fdw_tuple;
2184  Datum aclDatum;
2185  bool isNull;
2186  AclMode avail_goptions;
2187  AclMode this_privileges;
2188  Acl *old_acl;
2189  Acl *new_acl;
2190  Oid grantorId;
2191  Oid ownerId;
2192  HeapTuple tuple;
2193  HeapTuple newtuple;
2195  bool nulls[Natts_pg_foreign_data_wrapper];
2196  bool replaces[Natts_pg_foreign_data_wrapper];
2197  int noldmembers;
2198  int nnewmembers;
2199  Oid *oldmembers;
2200  Oid *newmembers;
2201 
2203  ObjectIdGetDatum(fdwid));
2204  if (!HeapTupleIsValid(tuple))
2205  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
2206 
2207  pg_fdw_tuple = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
2208 
2209  /*
2210  * Get owner ID and working copy of existing ACL. If there's no ACL,
2211  * substitute the proper default.
2212  */
2213  ownerId = pg_fdw_tuple->fdwowner;
2214  aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
2216  &isNull);
2217  if (isNull)
2218  {
2219  old_acl = acldefault(ACL_OBJECT_FDW, ownerId);
2220  /* There are no old member roles according to the catalogs */
2221  noldmembers = 0;
2222  oldmembers = NULL;
2223  }
2224  else
2225  {
2226  old_acl = DatumGetAclPCopy(aclDatum);
2227  /* Get the roles mentioned in the existing ACL */
2228  noldmembers = aclmembers(old_acl, &oldmembers);
2229  }
2230 
2231  /* Determine ID to do the grant as, and available grant options */
2232  select_best_grantor(GetUserId(), istmt->privileges,
2233  old_acl, ownerId,
2234  &grantorId, &avail_goptions);
2235 
2236  /*
2237  * Restrict the privileges to what we can actually grant, and emit the
2238  * standards-mandated warning and error messages.
2239  */
2240  this_privileges =
2241  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2242  istmt->all_privs, istmt->privileges,
2243  fdwid, grantorId, ACL_KIND_FDW,
2244  NameStr(pg_fdw_tuple->fdwname),
2245  0, NULL);
2246 
2247  /*
2248  * Generate new ACL.
2249  */
2250  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2251  istmt->grant_option, istmt->behavior,
2252  istmt->grantees, this_privileges,
2253  grantorId, ownerId);
2254 
2255  /*
2256  * We need the members of both old and new ACLs so we can correct the
2257  * shared dependency information.
2258  */
2259  nnewmembers = aclmembers(new_acl, &newmembers);
2260 
2261  /* finished building new ACL value, now insert it */
2262  MemSet(values, 0, sizeof(values));
2263  MemSet(nulls, false, sizeof(nulls));
2264  MemSet(replaces, false, sizeof(replaces));
2265 
2266  replaces[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
2268 
2269  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2270  nulls, replaces);
2271 
2272  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2273 
2274  /* Update initial privileges for extensions */
2276  new_acl);
2277 
2278  /* Update the shared dependency ACL info */
2280  HeapTupleGetOid(tuple), 0,
2281  ownerId,
2282  noldmembers, oldmembers,
2283  nnewmembers, newmembers);
2284 
2285  ReleaseSysCache(tuple);
2286 
2287  pfree(new_acl);
2288 
2289  /* prevent error when processing duplicate objects */
2291  }
2292 
2293  heap_close(relation, RowExclusiveLock);
2294 }
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:63
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:79
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:5674
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:1287
#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:162
#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 2297 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().

2298 {
2299  Relation relation;
2300  ListCell *cell;
2301 
2302  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2303  istmt->privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
2304 
2306 
2307  foreach(cell, istmt->objects)
2308  {
2309  Oid srvid = lfirst_oid(cell);
2310  Form_pg_foreign_server pg_server_tuple;
2311  Datum aclDatum;
2312  bool isNull;
2313  AclMode avail_goptions;
2314  AclMode this_privileges;
2315  Acl *old_acl;
2316  Acl *new_acl;
2317  Oid grantorId;
2318  Oid ownerId;
2319  HeapTuple tuple;
2320  HeapTuple newtuple;
2322  bool nulls[Natts_pg_foreign_server];
2323  bool replaces[Natts_pg_foreign_server];
2324  int noldmembers;
2325  int nnewmembers;
2326  Oid *oldmembers;
2327  Oid *newmembers;
2328 
2330  if (!HeapTupleIsValid(tuple))
2331  elog(ERROR, "cache lookup failed for foreign server %u", srvid);
2332 
2333  pg_server_tuple = (Form_pg_foreign_server) GETSTRUCT(tuple);
2334 
2335  /*
2336  * Get owner ID and working copy of existing ACL. If there's no ACL,
2337  * substitute the proper default.
2338  */
2339  ownerId = pg_server_tuple->srvowner;
2340  aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
2342  &isNull);
2343  if (isNull)
2344  {
2345  old_acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
2346  /* There are no old member roles according to the catalogs */
2347  noldmembers = 0;
2348  oldmembers = NULL;
2349  }
2350  else
2351  {
2352  old_acl = DatumGetAclPCopy(aclDatum);
2353  /* Get the roles mentioned in the existing ACL */
2354  noldmembers = aclmembers(old_acl, &oldmembers);
2355  }
2356 
2357  /* Determine ID to do the grant as, and available grant options */
2358  select_best_grantor(GetUserId(), istmt->privileges,
2359  old_acl, ownerId,
2360  &grantorId, &avail_goptions);
2361 
2362  /*
2363  * Restrict the privileges to what we can actually grant, and emit the
2364  * standards-mandated warning and error messages.
2365  */
2366  this_privileges =
2367  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2368  istmt->all_privs, istmt->privileges,
2369  srvid, grantorId, ACL_KIND_FOREIGN_SERVER,
2370  NameStr(pg_server_tuple->srvname),
2371  0, NULL);
2372 
2373  /*
2374  * Generate new ACL.
2375  */
2376  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2377  istmt->grant_option, istmt->behavior,
2378  istmt->grantees, this_privileges,
2379  grantorId, ownerId);
2380 
2381  /*
2382  * We need the members of both old and new ACLs so we can correct the
2383  * shared dependency information.
2384  */
2385  nnewmembers = aclmembers(new_acl, &newmembers);
2386 
2387  /* finished building new ACL value, now insert it */
2388  MemSet(values, 0, sizeof(values));
2389  MemSet(nulls, false, sizeof(nulls));
2390  MemSet(replaces, false, sizeof(replaces));
2391 
2392  replaces[Anum_pg_foreign_server_srvacl - 1] = true;
2393  values[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(new_acl);
2394 
2395  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2396  nulls, replaces);
2397 
2398  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2399 
2400  /* Update initial privileges for extensions */
2402 
2403  /* Update the shared dependency ACL info */
2405  HeapTupleGetOid(tuple), 0,
2406  ownerId,
2407  noldmembers, oldmembers,
2408  nnewmembers, newmembers);
2409 
2410  ReleaseSysCache(tuple);
2411 
2412  pfree(new_acl);
2413 
2414  /* prevent error when processing duplicate objects */
2416  }
2417 
2418  heap_close(relation, RowExclusiveLock);
2419 }
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:63
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:79
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:5674
#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:1287
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:162
#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 2422 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().

2423 {
2424  Relation relation;
2425  ListCell *cell;
2426 
2427  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2428  istmt->privileges = ACL_ALL_RIGHTS_FUNCTION;
2429 
2431 
2432  foreach(cell, istmt->objects)
2433  {
2434  Oid funcId = lfirst_oid(cell);
2435  Form_pg_proc pg_proc_tuple;
2436  Datum aclDatum;
2437  bool isNull;
2438  AclMode avail_goptions;
2439  AclMode this_privileges;
2440  Acl *old_acl;
2441  Acl *new_acl;
2442  Oid grantorId;
2443  Oid ownerId;
2444  HeapTuple tuple;
2445  HeapTuple newtuple;
2447  bool nulls[Natts_pg_proc];
2448  bool replaces[Natts_pg_proc];
2449  int noldmembers;
2450  int nnewmembers;
2451  Oid *oldmembers;
2452  Oid *newmembers;
2453 
2454  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
2455  if (!HeapTupleIsValid(tuple))
2456  elog(ERROR, "cache lookup failed for function %u", funcId);
2457 
2458  pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
2459 
2460  /*
2461  * Get owner ID and working copy of existing ACL. If there's no ACL,
2462  * substitute the proper default.
2463  */
2464  ownerId = pg_proc_tuple->proowner;
2465  aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
2466  &isNull);
2467  if (isNull)
2468  {
2469  old_acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
2470  /* There are no old member roles according to the catalogs */
2471  noldmembers = 0;
2472  oldmembers = NULL;
2473  }
2474  else
2475  {
2476  old_acl = DatumGetAclPCopy(aclDatum);
2477  /* Get the roles mentioned in the existing ACL */
2478  noldmembers = aclmembers(old_acl, &oldmembers);
2479  }
2480 
2481  /* Determine ID to do the grant as, and available grant options */
2482  select_best_grantor(GetUserId(), istmt->privileges,
2483  old_acl, ownerId,
2484  &grantorId, &avail_goptions);
2485 
2486  /*
2487  * Restrict the privileges to what we can actually grant, and emit the
2488  * standards-mandated warning and error messages.
2489  */
2490  this_privileges =
2491  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2492  istmt->all_privs, istmt->privileges,
2493  funcId, grantorId, ACL_KIND_PROC,
2494  NameStr(pg_proc_tuple->proname),
2495  0, NULL);
2496 
2497  /*
2498  * Generate new ACL.
2499  */
2500  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2501  istmt->grant_option, istmt->behavior,
2502  istmt->grantees, this_privileges,
2503  grantorId, ownerId);
2504 
2505  /*
2506  * We need the members of both old and new ACLs so we can correct the
2507  * shared dependency information.
2508  */
2509  nnewmembers = aclmembers(new_acl, &newmembers);
2510 
2511  /* finished building new ACL value, now insert it */
2512  MemSet(values, 0, sizeof(values));
2513  MemSet(nulls, false, sizeof(nulls));
2514  MemSet(replaces, false, sizeof(replaces));
2515 
2516  replaces[Anum_pg_proc_proacl - 1] = true;
2517  values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
2518 
2519  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2520  nulls, replaces);
2521 
2522  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2523 
2524  /* Update initial privileges for extensions */
2525  recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
2526 
2527  /* Update the shared dependency ACL info */
2529  ownerId,
2530  noldmembers, oldmembers,
2531  nnewmembers, newmembers);
2532 
2533  ReleaseSysCache(tuple);
2534 
2535  pfree(new_acl);
2536 
2537  /* prevent error when processing duplicate objects */
2539  }
2540 
2541  heap_close(relation, RowExclusiveLock);
2542 }
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:63
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:79
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:5674
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:1287
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:162
#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 2545 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().

2546 {
2547  Relation relation;
2548  ListCell *cell;
2549 
2550  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2551  istmt->privileges = ACL_ALL_RIGHTS_LANGUAGE;
2552 
2554 
2555  foreach(cell, istmt->objects)
2556  {
2557  Oid langId = lfirst_oid(cell);
2558  Form_pg_language pg_language_tuple;
2559  Datum aclDatum;
2560  bool isNull;
2561  AclMode avail_goptions;
2562  AclMode this_privileges;
2563  Acl *old_acl;
2564  Acl *new_acl;
2565  Oid grantorId;
2566  Oid ownerId;
2567  HeapTuple tuple;
2568  HeapTuple newtuple;
2570  bool nulls[Natts_pg_language];
2571  bool replaces[Natts_pg_language];
2572  int noldmembers;
2573  int nnewmembers;
2574  Oid *oldmembers;
2575  Oid *newmembers;
2576 
2577  tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(langId));
2578  if (!HeapTupleIsValid(tuple))
2579  elog(ERROR, "cache lookup failed for language %u", langId);
2580 
2581  pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
2582 
2583  if (!pg_language_tuple->lanpltrusted)
2584  ereport(ERROR,
2585  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2586  errmsg("language \"%s\" is not trusted",
2587  NameStr(pg_language_tuple->lanname)),
2588  errdetail("GRANT and REVOKE are not allowed on untrusted languages, "
2589  "because only superusers can use untrusted languages.")));
2590 
2591  /*
2592  * Get owner ID and working copy of existing ACL. If there's no ACL,
2593  * substitute the proper default.
2594  */
2595  ownerId = pg_language_tuple->lanowner;
2597  &isNull);
2598  if (isNull)
2599  {
2600  old_acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
2601  /* There are no old member roles according to the catalogs */
2602  noldmembers = 0;
2603  oldmembers = NULL;
2604  }
2605  else
2606  {
2607  old_acl = DatumGetAclPCopy(aclDatum);
2608  /* Get the roles mentioned in the existing ACL */
2609  noldmembers = aclmembers(old_acl, &oldmembers);
2610  }
2611 
2612  /* Determine ID to do the grant as, and available grant options */
2613  select_best_grantor(GetUserId(), istmt->privileges,
2614  old_acl, ownerId,
2615  &grantorId, &avail_goptions);
2616 
2617  /*
2618  * Restrict the privileges to what we can actually grant, and emit the
2619  * standards-mandated warning and error messages.
2620  */
2621  this_privileges =
2622  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2623  istmt->all_privs, istmt->privileges,
2624  langId, grantorId, ACL_KIND_LANGUAGE,
2625  NameStr(pg_language_tuple->lanname),
2626  0, NULL);
2627 
2628  /*
2629  * Generate new ACL.
2630  */
2631  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2632  istmt->grant_option, istmt->behavior,
2633  istmt->grantees, this_privileges,
2634  grantorId, ownerId);
2635 
2636  /*
2637  * We need the members of both old and new ACLs so we can correct the
2638  * shared dependency information.
2639  */
2640  nnewmembers = aclmembers(new_acl, &newmembers);
2641 
2642  /* finished building new ACL value, now insert it */
2643  MemSet(values, 0, sizeof(values));
2644  MemSet(nulls, false, sizeof(nulls));
2645  MemSet(replaces, false, sizeof(replaces));
2646 
2647  replaces[Anum_pg_language_lanacl - 1] = true;
2648  values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
2649 
2650  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2651  nulls, replaces);
2652 
2653  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2654 
2655  /* Update initial privileges for extensions */
2656  recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
2657 
2658  /* Update the shared dependency ACL info */
2660  ownerId,
2661  noldmembers, oldmembers,
2662  nnewmembers, newmembers);
2663 
2664  ReleaseSysCache(tuple);
2665 
2666  pfree(new_acl);
2667 
2668  /* prevent error when processing duplicate objects */
2670  }
2671 
2672  heap_close(relation, RowExclusiveLock);
2673 }
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:63
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:79
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:5674
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:1287
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:162
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 2676 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().

2677 {
2678  Relation relation;
2679  ListCell *cell;
2680 
2681  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2682  istmt->privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
2683 
2686 
2687  foreach(cell, istmt->objects)
2688  {
2689  Oid loid = lfirst_oid(cell);
2690  Form_pg_largeobject_metadata form_lo_meta;
2691  char loname[NAMEDATALEN];
2692  Datum aclDatum;
2693  bool isNull;
2694  AclMode avail_goptions;
2695  AclMode this_privileges;
2696  Acl *old_acl;
2697  Acl *new_acl;
2698  Oid grantorId;
2699  Oid ownerId;
2700  HeapTuple newtuple;
2702  bool nulls[Natts_pg_largeobject_metadata];
2703  bool replaces[Natts_pg_largeobject_metadata];
2704  int noldmembers;
2705  int nnewmembers;
2706  Oid *oldmembers;
2707  Oid *newmembers;
2708  ScanKeyData entry[1];
2709  SysScanDesc scan;
2710  HeapTuple tuple;
2711 
2712  /* There's no syscache for pg_largeobject_metadata */
2713  ScanKeyInit(&entry[0],
2715  BTEqualStrategyNumber, F_OIDEQ,
2716  ObjectIdGetDatum(loid));
2717 
2718  scan = systable_beginscan(relation,
2720  NULL, 1, entry);
2721 
2722  tuple = systable_getnext(scan);
2723  if (!HeapTupleIsValid(tuple))
2724  elog(ERROR, "cache lookup failed for large object %u", loid);
2725 
2726  form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
2727 
2728  /*
2729  * Get owner ID and working copy of existing ACL. If there's no ACL,
2730  * substitute the proper default.
2731  */
2732  ownerId = form_lo_meta->lomowner;
2733  aclDatum = heap_getattr(tuple,
2735  RelationGetDescr(relation), &isNull);
2736  if (isNull)
2737  {
2738  old_acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
2739  /* There are no old member roles according to the catalogs */
2740  noldmembers = 0;
2741  oldmembers = NULL;
2742  }
2743  else
2744  {
2745  old_acl = DatumGetAclPCopy(aclDatum);
2746  /* Get the roles mentioned in the existing ACL */
2747  noldmembers = aclmembers(old_acl, &oldmembers);
2748  }
2749 
2750  /* Determine ID to do the grant as, and available grant options */
2751  select_best_grantor(GetUserId(), istmt->privileges,
2752  old_acl, ownerId,
2753  &grantorId, &avail_goptions);
2754 
2755  /*
2756  * Restrict the privileges to what we can actually grant, and emit the
2757  * standards-mandated warning and error messages.
2758  */
2759  snprintf(loname, sizeof(loname), "large object %u", loid);
2760  this_privileges =
2761  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2762  istmt->all_privs, istmt->privileges,
2763  loid, grantorId, ACL_KIND_LARGEOBJECT,
2764  loname, 0, NULL);
2765 
2766  /*
2767  * Generate new ACL.
2768  */
2769  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2770  istmt->grant_option, istmt->behavior,
2771  istmt->grantees, this_privileges,
2772  grantorId, ownerId);
2773 
2774  /*
2775  * We need the members of both old and new ACLs so we can correct the
2776  * shared dependency information.
2777  */
2778  nnewmembers = aclmembers(new_acl, &newmembers);
2779 
2780  /* finished building new ACL value, now insert it */
2781  MemSet(values, 0, sizeof(values));
2782  MemSet(nulls, false, sizeof(nulls));
2783  MemSet(replaces, false, sizeof(replaces));
2784 
2785  replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
2787  = PointerGetDatum(new_acl);
2788 
2789  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2790  values, nulls, replaces);
2791 
2792  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2793 
2794  /* Update initial privileges for extensions */
2796 
2797  /* Update the shared dependency ACL info */
2799  HeapTupleGetOid(tuple), 0,
2800  ownerId,
2801  noldmembers, oldmembers,
2802  nnewmembers, newmembers);
2803 
2804  systable_endscan(scan);
2805 
2806  pfree(new_acl);
2807 
2808  /* prevent error when processing duplicate objects */
2810  }
2811 
2812  heap_close(relation, RowExclusiveLock);
2813 }
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:63
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:79
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:5674
#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:1287
#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:162
#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 2816 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().

2817 {
2818  Relation relation;
2819  ListCell *cell;
2820 
2821  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2822  istmt->privileges = ACL_ALL_RIGHTS_NAMESPACE;
2823 
2825 
2826  foreach(cell, istmt->objects)
2827  {
2828  Oid nspid = lfirst_oid(cell);
2829  Form_pg_namespace pg_namespace_tuple;
2830  Datum aclDatum;
2831  bool isNull;
2832  AclMode avail_goptions;
2833  AclMode this_privileges;
2834  Acl *old_acl;
2835  Acl *new_acl;
2836  Oid grantorId;
2837  Oid ownerId;
2838  HeapTuple tuple;
2839  HeapTuple newtuple;
2841  bool nulls[Natts_pg_namespace];
2842  bool replaces[Natts_pg_namespace];
2843  int noldmembers;
2844  int nnewmembers;
2845  Oid *oldmembers;
2846  Oid *newmembers;
2847 
2849  if (!HeapTupleIsValid(tuple))
2850  elog(ERROR, "cache lookup failed for namespace %u", nspid);
2851 
2852  pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
2853 
2854  /*
2855  * Get owner ID and working copy of existing ACL. If there's no ACL,
2856  * substitute the proper default.
2857  */
2858  ownerId = pg_namespace_tuple->nspowner;
2859  aclDatum = SysCacheGetAttr(NAMESPACENAME, tuple,
2861  &isNull);
2862  if (isNull)
2863  {
2864  old_acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
2865  /* There are no old member roles according to the catalogs */
2866  noldmembers = 0;
2867  oldmembers = NULL;
2868  }
2869  else
2870  {
2871  old_acl = DatumGetAclPCopy(aclDatum);
2872  /* Get the roles mentioned in the existing ACL */
2873  noldmembers = aclmembers(old_acl, &oldmembers);
2874  }
2875 
2876  /* Determine ID to do the grant as, and available grant options */
2877  select_best_grantor(GetUserId(), istmt->privileges,
2878  old_acl, ownerId,
2879  &grantorId, &avail_goptions);
2880 
2881  /*
2882  * Restrict the privileges to what we can actually grant, and emit the
2883  * standards-mandated warning and error messages.
2884  */
2885  this_privileges =
2886  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2887  istmt->all_privs, istmt->privileges,
2888  nspid, grantorId, ACL_KIND_NAMESPACE,
2889  NameStr(pg_namespace_tuple->nspname),
2890  0, NULL);
2891 
2892  /*
2893  * Generate new ACL.
2894  */
2895  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2896  istmt->grant_option, istmt->behavior,
2897  istmt->grantees, this_privileges,
2898  grantorId, ownerId);
2899 
2900  /*
2901  * We need the members of both old and new ACLs so we can correct the
2902  * shared dependency information.
2903  */
2904  nnewmembers = aclmembers(new_acl, &newmembers);
2905 
2906  /* finished building new ACL value, now insert it */
2907  MemSet(values, 0, sizeof(values));
2908  MemSet(nulls, false, sizeof(nulls));
2909  MemSet(replaces, false, sizeof(replaces));
2910 
2911  replaces[Anum_pg_namespace_nspacl - 1] = true;
2912  values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(new_acl);
2913 
2914  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2915  nulls, replaces);
2916 
2917  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2918 
2919  /* Update initial privileges for extensions */
2920  recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
2921 
2922  /* Update the shared dependency ACL info */
2924  ownerId,
2925  noldmembers, oldmembers,
2926  nnewmembers, newmembers);
2927 
2928  ReleaseSysCache(tuple);
2929 
2930  pfree(new_acl);
2931 
2932  /* prevent error when processing duplicate objects */
2934  }
2935 
2936  heap_close(relation, RowExclusiveLock);
2937 }
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:63
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:79
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:5674
#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:1287
#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:162
#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 1719 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().

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

2941 {
2942  Relation relation;
2943  ListCell *cell;
2944 
2945  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2946  istmt->privileges = ACL_ALL_RIGHTS_TABLESPACE;
2947 
2949 
2950  foreach(cell, istmt->objects)
2951  {
2952  Oid tblId = lfirst_oid(cell);
2953  Form_pg_tablespace pg_tablespace_tuple;
2954  Datum aclDatum;
2955  bool isNull;
2956  AclMode avail_goptions;
2957  AclMode this_privileges;
2958  Acl *old_acl;
2959  Acl *new_acl;
2960  Oid grantorId;
2961  Oid ownerId;
2962  HeapTuple newtuple;
2964  bool nulls[Natts_pg_tablespace];
2965  bool replaces[Natts_pg_tablespace];
2966  int noldmembers;
2967  int nnewmembers;
2968  Oid *oldmembers;
2969  Oid *newmembers;
2970  HeapTuple tuple;
2971 
2972  /* Search syscache for pg_tablespace */
2974  if (!HeapTupleIsValid(tuple))
2975  elog(ERROR, "cache lookup failed for tablespace %u", tblId);
2976 
2977  pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);
2978 
2979  /*
2980  * Get owner ID and working copy of existing ACL. If there's no ACL,
2981  * substitute the proper default.
2982  */
2983  ownerId = pg_tablespace_tuple->spcowner;
2984  aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl,
2985  RelationGetDescr(relation), &isNull);
2986  if (isNull)
2987  {
2988  old_acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
2989  /* There are no old member roles according to the catalogs */
2990  noldmembers = 0;
2991  oldmembers = NULL;
2992  }
2993  else
2994  {
2995  old_acl = DatumGetAclPCopy(aclDatum);
2996  /* Get the roles mentioned in the existing ACL */
2997  noldmembers = aclmembers(old_acl, &oldmembers);
2998  }
2999 
3000  /* Determine ID to do the grant as, and available grant options */
3001  select_best_grantor(GetUserId(), istmt->privileges,
3002  old_acl, ownerId,
3003  &grantorId, &avail_goptions);
3004 
3005  /*
3006  * Restrict the privileges to what we can actually grant, and emit the
3007  * standards-mandated warning and error messages.
3008  */
3009  this_privileges =
3010  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3011  istmt->all_privs, istmt->privileges,
3012  tblId, grantorId, ACL_KIND_TABLESPACE,
3013  NameStr(pg_tablespace_tuple->spcname),
3014  0, NULL);
3015 
3016  /*
3017  * Generate new ACL.
3018  */
3019  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3020  istmt->grant_option, istmt->behavior,
3021  istmt->grantees, this_privileges,
3022  grantorId, ownerId);
3023 
3024  /*
3025  * We need the members of both old and new ACLs so we can correct the
3026  * shared dependency information.
3027  */
3028  nnewmembers = aclmembers(new_acl, &newmembers);
3029 
3030  /* finished building new ACL value, now insert it */
3031  MemSet(values, 0, sizeof(values));
3032  MemSet(nulls, false, sizeof(nulls));
3033  MemSet(replaces, false, sizeof(replaces));
3034 
3035  replaces[Anum_pg_tablespace_spcacl - 1] = true;
3036  values[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(new_acl);
3037 
3038  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3039  nulls, replaces);
3040 
3041  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3042 
3043  /* Update the shared dependency ACL info */
3045  ownerId,
3046  noldmembers, oldmembers,
3047  nnewmembers, newmembers);
3048 
3049  ReleaseSysCache(tuple);
3050  pfree(new_acl);
3051 
3052  /* prevent error when processing duplicate objects */
3054  }
3055 
3056  heap_close(relation, RowExclusiveLock);
3057 }
#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:63
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:79
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:1287
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:162
#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 3060 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().

3061 {
3062  Relation relation;
3063  ListCell *cell;
3064 
3065  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
3066  istmt->privileges = ACL_ALL_RIGHTS_TYPE;
3067 
3069 
3070  foreach(cell, istmt->objects)
3071  {
3072  Oid typId = lfirst_oid(cell);
3073  Form_pg_type pg_type_tuple;
3074  Datum aclDatum;
3075  bool isNull;
3076  AclMode avail_goptions;
3077  AclMode this_privileges;
3078  Acl *old_acl;
3079  Acl *new_acl;
3080  Oid grantorId;
3081  Oid ownerId;
3082  HeapTuple newtuple;
3084  bool nulls[Natts_pg_type];
3085  bool replaces[Natts_pg_type];
3086  int noldmembers;
3087  int nnewmembers;
3088  Oid *oldmembers;
3089  Oid *newmembers;
3090  HeapTuple tuple;
3091 
3092  /* Search syscache for pg_type */
3093  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typId));
3094  if (!HeapTupleIsValid(tuple))
3095  elog(ERROR, "cache lookup failed for type %u", typId);
3096 
3097  pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
3098 
3099  if (pg_type_tuple->typelem != 0 && pg_type_tuple->typlen == -1)
3100  ereport(ERROR,
3101  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
3102  errmsg("cannot set privileges of array types"),
3103  errhint("Set the privileges of the element type instead.")));
3104 
3105  /* Used GRANT DOMAIN on a non-domain? */
3106  if (istmt->objtype == ACL_OBJECT_DOMAIN &&
3107  pg_type_tuple->typtype != TYPTYPE_DOMAIN)
3108  ereport(ERROR,
3109  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3110  errmsg("\"%s\" is not a domain",
3111  NameStr(pg_type_tuple->typname))));
3112 
3113  /*
3114  * Get owner ID and working copy of existing ACL. If there's no ACL,
3115  * substitute the proper default.
3116  */
3117  ownerId = pg_type_tuple->typowner;
3118  aclDatum = heap_getattr(tuple, Anum_pg_type_typacl,
3119  RelationGetDescr(relation), &isNull);
3120  if (isNull)
3121  {
3122  old_acl = acldefault(istmt->objtype, ownerId);
3123  /* There are no old member roles according to the catalogs */
3124  noldmembers = 0;
3125  oldmembers = NULL;
3126  }
3127  else
3128  {
3129  old_acl = DatumGetAclPCopy(aclDatum);
3130  /* Get the roles mentioned in the existing ACL */
3131  noldmembers = aclmembers(old_acl, &oldmembers);
3132  }
3133 
3134  /* Determine ID to do the grant as, and available grant options */
3135  select_best_grantor(GetUserId(), istmt->privileges,
3136  old_acl, ownerId,
3137  &grantorId, &avail_goptions);
3138 
3139  /*
3140  * Restrict the privileges to what we can actually grant, and emit the
3141  * standards-mandated warning and error messages.
3142  */
3143  this_privileges =
3144  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3145  istmt->all_privs, istmt->privileges,
3146  typId, grantorId, ACL_KIND_TYPE,
3147  NameStr(pg_type_tuple->typname),
3148  0, NULL);
3149 
3150  /*
3151  * Generate new ACL.
3152  */
3153  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3154  istmt->grant_option, istmt->behavior,
3155  istmt->grantees, this_privileges,
3156  grantorId, ownerId);
3157 
3158  /*
3159  * We need the members of both old and new ACLs so we can correct the
3160  * shared dependency information.
3161  */
3162  nnewmembers = aclmembers(new_acl, &newmembers);
3163 
3164  /* finished building new ACL value, now insert it */
3165  MemSet(values, 0, sizeof(values));
3166  MemSet(nulls, false, sizeof(nulls));
3167  MemSet(replaces, false, sizeof(replaces));
3168 
3169  replaces[Anum_pg_type_typacl - 1] = true;
3170  values[Anum_pg_type_typacl - 1] = PointerGetDatum(new_acl);
3171 
3172  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3173  nulls, replaces);
3174 
3175  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3176 
3177  /* Update initial privileges for extensions */
3178  recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
3179 
3180  /* Update the shared dependency ACL info */
3182  ownerId,
3183  noldmembers, oldmembers,
3184  nnewmembers, newmembers);
3185 
3186  ReleaseSysCache(tuple);
3187  pfree(new_acl);
3188 
3189  /* prevent error when processing duplicate objects */
3191  }
3192 
3193  heap_close(relation, RowExclusiveLock);
3194 }
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:718
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:63
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:79
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:5674
#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:1287
#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:162
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:2545
static void ExecGrant_Function(InternalGrant *grantStmt)
Definition: aclchk.c:2422
static void ExecGrant_Tablespace(InternalGrant *grantStmt)
Definition: aclchk.c:2940
static void ExecGrant_Namespace(InternalGrant *grantStmt)
Definition: aclchk.c:2816
static void ExecGrant_Type(InternalGrant *grantStmt)
Definition: aclchk.c:3060
static void ExecGrant_Database(InternalGrant *grantStmt)
Definition: aclchk.c:2050
GrantObjectType objtype
#define ERROR
Definition: elog.h:43
static void ExecGrant_Fdw(InternalGrant *grantStmt)
Definition: aclchk.c:2170
static void ExecGrant_Largeobject(InternalGrant *grantStmt)
Definition: aclchk.c:2676
static void ExecGrant_Relation(InternalGrant *grantStmt)
Definition: aclchk.c:1719
bool EventTriggerSupportsGrantObjectType(GrantObjectType objtype)
void EventTriggerCollectGrant(InternalGrant *istmt)
#define elog
Definition: elog.h:219
static void ExecGrant_ForeignServer(InternalGrant *grantStmt)
Definition: aclchk.c:2297
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:3198
AclMode privileges
bool grant_option
Definition: parsenodes.h:1812
#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:1842
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:63
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:79
#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:1804
static void ExecGrantStmt_oids(InternalGrant *istmt)
Definition: aclchk.c:565
RoleSpecType roletype
Definition: parsenodes.h:319
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:1809
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:157
DropBehavior behavior
DropBehavior behavior
Definition: parsenodes.h:1813
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
List * objects
Definition: parsenodes.h:1807
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:152
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:154
GrantObjectType objtype
Definition: parsenodes.h:1806
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:3235
List * grantees
Definition: parsenodes.h:1811
#define elog
Definition: elog.h:219
GrantTargetType targtype
Definition: parsenodes.h:1805
char * priv_name
Definition: parsenodes.h:1841
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 1521 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().

1525 {
1526  AttrNumber curr_att;
1527 
1528  Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
1529  for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
1530  curr_att <= classForm->relnatts;
1531  curr_att++)
1532  {
1533  HeapTuple attTuple;
1534  bool isdropped;
1535 
1536  if (curr_att == InvalidAttrNumber)
1537  continue;
1538 
1539  /* Skip OID column if it doesn't exist */
1540  if (curr_att == ObjectIdAttributeNumber && !classForm->relhasoids)
1541  continue;
1542 
1543  /* Views don't have any system columns at all */
1544  if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
1545  continue;
1546 
1547  attTuple = SearchSysCache2(ATTNUM,
1548  ObjectIdGetDatum(table_oid),
1549  Int16GetDatum(curr_att));
1550  if (!HeapTupleIsValid(attTuple))
1551  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1552  curr_att, table_oid);
1553 
1554  isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
1555 
1556  ReleaseSysCache(attTuple);
1557 
1558  /* ignore dropped columns */
1559  if (isdropped)
1560  continue;
1561 
1562  col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
1563  }
1564 }
#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:184
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 1488 of file aclchk.c.

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

Referenced by ExecGrant_Relation().

1492 {
1493  ListCell *cell;
1494 
1495  foreach(cell, colnames)
1496  {
1497  char *colname = strVal(lfirst(cell));
1498  AttrNumber attnum;
1499 
1500  attnum = get_attnum(table_oid, colname);
1501  if (attnum == InvalidAttrNumber)
1502  ereport(ERROR,
1503  (errcode(ERRCODE_UNDEFINED_COLUMN),
1504  errmsg("column \"%s\" of relation \"%s\" does not exist",
1505  colname, get_rel_name(table_oid))));
1507  if (attnum <= 0 || attnum >= num_col_privileges)
1508  elog(ERROR, "column number out of range"); /* safety check */
1509  col_privileges[attnum] |= this_privileges;
1510  }
1511 }
#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:1694
int16 AttrNumber
Definition: attnum.h:21
static Acl* get_default_acl_internal ( Oid  roleId,
Oid  nsp_oid,
char  objtype 
)
static

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

5197 {
5198  Acl *result = NULL;
5199  HeapTuple tuple;
5200 
5202  ObjectIdGetDatum(roleId),
5203  ObjectIdGetDatum(nsp_oid),
5204  CharGetDatum(objtype));
5205 
5206  if (HeapTupleIsValid(tuple))
5207  {
5208  Datum aclDatum;
5209  bool isNull;
5210 
5211  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
5213  &isNull);
5214  if (!isNull)
5215  result = DatumGetAclPCopy(aclDatum);
5216  ReleaseSysCache(tuple);
5217  }
5218 
5219  return result;
5220 }
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 5228 of file aclchk.c.

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

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

5229 {
5230  Acl *result;
5231  Acl *glob_acl;
5232  Acl *schema_acl;
5233  Acl *def_acl;
5234  char defaclobjtype;
5235 
5236  /*
5237  * Use NULL during bootstrap, since pg_default_acl probably isn't there
5238  * yet.
5239  */
5241  return NULL;
5242 
5243  /* Check if object type is supported in pg_default_acl */
5244  switch (objtype)
5245  {
5246  case ACL_OBJECT_RELATION:
5247  defaclobjtype = DEFACLOBJ_RELATION;
5248  break;
5249 
5250  case ACL_OBJECT_SEQUENCE:
5251  defaclobjtype = DEFACLOBJ_SEQUENCE;
5252  break;
5253 
5254  case ACL_OBJECT_FUNCTION:
5255  defaclobjtype = DEFACLOBJ_FUNCTION;
5256  break;
5257 
5258  case ACL_OBJECT_TYPE:
5259  defaclobjtype = DEFACLOBJ_TYPE;
5260  break;
5261 
5262  default:
5263  return NULL;
5264  }
5265 
5266  /* Look up the relevant pg_default_acl entries */
5267  glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
5268  schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
5269 
5270  /* Quick out if neither entry exists */
5271  if (glob_acl == NULL && schema_acl == NULL)
5272  return NULL;
5273 
5274  /* We need to know the hard-wired default value, too */
5275  def_acl = acldefault(objtype, ownerId);
5276 
5277  /* If there's no global entry, substitute the hard-wired default */
5278  if (glob_acl == NULL)
5279  glob_acl = def_acl;
5280 
5281  /* Merge in any per-schema privileges */
5282  result = aclmerge(glob_acl, schema_acl, ownerId);
5283 
5284  /*
5285  * For efficiency, we want to return NULL if the result equals default.
5286  * This requires sorting both arrays to get an accurate comparison.
5287  */
5288  aclitemsort(result);
5289  aclitemsort(def_acl);
5290  if (aclequal(result, def_acl))
5291  result = NULL;
5292 
5293  return result;
5294 }
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:5196
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_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:1581
#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:1402
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1797
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#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 5172 of file aclchk.c.

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

Referenced by check_enable_rls(), and RI_Initial_Check().

5173 {
5174  bool result = false;
5175  HeapTuple utup;
5176 
5177  /* Superusers bypass all permission checking. */
5178  if (superuser_arg(roleid))
5179  return true;
5180 
5181  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5182  if (HeapTupleIsValid(utup))
5183  {
5184  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
5185  ReleaseSysCache(utup);
5186  }
5187  return result;
5188 }
#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 5153 of file aclchk.c.

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

Referenced by check_object_ownership(), and have_createrole_privilege().

5154 {
5155  bool result = false;
5156  HeapTuple utup;
5157 
5158  /* Superusers bypass all permission checking. */
5159  if (superuser_arg(roleid))
5160  return true;
5161 
5162  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5163  if (HeapTupleIsValid(utup))
5164  {
5165  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
5166  ReleaseSysCache(utup);
5167  }
5168  return result;
5169 }
#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:79
#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:2001
#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:1581
#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:1402
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:1797
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#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 3452 of file aclchk.c.

References ACL_KIND_CLASS, ACL_KIND_COLUMN, ACL_KIND_DATABASE, ACL_KIND_EVENT_TRIGGER, ACL_KIND_FDW, ACL_KIND_FOREIGN_SERVER, ACL_KIND_LANGUAGE, ACL_KIND_LARGEOBJECT, ACL_KIND_NAMESPACE, ACL_KIND_PROC, ACL_KIND_SEQUENCE, ACL_KIND_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().

3454 {
3455  switch (objkind)
3456  {
3457  case ACL_KIND_COLUMN:
3458  return
3459  pg_class_aclmask(table_oid, roleid, mask, how) |
3460  pg_attribute_aclmask(table_oid, attnum, roleid, mask, how);
3461  case ACL_KIND_CLASS:
3462  case ACL_KIND_SEQUENCE:
3463  return pg_class_aclmask(table_oid, roleid, mask, how);
3464  case ACL_KIND_DATABASE:
3465  return pg_database_aclmask(table_oid, roleid, mask, how);
3466  case ACL_KIND_PROC:
3467  return pg_proc_aclmask(table_oid, roleid, mask, how);
3468  case ACL_KIND_LANGUAGE:
3469  return pg_language_aclmask(table_oid, roleid, mask, how);
3470  case ACL_KIND_LARGEOBJECT:
3471  return pg_largeobject_aclmask_snapshot(table_oid, roleid,
3472  mask, how, NULL);
3473  case ACL_KIND_NAMESPACE:
3474  return pg_namespace_aclmask(table_oid, roleid, mask, how);
3475  case ACL_KIND_STATISTICS:
3476  elog(ERROR, "grantable rights not supported for statistics");
3477  /* not reached, but keep compiler quiet */
3478  return ACL_NO_RIGHTS;
3479  case ACL_KIND_TABLESPACE:
3480  return pg_tablespace_aclmask(table_oid, roleid, mask, how);
3481  case ACL_KIND_FDW:
3482  return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
3484  return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
3486  elog(ERROR, "grantable rights not supported for event triggers");
3487  /* not reached, but keep compiler quiet */
3488  return ACL_NO_RIGHTS;
3489  case ACL_KIND_TYPE:
3490  return pg_type_aclmask(table_oid, roleid, mask, how);
3491  default:
3492  elog(ERROR, "unrecognized objkind: %d",
3493  (int) objkind);
3494  /* not reached, but keep compiler quiet */
3495  return ACL_NO_RIGHTS;
3496  }
3497 }
AclMode pg_foreign_server_aclmask(Oid srv_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4146
AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3520
AclMode pg_tablespace_aclmask(Oid spc_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4027
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3605
AclMode pg_database_aclmask(Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3701
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:79
AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3945
AclMode pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4207
#define NULL
Definition: c.h:229
AclMode pg_language_aclmask(Oid lang_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3809
AclMode pg_proc_aclmask(Oid proc_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3755
AclMode pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4084
#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:3872
AclResult pg_attribute_aclcheck ( Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mode 
)

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

4293 {
4294  if (pg_attribute_aclmask(table_oid, attnum, roleid, mode, ACLMASK_ANY) != 0)
4295  return ACLCHECK_OK;
4296  else
4297  return ACLCHECK_NO_PRIV;
4298 }
AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3520
AclResult pg_attribute_aclcheck_all ( Oid  table_oid,
Oid  roleid,
AclMode  mode,
AclMaskHow  how 
)

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

4322 {
4323  AclResult result;
4324  HeapTuple classTuple;
4325  Form_pg_class classForm;
4326  AttrNumber nattrs;
4327  AttrNumber curr_att;
4328 
4329  /*
4330  * Must fetch pg_class row to check number of attributes. As in
4331  * pg_attribute_aclmask, we prefer to return "no privileges" instead of
4332  * throwing an error if we get any unexpected lookup errors.
4333  */
4334  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
4335  if (!HeapTupleIsValid(classTuple))
4336  return ACLCHECK_NO_PRIV;
4337  classForm = (Form_pg_class) GETSTRUCT(classTuple);
4338 
4339  nattrs = classForm->relnatts;
4340 
4341  ReleaseSysCache(classTuple);
4342 
4343  /*
4344  * Initialize result in case there are no non-dropped columns. We want to
4345  * report failure in such cases for either value of 'how'.
4346  */
4347  result = ACLCHECK_NO_PRIV;
4348 
4349  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4350  {
4351  HeapTuple attTuple;
4352  AclMode attmask;
4353 
4354  attTuple = SearchSysCache2(ATTNUM,
4355  ObjectIdGetDatum(table_oid),
4356  Int16GetDatum(curr_att));
4357  if (!HeapTupleIsValid(attTuple))
4358  continue;
4359 
4360  /* ignore dropped columns */
4361  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4362  {
4363  ReleaseSysCache(attTuple);
4364  continue;
4365  }
4366 
4367  /*
4368  * Here we hard-wire knowledge that the default ACL for a column
4369  * grants no privileges, so that we can fall out quickly in the very
4370  * common case where attacl is null.
4371  */
4373  attmask = 0;
4374  else
4375  attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
4376  mode, ACLMASK_ANY);
4377 
4378  ReleaseSysCache(attTuple);
4379 
4380  if (attmask != 0)
4381  {
4382  result = ACLCHECK_OK;
4383  if (how == ACLMASK_ANY)
4384  break; /* succeed on any success */
4385  }
4386  else
4387  {
4388  result = ACLCHECK_NO_PRIV;
4389  if (how == ACLMASK_ALL)
4390  break; /* fail on any failure */
4391  }
4392  }
4393 
4394  return result;
4395 }
#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:3520
#define Int16GetDatum(X)
Definition: postgres.h:457
#define Anum_pg_attribute_attacl
Definition: pg_attribute.h:210
return result
Definition: formatting.c:1618
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
uint32 AclMode
Definition: parsenodes.h:63
#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:184
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 3520 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().

3522 {
3523  AclMode result;
3524  HeapTuple classTuple;
3525  HeapTuple attTuple;
3526  Form_pg_class classForm;
3527  Form_pg_attribute attributeForm;
3528  Datum aclDatum;
3529  bool isNull;
3530  Acl *acl;
3531  Oid ownerId;
3532 
3533  /*
3534  * First, get the column's ACL from its pg_attribute entry
3535  */
3536  attTuple = SearchSysCache2(ATTNUM,
3537  ObjectIdGetDatum(table_oid),
3538  Int16GetDatum(attnum));
3539  if (!HeapTupleIsValid(attTuple))
3540  ereport(ERROR,
3541  (errcode(ERRCODE_UNDEFINED_COLUMN),
3542  errmsg("attribute %d of relation with OID %u does not exist",
3543  attnum, table_oid)));
3544  attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
3545 
3546  /* Throw error on dropped columns, too */
3547  if (attributeForm->attisdropped)
3548  ereport(ERROR,
3549  (errcode(ERRCODE_UNDEFINED_COLUMN),
3550  errmsg("attribute %d of relation with OID %u does not exist",
3551  attnum, table_oid)));
3552 
3553  aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
3554  &isNull);
3555 
3556  /*
3557  * Here we hard-wire knowledge that the default ACL for a column grants no
3558  * privileges, so that we can fall out quickly in the very common case
3559  * where attacl is null.
3560  */
3561  if (isNull)
3562  {
3563  ReleaseSysCache(attTuple);
3564  return 0;
3565  }
3566 
3567  /*
3568  * Must get the relation's ownerId from pg_class. Since we already found
3569  * a pg_attribute entry, the only likely reason for this to fail is that a
3570  * concurrent DROP of the relation committed since then (which could only
3571  * happen if we don't have lock on the relation). We prefer to report "no
3572  * privileges" rather than failing in such a case, so as to avoid unwanted
3573  * failures in has_column_privilege() tests.
3574  */
3575  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3576  if (!HeapTupleIsValid(classTuple))
3577  {
3578  ReleaseSysCache(attTuple);
3579  return 0;
3580  }
3581  classForm = (Form_pg_class) GETSTRUCT(classTuple);
3582 
3583  ownerId = classForm->relowner;
3584 
3585  ReleaseSysCache(classTuple);
3586 
3587  /* detoast column's ACL if necessary */
3588  acl = DatumGetAclP(aclDatum);
3589 
3590  result = aclmask(acl, roleid, ownerId, mask, how);
3591 
3592  /* if we have a detoasted copy, free it */
3593  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3594  pfree(acl);
3595 
3596  ReleaseSysCache(attTuple);
3597 
3598  return result;
3599 }
#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, AclMaskHow how)
Definition: acl.c:1304
#define Int16GetDatum(X)
Definition: postgres.h:457
int errcode(int sqlerrcode)
Definition: elog.c:575
#define Anum_pg_attribute_attacl
Definition: pg_attribute.h:210
return result
Definition: formatting.c:1618
unsigned int Oid
Definition: postgres_ext.h:31
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
uint32 AclMode
Definition: parsenodes.h:63
void pfree(void *pointer)
Definition: mcxt.c:950
char * Pointer
Definition: c.h:245
#define ObjectIdGetDatum(X)
Definition: postgres.h:513