From 7fff3295f5a454780d17709d405e7aae075804f7 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Sat, 19 Jan 2019 14:47:58 -0800 Subject: [PATCH] if recursion is allowed and minimal-responses is no, search other databases 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 | 2 +- bin/tests/system/additional/ns1/naptr2.db | 2 +- bin/tests/system/additional/ns1/nid.db | 2 +- bin/tests/system/additional/ns1/rt.db | 3 +- bin/tests/system/additional/ns1/rt2.db | 2 +- bin/tests/system/additional/ns3/ex.db | 14 ++ bin/tests/system/additional/ns3/ex2.db | 13 ++ bin/tests/system/additional/ns3/named.conf.in | 11 + bin/tests/system/additional/tests.sh | 20 +- lib/ns/query.c | 216 ++++++++++++++---- 10 files changed, 235 insertions(+), 50 deletions(-) create mode 100644 bin/tests/system/additional/ns3/ex.db create mode 100644 bin/tests/system/additional/ns3/ex2.db diff --git a/bin/tests/system/additional/ns1/naptr.db b/bin/tests/system/additional/ns1/naptr.db index d604a3ac23..d14bec455d 100644 --- a/bin/tests/system/additional/ns1/naptr.db +++ b/bin/tests/system/additional/ns1/naptr.db @@ -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 diff --git a/bin/tests/system/additional/ns1/naptr2.db b/bin/tests/system/additional/ns1/naptr2.db index 090e9b6241..fbdd179756 100644 --- a/bin/tests/system/additional/ns1/naptr2.db +++ b/bin/tests/system/additional/ns1/naptr2.db @@ -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 diff --git a/bin/tests/system/additional/ns1/nid.db b/bin/tests/system/additional/ns1/nid.db index 70e4dc839c..5d5bee8e09 100644 --- a/bin/tests/system/additional/ns1/nid.db +++ b/bin/tests/system/additional/ns1/nid.db @@ -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 diff --git a/bin/tests/system/additional/ns1/rt.db b/bin/tests/system/additional/ns1/rt.db index 57ee400ec3..6958f38fd6 100644 --- a/bin/tests/system/additional/ns1/rt.db +++ b/bin/tests/system/additional/ns1/rt.db @@ -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 diff --git a/bin/tests/system/additional/ns1/rt2.db b/bin/tests/system/additional/ns1/rt2.db index 73cb9f30d6..667eb118a8 100644 --- a/bin/tests/system/additional/ns1/rt2.db +++ b/bin/tests/system/additional/ns1/rt2.db @@ -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 index 0000000000..409c2dfd48 --- /dev/null +++ b/bin/tests/system/additional/ns3/ex.db @@ -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 index 0000000000..30d4ca7c7a --- /dev/null +++ b/bin/tests/system/additional/ns3/ex2.db @@ -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 diff --git a/bin/tests/system/additional/ns3/named.conf.in b/bin/tests/system/additional/ns3/named.conf.in index bd730ae418..7dcd0bd0be 100644 --- a/bin/tests/system/additional/ns3/named.conf.in +++ b/bin/tests/system/additional/ns3/named.conf.in @@ -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"; +}; diff --git a/bin/tests/system/additional/tests.sh b/bin/tests/system/additional/tests.sh index 6819ec6224..e3e9a3da25 100644 --- a/bin/tests/system/additional/tests.sh +++ b/bin/tests/system/additional/tests.sh @@ -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 diff --git a/lib/ns/query.c b/lib/ns/query.c index 57d8b17ecd..3b6b3dc3d1 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -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; }