]> granicus.if.org Git - pdns/commitdiff
move some non-'keeper' dnssec signing logic away to a separate file, dnssecsigner.cc
authorBert Hubert <bert.hubert@netherlabs.nl>
Sun, 9 Jan 2011 15:54:20 +0000 (15:54 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sun, 9 Jan 2011 15:54:20 +0000 (15:54 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1848 d19b8d6e-7fed-0310-83ef-9ca221ded41b

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

index 4282594b9883e48fa2ad19b29021089158848285..500f27d3d62bd68737f01976efc9109dd7c3733b 100644 (file)
@@ -44,7 +44,7 @@ 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 dbdnsseckeeper.cc dnssecinfra.cc \
-dnsseckeeper.hh dnssecinfra.hh base32.hh dns.cc
+dnsseckeeper.hh dnssecinfra.hh base32.hh dns.cc dnssecsigner.cc
 
 #
 pdns_server_LDFLAGS=@moduleobjects@ @modulelibs@ @DYNLINKFLAGS@ @LIBDL@ @THREADFLAGS@ $(BOOST_FILESYSTEM_LDFLAGS) -Lext/polarssl/library
@@ -58,7 +58,7 @@ pdnssec_SOURCES=pdnssec.cc dbdnsseckeeper.cc sstuff.hh dnsparser.cc dnsparser.hh
        backends/bind/bindparser.cc backends/bind/bindlexer.c \
        backends/gsql/gsqlbackend.cc \
        backends/gsql/gsqlbackend.hh backends/gsql/ssql.hh zoneparser-tng.cc \
-       dynlistener.cc dns.cc randombackend.cc
+       dynlistener.cc dns.cc randombackend.cc dnssecsigner.cc
 
 pdnssec_LDFLAGS=@moduleobjects@ @modulelibs@ @DYNLINKFLAGS@ @LIBDL@ @THREADFLAGS@ -Lext/polarssl/library/ 
 pdnssec_LDADD=$(BOOST_FILESYSTEM_LIBS) $(BOOST_SYSTEM_LIBS) -lpolarssl $(BOOST_PROGRAM_OPTIONS_LIBS)
index 041e377b3ad1a46ea3dcc4bc4bd82b3c7dc2152f..9d8faca6237654b49b67db159804ae8ca102479c 100644 (file)
@@ -1,3 +1,21 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2001 - 2011  PowerDNS.COM BV
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License version 2 as 
+    published by the Free Software Foundation
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
 #include "dnsseckeeper.hh"
 #include "dnssecinfra.hh"
 #include "ueberbackend.hh"
@@ -177,138 +195,3 @@ void DNSSECKeeper::secureZone(const std::string& name, int algorithm)
 {
   addKey(name, true, algorithm);
 }
-
-// nobody should ever call this function, you know the SOA/auth already!
-bool getSignerApexFor(DNSSECKeeper& dk, const std::string& qname, std::string &signer)
-{
-  // cerr<<"getSignerApexFor: called, and should not be, should go away!"<<endl;
-  signer=qname;
-  do {
-    if(dk.haveActiveKSKFor(signer)) {
-      return true;
-    }
-  } while(chopOff(signer));
-  return false;
-}
-
-/* this is where the RRSIG gets filled out, the hashing gets done, key apex *name* gets found,
-   but the actual signing happens in fillOutRRSIG */
-int getRRSIGsForRRSET(DNSSECKeeper& dk, const std::string signQName, uint16_t signQType, uint32_t signTTL, 
-                    vector<shared_ptr<DNSRecordContent> >& toSign, vector<RRSIGRecordContent>& rrcs, bool ksk)
-{
-  if(toSign.empty())
-    return -1;
-  RRSIGRecordContent rrc;
-  rrc.d_type=signQType;
-
-  // d_algorithm gets filled out by getSignerAPEX, since only it looks up the key
-  rrc.d_labels=countLabels(signQName); 
-  rrc.d_originalttl=signTTL; 
-  rrc.d_siginception=getCurrentInception();;
-  rrc.d_sigexpire = rrc.d_siginception + 14*86400; // XXX should come from zone metadata
-  rrc.d_tag = 0;
-  
-  // XXX we know the apex already.. is is the SOA name which we determined earlier
-  if(!getSignerApexFor(dk, signQName, rrc.d_signer)) {
-    cerr<<"No signer known for '"<<signQName<<"'\n";
-    return -1;
-  }
-  // we sign the RRSET in toSign + the rrc w/o key
-  
-  DNSSECKeeper::keyset_t keys = dk.getKeys(rrc.d_signer);
-  vector<DNSSECPrivateKey> KSKs, ZSKs;
-  vector<DNSSECPrivateKey>* signingKeys;
-  
-  // if ksk==1, only get KSKs
-  // if ksk==0, get ZSKs, unless there is no ZSK, then get KSK
-  BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type& keymeta, keys) {
-    if(!keymeta.second.active) 
-      continue;
-      
-    if(keymeta.second.keyOrZone)
-      KSKs.push_back(keymeta.first);
-    else if(!ksk)
-      ZSKs.push_back(keymeta.first);
-  }
-  if(ksk)
-    signingKeys = &KSKs;
-  else {
-    if(ZSKs.empty())
-      signingKeys = &KSKs;
-    else
-      signingKeys =&ZSKs;
-  }
-  
-  BOOST_FOREACH(DNSSECPrivateKey& dpk, *signingKeys) {
-    fillOutRRSIG(dpk, signQName, rrc, toSign);
-    rrcs.push_back(rrc);
-  }
-  return 0;
-}
-
-// this is the entrypoint from DNSPacket
-void addSignature(DNSSECKeeper& dk, const std::string signQName, const std::string& wildcardname, uint16_t signQType, 
-  uint32_t signTTL, DNSPacketWriter::Place signPlace, 
-  vector<shared_ptr<DNSRecordContent> >& toSign, uint16_t maxReplyLen, DNSPacketWriter& pw)
-{
-  // cerr<<"Asked to sign '"<<signQName<<"'|"<<DNSRecordContent::NumberToType(signQType)<<", "<<toSign.size()<<" records\n";
-
-  vector<RRSIGRecordContent> rrcs;
-  if(toSign.empty())
-    return;
-
-  if(getRRSIGsForRRSET(dk, wildcardname.empty() ? signQName : wildcardname, signQType, signTTL, toSign, rrcs, signQType == QType::DNSKEY) < 0) {
-    cerr<<"Error signing a record!"<<endl;
-    return;
-  }
-  BOOST_FOREACH(RRSIGRecordContent& rrc, rrcs) {
-    pw.startRecord(signQName, QType::RRSIG, 3600, 1, 
-      signQType==QType::DNSKEY ? DNSPacketWriter:: ANSWER : signPlace); 
-    rrc.toPacket(pw);
-    if(maxReplyLen &&  (pw.size() + 20) > maxReplyLen) {
-      pw.rollback();
-      pw.getHeader()->tc=1;
-      return;
-    }
-  }
-  pw.commit();
-
-  toSign.clear();
-}
-
-static pthread_mutex_t g_signatures_lock = PTHREAD_MUTEX_INITIALIZER;
-static map<pair<RSAContext, string>, string> g_signatures;
-
-void fillOutRRSIG(DNSSECPrivateKey& dpk, const std::string& signQName, RRSIGRecordContent& rrc, vector<shared_ptr<DNSRecordContent> >& toSign) 
-{
-  DNSKEYRecordContent drc= dpk.getDNSKEY(); 
-  RSAContext& rc = dpk.d_key;
-  rrc.d_tag = drc.getTag();
-  rrc.d_algorithm = drc.d_algorithm;
-  string realhash=getHashForRRSET(signQName, rrc, toSign); // this is what we sign
-
-  unsigned char signature[mpi_size(&rc.getContext().N)];
-
-  {
-    Lock l(&g_signatures_lock);
-    if(g_signatures.count(make_pair(rc, realhash))) {
-      rrc.d_signature=g_signatures[make_pair(rc, realhash)];
-      return;
-    }
-  }
-  
-  int ret=rsa_pkcs1_sign(&rc.getContext(), RSA_PRIVATE, 
-    rrc.d_algorithm < 8 ? SIG_RSA_SHA1 : SIG_RSA_SHA256, 
-    rrc.d_algorithm < 8 ? 20 : 32,
-    (unsigned char*) realhash.c_str(), signature);
-  
-  if(ret!=0) {
-    cerr<<"signing returned: "<<ret<<endl;
-    exit(1);
-  }
-  
-  rrc.d_signature.assign((char*)signature, sizeof(signature));
-
-  Lock l(&g_signatures_lock);
-  g_signatures[make_pair(rc, realhash)] = rrc.d_signature;
-}
diff --git a/pdns/dnssecsigner.cc b/pdns/dnssecsigner.cc
new file mode 100644 (file)
index 0000000..4484a67
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+    PowerDNS Versatile Database Driven Nameserver
+    Copyright (C) 2001 - 2011  PowerDNS.COM BV
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License version 2 as 
+    published by the Free Software Foundation
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include "dnssecinfra.hh"
+#include "namespaces.hh"
+#include <boost/foreach.hpp>
+#include "dnsseckeeper.hh"
+#include "lock.hh"
+
+// nobody should ever call this function, you know the SOA/auth already!
+bool getSignerApexFor(DNSSECKeeper& dk, const std::string& qname, std::string &signer)
+{
+  // cerr<<"getSignerApexFor: called, and should not be, should go away!"<<endl;
+  signer=qname;
+  do {
+    if(dk.haveActiveKSKFor(signer)) {
+      return true;
+    }
+  } while(chopOff(signer));
+  return false;
+}
+
+/* this is where the RRSIGs begin, key apex *name* gets found, keys are retrieved,
+   but the actual signing happens in fillOutRRSIG */
+int getRRSIGsForRRSET(DNSSECKeeper& dk, const std::string signQName, uint16_t signQType, uint32_t signTTL, 
+                    vector<shared_ptr<DNSRecordContent> >& toSign, vector<RRSIGRecordContent>& rrcs, bool ksk)
+{
+  if(toSign.empty())
+    return -1;
+  RRSIGRecordContent rrc;
+  rrc.d_type=signQType;
+
+  // d_algorithm gets filled out by getSignerAPEX, since only it looks up the key
+  rrc.d_labels=countLabels(signQName); 
+  rrc.d_originalttl=signTTL; 
+  rrc.d_siginception=getCurrentInception();;
+  rrc.d_sigexpire = rrc.d_siginception + 14*86400; // XXX should come from zone metadata
+  rrc.d_tag = 0;
+  
+  // XXX we know the apex already.. is is the SOA name which we determined earlier
+  if(!getSignerApexFor(dk, signQName, rrc.d_signer)) {
+    cerr<<"No signer known for '"<<signQName<<"'\n";
+    return -1;
+  }
+  // we sign the RRSET in toSign + the rrc w/o key
+  
+  DNSSECKeeper::keyset_t keys = dk.getKeys(rrc.d_signer);
+  vector<DNSSECPrivateKey> KSKs, ZSKs;
+  vector<DNSSECPrivateKey>* signingKeys;
+  
+  // if ksk==1, only get KSKs
+  // if ksk==0, get ZSKs, unless there is no ZSK, then get KSK
+  BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type& keymeta, keys) {
+    if(!keymeta.second.active) 
+      continue;
+      
+    if(keymeta.second.keyOrZone)
+      KSKs.push_back(keymeta.first);
+    else if(!ksk)
+      ZSKs.push_back(keymeta.first);
+  }
+  if(ksk)
+    signingKeys = &KSKs;
+  else {
+    if(ZSKs.empty())
+      signingKeys = &KSKs;
+    else
+      signingKeys =&ZSKs;
+  }
+  
+  BOOST_FOREACH(DNSSECPrivateKey& dpk, *signingKeys) {
+    fillOutRRSIG(dpk, signQName, rrc, toSign);
+    rrcs.push_back(rrc);
+  }
+  return 0;
+}
+
+// this is the entrypoint from DNSPacket
+void addSignature(DNSSECKeeper& dk, const std::string signQName, const std::string& wildcardname, uint16_t signQType, 
+  uint32_t signTTL, DNSPacketWriter::Place signPlace, 
+  vector<shared_ptr<DNSRecordContent> >& toSign, uint16_t maxReplyLen, DNSPacketWriter& pw)
+{
+  // cerr<<"Asked to sign '"<<signQName<<"'|"<<DNSRecordContent::NumberToType(signQType)<<", "<<toSign.size()<<" records\n";
+
+  vector<RRSIGRecordContent> rrcs;
+  if(toSign.empty())
+    return;
+
+  if(getRRSIGsForRRSET(dk, wildcardname.empty() ? signQName : wildcardname, signQType, signTTL, toSign, rrcs, signQType == QType::DNSKEY) < 0) {
+    cerr<<"Error signing a record!"<<endl;
+    return;
+  }
+  BOOST_FOREACH(RRSIGRecordContent& rrc, rrcs) {
+    pw.startRecord(signQName, QType::RRSIG, 3600, 1, 
+      signQType==QType::DNSKEY ? DNSPacketWriter:: ANSWER : signPlace); 
+    rrc.toPacket(pw);
+    if(maxReplyLen &&  (pw.size() + 20) > maxReplyLen) {
+      pw.rollback();
+      pw.getHeader()->tc=1;
+      return;
+    }
+  }
+  pw.commit();
+
+  toSign.clear();
+}
+
+static pthread_mutex_t g_signatures_lock = PTHREAD_MUTEX_INITIALIZER;
+static map<pair<RSAContext, string>, string> g_signatures;
+
+void fillOutRRSIG(DNSSECPrivateKey& dpk, const std::string& signQName, RRSIGRecordContent& rrc, vector<shared_ptr<DNSRecordContent> >& toSign) 
+{
+  DNSKEYRecordContent drc= dpk.getDNSKEY(); 
+  RSAContext& rc = dpk.d_key;
+  rrc.d_tag = drc.getTag();
+  rrc.d_algorithm = drc.d_algorithm;
+  string realhash=getHashForRRSET(signQName, rrc, toSign); // this is what we sign
+
+  unsigned char signature[mpi_size(&rc.getContext().N)];
+
+  {
+    Lock l(&g_signatures_lock);
+    
+    // this is mindbogglingly inefficient, we store the whole private key as index!
+    if(g_signatures.count(make_pair(rc, realhash))) {
+      rrc.d_signature=g_signatures[make_pair(rc, realhash)];
+      return;
+    }
+  }
+  
+  int ret=rsa_pkcs1_sign(&rc.getContext(), RSA_PRIVATE, 
+    rrc.d_algorithm < 8 ? SIG_RSA_SHA1 : SIG_RSA_SHA256, 
+    rrc.d_algorithm < 8 ? 20 : 32,
+    (unsigned char*) realhash.c_str(), signature);
+  
+  if(ret!=0) {
+    cerr<<"signing returned: "<<ret<<endl;
+    exit(1);
+  }
+  
+  rrc.d_signature.assign((char*)signature, sizeof(signature));
+
+  Lock l(&g_signatures_lock);
+  g_signatures[make_pair(rc, realhash)] = rrc.d_signature;
+}