From: Alan T. DeKok Date: Sun, 28 Jan 2024 16:22:37 +0000 (-0500) Subject: add foreign handlers for DHCPv6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d590f8a83216e684cb79484ad0e57828bef521ee;p=thirdparty%2Ffreeradius-server.git add foreign handlers for DHCPv6 --- diff --git a/share/dictionary/radius/dictionary.rfc9445 b/share/dictionary/radius/dictionary.rfc9445 index e1745e25144..efd3ecd3697 100644 --- a/share/dictionary/radius/dictionary.rfc9445 +++ b/share/dictionary/radius/dictionary.rfc9445 @@ -8,5 +8,5 @@ # # $Id$ # -ATTRIBUTE DHCPv6-Options 245.3 octets # formatted as DHCPv6 options +ATTRIBUTE DHCPv6-Options 245.3 group ref=..DHCPv6 ATTRIBUTE DHCPv4-Options 245.4 group ref=..DHCPv4 diff --git a/src/protocols/dhcpv6/base.c b/src/protocols/dhcpv6/base.c index d7d122779cf..514cac97c2b 100644 --- a/src/protocols/dhcpv6/base.c +++ b/src/protocols/dhcpv6/base.c @@ -993,4 +993,11 @@ fr_dict_protocol_t libfreeradius_dhcpv6_dict_protocol = { .subtype_table = subtype_table, .subtype_table_len = NUM_ELEMENTS(subtype_table), .attr_valid = attr_valid, + + + .init = fr_dhcpv6_global_init, + .free = fr_dhcpv6_global_free, + + .encode = fr_dhcpv6_encode_foreign, + .decode = fr_dhcpv6_decode_foreign, }; diff --git a/src/protocols/dhcpv6/decode.c b/src/protocols/dhcpv6/decode.c index 5998a10a799..8ea258b98fa 100644 --- a/src/protocols/dhcpv6/decode.c +++ b/src/protocols/dhcpv6/decode.c @@ -421,6 +421,43 @@ ssize_t fr_dhcpv6_decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out, return decode_option(ctx, out, fr_dict_root(dict_dhcpv6), data, data_len, decode_ctx); } +ssize_t fr_dhcpv6_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_dhcpv6_decode_ctx_t decode_ctx = {}; + + decode_ctx.tmp_ctx = talloc(ctx, uint8_t); + + attr = data; + end = data + data_len; + + while (attr < end) { + slen = fr_dhcpv6_decode_option(ctx, out, attr, (end - attr), &decode_ctx); + if (slen < 0) { + talloc_free(decode_ctx.tmp_ctx); + return slen; + } + + /* + * 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; +} + /* * Stub functions to enable test context */ diff --git a/src/protocols/dhcpv6/dhcpv6.h b/src/protocols/dhcpv6/dhcpv6.h index 2b880655f07..b9484cc5a4e 100644 --- a/src/protocols/dhcpv6/dhcpv6.h +++ b/src/protocols/dhcpv6/dhcpv6.h @@ -171,8 +171,13 @@ void fr_dhcpv6_global_free(void); */ ssize_t fr_dhcpv6_encode_option(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void * encode_ctx); +ssize_t fr_dhcpv6_encode_foreign(fr_dbuff_t *dbuff, fr_pair_list_t const *list); + /* * decode.c */ ssize_t fr_dhcpv6_decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *data, size_t data_len, void *decode_ctx); + +ssize_t fr_dhcpv6_decode_foreign(TALLOC_CTX *ctx, fr_pair_list_t *out, + uint8_t const *data, size_t data_len); diff --git a/src/protocols/dhcpv6/encode.c b/src/protocols/dhcpv6/encode.c index 7e95163b117..2d4f48addb7 100644 --- a/src/protocols/dhcpv6/encode.c +++ b/src/protocols/dhcpv6/encode.c @@ -713,6 +713,34 @@ ssize_t fr_dhcpv6_encode_option(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void * return fr_dbuff_set(dbuff, &work_dbuff); } +ssize_t fr_dhcpv6_encode_foreign(fr_dbuff_t *dbuff, fr_pair_list_t const *list) +{ + ssize_t slen; + fr_dcursor_t cursor; + fr_dbuff_t work_dbuff = FR_DBUFF(dbuff); + + fr_assert(dict_dhcpv6 != NULL); + + fr_pair_dcursor_iter_init(&cursor, list, fr_dhcpv6_next_encodable, dict_dhcpv6); + + /* + * Loop over all DHCPv4 options. + * + * Unlike fr_dhcpv4_encode_dbuff(), we don't sort the options. If that causes problems, we will + * deal with it later. + */ + while (fr_dcursor_current(&cursor) != NULL) { + slen = fr_dhcpv6_encode_option(&work_dbuff, &cursor, &(fr_dhcpv6_encode_ctx_t){ .root = fr_dict_root(dict_dhcpv6) }); + if (slen <= 0) return slen - fr_dbuff_used(&work_dbuff); + } + + FR_PROTO_TRACE("Foreign option is %zu byte(s)", fr_dbuff_used(&work_dbuff)); + FR_PROTO_HEX_DUMP(dbuff->p, fr_dbuff_used(&work_dbuff), NULL); + + return fr_dbuff_set(dbuff, &work_dbuff); +} + + static int _test_ctx_free(UNUSED fr_dhcpv6_encode_ctx_t *ctx) { fr_dhcpv6_global_free(); diff --git a/src/tests/unit/protocols/radius/foreign.txt b/src/tests/unit/protocols/radius/foreign.txt index f79a86bfa88..a8ecc50ad0b 100644 --- a/src/tests/unit/protocols/radius/foreign.txt +++ b/src/tests/unit/protocols/radius/foreign.txt @@ -30,6 +30,17 @@ match 1a ff 00 00 19 7f 66 fa 02 04 00 00 08 40 38 f0 61 61 61 61 61 61 61 61 61 # No decode as of yet of concatenated DHCPv4 options # +###################################################################### +# +# DHCPv6 +# +encode-pair Extended-Attribute-5 = { DHCPv6-Options = { Rapid-Commit = true, Information-Refresh-Time = 6809 } } +match f5 10 03 00 00 0e 00 00 00 20 00 04 00 00 1a 99 + +decode-pair - +match Extended-Attribute-5 = { DHCPv6-Options = { Rapid-Commit = yes, Information-Refresh-Time = 6809 } } + + ###################################################################### # # Various cross-protocol tests taken from fuzzer output. @@ -46,4 +57,4 @@ decode-proto 04ac00edd604040404040404040404040302d700f30303f5040402f50303f504030 match Packet-Type = Accounting-Request, Packet-Authentication-Vector = 0xd604040404040404040404040302d700, raw.Extended-Attribute-3 = 0x03, raw.Extended-Attribute-5 = 0x0402, raw.Extended-Attribute-5 = 0x03, raw.Extended-Attribute-5 = 0x0303, raw.Extended-Attribute-5 = 0x0402, raw.Extended-Attribute-5 = 0x03, User-Password = "\366\356", raw.Extended-Attribute-3 = 0x03, raw.Extended-Attribute-5 = 0x0402, raw.Extended-Attribute-5 = 0x03, raw.Extended-Attribute-5 = 0x0402, User-Password = "\366\356", raw.Extended-Attribute-3 = 0x03, raw.Extended-Attribute-5 = 0x0402, raw.Extended-Attribute-5 = 0x03, User-Password = "\366\356", raw.Extended-Attribute-3 = 0x03, raw.Extended-Attribute-5 = 0x0402, raw.Extended-Attribute-5 = 0x03, raw.Extended-Attribute-5 = 0x0403, raw.Extended-Attribute-5 = 0x0402, raw.Extended-Attribute-5 = 0x02, raw.214 = 0x0402, User-Password = "\366\356", raw.Extended-Attribute-3 = 0x03, raw.Extended-Attribute-5 = 0x0402, raw.Extended-Attribute-5 = 0x03, User-Password = "\366\356", raw.Extended-Attribute-3 = 0x03, raw.Extended-Attribute-5 = 0x0402, raw.Extended-Attribute-5 = 0x03, Extended-Attribute-5 = { raw.DHCPv4-Options = 0x2a006004040404040404f30303f5040402f50303040202046000f30303f5040402f50303f5040303f5040402f50303040202046000f30303f5040402f50303f5040402020203023d046000f30303f5040303f5030402040404 }, raw.NAS-IP-Address = 0x0404, raw.NAS-IP-Address = 0x0404 count -match 19 +match 23