From 399f391d391d27cee61dbae5bc21f5ed9746b861 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Thu, 31 Dec 2020 13:43:32 +0100 Subject: [PATCH] rec: More wildcard denial tests, check DNAME --- pdns/recursordist/aggressive_nsec.cc | 30 ++++++-------------------- pdns/recursordist/test-syncres_cc8.cc | 31 +++++++++++++++++++++++++++ pdns/validate.cc | 18 ++++++++++++++-- 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/pdns/recursordist/aggressive_nsec.cc b/pdns/recursordist/aggressive_nsec.cc index 984b627e8b..ffc3071399 100644 --- a/pdns/recursordist/aggressive_nsec.cc +++ b/pdns/recursordist/aggressive_nsec.cc @@ -112,6 +112,7 @@ void AggressiveNSECCache::insertNSEC(const DNSName& zone, const DNSName& owner, return; } +#warning Ponder storing everything in raw form, without the zone instead. It still needs to be a DNSName for NSEC, though next = DNSName(toBase32Hex(content->d_nexthash)) + zone; entry->d_iterations = content->d_iterations; entry->d_salt = content->d_salt; @@ -477,6 +478,11 @@ bool AggressiveNSECCache::getDenial(time_t now, const DNSName& name, const QType denial = matchesNSEC(wc, type.getCode(), wcEntry.d_owner, nsecContent, wcEntry.d_signatures); if (denial == dState::NODENIAL) { /* too complicated for now */ + /* we would need: + - to store wildcard entries in the non-expanded form in the record cache, in addition to their expanded form ; + - do a lookup to retrieve them ; + - expand them and the NSEC + */ return false; } else if (denial == dState::NXQTYPE) { @@ -491,30 +497,6 @@ bool AggressiveNSECCache::getDenial(time_t now, const DNSName& name, const QType if (wcEntry.d_owner != wc) { needWildcard = true; } -#if 0 - if (wcEntry.d_owner == wc) { - if (!nsecContent) { - return false; - } - if (nsecContent->isSet(type.getCode())) { - /* too complicated for now */ - return false; - } - if (nsecContent->isSet(QType::CNAME)) { - /* too complicated for now */ - return false; - } - - covered = true; - res = RCode::NoError; - } - else if (isCoveredByNSEC(wc, wcEntry.d_owner, wcEntry.d_next)) { - cerr<<"next is "< records; + + sortedRecords_t recordContents; + vector> signatureContents; + + /* proves that a.example.com does exist, and has been generated from a wildcard (see the RRSIG below) */ + addNSECRecordToLW(DNSName("a.example.org."), DNSName("d.example.org"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records); + recordContents.insert(records.at(0).d_content); + addRRSIG(keys, records, DNSName("example.org."), 300, false, boost::none, DNSName("example.org.")); + signatureContents.push_back(getRR(records.at(1))); + records.clear(); + + ContentSigPair pair; + pair.records = recordContents; + pair.signatures = signatureContents; + cspmap_t denialMap; + denialMap[std::make_pair(DNSName("a.example.org."), QType::NSEC)] = pair; + + /* This is an expanded wildcard proof, meaning that it does prove that the exact name + does not exist so the wildcard can apply */ + dState denialState = getDenial(denialMap, DNSName("a.example.org."), QType(0).getCode(), false, false, false, /* normally retrieved from the RRSIG's d_labels */ 2); + BOOST_CHECK_EQUAL(denialState, dState::NXDOMAIN); +} + BOOST_AUTO_TEST_CASE(test_nsec_wildcard_with_cname) { initSR(); diff --git a/pdns/validate.cc b/pdns/validate.cc index b36acf9dea..c991dbe9dc 100644 --- a/pdns/validate.cc +++ b/pdns/validate.cc @@ -271,7 +271,7 @@ static bool provesNoDataWildCard(const DNSName& qname, const uint16_t qtype, con if (qname.isPartOf(wildcard)) { LOG("\tWildcard matches"); - if (qtype == 0 || (!nsec->isSet(qtype) && !nsec->isSet(QType::CNAME))) { + if (qtype == 0 || (!nsec->isSet(qtype) && !nsec->isSet(QType::CNAME) && !nsec->isSet(QType::DNAME))) { LOG(" and proves that the type did not exist"<isSet(qtype) && !nsec3->isSet(QType::CNAME))) { + if (qtype == 0 || (!nsec3->isSet(qtype) && !nsec3->isSet(QType::CNAME) && !nsec3->isSet(QType::DNAME))) { LOG(" and proves that the type did not exist"<isSet(QType::DNAME)) { + return dState::NODENIAL; + } + return dState::NXQTYPE; } @@ -500,6 +504,11 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16 return dState::NODENIAL; } + if (nsec->isSet(QType::DNAME)) { + LOG("However a CNAME exists"<isSet(QType::DNAME)) { + LOG("However a CNAME exists"<