]> granicus.if.org Git - pdns/commitdiff
hook up the dbdnsseckeeper to everything, implement (most) methods in the generic...
authorBert Hubert <bert.hubert@netherlabs.nl>
Sat, 1 Jan 2011 21:19:02 +0000 (21:19 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sat, 1 Jan 2011 21:19:02 +0000 (21:19 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1781 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/backends/gsql/gsqlbackend.cc
pdns/backends/gsql/gsqlbackend.hh
pdns/dbdnsseckeeper.cc [new file with mode: 0644]
pdns/ueberbackend.cc
pdns/ueberbackend.hh

index f49887c5c3ecd1f399c690c0f03357fd9ddb62c2..b93ca008c4a6cff62f2d60e3238ac25a05aa2980 100644 (file)
@@ -18,6 +18,7 @@ using namespace std;
 #include "pdns/arguments.hh"
 #include <boost/algorithm/string.hpp>
 #include <sstream>
+#include <boost/foreach.hpp>
 using namespace boost;
 
 void GSQLBackend::setNotified(uint32_t domain_id, uint32_t serial)
@@ -241,6 +242,12 @@ GSQLBackend::GSQLBackend(const string &mode, const string &suffix)
   d_beforeOrderQuery = getArg("get-order-before-query");
   d_afterOrderQuery = getArg("get-order-after-query");
   d_setOrderAuthQuery = getArg("set-order-and-auth-query");
+  
+  d_AddDomainKeyQuery = "insert into cryptokeys (domain_id, flags, active, content) select id, %d, %d, '%s' from domains where name='%s'";
+  d_ListDomainKeysQuery = "select cryptokeys.id, flags, active, content from domains, cryptokeys where domain_id=domains.id and name='%s'";
+  
+  d_GetDomainMetadataQuery = "select content from domains, domainmetadata where domain_id=domains.id and name='%s' and domainmetadata.kind='%s'";
+  d_SetDomainMetadataQuery = "insert into domainmetadata (domain_id, kind, content) select id, '%s', '%s' from domains where name='%s'";
 }
 
 bool GSQLBackend::updateDNSSECOrderAndAuth(uint32_t domain_id, const std::string& zonename, const std::string& qname, bool auth)
@@ -303,6 +310,86 @@ retryBefore:
   return true;
 }
 
+int GSQLBackend::addDomainKey(const string& name, const KeyData& key)
+{
+  char output[16384];  
+  snprintf(output,sizeof(output)-1,d_AddDomainKeyQuery.c_str(),
+          key.flags, (int)key.active, sqlEscape(key.content).c_str(), sqlEscape(name).c_str());
+
+  try {
+    d_db->doCommand(output);
+  }
+  catch (SSqlException &e) {
+    throw AhuException("GSQLBackend unable to store key: "+e.txtReason());
+  }
+  return 1; // XXX FIXME, no idea how to get the id
+}
+
+bool GSQLBackend::getDomainKeys(const string& name, unsigned int kind, std::vector<KeyData>& keys)
+{
+  char output[1024];  
+  snprintf(output,sizeof(output)-1,d_ListDomainKeysQuery.c_str(), sqlEscape(name).c_str());
+
+  try {
+    d_db->doQuery(output);
+  }
+  catch (SSqlException &e) {
+    throw AhuException("GSQLBackend unable to list keys: "+e.txtReason());
+  }
+  
+  SSql::row_t row;
+  //  "select id, kind, active, content from domains, cryptokeys where domain_id=domains.id and name='%s'";
+  KeyData kd;
+  while(d_db->getRow(row)) {
+    //~ BOOST_FOREACH(const std::string& val, row) {
+      //~ cerr<<"'"<<val<<"'"<<endl;
+    //~ }
+    kd.id = atoi(row[0].c_str());
+    kd.flags = atoi(row[1].c_str());
+    kd.active = atoi(row[2].c_str());
+    kd.content = row[3];
+    keys.push_back(kd);
+  }
+
+  return true;
+}
+
+bool GSQLBackend::getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta)
+{
+  char output[1024];  
+  snprintf(output,sizeof(output)-1,d_GetDomainMetadataQuery.c_str(), sqlEscape(name).c_str(), sqlEscape(kind).c_str());
+
+  try {
+    d_db->doQuery(output);
+  }
+  catch (SSqlException &e) {
+    throw AhuException("GSQLBackend unable to list keys: "+e.txtReason());
+  }
+  
+  SSql::row_t row;
+  //  "select id, kind, active, content from domains, cryptokeys where domain_id=domains.id and name='%s'";
+  KeyData kd;
+  while(d_db->getRow(row)) {
+    meta.push_back(row[0]);
+  }
+  return true;
+}
+
+bool GSQLBackend::setDomainMetadata(const string& name, const std::string& kind, const std::vector<std::string>& meta)
+{
+  char output[16384];  
+  snprintf(output,sizeof(output)-1,d_SetDomainMetadataQuery.c_str(),
+          sqlEscape(kind).c_str(), sqlEscape(*meta.begin()).c_str(), sqlEscape(name).c_str());
+
+  try {
+    d_db->doCommand(output);
+  }
+  catch (SSqlException &e) {
+    throw AhuException("GSQLBackend unable to store metadata key: "+e.txtReason());
+  }
+  return true;
+}
+
 
 void GSQLBackend::lookup(const QType &qtype,const string &qname, DNSPacket *pkt_p, int domain_id)
 {
index 51b9cec91ac9cef07aa021b924fe20c91d20dfa1..ee9e9aa89bf9f7b54016ead143536a48f91bcada 100644 (file)
@@ -43,7 +43,10 @@ public:
   bool updateDNSSECOrderAndAuth(uint32_t domain_id, const std::string& zonename, const std::string& qname, bool auth);
   virtual bool updateDNSSECOrderAndAuthAbsolute(uint32_t domain_id, const std::string& qname, const std::string& ordername, bool auth);
 
-
+  int addDomainKey(const string& name, const KeyData& key);
+  bool getDomainKeys(const string& name, unsigned int kind, std::vector<KeyData>& keys);
+  bool getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta);
+  bool setDomainMetadata(const string& name, const std::string& kind, const std::vector<std::string>& meta);
 private:
   string d_qname;
   QType d_qtype;
@@ -78,6 +81,10 @@ private:
   string d_afterOrderQuery;
   string d_setOrderAuthQuery;
 
+  string d_AddDomainKeyQuery;
+  string d_ListDomainKeysQuery;
+  string d_GetDomainMetadataQuery;
+  string d_SetDomainMetadataQuery;
 protected:  
   bool d_dnssecQueries;
 };
diff --git a/pdns/dbdnsseckeeper.cc b/pdns/dbdnsseckeeper.cc
new file mode 100644 (file)
index 0000000..6a8571c
--- /dev/null
@@ -0,0 +1,177 @@
+#include "dnsseckeeper.hh"
+#include "dnssecinfra.hh"
+#include "ueberbackend.hh"
+#include "statbag.hh"
+#include <iostream>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#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;
+
+bool DNSSECKeeper::haveActiveKSKFor(const std::string& zone, DNSSECPrivateKey* dpk)
+{
+  keyset_t keys = getKeys(zone, true);
+  // need to get an *active* one!
+  //cerr<<__FUNCTION__<<"Got "<<keys.size()<<" keys"<<endl;
+  if(dpk && !keys.empty()) {
+    *dpk = keys.begin()->first;
+  }
+  return !keys.empty();
+}
+
+
+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(bits); 
+  DNSBackend::KeyData kd;
+  kd.flags = 256 + keyOrZone;
+  kd.active = active;
+  kd.content = dpk.d_key.convertToISC(algorithm);
+ // now store it
+  UeberBackend db;
+  db.addDomainKey(name, kd);
+}
+
+
+static bool keyCompareByKindAndID(const DNSSECKeeper::keyset_t::value_type& a, const DNSSECKeeper::keyset_t::value_type& b)
+{
+  return make_pair(!a.second.keyOrZone, a.second.id) <
+         make_pair(!b.second.keyOrZone, b.second.id);
+}
+
+DNSSECPrivateKey DNSSECKeeper::getKeyById(const std::string& zname, unsigned int id)
+{  
+  UeberBackend db;
+  vector<DNSBackend::KeyData> keys;
+  db.getDomainKeys(zname, 0, keys);
+  BOOST_FOREACH(const DNSBackend::KeyData& kd, keys) {
+    if(kd.id != id) 
+      continue;
+    
+    DNSSECPrivateKey dpk;
+
+    getRSAKeyFromISCString(&dpk.d_key.getContext(), kd.content);
+    dpk.d_flags = kd.flags;
+    dpk.d_algorithm = 5 + 2*getNSEC3PARAM(zname);
+    
+    KeyMetaData kmd;
+
+    kmd.active = kd.active;
+    kmd.keyOrZone = (kd.flags == 257);
+    kmd.id = kd.id;
+    
+    return dpk;    
+  }
+  throw runtime_error("Can't find a key with id "+lexical_cast<string>(id)+" for zone '"+zname+"'");
+  
+  
+}
+
+
+void DNSSECKeeper::removeKey(const std::string& zname, unsigned int id)
+{
+  // XXX
+}
+
+void DNSSECKeeper::deactivateKey(const std::string& zname, unsigned int id)
+{
+  // XX
+}
+
+void DNSSECKeeper::activateKey(const std::string& zname, unsigned int id)
+{
+  // XXX
+}
+
+bool DNSSECKeeper::getNSEC3PARAM(const std::string& zname, NSEC3PARAMRecordContent* ns3p)
+{
+  UeberBackend db;
+  vector<string> meta;
+  db.getDomainMetadata(zname, "NSEC3PARAM", meta);
+  
+  if(meta.empty())
+    return false;
+    
+  if(ns3p) {
+    string descr = *meta.begin();
+    reportAllTypes();
+    NSEC3PARAMRecordContent* tmp=dynamic_cast<NSEC3PARAMRecordContent*>(DNSRecordContent::mastermake(QType::NSEC3PARAM, 1, descr));
+    if(!tmp) {
+      cerr<<"descr: '"<<descr<<"'\n";
+      return false;
+    }
+    *ns3p = *tmp;
+    delete tmp;
+  }
+  return true;
+}
+
+void DNSSECKeeper::setNSEC3PARAM(const std::string& zname, const NSEC3PARAMRecordContent& ns3p)
+{
+  string descr = ns3p.getZoneRepresentation();
+  vector<string> meta;
+  meta.push_back(descr);
+  UeberBackend db;
+  db.setDomainMetadata(zname, "NSEC3PARAM", meta);
+  
+  // XXX do db
+}
+
+void DNSSECKeeper::unsetNSEC3PARAM(const std::string& zname)
+{
+  // XXX do db
+}
+
+
+DNSSECKeeper::keyset_t DNSSECKeeper::getKeys(const std::string& zone, boost::tribool allOrKeyOrZone)
+{
+  keyset_t keyset;
+  UeberBackend db;
+  vector<UeberBackend::KeyData> dbkeyset;
+  
+  db.getDomainKeys(zone, 0, dbkeyset);
+  // do db thing
+  //cerr<<"Here: received " <<dbkeyset.size()<<" keys"<<endl;
+  BOOST_FOREACH(UeberBackend::KeyData& kd, dbkeyset) 
+  {
+    DNSSECPrivateKey dpk;
+
+    getRSAKeyFromISCString(&dpk.d_key.getContext(), kd.content);
+    dpk.d_flags = kd.flags;
+    dpk.d_algorithm = 5 + 2*getNSEC3PARAM(zone);
+    
+    KeyMetaData kmd;
+
+    kmd.active = kd.active;
+    kmd.keyOrZone = (kd.flags == 257);
+    kmd.id = kd.id;
+    
+    if(boost::indeterminate(allOrKeyOrZone) || allOrKeyOrZone == kmd.keyOrZone)
+      keyset.push_back(make_pair(dpk, kmd));
+  }
+  sort(keyset.begin(), keyset.end(), keyCompareByKindAndID);
+  return keyset;
+}
+
+void DNSSECKeeper::secureZone(const std::string& name, int algorithm)
+{
+  addKey(name, true, algorithm);
+}
+
index a2ac2a59d3417b7923c7f110e019ec1fe7d1939d..46710205dfb881be3518ff247534faee9becbbfe 100644 (file)
@@ -30,6 +30,7 @@
 #include <iostream>
 #include <sstream>
 #include <functional>
+#include <boost/foreach.hpp>
 
 #include "dns.hh"
 #include "arguments.hh"
@@ -98,6 +99,42 @@ bool UeberBackend::getDomainInfo(const string &domain, DomainInfo &di)
   return false;
 }
 
+int UeberBackend::addDomainKey(const string& name, const KeyData& key)
+{
+  BOOST_FOREACH(DNSBackend* db, backends) {
+    if(db->addDomainKey(name, key) >= 0)
+      return true;
+  }
+  return false;
+}
+bool UeberBackend::getDomainKeys(const string& name, unsigned int kind, std::vector<KeyData>& keys)
+{
+  BOOST_FOREACH(DNSBackend* db, backends) {
+    if(db->getDomainKeys(name, kind, keys))
+      return true;
+  }
+  return false;
+}
+
+bool UeberBackend::getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta)
+{
+  BOOST_FOREACH(DNSBackend* db, backends) {
+    if(db->getDomainMetadata(name, kind, meta))
+      return true;
+  }
+  return false;
+}
+
+bool UeberBackend::setDomainMetadata(const string& name, const std::string& kind, const std::vector<std::string>& meta)
+{
+  BOOST_FOREACH(DNSBackend* db, backends) {
+    if(db->setDomainMetadata(name, kind, meta))
+      return true;
+  }
+  return false;
+}
+
+
 void UeberBackend::reload()
 {
   for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
index e2fc6788fc759a2d9c66f5d54afc433a287004c5..27f07bc57a35974e9b6fb4ac9e29b87101a1f9cf 100644 (file)
@@ -122,6 +122,12 @@ public:
   void getUnfreshSlaveInfos(vector<DomainInfo>* domains);
   void getUpdatedMasters(vector<DomainInfo>* domains);
   bool getDomainInfo(const string &domain, DomainInfo &di);
+  
+  int addDomainKey(const string& name, const KeyData& key);
+  bool getDomainKeys(const string& name, unsigned int kind, std::vector<KeyData>& keys);
+  bool getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta);
+  bool setDomainMetadata(const string& name, const std::string& kind, const std::vector<std::string>& meta);
+  
   void alsoNotifies(const string &domain, set<string> *ips); 
   void rediscover(string* status=0);
   void reload();