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

Go to the source code of this file.

Data Structures

struct  InternalDefaultACL
 

Functions

static void ExecGrantStmt_oids (InternalGrant *istmt)
 
static void ExecGrant_Relation (InternalGrant *grantStmt)
 
static void ExecGrant_Database (InternalGrant *grantStmt)
 
static void ExecGrant_Fdw (InternalGrant *grantStmt)
 
static void ExecGrant_ForeignServer (InternalGrant *grantStmt)
 
static void ExecGrant_Function (InternalGrant *grantStmt)
 
static void ExecGrant_Language (InternalGrant *grantStmt)
 
static void ExecGrant_Largeobject (InternalGrant *grantStmt)
 
static void ExecGrant_Namespace (InternalGrant *grantStmt)
 
static void ExecGrant_Tablespace (InternalGrant *grantStmt)
 
static void ExecGrant_Type (InternalGrant *grantStmt)
 
static void SetDefaultACLsInSchemas (InternalDefaultACL *iacls, List *nspnames)
 
static void SetDefaultACL (InternalDefaultACL *iacls)
 
static ListobjectNamesToOids (ObjectType objtype, List *objnames)
 
static ListobjectsInSchemaToOids (ObjectType objtype, List *nspnames)
 
static ListgetRelationsInNamespace (Oid namespaceId, char relkind)
 
static void expand_col_privileges (List *colnames, Oid table_oid, AclMode this_privileges, AclMode *col_privileges, int num_col_privileges)
 
static void expand_all_col_privileges (Oid table_oid, Form_pg_class classForm, AclMode this_privileges, AclMode *col_privileges, int num_col_privileges)
 
static AclMode string_to_privilege (const char *privname)
 
static const char * privilege_to_string (AclMode privilege)
 
static AclMode restrict_and_check_grant (bool is_grant, AclMode avail_goptions, bool all_privs, AclMode privileges, Oid objectId, Oid grantorId, ObjectType objtype, const char *objname, AttrNumber att_number, const char *colname)
 
static AclMode pg_aclmask (ObjectType objtype, Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
 
static void recordExtensionInitPriv (Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
 
static void recordExtensionInitPrivWorker (Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
 
static Aclmerge_acl_with_grant (Acl *old_acl, bool is_grant, bool grant_option, DropBehavior behavior, List *grantees, AclMode privileges, Oid grantorId, Oid ownerId)
 
void ExecuteGrantStmt (GrantStmt *stmt)
 
void ExecAlterDefaultPrivilegesStmt (ParseState *pstate, AlterDefaultPrivilegesStmt *stmt)
 
void RemoveRoleFromObjectACL (Oid roleid, Oid classid, Oid objid)
 
void RemoveDefaultACLById (Oid defaclOid)
 
static void ExecGrant_Attribute (InternalGrant *istmt, Oid relOid, const char *relname, AttrNumber attnum, Oid ownerId, AclMode col_privileges, Relation attRelation, const Acl *old_rel_acl)
 
void aclcheck_error (AclResult aclerr, ObjectType objtype, const char *objectname)
 
void aclcheck_error_col (AclResult aclerr, ObjectType objtype, const char *objectname, const char *colname)
 
void aclcheck_error_type (AclResult aclerr, Oid typeOid)
 
AclMode pg_attribute_aclmask (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_class_aclmask (Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_database_aclmask (Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_proc_aclmask (Oid proc_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_language_aclmask (Oid lang_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_largeobject_aclmask_snapshot (Oid lobj_oid, Oid roleid, AclMode mask, AclMaskHow how, Snapshot snapshot)
 
AclMode pg_namespace_aclmask (Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_tablespace_aclmask (Oid spc_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_foreign_data_wrapper_aclmask (Oid fdw_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_foreign_server_aclmask (Oid srv_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclMode pg_type_aclmask (Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
AclResult pg_attribute_aclcheck (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
 
AclResult pg_attribute_aclcheck_all (Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
 
AclResult pg_class_aclcheck (Oid table_oid, Oid roleid, AclMode mode)
 
AclResult pg_database_aclcheck (Oid db_oid, Oid roleid, AclMode mode)
 
AclResult pg_proc_aclcheck (Oid proc_oid, Oid roleid, AclMode mode)
 
AclResult pg_language_aclcheck (Oid lang_oid, Oid roleid, AclMode mode)
 
AclResult pg_largeobject_aclcheck_snapshot (Oid lobj_oid, Oid roleid, AclMode mode, Snapshot snapshot)
 
AclResult pg_namespace_aclcheck (Oid nsp_oid, Oid roleid, AclMode mode)
 
AclResult pg_tablespace_aclcheck (Oid spc_oid, Oid roleid, AclMode mode)
 
AclResult pg_foreign_data_wrapper_aclcheck (Oid fdw_oid, Oid roleid, AclMode mode)
 
AclResult pg_foreign_server_aclcheck (Oid srv_oid, Oid roleid, AclMode mode)
 
AclResult pg_type_aclcheck (Oid type_oid, Oid roleid, AclMode mode)
 
bool pg_class_ownercheck (Oid class_oid, Oid roleid)
 
bool pg_type_ownercheck (Oid type_oid, Oid roleid)
 
bool pg_oper_ownercheck (Oid oper_oid, Oid roleid)
 
bool pg_proc_ownercheck (Oid proc_oid, Oid roleid)
 
bool pg_language_ownercheck (Oid lan_oid, Oid roleid)
 
bool pg_largeobject_ownercheck (Oid lobj_oid, Oid roleid)
 
bool pg_namespace_ownercheck (Oid nsp_oid, Oid roleid)
 
bool pg_tablespace_ownercheck (Oid spc_oid, Oid roleid)
 
bool pg_opclass_ownercheck (Oid opc_oid, Oid roleid)
 
bool pg_opfamily_ownercheck (Oid opf_oid, Oid roleid)
 
bool pg_ts_dict_ownercheck (Oid dict_oid, Oid roleid)
 
bool pg_ts_config_ownercheck (Oid cfg_oid, Oid roleid)
 
bool pg_foreign_data_wrapper_ownercheck (Oid srv_oid, Oid roleid)
 
bool pg_foreign_server_ownercheck (Oid srv_oid, Oid roleid)
 
bool pg_event_trigger_ownercheck (Oid et_oid, Oid roleid)
 
bool pg_database_ownercheck (Oid db_oid, Oid roleid)
 
bool pg_collation_ownercheck (Oid coll_oid, Oid roleid)
 
bool pg_conversion_ownercheck (Oid conv_oid, Oid roleid)
 
bool pg_extension_ownercheck (Oid ext_oid, Oid roleid)
 
bool pg_publication_ownercheck (Oid pub_oid, Oid roleid)
 
bool pg_subscription_ownercheck (Oid sub_oid, Oid roleid)
 
bool pg_statistics_object_ownercheck (Oid stat_oid, Oid roleid)
 
bool has_createrole_privilege (Oid roleid)
 
bool has_bypassrls_privilege (Oid roleid)
 
static Aclget_default_acl_internal (Oid roleId, Oid nsp_oid, char objtype)
 
Aclget_user_default_acl (ObjectType objtype, Oid ownerId, Oid nsp_oid)
 
void recordExtObjInitPriv (Oid objoid, Oid classoid)
 
void removeExtObjInitPriv (Oid objoid, Oid classoid)
 

Variables

bool binary_upgrade_record_init_privs = false
 

Function Documentation

◆ aclcheck_error()

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

Definition at line 3352 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(), ExecuteTruncate(), findRangeCanonicalFunction(), findRangeSubtypeDiffFunction(), get_connect_string(), get_other_operator(), get_rel_from_relname(), gin_clean_pending_list(), HandleFunctionRequest(), ImportForeignSchema(), init_sexpr(), initialize_peragg(), LockTableRecurse(), lookup_agg_function(), LookupCreationNamespace(), LookupExplicitNamespace(), MergeAttributes(), movedb(), OperatorCreate(), pg_prewarm(), pgrowlocks(), ProcedureCreate(), PublicationAddTables(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForLockTable(), RangeVarCallbackForPolicy(), RangeVarCallbackForReindexIndex(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackOwnsRelation(), RangeVarCallbackOwnsTable(), RangeVarGetAndCheckCreationNamespace(), ReindexMultipleTables(), renameatt_check(), RenameDatabase(), RenameSchema(), RenameTableSpace(), restrict_and_check_grant(), transformTableLikeClause(), truncate_check_rel(), TypeCreate(), user_mapping_ddl_aclcheck(), ValidateJoinEstimator(), and ValidateRestrictionEstimator().

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

◆ aclcheck_error_col()

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

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

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

◆ aclcheck_error_type()

void aclcheck_error_type ( AclResult  aclerr,
Oid  typeOid 
)

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

3664 {
3665  Oid element_type = get_element_type(typeOid);
3666 
3667  aclcheck_error(aclerr, OBJECT_TYPE, format_type_be(element_type ? element_type : typeOid));
3668 }
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2502
char * format_type_be(Oid type_oid)
Definition: format_type.c:320
unsigned int Oid
Definition: postgres_ext.h:31
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3352

◆ ExecAlterDefaultPrivilegesStmt()

void ExecAlterDefaultPrivilegesStmt ( ParseState pstate,
AlterDefaultPrivilegesStmt stmt 
)

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

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

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

References ACL_ALL_RIGHTS_COLUMN, ACL_NUM, aclconcat(), acldefault(), aclmembers(), Anum_pg_attribute_attacl, ATTNUM, InternalGrant::behavior, CatalogTupleUpdate(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum, InternalGrant::is_grant, MemSet, merge_acl_with_grant(), NameStr, Natts_pg_attribute, OBJECT_COLUMN, ObjectIdGetDatum, pfree(), PointerGetDatum, recordExtensionInitPriv(), RelationGetDescr, RelationRelationId, ReleaseSysCache(), restrict_and_check_grant(), SearchSysCache2(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), and values.

Referenced by ExecGrant_Relation().

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

◆ ExecGrant_Database()

static void ExecGrant_Database ( InternalGrant grantStmt)
static

Definition at line 2126 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Fdw()

static void ExecGrant_Fdw ( InternalGrant grantStmt)
static

Definition at line 2246 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_ForeignServer()

static void ExecGrant_ForeignServer ( InternalGrant grantStmt)
static

Definition at line 2373 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Function()

static void ExecGrant_Function ( InternalGrant grantStmt)
static

Definition at line 2498 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Language()

static void ExecGrant_Language ( InternalGrant grantStmt)
static

Definition at line 2621 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Largeobject()

static void ExecGrant_Largeobject ( InternalGrant grantStmt)
static

Definition at line 2752 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Namespace()

static void ExecGrant_Namespace ( InternalGrant grantStmt)
static

Definition at line 2892 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Relation()

static void ExecGrant_Relation ( InternalGrant grantStmt)
static

Definition at line 1794 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, Anum_pg_class_relacl, AttributeRelationId, InternalGrant::behavior, CatalogTupleUpdate(), InternalGrant::col_privs, AccessPriv::cols, CommandCounterIncrement(), DatumGetAclPCopy, elog, ereport, errcode(), errmsg(), ERROR, ExecGrant_Attribute(), expand_all_col_privileges(), expand_col_privileges(), FirstLowInvalidHeapAttributeNumber, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_close, heap_modify_tuple(), heap_open(), HeapTupleIsValid, i, InternalGrant::is_grant, lfirst, lfirst_oid, MemSet, merge_acl_with_grant(), NameStr, Natts_pg_class, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectIdGetDatum, InternalGrant::objects, InternalGrant::objtype, palloc0(), pfree(), PointerGetDatum, AccessPriv::priv_name, privilege_to_string(), InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, RelationRelationId, ReleaseSysCache(), RELKIND_COMPOSITE_TYPE, RELKIND_INDEX, RELKIND_PARTITIONED_INDEX, RELKIND_SEQUENCE, RELOID, restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), string_to_privilege(), SysCacheGetAttr(), HeapTupleData::t_self, updateAclDependencies(), values, and WARNING.

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Tablespace()

static void ExecGrant_Tablespace ( InternalGrant grantStmt)
static

Definition at line 3016 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrant_Type()

static void ExecGrant_Type ( InternalGrant grantStmt)
static

Definition at line 3136 of file aclchk.c.

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

Referenced by ExecGrantStmt_oids().

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

◆ ExecGrantStmt_oids()

static void ExecGrantStmt_oids ( InternalGrant istmt)
static

Definition at line 573 of file aclchk.c.

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

Referenced by ExecuteGrantStmt(), and RemoveRoleFromObjectACL().

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

◆ ExecuteGrantStmt()

void ExecuteGrantStmt ( GrantStmt stmt)

Definition at line 385 of file aclchk.c.

References ACL_ALL_RIGHTS_DATABASE, ACL_ALL_RIGHTS_FDW, ACL_ALL_RIGHTS_FOREIGN_SERVER, ACL_ALL_RIGHTS_FUNCTION, ACL_ALL_RIGHTS_LANGUAGE, ACL_ALL_RIGHTS_LARGEOBJECT, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SCHEMA, ACL_ALL_RIGHTS_SEQUENCE, ACL_ALL_RIGHTS_TABLESPACE, ACL_ALL_RIGHTS_TYPE, ACL_ID_PUBLIC, ACL_NO_RIGHTS, ACL_TARGET_ALL_IN_SCHEMA, ACL_TARGET_OBJECT, InternalGrant::all_privs, InternalGrant::behavior, GrantStmt::behavior, InternalGrant::col_privs, AccessPriv::cols, elog, ereport, errcode(), errmsg(), ERROR, ExecGrantStmt_oids(), get_rolespec_oid(), gettext_noop, InternalGrant::grant_option, GrantStmt::grant_option, InternalGrant::grantees, GrantStmt::grantees, InternalGrant::is_grant, GrantStmt::is_grant, lappend(), lappend_oid(), lfirst, NIL, OBJECT_DATABASE, OBJECT_DOMAIN, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TYPE, objectNamesToOids(), InternalGrant::objects, GrantStmt::objects, objectsInSchemaToOids(), InternalGrant::objtype, GrantStmt::objtype, AccessPriv::priv_name, privilege_to_string(), InternalGrant::privileges, GrantStmt::privileges, ROLESPEC_PUBLIC, RoleSpec::roletype, string_to_privilege(), and GrantStmt::targtype.

Referenced by ProcessUtilitySlow(), and standard_ProcessUtility().

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

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

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

Referenced by ExecGrant_Relation().

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

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

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

Referenced by ExecGrant_Relation().

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

◆ get_default_acl_internal()

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

Definition at line 5420 of file aclchk.c.

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

Referenced by get_user_default_acl().

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

◆ get_user_default_acl()

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

Definition at line 5452 of file aclchk.c.

References acldefault(), aclequal(), aclitemsort(), aclmerge(), DEFACLOBJ_FUNCTION, DEFACLOBJ_NAMESPACE, DEFACLOBJ_RELATION, DEFACLOBJ_SEQUENCE, DEFACLOBJ_TYPE, 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().

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

◆ getRelationsInNamespace()

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

Definition at line 877 of file aclchk.c.

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

Referenced by objectsInSchemaToOids().

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

◆ has_bypassrls_privilege()

bool has_bypassrls_privilege ( Oid  roleid)

Definition at line 5396 of file aclchk.c.

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

Referenced by check_enable_rls(), and RI_Initial_Check().

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

◆ has_createrole_privilege()

bool has_createrole_privilege ( Oid  roleid)

Definition at line 5377 of file aclchk.c.

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

Referenced by check_object_ownership(), and have_createrole_privilege().

5378 {
5379  bool result = false;
5380  HeapTuple utup;
5381 
5382  /* Superusers bypass all permission checking. */
5383  if (superuser_arg(roleid))
5384  return true;
5385 
5386  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5387  if (HeapTupleIsValid(utup))
5388  {
5389  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
5390  ReleaseSysCache(utup);
5391  }
5392  return result;
5393 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:72
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
bool superuser_arg(Oid roleid)
Definition: superuser.c:57
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77

◆ merge_acl_with_grant()

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

Definition at line 171 of file aclchk.c.

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

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

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

◆ objectNamesToOids()

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

Definition at line 637 of file aclchk.c.

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

Referenced by ExecuteGrantStmt().

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

◆ objectsInSchemaToOids()

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

Definition at line 786 of file aclchk.c.

References AccessShareLock, Anum_pg_proc_pronamespace, Anum_pg_proc_prorettype, BTEqualStrategyNumber, elog, ERROR, ForwardScanDirection, getRelationsInNamespace(), heap_beginscan_catalog(), heap_close, heap_endscan(), heap_getnext(), heap_open(), HeapTupleGetOid, InvalidOid, lappend_oid(), lfirst, list_concat(), LookupExplicitNamespace(), NIL, OBJECT_FUNCTION, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectIdGetDatum, ProcedureRelationId, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, ScanKeyInit(), and strVal.

Referenced by ExecuteGrantStmt().

787 {
788  List *objects = NIL;
789  ListCell *cell;
790 
791  foreach(cell, nspnames)
792  {
793  char *nspname = strVal(lfirst(cell));
794  Oid namespaceId;
795  List *objs;
796 
797  namespaceId = LookupExplicitNamespace(nspname, false);
798 
799  switch (objtype)
800  {
801  case OBJECT_TABLE:
802  objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
803  objects = list_concat(objects, objs);
804  objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
805  objects = list_concat(objects, objs);
806  objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
807  objects = list_concat(objects, objs);
808  objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
809  objects = list_concat(objects, objs);
811  objects = list_concat(objects, objs);
812  break;
813  case OBJECT_SEQUENCE:
814  objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
815  objects = list_concat(objects, objs);
816  break;
817  case OBJECT_FUNCTION:
818  case OBJECT_PROCEDURE:
819  case OBJECT_ROUTINE:
820  {
821  ScanKeyData key[2];
822  int keycount;
823  Relation rel;
824  HeapScanDesc scan;
825  HeapTuple tuple;
826 
827  keycount = 0;
828  ScanKeyInit(&key[keycount++],
830  BTEqualStrategyNumber, F_OIDEQ,
831  ObjectIdGetDatum(namespaceId));
832 
833  /*
834  * When looking for functions, check for return type <>0.
835  * When looking for procedures, check for return type ==0.
836  * When looking for routines, don't check the return type.
837  */
838  if (objtype == OBJECT_FUNCTION)
839  ScanKeyInit(&key[keycount++],
841  BTEqualStrategyNumber, F_OIDNE,
842  InvalidOid);
843  else if (objtype == OBJECT_PROCEDURE)
844  ScanKeyInit(&key[keycount++],
846  BTEqualStrategyNumber, F_OIDEQ,
847  InvalidOid);
848 
850  scan = heap_beginscan_catalog(rel, keycount, key);
851 
852  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
853  {
854  objects = lappend_oid(objects, HeapTupleGetOid(tuple));
855  }
856 
857  heap_endscan(scan);
859  }
860  break;
861  default:
862  /* should not happen */
863  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
864  (int) objtype);
865  }
866  }
867 
868  return objects;
869 }
#define NIL
Definition: pg_list.h:69
#define Anum_pg_proc_prorettype
Definition: pg_proc.h:108
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2853
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1568
#define ProcedureRelationId
Definition: pg_proc.h:33
#define RELKIND_MATVIEW
Definition: pg_class.h:165
#define AccessShareLock
Definition: lockdefs.h:36
#define strVal(v)
Definition: value.h:54
List * list_concat(List *list1, List *list2)
Definition: list.c:321
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: