From b3f0ed10d511989624531624afa275316c9ec3ab Mon Sep 17 00:00:00 2001 From: bert hubert Date: Fri, 27 Nov 2015 15:04:44 +0100 Subject: [PATCH] hook up the validator code with the recursor, keep toysdig independent so it can source records over TCP/IP --- build-scripts/dist-recursor | 9 ++++- pdns/Makefile-recursor | 7 +++- pdns/Makefile.am | 2 + pdns/pdns_recursor.cc | 16 +++++++- pdns/validate-recursor.cc | 69 +++++++++++++++++++++++++++++++++++ pdns/validate-recursor.hh | 5 +++ pdns/validate.cc | 73 ++++++++++++++++++++----------------- 7 files changed, 141 insertions(+), 40 deletions(-) create mode 100644 pdns/validate-recursor.cc create mode 100644 pdns/validate-recursor.hh diff --git a/build-scripts/dist-recursor b/build-scripts/dist-recursor index 663c0bf70..5c2304308 100755 --- a/build-scripts/dist-recursor +++ b/build-scripts/dist-recursor @@ -38,7 +38,7 @@ ws-recursor.hh ws-api.hh secpoll-recursor.hh \ responsestats.hh webserver.hh dnsname.hh dnspacket.hh ednssubnet.hh \ filterpo.hh rpzloader.hh ixfr.hh gss_context.hh resolver.hh dnssecinfra.hh \ dnsseckeeper.hh statbag.hh ueberbackend.hh sha.hh dnsbackend.hh comment.hh \ -ednssubnet.hh" +validate.hh validate-recursor.hh" CFILES="syncres.cc iputils.cc misc.cc unix_utility.cc qtype.cc \ logger.cc arguments.cc lwres.cc pdns_recursor.cc lua-iputils.cc \ @@ -50,7 +50,7 @@ devpollmplexer.cc recpacketcache.cc dns.cc reczones.cc base32.cc nsecrecords.cc dnslabeltext.cc json.cc ws-recursor.cc ws-api.cc version.cc dns_random.cc \ responsestats.cc webserver.cc rec-carbon.cc secpoll-recursor.cc dnsname.cc \ filterpo.cc rpzloader.cc ixfr.cc dnssecinfra.cc gss_context.cc resolver.cc \ -ednssubnet.cc" +ednssubnet.cc validate.cc validate-recursor.cc mbedtlssigners.cc" ./mkpubsuffixcc @@ -73,8 +73,13 @@ cp -a ../ext/rapidjson/include/rapidjson/*.h $DIRNAME/ext/rapidjson/include/rapi cp -a ../ext/rapidjson/include/rapidjson/internal/*.h $DIRNAME/ext/rapidjson/include/rapidjson/internal mkdir -p $DIRNAME/ext/mbedtls/include/mbedtls cp -a ../ext/mbedtls/include/mbedtls/{config.h,check_config.h,aes.h,ripemd160.h,sha1.h,md.h,md5.h,sha256.h,sha512.h,md_internal.h} ../ext/mbedtls/include/mbedtls/base64.h ../ext/mbedtls/include/mbedtls/platform.h ../ext/mbedtls/include/mbedtls/version.h $DIRNAME/ext/mbedtls/include/mbedtls +cp -a ../ext/mbedtls/include/mbedtls/{entropy.h,ctr_drbg.h,rsa.h,ecp.h,bignum.h,oid.h,asn1.h,pk.h,ecdsa.h,cipher.h,x509.h} $DIRNAME/ext/mbedtls/include/mbedtls +cp -a ../ext/mbedtls/include/mbedtls/{bn_mul.h,config.h,entropy_poll.h,timing.h} $DIRNAME/ext/mbedtls/include/mbedtls + mkdir -p $DIRNAME/ext/mbedtls/library cp -a ../ext/mbedtls/library/{aes.c,base64.c,md.c,md_wrap.c,md5.c,sha1.c,sha256.c,sha512.c,ripemd160.c} $DIRNAME/ext/mbedtls/library +cp -a ../ext/mbedtls/library/{rsa.c,bignum.c,oid.c,asn1parse.c,ctr_drbg.c,entropy.c,entropy_poll.c,timing.c} $DIRNAME/ext/mbedtls/library + cp -a ../ext/yahttp/ $DIRNAME/ext/yahttp echo '#include "../../../config.h"' > $DIRNAME/ext/yahttp/yahttp/yahttp-config.h mkdir $DIRNAME/rrd diff --git a/pdns/Makefile-recursor b/pdns/Makefile-recursor index baee721b2..436a56e32 100644 --- a/pdns/Makefile-recursor +++ b/pdns/Makefile-recursor @@ -23,13 +23,16 @@ rec_channel.o rec_channel_rec.o selectmplexer.o sillyrecords.o \ dns_random.o pubsuffix.o ext/mbedtls/library/aes.o ext/mbedtls/library/base64.o dnslabeltext.o \ ext/mbedtls/library/md5.o ext/mbedtls/library/sha1.o ext/mbedtls/library/sha256.o \ ext/mbedtls/library/sha512.o ext/mbedtls/library/md.o ext/mbedtls/library/md_wrap.o \ -ext/mbedtls/library/ripemd160.o \ +ext/mbedtls/library/ripemd160.o ext/mbedtls/library/rsa.o \ +ext/mbedtls/library/bignum.o ext/mbedtls/library/oid.o ext/mbedtls/library/asn1parse.o \ +ext/mbedtls/library/ctr_drbg.o ext/mbedtls/library/entropy.o ext/mbedtls/library/entropy_poll.o\ +ext/mbedtls/library/timing.o \ lua-pdns.o lua-recursor.o randomhelper.o recpacketcache.o dns.o \ reczones.o base32.o nsecrecords.o json.o ws-recursor.o ws-api.o \ version.o responsestats.o webserver.o ext/yahttp/yahttp/reqresp.o ext/yahttp/yahttp/router.o \ rec-carbon.o secpoll-recursor.o lua-iputils.o iputils.o dnsname.o \ rpzloader.o filterpo.o resolver.o ixfr.o dnssecinfra.o gss_context.o \ -ednssubnet.o +ednssubnet.o validate.o validate-recursor.o mbedtlssigners.o REC_CONTROL_OBJECTS=rec_channel.o rec_control.o arguments.o misc.o \ unix_utility.o logger.o qtype.o dnslabeltext.o dnsname.o diff --git a/pdns/Makefile.am b/pdns/Makefile.am index 4645b96de..474bceeb2 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -1122,6 +1122,7 @@ pdns_recursor_SOURCES = \ lua-recursor.cc lua-recursor.hh \ lwres.cc lwres.hh \ mbedtlscompat.hh \ + mbedtlssigners.cc \ misc.cc \ mtasker.hh \ nsecrecords.cc \ @@ -1147,6 +1148,7 @@ pdns_recursor_SOURCES = \ statbag.cc \ syncres.cc syncres.hh \ unix_utility.cc \ + validate.cc validate.hh validate-recursor.cc validate-recursor.hh \ version.cc version.hh \ webserver.cc webserver.hh \ ws-api.cc ws-api.hh \ diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 2a65c1e27..5d9e58cf3 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -76,6 +76,7 @@ #include "dnsname.hh" #include "filterpo.hh" #include "rpzloader.hh" +#include "validate-recursor.hh" #ifndef RECURSOR #include "statbag.hh" StatBag S; @@ -791,7 +792,7 @@ void startDoResolve(void *p) } } - if(res == PolicyDecision::PASS) { + if(res == PolicyDecision::PASS) { // XXX what does this MEAN? Why servfail on PASS? pw.getHeader()->rcode=RCode::ServFail; // no commit here, because no record g_stats.servFails++; @@ -799,6 +800,15 @@ void startDoResolve(void *p) else { pw.getHeader()->rcode=res; + if(edo.d_Z & EDNSOpts::DNSSECOK) { + if(validateRecords(ret)) + pw.getHeader()->ad=1; + else { + pw.getHeader()->rcode=RCode::ServFail; + goto sendit; + } + } + if(ret.size()) { orderAndShuffle(ret); for(auto i=ret.cbegin(); i!=ret.cend(); ++i) { @@ -816,10 +826,12 @@ void startDoResolve(void *p) } } - pw.commit(); + pw.commit(); } } sendit:; + + g_rs.submitResponse(dc->d_mdp.d_qtype, packet.size(), !dc->d_tcp); updateResponseStats(res, dc->d_remote, packet.size(), &dc->d_mdp.d_qname, dc->d_mdp.d_qtype); if(!dc->d_tcp) { diff --git a/pdns/validate-recursor.cc b/pdns/validate-recursor.cc new file mode 100644 index 000000000..89fd1de85 --- /dev/null +++ b/pdns/validate-recursor.cc @@ -0,0 +1,69 @@ +#include "validate.hh" +#include "validate-recursor.hh" +#include "syncres.hh" + +class SRRecordOracle : public DNSRecordOracle +{ +public: + vector get(const DNSName& qname, uint16_t qtype) override + { + struct timeval tv; + gettimeofday(&tv, 0); + SyncRes sr(tv); + + vector ret; + int res; + sr.d_doDNSSEC=true; + res=sr.beginResolve(qname, QType(qtype), 1, ret); + d_queries += sr.d_outqueries; + return ret; + } + int d_queries{0}; +}; + + +bool validateRecords(const vector& recs) +{ + g_rootDS = "19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5"; + cspmap_t cspmap=harvestCSPFromRecs(recs); + // cerr<<"Got "< keys; + cspmap_t validrrsets; + + SRRecordOracle sro; + + if(numsigs) { + for(const auto& csp : cspmap) { + for(const auto& sig : csp.second.signatures) { + // cerr<<"got rrsig "<d_signer<<"/"<d_tag<d_signer, keys); + // cerr<<"! state = "<d_name, keys); // um WHAT DOES THIS MEAN - try first qname?? + // cerr<<"! state = "<first.first<<"/"<first.second)<second.records.begin(); j!=i->second.records.end(); j++) { + // cerr<<"\t% > "<<(*j)->getZoneRepresentation()<& recs); diff --git a/pdns/validate.cc b/pdns/validate.cc index 233587c8d..8a5bd229b 100644 --- a/pdns/validate.cc +++ b/pdns/validate.cc @@ -48,23 +48,23 @@ static dState getDenial(cspmap_t &validrrsets, DNSName qname, uint16_t qtype) nsec3s.insert(make_pair(i->first.first, ns3r)); } } - cerr<<"got "< parts = i->first.getRawLabels(); string base=toLower(parts[0]); string next=toLower(toBase32Hex(i->second.d_nexthash)); string hashed = nsec3Hash(qname, i->second); - cerr<second.d_set.count(qtype)<second.d_set.count(qtype)<second.d_set.count(qtype) == 0) return INSECURE; // FIXME need to require 'NS in bitmap' here, otherwise no delegation! (but first, make sure this is reliable - does not work that way for direct auth queries) } else if ((hashed > base && hashed < next) || (next < base && (hashed < next || hashed > base))) { bool optout=(1 & i->second.d_flags); - cerr<<"negative name proof, optout = "< "<first.first)<<"/"<first.second)<<" with "<second.signatures.size()<<" sigs: "; + // cerr<<"validating "<<(i->first.first)<<"/"<first.second)<<" with "<second.signatures.size()<<" sigs: "; for(const auto& signature : i->second.signatures) { vector > toSign = i->second.records; if(getByTag(keys,signature->d_tag).empty()) { - cerr<<"No key provided for "<d_tag<d_tag<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 "; + ; // cerr<<"signature is expired/not yet valid "; } catch(std::exception& e) { - cerr<<"Error validating with engine: "<first] = i->second; - cerr<<"valid"<first.first<<"/"<d_type)<first.first<<"/"<d_type)<d_type != QType::DNSKEY) { dotEdge(signature->d_signer, "DNSKEY", signature->d_signer, lexical_cast(signature->d_tag), @@ -181,7 +182,7 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset) // start of this iteration // we can trust that dsmap has valid DS records for qname - cerr<<"got DS for ["< (rec); tkeys.insert(*drc); - cerr<<"Inserting key with tag "<getTag()<<": "<getZoneRepresentation()<getTag()<<": "<getZoneRepresentation()<(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()); } } - cerr<<"got "<second; auto r = getByTag(tkeys, i->first); - cerr<<"looking at DS with tag "<first<<", got "<first<<", got "<(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"); @@ -241,7 +242,7 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset) } } - cerr<<"got "<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); @@ -264,7 +265,7 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset) 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))<<" -> "<