From: Alan T. DeKok Date: Thu, 9 Jul 2026 15:14:33 +0000 (-0400) Subject: We don't support DHCPv6 Reconfigure messages. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f7e95f68d6134f906ab7be5d34a83ded1cb2fd83;p=thirdparty%2Ffreeradius-server.git We don't support DHCPv6 Reconfigure messages. Because (a) most clients don't support it, and (b) we still need to write the code to handle the Auth option. Which includes a bunch of additional requirements about storing keys and replay counters. --- diff --git a/src/protocols/dhcpv6/attrs.h b/src/protocols/dhcpv6/attrs.h index 49311f658a7..6082b728b1b 100644 --- a/src/protocols/dhcpv6/attrs.h +++ b/src/protocols/dhcpv6/attrs.h @@ -36,6 +36,7 @@ extern HIDDEN fr_dict_attr_t const *attr_hop_count; extern HIDDEN fr_dict_attr_t const *attr_relay_link_address; extern HIDDEN fr_dict_attr_t const *attr_relay_peer_address; extern HIDDEN fr_dict_attr_t const *attr_relay_message; +extern HIDDEN fr_dict_attr_t const *attr_auth; /* * A private function that is used only in base.c and encode.c diff --git a/src/protocols/dhcpv6/base.c b/src/protocols/dhcpv6/base.c index 9165b1c7fef..ca7d83c1b6c 100644 --- a/src/protocols/dhcpv6/base.c +++ b/src/protocols/dhcpv6/base.c @@ -53,6 +53,7 @@ fr_dict_attr_t const *attr_relay_link_address; fr_dict_attr_t const *attr_relay_peer_address; fr_dict_attr_t const *attr_relay_message; fr_dict_attr_t const *attr_option_request; +fr_dict_attr_t const *attr_auth; extern fr_dict_attr_autoload_t libfreeradius_dhcpv6_dict_attr[]; fr_dict_attr_autoload_t libfreeradius_dhcpv6_dict_attr[] = { @@ -63,6 +64,7 @@ fr_dict_attr_autoload_t libfreeradius_dhcpv6_dict_attr[] = { { .out = &attr_relay_peer_address, .name = "Relay-Peer-Address", .type = FR_TYPE_IPV6_ADDR, .dict = &dict_dhcpv6 }, { .out = &attr_relay_message, .name = "Relay-Message", .type = FR_TYPE_GROUP, .dict = &dict_dhcpv6 }, { .out = &attr_option_request, .name = "Option-Request", .type = FR_TYPE_ATTR, .dict = &dict_dhcpv6 }, + { .out = &attr_auth, .name = "Auth", .type = FR_TYPE_STRUCT, .dict = &dict_dhcpv6 }, DICT_AUTOLOAD_TERMINATOR }; @@ -348,6 +350,47 @@ static bool verify_to_client(uint8_t const *packet, size_t packet_len, fr_dhcpv6 goto check_duid; case FR_PACKET_TYPE_VALUE_RECONFIGURE: +#if 1 + /* + * See RFC 8415 Section 18 (option format), and Section 20 (functionality). + * + * In order to support sending Reconfigure messages, we have to support the Auth option. + * Except that common clients don't support it: + * + * https://www.cisco.com/c/en/us/td/docs/routers/asr920/configuration/guide/ipaddr-dhcp/17-1-1/b-dhcp-xe-17-1-asr920/b-dhcp-xe-17-1-asr920_chapter_0101.html + * + * "DHCPv6 Reconfigure message type is not be supported on the Cisco ASR920 Series routers." + * + * So we don't support it, either. The rest of the comments here are notes about what we + * would need to do in order to support Reconfigure, and the Auth option. + * + * If auth.type == 1, the contents of the attribute are just a reconfigure key, which is + * sent over the network in the clear. The server has to get the key from somewhere, OR + * create it from a CSRNG and then store it. The client just stores it somewhere. + * Except that the key is sent over the network in the clear, which make is pretty much + * useless for security. + * + * If auth.type == 2, then we need to check the encode/decode context for a key, and if + * not fail. + * + * For encode, encode the structure and remember in the encode context where we encoded + * it. Then when we are finished encoding the entire packet, go back and do an HMAC-MD5 + * over the packet and update the auth.value field. + * + * We also have to ignore any supplied auth.rdm and auth.replay-detection field, and then + * force auth.rdm=0, and set auth.reply-detection to the current 64-bit NTP time. The + * replay-detection field is a monotonically increasing 64-bit value which is saved + * across server restarts. So an NTP time is the easiest way to manage that. + * + * For decode, we have to check the reply-detection field, and fail if it's smaller than + * what we expect. Then, remember where the Auth option is in the packet, go back and do + * an HMAC-MD5 over the packet. + * + * See also references to attr_auth in encode.c and decode.c. + */ + fr_strerror_const("Sending Reconfigure to a client is not supported"); + return false; +#else if (!fr_dhcpv6_option_find(options, end, FR_SERVER_ID)) goto fail_sid; option = fr_dhcpv6_option_find(options, end, FR_CLIENT_ID); @@ -378,11 +421,12 @@ static bool verify_to_client(uint8_t const *packet, size_t packet_len, fr_dhcpv6 fr_strerror_const("Invalid Reconf-Msg option value"); return false; } + /* - * @todo - check for authentication option and - * verify it. + * @todo - Do an HMAC-MD5 of the Auth option. */ break; +#endif case FR_DHCPV6_RELAY_REPLY: if (packet_len < DHCPV6_RELAY_HDR_LEN) { diff --git a/src/protocols/dhcpv6/decode.c b/src/protocols/dhcpv6/decode.c index 1153050cb7b..3f36d72a808 100644 --- a/src/protocols/dhcpv6/decode.c +++ b/src/protocols/dhcpv6/decode.c @@ -393,6 +393,22 @@ static ssize_t decode_option(TALLOC_CTX *ctx, fr_pair_list_t *out, } else if (da->type == FR_TYPE_TLV) { slen = fr_pair_tlvs_from_network(ctx, out, da, data + 4, len, decode_ctx, decode_option, NULL, true); + } else if (da == attr_auth) { + /* + * See RFC 8415 Section 18 (option format), and Section 20 (functionality). + * + * The Auth option can be sent from a server to client in a Reply message, and contains a + * 128-bit secret key that is recorded somewhere on the server side. + * + * The Auth option can be sent from a server to a client in a Reconfigure message, and + * contains an HMAC-MD5 of the packet and the secret key. + * + * We are not currently a DHCPv6 client, so we do not support the Auth option, or + * Reconfigure messages. See verify_to_client() in base.c. + */ + fr_strerror_const("The 'Auth' option is not supported"); + return -1; + } else { slen = decode_value(ctx, out, da, data + 4, len, decode_ctx); } diff --git a/src/protocols/dhcpv6/encode.c b/src/protocols/dhcpv6/encode.c index ce22e2a466d..247c2d08f80 100644 --- a/src/protocols/dhcpv6/encode.c +++ b/src/protocols/dhcpv6/encode.c @@ -715,6 +715,25 @@ ssize_t fr_dhcpv6_encode_option(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void * slen = encode_rfc(&work_dbuff, &da_stack, depth, cursor, encode_ctx); break; + case FR_TYPE_STRUCT: + /* + * See RFC 8415 Section 18 (option format), and Section 20 (functionality). + * + * The Auth option can be sent from a server to client in a Reply message, and contains a + * 128-bit secret key that is recorded somewhere on the server side. + * + * The Auth option can be sent from a server to a client in a Reconfigure message, and + * contains an HMAC-MD5 of the packet and the secret key. + * + * We are not currently a DHCPv6 client, so we do not support the Auth option, or + * Reconfigure messages. See verify_to_client() in base.c. + */ + if (da_stack.da[depth] == attr_auth) { + fr_strerror_const("The 'Auth' option is not supported"); + return -1; + } + FALL_THROUGH; + default: slen = encode_child(&work_dbuff, &da_stack, depth, cursor, encode_ctx); break; diff --git a/src/tests/unit/protocols/dhcpv6/rfc8415.txt b/src/tests/unit/protocols/dhcpv6/rfc8415.txt index 9a70fa053e8..70dd8278f56 100644 --- a/src/tests/unit/protocols/dhcpv6/rfc8415.txt +++ b/src/tests/unit/protocols/dhcpv6/rfc8415.txt @@ -453,10 +453,10 @@ match Elapsed-Time = 45887 # option-len field). # encode-pair Auth.Protocol = Reconfigure-Key, Auth.Algorithm = HMAC-MD5, Auth.Replay-Detection-Method = Monotonicly-Increasing-Value, Auth.Replay-Detection = 1234567890, Auth.Information = 0x010203040506070809101112131415 -match 00 0b 00 1a 03 01 00 00 00 00 00 49 96 02 d2 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 +match ERROR: The 'Auth' option is not supported -decode-pair - -match Auth = { Protocol = ::Reconfigure-Key, Algorithm = ::HMAC-MD5, Replay-Detection-Method = ::Monotonicly-Increasing-Value, Replay-Detection = 1234567890, Information = 0x010203040506070809101112131415 } +decode-pair 00 0b 00 1a 03 01 00 00 00 00 00 49 96 02 d2 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 +match ERROR: The 'Auth' option is not supported # # 21.12. Server Unicast Option