Commit e6152707 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[2097] handle various invalid/unusal cases

parent c097d3c7
......@@ -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);
}
......
......@@ -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);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment