From: Nick Porter Date: Tue, 16 Mar 2021 19:08:59 +0000 (+0000) Subject: v4: 5 more xlats with argument definitions (#3987) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4f8a0fcfc75d610c5d86811cb95cf34bab702afb;p=thirdparty%2Ffreeradius-server.git v4: 5 more xlats with argument definitions (#3987) --- diff --git a/doc/antora/modules/reference/pages/xlat/builtin.adoc b/doc/antora/modules/reference/pages/xlat/builtin.adoc index f384d16e08c..3e2b8391223 100644 --- a/doc/antora/modules/reference/pages/xlat/builtin.adoc +++ b/doc/antora/modules/reference/pages/xlat/builtin.adoc @@ -419,7 +419,7 @@ update reply { Maximum should be 12300000000 ``` -=== %{pairs:<&list:[*]>} +=== %(pairs:<&list:[*]>) Serialize attributes as comma-delimited string. @@ -435,7 +435,7 @@ update { } update reply { - &Reply-Message := "Serialize output: %{pairs:&control[*]}" + &Reply-Message := "Serialize output: %(pairs:&control[*])" } ---- diff --git a/man/man5/unlang.5 b/man/man5/unlang.5 index 0725749687c..0bd613a4220 100644 --- a/man/man5/unlang.5 +++ b/man/man5/unlang.5 @@ -836,7 +836,7 @@ The number of attributes in the named list. .IP %{List-Name:[*]} All values of attributes in the named-list, concatenated together with ',' -as the separator. Use the %{pairs:} xlat to get a list of attributes and +as the separator. Use the %(pairs:) xlat to get a list of attributes and values. e.g. If a response contains "Reply-Message = 'Hello', Reply-Message = 'bob' @@ -963,10 +963,10 @@ Generate HMAC-SHA1 of input data. "%{hmacsha1:foo bar}" == "85d155c55ed286a300bd1cf124de08d87e914f3a" -.IP %{pairs:} +.IP %(pairs:) Serialize attributes as comma-delimited string -e.g. "%{pairs:request.}" == "User-Name = 'foo', User-Password = 'bar', ..." +e.g. "%(pairs:request.)" == "User-Name = 'foo', User-Password = 'bar', ..." .IP %{base64:} Encode string as base64. diff --git a/src/lib/unlang/xlat_builtin.c b/src/lib/unlang/xlat_builtin.c index ec2d7860a63..bd44becb1da 100644 --- a/src/lib/unlang/xlat_builtin.c +++ b/src/lib/unlang/xlat_builtin.c @@ -2218,6 +2218,11 @@ static xlat_action_t xlat_func_pack(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, U } +static xlat_arg_parser_t const xlat_func_pairs_args[] = { + { .required = true, .single = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR +}; + /** Encode attributes as a series of string attribute/value pairs * * This is intended to serialize one or more attributes as a comma @@ -2225,8 +2230,8 @@ static xlat_action_t xlat_func_pack(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, U * * Example: @verbatim -"%{pairs:request[*]}" == "User-Name = 'foo'User-Password = 'bar'" -"%{concat:, %{pairs:request[*]}}" == "User-Name = 'foo', User-Password = 'bar'" +"%(pairs:request[*])" == "User-Name = 'foo'User-Password = 'bar'" +"%{concat:, %(pairs:request[*])}" == "User-Name = 'foo', User-Password = 'bar'" @endverbatim * * @see #xlat_func_concat @@ -2243,16 +2248,6 @@ static xlat_action_t xlat_func_pairs(TALLOC_CTX *ctx, fr_dcursor_t *out, fr_value_box_t *vb; fr_value_box_t *in_head = fr_dlist_head(in); - /* - * If there's no input, there's no output - */ - if (!in_head) return XLAT_ACTION_DONE; - - if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) { - RPEDEBUG("Failed concatenating input"); - return XLAT_ACTION_FAIL; - } - fr_pair_t *vp; if (tmpl_afrom_attr_str(ctx, NULL, &vpt, in_head->vb_strvalue, @@ -2288,6 +2283,12 @@ static xlat_action_t xlat_func_pairs(TALLOC_CTX *ctx, fr_dcursor_t *out, } +static xlat_arg_parser_t const xlat_func_rand_arg = { + .required = true, + .single = true, + .type = FR_TYPE_UINT32 +}; + /** Generate a random integer value * * For "N = %{rand:MAX}", 0 <= N < MAX @@ -2299,20 +2300,14 @@ static xlat_action_t xlat_func_pairs(TALLOC_CTX *ctx, fr_dcursor_t *out, * * @ingroup xlat_functions */ -static xlat_action_t xlat_func_rand(TALLOC_CTX *ctx, fr_dcursor_t *out, - request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst, +static xlat_action_t xlat_func_rand(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED request_t *request, + UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst, fr_value_box_list_t *in) { int64_t result; fr_value_box_t *vb; fr_value_box_t *in_head = fr_dlist_head(in); - /* Make sure input can be converted to an unsigned 32 bit integer */ - if (fr_value_box_cast_in_place(ctx, in_head, FR_TYPE_UINT32, NULL) < 0) { - RPEDEBUG("Failed converting input to uint32"); - return XLAT_ACTION_FAIL; - } - result = in_head->vb_uint32; /* Make sure it isn't too big */ @@ -2330,6 +2325,12 @@ static xlat_action_t xlat_func_rand(TALLOC_CTX *ctx, fr_dcursor_t *out, } +static xlat_arg_parser_t const xlat_func_randstr_arg = { + .required = true, + .concat = true, + .type = FR_TYPE_STRING +}; + /** Generate a string of random chars * * Build strings of random chars, useful for generating tokens and passcodes @@ -2386,18 +2387,6 @@ static xlat_action_t xlat_func_randstr(TALLOC_CTX *ctx, fr_dcursor_t *out, */ #define REPETITION_MAX 1024 - /* - * Nothing to do if input is empty - */ - if (!in_head) return XLAT_ACTION_DONE; - /* - * Concatenate all input - */ - if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) { - RPEDEBUG("Failed concatenating input"); - return XLAT_ACTION_FAIL; - } - start = p = in_head->vb_strvalue; end = p + in_head->vb_length; @@ -2534,6 +2523,7 @@ static xlat_action_t xlat_func_randstr(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } + #if defined(HAVE_REGEX_PCRE) || defined(HAVE_REGEX_PCRE2) /** Get named subcapture value from previous regex * @@ -2637,6 +2627,11 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_dcursor_t *out, } #endif +static xlat_arg_parser_t const xlat_func_sha_arg = { + .concat = true, + .type = FR_TYPE_OCTETS +}; + /** Calculate the SHA1 hash of a string or attribute. * * Example: @@ -2646,8 +2641,8 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_dcursor_t *out, * * @ingroup xlat_functions */ -static xlat_action_t xlat_func_sha1(TALLOC_CTX *ctx, fr_dcursor_t *out, - request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst, +static xlat_action_t xlat_func_sha1(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED request_t *request, + UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst, fr_value_box_list_t *in) { uint8_t digest[SHA1_DIGEST_LENGTH]; @@ -2655,14 +2650,6 @@ static xlat_action_t xlat_func_sha1(TALLOC_CTX *ctx, fr_dcursor_t *out, fr_value_box_t *vb; fr_value_box_t *in_head = fr_dlist_head(in); - /* - * Concatenate all input if there is some - */ - if (in_head && fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_OCTETS, true) < 0) { - RPEDEBUG("Failed concatenating input"); - return XLAT_ACTION_FAIL; - } - fr_sha1_init(&sha1_ctx); if (in_head) { fr_sha1_update(&sha1_ctx, in_head->vb_octets, in_head->vb_length); @@ -2691,8 +2678,8 @@ static xlat_action_t xlat_func_sha1(TALLOC_CTX *ctx, fr_dcursor_t *out, * @ingroup xlat_functions */ #ifdef HAVE_OPENSSL_EVP_H -static xlat_action_t xlat_evp_md(TALLOC_CTX *ctx, fr_dcursor_t *out, - request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst, +static xlat_action_t xlat_evp_md(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED request_t *request, + UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst, fr_value_box_list_t *in, EVP_MD const *md) { uint8_t digest[EVP_MAX_MD_SIZE]; @@ -2701,14 +2688,6 @@ static xlat_action_t xlat_evp_md(TALLOC_CTX *ctx, fr_dcursor_t *out, fr_value_box_t *vb; fr_value_box_t *in_head = fr_dlist_head(in); - /* - * Concatenate all input if there is some - */ - if (in_head && fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_OCTETS, true) < 0) { - RPEDEBUG("Failed concatenating input"); - return XLAT_ACTION_FAIL; - } - md_ctx = EVP_MD_CTX_create(); EVP_DigestInit_ex(md_ctx, md, NULL); if (in_head) { @@ -3394,6 +3373,7 @@ do { \ xlat_func_args(xlat, _args); \ } while (0) + XLAT_REGISTER_ARGS("pairs", xlat_func_pairs, xlat_func_pairs_args); XLAT_REGISTER_ARGS("rpad", xlat_func_rpad, xlat_func_rpad_args); #define XLAT_REGISTER_MONO(_xlat, _func, _arg) \ @@ -3414,30 +3394,29 @@ do { \ XLAT_REGISTER_MONO("md5", xlat_func_md5, xlat_func_md5_arg); xlat_register(NULL, "module", xlat_func_module, false); XLAT_REGISTER_MONO("pack", xlat_func_pack, xlat_func_pack_arg); - xlat_register(NULL, "pairs", xlat_func_pairs, false); - xlat_register(NULL, "rand", xlat_func_rand, false); - xlat_register(NULL, "randstr", xlat_func_randstr, false); + XLAT_REGISTER_MONO("rand", xlat_func_rand, xlat_func_rand_arg); + XLAT_REGISTER_MONO("randstr", xlat_func_randstr, xlat_func_randstr_arg); #if defined(HAVE_REGEX_PCRE) || defined(HAVE_REGEX_PCRE2) xlat_register(NULL, "regex", xlat_func_regex, false); #endif - xlat_register(NULL, "sha1", xlat_func_sha1, false); + XLAT_REGISTER_MONO("sha1", xlat_func_sha1, xlat_func_sha_arg); #ifdef HAVE_OPENSSL_EVP_H - xlat_register(NULL, "sha2_224", xlat_func_sha2_224, false); - xlat_register(NULL, "sha2_256", xlat_func_sha2_256, false); - xlat_register(NULL, "sha2_384", xlat_func_sha2_384, false); - xlat_register(NULL, "sha2_512", xlat_func_sha2_512, false); + XLAT_REGISTER_MONO("sha2_224", xlat_func_sha2_224, xlat_func_sha_arg); + XLAT_REGISTER_MONO("sha2_256", xlat_func_sha2_256, xlat_func_sha_arg); + XLAT_REGISTER_MONO("sha2_384", xlat_func_sha2_384, xlat_func_sha_arg); + XLAT_REGISTER_MONO("sha2_512", xlat_func_sha2_512, xlat_func_sha_arg); # if OPENSSL_VERSION_NUMBER >= 0x10100000L - xlat_register(NULL, "blake2s_256", xlat_func_blake2s_256, false); - xlat_register(NULL, "blake2b_512", xlat_func_blake2b_512, false); + XLAT_REGISTER_MONO("blake2s_256", xlat_func_blake2s_256, xlat_func_sha_arg); + XLAT_REGISTER_MONO("blake2b_512", xlat_func_blake2b_512, xlat_func_sha_arg); # endif # if OPENSSL_VERSION_NUMBER >= 0x10101000L - xlat_register(NULL, "sha3_224", xlat_func_sha3_224, false); - xlat_register(NULL, "sha3_256", xlat_func_sha3_256, false); - xlat_register(NULL, "sha3_384", xlat_func_sha3_384, false); - xlat_register(NULL, "sha3_512", xlat_func_sha3_512, false); + XLAT_REGISTER_MONO("sha3_224", xlat_func_sha3_224, xlat_func_sha_arg); + XLAT_REGISTER_MONO("sha3_256", xlat_func_sha3_256, xlat_func_sha_arg); + XLAT_REGISTER_MONO("sha3_384", xlat_func_sha3_384, xlat_func_sha_arg); + XLAT_REGISTER_MONO("sha3_512", xlat_func_sha3_512, xlat_func_sha_arg); # endif #endif diff --git a/src/tests/keywords/pairs b/src/tests/keywords/pairs index bc23ba7b1e7..686795b4219 100644 --- a/src/tests/keywords/pairs +++ b/src/tests/keywords/pairs @@ -9,11 +9,11 @@ update { } update { - &request.Tmp-String-1 := "%{concat:, %{pairs:request[*]}}" - &request.Tmp-String-2 := "%{pairs:Tmp-String-0}" - &request.Tmp-String-3 := "%{concat:, %{pairs:Tmp-String-0[*]}}" - &request.Tmp-String-4 := "%{pairs:control.}" - &request.Tmp-String-5 := "%{pairs:control.User-Name}" + &request.Tmp-String-1 := "%{concat:, %(pairs:request[*])}" + &request.Tmp-String-2 := "%(pairs:Tmp-String-0)" + &request.Tmp-String-3 := "%{concat:, %(pairs:Tmp-String-0[*])}" + &request.Tmp-String-4 := "%(pairs:control.)" + &request.Tmp-String-5 := "%(pairs:control.User-Name)" } if (&request.Tmp-String-1 != "User-Name = \"bob\", User-Password = \"hello\", Tmp-String-0 = \"This is a string\", Tmp-String-0 = \"This is another one\", Tmp-Octets-0 = 0x000504030201, Tmp-Integer-0 = 7331") { diff --git a/src/tests/modules/ldap/auth.unlang b/src/tests/modules/ldap/auth.unlang index 146beadb5cb..7c1bc865902 100644 --- a/src/tests/modules/ldap/auth.unlang +++ b/src/tests/modules/ldap/auth.unlang @@ -54,7 +54,7 @@ else { test_pass } -if ("%{pairs:reply.}" == "") { +if ("%(pairs:reply.)" == "") { test_fail }