]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow &Attr references in function mono
authorAlan T. DeKok <aland@freeradius.org>
Thu, 28 Sep 2023 21:30:17 +0000 (17:30 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 28 Sep 2023 21:30:17 +0000 (17:30 -0400)
not in other ones, as the rest of the functions expect to see
an input argument which is a string, and they convert that to
a tmpl.

The tokenize / eval framework likely needs to be updated to
allow for something like &%{...}, which would create the tmpl
name at run time.  And then the function can get passed a tmpl
(in a value-box?) and not a raw value-box.

src/bin/unit_test_attribute.c
src/bin/unit_test_module.c
src/lib/server/tmpl_tokenize.c
src/lib/server/trigger.c
src/lib/unlang/xlat.h
src/lib/unlang/xlat_builtin.c
src/lib/unlang/xlat_tokenize.c
src/tests/unit/xlat/purify.txt
src/tests/xlat/expr.txt

index 791f0840dd824179230dbd92fe9057a59d7ba9c9..29c3cd77a661004b0e923056911c83527bba5c25 100644 (file)
@@ -2824,7 +2824,7 @@ static size_t command_xlat_argv(command_result_t *result, command_file_ctx_t *cc
                                                  .list_def = request_attr_request,
                                                  .allow_unresolved = cc->tmpl_rules.attr.allow_unresolved
                                          },
-                                 }, false);
+                                 }, false, false);
        if (slen <= 0) {
                fr_strerror_printf_push_head("ERROR offset %d", (int) -slen);
                RETURN_OK_WITH_ERROR();
index 198c786154bfce3eac9a303c6a35644a3538fb79..e8c7b49bd5c3a44788e9bf0b6b7f62091c7f6fdc 100644 (file)
@@ -347,7 +347,10 @@ static request_t *request_from_file(TALLOC_CTX *ctx, FILE *fp, fr_client_t *clie
        request->log.dst = talloc_zero(request, log_dst_t);
        request->log.dst->func = vlog_request;
        request->log.dst->uctx = &default_log;
+
+       request->master_state = REQUEST_ACTIVE;
        request->log.lvl = fr_debug_lvl;
+       request->async = talloc_zero(request, fr_async_t);
 
 
        /*
@@ -985,7 +988,7 @@ int main(int argc, char *argv[])
                        EXIT_WITH_FAILURE;
                }
 
-               if (!do_xlats(el, request, input_file, fp)) ret = EXIT_FAILURE;
+               if (!do_xlats(el, request, xlat_input_file, fp)) ret = EXIT_FAILURE;
                if (input_file) fclose(fp);
                goto cleanup;
        }
index d5bb2c486dd164acfb56b00162b70dff615b59ba..c68f2c3931cb0df957d799c8e18e8a43904f7414 100644 (file)
@@ -3238,7 +3238,7 @@ fr_slen_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
                 *      FIXME - We need an ephemeral version of this
                 *      too.
                 */
-               slen = xlat_tokenize_argv(vpt, &head, &our_in, p_rules, t_rules, false);
+               slen = xlat_tokenize_argv(vpt, &head, &our_in, p_rules, t_rules, false, false);
                if (slen < 0) {
                        talloc_free(vpt);
                        FR_SBUFF_ERROR_RETURN(&our_in);
index e941b611f27aae2f2b0843e385ab1c1e201a90a7..67d2bc06a5d065fb839c50a9ddfff24449b0820d 100644 (file)
@@ -430,7 +430,7 @@ int trigger_exec(unlang_interpret_t *intp,
        trigger->timeout = fr_time_delta_from_sec(5);   /* FIXME - Should be configurable? */
 
        slen = xlat_tokenize_argv(trigger, &trigger->xlat,
-                                 &FR_SBUFF_IN(trigger->command, talloc_array_length(trigger->command) - 1), NULL, NULL, false);
+                                 &FR_SBUFF_IN(trigger->command, talloc_array_length(trigger->command) - 1), NULL, NULL, false, false);
        if (slen <= 0) {
                char *spaces, *text;
 
index 08dc70d65752ee84929dea3abc95b1cf1d5ae328..40fbb4d8f2bd88653015ff87d55f453b5a5facf1 100644 (file)
@@ -402,7 +402,7 @@ fr_slen_t   xlat_tokenize_ephemeral(TALLOC_CTX *ctx, xlat_exp_head_t **head,
                                        fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
 
 fr_slen_t      xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
-                                  fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool comma);
+                                  fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool comma, bool allow_attr);
 
 fr_slen_t      xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_head_t **head, fr_sbuff_t *in,
                              fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
index 6c25430a15d6c35ed062f842b43d6770f833f120..6d490fa7ed2eab0999c18cf5bbfbffb4d41d809b 100644 (file)
@@ -1775,7 +1775,7 @@ static xlat_arg_parser_t const xlat_func_md5_arg[] = {
  */
 static xlat_action_t xlat_func_md5(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                   UNUSED xlat_ctx_t const *xctx,
-                                  UNUSED request_t *request, fr_value_box_list_t *args)
+                                  request_t *request, fr_value_box_list_t *args)
 {
        uint8_t         digest[MD5_DIGEST_LENGTH];
        fr_value_box_t  *vb;
@@ -1784,6 +1784,8 @@ static xlat_action_t xlat_func_md5(TALLOC_CTX *ctx, fr_dcursor_t *out,
        XLAT_ARGS(args, &in_head);
 
        if (in_head) {
+               RDEBUG("INPUT IS %pV", in_head);
+
                fr_md5_calc(digest, in_head->vb_octets, in_head->vb_length);
        } else {
                /* Digest of empty string */
index 00bfc0dc01033c9e3ad2620e96be406525fead0e..f1124ec6353b82ae97fec90819acd15acbeb6948 100644 (file)
@@ -610,7 +610,7 @@ int xlat_tokenize_function_args(xlat_exp_head_t *head, fr_sbuff_t *in,
         *      Now parse the child nodes that form the
         *      function's arguments.
         */
-       if (xlat_tokenize_argv(node, &node->call.args, in, &xlat_multi_arg_rules, t_rules, false) < 0) {
+       if (xlat_tokenize_argv(node, &node->call.args, in, &xlat_multi_arg_rules, t_rules, false, false) < 0) {
                goto error;
        }
        xlat_flags_merge(&node->flags, &node->call.args->flags);
@@ -755,7 +755,7 @@ static int xlat_tokenize_function_new(xlat_exp_head_t *head, fr_sbuff_t *in, tmp
         *      Now parse the child nodes that form the
         *      function's arguments.
         */
-       if (xlat_tokenize_argv(node, &node->call.args, in, &xlat_new_arg_rules, t_rules, true) < 0) {
+       if (xlat_tokenize_argv(node, &node->call.args, in, &xlat_new_arg_rules, t_rules, true, (node->call.input_type == XLAT_INPUT_MONO)) < 0) {
 error:
                talloc_free(node);
                return -1;
@@ -810,8 +810,8 @@ static int xlat_resolve_virtual_attribute(xlat_exp_t *node, tmpl_t *vpt)
 /** Parse an attribute ref or a virtual attribute
  *
  */
-static inline int xlat_tokenize_attribute(xlat_exp_head_t *head, fr_sbuff_t *in,
-                                         fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
+static int xlat_tokenize_attribute(xlat_exp_head_t *head, fr_sbuff_t *in,
+                                  fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, tmpl_attr_prefix_t attr_prefix)
 {
        tmpl_attr_error_t       err;
        tmpl_t                  *vpt = NULL;
@@ -837,7 +837,7 @@ static inline int xlat_tokenize_attribute(xlat_exp_head_t *head, fr_sbuff_t *in,
        }
 
        our_t_rules.attr.allow_unresolved = true;               /* So we can check for virtual attributes later */
-       our_t_rules.attr.prefix = TMPL_ATTR_REF_PREFIX_NO;      /* Must be NO to stop %{&User-Name} */
+       our_t_rules.attr.prefix = attr_prefix;                  /* Must be NO to stop %{&User-Name} */
 
        fr_sbuff_marker(&m_s, in);
 
@@ -900,11 +900,6 @@ done:
         */
        node->flags.pure = false;
 
-       if (!fr_sbuff_next_if_char(in, '}')) {
-               fr_strerror_const("Missing closing brace");
-               goto error;
-       }
-
        xlat_exp_insert_tail(head, node);
 
        fr_sbuff_marker_release(&m_s);
@@ -1035,7 +1030,14 @@ int xlat_tokenize_expansion(xlat_exp_head_t *head, fr_sbuff_t *in,
                fr_sbuff_set(in, &s_m);         /* backtrack */
                fr_sbuff_marker_release(&s_m);
 
-               return xlat_tokenize_attribute(head, in, &attr_p_rules, t_rules);
+               if (xlat_tokenize_attribute(head, in, &attr_p_rules, t_rules, TMPL_ATTR_REF_PREFIX_NO) < 0) return -1;
+
+               if (!fr_sbuff_next_if_char(in, '}')) {
+                       fr_strerror_const("Missing closing brace");
+                       return -1;
+               }
+
+               return 0;
 
        /*
         *      Hint token was whitespace
@@ -1672,12 +1674,13 @@ fr_slen_t xlat_tokenize_ephemeral(TALLOC_CTX *ctx, xlat_exp_head_t **out,
  *                             any expansions.
  * @param[in] t_rules          controlling how attribute references are parsed.
  * @param[in] comma            whether the arguments are delimited by commas
+ * @param[in] allow_attr       allow attribute references as arguments
  * @return
  *     - < 0 on error.
  *     - >0  on success which is the number of characters parsed.
  */
 fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t *in,
-                            fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool comma)
+                            fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules, bool comma, bool allow_attr)
 {
        int                             argc = 0;
        fr_sbuff_t                      our_in = FR_SBUFF(in);
@@ -1734,6 +1737,24 @@ fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t
                case T_BARE_WORD:
                        XLAT_DEBUG("ARGV bare word <-- %.*s", (int) fr_sbuff_remaining(&our_in), fr_sbuff_current(&our_in));
 
+                       /*
+                        *      &User-Name is an attribute reference
+                        *
+                        *      @todo - only the mono functions allow this automatic conversion.
+                        *      The input args ones (e.g. immutable) take an input string, and parse the tmpl from that.
+                        *
+                        *      We need to signal the tokenize / eval code that the parameter here is a tmpl, and not a string.
+                        *
+                        *      Perhaps &"foo" can dynamically create the string, and then pass it to the the
+                        *      tmpl tokenizer, and then pass the tmpl to the function.  Which also means that
+                        *      we need to be able to have a fr_value_box_t which holds a ptr to a tmpl.  And
+                        *      update the function arguments to say "we want a tmpl, not a string".
+                        */
+                       if (allow_attr && fr_sbuff_is_char(&our_in, '&')) {
+                               if (xlat_tokenize_attribute(node->group, &our_in, our_p_rules, t_rules, TMPL_ATTR_REF_PREFIX_YES) < 0) goto error;
+                               break;
+                       }
+
                        if (xlat_tokenize_input(node->group, &our_in,
                                                our_p_rules, t_rules) < 0) {
                        error:
index 4de530afdce68afd6184863474a991233eebc12a..1a258eb035e8e1a7d4c737371d89dda2463e7b79 100644 (file)
@@ -244,10 +244,10 @@ xlat_purify %md5('%md5(foo)')
 match 0x5e153571422b69cf5c5f7ce5f03985b5
 
 #
-#  Because this isn't a reference to the contents of &User-Name
+#  This is a reference to the contents of &User-Name
 #
 xlat_purify %md5(&User-Name)
-match 0x14d23a6ed8e7d19fcb3a38dc86c1fc0b
+match %{md5:&User-Name}
 
 
 xlat_purify %md5('foo')
@@ -256,8 +256,5 @@ match 0xacbd18db4cc2f85cedef654fccc4a4d8
 xlat_purify %md5("foo")
 match 0xacbd18db4cc2f85cedef654fccc4a4d8
 
-xlat_purify %md5(&User-Name)
-match 0x14d23a6ed8e7d19fcb3a38dc86c1fc0b
-
 count
-match 116
+match 114
index f590009e4fbb9291d8c5b20ad1592a80c8947cbd..38d117956a9708d80399db25e5ebb0d42367dbfa 100644 (file)
@@ -131,14 +131,30 @@ match true
 xlat_expr "foo " + "baz" + " bar"
 match foo baz bar
 
-xlat_expr "foo " + &User-Name + " bar"
-match foo bob bar
+#xlat_expr "foo " + &User-Name + " bar"
+#match foo bob bar
 
+#
+#  The User-Name has to exist
+#
+xlat_expr %{User-Name}
+match {bob}
+
+#
+#  We're not hashing the string value of the attribute reference
+#
+xlat_expr (octets) %md5('&User-Name')
+match 0x14d23a6ed8e7d19fcb3a38dc86c1fc0b
+
+#
+#  We're hashing the string contained by the User-Name
+#
 xlat_expr (octets) %md5('bob')
 match 0x9f9d51bc70ef21ca5c14f307980a29d8
 
 #
-#  @todo - not done yet!
+#  And if we take it from the &User-Name ref, we get the same thing
+#  as hashing the bare string.
 #
-#xlat_expr (octets) %md5(&User-Name)
-#match 0x9f9d51bc70ef21ca5c14f307980a29d8
+xlat_expr (octets) %md5(&User-Name)
+match 0x9f9d51bc70ef21ca5c14f307980a29d8