]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Use tmpl_rules_t when compiling call-envs
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 6 Dec 2023 23:19:22 +0000 (17:19 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 6 Dec 2023 23:20:19 +0000 (17:20 -0600)
This allows parent and caller to work correctly

src/lib/unlang/call_env.c
src/lib/unlang/call_env.h
src/lib/unlang/compile.c
src/lib/unlang/xlat_inst.c
src/modules/rlm_cache/rlm_cache.c
src/modules/rlm_ldap/rlm_ldap.c

index 39c620fc8e9c587417e2c36568cb78c1cd6b9b47..423f55b84051747708429e74e81a0ca580225921 100644 (file)
@@ -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;
        }
index 894ef8cc34e53ba161d2dec4ae4c81b0740eb58f..48ee07ae25815513f180df73f335d980df1cc2bd 100644 (file)
@@ -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
index c5689ce5886ef19872cf5307952689e4b60a2b73..c0d631d8b5a80c9908db04163984dd8f0a332893 100644 (file)
@@ -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:
index 31734300d0b3b6f25721b292d5fe95ed42bd3895..5d3915932eec848567535f171f605bfe31be7484 100644 (file)
@@ -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;
index 6129e600780adcf5c636acf4fc9fb1f36b58a5f3..2b0f8e834ee7d1d4afecfa84c8c47c139481695e 100644 (file)
@@ -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;
index d47d575097b7a60152032144be8795fa8d6df220..b5aecc4334f9aabab5c6239495401334f983793a 100644 (file)
@@ -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;
                }