From: Pieter Lexis Date: Wed, 31 Aug 2016 12:11:27 +0000 (+0200) Subject: DNSSEC: Implement keysearch based on zone-cuts X-Git-Tag: dnsdist-1.1.0-beta2~81^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7226d53b1fd71e016954e505f2c00ae21fea4d88;p=thirdparty%2Fpdns.git DNSSEC: Implement keysearch based on zone-cuts This prevents us sending out useless queries for DS records and doesn't confuse us anymore when the delegation jumps over several labels. --- diff --git a/pdns/validate.cc b/pdns/validate.cc index 534844c048..3bda3ca5aa 100644 --- a/pdns/validate.cc +++ b/pdns/validate.cc @@ -237,20 +237,22 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset) } } - vector labels = zone.getRawLabels(); - - dsmap_t dsmap; keyset_t validkeys; + dsmap_t dsmap; - DNSName qname = lowestTA; - vState state = Secure; // the lowest Trust Anchor is secure + dsmap_t* tmp = (dsmap_t*) rplookup(luaLocal->dsAnchors, lowestTA); + if (tmp) + dsmap = *tmp; - while(zone.isPartOf(qname)) - { - dsmap_t* tmp = (dsmap_t*) rplookup(luaLocal->dsAnchors, qname); - if (tmp) - dsmap = *tmp; + auto zoneCuts = getZoneCuts(zone, lowestTA, dro); + LOG("Found the following zonecuts:") + for(const auto& zonecut : zoneCuts) + LOG(" => "< sigs; vector > toSign; vector toSignTags; @@ -258,23 +260,22 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset) keyset_t tkeys; // tentative keys validkeys.clear(); - // start of this iteration - // we can trust that dsmap has valid DS records for qname - // cerr<<"got DS for ["< (rec); - LOG("Got signature: "<getZoneRepresentation()<<" with tag "<d_tag<<", for type "<d_type)<d_type != QType::DNSKEY) - continue; - sigs.push_back(*rrc); + if(rrc) { + LOG("Got signature: "<getZoneRepresentation()<<" with tag "<d_tag<<", for type "<d_type)<d_type != QType::DNSKEY) + continue; + sigs.push_back(*rrc); + } } else if(rec.d_type == QType::DNSKEY) { @@ -282,7 +283,7 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset) if(drc) { tkeys.insert(*drc); LOG("Inserting key with tag "<getTag()<<": "<getZoneRepresentation()<getTag()), (boost::format("tag=%d, algo=%d") % drc->getTag() % static_cast(drc->d_algorithm)).str()); + // dotNode("DNSKEY", *zoneCutIter, std::to_string(drc->getTag()), (boost::format("tag=%d, algo=%d") % drc->getTag() % static_cast(drc->d_algorithm)).str()); toSign.push_back(rec.d_content); toSignTags.push_back(drc->getTag()); @@ -291,6 +292,10 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset) } LOG("got "<(dsrc.d_digesttype) % static_cast(dsrc.d_algorithm)).str()); + dotNode("DS", *zoneCutIter, "" /*std::to_string(dsrc.d_tag)*/, (boost::format("tag=%d, digest algo=%d, algo=%d") % dsrc.d_tag % static_cast(dsrc.d_digesttype) % static_cast(dsrc.d_algorithm)).str()); } - else { - LOG("DNSKEY did not match the DS, parent DS: "< "<(dsrc.d_digesttype)<<"\" ]; label = \"zone: "<(drc.d_algorithm)).str()); + else { + LOG("DNSKEY did not match the DS, parent DS: "< "<(dsrc.d_digesttype)<<"\" ]; label = \"zone: "<<*zoneCutIter<<"\"; }"<(drc.d_algorithm)).str()); } } @@ -334,163 +339,152 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset) // whole set for(auto i=sigs.begin(); i!=sigs.end(); i++) { - // cerr<<"got sig for keytag "<d_tag<<" matching "<d_tag).size()<<" keys of which "<d_tag).size()<<" valid"<d_tag<<" matching "<d_tag).size()<<" keys of which "<d_tag).size()<<" valid"<d_tag); for(const auto& j : bytag) { - // cerr<<"validating : "; + // cerr<<"validating : "; bool isValid = false; - try { - unsigned int now = time(0); - if(i->d_siginception < now && i->d_sigexpire > now) { - std::shared_ptr dke = shared_ptr(DNSCryptoKeyEngine::makeFromPublicKeyString(j.d_algorithm, j.d_key)); - isValid = dke->verify(msg, i->d_signature); - } + try { + unsigned int now = time(0); + if(i->d_siginception < now && i->d_sigexpire > now) { + std::shared_ptr dke = shared_ptr(DNSCryptoKeyEngine::makeFromPublicKeyString(j.d_algorithm, j.d_key)); + isValid = dke->verify(msg, i->d_signature); + } else { LOG("Signature on DNSKEY expired"<d_tag), - "DNSKEY", qname, std::to_string(tag), isValid ? "green" : "red"); - } - + } + catch(std::exception& e) { + LOG("Could not make a validator for signature: "<d_tag), + "DNSKEY", *zoneCutIter, std::to_string(tag), isValid ? "green" : "red"); + } + if(isValid) { - LOG("validation succeeded - whole DNSKEY set is valid"<d_signer))<<" -> "<d_signer))<<" -> "<getZoneRepresentation()<(r); - if(nsec) { - if(v.first.first == qname && !nsec->d_set.count(QType::DS)) { - LOG("Denies existence of DS!"<d_next) ) { - LOG("Did not find DS for this level, trying one lower"<d_set.count(QType::DS)<<", next: "<d_next<getZoneRepresentation()<(r); - string h = hashQNameWithSalt(nsec3->d_salt, nsec3->d_iterations, qname); - // cerr<<"Salt length: "<d_salt.length()<<", iterations: "<d_iterations<<", hashed: "<d_nexthash) || - (nsec3->d_nexthash > h && beginHash > nsec3->d_nexthash) || // wrap // HASH --- END --- BEGINNING - (nsec3->d_nexthash < beginHash && beginHash < h) || // wrap other case // END -- BEGINNING -- HASH - beginHash == nsec3->d_nexthash) // "we have only 1 NSEC3 record, LOL!" - { + for(const auto& v : validrrsets) { + LOG("Do have: "<getZoneRepresentation()<(r); + if(nsec) { + if(v.first.first == *(zoneCutIter+1) && !nsec->d_set.count(QType::DS)) { LOG("Denies existence of DS!"<d_set.count(QType::DS)) { - LOG("Denies existence of DS (not opt-out)"<d_set.count(QType::DS)<<", next: "<d_next<second.records.cbegin(); j!=cspiter->second.records.cend(); j++) - { - const auto dsrc=std::dynamic_pointer_cast(*j); - if(dsrc) { - dsmap.insert(*dsrc); - // dotEdge(keyqname, - // "DNSKEY", keyqname, , - // "DS", qname, std::to_string(dsrc.d_tag)); - // cout<<" "< "<getZoneRepresentation()<(r); + string h = hashQNameWithSalt(nsec3->d_salt, nsec3->d_iterations, *(zoneCutIter+1)); + // cerr<<"Salt length: "<d_salt.length()<<", iterations: "<d_iterations<<", hashed: "<<*(zoneCutIter+1)<d_nexthash) || + (nsec3->d_nexthash > h && beginHash > nsec3->d_nexthash) || // wrap // HASH --- END --- BEGINNING + (nsec3->d_nexthash < beginHash && beginHash < h) || // wrap other case // END -- BEGINNING -- HASH + beginHash == nsec3->d_nexthash) // "we have only 1 NSEC3 record, LOL!" + { + LOG("Denies existence of DS!"<d_set.count(QType::DS)) { + LOG("Denies existence of DS (not opt-out)"<second.records.cbegin(); j!=cspiter->second.records.cend(); j++) + { + const auto dsrc=std::dynamic_pointer_cast(*j); + if(dsrc) { + dsmap.insert(*dsrc); + // dotEdge(key*(zoneCutIter+1), + // "DNSKEY", key*(zoneCutIter+1), , + // "DS", *(zoneCutIter+1), std::to_string(dsrc.d_tag)); + // cout<<" "< "<