]> 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:50:34 +0000 (06:50 +0000)
committerMark Andrews <marka@isc.org>
Thu, 7 Dec 2006 06:50:34 +0000 (06:50 +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 43664cfa2c9ead6d77ec968530283aa55de13eaa..beb5caaad34e492499e19279b8f49071aca90671 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 c776b6562743e9f33816f91105f0d1ee6c965001..a05a57fe4f3e7f8eba19ba35b9855dd3e98de04f 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resolver.c,v 1.284.18.52 2006/10/18 04:24:19 marka Exp $ */
+/* $Id: resolver.c,v 1.284.18.53 2006/12/07 06:50:34 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 963c19540e1befb6bb76fc6637b48d7050b19fc8..7a3229af16b9645798b39ef1d29419a4905b03d7 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: validator.c,v 1.119.18.26 2006/07/24 22:43:31 marka Exp $ */
+/* $Id: validator.c,v 1.119.18.27 2006/12/07 06:50:34 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;