]> granicus.if.org Git - pdns/commitdiff
spruce up 'show-zone' output, add 'set-nsec3', 'unset-nsec3', 'export-zone-key',...
authorBert Hubert <bert.hubert@netherlabs.nl>
Thu, 30 Dec 2010 19:52:51 +0000 (19:52 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Thu, 30 Dec 2010 19:52:51 +0000 (19:52 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1773 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/dnsseckeeper.hh
pdns/fsdnsseckeeper.cc
pdns/pdnssec.cc

index 4cb2a7c0189ee4ab4d17599926f8f10f7fdf7f62..45e5984f3ab22cddccdd1515328e0edb94af9648 100644 (file)
@@ -106,7 +106,8 @@ public:
   bool haveActiveKSKFor(const std::string& zone, DNSSECPrivateKey* ksk=0);
   
   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);
+  DNSSECPrivateKey getKeyById(const std::string& zone, unsigned int id);
+  void addKey(const std::string& zname, bool keyOrZone, int algorithm=5, int bits=0, 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);
@@ -114,7 +115,8 @@ public:
   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);
+  void setNSEC3PARAM(const std::string& zname, const NSEC3PARAMRecordContent& n3p);
+  void unsetNSEC3PARAM(const std::string& zname);
   static unsigned int getNextKeyIDFromDir(const std::string& dirname);
   std::string getKeyFilenameById(const std::string& dirname, unsigned int id);
 private:
index 1030b764dc71ab019f30d6cca2fc2929bbd791cd..f1330c26f6891b0e9c5b34ee1234702c4046a20b 100644 (file)
@@ -113,15 +113,17 @@ std::string DNSSECKeeper::getKeyFilenameById(const std::string& dirname, unsigne
 }
 
 
-void DNSSECKeeper::addKey(const std::string& name, bool keyOrZone, int algorithm, bool active)
+void DNSSECKeeper::addKey(const std::string& name, bool keyOrZone, int algorithm, int bits, bool active)
 {
+  if(!bits)
+    bits = keyOrZone ? 2048 : 1024;
   DNSSECPrivateKey dpk;
-  dpk.d_key.create(1024); // for testing, 1024
+  dpk.d_key.create(bits); // for testing, 1024
 
   string isc = dpk.d_key.convertToISC();
   DNSKEYRecordContent drc = dpk.getDNSKEY();
   drc.d_flags = 256 + keyOrZone; // KSK
-  drc.d_algorithm = algorithm; 
+  drc.d_algorithm = algorithm; // 5 = RSA, we'll add '2' later on for NSEC3 if needed
   string iscName=d_dirname+"/"+name+"/keys/";
   unsigned int id = getNextKeyIDFromDir(iscName);
   time_t inception=time(0);
@@ -129,9 +131,9 @@ void DNSSECKeeper::addKey(const std::string& name, bool keyOrZone, int algorithm
   struct tm ts;
   gmtime_r(&inception, &ts);
 
-  iscName += (boost::format("%06d-%04d%02d%02d%02d%02d.%u") % id
+  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 % drc.getTag()).str();
+             % ts.tm_mday % ts.tm_hour % ts.tm_min).str();
 
   iscName += keyOrZone ? ".ksk" : ".zsk";
   iscName += active ? ".active" : ".passive";
@@ -140,12 +142,12 @@ void DNSSECKeeper::addKey(const std::string& name, bool keyOrZone, int algorithm
     ofstream iscFile((iscName+".private").c_str());
     iscFile << isc;
   }
-
+#if 0
   {  
     ofstream dnskeyFile((iscName+".key").c_str());
     dnskeyFile << toCanonic("", name) << " IN DNSKEY " << drc.getZoneRepresentation()<<endl;
   }
-
+#endif
 }
 
 
@@ -155,6 +157,18 @@ static bool keyCompareByKindAndID(const DNSSECKeeper::keyset_t::value_type& a, c
          make_pair(!b.second.keyOrZone, b.second.id);
 }
 
+DNSSECPrivateKey DNSSECKeeper::getKeyById(const std::string& zname, unsigned int id)
+{
+  string fname = getKeyFilenameById(d_dirname+"/"+zname+"/keys", id);
+  DNSSECPrivateKey dpk;
+  getRSAKeyFromISC(&dpk.d_key.getContext(), fname.c_str());
+  dpk.d_algorithm = 5 + 2 * getNSEC3PARAM(zname);
+  dpk.d_flags = 256 + (fname.find(".ksk.") != string::npos); // this falls over on zones with .ksk. in the name!
+  return dpk;
+  
+}
+
+
 void DNSSECKeeper::removeKey(const std::string& zname, unsigned int id)
 {
   string fname = getKeyFilenameById(d_dirname+"/"+zname+"/keys", id);
@@ -189,32 +203,31 @@ bool DNSSECKeeper::getNSEC3PARAM(const std::string& zname, NSEC3PARAMRecordConte
   if(ns3p) {
     string descr;
     getline(ifs, descr);
+    reportAllTypes();
     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";
+      return false;
     }
     *ns3p = *tmp;
     delete tmp;
-    
-    cerr<<"hmm salt: "<<makeHexDump(ns3p->d_salt)<<endl;
   }
   return true;
 }
 
-void DNSSECKeeper::setNSEC3PARAM(const std::string& zname, const NSEC3PARAMRecordContent* ns3p)
+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());
-  }
+  string descr = ns3p.getZoneRepresentation();
+  ofstream of(full_path.external_directory_string().c_str());
+  of << descr;
+}
+
+void DNSSECKeeper::unsetNSEC3PARAM(const std::string& zname)
+{
+  fs::path full_path = fs::system_complete( fs::path(d_dirname + "/" + zname + "/nsec3param" ) );
+  unlink(full_path.external_directory_string().c_str());
 }
 
 
@@ -287,40 +300,8 @@ void DNSSECKeeper::secureZone(const std::string& name, int algorithm)
   if(mkdir((d_dirname+"/"+name+"/keys").c_str(), 0700) < 0)
     unixDie("Making directory for keys in '"+d_dirname+"'");
 
-
   // now add the KSK
-
   addKey(name, true, algorithm);
-#if 0
-
-  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+"/keys/";
-
-  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.%s.%s") % id
-             % (1900+ts.tm_year) % (ts.tm_mon + 1)
-             % ts.tm_mday % ts.tm_hour % ts.tm_min % drc.getTag() % "ksk" % "active").str();
-
-
-  {  
-    ofstream iscFile((iscName+".private").c_str());
-    iscFile << isc;
-  }
-
-  {  
-    ofstream dnskeyFile((iscName+".key").c_str());
-    dnskeyFile << toCanonic("", name) << " IN DNSKEY " << drc.getZoneRepresentation()<<endl;
-  }
-#endif
 }
  
 
index 9e7fe69e05fb7e62361bbd85276485dd314e0e48..042e37ead08442dce5a2b97b3589fc009a2f5ffb 100644 (file)
@@ -109,11 +109,6 @@ void orderZone(DNSSECKeeper& dk, const std::string& zone)
   //  cerr<<rr.qname<<endl;
     qnames.insert(rr.qname);
   }
-#if 0
-  string salt;
-  char tmp[]={0xab, 0xcd};
-  salt.assign(tmp, 2);
-#endif
 
   NSEC3PARAMRecordContent ns3pr;
   dk.getNSEC3PARAM(zone, &ns3pr);
@@ -197,6 +192,7 @@ try
 
   if(cmds.empty() || g_vm.count("help")) {
     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<<"         [import-zone-key] [export-zone-key] [set-nsec3] [unset-nsec3] [export-zone-dnskey]"<<endl;
     cerr<<desc<<endl;
     return 0;
   }
@@ -217,67 +213,22 @@ try
     }
     checkZone(dk, cmds[1]);
   }
-#if 0
-  else if(cmds[0] == "update-zone-keys") {
+
+  else if(cmds[0] == "show-zone") {
     if(cmds.size() != 2) {
       cerr << "Error: "<<cmds[0]<<" takes exactly 1 parameter"<<endl;
       return 0;
     }
-
     const string& zone=cmds[1];
-    DNSSECPrivateKey dpk;
-    
-    if(!dk.haveKSKFor(zone, &dpk)) {
-      cerr << "No KSK for zone '"<<zone<<"', can't update the ZSKs"<<endl;
-      return 0;
-    }
-    DNSSECKeeper::keyset_t zskset=dk.getZSKsFor(zone);
 
-    int inforce=0;
-    time_t now = time(&now);
-    
+    NSEC3PARAMRecordContent ns3pr;
+    dk.getNSEC3PARAM(zone, &ns3pr);
     
-    if(!zskset.empty())  {
-      cout<<"There were ZSKs already for zone '"<<zone<<"': "<<endl;
-      
-      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++;
-        if(!value.second.active) { // was: 'expired more than two days ago'  
-          cout<<"\tThis key is no longer used and too old to keep around, deleting!\n";
-          dk.deleteZSKFor(zone, value.second.fname);
-        } else /* if( value.second.endValidity < now  ) */{ // 'expired more than two days ago'  
-          cout<<"\tThis key is no longer in active use, but needs to linger\n";
-        }
-      }
-    }
-      
-    if(inforce >= 2) {
-      cerr << "Two or more ZSKs were active already, not generating a third" << endl;
-      return 0;
-    }
-    dk.addKey(zone, true, 5);
-    dk.addKey(zone, true, 5, false); // not yet active
-
-    keyset = dk.getKeys(zone);
-    if(zskset.empty()) {
-      cerr<<"This should not happen, still no ZSK!"<<endl;
-    }
+    if(ns3pr.d_salt.empty()) 
+      cerr<<"Zone has NSEC semantics"<<endl;
+    else
+      cerr<<"Zone has hashed NSEC3 semantics, configuration: "<<ns3pr.getZoneRepresentation()<<endl;
 
-    cout<<"There are now "<<zskset.size()<<" ZSKs"<<endl;
-    BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
-      cout<<"Tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<<endl;
-    }
-
-  }
-#endif
-  else if(cmds[0] == "show-zone") {
-    if(cmds.size() != 2) {
-      cerr << "Error: "<<cmds[0]<<" takes exactly 1 parameter"<<endl;
-      return 0;
-    }
-    const string& zone=cmds[1];
     
     DNSSECKeeper::keyset_t keyset=dk.getKeys(zone);
 
@@ -285,9 +236,10 @@ try
       cerr << "No keys for zone '"<<zone<<"'."<<endl;
     }
     else {  
-      cout << "keys: for zone '"<<zone<<"':"<<endl;
+      cout << "keys: "<<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;
+        cout<<"ID = "<<value.second.id<<" ("<<(value.second.keyOrZone ? "KSK" : "ZSK")<<"), tag = "<<value.first.getDNSKEY().getTag();
+        cout<<", algo = "<<(int)value.first.d_algorithm<<", bits = "<<value.first.d_key.getConstContext().len*8<<"\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;
@@ -345,7 +297,7 @@ try
     }
       
     dk.addKey(zone, false, 5);
-    dk.addKey(zone, false, 5, false); // not active
+    dk.addKey(zone, false, 5, 0, false); // not active
 
     zskset = dk.getKeys(zone, false);
     if(zskset.empty()) {
@@ -354,9 +306,34 @@ try
 
     cout<<"There are now "<<zskset.size()<<" ZSKs"<<endl;
     BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, zskset) {
-      cout<<"id = "<<value.second.id<<", tag = "<<value.first.getDNSKEY().getTag()<<"\tActive: "<<value.second.active<<endl;
+      cout<<"id = "<<value.second.id<<", tag = "<<value.first.getDNSKEY().getTag()<<", algo = "<<(int)value.first.d_algorithm<<
+        ", bits = "<<value.first.d_key.getContext().len*8;
+      cout<<"\tActive: "<<value.second.active<<endl;
     }
   }
+  else if(cmds[0]=="set-nsec3") {
+    string nsec3params =  cmds.size() > 2 ? cmds[2] : "1 0 1 ab";
+      
+    NSEC3PARAMRecordContent ns3pr(nsec3params);
+    dk.setNSEC3PARAM(cmds[1], ns3pr);
+  }
+  else if(cmds[0]=="unset-nsec3") {
+    dk.unsetNSEC3PARAM(cmds[1]);
+  }
+  else if(cmds[0]=="export-zone-key") {
+    string zone=cmds[1];
+    unsigned int id=atoi(cmds[2].c_str());
+    DNSSECPrivateKey dpk=dk.getKeyById(zone, id);
+    cout << dpk.d_key.convertToISC() <<endl;
+  }
+  else if(cmds[0]=="export-zone-dnskey") {
+    string zone=cmds[1];
+    unsigned int id=atoi(cmds[2].c_str());
+    DNSSECPrivateKey dpk=dk.getKeyById(zone, id);
+    cout << zone<<" IN DNSKEY "<<dpk.getDNSKEY().getZoneRepresentation() <<endl;
+    if(dpk.d_flags == 257)
+      cout << zone << " IN DS "<<makeDSFromDNSKey(zone, dpk.getDNSKEY()).getZoneRepresentation() << endl;
+  }
   else {
     cerr<<"Unknown command '"<<cmds[0]<<"'\n";
     return 1;