From: Remi Gacogne Date: Wed, 26 Jul 2017 13:51:21 +0000 (+0200) Subject: rec: Don't always validate when DNSSEC is set to process X-Git-Tag: dnsdist-1.2.0~34^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0c43f455a5a5f729562f21f1ddd533bb1180fb5a;p=pdns rec: Don't always validate when DNSSEC is set to process Also fix DNSSEC validation statistics. --- diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 997739a09..01e69844a 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -765,6 +765,7 @@ static void startDoResolve(void *p) uint32_t minTTL=std::numeric_limits::max(); SyncRes sr(dc->d_now); + bool DNSSECOK=false; if(t_pdl) { sr.setLuaEngine(t_pdl); @@ -782,9 +783,12 @@ static void startDoResolve(void *p) // Ignore the client-set CD flag pw.getHeader()->cd=0; } + sr.setDNSSECValidationRequested(g_dnssecmode == DNSSECMode::ValidateAll || g_dnssecmode==DNSSECMode::ValidateForLog || ((dc->d_mdp.d_header.ad || DNSSECOK) && g_dnssecmode==DNSSECMode::Process)); + #ifdef HAVE_PROTOBUF sr.setInitialRequestId(dc->d_uuid); #endif + if (g_useIncomingECS) { sr.setIncomingECSFound(dc->d_ecsFound); if (dc->d_ecsFound) { @@ -1030,7 +1034,7 @@ static void startDoResolve(void *p) pw.getHeader()->rcode=res; // Does the validation mode or query demand validation? - if(!shouldNotValidate && (g_dnssecmode == DNSSECMode::ValidateAll || g_dnssecmode==DNSSECMode::ValidateForLog || ((dc->d_mdp.d_header.ad || DNSSECOK) && g_dnssecmode==DNSSECMode::Process))) { + if(!shouldNotValidate && sr.isDNSSECValidationRequested()) { try { if(sr.doLog()) { L<d_mdp.d_qname<<"|"<d_mdp.d_qtype).getName()<<" for "<d_remote.toStringWithPort()<& sr, bool dnssec=false, bool debug=f sr = std::unique_ptr(new SyncRes(now)); sr->setDoEDNS0(true); - sr->setDoDNSSEC(dnssec); + if (dnssec) { + sr->setDoDNSSEC(dnssec); + } + sr->setLogMode(debug == false ? SyncRes::LogNone : SyncRes::Log); SyncRes::setDomainMap(std::make_shared()); SyncRes::clearNegCache(); } +static void setDNSSECValidation(std::unique_ptr& sr, const DNSSECMode& mode) +{ + sr->setDNSSECValidationRequested(true); + g_dnssecmode = mode; +} + static void setLWResult(LWResult* res, int rcode, bool aa=false, bool tc=false, bool edns=false) { res->d_rcode = rcode; @@ -3208,7 +3217,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_csk) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("."); @@ -3273,7 +3282,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_ksk_zsk) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("."); @@ -3359,7 +3368,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_dnskey) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("."); @@ -3423,7 +3432,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("."); @@ -3508,7 +3517,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("."); @@ -3583,7 +3592,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("."); @@ -3649,7 +3658,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_algorithm) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("."); @@ -3730,7 +3739,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_digest) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("."); @@ -3809,7 +3818,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_sig) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("."); @@ -3875,7 +3884,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_algo) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("."); @@ -3942,7 +3951,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -4041,7 +4050,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_a_then_ns) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -4149,7 +4158,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_a_then_ns) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -4253,7 +4262,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -4357,7 +4366,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_with_nta) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -4445,7 +4454,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -4541,7 +4550,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nxdomain_nsec) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("nx.powerdns.com."); @@ -4649,7 +4658,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("www.powerdns.com."); @@ -4752,7 +4761,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_secure) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("www.powerdns.com."); @@ -4862,7 +4871,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_insecure) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("www.powerdns.com."); @@ -4971,7 +4980,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_unsigned_nsec) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -5064,7 +5073,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_no_nsec) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -5157,7 +5166,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -5264,7 +5273,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("www.sub.powerdns.com."); @@ -5382,7 +5391,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_ta_skipped_cut) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("www.sub.powerdns.com."); @@ -5498,7 +5507,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nodata) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -5606,7 +5615,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -5730,7 +5739,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_secure_cname) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("power-dns.com."); @@ -5851,7 +5860,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_secure_cname) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("power-dns.com."); @@ -5952,7 +5961,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("power-dns.com."); @@ -6053,7 +6062,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_secure_cname) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("power-dns.com."); @@ -6154,7 +6163,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_insecure_cname) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -6271,7 +6280,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -6371,7 +6380,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta_norrsig) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("powerdns.com."); @@ -6471,7 +6480,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_nta) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("."); @@ -6537,7 +6546,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_no_ta) { std::unique_ptr sr; initSR(sr, true); - g_dnssecmode = DNSSECMode::ValidateAll; + setDNSSECValidation(sr, DNSSECMode::ValidateAll); primeHints(); const DNSName target("."); diff --git a/pdns/secpoll-recursor.cc b/pdns/secpoll-recursor.cc index 25d14187b..88145d16e 100644 --- a/pdns/secpoll-recursor.cc +++ b/pdns/secpoll-recursor.cc @@ -25,8 +25,11 @@ void doSecPoll(time_t* last_secpoll) struct timeval now; gettimeofday(&now, 0); SyncRes sr(now); - if (g_dnssecmode != DNSSECMode::Off) + if (g_dnssecmode != DNSSECMode::Off) { sr.setDoDNSSEC(true); + sr.setDNSSECValidationRequested(true); + } + vector ret; string version = "recursor-" +pkgv; diff --git a/pdns/syncres.cc b/pdns/syncres.cc index 0f608abfb..89975fc8e 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -135,6 +135,14 @@ int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qcl set beenthere; int res=doResolve(qname, qtype, ret, 0, beenthere, state); d_queryValidationState = state; + + if (d_queryValidationState != Indeterminate) { + g_stats.dnssecValidations++; + } + if (d_DNSSECValidationRequested) { + increaseDNSSECStateCounter(d_queryValidationState); + } + return res; } @@ -822,7 +830,7 @@ bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector 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) { + if (d_DNSSECValidationRequested && 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. */ /* make sure they are computed before validating */ @@ -978,7 +986,7 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector& records, const for(const auto& record : records) lowestTTD = min(lowestTTD, record.d_ttl); + /* even if it was not requested for that request (Process, and neither AD nor DO set), + it might be requested at a later time so we need to be careful with the TTL. */ if (validationEnabled() && !signatures.empty()) { /* if we are validating, we don't want to cache records after their signatures expires. */ @@ -1391,7 +1401,7 @@ vState SyncRes::getDSRecords(const DNSName& zone, dsmap_t& ds, bool taOnly, unsi bool SyncRes::haveExactValidationStatus(const DNSName& domain) { - if (!validationEnabled()) { + if (!d_DNSSECValidationRequested) { return false; } const auto& it = d_cutStates.find(domain); @@ -1405,7 +1415,7 @@ vState SyncRes::getValidationStatus(const DNSName& subdomain) { vState result = Indeterminate; - if (!validationEnabled()) { + if (!d_DNSSECValidationRequested) { return result; } DNSName name(subdomain); @@ -1443,7 +1453,7 @@ void SyncRes::computeZoneCuts(const DNSName& begin, const DNSName& end, unsigned LOG(d_prefix<<": setting cut state for "<first.name<first.place != DNSResourceRecord::ADDITIONAL) { /* the additional entries can be insecure, @@ -1839,7 +1849,7 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& lwr updateValidationState(state, recordState); } else { - if (validationEnabled()) { + if (d_DNSSECValidationRequested) { LOG(d_prefix<<"Skipping validation because the current state is "< ret; diff --git a/pdns/syncres.hh b/pdns/syncres.hh index cfe4ccf57..cbbae96c6 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -570,6 +570,16 @@ public: d_doDNSSEC=state; } + void setDNSSECValidationRequested(bool requested=true) + { + d_DNSSECValidationRequested = requested; + } + + bool isDNSSECValidationRequested() const + { + return d_DNSSECValidationRequested; + } + void setWantsRPZ(bool state=true) { d_wantsRPZ=state; @@ -778,6 +788,7 @@ private: */ bool d_cacheonly; bool d_doDNSSEC; + bool d_DNSSECValidationRequested{false}; bool d_doEDNS0{true}; bool d_incomingECSFound{false}; bool d_requireAuthData{true}; diff --git a/pdns/validate-recursor.cc b/pdns/validate-recursor.cc index ea36c83c9..83e383328 100644 --- a/pdns/validate-recursor.cc +++ b/pdns/validate-recursor.cc @@ -6,38 +6,6 @@ DNSSECMode g_dnssecmode{DNSSECMode::ProcessNoValidate}; bool g_dnssecLogBogus; -extern int getMTaskerTID(); - -#define LOG(x) if(g_dnssecLOG) { L < get(const DNSName& qname, uint16_t qtype) override - { - struct timeval tv; - gettimeofday(&tv, 0); - SyncRes sr(tv); - sr.setId(getMTaskerTID()); -#ifdef HAVE_PROTOBUF - sr.setInitialRequestId(d_ctx.d_initialRequestId); -#endif - - vector ret; - sr.setDoDNSSEC(true); - if (qtype == QType::DS || qtype == QType::DNSKEY || qtype == QType::NS) - sr.setSkipCNAMECheck(true); - sr.beginResolve(qname, QType(qtype), 1, ret); - d_queries += sr.d_outqueries; - return ret; - } - const ResolveContext& d_ctx; - unsigned int d_queries{0}; -}; - bool checkDNSSECDisabled() { return warnIfDNSSECDisabled(""); } @@ -51,127 +19,8 @@ bool warnIfDNSSECDisabled(const string& msg) { return false; } -static vState increaseDNSSECStateCounter(const vState& state) +vState increaseDNSSECStateCounter(const vState& state) { g_stats.dnssecResults[state]++; return state; } - -/* - * This inline possibly sets currentState based on the new state. It will only - * set it to Secure iff the newState is Secure and mayUpgradeToSecure == true. - * This should be set by the calling function when checking more than one record - * and this is not the first record, this way, we can never go *back* to Secure - * from an Insecure vState - */ -static void processNewState(vState& currentState, const vState& newState, bool& hadNTA, const bool& mayUpgradeToSecure) -{ - if (mayUpgradeToSecure && newState == Secure) - currentState = Secure; - - if (newState == Insecure || newState == NTA) // We can never go back to Secure - currentState = Insecure; - - if (newState == NTA) - hadNTA = true; -} - -vState validateRecords(const ResolveContext& ctx, const vector& recs) -{ - if(recs.empty()) - return Insecure; // can't secure nothing - - g_stats.dnssecValidations++; - - cspmap_t cspmap=harvestCSPFromRecs(recs); - LOG("Got "<d_signer, keys); // XXX check validity here - - if (newState == Bogus) // No hope - return increaseDNSSECStateCounter(Bogus); - - processNewState(state, newState, hadNTA, first); - - first = false; - - LOG("! state = "<getZoneRepresentation()<< " {tag="<getTag()<<"}"<d_name<first.first<<"/"<first.second)<second.records.begin(); j!=i->second.records.end(); j++) { - cerr<<"\t% > "<<(*j)->getZoneRepresentation()<& recs); /* Off: 3.x behaviour, we do no DNSSEC, no EDNS ProcessNoValidate: we gather DNSSEC records on all queries, but we will never validate @@ -41,3 +37,4 @@ extern bool g_dnssecLogBogus; bool checkDNSSECDisabled(); bool warnIfDNSSECDisabled(const string& msg); +vState increaseDNSSECStateCounter(const vState& state);