]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Process NSID and DNS COOKIE options when returning BADVERS
authorMark Andrews <marka@isc.org>
Fri, 25 Oct 2024 03:43:03 +0000 (14:43 +1100)
committerMark Andrews <marka@isc.org>
Tue, 15 Apr 2025 02:38:37 +0000 (02:38 +0000)
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

index 3eba3c61d90a51b7806690b0c9193ddd7ae169af..214e440440f29693d2b50257d7b113234f6613d1 100644 (file)
@@ -1580,17 +1580,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);
@@ -1602,6 +1591,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)) {
@@ -1683,6 +1683,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;