#include <exceptions/exceptions.h>
#include <dns/name.h>
+#include <dns/nsec3hash.h>
#include <dns/rdataclass.h>
#include <dns/rrclass.h>
#include <dns/rrsetlist.h>
// The optional NSEC3 related data
struct NSEC3Data {
- NSEC3Map map_; // Actual NSEC3 RRs
- // We should also have hash parameters here (maybe hold NSEC3Hash?)
+ NSEC3Data(const generic::NSEC3PARAM& nsec3param) :
+ hash_(NSEC3Hash::create(nsec3param))
+ {}
+ NSEC3Data(const generic::NSEC3& nsec3) :
+ hash_(NSEC3Hash::create(nsec3))
+ {}
+ NSEC3Map map_; // Actual NSEC3 RRs
+ const scoped_ptr<NSEC3Hash> hash_; // hash parameter/calculator
};
scoped_ptr<NSEC3Data> nsec3_data_; // non NULL only when it's NSEC3 signed
};
}
result::Result addNSEC3(const ConstRRsetPtr rrset, ZoneData& zone_data) {
+ // We know rrset has exactly one RDATA
+ const generic::NSEC3& nsec3_rdata =
+ dynamic_cast<const generic::NSEC3&>(
+ rrset->getRdataIterator()->getCurrent());
+
+ // If we've not done any NSEC3 setup for the zone, do it know;
+ // otherwise check parameter consistency.
if (!zone_data.nsec3_data_) {
- zone_data.nsec3_data_.reset(new ZoneData::NSEC3Data);
+ zone_data.nsec3_data_.reset(new ZoneData::NSEC3Data(nsec3_rdata));
+ } else {
+ if (!zone_data.nsec3_data_->hash_->match(nsec3_rdata)) {
+ isc_throw(AddError, "NSEC3 with inconsistent parameters: " <<
+ rrset->toText());
+ }
}
+
string fst_label = rrset->getName().split(0, 1).toText(true);
transform(fst_label.begin(), fst_label.end(), fst_label.begin(),
ToUpper());
node->setFlag(DomainNode::FLAG_CALLBACK);
}
+ // If we've added NSEC3PARAM and the zone isn't yet NSEC3-ready
+ // set it up (note: this part doesn't ensure strong exception
+ // guarantee)
+ if (rrset->getType() == RRType::NSEC3PARAM() &&
+ !zone_data.nsec3_data_) {
+ zone_data.nsec3_data_.reset(
+ new ZoneData::NSEC3Data(
+ dynamic_cast<const generic::NSEC3PARAM&>(
+ rrset->getRdataIterator()->getCurrent())));
+ }
+
return (result::SUCCESS);
} else {
// The RRSet of given type was already there
InMemoryZoneFinder::AddError);
}
+TEST_F(InMemoryZoneFinderTest, paramConsistencyWithNSEC3PARAM) {
+ // First, add an NSEC3PARAM RR
+ EXPECT_EQ(result::SUCCESS,
+ zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
+ "1 0 12 aabbccdd")));
+ // Adding an NSEC3 that has matching parameters is okay.
+ EXPECT_EQ(result::SUCCESS, zone_finder_.add(
+ textToRRset(string(apex_hash) + ".example.org." +
+ string(nsec3_common))));
+ // NSEC3 with inconsistent parameter will be rejected
+ EXPECT_THROW(zone_finder_.add(
+ textToRRset("a.example.org. 300 IN NSEC3 1 0 1 aabbccdd "
+ "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG")),
+ InMemoryZoneFinder::AddError);
+}
+
+TEST_F(InMemoryZoneFinderTest, paramConsistencyWithNSEC3) {
+ // Add an NSEC3 without adding NSEC3PARAM
+ EXPECT_EQ(result::SUCCESS, zone_finder_.add(
+ textToRRset(string(apex_hash) + ".example.org." +
+ string(nsec3_common))));
+ // Adding an NSEC3 with inconsistent parameter will be rejected at this pt.
+ EXPECT_THROW(zone_finder_.add(
+ textToRRset("a.example.org. 300 IN NSEC3 1 0 1 aabbccdd "
+ "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG")),
+ InMemoryZoneFinder::AddError);
+}
+
TEST_F(InMemoryZoneFinderTest, multiNSEC3PARAM) {
// In this current implementation multiple NSEC3PARAM isn't supported.
RRsetPtr nsec3param(new RRset(Name("example.org"), RRClass::IN(),
}
// TODO
-// - parameter consistency
// - existence of NSEC3PARAM
-// - parameter consistency with NSEC3PARAM
-// - add NSEC3PARAM first/second
+// - add NSEC3PARAM second, check consistency
+// - add NSEC3PARAM at non origin (should be ignored)
}