From: Remi Gacogne Date: Tue, 9 May 2017 14:19:09 +0000 (+0200) Subject: rec: Check NSEC3 closest encloser X-Git-Tag: rec-4.1.0-alpha1~50^2~25 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=812c3a693593a96e6108da97c04cafb1245f7b65;p=pdns rec: Check NSEC3 closest encloser --- diff --git a/pdns/recursordist/test-syncres_cc.cc b/pdns/recursordist/test-syncres_cc.cc index cbb1687b1..fc2e4fbec 100644 --- a/pdns/recursordist/test-syncres_cc.cc +++ b/pdns/recursordist/test-syncres_cc.cc @@ -268,7 +268,7 @@ static void computeRRSIG(const DNSSECPrivateKey& dpk, const DNSName& signer, con rrc.d_type = signQType; rrc.d_labels = signQName.countLabels() - signQName.isWildcard(); rrc.d_originalttl = signTTL; - rrc.d_siginception = now - 1; + rrc.d_siginception = now - 10; rrc.d_sigexpire = now + sigValidity; rrc.d_signer = signer; rrc.d_tag = 0; diff --git a/pdns/syncres.cc b/pdns/syncres.cc index 72e67709b..60b4f4998 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -1393,7 +1393,7 @@ vState SyncRes::getValidationStatus(const DNSName& subdomain, unsigned int depth return Secure; } -void SyncRes::updateValidationStatusAfterReferral(const DNSName& newauth, vState& state, unsigned int depth) +void SyncRes::updateValidationStatusAfterReferral(const DNSName& oldauth, const DNSName& newauth, vState& state, unsigned int depth) { if (!validationEnabled()) { return; @@ -1790,7 +1790,8 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co if (denialState == NXQTYPE || denialState == OPTOUT) { ne.d_validationState = Secure; rec.d_ttl = min(s_maxnegttl, rec.d_ttl); - LOG(prefix<& records, const std::vector >& signatures, uint32_t signaturesTTL) const; void updateValidationState(vState& state, const vState stateUpdate); - void updateValidationStatusAfterReferral(const DNSName& newauth, vState& state, unsigned int depth); + void updateValidationStatusAfterReferral(const DNSName& oldauth, const DNSName& newauth, vState& state, unsigned int depth); vState validateRecordsWithSigs(unsigned int depth, const DNSName& name, const std::vector& records, const std::vector >& signatures); vState validateDNSKeys(const DNSName& zone, const std::vector& dnskeys, const std::vector >& signatures, unsigned int depth); vState getDSRecords(const DNSName& zone, dsmap_t& ds, bool onlyTA, unsigned int depth); diff --git a/pdns/validate.cc b/pdns/validate.cc index f5b6de0e6..fe6661ee0 100644 --- a/pdns/validate.cc +++ b/pdns/validate.cc @@ -24,6 +24,14 @@ static vector > getByTag(const skeyset_t& keys, return ret; } +static bool isCoveredByNSEC3Hash(const std::string& h, const std::string& beginHash, const std::string& nextHash) +{ + return ((beginHash < h && h < nextHash) || // no wrap BEGINNING --- HASH -- END + (nextHash > h && beginHash > nextHash) || // wrap HASH --- END --- BEGINNING + (nextHash < beginHash && beginHash < h) || // wrap other case END --- BEGINNING --- HASH + beginHash == nextHash); // "we have only 1 NSEC3 record, LOL!" +} + // 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) @@ -75,7 +83,7 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16 continue; string h = hashQNameWithSalt(nsec3->d_salt, nsec3->d_iterations, qname); - // cerr<<"Salt length: "<d_salt.length()<<", iterations: "<d_iterations<<", hashed: "<<*(zoneCutIter+1)<d_salt.length()<<", iterations: "<d_iterations<<", hashed: "<d_nexthash) || // no wrap BEGINNING --- HASH -- END - (nsec3->d_nexthash > h && beginHash > nsec3->d_nexthash) || // wrap HASH --- END --- BEGINNING - (nsec3->d_nexthash < beginHash && beginHash < h) || // wrap other case END --- BEGINNING --- HASH - beginHash == nsec3->d_nexthash)) // "we have only 1 NSEC3 record, LOL!" - { + if(isCoveredByNSEC3Hash(h, beginHash, nsec3->d_nexthash)) { LOG("Denies existence of name "<d_flags & 1) { LOG(" but is opt-out!"<getZoneRepresentation()<(r); + if(!nsec3) + continue; + + string h = hashQNameWithSalt(nsec3->d_salt, nsec3->d_iterations, sname); + string beginHash=fromBase32Hex(v.first.first.getRawLabels()[0]); + + LOG("Comparing "<= 1) { + DNSName nextCloser(sname); + nextCloser.prependRawLabel(qname.getRawLabel(labelIdx - 1)); + LOG("Looking for a NSEC3 covering the next closer name "<getZoneRepresentation()<(r); + if(!nsec3) + continue; + + string h = hashQNameWithSalt(nsec3->d_salt, nsec3->d_iterations, nextCloser); + string beginHash=fromBase32Hex(v.first.first.getRawLabels()[0]); + + LOG("Comparing "<d_nexthash)) { + LOG("Denies existence of name "<d_flags & 1) { + LOG(" but is opt-out!"<d_tag<<" was " << (result ? "" : "NOT ")<<"valid"<d_siginception >= now) ? "not yet valid" : "expired")<d_siginception >= now) ? "not yet valid" : "expired")<<" (inception: "<d_siginception<<", expiration: "<d_sigexpire<<", now: "<