]> granicus.if.org Git - pdns/commitdiff
move to mature key management (unified zsks, proper ids, active, inactive)
authorBert Hubert <bert.hubert@netherlabs.nl>
Mon, 27 Dec 2010 15:56:20 +0000 (15:56 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Mon, 27 Dec 2010 15:56:20 +0000 (15:56 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1757 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/Makefile.am
pdns/dnssecinfra.cc
pdns/dnsseckeeper.cc [deleted file]
pdns/dnsseckeeper.hh
pdns/pdnssec.cc
pdns/toysdig.cc

index ae60dc8683344af99be3df57046a33fb83580137..44d04f363c399f55f4061698640a384559573222 100644 (file)
@@ -21,7 +21,7 @@ bin_PROGRAMS = pdns_control pdnssec dnsreplay
 endif
 
 EXTRA_PROGRAMS=pdns_recursor sdig tsig-tests speedtest pdns_control dnsscope dnsgram \
- dnsdemog dnswasher dnsscan dnslog nproxy notify pdnssec dnsbulktest # tcptorture
+toysdig dnsdemog dnswasher dnsscan dnslog nproxy notify pdnssec dnsbulktest # dnslabel # tcptorture
 
 pdns_server_SOURCES=dnspacket.cc nameserver.cc tcpreceiver.hh \
 qtype.cc logger.cc arguments.cc packethandler.cc tcpreceiver.cc \
@@ -43,7 +43,7 @@ base64.hh zoneparser-tng.cc dnsrecords.cc dnswriter.cc \
 rcpgenerator.cc        dnsparser.cc dns_random.hh aes/aescpp.h \
 aes/aescrypt.c aes/aes.h aes/aeskey.c aes/aes_modes.c aes/aesopt.h \
 aes/aestab.c aes/aestab.h aes/brg_endian.h aes/brg_types.h aes/dns_random.cc \
-randomhelper.cc namespaces.hh nsecrecords.cc base32.cc dnsseckeeper.cc dnssecinfra.cc \
+randomhelper.cc namespaces.hh nsecrecords.cc base32.cc fsdnsseckeeper.cc dnssecinfra.cc \
 dnsseckeeper.hh dnssecinfra.hh base32.hh
 
 #
@@ -52,7 +52,7 @@ pdns_server_LDADD=$(BOOST_FILESYSTEM_LIBS) $(BOOST_SYSTEM_LIBS) -lpolarssl
   
 
 
-pdnssec_SOURCES=pdnssec.cc dnsseckeeper.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter.cc dnswriter.hh \
+pdnssec_SOURCES=pdnssec.cc fsdnsseckeeper.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter.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 dnssecinfra.cc dnssecinfra.hh \
         base32.cc  ueberbackend.cc dnsbackend.cc arguments.cc packetcache.cc dnspacket.cc  \
@@ -69,6 +69,11 @@ 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
 
+toysdig_SOURCES=toysdig.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter.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
+
+
 #tcptorture_SOURCES=tcptorture.cc sstuff.hh dnsparser.cc dnsparser.hh dnsrecords.cc dnswriter.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
index 3fb90925beee98b50bcea393b4dffffd727df5d6..f664cecd50e18698998e5bb18c03b9a0a12e1be1 100644 (file)
@@ -186,7 +186,7 @@ bool getSignerFor(const std::string& keyRepositoryDir, const std::string& qname,
 
   signer=qname;
   do {
-    if(dk.haveKSKFor(signer)) 
+    if(dk.haveActiveKSKFor(signer)) 
       return true;
   } while(chopOff(signer));
   return false;
@@ -211,8 +211,8 @@ DNSKEYRecordContent getDNSKEYFor(const std::string& keyRepositoryDir, const std:
   DNSSECPrivateKey dpk;
 
   if(!withKSK) {
-    DNSSECKeeper::zskset_t zskset=dk.getZSKsFor(qname);
-    BOOST_FOREACH(DNSSECKeeper::zskset_t::value_type value, zskset) {
+    DNSSECKeeper::keyset_t zskset=dk.getKeys(qname, false);
+    BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
       if(value.second.active) {
         cerr<<"Found a ZSK for '"<<qname<<"', key tag = "<<value.first.getDNSKEY().getTag()<<endl;
         *rc=value.first.d_key;
@@ -224,7 +224,7 @@ DNSKEYRecordContent getDNSKEYFor(const std::string& keyRepositoryDir, const std:
     cerr<<"Could not find an active ZSK for '"<<qname<<"'"<<endl;
     exit(1);
   }
-  else if(dk.haveKSKFor(qname, &dpk)) {
+  else if(dk.haveActiveKSKFor(qname, &dpk)) {
     cerr<<"Found a KSK for '"<<qname<<"'"<<endl;
     *rc=dpk.d_key;
     return dpk.getDNSKEY();
diff --git a/pdns/dnsseckeeper.cc b/pdns/dnsseckeeper.cc
deleted file mode 100644 (file)
index 7f2d43a..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-#include "dnsseckeeper.hh"
-#include "dnssecinfra.hh"
-#include "statbag.hh"
-#include <iostream>
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-#include <polarssl/havege.h>
-#include <polarssl/base64.h>
-#include <boost/foreach.hpp>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fstream>
-#include <boost/algorithm/string.hpp>
-#include <boost/format.hpp>
-#include <boost/assign/std/vector.hpp> // for 'operator+=()'
-#include <boost/assign/list_inserter.hpp>
-using namespace boost::assign;
-namespace fs = boost::filesystem;
-
-using namespace std;
-using namespace boost;
-
-void RSAContext::create(unsigned int bits)
-{
-  havege_state hs;
-  havege_init( &hs );
-  
-  rsa_init(&d_context, RSA_PKCS_V15, 0, havege_rand, &hs ); // FIXME this leaks memory
-  int ret=rsa_gen_key(&d_context, bits, 65537);
-  if(ret < 0) 
-    throw runtime_error("Key generation failed");
-}
-
-std::string RSAContext::convertToISC()
-{
-  string ret;
-  typedef vector<pair<string, mpi*> > outputs_t;
-  outputs_t outputs;
-  push_back(outputs)("Modulus", &d_context.N)("PublicExponent",&d_context.E)
-    ("Modulus", &d_context.N)
-    ("PublicExponent",&d_context.E)
-    ("PrivateExponent",&d_context.D)
-    ("Prime1",&d_context.P)
-    ("Prime2",&d_context.Q)
-    ("Exponent1",&d_context.DP)
-    ("Exponent2",&d_context.DQ)
-    ("Coefficient",&d_context.QP);
-
-  ret = "Private-key-format: v1.2\nAlgorithm: 5 (RSASHA1)\n";
-
-  BOOST_FOREACH(outputs_t::value_type value, outputs) {
-    ret += value.first;
-    ret += ": ";
-    unsigned char tmp[mpi_size(value.second)];
-    mpi_write_binary(value.second, tmp, sizeof(tmp));
-    unsigned char base64tmp[sizeof(tmp)*2];
-    int dlen=sizeof(base64tmp);
-    base64_encode(base64tmp, &dlen, tmp, sizeof(tmp));
-    ret.append((const char*)base64tmp, dlen);
-    ret.append(1, '\n');
-  }
-  return ret;
-}
-
-bool DNSSECKeeper::haveKSKFor(const std::string& zone, DNSSECPrivateKey* dpk)
-{
-  fs::path full_path = fs::system_complete( fs::path(d_dirname + "/" + zone + "/ksks/" ) );
-
-  if ( !fs::exists( full_path ) )
-    return false;
-
-  fs::directory_iterator end_iter;
-  for ( fs::directory_iterator dir_itr( full_path );
-       dir_itr != end_iter;
-       ++dir_itr )
-  {
-    //    cerr<<"Entry: '"<< dir_itr->leaf() <<"'"<<endl;
-    if(ends_with(dir_itr->leaf(),".isc")) {
-      //      cerr<<"Hit!"<<endl;
-
-      if(dpk) {
-        getRSAKeyFromISC(&dpk->d_key.getContext(), dir_itr->path().file_string().c_str());
-       
-        if(getNSEC3PARAM(zone)) {
-          dpk->d_algorithm = 7;
-        }
-        else {
-          dpk->d_algorithm = 5;
-        }
-      
-      }
-      return true;
-    }
-  }
-
-  return false;
-}
-
-unsigned int DNSSECKeeper::getNextKeyIDFromDir(const std::string& dirname)
-{
-  fs::path full_path = fs::system_complete( fs::path(dirname));
-
-  if ( !fs::exists( full_path ) )
-    unixDie("Unable to get next free key id from '"+dirname+"'");
-
-  fs::directory_iterator end_iter;
-  unsigned int maxID=0;
-  for ( fs::directory_iterator dir_itr( full_path );
-       dir_itr != end_iter;
-       ++dir_itr )
-  {
-         if(ends_with(dir_itr->leaf(),".isc")) {
-                 maxID = max(maxID, (unsigned int)atoi(dir_itr->leaf().c_str()));
-         }
-  }
-  return maxID+1;
-}
-
-void DNSSECKeeper::addZSKFor(const std::string& name, int algorithm, bool active)
-{
-  DNSSECPrivateKey dpk;
-  dpk.d_key.create(1024); // for testing, 1024
-
-  string isc = dpk.d_key.convertToISC();
-  DNSKEYRecordContent drc = dpk.getDNSKEY();
-  drc.d_flags = 256; // KSK
-  drc.d_algorithm = algorithm; 
-  string iscName=d_dirname+"/"+name+"/zsks/";
-  unsigned int id = getNextKeyIDFromDir(iscName);
-  time_t inception=time(0);
-
-  struct tm ts;
-  gmtime_r(&inception, &ts);
-
-  iscName += (boost::format("%06d-%04d%02d%02d%02d%02d") % id
-             % (1900+ts.tm_year) % (ts.tm_mon + 1)
-             % ts.tm_mday % ts.tm_hour % ts.tm_min).str();
-
-  iscName += active ? ".active" : ".passive";
-  
-  {  
-    ofstream iscFile((iscName+".isc").c_str());
-    iscFile << isc;
-  }
-
-  {  
-    ofstream dnskeyFile((iscName+".dnskey").c_str());
-    dnskeyFile << toCanonic("", name) << " IN DNSKEY " << drc.getZoneRepresentation()<<endl;
-  }
-
-}
-
-
-static bool zskCompareByID(const DNSSECKeeper::zskset_t::value_type& a, const DNSSECKeeper::zskset_t::value_type& b)
-{
-  return a.second.id < b.second.id;
-}
-
-void DNSSECKeeper::deleteZSKFor(const std::string& zname, const std::string& fname)
-{
-  unlink((d_dirname +"/"+ zname +"/zsks/"+fname).c_str());
-}
-
-bool DNSSECKeeper::getNSEC3PARAM(const std::string& zname, NSEC3PARAMRecordContent* ns3p)
-{
-  fs::path full_path = fs::system_complete( fs::path(d_dirname + "/" + zname + "/nsec3param" ) );
-  ifstream ifs(full_path.external_directory_string().c_str());
-  // cerr<<"called for nsec3param..."<<endl;
-  if(!ifs)
-    return false;
-    
-  if(ns3p) {
-    string descr;
-    getline(ifs, descr);
-    NSEC3PARAMRecordContent* tmp=dynamic_cast<NSEC3PARAMRecordContent*>(DNSRecordContent::mastermake(QType::NSEC3PARAM, 1, descr));
-    if(!tmp) {
-      cerr<<"Could not parse "<< full_path.external_directory_string() <<endl;
-      cerr<<"descr: '"<<descr<<"'\n";
-    }
-    *ns3p = *tmp;
-    delete tmp;
-    
-    cerr<<"hmm salt: "<<makeHexDump(ns3p->d_salt)<<endl;
-  }
-  return true;
-}
-
-void DNSSECKeeper::setNSEC3PARAM(const std::string& zname, const NSEC3PARAMRecordContent* ns3p)
-{
-  fs::path full_path = fs::system_complete( fs::path(d_dirname + "/" + zname + "/nsec3param" ) );
-  if(ns3p) {
-    string descr = ns3p->getZoneRepresentation();
-    
-    
-    ofstream of(full_path.external_directory_string().c_str());
-    of << descr;
-  }
-  else {
-    unlink(full_path.external_directory_string().c_str());
-  }
-}
-
-
-DNSSECKeeper::zskset_t DNSSECKeeper::getZSKsFor(const std::string& zone, bool all)
-{
-  zskset_t zskset;
-
-  fs::path full_path = fs::system_complete( fs::path(d_dirname + "/" + zone + "/zsks/" ) );
-
-  if ( !fs::exists( full_path ) )
-    return zskset;
-
-  fs::directory_iterator end_iter;
-  for ( fs::directory_iterator dir_itr( full_path );
-       dir_itr != end_iter;
-       ++dir_itr )
-  {
-    //    cerr<<"Entry: '"<< dir_itr->leaf() <<"'"<<endl;
-    if(ends_with(dir_itr->leaf(),".isc")) {
-      //cerr<<"Hit!"<<endl;
-      DNSSECPrivateKey dpk;
-      getRSAKeyFromISC(&dpk.d_key.getContext(), dir_itr->path().file_string().c_str());
-
-      if(getNSEC3PARAM(zone)) {
-        dpk.d_algorithm = 7;
-      }
-      else {
-        dpk.d_algorithm = 5;
-      }
-      
-      struct tm ts1, ts2;
-      
-      memset(&ts1, 0, sizeof(ts1));
-      memset(&ts2, 0, sizeof(ts2));
-      
-      unsigned int id;
-      sscanf(dir_itr->leaf().c_str(), "%06u-%04d%02d%02d%02d%02d",
-                &id,
-            &ts1.tm_year, 
-            &ts1.tm_mon, &ts1.tm_mday, &ts1.tm_hour, &ts1.tm_min);
-            
-
-      ts1.tm_year -= 1900;
-      
-      ts1.tm_mon--;
-      
-      KeyMetaData kmd;
-      
-         kmd.id = id;
-      kmd.fname = dir_itr->leaf();
-      kmd.active = kmd.fname.find(".active") != string::npos;
-      zskset.push_back(make_pair(dpk, kmd));
-    }
-    sort(zskset.begin(), zskset.end(), zskCompareByID);
-  }
-
-  return zskset;
-}
-
-DNSKEYRecordContent DNSSECPrivateKey::getDNSKEY()
-{
-  return makeDNSKEYFromRSAKey(&d_key.getContext(), d_algorithm);
-}
-
-
-void DNSSECKeeper::secureZone(const std::string& name, int algorithm)
-{
-  mkdir((d_dirname+"/"+name).c_str(), 0700);
-  mkdir((d_dirname+"/"+name+"/ksks").c_str(), 0700);
-  if(mkdir((d_dirname+"/"+name+"/zsks").c_str(), 0700) < 0)
-    unixDie("Making directory for keys in '"+d_dirname+"'");
-
-  // now add the KSK
-
-  DNSSECPrivateKey dpk;
-  dpk.d_key.create(2048); // for testing, 1024
-
-  string isc = dpk.d_key.convertToISC();
-  DNSKEYRecordContent drc = dpk.getDNSKEY();
-  drc.d_flags = 257; // ZSK (?? for a KSK?)
-  drc.d_algorithm = algorithm;  
-  string iscName=d_dirname+"/"+name+"/ksks/";
-
-  time_t now=time(0);
-  struct tm ts;
-  gmtime_r(&now, &ts);
-  unsigned int id=1;
-  iscName += (boost::format("%06d-%04d%02d%02d%02d%02d.%u") % id
-             % (1900+ts.tm_year) % (ts.tm_mon + 1)
-             % ts.tm_mday % ts.tm_hour % ts.tm_min % drc.getTag()).str();
-
-
-  {  
-    ofstream iscFile((iscName+".isc").c_str());
-    iscFile << isc;
-  }
-
-  {  
-    ofstream dnskeyFile((iscName+".dnskey").c_str());
-    dnskeyFile << toCanonic("", name) << " IN DNSKEY " << drc.getZoneRepresentation()<<endl;
-  }
-
-}
-
index 2c0b12a92fdb94dcca632c5001604cb16c997a25..09420fb88357dcbe502287ed9623eb6f0ace66ad 100644 (file)
@@ -4,6 +4,7 @@
 #include <polarssl/rsa.h>
 #include <string.h>
 #include <vector>
+#include <boost/logic/tribool.hpp>
 #include "dnsrecords.hh"
 
 #define PDNSSEC_MI(x) mpi_init(&d_context.x, 0)
@@ -66,6 +67,7 @@ private:
   rsa_context d_context;
 };
 
+// ?
 #undef PDNSSEC_MC
 #undef PDNSSEC_MI
 #undef PDNSSEC_MF
@@ -84,27 +86,30 @@ class DNSSECKeeper
 public:
   struct KeyMetaData
   {
-       unsigned int id;
+    unsigned int id;
     bool active;
+    bool keyOrZone;
     string fname;
   }; 
-  typedef std::vector<std::pair<DNSSECPrivateKey, KeyMetaData> > zskset_t;
+  typedef std::vector<std::pair<DNSSECPrivateKey, KeyMetaData> > keyset_t;
    
 public:
   explicit DNSSECKeeper(const std::string& dirname) : d_dirname(dirname){}
 
-  bool haveKSKFor(const std::string& zone, DNSSECPrivateKey* ksk=0);
+  bool haveActiveKSKFor(const std::string& zone, DNSSECPrivateKey* ksk=0);
   
-  zskset_t getZSKsFor(const std::string& zone, bool all=false);
-  void addZSKFor(const std::string& zname, int algorithm, bool next=false);
-  
-  void deleteZSKFor(const std::string& zname, const std::string& fname);
+  keyset_t getKeys(const std::string& zone, boost::tribool allOrKeyOrZone = boost::indeterminate);
+  void addKey(const std::string& zname, bool keyOrZone, int algorithm, bool active=true);
+  void removeKey(const std::string& zname, unsigned int id);
+  void activateKey(const std::string& zname, unsigned int id);
+  void deactivateKey(const std::string& zname, unsigned int id);
 
   void secureZone(const std::string& fname, int algorithm);
 
   bool getNSEC3PARAM(const std::string& zname, NSEC3PARAMRecordContent* n3p=0);
   void setNSEC3PARAM(const std::string& zname, const NSEC3PARAMRecordContent* n3p);
   static unsigned int getNextKeyIDFromDir(const std::string& dirname);
+  std::string getKeyFilenameById(const std::string& dirname, unsigned int id);
 private:
   std::string d_dirname;
 };
index e7b1de00cf37beabf2865e6b2095755165dfccfa..321243b2e1423b2190f5c19933d0bd742b7e11b6 100644 (file)
@@ -189,7 +189,7 @@ try
     cmds = g_vm["commands"].as<vector<string> >();
 
   if(cmds.empty() || g_vm.count("help")) {
-    cerr<<"Usage: \npdnssec [options] [show-zone] [secure-zone] [alter-zone] [order-zone] [update-zone-keys]\n";
+    cerr<<"Usage: \npdnssec [options] [show-zone] [secure-zone] [alter-zone] [order-zone] [add-zone-key] [deactivate-zone-key] [remove-zone-key] [activate-zone-key]\n";
     cerr<<desc<<endl;
     return 0;
   }
@@ -224,7 +224,7 @@ try
       cerr << "No KSK for zone '"<<zone<<"', can't update the ZSKs"<<endl;
       return 0;
     }
-    DNSSECKeeper::zskset_t zskset=dk.getZSKsFor(zone);
+    DNSSECKeeper::keyset_t zskset=dk.getZSKsFor(zone);
 
     int inforce=0;
     time_t now = time(&now);
@@ -233,7 +233,7 @@ try
     if(!zskset.empty())  {
       cout<<"There were ZSKs already for zone '"<<zone<<"': "<<endl;
       
-      BOOST_FOREACH(DNSSECKeeper::zskset_t::value_type value, zskset) {
+      BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
         cout<<"Tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<<endl; // ", "<<humanTime(value.second.beginValidity)<<" - "<<humanTime(value.second.endValidity)<<endl;
         if(value.second.active) 
           inforce++;
@@ -250,16 +250,16 @@ try
       cerr << "Two or more ZSKs were active already, not generating a third" << endl;
       return 0;
     }
-    dk.addZSKFor(zone, 5);
-    dk.addZSKFor(zone, 5, true); // 'next'
+    dk.addKey(zone, true, 5);
+    dk.addKey(zone, true, 5, false); // not yet active
 
-    zskset = dk.getZSKsFor(zone);
+    keyset = dk.getKeys(zone);
     if(zskset.empty()) {
       cerr<<"This should not happen, still no ZSK!"<<endl;
     }
 
     cout<<"There are now "<<zskset.size()<<" ZSKs"<<endl;
-    BOOST_FOREACH(DNSSECKeeper::zskset_t::value_type value, zskset) {
+    BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
       cout<<"Tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<<endl;
     }
 
@@ -271,31 +271,45 @@ try
       return 0;
     }
     const string& zone=cmds[1];
-    DNSSECPrivateKey dpk;
     
-    if(!dk.haveKSKFor(zone, &dpk)) {
-      cerr << "No KSK for zone '"<<zone<<"'."<<endl;
-    }
-    else {
-      cout<<"KSK present:"<<endl;
-      cout<<"Tag = "<<dpk.getDNSKEY().getTag()<<endl;
-      cout<<"KSK DNSKEY = "<<zone<<" IN DNSKEY "<< dpk.getDNSKEY().getZoneRepresentation() << endl;
-      cout<<"DS = "<<zone<<" IN DS "<<makeDSFromDNSKey(zone, dpk.getDNSKEY()).getZoneRepresentation() << endl << endl;
-    }
-    
-    
-    DNSSECKeeper::zskset_t zskset=dk.getZSKsFor(zone);
+    DNSSECKeeper::keyset_t keyset=dk.getKeys(zone, boost::indeterminate);
 
-    if(zskset.empty())  {
-      cerr << "No ZSKs for zone '"<<zone<<"'."<<endl;
+    if(keyset.empty())  {
+      cerr << "No keys for zone '"<<zone<<"'."<<endl;
     }
     else {  
-      cout << "ZSKs for zone '"<<zone<<"':"<<endl;
-      BOOST_FOREACH(DNSSECKeeper::zskset_t::value_type value, zskset) {
-        cout<<"ID = "<<value.second.id<<", tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<< endl; // humanTime(value.second.beginValidity)<<" - "<<humanTime(value.second.endValidity)<<endl;
+      cout << "keys: for zone '"<<zone<<"':"<<endl;
+      BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, keyset) {
+        cout<<"ID = "<<value.second.id<<" ("<<(value.second.keyOrZone ? "KSK" : "ZSK")<<"), tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<< endl; // humanTime(value.second.beginValidity)<<" - "<<humanTime(value.second.endValidity)<<endl;
+        if(value.second.keyOrZone) {
+          cout<<"KSK DNSKEY = "<<zone<<" IN DNSKEY "<< value.first.getDNSKEY().getZoneRepresentation() << endl;
+          cout<<"DS = "<<zone<<" IN DS "<<makeDSFromDNSKey(zone, value.first.getDNSKEY()).getZoneRepresentation() << endl << endl;
+        }
       }
     }
   }
+  else if(cmds[0] == "activate-zone-key") {
+    const string& zone=cmds[1];
+    unsigned int id=atoi(cmds[2].c_str());
+    dk.activateKey(zone, id);
+  }
+  else if(cmds[0] == "deactivate-zone-key") {
+    const string& zone=cmds[1];
+    unsigned int id=atoi(cmds[2].c_str());
+    dk.deactivateKey(zone, id);
+  }
+  else if(cmds[0] == "add-zone-key") {
+    const string& zone=cmds[1];
+    // need to get algorithm & ksk or zsk
+    dk.addKey(zone, 1, 5, 0); 
+    cerr<<"Not implemented"<<endl;
+  }
+  else if(cmds[0] == "remove-zone-key") {
+    const string& zone=cmds[1];
+    unsigned int id=atoi(cmds[2].c_str());
+    dk.removeKey(zone, id);
+  }
+  
   else if(cmds[0] == "secure-zone") {
     if(cmds.size() != 2) {
       cerr << "Error: "<<cmds[0]<<" takes exactly 1 parameter"<<endl;
@@ -304,35 +318,35 @@ try
     const string& zone=cmds[1];
     DNSSECPrivateKey dpk;
     
-    if(dk.haveKSKFor(zone, &dpk) && !g_vm.count("force")) {
+    if(dk.haveActiveKSKFor(zone, &dpk) && !g_vm.count("force")) {
       cerr << "There is a key already for zone '"<<zone<<"', use --force to overwrite"<<endl;
       return 0;
     }
       
     dk.secureZone(zone, 5);
 
-    if(!dk.haveKSKFor(zone, &dpk)) {
+    if(!dk.haveActiveKSKFor(zone, &dpk)) {
       cerr << "This should not happen, still no key!" << endl;
     }
     cout<<"Created KSK with tag "<<dpk.getDNSKEY().getTag()<<endl;
   
-    DNSSECKeeper::zskset_t zskset=dk.getZSKsFor(zone);
+    DNSSECKeeper::keyset_t zskset=dk.getKeys(zone, false);
 
     if(!zskset.empty() && !g_vm.count("force"))  {
       cerr<<"There were ZSKs already for zone '"<<zone<<"'"<<endl;
       return 0;
     }
       
-    dk.addZSKFor(zone, 5);
-    dk.addZSKFor(zone, 5, true); // 'next'
+    dk.addKey(zone, false, 5);
+    dk.addKey(zone, false, 5, false); // not active
 
-    zskset = dk.getZSKsFor(zone);
+    zskset = dk.getKeys(zone, false);
     if(zskset.empty()) {
       cerr<<"This should not happen, still no ZSK!"<<endl;
     }
 
     cout<<"There are now "<<zskset.size()<<" ZSKs"<<endl;
-    BOOST_FOREACH(DNSSECKeeper::zskset_t::value_type value, zskset) {
+    BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
       cout<<"id = "<<value.second.id<<", tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<<endl;
     }
   }
index 3f7d46be12e8545ed50f8b770fb1cf9f5f17febb..7f48912a0516d4304390b90ead77be497716e6ba 100644 (file)
 #include "dnswriter.hh"
 #include "dnsrecords.hh"
 #include "statbag.hh"
-#include "iputils.hh"
-#include <boost/foreach.hpp>
-#include <polarssl/rsa.h>
-#include <polarssl/base64.h>
-#include <polarssl/sha1.h>
-#include "dnssecinfra.hh"
-#include "base32.hh"
-
 StatBag S;
 
-MOADNSParser* askQuestion(DNSPacketWriter&, vector<uint8_t>& packet, const char* remote, uint16_t port=53) 
-{
-  int sock=socket(AF_INET, SOCK_DGRAM, 0);
-  
-  if(sock < 0)
-    unixDie("Creating SCTP socket");
-  
-  ComboAddress dest(remote + (*remote=='@'), port);
-  struct msghdr msg;
-  struct iovec iomsg;
-  
-  msg.msg_name=&dest;
-  msg.msg_namelen=dest.getSocklen();
-  msg.msg_iov=&iomsg;
-  iomsg.iov_base=&*packet.begin();
-  iomsg.iov_len=packet.size();
-  msg.msg_iovlen=1;
-  msg.msg_control=0;
-  msg.msg_controllen=0;
-  msg.msg_flags=0; // just to be sure
-  
-  sendmsg(sock, &msg, 0); 
-  
-  char replybuf[4096];
-  socklen_t destlen=dest.getSocklen();
-  int len=recvfrom(sock, replybuf, sizeof(replybuf), 0, (struct sockaddr*)&dest, &destlen);
-  if(len < 0)
-    unixDie("recvfrom on sctp");
-  
-  string reply(replybuf, len);
-  
-  return new MOADNSParser(reply);
-}
-
-void getKeys(const std::string& qname, uint16_t tag);
-
-void doVerifySignature(const std::string& qname,  map<string, vector<shared_ptr<DNSKEYRecordContent > > >& dkrcs, pair<vector<shared_ptr<DNSRecordContent> >, vector<shared_ptr<RRSIGRecordContent> > >& records)
-{
-  rsa_context rsa;
-
-  BOOST_FOREACH(shared_ptr<RRSIGRecordContent>& rrc, records.second) {
-    cerr<<"\nVerifying "<<qname<<"|"<<DNSRecordContent::NumberToType(rrc->d_type)<<"\n";
-
-    cerr<<"Signer is: "<<rrc->d_signer<<" for which we have "<<dkrcs[rrc->d_signer].size()<<" DNSKEYs, want the one with";
-    cerr<<" tag: "<<rrc->d_tag<<endl;
-  
-
-    getKeys(rrc->d_signer, rrc->d_tag);
-
-    if(dkrcs[rrc->d_signer].empty())  {
-      cerr<<"\tNo keys!\n";
-      return;
-    }
-    
-    vector<shared_ptr<DNSRecordContent> >& signRecords= records.first;
-  
-    string hash=getSHA1HashForRRSET(qname, *rrc.get(), signRecords);
-    int ret;
-    int success=0;
-    BOOST_FOREACH(shared_ptr<DNSKEYRecordContent> dkrc, dkrcs[rrc->d_signer]) {
-      if(dkrc->getTag() != rrc->d_tag) {
-       cerr<<"Skipping key with wrong tag "<<dkrc->getTag()<< " != needed "<<rrc->d_tag<<endl;
-       continue;
-      }
-      makeRSAPublicKeyFromDNS(&rsa, *dkrc);
-  
-      if((ret=rsa_pkcs1_verify(&rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20, (unsigned char*)hash.c_str(), (unsigned char*)rrc->d_signature.c_str() ) ) != 0) {
-       fprintf(stderr, "Verification with tag %d failed with error %d\n", dkrc->getTag(), ret);
-      }
-      else {
-       fprintf(stderr, "DNSSEC Record verified Ok with tag %d!\n", dkrc->getTag());
-       success++;
-       break;
-      }
-    }
-    if(success)
-      cerr<<"\t at least one verification was succesful!\n";
-  }
-}
-
-typedef map<string, vector<shared_ptr<DNSKEYRecordContent> > > dkrc_t;
-dkrc_t dkrc;
-
-void getKeys(const std::string& qname, uint16_t tag)
-{
-  BOOST_FOREACH(shared_ptr<DNSKEYRecordContent>& drc, dkrc[qname]) {
-    if(drc->getTag() == tag) 
-      return;
-  }
-
-  vector<uint8_t> packet;
-  
-  DNSPacketWriter pw(packet, qname, QType::DNSKEY);
-
-  pw.getHeader()->id=1234;
-  pw.getHeader()->rd=1;
-
-  pw.addOpt(4000, 0, EDNSOpts::DNSSECOK); // int udpsize, int extRCode, int Z 
-  pw.commit();
-
-  MOADNSParser* mdp=askQuestion(pw, packet, "199.249.112.1", 53);
-  if(mdp->d_header.tc) {
-    cerr<<"Truncated!\n";
-  }
-  for(MOADNSParser::answers_t::const_iterator i=mdp->d_answers.begin(); i!=mdp->d_answers.end(); ++i) {          
-    if(i->first.d_type==QType::DNSKEY) {
-      shared_ptr<DNSKEYRecordContent> dkrcptr=dynamic_pointer_cast<DNSKEYRecordContent>(i->first.d_content);
-      dkrc[i->first.d_label].push_back(dkrcptr);
-      cerr<<"Added DNSKEY for '"<<qname<<"': tag = "<<dkrcptr->getTag()<<", key length = "<<dkrcptr->getModulus().length()*8<<", SEP = "<< dkrcptr->d_flags%2 <<endl;
-    }
-  }
-}
-
 int main(int argc, char** argv)
 try
 {
   reportAllTypes();
 
   if(argc < 4) {
-    cerr<<"Syntax: toysdig question question-type IP-address [port]\n";
+    cerr<<"Syntax: sdig IP-address port question question-type\n";
     exit(EXIT_FAILURE);
   }
 
   vector<uint8_t> packet;
   
-  DNSPacketWriter pw(packet, argv[1], DNSRecordContent::TypeToNumber(argv[2]));
+  DNSPacketWriter pw(packet, argv[3], DNSRecordContent::TypeToNumber(argv[4]));
 
-  pw.getHeader()->id=1234;
-  pw.getHeader()->rd=0;
+  pw.getHeader()->rd=1;
+  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);
 
-  pw.addOpt(4000, 0, EDNSOpts::DNSSECOK); // int udpsize, int extRCode, int Z 
-  pw.commit();
+  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;
 
-  MOADNSParser* mdp=askQuestion(pw, packet, argv[3], argc>4 ? atoi(argv[4]) : 53);
-  if(mdp->d_header.tc) {
-    cerr<<"Truncated!\n";
-  }
-  
-  typedef map< pair<string, uint16_t>, 
-    pair<vector<shared_ptr<DNSRecordContent> >, vector<shared_ptr<RRSIGRecordContent> > 
-    > > grouped_t;
-  grouped_t grouped;
-  
-  string salt;
-  int iterations;
-  for(MOADNSParser::answers_t::const_iterator i=mdp->d_answers.begin(); i!=mdp->d_answers.end(); ++i) {          
+  for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {          
     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(i->first.d_type==QType::DNSKEY) {
-      dkrc[i->first.d_label].push_back(dynamic_pointer_cast<DNSKEYRecordContent>(i->first.d_content));
-    }
-
-    if(i->first.d_type==QType::NSEC3) {
-      salt=dynamic_pointer_cast<NSEC3RecordContent>(i->first.d_content)->d_salt;
-      iterations=dynamic_pointer_cast<NSEC3RecordContent>(i->first.d_content)->d_iterations;
-    }
-
-    
-    if(i->first.d_type!=QType::RRSIG) 
-      grouped[make_pair(i->first.d_label, i->first.d_type)].first.push_back(i->first.d_content);
-    else {
-      shared_ptr<RRSIGRecordContent> rrc=dynamic_pointer_cast<RRSIGRecordContent>(i->first.d_content);
-      grouped[make_pair(i->first.d_label, rrc->d_type)].second.push_back(rrc);
-      cerr<<"Algorithm = "<<(int)rrc->d_algorithm<<endl;
-    }
-
-  }
-
-  if(!salt.empty()) {
-    cerr<<"We have a salt ("<<makeHexDump(salt)<<"), the NSEC3 of our query name ("<<argv[1]<<"): "<<toBase32Hex(hashQNameWithSalt(iterations, salt, argv[1]))<<endl;
-  }
-
-  cerr<<"Now have different names of "<<dkrc.size()<<" dnskeys!"<<endl;
-
-  BOOST_FOREACH(dkrc_t::value_type& value, dkrc) {
-    BOOST_FOREACH(shared_ptr<DNSKEYRecordContent>& content, value.second) {
-      DSRecordContent dsrc = makeDSFromDNSKey(value.first, *content.get());
-      cerr<<"ds: "<<value.first<<" IN DS "<<dsrc.getZoneRepresentation()<<endl;
-      dsrc = makeDSFromDNSKey(value.first, *content.get(),2);
-      cerr<<"ds: "<<value.first<<" IN DS "<<dsrc.getZoneRepresentation()<<endl;
-
-    }
-  }
-
-  cerr<<"\n";
-  BOOST_FOREACH(grouped_t::value_type& value, grouped) {
-    if(value.second.first.empty() && !value.second.second.empty()) 
-      cerr<<"Have a loose signature for"<<value.first.first<<"|"<<DNSRecordContent::NumberToType(value.first.second)<<endl;
-    else if(!value.second.first.empty() && value.second.second.empty()) 
-      cerr<<"Have unsigned content: "<<value.first.first<<"|"<<DNSRecordContent::NumberToType(value.first.second)<<endl;
-    else if(!value.second.first.empty() && !value.second.second.empty()) {
-      cerr<<"Have signed content: "<<value.first.first<<"|"<<DNSRecordContent::NumberToType(value.first.second);
-      cerr<<" ("<<value.second.first.size()<<" recs, "<<value.second.second.size()<<" signatures)"<<endl;
-      doVerifySignature(value.first.first, dkrc, value.second);
-    }
-    else
-      cerr<<"Have empty content?? "<<value.first.first<<"|"<<DNSRecordContent::NumberToType(value.first.second)<<endl;
   }
 
 
 }
 catch(std::exception &e)