From d6a6f0b13d2a79da2c0d7fdf4b2f016790eb6938 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 25 Oct 2024 14:43:03 +1100 Subject: [PATCH] Also process NSID and DNS COOKIE when returning BADVERS This will help identify the broken server if we happen to break EDNS version negotiation. It will also help protect the client from spoofed BADVERSION responses. --- lib/ns/client.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/ns/client.c b/lib/ns/client.c index 222a4f4f50..c02a25a390 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -1550,17 +1550,6 @@ process_opt(ns_client_t *client, dns_rdataset_t *opt) { * XXXRTH need library support for this! */ client->ednsversion = (opt->ttl & 0x00FF0000) >> 16; - if (client->ednsversion > DNS_EDNS_VERSION) { - ns_stats_increment(client->manager->sctx->nsstats, - ns_statscounter_badednsver); - result = ns_client_addopt(client, client->message, - &client->opt); - if (result == ISC_R_SUCCESS) { - result = DNS_R_BADVERS; - } - ns_client_error(client, result); - return result; - } /* Check for NSID request */ result = dns_rdataset_first(opt); @@ -1572,6 +1561,17 @@ process_opt(ns_client_t *client, dns_rdataset_t *opt) { while (isc_buffer_remaininglength(&optbuf) >= 4) { optcode = isc_buffer_getuint16(&optbuf); optlen = isc_buffer_getuint16(&optbuf); + /* + * Only process DNS_OPT_NSID or DNS_OPT_COOKIE when + * returning BADVERSION. + */ + if (client->ednsversion > DNS_EDNS_VERSION && + optcode != DNS_OPT_NSID && + optcode != DNS_OPT_COOKIE) + { + isc_buffer_forward(&optbuf, optlen); + continue; + } switch (optcode) { case DNS_OPT_NSID: if (!WANTNSID(client)) { @@ -1643,6 +1643,18 @@ process_opt(ns_client_t *client, dns_rdataset_t *opt) { } } + if (client->ednsversion > DNS_EDNS_VERSION) { + ns_stats_increment(client->manager->sctx->nsstats, + ns_statscounter_badednsver); + result = ns_client_addopt(client, client->message, + &client->opt); + if (result == ISC_R_SUCCESS || result == ISC_R_NOMORE) { + result = DNS_R_BADVERS; + } + ns_client_error(client, result); + return (result); + } + ns_stats_increment(client->manager->sctx->nsstats, ns_statscounter_edns0in); client->attributes |= NS_CLIENTATTR_WANTOPT;