PostgreSQL Source Code  git master
aclchk.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "access/tableam.h"
#include "access/xact.h"
#include "catalog/binary_upgrade.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_am.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_cast.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_database.h"
#include "catalog/pg_default_acl.h"
#include "catalog/pg_event_trigger.h"
#include "catalog/pg_extension.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_init_privs.h"
#include "catalog/pg_language.h"
#include "catalog/pg_largeobject.h"
#include "catalog/pg_largeobject_metadata.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_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 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 recordDependencyOnNewAcl (Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
 
void recordExtObjInitPriv (Oid objoid, Oid classoid)
 
void removeExtObjInitPriv (Oid objoid, Oid classoid)
 

Variables

bool binary_upgrade_record_init_privs = false
 

Function Documentation

◆ aclcheck_error()

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

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

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

◆ aclcheck_error_col()

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

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

3638 {
3639  switch (aclerr)
3640  {
3641  case ACLCHECK_OK:
3642  /* no error, so return to caller */
3643  break;
3644  case ACLCHECK_NO_PRIV:
3645  ereport(ERROR,
3646  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3647  errmsg("permission denied for column \"%s\" of relation \"%s\"",
3648  colname, objectname)));
3649  break;
3650  case ACLCHECK_NOT_OWNER:
3651  /* relation msg is OK since columns don't have separate owners */
3652  aclcheck_error(aclerr, objtype, objectname);
3653  break;
3654  default:
3655  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3656  break;
3657  }
3658 }
int errcode(int sqlerrcode)
Definition: elog.c:570
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3353
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226

◆ aclcheck_error_type()

void aclcheck_error_type ( AclResult  aclerr,
Oid  typeOid 
)

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

3667 {
3668  Oid element_type = get_element_type(typeOid);
3669 
3670  aclcheck_error(aclerr, OBJECT_TYPE, format_type_be(element_type ? element_type : typeOid));
3671 }
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2526
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
unsigned int Oid
Definition: postgres_ext.h:31
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3353

◆ ExecAlterDefaultPrivilegesStmt()

void ExecAlterDefaultPrivilegesStmt ( ParseState pstate,
AlterDefaultPrivilegesStmt stmt 
)

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

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

◆ 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 1647 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().

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

◆ ExecGrant_Database()

static void ExecGrant_Database ( InternalGrant grantStmt)
static

Definition at line 2127 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

2128 {
2129  Relation relation;
2130  ListCell *cell;
2131 
2132  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2133  istmt->privileges = ACL_ALL_RIGHTS_DATABASE;
2134 
2135  relation = table_open(DatabaseRelationId, RowExclusiveLock);
2136 
2137  foreach(cell, istmt->objects)
2138  {
2139  Oid datId = lfirst_oid(cell);
2140  Form_pg_database pg_database_tuple;
2141  Datum aclDatum;
2142  bool isNull;
2143  AclMode avail_goptions;
2144  AclMode this_privileges;
2145  Acl *old_acl;
2146  Acl *new_acl;
2147  Oid grantorId;
2148  Oid ownerId;
2149  HeapTuple newtuple;
2150  Datum values[Natts_pg_database];
2151  bool nulls[Natts_pg_database];
2152  bool replaces[Natts_pg_database];
2153  int noldmembers;
2154  int nnewmembers;
2155  Oid *oldmembers;
2156  Oid *newmembers;
2157  HeapTuple tuple;
2158 
2159  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(datId));
2160  if (!HeapTupleIsValid(tuple))
2161  elog(ERROR, "cache lookup failed for database %u", datId);
2162 
2163  pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
2164 
2165  /*
2166  * Get owner ID and working copy of existing ACL. If there's no ACL,
2167  * substitute the proper default.
2168  */
2169  ownerId = pg_database_tuple->datdba;
2170  aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
2171  RelationGetDescr(relation), &isNull);
2172  if (isNull)
2173  {
2174  old_acl = acldefault(OBJECT_DATABASE, ownerId);
2175  /* There are no old member roles according to the catalogs */
2176  noldmembers = 0;
2177  oldmembers = NULL;
2178  }
2179  else
2180  {
2181  old_acl = DatumGetAclPCopy(aclDatum);
2182  /* Get the roles mentioned in the existing ACL */
2183  noldmembers = aclmembers(old_acl, &oldmembers);
2184  }
2185 
2186  /* Determine ID to do the grant as, and available grant options */
2187  select_best_grantor(GetUserId(), istmt->privileges,
2188  old_acl, ownerId,
2189  &grantorId, &avail_goptions);
2190 
2191  /*
2192  * Restrict the privileges to what we can actually grant, and emit the
2193  * standards-mandated warning and error messages.
2194  */
2195  this_privileges =
2196  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2197  istmt->all_privs, istmt->privileges,
2198  datId, grantorId, OBJECT_DATABASE,
2199  NameStr(pg_database_tuple->datname),
2200  0, NULL);
2201 
2202  /*
2203  * Generate new ACL.
2204  */
2205  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2206  istmt->grant_option, istmt->behavior,
2207  istmt->grantees, this_privileges,
2208  grantorId, ownerId);
2209 
2210  /*
2211  * We need the members of both old and new ACLs so we can correct the
2212  * shared dependency information.
2213  */
2214  nnewmembers = aclmembers(new_acl, &newmembers);
2215 
2216  /* finished building new ACL value, now insert it */
2217  MemSet(values, 0, sizeof(values));
2218  MemSet(nulls, false, sizeof(nulls));
2219  MemSet(replaces, false, sizeof(replaces));
2220 
2221  replaces[Anum_pg_database_datacl - 1] = true;
2222  values[Anum_pg_database_datacl - 1] = PointerGetDatum(new_acl);
2223 
2224  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2225  nulls, replaces);
2226 
2227  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2228 
2229  /* Update the shared dependency ACL info */
2230  updateAclDependencies(DatabaseRelationId, pg_database_tuple->oid, 0,
2231  ownerId,
2232  noldmembers, oldmembers,
2233  nnewmembers, newmembers);
2234 
2235  ReleaseSysCache(tuple);
2236 
2237  pfree(new_acl);
2238 
2239  /* prevent error when processing duplicate objects */
2241  }
2242 
2243  table_close(relation, RowExclusiveLock);
2244 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:427
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:442
Oid GetUserId(void)
Definition: miscinit.c:380
FormData_pg_database * Form_pg_database
Definition: pg_database.h:81
#define PointerGetDatum(X)
Definition: postgres.h:556
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:749
#define MemSet(start, val, len)
Definition: c.h:955
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:507
#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:762
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1003
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
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:224
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5116
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:159
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:237
#define lfirst_oid(lc)
Definition: pg_list.h:192
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Fdw()

static void ExecGrant_Fdw ( InternalGrant grantStmt)
static

Definition at line 2247 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

2248 {
2249  Relation relation;
2250  ListCell *cell;
2251 
2252  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2253  istmt->privileges = ACL_ALL_RIGHTS_FDW;
2254 
2255  relation = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
2256 
2257  foreach(cell, istmt->objects)
2258  {
2259  Oid fdwid = lfirst_oid(cell);
2260  Form_pg_foreign_data_wrapper pg_fdw_tuple;
2261  Datum aclDatum;
2262  bool isNull;
2263  AclMode avail_goptions;
2264  AclMode this_privileges;
2265  Acl *old_acl;
2266  Acl *new_acl;
2267  Oid grantorId;
2268  Oid ownerId;
2269  HeapTuple tuple;
2270  HeapTuple newtuple;
2271  Datum values[Natts_pg_foreign_data_wrapper];
2272  bool nulls[Natts_pg_foreign_data_wrapper];
2273  bool replaces[Natts_pg_foreign_data_wrapper];
2274  int noldmembers;
2275  int nnewmembers;
2276  Oid *oldmembers;
2277  Oid *newmembers;
2278 
2280  ObjectIdGetDatum(fdwid));
2281  if (!HeapTupleIsValid(tuple))
2282  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
2283 
2284  pg_fdw_tuple = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
2285 
2286  /*
2287  * Get owner ID and working copy of existing ACL. If there's no ACL,
2288  * substitute the proper default.
2289  */
2290  ownerId = pg_fdw_tuple->fdwowner;
2291  aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
2292  Anum_pg_foreign_data_wrapper_fdwacl,
2293  &isNull);
2294  if (isNull)
2295  {
2296  old_acl = acldefault(OBJECT_FDW, ownerId);
2297  /* There are no old member roles according to the catalogs */
2298  noldmembers = 0;
2299  oldmembers = NULL;
2300  }
2301  else
2302  {
2303  old_acl = DatumGetAclPCopy(aclDatum);
2304  /* Get the roles mentioned in the existing ACL */
2305  noldmembers = aclmembers(old_acl, &oldmembers);
2306  }
2307 
2308  /* Determine ID to do the grant as, and available grant options */
2309  select_best_grantor(GetUserId(), istmt->privileges,
2310  old_acl, ownerId,
2311  &grantorId, &avail_goptions);
2312 
2313  /*
2314  * Restrict the privileges to what we can actually grant, and emit the
2315  * standards-mandated warning and error messages.
2316  */
2317  this_privileges =
2318  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2319  istmt->all_privs, istmt->privileges,
2320  fdwid, grantorId, OBJECT_FDW,
2321  NameStr(pg_fdw_tuple->fdwname),
2322  0, NULL);
2323 
2324  /*
2325  * Generate new ACL.
2326  */
2327  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2328  istmt->grant_option, istmt->behavior,
2329  istmt->grantees, this_privileges,
2330  grantorId, ownerId);
2331 
2332  /*
2333  * We need the members of both old and new ACLs so we can correct the
2334  * shared dependency information.
2335  */
2336  nnewmembers = aclmembers(new_acl, &newmembers);
2337 
2338  /* finished building new ACL value, now insert it */
2339  MemSet(values, 0, sizeof(values));
2340  MemSet(nulls, false, sizeof(nulls));
2341  MemSet(replaces, false, sizeof(replaces));
2342 
2343  replaces[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
2344  values[Anum_pg_foreign_data_wrapper_fdwacl - 1] = PointerGetDatum(new_acl);
2345 
2346  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2347  nulls, replaces);
2348 
2349  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2350 
2351  /* Update initial privileges for extensions */
2352  recordExtensionInitPriv(fdwid, ForeignDataWrapperRelationId, 0,
2353  new_acl);
2354 
2355  /* Update the shared dependency ACL info */
2356  updateAclDependencies(ForeignDataWrapperRelationId,
2357  pg_fdw_tuple->oid, 0,
2358  ownerId,
2359  noldmembers, oldmembers,
2360  nnewmembers, newmembers);
2361 
2362  ReleaseSysCache(tuple);
2363 
2364  pfree(new_acl);
2365 
2366  /* prevent error when processing duplicate objects */
2368  }
2369 
2370  table_close(relation, RowExclusiveLock);
2371 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:427
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:442
Oid GetUserId(void)
Definition: miscinit.c:380
#define PointerGetDatum(X)
Definition: postgres.h:556
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:749
#define MemSet(start, val, len)
Definition: c.h:955
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:507
#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:5934
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1003
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1385
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:224
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5116
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:160
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:237
#define lfirst_oid(lc)
Definition: pg_list.h:192
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_ForeignServer()

static void ExecGrant_ForeignServer ( InternalGrant grantStmt)
static

Definition at line 2374 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

2375 {
2376  Relation relation;
2377  ListCell *cell;
2378 
2379  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2380  istmt->privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
2381 
2382  relation = table_open(ForeignServerRelationId, RowExclusiveLock);
2383 
2384  foreach(cell, istmt->objects)
2385  {
2386  Oid srvid = lfirst_oid(cell);
2387  Form_pg_foreign_server pg_server_tuple;
2388  Datum aclDatum;
2389  bool isNull;
2390  AclMode avail_goptions;
2391  AclMode this_privileges;
2392  Acl *old_acl;
2393  Acl *new_acl;
2394  Oid grantorId;
2395  Oid ownerId;
2396  HeapTuple tuple;
2397  HeapTuple newtuple;
2398  Datum values[Natts_pg_foreign_server];
2399  bool nulls[Natts_pg_foreign_server];
2400  bool replaces[Natts_pg_foreign_server];
2401  int noldmembers;
2402  int nnewmembers;
2403  Oid *oldmembers;
2404  Oid *newmembers;
2405 
2407  if (!HeapTupleIsValid(tuple))
2408  elog(ERROR, "cache lookup failed for foreign server %u", srvid);
2409 
2410  pg_server_tuple = (Form_pg_foreign_server) GETSTRUCT(tuple);
2411 
2412  /*
2413  * Get owner ID and working copy of existing ACL. If there's no ACL,
2414  * substitute the proper default.
2415  */
2416  ownerId = pg_server_tuple->srvowner;
2417  aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
2418  Anum_pg_foreign_server_srvacl,
2419  &isNull);
2420  if (isNull)
2421  {
2422  old_acl = acldefault(OBJECT_FOREIGN_SERVER, ownerId);
2423  /* There are no old member roles according to the catalogs */
2424  noldmembers = 0;
2425  oldmembers = NULL;
2426  }
2427  else
2428  {
2429  old_acl = DatumGetAclPCopy(aclDatum);
2430  /* Get the roles mentioned in the existing ACL */
2431  noldmembers = aclmembers(old_acl, &oldmembers);
2432  }
2433 
2434  /* Determine ID to do the grant as, and available grant options */
2435  select_best_grantor(GetUserId(), istmt->privileges,
2436  old_acl, ownerId,
2437  &grantorId, &avail_goptions);
2438 
2439  /*
2440  * Restrict the privileges to what we can actually grant, and emit the
2441  * standards-mandated warning and error messages.
2442  */
2443  this_privileges =
2444  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2445  istmt->all_privs, istmt->privileges,
2446  srvid, grantorId, OBJECT_FOREIGN_SERVER,
2447  NameStr(pg_server_tuple->srvname),
2448  0, NULL);
2449 
2450  /*
2451  * Generate new ACL.
2452  */
2453  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2454  istmt->grant_option, istmt->behavior,
2455  istmt->grantees, this_privileges,
2456  grantorId, ownerId);
2457 
2458  /*
2459  * We need the members of both old and new ACLs so we can correct the
2460  * shared dependency information.
2461  */
2462  nnewmembers = aclmembers(new_acl, &newmembers);
2463 
2464  /* finished building new ACL value, now insert it */
2465  MemSet(values, 0, sizeof(values));
2466  MemSet(nulls, false, sizeof(nulls));
2467  MemSet(replaces, false, sizeof(replaces));
2468 
2469  replaces[Anum_pg_foreign_server_srvacl - 1] = true;
2470  values[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(new_acl);
2471 
2472  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2473  nulls, replaces);
2474 
2475  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2476 
2477  /* Update initial privileges for extensions */
2478  recordExtensionInitPriv(srvid, ForeignServerRelationId, 0, new_acl);
2479 
2480  /* Update the shared dependency ACL info */
2481  updateAclDependencies(ForeignServerRelationId,
2482  pg_server_tuple->oid, 0,
2483  ownerId,
2484  noldmembers, oldmembers,
2485  nnewmembers, newmembers);
2486 
2487  ReleaseSysCache(tuple);
2488 
2489  pfree(new_acl);
2490 
2491  /* prevent error when processing duplicate objects */
2493  }
2494 
2495  table_close(relation, RowExclusiveLock);
2496 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:427
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:442
Oid GetUserId(void)
Definition: miscinit.c:380
#define PointerGetDatum(X)
Definition: postgres.h:556
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:749
#define MemSet(start, val, len)
Definition: c.h:955
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:507
#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:5934
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1003
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1385
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:224
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5116
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:161
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:237
#define lfirst_oid(lc)
Definition: pg_list.h:192
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Function()

static void ExecGrant_Function ( InternalGrant grantStmt)
static

Definition at line 2499 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

2500 {
2501  Relation relation;
2502  ListCell *cell;
2503 
2504  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2505  istmt->privileges = ACL_ALL_RIGHTS_FUNCTION;
2506 
2507  relation = table_open(ProcedureRelationId, RowExclusiveLock);
2508 
2509  foreach(cell, istmt->objects)
2510  {
2511  Oid funcId = lfirst_oid(cell);
2512  Form_pg_proc pg_proc_tuple;
2513  Datum aclDatum;
2514  bool isNull;
2515  AclMode avail_goptions;
2516  AclMode this_privileges;
2517  Acl *old_acl;
2518  Acl *new_acl;
2519  Oid grantorId;
2520  Oid ownerId;
2521  HeapTuple tuple;
2522  HeapTuple newtuple;
2523  Datum values[Natts_pg_proc];
2524  bool nulls[Natts_pg_proc];
2525  bool replaces[Natts_pg_proc];
2526  int noldmembers;
2527  int nnewmembers;
2528  Oid *oldmembers;
2529  Oid *newmembers;
2530 
2531  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
2532  if (!HeapTupleIsValid(tuple))
2533  elog(ERROR, "cache lookup failed for function %u", funcId);
2534 
2535  pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
2536 
2537  /*
2538  * Get owner ID and working copy of existing ACL. If there's no ACL,
2539  * substitute the proper default.
2540  */
2541  ownerId = pg_proc_tuple->proowner;
2542  aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
2543  &isNull);
2544  if (isNull)
2545  {
2546  old_acl = acldefault(OBJECT_FUNCTION, ownerId);
2547  /* There are no old member roles according to the catalogs */
2548  noldmembers = 0;
2549  oldmembers = NULL;
2550  }
2551  else
2552  {
2553  old_acl = DatumGetAclPCopy(aclDatum);
2554  /* Get the roles mentioned in the existing ACL */
2555  noldmembers = aclmembers(old_acl, &oldmembers);
2556  }
2557 
2558  /* Determine ID to do the grant as, and available grant options */
2559  select_best_grantor(GetUserId(), istmt->privileges,
2560  old_acl, ownerId,
2561  &grantorId, &avail_goptions);
2562 
2563  /*
2564  * Restrict the privileges to what we can actually grant, and emit the
2565  * standards-mandated warning and error messages.
2566  */
2567  this_privileges =
2568  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2569  istmt->all_privs, istmt->privileges,
2570  funcId, grantorId, OBJECT_FUNCTION,
2571  NameStr(pg_proc_tuple->proname),
2572  0, NULL);
2573 
2574  /*
2575  * Generate new ACL.
2576  */
2577  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2578  istmt->grant_option, istmt->behavior,
2579  istmt->grantees, this_privileges,
2580  grantorId, ownerId);
2581 
2582  /*
2583  * We need the members of both old and new ACLs so we can correct the
2584  * shared dependency information.
2585  */
2586  nnewmembers = aclmembers(new_acl, &newmembers);
2587 
2588  /* finished building new ACL value, now insert it */
2589  MemSet(values, 0, sizeof(values));
2590  MemSet(nulls, false, sizeof(nulls));
2591  MemSet(replaces, false, sizeof(replaces));
2592 
2593  replaces[Anum_pg_proc_proacl - 1] = true;
2594  values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
2595 
2596  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2597  nulls, replaces);
2598 
2599  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2600 
2601  /* Update initial privileges for extensions */
2602  recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
2603 
2604  /* Update the shared dependency ACL info */
2605  updateAclDependencies(ProcedureRelationId, funcId, 0,
2606  ownerId,
2607  noldmembers, oldmembers,
2608  nnewmembers, newmembers);
2609 
2610  ReleaseSysCache(tuple);
2611 
2612  pfree(new_acl);
2613 
2614  /* prevent error when processing duplicate objects */
2616  }
2617 
2618  table_close(relation, RowExclusiveLock);
2619 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:427
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:162
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:442
Oid GetUserId(void)
Definition: miscinit.c:380
#define PointerGetDatum(X)
Definition: postgres.h:556
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:749
#define MemSet(start, val, len)
Definition: c.h:955
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:507
#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:5934
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1003
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1385
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:134
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:224
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5116
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:237
#define lfirst_oid(lc)
Definition: pg_list.h:192
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Language()

static void ExecGrant_Language ( InternalGrant grantStmt)
static

Definition at line 2622 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

2623 {
2624  Relation relation;
2625  ListCell *cell;
2626 
2627  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2628  istmt->privileges = ACL_ALL_RIGHTS_LANGUAGE;
2629 
2630  relation = table_open(LanguageRelationId, RowExclusiveLock);
2631 
2632  foreach(cell, istmt->objects)
2633  {
2634  Oid langId = lfirst_oid(cell);
2635  Form_pg_language pg_language_tuple;
2636  Datum aclDatum;
2637  bool isNull;
2638  AclMode avail_goptions;
2639  AclMode this_privileges;
2640  Acl *old_acl;
2641  Acl *new_acl;
2642  Oid grantorId;
2643  Oid ownerId;
2644  HeapTuple tuple;
2645  HeapTuple newtuple;
2646  Datum values[Natts_pg_language];
2647  bool nulls[Natts_pg_language];
2648  bool replaces[Natts_pg_language];
2649  int noldmembers;
2650  int nnewmembers;
2651  Oid *oldmembers;
2652  Oid *newmembers;
2653 
2654  tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(langId));
2655  if (!HeapTupleIsValid(tuple))
2656  elog(ERROR, "cache lookup failed for language %u", langId);
2657 
2658  pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
2659 
2660  if (!pg_language_tuple->lanpltrusted)
2661  ereport(ERROR,
2662  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2663  errmsg("language \"%s\" is not trusted",
2664  NameStr(pg_language_tuple->lanname)),
2665  errdetail("GRANT and REVOKE are not allowed on untrusted languages, "
2666  "because only superusers can use untrusted languages.")));
2667 
2668  /*
2669  * Get owner ID and working copy of existing ACL. If there's no ACL,
2670  * substitute the proper default.
2671  */
2672  ownerId = pg_language_tuple->lanowner;
2673  aclDatum = SysCacheGetAttr(LANGNAME, tuple, Anum_pg_language_lanacl,
2674  &isNull);
2675  if (isNull)
2676  {
2677  old_acl = acldefault(OBJECT_LANGUAGE, ownerId);
2678  /* There are no old member roles according to the catalogs */
2679  noldmembers = 0;
2680  oldmembers = NULL;
2681  }
2682  else
2683  {
2684  old_acl = DatumGetAclPCopy(aclDatum);
2685  /* Get the roles mentioned in the existing ACL */
2686  noldmembers = aclmembers(old_acl, &oldmembers);
2687  }
2688 
2689  /* Determine ID to do the grant as, and available grant options */
2690  select_best_grantor(GetUserId(), istmt->privileges,
2691  old_acl, ownerId,
2692  &grantorId, &avail_goptions);
2693 
2694  /*
2695  * Restrict the privileges to what we can actually grant, and emit the
2696  * standards-mandated warning and error messages.
2697  */
2698  this_privileges =
2699  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2700  istmt->all_privs, istmt->privileges,
2701  langId, grantorId, OBJECT_LANGUAGE,
2702  NameStr(pg_language_tuple->lanname),
2703  0, NULL);
2704 
2705  /*
2706  * Generate new ACL.
2707  */
2708  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2709  istmt->grant_option, istmt->behavior,
2710  istmt->grantees, this_privileges,
2711  grantorId, ownerId);
2712 
2713  /*
2714  * We need the members of both old and new ACLs so we can correct the
2715  * shared dependency information.
2716  */
2717  nnewmembers = aclmembers(new_acl, &newmembers);
2718 
2719  /* finished building new ACL value, now insert it */
2720  MemSet(values, 0, sizeof(values));
2721  MemSet(nulls, false, sizeof(nulls));
2722  MemSet(replaces, false, sizeof(replaces));
2723 
2724  replaces[Anum_pg_language_lanacl - 1] = true;
2725  values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
2726 
2727  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2728  nulls, replaces);
2729 
2730  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2731 
2732  /* Update initial privileges for extensions */
2733  recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
2734 
2735  /* Update the shared dependency ACL info */
2736  updateAclDependencies(LanguageRelationId, pg_language_tuple->oid, 0,
2737  ownerId,
2738  noldmembers, oldmembers,
2739  nnewmembers, newmembers);
2740 
2741  ReleaseSysCache(tuple);
2742 
2743  pfree(new_acl);
2744 
2745  /* prevent error when processing duplicate objects */
2747  }
2748 
2749  table_close(relation, RowExclusiveLock);
2750 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:427
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:442
Oid GetUserId(void)
Definition: miscinit.c:380
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:570
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:749
#define MemSet(start, val, len)
Definition: c.h:955
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:163
uint32 AclMode
Definition: parsenodes.h:72
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#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:860
#define ereport(elevel, rest)
Definition: elog.h:141
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5934
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1003
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1385
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:224
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5116
static Datum values[MAXATTR]
Definition: bootstrap.c:167
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:237
#define lfirst_oid(lc)
Definition: pg_list.h:192
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Largeobject()

static void ExecGrant_Largeobject ( InternalGrant grantStmt)
static

Definition at line 2753 of file aclchk.c.

References ACL_ALL_RIGHTS_LARGEOBJECT, ACL_NO_RIGHTS, acldefault(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, BTEqualStrategyNumber, CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_getattr, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, LargeObjectMetadataOidIndexId, lfirst_oid, MemSet, merge_acl_with_grant(), NAMEDATALEN, OBJECT_LARGEOBJECT, ObjectIdGetDatum, InternalGrant::objects, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, restrict_and_check_grant(), RowExclusiveLock, ScanKeyInit(), select_best_grantor(), snprintf, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

2754 {
2755  Relation relation;
2756  ListCell *cell;
2757 
2758  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2759  istmt->privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
2760 
2761  relation = table_open(LargeObjectMetadataRelationId,
2763 
2764  foreach(cell, istmt->objects)
2765  {
2766  Oid loid = lfirst_oid(cell);
2767  Form_pg_largeobject_metadata form_lo_meta;
2768  char loname[NAMEDATALEN];
2769  Datum aclDatum;
2770  bool isNull;
2771  AclMode avail_goptions;
2772  AclMode this_privileges;
2773  Acl *old_acl;
2774  Acl *new_acl;
2775  Oid grantorId;
2776  Oid ownerId;
2777  HeapTuple newtuple;
2778  Datum values[Natts_pg_largeobject_metadata];
2779  bool nulls[Natts_pg_largeobject_metadata];
2780  bool replaces[Natts_pg_largeobject_metadata];
2781  int noldmembers;
2782  int nnewmembers;
2783  Oid *oldmembers;
2784  Oid *newmembers;
2785  ScanKeyData entry[1];
2786  SysScanDesc scan;
2787  HeapTuple tuple;
2788 
2789  /* There's no syscache for pg_largeobject_metadata */
2790  ScanKeyInit(&entry[0],
2791  Anum_pg_largeobject_metadata_oid,
2792  BTEqualStrategyNumber, F_OIDEQ,
2793  ObjectIdGetDatum(loid));
2794 
2795  scan = systable_beginscan(relation,
2797  NULL, 1, entry);
2798 
2799  tuple = systable_getnext(scan);
2800  if (!HeapTupleIsValid(tuple))
2801  elog(ERROR, "could not find tuple for large object %u", loid);
2802 
2803  form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
2804 
2805  /*
2806  * Get owner ID and working copy of existing ACL. If there's no ACL,
2807  * substitute the proper default.
2808  */
2809  ownerId = form_lo_meta->lomowner;
2810  aclDatum = heap_getattr(tuple,
2811  Anum_pg_largeobject_metadata_lomacl,
2812  RelationGetDescr(relation), &isNull);
2813  if (isNull)
2814  {
2815  old_acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
2816  /* There are no old member roles according to the catalogs */
2817  noldmembers = 0;
2818  oldmembers = NULL;
2819  }
2820  else
2821  {
2822  old_acl = DatumGetAclPCopy(aclDatum);
2823  /* Get the roles mentioned in the existing ACL */
2824  noldmembers = aclmembers(old_acl, &oldmembers);
2825  }
2826 
2827  /* Determine ID to do the grant as, and available grant options */
2828  select_best_grantor(GetUserId(), istmt->privileges,
2829  old_acl, ownerId,
2830  &grantorId, &avail_goptions);
2831 
2832  /*
2833  * Restrict the privileges to what we can actually grant, and emit the
2834  * standards-mandated warning and error messages.
2835  */
2836  snprintf(loname, sizeof(loname), "large object %u", loid);
2837  this_privileges =
2838  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2839  istmt->all_privs, istmt->privileges,
2840  loid, grantorId, OBJECT_LARGEOBJECT,
2841  loname, 0, NULL);
2842 
2843  /*
2844  * Generate new ACL.
2845  */
2846  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2847  istmt->grant_option, istmt->behavior,
2848  istmt->grantees, this_privileges,
2849  grantorId, ownerId);
2850 
2851  /*
2852  * We need the members of both old and new ACLs so we can correct the
2853  * shared dependency information.
2854  */
2855  nnewmembers = aclmembers(new_acl, &newmembers);
2856 
2857  /* finished building new ACL value, now insert it */
2858  MemSet(values, 0, sizeof(values));
2859  MemSet(nulls, false, sizeof(nulls));
2860  MemSet(replaces, false, sizeof(replaces));
2861 
2862  replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
2863  values[Anum_pg_largeobject_metadata_lomacl - 1]
2864  = PointerGetDatum(new_acl);
2865 
2866  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2867  values, nulls, replaces);
2868 
2869  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2870 
2871  /* Update initial privileges for extensions */
2872  recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
2873 
2874  /* Update the shared dependency ACL info */
2875  updateAclDependencies(LargeObjectRelationId,
2876  form_lo_meta->oid, 0,
2877  ownerId,
2878  noldmembers, oldmembers,
2879  nnewmembers, newmembers);
2880 
2881  systable_endscan(scan);
2882 
2883  pfree(new_acl);
2884 
2885  /* prevent error when processing duplicate objects */
2887  }
2888 
2889  table_close(relation, RowExclusiveLock);
2890 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:427
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:442
Oid GetUserId(void)
Definition: miscinit.c:380
#define PointerGetDatum(X)
Definition: postgres.h:556
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:749
#define MemSet(start, val, len)
Definition: c.h:955
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:352
#define NAMEDATALEN
uint32 AclMode
Definition: parsenodes.h:72
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#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:5934
#define LargeObjectMetadataOidIndexId
Definition: indexing.h:187
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
FormData_pg_largeobject_metadata * Form_pg_largeobject_metadata
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1003
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:164
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:224
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5116
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define elog(elevel,...)
Definition: elog.h:226
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define snprintf
Definition: port.h:192
#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:192
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Namespace()

static void ExecGrant_Namespace ( InternalGrant grantStmt)
static

Definition at line 2893 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

2894 {
2895  Relation relation;
2896  ListCell *cell;
2897 
2898  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2899  istmt->privileges = ACL_ALL_RIGHTS_SCHEMA;
2900 
2901  relation = table_open(NamespaceRelationId, RowExclusiveLock);
2902 
2903  foreach(cell, istmt->objects)
2904  {
2905  Oid nspid = lfirst_oid(cell);
2906  Form_pg_namespace pg_namespace_tuple;
2907  Datum aclDatum;
2908  bool isNull;
2909  AclMode avail_goptions;
2910  AclMode this_privileges;
2911  Acl *old_acl;
2912  Acl *new_acl;
2913  Oid grantorId;
2914  Oid ownerId;
2915  HeapTuple tuple;
2916  HeapTuple newtuple;
2917  Datum values[Natts_pg_namespace];
2918  bool nulls[Natts_pg_namespace];
2919  bool replaces[Natts_pg_namespace];
2920  int noldmembers;
2921  int nnewmembers;
2922  Oid *oldmembers;
2923  Oid *newmembers;
2924 
2926  if (!HeapTupleIsValid(tuple))
2927  elog(ERROR, "cache lookup failed for namespace %u", nspid);
2928 
2929  pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
2930 
2931  /*
2932  * Get owner ID and working copy of existing ACL. If there's no ACL,
2933  * substitute the proper default.
2934  */
2935  ownerId = pg_namespace_tuple->nspowner;
2936  aclDatum = SysCacheGetAttr(NAMESPACENAME, tuple,
2937  Anum_pg_namespace_nspacl,
2938  &isNull);
2939  if (isNull)
2940  {
2941  old_acl = acldefault(OBJECT_SCHEMA, ownerId);
2942  /* There are no old member roles according to the catalogs */
2943  noldmembers = 0;
2944  oldmembers = NULL;
2945  }
2946  else
2947  {
2948  old_acl = DatumGetAclPCopy(aclDatum);
2949  /* Get the roles mentioned in the existing ACL */
2950  noldmembers = aclmembers(old_acl, &oldmembers);
2951  }
2952 
2953  /* Determine ID to do the grant as, and available grant options */
2954  select_best_grantor(GetUserId(), istmt->privileges,
2955  old_acl, ownerId,
2956  &grantorId, &avail_goptions);
2957 
2958  /*
2959  * Restrict the privileges to what we can actually grant, and emit the
2960  * standards-mandated warning and error messages.
2961  */
2962  this_privileges =
2963  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2964  istmt->all_privs, istmt->privileges,
2965  nspid, grantorId, OBJECT_SCHEMA,
2966  NameStr(pg_namespace_tuple->nspname),
2967  0, NULL);
2968 
2969  /*
2970  * Generate new ACL.
2971  */
2972  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2973  istmt->grant_option, istmt->behavior,
2974  istmt->grantees, this_privileges,
2975  grantorId, ownerId);
2976 
2977  /*
2978  * We need the members of both old and new ACLs so we can correct the
2979  * shared dependency information.
2980  */
2981  nnewmembers = aclmembers(new_acl, &newmembers);
2982 
2983  /* finished building new ACL value, now insert it */
2984  MemSet(values, 0, sizeof(values));
2985  MemSet(nulls, false, sizeof(nulls));
2986  MemSet(replaces, false, sizeof(replaces));
2987 
2988  replaces[Anum_pg_namespace_nspacl - 1] = true;
2989  values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(new_acl);
2990 
2991  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2992  nulls, replaces);
2993 
2994  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2995 
2996  /* Update initial privileges for extensions */
2997  recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
2998 
2999  /* Update the shared dependency ACL info */
3000  updateAclDependencies(NamespaceRelationId, pg_namespace_tuple->oid, 0,
3001  ownerId,
3002  noldmembers, oldmembers,
3003  nnewmembers, newmembers);
3004 
3005  ReleaseSysCache(tuple);
3006 
3007  pfree(new_acl);
3008 
3009  /* prevent error when processing duplicate objects */
3011  }
3012 
3013  table_close(relation, RowExclusiveLock);
3014 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:427
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:51
#define RelationGetDescr(relation)
Definition: rel.h:442
Oid GetUserId(void)
Definition: miscinit.c:380
#define PointerGetDatum(X)
Definition: postgres.h:556
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:749
#define MemSet(start, val, len)
Definition: c.h:955
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:507
#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:165
#define RowExclusiveLock
Definition: lockdefs.h:38
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5934
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1003
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1385
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:224
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5116
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:237
#define lfirst_oid(lc)
Definition: pg_list.h:192
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrant_Relation()

static void ExecGrant_Relation ( InternalGrant grantStmt)
static

Definition at line 1795 of file aclchk.c.

References ACL_ALL_RIGHTS_COLUMN, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SEQUENCE, ACL_NO_RIGHTS, ACL_SELECT, aclcopy(), acldefault(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, CatalogTupleUpdate(), InternalGrant::col_privs, AccessPriv::cols, CommandCounterIncrement(), DatumGetAclPCopy, elog, ereport, errcode(), errmsg(), ERROR, ExecGrant_Attribute(), expand_all_col_privileges(), expand_col_privileges(), FirstLowInvalidHeapAttributeNumber, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, i, InternalGrant::is_grant, lfirst, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectIdGetDatum, InternalGrant::objects, InternalGrant::objtype, palloc0(), pfree(), PointerGetDatum, AccessPriv::priv_name, privilege_to_string(), InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), RELOID, restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), string_to_privilege(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), updateAclDependencies(), values, and WARNING.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Tablespace()

static void ExecGrant_Tablespace ( InternalGrant grantStmt)
static

Definition at line 3017 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Type()

static void ExecGrant_Type ( InternalGrant grantStmt)
static

Definition at line 3137 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

3138 {
3139  Relation relation;
3140  ListCell *cell;
3141 
3142  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
3143  istmt->privileges = ACL_ALL_RIGHTS_TYPE;
3144 
3145  relation = table_open(TypeRelationId, RowExclusiveLock);
3146 
3147  foreach(cell, istmt->objects)
3148  {
3149  Oid typId = lfirst_oid(cell);
3150  Form_pg_type pg_type_tuple;
3151  Datum aclDatum;
3152  bool isNull;
3153  AclMode avail_goptions;
3154  AclMode this_privileges;
3155  Acl *old_acl;
3156  Acl *new_acl;
3157  Oid grantorId;
3158  Oid ownerId;
3159  HeapTuple newtuple;
3160  Datum values[Natts_pg_type];
3161  bool nulls[Natts_pg_type];
3162  bool replaces[Natts_pg_type];
3163  int noldmembers;
3164  int nnewmembers;
3165  Oid *oldmembers;
3166  Oid *newmembers;
3167  HeapTuple tuple;
3168 
3169  /* Search syscache for pg_type */
3170  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typId));
3171  if (!HeapTupleIsValid(tuple))
3172  elog(ERROR, "cache lookup failed for type %u", typId);
3173 
3174  pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
3175 
3176  if (pg_type_tuple->typelem != 0 && pg_type_tuple->typlen == -1)
3177  ereport(ERROR,
3178  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
3179  errmsg("cannot set privileges of array types"),
3180  errhint("Set the privileges of the element type instead.")));
3181 
3182  /* Used GRANT DOMAIN on a non-domain? */
3183  if (istmt->objtype == OBJECT_DOMAIN &&
3184  pg_type_tuple->typtype != TYPTYPE_DOMAIN)
3185  ereport(ERROR,
3186  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3187  errmsg("\"%s\" is not a domain",
3188  NameStr(pg_type_tuple->typname))));
3189 
3190  /*
3191  * Get owner ID and working copy of existing ACL. If there's no ACL,
3192  * substitute the proper default.
3193  */
3194  ownerId = pg_type_tuple->typowner;
3195  aclDatum = heap_getattr(tuple, Anum_pg_type_typacl,
3196  RelationGetDescr(relation), &isNull);
3197  if (isNull)
3198  {
3199  old_acl = acldefault(istmt->objtype, ownerId);
3200  /* There are no old member roles according to the catalogs */
3201  noldmembers = 0;
3202  oldmembers = NULL;
3203  }
3204  else
3205  {
3206  old_acl = DatumGetAclPCopy(aclDatum);
3207  /* Get the roles mentioned in the existing ACL */
3208  noldmembers = aclmembers(old_acl, &oldmembers);
3209  }
3210 
3211  /* Determine ID to do the grant as, and available grant options */
3212  select_best_grantor(GetUserId(), istmt->privileges,
3213  old_acl, ownerId,
3214  &grantorId, &avail_goptions);
3215 
3216  /*
3217  * Restrict the privileges to what we can actually grant, and emit the
3218  * standards-mandated warning and error messages.
3219  */
3220  this_privileges =
3221  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3222  istmt->all_privs, istmt->privileges,
3223  typId, grantorId, OBJECT_TYPE,
3224  NameStr(pg_type_tuple->typname),
3225  0, NULL);
3226 
3227  /*
3228  * Generate new ACL.
3229  */
3230  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3231  istmt->grant_option, istmt->behavior,
3232  istmt->grantees, this_privileges,
3233  grantorId, ownerId);
3234 
3235  /*
3236  * We need the members of both old and new ACLs so we can correct the
3237  * shared dependency information.
3238  */
3239  nnewmembers = aclmembers(new_acl, &newmembers);
3240 
3241  /* finished building new ACL value, now insert it */
3242  MemSet(values, 0, sizeof(values));
3243  MemSet(nulls, false, sizeof(nulls));
3244  MemSet(replaces, false, sizeof(replaces));
3245 
3246  replaces[Anum_pg_type_typacl - 1] = true;
3247  values[Anum_pg_type_typacl - 1] = PointerGetDatum(new_acl);
3248 
3249  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3250  nulls, replaces);
3251 
3252  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3253 
3254  /* Update initial privileges for extensions */
3255  recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
3256 
3257  /* Update the shared dependency ACL info */
3258  updateAclDependencies(TypeRelationId, typId, 0,
3259  ownerId,
3260  noldmembers, oldmembers,
3261  nnewmembers, newmembers);
3262 
3263  ReleaseSysCache(tuple);
3264  pfree(new_acl);
3265 
3266  /* prevent error when processing duplicate objects */
3268  }
3269 
3270  table_close(relation, RowExclusiveLock);
3271 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:427
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
int errhint(const char *fmt,...)
Definition: elog.c:974
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:442
Oid GetUserId(void)
Definition: miscinit.c:380
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:570
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:749
#define MemSet(start, val, len)
Definition: c.h:955
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:507
#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:167
#define ereport(elevel, rest)
Definition: elog.h:141
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:5934
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1003
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
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:224
FormData_pg_type * Form_pg_type
Definition: pg_type.h:251
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5116
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
#define NameStr(name)
Definition: c.h:609
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
Definition: aclchk.c:237
#define lfirst_oid(lc)
Definition: pg_list.h:192
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ ExecGrantStmt_oids()

static void ExecGrantStmt_oids ( InternalGrant istmt)
static

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

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

◆ 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  /*
451  * Because this might be a sequence, we test both relation and
452  * sequence bits, and later do a more limited test when we know
453  * the object type.
454  */
456  errormsg = gettext_noop("invalid privilege type %s for relation");
457  break;
458  case OBJECT_SEQUENCE:
459  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
460  errormsg = gettext_noop("invalid privilege type %s for sequence");
461  break;
462  case OBJECT_DATABASE:
463  all_privileges = ACL_ALL_RIGHTS_DATABASE;
464  errormsg = gettext_noop("invalid privilege type %s for database");
465  break;
466  case OBJECT_DOMAIN:
467  all_privileges = ACL_ALL_RIGHTS_TYPE;
468  errormsg = gettext_noop("invalid privilege type %s for domain");
469  break;
470  case OBJECT_FUNCTION:
471  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
472  errormsg = gettext_noop("invalid privilege type %s for function");
473  break;
474  case OBJECT_LANGUAGE:
475  all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
476  errormsg = gettext_noop("invalid privilege type %s for language");
477  break;
478  case OBJECT_LARGEOBJECT:
479  all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
480  errormsg = gettext_noop("invalid privilege type %s for large object");
481  break;
482  case OBJECT_SCHEMA:
483  all_privileges = ACL_ALL_RIGHTS_SCHEMA;
484  errormsg = gettext_noop("invalid privilege type %s for schema");
485  break;
486  case OBJECT_PROCEDURE:
487  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
488  errormsg = gettext_noop("invalid privilege type %s for procedure");
489  break;
490  case OBJECT_ROUTINE:
491  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
492  errormsg = gettext_noop("invalid privilege type %s for routine");
493  break;
494  case OBJECT_TABLESPACE:
495  all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
496  errormsg = gettext_noop("invalid privilege type %s for tablespace");
497  break;
498  case OBJECT_TYPE:
499  all_privileges = ACL_ALL_RIGHTS_TYPE;
500  errormsg = gettext_noop("invalid privilege type %s for type");
501  break;
502  case OBJECT_FDW:
503  all_privileges = ACL_ALL_RIGHTS_FDW;
504  errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
505  break;
507  all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
508  errormsg = gettext_noop("invalid privilege type %s for foreign server");
509  break;
510  default:
511  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
512  (int) stmt->objtype);
513  /* keep compiler quiet */
514  all_privileges = ACL_NO_RIGHTS;
515  errormsg = NULL;
516  }
517 
518  if (stmt->privileges == NIL)
519  {
520  istmt.all_privs = true;
521 
522  /*
523  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
524  * depending on the object type
525  */
526  istmt.privileges = ACL_NO_RIGHTS;
527  }
528  else
529  {
530  istmt.all_privs = false;
531  istmt.privileges = ACL_NO_RIGHTS;
532 
533  foreach(cell, stmt->privileges)
534  {
535  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
536  AclMode priv;
537 
538  /*
539  * If it's a column-level specification, we just set it aside in
540  * col_privs for the moment; but insist it's for a relation.
541  */
542  if (privnode->cols)
543  {
544  if (stmt->objtype != OBJECT_TABLE)
545  ereport(ERROR,
546  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
547  errmsg("column privileges are only valid for relations")));
548  istmt.col_privs = lappend(istmt.col_privs, privnode);
549  continue;
550  }
551 
552  if (privnode->priv_name == NULL) /* parser mistake? */
553  elog(ERROR, "AccessPriv node must specify privilege or columns");
554  priv = string_to_privilege(privnode->priv_name);
555 
556  if (priv & ~((AclMode) all_privileges))
557  ereport(ERROR,
558  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
559  errmsg(errormsg, privilege_to_string(priv))));
560 
561  istmt.privileges |= priv;
562  }
563  }
564 
565  ExecGrantStmt_oids(&istmt);
566 }
#define NIL
Definition: pg_list.h:65
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:162
static AclMode string_to_privilege(const char *privname)
Definition: aclchk.c:3275
AclMode privileges
bool grant_option
Definition: parsenodes.h:1912
#define gettext_noop(x)
Definition: c.h:1117
int errcode(int sqlerrcode)
Definition: elog.c:570
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:166
List * cols
Definition: parsenodes.h:1942
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:163
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:165
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:167
#define ereport(elevel, rest)
Definition: elog.h:141
List * lappend(List *list, void *datum)
Definition: list.c:321
bool is_grant
Definition: parsenodes.h:1904
static void ExecGrantStmt_oids(InternalGrant *istmt)
Definition: aclchk.c:574
static List * objectNamesToOids(ObjectType objtype, List *objnames)
Definition: aclchk.c:638
RoleSpecType roletype
Definition: parsenodes.h:328
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5225
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:158
List * privileges
Definition: parsenodes.h:1909
static List * objectsInSchemaToOids(ObjectType objtype, List *nspnames)
Definition: aclchk.c:787
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:164
DropBehavior behavior
DropBehavior behavior
Definition: parsenodes.h:1913
#define lfirst(lc)
Definition: pg_list.h:190
List * objects
Definition: parsenodes.h:1907
ObjectType objtype
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:159
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:161
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
#define ACL_ALL_RIGHTS_RELATION
Definition: acl.h:157
ObjectType objtype
Definition: parsenodes.h:1906
#define ACL_ID_PUBLIC
Definition: acl.h:46
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:160
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:3312
List * grantees
Definition: parsenodes.h:1911
GrantTargetType targtype
Definition: parsenodes.h:1905
char * priv_name
Definition: parsenodes.h:1941

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

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

Referenced by ExecGrant_Relation().

1605 {
1606  AttrNumber curr_att;
1607 
1608  Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
1609  for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
1610  curr_att <= classForm->relnatts;
1611  curr_att++)
1612  {
1613  HeapTuple attTuple;
1614  bool isdropped;
1615 
1616  if (curr_att == InvalidAttrNumber)
1617  continue;
1618 
1619  /* Views don't have any system columns at all */
1620  if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
1621  continue;
1622 
1623  attTuple = SearchSysCache2(ATTNUM,
1624  ObjectIdGetDatum(table_oid),
1625  Int16GetDatum(curr_att));
1626  if (!HeapTupleIsValid(attTuple))
1627  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1628  curr_att, table_oid);
1629 
1630  isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
1631 
1632  ReleaseSysCache(attTuple);
1633 
1634  /* ignore dropped columns */
1635  if (isdropped)
1636  continue;
1637 
1638  col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
1639  }
1640 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define Int16GetDatum(X)
Definition: postgres.h:451
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:732
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1135
#define InvalidAttrNumber
Definition: attnum.h:23
#define elog(elevel,...)
Definition: elog.h:226
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 1568 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().

1572 {
1573  ListCell *cell;
1574 
1575  foreach(cell, colnames)
1576  {
1577  char *colname = strVal(lfirst(cell));
1579 
1580  attnum = get_attnum(table_oid, colname);
1581  if (attnum == InvalidAttrNumber)
1582  ereport(ERROR,
1583  (errcode(ERRCODE_UNDEFINED_COLUMN),
1584  errmsg("column \"%s\" of relation \"%s\" does not exist",
1585  colname, get_rel_name(table_oid))));
1587  if (attnum <= 0 || attnum >= num_col_privileges)
1588  elog(ERROR, "column number out of range"); /* safety check */
1589  col_privileges[attnum] |= this_privileges;
1590  }
1591 }
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:570
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
#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:141
int16 attnum
Definition: pg_attribute.h:79
#define lfirst(lc)
Definition: pg_list.h:190
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define elog(elevel,...)
Definition: elog.h:226
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 5423 of file aclchk.c.

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

Referenced by get_user_default_acl().

5424 {
5425  Acl *result = NULL;
5426  HeapTuple tuple;
5427 
5429  ObjectIdGetDatum(roleId),
5430  ObjectIdGetDatum(nsp_oid),
5431  CharGetDatum(objtype));
5432 
5433  if (HeapTupleIsValid(tuple))
5434  {
5435  Datum aclDatum;
5436  bool isNull;
5437 
5438  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
5439  Anum_pg_default_acl_defaclacl,
5440  &isNull);
5441  if (!isNull)
5442  result = DatumGetAclPCopy(aclDatum);
5443  ReleaseSysCache(tuple);
5444  }
5445 
5446  return result;
5447 }
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1146
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1385
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define CharGetDatum(X)
Definition: postgres.h:416
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ get_user_default_acl()

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

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

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

◆ getRelationsInNamespace()

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

Definition at line 876 of file aclchk.c.

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

Referenced by objectsInSchemaToOids().

877 {
878  List *relations = NIL;
879  ScanKeyData key[2];
880  Relation rel;
881  TableScanDesc scan;
882  HeapTuple tuple;
883 
884  ScanKeyInit(&key[0],
885  Anum_pg_class_relnamespace,
886  BTEqualStrategyNumber, F_OIDEQ,
887  ObjectIdGetDatum(namespaceId));
888  ScanKeyInit(&key[1],
889  Anum_pg_class_relkind,
890  BTEqualStrategyNumber, F_CHAREQ,
892 
893  rel = table_open(RelationRelationId, AccessShareLock);
894  scan = table_beginscan_catalog(rel, 2, key);
895 
896  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
897  {
898  Oid oid = ((Form_pg_class) GETSTRUCT(tuple))->oid;
899 
900  relations = lappend_oid(relations, oid);
901  }
902 
903  table_endscan(scan);
905 
906  return relations;
907 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:98
#define AccessShareLock
Definition: lockdefs.h:36
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
char relkind
Definition: pg_class.h:81
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1290
#define CharGetDatum(X)
Definition: postgres.h:416
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:831
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ has_bypassrls_privilege()

bool has_bypassrls_privilege ( Oid  roleid)

Definition at line 5399 of file aclchk.c.

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

Referenced by check_enable_rls(), and RI_Initial_Check().

5400 {
5401  bool result = false;
5402  HeapTuple utup;
5403 
5404  /* Superusers bypass all permission checking. */
5405  if (superuser_arg(roleid))
5406  return true;
5407 
5408  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5409  if (HeapTupleIsValid(utup))
5410  {
5411  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
5412  ReleaseSysCache(utup);
5413  }
5414  return result;
5415 }
bool rolbypassrls
Definition: pg_authid.h:41
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
bool superuser_arg(Oid roleid)
Definition: superuser.c:57
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78

◆ has_createrole_privilege()

bool has_createrole_privilege ( Oid  roleid)

Definition at line 5380 of file aclchk.c.

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

Referenced by check_object_ownership(), and have_createrole_privilege().

5381 {
5382  bool result = false;
5383  HeapTuple utup;
5384 
5385  /* Superusers bypass all permission checking. */
5386  if (superuser_arg(roleid))
5387  return true;
5388 
5389  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5390  if (HeapTupleIsValid(utup))
5391  {
5392  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
5393  ReleaseSysCache(utup);
5394  }
5395  return result;
5396 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
bool rolcreaterole
Definition: pg_authid.h:37
bool superuser_arg(Oid roleid)
Definition: superuser.c:57
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#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:56
#define ACL_MODECHG_DEL
Definition: acl.h:130
int errcode(int sqlerrcode)
Definition: elog.c:570
Oid ai_grantor
Definition: acl.h:57
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:141
#define ACL_MODECHG_ADD
Definition: acl.h:129
Definition: acl.h:54
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define ACL_ID_PUBLIC
Definition: acl.h:46
Acl * aclupdate(const Acl *old_acl, const AclItem *mod_aip, int modechg, Oid ownerId, DropBehavior behavior)
Definition: acl.c:931
#define ACLITEM_SET_PRIVS_GOPTIONS(item, privs, goptions)
Definition: acl.h:82
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ objectNamesToOids()

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

Definition at line 638 of file aclchk.c.

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

Referenced by ExecuteGrantStmt().

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

◆ objectsInSchemaToOids()

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

Definition at line 787 of file aclchk.c.

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

Referenced by ExecuteGrantStmt().

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

◆ pg_aclmask()

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

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

3680 {
3681  switch (objtype)
3682  {
3683  case OBJECT_COLUMN:
3684  return
3685  pg_class_aclmask(table_oid, roleid, mask, how) |
3686  pg_attribute_aclmask(table_oid, attnum, roleid, mask, how);
3687  case OBJECT_TABLE:
3688  case OBJECT_SEQUENCE:
3689  return pg_class_aclmask(table_oid, roleid, mask, how);
3690  case OBJECT_DATABASE:
3691  return pg_database_aclmask(table_oid, roleid, mask, how);
3692  case OBJECT_FUNCTION:
3693  return pg_proc_aclmask(table_oid, roleid, mask, how);
3694  case OBJECT_LANGUAGE:
3695  return pg_language_aclmask(table_oid, roleid, mask, how);
3696  case OBJECT_LARGEOBJECT:
3697  return pg_largeobject_aclmask_snapshot(table_oid, roleid,
3698  mask, how, NULL);
3699  case OBJECT_SCHEMA:
3700  return pg_namespace_aclmask(table_oid, roleid, mask, how);
3701  case OBJECT_STATISTIC_EXT:
3702  elog(ERROR, "grantable rights not supported for statistics objects");
3703  /* not reached, but keep compiler quiet */
3704  return ACL_NO_RIGHTS;
3705  case OBJECT_TABLESPACE:
3706  return pg_tablespace_aclmask(table_oid, roleid, mask, how);
3707  case OBJECT_FDW:
3708  return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
3709  case OBJECT_FOREIGN_SERVER:
3710  return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
3711  case OBJECT_EVENT_TRIGGER:
3712  elog(ERROR, "grantable rights not supported for event triggers");
3713  /* not reached, but keep compiler quiet */
3714  return ACL_NO_RIGHTS;
3715  case OBJECT_TYPE:
3716  return pg_type_aclmask(table_oid, roleid, mask, how);
3717  default:
3718  elog(ERROR, "unrecognized objtype: %d",
3719  (int) objtype);
3720  /* not reached, but keep compiler quiet */
3721  return ACL_NO_RIGHTS;
3722  }
3723 }
AclMode pg_foreign_server_aclmask(Oid srv_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4372
AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3746
AclMode pg_tablespace_aclmask(Oid spc_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4253
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3831
AclMode pg_database_aclmask(Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3927
#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:4171
int16 attnum
Definition: pg_attribute.h:79
AclMode pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4433
AclMode pg_language_aclmask(Oid lang_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4035
AclMode pg_proc_aclmask(Oid proc_