From 82566a96bd5d286b1ebe58237dfbbad6961f5550 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Tue, 31 Oct 2017 14:55:25 +0100 Subject: [PATCH] rec: Split NODATA/NXDOMAIN NSEC wildcard denial proof of existence Otherwise there is a very real risk that a NSEC will cover a more specific wildcard and we end up with what looks like a NXDOMAIN proof but is a NODATA one. --- pdns/recursordist/test-syncres_cc.cc | 2 +- pdns/validate.cc | 95 +++++++++++++++++++--------- 2 files changed, 66 insertions(+), 31 deletions(-) diff --git a/pdns/recursordist/test-syncres_cc.cc b/pdns/recursordist/test-syncres_cc.cc index c29cff5fd..556138846 100644 --- a/pdns/recursordist/test-syncres_cc.cc +++ b/pdns/recursordist/test-syncres_cc.cc @@ -7856,7 +7856,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_ent_denial) { pair.signatures = signatureContents; denialMap[std::make_pair(DNSName(").powerdns.com."), QType::NSEC)] = pair; - denialState = getDenial(denialMap, DNSName("b.powerdns.com."), QType::A, true, true); + denialState = getDenial(denialMap, DNSName("b.powerdns.com."), QType::A, true, false); BOOST_CHECK_EQUAL(denialState, NXDOMAIN); } diff --git a/pdns/validate.cc b/pdns/validate.cc index 4f49ae8f3..6ce976079 100644 --- a/pdns/validate.cc +++ b/pdns/validate.cc @@ -155,13 +155,50 @@ static DNSName getNSECOwnerName(const DNSName& initialOwner, const std::vectorgetZoneRepresentation()<(r); + if (!nsec) { + continue; + } + + if (!v.first.first.isWildcard()) { + continue; + } + DNSName wildcard = getNSECOwnerName(v.first.first, v.second.signatures); + if (qname.countLabels() < wildcard.countLabels()) { + continue; + } + + wildcard.chopOff(); + + if (qname.isPartOf(wildcard)) { + LOG("\tWildcard matches"); + if (qtype == 0 || !nsec->d_set.count(qtype)) { + LOG(" and proves that the type did not exist"<= commonLabelsCount) { DNSName target = g_wildcarddnsname + wildcard; - if (owner == target) { - LOG("\tWildcard matches"); - if (wildcardExists) { - *wildcardExists = true; - } - if (qtype == 0 || !nsec->d_set.count(qtype)) { - LOG(" and proves that the type did not exist"<d_next)) { + if (isCoveredByNSEC(target, owner, nsec->d_next)) { LOG("\tWildcard is covered"<d_set.count(QType::NS) && !nsec->d_set.count(QType::SOA) && - signer.countLabels() < v.first.first.countLabels()) { - LOG("type is "<d_set.count(QType::NS))<<", SOA is "<d_set.count(QType::SOA))<<", signer is "<d_set.count(QType::NS))<<", SOA is "<d_set.count(QType::SOA))<<", signer is "<d_set.count(qtype)) { LOG("Does _not_ deny existence of type "<d_next)) { + if(isCoveredByNSEC(qname, owner, nsec->d_next)) { /* if the name is an ENT and we received a NODATA answer, we are fine with a NSEC proving that the name does not exist. */ - if (wantsNoDataProof && nsecProvesENT(qname, v.first.first, nsec->d_next)) { + if (wantsNoDataProof && nsecProvesENT(qname, owner, nsec->d_next)) { LOG("Denies existence of type "<d_set.count(qtype)<<", next: "<d_next<d_set.count(qtype)<<", next: "<d_next<