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_class.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/guc.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 *istmt)
 
static void ExecGrant_common (InternalGrant *istmt, Oid classid, AclMode default_privs, void(*object_check)(InternalGrant *istmt, HeapTuple tuple))
 
static void ExecGrant_Language_check (InternalGrant *istmt, HeapTuple tuple)
 
static void ExecGrant_Largeobject (InternalGrant *istmt)
 
static void ExecGrant_Type_check (InternalGrant *istmt, HeapTuple tuple)
 
static void ExecGrant_Parameter (InternalGrant *istmt)
 
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 object_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
 
static AclMode object_aclmask (Oid classid, Oid objectid, Oid roleid, AclMode mask, AclMaskHow how)
 
static AclMode pg_attribute_aclmask (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
 
static AclMode pg_attribute_aclmask_ext (Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
 
static AclMode pg_class_aclmask_ext (Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
 
static AclMode pg_parameter_acl_aclmask (Oid acl_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
static AclMode pg_largeobject_aclmask_snapshot (Oid lobj_oid, Oid roleid, AclMode mask, AclMaskHow how, Snapshot snapshot)
 
static AclMode pg_namespace_aclmask (Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
static AclMode pg_type_aclmask (Oid type_oid, 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_class_aclmask (Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
 
static AclMode pg_parameter_aclmask (const char *name, Oid roleid, AclMode mask, AclMaskHow how)
 
AclResult object_aclcheck (Oid classid, Oid objectid, Oid roleid, AclMode mode)
 
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_parameter_aclcheck (const char *name, Oid roleid, AclMode mode)
 
AclResult pg_largeobject_aclcheck_snapshot (Oid lobj_oid, Oid roleid, AclMode mode, Snapshot snapshot)
 
bool object_ownercheck (Oid classid, Oid objectid, 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 2669 of file aclchk.c.

2671 {
2672  switch (aclerr)
2673  {
2674  case ACLCHECK_OK:
2675  /* no error, so return to caller */
2676  break;
2677  case ACLCHECK_NO_PRIV:
2678  {
2679  const char *msg = "???";
2680 
2681  switch (objtype)
2682  {
2683  case OBJECT_AGGREGATE:
2684  msg = gettext_noop("permission denied for aggregate %s");
2685  break;
2686  case OBJECT_COLLATION:
2687  msg = gettext_noop("permission denied for collation %s");
2688  break;
2689  case OBJECT_COLUMN:
2690  msg = gettext_noop("permission denied for column %s");
2691  break;
2692  case OBJECT_CONVERSION:
2693  msg = gettext_noop("permission denied for conversion %s");
2694  break;
2695  case OBJECT_DATABASE:
2696  msg = gettext_noop("permission denied for database %s");
2697  break;
2698  case OBJECT_DOMAIN:
2699  msg = gettext_noop("permission denied for domain %s");
2700  break;
2701  case OBJECT_EVENT_TRIGGER:
2702  msg = gettext_noop("permission denied for event trigger %s");
2703  break;
2704  case OBJECT_EXTENSION:
2705  msg = gettext_noop("permission denied for extension %s");
2706  break;
2707  case OBJECT_FDW:
2708  msg = gettext_noop("permission denied for foreign-data wrapper %s");
2709  break;
2710  case OBJECT_FOREIGN_SERVER:
2711  msg = gettext_noop("permission denied for foreign server %s");
2712  break;
2713  case OBJECT_FOREIGN_TABLE:
2714  msg = gettext_noop("permission denied for foreign table %s");
2715  break;
2716  case OBJECT_FUNCTION:
2717  msg = gettext_noop("permission denied for function %s");
2718  break;
2719  case OBJECT_INDEX:
2720  msg = gettext_noop("permission denied for index %s");
2721  break;
2722  case OBJECT_LANGUAGE:
2723  msg = gettext_noop("permission denied for language %s");
2724  break;
2725  case OBJECT_LARGEOBJECT:
2726  msg = gettext_noop("permission denied for large object %s");
2727  break;
2728  case OBJECT_MATVIEW:
2729  msg = gettext_noop("permission denied for materialized view %s");
2730  break;
2731  case OBJECT_OPCLASS:
2732  msg = gettext_noop("permission denied for operator class %s");
2733  break;
2734  case OBJECT_OPERATOR:
2735  msg = gettext_noop("permission denied for operator %s");
2736  break;
2737  case OBJECT_OPFAMILY:
2738  msg = gettext_noop("permission denied for operator family %s");
2739  break;
2740  case OBJECT_PARAMETER_ACL:
2741  msg = gettext_noop("permission denied for parameter %s");
2742  break;
2743  case OBJECT_POLICY:
2744  msg = gettext_noop("permission denied for policy %s");
2745  break;
2746  case OBJECT_PROCEDURE:
2747  msg = gettext_noop("permission denied for procedure %s");
2748  break;
2749  case OBJECT_PUBLICATION:
2750  msg = gettext_noop("permission denied for publication %s");
2751  break;
2752  case OBJECT_ROUTINE:
2753  msg = gettext_noop("permission denied for routine %s");
2754  break;
2755  case OBJECT_SCHEMA:
2756  msg = gettext_noop("permission denied for schema %s");
2757  break;
2758  case OBJECT_SEQUENCE:
2759  msg = gettext_noop("permission denied for sequence %s");
2760  break;
2761  case OBJECT_STATISTIC_EXT:
2762  msg = gettext_noop("permission denied for statistics object %s");
2763  break;
2764  case OBJECT_SUBSCRIPTION:
2765  msg = gettext_noop("permission denied for subscription %s");
2766  break;
2767  case OBJECT_TABLE:
2768  msg = gettext_noop("permission denied for table %s");
2769  break;
2770  case OBJECT_TABLESPACE:
2771  msg = gettext_noop("permission denied for tablespace %s");
2772  break;
2774  msg = gettext_noop("permission denied for text search configuration %s");
2775  break;
2776  case OBJECT_TSDICTIONARY:
2777  msg = gettext_noop("permission denied for text search dictionary %s");
2778  break;
2779  case OBJECT_TYPE:
2780  msg = gettext_noop("permission denied for type %s");
2781  break;
2782  case OBJECT_VIEW:
2783  msg = gettext_noop("permission denied for view %s");
2784  break;
2785  /* these currently aren't used */
2786  case OBJECT_ACCESS_METHOD:
2787  case OBJECT_AMOP:
2788  case OBJECT_AMPROC:
2789  case OBJECT_ATTRIBUTE:
2790  case OBJECT_CAST:
2791  case OBJECT_DEFAULT:
2792  case OBJECT_DEFACL:
2793  case OBJECT_DOMCONSTRAINT:
2796  case OBJECT_ROLE:
2797  case OBJECT_RULE:
2798  case OBJECT_TABCONSTRAINT:
2799  case OBJECT_TRANSFORM:
2800  case OBJECT_TRIGGER:
2801  case OBJECT_TSPARSER:
2802  case OBJECT_TSTEMPLATE:
2803  case OBJECT_USER_MAPPING:
2804  elog(ERROR, "unsupported object type: %d", objtype);
2805  }
2806 
2807  ereport(ERROR,
2808  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2809  errmsg(msg, objectname)));
2810  break;
2811  }
2812  case ACLCHECK_NOT_OWNER:
2813  {
2814  const char *msg = "???";
2815 
2816  switch (objtype)
2817  {
2818  case OBJECT_AGGREGATE:
2819  msg = gettext_noop("must be owner of aggregate %s");
2820  break;
2821  case OBJECT_COLLATION:
2822  msg = gettext_noop("must be owner of collation %s");
2823  break;
2824  case OBJECT_CONVERSION:
2825  msg = gettext_noop("must be owner of conversion %s");
2826  break;
2827  case OBJECT_DATABASE:
2828  msg = gettext_noop("must be owner of database %s");
2829  break;
2830  case OBJECT_DOMAIN:
2831  msg = gettext_noop("must be owner of domain %s");
2832  break;
2833  case OBJECT_EVENT_TRIGGER:
2834  msg = gettext_noop("must be owner of event trigger %s");
2835  break;
2836  case OBJECT_EXTENSION:
2837  msg = gettext_noop("must be owner of extension %s");
2838  break;
2839  case OBJECT_FDW:
2840  msg = gettext_noop("must be owner of foreign-data wrapper %s");
2841  break;
2842  case OBJECT_FOREIGN_SERVER:
2843  msg = gettext_noop("must be owner of foreign server %s");
2844  break;
2845  case OBJECT_FOREIGN_TABLE:
2846  msg = gettext_noop("must be owner of foreign table %s");
2847  break;
2848  case OBJECT_FUNCTION:
2849  msg = gettext_noop("must be owner of function %s");
2850  break;
2851  case OBJECT_INDEX:
2852  msg = gettext_noop("must be owner of index %s");
2853  break;
2854  case OBJECT_LANGUAGE:
2855  msg = gettext_noop("must be owner of language %s");
2856  break;
2857  case OBJECT_LARGEOBJECT:
2858  msg = gettext_noop("must be owner of large object %s");
2859  break;
2860  case OBJECT_MATVIEW:
2861  msg = gettext_noop("must be owner of materialized view %s");
2862  break;
2863  case OBJECT_OPCLASS:
2864  msg = gettext_noop("must be owner of operator class %s");
2865  break;
2866  case OBJECT_OPERATOR:
2867  msg = gettext_noop("must be owner of operator %s");
2868  break;
2869  case OBJECT_OPFAMILY:
2870  msg = gettext_noop("must be owner of operator family %s");
2871  break;
2872  case OBJECT_PROCEDURE:
2873  msg = gettext_noop("must be owner of procedure %s");
2874  break;
2875  case OBJECT_PUBLICATION:
2876  msg = gettext_noop("must be owner of publication %s");
2877  break;
2878  case OBJECT_ROUTINE:
2879  msg = gettext_noop("must be owner of routine %s");
2880  break;
2881  case OBJECT_SEQUENCE:
2882  msg = gettext_noop("must be owner of sequence %s");
2883  break;
2884  case OBJECT_SUBSCRIPTION:
2885  msg = gettext_noop("must be owner of subscription %s");
2886  break;
2887  case OBJECT_TABLE:
2888  msg = gettext_noop("must be owner of table %s");
2889  break;
2890  case OBJECT_TYPE:
2891  msg = gettext_noop("must be owner of type %s");
2892  break;
2893  case OBJECT_VIEW:
2894  msg = gettext_noop("must be owner of view %s");
2895  break;
2896  case OBJECT_SCHEMA:
2897  msg = gettext_noop("must be owner of schema %s");
2898  break;
2899  case OBJECT_STATISTIC_EXT:
2900  msg = gettext_noop("must be owner of statistics object %s");
2901  break;
2902  case OBJECT_TABLESPACE:
2903  msg = gettext_noop("must be owner of tablespace %s");
2904  break;
2906  msg = gettext_noop("must be owner of text search configuration %s");
2907  break;
2908  case OBJECT_TSDICTIONARY:
2909  msg = gettext_noop("must be owner of text search dictionary %s");
2910  break;
2911 
2912  /*
2913  * Special cases: For these, the error message talks
2914  * about "relation", because that's where the
2915  * ownership is attached. See also
2916  * check_object_ownership().
2917  */
2918  case OBJECT_COLUMN:
2919  case OBJECT_POLICY:
2920  case OBJECT_RULE:
2921  case OBJECT_TABCONSTRAINT:
2922  case OBJECT_TRIGGER:
2923  msg = gettext_noop("must be owner of relation %s");
2924  break;
2925  /* these currently aren't used */
2926  case OBJECT_ACCESS_METHOD:
2927  case OBJECT_AMOP:
2928  case OBJECT_AMPROC:
2929  case OBJECT_ATTRIBUTE:
2930  case OBJECT_CAST:
2931  case OBJECT_DEFAULT:
2932  case OBJECT_DEFACL:
2933  case OBJECT_DOMCONSTRAINT:
2934  case OBJECT_PARAMETER_ACL:
2937  case OBJECT_ROLE:
2938  case OBJECT_TRANSFORM:
2939  case OBJECT_TSPARSER:
2940  case OBJECT_TSTEMPLATE:
2941  case OBJECT_USER_MAPPING:
2942  elog(ERROR, "unsupported object type: %d", objtype);
2943  }
2944 
2945  ereport(ERROR,
2946  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2947  errmsg(msg, objectname)));
2948  break;
2949  }
2950  default:
2951  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
2952  break;
2953  }
2954 }
@ 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:1209
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
@ OBJECT_EVENT_TRIGGER
Definition: parsenodes.h:2134
@ OBJECT_FDW
Definition: parsenodes.h:2136
@ OBJECT_TSPARSER
Definition: parsenodes.h:2167
@ OBJECT_COLLATION
Definition: parsenodes.h:2127
@ OBJECT_USER_MAPPING
Definition: parsenodes.h:2170
@ OBJECT_ACCESS_METHOD
Definition: parsenodes.h:2120
@ OBJECT_OPCLASS
Definition: parsenodes.h:2144
@ OBJECT_DEFACL
Definition: parsenodes.h:2131
@ OBJECT_AGGREGATE
Definition: parsenodes.h:2121
@ OBJECT_MATVIEW
Definition: parsenodes.h:2143
@ OBJECT_SCHEMA
Definition: parsenodes.h:2156
@ OBJECT_POLICY
Definition: parsenodes.h:2148
@ OBJECT_OPERATOR
Definition: parsenodes.h:2145
@ OBJECT_FOREIGN_TABLE
Definition: parsenodes.h:2138
@ OBJECT_TSCONFIGURATION
Definition: parsenodes.h:2165
@ OBJECT_OPFAMILY
Definition: parsenodes.h:2146
@ OBJECT_DOMAIN
Definition: parsenodes.h:2132
@ OBJECT_COLUMN
Definition: parsenodes.h:2126
@ OBJECT_TABLESPACE
Definition: parsenodes.h:2162
@ OBJECT_ROLE
Definition: parsenodes.h:2153
@ OBJECT_ROUTINE
Definition: parsenodes.h:2154
@ OBJECT_LARGEOBJECT
Definition: parsenodes.h:2142
@ OBJECT_PUBLICATION_NAMESPACE
Definition: parsenodes.h:2151
@ OBJECT_PROCEDURE
Definition: parsenodes.h:2149
@ OBJECT_EXTENSION
Definition: parsenodes.h:2135
@ OBJECT_INDEX
Definition: parsenodes.h:2140
@ OBJECT_DEFAULT
Definition: parsenodes.h:2130
@ OBJECT_DATABASE
Definition: parsenodes.h:2129
@ OBJECT_SEQUENCE
Definition: parsenodes.h:2157
@ OBJECT_TSTEMPLATE
Definition: parsenodes.h:2168
@ OBJECT_LANGUAGE
Definition: parsenodes.h:2141
@ OBJECT_AMOP
Definition: parsenodes.h:2122
@ OBJECT_PUBLICATION_REL
Definition: parsenodes.h:2152
@ OBJECT_FOREIGN_SERVER
Definition: parsenodes.h:2137
@ OBJECT_TSDICTIONARY
Definition: parsenodes.h:2166
@ OBJECT_ATTRIBUTE
Definition: parsenodes.h:2124
@ OBJECT_PUBLICATION
Definition: parsenodes.h:2150
@ OBJECT_RULE
Definition: parsenodes.h:2155
@ OBJECT_CONVERSION
Definition: parsenodes.h:2128
@ OBJECT_AMPROC
Definition: parsenodes.h:2123
@ OBJECT_TABLE
Definition: parsenodes.h:2161
@ OBJECT_VIEW
Definition: parsenodes.h:2171
@ OBJECT_PARAMETER_ACL
Definition: parsenodes.h:2147
@ OBJECT_TYPE
Definition: parsenodes.h:2169
@ OBJECT_FUNCTION
Definition: parsenodes.h:2139
@ OBJECT_TABCONSTRAINT
Definition: parsenodes.h:2160
@ OBJECT_DOMCONSTRAINT
Definition: parsenodes.h:2133
@ OBJECT_SUBSCRIPTION
Definition: parsenodes.h:2158
@ OBJECT_STATISTIC_EXT
Definition: parsenodes.h:2159
@ OBJECT_CAST
Definition: parsenodes.h:2125
@ OBJECT_TRIGGER
Definition: parsenodes.h:2164
@ OBJECT_TRANSFORM
Definition: parsenodes.h:2163

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(), CreateSubscription(), 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(), ExecCheckPermissions(), 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 2958 of file aclchk.c.

2960 {
2961  switch (aclerr)
2962  {
2963  case ACLCHECK_OK:
2964  /* no error, so return to caller */
2965  break;
2966  case ACLCHECK_NO_PRIV:
2967  ereport(ERROR,
2968  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2969  errmsg("permission denied for column \"%s\" of relation \"%s\"",
2970  colname, objectname)));
2971  break;
2972  case ACLCHECK_NOT_OWNER:
2973  /* relation msg is OK since columns don't have separate owners */
2974  aclcheck_error(aclerr, objtype, objectname);
2975  break;
2976  default:
2977  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
2978  break;
2979  }
2980 }
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2669

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

967 {
968  GrantStmt *action = stmt->action;
969  InternalDefaultACL iacls;
970  ListCell *cell;
971  List *rolespecs = NIL;
972  List *nspnames = NIL;
973  DefElem *drolespecs = NULL;
974  DefElem *dnspnames = NULL;
975  AclMode all_privileges;
976  const char *errormsg;
977 
978  /* Deconstruct the "options" part of the statement */
979  foreach(cell, stmt->options)
980  {
981  DefElem *defel = (DefElem *) lfirst(cell);
982 
983  if (strcmp(defel->defname, "schemas") == 0)
984  {
985  if (dnspnames)
986  errorConflictingDefElem(defel, pstate);
987  dnspnames = defel;
988  }
989  else if (strcmp(defel->defname, "roles") == 0)
990  {
991  if (drolespecs)
992  errorConflictingDefElem(defel, pstate);
993  drolespecs = defel;
994  }
995  else
996  elog(ERROR, "option \"%s\" not recognized", defel->defname);
997  }
998 
999  if (dnspnames)
1000  nspnames = (List *) dnspnames->arg;
1001  if (drolespecs)
1002  rolespecs = (List *) drolespecs->arg;
1003 
1004  /* Prepare the InternalDefaultACL representation of the statement */
1005  /* roleid to be filled below */
1006  /* nspid to be filled in SetDefaultACLsInSchemas */
1007  iacls.is_grant = action->is_grant;
1008  iacls.objtype = action->objtype;
1009  /* all_privs to be filled below */
1010  /* privileges to be filled below */
1011  iacls.grantees = NIL; /* filled below */
1012  iacls.grant_option = action->grant_option;
1013  iacls.behavior = action->behavior;
1014 
1015  /*
1016  * Convert the RoleSpec list into an Oid list. Note that at this point we
1017  * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
1018  * there shouldn't be any additional work needed to support this case.
1019  */
1020  foreach(cell, action->grantees)
1021  {
1022  RoleSpec *grantee = (RoleSpec *) lfirst(cell);
1023  Oid grantee_uid;
1024 
1025  switch (grantee->roletype)
1026  {
1027  case ROLESPEC_PUBLIC:
1028  grantee_uid = ACL_ID_PUBLIC;
1029  break;
1030  default:
1031  grantee_uid = get_rolespec_oid(grantee, false);
1032  break;
1033  }
1034  iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
1035  }
1036 
1037  /*
1038  * Convert action->privileges, a list of privilege strings, into an
1039  * AclMode bitmask.
1040  */
1041  switch (action->objtype)
1042  {
1043  case OBJECT_TABLE:
1044  all_privileges = ACL_ALL_RIGHTS_RELATION;
1045  errormsg = gettext_noop("invalid privilege type %s for relation");
1046  break;
1047  case OBJECT_SEQUENCE:
1048  all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1049  errormsg = gettext_noop("invalid privilege type %s for sequence");
1050  break;
1051  case OBJECT_FUNCTION:
1052  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1053  errormsg = gettext_noop("invalid privilege type %s for function");
1054  break;
1055  case OBJECT_PROCEDURE:
1056  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1057  errormsg = gettext_noop("invalid privilege type %s for procedure");
1058  break;
1059  case OBJECT_ROUTINE:
1060  all_privileges = ACL_ALL_RIGHTS_FUNCTION;
1061  errormsg = gettext_noop("invalid privilege type %s for routine");
1062  break;
1063  case OBJECT_TYPE:
1064  all_privileges = ACL_ALL_RIGHTS_TYPE;
1065  errormsg = gettext_noop("invalid privilege type %s for type");
1066  break;
1067  case OBJECT_SCHEMA:
1068  all_privileges = ACL_ALL_RIGHTS_SCHEMA;
1069  errormsg = gettext_noop("invalid privilege type %s for schema");
1070  break;
1071  default:
1072  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
1073  (int) action->objtype);
1074  /* keep compiler quiet */
1075  all_privileges = ACL_NO_RIGHTS;
1076  errormsg = NULL;
1077  }
1078 
1079  if (action->privileges == NIL)
1080  {
1081  iacls.all_privs = true;
1082 
1083  /*
1084  * will be turned into ACL_ALL_RIGHTS_* by the internal routines
1085  * depending on the object type
1086  */
1087  iacls.privileges = ACL_NO_RIGHTS;
1088  }
1089  else
1090  {
1091  iacls.all_privs = false;
1092  iacls.privileges = ACL_NO_RIGHTS;
1093 
1094  foreach(cell, action->privileges)
1095  {
1096  AccessPriv *privnode = (AccessPriv *) lfirst(cell);
1097  AclMode priv;
1098 
1099  if (privnode->cols)
1100  ereport(ERROR,
1101  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1102  errmsg("default privileges cannot be set for columns")));
1103 
1104  if (privnode->priv_name == NULL) /* parser mistake? */
1105  elog(ERROR, "AccessPriv node must specify privilege");
1106  priv = string_to_privilege(privnode->priv_name);
1107 
1108  if (priv & ~((AclMode) all_privileges))
1109  ereport(ERROR,
1110  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1111  errmsg(errormsg, privilege_to_string(priv))));
1112 
1113  iacls.privileges |= priv;
1114  }
1115  }
1116 
1117  if (rolespecs == NIL)
1118  {
1119  /* Set permissions for myself */
1120  iacls.roleid = GetUserId();
1121 
1122  SetDefaultACLsInSchemas(&iacls, nspnames);
1123  }
1124  else
1125  {
1126  /* Look up the role OIDs and do permissions checks */
1127  ListCell *rolecell;
1128 
1129  foreach(rolecell, rolespecs)
1130  {
1131  RoleSpec *rolespec = lfirst(rolecell);
1132 
1133  iacls.roleid = get_rolespec_oid(rolespec, false);
1134 
1135  if (!has_privs_of_role(GetUserId(), iacls.roleid))
1136  ereport(ERROR,
1137  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1138  errmsg("permission denied to change default privileges")));
1139 
1140  SetDefaultACLsInSchemas(&iacls, nspnames);
1141  }
1142  }
1143 }
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4961
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5281
#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:2583
static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
Definition: aclchk.c:1151
static const char * privilege_to_string(AclMode privilege)
Definition: aclchk.c:2624
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:385
#define stmt
Definition: indent_codes.h:59
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
List * lappend_oid(List *list, Oid datum)
Definition: list.c:374
Oid GetUserId(void)
Definition: miscinit.c:509
@ ROLESPEC_PUBLIC
Definition: parsenodes.h:395
uint64 AclMode
Definition: parsenodes.h:81
#define ACL_NO_RIGHTS
Definition: parsenodes.h:98
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
char * priv_name
Definition: parsenodes.h:2404
List * cols
Definition: parsenodes.h:2405
char * defname
Definition: parsenodes.h:809
Node * arg
Definition: parsenodes.h:810
bool grant_option
Definition: aclchk.c:96
AclMode privileges
Definition: aclchk.c:94
List * grantees
Definition: aclchk.c:95
DropBehavior behavior
Definition: aclchk.c:97
ObjectType objtype
Definition: aclchk.c:92
Definition: pg_list.h:54
RoleSpecType roletype
Definition: parsenodes.h:401

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, InternalDefaultACL::all_privs, DefElem::arg, InternalDefaultACL::behavior, AccessPriv::cols, DefElem::defname, elog(), ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), get_rolespec_oid(), gettext_noop, GetUserId(), InternalDefaultACL::grant_option, InternalDefaultACL::grantees, has_privs_of_role(), if(), InternalDefaultACL::is_grant, lappend_oid(), lfirst, NIL, OBJECT_FUNCTION, OBJECT_PROCEDURE, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TYPE, InternalDefaultACL::objtype, AccessPriv::priv_name, privilege_to_string(), InternalDefaultACL::privileges, InternalDefaultACL::roleid, ROLESPEC_PUBLIC, RoleSpec::roletype, SetDefaultACLsInSchemas(), stmt, 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 1658 of file aclchk.c.

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

static void ExecGrant_common ( InternalGrant istmt,
Oid  classid,
AclMode  default_privs,
void(*)(InternalGrant *istmt, HeapTuple tuple)  object_check 
)
static

Definition at line 2131 of file aclchk.c.

2133 {
2134  int cacheid;
2135  Relation relation;
2136  ListCell *cell;
2137 
2138  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2139  istmt->privileges = default_privs;
2140 
2141  cacheid = get_object_catcache_oid(classid);
2142 
2143  relation = table_open(classid, RowExclusiveLock);
2144 
2145  foreach(cell, istmt->objects)
2146  {
2147  Oid objectid = lfirst_oid(cell);
2148  Datum aclDatum;
2149  Datum nameDatum;
2150  bool isNull;
2151  AclMode avail_goptions;
2152  AclMode this_privileges;
2153  Acl *old_acl;
2154  Acl *new_acl;
2155  Oid grantorId;
2156  Oid ownerId;
2157  HeapTuple tuple;
2158  HeapTuple newtuple;
2159  Datum *values = palloc0_array(Datum, RelationGetDescr(relation)->natts);
2160  bool *nulls = palloc0_array(bool, RelationGetDescr(relation)->natts);
2161  bool *replaces = palloc0_array(bool, RelationGetDescr(relation)->natts);
2162  int noldmembers;
2163  int nnewmembers;
2164  Oid *oldmembers;
2165  Oid *newmembers;
2166 
2167  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
2168  if (!HeapTupleIsValid(tuple))
2169  elog(ERROR, "cache lookup failed for %s %u", get_object_class_descr(classid), objectid);
2170 
2171  /*
2172  * Additional object-type-specific checks
2173  */
2174  if (object_check)
2175  object_check(istmt, tuple);
2176 
2177  /*
2178  * Get owner ID and working copy of existing ACL. If there's no ACL,
2179  * substitute the proper default.
2180  */
2181  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
2182  tuple,
2183  get_object_attnum_owner(classid)));
2184  aclDatum = SysCacheGetAttr(cacheid,
2185  tuple,
2186  get_object_attnum_acl(classid),
2187  &isNull);
2188  if (isNull)
2189  {
2190  old_acl = acldefault(get_object_type(classid, objectid), ownerId);
2191  /* There are no old member roles according to the catalogs */
2192  noldmembers = 0;
2193  oldmembers = NULL;
2194  }
2195  else
2196  {
2197  old_acl = DatumGetAclPCopy(aclDatum);
2198  /* Get the roles mentioned in the existing ACL */
2199  noldmembers = aclmembers(old_acl, &oldmembers);
2200  }
2201 
2202  /* Determine ID to do the grant as, and available grant options */
2204  old_acl, ownerId,
2205  &grantorId, &avail_goptions);
2206 
2207  nameDatum = SysCacheGetAttrNotNull(cacheid, tuple,
2208  get_object_attnum_name(classid));
2209 
2210  /*
2211  * Restrict the privileges to what we can actually grant, and emit the
2212  * standards-mandated warning and error messages.
2213  */
2214  this_privileges =
2215  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2216  istmt->all_privs, istmt->privileges,
2217  objectid, grantorId, get_object_type(classid, objectid),
2218  NameStr(*DatumGetName(nameDatum)),
2219  0, NULL);
2220 
2221  /*
2222  * Generate new ACL.
2223  */
2224  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2225  istmt->grant_option, istmt->behavior,
2226  istmt->grantees, this_privileges,
2227  grantorId, ownerId);
2228 
2229  /*
2230  * We need the members of both old and new ACLs so we can correct the
2231  * shared dependency information.
2232  */
2233  nnewmembers = aclmembers(new_acl, &newmembers);
2234 
2235  /* finished building new ACL value, now insert it */
2236  replaces[get_object_attnum_acl(classid) - 1] = true;
2237  values[get_object_attnum_acl(classid) - 1] = PointerGetDatum(new_acl);
2238 
2239  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2240  nulls, replaces);
2241 
2242  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2243 
2244  /* Update initial privileges for extensions */
2245  recordExtensionInitPriv(objectid, classid, 0, new_acl);
2246 
2247  /* Update the shared dependency ACL info */
2248  updateAclDependencies(classid,
2249  objectid, 0,
2250  ownerId,
2251  noldmembers, oldmembers,
2252  nnewmembers, newmembers);
2253 
2254  ReleaseSysCache(tuple);
2255 
2256  pfree(new_acl);
2257 
2258  /* prevent error when processing duplicate objects */
2260  }
2261 
2262  table_close(relation, RowExclusiveLock);
2263 }
#define palloc0_array(type, count)
Definition: fe_memutils.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
AttrNumber get_object_attnum_owner(Oid class_id)
AttrNumber get_object_attnum_name(Oid class_id)
AttrNumber get_object_attnum_acl(Oid class_id)
int get_object_catcache_oid(Oid class_id)
ObjectType get_object_type(Oid class_id, Oid object_id)
const char * get_object_class_descr(Oid class_id)
#define lfirst_oid(lc)
Definition: pg_list.h:174
static Name DatumGetName(Datum X)
Definition: postgres.h:360
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
AclMode privileges
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:1112
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
void CommandCounterIncrement(void)
Definition: xact.c:1078

References ACL_NO_RIGHTS, acldefault(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, DatumGetName(), DatumGetObjectId(), elog(), ERROR, get_object_attnum_acl(), get_object_attnum_name(), get_object_attnum_owner(), get_object_catcache_oid(), get_object_class_descr(), get_object_type(), GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, merge_acl_with_grant(), NameStr, ObjectIdGetDatum(), InternalGrant::objects, palloc0_array, pfree(), PointerGetDatum(), InternalGrant::privileges, recordExtensionInitPriv(), RelationGetDescr, ReleaseSysCache(), restrict_and_check_grant(), RowExclusiveLock, SearchSysCache1(), select_best_grantor(), SysCacheGetAttr(), SysCacheGetAttrNotNull(), HeapTupleData::t_self, table_close(), table_open(), updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_Language_check()

static void ExecGrant_Language_check ( InternalGrant istmt,
HeapTuple  tuple 
)
static

Definition at line 2266 of file aclchk.c.

2267 {
2268  Form_pg_language pg_language_tuple;
2269 
2270  pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
2271 
2272  if (!pg_language_tuple->lanpltrusted)
2273  ereport(ERROR,
2274  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2275  errmsg("language \"%s\" is not trusted",
2276  NameStr(pg_language_tuple->lanname)),
2277  errdetail("GRANT and REVOKE are not allowed on untrusted languages, "
2278  "because only superusers can use untrusted languages.")));
2279 }
int errdetail(const char *fmt,...)
Definition: elog.c:1202
FormData_pg_language * Form_pg_language
Definition: pg_language.h:65

References ereport, errcode(), errdetail(), errmsg(), ERROR, GETSTRUCT, and NameStr.

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_Largeobject()

static void ExecGrant_Largeobject ( InternalGrant istmt)
static

Definition at line 2282 of file aclchk.c.

2283 {
2284  Relation relation;
2285  ListCell *cell;
2286 
2287  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2289 
2290  relation = table_open(LargeObjectMetadataRelationId,
2292 
2293  foreach(cell, istmt->objects)
2294  {
2295  Oid loid = lfirst_oid(cell);
2296  Form_pg_largeobject_metadata form_lo_meta;
2297  char loname[NAMEDATALEN];
2298  Datum aclDatum;
2299  bool isNull;
2300  AclMode avail_goptions;
2301  AclMode this_privileges;
2302  Acl *old_acl;
2303  Acl *new_acl;
2304  Oid grantorId;
2305  Oid ownerId;
2306  HeapTuple newtuple;
2307  Datum values[Natts_pg_largeobject_metadata] = {0};
2308  bool nulls[Natts_pg_largeobject_metadata] = {0};
2309  bool replaces[Natts_pg_largeobject_metadata] = {0};
2310  int noldmembers;
2311  int nnewmembers;
2312  Oid *oldmembers;
2313  Oid *newmembers;
2314  ScanKeyData entry[1];
2315  SysScanDesc scan;
2316  HeapTuple tuple;
2317 
2318  /* There's no syscache for pg_largeobject_metadata */
2319  ScanKeyInit(&entry[0],
2320  Anum_pg_largeobject_metadata_oid,
2321  BTEqualStrategyNumber, F_OIDEQ,
2322  ObjectIdGetDatum(loid));
2323 
2324  scan = systable_beginscan(relation,
2325  LargeObjectMetadataOidIndexId, true,
2326  NULL, 1, entry);
2327 
2328  tuple = systable_getnext(scan);
2329  if (!HeapTupleIsValid(tuple))
2330  elog(ERROR, "could not find tuple for large object %u", loid);
2331 
2332  form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
2333 
2334  /*
2335  * Get owner ID and working copy of existing ACL. If there's no ACL,
2336  * substitute the proper default.
2337  */
2338  ownerId = form_lo_meta->lomowner;
2339  aclDatum = heap_getattr(tuple,
2340  Anum_pg_largeobject_metadata_lomacl,
2341  RelationGetDescr(relation), &isNull);
2342  if (isNull)
2343  {
2344  old_acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
2345  /* There are no old member roles according to the catalogs */
2346  noldmembers = 0;
2347  oldmembers = NULL;
2348  }
2349  else
2350  {
2351  old_acl = DatumGetAclPCopy(aclDatum);
2352  /* Get the roles mentioned in the existing ACL */
2353  noldmembers = aclmembers(old_acl, &oldmembers);
2354  }
2355 
2356  /* Determine ID to do the grant as, and available grant options */
2358  old_acl, ownerId,
2359  &grantorId, &avail_goptions);
2360 
2361  /*
2362  * Restrict the privileges to what we can actually grant, and emit the
2363  * standards-mandated warning and error messages.
2364  */
2365  snprintf(loname, sizeof(loname), "large object %u", loid);
2366  this_privileges =
2367  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2368  istmt->all_privs, istmt->privileges,
2369  loid, grantorId, OBJECT_LARGEOBJECT,
2370  loname, 0, NULL);
2371 
2372  /*
2373  * Generate new ACL.
2374  */
2375  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2376  istmt->grant_option, istmt->behavior,
2377  istmt->grantees, this_privileges,
2378  grantorId, ownerId);
2379 
2380  /*
2381  * We need the members of both old and new ACLs so we can correct the
2382  * shared dependency information.
2383  */
2384  nnewmembers = aclmembers(new_acl, &newmembers);
2385 
2386  /* finished building new ACL value, now insert it */
2387  replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
2388  values[Anum_pg_largeobject_metadata_lomacl - 1]
2389  = PointerGetDatum(new_acl);
2390 
2391  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2392  values, nulls, replaces);
2393 
2394  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2395 
2396  /* Update initial privileges for extensions */
2397  recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
2398 
2399  /* Update the shared dependency ACL info */
2400  updateAclDependencies(LargeObjectRelationId,
2401  form_lo_meta->oid, 0,
2402  ownerId,
2403  noldmembers, oldmembers,
2404  nnewmembers, newmembers);
2405 
2406  systable_endscan(scan);
2407 
2408  pfree(new_acl);
2409 
2410  /* prevent error when processing duplicate objects */
2412  }
2413 
2414  table_close(relation, RowExclusiveLock);
2415 }
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition: acl.h:166
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:599
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:506
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define NAMEDATALEN
FormData_pg_largeobject_metadata * Form_pg_largeobject_metadata
#define snprintf
Definition: port.h:238
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, 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_Parameter()

static void ExecGrant_Parameter ( InternalGrant istmt)
static

Definition at line 2440 of file aclchk.c.

2441 {
2442  Relation relation;
2443  ListCell *cell;
2444 
2445  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2447 
2448  relation = table_open(ParameterAclRelationId, RowExclusiveLock);
2449 
2450  foreach(cell, istmt->objects)
2451  {
2452  Oid parameterId = lfirst_oid(cell);
2453  Datum nameDatum;
2454  const char *parname;
2455  Datum aclDatum;
2456  bool isNull;
2457  AclMode avail_goptions;
2458  AclMode this_privileges;
2459  Acl *old_acl;
2460  Acl *new_acl;
2461  Oid grantorId;
2462  Oid ownerId;
2463  HeapTuple tuple;
2464  int noldmembers;
2465  int nnewmembers;
2466  Oid *oldmembers;
2467  Oid *newmembers;
2468 
2469  tuple = SearchSysCache1(PARAMETERACLOID, ObjectIdGetDatum(parameterId));
2470  if (!HeapTupleIsValid(tuple))
2471  elog(ERROR, "cache lookup failed for parameter ACL %u",
2472  parameterId);
2473 
2474  /* We'll need the GUC's name */
2475  nameDatum = SysCacheGetAttrNotNull(PARAMETERACLOID, tuple,
2476  Anum_pg_parameter_acl_parname);
2477  parname = TextDatumGetCString(nameDatum);
2478 
2479  /* Treat all parameters as belonging to the bootstrap superuser. */
2480  ownerId = BOOTSTRAP_SUPERUSERID;
2481 
2482  /*
2483  * Get working copy of existing ACL. If there's no ACL, substitute the
2484  * proper default.
2485  */
2486  aclDatum = SysCacheGetAttr(PARAMETERACLOID, tuple,
2487  Anum_pg_parameter_acl_paracl,
2488  &isNull);
2489 
2490  if (isNull)
2491  {
2492  old_acl = acldefault(istmt->objtype, ownerId);
2493  /* There are no old member roles according to the catalogs */
2494  noldmembers = 0;
2495  oldmembers = NULL;
2496  }
2497  else
2498  {
2499  old_acl = DatumGetAclPCopy(aclDatum);
2500  /* Get the roles mentioned in the existing ACL */
2501  noldmembers = aclmembers(old_acl, &oldmembers);
2502  }
2503 
2504  /* Determine ID to do the grant as, and available grant options */
2506  old_acl, ownerId,
2507  &grantorId, &avail_goptions);
2508 
2509  /*
2510  * Restrict the privileges to what we can actually grant, and emit the
2511  * standards-mandated warning and error messages.
2512  */
2513  this_privileges =
2514  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2515  istmt->all_privs, istmt->privileges,
2516  parameterId, grantorId,
2518  parname,
2519  0, NULL);
2520 
2521  /*
2522  * Generate new ACL.
2523  */
2524  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2525  istmt->grant_option, istmt->behavior,
2526  istmt->grantees, this_privileges,
2527  grantorId, ownerId);
2528 
2529  /*
2530  * We need the members of both old and new ACLs so we can correct the
2531  * shared dependency information.
2532  */
2533  nnewmembers = aclmembers(new_acl, &newmembers);
2534 
2535  /*
2536  * If the new ACL is equal to the default, we don't need the catalog
2537  * entry any longer. Delete it rather than updating it, to avoid
2538  * leaving a degenerate entry.
2539  */
2540  if (aclequal(new_acl, acldefault(istmt->objtype, ownerId)))
2541  {
2542  CatalogTupleDelete(relation, &tuple->t_self);
2543  }
2544  else
2545  {
2546  /* finished building new ACL value, now insert it */
2547  HeapTuple newtuple;
2548  Datum values[Natts_pg_parameter_acl] = {0};
2549  bool nulls[Natts_pg_parameter_acl] = {0};
2550  bool replaces[Natts_pg_parameter_acl] = {0};
2551 
2552  replaces[Anum_pg_parameter_acl_paracl - 1] = true;
2553  values[Anum_pg_parameter_acl_paracl - 1] = PointerGetDatum(new_acl);
2554 
2555  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
2556  values, nulls, replaces);
2557 
2558  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2559  }
2560 
2561  /* Update initial privileges for extensions */
2562  recordExtensionInitPriv(parameterId, ParameterAclRelationId, 0,
2563  new_acl);
2564 
2565  /* Update the shared dependency ACL info */
2566  updateAclDependencies(ParameterAclRelationId, parameterId, 0,
2567  ownerId,
2568  noldmembers, oldmembers,
2569  nnewmembers, newmembers);
2570 
2571  ReleaseSysCache(tuple);
2572  pfree(new_acl);
2573 
2574  /* prevent error when processing duplicate objects */
2576  }
2577 
2578  table_close(relation, RowExclusiveLock);
2579 }
bool aclequal(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:533
#define ACL_ALL_RIGHTS_PARAMETER_ACL
Definition: acl.h:167
#define TextDatumGetCString(d)
Definition: builtins.h:95
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
ObjectType objtype
@ PARAMETERACLOID
Definition: syscache.h:76

References ACL_ALL_RIGHTS_PARAMETER_ACL, ACL_NO_RIGHTS, acldefault(), aclequal(), aclmembers(), InternalGrant::all_privs, InternalGrant::behavior, CatalogTupleDelete(), CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, elog(), ERROR, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, InternalGrant::is_grant, lfirst_oid, 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(), SysCacheGetAttrNotNull(), HeapTupleData::t_self, table_close(), table_open(), TextDatumGetCString, updateAclDependencies(), and values.

Referenced by ExecGrantStmt_oids().

◆ ExecGrant_Relation()

static void ExecGrant_Relation ( InternalGrant istmt)
static

Definition at line 1803 of file aclchk.c.

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

static void ExecGrant_Type_check ( InternalGrant istmt,
HeapTuple  tuple 
)
static

Definition at line 2418 of file aclchk.c.

2419 {
2420  Form_pg_type pg_type_tuple;
2421 
2422  pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
2423 
2424  if (IsTrueArrayType(pg_type_tuple))
2425  ereport(ERROR,
2426  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
2427  errmsg("cannot set privileges of array types"),
2428  errhint("Set the privileges of the element type instead.")));
2429 
2430  /* Used GRANT DOMAIN on a non-domain? */
2431  if (istmt->objtype == OBJECT_DOMAIN &&
2432  pg_type_tuple->typtype != TYPTYPE_DOMAIN)
2433  ereport(ERROR,
2434  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2435  errmsg("\"%s\" is not a domain",
2436  NameStr(pg_type_tuple->typname))));
2437 }
int errhint(const char *fmt,...)
Definition: elog.c:1316
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261

References ereport, errcode(), errhint(), errmsg(), ERROR, GETSTRUCT, NameStr, OBJECT_DOMAIN, and InternalGrant::objtype.

Referenced by ExecGrantStmt_oids().

◆ ExecGrantStmt_oids()

static void ExecGrantStmt_oids ( InternalGrant istmt)
static

Definition at line 592 of file aclchk.c.

593 {
594  switch (istmt->objtype)
595  {
596  case OBJECT_TABLE:
597  case OBJECT_SEQUENCE:
598  ExecGrant_Relation(istmt);
599  break;
600  case OBJECT_DATABASE:
601  ExecGrant_common(istmt, DatabaseRelationId, ACL_ALL_RIGHTS_DATABASE, NULL);
602  break;
603  case OBJECT_DOMAIN:
604  case OBJECT_TYPE:
606  break;
607  case OBJECT_FDW:
608  ExecGrant_common(istmt, ForeignDataWrapperRelationId, ACL_ALL_RIGHTS_FDW, NULL);
609  break;
611  ExecGrant_common(istmt, ForeignServerRelationId, ACL_ALL_RIGHTS_FOREIGN_SERVER, NULL);
612  break;
613  case OBJECT_FUNCTION:
614  case OBJECT_PROCEDURE:
615  case OBJECT_ROUTINE:
616  ExecGrant_common(istmt, ProcedureRelationId, ACL_ALL_RIGHTS_FUNCTION, NULL);
617  break;
618  case OBJECT_LANGUAGE:
620  break;
621  case OBJECT_LARGEOBJECT:
622  ExecGrant_Largeobject(istmt);
623  break;
624  case OBJECT_SCHEMA:
625  ExecGrant_common(istmt, NamespaceRelationId, ACL_ALL_RIGHTS_SCHEMA, NULL);
626  break;
627  case OBJECT_TABLESPACE:
628  ExecGrant_common(istmt, TableSpaceRelationId, ACL_ALL_RIGHTS_TABLESPACE, NULL);
629  break;
631  ExecGrant_Parameter(istmt);
632  break;
633  default:
634  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
635  (int) istmt->objtype);
636  }
637 
638  /*
639  * Pass the info to event triggers about the just-executed GRANT. Note
640  * that we prefer to do it after actually executing it, because that gives
641  * the functions a chance to adjust the istmt with privileges actually
642  * granted.
643  */
646 }
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:163
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:169
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:161
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:165
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:162
static void ExecGrant_Type_check(InternalGrant *istmt, HeapTuple tuple)
Definition: aclchk.c:2418
static void ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs, void(*object_check)(InternalGrant *istmt, HeapTuple tuple))
Definition: aclchk.c:2131
static void ExecGrant_Largeobject(InternalGrant *istmt)
Definition: aclchk.c:2282
static void ExecGrant_Parameter(InternalGrant *istmt)
Definition: aclchk.c:2440
static void ExecGrant_Relation(InternalGrant *istmt)
Definition: aclchk.c:1803
static void ExecGrant_Language_check(InternalGrant *istmt, HeapTuple tuple)
Definition: aclchk.c:2266
bool EventTriggerSupportsObjectType(ObjectType obtype)
void EventTriggerCollectGrant(InternalGrant *istmt)

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_SCHEMA, ACL_ALL_RIGHTS_TABLESPACE, ACL_ALL_RIGHTS_TYPE, elog(), ERROR, EventTriggerCollectGrant(), EventTriggerSupportsObjectType(), ExecGrant_common(), ExecGrant_Language_check(), ExecGrant_Largeobject(), ExecGrant_Parameter(), ExecGrant_Relation(), ExecGrant_Type_check(), 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 382 of file aclchk.c.

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

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, InternalGrant::behavior, InternalGrant::col_privs, AccessPriv::cols, elog(), ereport, errcode(), errmsg(), ERROR, ExecGrantStmt_oids(), get_rolespec_oid(), gettext_noop, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, 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(), InternalGrant::objects, objectsInSchemaToOids(), InternalGrant::objtype, AccessPriv::priv_name, privilege_to_string(), InternalGrant::privileges, ROLESPEC_PUBLIC, RoleSpec::roletype, stmt, and string_to_privilege().

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

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

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

1583 {
1584  ListCell *cell;
1585 
1586  foreach(cell, colnames)
1587  {
1588  char *colname = strVal(lfirst(cell));
1590 
1591  attnum = get_attnum(table_oid, colname);
1592  if (attnum == InvalidAttrNumber)
1593  ereport(ERROR,
1594  (errcode(ERRCODE_UNDEFINED_COLUMN),
1595  errmsg("column \"%s\" of relation \"%s\" does not exist",
1596  colname, get_rel_name(table_oid))));
1598  if (attnum <= 0 || attnum >= num_col_privileges)
1599  elog(ERROR, "column number out of range"); /* safety check */
1600  col_privileges[attnum] |= this_privileges;
1601  }
1602 }
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:857
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1932
#define strVal(v)
Definition: value.h:82

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

4082 {
4083  Acl *result = NULL;
4084  HeapTuple tuple;
4085 
4087  ObjectIdGetDatum(roleId),
4088  ObjectIdGetDatum(nsp_oid),
4089  CharGetDatum(objtype));
4090 
4091  if (HeapTupleIsValid(tuple))
4092  {
4093  Datum aclDatum;
4094  bool isNull;
4095 
4096  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
4097  Anum_pg_default_acl_defaclacl,
4098  &isNull);
4099  if (!isNull)
4100  result = DatumGetAclPCopy(aclDatum);
4101  ReleaseSysCache(tuple);
4102  }
4103 
4104  return result;
4105 }
static Datum CharGetDatum(char X)
Definition: postgres.h:122
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:842
@ 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 4116 of file aclchk.c.

4117 {
4118  Acl *result;
4119  Acl *glob_acl;
4120  Acl *schema_acl;
4121  Acl *def_acl;
4122  char defaclobjtype;
4123 
4124  /*
4125  * Use NULL during bootstrap, since pg_default_acl probably isn't there
4126  * yet.
4127  */
4129  return NULL;
4130 
4131  /* Check if object type is supported in pg_default_acl */
4132  switch (objtype)
4133  {
4134  case OBJECT_TABLE:
4135  defaclobjtype = DEFACLOBJ_RELATION;
4136  break;
4137 
4138  case OBJECT_SEQUENCE:
4139  defaclobjtype = DEFACLOBJ_SEQUENCE;
4140  break;
4141 
4142  case OBJECT_FUNCTION:
4143  defaclobjtype = DEFACLOBJ_FUNCTION;
4144  break;
4145 
4146  case OBJECT_TYPE:
4147  defaclobjtype = DEFACLOBJ_TYPE;
4148  break;
4149 
4150  case OBJECT_SCHEMA:
4151  defaclobjtype = DEFACLOBJ_NAMESPACE;
4152  break;
4153 
4154  default:
4155  return NULL;
4156  }
4157 
4158  /* Look up the relevant pg_default_acl entries */
4159  glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
4160  schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
4161 
4162  /* Quick out if neither entry exists */
4163  if (glob_acl == NULL && schema_acl == NULL)
4164  return NULL;
4165 
4166  /* We need to know the hard-wired default value, too */
4167  def_acl = acldefault(objtype, ownerId);
4168 
4169  /* If there's no global entry, substitute the hard-wired default */
4170  if (glob_acl == NULL)
4171  glob_acl = def_acl;
4172 
4173  /* Merge in any per-schema privileges */
4174  result = aclmerge(glob_acl, schema_acl, ownerId);
4175 
4176  /*
4177  * For efficiency, we want to return NULL if the result equals default.
4178  * This requires sorting both arrays to get an accurate comparison.
4179  */
4180  aclitemsort(result);
4181  aclitemsort(def_acl);
4182  if (aclequal(result, def_acl))
4183  result = NULL;
4184 
4185  return result;
4186 }
void aclitemsort(Acl *acl)
Definition: acl.c:519
Acl * aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
Definition: acl.c:475
static Acl * get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
Definition: aclchk.c:4081
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:414
#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 928 of file aclchk.c.

929 {
930  List *relations = NIL;
931  ScanKeyData key[2];
932  Relation rel;
933  TableScanDesc scan;
934  HeapTuple tuple;
935 
936  ScanKeyInit(&key[0],
937  Anum_pg_class_relnamespace,
938  BTEqualStrategyNumber, F_OIDEQ,
939  ObjectIdGetDatum(namespaceId));
940  ScanKeyInit(&key[1],
941  Anum_pg_class_relkind,
942  BTEqualStrategyNumber, F_CHAREQ,
943  CharGetDatum(relkind));
944 
945  rel = table_open(RelationRelationId, AccessShareLock);
946  scan = table_beginscan_catalog(rel, 2, key);
947 
948  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
949  {
950  Oid oid = ((Form_pg_class) GETSTRUCT(tuple))->oid;
951 
952  relations = lappend_oid(relations, oid);
953  }
954 
955  table_endscan(scan);
957 
958  return relations;
959 }
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1086
#define AccessShareLock
Definition: lockdefs.h:36
@ ForwardScanDirection
Definition: sdir.h:28
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1009

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

4058 {
4059  bool result = false;
4060  HeapTuple utup;
4061 
4062  /* Superusers bypass all permission checking. */
4063  if (superuser_arg(roleid))
4064  return true;
4065 
4066  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4067  if (HeapTupleIsValid(utup))
4068  {
4069  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
4070  ReleaseSysCache(utup);
4071  }
4072  return result;
4073 }
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 AlterRole(), check_enable_rls(), CreateRole(), and RI_Initial_Check().

◆ has_createrole_privilege()

bool has_createrole_privilege ( Oid  roleid)

Definition at line 4038 of file aclchk.c.

4039 {
4040  bool result = false;
4041  HeapTuple utup;
4042 
4043  /* Superusers bypass all permission checking. */
4044  if (superuser_arg(roleid))
4045  return true;
4046 
4047  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4048  if (HeapTupleIsValid(utup))
4049  {
4050  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
4051  ReleaseSysCache(utup);
4052  }
4053  return result;
4054 }
bool rolcreaterole
Definition: pg_authid.h:37

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

Referenced by check_object_ownership(), CreateRole(), 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 172 of file aclchk.c.

176 {
177  unsigned modechg;
178  ListCell *j;
179  Acl *new_acl;
180 
181  modechg = is_grant ? ACL_MODECHG_ADD : ACL_MODECHG_DEL;
182 
183  new_acl = old_acl;
184 
185  foreach(j, grantees)
186  {
187  AclItem aclitem;
188  Acl *newer_acl;
189 
190  aclitem.ai_grantee = lfirst_oid(j);
191 
192  /*
193  * Grant options can only be granted to individual roles, not PUBLIC.
194  * The reason is that if a user would re-grant a privilege that he
195  * held through PUBLIC, and later the user is removed, the situation
196  * is impossible to clean up.
197  */
198  if (is_grant && grant_option && aclitem.ai_grantee == ACL_ID_PUBLIC)
199  ereport(ERROR,
200  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
201  errmsg("grant options can only be granted to roles")));
202 
203  aclitem.ai_grantor = grantorId;
204 
205  /*
206  * The asymmetry in the conditions here comes from the spec. In
207  * GRANT, the grant_option flag signals WITH GRANT OPTION, which means
208  * to grant both the basic privilege and its grant option. But in
209  * REVOKE, plain revoke revokes both the basic privilege and its grant
210  * option, while REVOKE GRANT OPTION revokes only the option.
211  */
213  (is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
214  (!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS);
215 
216  newer_acl = aclupdate(new_acl, &aclitem, modechg, ownerId, behavior);
217 
218  /* avoid memory leak when there are many grantees */
219  pfree(new_acl);
220  new_acl = newer_acl;
221  }
222 
223  return new_acl;
224 }
Acl * aclupdate(const Acl *old_acl, const AclItem *mod_aip, int modechg, Oid ownerId, DropBehavior behavior)
Definition: acl.c:966
#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_common(), ExecGrant_Largeobject(), ExecGrant_Parameter(), ExecGrant_Relation(), and SetDefaultACL().

◆ object_aclcheck()

AclResult object_aclcheck ( Oid  classid,
Oid  objectid,
Oid  roleid,
AclMode  mode 
)

Definition at line 3760 of file aclchk.c.

3761 {
3762  if (object_aclmask(classid, objectid, roleid, mode, ACLMASK_ANY) != 0)
3763  return ACLCHECK_OK;
3764  else
3765  return ACLCHECK_NO_PRIV;
3766 }
@ ACLMASK_ANY
Definition: acl.h:176
static AclMode object_aclmask(Oid classid, Oid objectid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3065
static PgChecksumMode mode
Definition: pg_checksums.c:56

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

Referenced by AggregateCreate(), AlterExtensionNamespace(), AlterForeignServerOwner_internal(), AlterObjectNamespace_internal(), AlterObjectOwner_internal(), AlterObjectRename_internal(), AlterPublicationOwner_internal(), AlterSchemaOwner_internal(), AlterSubscriptionOwner_internal(), AlterTableMoveAll(), AlterTypeOwner(), ATExecAddColumn(), ATExecChangeOwner(), ATPrepAlterColumnType(), ATPrepSetTableSpace(), BuildDescForRelation(), calculate_database_size(), calculate_tablespace_size(), call_pltcl_start_proc(), check_temp_tablespaces(), CheckFunctionValidatorAccess(), CheckMyDatabase(), compute_return_type(), CreateCast(), CreateConversionCommand(), createdb(), CreateForeignServer(), CreateForeignTable(), CreateFunction(), CreatePublication(), CreateSchemaCommand(), CreateSubscription(), CreateTransform(), CreateTriggerFiringOn(), DefineAggregate(), DefineCollation(), DefineDomain(), DefineEnum(), DefineIndex(), DefineOpClass(), DefineOperator(), DefineOpFamily(), DefineRange(), DefineRelation(), DefineTSConfiguration(), DefineTSDictionary(), DefineType(), ExecBuildGroupingEqual(), ExecBuildParamSetEqual(), ExecInitAgg(), ExecInitExprRec(), ExecInitFunc(), ExecInitWindowAgg(), ExecReindex(), ExecuteCallStmt(), ExecuteDoStmt(), extension_is_trusted(), findRangeCanonicalFunction(), findRangeSubtypeDiffFunction(), get_connect_string(), get_other_operator(), HandleFunctionRequest(), has_database_privilege_id(), has_database_privilege_id_id(), has_database_privilege_id_name(), has_database_privilege_name(), has_database_privilege_name_id(), has_database_privilege_name_name(), has_foreign_data_wrapper_privilege_id(), has_foreign_data_wrapper_privilege_id_id(), has_foreign_data_wrapper_privilege_id_name(), has_foreign_data_wrapper_privilege_name(), has_foreign_data_wrapper_privilege_name_id(), has_foreign_data_wrapper_privilege_name_name(), has_function_privilege_id(), has_function_privilege_id_id(), has_function_privilege_id_name(), has_function_privilege_name(), has_function_privilege_name_id(), has_function_privilege_name_name(), has_language_privilege_id(), has_language_privilege_id_id(), has_language_privilege_id_name(), has_language_privilege_name(), has_language_privilege_name_id(), has_language_privilege_name_name(), has_schema_privilege_id(), has_schema_privilege_id_id(), has_schema_privilege_id_name(), has_schema_privilege_name(), has_schema_privilege_name_id(), has_schema_privilege_name_name(), has_server_privilege_id(), has_server_privilege_id_id(), has_server_privilege_id_name(), has_server_privilege_name(), has_server_privilege_name_id(), has_server_privilege_name_name(), has_tablespace_privilege_id(), has_tablespace_privilege_id_id(), has_tablespace_privilege_id_name(), has_tablespace_privilege_name(), has_tablespace_privilege_name_id(), has_tablespace_privilege_name_name(), has_type_privilege_id(), has_type_privilege_id_id(), has_type_privilege_id_name(), has_type_privilege_name(), has_type_privilege_name_id(), has_type_privilege_name_name(), ImportForeignSchema(), init_sexpr(), initialize_peragg(), InitTempTableNamespace(), inline_function(), inline_set_returning_function(), interpret_function_parameter_list(), lookup_agg_function(), LookupCreationNamespace(), LookupExplicitNamespace(), movedb(), pg_namespace_aclmask(), PrepareTempTablespaces(), RangeVarCallbackForAlterRelation(), RangeVarGetAndCheckCreationNamespace(), recomputeNamespacePath(), ReindexMultipleInternal(), RenameSchema(), transformTableLikeClause(), user_mapping_ddl_aclcheck(), ValidateJoinEstimator(), and ValidateRestrictionEstimator().

◆ object_aclmask()

static AclMode object_aclmask ( Oid  classid,
Oid  objectid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)
static

Definition at line 3065 of file aclchk.c.

3067 {
3068  int cacheid;
3069  AclMode result;
3070  HeapTuple tuple;
3071  Datum aclDatum;
3072  bool isNull;
3073  Acl *acl;
3074  Oid ownerId;
3075 
3076  /* Special cases */
3077  switch (classid)
3078  {
3079  case NamespaceRelationId:
3080  return pg_namespace_aclmask(objectid, roleid, mask, how);
3081  case TypeRelationId:
3082  return pg_type_aclmask(objectid, roleid, mask, how);
3083  }
3084 
3085  /* Even more special cases */
3086  Assert(classid != RelationRelationId); /* should use pg_class_acl* */
3087  Assert(classid != LargeObjectMetadataRelationId); /* should use
3088  * pg_largeobject_acl* */
3089 
3090  /* Superusers bypass all permission checking. */
3091  if (superuser_arg(roleid))
3092  return mask;
3093 
3094  /*
3095  * Get the objects's ACL from its catalog
3096  */
3097 
3098  cacheid = get_object_catcache_oid(classid);
3099 
3100  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
3101  if (!HeapTupleIsValid(tuple))
3102  ereport(ERROR,
3103  (errcode(ERRCODE_UNDEFINED_DATABASE),
3104  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
3105 
3106  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
3107  tuple,
3108  get_object_attnum_owner(classid)));
3109 
3110  aclDatum = SysCacheGetAttr(cacheid, tuple, get_object_attnum_acl(classid),
3111  &isNull);
3112  if (isNull)
3113  {
3114  /* No ACL, so build default ACL */
3115  acl = acldefault(get_object_type(classid, objectid), ownerId);
3116  aclDatum = (Datum) 0;
3117  }
3118  else
3119  {
3120  /* detoast ACL if necessary */
3121  acl = DatumGetAclP(aclDatum);
3122  }
3123 
3124  result = aclmask(acl, roleid, ownerId, mask, how);
3125 
3126  /* if we have a detoasted copy, free it */
3127  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3128  pfree(acl);
3129 
3130  ReleaseSysCache(tuple);
3131 
3132  return result;
3133 }
AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
Definition: acl.c:1356
#define DatumGetAclP(X)
Definition: acl.h:120
static AclMode pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3683
static AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3591
char * Pointer
Definition: c.h:472
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312

References acldefault(), aclmask(), Assert(), DatumGetAclP, DatumGetObjectId(), DatumGetPointer(), ereport, errcode(), errmsg(), ERROR, get_object_attnum_acl(), get_object_attnum_owner(), get_object_catcache_oid(), get_object_class_descr(), get_object_type(), HeapTupleIsValid, ObjectIdGetDatum(), pfree(), pg_namespace_aclmask(), pg_type_aclmask(), ReleaseSysCache(), SearchSysCache1(), superuser_arg(), SysCacheGetAttr(), and SysCacheGetAttrNotNull().

Referenced by object_aclcheck(), and pg_aclmask().

◆ object_ownercheck()

bool object_ownercheck ( Oid  classid,
Oid  objectid,
Oid  roleid 
)

Definition at line 3961 of file aclchk.c.

3962 {
3963  int cacheid;
3964  Oid ownerId;
3965 
3966  /* Superusers bypass all permission checking. */
3967  if (superuser_arg(roleid))
3968  return true;
3969 
3970  cacheid = get_object_catcache_oid(classid);
3971  if (cacheid != -1)
3972  {
3973  HeapTuple tuple;
3974 
3975  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
3976  if (!HeapTupleIsValid(tuple))
3977  ereport(ERROR,
3978  (errcode(ERRCODE_UNDEFINED_OBJECT),
3979  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
3980 
3981  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
3982  tuple,
3983  get_object_attnum_owner(classid)));
3984  ReleaseSysCache(tuple);
3985  }
3986  else
3987  {
3988  /* for catalogs without an appropriate syscache */
3989 
3990  Relation rel;
3991  ScanKeyData entry[1];
3992  SysScanDesc scan;
3993  HeapTuple tuple;
3994  bool isnull;
3995 
3996  rel = table_open(classid, AccessShareLock);
3997 
3998  ScanKeyInit(&entry[0],
3999  get_object_attnum_oid(classid),
4000  BTEqualStrategyNumber, F_OIDEQ,
4001  ObjectIdGetDatum(objectid));
4002 
4003  scan = systable_beginscan(rel,
4004  get_object_oid_index(classid), true,
4005  NULL, 1, entry);
4006 
4007  tuple = systable_getnext(scan);
4008  if (!HeapTupleIsValid(tuple))
4009  ereport(ERROR,
4010  (errcode(ERRCODE_UNDEFINED_OBJECT),
4011  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
4012 
4013  ownerId = DatumGetObjectId(heap_getattr(tuple,
4014  get_object_attnum_owner(classid),
4015  RelationGetDescr(rel),
4016  &isnull));
4017  Assert(!isnull);
4018 
4019  systable_endscan(scan);
4021  }
4022 
4023  return has_privs_of_role(roleid, ownerId);
4024 }
AttrNumber get_object_attnum_oid(Oid class_id)
Oid get_object_oid_index(Oid class_id)

References AccessShareLock, Assert(), BTEqualStrategyNumber, DatumGetObjectId(), ereport, errcode(), errmsg(), ERROR, get_object_attnum_oid(), get_object_attnum_owner(), get_object_catcache_oid(), get_object_class_descr(), get_object_oid_index(), has_privs_of_role(), heap_getattr(), HeapTupleIsValid, ObjectIdGetDatum(), RelationGetDescr, ReleaseSysCache(), ScanKeyInit(), SearchSysCache1(), superuser_arg(), SysCacheGetAttrNotNull(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterCollation(), AlterDatabase(), AlterDatabaseOwner(), AlterDatabaseRefreshColl(), AlterDatabaseSet(), AlterEventTrigger(), AlterEventTriggerOwner_internal(), AlterExtensionNamespace(), AlterForeignServer(), AlterForeignServerOwner_internal(), AlterFunction(), AlterOperator(), AlterOpFamilyAdd(), AlterPublication(), AlterPublicationOwner_internal(), AlterRoleSet(), AlterSchemaOwner_internal(), AlterStatistics(), AlterSubscription(), AlterSubscriptionOwner_internal(), AlterTableMoveAll(), AlterTableSpaceOptions(), AlterTSConfiguration(), AlterTSDictionary(), AlterType(), AlterTypeNamespace_oid(), AlterTypeOwner(), ATExecChangeOwner(), ATSimplePermissions(), be_lo_unlink(), brin_desummarize_range(), brin_summarize_range(), check_enable_rls(), check_object_ownership(), checkDomainOwner(), checkEnumOwner(), cluster_rel(), CreateCast(), createdb(), CreateProceduralLanguage(), CreateStatistics(), CreateTransform(), DefineOpClass(), DefineQueryRewrite(), DefineType(), dropdb(), DropSubscription(), DropTableSpace(), EnableDisableRule(), ExecAlterExtensionContentsStmt(), ExecAlterExtensionStmt(), ExecuteTruncateGuts(), get_tables_to_cluster(), get_tables_to_cluster_partitioned(), gin_clean_pending_list(), heap_force_common(), MergeAttributes(), movedb(), OperatorCreate(), ProcedureCreate(), PublicationAddTables(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForPolicy(), RangeVarCallbackForReindexIndex(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackOwnsRelation(), RangeVarCallbackOwnsTable(), RangeVarGetAndCheckCreationNamespace(), ReindexMultipleTables(), RemoveObjects(), renameatt_check(), RenameDatabase(), RenameSchema(), RenameTableSpace(), RenameType(), RI_Initial_Check(), user_mapping_ddl_aclcheck(), and vacuum_is_relation_owner().

◆ objectNamesToOids()

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

Definition at line 659 of file aclchk.c.

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

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

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  object_oid,
AttrNumber  attnum,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)
static

Definition at line 3000 of file aclchk.c.

3002 {
3003  switch (objtype)
3004  {
3005  case OBJECT_COLUMN:
3006  return
3007  pg_class_aclmask(object_oid, roleid, mask, how) |
3008  pg_attribute_aclmask(object_oid, attnum, roleid, mask, how);
3009  case OBJECT_TABLE:
3010  case OBJECT_SEQUENCE:
3011  return pg_class_aclmask(object_oid, roleid, mask, how);
3012  case OBJECT_DATABASE:
3013  return object_aclmask(DatabaseRelationId, object_oid, roleid, mask, how);
3014  case OBJECT_FUNCTION:
3015  return object_aclmask(ProcedureRelationId, object_oid, roleid, mask, how);
3016  case OBJECT_LANGUAGE:
3017  return object_aclmask(LanguageRelationId, object_oid, roleid, mask, how);
3018  case OBJECT_LARGEOBJECT:
3019  return pg_largeobject_aclmask_snapshot(object_oid, roleid,
3020  mask, how, NULL);
3021  case OBJECT_PARAMETER_ACL:
3022  return pg_parameter_acl_aclmask(object_oid, roleid, mask, how);
3023  case OBJECT_SCHEMA:
3024  return object_aclmask(NamespaceRelationId, object_oid, roleid, mask, how);
3025  case OBJECT_STATISTIC_EXT:
3026  elog(ERROR, "grantable rights not supported for statistics objects");
3027  /* not reached, but keep compiler quiet */
3028  return ACL_NO_RIGHTS;
3029  case OBJECT_TABLESPACE:
3030  return object_aclmask(TableSpaceRelationId, object_oid, roleid, mask, how);
3031  case OBJECT_FDW:
3032  return object_aclmask(ForeignDataWrapperRelationId, object_oid, roleid, mask, how);
3033  case OBJECT_FOREIGN_SERVER:
3034  return object_aclmask(ForeignServerRelationId, object_oid, roleid, mask, how);
3035  case OBJECT_EVENT_TRIGGER:
3036  elog(ERROR, "grantable rights not supported for event triggers");
3037  /* not reached, but keep compiler quiet */
3038  return ACL_NO_RIGHTS;
3039  case OBJECT_TYPE:
3040  return object_aclmask(TypeRelationId, object_oid, roleid, mask, how);
3041  default:
3042  elog(ERROR, "unrecognized object type: %d",
3043  (int) objtype);
3044  /* not reached, but keep compiler quiet */
3045  return ACL_NO_RIGHTS;
3046  }
3047 }
static AclMode pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid, AclMode mask, AclMaskHow how, Snapshot snapshot)
Definition: aclchk.c:3518
static AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3144
static AclMode pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3459
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3263

References ACL_NO_RIGHTS, attnum, elog(), ERROR, object_aclmask(), 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_largeobject_aclmask_snapshot(), and pg_parameter_acl_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 3779 of file aclchk.c.

3781 {
3782  return pg_attribute_aclcheck_ext(table_oid, attnum, roleid, mode, NULL);
3783 }
AclResult pg_attribute_aclcheck_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode, bool *is_missing)
Definition: aclchk.c:3793

References attnum, mode, and pg_attribute_aclcheck_ext().

Referenced by BuildIndexValueDescription(), checkFkeyPermissions(), examine_simple_variable(), ExecBuildSlotPartitionKeyDescription(), ExecBuildSlotValueDescription(), ExecCheckOneRelPerms(), ExecCheckPermissionsModified(), 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 3823 of file aclchk.c.

3825 {
3826  AclResult result;
3827  HeapTuple classTuple;
3828  Form_pg_class classForm;
3829  AttrNumber nattrs;
3830  AttrNumber curr_att;
3831 
3832  /*
3833  * Must fetch pg_class row to check number of attributes. As in
3834  * pg_attribute_aclmask, we prefer to return "no privileges" instead of
3835  * throwing an error if we get any unexpected lookup errors.
3836  */
3837  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3838  if (!HeapTupleIsValid(classTuple))
3839  return ACLCHECK_NO_PRIV;
3840  classForm = (Form_pg_class) GETSTRUCT(classTuple);
3841 
3842  nattrs = classForm->relnatts;
3843 
3844  ReleaseSysCache(classTuple);
3845 
3846  /*
3847  * Initialize result in case there are no non-dropped columns. We want to
3848  * report failure in such cases for either value of 'how'.
3849  */
3850  result = ACLCHECK_NO_PRIV;
3851 
3852  for (curr_att = 1; curr_att <= nattrs; curr_att++)
3853  {
3854  HeapTuple attTuple;
3855  AclMode attmask;
3856 
3857  attTuple = SearchSysCache2(ATTNUM,
3858  ObjectIdGetDatum(table_oid),
3859  Int16GetDatum(curr_att));
3860  if (!HeapTupleIsValid(attTuple))
3861  continue;
3862 
3863  /* ignore dropped columns */
3864  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
3865  {
3866  ReleaseSysCache(attTuple);
3867  continue;
3868  }
3869 
3870  /*
3871  * Here we hard-wire knowledge that the default ACL for a column
3872  * grants no privileges, so that we can fall out quickly in the very
3873  * common case where attacl is null.
3874  */
3875  if (heap_attisnull(attTuple, Anum_pg_attribute_attacl, NULL))
3876  attmask = 0;
3877  else
3878  attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
3879  mode, ACLMASK_ANY);
3880 
3881  ReleaseSysCache(attTuple);
3882 
3883  if (attmask != 0)
3884  {
3885  result = ACLCHECK_OK;
3886  if (how == ACLMASK_ANY)
3887  break; /* succeed on any success */
3888  }
3889  else
3890  {
3891  result = ACLCHECK_NO_PRIV;
3892  if (how == ACLMASK_ALL)
3893  break; /* fail on any failure */
3894  }
3895  }
3896 
3897  return result;
3898 }
AclResult
Definition: acl.h:181
@ ACLMASK_ALL
Definition: acl.h:175
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:447

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 ExecCheckOneRelPerms(), ExecCheckPermissionsModified(), 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 3793 of file aclchk.c.

3795 {
3796  if (pg_attribute_aclmask_ext(table_oid, attnum, roleid, mode,
3797  ACLMASK_ANY, is_missing) != 0)
3798  return ACLCHECK_OK;
3799  else
3800  return ACLCHECK_NO_PRIV;
3801 }
static AclMode pg_attribute_aclmask_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3158

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

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

Definition at line 3144 of file aclchk.c.

3146 {
3147  return pg_attribute_aclmask_ext(table_oid, attnum, roleid,
3148  mask, how, NULL);
3149 }

References attnum, and pg_attribute_aclmask_ext().

Referenced by pg_aclmask(), and pg_attribute_aclcheck_all().

◆ pg_attribute_aclmask_ext()

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

Definition at line 3158 of file aclchk.c.

3160 {
3161  AclMode result;
3162  HeapTuple classTuple;
3163  HeapTuple attTuple;
3164  Form_pg_class classForm;
3165  Form_pg_attribute attributeForm;
3166  Datum aclDatum;
3167  bool isNull;
3168  Acl *acl;
3169  Oid ownerId;
3170 
3171  /*
3172  * First, get the column's ACL from its pg_attribute entry
3173  */
3174  attTuple = SearchSysCache2(ATTNUM,
3175  ObjectIdGetDatum(table_oid),
3177  if (!HeapTupleIsValid(attTuple))
3178  {
3179  if (is_missing != NULL)
3180  {
3181  /* return "no privileges" instead of throwing an error */
3182  *is_missing = true;
3183  return 0;
3184  }
3185  else
3186  ereport(ERROR,
3187  (errcode(ERRCODE_UNDEFINED_COLUMN),
3188  errmsg("attribute %d of relation with OID %u does not exist",
3189  attnum, table_oid)));
3190  }
3191 
3192  attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
3193 
3194  /* Check dropped columns, too */
3195  if (attributeForm->attisdropped)
3196  {
3197  if (is_missing != NULL)
3198  {
3199  /* return "no privileges" instead of throwing an error */
3200  *is_missing = true;
3201  ReleaseSysCache(attTuple);
3202  return 0;
3203  }
3204  else
3205  ereport(ERROR,
3206  (errcode(ERRCODE_UNDEFINED_COLUMN),
3207  errmsg("attribute %d of relation with OID %u does not exist",
3208  attnum, table_oid)));
3209  }
3210 
3211  aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
3212  &isNull);
3213 
3214  /*
3215  * Here we hard-wire knowledge that the default ACL for a column grants no
3216  * privileges, so that we can fall out quickly in the very common case
3217  * where attacl is null.
3218  */
3219  if (isNull)
3220  {
3221  ReleaseSysCache(attTuple);
3222  return 0;
3223  }
3224 
3225  /*
3226  * Must get the relation's ownerId from pg_class. Since we already found
3227  * a pg_attribute entry, the only likely reason for this to fail is that a
3228  * concurrent DROP of the relation committed since then (which could only
3229  * happen if we don't have lock on the relation). We prefer to report "no
3230  * privileges" rather than failing in such a case, so as to avoid unwanted
3231  * failures in has_column_privilege() tests.
3232  */
3233  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3234  if (!HeapTupleIsValid(classTuple))
3235  {
3236  ReleaseSysCache(attTuple);
3237  return 0;
3238  }
3239  classForm = (Form_pg_class) GETSTRUCT(classTuple);
3240 
3241  ownerId = classForm->relowner;
3242 
3243  ReleaseSysCache(classTuple);
3244 
3245  /* detoast column's ACL if necessary */
3246  acl = DatumGetAclP(aclDatum);
3247 
3248  result = aclmask(acl, roleid, ownerId, mask, how);
3249 
3250  /* if we have a detoasted copy, free it */
3251  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3252  pfree(acl);
3253 
3254  ReleaseSysCache(attTuple);
3255 
3256  return result;
3257 }

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

3922 {
3923  if (pg_class_aclmask_ext(table_oid, roleid, mode,
3924  ACLMASK_ANY, is_missing) != 0)
3925  return ACLCHECK_OK;
3926  else
3927  return ACLCHECK_NO_PRIV;
3928 }
static AclMode pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3276

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

3265 {
3266  return pg_class_aclmask_ext(table_oid, roleid, mask, how, NULL);
3267 }

References pg_class_aclmask_ext().

Referenced by ExecCheckOneRelPerms(), and pg_aclmask().

◆ pg_class_aclmask_ext()

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

Definition at line 3276 of file aclchk.c.

3278 {
3279  AclMode result;
3280  HeapTuple tuple;
3281  Form_pg_class classForm;
3282  Datum aclDatum;
3283  bool isNull;
3284  Acl *acl;
3285  Oid ownerId;
3286 
3287  /*
3288  * Must get the relation's tuple from pg_class
3289  */
3290  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3291  if (!HeapTupleIsValid(tuple))
3292  {
3293  if (is_missing != NULL)
3294  {
3295  /* return "no privileges" instead of throwing an error */
3296  *is_missing = true;
3297  return 0;
3298  }
3299  else
3300  ereport(ERROR,
3302  errmsg("relation with OID %u does not exist",
3303  table_oid)));
3304  }
3305 
3306  classForm = (Form_pg_class) GETSTRUCT(tuple);
3307 
3308  /*
3309  * Deny anyone permission to update a system catalog unless
3310  * pg_authid.rolsuper is set.
3311  *
3312  * As of 7.4 we have some updatable system views; those shouldn't be
3313  * protected in this way. Assume the view rules can take care of
3314  * themselves. ACL_USAGE is if we ever have system sequences.
3315  */
3316  if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
3317  IsSystemClass(table_oid, classForm) &&
3318  classForm->relkind != RELKIND_VIEW &&
3319  !superuser_arg(roleid))
3321 
3322  /*
3323  * Otherwise, superusers bypass all permission-checking.
3324  */
3325  if (superuser_arg(roleid))
3326  {
3327  ReleaseSysCache(tuple);
3328  return mask;
3329  }
3330 
3331  /*
3332  * Normal case: get the relation's ACL from pg_class
3333  */
3334  ownerId = classForm->relowner;
3335 
3336  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
3337  &isNull);
3338  if (isNull)
3339  {
3340  /* No ACL, so build default ACL */
3341  switch (classForm->relkind)
3342  {
3343  case RELKIND_SEQUENCE:
3344  acl = acldefault(OBJECT_SEQUENCE, ownerId);
3345  break;
3346  default:
3347  acl = acldefault(OBJECT_TABLE, ownerId);
3348  break;
3349  }
3350  aclDatum = (Datum) 0;
3351  }
3352  else
3353  {
3354  /* detoast rel's ACL if necessary */
3355  acl = DatumGetAclP(aclDatum);
3356  }
3357 
3358  result = aclmask(acl, roleid, ownerId, mask, how);
3359 
3360  /* if we have a detoasted copy, free it */
3361  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3362  pfree(acl);
3363 
3364  ReleaseSysCache(tuple);
3365 
3366  /*
3367  * Check if ACL_SELECT is being checked and, if so, and not set already as
3368  * part of the result, then check if the user is a member of the
3369  * pg_read_all_data role, which allows read access to all relations.
3370  */
3371  if (mask & ACL_SELECT && !(result & ACL_SELECT) &&
3372  has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA))
3373  result |= ACL_SELECT;
3374 
3375  /*
3376  * Check if ACL_INSERT, ACL_UPDATE, or ACL_DELETE is being checked and, if
3377  * so, and not set already as part of the result, then check if the user
3378  * is a member of the pg_write_all_data role, which allows
3379  * INSERT/UPDATE/DELETE access to all relations (except system catalogs,
3380  * which requires superuser, see above).
3381  */
3382  if (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE) &&
3383  !(result & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
3384  has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA))
3385  result |= (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE));
3386 
3387  return result;
3388 }
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:87
#define ACL_DELETE
Definition: parsenodes.h:86
#define ACL_USAGE
Definition: parsenodes.h:91
#define ACL_INSERT
Definition: parsenodes.h:83
#define ACL_UPDATE
Definition: parsenodes.h:85
#define ACL_TRUNCATE
Definition: parsenodes.h:87
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:78

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_largeobject_aclcheck_snapshot()

AclResult pg_largeobject_aclcheck_snapshot ( Oid  lobj_oid,
Oid  roleid,
AclMode  mode,
Snapshot  snapshot 
)

Definition at line 3947 of file aclchk.c.

3949 {
3950  if (pg_largeobject_aclmask_snapshot(lobj_oid, roleid, mode,
3951  ACLMASK_ANY, snapshot) != 0)
3952  return ACLCHECK_OK;
3953  else
3954  return ACLCHECK_NO_PRIV;
3955 }

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

Referenced by be_lo_put(), and inv_open().

◆ pg_largeobject_aclmask_snapshot()

static AclMode pg_largeobject_aclmask_snapshot ( Oid  lobj_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how,
Snapshot  snapshot 
)
static

Definition at line 3518 of file aclchk.c.

3521 {
3522  AclMode result;
3523  Relation pg_lo_meta;
3524  ScanKeyData entry[1];
3525  SysScanDesc scan;
3526  HeapTuple tuple;
3527  Datum aclDatum;
3528  bool isNull;
3529  Acl *acl;
3530  Oid ownerId;
3531 
3532  /* Superusers bypass all permission checking. */
3533  if (superuser_arg(roleid))
3534  return mask;
3535 
3536  /*
3537  * Get the largeobject's ACL from pg_largeobject_metadata
3538  */
3539  pg_lo_meta = table_open(LargeObjectMetadataRelationId,
3540  AccessShareLock);
3541 
3542  ScanKeyInit(&entry[0],
3543  Anum_pg_largeobject_metadata_oid,
3544  BTEqualStrategyNumber, F_OIDEQ,
3545  ObjectIdGetDatum(lobj_oid));
3546 
3547  scan = systable_beginscan(pg_lo_meta,
3548  LargeObjectMetadataOidIndexId, true,
3549  snapshot, 1, entry);
3550 
3551  tuple = systable_getnext(scan);
3552  if (!HeapTupleIsValid(tuple))
3553  ereport(ERROR,
3554  (errcode(ERRCODE_UNDEFINED_OBJECT),
3555  errmsg("large object %u does not exist", lobj_oid)));
3556 
3557  ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
3558 
3559  aclDatum = heap_getattr(tuple, Anum_pg_largeobject_metadata_lomacl,
3560  RelationGetDescr(pg_lo_meta), &isNull);
3561 
3562  if (isNull)
3563  {
3564  /* No ACL, so build default ACL */
3565  acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
3566  aclDatum = (Datum) 0;
3567  }
3568  else
3569  {
3570  /* detoast ACL if necessary */
3571  acl = DatumGetAclP(aclDatum);
3572  }
3573 
3574  result = aclmask(acl, roleid, ownerId, mask, how);
3575 
3576  /* if we have a detoasted copy, free it */
3577  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3578  pfree(acl);
3579 
3580  systable_endscan(scan);
3581 
3582  table_close(pg_lo_meta, AccessShareLock);
3583 
3584  return result;
3585 }

References AccessShareLock, acldefault(), aclmask(), BTEqualStrategyNumber, DatumGetAclP, DatumGetPointer(), ereport, errcode(), errmsg(), ERROR, GETSTRUCT, heap_getattr(), HeapTupleIsValid, OBJECT_LARGEOBJECT, ObjectIdGetDatum(), pfree(), RelationGetDescr, ScanKeyInit(), superuser_arg(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by pg_aclmask(), and pg_largeobject_aclcheck_snapshot().

◆ pg_namespace_aclmask()

static AclMode pg_namespace_aclmask ( Oid  nsp_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)
static

Definition at line 3591 of file aclchk.c.

3593 {
3594  AclMode result;
3595  HeapTuple tuple;
3596  Datum aclDatum;
3597  bool isNull;
3598  Acl *acl;
3599  Oid ownerId;
3600 
3601  /* Superusers bypass all permission checking. */
3602  if (superuser_arg(roleid))
3603  return mask;
3604 
3605  /*
3606  * If we have been assigned this namespace as a temp namespace, check to
3607  * make sure we have CREATE TEMP permission on the database, and if so act
3608  * as though we have all standard (but not GRANT OPTION) permissions on
3609  * the namespace. If we don't have CREATE TEMP, act as though we have
3610  * only USAGE (and not CREATE) rights.
3611  *
3612  * This may seem redundant given the check in InitTempTableNamespace, but
3613  * it really isn't since current user ID may have changed since then. The
3614  * upshot of this behavior is that a SECURITY DEFINER function can create
3615  * temp tables that can then be accessed (if permission is granted) by
3616  * code in the same session that doesn't have permissions to create temp
3617  * tables.
3618  *
3619  * XXX Would it be safe to ereport a special error message as
3620  * InitTempTableNamespace does? Returning zero here means we'll get a
3621  * generic "permission denied for schema pg_temp_N" message, which is not
3622  * remarkably user-friendly.
3623  */
3624  if (isTempNamespace(nsp_oid))
3625  {
3626  if (object_aclcheck(DatabaseRelationId, MyDatabaseId, roleid,
3628  return mask & ACL_ALL_RIGHTS_SCHEMA;
3629  else
3630  return mask & ACL_USAGE;
3631  }
3632 
3633  /*
3634  * Get the schema's ACL from pg_namespace
3635  */
3636  tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
3637  if (!HeapTupleIsValid(tuple))
3638  ereport(ERROR,
3639  (errcode(ERRCODE_UNDEFINED_SCHEMA),
3640  errmsg("schema with OID %u does not exist", nsp_oid)));
3641 
3642  ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
3643 
3644  aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspacl,
3645  &isNull);
3646  if (isNull)
3647  {
3648  /* No ACL, so build default ACL */
3649  acl = acldefault(OBJECT_SCHEMA, ownerId);
3650  aclDatum = (Datum) 0;
3651  }
3652  else
3653  {
3654  /* detoast ACL if necessary */
3655  acl = DatumGetAclP(aclDatum);
3656  }
3657 
3658  result = aclmask(acl, roleid, ownerId, mask, how);
3659 
3660  /* if we have a detoasted copy, free it */
3661  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3662  pfree(acl);
3663 
3664  ReleaseSysCache(tuple);
3665 
3666  /*
3667  * Check if ACL_USAGE is being checked and, if so, and not set already as
3668  * part of the result, then check if the user is a member of the
3669  * pg_read_all_data or pg_write_all_data roles, which allow usage access
3670  * to all schemas.
3671  */
3672  if (mask & ACL_USAGE && !(result & ACL_USAGE) &&
3673  (has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA) ||
3674  has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA)))
3675  result |= ACL_USAGE;
3676  return result;
3677 }
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3760
Oid MyDatabaseId
Definition: globals.c:89
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3182
#define ACL_CREATE_TEMP
Definition: parsenodes.h:93
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:52
@ NAMESPACEOID
Definition: syscache.h:70

References ACL_ALL_RIGHTS_SCHEMA, ACL_CREATE_TEMP, ACL_USAGE, ACLCHECK_OK, acldefault(), aclmask(), DatumGetAclP, DatumGetPointer(), ereport, errcode(), errmsg(), ERROR, GETSTRUCT, has_privs_of_role(), HeapTupleIsValid, isTempNamespace(), MyDatabaseId, NAMESPACEOID, object_aclcheck(), OBJECT_SCHEMA, ObjectIdGetDatum(), pfree(), ReleaseSysCache(), SearchSysCache1(), superuser_arg(), and SysCacheGetAttr().

Referenced by object_aclmask().

◆ pg_parameter_acl_aclmask()

static AclMode pg_parameter_acl_aclmask ( Oid  acl_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)
static

Definition at line 3459 of file aclchk.c.

3460 {
3461  AclMode result;
3462  HeapTuple tuple;
3463  Datum aclDatum;
3464  bool isNull;
3465  Acl *acl;
3466 
3467  /* Superusers bypass all permission checking. */
3468  if (superuser_arg(roleid))
3469  return mask;
3470 
3471  /* Get the ACL from pg_parameter_acl */
3473  if (!HeapTupleIsValid(tuple))
3474  ereport(ERROR,
3475  (errcode(ERRCODE_UNDEFINED_OBJECT),
3476  errmsg("parameter ACL with OID %u does not exist",
3477  acl_oid)));
3478 
3479  aclDatum = SysCacheGetAttr(PARAMETERACLOID, tuple,
3480  Anum_pg_parameter_acl_paracl,
3481  &isNull);
3482  if (isNull)
3483  {
3484  /* No ACL, so build default ACL */
3485  acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
3486  aclDatum = (Datum) 0;
3487  }
3488  else
3489  {
3490  /* detoast ACL if necessary */
3491  acl = DatumGetAclP(aclDatum);
3492  }
3493 
3494  result = aclmask(acl, roleid, BOOTSTRAP_SUPERUSERID, mask, how);
3495 
3496  /* if we have a detoasted copy, free it */
3497  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3498  pfree(acl);
3499 
3500  ReleaseSysCache(tuple);
3501 
3502  return result;
3503 }

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

Referenced by pg_aclmask().

◆ pg_parameter_aclcheck()

AclResult pg_parameter_aclcheck ( const char *  name,
Oid  roleid,
AclMode  mode 
)

Definition at line 3935 of file aclchk.c.

3936 {
3937  if (pg_parameter_aclmask(name, roleid, mode, ACLMASK_ANY) != 0)
3938  return ACLCHECK_OK;
3939  else
3940  return ACLCHECK_NO_PRIV;
3941 }
static AclMode pg_parameter_aclmask(const char *name, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3395
const char * name

References ACLCHECK_NO_PRIV, ACLCHECK_OK, ACLMASK_ANY, mode, name, and pg_parameter_aclmask().

Referenced by AlterSystemSetConfigFile(), has_param_priv_byname(), set_config_option_ext(), and validate_option_array_item().

◆ pg_parameter_aclmask()

static AclMode pg_parameter_aclmask ( const char *  name,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)
static

Definition at line 3395 of file aclchk.c.

3396 {
3397  AclMode result;
3398  char *parname;
3399  text *partext;
3400  HeapTuple tuple;
3401 
3402  /* Superusers bypass all permission checking. */
3403  if (superuser_arg(roleid))
3404  return mask;
3405 
3406  /* Convert name to the form it should have in pg_parameter_acl... */
3408  partext = cstring_to_text(parname);
3409 
3410  /* ... and look it up */
3412 
3413  if (!HeapTupleIsValid(tuple))
3414  {
3415  /* If no entry, GUC has no permissions for non-superusers */
3416  result = ACL_NO_RIGHTS;
3417  }
3418  else
3419  {
3420  Datum aclDatum;
3421  bool isNull;
3422  Acl *acl;
3423 
3424  aclDatum = SysCacheGetAttr(PARAMETERACLNAME, tuple,
3425  Anum_pg_parameter_acl_paracl,
3426  &isNull);
3427  if (isNull)
3428  {
3429  /* No ACL, so build default ACL */
3430  acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
3431  aclDatum = (Datum) 0;
3432  }
3433  else
3434  {
3435  /* detoast ACL if necessary */
3436  acl = DatumGetAclP(aclDatum);
3437  }
3438 
3439  result = aclmask(acl, roleid, BOOTSTRAP_SUPERUSERID, mask, how);
3440 
3441  /* if we have a detoasted copy, free it */
3442  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3443  pfree(acl);
3444 
3445  ReleaseSysCache(tuple);
3446  }
3447 
3448  pfree(parname);
3449  pfree(partext);
3450 
3451  return result;
3452 }
char * convert_GUC_name_for_parameter_acl(const char *name)
Definition: guc.c:1339
Definition: c.h:676
@ PARAMETERACLNAME
Definition: syscache.h:75
text * cstring_to_text(const char *s)
Definition: varlena.c:182

References ACL_NO_RIGHTS, acldefault(), aclmask(), convert_GUC_name_for_parameter_acl(), cstring_to_text(), DatumGetAclP, DatumGetPointer(), HeapTupleIsValid, name, OBJECT_PARAMETER_ACL, PARAMETERACLNAME, pfree(), PointerGetDatum(), ReleaseSysCache(), SearchSysCache1(), superuser_arg(), and SysCacheGetAttr().

Referenced by pg_parameter_aclcheck().

◆ pg_type_aclmask()

static AclMode pg_type_aclmask ( Oid  type_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how 
)
static

Definition at line 3683 of file aclchk.c.

3684 {
3685  AclMode result;
3686  HeapTuple tuple;
3687  Datum aclDatum;
3688  bool isNull;
3689  Acl *acl;
3690  Oid ownerId;
3691 
3692  Form_pg_type typeForm;
3693 
3694  /* Bypass permission checks for superusers */
3695  if (superuser_arg(roleid))
3696  return mask;
3697 
3698  /*
3699  * Must get the type's tuple from pg_type
3700  */
3701  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
3702  if (!HeapTupleIsValid(tuple))
3703  ereport(ERROR,
3704  (errcode(ERRCODE_UNDEFINED_OBJECT),
3705  errmsg("type with OID %u does not exist",
3706  type_oid)));
3707  typeForm = (Form_pg_type) GETSTRUCT(tuple);
3708 
3709  /*
3710  * "True" array types don't manage permissions of their own; consult the
3711  * element type instead.
3712  */
3713  if (IsTrueArrayType(typeForm))
3714  {
3715  Oid elttype_oid = typeForm->typelem;
3716 
3717  ReleaseSysCache(tuple);
3718 
3719  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(elttype_oid));
3720  /* this case is not a user-facing error, so elog not ereport */
3721  if (!HeapTupleIsValid(tuple))
3722  elog(ERROR, "cache lookup failed for type %u", elttype_oid);
3723  typeForm = (Form_pg_type) GETSTRUCT(tuple);
3724  }
3725 
3726  /*
3727  * Now get the type's owner and ACL from the tuple
3728  */
3729  ownerId = typeForm->typowner;
3730 
3731  aclDatum = SysCacheGetAttr(TYPEOID, tuple,
3732  Anum_pg_type_typacl, &isNull);
3733  if (isNull)
3734  {
3735  /* No ACL, so build default ACL */
3736  acl = acldefault(OBJECT_TYPE, ownerId);
3737  aclDatum = (Datum) 0;
3738  }
3739  else
3740  {
3741  /* detoast rel's ACL if necessary */
3742  acl = DatumGetAclP(aclDatum);
3743  }
3744 
3745  result = aclmask(acl, roleid, ownerId, mask, how);
3746 
3747  /* if we have a detoasted copy, free it */
3748  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3749  pfree(acl);
3750 
3751  ReleaseSysCache(tuple);
3752 
3753  return result;
3754 }
@ TYPEOID
Definition: syscache.h:114

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

Referenced by object_aclmask().

◆ privilege_to_string()

static const char * privilege_to_string ( AclMode  privilege)
static

Definition at line 2624 of file aclchk.c.

2625 {
2626  switch (privilege)
2627  {
2628  case ACL_INSERT:
2629  return "INSERT";
2630  case ACL_SELECT:
2631  return "SELECT";
2632  case ACL_UPDATE:
2633  return "UPDATE";
2634  case ACL_DELETE:
2635  return "DELETE";
2636  case ACL_TRUNCATE:
2637  return "TRUNCATE";
2638  case ACL_REFERENCES:
2639  return "REFERENCES";
2640  case ACL_TRIGGER:
2641  return "TRIGGER";
2642  case ACL_EXECUTE:
2643  return "EXECUTE";
2644  case ACL_USAGE:
2645  return "USAGE";
2646  case ACL_CREATE:
2647  return "CREATE";
2648  case ACL_CREATE_TEMP:
2649  return "TEMP";
2650  case ACL_CONNECT:
2651  return "CONNECT";
2652  case ACL_SET:
2653  return "SET";
2654  case ACL_ALTER_SYSTEM:
2655  return "ALTER SYSTEM";
2656  default:
2657  elog(ERROR, "unrecognized privilege: %d", (int) privilege);
2658  }
2659  return NULL; /* appease compiler */
2660 }
#define ACL_SET
Definition: parsenodes.h:95
#define ACL_CONNECT
Definition: parsenodes.h:94
#define ACL_ALTER_SYSTEM
Definition: parsenodes.h:96
#define ACL_REFERENCES
Definition: parsenodes.h:88
#define ACL_EXECUTE
Definition: parsenodes.h:90
#define ACL_CREATE
Definition: parsenodes.h:92
#define ACL_TRIGGER
Definition: parsenodes.h:89

References ACL_ALTER_SYSTEM, ACL_CONNECT, ACL_CREATE, ACL_CREATE_TEMP, ACL_DELETE, ACL_EXECUTE, ACL_INSERT, ACL_REFERENCES, ACL_SELECT, ACL_SET, ACL_TRIGGER, ACL_TRUNCATE, ACL_UPDATE, ACL_USAGE, elog(), and ERROR.

Referenced by ExecAlterDefaultPrivilegesStmt(), ExecGrant_Relation(), and ExecuteGrantStmt().

◆ recordDependencyOnNewAcl()

void recordDependencyOnNewAcl ( Oid  classId,
Oid  objectId,
int32  objsubId,
Oid  ownerId,
Acl acl 
)

Definition at line 4192 of file aclchk.c.

4194 {
4195  int nmembers;
4196  Oid *members;
4197 
4198  /* Nothing to do if ACL is defaulted */
4199  if (acl == NULL)
4200  return;
4201 
4202  /* Extract roles mentioned in ACL */
4203  nmembers = aclmembers(acl, &members);
4204 
4205  /* Update the shared dependency ACL info */
4206  updateAclDependencies(classId, objectId, objsubId,
4207  ownerId,
4208  0, NULL,
4209  nmembers, members);
4210 }

References aclmembers(), and updateAclDependencies().

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

◆ recordExtensionInitPriv()

static void recordExtensionInitPriv ( Oid  objoid,
Oid  classoid,
int  objsubid,
Acl new_acl 
)
static

Definition at line 4465 of file aclchk.c.

4466 {
4467  /*
4468  * Generally, we only record the initial privileges when an extension is
4469  * being created, but because we don't actually use CREATE EXTENSION
4470  * during binary upgrades with pg_upgrade, there is a variable to let us
4471  * know that the GRANT and REVOKE statements being issued, while this
4472  * variable is true, are for the initial privileges of the extension
4473  * object and therefore we need to record them.
4474  */
4476  return;
4477 
4478  recordExtensionInitPrivWorker(objoid, classoid, objsubid, new_acl);
4479 }
static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:4494
bool binary_upgrade_record_init_privs
Definition: aclchk.c:105
bool creating_extension
Definition: extension.c:73

References binary_upgrade_record_init_privs, creating_extension, and recordExtensionInitPrivWorker().

Referenced by ExecGrant_Attribute(), ExecGrant_common(), ExecGrant_Largeobject(), ExecGrant_Parameter(), and ExecGrant_Relation().

◆ recordExtensionInitPrivWorker()

static void recordExtensionInitPrivWorker ( Oid  objoid,
Oid  classoid,
int  objsubid,
Acl new_acl 
)
static

Definition at line 4494 of file aclchk.c.

4495 {
4496  Relation relation;
4497  ScanKeyData key[3];
4498  SysScanDesc scan;
4499  HeapTuple tuple;
4500  HeapTuple oldtuple;
4501 
4502  relation = table_open(InitPrivsRelationId, RowExclusiveLock);
4503 
4504  ScanKeyInit(&key[0],
4505  Anum_pg_init_privs_objoid,
4506  BTEqualStrategyNumber, F_OIDEQ,
4507  ObjectIdGetDatum(objoid));
4508  ScanKeyInit(&key[1],
4509  Anum_pg_init_privs_classoid,
4510  BTEqualStrategyNumber, F_OIDEQ,
4511  ObjectIdGetDatum(classoid));
4512  ScanKeyInit(&key[2],
4513  Anum_pg_init_privs_objsubid,
4514  BTEqualStrategyNumber, F_INT4EQ,
4515  Int32GetDatum(objsubid));
4516 
4517  scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
4518  NULL, 3, key);
4519 
4520  /* There should exist only one entry or none. */
4521  oldtuple = systable_getnext(scan);
4522 
4523  /* If we find an entry, update it with the latest ACL. */
4524  if (HeapTupleIsValid(oldtuple))
4525  {
4526  Datum values[Natts_pg_init_privs] = {0};
4527  bool nulls[Natts_pg_init_privs] = {0};
4528  bool replace[Natts_pg_init_privs] = {0};
4529 
4530  /* If we have a new ACL to set, then update the row with it. */
4531  if (new_acl)
4532  {
4533  values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
4534  replace[Anum_pg_init_privs_initprivs - 1] = true;
4535 
4536  oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation),
4537  values, nulls, replace);
4538 
4539  CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple);
4540  }
4541  else
4542  {
4543  /* new_acl is NULL, so delete the entry we found. */
4544  CatalogTupleDelete(relation, &oldtuple->t_self);
4545  }
4546  }
4547  else
4548  {
4549  Datum values[Natts_pg_init_privs] = {0};
4550  bool nulls[Natts_pg_init_privs] = {0};
4551 
4552  /*
4553  * Only add a new entry if the new ACL is non-NULL.
4554  *
4555  * If we are passed in a NULL ACL and no entry exists, we can just
4556  * fall through and do nothing.
4557  */
4558  if (new_acl)
4559  {
4560  /* No entry found, so add it. */
4561  values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
4562  values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
4563  values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
4564 
4565  /* This function only handles initial privileges of extensions */
4566  values[Anum_pg_init_privs_privtype - 1] =
4568 
4569  values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
4570 
4571  tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
4572 
4573  CatalogTupleInsert(relation, tuple);
4574  }
4575  }
4576 
4577  systable_endscan(scan);
4578 
4579  /* prevent error when processing objects multiple times */
4581 
4582  table_close(relation, RowExclusiveLock);
4583 }
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1108
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
@ INITPRIVS_EXTENSION
Definition: pg_init_privs.h:80
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212

References BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleInsert(), CatalogTupleUpdate(), CharGetDatum(), CommandCounterIncrement(), heap_form_tuple(), heap_modify_tuple(), HeapTupleIsValid, INITPRIVS_EXTENSION, Int32GetDatum(), sort-test::key, ObjectIdGetDatum(), PointerGetDatum(), RelationGetDescr, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), and values.

Referenced by recordExtensionInitPriv(), recordExtObjInitPriv(), and removeExtObjInitPriv().

◆ recordExtObjInitPriv()

void recordExtObjInitPriv ( Oid  objoid,
Oid  classoid 
)

Definition at line 4219 of file aclchk.c.

4220 {
4221  /*
4222  * pg_class / pg_attribute
4223  *
4224  * If this is a relation then we need to see if there are any sub-objects
4225  * (eg: columns) for it and, if so, be sure to call
4226  * recordExtensionInitPrivWorker() for each one.
4227  */
4228  if (classoid == RelationRelationId)
4229  {
4230  Form_pg_class pg_class_tuple;
4231  Datum aclDatum;
4232  bool isNull;
4233  HeapTuple tuple;
4234 
4235  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
4236  if (!HeapTupleIsValid(tuple))
4237  elog(ERROR, "cache lookup failed for relation %u", objoid);
4238  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
4239 
4240  /*
4241  * Indexes don't have permissions, neither do the pg_class rows for
4242  * composite types. (These cases are unreachable given the
4243  * restrictions in ALTER EXTENSION ADD, but let's check anyway.)
4244  */
4245  if (pg_class_tuple->relkind == RELKIND_INDEX ||
4246  pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
4247  pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
4248  {
4249  ReleaseSysCache(tuple);
4250  return;
4251  }
4252 
4253  /*
4254  * If this isn't a sequence then it's possibly going to have
4255  * column-level ACLs associated with it.
4256  */
4257  if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
4258  {
4259  AttrNumber curr_att;
4260  AttrNumber nattrs = pg_class_tuple->relnatts;
4261 
4262  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4263  {
4264  HeapTuple attTuple;
4265  Datum attaclDatum;
4266 
4267  attTuple = SearchSysCache2(ATTNUM,
4268  ObjectIdGetDatum(objoid),
4269  Int16GetDatum(curr_att));
4270 
4271  if (!HeapTupleIsValid(attTuple))
4272  continue;
4273 
4274  /* ignore dropped columns */
4275  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4276  {
4277  ReleaseSysCache(attTuple);
4278  continue;
4279  }
4280 
4281  attaclDatum = SysCacheGetAttr(ATTNUM, attTuple,
4282  Anum_pg_attribute_attacl,
4283  &isNull);
4284 
4285  /* no need to do anything for a NULL ACL */
4286  if (isNull)
4287  {
4288  ReleaseSysCache(attTuple);
4289  continue;
4290  }
4291 
4292  recordExtensionInitPrivWorker(objoid, classoid, curr_att,
4293  DatumGetAclP(attaclDatum));
4294 
4295  ReleaseSysCache(attTuple);
4296  }
4297  }
4298 
4299  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
4300  &isNull);
4301 
4302  /* Add the record, if any, for the top-level object */
4303  if (!isNull)
4304  recordExtensionInitPrivWorker(objoid, classoid, 0,
4305  DatumGetAclP(aclDatum));
4306 
4307  ReleaseSysCache(tuple);
4308  }
4309  /* pg_largeobject_metadata */
4310  else if (classoid == LargeObjectMetadataRelationId)
4311  {
4312  Datum aclDatum;
4313  bool isNull;
4314  HeapTuple tuple;
4315  ScanKeyData entry[1];
4316  SysScanDesc scan;
4317  Relation relation;
4318 
4319  /*
4320  * Note: this is dead code, given that we don't allow large objects to
4321  * be made extension members. But it seems worth carrying in case
4322  * some future caller of this function has need for it.
4323  */
4324  relation = table_open(LargeObjectMetadataRelationId, RowExclusiveLock);
4325 
4326  /* There's no syscache for pg_largeobject_metadata */
4327  ScanKeyInit(&entry[0],
4328  Anum_pg_largeobject_metadata_oid,
4329  BTEqualStrategyNumber, F_OIDEQ,
4330  ObjectIdGetDatum(objoid));
4331 
4332  scan = systable_beginscan(relation,
4333  LargeObjectMetadataOidIndexId, true,
4334  NULL, 1, entry);
4335 
4336  tuple = systable_getnext(scan);
4337  if (!HeapTupleIsValid(tuple))
4338  elog(ERROR, "could not find tuple for large object %u", objoid);
4339 
4340  aclDatum = heap_getattr(tuple,
4341  Anum_pg_largeobject_metadata_lomacl,
4342  RelationGetDescr(relation), &isNull);
4343 
4344  /* Add the record, if any, for the top-level object */
4345  if (!isNull)
4346  recordExtensionInitPrivWorker(objoid, classoid, 0,
4347  DatumGetAclP(aclDatum));
4348 
4349  systable_endscan(scan);
4350  }
4351  /* This will error on unsupported classoid. */
4352  else if (get_object_attnum_acl(classoid) != InvalidAttrNumber)
4353  {
4354  Datum aclDatum;
4355  bool isNull;
4356  HeapTuple tuple;
4357 
4358  tuple = SearchSysCache1(get_object_catcache_oid(classoid),
4359  ObjectIdGetDatum(objoid));
4360  if (!HeapTupleIsValid(tuple))
4361  elog(ERROR, "cache lookup failed for %s %u",
4362  get_object_class_descr(classoid), objoid);
4363 
4364  aclDatum = SysCacheGetAttr(get_object_catcache_oid(classoid), tuple,
4365  get_object_attnum_acl(classoid),
4366  &isNull);
4367 
4368  /* Add the record, if any, for the top-level object */
4369  if (!isNull)
4370  recordExtensionInitPrivWorker(objoid, classoid, 0,
4371  DatumGetAclP(aclDatum));
4372 
4373  ReleaseSysCache(tuple);
4374  }
4375 }

References ATTNUM, BTEqualStrategyNumber, DatumGetAclP, elog(), ERROR, get_object_attnum_acl(), get_object_catcache_oid(), get_object_class_descr(), GETSTRUCT, heap_getattr(), HeapTupleIsValid, Int16GetDatum(), InvalidAttrNumber, ObjectIdGetDatum(), recordExtensionInitPrivWorker(), RelationGetDescr, ReleaseSysCache(), RELOID, RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), SearchSysCache2(), SysCacheGetAttr(), systable_beginscan(), systable_endscan(), systable_getnext(), and table_open().

Referenced by ExecAlterExtensionContentsStmt().

◆ removeExtObjInitPriv()

void removeExtObjInitPriv ( Oid  objoid,
Oid  classoid 
)

Definition at line 4382 of file aclchk.c.

4383 {
4384  /*
4385  * If this is a relation then we need to see if there are any sub-objects
4386  * (eg: columns) for it and, if so, be sure to call
4387  * recordExtensionInitPrivWorker() for each one.
4388  */
4389  if (classoid == RelationRelationId)
4390  {
4391  Form_pg_class pg_class_tuple;
4392  HeapTuple tuple;
4393 
4394  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
4395  if (!HeapTupleIsValid(tuple))
4396  elog(ERROR, "cache lookup failed for relation %u", objoid);
4397  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
4398 
4399  /*
4400  * Indexes don't have permissions, neither do the pg_class rows for
4401  * composite types. (These cases are unreachable given the
4402  * restrictions in ALTER EXTENSION DROP, but let's check anyway.)
4403  */
4404  if (pg_class_tuple->relkind == RELKIND_INDEX ||
4405  pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
4406  pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
4407  {
4408  ReleaseSysCache(tuple);
4409  return;
4410  }
4411 
4412  /*
4413  * If this isn't a sequence then it's possibly going to have
4414  * column-level ACLs associated with it.
4415  */
4416  if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
4417  {
4418  AttrNumber curr_att;
4419  AttrNumber nattrs = pg_class_tuple->relnatts;
4420 
4421  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4422  {
4423  HeapTuple attTuple;
4424 
4425  attTuple = SearchSysCache2(ATTNUM,
4426  ObjectIdGetDatum(objoid),
4427  Int16GetDatum(curr_att));
4428 
4429  if (!HeapTupleIsValid(attTuple))
4430  continue;
4431 
4432  /* when removing, remove all entries, even dropped columns */
4433 
4434  recordExtensionInitPrivWorker(objoid, classoid, curr_att, NULL);
4435 
4436  ReleaseSysCache(attTuple);
4437  }
4438  }
4439 
4440  ReleaseSysCache(tuple);
4441  }
4442 
4443  /* Remove the record, if any, for the top-level object */
4444  recordExtensionInitPrivWorker(objoid, classoid, 0, NULL);
4445 }

References ATTNUM, elog(), ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum(), ObjectIdGetDatum(), recordExtensionInitPrivWorker(), ReleaseSysCache(), RELOID, SearchSysCache1(), and SearchSysCache2().

Referenced by ExecAlterExtensionContentsStmt().

◆ RemoveRoleFromObjectACL()

void RemoveRoleFromObjectACL ( Oid  roleid,
Oid  classid,
Oid  objid 
)

Definition at line 1444 of file aclchk.c.

1445 {
1446  if (classid == DefaultAclRelationId)
1447  {
1448  InternalDefaultACL iacls;
1449  Form_pg_default_acl pg_default_acl_tuple;
1450  Relation rel;
1451  ScanKeyData skey[1];
1452  SysScanDesc scan;
1453  HeapTuple tuple;
1454 
1455  /* first fetch info needed by SetDefaultACL */
1456  rel = table_open(DefaultAclRelationId, AccessShareLock);
1457 
1458  ScanKeyInit(&skey[0],
1459  Anum_pg_default_acl_oid,
1460  BTEqualStrategyNumber, F_OIDEQ,
1461  ObjectIdGetDatum(objid));
1462 
1463  scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
1464  NULL, 1, skey);
1465 
1466  tuple = systable_getnext(scan);
1467 
1468  if (!HeapTupleIsValid(tuple))
1469  elog(ERROR, "could not find tuple for default ACL %u", objid);
1470 
1471  pg_default_acl_tuple = (Form_pg_default_acl) GETSTRUCT(tuple);
1472 
1473  iacls.roleid = pg_default_acl_tuple->defaclrole;
1474  iacls.nspid = pg_default_acl_tuple->defaclnamespace;
1475 
1476  switch (pg_default_acl_tuple->defaclobjtype)
1477  {
1478  case DEFACLOBJ_RELATION:
1479  iacls.objtype = OBJECT_TABLE;
1480  break;
1481  case DEFACLOBJ_SEQUENCE:
1482  iacls.objtype = OBJECT_SEQUENCE;
1483  break;
1484  case DEFACLOBJ_FUNCTION:
1485  iacls.objtype = OBJECT_FUNCTION;
1486  break;
1487  case DEFACLOBJ_TYPE:
1488  iacls.objtype = OBJECT_TYPE;
1489  break;
1490  case DEFACLOBJ_NAMESPACE:
1491  iacls.objtype = OBJECT_SCHEMA;
1492  break;
1493  default:
1494  /* Shouldn't get here */
1495  elog(ERROR, "unexpected default ACL type: %d",
1496  (int) pg_default_acl_tuple->defaclobjtype);
1497  break;
1498  }
1499 
1500  systable_endscan(scan);
1502 
1503  iacls.is_grant = false;
1504  iacls.all_privs = true;
1505  iacls.privileges = ACL_NO_RIGHTS;
1506  iacls.grantees = list_make1_oid(roleid);
1507  iacls.grant_option = false;
1508  iacls.behavior = DROP_CASCADE;
1509 
1510  /* Do it */
1511  SetDefaultACL(&iacls);
1512  }
1513  else
1514  {
1515  InternalGrant istmt;
1516 
1517  switch (classid)
1518  {
1519  case RelationRelationId:
1520  /* it's OK to use TABLE for a sequence */
1521  istmt.objtype = OBJECT_TABLE;
1522  break;
1523  case DatabaseRelationId:
1524  istmt.objtype = OBJECT_DATABASE;
1525  break;
1526  case TypeRelationId:
1527  istmt.objtype = OBJECT_TYPE;
1528  break;
1529  case ProcedureRelationId:
1530  istmt.objtype = OBJECT_ROUTINE;
1531  break;
1532  case LanguageRelationId:
1533  istmt.objtype = OBJECT_LANGUAGE;
1534  break;
1535  case LargeObjectRelationId:
1536  istmt.objtype = OBJECT_LARGEOBJECT;
1537  break;
1538  case NamespaceRelationId:
1539  istmt.objtype = OBJECT_SCHEMA;
1540  break;
1541  case TableSpaceRelationId:
1542  istmt.objtype = OBJECT_TABLESPACE;
1543  break;
1544  case ForeignServerRelationId:
1546  break;
1547  case ForeignDataWrapperRelationId:
1548  istmt.objtype = OBJECT_FDW;
1549  break;
1550  case ParameterAclRelationId:
1551  istmt.objtype = OBJECT_PARAMETER_ACL;
1552  break;
1553  default:
1554  elog(ERROR, "unexpected object class %u", classid);
1555  break;
1556  }
1557  istmt.is_grant = false;
1558  istmt.objects = list_make1_oid(objid);
1559  istmt.all_privs = true;
1560  istmt.privileges = ACL_NO_RIGHTS;
1561  istmt.col_privs = NIL;
1562  istmt.grantees = list_make1_oid(roleid);
1563  istmt.grant_option = false;
1564  istmt.behavior = DROP_CASCADE;
1565 
1566  ExecGrantStmt_oids(&istmt);
1567  }
1568 }
static void SetDefaultACL(InternalDefaultACL *iacls)
Definition: aclchk.c:1193
@ DROP_CASCADE
Definition: parsenodes.h:2194
FormData_pg_default_acl * Form_pg_default_acl
#define list_make1_oid(x1)
Definition: pg_list.h:242

References AccessShareLock, ACL_NO_RIGHTS, InternalDefaultACL::all_privs, InternalGrant::all_privs, InternalDefaultACL::behavior, InternalGrant::behavior, BTEqualStrategyNumber, InternalGrant::col_privs, DROP_CASCADE, elog(), ERROR, ExecGrantStmt_oids(), GETSTRUCT, InternalDefaultACL::grant_option, InternalGrant::grant_option, InternalDefaultACL::grantees, InternalGrant::grantees, HeapTupleIsValid, InternalDefaultACL::is_grant, InternalGrant::is_grant, list_make1_oid, NIL, InternalDefaultACL::nspid, OBJECT_DATABASE, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_PARAMETER_ACL, OBJECT_ROUTINE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TYPE, ObjectIdGetDatum(), InternalGrant::objects, InternalDefaultACL::objtype, InternalGrant::objtype, InternalDefaultACL::privileges, InternalGrant::privileges, InternalDefaultACL::roleid, ScanKeyInit(), SetDefaultACL(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by shdepDropOwned().

◆ restrict_and_check_grant()

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

Definition at line 231 of file aclchk.c.

235 {
236  AclMode this_privileges;
237  AclMode whole_mask;
238 
239  switch (objtype)
240  {
241  case OBJECT_COLUMN:
242  whole_mask = ACL_ALL_RIGHTS_COLUMN;
243  break;
244  case OBJECT_TABLE:
245  whole_mask = ACL_ALL_RIGHTS_RELATION;
246  break;
247  case OBJECT_SEQUENCE:
248  whole_mask = ACL_ALL_RIGHTS_SEQUENCE;
249  break;
250  case OBJECT_DATABASE:
251  whole_mask = ACL_ALL_RIGHTS_DATABASE;
252  break;
253  case OBJECT_FUNCTION:
254  whole_mask = ACL_ALL_RIGHTS_FUNCTION;
255  break;
256  case OBJECT_LANGUAGE:
257  whole_mask = ACL_ALL_RIGHTS_LANGUAGE;
258  break;
259  case OBJECT_LARGEOBJECT:
260  whole_mask = ACL_ALL_RIGHTS_LARGEOBJECT;
261  break;
262  case OBJECT_SCHEMA:
263  whole_mask = ACL_ALL_RIGHTS_SCHEMA;
264  break;
265  case OBJECT_TABLESPACE:
266  whole_mask = ACL_ALL_RIGHTS_TABLESPACE;
267  break;
268  case OBJECT_FDW:
269  whole_mask = ACL_ALL_RIGHTS_FDW;
270  break;
272  whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
273  break;
275  elog(ERROR, "grantable rights not supported for event triggers");
276  /* not reached, but keep compiler quiet */
277  return ACL_NO_RIGHTS;
278  case OBJECT_TYPE:
279  whole_mask = ACL_ALL_RIGHTS_TYPE;
280  break;
282  whole_mask = ACL_ALL_RIGHTS_PARAMETER_ACL;
283  break;
284  default:
285  elog(ERROR, "unrecognized object type: %d", objtype);
286  /* not reached, but keep compiler quiet */
287  return ACL_NO_RIGHTS;
288  }
289 
290  /*
291  * If we found no grant options, consider whether to issue a hard error.
292  * Per spec, having any privilege at all on the object will get you by
293  * here.
294  */
295  if (avail_goptions == ACL_NO_RIGHTS)
296  {
297  if (pg_aclmask(objtype, objectId, att_number, grantorId,
298  whole_mask | ACL_GRANT_OPTION_FOR(whole_mask),
300  {
301  if (objtype == OBJECT_COLUMN && colname)
302  aclcheck_error_col(ACLCHECK_NO_PRIV, objtype, objname, colname);
303  else
304  aclcheck_error(ACLCHECK_NO_PRIV, objtype, objname);
305  }
306  }
307 
308  /*
309  * Restrict the operation to what we can actually grant or revoke, and
310  * issue a warning if appropriate. (For REVOKE this isn't quite what the
311  * spec says to do: the spec seems to want a warning only if no privilege
312  * bits actually change in the ACL. In practice that behavior seems much
313  * too noisy, as well as inconsistent with the GRANT case.)
314  */
315  this_privileges = privileges &