]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
v4: 5 more xlats with argument definitions (#3987)
authorNick Porter <nick@portercomputing.co.uk>
Tue, 16 Mar 2021 19:08:59 +0000 (19:08 +0000)
committerGitHub <noreply@github.com>
Tue, 16 Mar 2021 19:08:59 +0000 (19:08 +0000)
doc/antora/modules/reference/pages/xlat/builtin.adoc
man/man5/unlang.5
src/lib/unlang/xlat_builtin.c
src/tests/keywords/pairs
src/tests/modules/ldap/auth.unlang

index f384d16e08c668153c15c0c4eef467f4d0b54d82..3e2b8391223c3293d821d18ac04ae05a672934bb 100644 (file)
@@ -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[*])"
 }
 ----
 
index 0725749687c40a4b1cc1096d6dba1e1401a67d67..0bd613a4220a60ed73b10362772e05f2abbe3b47 100644 (file)
@@ -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:<list_or_attr>}
+.IP %(pairs:<list_or_attr>)
 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:<string>}
 Encode string as base64.
index ec2d7860a6365a4ed9ac58108b82f2f650ad9f04..bd44becb1da3909a5b34338ec992f664fc8dd9de 100644 (file)
@@ -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
 
index bc23ba7b1e751ce81e76760ce44640ae00c71135..686795b421919485562dce23b0e4a56909f84e74 100644 (file)
@@ -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") {
index 146beadb5cbe749f241922985b4e43e51377eb42..7c1bc865902176990458c0c222bfca3efe079390 100644 (file)
@@ -54,7 +54,7 @@ else {
         test_pass
 }
 
-if ("%{pairs:reply.}" == "") {
+if ("%(pairs:reply.)" == "") {
         test_fail
 }