]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
always escape 'octets' in fr_value_box_print()
authorAlan T. DeKok <aland@freeradius.org>
Mon, 4 Jul 2022 18:59:25 +0000 (14:59 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 4 Jul 2022 22:19:38 +0000 (18:19 -0400)
fr_value_box_list_aprint() calls fr_value_box_print() to print
normal types.  And fr_value_box_print() prints 'octets' as hex
base16.

However, fr_value_box_list_aprint() calls
fr_value_box_list_concat_as_string() for 'group' types, and
that function just copies 'octets' to the output string.  Which
results in non-grouped 'octets' being printed as hex, and grouped
'octets' bring printed as binary.

the solution is to update fr_value_box_print() to enforce hex/octets
printing of 'octets'

At the same time, update the escaping logic so that if the octets
string is tainted, OR there are escaping rules, we just escape
the raw octets value.  The previous code printed it as hex, and
then escaped that, which doesn't make much sense.

src/lib/util/value.c
src/tests/unit/xlat/cond_base.txt

index e8aeee9099838a643186b5c36a788eadc1c80896..008d7425305ae9f6ff06c7377932f45993e9de5b 100644 (file)
@@ -5215,6 +5215,20 @@ ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff
                break;
 
        case FR_TYPE_GROUP:
+       {
+               fr_sbuff_escape_rules_t my_e_rules;
+
+               /*
+                *      If the caller didn't ask to escape binary data
+                *      in 'octets' types, then we force that now.
+                *      Otherwise any 'octets' type which is buried
+                *      inside of a 'group' will get copied verbatim
+                *      from input to output, with no escaping!
+                */
+               if (!e_rules || (!e_rules->do_oct && !e_rules->do_hex)) {
+                       e_rules = &fr_value_escape_double;
+               }
+
                /*
                 *      Represent groups as:
                 *
@@ -5226,6 +5240,7 @@ ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff
                                ", ", (sizeof(", ") - 1), e_rules,
                                0, false);
                FR_SBUFF_IN_CHAR_RETURN(&our_out, '}');
+       }
                break;
 
        case FR_TYPE_NULL:
@@ -5318,9 +5333,14 @@ ssize_t fr_value_box_list_concat_as_string(bool *tainted, fr_sbuff_t *sbuff, fr_
                        break;
 
                case FR_TYPE_OCTETS:
-                       if (vb->tainted && e_rules) goto cast;
-
-                       slen = fr_sbuff_in_bstrncpy(&our_sbuff, (char const *)vb->vb_strvalue, vb->vb_length);
+                       /*
+                        *      Copy the raw string over, if necessary with escaping.
+                        */
+                       if (e_rules && (vb->tainted || e_rules->do_oct || e_rules->do_hex)) {
+                               slen = fr_sbuff_in_escape(&our_sbuff, (char const *)vb->vb_strvalue, vb->vb_length, e_rules);
+                       } else {
+                               slen = fr_sbuff_in_bstrncpy(&our_sbuff, (char const *)vb->vb_strvalue, vb->vb_length);
+                       }
                        break;
 
                case FR_TYPE_STRING:
index 1539fa6d4b671e52d1f188132a184af3840e721a..97b20c00157776a6dd452bb1a325543ce0c88d7c 100644 (file)
@@ -264,14 +264,15 @@ match ERROR offset 0: Failed parsing string as type 'uint32'
 xlat_purify <ipaddr>127.0.0.1 == "127.0.0.1"
 match true
 
-# Invalid cast from octets to ipaddr.
+# LHS is IPaddr, RHS is string.
 xlat_purify <ipaddr>127.0.0.1 == "%{md4: 127.0.0.1}"
-match NULL
+match false
 
 #
 #  Bare %{...} is allowed.
 #
 
+# Invalid cast from octets to ipaddr.
 xlat_purify <ipaddr>127.0.0.1 == %{md4:127.0.0.1}
 match NULL
 
@@ -357,7 +358,11 @@ xlat_purify (&User-Name == (string) %{md4: blah})
 match (&User-Name == 0x544924d05ec4481925ba3749a096a0a7)
 
 xlat_purify (&User-Name == "%{md4: blah}")
-match (&User-Name == "TI$\320^\304H\031\%\2727I\240\226\240\247")
+match (&User-Name == "0x544924d05ec4481925ba3749a096a0a7")
+
+#  and without the double quotes.
+xlat_purify (&User-Name == %{md4: blah})
+match (&User-Name == 0x544924d05ec4481925ba3749a096a0a7)
 
 xlat_purify <ipaddr>127.0.0.1 == 2130706433
 match true
@@ -756,4 +761,4 @@ match %{rcode:'handled'}
 
 
 count
-match 312
+match 314