BIND 10 master, updated. fdf120001f60678e573b8c398a45a74256bf3374 [master] update changelog

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Jan 31 08:45:50 UTC 2012


The branch, master has been updated
       via  fdf120001f60678e573b8c398a45a74256bf3374 (commit)
       via  bd7a3ac98177573263950303d4b2ea7400781d0f (commit)
       via  e2ede2f46b3136296ae06282f686c04b9f751939 (commit)
       via  a1a68b2c05820950568fadc18e0496d57ff6cd5c (commit)
       via  0abbd388a70bd75a6460bcc7599bb8383fb6575d (commit)
       via  d4436ec72742cfa447c7a46b377b134a8e82185d (commit)
       via  c9739b8fcdb24832f58bcc0c550eb1f63917539f (commit)
       via  9447f34869eee38313cbf11f5052f12141f08472 (commit)
       via  177c449a612320ca77e8bfe2718e4dfc9ff7b8d4 (commit)
      from  d046d809853a5da2c8546cb49758d818a657d28c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit fdf120001f60678e573b8c398a45a74256bf3374
Author: Jelte Jansen <jelte at isc.org>
Date:   Tue Jan 31 09:45:42 2012 +0100

    [master] update changelog

commit bd7a3ac98177573263950303d4b2ea7400781d0f
Merge: d046d809853a5da2c8546cb49758d818a657d28c e2ede2f46b3136296ae06282f686c04b9f751939
Author: Jelte Jansen <jelte at isc.org>
Date:   Tue Jan 31 09:43:19 2012 +0100

    [master] Merge branch 'trac1573'

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                            |    7 ++
 src/bin/auth/query.cc                |   48 ++++++++++---
 src/bin/auth/query.h                 |   40 +++++++++++-
 src/bin/auth/tests/query_unittest.cc |  125 ++++++++++++++++++++++++++++++++-
 4 files changed, 205 insertions(+), 15 deletions(-)

-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index d673391..0e11042 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+371.	[bug]		jelte
+	The new query handling module of b10-auth (currently only used with
+	the in-memory data source) now correctly includes the DS record (or
+	the denial of its existence if NSEC is used) when returning a
+	delegation from a signed zone.
+	(Trac #1573, bd7a3ac98177573263950303d4b2ea7400781d0f)
+
 370.	[func]		jinmei
 	libdns++: a new class NSEC3Hash was introduced as a utility for
 	calculating NSEC3 hashes for various purposes.  Python binding was
diff --git a/src/bin/auth/query.cc b/src/bin/auth/query.cc
index aef1179..88624b8 100644
--- a/src/bin/auth/query.cc
+++ b/src/bin/auth/query.cc
@@ -207,7 +207,38 @@ Query::addWildcardNXRRSETProof(ZoneFinder& finder, ConstRRsetPtr nsec) {
                            dnssec_);
     }
 }
-    
+
+void
+Query::addDS(ZoneFinder& finder, const Name& dname) {
+    ZoneFinder::FindResult ds_result =
+        finder.find(dname, RRType::DS(), dnssec_opt_);
+    if (ds_result.code == ZoneFinder::SUCCESS) {
+        response_.addRRset(Message::SECTION_AUTHORITY,
+                           boost::const_pointer_cast<RRset>(ds_result.rrset),
+                           dnssec_);
+    } else if (ds_result.code == ZoneFinder::NXRRSET) {
+        addNXRRsetProof(finder, ds_result);
+    } else {
+        // Any other case should be an error
+        isc_throw(BadDS, "Unexpected result for DS lookup for delegation");
+    }
+}
+
+void
+Query::addNXRRsetProof(ZoneFinder& finder,
+                       const ZoneFinder::FindResult& db_result)
+{
+    if (db_result.isNSECSigned() && db_result.rrset) {
+        response_.addRRset(Message::SECTION_AUTHORITY,
+                           boost::const_pointer_cast<RRset>(
+                               db_result.rrset),
+                           dnssec_);
+        if (db_result.isWildcard()) {
+            addWildcardNXRRSETProof(finder, db_result.rrset);
+        }
+    }
+}
+
 void
 Query::addAuthAdditional(ZoneFinder& finder) {
     // Fill in authority and addtional sections.
@@ -362,6 +393,11 @@ Query::process() {
             response_.addRRset(Message::SECTION_AUTHORITY,
                 boost::const_pointer_cast<RRset>(db_result.rrset),
                 dnssec_);
+            // If DNSSEC is requested, see whether there is a DS
+            // record for this delegation.
+            if (dnssec_) {
+                addDS(*result.zone_finder, db_result.rrset->getName());
+            }
             addAdditional(*result.zone_finder, *db_result.rrset);
             break;
         case ZoneFinder::NXDOMAIN:
@@ -374,15 +410,7 @@ Query::process() {
         case ZoneFinder::NXRRSET:
             addSOA(*result.zone_finder);
             if (dnssec_) {
-                if (db_result.isNSECSigned() && db_result.rrset) {
-                    response_.addRRset(Message::SECTION_AUTHORITY,
-                                       boost::const_pointer_cast<RRset>(
-                                           db_result.rrset),
-                                       dnssec_);
-                    if (db_result.isWildcard()) {
-                        addWildcardNXRRSETProof(zfinder, db_result.rrset);
-                    }
-                }
+                addNXRRsetProof(zfinder, db_result);
             }
             break;
         default:
diff --git a/src/bin/auth/query.h b/src/bin/auth/query.h
index 43a8b6b..886ff93 100644
--- a/src/bin/auth/query.h
+++ b/src/bin/auth/query.h
@@ -71,6 +71,32 @@ private:
     ///
     void addSOA(isc::datasrc::ZoneFinder& finder);
 
+    /// \brief Adds the DS rrset for the given name, if available
+    ///
+    /// This is intended to be called when returning a delegation, and
+    /// if DNSSEC data is requested. If the DS record is not found
+    /// (signaled by find() returning NXRRSET), and the zone is signed
+    /// with NSEC, an NSEC denial of existence proof is added.
+    ///
+    /// \exception BadDS raised if find() returns anything other than
+    ///                  SUCCESS or NXRRSET when searching for the DS
+    ///                  record.
+    /// \param finder The ZoneFinder where the delegation was found
+    /// \param ds_name The name of the delegation RRset
+    void addDS(isc::datasrc::ZoneFinder& finder,
+               const isc::dns::Name& ds_name);
+
+    /// \brief Adds NSEC denial proof for the given NXRRset result
+    ///
+    /// NSEC records, if available (signaled by isNSECSigned(), are added
+    /// to the authority section.
+    ///
+    /// \param finder The ZoneFinder that was used to search for the missing
+    ///               data
+    /// \param db_result The ZoneFinder::FindResult returned by find()
+    void addNXRRsetProof(isc::datasrc::ZoneFinder& finder,
+        const isc::datasrc::ZoneFinder::FindResult& db_result);
+
     /// Add NSEC RRs that prove an NXDOMAIN result.
     ///
     /// This corresponds to Section 3.1.3.2 of RFC 4035.
@@ -235,7 +261,7 @@ public:
 
     /// An invalid result is given when a valid NSEC is expected
     ///
-    // This can only happen when the underlying data source implementation or
+    /// This can only happen when the underlying data source implementation or
     /// the zone is broken.  By throwing an exception we treat such cases
     /// as SERVFAIL.
     struct BadNSEC : public BadZone {
@@ -244,6 +270,18 @@ public:
         {}
     };
 
+    /// An invalid result is given when a valid DS records (or NXRRSET) is
+    /// expected
+    ///
+    /// This can only happen when the underlying data source implementation
+    /// or the zone is broken. A DS query for a known delegation point should
+    /// either result in SUCCESS (if available) or NXRRSET
+    struct BadDS : public BadZone {
+        BadDS(const char* file, size_t line, const char* what) :
+            BadZone(file, line, what)
+        {}
+    };
+
 private:
     const isc::datasrc::DataSourceClient& datasrc_client_;
     const isc::dns::Name& qname_;
diff --git a/src/bin/auth/tests/query_unittest.cc b/src/bin/auth/tests/query_unittest.cc
index 350bc63..0f330f5 100644
--- a/src/bin/auth/tests/query_unittest.cc
+++ b/src/bin/auth/tests/query_unittest.cc
@@ -163,6 +163,27 @@ const char* const nsec3_www_txt =
     "q04jkcevqvmu85r014c7dkba38o0ji5r.example.com. 3600 IN NSEC3 1 1 12 "
     "aabbccdd r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG\n";
 
+// (Secure) delegation data; Delegation with DS record
+const char* const signed_delegation_txt =
+    "signed-delegation.example.com. 3600 IN NS ns.example.net.\n";
+const char* const signed_delegation_ds_txt =
+    "signed-delegation.example.com. 3600 IN DS 12345 8 2 "
+    "764501411DE58E8618945054A3F620B36202E115D015A7773F4B78E0F952CECA\n";
+
+// (Secure) delegation data; Delegation without DS record (and NSEC denying
+// its existence.
+const char* const unsigned_delegation_txt =
+    "unsigned-delegation.example.com. 3600 IN NS ns.example.net.\n";
+const char* const unsigned_delegation_nsec_txt =
+    "unsigned-delegation.example.com. 3600 IN NSEC "
+    "*.uwild.example.com. NS RRSIG NSEC\n";
+
+// (Secure) delegation data; Delegation where the DS lookup will raise an
+// exception.
+const char* const bad_delegation_txt =
+    "bad-delegation.example.com. 3600 IN NS ns.example.net.\n";
+
+
 // A helper function that generates a textual representation of RRSIG RDATA
 // for the given covered type.  The resulting RRSIG may not necessarily make
 // sense in terms of the DNSSEC protocol, but for our testing purposes it's
@@ -190,6 +211,9 @@ public:
     MockZoneFinder() :
         origin_(Name("example.com")),
         delegation_name_("delegation.example.com"),
+        signed_delegation_name_("signed-delegation.example.com"),
+        bad_signed_delegation_name_("bad-delegation.example.com"),
+        unsigned_delegation_name_("unsigned-delegation.example.com"),
         dname_name_("dname.example.com"),
         has_SOA_(true),
         has_apex_NS_(true),
@@ -201,15 +225,18 @@ public:
         stringstream zone_stream;
         zone_stream << soa_txt << zone_ns_txt << ns_addrs_txt <<
             delegation_txt << mx_txt << www_a_txt << cname_txt <<
-            cname_nxdom_txt << cname_out_txt << dname_txt << dname_a_txt <<
-            other_zone_rrs << no_txt << nz_txt <<
+            cname_nxdom_txt << cname_out_txt << dname_txt <<
+            dname_a_txt << other_zone_rrs << no_txt << nz_txt <<
             nsec_apex_txt << nsec_mx_txt << nsec_no_txt << nsec_nz_txt <<
             nsec_nxdomain_txt << nsec_www_txt << nonsec_a_txt <<
             wild_txt << nsec_wild_txt << cnamewild_txt << nsec_cnamewild_txt <<
             wild_txt_nxrrset << nsec_wild_txt_nxrrset << wild_txt_next <<
             nsec_wild_txt_next << empty_txt << nsec_empty_txt <<
             empty_prev_txt << nsec_empty_prev_txt <<
-            nsec3_apex_txt << nsec3_www_txt;
+            nsec3_apex_txt << nsec3_www_txt <<
+            signed_delegation_txt << signed_delegation_ds_txt <<
+            unsigned_delegation_txt << unsigned_delegation_nsec_txt <<
+            bad_delegation_txt;
 
         masterLoad(zone_stream, origin_, rrclass_,
                    boost::bind(&MockZoneFinder::loadRRset, this, _1));
@@ -277,6 +304,10 @@ public:
 public:
     // We allow the tests to use these for convenience
     ConstRRsetPtr delegation_rrset_;
+    ConstRRsetPtr signed_delegation_rrset_;
+    ConstRRsetPtr signed_delegation_ds_rrset_;
+    ConstRRsetPtr bad_signed_delegation_rrset_;
+    ConstRRsetPtr unsigned_delegation_rrset_;
     ConstRRsetPtr empty_nsec_rrset_;
 
 private:
@@ -300,6 +331,22 @@ private:
         if (rrset->getName() == delegation_name_ &&
             rrset->getType() == RRType::NS()) {
             delegation_rrset_ = rrset;
+        } else if (rrset->getName() == signed_delegation_name_ &&
+                   rrset->getType() == RRType::NS()) {
+            signed_delegation_rrset_ = rrset;
+        } else if (rrset->getName() == bad_signed_delegation_name_ &&
+                   rrset->getType() == RRType::NS()) {
+            bad_signed_delegation_rrset_ = rrset;
+        } else if (rrset->getName() == unsigned_delegation_name_ &&
+                   rrset->getType() == RRType::NS()) {
+            unsigned_delegation_rrset_ = rrset;
+        } else if (rrset->getName() == signed_delegation_name_ &&
+                   rrset->getType() == RRType::DS()) {
+            signed_delegation_ds_rrset_ = rrset;
+            // Like NSEC(3), by nature it should have an RRSIG.
+            rrset->addRRsig(RdataPtr(new generic::RRSIG(
+                                         getCommonRRSIGText(rrset->getType().
+                                                            toText()))));
         } else if (rrset->getName() == dname_name_ &&
             rrset->getType() == RRType::DNAME()) {
             dname_rrset_ = rrset;
@@ -323,6 +370,9 @@ private:
     const Name origin_;
     // Names where we delegate somewhere else
     const Name delegation_name_;
+    const Name signed_delegation_name_;
+    const Name bad_signed_delegation_name_;
+    const Name unsigned_delegation_name_;
     const Name dname_name_;
     bool has_SOA_;
     bool has_apex_NS_;
@@ -441,7 +491,31 @@ MockZoneFinder::find(const Name& name, const RRType& type,
     // And under DNAME
     } else if (name.compare(dname_name_).getRelation() ==
         NameComparisonResult::SUBDOMAIN) {
-        return (FindResult(DNAME, dname_rrset_));
+        if (type != RRType::DS()) {
+            return (FindResult(DNAME, dname_rrset_));
+        }
+    } else if (name == signed_delegation_name_ ||
+               name.compare(signed_delegation_name_).getRelation() ==
+               NameComparisonResult::SUBDOMAIN) {
+        if (type != RRType::DS()) {
+            return (FindResult(DELEGATION, signed_delegation_rrset_));
+        } else {
+            return (FindResult(SUCCESS, signed_delegation_ds_rrset_));
+        }
+    } else if (name == unsigned_delegation_name_ ||
+               name.compare(unsigned_delegation_name_).getRelation() ==
+               NameComparisonResult::SUBDOMAIN) {
+        if (type != RRType::DS()) {
+            return (FindResult(DELEGATION, unsigned_delegation_rrset_));
+        }
+    } else if (name == bad_signed_delegation_name_ ||
+               name.compare(bad_signed_delegation_name_).getRelation() ==
+               NameComparisonResult::SUBDOMAIN) {
+        if (type != RRType::DS()) {
+            return (FindResult(DELEGATION, bad_signed_delegation_rrset_));
+        } else {
+            return (FindResult(NXDOMAIN, RRsetPtr()));
+        }
     }
 
     // normal cases.  names are searched for only per exact-match basis
@@ -864,6 +938,49 @@ TEST_F(QueryTest, delegation) {
                   NULL, delegation_txt, ns_addrs_txt);
 }
 
+TEST_F(QueryTest, secureDelegation) {
+    EXPECT_NO_THROW(Query(memory_client,
+                          Name("foo.signed-delegation.example.com"),
+                          qtype, response, true).process());
+
+    // Should now contain RRSIG and DS record as well.
+    responseCheck(response, Rcode::NOERROR(), 0, 0, 3, 0,
+                  NULL,
+                  (string(signed_delegation_txt) +
+                   string(signed_delegation_ds_txt) +
+                   string("signed-delegation.example.com. 3600 IN RRSIG ") +
+                   getCommonRRSIGText("DS")).c_str(),
+                  NULL);
+}
+
+TEST_F(QueryTest, secureUnsignedDelegation) {
+    EXPECT_NO_THROW(Query(memory_client,
+                          Name("foo.unsigned-delegation.example.com"),
+                          qtype, response, true).process());
+
+    // Should now contain RRSIG and NSEC record as well.
+    responseCheck(response, Rcode::NOERROR(), 0, 0, 3, 0,
+                  NULL,
+                  (string(unsigned_delegation_txt) +
+                   string(unsigned_delegation_nsec_txt) +
+                   string("unsigned-delegation.example.com. 3600 IN RRSIG ") +
+                   getCommonRRSIGText("NSEC")).c_str(),
+                  NULL);
+}
+
+TEST_F(QueryTest, badSecureDelegation) {
+    // Test whether exception is raised if DS query at delegation results in
+    // something different than SUCCESS or NXRRSET
+    EXPECT_THROW(Query(memory_client, Name("bad-delegation.example.com"),
+                       qtype, response, true).process(), Query::BadDS);
+
+    // But only if DNSSEC is requested (it shouldn't even try to look for
+    // the DS otherwise)
+    EXPECT_NO_THROW(Query(memory_client, Name("bad-delegation.example.com"),
+                          qtype, response).process());
+}
+
+
 TEST_F(QueryTest, nxdomain) {
     EXPECT_NO_THROW(Query(memory_client, Name("nxdomain.example.com"), qtype,
                           response).process());




More information about the bind10-changes mailing list