From: Remi Gacogne Date: Wed, 22 Nov 2017 11:02:17 +0000 (+0100) Subject: Merge pull request #5978 from rgacogne/rec-negcache-referral-to-unsigned X-Git-Tag: auth-4.1.0~22 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=206ae6160d1e9366b8c5a57858536ee45369200f;p=pdns Merge pull request #5978 from rgacogne/rec-negcache-referral-to-unsigned rec: Fix DNSSEC validation of DS denial from the negative cache --- 206ae6160d1e9366b8c5a57858536ee45369200f diff --cc pdns/recursordist/test-syncres_cc.cc index c5ed98d7f,c91f95cae..bd0cb1a88 --- a/pdns/recursordist/test-syncres_cc.cc +++ b/pdns/recursordist/test-syncres_cc.cc @@@ -8864,15 -8854,69 +8864,76 @@@ BOOST_AUTO_TEST_CASE(test_dnssec_valida BOOST_CHECK_EQUAL(sr->getValidationState(), Secure); BOOST_REQUIRE_EQUAL(ret.size(), 4); BOOST_CHECK_EQUAL(queriesCount, 4); + BOOST_CHECK_EQUAL(SyncRes::t_sstorage.negcache.size(), 1); + BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage.negcache.get(target, QType(QType::A), sr->getNow(), ne), true); + BOOST_CHECK_EQUAL(ne.d_validationState, Secure); + BOOST_CHECK_EQUAL(ne.authoritySOA.records.size(), 1); + BOOST_CHECK_EQUAL(ne.authoritySOA.signatures.size(), 1); + BOOST_CHECK_EQUAL(ne.DNSSECRecords.records.size(), 1); + BOOST_CHECK_EQUAL(ne.DNSSECRecords.signatures.size(), 1); } + BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_secure_ds) { + /* + Validation is optional, and the first query does not ask for it, + so the answer is negatively cached as Indeterminate. + The second query asks for validation, answer should be marked as + Secure. + The difference with test_dnssec_validation_from_negcache_secure is + that have one more level here, so we are going to look for the proof + that the DS does not exist for the last level. Since there is no cut, + we should accept the fact that the NSEC denies DS and NS both. + */ + std::unique_ptr sr; + initSR(sr, true); + + setDNSSECValidation(sr, DNSSECMode::Process); + + primeHints(); + const DNSName target("www.com."); + 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,&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 || type == QType::DNSKEY) { + if (domain == target) { + /* there is no cut */ + return genericDSAndDNSKEYHandler(res, domain, domain, type, keys, false); + } + return genericDSAndDNSKEYHandler(res, domain, domain, type, keys); + } + + return 0; + }); + + vector ret; + /* first query does not require validation */ + sr->setDNSSECValidationRequested(false); + int res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), Indeterminate); + BOOST_REQUIRE_EQUAL(ret.size(), 4); + BOOST_CHECK_EQUAL(queriesCount, 1); + + ret.clear(); + /* second one _does_ require validation */ + sr->setDNSSECValidationRequested(true); + res = sr->beginResolve(target, QType(QType::DS), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), Secure); + BOOST_REQUIRE_EQUAL(ret.size(), 4); + BOOST_CHECK_EQUAL(queriesCount, 4); + } + BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_insecure) { /* Validation is optional, and the first query does not ask for it,