From 71875eb25a88ded29b567df0180492fc46007ab0 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 25 Oct 2024 14:43:03 +1100 Subject: [PATCH] Process NSID and DNS COOKIE options 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. (cherry picked from commit 0d9cab15551be8cdc06969c39eaf851732cda51d) --- 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 0b38ffc078..048a6c72b7 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); + /* + * When returning BADVERSION, only process + * DNS_OPT_NSID or DNS_OPT_COOKIE options. + */ + 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 = 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;