From: Alan T. DeKok Date: Sun, 20 Aug 2023 15:33:40 +0000 (-0400) Subject: add undocumented immutable xlat, and test based on it X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=33bccaddad944a347743181bccdf6506d83be9e1;p=thirdparty%2Ffreeradius-server.git add undocumented immutable xlat, and test based on it --- diff --git a/src/lib/unlang/xlat_builtin.c b/src/lib/unlang/xlat_builtin.c index b1ee8fb8d95..a4384d46d7c 100644 --- a/src/lib/unlang/xlat_builtin.c +++ b/src/lib/unlang/xlat_builtin.c @@ -534,6 +534,64 @@ static xlat_action_t xlat_func_explode(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } +static xlat_arg_parser_t const xlat_func_immutable_attr_args[] = { + { .required = true, .single = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR +}; + +/** Mark one or more attributes as immutable + * + * Example: +@verbatim +"%(immutable:&request.State[*])" +@endverbatim + * + * @ingroup xlat_functions + */ +static xlat_action_t xlat_func_immutable_attr(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, + UNUSED xlat_ctx_t const *xctx, + request_t *request, fr_value_box_list_t *args) +{ + fr_pair_t *vp; + fr_dcursor_t cursor; + tmpl_dcursor_ctx_t cc; + tmpl_t *vpt; + fr_value_box_t *attr; + char const *fmt; + + XLAT_ARGS(args, &attr); + + fmt = attr->vb_strvalue; + + if (tmpl_afrom_attr_str(request, NULL, &vpt, fmt, + &(tmpl_rules_t){ + .attr = { + .dict_def = request->dict, + .list_def = request_attr_request, + .allow_wildcard = true, + .prefix = TMPL_ATTR_REF_PREFIX_AUTO + } + }) <= 0) { + RPEDEBUG("Invalid input"); + return XLAT_ACTION_FAIL; + } + + RIDEBUG("Attributes matching \"%s\"", fmt); + + RINDENT(); + for (vp = tmpl_dcursor_init(NULL, NULL, &cc, &cursor, request, vpt); + vp; + vp = fr_dcursor_next(&cursor)) { + if (fr_type_is_leaf(vp->vp_type)) fr_value_box_set_immutable(&vp->data); + } + tmpl_dcursor_clear(&cc); + REXDENT(); + + talloc_free(vpt); + + return XLAT_ACTION_DONE; +} + static xlat_arg_parser_t const xlat_func_integer_args[] = { { .required = true, .single = true, .type = FR_TYPE_VOID }, XLAT_ARG_PARSER_TERMINATOR @@ -3328,6 +3386,7 @@ do { \ XLAT_REGISTER_ARGS("debug", xlat_func_debug, FR_TYPE_INT8, xlat_func_debug_args); XLAT_REGISTER_ARGS("debug_attr", xlat_func_debug_attr, FR_TYPE_NULL, xlat_func_debug_attr_args); + XLAT_REGISTER_ARGS("immutable", xlat_func_immutable_attr, FR_TYPE_NULL, xlat_func_immutable_attr_args); XLAT_REGISTER_ARGS("nexttime", xlat_func_next_time, FR_TYPE_UINT64, xlat_func_next_time_args); XLAT_REGISTER_ARGS("pairs", xlat_func_pairs, FR_TYPE_STRING, xlat_func_pairs_args); XLAT_REGISTER_ARGS("subst", xlat_func_subst, FR_TYPE_STRING, xlat_func_subst_args); diff --git a/src/tests/keywords/immutable b/src/tests/keywords/immutable new file mode 100644 index 00000000000..8f5af3ca97a --- /dev/null +++ b/src/tests/keywords/immutable @@ -0,0 +1,42 @@ +# +# Tests for immutable values. +# +# They can't be modified or deleted. +# +&NAS-Port := 1812 + +# +# Editing it is fine. +# +&NAS-Port += 1 +if !(&NAS-Port == 1813) { + test_fail +} + +# +# Mark it as immutable. The value shouldn't change. +# +%(immutable:&request.NAS-Port[*]) +if !(&NAS-Port == 1813) { + test_fail +} + +# +# Try to edit it. The value shouldn't change. +# +# @todo - we don't have run-time exceptions... maybe this should return "fail"? +# +&NAS-Port += 1 +if !(&NAS-Port == 1813) { + test_fail +} + +# +# We can't delete it. Deletion is a noop +# +&request -= &NAS-Port[*] +if !(&NAS-Port == 1813) { + test_fail +} + +success