]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2117. [bug] DNSSEC fixes: named could fail to cache NSEC records
authorMark Andrews <marka@isc.org>
Thu, 7 Dec 2006 06:47:36 +0000 (06:47 +0000)
committerMark Andrews <marka@isc.org>
Thu, 7 Dec 2006 06:47:36 +0000 (06:47 +0000)
                        which could lead to validation failures.  named didn't
                        handle negative DS responses that were in the process
                        of being validated.  Check CNAME bit before accepting
                        NODATA proof. To be able to ignore a child NSEC there
                        must be SOA (and NS) set in the bitmap. [RT #16399]

CHANGES
lib/dns/resolver.c
lib/dns/validator.c

diff --git a/CHANGES b/CHANGES
index efad093e87324c9b22e76f728c37f5c296e3b483..f90d4b9056aeffb8e9c31798a8c36c5c23e48b8c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,10 @@
+2117.  [bug]           DNSSEC fixes: named could fail to cache NSEC records
+                       which could lead to validation failures.  named didn't
+                       handle negative DS responses that were in the process
+                       of being validated.  Check CNAME bit before accepting
+                       NODATA proof. To be able to ignore a child NSEC there
+                       must be SOA (and NS) set in the bitmap. [RT #16399]
+
 2116.  [bug]           'rndc reload' could cause the cache to continually
                        be cleaned. [RT #16401]
 
index 18fbeaeb9e69d614d197f411fc937cde2abe0b97..04127a911d58bbaadbe06d8bbd584ae55f03ca2a 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resolver.c,v 1.336 2006/10/18 04:18:54 marka Exp $ */
+/* $Id: resolver.c,v 1.337 2006/12/07 06:47:36 marka Exp $ */
 
 /*! \file */
 
@@ -4366,7 +4366,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
        dns_message_t *message;
        dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name;
        dns_rdataset_t *rdataset, *ns_rdataset;
-       isc_boolean_t done, aa, negative_response;
+       isc_boolean_t aa, negative_response;
        dns_rdatatype_t type;
        dns_section_t section =
                bind8_ns_resp ? DNS_SECTION_ANSWER : DNS_SECTION_AUTHORITY;
@@ -4425,13 +4425,12 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
        /*
         * Process the authority section.
         */
-       done = ISC_FALSE;
        ns_name = NULL;
        ns_rdataset = NULL;
        soa_name = NULL;
        ds_name = NULL;
        result = dns_message_firstname(message, section);
-       while (!done && result == ISC_R_SUCCESS) {
+       while (result == ISC_R_SUCCESS) {
                name = NULL;
                dns_message_currentname(message, section, &name);
                if (dns_name_issubdomain(name, &fctx->domain)) {
@@ -4493,15 +4492,29 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
                                                        dns_trust_additional;
                                }
                        }
-                       /*
-                        * A negative response has a SOA record (Type 2) 
-                        * and a optional NS RRset (Type 1) or it has neither
-                        * a SOA or a NS RRset (Type 3, handled above) or
-                        * rcode is NXDOMAIN (handled above) in which case
-                        * the NS RRset is allowed (Type 4).
-                        */
-                       if (soa_name != NULL)
-                               negative_response = ISC_TRUE;
+               }
+               result = dns_message_nextname(message, section);
+               if (result == ISC_R_NOMORE)
+                       break;
+               else if (result != ISC_R_SUCCESS)
+                       return (result);
+       }
+
+       /*
+        * A negative response has a SOA record (Type 2) 
+        * and a optional NS RRset (Type 1) or it has neither
+        * a SOA or a NS RRset (Type 3, handled above) or
+        * rcode is NXDOMAIN (handled above) in which case
+        * the NS RRset is allowed (Type 4).
+        */
+       if (soa_name != NULL)
+               negative_response = ISC_TRUE;
+
+       result = dns_message_firstname(message, section);
+       while (result == ISC_R_SUCCESS) {
+               name = NULL;
+               dns_message_currentname(message, section, &name);
+               if (dns_name_issubdomain(name, &fctx->domain)) {
                        for (rdataset = ISC_LIST_HEAD(name->list);
                             rdataset != NULL;
                             rdataset = ISC_LIST_NEXT(rdataset, link)) {
index 3f940f17bee62ea581d1b099e57950360e04c9d7..0371de2b7295854f854f1960fbaf2e28391decf1 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: validator.c,v 1.145 2006/07/24 22:41:59 marka Exp $ */
+/* $Id: validator.c,v 1.146 2006/12/07 06:47:36 marka Exp $ */
 
 /*! \file */
 
@@ -579,6 +579,8 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
        unsigned int olabels, nlabels, labels;
        dns_rdata_nsec_t nsec;
        isc_boolean_t atparent;
+       isc_boolean_t ns;
+       isc_boolean_t soa;
 
        REQUIRE(exists != NULL);
        REQUIRE(data != NULL);
@@ -610,9 +612,9 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
                 * The names are the same.
                 */
                atparent = dns_rdatatype_atparent(val->event->type);
-               if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
-                   !dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
-               {
+               ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
+               soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa);
+               if (ns && !soa) {
                        if (!atparent) {
                                /*
                                 * This NSEC record is from somewhere higher in
@@ -623,7 +625,7 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
                                              "ignoring parent nsec");
                                return (ISC_R_IGNORE);
                        }
-               } else if (atparent) {
+               } else if (atparent && ns && soa) {
                        /*
                         * This NSEC record is from the child.
                         * It can not be legitimately used here.
@@ -632,12 +634,20 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
                                      "ignoring child nsec");
                        return (ISC_R_IGNORE);
                }
-               *exists = ISC_TRUE;
-               *data = dns_nsec_typepresent(&rdata, val->event->type);
-               validator_log(val, ISC_LOG_DEBUG(3),
-                             "nsec proves name exists (owner) data=%d",
-                             *data);
-               return (ISC_R_SUCCESS);
+               if (val->event->type == dns_rdatatype_cname ||
+                   val->event->type == dns_rdatatype_nxt ||
+                   val->event->type == dns_rdatatype_nsec ||
+                   val->event->type == dns_rdatatype_key ||
+                   !dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) {
+                       *exists = ISC_TRUE;
+                       *data = dns_nsec_typepresent(&rdata, val->event->type);
+                       validator_log(val, ISC_LOG_DEBUG(3),
+                                     "nsec proves name exists (owner) data=%d",
+                                     *data);
+                       return (ISC_R_SUCCESS);
+               }
+               validator_log(val, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists");
+               return (ISC_R_IGNORE);
        }
 
        if (relation == dns_namereln_subdomain &&
@@ -697,6 +707,7 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
                result = dns_name_concatenate(dns_wildcardname, &common,
                                               wild, NULL);
                if (result != ISC_R_SUCCESS) {
+                       dns_rdata_freestruct(&nsec);
                        validator_log(val, ISC_LOG_DEBUG(3),
                                    "failure generating wildcard name");
                        return (result);
@@ -750,6 +761,7 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
                }
        } else {
                dns_name_t **proofs = val->event->proofs;
+               dns_name_t *wild = dns_fixedname_name(&val->wild);
                
                if (rdataset->trust == dns_trust_secure)
                        val->seensig = ISC_TRUE;
@@ -761,10 +773,9 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
                    (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
                    (val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
                    nsecnoexistnodata(val, val->event->name, devent->name,
-                                     rdataset, &exists, &data,
-                                     dns_fixedname_name(&val->wild))
+                                     rdataset, &exists, &data, wild)
                                      == ISC_R_SUCCESS)
-                {
+               {
                        if (exists && !data) {
                                val->attributes |= VALATTR_FOUNDNODATA;
                                if (NEEDNODATA(val))
@@ -2085,12 +2096,6 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
                        if (rdataset->type == dns_rdatatype_rrsig)
                                continue;
 
-                       if (rdataset->type == dns_rdatatype_soa) {
-                               val->soaset = rdataset;
-                               val->soaname = name;
-                       } else if (rdataset->type == dns_rdatatype_nsec)
-                               val->nsecset = rdataset;
-
                        for (sigrdataset = ISC_LIST_HEAD(name->list);
                             sigrdataset != NULL;
                             sigrdataset = ISC_LIST_NEXT(sigrdataset,
@@ -2545,11 +2550,21 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
                              namebuf);
 
                result = view_find(val, tname, dns_rdatatype_ds);
+
                if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
                        /*
                         * There is no DS.  If this is a delegation,
                         * we maybe done.
                         */
+                       if (val->frdataset.trust == dns_trust_pending) {
+                               result = create_fetch(val, tname,
+                                                     dns_rdatatype_ds,
+                                                     dsfetched2,
+                                                     "proveunsecure");
+                               if (result != ISC_R_SUCCESS)
+                                       goto out;
+                               return (DNS_R_WAIT);
+                       }
                        if (val->frdataset.trust < dns_trust_secure) {
                                /*
                                 * This shouldn't happen, since the negative
@@ -2852,9 +2867,6 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
        val->keyset = NULL;
        val->dsset = NULL;
        dns_rdataset_init(&val->dlv);
-       val->soaset = NULL;
-       val->nsecset = NULL;
-       val->soaname = NULL;
        val->seensig = ISC_FALSE;
        val->havedlvsep = ISC_FALSE;
        val->depth = 0;