]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Disable UPDATE and NOTIFY for non-IN classes
authorEvan Hunt <each@isc.org>
Wed, 4 Mar 2026 21:24:52 +0000 (13:24 -0800)
committerOndřej Surý <ondrej@isc.org>
Thu, 7 May 2026 13:14:06 +0000 (15:14 +0200)
Return NOTIMP for UPDATE and NOTIFY requests received for views with a
class other than IN.  Only QUERY is now supported for non-IN views such
as CHAOS.

When running dns dns_rdata_tostruct() with types that are only defined
for class IN, ensure that the class is correct before proceeding.

Add an assertion that any zone being updated is of class IN. (Note
that previously, a DLZ zone could have its class value set incorrectly
to NONE; this has been fixed.)

This addresses YWH-PGM40640-70 and YWH-PGM40640-73 (as well as any
similar problems that might have occurred in the future) by minimizing
the code paths that can be reached by rdata classes other than IN, so it
is safe for the implementation to assume that rdatatypes that are only
defined for class IN, such as SVCB or WKS, have been parsed and
validated, and not accepted as unknown/opaque data.

Fixes: isc-projects/bind9#5777
Fixes: isc-projects/bind9#5779
(cherry picked from commit 9ae24c32bec16c0f64225ef04f34670018bf0765)
(cherry picked from commit a2ca2408b3ff031c426c5dc785f550c9d30bf4aa)

bin/named/client.c
bin/named/server.c
bin/named/update.c
lib/dns/adb.c

index f6986cf3425b918db33bfe67941072f7dbd45a29..0f700cff96e486d0106eaf765d70fb64135621b2 100644 (file)
@@ -3151,11 +3151,19 @@ client_request(isc_task_t *task, isc_event_t *event) {
                break;
        case dns_opcode_update:
                CTRACE("update");
+               if (client->view->rdclass != dns_rdataclass_in) {
+                       ns_client_error(client, DNS_R_NOTIMP);
+                       break;
+               }
                ns_client_settimeout(client, 60);
                ns_update_start(client, sigresult);
                break;
        case dns_opcode_notify:
                CTRACE("notify");
+               if (client->view->rdclass != dns_rdataclass_in) {
+                       ns_client_error(client, DNS_R_NOTIMP);
+                       break;
+               }
                ns_client_settimeout(client, 60);
                ns_notify_start(client);
                break;
index b2b5e448806584d6ac29778350aa536b9851b9b3..c1d9485bd6b848bcdb00b6f944ce8e41ac6938b3 100644 (file)
@@ -1751,6 +1751,7 @@ dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) {
        dns_rdataclass_t zclass = view->rdclass;
        isc_result_t result;
 
+       dns_zone_setclass(zone, zclass);
        result = dns_zonemgr_managezone(ns_g_server->zonemgr, zone);
        if (result != ISC_R_SUCCESS)
                return (result);
index 6ad7d27d68df1bf4e4efa147afccd50d6c380c49..b5dd4e2448bf3105844dfbd7e4f1f44d15c688d7 100644 (file)
@@ -1265,7 +1265,10 @@ replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
                    dbsig.algorithm == updatesig.algorithm)
                        return (true);
        }
-       if (db_rr->type == dns_rdatatype_wks) {
+
+       if (db_rr->rdclass == dns_rdataclass_in &&
+           db_rr->type == dns_rdatatype_wks)
+       {
                /*
                 * Compare the address and protocol fields only.  These
                 * form the first five bytes of the RR data.  Do a
@@ -1408,8 +1411,7 @@ add_rr_prepare_action(void *data, rr_t *rr) {
  * 'rdata', and 'ttl', respectively.
  */
 static void
-get_current_rr(dns_message_t *msg, dns_section_t section,
-              dns_rdataclass_t zoneclass, dns_name_t **name,
+get_current_rr(dns_message_t *msg, dns_section_t section, dns_name_t **name,
               dns_rdata_t *rdata, dns_rdatatype_t *covers,
               dns_ttl_t *ttl, dns_rdataclass_t *update_class)
 {
@@ -1426,7 +1428,7 @@ get_current_rr(dns_message_t *msg, dns_section_t section,
        dns_rdataset_current(rdataset, rdata);
        INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE);
        *update_class = rdata->rdclass;
-       rdata->rdclass = zoneclass;
+       rdata->rdclass = dns_rdataclass_in;
 }
 
 /*%
@@ -1526,6 +1528,9 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
        isc_task_t *zonetask = NULL;
        ns_client_t *evclient;
 
+       /* Updates are only supported for class IN. */
+       INSIST(dns_zone_getclass(zone) == dns_rdataclass_in);
+
        event = (update_event_t *)
                isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE,
                                   update_action, NULL, sizeof(*event));
@@ -2502,8 +2507,8 @@ update_action(isc_task_t *task, isc_event_t *event) {
        isc_mem_t *mctx = client->mctx;
        dns_rdatatype_t covers;
        dns_message_t *request = client->message;
-       dns_rdataclass_t zoneclass;
        dns_name_t *zonename;
+       dns_rdataclass_t zoneclass;
        dns_ssutable_t *ssutable = NULL;
        dns_fixedname_t tmpnamefixed;
        dns_name_t *tmpname = NULL;
@@ -2534,6 +2539,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
        CHECK(checkqueryacl(client, dns_zone_getqueryacl(zone), zonename,
                            dns_zone_getupdateacl(zone), ssutable));
 
+       INSIST(dns_zone_getclass(zone) == dns_rdataclass_in);
        /*
         * Get old and new versions now that queryacl has been checked.
         */
@@ -2554,8 +2560,8 @@ update_action(isc_task_t *task, isc_event_t *event) {
                dns_rdataclass_t update_class;
                bool flag;
 
-               get_current_rr(request, DNS_SECTION_PREREQUISITE, zoneclass,
-                              &name, &rdata, &covers, &ttl, &update_class);
+               get_current_rr(request, DNS_SECTION_PREREQUISITE, &name, &rdata,
+                              &covers, &ttl, &update_class);
 
                if (ttl != 0)
                        PREREQFAILC(DNS_R_FORMERR,
@@ -2613,7 +2619,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
                                                     "satisfied");
                                }
                        }
-               } else if (update_class == zoneclass) {
+               } else if (update_class == dns_rdataclass_in) {
                        /* "temp<rr.name, rr.type> += rr;" */
                        result = temp_append(&temp, name, &rdata);
                        if (result != ISC_R_SUCCESS) {
@@ -2684,7 +2690,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
                dns_rdata_t rdata = DNS_RDATA_INIT;
                dns_ttl_t ttl;
                dns_rdataclass_t update_class;
-               get_current_rr(request, DNS_SECTION_UPDATE, zoneclass,
+               get_current_rr(request, DNS_SECTION_UPDATE,
                               &name, &rdata, &covers, &ttl, &update_class);
 
                if (! dns_name_issubdomain(name, zonename))
@@ -2795,11 +2801,10 @@ update_action(isc_task_t *task, isc_event_t *event) {
                dns_rdataclass_t update_class;
                bool flag;
 
-               get_current_rr(request, DNS_SECTION_UPDATE, zoneclass,
-                              &name, &rdata, &covers, &ttl, &update_class);
-
-               if (update_class == zoneclass) {
+               get_current_rr(request, DNS_SECTION_UPDATE, &name,
+                              &rdata, &covers, &ttl, &update_class);
 
+               if (update_class == dns_rdataclass_in) {
                        /*
                         * RFC1123 doesn't allow MF and MD in master zones.
                         */
index 82126f975ea0581566b79e73c1b8746d38c570c3..92609c14b490cb0a63c07d2f8b5d753ee156dae5 100644 (file)
@@ -898,7 +898,7 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
        INSIST(DNS_ADB_VALID(adb));
 
        rdtype = rdataset->type;
-       INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
+       REQUIRE(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
        if (rdtype == dns_rdatatype_a)
                findoptions = DNS_ADBFIND_INET;
        else