From 2cb98b9abdda1e03456697626a5001293cae2cec Mon Sep 17 00:00:00 2001 From: bert hubert Date: Wed, 18 Nov 2015 16:36:49 +0100 Subject: [PATCH] it is a wip, doesn't even compile --- pdns/Makefile.am | 5 + pdns/toysdig.cc | 408 ++++++++++++++++++++++------------------------- 2 files changed, 198 insertions(+), 215 deletions(-) diff --git a/pdns/Makefile.am b/pdns/Makefile.am index f0d0a23e3..20983d984 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -711,6 +711,11 @@ if GSS_TSIG toysdig_LDADD += $(GSS_LIBS) endif +if BOTAN110 +toysdig_SOURCES += botan110signers.cc botansigners.cc +toysdig_LDADD += $(BOTAN110_LIBS) +endif + tsig_tests_SOURCES = \ arguments.cc \ diff --git a/pdns/toysdig.cc b/pdns/toysdig.cc index 740b8d43d..97fec8efd 100644 --- a/pdns/toysdig.cc +++ b/pdns/toysdig.cc @@ -45,8 +45,11 @@ public: d_rsock.writen(string((char*)&*packet.begin(), (char*)&*packet.end())); - if(d_rsock.read((char *) &len, 2) != 2) - throw PDNSException("tcp read failed"); + int bread=d_rsock.read((char *) &len, 2); + if( bread <0) + throw PDNSException("tcp read failed: "+std::string(strerror(errno))); + if(bread != 2) + throw PDNSException("EOF on TCP read"); len=ntohs(len); char *creply = new char[len]; @@ -55,7 +58,7 @@ public: while(n g_anchors; - -vector getKeys(Socket& sock, const DNSName& name, uint16_t tag, bool* trusted) -{ - *trusted=false; - vector packet; - DNSPacketWriter pw(packet, name, QType::DNSKEY); - pw.getHeader()->rd=1; - pw.getHeader()->cd=1; - pw.getHeader()->id=getpid(); - pw.addOpt(1800, 0, EDNSOpts::DNSSECOK); - pw.commit(); - - sock.send(string((char*)&*packet.begin(), (char*)&*packet.end())); - string resp; - sock.read(resp); - MOADNSParser mdp(resp); - vector ret; - shared_ptr root; - for(const auto& r : mdp.d_answers) { - cout<getZoneRepresentation()<(r.first)) { - if(dk->getTag() == tag) { - cout<<"Found key with tag "<getTag()<getTag()<<" and DS "; - auto ds=makeDSFromDNSKey(name, *dk, 2); - cout<(r.first)) { - if(root) { - cout<<"Had a signature on "<d_tag<d_tag<d_algorithm, root->d_key); - vector> toSign; - toSign.push_back(std::make_shared(ret[0])); - toSign.push_back(root); - string msg = getMessageForRRSET(r.first.d_name, *rrsig, toSign); - *trusted=engine->verify(msg, rrsig->d_signature); - cout<<"Result for signature in DNSKEY: "<<*trusted< getMDP(const ComboAddress& dest, const DNSName& qname, uint16_t qtype) { TCPResolver tr(dest); - string resp=tr.query(qname, qtype); - return unique_ptr(new MOADNSParser(resp)); - + return make_unique(resp); } -void lookup(const ComboAddress& dest, const DNSName& qname, uint16_t qtype) -{ - if(qname==DNSName(".") && qtype == QType::DS) { - cerr<<"Hit root, should stop somehow ;-)"< packet; - - DNSPacketWriter pw(packet, qname, qtype); - pw.getHeader()->rd=1; - pw.getHeader()->cd=1; - pw.getHeader()->id=getpid(); - pw.addOpt(1800, 0, EDNSOpts::DNSSECOK); - pw.commit(); - - sock.send(string((char*)&*packet.begin(), (char*)&*packet.end())); - string resp; - sock.read(resp); - MOADNSParser mdp(resp); - - struct ContentPair { - vector content; - vector> signatures; - }; - - map, ContentPair > records; - - for(const auto& r : mdp.d_answers) { - cout<getZoneRepresentation()<(r.first)) { - records[make_pair(r.first.d_name, rrsig->d_type)].signatures.push_back(rrsig); - } - else if(auto opt = getRR(r.first)) { - continue; - } - - else - records[make_pair(r.first.d_name, r.first.d_type)].content.push_back(r.first); - - } - cout<<"Had "< > toSign; - for(const auto& c : rrset.second.content) - toSign.push_back(c.d_content); - - for(auto& sign : rrset.second.signatures) { - cout<<"Seeing if we can retrieve DNSKEY for "<d_signer<<" with tag "<d_tag<d_signer, sign->d_tag, &trusted); - cout<<"Got "<verify(msg, sign->d_signature)<d_signer<d_signer, QType::DS); - } - } - } - } -} - // 4033 5 -// FIXME: namespace this enum vState { Indeterminate, Bogus, Insecure, Secure }; const char *vStates[]={"Indeterminate", "Bogus", "Insecure", "Secure"}; // NSEC(3) results -// FIXME: namespace this enum dState { NODATA, NXDOMAIN, ENT, INSECURE }; const char *dStates[]={"nodata", "nxdomain", "empty non-terminal", "insecure (no-DS proof)"}; typedef std::multimap keymap_t; - -string nsec3Hash(const DNSName &qname, const NSEC3RecordContent& nrc) +static string nsec3Hash(const DNSName &qname, const NSEC3RecordContent& nrc) { NSEC3PARAMRecordContent ns3pr; ns3pr.d_iterations = nrc.d_iterations; @@ -231,11 +98,15 @@ string nsec3Hash(const DNSName &qname, const NSEC3RecordContent& nrc) return toBase32Hex(hashQNameWithSalt(ns3pr, qname)); } - +struct ContentSigPair +{ + vector> records; + vector> signatures; +}; +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; @@ -247,7 +118,7 @@ typedef pair ZT; //Zonename/keyTag pair // keymap_t g_vkeys; // validated keys // FIXME: needs a zone argument, to avoid things like 6840 4.1 -dState getDenial(rrsetmap_t &validrrsets, DNSName qname, uint16_t qtype) +static dState getDenial(rrsetmap_t &validrrsets, DNSName qname, uint16_t qtype) { std::multimap nsec3s; @@ -295,9 +166,9 @@ string dotEscape(string name) string dotName(string type, DNSName name, string tag) { if(tag == "") - return type+" "+name.toStringNoDot(); + return type+" "+name.toString(); else - return type+" "+name.toStringNoDot()+"/"+tag; + return type+" "+name.toString()+"/"+tag; } void dotNode(string type, DNSName name, string tag, string content) { @@ -309,36 +180,43 @@ void dotNode(string type, DNSName name, string tag, string content) void dotEdge(DNSName zone, string type1, DNSName name1, string tag1, string type2, DNSName name2, string tag2, string color="") { cout<<" "; - if(zone != DNSName(".")) cout<<"subgraph "< " <first.first)<<"/"<first.second)< r = rrsigs.equal_range(make_pair(i->first.first, i->first.second)); - for(rrsetmap_t::const_iterator j=r.first; j!=r.second; j++) { - for(set >::const_iterator k=j->second.begin(); k!=j->second.end(); k++) { - vector > toSign; - set > rrs = rrsets[make_pair(j->first.first, j->first.second)]; - toSign.assign(rrs.begin(), rrs.end()); - - const RRSIGRecordContent rrc=dynamic_cast (*(*k)); - - if(!keys.count(rrc.d_tag)) continue; + cerr<<"validating "<<(i->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 "<first.first, rrc, toSign); - pair r = keys.equal_range(rrc.d_tag); // FIXME: also take algorithm into account? right now we wrongly validate unknownalgorithm.bad-dnssec.wb.sidnlabs.nl + 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 = DNSCryptoKeyEngine::makeFromPublicKeyString(l->second.d_algorithm, l->second.d_key)->verify(msg, rrc.d_signature); + 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"< secure/powerdnssec.org/[keys] // www.dnssec-failed.org -> bogus/dnssec-failed.org/[] -char *rootDS; +const char *rootDS; -vState getKeysFor(TCPResolver& tr, const DNSName& zone, keymap_t &keyset) +static vState getKeysFor(TCPResolver& tr, const DNSName& zone, keymap_t &keyset) { vector labels = zone.getRawLabels(); vState state; @@ -408,38 +286,50 @@ vState getKeysFor(TCPResolver& tr, const DNSName& zone, keymap_t &keyset) if(i->first.d_type == QType::RRSIG) { - RRSIGRecordContent rrc=dynamic_cast (*(i->first.d_content)); - if(rrc.d_type != QType::DNSKEY) + auto rrc=getRR (i->first); + if(rrc->d_type != QType::DNSKEY) continue; - sigs.push_back(rrc); + sigs.push_back(*rrc); } else if(i->first.d_type == QType::DNSKEY) { - DNSKEYRecordContent drc=dynamic_cast (*(i->first.d_content)); - tkeymap.insert(make_pair(drc.getTag(), drc)); - dotNode("DNSKEY", qname, lexical_cast(drc.getTag()), (boost::format("tag=%d, algo=%d") % drc.getTag() % static_cast(drc.d_algorithm)).str()); + auto drc=getRR (i->first); + tkeymap.insert(make_pair(drc->getTag(), *drc)); + + dotNode("DNSKEY", qname, lexical_cast(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()); + toSignTags.push_back(drc->getTag()); } } - cerr<<"got "<second; - cerr<<"got DS with tag "<first<<", got "<first)<<" DNSKEYs for tag"< r = tkeymap.equal_range(i->first); + 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++) { DNSKEYRecordContent drc=j->second; - DSRecordContent dsrc2=makeDSFromDNSKey(qname, drc, dsrc.d_digesttype); - bool isValid = dsrc == dsrc2; + bool isValid = false; + DSRecordContent dsrc2; + try { + dsrc2=makeDSFromDNSKey(qname, drc, dsrc.d_digesttype); + isValid = dsrc == dsrc2; + } + catch(std::exception &e) { + cerr<<"Unable to make DS from DNSKey: "<(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"); // dotNode("DNSKEY", qname, (boost::format("tag=%d, algo=%d") % drc.getTag() % static_cast(drc.d_algorithm)).str()); @@ -461,14 +351,22 @@ vState getKeysFor(TCPResolver& tr, const DNSName& zone, keymap_t &keyset) string msg=getMessageForRRSET(qname, *i, toSign); pair r = keymap.equal_range(i->d_tag); for(keymap_t::const_iterator j=r.first; j!=r.second; j++) { - cerr<<"validating"<second.d_algorithm, j->second.d_key)->verify(msg, i->d_signature); - for(uint16_t tag : toSignTags) { - dotEdge(qname, - "DNSKEY", qname, lexical_cast(i->d_tag), - "DNSKEY", qname, lexical_cast(tag), isValid ? "green" : "red"); - } - + 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); + } + catch(std::exception& e) { + cerr<<"Could not make a validator for signature: "<(i->d_tag), + "DNSKEY", qname, lexical_cast(tag), isValid ? "green" : "red"); + } + if(isValid) { cerr<<"validation succeeded - whole DNSKEY set is valid"<first.d_name<<"/"<first.d_type<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); + auto rrc = getRR(i->first); + cspmap[{i->first.d_name,rrc->d_type}].signatures.push_back(getRR(i->first)); } else { - rrsets[make_pair(i->first.d_name,i->first.d_type)].insert(i->first.d_content); + cspmap[{i->first.d_name, i->first.d_type}].push_back(i->first.d_content); } } - rrsetmap_t validrrsets; - validateWithKeySet(rrsets, rrsigs, validrrsets, keymap); + cspmap_t validrrsets; + validateWithKeySet(cspmap, validrrsets, keymap); - cerr<<"got "< >::const_iterator j=i->second.begin(); j!=i->second.end(); j++) + for(auto cspiter =r.first; i!=r.second; i++) { + for(auto j=cspiter->second.records.cbegin(); j!=cspiter->second.records.cend(); j++) { - const DSRecordContent dsrc=dynamic_cast (**j); - dsmap.insert(make_pair(dsrc.d_tag, dsrc)); + const auto dsrc=getRR(*j); + dsmap.insert(make_pair(dsrc->d_tag, *dsrc)); // dotEdge(keyqname, // "DNSKEY", keyqname, , // "DS", qname, lexical_cast(dsrc.d_tag)); @@ -555,9 +453,6 @@ vState getKeysFor(TCPResolver& tr, const DNSName& zone, keymap_t &keyset) return state; } - - - int main(int argc, char** argv) try { @@ -566,9 +461,9 @@ try if(argv[5]) rootDS = argv[5]; - g_anchors.insert(DSRecordContent("19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5")); + // g_anchors.insert(DSRecordContent("19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5")); if(argc < 4) { - cerr<<"Syntax: sdig IP-address port question question-type\n"; + cerr<<"Syntax: toysdig IP-address port question question-type [rootDS]\n"; exit(EXIT_FAILURE); } ComboAddress dest(argv[1] + (*argv[1]=='@'), atoi(argv[2])); @@ -584,7 +479,7 @@ try 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_name<<"/"<first.d_type<first.d_type == QType::OPT) continue; if(i->first.d_type == QType::RRSIG) { @@ -598,8 +493,8 @@ try cerr<<"got "< r = rrsigs.equal_range(make_pair(qname, qtype)); - cerr<<"got "< >::const_iterator j=i->second.begin(); j!=i->second.end(); j++) + for(auto j=i->second.begin(); j!=i->second.end(); j++) { cerr<<"B"< (*(*j)); @@ -630,17 +525,100 @@ try for(rrsetmap_t::const_iterator i=validrrsets.begin(); i!=validrrsets.end(); i++) { cerr<<"% "<first.first<<"/"<first.second)< >::const_iterator j=i->second.begin(); j!=i->second.end(); j++) { - cerr<<"% > "<<(*j)->getZoneRepresentation()< "<<(*j)->getZoneRepresentation()< packet; + + DNSPacketWriter pw(packet, qname, qtype); + pw.getHeader()->rd=1; + pw.getHeader()->cd=1; + pw.getHeader()->id=getpid(); + pw.addOpt(1800, 0, EDNSOpts::DNSSECOK); + pw.commit(); + + sock.send(string((char*)&*packet.begin(), (char*)&*packet.end())); + string resp; + sock.read(resp); + MOADNSParser mdp(resp); + + struct ContentPair { + vector content; + vector> signatures; + }; + + map, ContentPair > records; + + for(const auto& r : mdp.d_answers) { + cout<getZoneRepresentation()<(r.first)) { + records[make_pair(r.first.d_name, rrsig->d_type)].signatures.push_back(rrsig); + } + else if(auto opt = getRR(r.first)) { + continue; + } + + else + records[make_pair(r.first.d_name, r.first.d_type)].content.push_back(r.first); + + } + cout<<"Had "< > toSign; + for(const auto& c : rrset.second.content) + toSign.push_back(c.d_content); + + for(auto& sign : rrset.second.signatures) { + cout<<"Seeing if we can retrieve DNSKEY for "<d_signer<<" with tag "<d_tag<d_signer, sign->d_tag, &trusted); + cout<<"Got "<verify(msg, sign->d_signature)<d_signer<d_signer, QType::DS); + } + } + } + } +} +#endif -- 2.40.0