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

[2420] handle RRSIG-for-NSEC3 only cases.

parent 4fb2c320
......@@ -243,14 +243,28 @@ ZoneDataUpdater::setupNSEC3(const ConstRRsetPtr rrset) {
}
void
ZoneDataUpdater::addNSEC3(const ConstRRsetPtr rrset, const ConstRRsetPtr rrsig)
ZoneDataUpdater::addNSEC3(const Name& name, const ConstRRsetPtr rrset,
const ConstRRsetPtr rrsig)
{
setupNSEC3<generic::NSEC3>(rrset);
if (rrset) {
setupNSEC3<generic::NSEC3>(rrset);
}
NSEC3Data* nsec3_data = zone_data_.getNSEC3Data();
if (nsec3_data == NULL) {
// This is some tricky case: an RRSIG for NSEC3 is given without the
// covered NSEC3, and we don't even know any NSEC3 related data.
// This situation is not necessarily broken, but in our current
// implementation it's very difficult to deal with. So we reject it;
// hopefully this case shouldn't happen in practice, at least unless
// zone is really broken.
assert(!rrset);
isc_throw(NotImplemented,
"RRSIG for NSEC3 cannot be added - no known NSEC3 data");
}
ZoneNode* node;
nsec3_data->insertName(mem_sgmt_, rrset->getName(), &node);
nsec3_data->insertName(mem_sgmt_, name, &node);
RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, rrset, rrsig);
RdataSet* old_rdataset = node->setData(rdataset);
......@@ -265,7 +279,7 @@ ZoneDataUpdater::addRdataSet(const Name& name, const RRType& rrtype,
const ConstRRsetPtr rrsig)
{
if (rrtype == RRType::NSEC3()) {
addNSEC3(rrset, rrsig); // TBD: check RRSIG only case
addNSEC3(name, rrset, rrsig);
} else {
ZoneNode* node;
zone_data_.insertName(mem_sgmt_, name, &node);
......
......@@ -121,9 +121,18 @@ public:
/// zone is half broken and really contains an RRSIG that doesn't have
/// any covered RRset. This implementation supports these cases.
///
/// There is one tricky case: Due to a limitation of the current
/// implementation, it cannot accept an RRSIG for NSEC3 without the covered
/// NSEC3, unless at least one NSEC3 or NSEC3PARAM has been added.
/// In this case an isc::NotImplemented exception will be thrown. It
/// should be very rare in practice, and hopefully wouldn't be a real
/// issue.
///
/// \throw NullRRset Both \c rrset and sig_rrset is NULL
/// \throw AddError any of a variety of validation checks fail for the
/// \c rrset and its associated \c sig_rrset.
/// \throw NotImplemented RRSIG for NSEC3 cannot be added due to internal
/// restriction.
///
/// \param rrset The RRset to be added.
/// \param sig_rrset An associated RRSIG RRset for the \c rrset. It
......@@ -162,7 +171,8 @@ private:
const isc::dns::NSEC3Hash* getNSEC3Hash();
template <typename T>
void setupNSEC3(const isc::dns::ConstRRsetPtr rrset);
void addNSEC3(const isc::dns::ConstRRsetPtr rrset,
void addNSEC3(const isc::dns::Name& name,
const isc::dns::ConstRRsetPtr rrset,
const isc::dns::ConstRRsetPtr rrsig);
void addRdataSet(const isc::dns::Name& name,
const isc::dns::RRType& rrtype,
......
......@@ -28,6 +28,8 @@
#include <gtest/gtest.h>
#include <cassert>
using isc::testutils::textToRRset;
using namespace isc::dns;
using namespace isc::datasrc::memory;
......@@ -47,6 +49,11 @@ protected:
ZoneData::destroy(mem_sgmt_, zone_data_, zclass_);
}
}
void clearZoneData() {
assert(zone_data_ != NULL);
ZoneData::destroy(mem_sgmt_, zone_data_, zclass_);
zone_data_ = ZoneData::create(mem_sgmt_, zname_);
}
void TearDown() {
if (zone_data_ != NULL) {
......@@ -136,4 +143,65 @@ TEST_F(ZoneDataUpdaterTest, rrisgOnly) {
EXPECT_FALSE(zone_data_->isSigned());
}
// Commonly used checks for rrisgForNSEC3Only
void
checkNSEC3Rdata(isc::util::MemorySegment& mem_sgmt, const Name& name,
ZoneData* zone_data)
{
ZoneNode* node = NULL;
zone_data->getNSEC3Data()->insertName(mem_sgmt, name, &node);
ASSERT_NE(static_cast<ZoneNode*>(NULL), node);
const RdataSet* rdset = node->getData();
ASSERT_NE(static_cast<RdataSet*>(NULL), rdset);
ASSERT_EQ(RRType::NSEC3(), rdset->type);
EXPECT_EQ(0, rdset->getRdataCount());
EXPECT_EQ(1, rdset->getSigRdataCount());
}
TEST_F(ZoneDataUpdaterTest, rrisgForNSEC3Only) {
// Adding only RRSIG covering NSEC3 is tricky. It should go to the
// separate NSEC3 tree, but the separate space is only created when
// NSEC3 or NSEC3PARAM is added. So, in many cases RRSIG-only is allowed,
// but if no NSEC3 or NSEC3PARAM has been added it will be rejected.
// Below we use abnormal owner names and RDATA for NSEC3s for brevity,
// but that doesn't matter for this test.
// Add NSEC3PARAM, then RRSIG-only, which is okay.
updater_.add(textToRRset(
"example.org. 3600 IN NSEC3PARAM 1 0 12 AABBCCDD"),
textToRRset(
"example.org. 3600 IN RRSIG NSEC3PARAM 5 3 3600 "
"20150420235959 20051021000000 1 example.org. FAKE"));
EXPECT_TRUE(zone_data_->isNSEC3Signed());
updater_.add(ConstRRsetPtr(),
textToRRset(
"09GM.example.org. 3600 IN RRSIG NSEC3 5 3 3600 "
"20150420235959 20051021000000 1 example.org. FAKE"));
checkNSEC3Rdata(mem_sgmt_, Name("09GM.example.org"), zone_data_);
// Clear the current content of zone, then add NSEC3
clearZoneData();
updater_.add(textToRRset(
"AABB.example.org. 3600 IN NSEC3 1 0 10 AA 00000000 A"),
textToRRset(
"AABB.example.org. 3600 IN RRSIG NSEC3 5 3 3600 "
"20150420235959 20051021000000 1 example.org. FAKE"));
updater_.add(ConstRRsetPtr(),
textToRRset(
"09GM.example.org. 3600 IN RRSIG NSEC3 5 3 3600 "
"20150420235959 20051021000000 1 example.org. FAKE"));
checkNSEC3Rdata(mem_sgmt_, Name("09GM.example.org"), zone_data_);
// If we add only RRSIG without any NSEC3 related data beforehand,
// it will be rejected; it's a limitation of the current implementation.
clearZoneData();
EXPECT_THROW(updater_.add(
ConstRRsetPtr(),
textToRRset(
"09GM.example.org. 3600 IN RRSIG NSEC3 5 3 3600 "
"20150420235959 20051021000000 1 example.org. FAKE")),
isc::NotImplemented);
}
}
Supports Markdown
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