cspmap_t denialMap;
denialMap[std::make_pair(DNSName("a.example.org."), QType::NSEC)] = pair;
- dState denialState = getDenial(denialMap, DNSName("b.example.org."), QType::A, false);
+ dState denialState = getDenial(denialMap, DNSName("b.example.org."), QType::A, false, false);
BOOST_CHECK_EQUAL(denialState, NXDOMAIN);
- denialState = getDenial(denialMap, DNSName("d.example.org."), QType::A, false);
+ denialState = getDenial(denialMap, DNSName("d.example.org."), QType::A, false, false);
/* let's check that d.example.org. is not denied by this proof */
BOOST_CHECK_EQUAL(denialState, NODATA);
}
cspmap_t denialMap;
denialMap[std::make_pair(DNSName("z.example.org."), QType::NSEC)] = pair;
- dState denialState = getDenial(denialMap, DNSName("a.example.org."), QType::A, false);
+ dState denialState = getDenial(denialMap, DNSName("a.example.org."), QType::A, false, false);
BOOST_CHECK_EQUAL(denialState, NXDOMAIN);
- denialState = getDenial(denialMap, DNSName("d.example.org."), QType::A, false);
+ denialState = getDenial(denialMap, DNSName("d.example.org."), QType::A, false, false);
/* let's check that d.example.org. is not denied by this proof */
BOOST_CHECK_EQUAL(denialState, NODATA);
}
cspmap_t denialMap;
denialMap[std::make_pair(DNSName("y.example.org."), QType::NSEC)] = pair;
- dState denialState = getDenial(denialMap, DNSName("z.example.org."), QType::A, false);
+ dState denialState = getDenial(denialMap, DNSName("z.example.org."), QType::A, false, false);
BOOST_CHECK_EQUAL(denialState, NXDOMAIN);
- denialState = getDenial(denialMap, DNSName("d.example.org."), QType::A, false);
+ denialState = getDenial(denialMap, DNSName("d.example.org."), QType::A, false, false);
/* let's check that d.example.org. is not denied by this proof */
BOOST_CHECK_EQUAL(denialState, NODATA);
}
cspmap_t denialMap;
denialMap[std::make_pair(DNSName("a.example.org."), QType::NSEC)] = pair;
- dState denialState = getDenial(denialMap, DNSName("b.example.org."), QType::A, false);
+ dState denialState = getDenial(denialMap, DNSName("b.example.org."), QType::A, false, false);
BOOST_CHECK_EQUAL(denialState, NXDOMAIN);
- denialState = getDenial(denialMap, DNSName("a.example.org."), QType::A, false);
+ denialState = getDenial(denialMap, DNSName("a.example.org."), QType::A, false, false);
/* let's check that d.example.org. is not denied by this proof */
BOOST_CHECK_EQUAL(denialState, NODATA);
}
cspmap_t denialMap;
denialMap[std::make_pair(DNSName("a."), QType::NSEC)] = pair;
- dState denialState = getDenial(denialMap, DNSName("b."), QType::A, false);
+ dState denialState = getDenial(denialMap, DNSName("b."), QType::A, false, false);
BOOST_CHECK_EQUAL(denialState, NXDOMAIN);
}
owner name regardless of type.
*/
- dState denialState = getDenial(denialMap, DNSName("a."), QType::A, false);
+ dState denialState = getDenial(denialMap, DNSName("a."), QType::A, false, false);
/* no data means the qname/qtype is not denied, because an ancestor
delegation NSEC can only deny the DS */
BOOST_CHECK_EQUAL(denialState, NODATA);
- denialState = getDenial(denialMap, DNSName("a."), QType::DS, true);
+ denialState = getDenial(denialMap, DNSName("a."), QType::DS, true, true);
BOOST_CHECK_EQUAL(denialState, NXQTYPE);
}
/* Insecure because the NS is not set, so while it does
denies the DS, it can't prove an insecure delegation */
- dState denialState = getDenial(denialMap, DNSName("a."), QType::DS, true);
+ dState denialState = getDenial(denialMap, DNSName("a."), QType::DS, true, true);
BOOST_CHECK_EQUAL(denialState, INSECURE);
}
+BOOST_AUTO_TEST_CASE(test_nsec_ent_denial) {
+ init();
+
+ testkeysset_t keys;
+ generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+
+ vector<DNSRecord> records;
+
+ vector<shared_ptr<DNSRecordContent>> recordContents;
+ vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+
+ addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), { QType::A }, 600, records);
+ recordContents.push_back(records.at(0).d_content);
+ addRRSIG(keys, records, DNSName("powerdns.com."), 300);
+ signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
+ records.clear();
+
+ ContentSigPair pair;
+ pair.records = recordContents;
+ pair.signatures = signatureContents;
+ cspmap_t denialMap;
+ denialMap[std::make_pair(DNSName("a.powerdns.com."), QType::NSEC)] = pair;
+
+ /* this NSEC is not valid to prove a NXQTYPE at b.powerdns.com */
+ dState denialState = getDenial(denialMap, DNSName("b.powerdns.com."), QType::AAAA, true, true);
+ BOOST_CHECK_EQUAL(denialState, NXDOMAIN);
+
+ /* it is valid to prove a NXQTYPE at c.powerdns.com because it proves that
+ it is an ENT */
+ denialState = getDenial(denialMap, DNSName("c.powerdns.com."), QType::AAAA, true, true);
+ BOOST_CHECK_EQUAL(denialState, NXQTYPE);
+}
+
BOOST_AUTO_TEST_CASE(test_nsec3_ancestor_nxqtype_denial) {
init();
owner name regardless of type.
*/
- dState denialState = getDenial(denialMap, DNSName("a."), QType::A, false);
+ dState denialState = getDenial(denialMap, DNSName("a."), QType::A, false, true);
/* no data means the qname/qtype is not denied, because an ancestor
delegation NSEC3 can only deny the DS */
BOOST_CHECK_EQUAL(denialState, NODATA);
- denialState = getDenial(denialMap, DNSName("a."), QType::DS, true);
+ denialState = getDenial(denialMap, DNSName("a."), QType::DS, true, true);
BOOST_CHECK_EQUAL(denialState, NXQTYPE);
}
/* Insecure because the NS is not set, so while it does
denies the DS, it can't prove an insecure delegation */
- dState denialState = getDenial(denialMap, DNSName("a."), QType::DS, true);
+ dState denialState = getDenial(denialMap, DNSName("a."), QType::DS, true, true);
BOOST_CHECK_EQUAL(denialState, INSECURE);
}
(begin == next && name != begin)); // "we have only 1 NSEC record, LOL!"
}
+static bool nsecProvesENT(const DNSName& name, const DNSName& begin, const DNSName& next)
+{
+ /* if name is an ENT:
+ - begin < name
+ - next is a child of name
+ */
+ return begin.canonCompare(name) && next.isPartOf(name);
+}
+
static std::string getHashFromNSEC3(const DNSName& qname, const std::shared_ptr<NSEC3RecordContent> nsec3)
{
std::string result;
return false;
}
-// FIXME: needs a zone argument, to avoid things like 6840 4.1
-// FIXME: Add ENT support
-// FIXME: Make usable for non-DS records and hook up to validateRecords (or another place)
-dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16_t qtype, bool referralToUnsigned)
+dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16_t qtype, bool referralToUnsigned, bool wantsNoDataProof)
{
for(const auto& v : validrrsets) {
LOG("Do have: "<<v.first.first<<"/"<<DNSRecordContent::NumberToType(v.first.second)<<endl);
/* check if the whole NAME is denied existing */
if(isCoveredByNSEC(qname, v.first.first, nsec->d_next)) {
+
+ if (wantsNoDataProof && nsecProvesENT(qname, v.first.first, nsec->d_next)) {
+ LOG("Denies existence of type "<<qname<<"/"<<QType(qtype).getName()<<" by proving that "<<qname<<" is an ENT"<<endl);
+ return NXQTYPE;
+ }
+
LOG("Denies existence of name "<<qname<<"/"<<QType(qtype).getName()<<endl);
return NXDOMAIN;
}
auto r = validrrsets.equal_range(make_pair(*(zoneCutIter+1), QType::DS));
if(r.first == r.second) {
LOG("No DS for "<<*(zoneCutIter+1)<<", now look for a secure denial"<<endl);
- dState res = getDenial(validrrsets, *(zoneCutIter+1), QType::DS, true);
+ dState res = getDenial(validrrsets, *(zoneCutIter+1), QType::DS, true, true);
if (res == INSECURE || res == NXDOMAIN)
return Bogus;
if (res == NXQTYPE || res == OPTOUT)