From: JINMEI Tatuya Date: Tue, 14 Aug 2012 00:29:05 +0000 (-0700) Subject: [2097] handle various invalid/unusal cases X-Git-Tag: trac2351_base~113^2~10 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e6152707a2bb03f93d4c72e4122eb0020b8949ae;p=thirdparty%2Fkea.git [2097] handle various invalid/unusal cases --- diff --git a/src/lib/datasrc/memory/rdataset.cc b/src/lib/datasrc/memory/rdataset.cc index 95ed554108..ed67b65f72 100644 --- a/src/lib/datasrc/memory/rdataset.cc +++ b/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 + +#include +#include #include #include #include @@ -24,32 +28,81 @@ #include #include +#include // for bad_cast #include // 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(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); } diff --git a/src/lib/datasrc/memory/tests/rdataset_unittest.cc b/src/lib/datasrc/memory/tests/rdataset_unittest.cc index 9122644376..5faf3fd177 100644 --- a/src/lib/datasrc/memory/tests/rdataset_unittest.cc +++ b/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 + #include #include @@ -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); +} }