]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
if recursion is allowed and minimal-responses is no, search other databases
authorEvan Hunt <each@isc.org>
Sat, 19 Jan 2019 22:47:58 +0000 (14:47 -0800)
committerEvan Hunt <each@isc.org>
Mon, 15 Apr 2019 18:05:04 +0000 (11:05 -0700)
this restores functionality that was removed in commit 03be5a6b4e,
allowing named to search in authoritative zone databases outside the
current zone for additional data, if and only if recursion is allowed
and minimal-responses is disabled.

bin/tests/system/additional/ns1/naptr.db
bin/tests/system/additional/ns1/naptr2.db
bin/tests/system/additional/ns1/nid.db
bin/tests/system/additional/ns1/rt.db
bin/tests/system/additional/ns1/rt2.db
bin/tests/system/additional/ns3/ex.db [new file with mode: 0644]
bin/tests/system/additional/ns3/ex2.db [new file with mode: 0644]
bin/tests/system/additional/ns3/named.conf.in
bin/tests/system/additional/tests.sh
lib/ns/query.c

index d604a3ac2360cff1899a2204c1babe7fd8b03b5d..d14bec455d41468bdf0369186235477fa3391673 100644 (file)
@@ -10,7 +10,7 @@
 $TTL 86400
 @ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
     NS ns1
-ns1 A 127.0.0.0
+ns1 A 10.53.0.1
 
 nap IN NAPTR 50 50 "S" "SIPS+D2T" "" server
 server SRV 0 0 5061 server
index 090e9b6241166217fc04cfc68b217b4efa4b7485..fbdd17975619521f55398650c775b7791f23c4e8 100644 (file)
@@ -10,7 +10,7 @@
 $TTL 86400
 @ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
     NS ns1
-ns1 A 127.0.0.0
+ns1 A 10.53.0.1
 
 nap IN NAPTR 50 50 "S" "SIPS+D2T" "" server.hang3a.zone.
 www AAAA 192::99
index 70e4dc839cb4986ca35507af1f3ac5cbff5d434d..5d5bee8e093754dfa5bc88b31712965461078d8e 100644 (file)
@@ -10,7 +10,7 @@
 $TTL 86400
 @ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
     NS ns1
-ns1 A 127.0.0.0
+ns1 A 10.53.0.1
 
 ns1 NID 2 0:0:0:0
 ns1 L64 2 0:0:0:0
index 57ee400ec31528028c35ec08381372168b6c706e..6958f38fd629d6a16b05a6a97f7b077faf39d310 100644 (file)
@@ -10,7 +10,8 @@
 $TTL 86400
 @ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
     NS ns1
-ns1 A 127.0.0.0
+    NS ns1.rt2.example.
+ns1 A 10.53.0.1
 
 rt RT 2 www
 www AAAA 192::99
index 73cb9f30d636982045f53d1b4c3279b9921df87e..667eb118a814b45d133726f7ee1c9db014e3d94e 100644 (file)
@@ -10,7 +10,7 @@
 $TTL 86400
 @ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
     NS ns1
-ns1 A 127.0.0.0
+ns1 A 10.53.0.1
 
 rt RT 2 www.hang3b.zone.
 server SRV 0 0 5061 server
diff --git a/bin/tests/system/additional/ns3/ex.db b/bin/tests/system/additional/ns3/ex.db
new file mode 100644 (file)
index 0000000..409c2df
--- /dev/null
@@ -0,0 +1,14 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; 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 http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+    NS ns1
+    NS ns1.ex2.
+ns1 A 10.53.0.1
diff --git a/bin/tests/system/additional/ns3/ex2.db b/bin/tests/system/additional/ns3/ex2.db
new file mode 100644 (file)
index 0000000..30d4ca7
--- /dev/null
@@ -0,0 +1,13 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; 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 http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 86400
+@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D );
+    NS ns1
+ns1 A 10.53.0.1
index bd730ae418cf558d29e1a6f6e944ce3a0fb4a783..7dcd0bd0be8be0f2323d60ea0b35f787665f7415 100644 (file)
@@ -21,9 +21,20 @@ options {
        listen-on-v6 { none; };
        recursion yes;
        dnssec-validation yes;
+       minimal-responses no;
 };
 
 zone "." {
        type hint;
        file "root.hint";
 };
+
+zone "ex" {
+       type master;
+       file "ex.db";
+};
+
+zone "ex2" {
+       type master;
+       file "ex2.db";
+};
index 6819ec62245dc37c24509ef1108bd75c5d2a3d71..e3e9a3da25ee435f2092e06bcbff76d181edc163 100644 (file)
@@ -228,7 +228,7 @@ n=`expr $n + 1`
 echo_i "testing with 'minimal-any no;' ($n)"
 ret=0
 $DIG $DIGOPTS -t ANY www.rt.example @10.53.0.1 > dig.out.$n || ret=1
-grep "ANSWER: 3, AUTHORITY: 1, ADDITIONAL: 2" dig.out.$n > /dev/null || ret=1
+grep "ANSWER: 3, AUTHORITY: 2, ADDITIONAL: 2" dig.out.$n > /dev/null || ret=1
 if [ $ret -eq 1 ] ; then
     echo_i " failed"; status=1
 fi
@@ -322,5 +322,23 @@ if [ $ret -eq 1 ] ; then
     echo_i " failed"; status=1
 fi
 
+n=`expr $n + 1`
+echo_i "testing out-of-zone additional data from auth zones (authoritative) ($n)"
+ret=0
+$DIG $DIGOPTS -t NS rt.example @10.53.0.1 > dig.out.$n || ret=1
+grep "ADDITIONAL: 2" dig.out.$n  > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+    echo_i " failed"; status=1
+fi
+
+n=`expr $n + 1`
+echo_i "testing out-of-zone additional data from auth zones (recursive) ($n)"
+ret=0
+$DIG $DIGOPTS -t NS ex @10.53.0.3 > dig.out.$n || ret=1
+grep "ADDITIONAL: 3" dig.out.$n  > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+    echo_i " failed"; status=1
+fi
+
 echo_i "exit status: $status"
 [ $status -eq 0 ] || exit 1
index 57d8b17ecd13f694552d98dda5e388ed992f17f3..3b6b3dc3d1a669c753825676ab0045ec11fa15e1 100644 (file)
@@ -1442,6 +1442,175 @@ query_isduplicate(ns_client_t *client, dns_name_t *name,
        return (false);
 }
 
+/*
+ * Look up data for given 'name' and 'type' in given 'version' of 'db' for
+ * 'client'. Called from query_additionalauth().
+ *
+ * If the lookup is successful:
+ *
+ *   - store the node containing the result at 'nodep',
+ *
+ *   - store the owner name of the returned node in 'fname',
+ *
+ *   - if 'type' is not ANY, dns_db_findext() will put the exact rdataset being
+ *     looked for in 'rdataset' and its signatures (if any) in 'sigrdataset',
+ *
+ *   - if 'type' is ANY, dns_db_findext() will leave 'rdataset' and
+ *     'sigrdataset' disassociated and the returned node will be iterated in
+ *     query_additional_cb().
+ *
+ * If the lookup is not successful:
+ *
+ *   - 'nodep' will not be written to,
+ *   - 'fname' may still be modified as it is passed to dns_db_findext(),
+ *   - 'rdataset' and 'sigrdataset' will remain disassociated.
+ */
+static isc_result_t
+query_additionalauthfind(dns_db_t *db, dns_dbversion_t *version,
+                        const dns_name_t *name, dns_rdatatype_t type,
+                        ns_client_t *client, dns_dbnode_t **nodep,
+                        dns_name_t *fname, dns_rdataset_t *rdataset,
+                        dns_rdataset_t *sigrdataset)
+{
+       dns_clientinfomethods_t cm;
+       dns_dbnode_t *node = NULL;
+       dns_clientinfo_t ci;
+       isc_result_t result;
+
+       dns_clientinfomethods_init(&cm, ns_client_sourceip);
+       dns_clientinfo_init(&ci, client, NULL);
+
+       /*
+        * Since we are looking for authoritative data, we do not set
+        * the GLUEOK flag.  Glue will be looked for later, but not
+        * necessarily in the same database.
+        */
+       result = dns_db_findext(db, name, version, type,
+                               client->query.dboptions, client->now, &node,
+                               fname, &cm, &ci, rdataset, sigrdataset);
+       if (result != ISC_R_SUCCESS) {
+               if (dns_rdataset_isassociated(rdataset)) {
+                       dns_rdataset_disassociate(rdataset);
+               }
+
+               if (sigrdataset != NULL &&
+                   dns_rdataset_isassociated(sigrdataset))
+               {
+                       dns_rdataset_disassociate(sigrdataset);
+               }
+
+               if (node != NULL) {
+                       dns_db_detachnode(db, &node);
+               }
+
+               return (result);
+       }
+
+       /*
+        * Do not return signatures if the zone is not fully signed.
+        */
+       if (sigrdataset != NULL && !dns_db_issecure(db) &&
+           dns_rdataset_isassociated(sigrdataset))
+       {
+               dns_rdataset_disassociate(sigrdataset);
+       }
+
+       *nodep = node;
+
+       return (ISC_R_SUCCESS);
+}
+
+/*
+ * For query context 'qctx', try finding authoritative additional data for
+ * given 'name' and 'type'. Called from query_additional_cb().
+ *
+ * If successful:
+ *
+ *   - store pointers to the database and node which contain the result in
+ *     'dbp' and 'nodep', respectively,
+ *
+ *   - store the owner name of the returned node in 'fname',
+ *
+ *   - potentially bind 'rdataset' and 'sigrdataset', as explained in the
+ *     comment for query_additionalauthfind().
+ *
+ * If unsuccessful:
+ *
+ *   - 'dbp' and 'nodep' will not be written to,
+ *   - 'fname' may still be modified as it is passed to dns_db_findext(),
+ *   - 'rdataset' and 'sigrdataset' will remain disassociated.
+ */
+static isc_result_t
+query_additionalauth(query_ctx_t *qctx, const dns_name_t *name,
+                    dns_rdatatype_t type, dns_db_t **dbp,
+                    dns_dbnode_t **nodep, dns_name_t *fname,
+                    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+       ns_client_t *client = qctx->client;
+       ns_dbversion_t *dbversion = NULL;
+       dns_dbversion_t *version = NULL;
+       dns_dbnode_t *node = NULL;
+       dns_zone_t *zone = NULL;
+       dns_db_t *db = NULL;
+       isc_result_t result;
+
+       /*
+        * First, look within the same zone database for authoritative
+        * additional data.
+        */
+       if (!client->query.authdbset || client->query.authdb == NULL) {
+               return (ISC_R_NOTFOUND);
+       }
+
+       dbversion = ns_client_findversion(client, client->query.authdb);
+       if (dbversion == NULL) {
+               return (ISC_R_NOTFOUND);
+       }
+
+       dns_db_attach(client->query.authdb, &db);
+       version = dbversion->version;
+
+       CTRACE(ISC_LOG_DEBUG(3), "query_additionalauth: same zone");
+
+       result = query_additionalauthfind(db, version, name, type, client,
+                                         &node, fname, rdataset, sigrdataset);
+       if (result != ISC_R_SUCCESS &&
+           qctx->view->minimalresponses == dns_minimal_no &&
+           RECURSIONOK(client))
+       {
+               /*
+                * If we aren't doing response minimization and recursion is
+                * allowed, we can try and see if any other zone matches.
+                */
+               version = NULL;
+               dns_db_detach(&db);
+               result = query_getzonedb(client, name, type, DNS_GETDB_NOLOG,
+                                        &zone, &db, &version);
+               if (result != ISC_R_SUCCESS) {
+                       return (result);
+               }
+               dns_zone_detach(&zone);
+
+               CTRACE(ISC_LOG_DEBUG(3), "query_additionalauth: other zone");
+
+               result = query_additionalauthfind(db, version, name, type,
+                                                 client, &node, fname,
+                                                 rdataset, sigrdataset);
+       }
+
+       if (result != ISC_R_SUCCESS) {
+               dns_db_detach(&db);
+       } else {
+               *nodep = node;
+               node = NULL;
+
+               *dbp = db;
+               db = NULL;
+       }
+
+       return (result);
+}
+
 static isc_result_t
 query_additional_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) {
        query_ctx_t *qctx = arg;
@@ -1515,58 +1684,17 @@ query_additional_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype) {
        }
 
        /*
-        * Look within the same zone database for authoritative
-        * additional data.
+        * First, look for authoritative additional data.
         */
-       if (!client->query.authdbset || client->query.authdb == NULL) {
-               goto try_cache;
-       }
-
-       dbversion = ns_client_findversion(client, client->query.authdb);
-       if (dbversion == NULL) {
-               goto try_cache;
-       }
-
-       dns_db_attach(client->query.authdb, &db);
-       version = dbversion->version;
-
-       CTRACE(ISC_LOG_DEBUG(3), "query_additional_cb: db_find");
-
-       /*
-        * Since we are looking for authoritative data, we do not set
-        * the GLUEOK flag.  Glue will be looked for later, but not
-        * necessarily in the same database.
-        */
-       result = dns_db_findext(db, name, version, type,
-                               client->query.dboptions,
-                               client->now, &node, fname, &cm, &ci,
-                               rdataset, sigrdataset);
+       result = query_additionalauth(qctx, name, type, &db, &node, fname,
+                                     rdataset, sigrdataset);
        if (result == ISC_R_SUCCESS) {
-               if (sigrdataset != NULL && !dns_db_issecure(db) &&
-                   dns_rdataset_isassociated(sigrdataset))
-               {
-                       dns_rdataset_disassociate(sigrdataset);
-               }
                goto found;
        }
 
-       if (dns_rdataset_isassociated(rdataset)) {
-               dns_rdataset_disassociate(rdataset);
-       }
-       if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
-               dns_rdataset_disassociate(sigrdataset);
-       }
-       if (node != NULL) {
-               dns_db_detachnode(db, &node);
-       }
-       version = NULL;
-       dns_db_detach(&db);
-
        /*
         * No authoritative data was found.  The cache is our next best bet.
         */
-
- try_cache:
        if (!qctx->view->recursion) {
                goto try_glue;
        }