BOOST_CHECK_EQUAL(queriesCount, 8);
}
+BOOST_AUTO_TEST_CASE(test_dnssec_secure_a_then_ns) {
+ std::unique_ptr<SyncRes> 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<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> 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<DNSRecord> 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<SyncRes> 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<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> 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<DNSRecord> 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<SyncRes> sr;
initSR(sr, true);
/* 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();
/* 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) {
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();
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) {
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();
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) {
BOOST_CHECK_EQUAL(queriesCount, 6);
}
-#if 0
-BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_hidden_cut) {
- std::unique_ptr<SyncRes> 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<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> 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<DNSRecord> 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<SyncRes> sr;
initSR(sr, true);
if(!d_skipCNAMECheck && doCNAMECacheCheck(qname,qtype,ret,depth,res,state, cuts)) // will reroute us if needed
return res;
- if(doCacheCheck(qname,qtype,ret,depth,res,state)) // we done
+ if(doCacheCheck(qname,qtype,ret,depth,res,state,cuts)) // we done
return res;
}
/** This function explicitly goes out for A or AAAA addresses
*/
-vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set<GetBestNSAnswer>& beenthere)
+vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set<GetBestNSAnswer>& beenthere, zonesStates_t& cuts)
{
typedef vector<DNSRecord> res_t;
res_t res;
}
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) {
vector<DNSRecord> cset;
vector<std::shared_ptr<RRSIGRecordContent>> signatures;
vector<std::shared_ptr<DNSRecord>> 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.."<<endl);
+ state = SyncRes::validateRecordsWithSigs(depth, qname, QType(QType::CNAME), qname, cset, signatures, cuts);
+ LOG("Got Indeterminate state from the CNAME cache, validation result is "<<vStates[state]<<endl);
+ }
+
LOG(prefix<<qname<<": Found cache CNAME hit for '"<< qname << "|CNAME" <<"' to '"<<j->d_content->getZoneRepresentation()<<"', validation state is "<<vStates[state]<<endl);
+
DNSRecord dr=*j;
dr.d_ttl-=d_now.tv_sec;
ret.push_back(dr);
}
-bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state)
+bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state, SyncRes::zonesStates_t& cuts)
{
bool giveNegative=false;
vector<std::shared_ptr<RRSIGRecordContent>> signatures;
vector<std::shared_ptr<DNSRecord>> 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<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
+
+ if (validationEnabled() && sqt != QType::DNSKEY && wasCachedAuth && cachedState == 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 cache, validating.."<<endl);
+ cachedState = SyncRes::validateRecordsWithSigs(depth, sqname, sqt, sqname, cset, signatures, cuts);
+ LOG("Got Indeterminate state from the cache, validation result is "<<vStates[cachedState]<<endl);
+ }
+
for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
LOG(j->d_content->getZoneRepresentation());
if(j->d_ttl>(unsigned int) d_now.tv_sec) {
return false;
}
-vector<ComboAddress> SyncRes::retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, vector<DNSName >::const_iterator& tns, const unsigned int depth, set<GetBestNSAnswer>& beenthere, const vector<DNSName >& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet)
+vector<ComboAddress> SyncRes::retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, vector<DNSName >::const_iterator& tns, const unsigned int depth, set<GetBestNSAnswer>& beenthere, const vector<DNSName >& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet, zonesStates_t& cuts)
{
vector<ComboAddress> result;
if(!tns->empty()) {
LOG(prefix<<qname<<": Trying to resolve NS '"<<*tns<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
- result = getAddrs(*tns, depth+2, beenthere);
+ result = getAddrs(*tns, depth+2, beenthere, cuts);
pierceDontQuery=false;
}
else {
void SyncRes::computeZoneCuts(SyncRes::zonesStates_t& cuts, const DNSName& begin, const DNSName& end, unsigned int depth)
{
+ LOG(__func__<<", from "<<begin.toString()<<" to "<<end.toString()<<endl);
+ if(!begin.isPartOf(end)) {
+ LOG(end.toLogString()<<" is not part of "<<begin.toString()<<endl);
+ throw PDNSException(end.toLogString() + " is not part of " + begin.toString());
+ }
+
if (cuts.count(begin) != 0) {
+ LOG(begin.toLogString()<<" is already in the table!"<<endl);
+ return;
+ }
+
+ if (d_computingZoneCut) {
+ LOG(begin.toLogString()<<" already computing zone cut!"<<endl);
return;
}
cuts[end] = cutState;
if (!validationEnabled()) {
+ LOG("validation is not enabled"<<endl);
return;
}
- if(!begin.isPartOf(end)) {
- throw PDNSException(end.toLogString() + " is not part of " + begin.toString());
- }
-
- if (d_computingZoneCut) {
+/* if (d_computingZoneCut) {
+ LOG("already computing zone cuts!"<<endl);
return;
- }
-
- LOG(__func__<<", from "<<begin.toString()<<" to "<<end.toString()<<endl);
+ }*/
DNSName qname(end);
std::vector<string> labelsToAdd = begin.makeRelative(end).getRawLabels();
std::vector<DNSRecord> 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()) {
cuts[qname] = cutState;
}
}
+ if (!foundCut) {
+ /* remove the temporary cut */
+ cuts.erase(qname);
+ }
}
d_skipCNAMECheck = oldSkipCNAME;
continue;
// vState recordState = state;
- vState recordState = getValidationStatus(cuts, i->first.name);
+ vState recordState = getValidationStatus(cuts, auth);
LOG("Got status "<<vStates[recordState]<<" for record "<<i->first.name<<endl);
if (validationEnabled() && recordState == Secure) {
}
else {
if (validationEnabled()) {
- LOG("Skipping validation because the current state is "<<vStates[state]<<endl);
+ LOG("Skipping validation because the current state is "<<vStates[recordState]<<endl);
}
}
}
}
-bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, const QType& qtype, const DNSName& auth, LWResult& lwr, const bool sendRDQuery, vector<DNSRecord>& ret, set<DNSName>& 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<DNSRecord>& ret, set<DNSName>& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic, vState& state, bool needWildcardProof, zonesStates_t& cuts)
{
bool done = false;
rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
LOG(prefix<<qname<<": got negative indication of DS record for '"<<newauth<<"'"<<endl);
updateValidationState(state, Insecure);
+ auto cut = cuts.find(newauth);
+ if (cut != cuts.end()) {
+ if (cut->second == Indeterminate) {
+ cut->second = state;
+ }
+ }
+ else {
+ cuts[newauth] = state;
+ }
if(!wasVariable()) {
t_sstorage.negcache.add(ne);
}
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<<qname<<": status=got results, this level of recursion done"<<endl);
set<GetBestNSAnswer> 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 "<<qname<<" from "<<vStates[state]<<" with the state from the CNAME quest: "<<vStates[cnameState]<<endl);
updateValidationState(state, cnameState);
-
+ d_computingZoneCut = oldComputingZoneCut;
return true;
}
}
else {
/* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
- remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet);
+ remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet, cuts);
if(remoteIPs.empty()) {
LOG(prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);