PostgreSQL Source Code  git master
aclchk.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "access/tableam.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_transform.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_type.h"
#include "commands/dbcommands.h"
#include "commands/defrem.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 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 (ObjectType objtype, List *objnames)
 
static ListobjectsInSchemaToOids (ObjectType 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, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
 
static AclMode pg_aclmask (ObjectType objtype, 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)
 
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, ObjectType objtype, const char *objectname)
 
void aclcheck_error_col (AclResult aclerr, ObjectType objtype, 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_attribute_aclmask_ext (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
 
AclMode pg_class_aclmask (Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_class_aclmask_ext (Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
 
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_ext (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode, bool *is_missing)
 
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_class_aclcheck_ext (Oid table_oid, Oid roleid, AclMode mode, bool *is_missing)
 
AclResult pg_database_aclcheck (Oid db_oid, Oid roleid, AclMode mode)
 
AclResult pg_proc_aclcheck (Oid proc_oid, Oid roleid, AclMode mode)
 
AclResult pg_language_aclcheck (Oid lang_oid, Oid roleid, AclMode mode)
 
AclResult pg_largeobject_aclcheck_snapshot (Oid lobj_oid, Oid roleid, AclMode mode, Snapshot snapshot)
 
AclResult pg_namespace_aclcheck (Oid nsp_oid, Oid roleid, AclMode mode)
 
AclResult pg_tablespace_aclcheck (Oid spc_oid, Oid roleid, AclMode mode)
 
AclResult pg_foreign_data_wrapper_aclcheck (Oid fdw_oid, Oid roleid, AclMode mode)
 
AclResult pg_foreign_server_aclcheck (Oid srv_oid, Oid roleid, AclMode mode)
 
AclResult pg_type_aclcheck (Oid type_oid, Oid roleid, AclMode mode)
 
bool pg_class_ownercheck (Oid class_oid, Oid roleid)
 
bool pg_type_ownercheck (Oid type_oid, Oid roleid)
 
bool pg_oper_ownercheck (Oid oper_oid, Oid roleid)
 
bool pg_proc_ownercheck (Oid proc_oid, Oid roleid)
 
bool pg_language_ownercheck (Oid lan_oid, Oid roleid)
 
bool pg_largeobject_ownercheck (Oid lobj_oid, Oid roleid)
 
bool pg_namespace_ownercheck (Oid nsp_oid, Oid roleid)
 
bool pg_tablespace_ownercheck (Oid spc_oid, Oid roleid)
 
bool pg_opclass_ownercheck (Oid opc_oid, Oid roleid)
 
bool pg_opfamily_ownercheck (Oid opf_oid, Oid roleid)
 
bool pg_ts_dict_ownercheck (Oid dict_oid, Oid roleid)
 
bool pg_ts_config_ownercheck (Oid cfg_oid, Oid roleid)
 
bool pg_foreign_data_wrapper_ownercheck (Oid srv_oid, Oid roleid)
 
bool pg_foreign_server_ownercheck (Oid srv_oid, Oid roleid)
 
bool pg_event_trigger_ownercheck (Oid et_oid, Oid roleid)
 
bool pg_database_ownercheck (Oid db_oid, Oid roleid)
 
bool pg_collation_ownercheck (Oid coll_oid, Oid roleid)
 
bool pg_conversion_ownercheck (Oid conv_oid, Oid roleid)
 
bool pg_extension_ownercheck (Oid ext_oid, Oid roleid)
 
bool pg_publication_ownercheck (Oid pub_oid, Oid roleid)
 
bool pg_subscription_ownercheck (Oid sub_oid, Oid roleid)
 
bool pg_statistics_object_ownercheck (Oid stat_oid, Oid roleid)
 
bool has_createrole_privilege (Oid roleid)
 
bool has_bypassrls_privilege (Oid roleid)
 
static Aclget_default_acl_internal (Oid roleId, Oid nsp_oid, char objtype)
 
Aclget_user_default_acl (ObjectType objtype, Oid ownerId, Oid nsp_oid)
 
void recordDependencyOnNewAcl (Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
 
void recordExtObjInitPriv (Oid objoid, Oid classoid)
 
void removeExtObjInitPriv (Oid objoid, Oid classoid)
 

Variables

bool binary_upgrade_record_init_privs = false
 

Function Documentation

◆ aclcheck_error()

void aclcheck_error ( AclResult  aclerr,
ObjectType  objtype,
const char *  objectname 
)

Definition at line 3308 of file aclchk.c.

References ACLCHECK_NO_PRIV, ACLCHECK_NOT_OWNER, ACLCHECK_OK, elog, ereport, errcode(), errmsg(), ERROR, gettext_noop, OBJECT_ACCESS_METHOD, OBJECT_AGGREGATE, OBJECT_AMOP, OBJECT_AMPROC, OBJECT_ATTRIBUTE, OBJECT_CAST, OBJECT_COLLATION, OBJECT_COLUMN, OBJECT_CONVERSION, OBJECT_DATABASE, OBJECT_DEFACL, OBJECT_DEFAULT, OBJECT_DOMAIN, OBJECT_DOMCONSTRAINT, OBJECT_EVENT_TRIGGER, OBJECT_EXTENSION, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FOREIGN_TABLE, OBJECT_FUNCTION, OBJECT_INDEX, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_MATVIEW, OBJECT_OPCLASS, OBJECT_OPERATOR, OBJECT_OPFAMILY, OBJECT_POLICY, OBJECT_PROCEDURE, OBJECT_PUBLICATION, OBJECT_PUBLICATION_REL, OBJECT_ROLE, OBJECT_ROUTINE, OBJECT_RULE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_STATISTIC_EXT, OBJECT_SUBSCRIPTION, OBJECT_TABCONSTRAINT, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TRANSFORM, OBJECT_TRIGGER, OBJECT_TSCONFIGURATION, OBJECT_TSDICTIONARY, OBJECT_TSPARSER, OBJECT_TSTEMPLATE, OBJECT_TYPE, OBJECT_USER_MAPPING, and OBJECT_VIEW.

Referenced by aclcheck_error_col(), 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(), AlterStatistics(), AlterSubscription(), AlterSubscriptionOwner_internal(), AlterTableMoveAll(), AlterTableSpaceOptions(), AlterTSConfiguration(), AlterTSDictionary(), AlterTypeOwner(), ATExecChangeOwner(), ATPrepSetTableSpace(), ATSimplePermissions(), brin_desummarize_range(), brin_summarize_range(), calculate_database_size(), calculate_tablespace_size(), call_pltcl_start_proc(), check_object_ownership(), check_temp_tablespaces(), checkFkeyPermissions(), CheckFunctionValidatorAccess(), compute_return_type(), CreateConversionCommand(), createdb(), CreateForeignServer(), CreateForeignTable(), CreateFunction(), CreateProceduralLanguage(), CreatePublication(), CreateSchemaCommand(), CreateStatistics(), CreateTransform(), CreateTriggerFiringOn(), currtid_internal(), DefineAggregate(), DefineCollation(), DefineDomain(), DefineEnum(), DefineIndex(), DefineOpClass(), DefineOperator(), DefineOpFamily(), DefineQueryRewrite(), DefineRange(), DefineRelation(), DefineTSConfiguration(), DefineTSDictionary(), DefineType(), dropdb(), DropSubscription(), DropTableSpace(), EnableDisableRule(), ExecAlterExtensionContentsStmt(), ExecAlterExtensionStmt(), ExecBuildGroupingEqual(), ExecBuildParamSetEqual(), ExecCheckRTPerms(), ExecInitAgg(), ExecInitExprRec(), ExecInitFunc(), ExecInitWindowAgg(), ExecReindex(), ExecuteCallStmt(), ExecuteDoStmt(), ExecuteTruncateGuts(), findRangeCanonicalFunction(), findRangeSubtypeDiffFunction(), get_connect_string(), get_other_operator(), get_rel_from_relname(), gin_clean_pending_list(), HandleFunctionRequest(), heap_force_common(), ImportForeignSchema(), init_sexpr(), initialize_peragg(), LockViewRecurse_walker(), lookup_agg_function(), LookupCreationNamespace(), LookupExplicitNamespace(), MergeAttributes(), movedb(), OperatorCreate(), pg_prewarm(), pgrowlocks(), ProcedureCreate(), PublicationAddTables(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForLockTable(), RangeVarCallbackForPolicy(), RangeVarCallbackForReindexIndex(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackOwnsRelation(), RangeVarCallbackOwnsTable(), RangeVarGetAndCheckCreationNamespace(), ReindexMultipleInternal(), ReindexMultipleTables(), renameatt_check(), RenameDatabase(), RenameSchema(), RenameTableSpace(), restrict_and_check_grant(), transformTableLikeClause(), truncate_check_perms(), TypeCreate(), user_mapping_ddl_aclcheck(), ValidateJoinEstimator(), and ValidateRestrictionEstimator().

3310 {
3311  switch (aclerr)
3312  {
3313  case ACLCHECK_OK:
3314  /* no error, so return to caller */
3315  break;
3316  case ACLCHECK_NO_PRIV:
3317  {
3318  const char *msg = "???";
3319 
3320  switch (objtype)
3321  {
3322  case OBJECT_AGGREGATE:
3323  msg = gettext_noop("permission denied for aggregate %s");
3324  break;
3325  case OBJECT_COLLATION:
3326  msg = gettext_noop("permission denied for collation %s");
3327  break;
3328  case OBJECT_COLUMN:
3329  msg = gettext_noop("permission denied for column %s");
3330  break;
3331  case OBJECT_CONVERSION:
3332  msg = gettext_noop("permission denied for conversion %s");
3333  break;
3334  case OBJECT_DATABASE:
3335  msg = gettext_noop("permission denied for database %s");
3336  break;
3337  case OBJECT_DOMAIN:
3338  msg = gettext_noop("permission denied for domain %s");
3339  break;
3340  case OBJECT_EVENT_TRIGGER:
3341  msg = gettext_noop("permission denied for event trigger %s");
3342  break;
3343  case OBJECT_EXTENSION:
3344  msg = gettext_noop("permission denied for extension %s");
3345  break;
3346  case OBJECT_FDW:
3347  msg = gettext_noop("permission denied for foreign-data wrapper %s");
3348  break;
3349  case OBJECT_FOREIGN_SERVER:
3350  msg = gettext_noop("permission denied for foreign server %s");
3351  break;
3352  case OBJECT_FOREIGN_TABLE:
3353  msg = gettext_noop("permission denied for foreign table %s");
3354  break;
3355  case OBJECT_FUNCTION:
3356  msg = gettext_noop("permission denied for function %s");
3357  break;
3358  case OBJECT_INDEX:
3359  msg = gettext_noop("permission denied for index %s");
3360  break;
3361  case OBJECT_LANGUAGE:
3362  msg = gettext_noop("permission denied for language %s");
3363  break;
3364  case OBJECT_LARGEOBJECT:
3365  msg = gettext_noop("permission denied for large object %s");
3366  break;
3367  case OBJECT_MATVIEW:
3368  msg = gettext_noop("permission denied for materialized view %s");
3369  break;
3370  case OBJECT_OPCLASS:
3371  msg = gettext_noop("permission denied for operator class %s");
3372  break;
3373  case OBJECT_OPERATOR:
3374  msg = gettext_noop("permission denied for operator %s");
3375  break;
3376  case OBJECT_OPFAMILY:
3377  msg = gettext_noop("permission denied for operator family %s");
3378  break;
3379  case OBJECT_POLICY:
3380  msg = gettext_noop("permission denied for policy %s");
3381  break;
3382  case OBJECT_PROCEDURE:
3383  msg = gettext_noop("permission denied for procedure %s");
3384  break;
3385  case OBJECT_PUBLICATION:
3386  msg = gettext_noop("permission denied for publication %s");
3387  break;
3388  case OBJECT_ROUTINE:
3389  msg = gettext_noop("permission denied for routine %s");
3390  break;
3391  case OBJECT_SCHEMA:
3392  msg = gettext_noop("permission denied for schema %s");
3393  break;
3394  case OBJECT_SEQUENCE:
3395  msg = gettext_noop("permission denied for sequence %s");
3396  break;
3397  case OBJECT_STATISTIC_EXT:
3398  msg = gettext_noop("permission denied for statistics object %s");
3399  break;
3400  case OBJECT_SUBSCRIPTION:
3401  msg = gettext_noop("permission denied for subscription %s");
3402  break;
3403  case OBJECT_TABLE:
3404  msg = gettext_noop("permission denied for table %s");
3405  break;
3406  case OBJECT_TABLESPACE:
3407  msg = gettext_noop("permission denied for tablespace %s");
3408  break;
3410  msg = gettext_noop("permission denied for text search configuration %s");
3411  break;
3412  case OBJECT_TSDICTIONARY:
3413  msg = gettext_noop("permission denied for text search dictionary %s");
3414  break;
3415  case OBJECT_TYPE:
3416  msg = gettext_noop("permission denied for type %s");
3417  break;
3418  case OBJECT_VIEW:
3419  msg = gettext_noop("permission denied for view %s");
3420  break;
3421  /* these currently aren't used */
3422  case OBJECT_ACCESS_METHOD:
3423  case OBJECT_AMOP:
3424  case OBJECT_AMPROC:
3425  case OBJECT_ATTRIBUTE:
3426  case OBJECT_CAST:
3427  case OBJECT_DEFAULT:
3428  case OBJECT_DEFACL:
3429  case OBJECT_DOMCONSTRAINT:
3431  case OBJECT_ROLE:
3432  case OBJECT_RULE:
3433  case OBJECT_TABCONSTRAINT:
3434  case OBJECT_TRANSFORM:
3435  case OBJECT_TRIGGER:
3436  case OBJECT_TSPARSER:
3437  case OBJECT_TSTEMPLATE:
3438  case OBJECT_USER_MAPPING:
3439  elog(ERROR, "unsupported object type %d", objtype);
3440  }
3441 
3442  ereport(ERROR,
3443  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3444  errmsg(msg, objectname)));
3445  break;
3446  }
3447  case ACLCHECK_NOT_OWNER:
3448  {
3449  const char *msg = "???";
3450 
3451  switch (objtype)
3452  {
3453  case OBJECT_AGGREGATE:
3454  msg = gettext_noop("must be owner of aggregate %s");
3455  break;
3456  case OBJECT_COLLATION:
3457  msg = gettext_noop("must be owner of collation %s");
3458  break;
3459  case OBJECT_CONVERSION:
3460  msg = gettext_noop("must be owner of conversion %s");
3461  break;
3462  case OBJECT_DATABASE:
3463  msg = gettext_noop("must be owner of database %s");
3464  break;
3465  case OBJECT_DOMAIN:
3466  msg = gettext_noop("must be owner of domain %s");
3467  break;
3468  case OBJECT_EVENT_TRIGGER:
3469  msg = gettext_noop("must be owner of event trigger %s");
3470  break;
3471  case OBJECT_EXTENSION:
3472  msg = gettext_noop("must be owner of extension %s");
3473  break;
3474  case OBJECT_FDW:
3475  msg = gettext_noop("must be owner of foreign-data wrapper %s");
3476  break;
3477  case OBJECT_FOREIGN_SERVER:
3478  msg = gettext_noop("must be owner of foreign server %s");
3479  break;
3480  case OBJECT_FOREIGN_TABLE:
3481  msg = gettext_noop("must be owner of foreign table %s");
3482  break;
3483  case OBJECT_FUNCTION:
3484  msg = gettext_noop("must be owner of function %s");
3485  break;
3486  case OBJECT_INDEX:
3487  msg = gettext_noop("must be owner of index %s");
3488  break;
3489  case OBJECT_LANGUAGE:
3490  msg = gettext_noop("must be owner of language %s");
3491  break;
3492  case OBJECT_LARGEOBJECT:
3493  msg = gettext_noop("must be owner of large object %s");
3494  break;
3495  case OBJECT_MATVIEW:
3496  msg = gettext_noop("must be owner of materialized view %s");
3497  break;
3498  case OBJECT_OPCLASS:
3499  msg = gettext_noop("must be owner of operator class %s");
3500  break;
3501  case OBJECT_OPERATOR:
3502  msg = gettext_noop("must be owner of operator %s");
3503  break;
3504  case OBJECT_OPFAMILY:
3505  msg = gettext_noop("must be owner of operator family %s");
3506  break;
3507  case OBJECT_PROCEDURE:
3508  msg = gettext_noop("must be owner of procedure %s");
3509  break;
3510  case OBJECT_PUBLICATION:
3511  msg = gettext_noop("must be owner of publication %s");
3512  break;
3513  case OBJECT_ROUTINE:
3514  msg = gettext_noop("must be owner of routine %s");
3515  break;
3516  case OBJECT_SEQUENCE:
3517  msg = gettext_noop("must be owner of sequence %s");
3518  break;
3519  case OBJECT_SUBSCRIPTION:
3520  msg = gettext_noop("must be owner of subscription %s");
3521  break;
3522  case OBJECT_TABLE:
3523  msg = gettext_noop("must be owner of table %s");
3524  break;
3525  case OBJECT_TYPE:
3526  msg = gettext_noop("must be owner of type %s");
3527  break;
3528  case OBJECT_VIEW:
3529  msg = gettext_noop("must be owner of view %s");
3530  break;
3531  case OBJECT_SCHEMA:
3532  msg = gettext_noop("must be owner of schema %s");
3533  break;
3534  case OBJECT_STATISTIC_EXT:
3535  msg = gettext_noop("must be owner of statistics object %s");
3536  break;
3537  case OBJECT_TABLESPACE:
3538  msg = gettext_noop("must be owner of tablespace %s");
3539  break;
3541  msg = gettext_noop("must be owner of text search configuration %s");
3542  break;
3543  case OBJECT_TSDICTIONARY:
3544  msg = gettext_noop("must be owner of text search dictionary %s");
3545  break;
3546 
3547  /*
3548  * Special cases: For these, the error message talks
3549  * about "relation", because that's where the
3550  * ownership is attached. See also
3551  * check_object_ownership().
3552  */
3553  case OBJECT_COLUMN:
3554  case OBJECT_POLICY:
3555  case OBJECT_RULE:
3556  case OBJECT_TABCONSTRAINT:
3557  case OBJECT_TRIGGER:
3558  msg = gettext_noop("must be owner of relation %s");
3559  break;
3560  /* these currently aren't used */
3561  case OBJECT_ACCESS_METHOD:
3562  case OBJECT_AMOP:
3563  case OBJECT_AMPROC:
3564  case OBJECT_ATTRIBUTE:
3565  case OBJECT_CAST:
3566  case OBJECT_DEFAULT:
3567  case OBJECT_DEFACL:
3568  case OBJECT_DOMCONSTRAINT:
3570  case OBJECT_ROLE:
3571  case OBJECT_TRANSFORM:
3572  case OBJECT_TSPARSER:
3573  case OBJECT_TSTEMPLATE:
3574  case OBJECT_USER_MAPPING:
3575  elog(ERROR, "unsupported object type %d", objtype);
3576  }
3577 
3578  ereport(ERROR,
3579  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3580  errmsg(msg, objectname)));
3581  break;
3582  }
3583  default:
3584  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3585  break;
3586  }
3587 }
#define gettext_noop(x)
Definition: c.h:1197
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232

◆ aclcheck_error_col()

void aclcheck_error_col ( AclResult  aclerr,
ObjectType  objtype,
const char *  objectname,
const char *  colname 
)

Definition at line 3591 of file aclchk.c.

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

Referenced by restrict_and_check_grant().

3593 {
3594  switch (aclerr)
3595  {
3596  case ACLCHECK_OK:
3597  /* no error, so return to caller */
3598  break;
3599  case ACLCHECK_NO_PRIV:
3600  ereport(ERROR,
3601  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3602  errmsg("permission denied for column \"%s\" of relation \"%s\"",
3603  colname, objectname)));
3604  break;
3605  case ACLCHECK_NOT_OWNER:
3606  /* relation msg is OK since columns don't have separate owners */
3607  aclcheck_error(aclerr, objtype, objectname);
3608  break;
3609  default:
3610  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3611  break;
3612  }
3613 }
int errcode(int sqlerrcode)
Definition: elog.c:698
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232

◆ aclcheck_error_type()

void aclcheck_error_type ( AclResult  aclerr,
Oid  typeOid 
)

Definition at line 3621 of file aclchk.c.

References aclcheck_error(), format_type_be(), get_element_type(), and OBJECT_TYPE.

Referenced by AggregateCreate(), AlterType(), 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().

3622 {
3623  Oid element_type = get_element_type(typeOid);
3624 
3625  aclcheck_error(aclerr, OBJECT_TYPE, format_type_be(element_type ? element_type : typeOid));
3626 }
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2706
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308

◆ ExecAlterDefaultPrivilegesStmt()

void ExecAlterDefaultPrivilegesStmt ( ParseState pstate,
AlterDefaultPrivilegesStmt stmt 
)

Definition at line 905 of file aclchk.c.

References ACL_ALL_RIGHTS_FUNCTION, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SCHEMA, ACL_ALL_RIGHTS_SEQUENCE, ACL_ALL_RIGHTS_TYPE, ACL_ID_PUBLIC, ACL_NO_RIGHTS, generate_unaccent_rules::action, AlterDefaultPrivilegesStmt::action, InternalDefaultACL::all_privs, DefElem::arg, InternalDefaultACL::behavior, GrantStmt::behavior, check_is_member_of_role(), AccessPriv::cols, DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), 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, NIL, OBJECT_FUNCTION, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TYPE, InternalDefaultACL::objtype, GrantStmt::objtype, AlterDefaultPrivilegesStmt::options, AccessPriv::priv_name, privilege_to_string(), InternalDefaultACL::privileges, GrantStmt::privileges, InternalDefaultACL::roleid, ROLESPEC_PUBLIC, RoleSpec::roletype, SetDefaultACLsInSchemas(), and string_to_privilege().

Referenced by ProcessUtilitySlow().

906 {
907  GrantStmt *action = stmt->action;
908  InternalDefaultACL iacls;
909  ListCell *cell;
910  List *rolespecs = NIL;
911  List *nspnames = NIL;
912  DefElem *drolespecs = NULL;
913  DefElem *dnspnames = NULL;
914  AclMode all_privileges;
915  const char *errormsg;
916 
917  /* Deconstruct the "options" part of the statement */
918  foreach(cell, stmt->options)
919  {
920  DefElem *defel = (DefElem *) lfirst(cell);
921 
922  if (strcmp(defel->defname, "schemas") == 0)
923  {
924  if (dnspnames)
925  errorConflictingDefElem(defel, pstate);
926  dnspnames = defel;
927  }
928  else if (strcmp(defel->defname, "roles") == 0)
929  {
930  if (drolespecs)
931  errorConflictingDefElem(defel, pstate);
932  drolespecs = defel;
933  }
934  else
935  elog(ERROR, "option \"%s\" not recognized", defel->defname);
936  }
937 
938  if (dnspnames)
939  nspnames = (List *) dnspnames->arg;
940  if (drolespecs)
941  rolespecs = (List *) drolespecs->arg;
942 
943  /* Prepare the InternalDefaultACL representation of the statement */
944  /* roleid to be filled below */
945  /* nspid to be filled in SetDefaultACLsInSchemas */
946  iacls.is_grant = action->is_grant;
947  iacls.objtype = action->objtype;
948  /* all_privs to be filled below */
949  /* privileges to be filled below */
950  iacls.grantees = NIL; /* filled below */
951  iacls.grant_option = action->grant_option;
952  iacls.behavior = action->behavior;
953 
954  /*
955  * Convert the RoleSpec list into an Oid list. Note that at this point we
956  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
957  * there shouldn't be any additional work needed to support this case.
958  */
959  foreach(cell, action->grantees)
960  {
961  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
962  Oid grantee_uid;
963 
964  switch (grantee->roletype)
965  {
966  case ROLESPEC_PUBLIC:
967  grantee_uid = ACL_ID_PUBLIC;
968  break;
969  default:
970  grantee_uid = get_rolespec_oid(grantee, false);
971  break;
972  }
973  iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
974  }
975 
976  /*
977  * Convert action->privileges, a list of privilege strings, into an
978  * AclMode bitmask.
979  */
980  switch (action->objtype)
981  {
982  case OBJECT_TABLE:
983  all_privileges = ACL_ALL_RIGHTS_RELATION;
984  errormsg = gettext_noop("invalid privilege type %s for relation");
985  break;
986  case OBJECT_SEQUENCE:
987  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
988  errormsg = gettext_noop("invalid privilege type %s for sequence");
989  break;
990  case OBJECT_FUNCTION:
991  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
992  errormsg = gettext_noop("invalid privilege type %s for function");
993  break;
994  case OBJECT_PROCEDURE:
995  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
996  errormsg = gettext_noop("invalid privilege type %s for procedure");
997  break;
998  case OBJECT_ROUTINE:
999  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1000  errormsg = gettext_noop("invalid privilege type %s for routine");
1001  break;
1002  case OBJECT_TYPE:
1003  all_privileges = ACL_ALL_RIGHTS_TYPE;
1004  errormsg = gettext_noop("invalid privilege type %s for type");
1005  break;
1006  case OBJECT_SCHEMA:
1007  all_privileges = ACL_ALL_RIGHTS_SCHEMA;
1008  errormsg = gettext_noop("invalid privilege type %s for schema");
1009  break;
1010  default:
1011  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
1012  (int) action->objtype);
1013  /* keep compiler quiet */
1014  all_privileges = ACL_NO_RIGHTS;
1015  errormsg = NULL;
1016  }
1017 
1018  if (action->privileges == NIL)
1019  {
1020  iacls.all_privs = true;
1021 
1022  /*
1023  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
1024  * depending on the object type
1025  */
1026  iacls.privileges = ACL_NO_RIGHTS;
1027  }
1028  else
1029  {
1030  iacls.all_privs = false;
1031  iacls.privileges = ACL_NO_RIGHTS;
1032 
1033  foreach(cell, action->privileges)
1034  {
1035  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
1036  AclMode priv;
1037 
1038  if (privnode->cols)
1039  ereport(ERROR,
1040  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1041  errmsg("default privileges cannot be set for columns")));
1042 
1043  if (privnode->priv_name == NULL) /* parser mistake? */
1044  elog(ERROR, "AccessPriv node must specify privilege");
1045  priv = string_to_privilege(privnode->priv_name);
1046 
1047  if (priv & ~((AclMode) all_privileges))
1048  ereport(ERROR,
1049  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1050  errmsg(errormsg, privilege_to_string(priv))));
1051 
1052  iacls.privileges |= priv;
1053  }
1054  }
1055 
1056  if (rolespecs == NIL)
1057  {
1058  /* Set permissions for myself */
1059  iacls.roleid = GetUserId();
1060 
1061  SetDefaultACLsInSchemas(&iacls, nspnames);
1062  }
1063  else
1064  {
1065  /* Look up the role OIDs and do permissions checks */
1066  ListCell *rolecell;
1067 
1068  foreach(rolecell, rolespecs)
1069  {
1070  RoleSpec *rolespec = lfirst(rolecell);
1071 
1072  iacls.roleid = get_rolespec_oid(rolespec, false);
1073 
1074  /*
1075  * We insist that calling user be a member of each target role. If
1076  * he has that, he could become that role anyway via SET ROLE, so
1077  * FOR ROLE is just a syntactic convenience and doesn't give any
1078  * special privileges.
1079  */
1081 
1082  SetDefaultACLsInSchemas(&iacls, nspnames);
1083  }
1084  }
1085 }
#define NIL
Definition: pg_list.h:65
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:162
bool grant_option
Definition: aclchk.c:93
Oid GetUserId(void)
Definition: miscinit.c:478
static AclMode string_to_privilege(const char *privname)
Definition: aclchk.c:3230
bool grant_option
Definition: parsenodes.h:2022
#define gettext_noop(x)
Definition: c.h:1197
int errcode(int sqlerrcode)
Definition: elog.c:698
List * cols
Definition: parsenodes.h:2064
unsigned int Oid
Definition: postgres_ext.h:31
List * grantees
Definition: aclchk.c:92
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
uint32 AclMode
Definition: parsenodes.h:80
#define ERROR
Definition: elog.h:46
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
#define ACL_ALL_RIGHTS_SCHEMA
Definition: acl.h:165
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:167
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4893
Node * arg
Definition: parsenodes.h:747
bool is_grant
Definition: parsenodes.h:2014
RoleSpecType roletype
Definition: parsenodes.h:339
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5128
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:158
DropBehavior behavior
Definition: aclchk.c:94
List * privileges
Definition: parsenodes.h:2019
#define ereport(elevel,...)
Definition: elog.h:157
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:355
DropBehavior behavior
Definition: parsenodes.h:2024
#define lfirst(lc)
Definition: pg_list.h:169
static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
Definition: aclchk.c:1093
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define ACL_ALL_RIGHTS_RELATION
Definition: acl.h:157
ObjectType objtype
Definition: parsenodes.h:2016
#define ACL_ID_PUBLIC
Definition: acl.h:46
char * defname
Definition: parsenodes.h:746
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:3267
List * grantees
Definition: parsenodes.h:2021
AclMode privileges
Definition: aclchk.c:91
Definition: pg_list.h:50
ObjectType objtype
Definition: aclchk.c:89
char * priv_name
Definition: parsenodes.h:2063

◆ ExecGrant_Attribute()

static void ExecGrant_Attribute ( InternalGrant istmt,
Oid  relOid,
const char *  relname,
AttrNumber  attnum,
Oid  ownerId,
AclMode  col_privileges,
Relation  attRelation,
const Acl old_rel_acl 
)
static

Definition at line 1602 of file aclchk.c.

References ACL_ALL_RIGHTS_COLUMN, ACL_NUM, aclconcat(), acldefault(), aclmembers(), 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, OBJECT_COLUMN, ObjectIdGetDatum, pfree(), PointerGetDatum, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), SearchSysCache2(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.

Referenced by ExecGrant_Relation().

1605 {
1606  HeapTuple attr_tuple;
1607  Form_pg_attribute pg_attribute_tuple;
1608  Acl *old_acl;
1609  Acl *new_acl;
1610  Acl *merged_acl;
1611  Datum aclDatum;
1612  bool isNull;
1613  Oid grantorId;
1614  AclMode avail_goptions;
1615  bool need_update;
1616  HeapTuple newtuple;
1617  Datum values[Natts_pg_attribute];
1618  bool nulls[Natts_pg_attribute];
1619  bool replaces[Natts_pg_attribute];
1620  int noldmembers;
1621  int nnewmembers;
1622  Oid *oldmembers;
1623  Oid *newmembers;
1624 
1625  attr_tuple = SearchSysCache2(ATTNUM,
1626  ObjectIdGetDatum(relOid),
1628  if (!HeapTupleIsValid(attr_tuple))
1629  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1630  attnum, relOid);
1631  pg_attribute_tuple = (Form_pg_attribute) GETSTRUCT(attr_tuple);
1632 
1633  /*
1634  * Get working copy of existing ACL. If there's no ACL, substitute the
1635  * proper default.
1636  */
1637  aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
1638  &isNull);
1639  if (isNull)
1640  {
1641  old_acl = acldefault(OBJECT_COLUMN, ownerId);
1642  /* There are no old member roles according to the catalogs */
1643  noldmembers = 0;
1644  oldmembers = NULL;
1645  }
1646  else
1647  {
1648  old_acl = DatumGetAclPCopy(aclDatum);
1649  /* Get the roles mentioned in the existing ACL */
1650  noldmembers = aclmembers(old_acl, &oldmembers);
1651  }
1652 
1653  /*
1654  * In select_best_grantor we should consider existing table-level ACL bits
1655  * as well as the per-column ACL. Build a new ACL that is their
1656  * concatenation. (This is a bit cheap and dirty compared to merging them
1657  * properly with no duplications, but it's all we need here.)
1658  */
1659  merged_acl = aclconcat(old_rel_acl, old_acl);
1660 
1661  /* Determine ID to do the grant as, and available grant options */
1662  select_best_grantor(GetUserId(), col_privileges,
1663  merged_acl, ownerId,
1664  &grantorId, &avail_goptions);
1665 
1666  pfree(merged_acl);
1667 
1668  /*
1669  * Restrict the privileges to what we can actually grant, and emit the
1670  * standards-mandated warning and error messages. Note: we don't track
1671  * whether the user actually used the ALL PRIVILEGES(columns) syntax for
1672  * each column; we just approximate it by whether all the possible
1673  * privileges are specified now. Since the all_privs flag only determines
1674  * whether a warning is issued, this seems close enough.
1675  */
1676  col_privileges =
1677  restrict_and_check_grant(istmt->is_grant, avail_goptions,
1678  (col_privileges == ACL_ALL_RIGHTS_COLUMN),
1679  col_privileges,
1680  relOid, grantorId, OBJECT_COLUMN,
1681  relname, attnum,
1682  NameStr(pg_attribute_tuple->attname));
1683 
1684  /*
1685  * Generate new ACL.
1686  */
1687  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
1688  istmt->grant_option,
1689  istmt->behavior, istmt->grantees,
1690  col_privileges, grantorId,
1691  ownerId);
1692 
1693  /*
1694  * We need the members of both old and new ACLs so we can correct the
1695  * shared dependency information.
1696  */
1697  nnewmembers = aclmembers(new_acl, &newmembers);
1698 
1699  /* finished building new ACL value, now insert it */
1700  MemSet(values, 0, sizeof(values));
1701  MemSet(nulls, false, sizeof(nulls));
1702  MemSet(replaces, false, sizeof(replaces));
1703 
1704  /*
1705  * If the updated ACL is empty, we can set attacl to null, and maybe even
1706  * avoid an update of the pg_attribute row. This is worth testing because
1707  * we'll come through here multiple times for any relation-level REVOKE,
1708  * even if there were never any column GRANTs. Note we are assuming that
1709  * the "default" ACL state for columns is empty.
1710  */
1711  if (ACL_NUM(new_acl) > 0)
1712  {
1713  values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl);
1714  need_update = true;
1715  }
1716  else
1717  {
1718  nulls[Anum_pg_attribute_attacl - 1] = true;
1719  need_update = !isNull;
1720  }
1721  replaces[Anum_pg_attribute_attacl - 1] = true;
1722 
1723  if (need_update)
1724  {
1725  newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
1726  values, nulls, replaces);
1727 
1728  CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
1729 
1730  /* Update initial privileges for extensions */
1731  recordExtensionInitPriv(relOid, RelationRelationId, attnum,
1732  ACL_NUM(new_acl) > 0 ? new_acl : NULL);
1733 
1734  /* Update the shared dependency ACL info */
1735  updateAclDependencies(RelationRelationId, relOid, attnum,
1736  ownerId,
1737  noldmembers, oldmembers,
1738  nnewmembers, newmembers);
1739  }
1740 
1741  pfree(new_acl);
1742 
1743  ReleaseSysCache(attr_tuple);
1744 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:480
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define ACL_ALL_RIGHTS_COLUMN
Definition: acl.h:156
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
#define Int16GetDatum(X)
Definition: postgres.h:495
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:734
#define MemSet(start, val, len)
Definition: c.h:1008
NameData relname
Definition: pg_class.h:38
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:153
uint32 AclMode
Definition: parsenodes.h:80
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_NUM(ACL)
Definition: acl.h:108
ItemPointerData t_self
Definition: htup.h:65
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:6008
Acl * aclconcat(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:413
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
int16 attnum
Definition: pg_attribute.h:83
DropBehavior behavior
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1458
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1138
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5018
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:212
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Database()

static void ExecGrant_Database ( InternalGrant grantStmt)
static

Definition at line 2082 of file aclchk.c.

References ACL_ALL_RIGHTS_DATABASE, ACL_NO_RIGHTS, acldefault(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, CatalogTupleUpdate(), CommandCounterIncrement(), DATABASEOID, DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_getattr, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, OBJECT_DATABASE, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), HeapTupleData::t_self, table_close(), table_open(), updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2083 {
2084  Relation relation;
2085  ListCell *cell;
2086 
2087  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2088  istmt->privileges = ACL_ALL_RIGHTS_DATABASE;
2089 
2090  relation = table_open(DatabaseRelationId, RowExclusiveLock);
2091 
2092  foreach(cell, istmt->objects)
2093  {
2094  Oid datId = lfirst_oid(cell);
2095  Form_pg_database pg_database_tuple;
2096  Datum aclDatum;
2097  bool isNull;
2098  AclMode avail_goptions;
2099  AclMode this_privileges;
2100  Acl *old_acl;
2101  Acl *new_acl;
2102  Oid grantorId;
2103  Oid ownerId;
2104  HeapTuple newtuple;
2105  Datum values[Natts_pg_database];
2106  bool nulls[Natts_pg_database];
2107  bool replaces[Natts_pg_database];
2108  int noldmembers;
2109  int nnewmembers;
2110  Oid *oldmembers;
2111  Oid *newmembers;
2112  HeapTuple tuple;
2113 
2114  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(datId));
2115  if (!HeapTupleIsValid(tuple))
2116  elog(ERROR, "cache lookup failed for database %u", datId);
2117 
2118  pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
2119 
2120  /*
2121  * Get owner ID and working copy of existing ACL. If there's no ACL,
2122  * substitute the proper default.
2123  */
2124  ownerId = pg_database_tuple->datdba;
2125  aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
2126  RelationGetDescr(relation), &isNull);
2127  if (isNull)
2128  {
2129  old_acl = acldefault(OBJECT_DATABASE, ownerId);
2130  /* There are no old member roles according to the catalogs */
2131  noldmembers = 0;
2132  oldmembers = NULL;
2133  }
2134  else
2135  {
2136  old_acl = DatumGetAclPCopy(aclDatum);
2137  /* Get the roles mentioned in the existing ACL */
2138  noldmembers = aclmembers(old_acl, &oldmembers);
2139  }
2140 
2141  /* Determine ID to do the grant as, and available grant options */
2142  select_best_grantor(GetUserId(), istmt->privileges,
2143  old_acl, ownerId,
2144  &grantorId, &avail_goptions);
2145 
2146  /*
2147  * Restrict the privileges to what we can actually grant, and emit the
2148  * standards-mandated warning and error messages.
2149  */
2150  this_privileges =
2151  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2152  istmt->all_privs, istmt->privileges,
2153  datId, grantorId, OBJECT_DATABASE,
2154  NameStr(pg_database_tuple->datname),
2155  0, NULL);
2156 
2157  /*
2158  * Generate new ACL.
2159  */
2160  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2161  istmt->grant_option, istmt->behavior,
2162  istmt->grantees, this_privileges,
2163  grantorId, ownerId);
2164 
2165  /*
2166  * We need the members of both old and new ACLs so we can correct the
2167  * shared dependency information.
2168  */
2169  nnewmembers = aclmembers(new_acl, &newmembers);
2170 
2171  /* finished building new ACL value, now insert it */
2172  MemSet(values, 0, sizeof(values));
2173  MemSet(nulls, false, sizeof(nulls));
2174  MemSet(replaces, false, sizeof(replaces));
2175 
2176  replaces[Anum_pg_database_datacl - 1] = true;
2177  values[Anum_pg_database_datacl - 1] = PointerGetDatum(new_acl);
2178 
2179  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2180  nulls, replaces);
2181 
2182  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2183 
2184  /* Update the shared dependency ACL info */
2185  updateAclDependencies(DatabaseRelationId, pg_database_tuple->oid, 0,
2186  ownerId,
2187  noldmembers, oldmembers,
2188  nnewmembers, newmembers);
2189 
2190  ReleaseSysCache(tuple);
2191 
2192  pfree(new_acl);
2193 
2194  /* prevent error when processing duplicate objects */
2196  }
2197 
2198  table_close(relation, RowExclusiveLock);
2199 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:480
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:478
FormData_pg_database * Form_pg_database
Definition: pg_database.h:81
#define PointerGetDatum(X)
Definition: postgres.h:600
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:734
#define MemSet(start, val, len)
Definition: c.h:1008
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:153
uint32 AclMode
Definition: parsenodes.h:80
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1458
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5018
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:159
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:212
#define lfirst_oid(lc)
Definition: pg_list.h:171
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Fdw()

static void ExecGrant_Fdw ( InternalGrant grantStmt)
static

Definition at line 2202 of file aclchk.c.

References ACL_ALL_RIGHTS_FDW, ACL_NO_RIGHTS, acldefault(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, FOREIGNDATAWRAPPEROID, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, OBJECT_FDW, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2203 {
2204  Relation relation;
2205  ListCell *cell;
2206 
2207  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2208  istmt->privileges = ACL_ALL_RIGHTS_FDW;
2209 
2210  relation = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
2211 
2212  foreach(cell, istmt->objects)
2213  {
2214  Oid fdwid = lfirst_oid(cell);
2215  Form_pg_foreign_data_wrapper pg_fdw_tuple;
2216  Datum aclDatum;
2217  bool isNull;
2218  AclMode avail_goptions;
2219  AclMode this_privileges;
2220  Acl *old_acl;
2221  Acl *new_acl;
2222  Oid grantorId;
2223  Oid ownerId;
2224  HeapTuple tuple;
2225  HeapTuple newtuple;
2226  Datum values[Natts_pg_foreign_data_wrapper];
2227  bool nulls[Natts_pg_foreign_data_wrapper];
2228  bool replaces[Natts_pg_foreign_data_wrapper];
2229  int noldmembers;
2230  int nnewmembers;
2231  Oid *oldmembers;
2232  Oid *newmembers;
2233 
2235  ObjectIdGetDatum(fdwid));
2236  if (!HeapTupleIsValid(tuple))
2237  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
2238 
2239  pg_fdw_tuple = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
2240 
2241  /*
2242  * Get owner ID and working copy of existing ACL. If there's no ACL,
2243  * substitute the proper default.
2244  */
2245  ownerId = pg_fdw_tuple->fdwowner;
2246  aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
2247  Anum_pg_foreign_data_wrapper_fdwacl,
2248  &isNull);
2249  if (isNull)
2250  {
2251  old_acl = acldefault(OBJECT_FDW, ownerId);
2252  /* There are no old member roles according to the catalogs */
2253  noldmembers = 0;
2254  oldmembers = NULL;
2255  }
2256  else
2257  {
2258  old_acl = DatumGetAclPCopy(aclDatum);
2259  /* Get the roles mentioned in the existing ACL */
2260  noldmembers = aclmembers(old_acl, &oldmembers);
2261  }
2262 
2263  /* Determine ID to do the grant as, and available grant options */
2264  select_best_grantor(GetUserId(), istmt->privileges,
2265  old_acl, ownerId,
2266  &grantorId, &avail_goptions);
2267 
2268  /*
2269  * Restrict the privileges to what we can actually grant, and emit the
2270  * standards-mandated warning and error messages.
2271  */
2272  this_privileges =
2273  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2274  istmt->all_privs, istmt->privileges,
2275  fdwid, grantorId, OBJECT_FDW,
2276  NameStr(pg_fdw_tuple->fdwname),
2277  0, NULL);
2278 
2279  /*
2280  * Generate new ACL.
2281  */
2282  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2283  istmt->grant_option, istmt->behavior,
2284  istmt->grantees, this_privileges,
2285  grantorId, ownerId);
2286 
2287  /*
2288  * We need the members of both old and new ACLs so we can correct the
2289  * shared dependency information.
2290  */
2291  nnewmembers = aclmembers(new_acl, &newmembers);
2292 
2293  /* finished building new ACL value, now insert it */
2294  MemSet(values, 0, sizeof(values));
2295  MemSet(nulls, false, sizeof(nulls));
2296  MemSet(replaces, false, sizeof(replaces));
2297 
2298  replaces[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
2299  values[Anum_pg_foreign_data_wrapper_fdwacl - 1] = PointerGetDatum(new_acl);
2300 
2301  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2302  nulls, replaces);
2303 
2304  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2305 
2306  /* Update initial privileges for extensions */
2307  recordExtensionInitPriv(fdwid, ForeignDataWrapperRelationId, 0,
2308  new_acl);
2309 
2310  /* Update the shared dependency ACL info */
2311  updateAclDependencies(ForeignDataWrapperRelationId,
2312  pg_fdw_tuple->oid, 0,
2313  ownerId,
2314  noldmembers, oldmembers,
2315  nnewmembers, newmembers);
2316 
2317  ReleaseSysCache(tuple);
2318 
2319  pfree(new_acl);
2320 
2321  /* prevent error when processing duplicate objects */
2323  }
2324 
2325  table_close(relation, RowExclusiveLock);
2326 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:480
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:734
#define MemSet(start, val, len)
Definition: c.h:1008
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:153
uint32 AclMode
Definition: parsenodes.h:80
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
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:6008
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1458
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5018
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:160
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:212
#define lfirst_oid(lc)
Definition: pg_list.h:171
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_ForeignServer()

static void ExecGrant_ForeignServer ( InternalGrant grantStmt)
static

Definition at line 2329 of file aclchk.c.

References ACL_ALL_RIGHTS_FOREIGN_SERVER, ACL_NO_RIGHTS, acldefault(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, FOREIGNSERVEROID, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, OBJECT_FOREIGN_SERVER, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2330 {
2331  Relation relation;
2332  ListCell *cell;
2333 
2334  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2335  istmt->privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
2336 
2337  relation = table_open(ForeignServerRelationId, RowExclusiveLock);
2338 
2339  foreach(cell, istmt->objects)
2340  {
2341  Oid srvid = lfirst_oid(cell);
2342  Form_pg_foreign_server pg_server_tuple;
2343  Datum aclDatum;
2344  bool isNull;
2345  AclMode avail_goptions;
2346  AclMode this_privileges;
2347  Acl *old_acl;
2348  Acl *new_acl;
2349  Oid grantorId;
2350  Oid ownerId;
2351  HeapTuple tuple;
2352  HeapTuple newtuple;
2353  Datum values[Natts_pg_foreign_server];
2354  bool nulls[Natts_pg_foreign_server];
2355  bool replaces[Natts_pg_foreign_server];
2356  int noldmembers;
2357  int nnewmembers;
2358  Oid *oldmembers;
2359  Oid *newmembers;
2360 
2362  if (!HeapTupleIsValid(tuple))
2363  elog(ERROR, "cache lookup failed for foreign server %u", srvid);
2364 
2365  pg_server_tuple = (Form_pg_foreign_server) GETSTRUCT(tuple);
2366 
2367  /*
2368  * Get owner ID and working copy of existing ACL. If there's no ACL,
2369  * substitute the proper default.
2370  */
2371  ownerId = pg_server_tuple->srvowner;
2372  aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
2373  Anum_pg_foreign_server_srvacl,
2374  &isNull);
2375  if (isNull)
2376  {
2377  old_acl = acldefault(OBJECT_FOREIGN_SERVER, ownerId);
2378  /* There are no old member roles according to the catalogs */
2379  noldmembers = 0;
2380  oldmembers = NULL;
2381  }
2382  else
2383  {
2384  old_acl = DatumGetAclPCopy(aclDatum);
2385  /* Get the roles mentioned in the existing ACL */
2386  noldmembers = aclmembers(old_acl, &oldmembers);
2387  }
2388 
2389  /* Determine ID to do the grant as, and available grant options */
2390  select_best_grantor(GetUserId(), istmt->privileges,
2391  old_acl, ownerId,
2392  &grantorId, &avail_goptions);
2393 
2394  /*
2395  * Restrict the privileges to what we can actually grant, and emit the
2396  * standards-mandated warning and error messages.
2397  */
2398  this_privileges =
2399  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2400  istmt->all_privs, istmt->privileges,
2401  srvid, grantorId, OBJECT_FOREIGN_SERVER,
2402  NameStr(pg_server_tuple->srvname),
2403  0, NULL);
2404 
2405  /*
2406  * Generate new ACL.
2407  */
2408  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2409  istmt->grant_option, istmt->behavior,
2410  istmt->grantees, this_privileges,
2411  grantorId, ownerId);
2412 
2413  /*
2414  * We need the members of both old and new ACLs so we can correct the
2415  * shared dependency information.
2416  */
2417  nnewmembers = aclmembers(new_acl, &newmembers);
2418 
2419  /* finished building new ACL value, now insert it */
2420  MemSet(values, 0, sizeof(values));
2421  MemSet(nulls, false, sizeof(nulls));
2422  MemSet(replaces, false, sizeof(replaces));
2423 
2424  replaces[Anum_pg_foreign_server_srvacl - 1] = true;
2425  values[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(new_acl);
2426 
2427  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2428  nulls, replaces);
2429 
2430  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2431 
2432  /* Update initial privileges for extensions */
2433  recordExtensionInitPriv(srvid, ForeignServerRelationId, 0, new_acl);
2434 
2435  /* Update the shared dependency ACL info */
2436  updateAclDependencies(ForeignServerRelationId,
2437  pg_server_tuple->oid, 0,
2438  ownerId,
2439  noldmembers, oldmembers,
2440  nnewmembers, newmembers);
2441 
2442  ReleaseSysCache(tuple);
2443 
2444  pfree(new_acl);
2445 
2446  /* prevent error when processing duplicate objects */
2448  }
2449 
2450  table_close(relation, RowExclusiveLock);
2451 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:480
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:734
#define MemSet(start, val, len)
Definition: c.h:1008
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:153
uint32 AclMode
Definition: parsenodes.h:80
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
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:6008
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
FormData_pg_foreign_server * Form_pg_foreign_server
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1458
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5018
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:161
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:212
#define lfirst_oid(lc)
Definition: pg_list.h:171
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Function()

static void ExecGrant_Function ( InternalGrant grantStmt)
static

Definition at line 2454 of file aclchk.c.

References ACL_ALL_RIGHTS_FUNCTION, ACL_NO_RIGHTS, acldefault(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, OBJECT_FUNCTION, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, PROCOID, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2455 {
2456  Relation relation;
2457  ListCell *cell;
2458 
2459  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2460  istmt->privileges = ACL_ALL_RIGHTS_FUNCTION;
2461 
2462  relation = table_open(ProcedureRelationId, RowExclusiveLock);
2463 
2464  foreach(cell, istmt->objects)
2465  {
2466  Oid funcId = lfirst_oid(cell);
2467  Form_pg_proc pg_proc_tuple;
2468  Datum aclDatum;
2469  bool isNull;
2470  AclMode avail_goptions;
2471  AclMode this_privileges;
2472  Acl *old_acl;
2473  Acl *new_acl;
2474  Oid grantorId;
2475  Oid ownerId;
2476  HeapTuple tuple;
2477  HeapTuple newtuple;
2478  Datum values[Natts_pg_proc];
2479  bool nulls[Natts_pg_proc];
2480  bool replaces[Natts_pg_proc];
2481  int noldmembers;
2482  int nnewmembers;
2483  Oid *oldmembers;
2484  Oid *newmembers;
2485 
2486  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
2487  if (!HeapTupleIsValid(tuple))
2488  elog(ERROR, "cache lookup failed for function %u", funcId);
2489 
2490  pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
2491 
2492  /*
2493  * Get owner ID and working copy of existing ACL. If there's no ACL,
2494  * substitute the proper default.
2495  */
2496  ownerId = pg_proc_tuple->proowner;
2497  aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
2498  &isNull);
2499  if (isNull)
2500  {
2501  old_acl = acldefault(OBJECT_FUNCTION, ownerId);
2502  /* There are no old member roles according to the catalogs */
2503  noldmembers = 0;
2504  oldmembers = NULL;
2505  }
2506  else
2507  {
2508  old_acl = DatumGetAclPCopy(aclDatum);
2509  /* Get the roles mentioned in the existing ACL */
2510  noldmembers = aclmembers(old_acl, &oldmembers);
2511  }
2512 
2513  /* Determine ID to do the grant as, and available grant options */
2514  select_best_grantor(GetUserId(), istmt->privileges,
2515  old_acl, ownerId,
2516  &grantorId, &avail_goptions);
2517 
2518  /*
2519  * Restrict the privileges to what we can actually grant, and emit the
2520  * standards-mandated warning and error messages.
2521  */
2522  this_privileges =
2523  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2524  istmt->all_privs, istmt->privileges,
2525  funcId, grantorId, OBJECT_FUNCTION,
2526  NameStr(pg_proc_tuple->proname),
2527  0, NULL);
2528 
2529  /*
2530  * Generate new ACL.
2531  */
2532  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2533  istmt->grant_option, istmt->behavior,
2534  istmt->grantees, this_privileges,
2535  grantorId, ownerId);
2536 
2537  /*
2538  * We need the members of both old and new ACLs so we can correct the
2539  * shared dependency information.
2540  */
2541  nnewmembers = aclmembers(new_acl, &newmembers);
2542 
2543  /* finished building new ACL value, now insert it */
2544  MemSet(values, 0, sizeof(values));
2545  MemSet(nulls, false, sizeof(nulls));
2546  MemSet(replaces, false, sizeof(replaces));
2547 
2548  replaces[Anum_pg_proc_proacl - 1] = true;
2549  values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
2550 
2551  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2552  nulls, replaces);
2553 
2554  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2555 
2556  /* Update initial privileges for extensions */
2557  recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
2558 
2559  /* Update the shared dependency ACL info */
2560  updateAclDependencies(ProcedureRelationId, funcId, 0,
2561  ownerId,
2562  noldmembers, oldmembers,
2563  nnewmembers, newmembers);
2564 
2565  ReleaseSysCache(tuple);
2566 
2567  pfree(new_acl);
2568 
2569  /* prevent error when processing duplicate objects */
2571  }
2572 
2573  table_close(relation, RowExclusiveLock);
2574 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:480
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:162
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:734
#define MemSet(start, val, len)
Definition: c.h:1008
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:153
uint32 AclMode
Definition: parsenodes.h:80
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
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:6008
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1458
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5018
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:212
#define lfirst_oid(lc)
Definition: pg_list.h:171
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Language()

static void ExecGrant_Language ( InternalGrant grantStmt)
static

Definition at line 2577 of file aclchk.c.

References ACL_ALL_RIGHTS_LANGUAGE, ACL_NO_RIGHTS, acldefault(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, LANGNAME, LANGOID, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, OBJECT_LANGUAGE, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2578 {
2579  Relation relation;
2580  ListCell *cell;
2581 
2582  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2583  istmt->privileges = ACL_ALL_RIGHTS_LANGUAGE;
2584 
2585  relation = table_open(LanguageRelationId, RowExclusiveLock);
2586 
2587  foreach(cell, istmt->objects)
2588  {
2589  Oid langId = lfirst_oid(cell);
2590  Form_pg_language pg_language_tuple;
2591  Datum aclDatum;
2592  bool isNull;
2593  AclMode avail_goptions;
2594  AclMode this_privileges;
2595  Acl *old_acl;
2596  Acl *new_acl;
2597  Oid grantorId;
2598  Oid ownerId;
2599  HeapTuple tuple;
2600  HeapTuple newtuple;
2601  Datum values[Natts_pg_language];
2602  bool nulls[Natts_pg_language];
2603  bool replaces[Natts_pg_language];
2604  int noldmembers;
2605  int nnewmembers;
2606  Oid *oldmembers;
2607  Oid *newmembers;
2608 
2609  tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(langId));
2610  if (!HeapTupleIsValid(tuple))
2611  elog(ERROR, "cache lookup failed for language %u", langId);
2612 
2613  pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
2614 
2615  if (!pg_language_tuple->lanpltrusted)
2616  ereport(ERROR,
2617  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2618  errmsg("language \"%s\" is not trusted",
2619  NameStr(pg_language_tuple->lanname)),
2620  errdetail("GRANT and REVOKE are not allowed on untrusted languages, "
2621  "because only superusers can use untrusted languages.")));
2622 
2623  /*
2624  * Get owner ID and working copy of existing ACL. If there's no ACL,
2625  * substitute the proper default.
2626  */
2627  ownerId = pg_language_tuple->lanowner;
2628  aclDatum = SysCacheGetAttr(LANGNAME, tuple, Anum_pg_language_lanacl,
2629  &isNull);
2630  if (isNull)
2631  {
2632  old_acl = acldefault(OBJECT_LANGUAGE, ownerId);
2633  /* There are no old member roles according to the catalogs */
2634  noldmembers = 0;
2635  oldmembers = NULL;
2636  }
2637  else
2638  {
2639  old_acl = DatumGetAclPCopy(aclDatum);
2640  /* Get the roles mentioned in the existing ACL */
2641  noldmembers = aclmembers(old_acl, &oldmembers);
2642  }
2643 
2644  /* Determine ID to do the grant as, and available grant options */
2645  select_best_grantor(GetUserId(), istmt->privileges,
2646  old_acl, ownerId,
2647  &grantorId, &avail_goptions);
2648 
2649  /*
2650  * Restrict the privileges to what we can actually grant, and emit the
2651  * standards-mandated warning and error messages.
2652  */
2653  this_privileges =
2654  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2655  istmt->all_privs, istmt->privileges,
2656  langId, grantorId, OBJECT_LANGUAGE,
2657  NameStr(pg_language_tuple->lanname),
2658  0, NULL);
2659 
2660  /*
2661  * Generate new ACL.
2662  */
2663  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2664  istmt->grant_option, istmt->behavior,
2665  istmt->grantees, this_privileges,
2666  grantorId, ownerId);
2667 
2668  /*
2669  * We need the members of both old and new ACLs so we can correct the
2670  * shared dependency information.
2671  */
2672  nnewmembers = aclmembers(new_acl, &newmembers);
2673 
2674  /* finished building new ACL value, now insert it */
2675  MemSet(values, 0, sizeof(values));
2676  MemSet(nulls, false, sizeof(nulls));
2677  MemSet(replaces, false, sizeof(replaces));
2678 
2679  replaces[Anum_pg_language_lanacl - 1] = true;
2680  values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
2681 
2682  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2683  nulls, replaces);
2684 
2685  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2686 
2687  /* Update initial privileges for extensions */
2688  recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
2689 
2690  /* Update the shared dependency ACL info */
2691  updateAclDependencies(LanguageRelationId, pg_language_tuple->oid, 0,
2692  ownerId,
2693  noldmembers, oldmembers,
2694  nnewmembers, newmembers);
2695 
2696  ReleaseSysCache(tuple);
2697 
2698  pfree(new_acl);
2699 
2700  /* prevent error when processing duplicate objects */
2702  }
2703 
2704  table_close(relation, RowExclusiveLock);
2705 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:480
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
int errcode(int sqlerrcode)
Definition: elog.c:698
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:734
#define MemSet(start, val, len)
Definition: c.h:1008
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:153
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:163
uint32 AclMode
Definition: parsenodes.h:80
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:1042
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:6008
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define ereport(elevel,...)
Definition: elog.h:157
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1458
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5018
static Datum values[MAXATTR]
Definition: bootstrap.c:166
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:212
#define lfirst_oid(lc)
Definition: pg_list.h:171
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Largeobject()

static void ExecGrant_Largeobject ( InternalGrant grantStmt)
static

Definition at line 2708 of file aclchk.c.

References ACL_ALL_RIGHTS_LARGEOBJECT, ACL_NO_RIGHTS, acldefault(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, BTEqualStrategyNumber, CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_getattr, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NAMEDATALEN, OBJECT_LARGEOBJECT, 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, table_close(), table_open(), updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2709 {
2710  Relation relation;
2711  ListCell *cell;
2712 
2713  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2714  istmt->privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
2715 
2716  relation = table_open(LargeObjectMetadataRelationId,
2718 
2719  foreach(cell, istmt->objects)
2720  {
2721  Oid loid = lfirst_oid(cell);
2722  Form_pg_largeobject_metadata form_lo_meta;
2723  char loname[NAMEDATALEN];
2724  Datum aclDatum;
2725  bool isNull;
2726  AclMode avail_goptions;
2727  AclMode this_privileges;
2728  Acl *old_acl;
2729  Acl *new_acl;
2730  Oid grantorId;
2731  Oid ownerId;
2732  HeapTuple newtuple;
2733  Datum values[Natts_pg_largeobject_metadata];
2734  bool nulls[Natts_pg_largeobject_metadata];
2735  bool replaces[Natts_pg_largeobject_metadata];
2736  int noldmembers;
2737  int nnewmembers;
2738  Oid *oldmembers;
2739  Oid *newmembers;
2740  ScanKeyData entry[1];
2741  SysScanDesc scan;
2742  HeapTuple tuple;
2743 
2744  /* There's no syscache for pg_largeobject_metadata */
2745  ScanKeyInit(&entry[0],
2746  Anum_pg_largeobject_metadata_oid,
2747  BTEqualStrategyNumber, F_OIDEQ,
2748  ObjectIdGetDatum(loid));
2749 
2750  scan = systable_beginscan(relation,
2751  LargeObjectMetadataOidIndexId, true,
2752  NULL, 1, entry);
2753 
2754  tuple = systable_getnext(scan);
2755  if (!HeapTupleIsValid(tuple))
2756  elog(ERROR, "could not find tuple for large object %u", loid);
2757 
2758  form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
2759 
2760  /*
2761  * Get owner ID and working copy of existing ACL. If there's no ACL,
2762  * substitute the proper default.
2763  */
2764  ownerId = form_lo_meta->lomowner;
2765  aclDatum = heap_getattr(tuple,
2766  Anum_pg_largeobject_metadata_lomacl,
2767  RelationGetDescr(relation), &isNull);
2768  if (isNull)
2769  {
2770  old_acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
2771  /* There are no old member roles according to the catalogs */
2772  noldmembers = 0;
2773  oldmembers = NULL;
2774  }
2775  else
2776  {
2777  old_acl = DatumGetAclPCopy(aclDatum);
2778  /* Get the roles mentioned in the existing ACL */
2779  noldmembers = aclmembers(old_acl, &oldmembers);
2780  }
2781 
2782  /* Determine ID to do the grant as, and available grant options */
2783  select_best_grantor(GetUserId(), istmt->privileges,
2784  old_acl, ownerId,
2785  &grantorId, &avail_goptions);
2786 
2787  /*
2788  * Restrict the privileges to what we can actually grant, and emit the
2789  * standards-mandated warning and error messages.
2790  */
2791  snprintf(loname, sizeof(loname), "large object %u", loid);
2792  this_privileges =
2793  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2794  istmt->all_privs, istmt->privileges,
2795  loid, grantorId, OBJECT_LARGEOBJECT,
2796  loname, 0, NULL);
2797 
2798  /*
2799  * Generate new ACL.
2800  */
2801  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2802  istmt->grant_option, istmt->behavior,
2803  istmt->grantees, this_privileges,
2804  grantorId, ownerId);
2805 
2806  /*
2807  * We need the members of both old and new ACLs so we can correct the
2808  * shared dependency information.
2809  */
2810  nnewmembers = aclmembers(new_acl, &newmembers);
2811 
2812  /* finished building new ACL value, now insert it */
2813  MemSet(values, 0, sizeof(values));
2814  MemSet(nulls, false, sizeof(nulls));
2815  MemSet(replaces, false, sizeof(replaces));
2816 
2817  replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
2818  values[Anum_pg_largeobject_metadata_lomacl - 1]
2819  = PointerGetDatum(new_acl);
2820 
2821  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2822  values, nulls, replaces);
2823 
2824  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2825 
2826  /* Update initial privileges for extensions */
2827  recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
2828 
2829  /* Update the shared dependency ACL info */
2830  updateAclDependencies(LargeObjectRelationId,
2831  form_lo_meta->oid, 0,
2832  ownerId,
2833  noldmembers, oldmembers,
2834  nnewmembers, newmembers);
2835 
2836  systable_endscan(scan);
2837 
2838  pfree(new_acl);
2839 
2840  /* prevent error when processing duplicate objects */
2842  }
2843 
2844  table_close(relation, RowExclusiveLock);
2845 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:480
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:734
#define MemSet(start, val, len)
Definition: c.h:1008
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:153
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
#define NAMEDATALEN
uint32 AclMode
Definition: parsenodes.h:80
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
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:6008
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
FormData_pg_largeobject_metadata * Form_pg_largeobject_metadata
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:164
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1458
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5018
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define elog(elevel,...)
Definition: elog.h:232
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define snprintf
Definition: port.h:216
#define BTEqualStrategyNumber
Definition: stratnum.h:31
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:212
#define lfirst_oid(lc)
Definition: pg_list.h:171
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Namespace()

static void ExecGrant_Namespace ( InternalGrant grantStmt)
static

Definition at line 2848 of file aclchk.c.

References ACL_ALL_RIGHTS_SCHEMA, ACL_NO_RIGHTS, acldefault(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NAMESPACENAME, NAMESPACEOID, NameStr, OBJECT_SCHEMA, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2849 {
2850  Relation relation;
2851  ListCell *cell;
2852 
2853  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2854  istmt->privileges = ACL_ALL_RIGHTS_SCHEMA;
2855 
2856  relation = table_open(NamespaceRelationId, RowExclusiveLock);
2857 
2858  foreach(cell, istmt->objects)
2859  {
2860  Oid nspid = lfirst_oid(cell);
2861  Form_pg_namespace pg_namespace_tuple;
2862  Datum aclDatum;
2863  bool isNull;
2864  AclMode avail_goptions;
2865  AclMode this_privileges;
2866  Acl *old_acl;
2867  Acl *new_acl;
2868  Oid grantorId;
2869  Oid ownerId;
2870  HeapTuple tuple;
2871  HeapTuple newtuple;
2872  Datum values[Natts_pg_namespace];
2873  bool nulls[Natts_pg_namespace];
2874  bool replaces[Natts_pg_namespace];
2875  int noldmembers;
2876  int nnewmembers;
2877  Oid *oldmembers;
2878  Oid *newmembers;
2879 
2881  if (!HeapTupleIsValid(tuple))
2882  elog(ERROR, "cache lookup failed for namespace %u", nspid);
2883 
2884  pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
2885 
2886  /*
2887  * Get owner ID and working copy of existing ACL. If there's no ACL,
2888  * substitute the proper default.
2889  */
2890  ownerId = pg_namespace_tuple->nspowner;
2891  aclDatum = SysCacheGetAttr(NAMESPACENAME, tuple,
2892  Anum_pg_namespace_nspacl,
2893  &isNull);
2894  if (isNull)
2895  {
2896  old_acl = acldefault(OBJECT_SCHEMA, ownerId);
2897  /* There are no old member roles according to the catalogs */
2898  noldmembers = 0;
2899  oldmembers = NULL;
2900  }
2901  else
2902  {
2903  old_acl = DatumGetAclPCopy(aclDatum);
2904  /* Get the roles mentioned in the existing ACL */
2905  noldmembers = aclmembers(old_acl, &oldmembers);
2906  }
2907 
2908  /* Determine ID to do the grant as, and available grant options */
2909  select_best_grantor(GetUserId(), istmt->privileges,
2910  old_acl, ownerId,
2911  &grantorId, &avail_goptions);
2912 
2913  /*
2914  * Restrict the privileges to what we can actually grant, and emit the
2915  * standards-mandated warning and error messages.
2916  */
2917  this_privileges =
2918  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2919  istmt->all_privs, istmt->privileges,
2920  nspid, grantorId, OBJECT_SCHEMA,
2921  NameStr(pg_namespace_tuple->nspname),
2922  0, NULL);
2923 
2924  /*
2925  * Generate new ACL.
2926  */
2927  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2928  istmt->grant_option, istmt->behavior,
2929  istmt->grantees, this_privileges,
2930  grantorId, ownerId);
2931 
2932  /*
2933  * We need the members of both old and new ACLs so we can correct the
2934  * shared dependency information.
2935  */
2936  nnewmembers = aclmembers(new_acl, &newmembers);
2937 
2938  /* finished building new ACL value, now insert it */
2939  MemSet(values, 0, sizeof(values));
2940  MemSet(nulls, false, sizeof(nulls));
2941  MemSet(replaces, false, sizeof(replaces));
2942 
2943  replaces[Anum_pg_namespace_nspacl - 1] = true;
2944  values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(new_acl);
2945 
2946  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2947  nulls, replaces);
2948 
2949  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2950 
2951  /* Update initial privileges for extensions */
2952  recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
2953 
2954  /* Update the shared dependency ACL info */
2955  updateAclDependencies(NamespaceRelationId, pg_namespace_tuple->oid, 0,
2956  ownerId,
2957  noldmembers, oldmembers,
2958  nnewmembers, newmembers);
2959 
2960  ReleaseSysCache(tuple);
2961 
2962  pfree(new_acl);
2963 
2964  /* prevent error when processing duplicate objects */
2966  }
2967 
2968  table_close(relation, RowExclusiveLock);
2969 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:480
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:52
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:734
#define MemSet(start, val, len)
Definition: c.h:1008
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:153
uint32 AclMode
Definition: parsenodes.h:80
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
ItemPointerData t_self
Definition: htup.h:65
#define ACL_ALL_RIGHTS_SCHEMA
Definition: acl.h:165
#define RowExclusiveLock
Definition: lockdefs.h:38
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:6008
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1458
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5018
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:212
#define lfirst_oid(lc)
Definition: pg_list.h:171
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Relation()

static void ExecGrant_Relation ( InternalGrant grantStmt)
static

Definition at line 1750 of file aclchk.c.

References ACL_ALL_RIGHTS_COLUMN, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SEQUENCE, ACL_NO_RIGHTS, ACL_SELECT, aclcopy(), acldefault(), aclmembers(), InternalGrant::all_privs, 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_modify_tuple(), HeapTupleIsValid, i, InternalGrant::is_grant, lfirst, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectIdGetDatum, InternalGrant::objects, InternalGrant::objtype, palloc0(), pfree(), PointerGetDatum, AccessPriv::priv_name, privilege_to_string(), InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), RELOID, restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), string_to_privilege(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), updateAclDependencies(), values, and WARNING.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Tablespace()

static void ExecGrant_Tablespace ( InternalGrant grantStmt)
static

Definition at line 2972 of file aclchk.c.

References ACL_ALL_RIGHTS_TABLESPACE, ACL_NO_RIGHTS, acldefault(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_getattr, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, OBJECT_TABLESPACE, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), HeapTupleData::t_self, table_close(), table_open(), TABLESPACEOID, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2973 {
2974  Relation relation;
2975  ListCell *cell;
2976 
2977  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2978  istmt->privileges = ACL_ALL_RIGHTS_TABLESPACE;
2979 
2980  relation = table_open(TableSpaceRelationId, RowExclusiveLock);
2981 
2982  foreach(cell, istmt->objects)
2983  {
2984  Oid tblId = lfirst_oid(cell);
2985  Form_pg_tablespace pg_tablespace_tuple;
2986  Datum aclDatum;
2987  bool isNull;
2988  AclMode avail_goptions;
2989  AclMode this_privileges;
2990  Acl *old_acl;
2991  Acl *new_acl;
2992  Oid grantorId;
2993  Oid ownerId;
2994  HeapTuple newtuple;
2995  Datum values[Natts_pg_tablespace];
2996  bool nulls[Natts_pg_tablespace];
2997  bool replaces[Natts_pg_tablespace];
2998  int noldmembers;
2999  int nnewmembers;
3000  Oid *oldmembers;
3001  Oid *newmembers;
3002  HeapTuple tuple;
3003 
3004  /* Search syscache for pg_tablespace */
3006  if (!HeapTupleIsValid(tuple))
3007  elog(ERROR, "cache lookup failed for tablespace %u", tblId);
3008 
3009  pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);
3010 
3011  /*
3012  * Get owner ID and working copy of existing ACL. If there's no ACL,
3013  * substitute the proper default.
3014  */
3015  ownerId = pg_tablespace_tuple->spcowner;
3016  aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl,
3017  RelationGetDescr(relation), &isNull);
3018  if (isNull)
3019  {
3020  old_acl = acldefault(OBJECT_TABLESPACE, ownerId);
3021  /* There are no old member roles according to the catalogs */
3022  noldmembers = 0;
3023  oldmembers = NULL;
3024  }
3025  else
3026  {
3027  old_acl = DatumGetAclPCopy(aclDatum);
3028  /* Get the roles mentioned in the existing ACL */
3029  noldmembers = aclmembers(old_acl, &oldmembers);
3030  }
3031 
3032  /* Determine ID to do the grant as, and available grant options */
3033  select_best_grantor(GetUserId(), istmt->privileges,
3034  old_acl, ownerId,
3035  &grantorId, &avail_goptions);
3036 
3037  /*
3038  * Restrict the privileges to what we can actually grant, and emit the
3039  * standards-mandated warning and error messages.
3040  */
3041  this_privileges =
3042  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3043  istmt->all_privs, istmt->privileges,
3044  tblId, grantorId, OBJECT_TABLESPACE,
3045  NameStr(pg_tablespace_tuple->spcname),
3046  0, NULL);
3047 
3048  /*
3049  * Generate new ACL.
3050  */
3051  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3052  istmt->grant_option, istmt->behavior,
3053  istmt->grantees, this_privileges,
3054  grantorId, ownerId);
3055 
3056  /*
3057  * We need the members of both old and new ACLs so we can correct the
3058  * shared dependency information.
3059  */
3060  nnewmembers = aclmembers(new_acl, &newmembers);
3061 
3062  /* finished building new ACL value, now insert it */
3063  MemSet(values, 0, sizeof(values));
3064  MemSet(nulls, false, sizeof(nulls));
3065  MemSet(replaces, false, sizeof(replaces));
3066 
3067  replaces[Anum_pg_tablespace_spcacl - 1] = true;
3068  values[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(new_acl);
3069 
3070  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3071  nulls, replaces);
3072 
3073  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3074 
3075  /* Update the shared dependency ACL info */
3076  updateAclDependencies(TableSpaceRelationId, tblId, 0,
3077  ownerId,
3078  noldmembers, oldmembers,
3079  nnewmembers, newmembers);
3080 
3081  ReleaseSysCache(tuple);
3082  pfree(new_acl);
3083 
3084  /* prevent error when processing duplicate objects */
3086  }
3087 
3088  table_close(relation, RowExclusiveLock);
3089 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:480
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:734
#define MemSet(start, val, len)
Definition: c.h:1008
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:166
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:153
uint32 AclMode
Definition: parsenodes.h:80
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_tablespace * Form_pg_tablespace
Definition: pg_tablespace.h:48
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1458
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5018
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:212
#define lfirst_oid(lc)
Definition: pg_list.h:171
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Type()

static void ExecGrant_Type ( InternalGrant grantStmt)
static

Definition at line 3092 of file aclchk.c.

References ACL_ALL_RIGHTS_TYPE, ACL_NO_RIGHTS, acldefault(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ereport, errcode(), errhint(), errmsg(), ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_getattr, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, OBJECT_DOMAIN, OBJECT_TYPE, ObjectIdGetDatum, InternalGrant::objects, InternalGrant::objtype, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), HeapTupleData::t_self, table_close(), table_open(), TYPEOID, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

3093 {
3094  Relation relation;
3095  ListCell *cell;
3096 
3097  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
3098  istmt->privileges = ACL_ALL_RIGHTS_TYPE;
3099 
3100  relation = table_open(TypeRelationId, RowExclusiveLock);
3101 
3102  foreach(cell, istmt->objects)
3103  {
3104  Oid typId = lfirst_oid(cell);
3105  Form_pg_type pg_type_tuple;
3106  Datum aclDatum;
3107  bool isNull;
3108  AclMode avail_goptions;
3109  AclMode this_privileges;
3110  Acl *old_acl;
3111  Acl *new_acl;
3112  Oid grantorId;
3113  Oid ownerId;
3114  HeapTuple newtuple;
3115  Datum values[Natts_pg_type];
3116  bool nulls[Natts_pg_type];
3117  bool replaces[Natts_pg_type];
3118  int noldmembers;
3119  int nnewmembers;
3120  Oid *oldmembers;
3121  Oid *newmembers;
3122  HeapTuple tuple;
3123 
3124  /* Search syscache for pg_type */
3125  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typId));
3126  if (!HeapTupleIsValid(tuple))
3127  elog(ERROR, "cache lookup failed for type %u", typId);
3128 
3129  pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
3130 
3131  if (IsTrueArrayType(pg_type_tuple))
3132  ereport(ERROR,
3133  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
3134  errmsg("cannot set privileges of array types"),
3135  errhint("Set the privileges of the element type instead.")));
3136 
3137  /* Used GRANT DOMAIN on a non-domain? */
3138  if (istmt->objtype == OBJECT_DOMAIN &&
3139  pg_type_tuple->typtype != TYPTYPE_DOMAIN)
3140  ereport(ERROR,
3141  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3142  errmsg("\"%s\" is not a domain",
3143  NameStr(pg_type_tuple->typname))));
3144 
3145  /*
3146  * Get owner ID and working copy of existing ACL. If there's no ACL,
3147  * substitute the proper default.
3148  */
3149  ownerId = pg_type_tuple->typowner;
3150  aclDatum = heap_getattr(tuple, Anum_pg_type_typacl,
3151  RelationGetDescr(relation), &isNull);
3152  if (isNull)
3153  {
3154  old_acl = acldefault(istmt->objtype, ownerId);
3155  /* There are no old member roles according to the catalogs */
3156  noldmembers = 0;
3157  oldmembers = NULL;
3158  }
3159  else
3160  {
3161  old_acl = DatumGetAclPCopy(aclDatum);
3162  /* Get the roles mentioned in the existing ACL */
3163  noldmembers = aclmembers(old_acl, &oldmembers);
3164  }
3165 
3166  /* Determine ID to do the grant as, and available grant options */
3167  select_best_grantor(GetUserId(), istmt->privileges,
3168  old_acl, ownerId,
3169  &grantorId, &avail_goptions);
3170 
3171  /*
3172  * Restrict the privileges to what we can actually grant, and emit the
3173  * standards-mandated warning and error messages.
3174  */
3175  this_privileges =
3176  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3177  istmt->all_privs, istmt->privileges,
3178  typId, grantorId, OBJECT_TYPE,
3179  NameStr(pg_type_tuple->typname),
3180  0, NULL);
3181 
3182  /*
3183  * Generate new ACL.
3184  */
3185  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3186  istmt->grant_option, istmt->behavior,
3187  istmt->grantees, this_privileges,
3188  grantorId, ownerId);
3189 
3190  /*
3191  * We need the members of both old and new ACLs so we can correct the
3192  * shared dependency information.
3193  */
3194  nnewmembers = aclmembers(new_acl, &newmembers);
3195 
3196  /* finished building new ACL value, now insert it */
3197  MemSet(values, 0, sizeof(values));
3198  MemSet(nulls, false, sizeof(nulls));
3199  MemSet(replaces, false, sizeof(replaces));
3200 
3201  replaces[Anum_pg_type_typacl - 1] = true;
3202  values[Anum_pg_type_typacl - 1] = PointerGetDatum(new_acl);
3203 
3204  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3205  nulls, replaces);
3206 
3207  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3208 
3209  /* Update initial privileges for extensions */
3210  recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
3211 
3212  /* Update the shared dependency ACL info */
3213  updateAclDependencies(TypeRelationId, typId, 0,
3214  ownerId,
3215  noldmembers, oldmembers,
3216  nnewmembers, newmembers);
3217 
3218  ReleaseSysCache(tuple);
3219  pfree(new_acl);
3220 
3221  /* prevent error when processing duplicate objects */
3223  }
3224 
3225  table_close(relation, RowExclusiveLock);
3226 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:480
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
int errhint(const char *fmt,...)
Definition: elog.c:1156
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:478
#define PointerGetDatum(X)
Definition: postgres.h:600
int errcode(int sqlerrcode)
Definition: elog.c:698
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:734
#define MemSet(start, val, len)
Definition: c.h:1008
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:153
uint32 AclMode
Definition: parsenodes.h:80
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:167
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:6008
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define ereport(elevel,...)
Definition: elog.h:157
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1458
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5018
static Datum values[MAXATTR]
Definition: bootstrap.c:166
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:212
#define lfirst_oid(lc)
Definition: pg_list.h:171
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrantStmt_oids()

static void ExecGrantStmt_oids ( InternalGrant istmt)
static

Definition at line 565 of file aclchk.c.

References elog, ERROR, EventTriggerCollectGrant(), EventTriggerSupportsObjectType(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), OBJECT_DATABASE, OBJECT_DOMAIN, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TYPE, and InternalGrant::objtype.

Referenced by ExecuteGrantStmt(), and RemoveRoleFromObjectACL().

566 {
567  switch (istmt->objtype)
568  {
569  case OBJECT_TABLE:
570  case OBJECT_SEQUENCE:
571  ExecGrant_Relation(istmt);
572  break;
573  case OBJECT_DATABASE:
574  ExecGrant_Database(istmt);
575  break;
576  case OBJECT_DOMAIN:
577  case OBJECT_TYPE:
578  ExecGrant_Type(istmt);
579  break;
580  case OBJECT_FDW:
581  ExecGrant_Fdw(istmt);
582  break;
585  break;
586  case OBJECT_FUNCTION:
587  case OBJECT_PROCEDURE:
588  case OBJECT_ROUTINE:
589  ExecGrant_Function(istmt);
590  break;
591  case OBJECT_LANGUAGE:
592  ExecGrant_Language(istmt);
593  break;
594  case OBJECT_LARGEOBJECT:
595  ExecGrant_Largeobject(istmt);
596  break;
597  case OBJECT_SCHEMA:
598  ExecGrant_Namespace(istmt);
599  break;
600  case OBJECT_TABLESPACE:
601  ExecGrant_Tablespace(istmt);
602  break;
603  default:
604  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
605  (int) istmt->objtype);
606  }
607 
608  /*
609  * Pass the info to event triggers about the just-executed GRANT. Note
610  * that we prefer to do it after actually executing it, because that gives
611  * the functions a chance to adjust the istmt with privileges actually
612  * granted.
613  */
616 }
static void ExecGrant_Language(InternalGrant *grantStmt)
Definition: aclchk.c:2577
static void ExecGrant_Function(InternalGrant *grantStmt)
Definition: aclchk.c:2454
static void ExecGrant_Tablespace(InternalGrant *grantStmt)
Definition: aclchk.c:2972
static void ExecGrant_Namespace(InternalGrant *grantStmt)
Definition: aclchk.c:2848
static void ExecGrant_Type(InternalGrant *grantStmt)
Definition: aclchk.c:3092
static void ExecGrant_Database(InternalGrant *grantStmt)
Definition: aclchk.c:2082
#define ERROR
Definition: elog.h:46
static void ExecGrant_Fdw(InternalGrant *grantStmt)
Definition: aclchk.c:2202
static void ExecGrant_Largeobject(InternalGrant *grantStmt)
Definition: aclchk.c:2708
static void ExecGrant_Relation(InternalGrant *grantStmt)
Definition: aclchk.c:1750
bool EventTriggerSupportsObjectType(ObjectType obtype)
ObjectType objtype
#define elog(elevel,...)
Definition: elog.h:232
void EventTriggerCollectGrant(InternalGrant *istmt)
static void ExecGrant_ForeignServer(InternalGrant *grantStmt)
Definition: aclchk.c:2329

◆ ExecuteGrantStmt()

void ExecuteGrantStmt ( GrantStmt stmt)

Definition at line 360 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_RELATION, ACL_ALL_RIGHTS_SCHEMA, ACL_ALL_RIGHTS_SEQUENCE, ACL_ALL_RIGHTS_TABLESPACE, ACL_ALL_RIGHTS_TYPE, ACL_ID_PUBLIC, ACL_NO_RIGHTS, 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, GetUserId(), InternalGrant::grant_option, GrantStmt::grant_option, InternalGrant::grantees, GrantStmt::grantees, GrantStmt::grantor, InternalGrant::is_grant, GrantStmt::is_grant, lappend(), lappend_oid(), lfirst, NIL, OBJECT_DATABASE, OBJECT_DOMAIN, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TYPE, 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().

361 {
362  InternalGrant istmt;
363  ListCell *cell;
364  const char *errormsg;
365  AclMode all_privileges;
366 
367  if (stmt->grantor)
368  {
369  Oid grantor;
370 
371  grantor = get_rolespec_oid(stmt->grantor, false);
372 
373  /*
374  * Currently, this clause is only for SQL compatibility, not very
375  * interesting otherwise.
376  */
377  if (grantor != GetUserId())
378  ereport(ERROR,
379  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
380  errmsg("grantor must be current user")));
381  }
382 
383  /*
384  * Turn the regular GrantStmt into the InternalGrant form.
385  */
386  istmt.is_grant = stmt->is_grant;
387  istmt.objtype = stmt->objtype;
388 
389  /* Collect the OIDs of the target objects */
390  switch (stmt->targtype)
391  {
392  case ACL_TARGET_OBJECT:
393  istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects);
394  break;
396  istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
397  break;
398  /* ACL_TARGET_DEFAULTS should not be seen here */
399  default:
400  elog(ERROR, "unrecognized GrantStmt.targtype: %d",
401  (int) stmt->targtype);
402  }
403 
404  /* all_privs to be filled below */
405  /* privileges to be filled below */
406  istmt.col_privs = NIL; /* may get filled below */
407  istmt.grantees = NIL; /* filled below */
408  istmt.grant_option = stmt->grant_option;
409  istmt.behavior = stmt->behavior;
410 
411  /*
412  * Convert the RoleSpec list into an Oid list. Note that at this point we
413  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
414  * there shouldn't be any additional work needed to support this case.
415  */
416  foreach(cell, stmt->grantees)
417  {
418  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
419  Oid grantee_uid;
420 
421  switch (grantee->roletype)
422  {
423  case ROLESPEC_PUBLIC:
424  grantee_uid = ACL_ID_PUBLIC;
425  break;
426  default:
427  grantee_uid = get_rolespec_oid(grantee, false);
428  break;
429  }
430  istmt.grantees = lappend_oid(istmt.grantees, grantee_uid);
431  }
432 
433  /*
434  * Convert stmt->privileges, a list of AccessPriv nodes, into an AclMode
435  * bitmask. Note: objtype can't be OBJECT_COLUMN.
436  */
437  switch (stmt->objtype)
438  {
439  case OBJECT_TABLE:
440 
441  /*
442  * Because this might be a sequence, we test both relation and
443  * sequence bits, and later do a more limited test when we know
444  * the object type.
445  */
447  errormsg = gettext_noop("invalid privilege type %s for relation");
448  break;
449  case OBJECT_SEQUENCE:
450  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
451  errormsg = gettext_noop("invalid privilege type %s for sequence");
452  break;
453  case OBJECT_DATABASE:
454  all_privileges = ACL_ALL_RIGHTS_DATABASE;
455  errormsg = gettext_noop("invalid privilege type %s for database");
456  break;
457  case OBJECT_DOMAIN:
458  all_privileges = ACL_ALL_RIGHTS_TYPE;
459  errormsg = gettext_noop("invalid privilege type %s for domain");
460  break;
461  case OBJECT_FUNCTION:
462  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
463  errormsg = gettext_noop("invalid privilege type %s for function");
464  break;
465  case OBJECT_LANGUAGE:
466  all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
467  errormsg = gettext_noop("invalid privilege type %s for language");
468  break;
469  case OBJECT_LARGEOBJECT:
470  all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
471  errormsg = gettext_noop("invalid privilege type %s for large object");
472  break;
473  case OBJECT_SCHEMA:
474  all_privileges = ACL_ALL_RIGHTS_SCHEMA;
475  errormsg = gettext_noop("invalid privilege type %s for schema");
476  break;
477  case OBJECT_PROCEDURE:
478  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
479  errormsg = gettext_noop("invalid privilege type %s for procedure");
480  break;
481  case OBJECT_ROUTINE:
482  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
483  errormsg = gettext_noop("invalid privilege type %s for routine");
484  break;
485  case OBJECT_TABLESPACE:
486  all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
487  errormsg = gettext_noop("invalid privilege type %s for tablespace");
488  break;
489  case OBJECT_TYPE:
490  all_privileges = ACL_ALL_RIGHTS_TYPE;
491  errormsg = gettext_noop("invalid privilege type %s for type");
492  break;
493  case 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 != OBJECT_TABLE)
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:65
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:162
Oid GetUserId(void)
Definition: miscinit.c:478
static AclMode string_to_privilege(const char *privname)
Definition: aclchk.c:3230
AclMode privileges
bool grant_option
Definition: parsenodes.h:2022
#define gettext_noop(x)
Definition: c.h:1197
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:166
List * cols
Definition: parsenodes.h:2064
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:163
uint32 AclMode
Definition: parsenodes.h:80
#define ERROR
Definition: elog.h:46
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
#define ACL_ALL_RIGHTS_SCHEMA
Definition: acl.h:165
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:167
List * lappend(List *list, void *datum)
Definition: list.c:336
bool is_grant
Definition: parsenodes.h:2014
static void ExecGrantStmt_oids(InternalGrant *istmt)
Definition: aclchk.c:565
static List * objectNamesToOids(ObjectType objtype, List *objnames)
Definition: aclchk.c:629
RoleSpecType roletype
Definition: parsenodes.h:339
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5128
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:158
List * privileges
Definition: parsenodes.h:2019
static List * objectsInSchemaToOids(ObjectType objtype, List *nspnames)
Definition: aclchk.c:778
#define ereport(elevel,...)
Definition: elog.h:157
RoleSpec * grantor
Definition: parsenodes.h:2023
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:164
DropBehavior behavior
DropBehavior behavior
Definition: parsenodes.h:2024
#define lfirst(lc)
Definition: pg_list.h:169
List * objects
Definition: parsenodes.h:2017
ObjectType objtype
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:159
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:161
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define ACL_ALL_RIGHTS_RELATION
Definition: acl.h:157
ObjectType objtype
Definition: parsenodes.h:2016
#define ACL_ID_PUBLIC
Definition: acl.h:46
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:160
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:3267
List * grantees
Definition: parsenodes.h:2021
GrantTargetType targtype
Definition: parsenodes.h:2015
char * priv_name
Definition: parsenodes.h:2063

◆ expand_all_col_privileges()

static void expand_all_col_privileges ( Oid  table_oid,
Form_pg_class  classForm,
AclMode  this_privileges,
AclMode col_privileges,
int  num_col_privileges 
)
static

Definition at line 1556 of file aclchk.c.

References Assert, ATTNUM, elog, ERROR, FirstLowInvalidHeapAttributeNumber, GETSTRUCT, HeapTupleIsValid, Int16GetDatum, InvalidAttrNumber, ObjectIdGetDatum, ReleaseSysCache(), and SearchSysCache2().

Referenced by ExecGrant_Relation().

1560 {
1561  AttrNumber curr_att;
1562 
1563  Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
1564  for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
1565  curr_att <= classForm->relnatts;
1566  curr_att++)
1567  {
1568  HeapTuple attTuple;
1569  bool isdropped;
1570 
1571  if (curr_att == InvalidAttrNumber)
1572  continue;
1573 
1574  /* Views don't have any system columns at all */
1575  if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
1576  continue;
1577 
1578  attTuple = SearchSysCache2(ATTNUM,
1579  ObjectIdGetDatum(table_oid),
1580  Int16GetDatum(curr_att));
1581  if (!HeapTupleIsValid(attTuple))
1582  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1583  curr_att, table_oid);
1584 
1585  isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
1586 
1587  ReleaseSysCache(attTuple);
1588 
1589  /* ignore dropped columns */
1590  if (isdropped)
1591  continue;
1592 
1593  col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
1594  }
1595 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define Int16GetDatum(X)
Definition: postgres.h:495
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1138
#define InvalidAttrNumber
Definition: attnum.h:23
#define elog(elevel,...)
Definition: elog.h:232
int16 AttrNumber
Definition: attnum.h:21

◆ expand_col_privileges()

static void expand_col_privileges ( List colnames,
Oid  table_oid,
AclMode  this_privileges,
AclMode col_privileges,
int  num_col_privileges 
)
static

Definition at line 1523 of file aclchk.c.

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

Referenced by ExecGrant_Relation().

1527 {
1528  ListCell *cell;
1529 
1530  foreach(cell, colnames)
1531  {
1532  char *colname = strVal(lfirst(cell));
1534 
1535  attnum = get_attnum(table_oid, colname);
1536  if (attnum == InvalidAttrNumber)
1537  ereport(ERROR,
1538  (errcode(ERRCODE_UNDEFINED_COLUMN),
1539  errmsg("column \"%s\" of relation \"%s\" does not exist",
1540  colname, get_rel_name(table_oid))));
1542  if (attnum <= 0 || attnum >= num_col_privileges)
1543  elog(ERROR, "column number out of range"); /* safety check */
1544  col_privileges[attnum] |= this_privileges;
1545  }
1546 }
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:698
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
#define ERROR
Definition: elog.h:46
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:856
int16 attnum
Definition: pg_attribute.h:83
#define ereport(elevel,...)
Definition: elog.h:157
#define lfirst(lc)
Definition: pg_list.h:169
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1899
int16 AttrNumber
Definition: attnum.h:21

◆ get_default_acl_internal()

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

Definition at line 5486 of file aclchk.c.

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

Referenced by get_user_default_acl().

5487 {
5488  Acl *result = NULL;
5489  HeapTuple tuple;
5490 
5492  ObjectIdGetDatum(roleId),
5493  ObjectIdGetDatum(nsp_oid),
5494  CharGetDatum(objtype));
5495 
5496  if (HeapTupleIsValid(tuple))
5497  {
5498  Datum aclDatum;
5499  bool isNull;
5500 
5501  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
5502  Anum_pg_default_acl_defaclacl,
5503  &isNull);
5504  if (!isNull)
5505  result = DatumGetAclPCopy(aclDatum);
5506  ReleaseSysCache(tuple);
5507  }
5508 
5509  return result;
5510 }
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1149
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define CharGetDatum(X)
Definition: postgres.h:460
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ get_user_default_acl()

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

Definition at line 5521 of file aclchk.c.

References acldefault(), aclequal(), aclitemsort(), aclmerge(), get_default_acl_internal(), InvalidOid, IsBootstrapProcessingMode, OBJECT_FUNCTION, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, and OBJECT_TYPE.

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

5522 {
5523  Acl *result;
5524  Acl *glob_acl;
5525  Acl *schema_acl;
5526  Acl *def_acl;
5527  char defaclobjtype;
5528 
5529  /*
5530  * Use NULL during bootstrap, since pg_default_acl probably isn't there
5531  * yet.
5532  */
5534  return NULL;
5535 
5536  /* Check if object type is supported in pg_default_acl */
5537  switch (objtype)
5538  {
5539  case OBJECT_TABLE:
5540  defaclobjtype = DEFACLOBJ_RELATION;
5541  break;
5542 
5543  case OBJECT_SEQUENCE:
5544  defaclobjtype = DEFACLOBJ_SEQUENCE;
5545  break;
5546 
5547  case OBJECT_FUNCTION:
5548  defaclobjtype = DEFACLOBJ_FUNCTION;
5549  break;
5550 
5551  case OBJECT_TYPE:
5552  defaclobjtype = DEFACLOBJ_TYPE;
5553  break;
5554 
5555  case OBJECT_SCHEMA:
5556  defaclobjtype = DEFACLOBJ_NAMESPACE;
5557  break;
5558 
5559  default:
5560  return NULL;
5561  }
5562 
5563  /* Look up the relevant pg_default_acl entries */
5564  glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
5565  schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
5566 
5567  /* Quick out if neither entry exists */
5568  if (glob_acl == NULL && schema_acl == NULL)
5569  return NULL;
5570 
5571  /* We need to know the hard-wired default value, too */
5572  def_acl = acldefault(objtype, ownerId);
5573 
5574  /* If there's no global entry, substitute the hard-wired default */
5575  if (glob_acl == NULL)
5576  glob_acl = def_acl;
5577 
5578  /* Merge in any per-schema privileges */
5579  result = aclmerge(glob_acl, schema_acl, ownerId);
5580 
5581  /*
5582  * For efficiency, we want to return NULL if the result equals default.
5583  * This requires sorting both arrays to get an accurate comparison.
5584  */
5585  aclitemsort(result);
5586  aclitemsort(def_acl);
5587  if (aclequal(result, def_acl))
5588  result = NULL;
5589 
5590  return result;
5591 }
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:734
static Acl * get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
Definition: aclchk.c:5486
bool aclequal(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:495
#define InvalidOid
Definition: postgres_ext.h:36
Acl * aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
Definition: acl.c:437
void aclitemsort(Acl *acl)
Definition: acl.c:481
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406

◆ getRelationsInNamespace()

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

Definition at line 867 of file aclchk.c.

References AccessShareLock, BTEqualStrategyNumber, CharGetDatum, ForwardScanDirection, GETSTRUCT, heap_getnext(), sort-test::key, lappend_oid(), NIL, ObjectIdGetDatum, ScanKeyInit(), table_beginscan_catalog(), table_close(), table_endscan(), and table_open().

Referenced by objectsInSchemaToOids().

868 {
869  List *relations = NIL;
870  ScanKeyData key[2];
871  Relation rel;
872  TableScanDesc scan;
873  HeapTuple tuple;
874 
875  ScanKeyInit(&key[0],
876  Anum_pg_class_relnamespace,
877  BTEqualStrategyNumber, F_OIDEQ,
878  ObjectIdGetDatum(namespaceId));
879  ScanKeyInit(&key[1],
880  Anum_pg_class_relkind,
881  BTEqualStrategyNumber, F_CHAREQ,
882  CharGetDatum(relkind));
883 
884  rel = table_open(RelationRelationId, AccessShareLock);
885  scan = table_beginscan_catalog(rel, 2, key);
886 
887  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
888  {
889  Oid oid = ((Form_pg_class) GETSTRUCT(tuple))->oid;
890 
891  relations = lappend_oid(relations, oid);
892  }
893 
894  table_endscan(scan);
896 
897  return relations;
898 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
#define AccessShareLock
Definition: lockdefs.h:36
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1340
#define CharGetDatum(X)
Definition: postgres.h:460
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:991
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ has_bypassrls_privilege()

bool has_bypassrls_privilege ( Oid  roleid)

Definition at line 5462 of file aclchk.c.

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

Referenced by check_enable_rls(), and RI_Initial_Check().

5463 {
5464  bool result = false;
5465  HeapTuple utup;
5466 
5467  /* Superusers bypass all permission checking. */
5468  if (superuser_arg(roleid))
5469  return true;
5470 
5471  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5472  if (HeapTupleIsValid(utup))
5473  {
5474  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
5475  ReleaseSysCache(utup);
5476  }
5477  return result;
5478 }
bool rolbypassrls
Definition: pg_authid.h:41
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78

◆ has_createrole_privilege()

bool has_createrole_privilege ( Oid  roleid)

Definition at line 5443 of file aclchk.c.

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

Referenced by check_object_ownership(), and have_createrole_privilege().

5444 {
5445  bool result = false;
5446  HeapTuple utup;
5447 
5448  /* Superusers bypass all permission checking. */
5449  if (superuser_arg(roleid))
5450  return true;
5451 
5452  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5453  if (HeapTupleIsValid(utup))
5454  {
5455  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
5456  ReleaseSysCache(utup);
5457  }
5458  return result;
5459 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
bool rolcreaterole
Definition: pg_authid.h:37
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78

◆ merge_acl_with_grant()

static Acl* merge_acl_with_grant ( Acl old_acl,
bool  is_grant,
bool  grant_option,
DropBehavior  behavior,
List grantees,
AclMode  privileges,
Oid  grantorId,
Oid  ownerId 
)
static

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

157 {
158  unsigned modechg;
159  ListCell *j;
160  Acl *new_acl;
161 
162  modechg = is_grant ? ACL_MODECHG_ADD : ACL_MODECHG_DEL;
163 
164  new_acl = old_acl;
165 
166  foreach(j, grantees)
167  {
168  AclItem aclitem;
169  Acl *newer_acl;
170 
171  aclitem.ai_grantee = lfirst_oid(j);
172 
173  /*
174  * Grant options can only be granted to individual roles, not PUBLIC.
175  * The reason is that if a user would re-grant a privilege that he
176  * held through PUBLIC, and later the user is removed, the situation
177  * is impossible to clean up.
178  */
179  if (is_grant && grant_option && aclitem.ai_grantee == ACL_ID_PUBLIC)
180  ereport(ERROR,
181  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
182  errmsg("grant options can only be granted to roles")));
183 
184  aclitem.ai_grantor = grantorId;
185 
186  /*
187  * The asymmetry in the conditions here comes from the spec. In
188  * GRANT, the grant_option flag signals WITH GRANT OPTION, which means
189  * to grant both the basic privilege and its grant option. But in
190  * REVOKE, plain revoke revokes both the basic privilege and its grant
191  * option, while REVOKE GRANT OPTION revokes only the option.
192  */
194  (is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
195  (!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS);
196 
197  newer_acl = aclupdate(new_acl, &aclitem, modechg, ownerId, behavior);
198 
199  /* avoid memory leak when there are many grantees */
200  pfree(new_acl);
201  new_acl = newer_acl;
202  }
203 
204  return new_acl;
205 }
Oid ai_grantee
Definition: acl.h:56
#define ACL_MODECHG_DEL
Definition: acl.h:130
int errcode(int sqlerrcode)
Definition: elog.c:698
Oid ai_grantor
Definition: acl.h:57
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
#define ACL_NO_RIGHTS
Definition: parsenodes.h:96
#define ACL_MODECHG_ADD
Definition: acl.h:129
#define ereport(elevel,...)
Definition: elog.h:157
Definition: acl.h:54
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define ACL_ID_PUBLIC
Definition: acl.h:46
Acl * aclupdate(const Acl *old_acl, const AclItem *mod_aip, int modechg, Oid ownerId, DropBehavior behavior)
Definition: acl.c:916
#define ACLITEM_SET_PRIVS_GOPTIONS(item, privs, goptions)
Definition: acl.h:82
#define lfirst_oid(lc)
Definition: pg_list.h:171

◆ objectNamesToOids()

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

Definition at line 629 of file aclchk.c.

References Assert, dbname, elog, ereport, errcode(), errmsg(), ERROR, get_database_oid(), get_foreign_data_wrapper_oid(), get_foreign_server_oid(), get_language_oid(), get_namespace_oid(), get_tablespace_oid(), lappend_oid(), LargeObjectExists(), lfirst, LookupFuncWithArgs(), makeTypeNameFromNameList(), NIL, NoLock, OBJECT_DATABASE, OBJECT_DOMAIN, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TYPE, oidparse(), RangeVarGetRelid, strVal, typenameTypeId(), and typname.

Referenced by ExecuteGrantStmt().

630 {
631  List *objects = NIL;
632  ListCell *cell;
633 
634  Assert(objnames != NIL);
635 
636  switch (objtype)
637  {
638  case OBJECT_TABLE:
639  case OBJECT_SEQUENCE:
640  foreach(cell, objnames)
641  {
642  RangeVar *relvar = (RangeVar *) lfirst(cell);
643  Oid relOid;
644 
645  relOid = RangeVarGetRelid(relvar, NoLock, false);
646  objects = lappend_oid(objects, relOid);
647  }
648  break;
649  case OBJECT_DATABASE:
650  foreach(cell, objnames)
651  {
652  char *dbname = strVal(lfirst(cell));
653  Oid dbid;
654 
655  dbid = get_database_oid(dbname, false);
656  objects = lappend_oid(objects, dbid);
657  }
658  break;
659  case OBJECT_DOMAIN:
660  case OBJECT_TYPE:
661  foreach(cell, objnames)
662  {
663  List *typname = (List *) lfirst(cell);
664  Oid oid;
665 
666  oid = typenameTypeId(NULL, makeTypeNameFromNameList(typname));
667  objects = lappend_oid(objects, oid);
668  }
669  break;
670  case OBJECT_FUNCTION:
671  foreach(cell, objnames)
672  {
673  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
674  Oid funcid;
675 
676  funcid = LookupFuncWithArgs(OBJECT_FUNCTION, func, false);
677  objects = lappend_oid(objects, funcid);
678  }
679  break;
680  case OBJECT_LANGUAGE:
681  foreach(cell, objnames)
682  {
683  char *langname = strVal(lfirst(cell));
684  Oid oid;
685 
686  oid = get_language_oid(langname, false);
687  objects = lappend_oid(objects, oid);
688  }
689  break;
690  case OBJECT_LARGEOBJECT:
691  foreach(cell, objnames)
692  {
693  Oid lobjOid = oidparse(lfirst(cell));
694 
695  if (!LargeObjectExists(lobjOid))
696  ereport(ERROR,
697  (errcode(ERRCODE_UNDEFINED_OBJECT),
698  errmsg("large object %u does not exist",
699  lobjOid)));
700 
701  objects = lappend_oid(objects, lobjOid);
702  }
703  break;
704  case OBJECT_SCHEMA:
705  foreach(cell, objnames)
706  {
707  char *nspname = strVal(lfirst(cell));
708  Oid oid;
709 
710  oid = get_namespace_oid(nspname, false);
711  objects = lappend_oid(objects, oid);
712  }
713  break;
714  case OBJECT_PROCEDURE:
715  foreach(cell, objnames)
716  {
717  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
718  Oid procid;
719 
720  procid = LookupFuncWithArgs(OBJECT_PROCEDURE, func, false);
721  objects = lappend_oid(objects, procid);
722  }
723  break;
724  case OBJECT_ROUTINE:
725  foreach(cell, objnames)
726  {
727  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
728  Oid routid;
729 
730  routid = LookupFuncWithArgs(OBJECT_ROUTINE, func, false);
731  objects = lappend_oid(objects, routid);
732  }
733  break;
734  case OBJECT_TABLESPACE:
735  foreach(cell, objnames)
736  {
737  char *spcname = strVal(lfirst(cell));
738  Oid spcoid;
739 
740  spcoid = get_tablespace_oid(spcname, false);
741  objects = lappend_oid(objects, spcoid);
742  }
743  break;
744  case OBJECT_FDW:
745  foreach(cell, objnames)
746  {
747  char *fdwname = strVal(lfirst(cell));
748  Oid fdwid = get_foreign_data_wrapper_oid(fdwname, false);
749 
750  objects = lappend_oid(objects, fdwid);
751  }
752  break;
754  foreach(cell, objnames)
755  {
756  char *srvname = strVal(lfirst(cell));
757  Oid srvid = get_foreign_server_oid(srvname, false);
758 
759  objects = lappend_oid(objects, srvid);
760  }
761  break;
762  default:
763  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
764  (int) objtype);
765  }
766 
767  return objects;
768 }
#define NIL
Definition: pg_list.h:65
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1431
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3088
Oid oidparse(Node *node)
Definition: oid.c:314
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:79
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:228
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition: foreign.c:691
#define ERROR
Definition: elog.h:46
#define NoLock
Definition: lockdefs.h:34
NameData typname
Definition: pg_type.h:41
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2066
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
char * dbname
Definition: streamutil.c:51
bool LargeObjectExists(Oid loid)
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2207
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:456
Definition: pg_list.h:50
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition: foreign.c:714
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291

◆ objectsInSchemaToOids()

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

Definition at line 778 of file aclchk.c.

References AccessShareLock, BTEqualStrategyNumber, CharGetDatum, elog, ERROR, ForwardScanDirection, getRelationsInNamespace(), GETSTRUCT, heap_getnext(), sort-test::key, lappend_oid(), lfirst, list_concat(), LookupExplicitNamespace(), NIL, OBJECT_FUNCTION, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectIdGetDatum, ScanKeyInit(), strVal, table_beginscan_catalog(), table_close(), table_endscan(), and table_open().

Referenced by ExecuteGrantStmt().

779 {
780  List *objects = NIL;
781  ListCell *cell;
782 
783  foreach(cell, nspnames)
784  {
785  char *nspname = strVal(lfirst(cell));
786  Oid namespaceId;
787  List *objs;
788 
789  namespaceId = LookupExplicitNamespace(nspname, false);
790 
791  switch (objtype)
792  {
793  case OBJECT_TABLE:
794  objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
795  objects = list_concat(objects, objs);
796  objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
797  objects = list_concat(objects, objs);
798  objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
799  objects = list_concat(objects, objs);
800  objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
801  objects = list_concat(objects, objs);
802  objs = getRelationsInNamespace(namespaceId, RELKIND_PARTITIONED_TABLE);
803  objects = list_concat(objects, objs);
804  break;
805  case OBJECT_SEQUENCE:
806  objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
807  objects = list_concat(objects, objs);
808  break;
809  case OBJECT_FUNCTION:
810  case OBJECT_PROCEDURE:
811  case OBJECT_ROUTINE:
812  {
813  ScanKeyData key[2];
814  int keycount;
815  Relation rel;
816  TableScanDesc scan;
817  HeapTuple tuple;
818 
819  keycount = 0;
820  ScanKeyInit(&key[keycount++],
821  Anum_pg_proc_pronamespace,
822  BTEqualStrategyNumber, F_OIDEQ,
823  ObjectIdGetDatum(namespaceId));
824 
825  if (objtype == OBJECT_FUNCTION)
826  /* includes aggregates and window functions */
827  ScanKeyInit(&key[keycount++],
828  Anum_pg_proc_prokind,
829  BTEqualStrategyNumber, F_CHARNE,
830  CharGetDatum(PROKIND_PROCEDURE));
831  else if (objtype == OBJECT_PROCEDURE)
832  ScanKeyInit(&key[keycount++],
833  Anum_pg_proc_prokind,
834  BTEqualStrategyNumber, F_CHAREQ,
835  CharGetDatum(PROKIND_PROCEDURE));
836 
837  rel = table_open(ProcedureRelationId, AccessShareLock);
838  scan = table_beginscan_catalog(rel, keycount, key);
839 
840  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
841  {
842  Oid oid = ((Form_pg_proc) GETSTRUCT(tuple))->oid;
843 
844  objects = lappend_oid(objects, oid);
845  }
846 
847  table_endscan(scan);
849  }
850  break;
851  default:
852  /* should not happen */
853  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
854  (int) objtype);
855  }
856  }
857 
858  return objects;
859 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2938
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
#define AccessShareLock
Definition: lockdefs.h:36
#define strVal(v)
Definition: value.h:54
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1340
static List * getRelationsInNamespace(Oid namespaceId, char relkind)
Definition: aclchk.c:867
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
#define lfirst(lc)
Definition: pg_list.h:169
#define CharGetDatum(X)
Definition: postgres.h:460
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:991
#define elog(elevel,...)
Definition: elog.h:232
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ pg_aclmask()

static AclMode pg_aclmask ( ObjectType  objtype,
Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)
static

Definition at line 3633 of file aclchk.c.

References ACL_NO_RIGHTS, elog, ERROR, OBJECT_COLUMN, OBJECT_DATABASE, OBJECT_EVENT_TRIGGER, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_STATISTIC_EXT, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TYPE, 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().

3635 {
3636  switch (objtype)
3637  {
3638  case OBJECT_COLUMN:
3639  return
3640  pg_class_aclmask(table_oid, roleid, mask, how) |
3641  pg_attribute_aclmask(table_oid, attnum, roleid, mask, how);
3642  case OBJECT_TABLE:
3643  case OBJECT_SEQUENCE:
3644  return pg_class_aclmask(table_oid, roleid, mask, how);
3645  case OBJECT_DATABASE:
3646  return pg_database_aclmask(table_oid, roleid, mask, how);
3647  case OBJECT_FUNCTION:
3648  return pg_proc_aclmask(table_oid, roleid, mask, how);
3649  case OBJECT_LANGUAGE:
3650  return pg_language_aclmask(table_oid, roleid, mask, how);
3651  case OBJECT_LARGEOBJECT:
3652  return pg_largeobject_aclmask_snapshot(table_oid, roleid,
3653  mask, how, NULL);
3654  case OBJECT_SCHEMA:
3655  return pg_namespace_aclmask(table_oid, roleid, mask, how);
3656  case OBJECT_STATISTIC_EXT:
3657  elog(ERROR, "grantable rights not supported for statistics objects");
3658  /* not reached, but keep compiler quiet */
3659  return ACL_NO_RIGHTS;
3660  case OBJECT_TABLESPACE:
3661  return pg_tablespace_aclmask(table_oid, roleid, mask, how);
3662  case OBJECT_FDW:
3663  return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
3664  case OBJECT_FOREIGN_SERVER:
3665  return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
3666  case OBJECT_EVENT_TRIGGER:
3667  elog(ERROR, "grantable rights not supported for event triggers");
3668  /* not reached, but keep compiler quiet */
3669  return ACL_NO_RIGHTS;
3670  case OBJECT_TYPE:
3671  return pg_type_aclmask(table_oid, roleid, mask, how);
3672  default:
3673  elog(ERROR, "unrecognized objtype: %d",
3674  (int) objtype);
3675  /* not reached, but keep compiler quiet */
3676  return ACL_NO_RIGHTS;
3677  }
3678 }
AclMode pg_foreign_server_aclmask(Oid srv_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4406
AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3701
AclMode pg_tablespace_aclmask(Oid spc_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4287
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3820
AclMode pg_database_aclmask(Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3951
#define ERROR
Definition: elog.h:46