]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add foreign decoder for RADIUS and DHCPv4
authorAlan T. DeKok <aland@freeradius.org>
Fri, 26 Jan 2024 16:35:16 +0000 (11:35 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 26 Jan 2024 16:35:48 +0000 (11:35 -0500)
share/dictionary/radius/dictionary.rfc9445
src/protocols/dhcpv4/base.c
src/protocols/dhcpv4/decode.c
src/protocols/dhcpv4/dhcpv4.h
src/protocols/radius/decode.c
src/tests/unit/protocols/radius/foreign.txt [new file with mode: 0644]

index b64b37367ed914a6bcdcefcbaeae7890e7f5bc5f..e1745e251441309e1fe628b6503c0a8c4d792f8f 100644 (file)
@@ -9,4 +9,4 @@
 #      $Id$
 #
 ATTRIBUTE      DHCPv6-Options                          245.3   octets # formatted as DHCPv6 options
-ATTRIBUTE      DHCPv4-Options                          245.4   octets # formatted as DHCPv4 options
+ATTRIBUTE      DHCPv4-Options                          245.4   group ref=..DHCPv4
index bff36f50b05869fea4b8680d142b16ef6ebb03dc..589def994b5a14341449a1b0123ab4dc6d2998a6 100644 (file)
@@ -734,4 +734,5 @@ fr_dict_protocol_t libfreeradius_dhcpv4_dict_protocol = {
        .subtype_table_len = NUM_ELEMENTS(subtype_table),
        .attr_valid = attr_valid,
        .encode         = fr_dhcpv4_encode_foreign,
+       .decode         = fr_dhcpv4_decode_foreign,
 };
index 95665c0a261a416f4c1496148c950cd3b856b8d4..bf7ab0e8427cbacadf1a67a983d122663eeabe0b 100644 (file)
@@ -637,6 +637,44 @@ ssize_t fr_dhcpv4_decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
        return data[1] + 2;
 }
 
+ssize_t        fr_dhcpv4_decode_foreign(TALLOC_CTX *ctx, fr_pair_list_t *out,
+                                uint8_t const *data, size_t data_len)
+{
+       ssize_t slen;
+       uint8_t const *attr, *end;
+
+       fr_dhcpv4_ctx_t decode_ctx = {};
+
+       decode_ctx.tmp_ctx = talloc(ctx, uint8_t);
+
+       attr = data;
+       end = data + data_len;
+
+       while (attr < end) {
+               slen = fr_dhcpv4_decode_option(ctx, out, attr, (end - attr), &decode_ctx);
+               if (slen < 0) {
+                       talloc_free(decode_ctx.tmp_ctx);
+                       return slen - (attr - data);
+               }
+
+               /*
+                *      If slen is larger than the room in the packet,
+                *      all kinds of bad things happen.
+                */
+                if (!fr_cond_assert(slen <= (end - attr))) {
+                       talloc_free(decode_ctx.tmp_ctx);
+                        return -slen - (attr - data);
+                }
+
+               attr += slen;
+               talloc_free_children(decode_ctx.tmp_ctx);
+       }
+
+       talloc_free(decode_ctx.tmp_ctx);
+       return data_len;
+}
+
+
 static int _decode_test_ctx(UNUSED fr_dhcpv4_ctx_t *test_ctx)
 {
        fr_dhcpv4_global_free();
index 965989216e6620690c851059fa04c53f04f15fe9..4a1a5ecbad23771f5be8f63822af2ad60d7d24cd 100644 (file)
@@ -177,6 +177,9 @@ void                fr_dhcpv4_print_hex(FILE *fp, uint8_t const *packet, size_t packet_len);
 ssize_t                fr_dhcpv4_decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out,
                                        uint8_t const *data, size_t len, void *decode_ctx) CC_HINT(nonnull);
 
+ssize_t                fr_dhcpv4_decode_foreign(TALLOC_CTX *ctx, fr_pair_list_t *out,
+                                        uint8_t const *data, size_t data_len) CC_HINT(nonnull);
+
 /*
  *     encode.c
  */
index 6aaf3116627b47fc892deacb41184b761832e009..ec77f9fa793ee88e6ec129ed04042ed97bc26d2c 100644 (file)
@@ -1780,6 +1780,33 @@ ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, fr_pair_list_t *out,
                if (ret < 0) goto raw;
                return attr_len;
 
+       case FR_TYPE_GROUP:
+       {
+               fr_dict_attr_t const *ref;
+               fr_dict_protocol_t const *proto;
+
+               ref = fr_dict_attr_ref(parent);
+               if (!ref) goto raw;
+
+               fr_assert(ref->dict != parent->dict);
+
+               proto = fr_dict_protocol(ref->dict);
+               fr_assert(proto != NULL);
+
+               if (!proto->decode) goto raw;
+
+               vp = fr_pair_afrom_da(ctx, parent);
+               if (!vp) return -1;
+
+               ret = proto->decode(vp, &vp->vp_group, p, attr_len);
+               if (ret < 0) goto raw;
+
+               vp->vp_tainted = true;
+
+               fr_pair_append(out, vp);
+               return attr_len;
+       }
+
        default:
        raw:
                if (vp) talloc_free(vp);
diff --git a/src/tests/unit/protocols/radius/foreign.txt b/src/tests/unit/protocols/radius/foreign.txt
new file mode 100644 (file)
index 0000000..861ce8a
--- /dev/null
@@ -0,0 +1,12 @@
+proto radius
+proto-dictionary radius
+fuzzer-out radius
+
+encode-pair Extended-Attribute-5.DHCPv4-Options := { Time-Offset = 2112 }
+match f5 0a 04 00 02 04 00 00 08 40
+
+decode-pair -
+match Extended-Attribute-5 = { DHCPv4-Options = { Time-Offset = 2112 } }
+
+count
+match 7