Browse Source

[2097] handle various invalid/unusal cases

JINMEI Tatuya 12 years ago
parent
commit
e6152707a2
2 changed files with 137 additions and 10 deletions
  1. 61 8
      src/lib/datasrc/memory/rdataset.cc
  2. 76 2
      src/lib/datasrc/memory/tests/rdataset_unittest.cc

+ 61 - 8
src/lib/datasrc/memory/rdataset.cc

@@ -12,6 +12,10 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <exceptions/exceptions.h>
+
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
 #include <dns/rrclass.h>
 #include <dns/rrtype.h>
 #include <dns/rrset.h>
@@ -24,32 +28,81 @@
 
 #include <stdint.h>
 #include <cstring>
+#include <typeinfo>             // for bad_cast
 #include <new>                  // for the placement new
 
 using namespace isc::dns;
+using namespace isc::dns::rdata;
 
 namespace isc {
 namespace datasrc {
 namespace memory {
 
+namespace {
+RRType
+getCoveredType(const Rdata& rdata) {
+    try {
+        const generic::RRSIG& rrsig_rdata =
+            dynamic_cast<const generic::RRSIG&>(rdata);
+        return (rrsig_rdata.typeCovered());
+    } catch (const std::bad_cast&) {
+        isc_throw(BadValue, "Non RRSIG is given where it's expected");
+    }
+}
+}
+
 RdataSet*
 RdataSet::create(util::MemorySegment& mem_sgmt, RdataEncoder& encoder,
                  ConstRRsetPtr rrset, ConstRRsetPtr sig_rrset)
 {
-    encoder.start(rrset->getClass(), rrset->getType());
-    for (RdataIteratorPtr it = rrset->getRdataIterator();
-         !it->isLast();
-         it->next()) {
-        encoder.addRdata(it->getCurrent());
+    if (!rrset && !sig_rrset) {
+        isc_throw(BadValue, "Both RRset and RRSIG are NULL");
+    }
+    if (rrset && rrset->getRdataCount() == 0) {
+        isc_throw(BadValue, "Empty RRset");
+    }
+    if (sig_rrset && sig_rrset->getRdataCount() == 0) {
+        isc_throw(BadValue, "Empty SIG RRset");
+    }
+    if (rrset && sig_rrset) {
+        if (rrset->getClass() != sig_rrset->getClass()) {
+            isc_throw(BadValue,
+                      "RR class doesn't match between RRset and RRSIG");
+        }
+    }
+
+    const RRClass rrclass = rrset ? rrset->getClass() : sig_rrset->getClass();
+    const RRType rrtype = rrset ? rrset->getType() :
+        getCoveredType(sig_rrset->getRdataIterator()->getCurrent());
+    const RRTTL rrttl = rrset ? rrset->getTTL() : sig_rrset->getTTL();
+
+    encoder.start(rrclass, rrtype);
+    if (rrset) {
+        for (RdataIteratorPtr it = rrset->getRdataIterator();
+             !it->isLast();
+             it->next()) {
+            encoder.addRdata(it->getCurrent());
+        }
+    }
+    if (sig_rrset) {
+        for (RdataIteratorPtr it = sig_rrset->getRdataIterator();
+             !it->isLast();
+             it->next())
+        {
+            if (getCoveredType(it->getCurrent()) != rrtype) {
+                isc_throw(BadValue, "Type covered doesn't match");
+            }
+            encoder.addSIGRdata(it->getCurrent());
+        }
     }
 
     const size_t data_len = encoder.getStorageLength();
     void* p = mem_sgmt.allocate(sizeof(RdataSet) + data_len);
-    RdataSet* rdataset = new(p) RdataSet(rrset->getType(),
-                                         rrset->getRdataCount(),
+    RdataSet* rdataset = new(p) RdataSet(rrtype,
+                                         rrset ? rrset->getRdataCount() : 0,
                                          sig_rrset ?
                                          sig_rrset->getRdataCount() : 0,
-                                         rrset->getTTL());
+                                         rrttl);
     encoder.encode(rdataset->getDataBuf(), data_len);
     return (rdataset);
 }

+ 76 - 2
src/lib/datasrc/memory/tests/rdataset_unittest.cc

@@ -12,6 +12,8 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <exceptions/exceptions.h>
+
 #include <util/buffer.h>
 #include <util/memory_segment_local.h>
 
@@ -38,13 +40,16 @@ protected:
     RdataSetTest() :
         // 1076895760 = 0x40302010.  Use this so we fill in all 8-bit "field"
         // of the 32-bit TTL
-        a_rrset_(textToRRset("www.example.com. 1076895760 IN A 192.0.2.1"))
+        a_rrset_(textToRRset("www.example.com. 1076895760 IN A 192.0.2.1")),
+        rrsig_rrset_(textToRRset("www.example.com. 1076895760 IN RRSIG "
+                                 "A 5 2 3600 20120814220826 20120715220826 "
+                                 "1234 example.com. FAKE"))
     {}
     void TearDown() {
         EXPECT_TRUE(mem_sgmt_.allMemoryDeallocated());
     }
 
-    ConstRRsetPtr a_rrset_;
+    ConstRRsetPtr a_rrset_, rrsig_rrset_;
     isc::util::MemorySegmentLocal mem_sgmt_;
     RdataEncoder encoder_;
 };
@@ -70,4 +75,73 @@ TEST_F(RdataSetTest, create) {
     EXPECT_EQ(0, rdataset->getSigRdataCount());
     RdataSet::destroy(mem_sgmt_, RRClass::IN(), rdataset);
 }
+
+TEST_F(RdataSetTest, createWithRRSIG) {
+    // Normal case.
+    RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
+                                          rrsig_rrset_);
+    EXPECT_EQ(RRTTL(1076895760), restoreTTL(rdataset->getTTLData()));
+    EXPECT_EQ(1, rdataset->getSigRdataCount());
+    RdataSet::destroy(mem_sgmt_, RRClass::IN(), rdataset);
+
+    // Unusual case: TTL doesn't match.  This implementation accepts that,
+    // using the TTL of the covered RRset.
+    ConstRRsetPtr rrsig_badttl(textToRRset(
+                                   "www.example.com. 3600 IN RRSIG "
+                                   "A 5 2 3600 20120814220826 "
+                                   "20120715220826 1234 example.com. FAKE"));
+    rdataset = RdataSet::create(mem_sgmt_, encoder_, a_rrset_, rrsig_badttl);
+    EXPECT_EQ(RRTTL(1076895760), restoreTTL(rdataset->getTTLData()));
+    RdataSet::destroy(mem_sgmt_, RRClass::IN(), rdataset);
+}
+
+TEST_F(RdataSetTest, createWithRRSIGOnly) {
+    // A rare, but allowed, case: RdataSet without the main RRset but with
+    // RRSIG.
+    RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, ConstRRsetPtr(),
+                                          rrsig_rrset_);
+    EXPECT_EQ(RRType::A(), rdataset->type); // type covered is used as type
+    EXPECT_EQ(RRTTL(1076895760), restoreTTL(rdataset->getTTLData()));
+    EXPECT_EQ(0, rdataset->getRdataCount());
+    EXPECT_EQ(1, rdataset->getSigRdataCount());
+    RdataSet::destroy(mem_sgmt_, RRClass::IN(), rdataset);
+}
+
+TEST_F(RdataSetTest, badCeate) {
+    // Neither the RRset nor RRSIG RRset is given
+    EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, ConstRRsetPtr(),
+                                  ConstRRsetPtr()), isc::BadValue);
+
+    // Empty RRset (An RRset without RDATA)
+    ConstRRsetPtr empty_rrset(new RRset(Name("example.com"), RRClass::IN(),
+                                        RRType::A(), RRTTL(3600)));
+    EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, empty_rrset,
+                                  ConstRRsetPtr()), isc::BadValue);
+    ConstRRsetPtr empty_rrsig(new RRset(Name("example.com"), RRClass::IN(),
+                                        RRType::RRSIG(), RRTTL(3600)));
+    EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, ConstRRsetPtr(),
+                                  empty_rrsig), isc::BadValue);
+
+    // The RRset type and RRSIG's type covered don't match
+    ConstRRsetPtr bad_rrsig(textToRRset(
+                                "www.example.com. 1076895760 IN RRSIG "
+                                "NS 5 2 3600 20120814220826 20120715220826 "
+                                "1234 example.com. FAKE"));
+    EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, a_rrset_, bad_rrsig),
+                 isc::BadValue);
+
+    // Pass non RRSIG for the sig parameter
+    EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, a_rrset_, a_rrset_),
+                 isc::BadValue);
+
+    // RR class doesn't match between RRset and RRSIG
+    ConstRRsetPtr badclass_rrsig(textToRRset(
+                                     "www.example.com. 1076895760 CH RRSIG "
+                                     "A 5 2 3600 20120814220826 "
+                                     "20120715220826 1234 example.com. FAKE",
+                                     RRClass::CH()));
+    EXPECT_THROW(RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
+                                  badclass_rrsig),
+                 isc::BadValue);
+}
 }