From: Remi Gacogne Date: Tue, 6 Jun 2017 10:05:39 +0000 (+0200) Subject: rec: Pass the zone cuts and states around X-Git-Tag: rec-4.1.0-alpha1~50^2~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ad75fdbd433a8f14b58747aa17b03a3780926c5d;p=thirdparty%2Fpdns.git rec: Pass the zone cuts and states around --- diff --git a/pdns/syncres.cc b/pdns/syncres.cc index c9070e3e52..c94ab138d1 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -131,7 +131,8 @@ int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qcl return -1; set beenthere; - int res=doResolve(qname, qtype, ret, 0, beenthere, state); + SyncRes::zonesStates_t cuts; + int res=doResolve(qname, qtype, ret, 0, beenthere, state, cuts); d_queryValidationState = state; return res; } @@ -488,7 +489,7 @@ int SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, con * \param beenthere * \return DNS RCODE or -1 (Error) or -2 (RPZ hit) */ -int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, set& beenthere, vState& state) +int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, set& beenthere, vState& state, SyncRes::zonesStates_t& cuts) { string prefix; if(doLog()) { @@ -540,7 +541,7 @@ int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector SyncRes::getAddrs(const DNSName &qname, unsigned int depth, } vState newState = Indeterminate; - if(!doResolve(qname, type, res,depth+1, beenthere, newState) && !res.empty()) { // this consults cache, OR goes out + zonesStates_t cuts; + if(!doResolve(qname, type, res,depth+1, beenthere, newState, cuts) && !res.empty()) { // this consults cache, OR goes out for(res_t::const_iterator i=res.begin(); i!= res.end(); ++i) { if(i->d_type == QType::A || i->d_type == QType::AAAA) { if(auto rec = std::dynamic_pointer_cast(i->d_content)) @@ -796,7 +798,7 @@ DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType& qtyp return subdomain; } -bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector& ret, unsigned int depth, int &res, vState& state) +bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector& ret, unsigned int depth, int &res, vState& state, SyncRes::zonesStates_t& cuts) { string prefix; if(doLog()) { @@ -844,7 +846,7 @@ bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector setbeenthere; vState cnameState = Indeterminate; - res=doResolve(std::dynamic_pointer_cast(j->d_content)->getTarget(), qtype, ret, depth+1, beenthere, cnameState); + res=doResolve(std::dynamic_pointer_cast(j->d_content)->getTarget(), qtype, ret, depth+1, beenthere, cnameState, cuts); LOG("Updating validation state for response to "< dsrecords; vState state = Indeterminate; - int rcode = doResolve(zone, QType(QType::DS), dsrecords, depth + 1, beenthere, state); + int rcode = doResolve(zone, QType(QType::DS), dsrecords, depth + 1, beenthere, state, cuts); d_skipCNAMECheck = oldSkipCNAME; d_requireAuthData = oldRequireAuthData; @@ -1356,6 +1358,7 @@ vState SyncRes::getValidationStatus(const SyncRes::zonesStates_t& cuts, const DN do { const auto& it = cuts.find(name); if (it != cuts.cend()) { + LOG("Got status "<second]<<" for name "<second; } } @@ -1364,78 +1367,14 @@ vState SyncRes::getValidationStatus(const SyncRes::zonesStates_t& cuts, const DN return result; } -#if 0 -vState SyncRes::getValidationStatus(const DNSName& subdomain, unsigned int depth) +void SyncRes::computeZoneCuts(SyncRes::zonesStates_t& cuts, const DNSName& begin, const DNSName& end, unsigned int depth) { - if (!validationEnabled()) { - return Indeterminate; - } - - dsmap_t ds; - vState result = getTA(subdomain, ds); - if (result != Indeterminate) { - if (result == TA) { - result = Secure; - } - else if (result == NTA) { - result = Insecure; - } - - if (result == Secure && countSupportedDS(ds) == 0) { - ds.clear(); - result = Insecure; - } - - return result; - } - - vector cset; - if(t_RC->get(d_now.tv_sec, subdomain, QType(QType::DS), false, &cset, d_requestor, nullptr, nullptr, nullptr, &result) > 0) { - if (result != Indeterminate) { - return result; - } - } - - /* we are out of luck */ - DNSName higher(subdomain); - if (!higher.chopOff()) { - /* No (N)TA for ".", something is very wrong */ - return Bogus; - } - - result = getValidationStatus(higher, depth); - - if (result != Secure) { - /* we know we don't have any (N)TA, so we are done */ - return result; - } - - /* get subdomain DS */ - result = getDSRecords(subdomain, ds, false, depth); - - if (result == TA) { - result = Secure; - } - else if (result != Secure) { - if (result == NTA) { - result = Insecure; - } - return result; - } - - if (ds.empty()) { - return Insecure; + if (cuts.count(begin) != 0) { + return; } - return Secure; -} -#endif /* 0 */ - -SyncRes::zonesStates_t SyncRes::computeZoneCuts(const DNSName& begin, const DNSName& end, unsigned int depth) -{ - SyncRes::zonesStates_t cuts; dsmap_t ds; - vState cutState = getDSRecords(end, ds, false, depth); + vState cutState = getDSRecords(end, ds, false, depth, cuts); if (cutState == TA) { cutState = Secure; } @@ -1444,20 +1383,30 @@ SyncRes::zonesStates_t SyncRes::computeZoneCuts(const DNSName& begin, const DNSN } cuts[end] = cutState; - LOG(__func__<<", from "< labelsToAdd = begin.makeRelative(end).getRawLabels(); + bool oldSkipCNAME = d_skipCNAMECheck; + bool oldRequireAuthData = d_requireAuthData; + bool oldComputingZoneCut = d_computingZoneCut; + d_skipCNAMECheck = true; + d_requireAuthData = false; + d_computingZoneCut = true; + while(qname != begin) { bool foundCut = false; if (labelsToAdd.empty()) @@ -1467,18 +1416,12 @@ SyncRes::zonesStates_t SyncRes::computeZoneCuts(const DNSName& begin, const DNSN labelsToAdd.pop_back(); LOG("- Looking for a cut at "< beenthere; std::vector nsrecords; vState state = Indeterminate; - int rcode = doResolve(qname, QType(QType::NS), nsrecords, depth + 1, beenthere, state); - d_skipCNAMECheck = oldSkipCNAME; - d_requireAuthData = oldRequireAuthData; + SyncRes::zonesStates_t tempCuts; + int rcode = doResolve(qname, QType(QType::NS), nsrecords, depth + 1, beenthere, state, tempCuts); if (rcode == RCode::NoError && !nsrecords.empty()) { for (const auto& record : nsrecords) { @@ -1490,7 +1433,7 @@ SyncRes::zonesStates_t SyncRes::computeZoneCuts(const DNSName& begin, const DNSN if (foundCut) { LOG("- Found cut at "<& dnskeys, const std::vector >& signatures, unsigned int depth) +vState SyncRes::validateDNSKeys(const DNSName& zone, const std::vector& dnskeys, const std::vector >& signatures, unsigned int depth, SyncRes::zonesStates_t& cuts) { dsmap_t ds; if (!signatures.empty()) { DNSName signer = getSigner(signatures); if (!signer.empty() && signer.isPartOf(zone)) { - vState state = getDSRecords(signer, ds, false, depth); + vState state = getDSRecords(signer, ds, false, depth, cuts); if (state == TA) { state = Secure; @@ -1589,7 +1507,7 @@ vState SyncRes::validateDNSKeys(const DNSName& zone, const std::vector records; std::set beenthere; @@ -1599,7 +1517,7 @@ vState SyncRes::getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int /* following CNAME might lead to us to the wrong DNSKEY */ bool oldSkipCNAME = d_skipCNAMECheck; d_skipCNAMECheck = true; - int rcode = doResolve(signer, QType(QType::DNSKEY), records, depth + 1, beenthere, state); + int rcode = doResolve(signer, QType(QType::DNSKEY), records, depth + 1, beenthere, state, cuts); d_skipCNAMECheck = oldSkipCNAME; if (rcode == RCode::NoError) { @@ -1621,7 +1539,7 @@ vState SyncRes::getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int return Bogus; } -vState SyncRes::validateRecordsWithSigs(unsigned int depth, const DNSName& qname, const QType& qtype, const DNSName& name, const std::vector& records, const std::vector >& signatures) +vState SyncRes::validateRecordsWithSigs(unsigned int depth, const DNSName& qname, const QType& qtype, const DNSName& name, const std::vector& records, const std::vector >& signatures, SyncRes::zonesStates_t& cuts) { skeyset_t keys; if (!signatures.empty()) { @@ -1631,7 +1549,7 @@ vState SyncRes::validateRecordsWithSigs(unsigned int depth, const DNSName& qname /* we are already retrieving those keys, sorry */ return Indeterminate; } - vState state = getDNSKeys(signer, keys, depth); + vState state = getDNSKeys(signer, keys, depth, cuts); if (state != Secure) { return state; } @@ -1656,7 +1574,7 @@ vState SyncRes::validateRecordsWithSigs(unsigned int depth, const DNSName& qname return Bogus; } -RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, const DNSName& auth, bool wasForwarded, const boost::optional ednsmask, vState& state, const SyncRes::zonesStates_t& cuts, bool& needWildcardProof) +RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, const DNSName& auth, bool wasForwarded, const boost::optional ednsmask, vState& state, SyncRes::zonesStates_t& cuts, bool& needWildcardProof) { struct CacheEntry { @@ -1801,11 +1719,11 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& lwr */ if (i->first.type == QType::DNSKEY && i->first.place == DNSResourceRecord::ANSWER) { LOG("Validating DNSKEY for "<first.name<first.name, i->second.records, i->second.signatures, depth); + recordState = validateDNSKeys(i->first.name, i->second.records, i->second.signatures, depth, cuts); } else { LOG("Validating non-additional record for "<first.name<first.name, i->second.records, i->second.signatures); + recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures, cuts); } } } @@ -1813,7 +1731,7 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& lwr /* for non authoritative answer, we only care about the DS record (or lack of) */ if ((i->first.type == QType::DS || i->first.type == QType::NSEC || i->first.type == QType::NSEC3) && i->first.place == DNSResourceRecord::AUTHORITY) { LOG("Validating DS record for "<first.name<first.name, i->second.records, i->second.signatures); + recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures, cuts); } } updateValidationState(state, recordState); @@ -2105,7 +2023,7 @@ bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname, return true; } -bool SyncRes::processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, DNSName& auth, bool wasForwarded, const boost::optional ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state, const SyncRes::zonesStates_t& cuts) +bool SyncRes::processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, DNSName& auth, bool wasForwarded, const boost::optional ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state, SyncRes::zonesStates_t& cuts) { string prefix; if(doLog()) { @@ -2157,7 +2075,7 @@ bool SyncRes::processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qn set beenthere2; vState cnameState = Indeterminate; - *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2, cnameState); + *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2, cnameState, cuts); LOG("Updating validation state for response to "<&ret, - unsigned int depth, set&beenthere, vState& state, const SyncRes::zonesStates_t& cuts) + unsigned int depth, set&beenthere, vState& state, SyncRes::zonesStates_t& cuts) { auto luaconfsLocal = g_luaconfs.getLocal(); string prefix; diff --git a/pdns/syncres.hh b/pdns/syncres.hh index 247555fd4f..38f8be9431 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -702,15 +702,15 @@ private: typedef std::map zonesStates_t; int doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector&ret, - unsigned int depth, set&beenthere, vState& state, const zonesStates_t& cuts); + unsigned int depth, set&beenthere, vState& state, zonesStates_t& cuts); bool doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType& qtype, LWResult& lwr, boost::optional& ednsmask, const DNSName& auth, bool const sendRDQuery, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool* truncated); - bool processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, DNSName& auth, bool wasForwarded, const boost::optional ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state, const zonesStates_t& cuts); + bool processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, DNSName& auth, bool wasForwarded, const boost::optional ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state, zonesStates_t& cuts); - int doResolve(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, set& beenthere, vState& state); + int doResolve(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, set& beenthere, vState& state, zonesStates_t& cuts); bool doOOBResolve(const AuthDomain& domain, const DNSName &qname, const QType &qtype, vector&ret, int& res) const; bool doOOBResolve(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, int &res); domainmap_t::const_iterator getBestAuthZone(DNSName* qname) const; - bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, int &res, vState& state); + bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, int &res, vState& state, SyncRes::zonesStates_t& cuts); bool doCacheCheck(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, int &res, vState& state); void getBestNSFromCache(const DNSName &qname, const QType &qtype, vector&bestns, bool* flawedNSSet, unsigned int depth, set& beenthere); DNSName getBestNSNamesFromCache(const DNSName &qname, const QType &qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, set&beenthere); @@ -724,7 +724,7 @@ private: bool throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery); vector retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, vector::const_iterator& tns, const unsigned int depth, set& beenthere, const vector& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet); - RCode::rcodes_ updateCacheFromRecords(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, const DNSName& auth, bool wasForwarded, const boost::optional, vState& state, const zonesStates_t& cuts, bool& needWildcardProof); + RCode::rcodes_ updateCacheFromRecords(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, const DNSName& auth, bool wasForwarded, const boost::optional, vState& state, zonesStates_t& cuts, bool& needWildcardProof); bool processRecords(const std::string& prefix, const DNSName& qname, const QType& qtype, const DNSName& auth, LWResult& lwr, const bool sendRDQuery, vector& ret, set& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic, vState& state, bool needWildcardProof); bool doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector &ret); @@ -736,16 +736,15 @@ private: bool validationEnabled() const; uint32_t computeLowestTTD(const std::vector& records, const std::vector >& signatures, uint32_t signaturesTTL) const; void updateValidationState(vState& state, const vState stateUpdate); - void updateValidationStatusAfterReferral(const DNSName& qname, const DNSName& oldauth, const DNSName& newauth, vState& state, unsigned int depth); - vState validateRecordsWithSigs(unsigned int depth, const DNSName& qname, const QType& qtype, 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); - vState getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int depth); + vState validateRecordsWithSigs(unsigned int depth, const DNSName& qname, const QType& qtype, const DNSName& name, const std::vector& records, const std::vector >& signatures, zonesStates_t& cuts); + vState validateDNSKeys(const DNSName& zone, const std::vector& dnskeys, const std::vector >& signatures, unsigned int depth, SyncRes::zonesStates_t& cuts); + vState getDSRecords(const DNSName& zone, dsmap_t& ds, bool onlyTA, unsigned int depth, SyncRes::zonesStates_t& cuts); + vState getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int depth, zonesStates_t& cuts); void getDenialValidationState(NegCache::NegCacheEntry& ne, vState& state, const dState expectedState, bool allowOptOut); vState getTA(const DNSName& zone, dsmap_t& ds); vState getValidationStatus(const zonesStates_t& cuts, const DNSName& subdomain); - zonesStates_t computeZoneCuts(const DNSName& begin, const DNSName& end, unsigned int depth); + void computeZoneCuts(zonesStates_t& cuts, const DNSName& begin, const DNSName& end, unsigned int depth); void setUpdatingRootNS() { @@ -776,6 +775,7 @@ private: bool d_wantsRPZ{true}; bool d_wasOutOfBand{false}; bool d_wasVariable{false}; + bool d_computingZoneCut{false}; LogMode d_lm; };