]> 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)
committerMichał Kępień <michal@isc.org>
Thu, 7 May 2026 11:32:15 +0000 (13:32 +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
bin/named/server.c
lib/dns/adb.c
lib/ns/client.c
lib/ns/update.c

index 1a98450e81178da9d5632166839f7eb2fd4820f2..d584c1249e859006b1858d1054d9805ffc2962c3 100644 (file)
@@ -1715,6 +1715,7 @@ dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) {
        dns_name_t *origin = dns_zone_getorigin(zone);
        dns_rdataclass_t zclass = view->rdclass;
 
+       dns_zone_setclass(zone, zclass);
        RETERR(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
 
        dns_zone_setstats(zone, named_g_server->zonestats);
index f51b2a88216a0af7c28a13e0d15152e448bf6001..758f0d8187f3688b095917691007c5206712de52 100644 (file)
@@ -566,6 +566,9 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
 
        rdtype = rdataset->type;
 
+       REQUIRE(rdataset->rdclass == dns_rdataclass_in);
+       REQUIRE(dns_rdatatype_isaddr(rdtype));
+
        switch (rdataset->trust) {
        case dns_trust_glue:
        case dns_trust_additional:
@@ -584,8 +587,6 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
                rdataset->ttl = ttlclamp(rdataset->ttl);
        }
 
-       REQUIRE(dns_rdatatype_isaddr(rdtype));
-
        DNS_RDATASET_FOREACH(rdataset) {
                /* FIXME: Move to a separate function */
                dns_adbnamehooklist_t *hookhead = NULL;
index 7a4fd19771068fee7536424160f63cc74786c224..2faf971041f82298df8d7236f575005377c3263c 100644 (file)
@@ -2459,6 +2459,10 @@ ns_client_request_continue(void *arg) {
                break;
        case dns_opcode_update:
                CTRACE("update");
+               if (client->inner.view->rdclass != dns_rdataclass_in) {
+                       ns_client_error(client, DNS_R_NOTIMP);
+                       break;
+               }
 #ifdef HAVE_DNSTAP
                dns_dt_send(client->inner.view, DNS_DTTYPE_UQ,
                            &client->inner.peeraddr,
@@ -2472,6 +2476,10 @@ ns_client_request_continue(void *arg) {
                break;
        case dns_opcode_notify:
                CTRACE("notify");
+               if (client->inner.view->rdclass != dns_rdataclass_in) {
+                       ns_client_error(client, DNS_R_NOTIMP);
+                       break;
+               }
                ns_client_settimeout(client, 60);
                ns_notify_start(client, client->inner.handle);
                break;
index 93240ca250c2108d0815de17bd7b8ec51b837889..b5ea58287911ebf7b3ededebf2e87f8e7f3672e7 100644 (file)
@@ -966,7 +966,9 @@ ssu_checkrr(void *data, rr_t *rr) {
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
                target = &ptr.ptr;
        }
-       if (rr->rdata.type == dns_rdatatype_srv) {
+       if (rr->rdata.rdclass == dns_rdataclass_in &&
+           rr->rdata.type == dns_rdatatype_srv)
+       {
                result = dns_rdata_tostruct(&rr->rdata, &srv, NULL);
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
                target = &srv.target;
@@ -1311,7 +1313,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
@@ -1451,9 +1456,8 @@ add_rr_prepare_action(void *data, rr_t *rr) {
  * 'rdata', and 'ttl', respectively.
  */
 static void
-get_current_rr(dns_rdataclass_t zoneclass, dns_name_t *name, dns_rdata_t *rdata,
-              dns_rdatatype_t *covers, dns_ttl_t *ttl,
-              dns_rdataclass_t *update_class) {
+get_current_rr(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;
        isc_result_t result;
        rdataset = ISC_LIST_HEAD(name->list);
@@ -1466,7 +1470,7 @@ get_current_rr(dns_rdataclass_t zoneclass, dns_name_t *name, dns_rdata_t *rdata,
        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;
 }
 
 /*%
@@ -1562,7 +1566,6 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
        dns_message_t *request = client->message;
        isc_mem_t *mctx = client->manager->mctx;
        dns_aclenv_t *env = client->manager->aclenv;
-       dns_rdataclass_t zoneclass;
        dns_rdatatype_t covers;
        dns_name_t *zonename = NULL;
        unsigned int *maxbytype = NULL;
@@ -1574,11 +1577,13 @@ send_update(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);
        options = dns_zone_getoptions(zone);
        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,
@@ -1623,13 +1628,12 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
                dns_rdataclass_t update_class;
 
                INSIST(ssutable == NULL || update < maxbytypelen);
-               get_current_rr(zoneclass, name, &rdata, &covers, &ttl,
-                              &update_class);
+               get_current_rr(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
@@ -1643,6 +1647,7 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
                                CLEANUP(DNS_R_REFUSED);
                        }
                        if ((options & DNS_ZONEOPT_CHECKSVCB) != 0 &&
+                           rdata.rdclass == dns_rdataclass_in &&
                            rdata.type == dns_rdatatype_svcb)
                        {
                                result = dns_rdata_checksvcb(name, &rdata);
@@ -1731,7 +1736,6 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
                        }
 
                        if (update_class == dns_rdataclass_any &&
-                           zoneclass == dns_rdataclass_in &&
                            (rdata.type == dns_rdatatype_ptr ||
                             rdata.type == dns_rdatatype_srv))
                        {
@@ -2629,7 +2633,6 @@ update_action(void *arg) {
        isc_mem_t *mctx = client->manager->mctx;
        dns_rdatatype_t covers;
        dns_message_t *request = client->message;
-       dns_rdataclass_t zoneclass;
        dns_name_t *zonename = NULL;
        dns_fixedname_t tmpnamefixed;
        dns_name_t *tmpname = NULL;
@@ -2646,9 +2649,10 @@ update_action(void *arg) {
 
        CHECK(dns_zone_getdb(zone, &db));
        zonename = dns_db_origin(db);
-       zoneclass = dns_db_class(db);
        options = dns_zone_getoptions(zone);
 
+       INSIST(dns_zone_getclass(zone) == dns_rdataclass_in);
+
        is_inline = (!dns_zone_israw(zone) && dns_zone_issecure(zone));
        is_maintain = (dns_zone_getkasp(zone) != NULL) && !dns_zone_israw(zone);
        is_signing = is_inline || is_maintain;
@@ -2669,8 +2673,7 @@ update_action(void *arg) {
                dns_rdataclass_t update_class;
                bool flag;
 
-               get_current_rr(zoneclass, name, &rdata, &covers, &ttl,
-                              &update_class);
+               get_current_rr(name, &rdata, &covers, &ttl, &update_class);
 
                if (ttl != 0) {
                        PREREQFAILC(DNS_R_FORMERR,
@@ -2733,7 +2736,7 @@ update_action(void *arg) {
                                                "prerequisite not satisfied");
                                }
                        }
-               } else if (update_class == zoneclass) {
+               } else if (update_class == dns_rdataclass_in) {
                        /* "temp<rr.name, rr.type> += rr;" */
                        temp_append(&temp, name, &rdata);
                } else {
@@ -2784,10 +2787,9 @@ update_action(void *arg) {
 
                INSIST(ssutable == NULL || maxidx < maxbytypelen);
 
-               get_current_rr(zoneclass, name, &rdata, &covers, &ttl,
-                              &update_class);
+               get_current_rr(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 files.
                         */