]> 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)
committerEvan Hunt <each@isc.org>
Wed, 6 May 2026 04:05:37 +0000 (21:05 -0700)
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/server.c
lib/dns/adb.c
lib/ns/client.c
lib/ns/update.c

index fc8b3e8a0ccddb0d3d3adfdf943c2f322e9c8950..f27ed2157221f9163dd2f9a3ea3e55c8e3cd2de1 100644 (file)
@@ -1932,10 +1932,12 @@ 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(named_g_server->zonemgr, zone);
        if (result != ISC_R_SUCCESS) {
                return (result);
        }
+
        dns_zone_setstats(zone, named_g_server->zonestats);
 
        return (named_zone_configure_writeable_dlz(dlzdb, zone, zclass,
index 99e83100de5c3498d39aee3faf024b50ce1f0dc8..fefec56e50707c01a6e4387476ce5dd9a0d96980 100644 (file)
@@ -932,7 +932,8 @@ 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 {
index 5f958fdf341480c1a60dc7a5a4bd899cbf71b716..fed6a57176c3d1b3ea20f2a73761026c6fcfbb83 100644 (file)
@@ -2194,6 +2194,10 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
                break;
        case dns_opcode_update:
                CTRACE("update");
+               if (client->view->rdclass != dns_rdataclass_in) {
+                       ns_client_error(client, DNS_R_NOTIMP);
+                       break;
+               }
 #ifdef HAVE_DNSTAP
                dns_dt_send(client->view, DNS_DTTYPE_UQ, &client->peeraddr,
                            &client->destsockaddr, TCP_CLIENT(client), NULL,
@@ -2204,6 +2208,10 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
                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, handle);
                break;
index d9cea2c4c6a869e0f2ab98e3d872a07af4a8b935..30a9206a6627128c1f532e32d63f0d3ba24da5a7 100644 (file)
@@ -1294,7 +1294,10 @@ replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
                        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
@@ -1438,8 +1441,7 @@ failure:
  * '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) {
        dns_rdataset_t *rdataset;
@@ -1455,7 +1457,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;
 }
 
 /*%
@@ -1557,7 +1559,6 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
        dns_message_t *request = client->message;
        dns_aclenv_t *env =
                ns_interfacemgr_getaclenv(client->manager->interface->mgr);
-       dns_rdataclass_t zoneclass;
        dns_rdatatype_t covers;
        dns_name_t *zonename = NULL;
        dns_db_t *db = NULL;
@@ -1565,10 +1566,12 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
 
        CHECK(dns_zone_getdb(zone, &db));
        zonename = dns_db_origin(db);
-       zoneclass = dns_db_class(db);
        dns_zone_getssutable(zone, &ssutable);
        dns_db_currentversion(db, &ver);
 
+       /* Updates are only supported for class IN. */
+       INSIST(dns_zone_getclass(zone) == dns_rdataclass_in);
+
        /*
         * Update message processing can leak record existence information
         * so check that we are allowed to query this zone.  Additionally,
@@ -1609,13 +1612,13 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
                dns_ttl_t ttl;
                dns_rdataclass_t update_class;
 
-               get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, &name,
+               get_current_rr(request, DNS_SECTION_UPDATE, &name,
                               &rdata, &covers, &ttl, &update_class);
 
                if (!dns_name_issubdomain(name, zonename)) {
                        FAILC(DNS_R_NOTZONE, "update RR is outside zone");
                }
-               if (update_class == zoneclass) {
+               if (update_class == dns_rdataclass_in) {
                        /*
                         * Check for meta-RRs.  The RFC2136 pseudocode says
                         * check for ANY|AXFR|MAILA|MAILB, but the text adds
@@ -2755,9 +2758,7 @@ 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 = NULL;
-       dns_ssutable_t *ssutable = NULL;
        dns_fixedname_t tmpnamefixed;
        dns_name_t *tmpname = NULL;
        dns_zoneopt_t options;
@@ -2776,10 +2777,9 @@ update_action(isc_task_t *task, isc_event_t *event) {
 
        CHECK(dns_zone_getdb(zone, &db));
        zonename = dns_db_origin(db);
-       zoneclass = dns_db_class(db);
-       dns_zone_getssutable(zone, &ssutable);
        options = dns_zone_getoptions(zone);
 
+       INSIST(dns_zone_getclass(zone) == dns_rdataclass_in);
        /*
         * Get old and new versions now that queryacl has been checked.
         */
@@ -2800,8 +2800,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, "prerequisite TTL is not "
@@ -2868,7 +2868,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) {
@@ -2927,10 +2927,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,
+               get_current_rr(request, DNS_SECTION_UPDATE, &name,
                               &rdata, &covers, &ttl, &update_class);
 
-               if (update_class == zoneclass) {
+               if (update_class == dns_rdataclass_in) {
                        /*
                         * RFC1123 doesn't allow MF and MD in master zones.
                         */
@@ -3516,10 +3516,6 @@ common:
                dns_db_detach(&db);
        }
 
-       if (ssutable != NULL) {
-               dns_ssutable_detach(&ssutable);
-       }
-
        isc_task_detach(&task);
        uev->result = result;
        if (zone != NULL) {