From: Remi Gacogne Date: Mon, 6 Jul 2020 13:00:44 +0000 (+0200) Subject: rec: Validate cached DNSKEYs against the DSs, not the RRSIGs only X-Git-Tag: rec-4.4.0-alpha2~11^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F9309%2Fhead;p=thirdparty%2Fpdns.git rec: Validate cached DNSKEYs against the DSs, not the RRSIGs only DNSKEYs might be cached in a non-validated state ("Indeterminate") when the DNSSEC mode is set to "Process" and the initial query did not ask for validation. We would then validate the DNSKEY records against the RRSIGs, like for regular records, but not against the DSs. --- diff --git a/pdns/recursordist/test-syncres_cc4.cc b/pdns/recursordist/test-syncres_cc4.cc index f879409d4a..7c72748fdd 100644 --- a/pdns/recursordist/test-syncres_cc4.cc +++ b/pdns/recursordist/test-syncres_cc4.cc @@ -689,7 +689,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds) std::unique_ptr sr; initSR(sr, true); - setDNSSECValidation(sr, DNSSECMode::ValidateAll); + setDNSSECValidation(sr, DNSSECMode::Process); primeHints(); const DNSName target("."); @@ -754,6 +754,8 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds) return 0; }); + /* === with validation enabled === */ + sr->setDNSSECValidationRequested(true); vector ret; int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); BOOST_CHECK_EQUAL(res, RCode::NoError); @@ -769,6 +771,39 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_ds) BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus); BOOST_REQUIRE_EQUAL(ret.size(), 14U); BOOST_CHECK_EQUAL(queriesCount, 2U); + + /* === first without validation, then with (just-in-time validation) === */ + /* clear the caches */ + s_RC = std::unique_ptr(new MemRecursorCache()); + SyncRes::clearNegCache(); + sr->setDNSSECValidationRequested(false); + primeHints(); + + ret.clear(); + res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), Indeterminate); + /* 13 NS + 1 RRSIG */ + BOOST_REQUIRE_EQUAL(ret.size(), 14U); + BOOST_CHECK_EQUAL(queriesCount, 3U); + + /* now we ask for the DNSKEYs (still without validation) */ + ret.clear(); + res = sr->beginResolve(target, QType(QType::DNSKEY), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), Indeterminate); + /* 1 SOA + 1 RRSIG */ + BOOST_REQUIRE_EQUAL(ret.size(), 2U); + BOOST_CHECK_EQUAL(queriesCount, 4U); + + /* again, to test the cache WITH validation */ + sr->setDNSSECValidationRequested(true); + ret.clear(); + res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus); + BOOST_REQUIRE_EQUAL(ret.size(), 14U); + BOOST_CHECK_EQUAL(queriesCount, 4U); } BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey) diff --git a/pdns/syncres.cc b/pdns/syncres.cc index 19eaa418a4..f2e627939e 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -1598,7 +1598,12 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const DNSName& authname, bool w vState recordState = getValidationStatus(qname, false); if (recordState == Secure) { LOG(prefix<