From: Alan T. DeKok Date: Fri, 26 Jan 2024 16:35:16 +0000 (-0500) Subject: add foreign decoder for RADIUS and DHCPv4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0481c9587e3fbb997211981f17b37ef323e168c8;p=thirdparty%2Ffreeradius-server.git add foreign decoder for RADIUS and DHCPv4 --- diff --git a/share/dictionary/radius/dictionary.rfc9445 b/share/dictionary/radius/dictionary.rfc9445 index b64b37367ed..e1745e25144 100644 --- a/share/dictionary/radius/dictionary.rfc9445 +++ b/share/dictionary/radius/dictionary.rfc9445 @@ -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 diff --git a/src/protocols/dhcpv4/base.c b/src/protocols/dhcpv4/base.c index bff36f50b05..589def994b5 100644 --- a/src/protocols/dhcpv4/base.c +++ b/src/protocols/dhcpv4/base.c @@ -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, }; diff --git a/src/protocols/dhcpv4/decode.c b/src/protocols/dhcpv4/decode.c index 95665c0a261..bf7ab0e8427 100644 --- a/src/protocols/dhcpv4/decode.c +++ b/src/protocols/dhcpv4/decode.c @@ -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(); diff --git a/src/protocols/dhcpv4/dhcpv4.h b/src/protocols/dhcpv4/dhcpv4.h index 965989216e6..4a1a5ecbad2 100644 --- a/src/protocols/dhcpv4/dhcpv4.h +++ b/src/protocols/dhcpv4/dhcpv4.h @@ -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 */ diff --git a/src/protocols/radius/decode.c b/src/protocols/radius/decode.c index 6aaf3116627..ec77f9fa793 100644 --- a/src/protocols/radius/decode.c +++ b/src/protocols/radius/decode.c @@ -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 index 00000000000..861ce8af85d --- /dev/null +++ b/src/tests/unit/protocols/radius/foreign.txt @@ -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