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

Go to the source code of this file.

Data Structures

struct  InternalDefaultACL
 

Functions

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

Variables

bool binary_upgrade_record_init_privs = false
 

Function Documentation

◆ aclcheck_error()

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

Definition at line 3512 of file aclchk.c.

3514 {
3515  switch (aclerr)
3516  {
3517  case ACLCHECK_OK:
3518  /* no error, so return to caller */
3519  break;
3520  case ACLCHECK_NO_PRIV:
3521  {
3522  const char *msg = "???";
3523 
3524  switch (objtype)
3525  {
3526  case OBJECT_AGGREGATE:
3527  msg = gettext_noop("permission denied for aggregate %s");
3528  break;
3529  case OBJECT_COLLATION:
3530  msg = gettext_noop("permission denied for collation %s");
3531  break;
3532  case OBJECT_COLUMN:
3533  msg = gettext_noop("permission denied for column %s");
3534  break;
3535  case OBJECT_CONVERSION:
3536  msg = gettext_noop("permission denied for conversion %s");
3537  break;
3538  case OBJECT_DATABASE:
3539  msg = gettext_noop("permission denied for database %s");
3540  break;
3541  case OBJECT_DOMAIN:
3542  msg = gettext_noop("permission denied for domain %s");
3543  break;
3544  case OBJECT_EVENT_TRIGGER:
3545  msg = gettext_noop("permission denied for event trigger %s");
3546  break;
3547  case OBJECT_EXTENSION:
3548  msg = gettext_noop("permission denied for extension %s");
3549  break;
3550  case OBJECT_FDW:
3551  msg = gettext_noop("permission denied for foreign-data wrapper %s");
3552  break;
3553  case OBJECT_FOREIGN_SERVER:
3554  msg = gettext_noop("permission denied for foreign server %s");
3555  break;
3556  case OBJECT_FOREIGN_TABLE:
3557  msg = gettext_noop("permission denied for foreign table %s");
3558  break;
3559  case OBJECT_FUNCTION:
3560  msg = gettext_noop("permission denied for function %s");
3561  break;
3562  case OBJECT_INDEX:
3563  msg = gettext_noop("permission denied for index %s");
3564  break;
3565  case OBJECT_LANGUAGE:
3566  msg = gettext_noop("permission denied for language %s");
3567  break;
3568  case OBJECT_LARGEOBJECT:
3569  msg = gettext_noop("permission denied for large object %s");
3570  break;
3571  case OBJECT_MATVIEW:
3572  msg = gettext_noop("permission denied for materialized view %s");
3573  break;
3574  case OBJECT_OPCLASS:
3575  msg = gettext_noop("permission denied for operator class %s");
3576  break;
3577  case OBJECT_OPERATOR:
3578  msg = gettext_noop("permission denied for operator %s");
3579  break;
3580  case OBJECT_OPFAMILY:
3581  msg = gettext_noop("permission denied for operator family %s");
3582  break;
3583  case OBJECT_PARAMETER_ACL:
3584  msg = gettext_noop("permission denied for parameter %s");
3585  break;
3586  case OBJECT_POLICY:
3587  msg = gettext_noop("permission denied for policy %s");
3588  break;
3589  case OBJECT_PROCEDURE:
3590  msg = gettext_noop("permission denied for procedure %s");
3591  break;
3592  case OBJECT_PUBLICATION:
3593  msg = gettext_noop("permission denied for publication %s");
3594  break;
3595  case OBJECT_ROUTINE:
3596  msg = gettext_noop("permission denied for routine %s");
3597  break;
3598  case OBJECT_SCHEMA:
3599  msg = gettext_noop("permission denied for schema %s");
3600  break;
3601  case OBJECT_SEQUENCE:
3602  msg = gettext_noop("permission denied for sequence %s");
3603  break;
3604  case OBJECT_STATISTIC_EXT:
3605  msg = gettext_noop("permission denied for statistics object %s");
3606  break;
3607  case OBJECT_SUBSCRIPTION:
3608  msg = gettext_noop("permission denied for subscription %s");
3609  break;
3610  case OBJECT_TABLE:
3611  msg = gettext_noop("permission denied for table %s");
3612  break;
3613  case OBJECT_TABLESPACE:
3614  msg = gettext_noop("permission denied for tablespace %s");
3615  break;
3617  msg = gettext_noop("permission denied for text search configuration %s");
3618  break;
3619  case OBJECT_TSDICTIONARY:
3620  msg = gettext_noop("permission denied for text search dictionary %s");
3621  break;
3622  case OBJECT_TYPE:
3623  msg = gettext_noop("permission denied for type %s");
3624  break;
3625  case OBJECT_VIEW:
3626  msg = gettext_noop("permission denied for view %s");
3627  break;
3628  /* these currently aren't used */
3629  case OBJECT_ACCESS_METHOD:
3630  case OBJECT_AMOP:
3631  case OBJECT_AMPROC:
3632  case OBJECT_ATTRIBUTE:
3633  case OBJECT_CAST:
3634  case OBJECT_DEFAULT:
3635  case OBJECT_DEFACL:
3636  case OBJECT_DOMCONSTRAINT:
3639  case OBJECT_ROLE:
3640  case OBJECT_RULE:
3641  case OBJECT_TABCONSTRAINT:
3642  case OBJECT_TRANSFORM:
3643  case OBJECT_TRIGGER:
3644  case OBJECT_TSPARSER:
3645  case OBJECT_TSTEMPLATE:
3646  case OBJECT_USER_MAPPING:
3647  elog(ERROR, "unsupported object type %d", objtype);
3648  }
3649 
3650  ereport(ERROR,
3651  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3652  errmsg(msg, objectname)));
3653  break;
3654  }
3655  case ACLCHECK_NOT_OWNER:
3656  {
3657  const char *msg = "???";
3658 
3659  switch (objtype)
3660  {
3661  case OBJECT_AGGREGATE:
3662  msg = gettext_noop("must be owner of aggregate %s");
3663  break;
3664  case OBJECT_COLLATION:
3665  msg = gettext_noop("must be owner of collation %s");
3666  break;
3667  case OBJECT_CONVERSION:
3668  msg = gettext_noop("must be owner of conversion %s");
3669  break;
3670  case OBJECT_DATABASE:
3671  msg = gettext_noop("must be owner of database %s");
3672  break;
3673  case OBJECT_DOMAIN:
3674  msg = gettext_noop("must be owner of domain %s");
3675  break;
3676  case OBJECT_EVENT_TRIGGER:
3677  msg = gettext_noop("must be owner of event trigger %s");
3678  break;
3679  case OBJECT_EXTENSION:
3680  msg = gettext_noop("must be owner of extension %s");
3681  break;
3682  case OBJECT_FDW:
3683  msg = gettext_noop("must be owner of foreign-data wrapper %s");
3684  break;
3685  case OBJECT_FOREIGN_SERVER:
3686  msg = gettext_noop("must be owner of foreign server %s");
3687  break;
3688  case OBJECT_FOREIGN_TABLE:
3689  msg = gettext_noop("must be owner of foreign table %s");
3690  break;
3691  case OBJECT_FUNCTION:
3692  msg = gettext_noop("must be owner of function %s");
3693  break;
3694  case OBJECT_INDEX:
3695  msg = gettext_noop("must be owner of index %s");
3696  break;
3697  case OBJECT_LANGUAGE:
3698  msg = gettext_noop("must be owner of language %s");
3699  break;
3700  case OBJECT_LARGEOBJECT:
3701  msg = gettext_noop("must be owner of large object %s");
3702  break;
3703  case OBJECT_MATVIEW:
3704  msg = gettext_noop("must be owner of materialized view %s");
3705  break;
3706  case OBJECT_OPCLASS:
3707  msg = gettext_noop("must be owner of operator class %s");
3708  break;
3709  case OBJECT_OPERATOR:
3710  msg = gettext_noop("must be owner of operator %s");
3711  break;
3712  case OBJECT_OPFAMILY:
3713  msg = gettext_noop("must be owner of operator family %s");
3714  break;
3715  case OBJECT_PROCEDURE:
3716  msg = gettext_noop("must be owner of procedure %s");
3717  break;
3718  case OBJECT_PUBLICATION:
3719  msg = gettext_noop("must be owner of publication %s");
3720  break;
3721  case OBJECT_ROUTINE:
3722  msg = gettext_noop("must be owner of routine %s");
3723  break;
3724  case OBJECT_SEQUENCE:
3725  msg = gettext_noop("must be owner of sequence %s");
3726  break;
3727  case OBJECT_SUBSCRIPTION:
3728  msg = gettext_noop("must be owner of subscription %s");
3729  break;
3730  case OBJECT_TABLE:
3731  msg = gettext_noop("must be owner of table %s");
3732  break;
3733  case OBJECT_TYPE:
3734  msg = gettext_noop("must be owner of type %s");
3735  break;
3736  case OBJECT_VIEW:
3737  msg = gettext_noop("must be owner of view %s");
3738  break;
3739  case OBJECT_SCHEMA:
3740  msg = gettext_noop("must be owner of schema %s");
3741  break;
3742  case OBJECT_STATISTIC_EXT:
3743  msg = gettext_noop("must be owner of statistics object %s");
3744  break;
3745  case OBJECT_TABLESPACE:
3746  msg = gettext_noop("must be owner of tablespace %s");
3747  break;
3749  msg = gettext_noop("must be owner of text search configuration %s");
3750  break;
3751  case OBJECT_TSDICTIONARY:
3752  msg = gettext_noop("must be owner of text search dictionary %s");
3753  break;
3754 
3755  /*
3756  * Special cases: For these, the error message talks
3757  * about "relation", because that's where the
3758  * ownership is attached. See also
3759  * check_object_ownership().
3760  */
3761  case OBJECT_COLUMN:
3762  case OBJECT_POLICY:
3763  case OBJECT_RULE:
3764  case OBJECT_TABCONSTRAINT:
3765  case OBJECT_TRIGGER:
3766  msg = gettext_noop("must be owner of relation %s");
3767  break;
3768  /* these currently aren't used */
3769  case OBJECT_ACCESS_METHOD:
3770  case OBJECT_AMOP:
3771  case OBJECT_AMPROC:
3772  case OBJECT_ATTRIBUTE:
3773  case OBJECT_CAST:
3774  case OBJECT_DEFAULT:
3775  case OBJECT_DEFACL:
3776  case OBJECT_DOMCONSTRAINT:
3777  case OBJECT_PARAMETER_ACL:
3780  case OBJECT_ROLE:
3781  case OBJECT_TRANSFORM:
3782  case OBJECT_TSPARSER:
3783  case OBJECT_TSTEMPLATE:
3784  case OBJECT_USER_MAPPING:
3785  elog(ERROR, "unsupported object type %d", objtype);
3786  }
3787 
3788  ereport(ERROR,
3789  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3790  errmsg(msg, objectname)));
3791  break;
3792  }
3793  default:
3794  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3795  break;
3796  }
3797 }
@ ACLCHECK_NO_PRIV
Definition: acl.h:183
@ ACLCHECK_OK
Definition: acl.h:182
@ ACLCHECK_NOT_OWNER
Definition: acl.h:184
#define gettext_noop(x)
Definition: c.h:1194
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define ereport(elevel,...)
Definition: elog.h:143
@ OBJECT_EVENT_TRIGGER
Definition: parsenodes.h:2148
@ OBJECT_FDW
Definition: parsenodes.h:2150
@ OBJECT_TSPARSER
Definition: parsenodes.h:2181
@ OBJECT_COLLATION
Definition: parsenodes.h:2141
@ OBJECT_USER_MAPPING
Definition: parsenodes.h:2184
@ OBJECT_ACCESS_METHOD
Definition: parsenodes.h:2134
@ OBJECT_OPCLASS
Definition: parsenodes.h:2158
@ OBJECT_DEFACL
Definition: parsenodes.h:2145
@ OBJECT_AGGREGATE
Definition: parsenodes.h:2135
@ OBJECT_MATVIEW
Definition: parsenodes.h:2157
@ OBJECT_SCHEMA
Definition: parsenodes.h:2170
@ OBJECT_POLICY
Definition: parsenodes.h:2162
@ OBJECT_OPERATOR
Definition: parsenodes.h:2159
@ OBJECT_FOREIGN_TABLE
Definition: parsenodes.h:2152
@ OBJECT_TSCONFIGURATION
Definition: parsenodes.h:2179
@ OBJECT_OPFAMILY
Definition: parsenodes.h:2160
@ OBJECT_DOMAIN
Definition: parsenodes.h:2146
@ OBJECT_COLUMN
Definition: parsenodes.h:2140
@ OBJECT_TABLESPACE
Definition: parsenodes.h:2176
@ OBJECT_ROLE
Definition: parsenodes.h:2167
@ OBJECT_ROUTINE
Definition: parsenodes.h:2168
@ OBJECT_LARGEOBJECT
Definition: parsenodes.h:2156
@ OBJECT_PUBLICATION_NAMESPACE
Definition: parsenodes.h:2165
@ OBJECT_PROCEDURE
Definition: parsenodes.h:2163
@ OBJECT_EXTENSION
Definition: parsenodes.h:2149
@ OBJECT_INDEX
Definition: parsenodes.h:2154
@ OBJECT_DEFAULT
Definition: parsenodes.h:2144
@ OBJECT_DATABASE
Definition: parsenodes.h:2143
@ OBJECT_SEQUENCE
Definition: parsenodes.h:2171
@ OBJECT_TSTEMPLATE
Definition: parsenodes.h:2182
@ OBJECT_LANGUAGE
Definition: parsenodes.h:2155
@ OBJECT_AMOP
Definition: parsenodes.h:2136
@ OBJECT_PUBLICATION_REL
Definition: parsenodes.h:2166
@ OBJECT_FOREIGN_SERVER
Definition: parsenodes.h:2151
@ OBJECT_TSDICTIONARY
Definition: parsenodes.h:2180
@ OBJECT_ATTRIBUTE
Definition: parsenodes.h:2138
@ OBJECT_PUBLICATION
Definition: parsenodes.h:2164
@ OBJECT_RULE
Definition: parsenodes.h:2169
@ OBJECT_CONVERSION
Definition: parsenodes.h:2142
@ OBJECT_AMPROC
Definition: parsenodes.h:2137
@ OBJECT_TABLE
Definition: parsenodes.h:2175
@ OBJECT_VIEW
Definition: parsenodes.h:2185
@ OBJECT_PARAMETER_ACL
Definition: parsenodes.h:2161
@ OBJECT_TYPE
Definition: parsenodes.h:2183
@ OBJECT_FUNCTION
Definition: parsenodes.h:2153
@ OBJECT_TABCONSTRAINT
Definition: parsenodes.h:2174
@ OBJECT_DOMCONSTRAINT
Definition: parsenodes.h:2147
@ OBJECT_SUBSCRIPTION
Definition: parsenodes.h:2172
@ OBJECT_STATISTIC_EXT
Definition: parsenodes.h:2173
@ OBJECT_CAST
Definition: parsenodes.h:2139
@ OBJECT_TRIGGER
Definition: parsenodes.h:2178
@ OBJECT_TRANSFORM
Definition: parsenodes.h:2177

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

◆ aclcheck_error_col()

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

Definition at line 3801 of file aclchk.c.

3803 {
3804  switch (aclerr)
3805  {
3806  case ACLCHECK_OK:
3807  /* no error, so return to caller */
3808  break;
3809  case ACLCHECK_NO_PRIV:
3810  ereport(ERROR,
3811  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3812  errmsg("permission denied for column \"%s\" of relation \"%s\"",
3813  colname, objectname)));
3814  break;
3815  case ACLCHECK_NOT_OWNER:
3816  /* relation msg is OK since columns don't have separate owners */
3817  aclcheck_error(aclerr, objtype, objectname);
3818  break;
3819  default:
3820  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3821  break;
3822  }
3823 }
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3512

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

Referenced by restrict_and_check_grant().

◆ aclcheck_error_type()

void aclcheck_error_type ( AclResult  aclerr,
Oid  typeOid 
)

◆ ExecAlterDefaultPrivilegesStmt()

void ExecAlterDefaultPrivilegesStmt ( ParseState pstate,
AlterDefaultPrivilegesStmt stmt 
)

Definition at line 950 of file aclchk.c.

951 {
952  GrantStmt *action = stmt->action;
953  InternalDefaultACL iacls;
954  ListCell *cell;
955  List *rolespecs = NIL;
956  List *nspnames = NIL;
957  DefElem *drolespecs = NULL;
958  DefElem *dnspnames = NULL;
959  AclMode all_privileges;
960  const char *errormsg;
961 
962  /* Deconstruct the "options" part of the statement */
963  foreach(cell, stmt->options)
964  {
965  DefElem *defel = (DefElem *) lfirst(cell);
966 
967  if (strcmp(defel->defname, "schemas") == 0)
968  {
969  if (dnspnames)
970  errorConflictingDefElem(defel, pstate);
971  dnspnames = defel;
972  }
973  else if (strcmp(defel->defname, "roles") == 0)
974  {
975  if (drolespecs)
976  errorConflictingDefElem(defel, pstate);
977  drolespecs = defel;
978  }
979  else
980  elog(ERROR, "option \"%s\" not recognized", defel->defname);
981  }
982 
983  if (dnspnames)
984  nspnames = (List *) dnspnames->arg;
985  if (drolespecs)
986  rolespecs = (List *) drolespecs->arg;
987 
988  /* Prepare the InternalDefaultACL representation of the statement */
989  /* roleid to be filled below */
990  /* nspid to be filled in SetDefaultACLsInSchemas */
991  iacls.is_grant = action->is_grant;
992  iacls.objtype = action->objtype;
993  /* all_privs to be filled below */
994  /* privileges to be filled below */
995  iacls.grantees = NIL; /* filled below */
996  iacls.grant_option = action->grant_option;
997  iacls.behavior = action->behavior;
998 
999  /*
1000  * Convert the RoleSpec list into an Oid list. Note that at this point we
1001  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
1002  * there shouldn't be any additional work needed to support this case.
1003  */
1004  foreach(cell, action->grantees)
1005  {
1006  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
1007  Oid grantee_uid;
1008 
1009  switch (grantee->roletype)
1010  {
1011  case ROLESPEC_PUBLIC:
1012  grantee_uid = ACL_ID_PUBLIC;
1013  break;
1014  default:
1015  grantee_uid = get_rolespec_oid(grantee, false);
1016  break;
1017  }
1018  iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
1019  }
1020 
1021  /*
1022  * Convert action->privileges, a list of privilege strings, into an
1023  * AclMode bitmask.
1024  */
1025  switch (action->objtype)
1026  {
1027  case OBJECT_TABLE:
1028  all_privileges = ACL_ALL_RIGHTS_RELATION;
1029  errormsg = gettext_noop("invalid privilege type %s for relation");
1030  break;
1031  case OBJECT_SEQUENCE:
1032  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1033  errormsg = gettext_noop("invalid privilege type %s for sequence");
1034  break;
1035  case OBJECT_FUNCTION:
1036  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1037  errormsg = gettext_noop("invalid privilege type %s for function");
1038  break;
1039  case OBJECT_PROCEDURE:
1040  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1041  errormsg = gettext_noop("invalid privilege type %s for procedure");
1042  break;
1043  case OBJECT_ROUTINE:
1044  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1045  errormsg = gettext_noop("invalid privilege type %s for routine");
1046  break;
1047  case OBJECT_TYPE:
1048  all_privileges = ACL_ALL_RIGHTS_TYPE;
1049  errormsg = gettext_noop("invalid privilege type %s for type");
1050  break;
1051  case OBJECT_SCHEMA:
1052  all_privileges = ACL_ALL_RIGHTS_SCHEMA;
1053  errormsg = gettext_noop("invalid privilege type %s for schema");
1054  break;
1055  default:
1056  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
1057  (int) action->objtype);
1058  /* keep compiler quiet */
1059  all_privileges = ACL_NO_RIGHTS;
1060  errormsg = NULL;
1061  }
1062 
1063  if (action->privileges == NIL)
1064  {
1065  iacls.all_privs = true;
1066 
1067  /*
1068  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
1069  * depending on the object type
1070  */
1071  iacls.privileges = ACL_NO_RIGHTS;
1072  }
1073  else
1074  {
1075  iacls.all_privs = false;
1076  iacls.privileges = ACL_NO_RIGHTS;
1077 
1078  foreach(cell, action->privileges)
1079  {
1080  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
1081  AclMode priv;
1082 
1083  if (privnode->cols)
1084  ereport(ERROR,
1085  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1086  errmsg("default privileges cannot be set for columns")));
1087 
1088  if (privnode->priv_name == NULL) /* parser mistake? */
1089  elog(ERROR, "AccessPriv node must specify privilege");
1090  priv = string_to_privilege(privnode->priv_name);
1091 
1092  if (priv & ~((AclMode) all_privileges))
1093  ereport(ERROR,
1094  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1095  errmsg(errormsg, privilege_to_string(priv))));
1096 
1097  iacls.privileges |= priv;
1098  }
1099  }
1100 
1101  if (rolespecs == NIL)
1102  {
1103  /* Set permissions for myself */
1104  iacls.roleid = GetUserId();
1105 
1106  SetDefaultACLsInSchemas(&iacls, nspnames);
1107  }
1108  else
1109  {
1110  /* Look up the role OIDs and do permissions checks */
1111  ListCell *rolecell;
1112 
1113  foreach(rolecell, rolespecs)
1114  {
1115  RoleSpec *rolespec = lfirst(rolecell);
1116 
1117  iacls.roleid = get_rolespec_oid(rolespec, false);
1118 
1119  /*
1120  * We insist that calling user be a member of each target role. If
1121  * he has that, he could become that role anyway via SET ROLE, so
1122  * FOR ROLE is just a syntactic convenience and doesn't give any
1123  * special privileges.
1124  */
1126 
1127  SetDefaultACLsInSchemas(&iacls, nspnames);
1128  }
1129  }
1130 }
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:5003
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5211
#define ACL_ALL_RIGHTS_SCHEMA
Definition: acl.h:168
#define ACL_ALL_RIGHTS_SEQUENCE
Definition: acl.h:160
#define ACL_ALL_RIGHTS_FUNCTION
Definition: acl.h:164
#define ACL_ALL_RIGHTS_TYPE
Definition: acl.h:170
#define ACL_ALL_RIGHTS_RELATION
Definition: acl.h:159
#define ACL_ID_PUBLIC
Definition: acl.h:46
static AclMode string_to_privilege(const char *privname)
Definition: aclchk.c:3426
static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
Definition: aclchk.c:1138
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:3467
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:352
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
Oid GetUserId(void)
Definition: miscinit.c:492
@ ROLESPEC_PUBLIC
Definition: parsenodes.h:352
#define ACL_NO_RIGHTS
Definition: parsenodes.h:97
uint32 AclMode
Definition: parsenodes.h:80
#define lfirst(lc)
Definition: pg_list.h:169
#define NIL
Definition: pg_list.h:65
char * priv_name
Definition: parsenodes.h:2422
List * cols
Definition: parsenodes.h:2423
char * defname
Definition: parsenodes.h:765
Node * arg
Definition: parsenodes.h:766
bool grant_option
Definition: aclchk.c:94
AclMode privileges
Definition: aclchk.c:92
List * grantees
Definition: aclchk.c:93
DropBehavior behavior
Definition: aclchk.c:95
ObjectType objtype
Definition: aclchk.c:90
Definition: pg_list.h:51
RoleSpecType roletype
Definition: parsenodes.h:358

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, check_is_member_of_role(), AccessPriv::cols, DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), get_rolespec_oid(), gettext_noop, GetUserId(), InternalDefaultACL::grant_option, InternalDefaultACL::grantees, if(), InternalDefaultACL::is_grant, lappend_oid(), lfirst, NIL, OBJECT_FUNCTION, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TYPE, InternalDefaultACL::objtype, AlterDefaultPrivilegesStmt::options, AccessPriv::priv_name, privilege_to_string(), InternalDefaultACL::privileges, InternalDefaultACL::roleid, ROLESPEC_PUBLIC, RoleSpec::roletype, SetDefaultACLsInSchemas(), and string_to_privilege().

Referenced by ProcessUtilitySlow().

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

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

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

Referenced by ExecGrant_Relation().

◆ ExecGrant_Database()

static void ExecGrant_Database ( InternalGrant grantStmt)
static

Definition at line 2130 of file aclchk.c.

2131 {
2132  Relation relation;
2133  ListCell *cell;
2134 
2135  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2136  istmt->privileges = ACL_ALL_RIGHTS_DATABASE;
2137 
2138  relation = table_open(DatabaseRelationId, RowExclusiveLock);
2139 
2140  foreach(cell, istmt->objects)
2141  {
2142  Oid datId = lfirst_oid(cell);
2143  Form_pg_database pg_database_tuple;
2144  Datum aclDatum;
2145  bool isNull;
2146  AclMode avail_goptions;
2147  AclMode this_privileges;
2148  Acl *old_acl;
2149  Acl *new_acl;
2150  Oid grantorId;
2151  Oid ownerId;
2152  HeapTuple newtuple;
2153  Datum values[Natts_pg_database];
2154  bool nulls[Natts_pg_database];
2155  bool replaces[Natts_pg_database];
2156  int noldmembers;
2157  int nnewmembers;
2158  Oid *oldmembers;
2159  Oid *newmembers;
2160  HeapTuple tuple;
2161 
2162  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(datId));
2163  if (!HeapTupleIsValid(tuple))
2164  elog(ERROR, "cache lookup failed for database %u", datId);
2165 
2166  pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
2167 
2168  /*
2169  * Get owner ID and working copy of existing ACL. If there's no ACL,
2170  * substitute the proper default.
2171  */
2172  ownerId = pg_database_tuple->datdba;
2173  aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
2174  RelationGetDescr(relation), &isNull);
2175  if (isNull)
2176  {
2177  old_acl = acldefault(OBJECT_DATABASE, ownerId);
2178  /* There are no old member roles according to the catalogs */
2179  noldmembers = 0;
2180  oldmembers = NULL;
2181  }
2182  else
2183  {
2184  old_acl = DatumGetAclPCopy(aclDatum);
2185  /* Get the roles mentioned in the existing ACL */
2186  noldmembers = aclmembers(old_acl, &oldmembers);
2187  }
2188 
2189  /* Determine ID to do the grant as, and available grant options */
2190  select_best_grantor(GetUserId(), istmt->privileges,
2191  old_acl, ownerId,
2192  &grantorId, &avail_goptions);
2193 
2194  /*
2195  * Restrict the privileges to what we can actually grant, and emit the
2196  * standards-mandated warning and error messages.
2197  */
2198  this_privileges =
2199  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2200  istmt->all_privs, istmt->privileges,
2201  datId, grantorId, OBJECT_DATABASE,
2202  NameStr(pg_database_tuple->datname),
2203  0, NULL);
2204 
2205  /*
2206  * Generate new ACL.
2207  */
2208  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2209  istmt->grant_option, istmt->behavior,
2210  istmt->grantees, this_privileges,
2211  grantorId, ownerId);
2212 
2213  /*
2214  * We need the members of both old and new ACLs so we can correct the
2215  * shared dependency information.
2216  */
2217  nnewmembers = aclmembers(new_acl, &newmembers);
2218 
2219  /* finished building new ACL value, now insert it */
2220  MemSet(values, 0, sizeof(values));
2221  MemSet(nulls, false, sizeof(nulls));
2222  MemSet(replaces, false, sizeof(replaces));
2223 
2224  replaces[Anum_pg_database_datacl - 1] = true;
2225  values[Anum_pg_database_datacl - 1] = PointerGetDatum(new_acl);
2226 
2227  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2228  nulls, replaces);
2229 
2230  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2231 
2232  /* Update the shared dependency ACL info */
2233  updateAclDependencies(DatabaseRelationId, pg_database_tuple->oid, 0,
2234  ownerId,
2235  noldmembers, oldmembers,
2236  nnewmembers, newmembers);
2237 
2238  ReleaseSysCache(tuple);
2239 
2240  pfree(new_acl);
2241 
2242  /* prevent error when processing duplicate objects */
2244  }
2245 
2246  table_close(relation, RowExclusiveLock);
2247 }
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:161
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:788
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_database * Form_pg_database
Definition: pg_database.h:87
#define lfirst_oid(lc)
Definition: pg_list.h:171
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
@ DATABASEOID
Definition: syscache.h:55
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void CommandCounterIncrement(void)
Definition: xact.c:1074

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

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_Fdw()

static void ExecGrant_Fdw ( InternalGrant grantStmt)
static

Definition at line 2250 of file aclchk.c.

2251 {
2252  Relation relation;
2253  ListCell *cell;
2254 
2255  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2256  istmt->privileges = ACL_ALL_RIGHTS_FDW;
2257 
2258  relation = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
2259 
2260  foreach(cell, istmt->objects)
2261  {
2262  Oid fdwid = lfirst_oid(cell);
2263  Form_pg_foreign_data_wrapper pg_fdw_tuple;
2264  Datum aclDatum;
2265  bool isNull;
2266  AclMode avail_goptions;
2267  AclMode this_privileges;
2268  Acl *old_acl;
2269  Acl *new_acl;
2270  Oid grantorId;
2271  Oid ownerId;
2272  HeapTuple tuple;
2273  HeapTuple newtuple;
2274  Datum values[Natts_pg_foreign_data_wrapper];
2275  bool nulls[Natts_pg_foreign_data_wrapper];
2276  bool replaces[Natts_pg_foreign_data_wrapper];
2277  int noldmembers;
2278  int nnewmembers;
2279  Oid *oldmembers;
2280  Oid *newmembers;
2281 
2283  ObjectIdGetDatum(fdwid));
2284  if (!HeapTupleIsValid(tuple))
2285  elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
2286 
2287  pg_fdw_tuple = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
2288 
2289  /*
2290  * Get owner ID and working copy of existing ACL. If there's no ACL,
2291  * substitute the proper default.
2292  */
2293  ownerId = pg_fdw_tuple->fdwowner;
2294  aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
2295  Anum_pg_foreign_data_wrapper_fdwacl,
2296  &isNull);
2297  if (isNull)
2298  {
2299  old_acl = acldefault(OBJECT_FDW, ownerId);
2300  /* There are no old member roles according to the catalogs */
2301  noldmembers = 0;
2302  oldmembers = NULL;
2303  }
2304  else
2305  {
2306  old_acl = DatumGetAclPCopy(aclDatum);
2307  /* Get the roles mentioned in the existing ACL */
2308  noldmembers = aclmembers(old_acl, &oldmembers);
2309  }
2310 
2311  /* Determine ID to do the grant as, and available grant options */
2312  select_best_grantor(GetUserId(), istmt->privileges,
2313  old_acl, ownerId,
2314  &grantorId, &avail_goptions);
2315 
2316  /*
2317  * Restrict the privileges to what we can actually grant, and emit the
2318  * standards-mandated warning and error messages.
2319  */
2320  this_privileges =
2321  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2322  istmt->all_privs, istmt->privileges,
2323  fdwid, grantorId, OBJECT_FDW,
2324  NameStr(pg_fdw_tuple->fdwname),
2325  0, NULL);
2326 
2327  /*
2328  * Generate new ACL.
2329  */
2330  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2331  istmt->grant_option, istmt->behavior,
2332  istmt->grantees, this_privileges,
2333  grantorId, ownerId);
2334 
2335  /*
2336  * We need the members of both old and new ACLs so we can correct the
2337  * shared dependency information.
2338  */
2339  nnewmembers = aclmembers(new_acl, &newmembers);
2340 
2341  /* finished building new ACL value, now insert it */
2342  MemSet(values, 0, sizeof(values));
2343  MemSet(nulls, false, sizeof(nulls));
2344  MemSet(replaces, false, sizeof(replaces));
2345 
2346  replaces[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
2347  values[Anum_pg_foreign_data_wrapper_fdwacl - 1] = PointerGetDatum(new_acl);
2348 
2349  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2350  nulls, replaces);
2351 
2352  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2353 
2354  /* Update initial privileges for extensions */
2355  recordExtensionInitPriv(fdwid, ForeignDataWrapperRelationId, 0,
2356  new_acl);
2357 
2358  /* Update the shared dependency ACL info */
2359  updateAclDependencies(ForeignDataWrapperRelationId,
2360  pg_fdw_tuple->oid, 0,
2361  ownerId,
2362  noldmembers, oldmembers,
2363  nnewmembers, newmembers);
2364 
2365  ReleaseSysCache(tuple);
2366 
2367  pfree(new_acl);
2368 
2369  /* prevent error when processing duplicate objects */
2371  }
2372 
2373  table_close(relation, RowExclusiveLock);
2374 }
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:162
FormData_pg_foreign_data_wrapper * Form_pg_foreign_data_wrapper
@ FOREIGNDATAWRAPPEROID
Definition: syscache.h:62

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

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_ForeignServer()

static void ExecGrant_ForeignServer ( InternalGrant grantStmt)
static

Definition at line 2377 of file aclchk.c.

2378 {
2379  Relation relation;
2380  ListCell *cell;
2381 
2382  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2383  istmt->privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
2384 
2385  relation = table_open(ForeignServerRelationId, RowExclusiveLock);
2386 
2387  foreach(cell, istmt->objects)
2388  {
2389  Oid srvid = lfirst_oid(cell);
2390  Form_pg_foreign_server pg_server_tuple;
2391  Datum aclDatum;
2392  bool isNull;
2393  AclMode avail_goptions;
2394  AclMode this_privileges;
2395  Acl *old_acl;
2396  Acl *new_acl;
2397  Oid grantorId;
2398  Oid ownerId;
2399  HeapTuple tuple;
2400  HeapTuple newtuple;
2401  Datum values[Natts_pg_foreign_server];
2402  bool nulls[Natts_pg_foreign_server];
2403  bool replaces[Natts_pg_foreign_server];
2404  int noldmembers;
2405  int nnewmembers;
2406  Oid *oldmembers;
2407  Oid *newmembers;
2408 
2410  if (!HeapTupleIsValid(tuple))
2411  elog(ERROR, "cache lookup failed for foreign server %u", srvid);
2412 
2413  pg_server_tuple = (Form_pg_foreign_server) GETSTRUCT(tuple);
2414 
2415  /*
2416  * Get owner ID and working copy of existing ACL. If there's no ACL,
2417  * substitute the proper default.
2418  */
2419  ownerId = pg_server_tuple->srvowner;
2420  aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
2421  Anum_pg_foreign_server_srvacl,
2422  &isNull);
2423  if (isNull)
2424  {
2425  old_acl = acldefault(OBJECT_FOREIGN_SERVER, ownerId);
2426  /* There are no old member roles according to the catalogs */
2427  noldmembers = 0;
2428  oldmembers = NULL;
2429  }
2430  else
2431  {
2432  old_acl = DatumGetAclPCopy(aclDatum);
2433  /* Get the roles mentioned in the existing ACL */
2434  noldmembers = aclmembers(old_acl, &oldmembers);
2435  }
2436 
2437  /* Determine ID to do the grant as, and available grant options */
2438  select_best_grantor(GetUserId(), istmt->privileges,
2439  old_acl, ownerId,
2440  &grantorId, &avail_goptions);
2441 
2442  /*
2443  * Restrict the privileges to what we can actually grant, and emit the
2444  * standards-mandated warning and error messages.
2445  */
2446  this_privileges =
2447  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2448  istmt->all_privs, istmt->privileges,
2449  srvid, grantorId, OBJECT_FOREIGN_SERVER,
2450  NameStr(pg_server_tuple->srvname),
2451  0, NULL);
2452 
2453  /*
2454  * Generate new ACL.
2455  */
2456  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2457  istmt->grant_option, istmt->behavior,
2458  istmt->grantees, this_privileges,
2459  grantorId, ownerId);
2460 
2461  /*
2462  * We need the members of both old and new ACLs so we can correct the
2463  * shared dependency information.
2464  */
2465  nnewmembers = aclmembers(new_acl, &newmembers);
2466 
2467  /* finished building new ACL value, now insert it */
2468  MemSet(values, 0, sizeof(values));
2469  MemSet(nulls, false, sizeof(nulls));
2470  MemSet(replaces, false, sizeof(replaces));
2471 
2472  replaces[Anum_pg_foreign_server_srvacl - 1] = true;
2473  values[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(new_acl);
2474 
2475  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2476  nulls, replaces);
2477 
2478  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2479 
2480  /* Update initial privileges for extensions */
2481  recordExtensionInitPriv(srvid, ForeignServerRelationId, 0, new_acl);
2482 
2483  /* Update the shared dependency ACL info */
2484  updateAclDependencies(ForeignServerRelationId,
2485  pg_server_tuple->oid, 0,
2486  ownerId,
2487  noldmembers, oldmembers,
2488  nnewmembers, newmembers);
2489 
2490  ReleaseSysCache(tuple);
2491 
2492  pfree(new_acl);
2493 
2494  /* prevent error when processing duplicate objects */
2496  }
2497 
2498  table_close(relation, RowExclusiveLock);
2499 }
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:163
FormData_pg_foreign_server * Form_pg_foreign_server
@ FOREIGNSERVEROID
Definition: syscache.h:64

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

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_Function()

static void ExecGrant_Function ( InternalGrant grantStmt)
static

Definition at line 2502 of file aclchk.c.

2503 {
2504  Relation relation;
2505  ListCell *cell;
2506 
2507  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2508  istmt->privileges = ACL_ALL_RIGHTS_FUNCTION;
2509 
2510  relation = table_open(ProcedureRelationId, RowExclusiveLock);
2511 
2512  foreach(cell, istmt->objects)
2513  {
2514  Oid funcId = lfirst_oid(cell);
2515  Form_pg_proc pg_proc_tuple;
2516  Datum aclDatum;
2517  bool isNull;
2518  AclMode avail_goptions;
2519  AclMode this_privileges;
2520  Acl *old_acl;
2521  Acl *new_acl;
2522  Oid grantorId;
2523  Oid ownerId;
2524  HeapTuple tuple;
2525  HeapTuple newtuple;
2526  Datum values[Natts_pg_proc];
2527  bool nulls[Natts_pg_proc];
2528  bool replaces[Natts_pg_proc];
2529  int noldmembers;
2530  int nnewmembers;
2531  Oid *oldmembers;
2532  Oid *newmembers;
2533 
2534  tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
2535  if (!HeapTupleIsValid(tuple))
2536  elog(ERROR, "cache lookup failed for function %u", funcId);
2537 
2538  pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
2539 
2540  /*
2541  * Get owner ID and working copy of existing ACL. If there's no ACL,
2542  * substitute the proper default.
2543  */
2544  ownerId = pg_proc_tuple->proowner;
2545  aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
2546  &isNull);
2547  if (isNull)
2548  {
2549  old_acl = acldefault(OBJECT_FUNCTION, ownerId);
2550  /* There are no old member roles according to the catalogs */
2551  noldmembers = 0;
2552  oldmembers = NULL;
2553  }
2554  else
2555  {
2556  old_acl = DatumGetAclPCopy(aclDatum);
2557  /* Get the roles mentioned in the existing ACL */
2558  noldmembers = aclmembers(old_acl, &oldmembers);
2559  }
2560 
2561  /* Determine ID to do the grant as, and available grant options */
2562  select_best_grantor(GetUserId(), istmt->privileges,
2563  old_acl, ownerId,
2564  &grantorId, &avail_goptions);
2565 
2566  /*
2567  * Restrict the privileges to what we can actually grant, and emit the
2568  * standards-mandated warning and error messages.
2569  */
2570  this_privileges =
2571  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2572  istmt->all_privs, istmt->privileges,
2573  funcId, grantorId, OBJECT_FUNCTION,
2574  NameStr(pg_proc_tuple->proname),
2575  0, NULL);
2576 
2577  /*
2578  * Generate new ACL.
2579  */
2580  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2581  istmt->grant_option, istmt->behavior,
2582  istmt->grantees, this_privileges,
2583  grantorId, ownerId);
2584 
2585  /*
2586  * We need the members of both old and new ACLs so we can correct the
2587  * shared dependency information.
2588  */
2589  nnewmembers = aclmembers(new_acl, &newmembers);
2590 
2591  /* finished building new ACL value, now insert it */
2592  MemSet(values, 0, sizeof(values));
2593  MemSet(nulls, false, sizeof(nulls));
2594  MemSet(replaces, false, sizeof(replaces));
2595 
2596  replaces[Anum_pg_proc_proacl - 1] = true;
2597  values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
2598 
2599  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2600  nulls, replaces);
2601 
2602  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2603 
2604  /* Update initial privileges for extensions */
2605  recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
2606 
2607  /* Update the shared dependency ACL info */
2608  updateAclDependencies(ProcedureRelationId, funcId, 0,
2609  ownerId,
2610  noldmembers, oldmembers,
2611  nnewmembers, newmembers);
2612 
2613  ReleaseSysCache(tuple);
2614 
2615  pfree(new_acl);
2616 
2617  /* prevent error when processing duplicate objects */
2619  }
2620 
2621  table_close(relation, RowExclusiveLock);
2622 }
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
@ PROCOID
Definition: syscache.h:79

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

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_Language()

static void ExecGrant_Language ( InternalGrant grantStmt)
static

Definition at line 2625 of file aclchk.c.

2626 {
2627  Relation relation;
2628  ListCell *cell;
2629 
2630  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2631  istmt->privileges = ACL_ALL_RIGHTS_LANGUAGE;
2632 
2633  relation = table_open(LanguageRelationId, RowExclusiveLock);
2634 
2635  foreach(cell, istmt->objects)
2636  {
2637  Oid langId = lfirst_oid(cell);
2638  Form_pg_language pg_language_tuple;
2639  Datum aclDatum;
2640  bool isNull;
2641  AclMode avail_goptions;
2642  AclMode this_privileges;
2643  Acl *old_acl;
2644  Acl *new_acl;
2645  Oid grantorId;
2646  Oid ownerId;
2647  HeapTuple tuple;
2648  HeapTuple newtuple;
2649  Datum values[Natts_pg_language];
2650  bool nulls[Natts_pg_language];
2651  bool replaces[Natts_pg_language];
2652  int noldmembers;
2653  int nnewmembers;
2654  Oid *oldmembers;
2655  Oid *newmembers;
2656 
2657  tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(langId));
2658  if (!HeapTupleIsValid(tuple))
2659  elog(ERROR, "cache lookup failed for language %u", langId);
2660 
2661  pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
2662 
2663  if (!pg_language_tuple->lanpltrusted)
2664  ereport(ERROR,
2665  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2666  errmsg("language \"%s\" is not trusted",
2667  NameStr(pg_language_tuple->lanname)),
2668  errdetail("GRANT and REVOKE are not allowed on untrusted languages, "
2669  "because only superusers can use untrusted languages.")));
2670 
2671  /*
2672  * Get owner ID and working copy of existing ACL. If there's no ACL,
2673  * substitute the proper default.
2674  */
2675  ownerId = pg_language_tuple->lanowner;
2676  aclDatum = SysCacheGetAttr(LANGNAME, tuple, Anum_pg_language_lanacl,
2677  &isNull);
2678  if (isNull)
2679  {
2680  old_acl = acldefault(OBJECT_LANGUAGE, ownerId);
2681  /* There are no old member roles according to the catalogs */
2682  noldmembers = 0;
2683  oldmembers = NULL;
2684  }
2685  else
2686  {
2687  old_acl = DatumGetAclPCopy(aclDatum);
2688  /* Get the roles mentioned in the existing ACL */
2689  noldmembers = aclmembers(old_acl, &oldmembers);
2690  }
2691 
2692  /* Determine ID to do the grant as, and available grant options */
2693  select_best_grantor(GetUserId(), istmt->privileges,
2694  old_acl, ownerId,
2695  &grantorId, &avail_goptions);
2696 
2697  /*
2698  * Restrict the privileges to what we can actually grant, and emit the
2699  * standards-mandated warning and error messages.
2700  */
2701  this_privileges =
2702  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2703  istmt->all_privs, istmt->privileges,
2704  langId, grantorId, OBJECT_LANGUAGE,
2705  NameStr(pg_language_tuple->lanname),
2706  0, NULL);
2707 
2708  /*
2709  * Generate new ACL.
2710  */
2711  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2712  istmt->grant_option, istmt->behavior,
2713  istmt->grantees, this_privileges,
2714  grantorId, ownerId);
2715 
2716  /*
2717  * We need the members of both old and new ACLs so we can correct the
2718  * shared dependency information.
2719  */
2720  nnewmembers = aclmembers(new_acl, &newmembers);
2721 
2722  /* finished building new ACL value, now insert it */
2723  MemSet(values, 0, sizeof(values));
2724  MemSet(nulls, false, sizeof(nulls));
2725  MemSet(replaces, false, sizeof(replaces));
2726 
2727  replaces[Anum_pg_language_lanacl - 1] = true;
2728  values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
2729 
2730  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2731  nulls, replaces);
2732 
2733  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2734 
2735  /* Update initial privileges for extensions */
2736  recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
2737 
2738  /* Update the shared dependency ACL info */
2739  updateAclDependencies(LanguageRelationId, pg_language_tuple->oid, 0,
2740  ownerId,
2741  noldmembers, oldmembers,
2742  nnewmembers, newmembers);
2743 
2744  ReleaseSysCache(tuple);
2745 
2746  pfree(new_acl);
2747 
2748  /* prevent error when processing duplicate objects */
2750  }
2751 
2752  table_close(relation, RowExclusiveLock);
2753 }
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:165
int errdetail(const char *fmt,...)
Definition: elog.c:1037
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65
@ LANGNAME
Definition: syscache.h:67
@ LANGOID
Definition: syscache.h:68

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

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_Largeobject()

static void ExecGrant_Largeobject ( InternalGrant grantStmt)
static

Definition at line 2756 of file aclchk.c.

2757 {
2758  Relation relation;
2759  ListCell *cell;
2760 
2761  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2762  istmt->privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
2763 
2764  relation = table_open(LargeObjectMetadataRelationId,
2766 
2767  foreach(cell, istmt->objects)
2768  {
2769  Oid loid = lfirst_oid(cell);
2770  Form_pg_largeobject_metadata form_lo_meta;
2771  char loname[NAMEDATALEN];
2772  Datum aclDatum;
2773  bool isNull;
2774  AclMode avail_goptions;
2775  AclMode this_privileges;
2776  Acl *old_acl;
2777  Acl *new_acl;
2778  Oid grantorId;
2779  Oid ownerId;
2780  HeapTuple newtuple;
2781  Datum values[Natts_pg_largeobject_metadata];
2782  bool nulls[Natts_pg_largeobject_metadata];
2783  bool replaces[Natts_pg_largeobject_metadata];
2784  int noldmembers;
2785  int nnewmembers;
2786  Oid *oldmembers;
2787  Oid *newmembers;
2788  ScanKeyData entry[1];
2789  SysScanDesc scan;
2790  HeapTuple tuple;
2791 
2792  /* There's no syscache for pg_largeobject_metadata */
2793  ScanKeyInit(&entry[0],
2794  Anum_pg_largeobject_metadata_oid,
2795  BTEqualStrategyNumber, F_OIDEQ,
2796  ObjectIdGetDatum(loid));
2797 
2798  scan = systable_beginscan(relation,
2799  LargeObjectMetadataOidIndexId, true,
2800  NULL, 1, entry);
2801 
2802  tuple = systable_getnext(scan);
2803  if (!HeapTupleIsValid(tuple))
2804  elog(ERROR, "could not find tuple for large object %u", loid);
2805 
2806  form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
2807 
2808  /*
2809  * Get owner ID and working copy of existing ACL. If there's no ACL,
2810  * substitute the proper default.
2811  */
2812  ownerId = form_lo_meta->lomowner;
2813  aclDatum = heap_getattr(tuple,
2814  Anum_pg_largeobject_metadata_lomacl,
2815  RelationGetDescr(relation), &isNull);
2816  if (isNull)
2817  {
2818  old_acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
2819  /* There are no old member roles according to the catalogs */
2820  noldmembers = 0;
2821  oldmembers = NULL;
2822  }
2823  else
2824  {
2825  old_acl = DatumGetAclPCopy(aclDatum);
2826  /* Get the roles mentioned in the existing ACL */
2827  noldmembers = aclmembers(old_acl, &oldmembers);
2828  }
2829 
2830  /* Determine ID to do the grant as, and available grant options */
2831  select_best_grantor(GetUserId(), istmt->privileges,
2832  old_acl, ownerId,
2833  &grantorId, &avail_goptions);
2834 
2835  /*
2836  * Restrict the privileges to what we can actually grant, and emit the
2837  * standards-mandated warning and error messages.
2838  */
2839  snprintf(loname, sizeof(loname), "large object %u", loid);
2840  this_privileges =
2841  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2842  istmt->all_privs, istmt->privileges,
2843  loid, grantorId, OBJECT_LARGEOBJECT,
2844  loname, 0, NULL);
2845 
2846  /*
2847  * Generate new ACL.
2848  */
2849  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2850  istmt->grant_option, istmt->behavior,
2851  istmt->grantees, this_privileges,
2852  grantorId, ownerId);
2853 
2854  /*
2855  * We need the members of both old and new ACLs so we can correct the
2856  * shared dependency information.
2857  */
2858  nnewmembers = aclmembers(new_acl, &newmembers);
2859 
2860  /* finished building new ACL value, now insert it */
2861  MemSet(values, 0, sizeof(values));
2862  MemSet(nulls, false, sizeof(nulls));
2863  MemSet(replaces, false, sizeof(replaces));
2864 
2865  replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
2866  values[Anum_pg_largeobject_metadata_lomacl - 1]
2867  = PointerGetDatum(new_acl);
2868 
2869  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2870  values, nulls, replaces);
2871 
2872  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2873 
2874  /* Update initial privileges for extensions */
2875  recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
2876 
2877  /* Update the shared dependency ACL info */
2878  updateAclDependencies(LargeObjectRelationId,
2879  form_lo_meta->oid, 0,
2880  ownerId,
2881  noldmembers, oldmembers,
2882  nnewmembers, newmembers);
2883 
2884  systable_endscan(scan);
2885 
2886  pfree(new_acl);
2887 
2888  /* prevent error when processing duplicate objects */
2890  }
2891 
2892  table_close(relation, RowExclusiveLock);
2893 }
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:166
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:598
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:505
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:386
#define NAMEDATALEN
FormData_pg_largeobject_metadata * Form_pg_largeobject_metadata
#define snprintf
Definition: port.h:225
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

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

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_Namespace()

static void ExecGrant_Namespace ( InternalGrant grantStmt)
static

Definition at line 2896 of file aclchk.c.

2897 {
2898  Relation relation;
2899  ListCell *cell;
2900 
2901  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2902  istmt->privileges = ACL_ALL_RIGHTS_SCHEMA;
2903 
2904  relation = table_open(NamespaceRelationId, RowExclusiveLock);
2905 
2906  foreach(cell, istmt->objects)
2907  {
2908  Oid nspid = lfirst_oid(cell);
2909  Form_pg_namespace pg_namespace_tuple;
2910  Datum aclDatum;
2911  bool isNull;
2912  AclMode avail_goptions;
2913  AclMode this_privileges;
2914  Acl *old_acl;
2915  Acl *new_acl;
2916  Oid grantorId;
2917  Oid ownerId;
2918  HeapTuple tuple;
2919  HeapTuple newtuple;
2920  Datum values[Natts_pg_namespace];
2921  bool nulls[Natts_pg_namespace];
2922  bool replaces[Natts_pg_namespace];
2923  int noldmembers;
2924  int nnewmembers;
2925  Oid *oldmembers;
2926  Oid *newmembers;
2927 
2929  if (!HeapTupleIsValid(tuple))
2930  elog(ERROR, "cache lookup failed for namespace %u", nspid);
2931 
2932  pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
2933 
2934  /*
2935  * Get owner ID and working copy of existing ACL. If there's no ACL,
2936  * substitute the proper default.
2937  */
2938  ownerId = pg_namespace_tuple->nspowner;
2939  aclDatum = SysCacheGetAttr(NAMESPACENAME, tuple,
2940  Anum_pg_namespace_nspacl,
2941  &isNull);
2942  if (isNull)
2943  {
2944  old_acl = acldefault(OBJECT_SCHEMA, ownerId);
2945  /* There are no old member roles according to the catalogs */
2946  noldmembers = 0;
2947  oldmembers = NULL;
2948  }
2949  else
2950  {
2951  old_acl = DatumGetAclPCopy(aclDatum);
2952  /* Get the roles mentioned in the existing ACL */
2953  noldmembers = aclmembers(old_acl, &oldmembers);
2954  }
2955 
2956  /* Determine ID to do the grant as, and available grant options */
2957  select_best_grantor(GetUserId(), istmt->privileges,
2958  old_acl, ownerId,
2959  &grantorId, &avail_goptions);
2960 
2961  /*
2962  * Restrict the privileges to what we can actually grant, and emit the
2963  * standards-mandated warning and error messages.
2964  */
2965  this_privileges =
2966  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2967  istmt->all_privs, istmt->privileges,
2968  nspid, grantorId, OBJECT_SCHEMA,
2969  NameStr(pg_namespace_tuple->nspname),
2970  0, NULL);
2971 
2972  /*
2973  * Generate new ACL.
2974  */
2975  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2976  istmt->grant_option, istmt->behavior,
2977  istmt->grantees, this_privileges,
2978  grantorId, ownerId);
2979 
2980  /*
2981  * We need the members of both old and new ACLs so we can correct the
2982  * shared dependency information.
2983  */
2984  nnewmembers = aclmembers(new_acl, &newmembers);
2985 
2986  /* finished building new ACL value, now insert it */
2987  MemSet(values, 0, sizeof(values));
2988  MemSet(nulls, false, sizeof(nulls));
2989  MemSet(replaces, false, sizeof(replaces));
2990 
2991  replaces[Anum_pg_namespace_nspacl - 1] = true;
2992  values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(new_acl);
2993 
2994  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2995  nulls, replaces);
2996 
2997  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2998 
2999  /* Update initial privileges for extensions */
3000  recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
3001 
3002  /* Update the shared dependency ACL info */
3003  updateAclDependencies(NamespaceRelationId, pg_namespace_tuple->oid, 0,
3004  ownerId,
3005  noldmembers, oldmembers,
3006  nnewmembers, newmembers);
3007 
3008  ReleaseSysCache(tuple);
3009 
3010  pfree(new_acl);
3011 
3012  /* prevent error when processing duplicate objects */
3014  }
3015 
3016  table_close(relation, RowExclusiveLock);
3017 }
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:52
@ NAMESPACEOID
Definition: syscache.h:70
@ NAMESPACENAME
Definition: syscache.h:69

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

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_Parameter()

static void ExecGrant_Parameter ( InternalGrant grantStmt)
static

Definition at line 3277 of file aclchk.c.

3278 {
3279  Relation relation;
3280  ListCell *cell;
3281 
3282  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
3283  istmt->privileges = ACL_ALL_RIGHTS_PARAMETER_ACL;
3284 
3285  relation = table_open(ParameterAclRelationId, RowExclusiveLock);
3286 
3287  foreach(cell, istmt->objects)
3288  {
3289  Oid parameterId = lfirst_oid(cell);
3290  Datum nameDatum;
3291  const char *parname;
3292  Datum aclDatum;
3293  bool isNull;
3294  AclMode avail_goptions;
3295  AclMode this_privileges;
3296  Acl *old_acl;
3297  Acl *new_acl;
3298  Oid grantorId;
3299  Oid ownerId;
3300  HeapTuple tuple;
3301  int noldmembers;
3302  int nnewmembers;
3303  Oid *oldmembers;
3304  Oid *newmembers;
3305 
3306  tuple = SearchSysCache1(PARAMETERACLOID, ObjectIdGetDatum(parameterId));
3307  if (!HeapTupleIsValid(tuple))
3308  elog(ERROR, "cache lookup failed for parameter ACL %u",
3309  parameterId);
3310 
3311  /* We'll need the GUC's name */
3312  nameDatum = SysCacheGetAttr(PARAMETERACLOID, tuple,
3313  Anum_pg_parameter_acl_parname,
3314  &isNull);
3315  Assert(!isNull);
3316  parname = TextDatumGetCString(nameDatum);
3317 
3318  /* Treat all parameters as belonging to the bootstrap superuser. */
3319  ownerId = BOOTSTRAP_SUPERUSERID;
3320 
3321  /*
3322  * Get working copy of existing ACL. If there's no ACL, substitute the
3323  * proper default.
3324  */
3325  aclDatum = SysCacheGetAttr(PARAMETERACLOID, tuple,
3326  Anum_pg_parameter_acl_paracl,
3327  &isNull);
3328 
3329  if (isNull)
3330  {
3331  old_acl = acldefault(istmt->objtype, ownerId);
3332  /* There are no old member roles according to the catalogs */
3333  noldmembers = 0;
3334  oldmembers = NULL;
3335  }
3336  else
3337  {
3338  old_acl = DatumGetAclPCopy(aclDatum);
3339  /* Get the roles mentioned in the existing ACL */
3340  noldmembers = aclmembers(old_acl, &oldmembers);
3341  }
3342 
3343  /* Determine ID to do the grant as, and available grant options */
3344  select_best_grantor(GetUserId(), istmt->privileges,
3345  old_acl, ownerId,
3346  &grantorId, &avail_goptions);
3347 
3348  /*
3349  * Restrict the privileges to what we can actually grant, and emit the
3350  * standards-mandated warning and error messages.
3351  */
3352  this_privileges =
3353  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3354  istmt->all_privs, istmt->privileges,
3355  parameterId, grantorId,
3357  parname,
3358  0, NULL);
3359 
3360  /*
3361  * Generate new ACL.
3362  */
3363  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3364  istmt->grant_option, istmt->behavior,
3365  istmt->grantees, this_privileges,
3366  grantorId, ownerId);
3367 
3368  /*
3369  * We need the members of both old and new ACLs so we can correct the
3370  * shared dependency information.
3371  */
3372  nnewmembers = aclmembers(new_acl, &newmembers);
3373 
3374  /*
3375  * If the new ACL is equal to the default, we don't need the catalog
3376  * entry any longer. Delete it rather than updating it, to avoid
3377  * leaving a degenerate entry.
3378  */
3379  if (aclequal(new_acl, acldefault(istmt->objtype, ownerId)))
3380  {
3381  CatalogTupleDelete(relation, &tuple->t_self);
3382  }
3383  else
3384  {
3385  /* finished building new ACL value, now insert it */
3386  HeapTuple newtuple;
3387  Datum values[Natts_pg_parameter_acl];
3388  bool nulls[Natts_pg_parameter_acl];
3389  bool replaces[Natts_pg_parameter_acl];
3390 
3391  MemSet(values, 0, sizeof(values));
3392  MemSet(nulls, false, sizeof(nulls));
3393  MemSet(replaces, false, sizeof(replaces));
3394 
3395  replaces[Anum_pg_parameter_acl_paracl - 1] = true;
3396  values[Anum_pg_parameter_acl_paracl - 1] = PointerGetDatum(new_acl);
3397 
3398  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
3399  values, nulls, replaces);
3400 
3401  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3402  }
3403 
3404  /* Update initial privileges for extensions */
3405  recordExtensionInitPriv(parameterId, ParameterAclRelationId, 0,
3406  new_acl);
3407 
3408  /* Update the shared dependency ACL info */
3409  updateAclDependencies(ParameterAclRelationId, parameterId, 0,
3410  ownerId,
3411  noldmembers, oldmembers,
3412  nnewmembers, newmembers);
3413 
3414  ReleaseSysCache(tuple);
3415  pfree(new_acl);
3416 
3417  /* prevent error when processing duplicate objects */
3419  }
3420 
3421  table_close(relation, RowExclusiveLock);
3422 }
bool aclequal(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:504
#define ACL_ALL_RIGHTS_PARAMETER_ACL
Definition: acl.h:167
#define TextDatumGetCString(d)
Definition: builtins.h:86
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
Assert(fmt[strlen(fmt) - 1] !='\n')
@ PARAMETERACLOID
Definition: syscache.h:76

References ACL_ALL_RIGHTS_PARAMETER_ACL, ACL_NO_RIGHTS, acldefault(), aclequal(), aclmembers(), InternalGrant::all_privs, Assert(), InternalGrant::behavior, CatalogTupleDelete(), CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, elog, ERROR, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, MemSet, merge_acl_with_grant(), OBJECT_PARAMETER_ACL, ObjectIdGetDatum, InternalGrant::objects, InternalGrant::objtype, PARAMETERACLOID, pfree(), PointerGetDatum, InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), TextDatumGetCString, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_Relation()

static void ExecGrant_Relation ( InternalGrant grantStmt)
static

Definition at line 1798 of file aclchk.c.

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

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

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_Tablespace()

static void ExecGrant_Tablespace ( InternalGrant grantStmt)
static

Definition at line 3020 of file aclchk.c.

3021 {
3022  Relation relation;
3023  ListCell *cell;
3024 
3025  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
3026  istmt->privileges = ACL_ALL_RIGHTS_TABLESPACE;
3027 
3028  relation = table_open(TableSpaceRelationId, RowExclusiveLock);
3029 
3030  foreach(cell, istmt->objects)
3031  {
3032  Oid tblId = lfirst_oid(cell);
3033  Form_pg_tablespace pg_tablespace_tuple;
3034  Datum aclDatum;
3035  bool isNull;
3036  AclMode avail_goptions;
3037  AclMode this_privileges;
3038  Acl *old_acl;
3039  Acl *new_acl;
3040  Oid grantorId;
3041  Oid ownerId;
3042  HeapTuple newtuple;
3043  Datum values[Natts_pg_tablespace];
3044  bool nulls[Natts_pg_tablespace];
3045  bool replaces[Natts_pg_tablespace];
3046  int noldmembers;
3047  int nnewmembers;
3048  Oid *oldmembers;
3049  Oid *newmembers;
3050  HeapTuple tuple;
3051 
3052  /* Search syscache for pg_tablespace */
3054  if (!HeapTupleIsValid(tuple))
3055  elog(ERROR, "cache lookup failed for tablespace %u", tblId);
3056 
3057  pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);
3058 
3059  /*
3060  * Get owner ID and working copy of existing ACL. If there's no ACL,
3061  * substitute the proper default.
3062  */
3063  ownerId = pg_tablespace_tuple->spcowner;
3064  aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl,
3065  RelationGetDescr(relation), &isNull);
3066  if (isNull)
3067  {
3068  old_acl = acldefault(OBJECT_TABLESPACE, ownerId);
3069  /* There are no old member roles according to the catalogs */
3070  noldmembers = 0;
3071  oldmembers = NULL;
3072  }
3073  else
3074  {
3075  old_acl = DatumGetAclPCopy(aclDatum);
3076  /* Get the roles mentioned in the existing ACL */
3077  noldmembers = aclmembers(old_acl, &oldmembers);
3078  }
3079 
3080  /* Determine ID to do the grant as, and available grant options */
3081  select_best_grantor(GetUserId(), istmt->privileges,
3082  old_acl, ownerId,
3083  &grantorId, &avail_goptions);
3084 
3085  /*
3086  * Restrict the privileges to what we can actually grant, and emit the
3087  * standards-mandated warning and error messages.
3088  */
3089  this_privileges =
3090  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3091  istmt->all_privs, istmt->privileges,
3092  tblId, grantorId, OBJECT_TABLESPACE,
3093  NameStr(pg_tablespace_tuple->spcname),
3094  0, NULL);
3095 
3096  /*
3097  * Generate new ACL.
3098  */
3099  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3100  istmt->grant_option, istmt->behavior,
3101  istmt->grantees, this_privileges,
3102  grantorId, ownerId);
3103 
3104  /*
3105  * We need the members of both old and new ACLs so we can correct the
3106  * shared dependency information.
3107  */
3108  nnewmembers = aclmembers(new_acl, &newmembers);
3109 
3110  /* finished building new ACL value, now insert it */
3111  MemSet(values, 0, sizeof(values));
3112  MemSet(nulls, false, sizeof(nulls));
3113  MemSet(replaces, false, sizeof(replaces));
3114 
3115  replaces[Anum_pg_tablespace_spcacl - 1] = true;
3116  values[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(new_acl);
3117 
3118  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3119  nulls, replaces);
3120 
3121  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3122 
3123  /* Update the shared dependency ACL info */
3124  updateAclDependencies(TableSpaceRelationId, tblId, 0,
3125  ownerId,
3126  noldmembers, oldmembers,
3127  nnewmembers, newmembers);
3128 
3129  ReleaseSysCache(tuple);
3130  pfree(new_acl);
3131 
3132  /* prevent error when processing duplicate objects */
3134  }
3135 
3136  table_close(relation, RowExclusiveLock);
3137 }
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:169
FormData_pg_tablespace * Form_pg_tablespace
Definition: pg_tablespace.h:48
@ TABLESPACEOID
Definition: syscache.h:101

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

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_Type()

static void ExecGrant_Type ( InternalGrant grantStmt)
static

Definition at line 3140 of file aclchk.c.

3141 {
3142  Relation relation;
3143  ListCell *cell;
3144 
3145  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
3146  istmt->privileges = ACL_ALL_RIGHTS_TYPE;
3147 
3148  relation = table_open(TypeRelationId, RowExclusiveLock);
3149 
3150  foreach(cell, istmt->objects)
3151  {
3152  Oid typId = lfirst_oid(cell);
3153  Form_pg_type pg_type_tuple;
3154  Datum aclDatum;
3155  bool isNull;
3156  AclMode avail_goptions;
3157  AclMode this_privileges;
3158  Acl *old_acl;
3159  Acl *new_acl;
3160  Oid grantorId;
3161  Oid ownerId;
3162  HeapTuple newtuple;
3163  Datum values[Natts_pg_type];
3164  bool nulls[Natts_pg_type];
3165  bool replaces[Natts_pg_type];
3166  int noldmembers;
3167  int nnewmembers;
3168  Oid *oldmembers;
3169  Oid *newmembers;
3170  HeapTuple tuple;
3171 
3172  /* Search syscache for pg_type */
3173  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typId));
3174  if (!HeapTupleIsValid(tuple))
3175  elog(ERROR, "cache lookup failed for type %u", typId);
3176 
3177  pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
3178 
3179  if (IsTrueArrayType(pg_type_tuple))
3180  ereport(ERROR,
3181  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
3182  errmsg("cannot set privileges of array types"),
3183  errhint("Set the privileges of the element type instead.")));
3184 
3185  /* Used GRANT DOMAIN on a non-domain? */
3186  if (istmt->objtype == OBJECT_DOMAIN &&
3187  pg_type_tuple->typtype != TYPTYPE_DOMAIN)
3188  ereport(ERROR,
3189  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3190  errmsg("\"%s\" is not a domain",
3191  NameStr(pg_type_tuple->typname))));
3192 
3193  /*
3194  * Get owner ID and working copy of existing ACL. If there's no ACL,
3195  * substitute the proper default.
3196  */
3197  ownerId = pg_type_tuple->typowner;
3198  aclDatum = heap_getattr(tuple, Anum_pg_type_typacl,
3199  RelationGetDescr(relation), &isNull);
3200  if (isNull)
3201  {
3202  old_acl = acldefault(istmt->objtype, ownerId);
3203  /* There are no old member roles according to the catalogs */
3204  noldmembers = 0;
3205  oldmembers = NULL;
3206  }
3207  else
3208  {
3209  old_acl = DatumGetAclPCopy(aclDatum);
3210  /* Get the roles mentioned in the existing ACL */
3211  noldmembers = aclmembers(old_acl, &oldmembers);
3212  }
3213 
3214  /* Determine ID to do the grant as, and available grant options */
3215  select_best_grantor(GetUserId(), istmt->privileges,
3216  old_acl, ownerId,
3217  &grantorId, &avail_goptions);
3218 
3219  /*
3220  * Restrict the privileges to what we can actually grant, and emit the
3221  * standards-mandated warning and error messages.
3222  */
3223  this_privileges =
3224  restrict_and_check_grant(istmt->is_grant, avail_goptions,
3225  istmt->all_privs, istmt->privileges,
3226  typId, grantorId, OBJECT_TYPE,
3227  NameStr(pg_type_tuple->typname),
3228  0, NULL);
3229 
3230  /*
3231  * Generate new ACL.
3232  */
3233  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
3234  istmt->grant_option, istmt->behavior,
3235  istmt->grantees, this_privileges,
3236  grantorId, ownerId);
3237 
3238  /*
3239  * We need the members of both old and new ACLs so we can correct the
3240  * shared dependency information.
3241  */
3242  nnewmembers = aclmembers(new_acl, &newmembers);
3243 
3244  /* finished building new ACL value, now insert it */
3245  MemSet(values, 0, sizeof(values));
3246  MemSet(nulls, false, sizeof(nulls));
3247  MemSet(replaces, false, sizeof(replaces));
3248 
3249  replaces[Anum_pg_type_typacl - 1] = true;
3250  values[Anum_pg_type_typacl - 1] = PointerGetDatum(new_acl);
3251 
3252  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
3253  nulls, replaces);
3254 
3255  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
3256 
3257  /* Update initial privileges for extensions */
3258  recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
3259 
3260  /* Update the shared dependency ACL info */
3261  updateAclDependencies(TypeRelationId, typId, 0,
3262  ownerId,
3263  noldmembers, oldmembers,
3264  nnewmembers, newmembers);
3265 
3266  ReleaseSysCache(tuple);
3267  pfree(new_acl);
3268 
3269  /* prevent error when processing duplicate objects */
3271  }
3272 
3273  table_close(relation, RowExclusiveLock);
3274 }
int errhint(const char *fmt,...)
Definition: elog.c:1151
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
@ TYPEOID
Definition: syscache.h:114

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

Referenced by ExecGrantStmt_oids().

◆ ExecGrantStmt_oids()

static void ExecGrantStmt_oids ( InternalGrant istmt)
static

Definition at line 576 of file aclchk.c.

577 {
578  switch (istmt->objtype)
579  {
580  case OBJECT_TABLE:
581  case OBJECT_SEQUENCE:
582  ExecGrant_Relation(istmt);
583  break;
584  case OBJECT_DATABASE:
585  ExecGrant_Database(istmt);
586  break;
587  case OBJECT_DOMAIN:
588  case OBJECT_TYPE:
589  ExecGrant_Type(istmt);
590  break;
591  case OBJECT_FDW:
592  ExecGrant_Fdw(istmt);
593  break;
596  break;
597  case OBJECT_FUNCTION:
598  case OBJECT_PROCEDURE:
599  case OBJECT_ROUTINE:
600  ExecGrant_Function(istmt);
601  break;
602  case OBJECT_LANGUAGE:
603  ExecGrant_Language(istmt);
604  break;
605  case OBJECT_LARGEOBJECT:
606  ExecGrant_Largeobject(istmt);
607  break;
608  case OBJECT_SCHEMA:
609  ExecGrant_Namespace(istmt);
610  break;
611  case OBJECT_TABLESPACE:
612  ExecGrant_Tablespace(istmt);
613  break;
615  ExecGrant_Parameter(istmt);
616  break;
617  default:
618  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
619  (int) istmt->objtype);
620  }
621 
622  /*
623  * Pass the info to event triggers about the just-executed GRANT. Note
624  * that we prefer to do it after actually executing it, because that gives
625  * the functions a chance to adjust the istmt with privileges actually
626  * granted.
627  */
630 }
static void ExecGrant_Largeobject(InternalGrant *grantStmt)
Definition: aclchk.c:2756
static void ExecGrant_Namespace(InternalGrant *grantStmt)
Definition: aclchk.c:2896
static void ExecGrant_Tablespace(InternalGrant *grantStmt)
Definition: aclchk.c:3020
static void ExecGrant_Database(InternalGrant *grantStmt)
Definition: aclchk.c:2130
static void ExecGrant_Type(InternalGrant *grantStmt)
Definition: aclchk.c:3140
static void ExecGrant_Fdw(InternalGrant *grantStmt)
Definition: aclchk.c:2250
static void ExecGrant_Relation(InternalGrant *grantStmt)
Definition: aclchk.c:1798
static void ExecGrant_Parameter(InternalGrant *grantStmt)
Definition: aclchk.c:3277
static void ExecGrant_Language(InternalGrant *grantStmt)
Definition: aclchk.c:2625
static void ExecGrant_Function(InternalGrant *grantStmt)
Definition: aclchk.c:2502
static void ExecGrant_ForeignServer(InternalGrant *grantStmt)
Definition: aclchk.c:2377
bool EventTriggerSupportsObjectType(ObjectType obtype)
void EventTriggerCollectGrant(InternalGrant *istmt)
ObjectType objtype

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

Referenced by ExecuteGrantStmt(), and RemoveRoleFromObjectACL().

◆ ExecuteGrantStmt()

void ExecuteGrantStmt ( GrantStmt stmt)

Definition at line 366 of file aclchk.c.

367 {
368  InternalGrant istmt;
369  ListCell *cell;
370  const char *errormsg;
371  AclMode all_privileges;
372 
373  if (stmt->grantor)
374  {
375  Oid grantor;
376 
377  grantor = get_rolespec_oid(stmt->grantor, false);
378 
379  /*
380  * Currently, this clause is only for SQL compatibility, not very
381  * interesting otherwise.
382  */
383  if (grantor != GetUserId())
384  ereport(ERROR,
385  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
386  errmsg("grantor must be current user")));
387  }
388 
389  /*
390  * Turn the regular GrantStmt into the InternalGrant form.
391  */
392  istmt.is_grant = stmt->is_grant;
393  istmt.objtype = stmt->objtype;
394 
395  /* Collect the OIDs of the target objects */
396  switch (stmt->targtype)
397  {
398  case ACL_TARGET_OBJECT:
399  istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects,
400  stmt->is_grant);
401  break;
403  istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
404  break;
405  /* ACL_TARGET_DEFAULTS should not be seen here */
406  default:
407  elog(ERROR, "unrecognized GrantStmt.targtype: %d",
408  (int) stmt->targtype);
409  }
410 
411  /* all_privs to be filled below */
412  /* privileges to be filled below */
413  istmt.col_privs = NIL; /* may get filled below */
414  istmt.grantees = NIL; /* filled below */
415  istmt.grant_option = stmt->grant_option;
416  istmt.behavior = stmt->behavior;
417 
418  /*
419  * Convert the RoleSpec list into an Oid list. Note that at this point we
420  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
421  * there shouldn't be any additional work needed to support this case.
422  */
423  foreach(cell, stmt->grantees)
424  {
425  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
426  Oid grantee_uid;
427 
428  switch (grantee->roletype)
429  {
430  case ROLESPEC_PUBLIC:
431  grantee_uid = ACL_ID_PUBLIC;
432  break;
433  default:
434  grantee_uid = get_rolespec_oid(grantee, false);
435  break;
436  }
437  istmt.grantees = lappend_oid(istmt.grantees, grantee_uid);
438  }
439 
440  /*
441  * Convert stmt->privileges, a list of AccessPriv nodes, into an AclMode
442  * bitmask. Note: objtype can't be OBJECT_COLUMN.
443  */
444  switch (stmt->objtype)
445  {
446  case OBJECT_TABLE:
447 
448  /*
449  * Because this might be a sequence, we test both relation and
450  * sequence bits, and later do a more limited test when we know
451  * the object type.
452  */
454  errormsg = gettext_noop("invalid privilege type %s for relation");
455  break;
456  case OBJECT_SEQUENCE:
457  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
458  errormsg = gettext_noop("invalid privilege type %s for sequence");
459  break;
460  case OBJECT_DATABASE:
461  all_privileges = ACL_ALL_RIGHTS_DATABASE;
462  errormsg = gettext_noop("invalid privilege type %s for database");
463  break;
464  case OBJECT_DOMAIN:
465  all_privileges = ACL_ALL_RIGHTS_TYPE;
466  errormsg = gettext_noop("invalid privilege type %s for domain");
467  break;
468  case OBJECT_FUNCTION:
469  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
470  errormsg = gettext_noop("invalid privilege type %s for function");
471  break;
472  case OBJECT_LANGUAGE:
473  all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
474  errormsg = gettext_noop("invalid privilege type %s for language");
475  break;
476  case OBJECT_LARGEOBJECT:
477  all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
478  errormsg = gettext_noop("invalid privilege type %s for large object");
479  break;
480  case OBJECT_SCHEMA:
481  all_privileges = ACL_ALL_RIGHTS_SCHEMA;
482  errormsg = gettext_noop("invalid privilege type %s for schema");
483  break;
484  case OBJECT_PROCEDURE:
485  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
486  errormsg = gettext_noop("invalid privilege type %s for procedure");
487  break;
488  case OBJECT_ROUTINE:
489  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
490  errormsg = gettext_noop("invalid privilege type %s for routine");
491  break;
492  case OBJECT_TABLESPACE:
493  all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
494  errormsg = gettext_noop("invalid privilege type %s for tablespace");
495  break;
496  case OBJECT_TYPE:
497  all_privileges = ACL_ALL_RIGHTS_TYPE;
498  errormsg = gettext_noop("invalid privilege type %s for type");
499  break;
500  case OBJECT_FDW:
501  all_privileges = ACL_ALL_RIGHTS_FDW;
502  errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
503  break;
505  all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
506  errormsg = gettext_noop("invalid privilege type %s for foreign server");
507  break;
509  all_privileges = ACL_ALL_RIGHTS_PARAMETER_ACL;
510  errormsg = gettext_noop("invalid privilege type %s for parameter");
511  break;
512  default:
513  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
514  (int) stmt->objtype);
515  /* keep compiler quiet */
516  all_privileges = ACL_NO_RIGHTS;
517  errormsg = NULL;
518  }
519 
520  if (stmt->privileges == NIL)
521  {
522  istmt.all_privs = true;
523 
524  /*
525  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
526  * depending on the object type
527  */
528  istmt.privileges = ACL_NO_RIGHTS;
529  }
530  else
531  {
532  istmt.all_privs = false;
533  istmt.privileges = ACL_NO_RIGHTS;
534 
535  foreach(cell, stmt->privileges)
536  {
537  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
538  AclMode priv;
539 
540  /*
541  * If it's a column-level specification, we just set it aside in
542  * col_privs for the moment; but insist it's for a relation.
543  */
544  if (privnode->cols)
545  {
546  if (stmt->objtype != OBJECT_TABLE)
547  ereport(ERROR,
548  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
549  errmsg("column privileges are only valid for relations")));
550  istmt.col_privs = lappend(istmt.col_privs, privnode);
551  continue;
552  }
553 
554  if (privnode->priv_name == NULL) /* parser mistake? */
555  elog(ERROR, "AccessPriv node must specify privilege or columns");
556  priv = string_to_privilege(privnode->priv_name);
557 
558  if (priv & ~((AclMode) all_privileges))
559  ereport(ERROR,
560  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
561  errmsg(errormsg, privilege_to_string(priv))));
562 
563  istmt.privileges |= priv;
564  }
565  }
566 
567  ExecGrantStmt_oids(&istmt);
568 }
static void ExecGrantStmt_oids(InternalGrant *istmt)
Definition: aclchk.c:576
static List * objectNamesToOids(ObjectType objtype, List *objnames, bool is_grant)
Definition: aclchk.c:643
static List * objectsInSchemaToOids(ObjectType objtype, List *nspnames)
Definition: aclchk.c:823
List * lappend(List *list, void *datum)
Definition: list.c:336
@ ACL_TARGET_OBJECT
Definition: parsenodes.h:2365
@ ACL_TARGET_ALL_IN_SCHEMA
Definition: parsenodes.h:2366
ObjectType objtype
Definition: parsenodes.h:2375
bool is_grant
Definition: parsenodes.h:2373
List * objects
Definition: parsenodes.h:2376
bool grant_option
Definition: parsenodes.h:2381
List * grantees
Definition: parsenodes.h:2380
List * privileges
Definition: parsenodes.h:2378
GrantTargetType targtype
Definition: parsenodes.h:2374
DropBehavior behavior
Definition: parsenodes.h:2383
RoleSpec * grantor
Definition: parsenodes.h:2382
AclMode privileges

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_PARAMETER_ACL, 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, GrantStmt::behavior, InternalGrant::behavior, InternalGrant::col_privs, AccessPriv::cols, elog, ereport, errcode(), errmsg(), ERROR, ExecGrantStmt_oids(), get_rolespec_oid(), gettext_noop, GetUserId(), GrantStmt::grant_option, InternalGrant::grant_option, GrantStmt::grantees, InternalGrant::grantees, GrantStmt::grantor, GrantStmt::is_grant, InternalGrant::is_grant, lappend(), lappend_oid(), lfirst, NIL, OBJECT_DATABASE, OBJECT_DOMAIN, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_PARAMETER_ACL, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TYPE, objectNamesToOids(), GrantStmt::objects, InternalGrant::objects, objectsInSchemaToOids(), GrantStmt::objtype, InternalGrant::objtype, AccessPriv::priv_name, privilege_to_string(), GrantStmt::privileges, InternalGrant::privileges, ROLESPEC_PUBLIC, RoleSpec::roletype, string_to_privilege(), and GrantStmt::targtype.

Referenced by ProcessUtilitySlow(), and standard_ProcessUtility().

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

1608 {
1609  AttrNumber curr_att;
1610 
1611  Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
1612  for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
1613  curr_att <= classForm->relnatts;
1614  curr_att++)
1615  {
1616  HeapTuple attTuple;
1617  bool isdropped;
1618 
1619  if (curr_att == InvalidAttrNumber)
1620  continue;
1621 
1622  /* Views don't have any system columns at all */
1623  if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
1624  continue;
1625 
1626  attTuple = SearchSysCache2(ATTNUM,
1627  ObjectIdGetDatum(table_oid),
1628  Int16GetDatum(curr_att));
1629  if (!HeapTupleIsValid(attTuple))
1630  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1631  curr_att, table_oid);
1632 
1633  isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
1634 
1635  ReleaseSysCache(attTuple);
1636 
1637  /* ignore dropped columns */
1638  if (isdropped)
1639  continue;
1640 
1641  col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
1642  }
1643 }
#define InvalidAttrNumber
Definition: attnum.h:23

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

Referenced by ExecGrant_Relation().

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

1575 {
1576  ListCell *cell;
1577 
1578  foreach(cell, colnames)
1579  {
1580  char *colname = strVal(lfirst(cell));
1582 
1583  attnum = get_attnum(table_oid, colname);
1584  if (attnum == InvalidAttrNumber)
1585  ereport(ERROR,
1586  (errcode(ERRCODE_UNDEFINED_COLUMN),
1587  errmsg("column \"%s\" of relation \"%s\" does not exist",
1588  colname, get_rel_name(table_oid))));
1590  if (attnum <= 0 || attnum >= num_col_privileges)
1591  elog(ERROR, "column number out of range"); /* safety check */
1592  col_privileges[attnum] |= this_privileges;
1593  }
1594 }
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:856
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1909
#define strVal(v)
Definition: value.h:72

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

Referenced by ExecGrant_Relation().

◆ get_default_acl_internal()

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

Definition at line 5839 of file aclchk.c.

5840 {
5841  Acl *result = NULL;
5842  HeapTuple tuple;
5843 
5845  ObjectIdGetDatum(roleId),
5846  ObjectIdGetDatum(nsp_oid),
5847  CharGetDatum(objtype));
5848 
5849  if (HeapTupleIsValid(tuple))
5850  {
5851  Datum aclDatum;
5852  bool isNull;
5853 
5854  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
5855  Anum_pg_default_acl_defaclacl,
5856  &isNull);
5857  if (!isNull)
5858  result = DatumGetAclPCopy(aclDatum);
5859  ReleaseSysCache(tuple);
5860  }
5861 
5862  return result;
5863 }
#define CharGetDatum(X)
Definition: postgres.h:460
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1195
@ DEFACLROLENSPOBJ
Definition: syscache.h:56

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

Referenced by get_user_default_acl().

◆ get_user_default_acl()

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

Definition at line 5874 of file aclchk.c.

5875 {
5876  Acl *result;
5877  Acl *glob_acl;
5878  Acl *schema_acl;
5879  Acl *def_acl;
5880  char defaclobjtype;
5881 
5882  /*
5883  * Use NULL during bootstrap, since pg_default_acl probably isn't there
5884  * yet.
5885  */
5887  return NULL;
5888 
5889  /* Check if object type is supported in pg_default_acl */
5890  switch (objtype)
5891  {
5892  case OBJECT_TABLE:
5893  defaclobjtype = DEFACLOBJ_RELATION;
5894  break;
5895 
5896  case OBJECT_SEQUENCE:
5897  defaclobjtype = DEFACLOBJ_SEQUENCE;
5898  break;
5899 
5900  case OBJECT_FUNCTION:
5901  defaclobjtype = DEFACLOBJ_FUNCTION;
5902  break;
5903 
5904  case OBJECT_TYPE:
5905  defaclobjtype = DEFACLOBJ_TYPE;
5906  break;
5907 
5908  case OBJECT_SCHEMA:
5909  defaclobjtype = DEFACLOBJ_NAMESPACE;
5910  break;
5911 
5912  default:
5913  return NULL;
5914  }
5915 
5916  /* Look up the relevant pg_default_acl entries */
5917  glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
5918  schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
5919 
5920  /* Quick out if neither entry exists */
5921  if (glob_acl == NULL && schema_acl == NULL)
5922  return NULL;
5923 
5924  /* We need to know the hard-wired default value, too */
5925  def_acl = acldefault(objtype, ownerId);
5926 
5927  /* If there's no global entry, substitute the hard-wired default */
5928  if (glob_acl == NULL)
5929  glob_acl = def_acl;
5930 
5931  /* Merge in any per-schema privileges */
5932  result = aclmerge(glob_acl, schema_acl, ownerId);
5933 
5934  /*
5935  * For efficiency, we want to return NULL if the result equals default.
5936  * This requires sorting both arrays to get an accurate comparison.
5937  */
5938  aclitemsort(result);
5939  aclitemsort(def_acl);
5940  if (aclequal(result, def_acl))
5941  result = NULL;
5942 
5943  return result;
5944 }
void aclitemsort(Acl *acl)
Definition: acl.c:490
Acl * aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
Definition: acl.c:446
static Acl * get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
Definition: aclchk.c:5839
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406
#define InvalidOid
Definition: postgres_ext.h:36

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

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

◆ getRelationsInNamespace()

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

Definition at line 912 of file aclchk.c.

913 {
914  List *relations = NIL;
915  ScanKeyData key[2];
916  Relation rel;
917  TableScanDesc scan;
918  HeapTuple tuple;
919 
920  ScanKeyInit(&key[0],
921  Anum_pg_class_relnamespace,
922  BTEqualStrategyNumber, F_OIDEQ,
923  ObjectIdGetDatum(namespaceId));
924  ScanKeyInit(&key[1],
925  Anum_pg_class_relkind,
926  BTEqualStrategyNumber, F_CHAREQ,
927  CharGetDatum(relkind));
928 
929  rel = table_open(RelationRelationId, AccessShareLock);
930  scan = table_beginscan_catalog(rel, 2, key);
931 
932  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
933  {
934  Oid oid = ((Form_pg_class) GETSTRUCT(tuple))->oid;
935 
936  relations = lappend_oid(relations, oid);
937  }
938 
939  table_endscan(scan);
941 
942  return relations;
943 }
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1296
#define AccessShareLock
Definition: lockdefs.h:36
@ ForwardScanDirection
Definition: sdir.h:26
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:993

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

Referenced by objectsInSchemaToOids().

◆ has_bypassrls_privilege()

bool has_bypassrls_privilege ( Oid  roleid)

Definition at line 5815 of file aclchk.c.

5816 {
5817  bool result = false;
5818  HeapTuple utup;
5819 
5820  /* Superusers bypass all permission checking. */
5821  if (superuser_arg(roleid))
5822  return true;
5823 
5824  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5825  if (HeapTupleIsValid(utup))
5826  {
5827  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
5828  ReleaseSysCache(utup);
5829  }
5830  return result;
5831 }
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
bool rolbypassrls
Definition: pg_authid.h:41
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
@ AUTHOID
Definition: syscache.h:45

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

Referenced by check_enable_rls(), and RI_Initial_Check().

◆ has_createrole_privilege()

bool has_createrole_privilege ( Oid  roleid)

Definition at line 5796 of file aclchk.c.

5797 {
5798  bool result = false;
5799  HeapTuple utup;
5800 
5801  /* Superusers bypass all permission checking. */
5802  if (superuser_arg(roleid))
5803  return true;
5804 
5805  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
5806  if (HeapTupleIsValid(utup))
5807  {
5808  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
5809  ReleaseSysCache(utup);
5810  }
5811  return result;
5812 }
bool rolcreaterole
Definition: pg_authid.h:37

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

Referenced by check_object_ownership(), and have_createrole_privilege().

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

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

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, j, lfirst_oid, and pfree().

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

◆ objectNamesToOids()

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

Definition at line 643 of file aclchk.c.

644 {
645  List *objects = NIL;
646  ListCell *cell;
647 
648  Assert(objnames != NIL);
649 
650  switch (objtype)
651  {
652  case OBJECT_TABLE:
653  case OBJECT_SEQUENCE:
654  foreach(cell, objnames)
655  {
656  RangeVar *relvar = (RangeVar *) lfirst(cell);
657  Oid relOid;
658 
659  relOid = RangeVarGetRelid(relvar, NoLock, false);
660  objects = lappend_oid(objects, relOid);
661  }
662  break;
663  case OBJECT_DATABASE:
664  foreach(cell, objnames)
665  {
666  char *dbname = strVal(lfirst(cell));
667  Oid dbid;
668 
669  dbid = get_database_oid(dbname, false);
670  objects = lappend_oid(objects, dbid);
671  }
672  break;
673  case OBJECT_DOMAIN:
674  case OBJECT_TYPE:
675  foreach(cell, objnames)
676  {
677  List *typname = (List *) lfirst(cell);
678  Oid oid;
679 
681  objects = lappend_oid(objects, oid);
682  }
683  break;
684  case OBJECT_FUNCTION:
685  foreach(cell, objnames)
686  {
687  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
688  Oid funcid;
689 
690  funcid = LookupFuncWithArgs(OBJECT_FUNCTION, func, false);
691  objects = lappend_oid(objects, funcid);
692  }
693  break;
694  case OBJECT_LANGUAGE:
695  foreach(cell, objnames)
696  {
697  char *langname = strVal(lfirst(cell));
698  Oid oid;
699 
700  oid = get_language_oid(langname, false);
701  objects = lappend_oid(objects, oid);
702  }
703  break;
704  case OBJECT_LARGEOBJECT:
705  foreach(cell, objnames)
706  {
707  Oid lobjOid = oidparse(lfirst(cell));
708 
709  if (!LargeObjectExists(lobjOid))
710  ereport(ERROR,
711  (errcode(ERRCODE_UNDEFINED_OBJECT),
712  errmsg("large object %u does not exist",
713  lobjOid)));
714 
715  objects = lappend_oid(objects, lobjOid);
716  }
717  break;
718  case OBJECT_SCHEMA:
719  foreach(cell, objnames)
720  {
721  char *nspname = strVal(lfirst(cell));
722  Oid oid;
723 
724  oid = get_namespace_oid(nspname, false);
725  objects = lappend_oid(objects, oid);
726  }
727  break;
728  case OBJECT_PROCEDURE:
729  foreach(cell, objnames)
730  {
731  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
732  Oid procid;
733 
734  procid = LookupFuncWithArgs(OBJECT_PROCEDURE, func, false);
735  objects = lappend_oid(objects, procid);
736  }
737  break;
738  case OBJECT_ROUTINE:
739  foreach(cell, objnames)
740  {
741  ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
742  Oid routid;
743 
744  routid = LookupFuncWithArgs(OBJECT_ROUTINE, func, false);
745  objects = lappend_oid(objects, routid);
746  }
747  break;
748  case OBJECT_TABLESPACE:
749  foreach(cell, objnames)
750  {
751  char *spcname = strVal(lfirst(cell));
752  Oid spcoid;
753 
754  spcoid = get_tablespace_oid(spcname, false);
755  objects = lappend_oid(objects, spcoid);
756  }
757  break;
758  case OBJECT_FDW:
759  foreach(cell, objnames)
760  {
761  char *fdwname = strVal(lfirst(cell));
762  Oid fdwid = get_foreign_data_wrapper_oid(fdwname, false);
763 
764  objects = lappend_oid(objects, fdwid);
765  }
766  break;
768  foreach(cell, objnames)
769  {
770  char *srvname = strVal(lfirst(cell));
771  Oid srvid = get_foreign_server_oid(srvname, false);
772 
773  objects = lappend_oid(objects, srvid);
774  }
775  break;
777  foreach(cell, objnames)
778  {
779  /*
780  * In this code we represent a GUC by the OID of its entry in
781  * pg_parameter_acl, which we have to manufacture here if it
782  * doesn't exist yet. (That's a hack for sure, but it avoids
783  * messing with all the GRANT/REVOKE infrastructure that
784  * expects to use OIDs for object identities.) However, if
785  * this is a REVOKE, we can instead just ignore any GUCs that
786  * don't have such an entry, as they must not have any
787  * privileges needing removal.
788  */
789  char *parameter = strVal(lfirst(cell));
790  Oid parameterId = ParameterAclLookup(parameter, true);
791 
792  if (!OidIsValid(parameterId) && is_grant)
793  {
794  parameterId = ParameterAclCreate(parameter);
795 
796  /*
797  * Prevent error when processing duplicate objects, and
798  * make this new entry visible so that ExecGrant_Parameter
799  * can update it.
800  */
802  }
803  if (OidIsValid(parameterId))
804  objects = lappend_oid(objects, parameterId);
805  }
806  break;
807  default:
808  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
809  (int) objtype);
810  }
811 
812  return objects;
813 }
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1474
#define OidIsValid(objectId)
Definition: c.h:710
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2947
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition: foreign.c:682
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition: foreign.c:659
#define NoLock
Definition: lockdefs.h:34
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:457
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3089
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:79
Oid oidparse(Node *node)
Definition: oid.c:314
Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool missing_ok)
Definition: parse_func.c:2207
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291
bool LargeObjectExists(Oid loid)
Oid ParameterAclLookup(const char *parameter, bool missing_ok)
Oid ParameterAclCreate(const char *parameter)
NameData typname
Definition: pg_type.h:41
Oid get_language_oid(const char *langname, bool missing_ok)
Definition: proclang.c:228
char * dbname
Definition: streamutil.c:51

References Assert(), CommandCounterIncrement(), 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_PARAMETER_ACL, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TYPE, OidIsValid, oidparse(), ParameterAclCreate(), ParameterAclLookup(), RangeVarGetRelid, strVal, typenameTypeId(), and typname.

Referenced by ExecuteGrantStmt().

◆ objectsInSchemaToOids()

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

Definition at line 823 of file aclchk.c.

824 {
825  List *objects = NIL;
826  ListCell *cell;
827 
828  foreach(cell, nspnames)
829  {
830  char *nspname = strVal(lfirst(cell));
831  Oid namespaceId;
832  List *objs;
833 
834  namespaceId = LookupExplicitNamespace(nspname, false);
835 
836  switch (objtype)
837  {
838  case OBJECT_TABLE:
839  objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
840  objects = list_concat(objects, objs);
841  objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
842  objects = list_concat(objects, objs);
843  objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
844  objects = list_concat(objects, objs);
845  objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
846  objects = list_concat(objects, objs);
847  objs = getRelationsInNamespace(namespaceId, RELKIND_PARTITIONED_TABLE);
848  objects = list_concat(objects, objs);
849  break;
850  case OBJECT_SEQUENCE:
851  objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
852  objects = list_concat(objects, objs);
853  break;
854  case OBJECT_FUNCTION:
855  case OBJECT_PROCEDURE:
856  case OBJECT_ROUTINE:
857  {
858  ScanKeyData key[2];
859  int keycount;
860  Relation rel;
861  TableScanDesc scan;
862  HeapTuple tuple;
863 
864  keycount = 0;
865  ScanKeyInit(&key[keycount++],
866  Anum_pg_proc_pronamespace,
867  BTEqualStrategyNumber, F_OIDEQ,
868  ObjectIdGetDatum(namespaceId));
869 
870  if (objtype == OBJECT_FUNCTION)
871  /* includes aggregates and window functions */
872  ScanKeyInit(&key[keycount++],
873  Anum_pg_proc_prokind,
874  BTEqualStrategyNumber, F_CHARNE,
875  CharGetDatum(PROKIND_PROCEDURE));
876  else if (objtype == OBJECT_PROCEDURE)
877  ScanKeyInit(&key[keycount++],
878  Anum_pg_proc_prokind,
879  BTEqualStrategyNumber, F_CHAREQ,
880  CharGetDatum(PROKIND_PROCEDURE));
881 
882  rel = table_open(ProcedureRelationId, AccessShareLock);
883  scan = table_beginscan_catalog(rel, keycount, key);
884 
885  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
886  {
887  Oid oid = ((Form_pg_proc) GETSTRUCT(tuple))->oid;
888 
889  objects = lappend_oid(objects, oid);
890  }
891 
892  table_endscan(scan);
894  }
895  break;
896  default:
897  /* should not happen */
898  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
899  (int) objtype);
900  }
901  }
902 
903  return objects;
904 }
static List * getRelationsInNamespace(Oid namespaceId, char relkind)
Definition: aclchk.c:912
List * list_concat(List *list1, const List *list2)
Definition: list.c:540
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2939

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

Referenced by ExecuteGrantStmt().

◆ pg_aclmask()

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

Definition at line 3843 of file aclchk.c.

3845 {
3846  switch (objtype)
3847  {
3848  case OBJECT_COLUMN:
3849  return
3850  pg_class_aclmask(table_oid, roleid, mask, how) |
3851  pg_attribute_aclmask(table_oid, attnum, roleid, mask, how);
3852  case OBJECT_TABLE:
3853  case OBJECT_SEQUENCE:
3854  return pg_class_aclmask(table_oid, roleid, mask, how);
3855  case OBJECT_DATABASE:
3856  return pg_database_aclmask(table_oid, roleid, mask, how);
3857  case OBJECT_FUNCTION:
3858  return pg_proc_aclmask(table_oid, roleid, mask, how);
3859  case OBJECT_LANGUAGE:
3860  return pg_language_aclmask(table_oid, roleid, mask, how);
3861  case OBJECT_LARGEOBJECT:
3862  return pg_largeobject_aclmask_snapshot(table_oid, roleid,
3863  mask, how, NULL);
3864  case OBJECT_PARAMETER_ACL:
3865  return pg_parameter_acl_aclmask(table_oid, roleid, mask, how);
3866  case OBJECT_SCHEMA:
3867  return pg_namespace_aclmask(table_oid, roleid, mask, how);
3868  case OBJECT_STATISTIC_EXT:
3869  elog(ERROR, "grantable rights not supported for statistics objects");
3870  /* not reached, but keep compiler quiet */
3871  return ACL_NO_RIGHTS;
3872  case OBJECT_TABLESPACE:
3873  return pg_tablespace_aclmask(table_oid, roleid, mask, how);
3874  case OBJECT_FDW:
3875  return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
3876  case OBJECT_FOREIGN_SERVER:
3877  return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
3878  case OBJECT_EVENT_TRIGGER:
3879  elog(ERROR, "grantable rights not supported for event triggers");
3880  /* not reached, but keep compiler quiet */
3881  return ACL_NO_RIGHTS;
3882  case OBJECT_TYPE:
3883  return pg_type_aclmask(table_oid, roleid, mask, how);
3884  default:
3885  elog(ERROR, "unrecognized objtype: %d",
3886  (int) objtype);
3887  /* not reached, but keep compiler quiet */
3888  return ACL_NO_RIGHTS;
3889  }
3890 }
AclMode pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4282
AclMode pg_foreign_server_aclmask(Oid srv_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4733
AclMode pg_language_aclmask(Oid lang_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4386
AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3913
AclMode pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid, AclMode mask, AclMaskHow how, Snapshot snapshot)
Definition: aclchk.c:4449
AclMode pg_database_aclmask(Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4163
AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4522
AclMode pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4794
AclMode pg_proc_aclmask(Oid proc_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4332
AclMode pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4671
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4032
AclMode pg_tablespace_aclmask(Oid spc_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:4614

References ACL_NO_RIGHTS, attnum, elog, ERROR, OBJECT_COLUMN, OBJECT_DATABASE, OBJECT_EVENT_TRIGGER, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_PARAMETER_ACL, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_STATISTIC_EXT, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TYPE, pg_attribute_aclmask(), pg_class_aclmask(), pg_database_aclmask(), pg_foreign_data_wrapper_aclmask(), pg_foreign_server_aclmask(), pg_language_aclmask(), pg_largeobject_aclmask_snapshot(), pg_namespace_aclmask(), pg_parameter_acl_aclmask(), pg_proc_aclmask(), pg_tablespace_aclmask(), and pg_type_aclmask().

Referenced by restrict_and_check_grant().

◆ pg_attribute_aclcheck()

AclResult pg_attribute_aclcheck ( Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mode 
)

Definition at line 4878 of file aclchk.c.

4880 {
4881  return pg_attribute_aclcheck_ext(table_oid, attnum, roleid, mode, NULL);
4882 }
AclResult pg_attribute_aclcheck_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode, bool *is_missing)
Definition: aclchk.c:4892
static PgChecksumMode mode
Definition: pg_checksums.c:65

References attnum, mode, and pg_attribute_aclcheck_ext().

Referenced by BuildIndexValueDescription(), checkFkeyPermissions(), examine_simple_variable(), ExecBuildSlotPartitionKeyDescription(), ExecBuildSlotValueDescription(), ExecCheckRTEPerms(), ExecCheckRTEPermsModified(), ri_ReportViolation(), and statext_is_compatible_clause().

◆ pg_attribute_aclcheck_all()

AclResult pg_attribute_aclcheck_all ( Oid  table_oid,
Oid  roleid,
AclMode  mode,
AclMaskHow  how 
)

Definition at line 4922 of file aclchk.c.

4924 {
4925  AclResult result;
4926  HeapTuple classTuple;
4927  Form_pg_class classForm;
4928  AttrNumber nattrs;
4929  AttrNumber curr_att;
4930 
4931  /*
4932  * Must fetch pg_class row to check number of attributes. As in
4933  * pg_attribute_aclmask, we prefer to return "no privileges" instead of
4934  * throwing an error if we get any unexpected lookup errors.
4935  */
4936  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
4937  if (!HeapTupleIsValid(classTuple))
4938  return ACLCHECK_NO_PRIV;
4939  classForm = (Form_pg_class) GETSTRUCT(classTuple);
4940 
4941  nattrs = classForm->relnatts;
4942 
4943  ReleaseSysCache(classTuple);
4944 
4945  /*
4946  * Initialize result in case there are no non-dropped columns. We want to
4947  * report failure in such cases for either value of 'how'.
4948  */
4949  result = ACLCHECK_NO_PRIV;
4950 
4951  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4952  {
4953  HeapTuple attTuple;
4954  AclMode attmask;
4955 
4956  attTuple = SearchSysCache2(ATTNUM,
4957  ObjectIdGetDatum(table_oid),
4958  Int16GetDatum(curr_att));
4959  if (!HeapTupleIsValid(attTuple))
4960  continue;
4961 
4962  /* ignore dropped columns */
4963  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4964  {
4965  ReleaseSysCache(attTuple);
4966  continue;
4967  }
4968 
4969  /*
4970  * Here we hard-wire knowledge that the default ACL for a column
4971  * grants no privileges, so that we can fall out quickly in the very
4972  * common case where attacl is null.
4973  */
4974  if (heap_attisnull(attTuple, Anum_pg_attribute_attacl, NULL))
4975  attmask = 0;
4976  else
4977  attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
4978  mode, ACLMASK_ANY);
4979 
4980  ReleaseSysCache(attTuple);
4981 
4982  if (attmask != 0)
4983  {
4984  result = ACLCHECK_OK;
4985  if (how == ACLMASK_ANY)
4986  break; /* succeed on any success */
4987  }
4988  else
4989  {
4990  result = ACLCHECK_NO_PRIV;
4991  if (how == ACLMASK_ALL)
4992  break; /* fail on any failure */
4993  }
4994  }
4995 
4996  return result;
4997 }
AclResult
Definition: acl.h:181
@ ACLMASK_ANY
Definition: acl.h:176
@ ACLMASK_ALL
Definition: acl.h:175
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359

References ACLCHECK_NO_PRIV, ACLCHECK_OK, ACLMASK_ALL, ACLMASK_ANY, ATTNUM, GETSTRUCT, heap_attisnull(), HeapTupleIsValid, Int16GetDatum, mode, ObjectIdGetDatum, pg_attribute_aclmask(), ReleaseSysCache(), RELOID, SearchSysCache1(), and SearchSysCache2().

Referenced by ExecCheckRTEPerms(), ExecCheckRTEPermsModified(), has_any_column_privilege_id(), has_any_column_privilege_id_id(), has_any_column_privilege_id_name(), has_any_column_privilege_name(), has_any_column_privilege_name_id(), has_any_column_privilege_name_name(), and statext_is_compatible_clause().

◆ pg_attribute_aclcheck_ext()

AclResult pg_attribute_aclcheck_ext ( Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mode,
bool is_missing 
)

Definition at line 4892 of file aclchk.c.

4894 {
4895  if (pg_attribute_aclmask_ext(table_oid, attnum, roleid, mode,
4896  ACLMASK_ANY, is_missing) != 0)
4897  return ACLCHECK_OK;
4898  else
4899  return ACLCHECK_NO_PRIV;
4900 }
AclMode pg_attribute_aclmask_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3927

References ACLCHECK_NO_PRIV, ACLCHECK_OK, ACLMASK_ANY, attnum, mode, and pg_attribute_aclmask_ext().

Referenced by column_privilege_check(), and pg_attribute_aclcheck().

◆ pg_attribute_aclmask()

AclMode pg_attribute_aclmask ( Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 3913 of file aclchk.c.

3915 {
3916  return pg_attribute_aclmask_ext(table_oid, attnum, roleid,
3917  mask, how, NULL);
3918 }

References attnum, and pg_attribute_aclmask_ext().

Referenced by pg_aclmask(), and pg_attribute_aclcheck_all().

◆ pg_attribute_aclmask_ext()

AclMode pg_attribute_aclmask_ext ( Oid  table_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mask,
AclMaskHow  how,
bool is_missing 
)

Definition at line 3927 of file aclchk.c.

3929 {
3930  AclMode result;
3931  HeapTuple classTuple;
3932  HeapTuple attTuple;
3933  Form_pg_class classForm;
3934  Form_pg_attribute attributeForm;
3935  Datum aclDatum;
3936  bool isNull;
3937  Acl *acl;
3938  Oid ownerId;
3939 
3940  /*
3941  * First, get the column's ACL from its pg_attribute entry
3942  */
3943  attTuple = SearchSysCache2(ATTNUM,
3944  ObjectIdGetDatum(table_oid),
3946  if (!HeapTupleIsValid(attTuple))
3947  {
3948  if (is_missing != NULL)
3949  {
3950  /* return "no privileges" instead of throwing an error */
3951  *is_missing = true;
3952  return 0;
3953  }
3954  else
3955  ereport(ERROR,
3956  (errcode(ERRCODE_UNDEFINED_COLUMN),
3957  errmsg("attribute %d of relation with OID %u does not exist",
3958  attnum, table_oid)));
3959  }
3960 
3961  attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
3962 
3963  /* Check dropped columns, too */
3964  if (attributeForm->attisdropped)
3965  {
3966  if (is_missing != NULL)
3967  {
3968  /* return "no privileges" instead of throwing an error */
3969  *is_missing = true;
3970  ReleaseSysCache(attTuple);
3971  return 0;
3972  }
3973  else
3974  ereport(ERROR,
3975  (errcode(ERRCODE_UNDEFINED_COLUMN),
3976  errmsg("attribute %d of relation with OID %u does not exist",
3977  attnum, table_oid)));
3978  }
3979 
3980  aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
3981  &isNull);
3982 
3983  /*
3984  * Here we hard-wire knowledge that the default ACL for a column grants no
3985  * privileges, so that we can fall out quickly in the very common case
3986  * where attacl is null.
3987  */
3988  if (isNull)
3989  {
3990  ReleaseSysCache(attTuple);
3991  return 0;
3992  }
3993 
3994  /*
3995  * Must get the relation's ownerId from pg_class. Since we already found
3996  * a pg_attribute entry, the only likely reason for this to fail is that a
3997  * concurrent DROP of the relation committed since then (which could only
3998  * happen if we don't have lock on the relation). We prefer to report "no
3999  * privileges" rather than failing in such a case, so as to avoid unwanted
4000  * failures in has_column_privilege() tests.
4001  */
4002  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
4003  if (!HeapTupleIsValid(classTuple))
4004  {
4005  ReleaseSysCache(attTuple);
4006  return 0;
4007  }
4008  classForm = (Form_pg_class) GETSTRUCT(classTuple);
4009 
4010  ownerId = classForm->relowner;
4011 
4012  ReleaseSysCache(classTuple);
4013 
4014  /* detoast column's ACL if necessary */
4015  acl = DatumGetAclP(aclDatum);
4016 
4017  result = aclmask(acl, roleid, ownerId, mask, how);
4018 
4019  /* if we have a detoasted copy, free it */
4020  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
4021  pfree(acl);
4022 
4023  ReleaseSysCache(attTuple);
4024 
4025  return result;
4026 }
AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
Definition: acl.c:1322
#define DatumGetAclP(X)
Definition: acl.h:120
char * Pointer
Definition: c.h:418
#define DatumGetPointer(X)
Definition: postgres.h:593

References aclmask(), attnum, ATTNUM, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum, ObjectIdGetDatum, pfree(), ReleaseSysCache(), RELOID, SearchSysCache1(), SearchSysCache2(), and SysCacheGetAttr().

Referenced by pg_attribute_aclcheck_ext(), and pg_attribute_aclmask().

◆ pg_class_aclcheck()

AclResult pg_class_aclcheck ( Oid  table_oid,
Oid  roleid,
AclMode  mode 
)

◆ pg_class_aclcheck_ext()

AclResult pg_class_aclcheck_ext ( Oid  table_oid,
Oid  roleid,
AclMode  mode,
bool is_missing 
)

Definition at line 5019 of file aclchk.c.

5021 {
5022  if (pg_class_aclmask_ext(table_oid, roleid, mode,
5023  ACLMASK_ANY, is_missing) != 0)
5024  return ACLCHECK_OK;
5025  else
5026  return ACLCHECK_NO_PRIV;
5027 }
AclMode pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:4045

References ACLCHECK_NO_PRIV, ACLCHECK_OK, ACLMASK_ANY, mode, and pg_class_aclmask_ext().

Referenced by column_privilege_check(), and pg_class_aclcheck().

◆ pg_class_aclmask()

AclMode pg_class_aclmask ( Oid  table_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 4032 of file aclchk.c.

4034 {
4035  return pg_class_aclmask_ext(table_oid, roleid, mask, how, NULL);
4036 }

References pg_class_aclmask_ext().

Referenced by ExecCheckRTEPerms(), and pg_aclmask().

◆ pg_class_aclmask_ext()

AclMode pg_class_aclmask_ext ( Oid  table_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how,
bool is_missing 
)

Definition at line 4045 of file aclchk.c.

4047 {
4048  AclMode result;
4049  HeapTuple tuple;
4050  Form_pg_class classForm;
4051  Datum aclDatum;
4052  bool isNull;
4053  Acl *acl;
4054  Oid ownerId;
4055 
4056  /*
4057  * Must get the relation's tuple from pg_class
4058  */
4059  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
4060  if (!HeapTupleIsValid(tuple))
4061  {
4062  if (is_missing != NULL)
4063  {
4064  /* return "no privileges" instead of throwing an error */
4065  *is_missing = true;
4066  return 0;
4067  }
4068  else
4069  ereport(ERROR,
4071  errmsg("relation with OID %u does not exist",
4072  table_oid)));
4073  }
4074 
4075  classForm = (Form_pg_class) GETSTRUCT(tuple);
4076 
4077  /*
4078  * Deny anyone permission to update a system catalog unless
4079  * pg_authid.rolsuper is set.
4080  *
4081  * As of 7.4 we have some updatable system views; those shouldn't be
4082  * protected in this way. Assume the view rules can take care of
4083  * themselves. ACL_USAGE is if we ever have system sequences.
4084  */
4085  if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
4086  IsSystemClass(table_oid, classForm) &&
4087  classForm->relkind != RELKIND_VIEW &&
4088  !superuser_arg(roleid))
4090 
4091  /*
4092  * Otherwise, superusers bypass all permission-checking.
4093  */
4094  if (superuser_arg(roleid))
4095  {
4096  ReleaseSysCache(tuple);
4097  return mask;
4098  }
4099 
4100  /*
4101  * Normal case: get the relation's ACL from pg_class
4102  */
4103  ownerId = classForm->relowner;
4104 
4105  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
4106  &isNull);
4107  if (isNull)
4108  {
4109  /* No ACL, so build default ACL */
4110  switch (classForm->relkind)
4111  {
4112  case RELKIND_SEQUENCE:
4113  acl = acldefault(OBJECT_SEQUENCE, ownerId);
4114  break;
4115  default:
4116  acl = acldefault(OBJECT_TABLE, ownerId);
4117  break;
4118  }
4119  aclDatum = (Datum) 0;
4120  }
4121  else
4122  {
4123  /* detoast rel's ACL if necessary */
4124  acl = DatumGetAclP(aclDatum);
4125  }
4126 
4127  result = aclmask(acl, roleid, ownerId, mask, how);
4128 
4129  /* if we have a detoasted copy, free it */
4130  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
4131  pfree(acl);
4132 
4133  ReleaseSysCache(tuple);
4134 
4135  /*
4136  * Check if ACL_SELECT is being checked and, if so, and not set already as
4137  * part of the result, then check if the user is a member of the
4138  * pg_read_all_data role, which allows read access to all relations.
4139  */
4140  if (mask & ACL_SELECT && !(result & ACL_SELECT) &&
4141  has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA))
4142  result |= ACL_SELECT;
4143 
4144  /*
4145  * Check if ACL_INSERT, ACL_UPDATE, or ACL_DELETE is being checked and, if
4146  * so, and not set already as part of the result, then check if the user
4147  * is a member of the pg_write_all_data role, which allows
4148  * INSERT/UPDATE/DELETE access to all relations (except system catalogs,
4149  * which requires superuser, see above).
4150  */
4151  if (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE) &&
4152  !(result & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
4153  has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA))
4154  result |= (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE));
4155 
4156  return result;
4157 }
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4951
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:87
#define ACL_DELETE
Definition: parsenodes.h:85
#define ACL_USAGE
Definition: parsenodes.h:90
#define ACL_INSERT
Definition: parsenodes.h:82
#define ACL_UPDATE
Definition: parsenodes.h:84
#define ACL_TRUNCATE
Definition: parsenodes.h:86
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:81

References ACL_DELETE, ACL_INSERT, ACL_SELECT, ACL_TRUNCATE, ACL_UPDATE, ACL_USAGE, acldefault(), aclmask(), DatumGetAclP, DatumGetPointer, ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, IsSystemClass(), OBJECT_SEQUENCE, OBJECT_TABLE, ObjectIdGetDatum, pfree(), ReleaseSysCache(), RELOID, SearchSysCache1(), superuser_arg(), and SysCacheGetAttr().

Referenced by pg_class_aclcheck_ext(), and pg_class_aclmask().

◆ pg_class_ownercheck()

bool pg_class_ownercheck ( Oid  class_oid,
Oid  roleid 
)

Definition at line 5171 of file aclchk.c.

5172 {
5173  HeapTuple tuple;
5174  Oid ownerId;
5175 
5176  /* Superusers bypass all permission checking. */
5177  if (superuser_arg(roleid))
5178  return true;
5179 
5180  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(class_oid));
5181  if (!HeapTupleIsValid(tuple))
5182  ereport(ERROR,
5184  errmsg("relation with OID %u does not exist", class_oid)));
5185 
5186  ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
5187 
5188  ReleaseSysCache(tuple);
5189 
5190  return has_privs_of_role(roleid, ownerId);
5191 }

References ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), RELOID, SearchSysCache1(), and superuser_arg().

Referenced by AlterTableMoveAll(), ATExecChangeOwner(), ATSimplePermissions(), brin_desummarize_range(), brin_summarize_range(), check_enable_rls(), check_object_ownership(), cluster_rel(), CreateStatistics(), DefineQueryRewrite(), EnableDisableRule(), ExecuteTruncateGuts(), get_tables_to_cluster(), get_tables_to_cluster_partitioned(), gin_clean_pending_list(), heap_force_common(), MergeAttributes(), PublicationAddTables(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForPolicy(), RangeVarCallbackForReindexIndex(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackOwnsRelation(), RangeVarCallbackOwnsTable(), RangeVarGetAndCheckCreationNamespace(), ReindexMultipleTables(), renameatt_check(), RI_Initial_Check(), and vacuum_is_relation_owner().

◆ pg_collation_ownercheck()

bool pg_collation_ownercheck ( Oid  coll_oid,
Oid  roleid 
)

Definition at line 5615 of file aclchk.c.

5616 {
5617  HeapTuple tuple;
5618  Oid ownerId;
5619 
5620  /* Superusers bypass all permission checking. */
5621  if (superuser_arg(roleid))
5622  return true;
5623 
5624  tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(coll_oid));
5625  if (!HeapTupleIsValid(tuple))
5626  ereport(ERROR,
5627  (errcode(ERRCODE_UNDEFINED_OBJECT),
5628  errmsg("collation with OID %u does not exist", coll_oid)));
5629 
5630  ownerId = ((Form_pg_collation) GETSTRUCT(tuple))->collowner;
5631 
5632  ReleaseSysCache(tuple);
5633 
5634  return has_privs_of_role(roleid, ownerId);
5635 }
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:57
@ COLLOID
Definition: syscache.h:50

References COLLOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1(), and superuser_arg().

Referenced by AlterCollation(), and check_object_ownership().

◆ pg_conversion_ownercheck()

bool pg_conversion_ownercheck ( Oid  conv_oid,
Oid  roleid 
)

Definition at line 5641 of file aclchk.c.

5642 {
5643  HeapTuple tuple;
5644  Oid ownerId;
5645 
5646  /* Superusers bypass all permission checking. */
5647  if (superuser_arg(roleid))
5648  return true;
5649 
5650  tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(conv_oid));
5651  if (!HeapTupleIsValid(tuple))
5652  ereport(ERROR,
5653  (errcode(ERRCODE_UNDEFINED_OBJECT),
5654  errmsg("conversion with OID %u does not exist", conv_oid)));
5655 
5656  ownerId = ((Form_pg_conversion) GETSTRUCT(tuple))->conowner;
5657 
5658  ReleaseSysCache(tuple);
5659 
5660  return has_privs_of_role(roleid, ownerId);
5661 }
FormData_pg_conversion * Form_pg_conversion
Definition: pg_conversion.h:61
@ CONVOID
Definition: syscache.h:54

References CONVOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1(), and superuser_arg().

Referenced by check_object_ownership().

◆ pg_database_aclcheck()

◆ pg_database_aclmask()

AclMode pg_database_aclmask ( Oid  db_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 4163 of file aclchk.c.

4165 {
4166  AclMode result;
4167  HeapTuple tuple;
4168  Datum aclDatum;
4169  bool isNull;
4170  Acl *acl;
4171  Oid ownerId;
4172 
4173  /* Superusers bypass all permission checking. */
4174  if (superuser_arg(roleid))
4175  return mask;
4176 
4177  /*
4178  * Get the database's ACL from pg_database
4179  */
4180  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
4181  if (!HeapTupleIsValid(tuple))
4182  ereport(ERROR,
4183  (errcode(ERRCODE_UNDEFINED_DATABASE),
4184  errmsg("database with OID %u does not exist", db_oid)));
4185 
4186  ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
4187 
4188  aclDatum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datacl,
4189  &isNull);
4190  if (isNull)
4191  {
4192  /* No ACL, so build default ACL */
4193  acl = acldefault(OBJECT_DATABASE, ownerId);
4194  aclDatum = (Datum) 0;
4195  }
4196  else
4197  {
4198  /* detoast ACL if necessary */
4199  acl = DatumGetAclP(aclDatum);
4200  }
4201 
4202  result = aclmask(acl, roleid, ownerId, mask, how);
4203 
4204  /* if we have a detoasted copy, free it */
4205  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
4206  pfree(acl);
4207 
4208  ReleaseSysCache(tuple);
4209 
4210  return result;
4211 }

References acldefault(), aclmask(), DATABASEOID, DatumGetAclP, DatumGetPointer, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, OBJECT_DATABASE, ObjectIdGetDatum, pfree(), ReleaseSysCache(), SearchSysCache1(), superuser_arg(), and SysCacheGetAttr().

Referenced by pg_aclmask(), and pg_database_aclcheck().

◆ pg_database_ownercheck()

bool pg_database_ownercheck ( Oid  db_oid,
Oid  roleid 
)

Definition at line 5589 of file aclchk.c.

5590 {
5591  HeapTuple tuple;
5592  Oid dba;
5593 
5594  /* Superusers bypass all permission checking. */
5595  if (superuser_arg(roleid))
5596  return true;
5597 
5598  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
5599  if (!HeapTupleIsValid(tuple))
5600  ereport(ERROR,
5601  (errcode(ERRCODE_UNDEFINED_DATABASE),
5602  errmsg("database with OID %u does not exist", db_oid)));
5603 
5604  dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
5605 
5606  ReleaseSysCache(tuple);
5607 
5608  return has_privs_of_role(roleid, dba);
5609 }

References DATABASEOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1(), and superuser_arg().

Referenced by AlterDatabase(), AlterDatabaseOwner(), AlterDatabaseRefreshColl(), AlterDatabaseSet(), AlterRoleSet(), check_object_ownership(), createdb(), dropdb(), get_tables_to_cluster_partitioned(), movedb(), ReindexMultipleTables(), RenameDatabase(), and vacuum_is_relation_owner().

◆ pg_event_trigger_ownercheck()

bool pg_event_trigger_ownercheck ( Oid  et_oid,
Oid  roleid 
)

Definition at line 5562 of file aclchk.c.

5563 {
5564  HeapTuple tuple;
5565  Oid ownerId;
5566 
5567  /* Superusers bypass all permission checking. */
5568  if (superuser_arg(roleid))
5569  return true;
5570 
5572  if (!HeapTupleIsValid(tuple))
5573  ereport(ERROR,
5574  (errcode(ERRCODE_UNDEFINED_OBJECT),
5575  errmsg("event trigger with OID %u does not exist",
5576  et_oid)));
5577 
5578  ownerId = ((Form_pg_event_trigger) GETSTRUCT(tuple))->evtowner;
5579 
5580  ReleaseSysCache(tuple);
5581 
5582  return has_privs_of_role(roleid, ownerId);
5583 }
FormData_pg_event_trigger * Form_pg_event_trigger
@ EVENTTRIGGEROID
Definition: syscache.h:60

References ereport, errcode(), errmsg(), ERROR, EVENTTRIGGEROID, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1(), and superuser_arg().

Referenced by AlterEventTrigger(), AlterEventTriggerOwner_internal(), and check_object_ownership().

◆ pg_extension_ownercheck()

bool pg_extension_ownercheck ( Oid  ext_oid,
Oid  roleid 
)

Definition at line 5667 of file aclchk.c.

5668 {
5669  Relation pg_extension;
5670  ScanKeyData entry[1];
5671  SysScanDesc scan;
5672  HeapTuple tuple;
5673  Oid ownerId;
5674 
5675  /* Superusers bypass all permission checking. */
5676  if (superuser_arg(roleid))
5677  return true;
5678 
5679  /* There's no syscache for pg_extension, so do it the hard way */
5680  pg_extension = table_open(ExtensionRelationId, AccessShareLock);
5681 
5682  ScanKeyInit(&entry[0],
5683  Anum_pg_extension_oid,
5684  BTEqualStrategyNumber, F_OIDEQ,
5685  ObjectIdGetDatum(ext_oid));
5686 
5687  scan = systable_beginscan(pg_extension,
5688  ExtensionOidIndexId, true,
5689  NULL, 1, entry);
5690 
5691  tuple = systable_getnext(scan);
5692  if (!HeapTupleIsValid(tuple))
5693  ereport(ERROR,
5694  (errcode(ERRCODE_UNDEFINED_OBJECT),
5695  errmsg("extension with OID %u does not exist", ext_oid)));
5696 
5697  ownerId = ((Form_pg_extension) GETSTRUCT(tuple))->extowner;
5698 
5699  systable_endscan(scan);
5700  table_close(pg_extension, AccessShareLock);
5701 
5702  return has_privs_of_role(roleid, ownerId);
5703 }
FormData_pg_extension * Form_pg_extension
Definition: pg_extension.h:52

References AccessShareLock, BTEqualStrategyNumber, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, ObjectIdGetDatum, ScanKeyInit(), superuser_arg(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterExtensionNamespace(), check_object_ownership(), ExecAlterExtensionContentsStmt(), and ExecAlterExtensionStmt().

◆ pg_foreign_data_wrapper_aclcheck()

◆ pg_foreign_data_wrapper_aclmask()

AclMode pg_foreign_data_wrapper_aclmask ( Oid  fdw_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)

Definition at line 4671 of file aclchk.c.

4673 {
4674  AclMode result;
4675  HeapTuple tuple;
4676  Datum aclDatum;
4677  bool isNull;
4678  Acl *acl;
4679  Oid ownerId;
4680 
4682 
4683  /* Bypass permission checks for superusers */
4684  if (superuser_arg(roleid))
4685  return mask;
4686 
4687  /*
4688  * Must get the FDW's tuple from pg_foreign_data_wrapper
4689  */
4691  if (!HeapTupleIsValid(tuple))
4692  ereport(ERROR,
4693  (errcode(ERRCODE_UNDEFINED_OBJECT),
4694  errmsg("foreign-data wrapper with OID %u does not exist",
4695  fdw_oid)));
4696  fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
4697 
4698  /*
4699  * Normal case: get the FDW's ACL from pg_foreign_data_wrapper
4700  */
4701  ownerId = fdwForm->fdwowner;
4702 
4703  aclDatum = SysCacheGetAttr(