From: bert hubert Date: Wed, 18 Nov 2015 21:24:10 +0000 (+0100) Subject: successfully validates most things, detects as bogus the obviously broken domains X-Git-Tag: dnsdist-1.0.0-alpha1~187^2~6 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9c3caa793fa1f95cddcb627ea98acef862cc6c39;p=pdns successfully validates most things, detects as bogus the obviously broken domains --- diff --git a/pdns/toysdig.cc b/pdns/toysdig.cc index 97fec8efd..032f79f03 100644 --- a/pdns/toysdig.cc +++ b/pdns/toysdig.cc @@ -88,7 +88,16 @@ enum dState { NODATA, NXDOMAIN, ENT, INSECURE }; const char *dStates[]={"nodata", "nxdomain", "empty non-terminal", "insecure (no-DS proof)"}; -typedef std::multimap keymap_t; +typedef std::set keyset_t; +vector getByTag(const keyset_t& keys, uint16_t tag) +{ + vector ret; + for(const auto& key : keys) + if(key.getTag() == tag) + ret.push_back(key); + return ret; +} + static string nsec3Hash(const DNSName &qname, const NSEC3RecordContent& nrc) { @@ -102,11 +111,10 @@ struct ContentSigPair { vector> records; vector> signatures; + // ponder adding a validate method that accepts a key }; typedef map, ContentSigPair> cspmap_t; - -typedef map, set > > rrsetmap_t; typedef pair NT; // Name/Type pair typedef std::multimap > recmap_t; typedef std::multimap sigmap_t; @@ -118,16 +126,16 @@ typedef pair ZT; //Zonename/keyTag pair // keymap_t g_vkeys; // validated keys // FIXME: needs a zone argument, to avoid things like 6840 4.1 -static dState getDenial(rrsetmap_t &validrrsets, DNSName qname, uint16_t qtype) +static dState getDenial(cspmap_t &validrrsets, DNSName qname, uint16_t qtype) { std::multimap nsec3s; - for(rrsetmap_t::const_iterator i=validrrsets.begin(); i!=validrrsets.end(); ++i) + for(auto i=validrrsets.begin(); i!=validrrsets.end(); ++i) { // FIXME also support NSEC if(i->first.second != QType::NSEC3) continue; - for(set >::const_iterator j=i->second.begin(); j!=i->second.end(); ++j) { + for(auto j=i->second.records.begin(); j!=i->second.records.end(); ++j) { NSEC3RecordContent ns3r = dynamic_cast (**j); // nsec3.insert(new nsec3() // cerr< "<first.first)<<"/"<first.second)<<" with "<second.signatures.size()<<" sigs: "; for(const auto& signature : i->second.signatures) { - for(auto k=i->second.records.begin(); k!=j->second.records.end(); k++) { - vector > toSign = j->records; - auto rrc = *signature->d_content; - - if(!keys.count(rrc.d_tag)) { - cerr<<"No key provided for "< > toSign = i->second.records; + + if(getByTag(keys,signature->d_tag).empty()) { + cerr<<"No key provided for "<d_tag<first.first, *signature, toSign); + auto r = getByTag(keys,signature->d_tag); // FIXME: also take algorithm into account? right now we wrongly validate unknownalgorithm.bad-dnssec.wb.sidnlabs.nl + for(const auto& l : r) { + bool isValid = false; + try { + unsigned int now=time(0); + if(signature->d_siginception < now && signature->d_sigexpire > now) + isValid = DNSCryptoKeyEngine::makeFromPublicKeyString(l.d_algorithm, l.d_key)->verify(msg, signature->d_signature); + else + cerr<<"signature is expired/not yet valid "; } - - string msg=getMessageForRRSET(j->first.first, rrc, toSign); - auto r = keys.equal_range(rrc.d_tag); // FIXME: also take algorithm into account? right now we wrongly validate unknownalgorithm.bad-dnssec.wb.sidnlabs.nl - for(keymap_t::const_iterator l=r.first; l!=r.second; l++) { - bool isValid = false; - try { - unsigned int now=time(0); - if(rrc.d_siginception < now && rrc.d_sigexpire > now) - isValid = DNSCryptoKeyEngine::makeFromPublicKeyString(l->second.d_algorithm, l->second.d_key)->verify(msg, rrc.d_signature); - } - catch(std::exception& e) { - cerr<<"Error validating with engine: "<first.first, j->first.second)] = rrs; - cerr<<"valid"<first.first<<"/"<(rrc.d_tag), - DNSRecordContent::NumberToType(rrc.d_type), j->first.first, "", isValid ? "green" : "red"); - - } - // FIXME: break out enough levels - } + catch(std::exception& e) { + cerr<<"Error validating with engine: "<first] = i->second; + cerr<<"valid"<first.first<<"/"<d_type)<d_type != QType::DNSKEY) { + dotEdge(signature->d_signer, + "DNSKEY", signature->d_signer, lexical_cast(signature->d_tag), + DNSRecordContent::NumberToType(signature->d_type), i->first.first, "", isValid ? "green" : "red"); + + } + // FIXME: break out enough levels } } } } + // returns vState // should return vState, zone cut and validated keyset // i.e. www.7bits.nl -> insecure/7bits.nl/[] @@ -243,7 +257,25 @@ static void validateWithKeySet(const cspmap& rrsets, cspmap_t& validated, keymap const char *rootDS; -static vState getKeysFor(TCPResolver& tr, const DNSName& zone, keymap_t &keyset) +cspmap_t harvestCSPFromMDP(const MOADNSParser& mdp) +{ + cspmap_t cspmap; + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { + // cerr<<"res "<first.d_name<<"/"<first.d_type<first.d_type == QType::OPT) continue; + + if(i->first.d_type == QType::RRSIG) { + auto rrc = getRR(i->first); + cspmap[{i->first.d_name,rrc->d_type}].signatures.push_back(getRR(i->first)); + } + else { + cspmap[{i->first.d_name, i->first.d_type}].records.push_back(i->first.d_content); + } + } + return cspmap; +} + +static vState getKeysFor(TCPResolver& tr, const DNSName& zone, keyset_t &keyset) { vector labels = zone.getRawLabels(); vState state; @@ -253,10 +285,9 @@ static vState getKeysFor(TCPResolver& tr, const DNSName& zone, keymap_t &keyset) DNSName qname("."); typedef std::multimap dsmap_t; dsmap_t dsmap; - keymap_t keymap; - recmap_t recs; + keyset_t validkeys; - state = Secure; + state = Secure; // nice while(zone.isPartOf(qname)) { if(qname.isRoot()) @@ -266,20 +297,19 @@ static vState getKeysFor(TCPResolver& tr, const DNSName& zone, keymap_t &keyset) dsmap.insert(make_pair(rootanchor.d_tag, rootanchor)); } - recs.clear(); vector sigs; vector > toSign; vector toSignTags; - keymap_t tkeymap; // tentative keys - keymap.clear(); + 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 ["<first.d_name != qname) continue; @@ -294,24 +324,24 @@ static vState getKeysFor(TCPResolver& tr, const DNSName& zone, keymap_t &keyset) else if(i->first.d_type == QType::DNSKEY) { auto drc=getRR (i->first); - tkeymap.insert(make_pair(drc->getTag(), *drc)); - + tkeys.insert(*drc); + cerr<<"Inserting key with tag "<getTag()<<": "<getZoneRepresentation()<(drc->getTag()), (boost::format("tag=%d, algo=%d") % drc->getTag() % static_cast(drc->d_algorithm)).str()); toSign.push_back(i->first.d_content); toSignTags.push_back(drc->getTag()); } } - cerr<<"got "<second; - cerr<<"looking at DS with tag "<first<<", got "<first)<<" DNSKEYs for tag"<first); - for(keymap_t::const_iterator j=r.first; j!=r.second; j++) + auto r = getByTag(tkeys, i->first); + cerr<<"looking at DS with tag "<first<<", got "<second; bool isValid = false; DSRecordContent dsrc2; try { @@ -324,22 +354,23 @@ static vState getKeysFor(TCPResolver& tr, const DNSName& zone, keymap_t &keyset) if(isValid) { cerr<<"got valid DNSKEY (it matches the DS) for "<(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()); + + validkeys.insert(drc); + dotNode("DS", qname, "" /*lexical_cast(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 { cerr<<"DNSKEY did not match the DS, parent DS: "< "<(dsrc.d_digesttype)<<"\" ]; label = \"zone: "<(dsrc.d_tag)*/, "DNSKEY", qname, lexical_cast(drc.getTag()), isValid ? "green" : "red"); + dotEdge(DNSName("."), "DS", qname, "" /*lexical_cast(dsrc.d_tag)*/, "DNSKEY", qname, lexical_cast(drc.getTag()), isValid ? "green" : "red"); // dotNode("DNSKEY", qname, (boost::format("tag=%d, algo=%d") % drc.getTag() % static_cast(drc.d_algorithm)).str()); } } - cerr<<"got "<d_tag<<" matching "<d_tag)<<" keys of which "<d_tag)<<" valid"<d_tag<<" matching "<d_tag).size()<<" keys of which "<d_tag).size()<<" valid"< r = keymap.equal_range(i->d_tag); - for(keymap_t::const_iterator j=r.first; j!=r.second; j++) { + auto bytag = getByTag(validkeys, i->d_tag); + for(const auto& j : bytag) { cerr<<"validating : "; bool isValid = false; try { unsigned int now = time(0); if(i->d_siginception < now && i->d_sigexpire > now) - isValid = DNSCryptoKeyEngine::makeFromPublicKeyString(j->second.d_algorithm, j->second.d_key)->verify(msg, i->d_signature); + isValid = DNSCryptoKeyEngine::makeFromPublicKeyString(j.d_algorithm, j.d_key)->verify(msg, i->d_signature); } catch(std::exception& e) { cerr<<"Could not make a validator for signature: "<d_signer))<<" -> "<first.d_name<<"/"<first.d_type<first.d_type == QType::OPT) continue; - - if(i->first.d_type == QType::RRSIG) { - auto rrc = getRR(i->first); - cspmap[{i->first.d_name,rrc->d_type}].signatures.push_back(getRR(i->first)); - } - else { - cspmap[{i->first.d_name, i->first.d_type}].push_back(i->first.d_content); - } - } + cspmap_t cspmap=harvestCSPFromMDP(mdp); cspmap_t validrrsets; - validateWithKeySet(cspmap, validrrsets, keymap); + validateWithKeySet(cspmap, validrrsets, validkeys); cerr<<"got "<second.records.cbegin(); j!=cspiter->second.records.cend(); j++) { - const auto dsrc=getRR(*j); + const auto dsrc=std::dynamic_pointer_cast(*j); dsmap.insert(make_pair(dsrc->d_tag, *dsrc)); // dotEdge(keyqname, // "DNSKEY", keyqname, , @@ -475,56 +492,40 @@ try auto mdp=getMDP(dest, qname, qtype); - rrsetmap_t rrsets; - rrsetmap_t rrsigs; - - for(auto i = mdp->d_answers.begin(); i != mdp->d_answers.end(); ++i) { - // cerr<<"res "<first.d_name<<"/"<first.d_type<first.d_type == QType::OPT) continue; - - if(i->first.d_type == QType::RRSIG) { - RRSIGRecordContent rrc = dynamic_cast (*(i->first.d_content)); - rrsigs[make_pair(i->first.d_name,rrc.d_type)].insert(i->first.d_content); - } - else { - rrsets[make_pair(i->first.d_name,i->first.d_type)].insert(i->first.d_content); - } + cspmap_t cspmap=harvestCSPFromMDP(*mdp); + cerr<<"Got "<second.begin(); j!=i->second.end(); j++) - { - cerr<<"B"< (*(*j)); - cerr<<"got rrsig "<d_signer<<"/"<d_tag<d_signer, keys); + cerr<<"! state = "<first.first<<"/"<first.second)< >::const_iterator j=i->second.begin(); j!=i->second.end(); j++) { + for(auto j=i->second.records.begin(); j!=i->second.records.end(); j++) { cerr<<"\t% > "<<(*j)->getZoneRepresentation()<