]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Disable recursion for non-IN classes
authorEvan Hunt <each@isc.org>
Tue, 3 Mar 2026 22:00:38 +0000 (14:00 -0800)
committerEvan Hunt <each@isc.org>
Wed, 6 May 2026 04:05:32 +0000 (21:05 -0700)
Force recursion off, and set allow-recursion/allow-recursion-on ACLs
to none, for views with a class other than IN. Log a configuration
warning if recursion is explicitly enabled for a non-IN view.

This addresses YWH-PGM40640-74 and YWH-PGM40640-75 by preventing any
attempt at recursive processing in a class-CHAOS view, ensuring that
server addresses used for recursive queries and received in recursive
responses are of the expected format.

Fixes: isc-projects/bind9#5780
Fixes: isc-projects/bind9#5781
(cherry picked from commit 70532a37a1aec761e8a12444852866ce9d9d5fcc)
(cherry picked from commit cf0d5a4e385525e21f2ae39098b1ab90c1137a2a)

bin/named/server.c
bin/tests/system/checkconf/tests.sh
bin/tests/system/checkconf/warn-chaos-recursion.conf [new file with mode: 0644]
bin/tests/system/resolver/tests.sh
lib/bind9/check.c

index 444bb9be059e05f379df99775f0b2a15817b4712..fc8b3e8a0ccddb0d3d3adfdf943c2f322e9c8950 100644 (file)
@@ -4215,6 +4215,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
        obj = NULL;
        result = named_config_get(maps, "max-cache-size", &obj);
        INSIST(result == ISC_R_SUCCESS);
+
        /*
         * If "-T maxcachesize=..." is in effect, it overrides any other
         * "max-cache-size" setting found in configuration, either implicit or
@@ -4965,34 +4966,15 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
        }
 
        /*
-        * We have default hints for class IN if we need them.
+        * We have default root hints for class IN if we need them.
+        * Each view gets its own rootdb so a priming response only
+        * writes into that view's copy.  Other classes don't support
+        * recursion and don't need hints.
         */
        if (view->rdclass == dns_rdataclass_in && view->hints == NULL) {
                dns_view_sethints(view, named_g_server->in_roothints);
        }
 
-       /*
-        * If we still have no hints, this is a non-IN view with no
-        * "hints zone" configured.  Issue a warning, except if this
-        * is a root server.  Root servers never need to consult
-        * their hints, so it's no point requiring users to configure
-        * them.
-        */
-       if (view->hints == NULL) {
-               dns_zone_t *rootzone = NULL;
-               (void)dns_view_findzone(view, dns_rootname, &rootzone);
-               if (rootzone != NULL) {
-                       dns_zone_detach(&rootzone);
-                       need_hints = false;
-               }
-               if (need_hints) {
-                       isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
-                                     NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
-                                     "no root hints for view '%s'",
-                                     view->name);
-               }
-       }
-
        /*
         * Configure the view's TSIG keys.
         */
@@ -5102,7 +5084,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
        obj = NULL;
        result = named_config_get(maps, "recursion", &obj);
        INSIST(result == ISC_R_SUCCESS);
-       view->recursion = cfg_obj_asboolean(obj);
+       view->recursion = (view->rdclass == dns_rdataclass_in &&
+                          cfg_obj_asboolean(obj));
 
        obj = NULL;
        result = named_config_get(maps, "qname-minimization", &obj);
@@ -5201,14 +5184,13 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
        CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache-on",
                                 NULL, actx, named_g_mctx, &view->cacheonacl));
 
-       if (strcmp(view->name, "_bind") != 0 &&
-           view->rdclass != dns_rdataclass_chaos)
-       {
-               /* named.conf only */
+       if (view->rdclass != dns_rdataclass_in) {
+               dns_acl_none(named_g_mctx, &view->recursionacl);
+               dns_acl_none(named_g_mctx, &view->recursiononacl);
+       } else {
                CHECK(configure_view_acl(vconfig, config, NULL,
                                         "allow-recursion", NULL, actx,
                                         named_g_mctx, &view->recursionacl));
-               /* named.conf only */
                CHECK(configure_view_acl(vconfig, config, NULL,
                                         "allow-recursion-on", NULL, actx,
                                         named_g_mctx, &view->recursiononacl));
index c8f883e38da875585df343911431652d5fdd88b1..cc7d37d28e999313af634d91bde17ff817a0a3e5 100644 (file)
@@ -481,6 +481,7 @@ $CHECKCONF -l good.conf \
   | grep -v "is not implemented" \
   | grep -v "is not recommended" \
   | grep -v "no longer exists" \
+  | grep -v "recursion will be disabled" \
   | grep -v "is obsolete" >checkconf.out$n || ret=1
 diff good.zonelist checkconf.out$n >diff.out$n || ret=1
 if [ $ret -ne 0 ]; then
@@ -763,5 +764,16 @@ status=$(expr $status + $ret)
 
 rmdir keys
 
+n=$((n + 1))
+echo_i "check 'recursion yes;' is warned and disabled in a non-IN view ($n)"
+ret=0
+$CHECKCONF warn-chaos-recursion.conf >checkconf.out$n 2>&1 || ret=1
+grep -F "recursion will be disabled" checkconf.out$n >/dev/null || ret=1
+if [ $ret != 0 ]; then
+  echo_i "failed"
+  ret=1
+fi
+status=$((status + ret))
+
 echo_i "exit status: $status"
 [ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/checkconf/warn-chaos-recursion.conf b/bin/tests/system/checkconf/warn-chaos-recursion.conf
new file mode 100644 (file)
index 0000000..e384533
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.  If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+       directory ".";
+};
+
+view chaos ch {
+        match-clients { any; };
+        recursion yes;
+        zone "." {
+                type hint;
+                file "chaos.hints";
+        };
+};
index 761a728eba9703da24cee68dc670b8509158e3cd..09ace25f2a3f34db1ec46136483a3a51dba9445f 100755 (executable)
@@ -905,10 +905,12 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status + ret))
 
 n=$((n + 1))
-echo_i "checking NXDOMAIN is returned when querying non existing domain in CH class ($n)"
+echo_i "checking REFUSED is returned when querying non existing domain in CH class ($n)"
 ret=0
-dig_with_opts @10.53.0.1 id.hostname txt ch >dig.ns1.out.${n} || ret=1
-grep "status: NXDOMAIN" dig.ns1.out.${n} >/dev/null || ret=1
+dig_with_opts @10.53.0.1 hostname.chaostest txt ch >dig.ns1.out.1.${n} || ret=1
+grep "status: NOERROR" dig.ns1.out.1.${n} >/dev/null || ret=1
+dig_with_opts @10.53.0.1 id.hostname txt ch >dig.ns1.out.2.${n} || ret=1
+grep "status: REFUSED" dig.ns1.out.2.${n} >/dev/null || ret=1
 if [ $ret != 0 ]; then echo_i "failed"; fi
 status=$((status + ret))
 
index db87964ce0579f30b0941639d28087aa8dbe55cd..bf623cb5a3d6717763c153a6736d8f9904f1b699 100644 (file)
@@ -2306,13 +2306,17 @@ check_mirror_zone_notify(const cfg_obj_t *zoptions, const char *znamestr,
  */
 static bool
 check_recursion(const cfg_obj_t *config, const cfg_obj_t *voptions,
-               const cfg_obj_t *goptions, isc_log_t *logctx,
-               cfg_aclconfctx_t *actx, isc_mem_t *mctx) {
+               dns_rdataclass_t vclass, const cfg_obj_t *goptions,
+               isc_log_t *logctx, cfg_aclconfctx_t *actx, isc_mem_t *mctx) {
        dns_acl_t *acl = NULL;
        const cfg_obj_t *obj;
        isc_result_t result;
        bool retval = true;
 
+       if (vclass != dns_rdataclass_in) {
+               return false;
+       }
+
        /*
         * Check the "recursion" option first.
         */
@@ -2892,7 +2896,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
         * contradicts the purpose of the former.
         */
        if (ztype == CFG_ZONE_MIRROR &&
-           !check_recursion(config, voptions, goptions, logctx, actx, mctx))
+           !check_recursion(config, voptions, zclass, goptions, logctx, actx,
+                            mctx))
        {
                cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
                            "zone '%s': mirror zones cannot be used if "
@@ -4645,6 +4650,17 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
 
        cfg_aclconfctx_create(mctx, &actx);
 
+       if (vclass != dns_rdataclass_in) {
+               if (check_recursion(config, voptions, dns_rdataclass_in,
+                                   options, logctx, actx, mctx))
+               {
+                       cfg_obj_log(opts, logctx, ISC_LOG_WARNING,
+                                   "recursion will be disabled for "
+                                   "non-IN view '%s'",
+                                   viewname);
+               }
+       }
+
        if (voptions != NULL) {
                (void)cfg_map_get(voptions, "zone", &zones);
        } else {