]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] fix nxrrset in nxdomain redirection
authorEvan Hunt <each@isc.org>
Wed, 5 Nov 2014 07:49:56 +0000 (23:49 -0800)
committerEvan Hunt <each@isc.org>
Wed, 5 Nov 2014 07:49:56 +0000 (23:49 -0800)
4000. [bug] NXDOMAIN redirection incorrectly handled NXRRSET
from the redirect zone. [RT #37722]

CHANGES
bin/named/query.c
bin/tests/system/redirect/tests.sh
doc/arm/notes.xml

diff --git a/CHANGES b/CHANGES
index cb15c9b632cd1091e68a6123f0befcb2175d72dc..a903fa6b8732a2171af70734696e85f0b69919b6 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+4000.  [bug]           NXDOMAIN redirection incorrectly handled NXRRSET
+                       from the redirect zone. [RT #37722]
+
 3999.  [func]          "mkeys" and "nzf" files are now named after
                        their corresponding views, unless the view name
                        contains characters that would be incompatible
index 6f90c0fc418a57380f35844a386cb43ebb00eb65..87f00332566fbc3ac59bf13e92d70837ef33a44a 100644 (file)
@@ -6010,7 +6010,7 @@ dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
  * Only perform the update if the client is in the allow query acl and
  * returning the update would not cause a DNSSEC validation failure.
  */
-static isc_boolean_t
+static isc_result_t
 redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
         dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp,
         dns_rdatatype_t qtype)
@@ -6029,7 +6029,7 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
        CTRACE(ISC_LOG_DEBUG(3), "redirect");
 
        if (client->view->redirect == NULL)
-               return (ISC_FALSE);
+               return (ISC_R_NOTFOUND);
 
        dns_fixedname_init(&fixed);
        found = dns_fixedname_name(&fixed);
@@ -6039,15 +6039,15 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
        dns_clientinfo_init(&ci, client, NULL);
 
        if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp))
-               return (ISC_FALSE);
+               return (ISC_R_NOTFOUND);
 
        if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) {
                if (rdataset->trust == dns_trust_secure)
-                       return (ISC_FALSE);
+                       return (ISC_R_NOTFOUND);
                if (rdataset->trust == dns_trust_ultimate &&
                    (rdataset->type == dns_rdatatype_nsec ||
                     rdataset->type == dns_rdatatype_nsec3))
-                       return (ISC_FALSE);
+                       return (ISC_R_NOTFOUND);
                if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
                        for (result = dns_rdataset_first(rdataset);
                             result == ISC_R_SUCCESS;
@@ -6058,7 +6058,7 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
                                if (type == dns_rdatatype_nsec ||
                                    type == dns_rdatatype_nsec3 ||
                                    type == dns_rdatatype_rrsig)
-                                       return (ISC_FALSE);
+                                       return (ISC_R_NOTFOUND);
                        }
                }
        }
@@ -6067,16 +6067,16 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
                                 dns_zone_getqueryacl(client->view->redirect),
                                          ISC_TRUE);
        if (result != ISC_R_SUCCESS)
-               return (ISC_FALSE);
+               return (ISC_R_NOTFOUND);
 
        result = dns_zone_getdb(client->view->redirect, &db);
        if (result != ISC_R_SUCCESS)
-               return (ISC_FALSE);
+               return (ISC_R_NOTFOUND);
 
        dbversion = query_findversion(client, db);
        if (dbversion == NULL) {
                dns_db_detach(&db);
-               return (ISC_FALSE);
+               return (ISC_R_NOTFOUND);
        }
 
        /*
@@ -6085,16 +6085,22 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
        result = dns_db_findext(db, client->query.qname, dbversion->version,
                                qtype, DNS_DBFIND_NOZONECUT, client->now,
                                &node, found, &cm, &ci, &trdataset, NULL);
-       if (result != ISC_R_SUCCESS) {
+       if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
+               if (dns_rdataset_isassociated(rdataset))
+                       dns_rdataset_disassociate(rdataset);
+               if (dns_rdataset_isassociated(&trdataset))
+                       dns_rdataset_disassociate(&trdataset);
+               goto nxrrset;
+       } else if (result != ISC_R_SUCCESS) {
                if (dns_rdataset_isassociated(&trdataset))
                        dns_rdataset_disassociate(&trdataset);
                if (node != NULL)
                        dns_db_detachnode(db, &node);
                dns_db_detach(&db);
-               return (ISC_FALSE);
+               return (ISC_R_NOTFOUND);
        }
-       CTRACE(ISC_LOG_DEBUG(3), "redirect: found data: done");
 
+       CTRACE(ISC_LOG_DEBUG(3), "redirect: found data: done");
        dns_name_copy(found, name, NULL);
        if (dns_rdataset_isassociated(rdataset))
                dns_rdataset_disassociate(rdataset);
@@ -6102,6 +6108,7 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
                dns_rdataset_clone(&trdataset, rdataset);
                dns_rdataset_disassociate(&trdataset);
        }
+ nxrrset:
        if (*nodep != NULL)
                dns_db_detachnode(*dbp, nodep);
        dns_db_detach(dbp);
@@ -6114,7 +6121,7 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
        client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
                                     NS_QUERYATTR_NOADDITIONAL);
 
-       return (ISC_TRUE);
+       return (result);
 }
 
 /*
@@ -6142,7 +6149,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
        int order;
        isc_buffer_t *dbuf;
        isc_buffer_t b;
-       isc_result_t result, eresult;
+       isc_result_t result, eresult, tresult;
        dns_fixedname_t fixed;
        dns_fixedname_t wildcardname;
        dns_dbversion_t *version, *zversion;
@@ -6157,6 +6164,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
        int line = -1;
        isc_boolean_t dns64_exclude, dns64;
        isc_boolean_t nxrewrite = ISC_FALSE;
+       isc_boolean_t redirected = ISC_FALSE;
        dns_clientinfomethods_t cm;
        dns_clientinfo_t ci;
        char errmsg[256];
@@ -6388,7 +6396,6 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                dns_db_t *tdb = NULL;
                dns_zone_t *tzone = NULL;
                dns_dbversion_t *tversion = NULL;
-               isc_result_t tresult;
 
                tresult = query_getzonedb(client, client->query.qname, qtype,
                                         DNS_GETDB_PARTIAL, &tzone, &tdb,
@@ -7191,6 +7198,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                 * Look for a NSEC3 record if we don't have a NSEC record.
                 */
  nxrrset_rrsig:
+               if (redirected)
+                       goto cleanup;
                if (!dns_rdataset_isassociated(rdataset) &&
                     WANTDNSSEC(client)) {
                        if ((fname->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
@@ -7315,10 +7324,21 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
 
        case DNS_R_NXDOMAIN:
                INSIST(is_zone);
-               if (!empty_wild &&
-                   redirect(client, fname, rdataset, &node, &db, &version,
-                            type))
-                       break;
+               if (!empty_wild) {
+                       tresult = redirect(client, fname, rdataset, &node,
+                                          &db, &version, type);
+                       if (tresult == ISC_R_SUCCESS)
+                               break;
+                       if (tresult == DNS_R_NXRRSET) {
+                               redirected = ISC_TRUE;
+                               goto iszone_nxrrset;
+                       }
+                       if (tresult == DNS_R_NCACHENXRRSET) {
+                               redirected = ISC_TRUE;
+                               is_zone = ISC_FALSE;
+                               goto ncache_nxrrset;
+                       }
+               }
                if (dns_rdataset_isassociated(rdataset)) {
                        /*
                         * If we've got a NSEC record, we need to save the
@@ -7381,9 +7401,22 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                goto cleanup;
 
        case DNS_R_NCACHENXDOMAIN:
-               if (redirect(client, fname, rdataset, &node, &db, &version,
-                            type))
+               tresult = redirect(client, fname, rdataset, &node,
+                                  &db, &version, type);
+               if (tresult == ISC_R_SUCCESS)
                        break;
+               if (tresult == DNS_R_NXRRSET) {
+                       redirected = ISC_TRUE;
+                       is_zone = ISC_TRUE;
+                       goto iszone_nxrrset;
+               }
+               if (tresult == DNS_R_NCACHENXRRSET) {
+                       redirected = ISC_TRUE;
+                       result = tresult;
+                       goto ncache_nxrrset;
+               }
+               /* FALLTHROUGH */
+
        case DNS_R_NCACHENXRRSET:
        ncache_nxrrset:
                INSIST(!is_zone);
index a9de4130fded23213b66f7b87ba3a457c2578de4..1b802aad3ddb18a758e89170abbcdcb2b584ca56 100644 (file)
@@ -332,6 +332,14 @@ n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+echo "I:checking redirect works (with noerror) when qtype is not found ($n)"
+ret=0
+$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 echo "I:checking that redirect zones reload correctly"
 ret=0
 sleep 1 # ensure file mtime will have changed
index ed00f28a41ce5768df04a05029caf6eb1997e82e..db721d7f9a98efab1ee7ee7668f781653dbf8029 100644 (file)
          corrected at run time. [RT #37187]
         </para>
       </listitem>
+      <listitem>
+        <para>
+         When NXDOMAIN redirection is in use, queries for a name
+         that is present in the redirection zone but a type that
+         is not present will now return NOERROR instead of NXDOMAIN.
+        </para>
+      </listitem>
     </itemizedlist>
   </sect2>
   <sect2 id="end_of_life">