]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
add nsec3dig debugging tool
authorPeter van Dijk <peter.van.dijk@netherlabs.nl>
Thu, 19 Jul 2012 10:20:29 +0000 (10:20 +0000)
committerPeter van Dijk <peter.van.dijk@netherlabs.nl>
Thu, 19 Jul 2012 10:20:29 +0000 (10:20 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@2681 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/Makefile.am
pdns/nsec3dig.cc [new file with mode: 0644]

index 4b61986512e9b30714252669e930617621d8b0f8..3bca54f680c817dc42f018a44453c49d30ffdcfa 100644 (file)
@@ -23,7 +23,7 @@ bin_PROGRAMS = pdns_control pdnssec dnsreplay
 endif
 
 EXTRA_PROGRAMS=pdns_recursor sdig tsig-tests speedtest pdns_control dnsscope dnsgram \
-toysdig dnsdemog dnswasher dnsscan nproxy notify pdnssec dnsbulktest  # dnslabel # tcptorture
+toysdig dnsdemog dnswasher dnsscan nproxy notify pdnssec dnsbulktest nsec3dig # dnslabel # tcptorture
 
 pdns_server_SOURCES=dnspacket.cc nameserver.cc tcpreceiver.hh \
 qtype.cc logger.cc arguments.cc packethandler.cc tcpreceiver.cc \
@@ -112,6 +112,13 @@ sdig_SOURCES=sdig.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter
        misc.cc misc.hh rcpgenerator.cc rcpgenerator.hh base64.cc base64.hh unix_utility.cc \
        logger.cc statbag.cc qtype.cc sillyrecords.cc nsecrecords.cc base32.cc
 
+nsec3dig_SOURCES=nsec3dig.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter.cc dnslabeltext.cc \
+    dnswriter.hh dnssecinfra.cc md5.cc \
+       misc.cc misc.hh rcpgenerator.cc rcpgenerator.hh base64.cc base64.hh unix_utility.cc \
+       logger.cc statbag.cc qtype.cc sillyrecords.cc nsecrecords.cc base32.cc
+nsec3dig_LDFLAGS= -Lext/polarssl-1.1.2/library         
+nsec3dig_LDADD= -lpolarssl
+
 toysdig_SOURCES=toysdig.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter.cc dnslabeltext.cc dnswriter.hh \
        misc.cc misc.hh rcpgenerator.cc rcpgenerator.hh base64.cc base64.hh unix_utility.cc \
        logger.cc statbag.cc qtype.cc sillyrecords.cc nsecrecords.cc base32.cc dnslabel.cc dnslabel.hh \
diff --git a/pdns/nsec3dig.cc b/pdns/nsec3dig.cc
new file mode 100644 (file)
index 0000000..d7bf53d
--- /dev/null
@@ -0,0 +1,140 @@
+#include "dnsparser.hh"
+#include "sstuff.hh"
+#include "misc.hh"
+#include "dnswriter.hh"
+#include "dnsrecords.hh"
+#include "statbag.hh"
+#include "base32.hh"
+#include "dnssecinfra.hh"
+
+StatBag S;
+
+typedef std::pair<string,string> nsec3;
+typedef set<nsec3> nsec3set;
+
+string nsec3Hash(const string &qname, const string &salt, unsigned int iters)
+{
+  return toLower(toBase32Hex(hashQNameWithSalt(iters, salt, qname)));
+}
+
+string proveOrDeny(const nsec3set &nsec3s, const string &qname, const string &salt, unsigned int iters)
+{
+  string hashed = nsec3Hash(qname, salt, iters);
+
+  // cerr<<"hashed: "<<hashed<<endl;
+  for(nsec3set::const_iterator pos=nsec3s.begin(); pos != nsec3s.end(); ++pos) {
+    string base=(*pos).first;
+    string next=(*pos).second;
+
+    if(hashed == base)
+    {
+      return qname+" ("+hashed+") proven by base of "+base+".."+next;
+    }
+    if(hashed == next)
+    {
+      return qname+" ("+hashed+") proven by next of "+base+".."+next;
+    }
+    if((hashed > base && hashed < next) ||
+       (next < base && (hashed < next || hashed > base)))
+    {
+      return qname+" ("+hashed+") denied by "+base+".."+next;
+    }
+  }
+  return "";
+}
+
+int main(int argc, char** argv)
+try
+{
+  bool recurse=false;
+
+  reportAllTypes();
+
+  if(argc < 5) {
+    cerr<<"Syntax: nsec3dig IP-address port question question-type [recurse]\n";
+    exit(EXIT_FAILURE);
+  }
+
+  // FIXME: turn recurse and dnssec into proper flags or something
+  if(argc > 5 && strcmp(argv[5], "recurse")==0)
+  {
+    recurse=true;
+  }
+
+  vector<uint8_t> packet;
+  string qname=argv[3];
+  DNSPacketWriter pw(packet, qname, DNSRecordContent::TypeToNumber(argv[4]));
+
+  if(recurse)
+  {
+    pw.getHeader()->rd=true;
+  }
+
+  pw.addOpt(2800, 0, EDNSOpts::DNSSECOK);
+  pw.commit();
+
+  Socket sock(InterNetwork, Datagram);
+  ComboAddress dest(argv[1] + (*argv[1]=='@'), atoi(argv[2]));
+  sock.sendTo(string((char*)&*packet.begin(), (char*)&*packet.end()), dest);
+  
+  string reply;
+  sock.recvFrom(reply, dest);
+
+  MOADNSParser mdp(reply);
+  cout<<"Reply to question for qname='"<<mdp.d_qname<<"', qtype="<<DNSRecordContent::NumberToType(mdp.d_qtype)<<endl;
+  cout<<"Rcode: "<<mdp.d_header.rcode<<", RD: "<<mdp.d_header.rd<<", QR: "<<mdp.d_header.qr;
+  cout<<", TC: "<<mdp.d_header.tc<<", AA: "<<mdp.d_header.aa<<", opcode: "<<mdp.d_header.opcode<<endl;
+
+  set<string> names;
+  nsec3set nsec3s;
+  string nsec3salt;
+  int nsec3iters;
+  for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {     
+    if(i->first.d_type == QType::NSEC3)
+    {
+      // cerr<<"got nsec3 ["<<i->first.d_label<<"]"<<endl;
+      // cerr<<i->first.d_content->getZoneRepresentation()<<endl;
+      NSEC3RecordContent r = dynamic_cast<NSEC3RecordContent&> (*(i->first.d_content));
+      // nsec3.insert(new nsec3()
+      // cerr<<toBase32Hex(r.d_nexthash)<<endl;
+      vector<string> parts;
+      boost::split(parts, i->first.d_label, boost::is_any_of("."));
+      nsec3s.insert(make_pair(toLower(parts[0]), toLower(toBase32Hex(r.d_nexthash))));
+      nsec3salt = r.d_salt;
+      nsec3iters = r.d_iterations;
+    }
+    else
+    {
+      names.insert(i->first.d_label);
+    }
+
+    cout<<i->first.d_place-1<<"\t"<<i->first.d_label<<"\tIN\t"<<DNSRecordContent::NumberToType(i->first.d_type);
+    cout<<"\t"<<i->first.d_ttl<<"\t"<< i->first.d_content->getZoneRepresentation()<<"\n";
+  }
+
+#if 0
+  cerr<<"got "<<names.size()<<" names"<<endl;
+  for(set<string>::const_iterator pos=names.begin(); pos != names.end(); ++pos) {
+    cerr<<"name: "<<*pos<<endl;
+  }
+  cerr<<"got "<<nsec3s.size()<<" names"<<endl;
+  for(nsec3set::const_iterator pos=nsec3s.begin(); pos != nsec3s.end(); ++pos) {
+    cerr<<"nsec3: "<<(*pos).first<<".."<<(*pos).second<<endl;
+  }
+#endif
+
+  cout<<"== nsec3 prove/deny report follows =="<<endl;
+  string r=proveOrDeny(nsec3s, qname, nsec3salt, nsec3iters);
+  string shorter(qname);
+  do {
+    string r;
+    r=proveOrDeny(nsec3s, shorter, nsec3salt, nsec3iters);
+    if(r.size()) cout<<r<<endl;
+    r=proveOrDeny(nsec3s, "*."+shorter, nsec3salt, nsec3iters);
+    if(r.size()) cout<<r<<endl;
+  } while(chopOff(shorter));
+}
+catch(std::exception &e)
+{
+  cerr<<"Fatal: "<<e.what()<<endl;
+}