From: Alan T. DeKok Date: Wed, 15 Feb 2023 15:28:34 +0000 (-0500) Subject: allow (and test) xlat expansions in RHS leaf assignments X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=58503e4018cc6b5eac886cbe2fcc9d1a5b3baed1;p=thirdparty%2Ffreeradius-server.git allow (and test) xlat expansions in RHS leaf assignments --- diff --git a/src/lib/unlang/edit.c b/src/lib/unlang/edit.c index be4bddc9c04..c73f8e5d67a 100644 --- a/src/lib/unlang/edit.c +++ b/src/lib/unlang/edit.c @@ -1077,9 +1077,74 @@ static int check_lhs_value(request_t *request, unlang_frame_state_edit_t *state, */ static int expanded_lhs_value(request_t *request, unlang_frame_state_edit_t *state, edit_map_t *current) { + fr_dict_attr_t const *da; + fr_type_t type; + fr_value_box_t *box = fr_value_box_list_head(¤t->lhs.result); + fr_value_box_t *dst; + fr_sbuff_unescape_rules_t *erules = NULL; + fr_assert(current->parent); - fr_value_box_list_move(¤t->parent->rhs.result, ¤t->lhs.result); + if (!box) { + RWDEBUG("Failed exapnding result"); + return -1; + } + + fr_assert(tmpl_is_attr(current->parent->lhs.vpt)); + + /* + * There's only one value-box, just use it as-is. We let the parent handler complain about being + * able to parse (or not) the value. + */ + if (!fr_value_box_list_next(¤t->lhs.result, box)) goto done; + + /* + * Figure out how to parse the string. + */ + da = tmpl_attr_tail_da(current->parent->lhs.vpt); + if (fr_type_is_structural(da->type)) { + fr_assert(da->type == FR_TYPE_GROUP); + + type = FR_TYPE_STRING; + + } else if (fr_type_is_variable_size(da->type)) { + type = da->type; + + } else { + type = FR_TYPE_STRING; + } + + /* + * Mash all of the results together. + */ + if (fr_value_box_list_concat_in_place(box, box, ¤t->lhs.result, type, FR_VALUE_BOX_LIST_FREE, true, SIZE_MAX) < 0) { + RWDEBUG("Failed converting result to '%s' - no memory", fr_type_to_str(type)); + return -1; + } + + /* + * Strings, etc. get assigned to the parent. Fixed-size things ger parsed according to their values / enums. + */ + if (!fr_type_is_fixed_size(da->type)) { + done: + fr_value_box_list_move(¤t->parent->rhs.result, ¤t->lhs.result); + return next_map(request, state, current); + } + + /* + * Try to re-parse the box as the destination data type. + */ + MEM(dst = fr_value_box_alloc(state, type, da, box->tainted)); + + erules = fr_value_unescape_by_quote[current->map->lhs->quote]; + + if (fr_value_box_from_str(dst, dst, da->type, da, box->vb_strvalue, box->vb_length, erules, box->tainted) < 0) { + RWDEBUG("Failed converting result to '%s' - %s", fr_type_to_str(type), fr_strerror()); + return -1; + } + + fr_value_box_list_talloc_free(¤t->lhs.result); + fr_value_box_list_insert_tail(¤t->parent->rhs.result, dst); return next_map(request, state, current); } diff --git a/src/tests/keywords/edit-leaf-multivalue b/src/tests/keywords/edit-leaf-multivalue index 143c300d533..557937f176d 100644 --- a/src/tests/keywords/edit-leaf-multivalue +++ b/src/tests/keywords/edit-leaf-multivalue @@ -2,7 +2,7 @@ # PRE: edit # &Tmp-String-0 := { - "foo", + "foo %{User-Name}", "bar", "baz", &User-Name @@ -12,7 +12,7 @@ if (!(%{request.Tmp-String-0[#]} == 4)) { test_fail } -if (!(&Tmp-String-0[0] == "foo")) { +if (!(&Tmp-String-0[0] == "foo bob")) { test_fail } @@ -28,4 +28,26 @@ if (!(&Tmp-String-0[3] == "bob")) { test_fail } +# +# And test non-string things +# +&Tmp-String-0 := "127" + +&Framed-IP-Address := { + "%{Tmp-String-0}.0.0.1", + 192.0.2.1 +} + +if (!(%{request.Framed-IP-Address[#]} == 2)) { + test_fail +} + +if (!(&Framed-IP-Address[0] == 127.0.0.1)) { + test_fail +} + +if (!(&Framed-IP-Address[1] == 192.0.2.1)) { + test_fail +} + success