PostgreSQL Source Code  git master
aclchk.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "access/xact.h"
#include "catalog/binary_upgrade.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_am.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_cast.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_database.h"
#include "catalog/pg_default_acl.h"
#include "catalog/pg_event_trigger.h"
#include "catalog/pg_extension.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_init_privs.h"
#include "catalog/pg_language.h"
#include "catalog/pg_largeobject.h"
#include "catalog/pg_largeobject_metadata.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "catalog/pg_ts_parser.h"
#include "catalog/pg_ts_template.h"
#include "catalog/pg_transform.h"
#include "commands/dbcommands.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
#include "commands/proclang.h"
#include "commands/tablespace.h"
#include "foreign/foreign.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
#include "utils/aclchk_internal.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
Include dependency graph for aclchk.c:

Go to the source code of this file.

Data Structures

struct  InternalDefaultACL
 

Functions

static void ExecGrantStmt_oids (InternalGrant *istmt)
 
static void ExecGrant_Relation (InternalGrant *grantStmt)
 
static void ExecGrant_Database (InternalGrant *grantStmt)
 
static void ExecGrant_Fdw (InternalGrant *grantStmt)
 
static void ExecGrant_ForeignServer (InternalGrant *grantStmt)
 
static void ExecGrant_Function (InternalGrant *grantStmt)
 
static void ExecGrant_Language (InternalGrant *grantStmt)
 
static void ExecGrant_Largeobject (InternalGrant *grantStmt)
 
static void ExecGrant_Namespace (InternalGrant *grantStmt)
 
static void ExecGrant_Tablespace (InternalGrant *grantStmt)
 
static void ExecGrant_Type (InternalGrant *grantStmt)
 
static void SetDefaultACLsInSchemas (InternalDefaultACL *iacls, List *nspnames)
 
static void SetDefaultACL (InternalDefaultACL *iacls)
 
static ListobjectNamesToOids (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)
 
void RemoveDefaultACLById (Oid defaclOid)
 
static void ExecGrant_Attribute (InternalGrant *istmt, Oid relOid, const char *relname, AttrNumber attnum, Oid ownerId, AclMode col_privileges, Relation attRelation, const Acl *old_rel_acl)
 
void aclcheck_error (AclResult aclerr, 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_class_aclmask (Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_database_aclmask (Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_proc_aclmask (Oid proc_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_language_aclmask (Oid lang_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_largeobject_aclmask_snapshot (Oid lobj_oid, Oid roleid, AclMode mask, AclMaskHow how, Snapshot snapshot)
 
AclMode pg_namespace_aclmask (Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_tablespace_aclmask (Oid spc_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_foreign_data_wrapper_aclmask (Oid fdw_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_foreign_server_aclmask (Oid srv_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_type_aclmask (Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclResult pg_attribute_aclcheck (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
 
AclResult pg_attribute_aclcheck_all (Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
 
AclResult pg_class_aclcheck (Oid table_oid, Oid roleid, AclMode mode)
 
AclResult pg_database_aclcheck (Oid db_oid, Oid roleid, AclMode mode)
 
AclResult pg_proc_aclcheck (Oid proc_oid, Oid roleid, AclMode mode)
 
AclResult pg_language_aclcheck (Oid lang_oid, Oid roleid, AclMode mode)
 
AclResult pg_largeobject_aclcheck_snapshot (Oid lobj_oid, Oid roleid, AclMode mode, Snapshot snapshot)
 
AclResult pg_namespace_aclcheck (Oid nsp_oid, Oid roleid, AclMode mode)
 
AclResult pg_tablespace_aclcheck (Oid spc_oid, Oid roleid, AclMode mode)
 
AclResult pg_foreign_data_wrapper_aclcheck (Oid fdw_oid, Oid roleid, AclMode mode)
 
AclResult pg_foreign_server_aclcheck (Oid srv_oid, Oid roleid, AclMode mode)
 
AclResult pg_type_aclcheck (Oid type_oid, Oid roleid, AclMode mode)
 
bool pg_class_ownercheck (Oid class_oid, Oid roleid)
 
bool pg_type_ownercheck (Oid type_oid, Oid roleid)
 
bool pg_oper_ownercheck (Oid oper_oid, Oid roleid)
 
bool pg_proc_ownercheck (Oid proc_oid, Oid roleid)
 
bool pg_language_ownercheck (Oid lan_oid, Oid roleid)
 
bool pg_largeobject_ownercheck (Oid lobj_oid, Oid roleid)
 
bool pg_namespace_ownercheck (Oid nsp_oid, Oid roleid)
 
bool pg_tablespace_ownercheck (Oid spc_oid, Oid roleid)
 
bool pg_opclass_ownercheck (Oid opc_oid, Oid roleid)
 
bool pg_opfamily_ownercheck (Oid opf_oid, Oid roleid)
 
bool pg_ts_dict_ownercheck (Oid dict_oid, Oid roleid)
 
bool pg_ts_config_ownercheck (Oid cfg_oid, Oid roleid)
 
bool pg_foreign_data_wrapper_ownercheck (Oid srv_oid, Oid roleid)
 
bool pg_foreign_server_ownercheck (Oid srv_oid, Oid roleid)
 
bool pg_event_trigger_ownercheck (Oid et_oid, Oid roleid)
 
bool pg_database_ownercheck (Oid db_oid, Oid roleid)
 
bool pg_collation_ownercheck (Oid coll_oid, Oid roleid)
 
bool pg_conversion_ownercheck (Oid conv_oid, Oid roleid)
 
bool pg_extension_ownercheck (Oid ext_oid, Oid roleid)
 
bool pg_publication_ownercheck (Oid pub_oid, Oid roleid)
 
bool pg_subscription_ownercheck (Oid sub_oid, Oid roleid)
 
bool pg_statistics_object_ownercheck (Oid stat_oid, Oid roleid)
 
bool has_createrole_privilege (Oid roleid)
 
bool has_bypassrls_privilege (Oid roleid)
 
static Aclget_default_acl_internal (Oid roleId, Oid nsp_oid, char objtype)
 
Aclget_user_default_acl (ObjectType objtype, Oid ownerId, Oid nsp_oid)
 
void recordExtObjInitPriv (Oid objoid, Oid classoid)
 
void removeExtObjInitPriv (Oid objoid, Oid classoid)
 

Variables

bool binary_upgrade_record_init_privs = false
 

Function Documentation

◆ aclcheck_error()

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

Definition at line 3348 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(), AlterSubscription(), AlterSubscriptionOwner_internal(), AlterTableMoveAll(), AlterTableSpaceOptions(), AlterTSConfiguration(), AlterTSDictionary(), AlterTypeOwner(), ATExecChangeOwner(), ATPrepSetStatistics(), ATPrepSetTableSpace(), ATSimplePermissions(), brin_desummarize_range(), brin_summarize_range(), calculate_database_size(), calculate_tablespace_size(), call_pltcl_start_proc(), check_object_ownership(), check_temp_tablespaces(), checkFkeyPermissions(), CheckFunctionValidatorAccess(), compute_return_type(), create_proc_lang(), CreateConversionCommand(), createdb(), CreateForeignServer(), CreateForeignTable(), CreateFunction(), CreateProceduralLanguage(), CreatePublication(), CreateSchemaCommand(), CreateStatistics(), CreateTransform(), CreateTrigger(), currtid_byrelname(), currtid_byreloid(), DefineAggregate(), DefineCollation(), DefineDomain(), DefineEnum(), DefineIndex(), DefineOpClass(), DefineOperator(), DefineOpFamily(), DefineQueryRewrite(), DefineRange(), DefineRelation(), DefineTSConfiguration(), DefineTSDictionary(), DefineType(), dropdb(), DropSubscription(), DropTableSpace(), EnableDisableRule(), ExecAlterExtensionContentsStmt(), ExecAlterExtensionStmt(), ExecBuildGroupingEqual(), ExecCheckRTPerms(), ExecInitAgg(), ExecInitExprRec(), ExecInitFunc(), ExecInitWindowAgg(), ExecuteCallStmt(), ExecuteDoStmt(), ExecuteTruncateGuts(), findRangeCanonicalFunction(), findRangeSubtypeDiffFunction(), get_connect_string(), get_other_operator(), get_rel_from_relname(), gin_clean_pending_list(), HandleFunctionRequest(), ImportForeignSchema(), init_sexpr(), initialize_peragg(), LockTableRecurse(), 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(), ReindexMultipleTables(), renameatt_check(), RenameDatabase(), RenameSchema(), RenameTableSpace(), restrict_and_check_grant(), transformTableLikeClause(), truncate_check_rel(), TypeCreate(), user_mapping_ddl_aclcheck(), ValidateJoinEstimator(), and ValidateRestrictionEstimator().

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

◆ aclcheck_error_col()

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

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

3631 {
3632  switch (aclerr)
3633  {
3634  case ACLCHECK_OK:
3635  /* no error, so return to caller */
3636  break;
3637  case ACLCHECK_NO_PRIV:
3638  ereport(ERROR,
3639  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3640  errmsg("permission denied for column \"%s\" of relation \"%s\"",
3641  colname, objectname)));
3642  break;
3643  case ACLCHECK_NOT_OWNER:
3644  /* relation msg is OK since columns don't have separate owners */
3645  aclcheck_error(aclerr, objtype, objectname);
3646  break;
3647  default:
3648  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3649  break;
3650  }
3651 }
int errcode(int sqlerrcode)
Definition: elog.c:575
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3348
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219

◆ aclcheck_error_type()

void aclcheck_error_type ( AclResult  aclerr,
Oid  typeOid 
)

Definition at line 3659 of file aclchk.c.

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

Referenced by AggregateCreate(), AlterTypeNamespace_oid(), AlterTypeOwner(), ATExecAddColumn(), ATPrepAlterColumnType(), BuildDescForRelation(), check_object_ownership(), checkDomainOwner(), checkEnumOwner(), compute_return_type(), CreateCast(), CreateTransform(), DefineDomain(), DefineOpClass(), DefineOperator(), DefineRelation(), interpret_function_parameter_list(), and RenameType().

3660 {
3661  Oid element_type = get_element_type(typeOid);
3662 
3663  aclcheck_error(aclerr, OBJECT_TYPE, format_type_be(element_type ? element_type : typeOid));
3664 }
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2502
char * format_type_be(Oid type_oid)
Definition: format_type.c:328
unsigned int Oid
Definition: postgres_ext.h:31
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3348

◆ ExecAlterDefaultPrivilegesStmt()

void ExecAlterDefaultPrivilegesStmt ( ParseState pstate,
AlterDefaultPrivilegesStmt stmt 
)

Definition at line 909 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, get_rolespec_oid(), gettext_noop, GetUserId(), InternalDefaultACL::grant_option, GrantStmt::grant_option, InternalDefaultACL::grantees, GrantStmt::grantees, InternalDefaultACL::is_grant, GrantStmt::is_grant, lappend_oid(), lfirst, DefElem::location, NIL, OBJECT_FUNCTION, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TYPE, InternalDefaultACL::objtype, GrantStmt::objtype, AlterDefaultPrivilegesStmt::options, parser_errposition(), AccessPriv::priv_name, privilege_to_string(), InternalDefaultACL::privileges, GrantStmt::privileges, InternalDefaultACL::roleid, ROLESPEC_PUBLIC, RoleSpec::roletype, SetDefaultACLsInSchemas(), and string_to_privilege().

Referenced by ProcessUtilitySlow().

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

◆ ExecGrant_Attribute()

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

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

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

◆ ExecGrant_Database()

static void ExecGrant_Database ( InternalGrant grantStmt)
static

Definition at line 2122 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_close, heap_getattr, heap_modify_tuple(), heap_open(), HeapTupleGetOid, 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, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Fdw()

static void ExecGrant_Fdw ( InternalGrant grantStmt)
static

Definition at line 2242 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_close, heap_modify_tuple(), heap_open(), HeapTupleGetOid, 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, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_ForeignServer()

static void ExecGrant_ForeignServer ( InternalGrant grantStmt)
static

Definition at line 2369 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_close, heap_modify_tuple(), heap_open(), HeapTupleGetOid, 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, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Function()

static void ExecGrant_Function ( InternalGrant grantStmt)
static

Definition at line 2494 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_close, heap_modify_tuple(), heap_open(), 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, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Language()

static void ExecGrant_Language ( InternalGrant grantStmt)
static

Definition at line 2617 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_close, heap_modify_tuple(), heap_open(), HeapTupleGetOid, 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, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Largeobject()

static void ExecGrant_Largeobject ( InternalGrant grantStmt)
static

Definition at line 2748 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_close, heap_getattr, heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InternalGrant::is_grant, LargeObjectMetadataOidIndexId, lfirst_oid, MemSet, merge_acl_with_grant(), NAMEDATALEN, OBJECT_LARGEOBJECT, ObjectIdAttributeNumber, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, restrict_and_check_grant(), RowExclusiveLock, ScanKeyInit(), select_best_grantor(), snprintf(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Namespace()

static void ExecGrant_Namespace ( InternalGrant grantStmt)
static

Definition at line 2888 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_close, heap_modify_tuple(), heap_open(), HeapTupleGetOid, 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, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Relation()

static void ExecGrant_Relation ( InternalGrant grantStmt)
static

Definition at line 1790 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_close, heap_modify_tuple(), heap_open(), 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, updateAclDependencies(), values, and WARNING.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Tablespace()

static void ExecGrant_Tablespace ( InternalGrant grantStmt)
static

Definition at line 3012 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_close, heap_getattr, heap_modify_tuple(), heap_open(), 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, TABLESPACEOID, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Type()

static void ExecGrant_Type ( InternalGrant grantStmt)
static

Definition at line 3132 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_close, heap_getattr, heap_modify_tuple(), heap_open(), 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, TYPEOID, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrantStmt_oids()

static void ExecGrantStmt_oids ( InternalGrant istmt)
static

Definition at line 573 of file aclchk.c.

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

574 {
575  switch (istmt->objtype)
576  {
577  case OBJECT_TABLE:
578  case OBJECT_SEQUENCE:
579  ExecGrant_Relation(istmt);
580  break;
581  case OBJECT_DATABASE:
582  ExecGrant_Database(istmt);
583  break;
584  case OBJECT_DOMAIN:
585  case OBJECT_TYPE:
586  ExecGrant_Type(istmt);
587  break;
588  case OBJECT_FDW:
589  ExecGrant_Fdw(istmt);
590  break;
593  break;
594  case OBJECT_FUNCTION:
595  case OBJECT_PROCEDURE:
596  case OBJECT_ROUTINE:
597  ExecGrant_Function(istmt);
598  break;
599  case OBJECT_LANGUAGE:
600  ExecGrant_Language(istmt);
601  break;
602  case OBJECT_LARGEOBJECT:
603  ExecGrant_Largeobject(istmt);
604  break;
605  case OBJECT_SCHEMA:
606  ExecGrant_Namespace(istmt);
607  break;
608  case OBJECT_TABLESPACE:
609  ExecGrant_Tablespace(istmt);
610  break;
611  default:
612  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
613  (int) istmt->objtype);
614  }
615 
616  /*
617  * Pass the info to event triggers about the just-executed GRANT. Note
618  * that we prefer to do it after actually executing it, because that gives
619  * the functions a chance to adjust the istmt with privileges actually
620  * granted.
621  */
624 }
static void ExecGrant_Language(InternalGrant *grantStmt)
Definition: aclchk.c:2617
static void ExecGrant_Function(InternalGrant *grantStmt)
Definition: aclchk.c:2494
static void ExecGrant_Tablespace(InternalGrant *grantStmt)
Definition: aclchk.c:3012
static void ExecGrant_Namespace(InternalGrant *grantStmt)
Definition: aclchk.c:2888
static void ExecGrant_Type(InternalGrant *grantStmt)
Definition: aclchk.c:3132
static void ExecGrant_Database(InternalGrant *grantStmt)
Definition: aclchk.c:2122
#define ERROR
Definition: elog.h:43
static void ExecGrant_Fdw(InternalGrant *grantStmt)
Definition: aclchk.c:2242
static void ExecGrant_Largeobject(InternalGrant *grantStmt)
Definition: aclchk.c:2748
static void ExecGrant_Relation(InternalGrant *grantStmt)
Definition: aclchk.c:1790
bool EventTriggerSupportsObjectType(ObjectType obtype)
ObjectType objtype
void EventTriggerCollectGrant(InternalGrant *istmt)
#define elog
Definition: elog.h:219
static void ExecGrant_ForeignServer(InternalGrant *grantStmt)
Definition: aclchk.c:2369

◆ ExecuteGrantStmt()

void ExecuteGrantStmt ( GrantStmt stmt)

Definition at line 385 of file aclchk.c.

References ACL_ALL_RIGHTS_DATABASE, ACL_ALL_RIGHTS_FDW, ACL_ALL_RIGHTS_FOREIGN_SERVER, ACL_ALL_RIGHTS_FUNCTION, ACL_ALL_RIGHTS_LANGUAGE, ACL_ALL_RIGHTS_LARGEOBJECT, ACL_ALL_RIGHTS_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, InternalGrant::grant_option, GrantStmt::grant_option, InternalGrant::grantees, GrantStmt::grantees, 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().

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

◆ expand_all_col_privileges()

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

Definition at line 1592 of file aclchk.c.

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

Referenced by ExecGrant_Relation().

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

◆ expand_col_privileges()

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

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

1563 {
1564  ListCell *cell;
1565 
1566  foreach(cell, colnames)
1567  {
1568  char *colname = strVal(lfirst(cell));
1570 
1571  attnum = get_attnum(table_oid, colname);
1572  if (attnum == InvalidAttrNumber)
1573  ereport(ERROR,
1574  (errcode(ERRCODE_UNDEFINED_COLUMN),
1575  errmsg("column \"%s\" of relation \"%s\" does not exist",
1576  colname, get_rel_name(table_oid))));
1578  if (attnum <= 0 || attnum >= num_col_privileges)
1579  elog(ERROR, "column number out of range"); /* safety check */
1580  col_privileges[attnum] |= this_privileges;
1581  }
1582 }
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
#define ERROR
Definition: elog.h:43
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:806
#define ereport(elevel, rest)
Definition: elog.h:122
int16 attnum
Definition: pg_attribute.h:79
#define lfirst(lc)
Definition: pg_list.h:106
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1730
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 5416 of file aclchk.c.

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

Referenced by get_user_default_acl().

5417 {
5418  Acl *result = NULL;
5419  HeapTuple tuple;
5420 
5422  ObjectIdGetDatum(roleId),
5423  ObjectIdGetDatum(nsp_oid),
5424  CharGetDatum(objtype));
5425 
5426  if (HeapTupleIsValid(tuple))
5427  {
5428  Datum aclDatum;
5429  bool isNull;
5430 
5431  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
5432  Anum_pg_default_acl_defaclacl,
5433  &isNull);
5434  if (!isNull)
5435  result = DatumGetAclPCopy(aclDatum);
5436  ReleaseSysCache(tuple);
5437  }
5438 
5439  return result;
5440 }
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1134
uintptr_t Datum
Definition: postgres.h:365
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define CharGetDatum(X)
Definition: postgres.h:399
#define DatumGetAclPCopy(X)
Definition: acl.h:122

◆ get_user_default_acl()

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

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

5449 {
5450  Acl *result;
5451  Acl *glob_acl;
5452  Acl *schema_acl;
5453  Acl *def_acl;
5454  char defaclobjtype;
5455 
5456  /*
5457  * Use NULL during bootstrap, since pg_default_acl probably isn't there
5458  * yet.
5459  */
5461  return NULL;
5462 
5463  /* Check if object type is supported in pg_default_acl */
5464  switch (objtype)
5465  {
5466  case OBJECT_TABLE:
5467  defaclobjtype = DEFACLOBJ_RELATION;
5468  break;
5469 
5470  case OBJECT_SEQUENCE:
5471  defaclobjtype = DEFACLOBJ_SEQUENCE;
5472  break;
5473 
5474  case OBJECT_FUNCTION:
5475  defaclobjtype = DEFACLOBJ_FUNCTION;
5476  break;
5477 
5478  case OBJECT_TYPE:
5479  defaclobjtype = DEFACLOBJ_TYPE;
5480  break;
5481 
5482  case OBJECT_SCHEMA:
5483  defaclobjtype = DEFACLOBJ_NAMESPACE;
5484  break;
5485 
5486  default:
5487  return NULL;
5488  }
5489 
5490  /* Look up the relevant pg_default_acl entries */
5491  glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
5492  schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
5493 
5494  /* Quick out if neither entry exists */
5495  if (glob_acl == NULL && schema_acl == NULL)
5496  return NULL;
5497 
5498  /* We need to know the hard-wired default value, too */
5499  def_acl = acldefault(objtype, ownerId);
5500 
5501  /* If there's no global entry, substitute the hard-wired default */
5502  if (glob_acl == NULL)
5503  glob_acl = def_acl;
5504 
5505  /* Merge in any per-schema privileges */
5506  result = aclmerge(glob_acl, schema_acl, ownerId);
5507 
5508  /*
5509  * For efficiency, we want to return NULL if the result equals default.
5510  * This requires sorting both arrays to get an accurate comparison.
5511  */
5512  aclitemsort(result);
5513  aclitemsort(def_acl);
5514  if (aclequal(result, def_acl))
5515  result = NULL;
5516 
5517  return result;
5518 }
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:748
static Acl * get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
Definition: aclchk.c:5416
bool aclequal(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:509
#define InvalidOid
Definition: postgres_ext.h:36
Acl * aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
Definition: acl.c:451
void aclitemsort(Acl *acl)
Definition: acl.c:495
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:372

◆ getRelationsInNamespace()

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

Definition at line 873 of file aclchk.c.

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

Referenced by objectsInSchemaToOids().

874 {
875  List *relations = NIL;
876  ScanKeyData key[2];
877  Relation rel;
878  HeapScanDesc scan;
879  HeapTuple tuple;
880 
881  ScanKeyInit(&key[0],
882  Anum_pg_class_relnamespace,
883  BTEqualStrategyNumber, F_OIDEQ,
884  ObjectIdGetDatum(namespaceId));
885  ScanKeyInit(&key[1],
886  Anum_pg_class_relkind,
887  BTEqualStrategyNumber, F_CHAREQ,
889 
890  rel = heap_open(RelationRelationId, AccessShareLock);
891  scan = heap_beginscan_catalog(rel, 2, key);
892 
893  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
894  {
895  relations = lappend_oid(relations, HeapTupleGetOid(tuple));
896  }
897 
898  heap_endscan(scan);
900 
901  return relations;
902 }
#define NIL
Definition: pg_list.h:69
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1572
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
char relkind
Definition: pg_class.h:51
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1412
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1835
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define CharGetDatum(X)
Definition: postgres.h:399
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:712
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ has_bypassrls_privilege()

bool has_bypassrls_privilege ( Oid  roleid)

Definition at line 5392 of file aclchk.c.

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

Referenced by check_enable_rls(), and RI_Initial_Check().

5393 {
5394  bool result = false;
5395  HeapTuple utup;
5396 
5397  /* Superusers bypass all permission checking. */
5398  if (superuser_arg(roleid))
5399  return true;
5400 
5401  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5402  if (HeapTupleIsValid(utup))
5403  {
5404  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
5405  ReleaseSysCache(utup);
5406  }
5407  return result;
5408 }
bool rolbypassrls
Definition: pg_authid.h:40
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:55
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
bool superuser_arg(Oid roleid)
Definition: superuser.c:57
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:78

◆ has_createrole_privilege()

bool has_createrole_privilege ( Oid  roleid)

Definition at line 5373 of file aclchk.c.

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

Referenced by check_object_ownership(), and have_createrole_privilege().

5374 {
5375  bool result = false;
5376  HeapTuple utup;
5377 
5378  /* Superusers bypass all permission checking. */
5379  if (superuser_arg(roleid))
5380  return true;
5381 
5382  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5383  if (HeapTupleIsValid(utup))
5384  {
5385  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
5386  ReleaseSysCache(utup);
5387  }
5388  return result;
5389 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:55
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
bool rolcreaterole
Definition: pg_authid.h:36
bool superuser_arg(Oid roleid)
Definition: superuser.c:57
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h: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 171 of file aclchk.c.

References ACL_ID_PUBLIC, ACL_MODECHG_ADD, ACL_MODECHG_DEL, ACL_NO_RIGHTS, ACLITEM_SET_PRIVS_GOPTIONS, aclupdate(), AclItem::ai_grantee, AclItem::ai_grantor, ereport, errcode(), errmsg(), ERROR, lfirst_oid, and pfree().

Referenced by ExecGrant_Attribute(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), and SetDefaultACL().

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

◆ objectNamesToOids()

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

Definition at line 637 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, and typenameTypeId().

Referenced by ExecuteGrantStmt().

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

◆ objectsInSchemaToOids()

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

Definition at line 786 of file aclchk.c.

References AccessShareLock, BTEqualStrategyNumber, CharGetDatum, elog, ERROR, ForwardScanDirection, getRelationsInNamespace(), heap_beginscan_catalog(), heap_close, heap_endscan(), heap_getnext(), heap_open(), HeapTupleGetOid, lappend_oid(), lfirst, list_concat(), LookupExplicitNamespace(), NIL, OBJECT_FUNCTION, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectIdGetDatum, ScanKeyInit(), and strVal.

Referenced by ExecuteGrantStmt().

787 {
788  List *objects = NIL;
789  ListCell *cell;
790 
791  foreach(cell, nspnames)
792  {
793  char *nspname = strVal(lfirst(cell));
794  Oid namespaceId;
795  List *objs;
796 
797  namespaceId = LookupExplicitNamespace(nspname, false);
798 
799  switch (objtype)
800  {
801  case OBJECT_TABLE:
802  objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
803  objects = list_concat(objects, objs);
804  objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
805  objects = list_concat(objects, objs);
806  objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
807  objects = list_concat(objects, objs);
808  objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
809  objects = list_concat(objects, objs);
810  objs = getRelationsInNamespace(namespaceId, RELKIND_PARTITIONED_TABLE);
811  objects = list_concat(objects, objs);
812  break;
813  case OBJECT_SEQUENCE:
814  objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
815  objects = list_concat(objects, objs);
816  break;
817  case OBJECT_FUNCTION:
818  case OBJECT_PROCEDURE:
819  case OBJECT_ROUTINE:
820  {
821  ScanKeyData key[2];
822  int keycount;
823  Relation rel;
824  HeapScanDesc scan;
825  HeapTuple tuple;
826 
827  keycount = 0;
828  ScanKeyInit(&key[keycount++],
829  Anum_pg_proc_pronamespace,
830  BTEqualStrategyNumber, F_OIDEQ,
831  ObjectIdGetDatum(namespaceId));
832 
833  if (objtype == OBJECT_FUNCTION)
834  /* includes aggregates and window functions */
835  ScanKeyInit(&key[keycount++],
836  Anum_pg_proc_prokind,
837  BTEqualStrategyNumber, F_CHARNE,
838  CharGetDatum(PROKIND_PROCEDURE));
839  else if (objtype == OBJECT_PROCEDURE)
840  ScanKeyInit(&key[keycount++],
841  Anum_pg_proc_prokind,
842  BTEqualStrategyNumber, F_CHAREQ,
843  CharGetDatum(PROKIND_PROCEDURE));
844 
845  rel = heap_open(ProcedureRelationId, AccessShareLock);
846  scan = heap_beginscan_catalog(rel, keycount, key);
847 
848  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
849  {
850  objects = lappend_oid(objects, HeapTupleGetOid(tuple));
851  }
852 
853  heap_endscan(scan);
855  }
856  break;
857  default:
858  /* should not happen */
859  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
860  (int) objtype);
861  }
862  }
863 
864  return objects;
865 }
#define NIL
Definition: pg_list.h:69
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2872
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1572
#define AccessShareLock
Definition: lockdefs.h:36
#define strVal(v)
Definition: value.h:54
List * list_concat(List *list1, List *list2)
Definition: list.c:321
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1412
static List * getRelationsInNamespace(Oid namespaceId, char relkind)
Definition: aclchk.c:873
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1835
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define lfirst(lc)
Definition: pg_list.h:106
#define CharGetDatum(X)
Definition: postgres.h:399
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:712
Definition: pg_list.h:45
#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 3671 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().

3673 {
3674  switch (objtype)
3675  {
3676  case OBJECT_COLUMN:
3677  return
3678  pg_class_aclmask(table_oid, roleid, mask, how) |
3679  pg_attribute_aclmask(table_oid, attnum, roleid, mask, how);
3680  case OBJECT_TABLE:
3681  case OBJECT_SEQUENCE:
3682  return pg_class_aclmask(table_oid, roleid, mask, how);
3683  case OBJECT_DATABASE:
3684  return pg_database_aclmask(table_oid, roleid, mask, how);
3685  case OBJECT_FUNCTION:
3686  return pg_proc_aclmask(table_oid, roleid, mask, how);
3687  case OBJECT_LANGUAGE:
3688  return pg_language_aclmask(table_oid, roleid, mask, how);
3689  case OBJECT_LARGEOBJECT:
3690  return pg_largeobject_aclmask_snapshot(table_oid, roleid,
3691  mask, how, NULL);
3692  case OBJECT_SCHEMA:
3693  return pg_namespace_aclmask(table_oid, roleid, mask, how);
3694  case OBJECT_STATISTIC_EXT:
3695  elog(ERROR, "grantable rights not supported for statistics objects");
3696  /* not reached, but keep compiler quiet */
3697  return ACL_NO_RIGHTS;
3698  case OBJECT_TABLESPACE:
3699  return pg_tablespace_aclmask(table_oid, roleid, mask, how);
3700  case OBJECT_FDW:
3701  return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
3702  case OBJECT_FOREIGN_SERVER:
3703  return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
3704  case OBJECT_EVENT_TRIGGER:
3705  elog(ERROR, "grantable rights not supported for event triggers");
3706  /* not reached, but keep compiler quiet */
3707  return ACL_NO_RIGHTS;
3708  case OBJECT_TYPE:
3709  return pg_type_aclmask(table_oid, roleid, mask, how);
3710  default:
3711  elog(ERROR, "unrecognized objtype: %d",
3712  (int) objtype);
3713  /* not reached, but keep compiler quiet */
3714  return ACL_NO_RIGHTS;
3715  }
3716 }
AclMode pg_foreign_server_aclmask(Oid srv_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4365
AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3739
AclMode pg_tablespace_aclmask(Oid spc_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4246
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3824
AclMode pg_database_aclmask(Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3920
#define ERROR
Definition: elog.h:43
#define ACL_NO_RIGHTS
Definition: parsenodes.h:88
AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4164
int16 attnum
Definition: pg_attribute.h:79
AclMode pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4426
AclMode pg_language_aclmask(Oid lang_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4028
AclMode pg_proc_aclmask(Oid proc_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3974
AclMode pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4303
#define elog
Definition: elog.h:219
AclMode pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid, AclMode mask, AclMaskHow how, Snapshot snapshot)
Definition: aclchk.c:4091