]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Validate DNS message CLASS early in request processing
authorOndřej Surý <ondrej@isc.org>
Wed, 4 Mar 2026 09:46:58 +0000 (10:46 +0100)
committerOndřej Surý <ondrej@isc.org>
Thu, 7 May 2026 13:14:06 +0000 (15:14 +0200)
Reject requests with unsupported or misused CLASS values before
further processing.  Only IN, CH, HS, RESERVED0 (for DNS Cookies),
ANY (for TKEY negotiation), and NONE (for DNS UPDATE) are accepted;
all other classes return NOTIMP.  Misuse of NONE or ANY outside
their allowed contexts returns FORMERR.

This adds further protection against bugs of the same general class
as YWH-PGM40640-70 and YWH-PGM40640-73.

(cherry picked from commit d41865a458b9ecd76be4097ac1bea1005cad72db)
(cherry picked from commit 1c8016c91c3674929f87cbe7ad09f3670e05ad4e)

bin/named/client.c
bin/tests/system/unknown/tests.sh

index 0f700cff96e486d0106eaf765d70fb64135621b2..dddb2a63faeec9948265c8f0b474d3866c9d11aa 100644 (file)
@@ -40,6 +40,7 @@
 #include <dns/dnstap.h>
 #include <dns/cache.h>
 #include <dns/edns.h>
+#include <dns/enumclass.h>
 #include <dns/events.h>
 #include <dns/message.h>
 #include <dns/peer.h>
@@ -2832,7 +2833,9 @@ client_request(isc_task_t *task, isc_event_t *event) {
                        goto cleanup;
        }
 
-       if (client->message->rdclass == 0) {
+       char classbuf[DNS_RDATACLASS_FORMATSIZE];
+       switch (client->message->rdclass) {
+       case dns_rdataclass_reserved0:
                if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0 &&
                    client->message->opcode == dns_opcode_query &&
                    client->message->counts[DNS_SECTION_QUESTION] == 0U)
@@ -2854,6 +2857,44 @@ client_request(isc_task_t *task, isc_event_t *event) {
                                      "message class could not be determined");
                ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
                goto cleanup;
+       case dns_rdataclass_in:
+               break;
+       case dns_rdataclass_chaos:
+               break;
+       case dns_rdataclass_hs:
+               break;
+       case dns_rdataclass_none:
+               if (client->message->opcode != dns_opcode_update) {
+                       ns_client_dumpmessage(client,
+                                             "message class NONE can be only "
+                                             "used in DNS updates");
+                       ns_client_error(client, DNS_R_FORMERR);
+                       return;
+               }
+               break;
+       case dns_rdataclass_any:
+               /*
+                * Required for TKEY negotiation.
+                */
+               if (client->message->tkey == 0) {
+                       ns_client_dumpmessage(client,
+                                             "message class ANY can be only "
+                                             "used for TKEY negotiation");
+                       ns_client_error(client, DNS_R_FORMERR);
+                       return;
+               }
+               break;
+       default:
+               dns_rdataclass_format(client->message->rdclass, classbuf,
+                                     sizeof(classbuf));
+               ns_client_dumpmessage(client, NULL);
+               ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+                             NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
+                             "message class could not be determined");
+               ns_client_dumpmessage(client, "message class could not be "
+                                             "determined");
+               ns_client_error(client, DNS_R_NOTIMP);
+               goto cleanup;
        }
 
        /*
@@ -2972,7 +3013,7 @@ client_request(isc_task_t *task, isc_event_t *event) {
                ns_client_log(client, NS_LOGCATEGORY_CLIENT,
                              NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
                              "no matching view in class '%s'", classname);
-               ns_client_dumpmessage(client, "no matching view in class");
+               ns_client_dumpmessage(client, NULL);
                ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
                goto cleanup;
        }
@@ -4251,8 +4292,9 @@ ns_client_dumpmessage(ns_client_t *client, const char *reason) {
        int len = 1024;
        isc_result_t result;
 
-       if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(1)))
+       if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(1)) || reason == NULL) {
                return;
+       }
 
        /*
         * Note that these are multiline debug messages.  We want a newline
index deb9a419abe0b09c72d00863a7710db2a3d1bae6..a6ceb7c69b09c3aeda1c11d952bf27f7a145d25e 100644 (file)
@@ -73,8 +73,8 @@ echo_i "querying for various representations of a CLASS10 TYPE1 record"
 for i in 1 2
 do
        ret=0
-       $DIG +short $DIGOPTS @10.53.0.1 a$i.example a class10 > dig.out || ret=1
-       echo '\# 4 0A000001' | $DIFF - dig.out || ret=1
+       $DIG $DIGOPTS @10.53.0.1 a$i.example a class10 > dig.out || ret=1
+        grep -q "NOTIMP" dig.out || ret=1
        if [ $ret != 0 ]
        then
                echo_i "#$i failed"
@@ -86,8 +86,8 @@ echo_i "querying for various representations of a CLASS10 TXT record"
 for i in 1 2 3 4
 do
        ret=0
-       $DIG +short $DIGOPTS @10.53.0.1 txt$i.example txt class10 > dig.out || ret=1
-       echo '"hello"' | $DIFF - dig.out || ret=1
+       $DIG $DIGOPTS @10.53.0.1 txt$i.example txt class10 > dig.out || ret=1
+        grep -q "NOTIMP" dig.out || ret=1
        if [ $ret != 0 ]
        then
                echo_i "#$i failed"
@@ -99,8 +99,8 @@ echo_i "querying for various representations of a CLASS10 TYPE123 record"
 for i in 1 2
 do
        ret=0
-       $DIG +short $DIGOPTS @10.53.0.1 unk$i.example type123 class10 > dig.out || ret=1
-       echo '\# 1 00' | $DIFF - dig.out || ret=1
+       $DIG $DIGOPTS @10.53.0.1 unk$i.example type123 class10 > dig.out || ret=1
+        grep -q "NOTIMP" dig.out || ret=1
        if [ $ret != 0 ]
        then
                echo_i "#$i failed"