PostgreSQL Source Code  git master
aclchk.c File Reference
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 object_aclmask_ext (Oid classid, Oid objectid, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
 
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_ext (Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
 
static AclMode pg_type_aclmask_ext (Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
 
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 object_aclcheck_ext (Oid classid, Oid objectid, Oid roleid, AclMode mode, bool *is_missing)
 
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_attribute_aclcheck_all_ext (Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how, bool *is_missing)
 
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)
 
void ReplaceRoleInInitPriv (Oid oldroleid, Oid newroleid, Oid classid, Oid objid, int32 objsubid)
 
void RemoveRoleFromInitPriv (Oid roleid, Oid classid, Oid objid, int32 objsubid)
 

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

2702 {
2703  switch (aclerr)
2704  {
2705  case ACLCHECK_OK:
2706  /* no error, so return to caller */
2707  break;
2708  case ACLCHECK_NO_PRIV:
2709  {
2710  const char *msg = "???";
2711 
2712  switch (objtype)
2713  {
2714  case OBJECT_AGGREGATE:
2715  msg = gettext_noop("permission denied for aggregate %s");
2716  break;
2717  case OBJECT_COLLATION:
2718  msg = gettext_noop("permission denied for collation %s");
2719  break;
2720  case OBJECT_COLUMN:
2721  msg = gettext_noop("permission denied for column %s");
2722  break;
2723  case OBJECT_CONVERSION:
2724  msg = gettext_noop("permission denied for conversion %s");
2725  break;
2726  case OBJECT_DATABASE:
2727  msg = gettext_noop("permission denied for database %s");
2728  break;
2729  case OBJECT_DOMAIN:
2730  msg = gettext_noop("permission denied for domain %s");
2731  break;
2732  case OBJECT_EVENT_TRIGGER:
2733  msg = gettext_noop("permission denied for event trigger %s");
2734  break;
2735  case OBJECT_EXTENSION:
2736  msg = gettext_noop("permission denied for extension %s");
2737  break;
2738  case OBJECT_FDW:
2739  msg = gettext_noop("permission denied for foreign-data wrapper %s");
2740  break;
2741  case OBJECT_FOREIGN_SERVER:
2742  msg = gettext_noop("permission denied for foreign server %s");
2743  break;
2744  case OBJECT_FOREIGN_TABLE:
2745  msg = gettext_noop("permission denied for foreign table %s");
2746  break;
2747  case OBJECT_FUNCTION:
2748  msg = gettext_noop("permission denied for function %s");
2749  break;
2750  case OBJECT_INDEX:
2751  msg = gettext_noop("permission denied for index %s");
2752  break;
2753  case OBJECT_LANGUAGE:
2754  msg = gettext_noop("permission denied for language %s");
2755  break;
2756  case OBJECT_LARGEOBJECT:
2757  msg = gettext_noop("permission denied for large object %s");
2758  break;
2759  case OBJECT_MATVIEW:
2760  msg = gettext_noop("permission denied for materialized view %s");
2761  break;
2762  case OBJECT_OPCLASS:
2763  msg = gettext_noop("permission denied for operator class %s");
2764  break;
2765  case OBJECT_OPERATOR:
2766  msg = gettext_noop("permission denied for operator %s");
2767  break;
2768  case OBJECT_OPFAMILY:
2769  msg = gettext_noop("permission denied for operator family %s");
2770  break;
2771  case OBJECT_PARAMETER_ACL:
2772  msg = gettext_noop("permission denied for parameter %s");
2773  break;
2774  case OBJECT_POLICY:
2775  msg = gettext_noop("permission denied for policy %s");
2776  break;
2777  case OBJECT_PROCEDURE:
2778  msg = gettext_noop("permission denied for procedure %s");
2779  break;
2780  case OBJECT_PUBLICATION:
2781  msg = gettext_noop("permission denied for publication %s");
2782  break;
2783  case OBJECT_ROUTINE:
2784  msg = gettext_noop("permission denied for routine %s");
2785  break;
2786  case OBJECT_SCHEMA:
2787  msg = gettext_noop("permission denied for schema %s");
2788  break;
2789  case OBJECT_SEQUENCE:
2790  msg = gettext_noop("permission denied for sequence %s");
2791  break;
2792  case OBJECT_STATISTIC_EXT:
2793  msg = gettext_noop("permission denied for statistics object %s");
2794  break;
2795  case OBJECT_SUBSCRIPTION:
2796  msg = gettext_noop("permission denied for subscription %s");
2797  break;
2798  case OBJECT_TABLE:
2799  msg = gettext_noop("permission denied for table %s");
2800  break;
2801  case OBJECT_TABLESPACE:
2802  msg = gettext_noop("permission denied for tablespace %s");
2803  break;
2805  msg = gettext_noop("permission denied for text search configuration %s");
2806  break;
2807  case OBJECT_TSDICTIONARY:
2808  msg = gettext_noop("permission denied for text search dictionary %s");
2809  break;
2810  case OBJECT_TYPE:
2811  msg = gettext_noop("permission denied for type %s");
2812  break;
2813  case OBJECT_VIEW:
2814  msg = gettext_noop("permission denied for view %s");
2815  break;
2816  /* these currently aren't used */
2817  case OBJECT_ACCESS_METHOD:
2818  case OBJECT_AMOP:
2819  case OBJECT_AMPROC:
2820  case OBJECT_ATTRIBUTE:
2821  case OBJECT_CAST:
2822  case OBJECT_DEFAULT:
2823  case OBJECT_DEFACL:
2824  case OBJECT_DOMCONSTRAINT:
2827  case OBJECT_ROLE:
2828  case OBJECT_RULE:
2829  case OBJECT_TABCONSTRAINT:
2830  case OBJECT_TRANSFORM:
2831  case OBJECT_TRIGGER:
2832  case OBJECT_TSPARSER:
2833  case OBJECT_TSTEMPLATE:
2834  case OBJECT_USER_MAPPING:
2835  elog(ERROR, "unsupported object type: %d", objtype);
2836  }
2837 
2838  ereport(ERROR,
2839  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2840  errmsg(msg, objectname)));
2841  break;
2842  }
2843  case ACLCHECK_NOT_OWNER:
2844  {
2845  const char *msg = "???";
2846 
2847  switch (objtype)
2848  {
2849  case OBJECT_AGGREGATE:
2850  msg = gettext_noop("must be owner of aggregate %s");
2851  break;
2852  case OBJECT_COLLATION:
2853  msg = gettext_noop("must be owner of collation %s");
2854  break;
2855  case OBJECT_CONVERSION:
2856  msg = gettext_noop("must be owner of conversion %s");
2857  break;
2858  case OBJECT_DATABASE:
2859  msg = gettext_noop("must be owner of database %s");
2860  break;
2861  case OBJECT_DOMAIN:
2862  msg = gettext_noop("must be owner of domain %s");
2863  break;
2864  case OBJECT_EVENT_TRIGGER:
2865  msg = gettext_noop("must be owner of event trigger %s");
2866  break;
2867  case OBJECT_EXTENSION:
2868  msg = gettext_noop("must be owner of extension %s");
2869  break;
2870  case OBJECT_FDW:
2871  msg = gettext_noop("must be owner of foreign-data wrapper %s");
2872  break;
2873  case OBJECT_FOREIGN_SERVER:
2874  msg = gettext_noop("must be owner of foreign server %s");
2875  break;
2876  case OBJECT_FOREIGN_TABLE:
2877  msg = gettext_noop("must be owner of foreign table %s");
2878  break;
2879  case OBJECT_FUNCTION:
2880  msg = gettext_noop("must be owner of function %s");
2881  break;
2882  case OBJECT_INDEX:
2883  msg = gettext_noop("must be owner of index %s");
2884  break;
2885  case OBJECT_LANGUAGE:
2886  msg = gettext_noop("must be owner of language %s");
2887  break;
2888  case OBJECT_LARGEOBJECT:
2889  msg = gettext_noop("must be owner of large object %s");
2890  break;
2891  case OBJECT_MATVIEW:
2892  msg = gettext_noop("must be owner of materialized view %s");
2893  break;
2894  case OBJECT_OPCLASS:
2895  msg = gettext_noop("must be owner of operator class %s");
2896  break;
2897  case OBJECT_OPERATOR:
2898  msg = gettext_noop("must be owner of operator %s");
2899  break;
2900  case OBJECT_OPFAMILY:
2901  msg = gettext_noop("must be owner of operator family %s");
2902  break;
2903  case OBJECT_PROCEDURE:
2904  msg = gettext_noop("must be owner of procedure %s");
2905  break;
2906  case OBJECT_PUBLICATION:
2907  msg = gettext_noop("must be owner of publication %s");
2908  break;
2909  case OBJECT_ROUTINE:
2910  msg = gettext_noop("must be owner of routine %s");
2911  break;
2912  case OBJECT_SEQUENCE:
2913  msg = gettext_noop("must be owner of sequence %s");
2914  break;
2915  case OBJECT_SUBSCRIPTION:
2916  msg = gettext_noop("must be owner of subscription %s");
2917  break;
2918  case OBJECT_TABLE:
2919  msg = gettext_noop("must be owner of table %s");
2920  break;
2921  case OBJECT_TYPE:
2922  msg = gettext_noop("must be owner of type %s");
2923  break;
2924  case OBJECT_VIEW:
2925  msg = gettext_noop("must be owner of view %s");
2926  break;
2927  case OBJECT_SCHEMA:
2928  msg = gettext_noop("must be owner of schema %s");
2929  break;
2930  case OBJECT_STATISTIC_EXT:
2931  msg = gettext_noop("must be owner of statistics object %s");
2932  break;
2933  case OBJECT_TABLESPACE:
2934  msg = gettext_noop("must be owner of tablespace %s");
2935  break;
2937  msg = gettext_noop("must be owner of text search configuration %s");
2938  break;
2939  case OBJECT_TSDICTIONARY:
2940  msg = gettext_noop("must be owner of text search dictionary %s");
2941  break;
2942 
2943  /*
2944  * Special cases: For these, the error message talks
2945  * about "relation", because that's where the
2946  * ownership is attached. See also
2947  * check_object_ownership().
2948  */
2949  case OBJECT_COLUMN:
2950  case OBJECT_POLICY:
2951  case OBJECT_RULE:
2952  case OBJECT_TABCONSTRAINT:
2953  case OBJECT_TRIGGER:
2954  msg = gettext_noop("must be owner of relation %s");
2955  break;
2956  /* these currently aren't used */
2957  case OBJECT_ACCESS_METHOD:
2958  case OBJECT_AMOP:
2959  case OBJECT_AMPROC:
2960  case OBJECT_ATTRIBUTE:
2961  case OBJECT_CAST:
2962  case OBJECT_DEFAULT:
2963  case OBJECT_DEFACL:
2964  case OBJECT_DOMCONSTRAINT:
2965  case OBJECT_PARAMETER_ACL:
2968  case OBJECT_ROLE:
2969  case OBJECT_TRANSFORM:
2970  case OBJECT_TSPARSER:
2971  case OBJECT_TSTEMPLATE:
2972  case OBJECT_USER_MAPPING:
2973  elog(ERROR, "unsupported object type: %d", objtype);
2974  }
2975 
2976  ereport(ERROR,
2977  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2978  errmsg(msg, objectname)));
2979  break;
2980  }
2981  default:
2982  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
2983  break;
2984  }
2985 }
@ ACLCHECK_NO_PRIV
Definition: acl.h:184
@ ACLCHECK_OK
Definition: acl.h:183
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
#define gettext_noop(x)
Definition: c.h:1196
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
@ OBJECT_EVENT_TRIGGER
Definition: parsenodes.h:2275
@ OBJECT_FDW
Definition: parsenodes.h:2277
@ OBJECT_TSPARSER
Definition: parsenodes.h:2308
@ OBJECT_COLLATION
Definition: parsenodes.h:2268
@ OBJECT_USER_MAPPING
Definition: parsenodes.h:2311
@ OBJECT_ACCESS_METHOD
Definition: parsenodes.h:2261
@ OBJECT_OPCLASS
Definition: parsenodes.h:2285
@ OBJECT_DEFACL
Definition: parsenodes.h:2272
@ OBJECT_AGGREGATE
Definition: parsenodes.h:2262
@ OBJECT_MATVIEW
Definition: parsenodes.h:2284
@ OBJECT_SCHEMA
Definition: parsenodes.h:2297
@ OBJECT_POLICY
Definition: parsenodes.h:2289
@ OBJECT_OPERATOR
Definition: parsenodes.h:2286
@ OBJECT_FOREIGN_TABLE
Definition: parsenodes.h:2279
@ OBJECT_TSCONFIGURATION
Definition: parsenodes.h:2306
@ OBJECT_OPFAMILY
Definition: parsenodes.h:2287
@ OBJECT_DOMAIN
Definition: parsenodes.h:2273
@ OBJECT_COLUMN
Definition: parsenodes.h:2267
@ OBJECT_TABLESPACE
Definition: parsenodes.h:2303
@ OBJECT_ROLE
Definition: parsenodes.h:2294
@ OBJECT_ROUTINE
Definition: parsenodes.h:2295
@ OBJECT_LARGEOBJECT
Definition: parsenodes.h:2283
@ OBJECT_PUBLICATION_NAMESPACE
Definition: parsenodes.h:2292
@ OBJECT_PROCEDURE
Definition: parsenodes.h:2290
@ OBJECT_EXTENSION
Definition: parsenodes.h:2276
@ OBJECT_INDEX
Definition: parsenodes.h:2281
@ OBJECT_DEFAULT
Definition: parsenodes.h:2271
@ OBJECT_DATABASE
Definition: parsenodes.h:2270
@ OBJECT_SEQUENCE
Definition: parsenodes.h:2298
@ OBJECT_TSTEMPLATE
Definition: parsenodes.h:2309
@ OBJECT_LANGUAGE
Definition: parsenodes.h:2282
@ OBJECT_AMOP
Definition: parsenodes.h:2263
@ OBJECT_PUBLICATION_REL
Definition: parsenodes.h:2293
@ OBJECT_FOREIGN_SERVER
Definition: parsenodes.h:2278
@ OBJECT_TSDICTIONARY
Definition: parsenodes.h:2307
@ OBJECT_ATTRIBUTE
Definition: parsenodes.h:2265
@ OBJECT_PUBLICATION
Definition: parsenodes.h:2291
@ OBJECT_RULE
Definition: parsenodes.h:2296
@ OBJECT_CONVERSION
Definition: parsenodes.h:2269
@ OBJECT_AMPROC
Definition: parsenodes.h:2264
@ OBJECT_TABLE
Definition: parsenodes.h:2302
@ OBJECT_VIEW
Definition: parsenodes.h:2312
@ OBJECT_PARAMETER_ACL
Definition: parsenodes.h:2288
@ OBJECT_TYPE
Definition: parsenodes.h:2310
@ OBJECT_FUNCTION
Definition: parsenodes.h:2280
@ OBJECT_TABCONSTRAINT
Definition: parsenodes.h:2301
@ OBJECT_DOMCONSTRAINT
Definition: parsenodes.h:2274
@ OBJECT_SUBSCRIPTION
Definition: parsenodes.h:2299
@ OBJECT_STATISTIC_EXT
Definition: parsenodes.h:2300
@ OBJECT_CAST
Definition: parsenodes.h:2266
@ OBJECT_TRIGGER
Definition: parsenodes.h:2305
@ OBJECT_TRANSFORM
Definition: parsenodes.h:2304

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(), checkPartition(), 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(), RangeVarCallbackMaintainsTable(), RangeVarCallbackOwnsRelation(), RangeVarGetAndCheckCreationNamespace(), ReindexMultipleInternal(), ReindexMultipleTables(), renameatt_check(), RenameDatabase(), RenameSchema(), RenameTableSpace(), restrict_and_check_grant(), TargetPrivilegesCheck(), transformTableLikeClause(), truncate_check_perms(), TypeCreate(), user_mapping_ddl_aclcheck(), ValidateJoinEstimator(), ValidateOperatorReference(), and ValidateRestrictionEstimator().

◆ aclcheck_error_col()

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

Definition at line 2989 of file aclchk.c.

2991 {
2992  switch (aclerr)
2993  {
2994  case ACLCHECK_OK:
2995  /* no error, so return to caller */
2996  break;
2997  case ACLCHECK_NO_PRIV:
2998  ereport(ERROR,
2999  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3000  errmsg("permission denied for column \"%s\" of relation \"%s\"",
3001  colname, objectname)));
3002  break;
3003  case ACLCHECK_NOT_OWNER:
3004  /* relation msg is OK since columns don't have separate owners */
3005  aclcheck_error(aclerr, objtype, objectname);
3006  break;
3007  default:
3008  elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
3009  break;
3010  }
3011 }
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2700

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

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

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

1682 {
1683  HeapTuple attr_tuple;
1684  Form_pg_attribute pg_attribute_tuple;
1685  Acl *old_acl;
1686  Acl *new_acl;
1687  Acl *merged_acl;
1688  Datum aclDatum;
1689  bool isNull;
1690  Oid grantorId;
1691  AclMode avail_goptions;
1692  bool need_update;
1693  HeapTuple newtuple;
1694  Datum values[Natts_pg_attribute] = {0};
1695  bool nulls[Natts_pg_attribute] = {0};
1696  bool replaces[Natts_pg_attribute] = {0};
1697  int noldmembers;
1698  int nnewmembers;
1699  Oid *oldmembers;
1700  Oid *newmembers;
1701 
1702  attr_tuple = SearchSysCache2(ATTNUM,
1703  ObjectIdGetDatum(relOid),
1705  if (!HeapTupleIsValid(attr_tuple))
1706  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1707  attnum, relOid);
1708  pg_attribute_tuple = (Form_pg_attribute) GETSTRUCT(attr_tuple);
1709 
1710  /*
1711  * Get working copy of existing ACL. If there's no ACL, substitute the
1712  * proper default.
1713  */
1714  aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
1715  &isNull);
1716  if (isNull)
1717  {
1718  old_acl = acldefault(OBJECT_COLUMN, ownerId);
1719  /* There are no old member roles according to the catalogs */
1720  noldmembers = 0;
1721  oldmembers = NULL;
1722  }
1723  else
1724  {
1725  old_acl = DatumGetAclPCopy(aclDatum);
1726  /* Get the roles mentioned in the existing ACL */
1727  noldmembers = aclmembers(old_acl, &oldmembers);
1728  }
1729 
1730  /*
1731  * In select_best_grantor we should consider existing table-level ACL bits
1732  * as well as the per-column ACL. Build a new ACL that is their
1733  * concatenation. (This is a bit cheap and dirty compared to merging them
1734  * properly with no duplications, but it's all we need here.)
1735  */
1736  merged_acl = aclconcat(old_rel_acl, old_acl);
1737 
1738  /* Determine ID to do the grant as, and available grant options */
1739  select_best_grantor(GetUserId(), col_privileges,
1740  merged_acl, ownerId,
1741  &grantorId, &avail_goptions);
1742 
1743  pfree(merged_acl);
1744 
1745  /*
1746  * Restrict the privileges to what we can actually grant, and emit the
1747  * standards-mandated warning and error messages. Note: we don't track
1748  * whether the user actually used the ALL PRIVILEGES(columns) syntax for
1749  * each column; we just approximate it by whether all the possible
1750  * privileges are specified now. Since the all_privs flag only determines
1751  * whether a warning is issued, this seems close enough.
1752  */
1753  col_privileges =
1754  restrict_and_check_grant(istmt->is_grant, avail_goptions,
1755  (col_privileges == ACL_ALL_RIGHTS_COLUMN),
1756  col_privileges,
1757  relOid, grantorId, OBJECT_COLUMN,
1758  relname, attnum,
1759  NameStr(pg_attribute_tuple->attname));
1760 
1761  /*
1762  * Generate new ACL.
1763  */
1764  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
1765  istmt->grant_option,
1766  istmt->behavior, istmt->grantees,
1767  col_privileges, grantorId,
1768  ownerId);
1769 
1770  /*
1771  * We need the members of both old and new ACLs so we can correct the
1772  * shared dependency information.
1773  */
1774  nnewmembers = aclmembers(new_acl, &newmembers);
1775 
1776  /* finished building new ACL value, now insert it */
1777 
1778  /*
1779  * If the updated ACL is empty, we can set attacl to null, and maybe even
1780  * avoid an update of the pg_attribute row. This is worth testing because
1781  * we'll come through here multiple times for any relation-level REVOKE,
1782  * even if there were never any column GRANTs. Note we are assuming that
1783  * the "default" ACL state for columns is empty.
1784  */
1785  if (ACL_NUM(new_acl) > 0)
1786  {
1787  values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl);
1788  need_update = true;
1789  }
1790  else
1791  {
1792  nulls[Anum_pg_attribute_attacl - 1] = true;
1793  need_update = !isNull;
1794  }
1795  replaces[Anum_pg_attribute_attacl - 1] = true;
1796 
1797  if (need_update)
1798  {
1799  newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
1800  values, nulls, replaces);
1801 
1802  CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
1803 
1804  /* Update initial privileges for extensions */
1805  recordExtensionInitPriv(relOid, RelationRelationId, attnum,
1806  ACL_NUM(new_acl) > 0 ? new_acl : NULL);
1807 
1808  /* Update the shared dependency ACL info */
1809  updateAclDependencies(RelationRelationId, relOid, attnum,
1810  ownerId,
1811  noldmembers, oldmembers,
1812  nnewmembers, newmembers);
1813  }
1814 
1815  pfree(new_acl);
1816 
1817  ReleaseSysCache(attr_tuple);
1818 }
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition: acl.c:5344
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1523
Acl * aclconcat(const Acl *left_acl, const Acl *right_acl)
Definition: acl.c:460
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:786
#define ACL_ALL_RIGHTS_COLUMN
Definition: acl.h:159
#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:4651
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:181
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:240
static Datum values[MAXATTR]
Definition: bootstrap.c:150
#define NameStr(name)
Definition: c.h:746
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1209
#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:1521
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:491
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:531
ItemPointerData t_self
Definition: htup.h:65
DropBehavior behavior
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:479
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:229

References ACL_ALL_RIGHTS_COLUMN, ACL_NUM, aclconcat(), acldefault(), aclmembers(), attnum, InternalGrant::behavior, CatalogTupleUpdate(), DatumGetAclPCopy, elog, ERROR, GETSTRUCT, GetUserId(), InternalGrant::grant_option, InternalGrant::grantees, heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum(), InternalGrant::is_grant, 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 2152 of file aclchk.c.

2154 {
2155  int cacheid;
2156  Relation relation;
2157  ListCell *cell;
2158 
2159  if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
2160  istmt->privileges = default_privs;
2161 
2162  cacheid = get_object_catcache_oid(classid);
2163 
2164  relation = table_open(classid, RowExclusiveLock);
2165 
2166  foreach(cell, istmt->objects)
2167  {
2168  Oid objectid = lfirst_oid(cell);
2169  Datum aclDatum;
2170  Datum nameDatum;
2171  bool isNull;
2172  AclMode avail_goptions;
2173  AclMode this_privileges;
2174  Acl *old_acl;
2175  Acl *new_acl;
2176  Oid grantorId;
2177  Oid ownerId;
2178  HeapTuple tuple;
2179  HeapTuple newtuple;
2180  Datum *values = palloc0_array(Datum, RelationGetDescr(relation)->natts);
2181  bool *nulls = palloc0_array(bool, RelationGetDescr(relation)->natts);
2182  bool *replaces = palloc0_array(bool, RelationGetDescr(relation)->natts);
2183  int noldmembers;
2184  int nnewmembers;
2185  Oid *oldmembers;
2186  Oid *newmembers;
2187 
2188  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
2189  if (!HeapTupleIsValid(tuple))
2190  elog(ERROR, "cache lookup failed for %s %u", get_object_class_descr(classid), objectid);
2191 
2192  /*
2193  * Additional object-type-specific checks
2194  */
2195  if (object_check)
2196  object_check(istmt, tuple);
2197 
2198  /*
2199  * Get owner ID and working copy of existing ACL. If there's no ACL,
2200  * substitute the proper default.
2201  */
2202  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
2203  tuple,
2204  get_object_attnum_owner(classid)));
2205  aclDatum = SysCacheGetAttr(cacheid,
2206  tuple,
2207  get_object_attnum_acl(classid),
2208  &isNull);
2209  if (isNull)
2210  {
2211  old_acl = acldefault(get_object_type(classid, objectid), ownerId);
2212  /* There are no old member roles according to the catalogs */
2213  noldmembers = 0;
2214  oldmembers = NULL;
2215  }
2216  else
2217  {
2218  old_acl = DatumGetAclPCopy(aclDatum);
2219  /* Get the roles mentioned in the existing ACL */
2220  noldmembers = aclmembers(old_acl, &oldmembers);
2221  }
2222 
2223  /* Determine ID to do the grant as, and available grant options */
2225  old_acl, ownerId,
2226  &grantorId, &avail_goptions);
2227 
2228  nameDatum = SysCacheGetAttrNotNull(cacheid, tuple,
2229  get_object_attnum_name(classid));
2230 
2231  /*
2232  * Restrict the privileges to what we can actually grant, and emit the
2233  * standards-mandated warning and error messages.
2234  */
2235  this_privileges =
2236  restrict_and_check_grant(istmt->is_grant, avail_goptions,
2237  istmt->all_privs, istmt->privileges,
2238  objectid, grantorId, get_object_type(classid, objectid),
2239  NameStr(*DatumGetName(nameDatum)),
2240  0, NULL);
2241 
2242  /*
2243  * Generate new ACL.
2244  */
2245  new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
2246  istmt->grant_option, istmt->behavior,
2247  istmt->grantees, this_privileges,
2248  grantorId, ownerId);
2249 
2250  /*
2251  * We need the members of both old and new ACLs so we can correct the
2252  * shared dependency information.
2253  */
2254  nnewmembers = aclmembers(new_acl, &newmembers);
2255 
2256  /* finished building new ACL value, now insert it */
2257  replaces[get_object_attnum_acl(classid) - 1] = true;
2258  values[get_object_attnum_acl(classid) - 1] = PointerGetDatum(new_acl);
2259 
2260  newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
2261  nulls, replaces);
2262 
2263  CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
2264 
2265  /* Update initial privileges for extensions */
2266  recordExtensionInitPriv(objectid, classid, 0, new_acl);
2267 
2268  /* Update the shared dependency ACL info */
2269  updateAclDependencies(classid,
2270  objectid, 0,
2271  ownerId,
2272  noldmembers, oldmembers,
2273  nnewmembers, newmembers);
2274 
2275  ReleaseSysCache(tuple);
2276 
2277  pfree(new_acl);
2278 
2279  /* prevent error when processing duplicate objects */
2281  }
2282 
2283  table_close(relation, RowExclusiveLock);
2284 }
#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:218
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:510
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:1098

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

2288 {
2289  Form_pg_language pg_language_tuple;
2290 
2291  pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
2292 
2293  if (!pg_language_tuple->lanpltrusted)
2294  ereport(ERROR,
2295  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2296  errmsg("language \"%s\" is not trusted",
2297  NameStr(pg_language_tuple->lanname)),
2298  errdetail("GRANT and REVOKE are not allowed on untrusted languages, "
2299  "because only superusers can use untrusted languages.")));
2300 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
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 2303 of file aclchk.c.

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

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

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

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

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

2440 {
2441  Form_pg_type pg_type_tuple;
2442 
2443  pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
2444 
2445  /* Disallow GRANT on dependent types */
2446  if (IsTrueArrayType(pg_type_tuple))
2447  ereport(ERROR,
2448  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
2449  errmsg("cannot set privileges of array types"),
2450  errhint("Set the privileges of the element type instead.")));
2451  if (pg_type_tuple->typtype == TYPTYPE_MULTIRANGE)
2452  ereport(ERROR,
2453  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
2454  errmsg("cannot set privileges of multirange types"),
2455  errhint("Set the privileges of the range type instead.")));
2456 
2457  /* Used GRANT DOMAIN on a non-domain? */
2458  if (istmt->objtype == OBJECT_DOMAIN &&
2459  pg_type_tuple->typtype != TYPTYPE_DOMAIN)
2460  ereport(ERROR,
2461  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2462  errmsg("\"%s\" is not a domain",
2463  NameStr(pg_type_tuple->typname))));
2464 }
int errhint(const char *fmt,...)
Definition: elog.c:1317
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 601 of file aclchk.c.

602 {
603  switch (istmt->objtype)
604  {
605  case OBJECT_TABLE:
606  case OBJECT_SEQUENCE:
607  ExecGrant_Relation(istmt);
608  break;
609  case OBJECT_DATABASE:
610  ExecGrant_common(istmt, DatabaseRelationId, ACL_ALL_RIGHTS_DATABASE, NULL);
611  break;
612  case OBJECT_DOMAIN:
613  case OBJECT_TYPE:
615  break;
616  case OBJECT_FDW:
617  ExecGrant_common(istmt, ForeignDataWrapperRelationId, ACL_ALL_RIGHTS_FDW, NULL);
618  break;
620  ExecGrant_common(istmt, ForeignServerRelationId, ACL_ALL_RIGHTS_FOREIGN_SERVER, NULL);
621  break;
622  case OBJECT_FUNCTION:
623  case OBJECT_PROCEDURE:
624  case OBJECT_ROUTINE:
625  ExecGrant_common(istmt, ProcedureRelationId, ACL_ALL_RIGHTS_FUNCTION, NULL);
626  break;
627  case OBJECT_LANGUAGE:
629  break;
630  case OBJECT_LARGEOBJECT:
631  ExecGrant_Largeobject(istmt);
632  break;
633  case OBJECT_SCHEMA:
634  ExecGrant_common(istmt, NamespaceRelationId, ACL_ALL_RIGHTS_SCHEMA, NULL);
635  break;
636  case OBJECT_TABLESPACE:
637  ExecGrant_common(istmt, TableSpaceRelationId, ACL_ALL_RIGHTS_TABLESPACE, NULL);
638  break;
640  ExecGrant_Parameter(istmt);
641  break;
642  default:
643  elog(ERROR, "unrecognized GrantStmt.objtype: %d",
644  (int) istmt->objtype);
645  }
646 
647  /*
648  * Pass the info to event triggers about the just-executed GRANT. Note
649  * that we prefer to do it after actually executing it, because that gives
650  * the functions a chance to adjust the istmt with privileges actually
651  * granted.
652  */
655 }
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition: acl.h:164
#define ACL_ALL_RIGHTS_TABLESPACE
Definition: acl.h:170
#define ACL_ALL_RIGHTS_DATABASE
Definition: acl.h:162
#define ACL_ALL_RIGHTS_LANGUAGE
Definition: acl.h:166
#define ACL_ALL_RIGHTS_FDW
Definition: acl.h:163
static void ExecGrant_Type_check(InternalGrant *istmt, HeapTuple tuple)
Definition: aclchk.c:2439
static void ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs, void(*object_check)(InternalGrant *istmt, HeapTuple tuple))
Definition: aclchk.c:2152
static void ExecGrant_Largeobject(InternalGrant *istmt)
Definition: aclchk.c:2303
static void ExecGrant_Parameter(InternalGrant *istmt)
Definition: aclchk.c:2467
static void ExecGrant_Relation(InternalGrant *istmt)
Definition: aclchk.c:1824
static void ExecGrant_Language_check(InternalGrant *istmt, HeapTuple tuple)
Definition: aclchk.c:2287
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 391 of file aclchk.c.

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

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

1637 {
1638  AttrNumber curr_att;
1639 
1640  Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
1641  for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
1642  curr_att <= classForm->relnatts;
1643  curr_att++)
1644  {
1645  HeapTuple attTuple;
1646  bool isdropped;
1647 
1648  if (curr_att == InvalidAttrNumber)
1649  continue;
1650 
1651  /* Views don't have any system columns at all */
1652  if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
1653  continue;
1654 
1655  attTuple = SearchSysCache2(ATTNUM,
1656  ObjectIdGetDatum(table_oid),
1657  Int16GetDatum(curr_att));
1658  if (!HeapTupleIsValid(attTuple))
1659  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1660  curr_att, table_oid);
1661 
1662  isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
1663 
1664  ReleaseSysCache(attTuple);
1665 
1666  /* ignore dropped columns */
1667  if (isdropped)
1668  continue;
1669 
1670  col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
1671  }
1672 }
#define InvalidAttrNumber
Definition: attnum.h:23
#define Assert(condition)
Definition: c.h:858

References Assert, 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 1600 of file aclchk.c.

1604 {
1605  ListCell *cell;
1606 
1607  foreach(cell, colnames)
1608  {
1609  char *colname = strVal(lfirst(cell));
1611 
1612  attnum = get_attnum(table_oid, colname);
1613  if (attnum == InvalidAttrNumber)
1614  ereport(ERROR,
1615  (errcode(ERRCODE_UNDEFINED_COLUMN),
1616  errmsg("column \"%s\" of relation \"%s\" does not exist",
1617  colname, get_rel_name(table_oid))));
1619  if (attnum <= 0 || attnum >= num_col_privileges)
1620  elog(ERROR, "column number out of range"); /* safety check */
1621  col_privileges[attnum] |= this_privileges;
1622  }
1623 }
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:858
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1928
#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 4266 of file aclchk.c.

4267 {
4268  Acl *result = NULL;
4269  HeapTuple tuple;
4270 
4271  tuple = SearchSysCache3(DEFACLROLENSPOBJ,
4272  ObjectIdGetDatum(roleId),
4273  ObjectIdGetDatum(nsp_oid),
4274  CharGetDatum(objtype));
4275 
4276  if (HeapTupleIsValid(tuple))
4277  {
4278  Datum aclDatum;
4279  bool isNull;
4280 
4281  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
4282  Anum_pg_default_acl_defaclacl,
4283  &isNull);
4284  if (!isNull)
4285  result = DatumGetAclPCopy(aclDatum);
4286  ReleaseSysCache(tuple);
4287  }
4288 
4289  return result;
4290 }
static Datum CharGetDatum(char X)
Definition: postgres.h:122
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:240

References CharGetDatum(), DatumGetAclPCopy, 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 4301 of file aclchk.c.

4302 {
4303  Acl *result;
4304  Acl *glob_acl;
4305  Acl *schema_acl;
4306  Acl *def_acl;
4307  char defaclobjtype;
4308 
4309  /*
4310  * Use NULL during bootstrap, since pg_default_acl probably isn't there
4311  * yet.
4312  */
4314  return NULL;
4315 
4316  /* Check if object type is supported in pg_default_acl */
4317  switch (objtype)
4318  {
4319  case OBJECT_TABLE:
4320  defaclobjtype = DEFACLOBJ_RELATION;
4321  break;
4322 
4323  case OBJECT_SEQUENCE:
4324  defaclobjtype = DEFACLOBJ_SEQUENCE;
4325  break;
4326 
4327  case OBJECT_FUNCTION:
4328  defaclobjtype = DEFACLOBJ_FUNCTION;
4329  break;
4330 
4331  case OBJECT_TYPE:
4332  defaclobjtype = DEFACLOBJ_TYPE;
4333  break;
4334 
4335  case OBJECT_SCHEMA:
4336  defaclobjtype = DEFACLOBJ_NAMESPACE;
4337  break;
4338 
4339  default:
4340  return NULL;
4341  }
4342 
4343  /* Look up the relevant pg_default_acl entries */
4344  glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
4345  schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
4346 
4347  /* Quick out if neither entry exists */
4348  if (glob_acl == NULL && schema_acl == NULL)
4349  return NULL;
4350 
4351  /* We need to know the hard-wired default value, too */
4352  def_acl = acldefault(objtype, ownerId);
4353 
4354  /* If there's no global entry, substitute the hard-wired default */
4355  if (glob_acl == NULL)
4356  glob_acl = def_acl;
4357 
4358  /* Merge in any per-schema privileges */
4359  result = aclmerge(glob_acl, schema_acl, ownerId);
4360 
4361  /*
4362  * For efficiency, we want to return NULL if the result equals default.
4363  * This requires sorting both arrays to get an accurate comparison.
4364  */
4365  aclitemsort(result);
4366  aclitemsort(def_acl);
4367  if (aclequal(result, def_acl))
4368  result = NULL;
4369 
4370  return result;
4371 }
void aclitemsort(Acl *acl)
Definition: acl.c:528
Acl * aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
Definition: acl.c:484
static Acl * get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
Definition: aclchk.c:4266
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:454
#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 937 of file aclchk.c.

938 {
939  List *relations = NIL;
940  ScanKeyData key[2];
941  Relation rel;
942  TableScanDesc scan;
943  HeapTuple tuple;
944 
945  ScanKeyInit(&key[0],
946  Anum_pg_class_relnamespace,
947  BTEqualStrategyNumber, F_OIDEQ,
948  ObjectIdGetDatum(namespaceId));
949  ScanKeyInit(&key[1],
950  Anum_pg_class_relkind,
951  BTEqualStrategyNumber, F_CHAREQ,
952  CharGetDatum(relkind));
953 
954  rel = table_open(RelationRelationId, AccessShareLock);
955  scan = table_beginscan_catalog(rel, 2, key);
956 
957  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
958  {
959  Oid oid = ((Form_pg_class) GETSTRUCT(tuple))->oid;
960 
961  relations = lappend_oid(relations, oid);
962  }
963 
964  table_endscan(scan);
966 
967  return relations;
968 }
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1252
#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:1019

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

4243 {
4244  bool result = false;
4245  HeapTuple utup;
4246 
4247  /* Superusers bypass all permission checking. */
4248  if (superuser_arg(roleid))
4249  return true;
4250 
4251  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4252  if (HeapTupleIsValid(utup))
4253  {
4254  result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
4255  ReleaseSysCache(utup);
4256  }
4257  return result;
4258 }
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

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

4224 {
4225  bool result = false;
4226  HeapTuple utup;
4227 
4228  /* Superusers bypass all permission checking. */
4229  if (superuser_arg(roleid))
4230  return true;
4231 
4232  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
4233  if (HeapTupleIsValid(utup))
4234  {
4235  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
4236  ReleaseSysCache(utup);
4237  }
4238  return result;
4239 }
bool rolcreaterole
Definition: pg_authid.h:37

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

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

◆ object_aclcheck()

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

Definition at line 3888 of file aclchk.c.

3889 {
3890  return object_aclcheck_ext(classid, objectid, roleid, mode, NULL);
3891 }
AclResult object_aclcheck_ext(Oid classid, Oid objectid, Oid roleid, AclMode mode, bool *is_missing)
Definition: aclchk.c:3898
static PgChecksumMode mode
Definition: pg_checksums.c:56

References mode, and object_aclcheck_ext().

Referenced by AggregateCreate(), AlterExtensionNamespace(), AlterForeignServerOwner_internal(), AlterObjectNamespace_internal(), AlterObjectOwner_internal(), AlterObjectRename_internal(), AlterPublicationOwner_internal(), AlterSchemaOwner_internal(), AlterSubscriptionOwner_internal(), AlterTableMoveAll(), AlterTypeOwner(), 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_name(), has_database_privilege_name(), has_database_privilege_name_name(), has_foreign_data_wrapper_privilege_id_name(), has_foreign_data_wrapper_privilege_name(), has_foreign_data_wrapper_privilege_name_name(), has_function_privilege_id_name(), has_function_privilege_name(), has_function_privilege_name_name(), has_language_privilege_id_name(), has_language_privilege_name(), has_language_privilege_name_name(), has_schema_privilege_id_name(), has_schema_privilege_name(), has_schema_privilege_name_name(), has_server_privilege_id_name(), has_server_privilege_name(), has_server_privilege_name_name(), has_tablespace_privilege_id_name(), has_tablespace_privilege_name(), has_tablespace_privilege_name_name(), has_type_privilege_id_name(), has_type_privilege_name(), 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(), PrepareTempTablespaces(), preprocessNamespacePath(), RangeVarCallbackForAlterRelation(), RangeVarGetAndCheckCreationNamespace(), ReindexMultipleInternal(), RenameSchema(), transformTableLikeClause(), user_mapping_ddl_aclcheck(), ValidateJoinEstimator(), and ValidateRestrictionEstimator().

◆ object_aclcheck_ext()

◆ object_aclmask()

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

Definition at line 3096 of file aclchk.c.

3098 {
3099  return object_aclmask_ext(classid, objectid, roleid, mask, how, NULL);
3100 }

References object_aclmask_ext().

Referenced by pg_aclmask().

◆ object_aclmask_ext()

static AclMode object_aclmask_ext ( Oid  classid,
Oid  objectid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how,
bool is_missing 
)
static

Definition at line 3107 of file aclchk.c.

3110 {
3111  int cacheid;
3112  AclMode result;
3113  HeapTuple tuple;
3114  Datum aclDatum;
3115  bool isNull;
3116  Acl *acl;
3117  Oid ownerId;
3118 
3119  /* Special cases */
3120  switch (classid)
3121  {
3122  case NamespaceRelationId:
3123  return pg_namespace_aclmask_ext(objectid, roleid, mask, how,
3124  is_missing);
3125  case TypeRelationId:
3126  return pg_type_aclmask_ext(objectid, roleid, mask, how,
3127  is_missing);
3128  }
3129 
3130  /* Even more special cases */
3131  Assert(classid != RelationRelationId); /* should use pg_class_acl* */
3132  Assert(classid != LargeObjectMetadataRelationId); /* should use
3133  * pg_largeobject_acl* */
3134 
3135  /* Superusers bypass all permission checking. */
3136  if (superuser_arg(roleid))
3137  return mask;
3138 
3139  /*
3140  * Get the object's ACL from its catalog
3141  */
3142 
3143  cacheid = get_object_catcache_oid(classid);
3144 
3145  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
3146  if (!HeapTupleIsValid(tuple))
3147  {
3148  if (is_missing != NULL)
3149  {
3150  /* return "no privileges" instead of throwing an error */
3151  *is_missing = true;
3152  return 0;
3153  }
3154  else
3155  ereport(ERROR,
3156  (errcode(ERRCODE_UNDEFINED_OBJECT),
3157  errmsg("%s with OID %u does not exist",
3158  get_object_class_descr(classid), objectid)));
3159  }
3160 
3161  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
3162  tuple,
3163  get_object_attnum_owner(classid)));
3164 
3165  aclDatum = SysCacheGetAttr(cacheid, tuple, get_object_attnum_acl(classid),
3166  &isNull);
3167  if (isNull)
3168  {
3169  /* No ACL, so build default ACL */
3170  acl = acldefault(get_object_type(classid, objectid), ownerId);
3171  aclDatum = (Datum) 0;
3172  }
3173  else
3174  {
3175  /* detoast ACL if necessary */
3176  acl = DatumGetAclP(aclDatum);
3177  }
3178 
3179  result = aclmask(acl, roleid, ownerId, mask, how);
3180 
3181  /* if we have a detoasted copy, free it */
3182  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3183  pfree(acl);
3184 
3185  ReleaseSysCache(tuple);
3186 
3187  return result;
3188 }
AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
Definition: acl.c:1371
#define DatumGetAclP(X)
Definition: acl.h:120
static AclMode pg_namespace_aclmask_ext(Oid nsp_oid, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3660
static AclMode pg_type_aclmask_ext(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3762
char * Pointer
Definition: c.h:483
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_ext(), pg_type_aclmask_ext(), ReleaseSysCache(), SearchSysCache1(), superuser_arg(), SysCacheGetAttr(), and SysCacheGetAttrNotNull().

Referenced by object_aclcheck_ext(), and object_aclmask().

◆ object_ownercheck()

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

Definition at line 4142 of file aclchk.c.

4143 {
4144  int cacheid;
4145  Oid ownerId;
4146 
4147  /* Superusers bypass all permission checking. */
4148  if (superuser_arg(roleid))
4149  return true;
4150 
4151  /* For large objects, the catalog to consult is pg_largeobject_metadata */
4152  if (classid == LargeObjectRelationId)
4153  classid = LargeObjectMetadataRelationId;
4154 
4155  cacheid = get_object_catcache_oid(classid);
4156  if (cacheid != -1)
4157  {
4158  /* we can get the object's tuple from the syscache */
4159  HeapTuple tuple;
4160 
4161  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
4162  if (!HeapTupleIsValid(tuple))
4163  ereport(ERROR,
4164  (errcode(ERRCODE_UNDEFINED_OBJECT),
4165  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
4166 
4167  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
4168  tuple,
4169  get_object_attnum_owner(classid)));
4170  ReleaseSysCache(tuple);
4171  }
4172  else
4173  {
4174  /* for catalogs without an appropriate syscache */
4175  Relation rel;
4176  ScanKeyData entry[1];
4177  SysScanDesc scan;
4178  HeapTuple tuple;
4179  bool isnull;
4180 
4181  rel = table_open(classid, AccessShareLock);
4182 
4183  ScanKeyInit(&entry[0],
4184  get_object_attnum_oid(classid),
4185  BTEqualStrategyNumber, F_OIDEQ,
4186  ObjectIdGetDatum(objectid));
4187 
4188  scan = systable_beginscan(rel,
4189  get_object_oid_index(classid), true,
4190  NULL, 1, entry);
4191 
4192  tuple = systable_getnext(scan);
4193  if (!HeapTupleIsValid(tuple))
4194  ereport(ERROR,
4195  (errcode(ERRCODE_UNDEFINED_OBJECT),
4196  errmsg("%s with OID %u does not exist", get_object_class_descr(classid), objectid)));
4197 
4198  ownerId = DatumGetObjectId(heap_getattr(tuple,
4199  get_object_attnum_owner(classid),
4200  RelationGetDescr(rel),
4201  &isnull));
4202  Assert(!isnull);
4203 
4204  systable_endscan(scan);
4206  }
4207 
4208  return has_privs_of_role(roleid, ownerId);
4209 }
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(), checkPartition(), CreateCast(), createdb(), CreateProceduralLanguage(), CreateStatistics(), CreateTransform(), DefineOpClass(), DefineQueryRewrite(), DefineType(), dropdb(), DropSubscription(), DropTableSpace(), EnableDisableRule(), ExecAlterExtensionContentsStmt(), ExecAlterExtensionStmt(), ExecuteTruncateGuts(), gin_clean_pending_list(), heap_force_common(), MergeAttributes(), movedb(), OperatorCreate(), ProcedureCreate(), PublicationAddTables(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForPolicy(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackOwnsRelation(), RangeVarGetAndCheckCreationNamespace(), ReindexMultipleTables(), RemoveObjects(), renameatt_check(), RenameDatabase(), RenameSchema(), RenameTableSpace(), RenameType(), RI_Initial_Check(), user_mapping_ddl_aclcheck(), vacuum_is_permitted_for_relation(), and ValidateOperatorReference().

◆ objectNamesToOids()

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

Definition at line 668 of file aclchk.c.

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

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

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

3033 {
3034  switch (objtype)
3035  {
3036  case OBJECT_COLUMN:
3037  return
3038  pg_class_aclmask(object_oid, roleid, mask, how) |
3039  pg_attribute_aclmask(object_oid, attnum, roleid, mask, how);
3040  case OBJECT_TABLE:
3041  case OBJECT_SEQUENCE:
3042  return pg_class_aclmask(object_oid, roleid, mask, how);
3043  case OBJECT_DATABASE:
3044  return object_aclmask(DatabaseRelationId, object_oid, roleid, mask, how);
3045  case OBJECT_FUNCTION:
3046  return object_aclmask(ProcedureRelationId, object_oid, roleid, mask, how);
3047  case OBJECT_LANGUAGE:
3048  return object_aclmask(LanguageRelationId, object_oid, roleid, mask, how);
3049  case OBJECT_LARGEOBJECT:
3050  return pg_largeobject_aclmask_snapshot(object_oid, roleid,
3051  mask, how, NULL);
3052  case OBJECT_PARAMETER_ACL:
3053  return pg_parameter_acl_aclmask(object_oid, roleid, mask, how);
3054  case OBJECT_SCHEMA:
3055  return object_aclmask(NamespaceRelationId, object_oid, roleid, mask, how);
3056  case OBJECT_STATISTIC_EXT:
3057  elog(ERROR, "grantable rights not supported for statistics objects");
3058  /* not reached, but keep compiler quiet */
3059  return ACL_NO_RIGHTS;
3060  case OBJECT_TABLESPACE:
3061  return object_aclmask(TableSpaceRelationId, object_oid, roleid, mask, how);
3062  case OBJECT_FDW:
3063  return object_aclmask(ForeignDataWrapperRelationId, object_oid, roleid, mask, how);
3064  case OBJECT_FOREIGN_SERVER:
3065  return object_aclmask(ForeignServerRelationId, object_oid, roleid, mask, how);
3066  case OBJECT_EVENT_TRIGGER:
3067  elog(ERROR, "grantable rights not supported for event triggers");
3068  /* not reached, but keep compiler quiet */
3069  return ACL_NO_RIGHTS;
3070  case OBJECT_TYPE:
3071  return object_aclmask(TypeRelationId, object_oid, roleid, mask, how);
3072  default:
3073  elog(ERROR, "unrecognized object type: %d",
3074  (int) objtype);
3075  /* not reached, but keep compiler quiet */
3076  return ACL_NO_RIGHTS;
3077  }
3078 }
static AclMode pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid, AclMode mask, AclMaskHow how, Snapshot snapshot)
Definition: aclchk.c:3587
static AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3199
static AclMode pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3528
static AclMode object_aclmask(Oid classid, Oid objectid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3096
AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3324

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

3922 {
3923  return pg_attribute_aclcheck_ext(table_oid, attnum, roleid, mode, NULL);
3924 }
AclResult pg_attribute_aclcheck_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode, bool *is_missing)
Definition: aclchk.c:3932

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

3964 {
3965  return pg_attribute_aclcheck_all_ext(table_oid, roleid, mode, how, NULL);
3966 }
AclResult pg_attribute_aclcheck_all_ext(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3973

References mode, and pg_attribute_aclcheck_all_ext().

Referenced by ExecCheckOneRelPerms(), ExecCheckPermissionsModified(), has_any_column_privilege_id_name(), has_any_column_privilege_name(), has_any_column_privilege_name_name(), and statext_is_compatible_clause().

◆ pg_attribute_aclcheck_all_ext()

AclResult pg_attribute_aclcheck_all_ext ( Oid  table_oid,
Oid  roleid,
AclMode  mode,
AclMaskHow  how,
bool is_missing 
)

Definition at line 3973 of file aclchk.c.

3976 {
3977  AclResult result;
3978  HeapTuple classTuple;
3979  Form_pg_class classForm;
3980  Oid ownerId;
3981  AttrNumber nattrs;
3982  AttrNumber curr_att;
3983 
3984  /*
3985  * Must fetch pg_class row to get owner ID and number of attributes.
3986  */
3987  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3988  if (!HeapTupleIsValid(classTuple))
3989  {
3990  if (is_missing != NULL)
3991  {
3992  /* return "no privileges" instead of throwing an error */
3993  *is_missing = true;
3994  return ACLCHECK_NO_PRIV;
3995  }
3996  else
3997  ereport(ERROR,
3999  errmsg("relation with OID %u does not exist",
4000  table_oid)));
4001  }
4002  classForm = (Form_pg_class) GETSTRUCT(classTuple);
4003 
4004  ownerId = classForm->relowner;
4005  nattrs = classForm->relnatts;
4006 
4007  ReleaseSysCache(classTuple);
4008 
4009  /*
4010  * Initialize result in case there are no non-dropped columns. We want to
4011  * report failure in such cases for either value of 'how'.
4012  */
4013  result = ACLCHECK_NO_PRIV;
4014 
4015  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4016  {
4017  HeapTuple attTuple;
4018  Datum aclDatum;
4019  bool isNull;
4020  Acl *acl;
4021  AclMode attmask;
4022 
4023  attTuple = SearchSysCache2(ATTNUM,
4024  ObjectIdGetDatum(table_oid),
4025  Int16GetDatum(curr_att));
4026 
4027  /*
4028  * Lookup failure probably indicates that the table was just dropped,
4029  * but we'll treat it the same as a dropped column rather than
4030  * throwing error.
4031  */
4032  if (!HeapTupleIsValid(attTuple))
4033  continue;
4034 
4035  /* ignore dropped columns */
4036  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4037  {
4038  ReleaseSysCache(attTuple);
4039  continue;
4040  }
4041 
4042  aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
4043  &isNull);
4044 
4045  /*
4046  * Here we hard-wire knowledge that the default ACL for a column
4047  * grants no privileges, so that we can fall out quickly in the very
4048  * common case where attacl is null.
4049  */
4050  if (isNull)
4051  attmask = 0;
4052  else
4053  {
4054  /* detoast column's ACL if necessary */
4055  acl = DatumGetAclP(aclDatum);
4056 
4057  attmask = aclmask(acl, roleid, ownerId, mode, ACLMASK_ANY);
4058 
4059  /* if we have a detoasted copy, free it */
4060  if ((Pointer) acl != DatumGetPointer(aclDatum))
4061  pfree(acl);
4062  }
4063 
4064  ReleaseSysCache(attTuple);
4065 
4066  if (attmask != 0)
4067  {
4068  result = ACLCHECK_OK;
4069  if (how == ACLMASK_ANY)
4070  break; /* succeed on any success */
4071  }
4072  else
4073  {
4074  result = ACLCHECK_NO_PRIV;
4075  if (how == ACLMASK_ALL)
4076  break; /* fail on any failure */
4077  }
4078  }
4079 
4080  return result;
4081 }
AclResult
Definition: acl.h:182
@ ACLMASK_ALL
Definition: acl.h:176
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:78

References ACLCHECK_NO_PRIV, ACLCHECK_OK, aclmask(), ACLMASK_ALL, ACLMASK_ANY, DatumGetAclP, DatumGetPointer(), ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum(), mode, ObjectIdGetDatum(), pfree(), ReleaseSysCache(), SearchSysCache1(), SearchSysCache2(), and SysCacheGetAttr().

Referenced by has_any_column_privilege_id(), has_any_column_privilege_id_id(), has_any_column_privilege_name_id(), and pg_attribute_aclcheck_all().

◆ pg_attribute_aclcheck_ext()

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

Definition at line 3932 of file aclchk.c.

3934 {
3935  if (pg_attribute_aclmask_ext(table_oid, attnum, roleid, mode,
3936  ACLMASK_ANY, is_missing) != 0)
3937  return ACLCHECK_OK;
3938  else
3939  return ACLCHECK_NO_PRIV;
3940 }
static AclMode pg_attribute_aclmask_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3210

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

3201 {
3202  return pg_attribute_aclmask_ext(table_oid, attnum, roleid,
3203  mask, how, NULL);
3204 }

References attnum, and pg_attribute_aclmask_ext().

Referenced by pg_aclmask().

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

3212 {
3213  AclMode result;
3214  HeapTuple classTuple;
3215  HeapTuple attTuple;
3216  Form_pg_class classForm;
3217  Form_pg_attribute attributeForm;
3218  Datum aclDatum;
3219  bool isNull;
3220  Acl *acl;
3221  Oid ownerId;
3222 
3223  /*
3224  * First, get the column's ACL from its pg_attribute entry
3225  */
3226  attTuple = SearchSysCache2(ATTNUM,
3227  ObjectIdGetDatum(table_oid),
3229  if (!HeapTupleIsValid(attTuple))
3230  {
3231  if (is_missing != NULL)
3232  {
3233  /* return "no privileges" instead of throwing an error */
3234  *is_missing = true;
3235  return 0;
3236  }
3237  else
3238  ereport(ERROR,
3239  (errcode(ERRCODE_UNDEFINED_COLUMN),
3240  errmsg("attribute %d of relation with OID %u does not exist",
3241  attnum, table_oid)));
3242  }
3243 
3244  attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
3245 
3246  /* Check dropped columns, too */
3247  if (attributeForm->attisdropped)
3248  {
3249  if (is_missing != NULL)
3250  {
3251  /* return "no privileges" instead of throwing an error */
3252  *is_missing = true;
3253  ReleaseSysCache(attTuple);
3254  return 0;
3255  }
3256  else
3257  ereport(ERROR,
3258  (errcode(ERRCODE_UNDEFINED_COLUMN),
3259  errmsg("attribute %d of relation with OID %u does not exist",
3260  attnum, table_oid)));
3261  }
3262 
3263  aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
3264  &isNull);
3265 
3266  /*
3267  * Here we hard-wire knowledge that the default ACL for a column grants no
3268  * privileges, so that we can fall out quickly in the very common case
3269  * where attacl is null.
3270  */
3271  if (isNull)
3272  {
3273  ReleaseSysCache(attTuple);
3274  return 0;
3275  }
3276 
3277  /*
3278  * Must get the relation's ownerId from pg_class. Since we already found
3279  * a pg_attribute entry, the only likely reason for this to fail is that a
3280  * concurrent DROP of the relation committed since then (which could only
3281  * happen if we don't have lock on the relation). Treat that similarly to
3282  * not finding the attribute entry.
3283  */
3284  classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3285  if (!HeapTupleIsValid(classTuple))
3286  {
3287  ReleaseSysCache(attTuple);
3288  if (is_missing != NULL)
3289  {
3290  /* return "no privileges" instead of throwing an error */
3291  *is_missing = true;
3292  return 0;
3293  }
3294  else
3295  ereport(ERROR,
3297  errmsg("relation with OID %u does not exist",
3298  table_oid)));
3299  }
3300  classForm = (Form_pg_class) GETSTRUCT(classTuple);
3301 
3302  ownerId = classForm->relowner;
3303 
3304  ReleaseSysCache(classTuple);
3305 
3306  /* detoast column's ACL if necessary */
3307  acl = DatumGetAclP(aclDatum);
3308 
3309  result = aclmask(acl, roleid, ownerId, mask, how);
3310 
3311  /* if we have a detoasted copy, free it */
3312  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3313  pfree(acl);
3314 
3315  ReleaseSysCache(attTuple);
3316 
3317  return result;
3318 }

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

Referenced by pg_attribute_aclcheck_ext(), and pg_attribute_aclmask().

◆ pg_class_aclcheck()

◆ pg_class_aclcheck_ext()

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

Definition at line 4101 of file aclchk.c.

4103 {
4104  if (pg_class_aclmask_ext(table_oid, roleid, mode,
4105  ACLMASK_ANY, is_missing) != 0)
4106  return ACLCHECK_OK;
4107  else
4108  return ACLCHECK_NO_PRIV;
4109 }
static AclMode pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how, bool *is_missing)
Definition: aclchk.c:3334

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

Referenced by column_privilege_check(), has_any_column_privilege_id(), has_any_column_privilege_id_id(), has_any_column_privilege_name_id(), has_sequence_privilege_id(), has_sequence_privilege_id_id(), has_sequence_privilege_name_id(), has_table_privilege_id(), has_table_privilege_id_id(), has_table_privilege_name_id(), and pg_class_aclcheck().

◆ pg_class_aclmask()

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

Definition at line 3324 of file aclchk.c.

3326 {
3327  return pg_class_aclmask_ext(table_oid, roleid, mask, how, NULL);
3328 }

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

3336 {
3337  AclMode result;
3338  HeapTuple tuple;
3339  Form_pg_class classForm;
3340  Datum aclDatum;
3341  bool isNull;
3342  Acl *acl;
3343  Oid ownerId;
3344 
3345  /*
3346  * Must get the relation's tuple from pg_class
3347  */
3348  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
3349  if (!HeapTupleIsValid(tuple))
3350  {
3351  if (is_missing != NULL)
3352  {
3353  /* return "no privileges" instead of throwing an error */
3354  *is_missing = true;
3355  return 0;
3356  }
3357  else
3358  ereport(ERROR,
3360  errmsg("relation with OID %u does not exist",
3361  table_oid)));
3362  }
3363 
3364  classForm = (Form_pg_class) GETSTRUCT(tuple);
3365 
3366  /*
3367  * Deny anyone permission to update a system catalog unless
3368  * pg_authid.rolsuper is set.
3369  *
3370  * As of 7.4 we have some updatable system views; those shouldn't be
3371  * protected in this way. Assume the view rules can take care of
3372  * themselves. ACL_USAGE is if we ever have system sequences.
3373  */
3374  if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
3375  IsSystemClass(table_oid, classForm) &&
3376  classForm->relkind != RELKIND_VIEW &&
3377  !superuser_arg(roleid))
3379 
3380  /*
3381  * Otherwise, superusers bypass all permission-checking.
3382  */
3383  if (superuser_arg(roleid))
3384  {
3385  ReleaseSysCache(tuple);
3386  return mask;
3387  }
3388 
3389  /*
3390  * Normal case: get the relation's ACL from pg_class
3391  */
3392  ownerId = classForm->relowner;
3393 
3394  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
3395  &isNull);
3396  if (isNull)
3397  {
3398  /* No ACL, so build default ACL */
3399  switch (classForm->relkind)
3400  {
3401  case RELKIND_SEQUENCE:
3402  acl = acldefault(OBJECT_SEQUENCE, ownerId);
3403  break;
3404  default:
3405  acl = acldefault(OBJECT_TABLE, ownerId);
3406  break;
3407  }
3408  aclDatum = (Datum) 0;
3409  }
3410  else
3411  {
3412  /* detoast rel's ACL if necessary */
3413  acl = DatumGetAclP(aclDatum);
3414  }
3415 
3416  result = aclmask(acl, roleid, ownerId, mask, how);
3417 
3418  /* if we have a detoasted copy, free it */
3419  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3420  pfree(acl);
3421 
3422  ReleaseSysCache(tuple);
3423 
3424  /*
3425  * Check if ACL_SELECT is being checked and, if so, and not set already as
3426  * part of the result, then check if the user is a member of the
3427  * pg_read_all_data role, which allows read access to all relations.
3428  */
3429  if (mask & ACL_SELECT && !(result & ACL_SELECT) &&
3430  has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA))
3431  result |= ACL_SELECT;
3432 
3433  /*
3434  * Check if ACL_INSERT, ACL_UPDATE, or ACL_DELETE is being checked and, if
3435  * so, and not set already as part of the result, then check if the user
3436  * is a member of the pg_write_all_data role, which allows
3437  * INSERT/UPDATE/DELETE access to all relations (except system catalogs,
3438  * which requires superuser, see above).
3439  */
3440  if (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE) &&
3441  !(result & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
3442  has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA))
3443  result |= (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE));
3444 
3445  /*
3446  * Check if ACL_MAINTAIN is being checked and, if so, and not already set
3447  * as part of the result, then check if the user is a member of the
3448  * pg_maintain role, which allows VACUUM, ANALYZE, CLUSTER, REFRESH
3449  * MATERIALIZED VIEW, and REINDEX on all relations.
3450  */
3451  if (mask & ACL_MAINTAIN &&
3452  !(result & ACL_MAINTAIN) &&
3453  has_privs_of_role(roleid, ROLE_PG_MAINTAIN))
3454  result |= ACL_MAINTAIN;
3455 
3456  return result;
3457 }
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:85
#define ACL_DELETE
Definition: parsenodes.h:79
#define ACL_MAINTAIN
Definition: parsenodes.h:90
#define ACL_USAGE
Definition: parsenodes.h:84
#define ACL_INSERT
Definition: parsenodes.h:76
#define ACL_UPDATE
Definition: parsenodes.h:78
#define ACL_TRUNCATE
Definition: parsenodes.h:80

References ACL_DELETE, ACL_INSERT, ACL_MAINTAIN, 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(), 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 4128 of file aclchk.c.

4130 {
4131  if (pg_largeobject_aclmask_snapshot(lobj_oid, roleid, mode,
4132  ACLMASK_ANY, snapshot) != 0)
4133  return ACLCHECK_OK;
4134  else
4135  return ACLCHECK_NO_PRIV;
4136 }

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

Referenced by 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 3587 of file aclchk.c.

3590 {
3591  AclMode result;
3592  Relation pg_lo_meta;
3593  ScanKeyData entry[1];
3594  SysScanDesc scan;
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  * Get the largeobject's ACL from pg_largeobject_metadata
3607  */
3608  pg_lo_meta = table_open(LargeObjectMetadataRelationId,
3609  AccessShareLock);
3610 
3611  ScanKeyInit(&entry[0],
3612  Anum_pg_largeobject_metadata_oid,
3613  BTEqualStrategyNumber, F_OIDEQ,
3614  ObjectIdGetDatum(lobj_oid));
3615 
3616  scan = systable_beginscan(pg_lo_meta,
3617  LargeObjectMetadataOidIndexId, true,
3618  snapshot, 1, entry);
3619 
3620  tuple = systable_getnext(scan);
3621  if (!HeapTupleIsValid(tuple))
3622  ereport(ERROR,
3623  (errcode(ERRCODE_UNDEFINED_OBJECT),
3624  errmsg("large object %u does not exist", lobj_oid)));
3625 
3626  ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
3627 
3628  aclDatum = heap_getattr(tuple, Anum_pg_largeobject_metadata_lomacl,
3629  RelationGetDescr(pg_lo_meta), &isNull);
3630 
3631  if (isNull)
3632  {
3633  /* No ACL, so build default ACL */
3634  acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
3635  aclDatum = (Datum) 0;
3636  }
3637  else
3638  {
3639  /* detoast ACL if necessary */
3640  acl = DatumGetAclP(aclDatum);
3641  }
3642 
3643  result = aclmask(acl, roleid, ownerId, mask, how);
3644 
3645  /* if we have a detoasted copy, free it */
3646  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3647  pfree(acl);
3648 
3649  systable_endscan(scan);
3650 
3651  table_close(pg_lo_meta, AccessShareLock);
3652 
3653  return result;
3654 }

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

static AclMode pg_namespace_aclmask_ext ( Oid  nsp_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how,
bool is_missing 
)
static

Definition at line 3660 of file aclchk.c.

3663 {
3664  AclMode result;
3665  HeapTuple tuple;
3666  Datum aclDatum;
3667  bool isNull;
3668  Acl *acl;
3669  Oid ownerId;
3670 
3671  /* Superusers bypass all permission checking. */
3672  if (superuser_arg(roleid))
3673  return mask;
3674 
3675  /*
3676  * If we have been assigned this namespace as a temp namespace, check to
3677  * make sure we have CREATE TEMP permission on the database, and if so act
3678  * as though we have all standard (but not GRANT OPTION) permissions on
3679  * the namespace. If we don't have CREATE TEMP, act as though we have
3680  * only USAGE (and not CREATE) rights.
3681  *
3682  * This may seem redundant given the check in InitTempTableNamespace, but
3683  * it really isn't since current user ID may have changed since then. The
3684  * upshot of this behavior is that a SECURITY DEFINER function can create
3685  * temp tables that can then be accessed (if permission is granted) by
3686  * code in the same session that doesn't have permissions to create temp
3687  * tables.
3688  *
3689  * XXX Would it be safe to ereport a special error message as
3690  * InitTempTableNamespace does? Returning zero here means we'll get a
3691  * generic "permission denied for schema pg_temp_N" message, which is not
3692  * remarkably user-friendly.
3693  */
3694  if (isTempNamespace(nsp_oid))
3695  {
3696  if (object_aclcheck_ext(DatabaseRelationId, MyDatabaseId, roleid,
3697  ACL_CREATE_TEMP, is_missing) == ACLCHECK_OK)
3698  return mask & ACL_ALL_RIGHTS_SCHEMA;
3699  else
3700  return mask & ACL_USAGE;
3701  }
3702 
3703  /*
3704  * Get the schema's ACL from pg_namespace
3705  */
3706  tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
3707  if (!HeapTupleIsValid(tuple))
3708  {
3709  if (is_missing != NULL)
3710  {
3711  /* return "no privileges" instead of throwing an error */
3712  *is_missing = true;
3713  return 0;
3714  }
3715  else
3716  ereport(ERROR,
3717  (errcode(ERRCODE_UNDEFINED_SCHEMA),
3718  errmsg("schema with OID %u does not exist", nsp_oid)));
3719  }
3720 
3721  ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
3722 
3723  aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspacl,
3724  &isNull);
3725  if (isNull)
3726  {
3727  /* No ACL, so build default ACL */
3728  acl = acldefault(OBJECT_SCHEMA, ownerId);
3729  aclDatum = (Datum) 0;
3730  }
3731  else
3732  {
3733  /* detoast ACL if necessary */
3734  acl = DatumGetAclP(aclDatum);
3735  }
3736 
3737  result = aclmask(acl, roleid, ownerId, mask, how);
3738 
3739  /* if we have a detoasted copy, free it */
3740  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3741  pfree(acl);
3742 
3743  ReleaseSysCache(tuple);
3744 
3745  /*
3746  * Check if ACL_USAGE is being checked and, if so, and not set already as
3747  * part of the result, then check if the user is a member of the
3748  * pg_read_all_data or pg_write_all_data roles, which allow usage access
3749  * to all schemas.
3750  */
3751  if (mask & ACL_USAGE && !(result & ACL_USAGE) &&
3752  (has_privs_of_role(roleid, ROLE_PG_READ_ALL_DATA) ||
3753  has_privs_of_role(roleid, ROLE_PG_WRITE_ALL_DATA)))
3754  result |= ACL_USAGE;
3755  return result;
3756 }
Oid MyDatabaseId
Definition: globals.c:92
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3634
#define ACL_CREATE_TEMP
Definition: parsenodes.h:86
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:52

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, object_aclcheck_ext(), OBJECT_SCHEMA, ObjectIdGetDatum(), pfree(), ReleaseSysCache(), SearchSysCache1(), superuser_arg(), and SysCacheGetAttr().

Referenced by object_aclmask_ext().

◆ pg_parameter_acl_aclmask()

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

Definition at line 3528 of file aclchk.c.

3529 {
3530  AclMode result;
3531  HeapTuple tuple;
3532  Datum aclDatum;
3533  bool isNull;
3534  Acl *acl;
3535 
3536  /* Superusers bypass all permission checking. */
3537  if (superuser_arg(roleid))
3538  return mask;
3539 
3540  /* Get the ACL from pg_parameter_acl */
3541  tuple = SearchSysCache1(PARAMETERACLOID, ObjectIdGetDatum(acl_oid));
3542  if (!HeapTupleIsValid(tuple))
3543  ereport(ERROR,
3544  (errcode(ERRCODE_UNDEFINED_OBJECT),
3545  errmsg("parameter ACL with OID %u does not exist",
3546  acl_oid)));
3547 
3548  aclDatum = SysCacheGetAttr(PARAMETERACLOID, tuple,
3549  Anum_pg_parameter_acl_paracl,
3550  &isNull);
3551  if (isNull)
3552  {
3553  /* No ACL, so build default ACL */
3554  acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
3555  aclDatum = (Datum) 0;
3556  }
3557  else
3558  {
3559  /* detoast ACL if necessary */
3560  acl = DatumGetAclP(aclDatum);
3561  }
3562 
3563  result = aclmask(acl, roleid, BOOTSTRAP_SUPERUSERID, mask, how);
3564 
3565  /* if we have a detoasted copy, free it */
3566  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3567  pfree(acl);
3568 
3569  ReleaseSysCache(tuple);
3570 
3571  return result;
3572 }

References acldefault(), aclmask(), DatumGetAclP, DatumGetPointer(), ereport, errcode(), errmsg(), ERROR, HeapTupleIsValid, OBJECT_PARAMETER_ACL, ObjectIdGetDatum(), 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 4116 of file aclchk.c.

4117 {
4118  if (pg_parameter_aclmask(name, roleid, mode, ACLMASK_ANY) != 0)
4119  return ACLCHECK_OK;
4120  else
4121  return ACLCHECK_NO_PRIV;
4122 }
static AclMode pg_parameter_aclmask(const char *name, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3464
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_with_handle(), 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 3464 of file aclchk.c.

3465 {
3466  AclMode result;
3467  char *parname;
3468  text *partext;
3469  HeapTuple tuple;
3470 
3471  /* Superusers bypass all permission checking. */
3472  if (superuser_arg(roleid))
3473  return mask;
3474 
3475  /* Convert name to the form it should have in pg_parameter_acl... */
3477  partext = cstring_to_text(parname);
3478 
3479  /* ... and look it up */
3480  tuple = SearchSysCache1(PARAMETERACLNAME, PointerGetDatum(partext));
3481 
3482  if (!HeapTupleIsValid(tuple))
3483  {
3484  /* If no entry, GUC has no permissions for non-superusers */
3485  result = ACL_NO_RIGHTS;
3486  }
3487  else
3488  {
3489  Datum aclDatum;
3490  bool isNull;
3491  Acl *acl;
3492 
3493  aclDatum = SysCacheGetAttr(PARAMETERACLNAME, tuple,
3494  Anum_pg_parameter_acl_paracl,
3495  &isNull);
3496  if (isNull)
3497  {
3498  /* No ACL, so build default ACL */
3499  acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
3500  aclDatum = (Datum) 0;
3501  }
3502  else
3503  {
3504  /* detoast ACL if necessary */
3505  acl = DatumGetAclP(aclDatum);
3506  }
3507 
3508  result = aclmask(acl, roleid, BOOTSTRAP_SUPERUSERID, mask, how);
3509 
3510  /* if we have a detoasted copy, free it */
3511  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3512  pfree(acl);
3513 
3514  ReleaseSysCache(tuple);
3515  }
3516 
3517  pfree(parname);
3518  pfree(partext);
3519 
3520  return result;
3521 }
char * convert_GUC_name_for_parameter_acl(const char *name)
Definition: guc.c:1373
Definition: c.h:687
text * cstring_to_text(const char *s)
Definition: varlena.c:184

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

Referenced by pg_parameter_aclcheck().

◆ pg_type_aclmask_ext()

static AclMode pg_type_aclmask_ext ( Oid  type_oid,
Oid  roleid,
AclMode  mask,
AclMaskHow  how,
bool is_missing 
)
static

Definition at line 3762 of file aclchk.c.

3764 {
3765  AclMode result;
3766  HeapTuple tuple;
3767  Form_pg_type typeForm;
3768  Datum aclDatum;
3769  bool isNull;
3770  Acl *acl;
3771  Oid ownerId;
3772 
3773  /* Bypass permission checks for superusers */
3774  if (superuser_arg(roleid))
3775  return mask;
3776 
3777  /*
3778  * Must get the type's tuple from pg_type
3779  */
3780  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
3781  if (!HeapTupleIsValid(tuple))
3782  {
3783  if (is_missing != NULL)
3784  {
3785  /* return "no privileges" instead of throwing an error */
3786  *is_missing = true;
3787  return 0;
3788  }
3789  else
3790  ereport(ERROR,
3791  (errcode(ERRCODE_UNDEFINED_OBJECT),
3792  errmsg("type with OID %u does not exist",
3793  type_oid)));
3794  }
3795  typeForm = (Form_pg_type) GETSTRUCT(tuple);
3796 
3797  /*
3798  * "True" array types don't manage permissions of their own; consult the
3799  * element type instead.
3800  */
3801  if (IsTrueArrayType(typeForm))
3802  {
3803  Oid elttype_oid = typeForm->typelem;
3804 
3805  ReleaseSysCache(tuple);
3806 
3807  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(elttype_oid));
3808  if (!HeapTupleIsValid(tuple))
3809  {
3810  if (is_missing != NULL)
3811  {
3812  /* return "no privileges" instead of throwing an error */
3813  *is_missing = true;
3814  return 0;
3815  }
3816  else
3817  ereport(ERROR,
3818  (errcode(ERRCODE_UNDEFINED_OBJECT),
3819  errmsg("type with OID %u does not exist",
3820  elttype_oid)));
3821  }
3822  typeForm = (Form_pg_type) GETSTRUCT(tuple);
3823  }
3824 
3825  /*
3826  * Likewise, multirange types don't manage their own permissions; consult
3827  * the associated range type. (Note we must do this after the array step
3828  * to get the right answer for arrays of multiranges.)
3829  */
3830  if (typeForm->typtype == TYPTYPE_MULTIRANGE)
3831  {
3832  Oid rangetype = get_multirange_range(typeForm->oid);
3833 
3834  ReleaseSysCache(tuple);
3835 
3836  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rangetype));
3837  if (!HeapTupleIsValid(tuple))
3838  {
3839  if (is_missing != NULL)
3840  {
3841  /* return "no privileges" instead of throwing an error */
3842  *is_missing = true;
3843  return 0;
3844  }
3845  else
3846  ereport(ERROR,
3847  (errcode(ERRCODE_UNDEFINED_OBJECT),
3848  errmsg("type with OID %u does not exist",
3849  rangetype)));
3850  }
3851  typeForm = (Form_pg_type) GETSTRUCT(tuple);
3852  }
3853 
3854  /*
3855  * Now get the type's owner and ACL from the tuple
3856  */
3857  ownerId = typeForm->typowner;
3858 
3859  aclDatum = SysCacheGetAttr(TYPEOID, tuple,
3860  Anum_pg_type_typacl, &isNull);
3861  if (isNull)
3862  {
3863  /* No ACL, so build default ACL */
3864  acl = acldefault(OBJECT_TYPE, ownerId);
3865  aclDatum = (Datum) 0;
3866  }
3867  else
3868  {
3869  /* detoast rel's ACL if necessary */
3870  acl = DatumGetAclP(aclDatum);
3871  }
3872 
3873  result = aclmask(acl, roleid, ownerId, mask, how);
3874 
3875  /* if we have a detoasted copy, free it */
3876  if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
3877  pfree(acl);
3878 
3879  ReleaseSysCache(tuple);
3880 
3881  return result;
3882 }
Oid get_multirange_range(Oid multirangeOid)
Definition: lsyscache.c:3483

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

Referenced by object_aclmask_ext().

◆ privilege_to_string()

static const char * privilege_to_string ( AclMode  privilege)
static

Definition at line 2653 of file aclchk.c.

2654 {
2655  switch (privilege)
2656  {
2657  case ACL_INSERT:
2658  return "INSERT";
2659  case ACL_SELECT:
2660  return "SELECT";
2661  case ACL_UPDATE:
2662  return "UPDATE";
2663  case ACL_DELETE:
2664  return "DELETE";
2665  case ACL_TRUNCATE:
2666  return "TRUNCATE";
2667  case ACL_REFERENCES:
2668  return "REFERENCES";
2669  case ACL_TRIGGER:
2670  return "TRIGGER";
2671  case ACL_EXECUTE:
2672  return "EXECUTE";
2673  case ACL_USAGE:
2674  return "USAGE";
2675  case ACL_CREATE:
2676  return "CREATE";
2677  case ACL_CREATE_TEMP:
2678  return "TEMP";
2679  case ACL_CONNECT:
2680  return "CONNECT";
2681  case ACL_SET:
2682  return "SET";
2683  case ACL_ALTER_SYSTEM:
2684  return "ALTER SYSTEM";
2685  case ACL_MAINTAIN:
2686  return "MAINTAIN";
2687  default:
2688  elog(ERROR, "unrecognized privilege: %d", (int) privilege);
2689  }
2690  return NULL; /* appease compiler */
2691 }
#define ACL_SET
Definition: parsenodes.h:88
#define ACL_CONNECT
Definition: parsenodes.h:87
#define ACL_ALTER_SYSTEM
Definition: parsenodes.h:89
#define ACL_REFERENCES
Definition: parsenodes.h:81
#define ACL_EXECUTE
Definition: parsenodes.h:83
#define ACL_CREATE
Definition: parsenodes.h:85
#define ACL_TRIGGER
Definition: parsenodes.h:82

References ACL_ALTER_SYSTEM, ACL_CONNECT, ACL_CREATE, ACL_CREATE_TEMP, ACL_DELETE, ACL_EXECUTE, ACL_INSERT, ACL_MAINTAIN, 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 4377 of file aclchk.c.

4379 {
4380  int nmembers;
4381  Oid *members;
4382 
4383  /* Nothing to do if ACL is defaulted */
4384  if (acl == NULL)
4385  return;
4386 
4387  /* Extract roles mentioned in ACL */
4388  nmembers = aclmembers(acl, &members);
4389 
4390  /* Update the shared dependency ACL info */
4391  updateAclDependencies(classId, objectId, objsubId,
4392  ownerId,
4393  0, NULL,
4394  nmembers, members);
4395 }

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

4652 {
4653  /*
4654  * Generally, we only record the initial privileges when an extension is
4655  * being created, but because we don't actually use CREATE EXTENSION
4656  * during binary upgrades with pg_upgrade, there is a variable to let us
4657  * know that the GRANT and REVOKE statements being issued, while this
4658  * variable is true, are for the initial privileges of the extension
4659  * object and therefore we need to record them.
4660  */
4662  return;
4663 
4664  recordExtensionInitPrivWorker(objoid, classoid, objsubid, new_acl);
4665 }
static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
Definition: aclchk.c:4680
bool binary_upgrade_record_init_privs
Definition: aclchk.c:109
bool creating_extension
Definition: extension.c:71

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

4682 {
4683  Relation relation;
4684  ScanKeyData key[3];
4685  SysScanDesc scan;
4686  HeapTuple tuple;
4687  HeapTuple oldtuple;
4688  int noldmembers;
4689  int nnewmembers;
4690  Oid *oldmembers;
4691  Oid *newmembers;
4692 
4693  /* We'll need the role membership of the new ACL. */
4694  nnewmembers = aclmembers(new_acl, &newmembers);
4695 
4696  /* Search pg_init_privs for an existing entry. */
4697  relation = table_open(InitPrivsRelationId, RowExclusiveLock);
4698 
4699  ScanKeyInit(&key[0],
4700  Anum_pg_init_privs_objoid,
4701  BTEqualStrategyNumber, F_OIDEQ,
4702  ObjectIdGetDatum(objoid));
4703  ScanKeyInit(&key[1],
4704  Anum_pg_init_privs_classoid,
4705  BTEqualStrategyNumber, F_OIDEQ,
4706  ObjectIdGetDatum(classoid));
4707  ScanKeyInit(&key[2],
4708  Anum_pg_init_privs_objsubid,
4709  BTEqualStrategyNumber, F_INT4EQ,
4710  Int32GetDatum(objsubid));
4711 
4712  scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
4713  NULL, 3, key);
4714 
4715  /* There should exist only one entry or none. */
4716  oldtuple = systable_getnext(scan);
4717 
4718  /* If we find an entry, update it with the latest ACL. */
4719  if (HeapTupleIsValid(oldtuple))
4720  {
4721  Datum values[Natts_pg_init_privs] = {0};
4722  bool nulls[Natts_pg_init_privs] = {0};
4723  bool replace[Natts_pg_init_privs] = {0};
4724  Datum oldAclDatum;
4725  bool isNull;
4726  Acl *old_acl;
4727 
4728  /* Update pg_shdepend for roles mentioned in the old/new ACLs. */
4729  oldAclDatum = heap_getattr(oldtuple, Anum_pg_init_privs_initprivs,
4730  RelationGetDescr(relation), &isNull);
4731  Assert(!isNull);
4732  old_acl = DatumGetAclP(oldAclDatum);
4733  noldmembers = aclmembers(old_acl, &oldmembers);
4734 
4735  updateInitAclDependencies(classoid, objoid, objsubid,
4736  noldmembers, oldmembers,
4737  nnewmembers, newmembers);
4738 
4739  /* If we have a new ACL to set, then update the row with it. */
4740  if (new_acl && ACL_NUM(new_acl) != 0)
4741  {
4742  values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
4743  replace[Anum_pg_init_privs_initprivs - 1] = true;
4744 
4745  oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation),
4746  values, nulls, replace);
4747 
4748  CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple);
4749  }
4750  else
4751  {
4752  /* new_acl is NULL/empty, so delete the entry we found. */
4753  CatalogTupleDelete(relation, &oldtuple->t_self);
4754  }
4755  }
4756  else
4757  {
4758  Datum values[Natts_pg_init_privs] = {0};
4759  bool nulls[Natts_pg_init_privs] = {0};
4760 
4761  /*
4762  * Only add a new entry if the new ACL is non-NULL.
4763  *
4764  * If we are passed in a NULL ACL and no entry exists, we can just
4765  * fall through and do nothing.
4766  */
4767  if (new_acl && ACL_NUM(new_acl) != 0)
4768  {
4769  /* No entry found, so add it. */
4770  values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
4771  values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
4772  values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
4773 
4774  /* This function only handles initial privileges of extensions */
4775  values[Anum_pg_init_privs_privtype - 1] =
4777 
4778  values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
4779 
4780  tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
4781 
4782  CatalogTupleInsert(relation, tuple);
4783 
4784  /* Update pg_shdepend, too. */
4785  noldmembers = 0;
4786  oldmembers = NULL;
4787 
4788  updateInitAclDependencies(classoid, objoid, objsubid,
4789  noldmembers, oldmembers,
4790  nnewmembers, newmembers);
4791  }
4792  }
4793 
4794  systable_endscan(scan);
4795 
4796  /* prevent error when processing objects multiple times */
4798 
4799  table_close(relation, RowExclusiveLock);
4800 }
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
@ INITPRIVS_EXTENSION
Definition: pg_init_privs.h:80
void updateInitAclDependencies(Oid classId, Oid objectId, int32 objsubId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:512
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212

References ACL_NUM, aclmembers(), Assert, BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleInsert(), CatalogTupleUpdate(), CharGetDatum(), CommandCounterIncrement(), DatumGetAclP, heap_form_tuple(), heap_getattr(), 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(), updateInitAclDependencies(), and values.

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

◆ recordExtObjInitPriv()

void recordExtObjInitPriv ( Oid  objoid,
Oid  classoid 
)

Definition at line 4404 of file aclchk.c.

4405 {
4406  /*
4407  * pg_class / pg_attribute
4408  *
4409  * If this is a relation then we need to see if there are any sub-objects
4410  * (eg: columns) for it and, if so, be sure to call
4411  * recordExtensionInitPrivWorker() for each one.
4412  */
4413  if (classoid == RelationRelationId)
4414  {
4415  Form_pg_class pg_class_tuple;
4416  Datum aclDatum;
4417  bool isNull;
4418  HeapTuple tuple;
4419 
4420  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
4421  if (!HeapTupleIsValid(tuple))
4422  elog(ERROR, "cache lookup failed for relation %u", objoid);
4423  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
4424 
4425  /*
4426  * Indexes don't have permissions, neither do the pg_class rows for
4427  * composite types. (These cases are unreachable given the
4428  * restrictions in ALTER EXTENSION ADD, but let's check anyway.)
4429  */
4430  if (pg_class_tuple->relkind == RELKIND_INDEX ||
4431  pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
4432  pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
4433  {
4434  ReleaseSysCache(tuple);
4435  return;
4436  }
4437 
4438  /*
4439  * If this isn't a sequence then it's possibly going to have
4440  * column-level ACLs associated with it.
4441  */
4442  if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
4443  {
4444  AttrNumber curr_att;
4445  AttrNumber nattrs = pg_class_tuple->relnatts;
4446 
4447  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4448  {
4449  HeapTuple attTuple;
4450  Datum attaclDatum;
4451 
4452  attTuple = SearchSysCache2(ATTNUM,
4453  ObjectIdGetDatum(objoid),
4454  Int16GetDatum(curr_att));
4455 
4456  if (!HeapTupleIsValid(attTuple))
4457  continue;
4458 
4459  /* ignore dropped columns */
4460  if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
4461  {
4462  ReleaseSysCache(attTuple);
4463  continue;
4464  }
4465 
4466  attaclDatum = SysCacheGetAttr(ATTNUM, attTuple,
4467  Anum_pg_attribute_attacl,
4468  &isNull);
4469 
4470  /* no need to do anything for a NULL ACL */
4471  if (isNull)
4472  {
4473  ReleaseSysCache(attTuple);
4474  continue;
4475  }
4476 
4477  recordExtensionInitPrivWorker(objoid, classoid, curr_att,
4478  DatumGetAclP(attaclDatum));
4479 
4480  ReleaseSysCache(attTuple);
4481  }
4482  }
4483 
4484  aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
4485  &isNull);
4486 
4487  /* Add the record, if any, for the top-level object */
4488  if (!isNull)
4489  recordExtensionInitPrivWorker(objoid, classoid, 0,
4490  DatumGetAclP(aclDatum));
4491 
4492  ReleaseSysCache(tuple);
4493  }
4494  else if (classoid == LargeObjectRelationId)
4495  {
4496  /* For large objects, we must consult pg_largeobject_metadata */
4497  Datum aclDatum;
4498  bool isNull;
4499  HeapTuple tuple;
4500  ScanKeyData entry[1];
4501  SysScanDesc scan;
4502  Relation relation;
4503 
4504  /*
4505  * Note: this is dead code, given that we don't allow large objects to
4506  * be made extension members. But it seems worth carrying in case
4507  * some future caller of this function has need for it.
4508  */
4509  relation = table_open(LargeObjectMetadataRelationId, RowExclusiveLock);
4510 
4511  /* There's no syscache for pg_largeobject_metadata */
4512  ScanKeyInit(&entry[0],
4513  Anum_pg_largeobject_metadata_oid,
4514  BTEqualStrategyNumber, F_OIDEQ,
4515  ObjectIdGetDatum(objoid));
4516 
4517  scan = systable_beginscan(relation,
4518  LargeObjectMetadataOidIndexId, true,
4519  NULL, 1, entry);
4520 
4521  tuple = systable_getnext(scan);
4522  if (!HeapTupleIsValid(tuple))
4523  elog(ERROR, "could not find tuple for large object %u", objoid);
4524 
4525  aclDatum = heap_getattr(tuple,
4526  Anum_pg_largeobject_metadata_lomacl,
4527  RelationGetDescr(relation), &isNull);
4528 
4529  /* Add the record, if any, for the top-level object */
4530  if (!isNull)
4531  recordExtensionInitPrivWorker(objoid, classoid, 0,
4532  DatumGetAclP(aclDatum));
4533 
4534  systable_endscan(scan);
4535  }
4536  /* This will error on unsupported classoid. */
4537  else if (get_object_attnum_acl(classoid) != InvalidAttrNumber)
4538  {
4539  int cacheid;
4540  Datum aclDatum;
4541  bool isNull;
4542  HeapTuple tuple;
4543 
4544  cacheid = get_object_catcache_oid(classoid);
4545  tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objoid));
4546  if (!HeapTupleIsValid(tuple))
4547  elog(ERROR, "cache lookup failed for %s %u",
4548  get_object_class_descr(classoid), objoid);
4549 
4550  aclDatum = SysCacheGetAttr(cacheid, tuple,
4551  get_object_attnum_acl(classoid),
4552  &isNull);
4553 
4554  /* Add the record, if any, for the top-level object */
4555  if (!isNull)
4556  recordExtensionInitPrivWorker(objoid, classoid, 0,
4557  DatumGetAclP(aclDatum));
4558 
4559  ReleaseSysCache(tuple);
4560  }
4561 }

References 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(), RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), SearchSysCache2(), SysCacheGetAttr(), systable_beginscan(), systable_endscan(), systable_getnext(), and table_open().

Referenced by ExecAlterExtensionContentsRecurse().

◆ removeExtObjInitPriv()

void removeExtObjInitPriv ( Oid  objoid,
Oid  classoid 
)

Definition at line 4568 of file aclchk.c.

4569 {
4570  /*
4571  * If this is a relation then we need to see if there are any sub-objects
4572  * (eg: columns) for it and, if so, be sure to call
4573  * recordExtensionInitPrivWorker() for each one.
4574  */
4575  if (classoid == RelationRelationId)
4576  {
4577  Form_pg_class pg_class_tuple;
4578  HeapTuple tuple;
4579 
4580  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
4581  if (!HeapTupleIsValid(tuple))
4582  elog(ERROR, "cache lookup failed for relation %u", objoid);
4583  pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
4584 
4585  /*
4586  * Indexes don't have permissions, neither do the pg_class rows for
4587  * composite types. (These cases are unreachable given the
4588  * restrictions in ALTER EXTENSION DROP, but let's check anyway.)
4589  */
4590  if (pg_class_tuple->relkind == RELKIND_INDEX ||
4591  pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
4592  pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
4593  {
4594  ReleaseSysCache(tuple);
4595  return;
4596  }
4597 
4598  /*
4599  * If this isn't a sequence then it's possibly going to have
4600  * column-level ACLs associated with it.
4601  */
4602  if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
4603  {
4604  AttrNumber curr_att;
4605  AttrNumber nattrs = pg_class_tuple->relnatts;
4606 
4607  for (curr_att = 1; curr_att <= nattrs; curr_att++)
4608  {
4609  HeapTuple attTuple;
4610 
4611  attTuple = SearchSysCache2(ATTNUM,
4612  ObjectIdGetDatum(objoid),
4613  Int16GetDatum(curr_att));
4614 
4615  if (!HeapTupleIsValid(attTuple))
4616  continue;
4617 
4618  /* when removing, remove all entries, even dropped columns */
4619 
4620  recordExtensionInitPrivWorker(objoid, classoid, curr_att, NULL);
4621 
4622  ReleaseSysCache(attTuple);
4623  }
4624  }
4625 
4626  ReleaseSysCache(tuple);
4627  }
4628 
4629  /* Remove the record, if any, for the top-level object */
4630  recordExtensionInitPrivWorker(objoid, classoid, 0, NULL);
4631 }

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

Referenced by ExecAlterExtensionContentsRecurse().

◆ RemoveRoleFromInitPriv()

void RemoveRoleFromInitPriv ( Oid  roleid,
Oid  classid,
Oid  objid,
int32  objsubid 
)

Definition at line 4917 of file aclchk.c.

4918 {
4919  Relation rel;
4920  ScanKeyData key[3];
4921  SysScanDesc scan;
4922  HeapTuple oldtuple;
4923  int cacheid;
4924  HeapTuple objtuple;
4925  Oid ownerId;
4926  Datum oldAclDatum;
4927  bool isNull;
4928  Acl *old_acl;
4929  Acl *new_acl;
4930  HeapTuple newtuple;
4931  int noldmembers;
4932  int nnewmembers;
4933  Oid *oldmembers;
4934  Oid *newmembers;
4935 
4936  /* Search for existing pg_init_privs entry for the target object. */
4937  rel = table_open(InitPrivsRelationId, RowExclusiveLock);
4938 
4939  ScanKeyInit(&key[0],
4940  Anum_pg_init_privs_objoid,
4941  BTEqualStrategyNumber, F_OIDEQ,
4942  ObjectIdGetDatum(objid));
4943  ScanKeyInit(&key[1],
4944  Anum_pg_init_privs_classoid,
4945  BTEqualStrategyNumber, F_OIDEQ,
4946  ObjectIdGetDatum(classid));
4947  ScanKeyInit(&key[2],
4948  Anum_pg_init_privs_objsubid,
4949  BTEqualStrategyNumber, F_INT4EQ,
4950  Int32GetDatum(objsubid));
4951 
4952  scan = systable_beginscan(rel, InitPrivsObjIndexId, true,
4953  NULL, 3, key);
4954 
4955  /* There should exist only one entry or none. */
4956  oldtuple = systable_getnext(scan);
4957 
4958  if (!HeapTupleIsValid(oldtuple))
4959  {
4960  /*
4961  * Hmm, why are we here if there's no entry? But pack up and go away
4962  * quietly.
4963  */
4964  systable_endscan(scan);
4966  return;
4967  }
4968 
4969  /* Get a writable copy of the existing ACL. */
4970  oldAclDatum = heap_getattr(oldtuple, Anum_pg_init_privs_initprivs,
4971  RelationGetDescr(rel), &isNull);
4972  Assert(!isNull);
4973  old_acl = DatumGetAclPCopy(oldAclDatum);
4974 
4975  /*
4976  * We need the members of both old and new ACLs so we can correct the
4977  * shared dependency information. Collect data before
4978  * merge_acl_with_grant throws away old_acl.
4979  */
4980  noldmembers = aclmembers(old_acl, &oldmembers);
4981 
4982  /* Must find out the owner's OID the hard way. */
4983  cacheid = get_object_catcache_oid(classid);
4984  objtuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objid));
4985  if (!HeapTupleIsValid(objtuple))
4986  elog(ERROR, "cache lookup failed for %s %u",
4987  get_object_class_descr(classid), objid);
4988 
4989  ownerId = DatumGetObjectId(SysCacheGetAttrNotNull(cacheid,
4990  objtuple,
4991  get_object_attnum_owner(classid)));
4992  ReleaseSysCache(objtuple);
4993 
4994  /*
4995  * Generate new ACL. Grantor of rights is always the same as the owner.
4996  */
4997  if (old_acl != NULL)
4998  new_acl = merge_acl_with_grant(old_acl,
4999  false, /* is_grant */
5000  false, /* grant_option */
5001  DROP_RESTRICT,
5002  list_make1_oid(roleid),
5004  ownerId,
5005  ownerId);
5006  else
5007  new_acl = NULL; /* this case shouldn't happen, probably */
5008 
5009  /* If we end with an empty ACL, delete the pg_init_privs entry. */
5010  if (new_acl == NULL || ACL_NUM(new_acl) == 0)
5011  {
5012  CatalogTupleDelete(rel, &oldtuple->t_self);
5013  }
5014  else
5015  {
5016  Datum values[Natts_pg_init_privs] = {0};
5017  bool nulls[Natts_pg_init_privs] = {0};
5018  bool replaces[Natts_pg_init_privs] = {0};
5019 
5020  /* Update existing entry. */
5021  values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
5022  replaces[Anum_pg_init_privs_initprivs - 1] = true;
5023 
5024  newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel),
5025  values, nulls, replaces);
5026  CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
5027  }
5028 
5029  /*
5030  * Update the shared dependency ACL info.
5031  */
5032  nnewmembers = aclmembers(new_acl, &newmembers);
5033 
5034  updateInitAclDependencies(classid, objid, objsubid,
5035  noldmembers, oldmembers,
5036  nnewmembers, newmembers);
5037 
5038  systable_endscan(scan);
5039 
5040  /* prevent error when processing objects multiple times */
5042 
5044 }
#define ACLITEM_ALL_PRIV_BITS
Definition: acl.h:87
@ DROP_RESTRICT
Definition: parsenodes.h:2334
#define list_make1_oid(x1)
Definition: pg_list.h:242

References ACL_NUM, ACLITEM_ALL_PRIV_BITS, aclmembers(), Assert, BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, DatumGetObjectId(), DROP_RESTRICT, elog, ERROR, get_object_attnum_owner(), get_object_catcache_oid(), get_object_class_descr(), heap_getattr(), heap_modify_tuple(), HeapTupleIsValid, Int32GetDatum(), sort-test::key, list_make1_oid, merge_acl_with_grant(), ObjectIdGetDatum(), PointerGetDatum(), RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), SysCacheGetAttrNotNull(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), updateInitAclDependencies(), and values.

Referenced by shdepDropOwned().

◆ RemoveRoleFromObjectACL()

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

Definition at line 1465 of file aclchk.c.

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

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

◆ ReplaceRoleInInitPriv()

void ReplaceRoleInInitPriv ( Oid  oldroleid,
Oid  newroleid,
Oid  classid,
Oid  objid,
int32  objsubid 
)

Definition at line 4808 of file aclchk.c.

4810 {
4811  Relation rel;
4812  ScanKeyData key[3];
4813  SysScanDesc scan;
4814  HeapTuple oldtuple;
4815  Datum oldAclDatum;
4816  bool isNull;
4817  Acl *old_acl;
4818  Acl *new_acl;
4819  HeapTuple newtuple;
4820  int noldmembers;
4821  int nnewmembers;
4822  Oid *oldmembers;
4823  Oid *newmembers;
4824 
4825  /* Search for existing pg_init_privs entry for the target object. */
4826  rel = table_open(InitPrivsRelationId, RowExclusiveLock);
4827 
4828  ScanKeyInit(&key[0],
4829  Anum_pg_init_privs_objoid,
4830  BTEqualStrategyNumber, F_OIDEQ,
4831  ObjectIdGetDatum(objid));
4832  ScanKeyInit(&key[1],
4833  Anum_pg_init_privs_classoid,
4834  BTEqualStrategyNumber, F_OIDEQ,
4835  ObjectIdGetDatum(classid));
4836  ScanKeyInit(&key[2],
4837  Anum_pg_init_privs_objsubid,
4838  BTEqualStrategyNumber, F_INT4EQ,
4839  Int32GetDatum(objsubid));
4840 
4841  scan = systable_beginscan(rel, InitPrivsObjIndexId, true,
4842  NULL, 3, key);
4843 
4844  /* There should exist only one entry or none. */
4845  oldtuple = systable_getnext(scan);
4846 
4847  if (!HeapTupleIsValid(oldtuple))
4848  {
4849  /*
4850  * Hmm, why are we here if there's no entry? But pack up and go away
4851  * quietly.
4852  */
4853  systable_endscan(scan);
4855  return;
4856  }
4857 
4858  /* Get a writable copy of the existing ACL. */
4859  oldAclDatum = heap_getattr(oldtuple, Anum_pg_init_privs_initprivs,
4860  RelationGetDescr(rel), &isNull);
4861  Assert(!isNull);
4862  old_acl = DatumGetAclPCopy(oldAclDatum);
4863 
4864  /*
4865  * Generate new ACL. This usage of aclnewowner is a bit off-label when
4866  * oldroleid isn't the owner; but it does the job fine.
4867  */
4868  new_acl = aclnewowner(old_acl, oldroleid, newroleid);
4869 
4870  /*
4871  * If we end with an empty ACL, delete the pg_init_privs entry. (That
4872  * probably can't happen here, but we may as well cover the case.)
4873  */
4874  if (new_acl == NULL || ACL_NUM(new_acl) == 0)
4875  {
4876  CatalogTupleDelete(rel, &oldtuple->t_self);
4877  }
4878  else
4879  {
4880  Datum values[Natts_pg_init_privs] = {0};
4881  bool nulls[Natts_pg_init_privs] = {0};
4882  bool replaces[Natts_pg_init_privs] = {0};
4883 
4884  /* Update existing entry. */
4885  values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
4886  replaces[Anum_pg_init_privs_initprivs - 1] = true;
4887 
4888  newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel),
4889  values, nulls, replaces);
4890  CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
4891  }
4892 
4893  /*
4894  * Update the shared dependency ACL info.
4895  */
4896  noldmembers = aclmembers(old_acl, &oldmembers);
4897  nnewmembers = aclmembers(new_acl, &newmembers);
4898 
4899  updateInitAclDependencies(classid, objid, objsubid,
4900  noldmembers, oldmembers,
4901  nnewmembers, newmembers);
4902 
4903  systable_endscan(scan);
4904 
4905  /* prevent error when processing objects multiple times */
4907 
4909 }
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1102

References ACL_NUM, aclmembers(), aclnewowner(), Assert, BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleUpdate(), CommandCounterIncrement(), DatumGetAclPCopy, heap_getattr(), heap_modify_tuple(), HeapTupleIsValid, Int32GetDatum(), sort-test::key, ObjectIdGetDatum(), PointerGetDatum(), RelationGetDescr, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), updateInitAclDependencies(), and values.

Referenced by shdepReassignOwned_InitAcl().

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

244 {
245  AclMode this_privileges;
246  AclMode whole_mask;
247 
248  switch (objtype)
249  {
250  case OBJECT_COLUMN:
251  whole_mask = ACL_ALL_RIGHTS_COLUMN;
252  break;
253  case OBJECT_TABLE:
254  whole_mask = ACL_ALL_RIGHTS_RELATION;
255  break;
256  case OBJECT_SEQUENCE:
257  whole_mask = ACL_ALL_RIGHTS_SEQUENCE;
258  break;
259  case OBJECT_DATABASE:
260  whole_mask = ACL_ALL_RIGHTS_DATABASE;
261  break;
262  case OBJECT_FUNCTION:
263  whole_mask = ACL_ALL_RIGHTS_FUNCTION;
264  break;
265  case OBJECT_LANGUAGE:
266  whole_mask = ACL_ALL_RIGHTS_LANGUAGE;
267  break;
268  case OBJECT_LARGEOBJECT:
269  whole_mask = ACL_ALL_RIGHTS_LARGEOBJECT;
270  break;
271  case OBJECT_SCHEMA:
272  whole_mask = ACL_ALL_RIGHTS_SCHEMA;
273  break;
274  case OBJECT_TABLESPACE:
275  whole_mask = ACL_ALL_RIGHTS_TABLESPACE;
276  break;
277  case OBJECT_FDW:
278  whole_mask = ACL_ALL_RIGHTS_FDW;
279  break;
281  whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
282  break;
284  elog(ERROR, "grantable rights not supported for event triggers");
285  /* not reached, but keep compiler quiet */
286  return ACL_NO_RIGHTS;
287  case OBJECT_TYPE:
288  whole_mask = ACL_ALL_RIGHTS_TYPE;
289  break;
291  whole_mask = ACL_ALL_RIGHTS_PARAMETER_ACL;
292  break;
293  default:
294  elog(ERROR, "unrecognized object type: %d", objtype);
295  /* not reached, but keep compiler quiet */
296  return ACL_NO_RIGHTS;
297  }
298 
299  /*
300  * If we found no grant options, consider whether to issue a hard error.
301  * Per spec, having any privilege at all on the object will get you by
302  * here.
303  */
304  if (avail_goptions == ACL_NO_RIGHTS)
305  {
306  if (pg_aclmask(objtype, objectId, att_number, grantorId,
307  whole_mask | ACL_GRANT_OPTION_FOR(whole_mask),
309  {
310  if (objtype == OBJECT_COLUMN && colname)
311  aclcheck_error_col(ACLCHECK_NO_PRIV, objtype, objname, colname);
312  else
313  aclcheck_error(ACLCHECK_NO_PRIV, objtype, objname);
314  }
315  }
316 
317  /*
318  * Restrict the operation to what we can actually grant or revoke, and
319  * issue a warning if appropriate. (For REVOKE this isn't quite what the
320  * spec says to do: the spec seems to want a warning only if no privilege
321  * bits actually change in the ACL. In practice that behavior seems much
322  * too noisy, as well as inconsistent with the GRANT case.)
323  */
324  this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
325  if (is_grant)
326  {
327  if (this_privileges == 0)
328  {
329  if (objtype == OBJECT_COLUMN && colname)
331  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
332  errmsg("no privileges were granted for column \"%s\" of relation \"%s\"",
333  colname, objname)));
334  else
336  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
337  errmsg("no privileges were granted for \"%s\"",
338  objname)));
339  }
340  else if (!all_privs && this_privileges != privileges)
341  {
342  if (objtype == OBJECT_COLUMN && colname)
344  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
345  errmsg("not all privileges were granted for column \"%s\" of relation \"%s\"",
346  colname, objname)));
347  else
349  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
350  errmsg("not all privileges were granted for \"%s\"",
351  objname)));
352  }
353  }
354  else
355  {
356  if (this_privileges == 0)
357  {
358  if (objtype == OBJECT_COLUMN && colname)
360  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
361  errmsg("no privileges could be revoked for column \"%s\" of relation \"%s\"",
362  colname, objname)));
363  else
365  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
366  errmsg("no privileges could be revoked for \"%s\"",
367  objname)));
368  }
369  else if (!all_privs && this_privileges != privileges)
370  {
371  if (objtype == OBJECT_COLUMN && colname)
373  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
374  errmsg("not all privileges could be revoked for column \"%s\" of relation \"%s\"",
375  colname, objname)));
376  else
378  (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
379  errmsg("not all privileges could be revoked for \"%s\"",
380  objname)));
381  }
382  }
383 
384  return this_privileges;
385 }
#define ACL_OPTION_TO_PRIVS(privs)
Definition: acl.h:71
#define ACL_GRANT_OPTION_FOR(privs)
Definition: acl.h:70
void aclcheck_error_col(AclResult aclerr, ObjectType objtype, const char *objectname, const char *colname)
Definition: aclchk.c:2989
static AclMode pg_aclmask(ObjectType objtype, Oid object_oid, AttrNumber attnum, Oid roleid, AclMode mask, AclMaskHow how)
Definition: aclchk.c:3031

References ACL_ALL_RIGHTS_COLUMN, 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_GRANT_OPTION_FOR, ACL_NO_RIGHTS, ACL_OPTION_TO_PRIVS, aclcheck_error(), aclcheck_error_col(), ACLCHECK_NO_PRIV, ACLMASK_ANY, elog, ereport, errcode(), errmsg(), ERROR, OBJECT_COLUMN, OBJECT_DATABASE, OBJECT_EVENT_TRIGGER, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FUNCTION, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_PARAMETER_ACL, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TYPE, pg_aclmask(), and WARNING.

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

◆ SetDefaultACL()

static void SetDefaultACL ( InternalDefaultACL iacls)
static

Definition at line 1202 of file aclchk.c.

1203 {
1204  AclMode this_privileges = iacls->privileges;
1205  char objtype;
1206  Relation rel;
1207  HeapTuple tuple;
1208  bool isNew;
1209  Acl *def_acl;
1210  Acl *old_acl;
1211  Acl *new_acl;
1212  HeapTuple newtuple;
1213  int noldmembers;
1214  int nnewmembers;
1215  Oid *oldmembers;
1216  Oid *newmembers;
1217 
1218  rel = table_open(DefaultAclRelationId, RowExclusiveLock);
1219 
1220  /*
1221  * The default for a global entry is the hard-wired default ACL for the
1222  * particular object type. The default for non-global entries is an empty
1223  * ACL. This must be so because global entries replace the hard-wired
1224  * defaults, while others are added on.
1225  */
1226  if (!OidIsValid(iacls->nspid))
1227  def_acl = acldefault(iacls->objtype, iacls->roleid);
1228  else
1229  def_acl = make_empty_acl();
1230 
1231  /*
1232  * Convert ACL object type to pg_default_acl object type and handle
1233  * all_privs option
1234  */
1235  switch (iacls->objtype)
1236  {
1237  case OBJECT_TABLE:
1238  objtype = DEFACLOBJ_RELATION;
1239  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1240  this_privileges = ACL_ALL_RIGHTS_RELATION;
1241  break;
1242 
1243  case OBJECT_SEQUENCE:
1244  objtype = DEFACLOBJ_SEQUENCE;
1245  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1246  this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
1247  break;
1248 
1249  case OBJECT_FUNCTION:
1250  objtype = DEFACLOBJ_FUNCTION;
1251  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1252  this_privileges = ACL_ALL_RIGHTS_FUNCTION;
1253  break;
1254 
1255  case OBJECT_TYPE:
1256  objtype = DEFACLOBJ_TYPE;
1257  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1258  this_privileges = ACL_ALL_RIGHTS_TYPE;
1259  break;
1260 
1261  case OBJECT_SCHEMA:
1262  if (OidIsValid(iacls->nspid))
1263  ereport(ERROR,
1264  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1265  errmsg("cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS")));
1266  objtype = DEFACLOBJ_NAMESPACE;
1267  if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
1268  this_privileges = ACL_ALL_RIGHTS_SCHEMA;
1269  break;
1270 
1271  default:
1272  elog(ERROR, "unrecognized object type: %d",
1273  (int) iacls->objtype);
1274  objtype = 0; /* keep compiler quiet */
1275  break;
1276  }
1277 
1278  /* Search for existing row for this object type in catalog */
1279  tuple = SearchSysCache3(DEFACLROLENSPOBJ,
1280  ObjectIdGetDatum(iacls->roleid),
1281  ObjectIdGetDatum(iacls->nspid),
1282  CharGetDatum(objtype));
1283 
1284  if (HeapTupleIsValid(tuple))
1285  {
1286  Datum aclDatum;
1287  bool isNull;
1288 
1289  aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
1290  Anum_pg_default_acl_defaclacl,
1291  &isNull);
1292  if (!isNull)
1293  old_acl = DatumGetAclPCopy(aclDatum);
1294  else
1295  old_acl = NULL; /* this case shouldn't happen, probably */
1296  isNew = false;
1297  }
1298  else
1299  {
1300  old_acl = NULL;
1301  isNew = true;
1302  }
1303 
1304  if (old_acl != NULL)
1305  {
1306  /*
1307  * We need the members of both old and new ACLs so we can correct the
1308  * shared dependency information. Collect data before
1309  * merge_acl_with_grant throws away old_acl.
1310  */
1311  noldmembers = aclmembers(old_acl, &oldmembers);
1312  }
1313  else
1314  {
1315  /* If no or null entry, start with the default ACL value */
1316  old_acl = aclcopy(def_acl);
1317  /* There are no old member roles according to the catalogs */
1318  noldmembers = 0;
1319  oldmembers = NULL;
1320  }
1321 
1322  /*
1323  * Generate new ACL. Grantor of rights is always the same as the target
1324  * role.
1325  */
1326  new_acl = merge_acl_with_grant(old_acl,
1327  iacls->is_grant,
1328  iacls->grant_option,
1329  iacls->behavior,
1330  iacls->grantees,
1331  this_privileges,
1332  iacls->roleid,
1333  iacls->roleid);
1334 
1335  /*
1336  * If the result is the same as the default value, we do not need an
1337  * explicit pg_default_acl entry, and should in fact remove the entry if
1338  * it exists. Must sort both arrays to compare properly.
1339  */
1340  aclitemsort(new_acl);
1341  aclitemsort(def_acl);
1342  if (aclequal(new_acl, def_acl))
1343  {
1344  /* delete old entry, if indeed there is one */
1345  if (!isNew)
1346  {
1347  ObjectAddress myself;
1348 
1349  /*
1350  * The dependency machinery will take care of removing all
1351  * associated dependency entries. We use DROP_RESTRICT since
1352  * there shouldn't be anything depending on this entry.
1353  */
1354  myself.classId = DefaultAclRelationId;
1355  myself.objectId = ((Form_pg_default_acl) GETSTRUCT(tuple))->oid;
1356  myself.objectSubId = 0;
1357 
1358  performDeletion(&myself, DROP_RESTRICT, 0);
1359  }
1360  }
1361  else
1362  {
1363  Datum values[Natts_pg_default_acl] = {0};
1364  bool nulls[Natts_pg_default_acl] = {0};
1365  bool replaces[Natts_pg_default_acl] = {0};
1366  Oid defAclOid;
1367 
1368  if (isNew)
1369  {
1370  /* insert new entry */
1371  defAclOid = GetNewOidWithIndex(rel, DefaultAclOidIndexId,
1372  Anum_pg_default_acl_oid);
1373  values[Anum_pg_default_acl_oid - 1] = ObjectIdGetDatum(defAclOid);
1374  values[Anum_pg_default_acl_defaclrole - 1] = ObjectIdGetDatum(iacls->roleid);
1375  values[Anum_pg_default_acl_defaclnamespace - 1] = ObjectIdGetDatum(iacls->nspid);
1376  values[Anum_pg_default_acl_defaclobjtype - 1] = CharGetDatum(objtype);
1377  values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
1378 
1379  newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
1380  CatalogTupleInsert(rel, newtuple);
1381  }
1382  else
1383  {
1384  defAclOid = ((Form_pg_default_acl) GETSTRUCT(tuple))->oid;
1385 
1386  /* update existing entry */
1387  values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
1388  replaces[Anum_pg_default_acl_defaclacl - 1] = true;
1389 
1390  newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
1391  values, nulls, replaces);
1392  CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
1393  }
1394 
1395  /* these dependencies don't change in an update */
1396  if (isNew)
1397  {
1398  /* dependency on role */
1399  recordDependencyOnOwner(DefaultAclRelationId, defAclOid,
1400  iacls->roleid);
1401 
1402  /* dependency on namespace */
1403  if (OidIsValid(iacls->nspid))
1404  {
1405  ObjectAddress myself,
1406  referenced;
1407 
1408  myself.classId = DefaultAclRelationId;
1409  myself.objectId = defAclOid;
1410  myself.objectSubId = 0;
1411 
1412  referenced.classId = NamespaceRelationId;
1413  referenced.objectId = iacls->nspid;
1414  referenced.objectSubId = 0;
1415 
1416  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1417  }
1418  }
1419 
1420  /*
1421  * Update the shared dependency ACL info
1422  */
1423  nnewmembers = aclmembers(new_acl, &newmembers);
1424 
1425  updateAclDependencies(DefaultAclRelationId,
1426  defAclOid, 0,
1427  iacls->roleid,
1428  noldmembers, oldmembers,
1429  nnewmembers, newmembers);
1430 
1431  if (isNew)
1432  InvokeObjectPostCreateHook(DefaultAclRelationId, defAclOid, 0);
1433  else
1434  InvokeObjectPostAlterHook(DefaultAclRelationId, defAclOid, 0);
1435  }
1436 
1437  if (HeapTupleIsValid(tuple))
1438  ReleaseSysCache(tuple);
1439 
1441 
1442  /* prevent error when processing duplicate objects */
1444 }
Acl * make_empty_acl(void)
Definition: acl.c:431
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:412
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:273
@ DEPENDENCY_AUTO
Definition: dependency.h:34
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:46
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:168

References ACL_ALL_RIGHTS_FUNCTION, ACL_ALL_RIGHTS_RELATION, ACL_ALL_RIGHTS_SCHEMA, ACL_ALL_RIGHTS_SEQUENCE, ACL_ALL_RIGHTS_TYPE, ACL_NO_RIGHTS, aclcopy(), acldefault(), aclequal(), aclitemsort(), aclmembers(), InternalDefaultACL::all_privs, InternalDefaultACL::behavior, CatalogTupleInsert(), CatalogTupleUpdate(), CharGetDatum(), ObjectAddress::classId, CommandCounterIncrement(), DatumGetAclPCopy, DEPENDENCY_AUTO, DROP_RESTRICT, elog, ereport, errcode(), errmsg(), ERROR, GetNewOidWithIndex(), GETSTRUCT, InternalDefaultACL::grant_option, InternalDefaultACL::grantees, heap_form_tuple(), heap_modify_tuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, InvokeObjectPostCreateHook, InternalDefaultACL::is_grant, make_empty_acl(), merge_acl_with_grant(), InternalDefaultACL::nspid, OBJECT_FUNCTION, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_TABLE, OBJECT_TYPE, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, InternalDefaultACL::objtype, OidIsValid, performDeletion(), PointerGetDatum(), InternalDefaultACL::privileges, recordDependencyOn(), recordDependencyOnOwner(), RelationGetDescr, ReleaseSysCache(), InternalDefaultACL::roleid, RowExclusiveLock, SearchSysCache3(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), updateAclDependencies(), and values.

Referenced by RemoveRoleFromObjectACL(), and SetDefaultACLsInSchemas().

◆ SetDefaultACLsInSchemas()

static void SetDefaultACLsInSchemas ( InternalDefaultACL iacls,
List nspnames 
)
static

Definition at line 1160 of file aclchk.c.

1161 {
1162  if (nspnames == NIL)
1163  {
1164  /* Set database-wide permissions if no schema was specified */
1165  iacls->nspid = InvalidOid;
1166 
1167  SetDefaultACL(iacls);
1168  }
1169  else
1170  {
1171  /* Look up the schema OIDs and set permissions for each one */
1172  ListCell *nspcell;
1173 
1174  foreach(nspcell, nspnames)
1175  {
1176  char *nspname = strVal(lfirst(nspcell));
1177 
1178  iacls->nspid = get_namespace_oid(nspname, false);
1179 
1180  /*
1181  * We used to insist that the target role have CREATE privileges
1182  * on the schema, since without that it wouldn't be able to create
1183  * an object for which these default privileges would apply.
1184  * However, this check proved to be more confusing than helpful,
1185  * and it also caused certain database states to not be
1186  * dumpable/restorable, since revoking CREATE doesn't cause
1187  * default privileges for the schema to go away. So now, we just
1188  * allow the ALTER; if the user lacks CREATE he'll find out when
1189  * he tries to create an object.
1190  */
1191 
1192  SetDefaultACL(iacls);
1193  }
1194  }
1195 }

References get_namespace_oid(), InvalidOid, lfirst, NIL, InternalDefaultACL::nspid, SetDefaultACL(), and strVal.

Referenced by ExecAlterDefaultPrivilegesStmt().

◆ string_to_privilege()

static AclMode string_to_privilege ( const char *  privname)
static

Definition at line 2610 of file aclchk.c.

2611 {
2612  if (strcmp(privname, "insert") == 0)
2613  return ACL_INSERT;
2614  if (strcmp(privname, "select") == 0)
2615  return ACL_SELECT;
2616  if (strcmp(privname, "update") == 0)
2617  return ACL_UPDATE;
2618  if (strcmp(privname, "delete") == 0)
2619  return ACL_DELETE;
2620  if (strcmp(privname, "truncate") == 0)
2621  return ACL_TRUNCATE;
2622  if (strcmp(privname, "references") == 0)
2623  return ACL_REFERENCES;
2624  if (strcmp(privname, "trigger") == 0)
2625  return ACL_TRIGGER;
2626  if (strcmp(privname, "execute") == 0)
2627  return ACL_EXECUTE;
2628  if (strcmp(privname, "usage") == 0)
2629  return ACL_USAGE;
2630  if (strcmp(privname, "create") == 0)
2631  return ACL_CREATE;
2632  if (strcmp(privname, "temporary") == 0)
2633  return ACL_CREATE_TEMP;
2634  if (strcmp(privname, "temp") == 0)
2635  return ACL_CREATE_TEMP;
2636  if (strcmp(privname, "connect") == 0)
2637  return ACL_CONNECT;
2638  if (strcmp(privname, "set") == 0)
2639  return ACL_SET;
2640  if (strcmp(privname, "alter system") == 0)
2641  return ACL_ALTER_SYSTEM;
2642  if (strcmp(privname, "maintain") == 0)
2643  return ACL_MAINTAIN;
2644  if (strcmp(privname, "rule") == 0)
2645  return 0; /* ignore old RULE privileges */
2646  ereport(ERROR,
2647  (errcode(ERRCODE_SYNTAX_ERROR),
2648  errmsg("unrecognized privilege type \"%s\"", privname)));
2649  return 0; /* appease compiler */
2650 }

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

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

Variable Documentation

◆ binary_upgrade_record_init_privs

bool binary_upgrade_record_init_privs = false

Definition at line 109 of file aclchk.c.

Referenced by binary_upgrade_set_record_init_privs(), and recordExtensionInitPriv().