From: Arran Cudbard-Bell Date: Wed, 6 Dec 2023 23:19:22 +0000 (-0600) Subject: Use tmpl_rules_t when compiling call-envs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5ceb1dbba62e401f7cf9491614bf665d4244ba18;p=thirdparty%2Ffreeradius-server.git Use tmpl_rules_t when compiling call-envs This allows parent and caller to work correctly --- diff --git a/src/lib/unlang/call_env.c b/src/lib/unlang/call_env.c index 39c620fc8e9..423f55b8405 100644 --- a/src/lib/unlang/call_env.c +++ b/src/lib/unlang/call_env.c @@ -334,19 +334,18 @@ int call_env_parsed_valid(call_env_parsed_t const *parsed, CONF_ITEM const *ci, * @param[in] ctx To allocate parsed environment in. * @param[out] parsed Where to write parsed environment. * @param[in] name Module name for error messages. - * @param[in] namespace we're operating in. + * @param[in] t_rules controlling how the call env is parsed. * @param[in] cs Module config. * @param[in] rule to parse. * @return * - 0 on success; * - <0 on failure; */ -static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char const *name, fr_dict_t const *namespace, +static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char const *name, tmpl_rules_t const *t_rules, CONF_SECTION const *cs, call_env_parser_t const *rule) { CONF_PAIR const *cp, *next; call_env_parsed_t *call_env_parsed = NULL; ssize_t count, multi_index; - fr_type_t type; while (rule->name) { if (call_env_is_subsection(rule->flags)) { @@ -368,7 +367,7 @@ static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char */ call_env_parsed_t *last = call_env_parsed_tail(parsed); - if (rule->section.func(ctx, parsed, namespace, cf_section_to_item(subcs), rule) < 0) { + if (rule->section.func(ctx, parsed, t_rules, cf_section_to_item(subcs), rule) < 0) { cf_log_perr(cs, "Failed parsing configuration section %s", rule->name); talloc_free(call_env_parsed); return -1; @@ -389,7 +388,7 @@ static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char goto next; } - if (call_env_parse(ctx, parsed, name, namespace, subcs, rule->section.subcs) < 0) return -1; + if (call_env_parse(ctx, parsed, name, t_rules, subcs, rule->section.subcs) < 0) return -1; goto next; } @@ -449,7 +448,7 @@ static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char * result structure. */ if (rule->pair.func) { - if (unlikely(rule->pair.func(ctx, &call_env_parsed->data, namespace, cf_pair_to_item(to_parse), rule) < 0)) { + if (unlikely(rule->pair.func(ctx, &call_env_parsed->data, t_rules, cf_pair_to_item(to_parse), rule) < 0)) { error: cf_log_perr(to_parse, "Failed to parse configuration item '%s = %s'", rule->name, cf_pair_value(to_parse)); talloc_free(call_env_parsed); @@ -459,17 +458,9 @@ static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char } else { tmpl_t *parsed_tmpl; - type = rule->pair.cast_type; - if (tmpl_afrom_substr(call_env_parsed, &parsed_tmpl, &FR_SBUFF_IN(cf_pair_value(to_parse), talloc_array_length(cf_pair_value(to_parse)) - 1), - cf_pair_value_quote(to_parse), NULL, &(tmpl_rules_t){ - .cast = ((type == FR_TYPE_VOID) ? FR_TYPE_NULL : type), - .attr = { - .list_def = request_attr_request, - .dict_def = namespace - } - }) < 0) { + cf_pair_value_quote(to_parse), NULL, t_rules) < 0) { goto error; } call_env_parsed->data.tmpl = parsed_tmpl; @@ -646,14 +637,14 @@ void call_env_parsed_free(call_env_parsed_head_t *parsed, call_env_parsed_t *ptr * @param[in] ctx to allocate the call_env_t in. * @param[in] name Module name for error messages. * @param[in] call_env_method containing the call_env_pair_t to evaluate against the specified CONF_SECTION. - * @param[in] namespace to pass to the tmpl tokenizer when parsing pairs from the specified CONF_SECTION. + * @param[in] t_rules that control how call_env_pair_t are parsed. * @param[in] cs to parse in the context of the call. * @return * - A new call_env_t on success. * - NULL on failure. */ call_env_t *call_env_alloc(TALLOC_CTX *ctx, char const *name, call_env_method_t const *call_env_method, - fr_dict_t const *namespace, CONF_SECTION *cs) + tmpl_rules_t const *t_rules, CONF_SECTION *cs) { unsigned int count; size_t names_len; @@ -683,7 +674,7 @@ call_env_t *call_env_alloc(TALLOC_CTX *ctx, char const *name, call_env_method_t MEM(call_env = talloc_pooled_object(ctx, call_env_t, count * 4, (sizeof(call_env_parser_t) + sizeof(tmpl_t)) * count + names_len * 2)); call_env->method = call_env_method; call_env_parsed_init(&call_env->parsed); - if (call_env_parse(call_env, &call_env->parsed, name, namespace, cs, call_env_method->env) < 0) { + if (call_env_parse(call_env, &call_env->parsed, name, t_rules, cs, call_env_method->env) < 0) { talloc_free(call_env); return NULL; } diff --git a/src/lib/unlang/call_env.h b/src/lib/unlang/call_env.h index 894ef8cc34e..48ee07ae258 100644 --- a/src/lib/unlang/call_env.h +++ b/src/lib/unlang/call_env.h @@ -124,14 +124,14 @@ DIAG_ON(attributes) * * @param[in] ctx to allocate any data in. * @param[out] out Where to write the result of parsing. - * @param[in] namespace we're operating in. + * @param[in] t_rules we're parsing attributes with. Contains the default dictionary and nested 'caller' tmpl_rules_t. * @param[in] ci The #CONF_SECTION or #CONF_PAIR to parse. * @param[in] rule Parse rules - How the #CONF_PAIR or #CONF_SECTION should be converted. * @return * - 0 on success. * - -1 on failure. */ -typedef int (*call_env_parse_pair_t)(TALLOC_CTX *ctx, void *out, fr_dict_t const *namespace, CONF_ITEM *ci, call_env_parser_t const *rule); +typedef int (*call_env_parse_pair_t)(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_parser_t const *rule); /** Callback for performing custom parsing of a #CONF_SECTION * @@ -141,14 +141,14 @@ typedef int (*call_env_parse_pair_t)(TALLOC_CTX *ctx, void *out, fr_dict_t const * * @param[in] ctx to allocate any data in. * @param[out] out Where to write the result of parsing. - * @param[in] namespace we're operating in. + * @param[in] t_rules we're parsing attributes with. Contains the default dictionary and nested 'caller' tmpl_rules_t. * @param[in] ci The #CONF_SECTION or #CONF_PAIR to parse. * @param[in] rule Parse rules - How the #CONF_PAIR or #CONF_SECTION should be converted. * @return * - 0 on success. * - -1 on failure. */ -typedef int (*call_env_parse_section_t)(TALLOC_CTX *ctx, call_env_parsed_head_t *out, fr_dict_t const *namespace, CONF_ITEM *ci, call_env_parser_t const *rule); +typedef int (*call_env_parse_section_t)(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_parser_t const *rule); /** Per method call config * @@ -406,7 +406,7 @@ void call_env_parsed_free(call_env_parsed_head_t *parsed, call_env_parsed_t *ptr * @{ */ call_env_t *call_env_alloc(TALLOC_CTX *ctx, char const *name, call_env_method_t const *call_env_method, - fr_dict_t const *namespace, CONF_SECTION *cs) CC_HINT(nonnull(3,4,5)); + tmpl_rules_t const *rules, CONF_SECTION *cs) CC_HINT(nonnull(3,4,5)); /** @} */ #ifdef __cplusplus diff --git a/src/lib/unlang/compile.c b/src/lib/unlang/compile.c index c5689ce5886..c0d631d8b5a 100644 --- a/src/lib/unlang/compile.c +++ b/src/lib/unlang/compile.c @@ -4427,7 +4427,7 @@ static unlang_t *compile_module(unlang_t *parent, unlang_compile_t *unlang_ctx, inst->module->name, unlang_ctx->section_name1, unlang_ctx->section_name2); single->call_env = call_env_alloc(single, single->self.name, method_env, - unlang_ctx->rules ? unlang_ctx->rules->attr.dict_def : fr_dict_internal(), + unlang_ctx->rules, inst->dl_inst->conf); if (!single->call_env) { error: diff --git a/src/lib/unlang/xlat_inst.c b/src/lib/unlang/xlat_inst.c index 31734300d0b..5d3915932ee 100644 --- a/src/lib/unlang/xlat_inst.c +++ b/src/lib/unlang/xlat_inst.c @@ -253,8 +253,26 @@ static xlat_inst_t *xlat_inst_alloc(xlat_exp_t *node) "Method environment for module %s, xlat %s declared, " "but no inst_size set", call->func->mctx->inst->name, call->func->name); + /* + * FIXME - This is wrong, we should pass in the tmpl_rule_t + * from the compiler call. But it would be prohibitively + * memory inefficient to copy it on every xlat call, and it + * only exists for the duration of the compilation phase + * because many elements are stack allocated. The correct + * fix is to allocate all tmpl_rules_t on the heap. + * OR just bite the bullet and duplicate the whole nested + * rules structure for every xlat node. + * + * Because of this hack, outer. and parent. will not work + * within xlat call envs. + */ xi->call_env = call_env_alloc(xi, call->func->name, call->func->call_env_method, - call->dict, call->func->mctx->inst->conf); + &(tmpl_rules_t){ + .attr = { + .dict_def = call->dict, + .list_def = request_attr_request + } + }, call->func->mctx->inst->conf); if (!xi->call_env) { talloc_free(xi); return NULL; diff --git a/src/modules/rlm_cache/rlm_cache.c b/src/modules/rlm_cache/rlm_cache.c index 6129e600780..2b0f8e834ee 100644 --- a/src/modules/rlm_cache/rlm_cache.c +++ b/src/modules/rlm_cache/rlm_cache.c @@ -38,7 +38,7 @@ RCSID("$Id$") extern module_rlm_t rlm_cache; -static int cache_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, fr_dict_t const *namespace, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule); +static int cache_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule); static const conf_parser_t module_config[] = { { FR_CONF_OFFSET_TYPE_FLAGS("driver", FR_TYPE_VOID, 0, rlm_cache_t, driver_submodule), .dflt = "rbtree", @@ -1242,21 +1242,12 @@ static int cache_verify(map_t *map, void *uctx) return 0; } -static int cache_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, fr_dict_t const *namespace, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule) +static int cache_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule) { CONF_SECTION *update = cf_item_to_section(ci); call_env_parsed_t *parsed; map_list_t *maps; - tmpl_rules_t parse_rules = { - .attr = { - .dict_def = namespace, - .list_def = request_attr_request, - .allow_wildcard = true, - .allow_foreign = true /* Because we don't know where we'll be called */ - } - }; - MEM(parsed = call_env_parsed_add(ctx, out, &(call_env_parser_t){ FR_CALL_ENV_PARSE_ONLY_OFFSET("update", FR_TYPE_VOID, 0, cache_call_env_t, maps)})); @@ -1264,7 +1255,7 @@ static int cache_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *o map_list_init(maps); if (map_afrom_cs(maps, maps, update, - &parse_rules, &parse_rules, cache_verify, NULL, MAX_ATTRMAP) < 0) { + t_rules, t_rules, cache_verify, NULL, MAX_ATTRMAP) < 0) { error: call_env_parsed_free(out, parsed); return -1; diff --git a/src/modules/rlm_ldap/rlm_ldap.c b/src/modules/rlm_ldap/rlm_ldap.c index d47d575097b..b5aecc4334f 100644 --- a/src/modules/rlm_ldap/rlm_ldap.c +++ b/src/modules/rlm_ldap/rlm_ldap.c @@ -71,7 +71,7 @@ typedef struct { map_list_t *profile_map; //!< List of maps to apply to the profile. } ldap_xlat_profile_call_env_t; -static int ldap_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, fr_dict_t const *namespace, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule); +static int ldap_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule); static const call_env_parser_t sasl_call_env[] = { { FR_CALL_ENV_OFFSET("mech", FR_TYPE_STRING, CALL_ENV_FLAG_NONE, ldap_auth_call_env_t, user_sasl_mech) }, @@ -2288,7 +2288,7 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) return 0; } -static int ldap_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, fr_dict_t const *namespace, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule) +static int ldap_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule) { map_list_t *maps; CONF_SECTION *update = cf_item_to_section(ci); @@ -2303,12 +2303,6 @@ static int ldap_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *ou map_t const *map = NULL; tmpl_attr_t const *ar; call_env_parsed_t *parsed; - tmpl_rules_t parse_rules = { - .attr = { - .dict_def = namespace, - .list_def = request_attr_request, - } - }; MEM(parsed = call_env_parsed_add(ctx, out, &(call_env_parser_t){ @@ -2325,7 +2319,7 @@ static int ldap_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *ou MEM(maps = talloc(parsed, map_list_t)); map_list_init(maps); - if (map_afrom_cs(maps, maps, update, &parse_rules, &parse_rules, fr_ldap_map_verify, NULL, LDAP_MAX_ATTRMAP) < 0) { + if (map_afrom_cs(maps, maps, update, t_rules, t_rules, fr_ldap_map_verify, NULL, LDAP_MAX_ATTRMAP) < 0) { call_env_parsed_free(out, parsed); return -1; }