From 428f41b7ced6f1b0a6bc2b0dae2acd7f5938355b Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 9 Jun 2017 16:30:57 +0200 Subject: [PATCH] rec: Use a single zone cuts and states variable --- pdns/recursor_cache.cc | 5 +- pdns/recursor_cache.hh | 2 +- pdns/recursordist/test-syncres_cc.cc | 325 ++++++++++++++++++--------- pdns/syncres.cc | 96 ++++++-- pdns/syncres.hh | 8 +- 5 files changed, 299 insertions(+), 137 deletions(-) diff --git a/pdns/recursor_cache.cc b/pdns/recursor_cache.cc index 65397f8e6..765216efa 100644 --- a/pdns/recursor_cache.cc +++ b/pdns/recursor_cache.cc @@ -34,7 +34,7 @@ unsigned int MemRecursorCache::bytes() } // returns -1 for no hits -int32_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, bool requireAuth, vector* res, const ComboAddress& who, vector>* signatures, std::vector>* authorityRecs, bool* variable, vState* state) +int32_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, bool requireAuth, vector* res, const ComboAddress& who, vector>* signatures, std::vector>* authorityRecs, bool* variable, vState* state, bool* wasAuth) { time_t ttd=0; // cerr<<"looking up "<< qname<<"|"+qt.getName()<<"\n"; @@ -93,6 +93,9 @@ int32_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, if(state) { *state = i->d_state; } + if(wasAuth) { + *wasAuth = i->d_auth; + } if(qt.getCode()!=QType::ANY && qt.getCode()!=QType::ADDR) // normally if we have a hit, we are done break; } diff --git a/pdns/recursor_cache.hh b/pdns/recursor_cache.hh index 78150d292..1eacf12b3 100644 --- a/pdns/recursor_cache.hh +++ b/pdns/recursor_cache.hh @@ -54,7 +54,7 @@ public: } unsigned int size(); unsigned int bytes(); - int32_t get(time_t, const DNSName &qname, const QType& qt, bool requireAuth, vector* res, const ComboAddress& who, vector>* signatures=nullptr, std::vector>* authorityRecs=nullptr, bool* variable=nullptr, vState* state=nullptr); + int32_t get(time_t, const DNSName &qname, const QType& qt, bool requireAuth, vector* res, const ComboAddress& who, vector>* signatures=nullptr, std::vector>* authorityRecs=nullptr, bool* variable=nullptr, vState* state=nullptr, bool* wasAuth=nullptr); void replace(time_t, const DNSName &qname, const QType& qt, const vector& content, const vector>& signatures, const std::vector>& authorityRecs, bool auth, boost::optional ednsmask=boost::none, vState state=Indeterminate); diff --git a/pdns/recursordist/test-syncres_cc.cc b/pdns/recursordist/test-syncres_cc.cc index 8c7b25c91..8c2190d6e 100644 --- a/pdns/recursordist/test-syncres_cc.cc +++ b/pdns/recursordist/test-syncres_cc.cc @@ -4073,6 +4073,218 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos) { BOOST_CHECK_EQUAL(queriesCount, 8); } +BOOST_AUTO_TEST_CASE(test_dnssec_secure_a_then_ns) { + std::unique_ptr sr; + initSR(sr, true); + + g_dnssecmode = DNSSECMode::ValidateAll; + + primeHints(); + const DNSName target("powerdns.com."); + const ComboAddress targetAddr("192.0.2.42"); + testkeysset_t keys; + + auto luaconfsCopy = g_luaconfs.getCopy(); + luaconfsCopy.dsAnchors.clear(); + generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors); + generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys); + generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys); + g_luaconfs.setState(luaconfsCopy); + + size_t queriesCount = 0; + + sr->setAsyncCallback([target,targetAddr,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res) { + queriesCount++; + + DNSName auth = domain; + if (domain == target) { + auth = DNSName("powerdns.com."); + } + if (type == QType::DS) { + return 0; + } + else if (type == QType::DNSKEY) { + setLWResult(res, 0, true, false, true); + addDNSKEY(keys, auth, 300, res->d_records); + addRRSIG(keys, res->d_records, auth, 300); + return 1; + } + else { + if (isRootServer(ip)) { + setLWResult(res, 0, false, false, true); + addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600); + addDS(DNSName("com."), 300, res->d_records, keys); + addRRSIG(keys, res->d_records, DNSName("."), 300); + addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); + return 1; + } + else if (ip == ComboAddress("192.0.2.1:53")) { + if (domain == DNSName("com.")) { + setLWResult(res, 0, true, false, true); + addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com."); + addRRSIG(keys, res->d_records, domain, 300); + addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); + addRRSIG(keys, res->d_records, domain, 300); + } + else { + setLWResult(res, 0, false, false, true); + addRecordToLW(res, auth, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600); + addDS(auth, 300, res->d_records, keys); + addRRSIG(keys, res->d_records, DNSName("com."), 300); + addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600); + } + return 1; + } + else if (ip == ComboAddress("192.0.2.2:53")) { + if (type == QType::NS) { + setLWResult(res, 0, true, false, true); + addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com."); + addRRSIG(keys, res->d_records, auth, 300); + addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600); + addRRSIG(keys, res->d_records, auth, 300); + } + else { + setLWResult(res, RCode::NoError, true, false, true); + addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600); + addRRSIG(keys, res->d_records, auth, 300); + } + return 1; + } + } + + return 0; + }); + + vector ret; + int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), Secure); + BOOST_REQUIRE_EQUAL(ret.size(), 2); + BOOST_CHECK_EQUAL(queriesCount, 8); + + /* again, to test the cache */ + ret.clear(); + res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), Secure); + BOOST_REQUIRE_EQUAL(ret.size(), 2); + BOOST_CHECK_EQUAL(queriesCount, 8); + + /* this time we ask for the NS that should be in the cache, to check + the validation status */ + ret.clear(); + res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), Secure); + BOOST_REQUIRE_EQUAL(ret.size(), 2); + BOOST_CHECK_EQUAL(queriesCount, 8); + +} + +BOOST_AUTO_TEST_CASE(test_dnssec_insecure_a_then_ns) { + std::unique_ptr sr; + initSR(sr, true); + + g_dnssecmode = DNSSECMode::ValidateAll; + + primeHints(); + const DNSName target("powerdns.com."); + const ComboAddress targetAddr("192.0.2.42"); + testkeysset_t keys; + + auto luaconfsCopy = g_luaconfs.getCopy(); + luaconfsCopy.dsAnchors.clear(); + generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors); + generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys); + g_luaconfs.setState(luaconfsCopy); + + size_t queriesCount = 0; + + sr->setAsyncCallback([target,targetAddr,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res) { + queriesCount++; + + DNSName auth = domain; + if (domain == target) { + auth = DNSName("powerdns.com."); + } + if (type == QType::DS) { + return 0; + } + else if (type == QType::DNSKEY) { + setLWResult(res, 0, true, false, true); + addDNSKEY(keys, auth, 300, res->d_records); + addRRSIG(keys, res->d_records, auth, 300); + return 1; + } + else { + if (isRootServer(ip)) { + setLWResult(res, 0, false, false, true); + addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600); + addDS(DNSName("com."), 300, res->d_records, keys); + addRRSIG(keys, res->d_records, DNSName("."), 300); + addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); + return 1; + } + else if (ip == ComboAddress("192.0.2.1:53")) { + if (domain == DNSName("com.")) { + setLWResult(res, 0, true, false, true); + addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com."); + addRRSIG(keys, res->d_records, domain, 300); + addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); + addRRSIG(keys, res->d_records, domain, 300); + } + else { + setLWResult(res, 0, false, false, true); + addRecordToLW(res, auth, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600); + /* no DS */ + addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records); + addRRSIG(keys, res->d_records, DNSName("com."), 300); + addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600); + } + return 1; + } + else if (ip == ComboAddress("192.0.2.2:53")) { + if (type == QType::NS) { + setLWResult(res, 0, true, false, true); + addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com."); + addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600); + } + else { + setLWResult(res, RCode::NoError, true, false, true); + addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600); + } + return 1; + } + } + + return 0; + }); + + vector ret; + int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure); + BOOST_REQUIRE_EQUAL(ret.size(), 1); + BOOST_CHECK_EQUAL(queriesCount, 7); + + /* again, to test the cache */ + ret.clear(); + res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure); + BOOST_REQUIRE_EQUAL(ret.size(), 1); + BOOST_CHECK_EQUAL(queriesCount, 7); + + /* this time we ask for the NS that should be in the cache, to check + the validation status */ + ret.clear(); + res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure); + BOOST_REQUIRE_EQUAL(ret.size(), 1); + BOOST_CHECK_EQUAL(queriesCount, 7); +} + BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta) { std::unique_ptr sr; initSR(sr, true); @@ -4165,7 +4377,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta) { /* Should be insecure because of the NTA */ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure); BOOST_REQUIRE_EQUAL(ret.size(), 2); - BOOST_CHECK_EQUAL(queriesCount, 8); + BOOST_CHECK_EQUAL(queriesCount, 7); /* again, to test the cache */ ret.clear(); @@ -4174,7 +4386,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta) { /* Should be insecure because of the NTA */ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure); BOOST_REQUIRE_EQUAL(ret.size(), 2); - BOOST_CHECK_EQUAL(queriesCount, 8); + BOOST_CHECK_EQUAL(queriesCount, 7); } BOOST_AUTO_TEST_CASE(test_dnssec_bogus_with_nta) { @@ -5764,7 +5976,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_secure_cname) { BOOST_CHECK_EQUAL(res, RCode::NoError); BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus); BOOST_REQUIRE_EQUAL(ret.size(), 3); - BOOST_CHECK_EQUAL(queriesCount, 12); + BOOST_CHECK_EQUAL(queriesCount, 11); /* again, to test the cache */ ret.clear(); @@ -5772,7 +5984,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_secure_cname) { BOOST_CHECK_EQUAL(res, RCode::NoError); BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus); BOOST_REQUIRE_EQUAL(ret.size(), 3); - BOOST_CHECK_EQUAL(queriesCount, 12); + BOOST_CHECK_EQUAL(queriesCount, 11); } BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname) { @@ -5865,7 +6077,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname) { BOOST_CHECK_EQUAL(res, RCode::NoError); BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus); BOOST_REQUIRE_EQUAL(ret.size(), 3); - BOOST_CHECK_EQUAL(queriesCount, 12); + BOOST_CHECK_EQUAL(queriesCount, 11); /* again, to test the cache */ ret.clear(); @@ -5873,7 +6085,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname) { BOOST_CHECK_EQUAL(res, RCode::NoError); BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus); BOOST_REQUIRE_EQUAL(ret.size(), 3); - BOOST_CHECK_EQUAL(queriesCount, 12); + BOOST_CHECK_EQUAL(queriesCount, 11); } BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_secure_cname) { @@ -6294,107 +6506,6 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta_norrsig) { BOOST_CHECK_EQUAL(queriesCount, 6); } -#if 0 -BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_hidden_cut) { - std::unique_ptr sr; - initSR(sr, true, true); - - g_dnssecLOG = true; - g_dnssecmode = DNSSECMode::ValidateAll; - - primeHints(); - const DNSName target("gov.nl.ca."); - const ComboAddress targetAddr("192.0.2.42"); - testkeysset_t keys; - - auto luaconfsCopy = g_luaconfs.getCopy(); - luaconfsCopy.dsAnchors.clear(); - generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors); - generateKeyMaterial(DNSName("ca."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys); - - g_luaconfs.setState(luaconfsCopy); - - size_t queriesCount = 0; - - sr->setAsyncCallback([target,targetAddr,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional& srcmask, boost::optional context, std::shared_ptr outgoingLogger, LWResult* res) { - queriesCount++; - - if (type == QType::DS) { - if (domain == g_rootdnsname || domain == DNSName("ca.")) { - setLWResult(res, 0, false, false, true); - addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER); - addRRSIG(keys, res->d_records, domain, 300); - return 1; - } - else { - setLWResult(res, 0, false, false, true); - addRecordToLW(res, DNSName("ca."), QType::SOA, "jbq01.prd.cira.ca. admin-dns.cira.ca. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600); - addNSECRecordToLW(DNSName("nl.ca."), DNSName("nm.ca."), { QType::NS }, 600, res->d_records); - addRRSIG(keys, res->d_records, DNSName("ca."), 300); - return 1; - } - } - else if (type == QType::DNSKEY) { - if (domain == g_rootdnsname || domain == DNSName("ca.")) { - setLWResult(res, 0, true, false, true); - addDNSKEY(keys, domain, 300, res->d_records); - addRRSIG(keys, res->d_records, domain, 300); - return 1; - } - else { - setLWResult(res, 0, false, false, true); - addRecordToLW(res, domain, QType::SOA, "jbq01.prd.cira.ca. admin-dns.cira.ca. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600); - return 1; - } - } - else if (domain == target) { - if (isRootServer(ip)) { - setLWResult(res, 0, false, false, true); - addRecordToLW(res, "ca.", QType::NS, "c.ca-servers.ca.", DNSResourceRecord::AUTHORITY, 3600); - addDS(DNSName("ca."), 300, res->d_records, keys); - addRRSIG(keys, res->d_records, DNSName("."), 300); - addRecordToLW(res, "c.ca-servers.ca.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); - return 1; - } - else if (ip == ComboAddress("192.0.2.1:53")) { - setLWResult(res, 0, false, false, true); - addRecordToLW(res, domain, QType::NS, "ns.gov.nl.ca.", DNSResourceRecord::AUTHORITY, 3600); - /* denial of DS FOR nl.ca while sending a referral for gov.nl.ca !! */ - addNSECRecordToLW(DNSName("nl.ca"), DNSName("nm.ca."), { QType::NS }, 600, res->d_records); - addRRSIG(keys, res->d_records, DNSName("ca."), 300); - addRecordToLW(res, "ns.gov.nl.ca.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600); - return 1; - } - else if (ip == ComboAddress("192.0.2.2:53")) { - setLWResult(res, 0, true, false, true); - addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600); - return 1; - } - } - - return 0; - }); - - vector ret; - int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); - BOOST_CHECK_EQUAL(res, RCode::NoError); - BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure); - BOOST_REQUIRE_EQUAL(ret.size(), 1); - BOOST_CHECK(ret[0].d_type == QType::A); - /* only 5 because no DNSKEY query for powerdns.com (insecure) */ - BOOST_CHECK_EQUAL(queriesCount, 5); - - /* again, to test the cache */ - ret.clear(); - res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); - BOOST_CHECK_EQUAL(res, RCode::NoError); - BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure); - BOOST_REQUIRE_EQUAL(ret.size(), 1); - BOOST_CHECK(ret[0].d_type == QType::A); - BOOST_CHECK_EQUAL(queriesCount, 5); -} -#endif /* 0 */ - BOOST_AUTO_TEST_CASE(test_dnssec_nta) { std::unique_ptr sr; initSR(sr, true); diff --git a/pdns/syncres.cc b/pdns/syncres.cc index 3ab08bfc5..fc986e9e5 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -544,7 +544,7 @@ int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set& beenthere) +vector SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set& beenthere, zonesStates_t& cuts) { typedef vector res_t; res_t res; @@ -620,7 +620,6 @@ vector SyncRes::getAddrs(const DNSName &qname, unsigned int depth, } vState newState = Indeterminate; - 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) { @@ -816,11 +815,22 @@ bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector vector cset; vector> signatures; vector> authorityRecs; - if(t_RC->get(d_now.tv_sec, qname, QType(QType::CNAME), d_requireAuthData, &cset, d_requestor, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &state) > 0) { + bool wasAuth; + if(t_RC->get(d_now.tv_sec, qname, QType(QType::CNAME), d_requireAuthData, &cset, d_requestor, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &state, &wasAuth) > 0) { for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) { if(j->d_ttl>(unsigned int) d_now.tv_sec) { + + if (validationEnabled() && wasAuth && state == Indeterminate && d_requireAuthData) { + /* This means we couldn't figure out the state when this entry was cached, + most likely because we hadn't computed the zone cuts yet. */ + LOG("Got Indeterminate state from the CNAME cache, validating.."<d_content->getZoneRepresentation()<<"', validation state is "<& records, const uint32 } -bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, int &res, vState& state) +bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, int &res, vState& state, SyncRes::zonesStates_t& cuts) { bool giveNegative=false; @@ -953,8 +963,20 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector> signatures; vector> authorityRecs; uint32_t ttl=0; - if(t_RC->get(d_now.tv_sec, sqname, sqt, d_requireAuthData, &cset, d_requestor, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &cachedState) > 0) { + bool wasCachedAuth; + if(t_RC->get(d_now.tv_sec, sqname, sqt, d_requireAuthData, &cset, d_requestor, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &cachedState, &wasCachedAuth) > 0) { + LOG(prefix<d_content->getZoneRepresentation()); if(j->d_ttl>(unsigned int) d_now.tv_sec) { @@ -1161,13 +1183,13 @@ bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAd return false; } -vector SyncRes::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) +vector SyncRes::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, zonesStates_t& cuts) { vector result; if(!tns->empty()) { LOG(prefix< labelsToAdd = begin.makeRelative(end).getRawLabels(); @@ -1420,7 +1450,10 @@ void SyncRes::computeZoneCuts(SyncRes::zonesStates_t& cuts, const DNSName& begin std::vector nsrecords; vState state = Indeterminate; - SyncRes::zonesStates_t tempCuts; + /* temporarily mark as Indeterminate, so that we won't enter an endless loop + trying to determine that zone cut again. */ + cuts[qname] = state; + SyncRes::zonesStates_t tempCuts = cuts; int rcode = doResolve(qname, QType(QType::NS), nsrecords, depth + 1, beenthere, state, tempCuts); if (rcode == RCode::NoError && !nsrecords.empty()) { @@ -1447,6 +1480,10 @@ void SyncRes::computeZoneCuts(SyncRes::zonesStates_t& cuts, const DNSName& begin cuts[qname] = cutState; } } + if (!foundCut) { + /* remove the temporary cut */ + cuts.erase(qname); + } } d_skipCNAMECheck = oldSkipCNAME; @@ -1712,7 +1749,7 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& lwr continue; // vState recordState = state; - vState recordState = getValidationStatus(cuts, i->first.name); + vState recordState = getValidationStatus(cuts, auth); LOG("Got status "<first.name<& ret, set& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic, vState& state, bool needWildcardProof) +bool SyncRes::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, zonesStates_t& cuts) { bool done = false; @@ -1873,6 +1910,15 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co rec.d_ttl = min(s_maxnegttl, rec.d_ttl); LOG(prefix<second == Indeterminate) { + cut->second = state; + } + } + else { + cuts[newauth] = state; + } if(!wasVariable()) { t_sstorage.negcache.add(ne); } @@ -2055,7 +2101,7 @@ bool SyncRes::processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qn DNSName newauth; DNSName newtarget; - bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic, state, needWildcardProof); + bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic, state, needWildcardProof, cuts); if(done){ LOG(prefix< beenthere2; vState cnameState = Indeterminate; - *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2, cnameState, cuts); + bool oldComputingZoneCut = d_computingZoneCut; + d_computingZoneCut = false; + *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2, cnameState, cuts); LOG("Updating validation state for response to "<&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, SyncRes::zonesStates_t& cuts); - bool doCacheCheck(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, int &res, vState& state); + bool doCacheCheck(const DNSName &qname, const QType &qtype, vector&ret, unsigned int depth, int &res, vState& state, SyncRes::zonesStates_t& cuts); 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); inline vector shuffleInSpeedOrder(NsSet &nameservers, const string &prefix); bool moreSpecificThan(const DNSName& a, const DNSName &b) const; - vector getAddrs(const DNSName &qname, unsigned int depth, set& beenthere); + vector getAddrs(const DNSName &qname, unsigned int depth, set& beenthere, zonesStates_t& cuts); bool nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers); bool nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress&); 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); + 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, zonesStates_t& cuts); 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 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, zonesStates_t& cuts); bool doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector &ret); -- 2.40.0