]> granicus.if.org Git - pdns/commitdiff
hook up the validator code with the recursor, keep toysdig independent so it can...
authorbert hubert <bert.hubert@netherlabs.nl>
Fri, 27 Nov 2015 14:04:44 +0000 (15:04 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Fri, 27 Nov 2015 14:04:44 +0000 (15:04 +0100)
build-scripts/dist-recursor
pdns/Makefile-recursor
pdns/Makefile.am
pdns/pdns_recursor.cc
pdns/validate-recursor.cc [new file with mode: 0644]
pdns/validate-recursor.hh [new file with mode: 0644]
pdns/validate.cc

index 663c0bf70e7ae49f9bf6a8d3c2c37acaaaceb161..5c2304308849c7251947f4acbe8422021cdf1133 100755 (executable)
@@ -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
index baee721b2849d0594e5ce004c45d5f2b295be4c9..436a56e32dc430af97cc408ab562e3ace191701e 100644 (file)
@@ -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
index 4645b96de6388c971ccfe736de8919f56e56cea1..474bceeb289c0bf0aa03d9ddb918c57d1bddca6e 100644 (file)
@@ -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 \
index 2a65c1e27f9deaa8c9cacf318f928ccc350dda45..5d9e58cf34bf9e8a403ff530d9bba3408de8374a 100644 (file)
@@ -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 (file)
index 0000000..89fd1de
--- /dev/null
@@ -0,0 +1,69 @@
+#include "validate.hh"
+#include "validate-recursor.hh"
+#include "syncres.hh"
+
+class SRRecordOracle : public DNSRecordOracle
+{
+public:
+  vector<DNSRecord> get(const DNSName& qname, uint16_t qtype) override
+  {
+    struct timeval tv;
+    gettimeofday(&tv, 0);
+    SyncRes sr(tv);
+
+    vector<DNSRecord> 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<DNSRecord>& recs)
+{
+  g_rootDS =  "19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5";
+  cspmap_t cspmap=harvestCSPFromRecs(recs);
+  //  cerr<<"Got "<<cspmap.size()<<" RRSETs: ";
+  int numsigs=0;
+  for(const auto& csp : cspmap) {
+    //    cerr<<" "<<csp.first.first<<'/'<<DNSRecordContent::NumberToType(csp.first.second)<<": "<<csp.second.signatures.size()<<" sigs for "<<csp.second.records.size()<<" records"<<endl;
+    numsigs+= csp.second.signatures.size();
+  }
+   
+  set<DNSKEYRecordContent> keys;
+  cspmap_t validrrsets;
+
+  SRRecordOracle sro;
+
+  if(numsigs) {
+    for(const auto& csp : cspmap) {
+      for(const auto& sig : csp.second.signatures) {
+       //      cerr<<"got rrsig "<<sig->d_signer<<"/"<<sig->d_tag<<endl;
+       vState state = getKeysFor(sro, sig->d_signer, keys);
+       //      cerr<<"! state = "<<vStates[state]<<", now have "<<keys.size()<<" keys"<<endl;
+        // dsmap.insert(make_pair(dsrc.d_tag, dsrc));
+      }
+    }
+
+    validateWithKeySet(cspmap, validrrsets, keys);
+  }
+  else {
+    //    cerr<<"no sigs, hoping for Insecure"<<endl;
+    vState state = getKeysFor(sro, recs.begin()->d_name, keys); // um WHAT DOES THIS MEAN - try first qname??
+    //    cerr<<"! state = "<<vStates[state]<<", now have "<<keys.size()<<" keys "<<endl;
+  }
+  //  cerr<<"! validated "<<validrrsets.size()<<" RRsets out of "<<cspmap.size()<<endl;
+
+  //  cerr<<"% validated RRs:"<<endl;
+  for(auto i=validrrsets.begin(); i!=validrrsets.end(); i++) {
+    //    cerr<<"% "<<i->first.first<<"/"<<DNSRecordContent::NumberToType(i->first.second)<<endl;
+    for(auto j=i->second.records.begin(); j!=i->second.records.end(); j++) {
+      //      cerr<<"\t% > "<<(*j)->getZoneRepresentation()<<endl;
+    }
+  }
+  //  cerr<<"Took "<<sro.d_queries<<" queries"<<endl;
+  return validrrsets.size() == cspmap.size();
+}
diff --git a/pdns/validate-recursor.hh b/pdns/validate-recursor.hh
new file mode 100644 (file)
index 0000000..e3fd399
--- /dev/null
@@ -0,0 +1,5 @@
+#pragma once
+#include "dnsparser.hh"
+#include "namespaces.hh"
+
+bool validateRecords(const vector<DNSRecord>& recs);
index 233587c8d365a79603709c842380ee31cf4044a1..8a5bd229b8ee52d4d287d16c9868ba108d5a1d44 100644 (file)
@@ -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 "<<nsec3s.size()<<" NSEC3s"<<endl;
+  //  cerr<<"got "<<nsec3s.size()<<" NSEC3s"<<endl;
   for(auto i=nsec3s.begin(); i != nsec3s.end(); ++i) {
     vector<string> parts = i->first.getRawLabels();
 
       string base=toLower(parts[0]);
       string next=toLower(toBase32Hex(i->second.d_nexthash));
       string hashed = nsec3Hash(qname, i->second);
-      cerr<<base<<" .. ? "<<hashed<<" ("<<qname<<") ? .. "<<next<<endl;
+      //      cerr<<base<<" .. ? "<<hashed<<" ("<<qname<<") ? .. "<<next<<endl;
       if(base==hashed) {
         // positive name proof, need to check type
-        cerr<<"positive name proof, checking type bitmap"<<endl;
-        cerr<<"d_set.count("<<qtype<<"): "<<i->second.d_set.count(qtype)<<endl;
+       //        cerr<<"positive name proof, checking type bitmap"<<endl;
+       //        cerr<<"d_set.count("<<qtype<<"): "<<i->second.d_set.count(qtype)<<endl;
         if(qtype == QType::DS && i->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 = "<<optout<<endl;
+       //        cerr<<"negative name proof, optout = "<<optout<<endl;
         if(qtype == QType::DS && optout) return INSECURE;
       }
   }
@@ -75,17 +75,18 @@ static dState getDenial(cspmap_t &validrrsets, DNSName qname, uint16_t qtype)
 void validateWithKeySet(const cspmap_t& rrsets, cspmap_t& validated, const keyset_t& keys)
 {
   validated.clear();
-  cerr<<"Validating an rrset with following keys: "<<endl;
+  /*  cerr<<"Validating an rrset with following keys: "<<endl;
   for(auto& key : keys) {
     cerr<<"\tTag: "<<key.getTag()<<" -> "<<key.getZoneRepresentation()<<endl;
   }
+  */
   for(auto i=rrsets.begin(); i!=rrsets.end(); i++) {
-    cerr<<"validating "<<(i->first.first)<<"/"<<DNSRecordContent::NumberToType(i->first.second)<<" with "<<i->second.signatures.size()<<" sigs: ";
+    //    cerr<<"validating "<<(i->first.first)<<"/"<<DNSRecordContent::NumberToType(i->first.second)<<" with "<<i->second.signatures.size()<<" sigs: ";
     for(const auto& signature : i->second.signatures) {
       vector<shared_ptr<DNSRecordContent> > toSign = i->second.records;
       
       if(getByTag(keys,signature->d_tag).empty()) {
-       cerr<<"No key provided for "<<signature->d_tag<<endl;
+       //      cerr<<"No key provided for "<<signature->d_tag<<endl;
        continue;
       }
       
@@ -98,18 +99,18 @@ void validateWithKeySet(const cspmap_t& rrsets, cspmap_t& validated, const keyse
          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 ";
+           ; // cerr<<"signature is expired/not yet valid ";
        }
        catch(std::exception& e) {
-         cerr<<"Error validating with engine: "<<e.what()<<endl;
+         // cerr<<"Error validating with engine: "<<e.what()<<endl;
        }
        if(isValid) {
          validated[i->first] = i->second;
-         cerr<<"valid"<<endl;
-         cerr<<"! validated "<<i->first.first<<"/"<<DNSRecordContent::NumberToType(signature->d_type)<<endl;
+         //      cerr<<"valid"<<endl;
+         //      cerr<<"! validated "<<i->first.first<<"/"<<DNSRecordContent::NumberToType(signature->d_type)<<endl;
        }
        else 
-         cerr<<"signature invalid"<<endl;
+         ; // cerr<<"signature invalid"<<endl;
        if(signature->d_type != QType::DNSKEY) {
          dotEdge(signature->d_signer,
                  "DNSKEY", signature->d_signer, lexical_cast<string>(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 ["<<qname<<"], grabbing DNSKEYs"<<endl;
+    //    cerr<<"got DS for ["<<qname<<"], grabbing DNSKEYs"<<endl;
     auto recs=dro.get(qname, (uint16_t)QType::DNSKEY);
     // this should use harvest perhaps
     for(const auto& rec : recs) {
@@ -199,20 +200,20 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset)
       {
         auto drc=getRR<DNSKEYRecordContent> (rec);
         tkeys.insert(*drc);
-       cerr<<"Inserting key with tag "<<drc->getTag()<<": "<<drc->getZoneRepresentation()<<endl;
+       //      cerr<<"Inserting key with tag "<<drc->getTag()<<": "<<drc->getZoneRepresentation()<<endl;
        dotNode("DNSKEY", qname, lexical_cast<string>(drc->getTag()), (boost::format("tag=%d, algo=%d") % drc->getTag() % static_cast<int>(drc->d_algorithm)).str());
 
         toSign.push_back(rec.d_content);
         toSignTags.push_back(drc->getTag());
       }
     }
-    cerr<<"got "<<tkeys.size()<<" keys and "<<sigs.size()<<" sigs from server"<<endl;
+    //    cerr<<"got "<<tkeys.size()<<" keys and "<<sigs.size()<<" sigs from server"<<endl;
 
     for(dsmap_t::const_iterator i=dsmap.begin(); i!=dsmap.end(); i++)
     {
       DSRecordContent dsrc=i->second;
       auto r = getByTag(tkeys, i->first);
-      cerr<<"looking at DS with tag "<<dsrc.d_tag<<"/"<<i->first<<", got "<<r.size()<<" DNSKEYs for tag"<<endl;
+      //      cerr<<"looking at DS with tag "<<dsrc.d_tag<<"/"<<i->first<<", got "<<r.size()<<" DNSKEYs for tag"<<endl;
 
       for(const auto& drc : r) 
       {
@@ -223,17 +224,17 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset)
          isValid = dsrc == dsrc2;
        } 
        catch(std::exception &e) {
-         cerr<<"Unable to make DS from DNSKey: "<<e.what()<<endl;
+         //      cerr<<"Unable to make DS from DNSKey: "<<e.what()<<endl;
        }
 
         if(isValid) {
-          cerr<<"got valid DNSKEY (it matches the DS) for "<<qname<<endl;
+         //          cerr<<"got valid DNSKEY (it matches the DS) for "<<qname<<endl;
          
           validkeys.insert(drc);
          dotNode("DS", qname, "" /*lexical_cast<string>(dsrc.d_tag)*/, (boost::format("tag=%d, digest algo=%d, algo=%d") % dsrc.d_tag % static_cast<int>(dsrc.d_digesttype) % static_cast<int>(dsrc.d_algorithm)).str());
         }
        else {
-         cerr<<"DNSKEY did not match the DS, parent DS: "<<drc.getZoneRepresentation() << " ! = "<<dsrc2.getZoneRepresentation()<<endl;
+         //      cerr<<"DNSKEY did not match the DS, parent DS: "<<drc.getZoneRepresentation() << " ! = "<<dsrc2.getZoneRepresentation()<<endl;
        }
         // cout<<"    subgraph "<<dotEscape("cluster "+qname)<<" { "<<dotEscape("DS "+qname)<<" -> "<<dotEscape("DNSKEY "+qname)<<" [ label = \""<<dsrc.d_tag<<"/"<<static_cast<int>(dsrc.d_digesttype)<<"\" ]; label = \"zone: "<<qname<<"\"; }"<<endl;
        dotEdge(DNSName("."), "DS", qname, "" /*lexical_cast<string>(dsrc.d_tag)*/, "DNSKEY", qname, lexical_cast<string>(drc.getTag()), isValid ? "green" : "red");
@@ -241,7 +242,7 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset)
       }
     }
 
-    cerr<<"got "<<validkeys.size()<<"/"<<tkeys.size()<<" valid/tentative keys"<<endl;
+    //    cerr<<"got "<<validkeys.size()<<"/"<<tkeys.size()<<" valid/tentative keys"<<endl;
     // these counts could be off if we somehow ended up with 
     // duplicate keys. Should switch to a type that prevents that.
     if(validkeys.size() < tkeys.size())
@@ -252,11 +253,11 @@ 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 "<<i->d_tag<<" matching "<<getByTag(tkeys, i->d_tag).size()<<" keys of which "<<getByTag(validkeys, i->d_tag).size()<<" valid"<<endl;
+       //        cerr<<"got sig for keytag "<<i->d_tag<<" matching "<<getByTag(tkeys, i->d_tag).size()<<" keys of which "<<getByTag(validkeys, i->d_tag).size()<<" valid"<<endl;
         string msg=getMessageForRRSET(qname, *i, toSign);
         auto bytag = getByTag(validkeys, i->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: "<<e.what()<<endl;
+           //      cerr<<"Could not make a validator for signature: "<<e.what()<<endl;
          }
          for(uint16_t tag : toSignTags) {
            dotEdge(qname,
@@ -274,36 +275,36 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset)
          
           if(isValid)
           {
-            cerr<<"validation succeeded - whole DNSKEY set is valid"<<endl;
+           //            cerr<<"validation succeeded - whole DNSKEY set is valid"<<endl;
             // cout<<"    "<<dotEscape("DNSKEY "+stripDot(i->d_signer))<<" -> "<<dotEscape("DNSKEY "+qname)<<";"<<endl;
             validkeys=tkeys;
             break;
           }
          else
-           cerr<<"Validation did not succeed!"<<endl;
+           ; // cerr<<"Validation did not succeed!"<<endl;
         }
-        if(validkeys.empty()) cerr<<"did not manage to validate DNSKEY set based on DS-validated KSK, only passing KSK on"<<endl;
+       //        if(validkeys.empty()) cerr<<"did not manage to validate DNSKEY set based on DS-validated KSK, only passing KSK on"<<endl;
       }
     }
 
     if(validkeys.empty())
     {
-      cerr<<"ended up with zero valid DNSKEYs, going Bogus"<<endl;
+      //      cerr<<"ended up with zero valid DNSKEYs, going Bogus"<<endl;
       state=Bogus;
       break;
     }
-    cerr<<"situation: we have one or more valid DNSKEYs for ["<<qname<<"] (want ["<<zone<<"])"<<endl;
+    //    cerr<<"situation: we have one or more valid DNSKEYs for ["<<qname<<"] (want ["<<zone<<"])"<<endl;
     if(qname == zone) {
-      cerr<<"requested keyset found! returning Secure for the keyset"<<endl;
+      //      cerr<<"requested keyset found! returning Secure for the keyset"<<endl;
       keyset.insert(validkeys.begin(), validkeys.end());
       return Secure;
     }
-    cerr<<"walking downwards to find DS"<<endl;
+    //    cerr<<"walking downwards to find DS"<<endl;
     DNSName keyqname=qname;
     do {
       qname=DNSName(labels.back())+qname;
       labels.pop_back();
-      cerr<<"next name ["<<qname<<"], trying to get DS"<<endl;
+      //      cerr<<"next name ["<<qname<<"], trying to get DS"<<endl;
 
       dsmap_t tdsmap; // tentative DSes
       dsmap.clear();
@@ -317,7 +318,7 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset)
       cspmap_t validrrsets;
       validateWithKeySet(cspmap, validrrsets, validkeys);
 
-      cerr<<"got "<<cspmap.count(make_pair(qname,QType::DS))<<" DS of which "<<validrrsets.count(make_pair(qname,QType::DS))<<" valid "<<endl;
+      //      cerr<<"got "<<cspmap.count(make_pair(qname,QType::DS))<<" DS of which "<<validrrsets.count(make_pair(qname,QType::DS))<<" valid "<<endl;
 
       auto r = validrrsets.equal_range(make_pair(qname, QType::DS));
       for(auto cspiter =r.first;  cspiter!=r.second; cspiter++) {
@@ -332,7 +333,7 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset)
         }
       }
       if(!dsmap.size()) {
-        cerr<<"no DS at this level, checking for denials"<<endl;
+       //        cerr<<"no DS at this level, checking for denials"<<endl;
         dState dres = getDenial(validrrsets, qname, QType::DS);
         if(dres == INSECURE) return Insecure;
       }
@@ -361,13 +362,16 @@ string dotName(string type, DNSName name, string tag)
 }
 void dotNode(string type, DNSName name, string tag, string content)
 {
+#ifdef GRAPHVIZ
   cout<<"    "
       <<dotEscape(dotName(type, name, tag))
       <<" [ label="<<dotEscape(dotName(type, name, tag)+"\\n"+content)<<" ];"<<endl;
+#endif
 }
 
 void dotEdge(DNSName zone, string type1, DNSName name1, string tag1, string type2, DNSName name2, string tag2, string color)
 {
+#ifdef GRAPHVIZ
   cout<<"    ";
   if(zone != DNSName(".")) cout<<"subgraph "<<dotEscape("cluster "+zone.toString())<<" { ";
   cout<<dotEscape(dotName(type1, name1, tag1))
@@ -377,5 +381,6 @@ void dotEdge(DNSName zone, string type1, DNSName name1, string tag1, string type
   else cout<<"; ";
   if(zone != DNSName(".")) cout<<"label = "<<dotEscape("zone: "+zone.toString())<<";"<<"}";
   cout<<endl;
+#endif
 }