]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
port decode_raw() over from dhcpv6
authorAlan T. DeKok <aland@freeradius.org>
Sat, 12 Mar 2022 15:56:07 +0000 (10:56 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 12 Mar 2022 15:56:07 +0000 (10:56 -0500)
which involves adding a tmp_ctx to packet_ctx

ensuring that all functions have a decode_ctx passed to them

fixing up the calls to decode_raw() to pass the correct values

fixing the test output so that it shows the current attribute
as raw, and not something else.

src/protocols/dhcpv4/decode.c
src/protocols/dhcpv4/dhcpv4.h
src/protocols/dhcpv4/packet.c
src/tests/unit/protocols/dhcpv4/error.txt
src/tests/unit/protocols/dhcpv4/vendor.txt

index ff850eecdccafce633af5b0d3f58612f7a16770d..070dd7159efa242ab890fa4898a6598c3ec2be64 100644 (file)
 #include "attrs.h"
 
 static ssize_t decode_tlv(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
-                         uint8_t const *data, size_t data_len);
+                         uint8_t const *data, size_t data_len, void *decode_ctx);
 
-static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out,
-                           fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len);
+static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
+                           uint8_t const *data, size_t data_len, void *decode_ctx);
 
 /** Returns the number of array members for arrays with fixed element sizes
  *
@@ -193,32 +193,49 @@ finish:
        return p - data;
 }
 
-static ssize_t decode_raw(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, uint8_t attr,
-                         uint8_t const *data, size_t data_len)
+static ssize_t decode_raw(TALLOC_CTX *ctx, fr_pair_list_t *out,
+                         fr_dict_attr_t const *parent,
+                         uint8_t const *data, size_t const data_len, void *decode_ctx)
 {
-       ssize_t slen;
-       fr_dict_attr_t *unknown;
-       fr_dict_attr_t const *child;
+       fr_pair_t               *vp;
+       fr_dict_attr_t          *unknown;
+       fr_dict_attr_t const    *da;
+       fr_dhcpv4_ctx_t         *packet_ctx = decode_ctx;
+       ssize_t                 slen;
+
+#ifdef __clang_analyzer__
+       if (!packet_ctx || !packet_ctx->tmp_ctx || !parent->parent) return PAIR_DECODE_FATAL_ERROR;
+#endif
 
        FR_PROTO_HEX_DUMP(data, data_len, "decode_raw");
 
        /*
-        *      Build an unknown attr.
+        *      Re-write the attribute to be "raw".  It is
+        *      therefore of type "octets", and will be
+        *      handled below.
         */
-       unknown = fr_dict_unknown_attr_afrom_num(ctx, parent, attr);
-       if (!unknown) return -1;
+       unknown = fr_dict_unknown_attr_afrom_da(packet_ctx->tmp_ctx, parent);
+       if (!unknown) {
+               fr_strerror_printf("%s: Internal sanity check %d", __FUNCTION__, __LINE__);
+               return PAIR_DECODE_OOM;
+       }
        unknown->flags.is_raw = 1;
 
-       child = unknown;                /* const issues */
-
-       FR_PROTO_TRACE("decode context changed %s:%s -> %s:%s",
-                      fr_type_to_str(parent->type), parent->name,
-                      fr_type_to_str(child->type), child->name);
+       vp = fr_pair_afrom_da(ctx, unknown);
+       if (!vp) return PAIR_DECODE_OOM;
 
-       slen = decode_value(ctx, out, child, data, data_len);
-       if (slen < 0) fr_dict_unknown_free(&child);
+       slen = fr_value_box_from_network(vp, &vp->data, vp->da->type, vp->da,
+                                        &FR_DBUFF_TMP(data, data_len), data_len, true);
+       if (slen < 0) {
+               talloc_free(vp);
+               da = unknown;
+               fr_dict_unknown_free(&da);
+               return slen;
+       }
 
-       return slen;
+       vp->vp_tainted = true;
+       fr_pair_append(out, vp);
+       return data_len;
 }
 
 
@@ -261,7 +278,7 @@ static ssize_t decode_raw(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t c
  *     data_len on success.
  */
 static ssize_t decode_tlv(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
-                         uint8_t const *data, size_t data_len)
+                         uint8_t const *data, size_t data_len, void *decode_ctx)
 {
        uint8_t const           *p = data;
        uint8_t const           *end = data + data_len;
@@ -306,7 +323,7 @@ static ssize_t decode_tlv(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t c
                         *      options" option.  Return it as random crap.
                         */
                raw:
-                       tlv_len = decode_raw(ctx, out, parent, p[0], p, end - p);
+                       tlv_len = decode_raw(ctx, out, parent, p, end - p, decode_ctx);
                        if (tlv_len < 0) return tlv_len;
 
                        return data_len;
@@ -336,7 +353,7 @@ static ssize_t decode_tlv(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t c
                               fr_type_to_str(parent->type), parent->name,
                               fr_type_to_str(child->type), child->name);
 
-               tlv_len = decode_value(ctx, out, child, p + 2, p[1]);
+               tlv_len = decode_value(ctx, out, child, p + 2, p[1], decode_ctx);
                if (tlv_len < 0) {
                        fr_dict_unknown_free(&child);
                        return tlv_len;
@@ -350,8 +367,8 @@ static ssize_t decode_tlv(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t c
        return data_len;
 }
 
-static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out,
-                           fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len)
+static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
+                           uint8_t const *data, size_t data_len, void *decode_ctx)
 {
        unsigned int    values, i;              /* How many values we need to decode */
        uint8_t const   *p = data;
@@ -364,7 +381,7 @@ static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out,
        /*
         *      TLVs can't be coalesced as they're variable length
         */
-       if (parent->type == FR_TYPE_TLV) return decode_tlv(ctx, out, parent, data, data_len);
+       if (parent->type == FR_TYPE_TLV) return decode_tlv(ctx, out, parent, data, data_len, decode_ctx);
 
        /*
         *      Values with a fixed length may be coalesced into a single option
@@ -424,7 +441,7 @@ static ssize_t decode_value(TALLOC_CTX *ctx, fr_pair_list_t *out,
  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ----
  */
 static ssize_t decode_vsa(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent,
-                         uint8_t const *data, size_t const data_len)
+                         uint8_t const *data, size_t const data_len, void *decode_ctx)
 {
        ssize_t                 len;
        uint8_t                 option_len;
@@ -446,7 +463,7 @@ next:
         *      attributes.
         */
        if ((size_t)(end - p) < (sizeof(uint32_t) + 1 + 1)) {
-               len = decode_raw(ctx, out, parent->parent, parent->attr, p, end - p);
+               len = decode_raw(ctx, out, parent, p, end - p, decode_ctx);
                if (len < 0) return len;
 
                return data_len + 2; /* decoded the whole thing */
@@ -476,14 +493,14 @@ next:
 
        option_len = p[0];
        if ((p + 1 + option_len) > end) {
-               len = decode_raw(ctx, out, vendor, p[1], p, end - p);
+               len = decode_raw(ctx, out, vendor, p, end - p, decode_ctx);
                if (len < 0) return len;
 
                return data_len + 2; /* decoded the whole thing */
        }
        p++;
 
-       len = decode_tlv(ctx, out, vendor, p, option_len);
+       len = decode_tlv(ctx, out, vendor, p, option_len, decode_ctx);
        if (len <= 0) return len;
 
        p += len;
@@ -548,7 +565,7 @@ ssize_t fr_dhcpv4_decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
                       fr_type_to_str(parent->type), parent->name,
                       fr_type_to_str(da->type), da->name);
 
-       if (da->type == FR_TYPE_VSA) return decode_vsa(ctx, out, da, data + 2, data[1]);
+       if (da->type == FR_TYPE_VSA) return decode_vsa(ctx, out, da, data + 2, data[1], decode_ctx);
 
        /*
         *      Check for multiple options of the same type, and concatenate their values together.
@@ -576,7 +593,7 @@ ssize_t fr_dhcpv4_decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
                        q += next[1];
                }
 
-               slen = decode_value(ctx, out, da, packet_ctx->buffer, q - packet_ctx->buffer);
+               slen = decode_value(ctx, out, da, packet_ctx->buffer, q - packet_ctx->buffer, packet_ctx);
                if (slen <= 0) return slen;
 
                /*
@@ -601,7 +618,7 @@ ssize_t fr_dhcpv4_decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
         *      mashed into the temporary buffer.  Then, that buffer
         *      gets used for value decoding.
         */
-       slen = decode_value(ctx, out, da, data + 2, data[1]);
+       slen = decode_value(ctx, out, da, data + 2, data[1], decode_ctx);
        if (slen < 0) {
                fr_dict_unknown_free(&da);
                return slen;
@@ -629,6 +646,7 @@ static int decode_test_ctx(void **out, TALLOC_CTX *ctx)
 
        test_ctx = talloc_zero(ctx, fr_dhcpv4_ctx_t);
        talloc_set_destructor(test_ctx, _decode_test_ctx);
+       test_ctx->tmp_ctx = talloc(test_ctx, uint8_t);
 
        *out = test_ctx;
 
index d2b3f7e0ece6c5009fae151dda2d2f0d3ccad915..5fd41c28bd2095e914af5e6bb7ca49ce463c044e 100644 (file)
@@ -143,6 +143,7 @@ extern HIDDEN fr_dict_attr_t const  *dhcp_option_82;
 typedef struct {
        fr_dict_attr_t const *root;
        uint8_t         *buffer;                //! for coalescing concatenated options
+       TALLOC_CTX      *tmp_ctx;               //!< for temporary things cleaned up during decoding
 } fr_dhcpv4_ctx_t;
 
 /*
index 651df4f621ee83f8e03ae8811d4d35e866925b80..06fb033ebdf0d21104aeec18633824d0627ba428 100644 (file)
@@ -118,6 +118,7 @@ int fr_dhcpv4_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data,
 
        packet_ctx = talloc_zero(ctx, fr_dhcpv4_ctx_t);
        if (!packet_ctx) return -1;
+       packet_ctx->tmp_ctx = talloc(packet_ctx, uint8_t);
 
        /*
         *      Decode the header.
index 548ecc6b6471a69215f75be66734d1b78bef88a0..5a8a186dba21478efff073cf74957915bc8dc0ac 100644 (file)
@@ -6,13 +6,13 @@ proto-dictionary dhcpv4
 fuzzer-out dhcpv4
 
 decode-pair 7d 7d 7d 7d 7d 7d 7d 7d 37 37 37 37 37 37 37 37 3f 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 be 37 37 37 2a 30 30 30 30 30 74 30 30 30 30 30 30 32 1d 00 37 31 37 38 30 38 32 35 37 33 30 36 31 37 00 04 00 00 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa 00 00 00 00 00 00 00 20 00 37 37 37 37 37 37 37 37 00 00 1a 29 00 00 00 00 63 00 01 00 00
-match raw.V-I-Vendor-Specific.2105376125.125 = 0x7d7d37373737373737373f37373737373737373737373737373737373737373737373737be3737372a303030303074303030303030321d00373137383038323537333036313700040000370000000000000000000000000000000000fa000000000000002000373737373737373700001a2900000000630001
+match raw.V-I-Vendor-Specific.2105376125 = 0x7d7d37373737373737373f37373737373737373737373737373737373737373737373737be3737372a303030303074303030303030321d00373137383038323537333036313700040000370000000000000000000000000000000000fa000000000000002000373737373737373700001a2900000000630001
 
 decode-pair 7d 00
-match raw.125 = 0x
+match raw.V-I-Vendor-Specific = 0x
 
 decode-proto 03 00 00 f5 00 11 41 04 04 04 04 04 29 04 04 00 04 ca 04 04 04 09 04 04 1a f3 ff 7e a0 b5 25 07 80 3b 60 00 00 1a 23 00 00 fd 00 80 00 00 00 00 00 10 00 80 00 00 00 00 00 00 2f 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa 67 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ca 04 04 04 04 04 04 1a 0d 00 00 60 b5 25 07 2b 35 60 00 00 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f7 00 00 00 00 00 00 11 00 00 00 00 00 32 60 1a 00 08 0d 00 00 60 b5 00 00 00 25 21 39 21 1a 0d 00 00 60 b5 25 07 80 34 60 00 00 1a 0d 00 00 60 b5 25 2a 60 00 31 00 80 1a 0d 00 00 60 b5 25 07 80 34 21 21 04 1a 0d 00 00 60 63 82 53 63 f2 60 b5 25 07 80 31 60 00 00 1a 29 00 00 00 f8 ff ff fc 00 00 00 00 00 00 04 00 00 00 d6 00 00 5d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ca 04 04 04 04 04 04 1a 0d 00 00 60 b5 25 07 80 34 65 00 00 1a 00 00 00 00 00 00 00 00 00 00 00 1a 0d 00 00 20 b5 25 07 80 35 2f 04 00 00 00 00 ff fb 00 00 00 00 00 00 00 00 00 00 00 04 00 04 0d 7a 7a 7a 7a 00 10 00 00 00 00 00 00 d5 10 00 00 00 00 00 00 00 00 00 02 00 7d 00 00 00 00 00
-match Opcode = 3, Hardware-Type = 0, Hardware-Address-Length = 0, Hop-Count = 245, Transaction-Id = 1130756, Number-of-Seconds = 1028, Flags = 1028, Client-IP-Address = 41.4.4.0, Your-IP-Address = 4.202.4.4, Server-IP-Address = 4.9.4.4, Gateway-IP-Address = 26.243.255.126, Server-Host-Name = "\240\265\%\a\200;`", Site-specific-18 = 0xb5250780316000001a29000000f8fffffc00000000000004000000d600005d000000000000000000000000000000000000000000000004ca0404040404041a0d000060b5250780346500001a00000000000000000000001a0d000020b5250780, raw.Message-Type = 0x0400000000fffb00000000000000000000000400040d7a7a7a7a0010000000000000d5100000000000000000000200, raw.125 = 0x, Network-Subnet = 26.243.255.126/32
+match Opcode = 3, Hardware-Type = 0, Hardware-Address-Length = 0, Hop-Count = 245, Transaction-Id = 1130756, Number-of-Seconds = 1028, Flags = 1028, Client-IP-Address = 41.4.4.0, Your-IP-Address = 4.202.4.4, Server-IP-Address = 4.9.4.4, Gateway-IP-Address = 26.243.255.126, Server-Host-Name = "\240\265\%\a\200;`", Site-specific-18 = 0xb5250780316000001a29000000f8fffffc00000000000004000000d600005d000000000000000000000000000000000000000000000004ca0404040404041a0d000060b5250780346500001a00000000000000000000001a0d000020b5250780, raw.Message-Type = 0x0400000000fffb00000000000000000000000400040d7a7a7a7a0010000000000000d5100000000000000000000200, raw.V-I-Vendor-Specific = 0x, Network-Subnet = 26.243.255.126/32
 
 decode-pair 76 03 01 02 03
 match raw.Subnet-Selection-Option = 0x010203
index 3761dacb50daad3bb95a2dc95f8aaee588a7ef28..540ebd72d8ee4dd770bc6763bce39b5cccde955a 100644 (file)
@@ -24,7 +24,7 @@ match 7d 0e 00 00 0d e9 09 01 01 01 02 01 02 03 01 03
 #  PEN + option_len, where option_len 09 > end of attribute
 #
 decode-pair 7d 0d 00 00 00 09 09 05 06 61 61 2e 74 78 74
-match raw.V-I-Vendor-Specific.Cisco.5 = 0x09050661612e747874
+match raw.V-I-Vendor-Specific.Cisco = 0x09050661612e747874
 
 count
 match 15