]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Add the 'CSK' (Combined Signing Key) nomenclature 3124/head
authorPieter Lexis <pieter.lexis@powerdns.com>
Tue, 19 Jan 2016 17:09:55 +0000 (18:09 +0100)
committerPieter Lexis <pieter.lexis@powerdns.com>
Tue, 19 Jan 2016 21:45:57 +0000 (22:45 +0100)
This commit removes the 'keyOrZone' boolean from
DNSSECKeeper::KeyMetaData and adds 'keyType' enum to it that can contain
one of 3 values (KSK, ZSK or CSK). A key is marked as a CSK when there
is no other key with the same algorithm for the zone, and if there is
another key, that it does not have a different SEP-bit set.

By default, we now also set the SEP-bit in `pdnsutil secure-zone` when
only a ZSK is created (this is the default) so we comply with the
recommendation in RFC 6781 ยง3.2.3.

Closes #3194

13 files changed:
modules/remotebackend/regression-tests/dnssec-keys/expected_result
pdns/dbdnsseckeeper.cc
pdns/dnsseckeeper.hh
pdns/dnssecsigner.cc
pdns/pdnsutil.cc
pdns/ws-auth.cc
regression-tests.api/runtests
regression-tests.api/test_Zones.py
regression-tests/tests/00dnssec-grabkeys/command
regression-tests/tests/axfr/expected_result.dnssec
regression-tests/tests/axfr/expected_result.nsec3
regression-tests/tests/axfr/expected_result.nsec3-optout
regression-tests/tests/direct-dnskey/expected_result.dnssec

index 99fc090d1a60926f742854bd3511dc6f608fd3fb..bcf7d1d55d2a8330cdacac62ece1346082b47cef 100644 (file)
@@ -1,3 +1,3 @@
-0      example.com.    IN      DNSKEY  120     256 3 13 ...
+0      example.com.    IN      DNSKEY  120     257 3 13 ...
 Rcode: 0 (No Error), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
 Reply to question for qname='example.com.', qtype=DNSKEY
index 35360cfff7d88efb8493ab122f2e28a3bd7b7a68..3e51278fb6a1344f3580da1b9a162580e0695ff1 100644 (file)
@@ -74,11 +74,11 @@ bool DNSSECKeeper::isPresigned(const DNSName& name)
   return meta=="1";
 }
 
-bool DNSSECKeeper::addKey(const DNSName& name, bool keyOrZone, int algorithm, int bits, bool active)
+bool DNSSECKeeper::addKey(const DNSName& name, bool setSEPBit, int algorithm, int bits, bool active)
 {
   if(!bits) {
     if(algorithm <= 10)
-      bits = keyOrZone ? 2048 : 1024;
+      throw runtime_error("Creating an algorithm " +std::to_string(algorithm)+" ("+algorithm2name(algorithm)+") key requires the size (in bits) to be passed");
     else {
       if(algorithm == 12 || algorithm == 13 || algorithm == 250) // GOST, ECDSAP256SHA256, ED25519SHA512
         bits = 256;
@@ -90,11 +90,11 @@ bool DNSSECKeeper::addKey(const DNSName& name, bool keyOrZone, int algorithm, in
     }
   }
   DNSSECPrivateKey dspk;
-  shared_ptr<DNSCryptoKeyEngine> dpk(DNSCryptoKeyEngine::make(algorithm)); // defaults to RSA for now, could be smart w/algorithm! XXX FIXME
+  shared_ptr<DNSCryptoKeyEngine> dpk(DNSCryptoKeyEngine::make(algorithm));
   dpk->create(bits);
   dspk.setKey(dpk);
   dspk.d_algorithm = algorithm;
-  dspk.d_flags = keyOrZone ? 257 : 256;
+  dspk.d_flags = setSEPBit ? 257 : 256;
   return addKey(name, dspk, active);
 }
 
@@ -134,8 +134,8 @@ bool DNSSECKeeper::addKey(const DNSName& name, const DNSSECPrivateKey& dpk, bool
 
 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);
+  return make_pair(!a.second.keyType, a.second.id) <
+         make_pair(!b.second.keyType, b.second.id);
 }
 
 DNSSECPrivateKey DNSSECKeeper::getKeyById(const DNSName& zname, unsigned int id)
@@ -379,27 +379,13 @@ DNSSECKeeper::keyset_t DNSSECKeeper::getEntryPoints(const DNSName& zname)
   DNSSECKeeper::keyset_t ret;
   DNSSECKeeper::keyset_t keys = getKeys(zname);
 
-  set<int> algoHasKSK;
-
-  for(auto const &keymeta : keys) {
-    if(keymeta.second.active && keymeta.second.keyOrZone) {
-      // KSKs should always be returned
+  for(auto const &keymeta : keys)
+    if(keymeta.second.active && (keymeta.second.keyType == KSK || keymeta.second.keyType == CSK))
       ret.push_back(keymeta);
-      algoHasKSK.insert(keymeta.first.d_algorithm);
-    }
-  }
-
-  // Now add ZSK EntryPoints
-  for(auto const &keymeta : keys) {
-    // Skip inactive keys, KSKs and algos that have a KSK
-    if (!keymeta.second.active || keymeta.second.keyOrZone || algoHasKSK.count(keymeta.first.d_algorithm))
-      continue;
-    ret.push_back(keymeta);
-  }
   return ret;
 }
 
-DNSSECKeeper::keyset_t DNSSECKeeper::getKeys(const DNSName& zone, boost::tribool allOrKeyOrZone, bool useCache)
+DNSSECKeeper::keyset_t DNSSECKeeper::getKeys(const DNSName& zone, bool useCache)
 {
   unsigned int now = time(0);
 
@@ -410,56 +396,75 @@ DNSSECKeeper::keyset_t DNSSECKeeper::getKeys(const DNSName& zone, boost::tribool
   if (useCache) {
     ReadLock l(&s_keycachelock);
     keycache_t::const_iterator iter = s_keycache.find(zone);
-      
-    if(iter != s_keycache.end() && iter->d_ttd > now) { 
+
+    if(iter != s_keycache.end() && iter->d_ttd > now) {
       keyset_t ret;
-      for(const keyset_t::value_type& value :  iter->d_keys) {
-        if(boost::indeterminate(allOrKeyOrZone) || allOrKeyOrZone == value.second.keyOrZone)
-          ret.push_back(value);
-      }
+      for(const keyset_t::value_type& value :  iter->d_keys)
+        ret.push_back(value);
       return ret;
     }
-  }    
-  keyset_t retkeyset, allkeyset;
+  }
+
+  keyset_t retkeyset;
   vector<DNSBackend::KeyData> dbkeyset;
-  
+
   d_keymetadb->getDomainKeys(zone, 0, dbkeyset);
-  
-  for(DNSBackend::KeyData& kd :  dbkeyset)
-  {
+
+  // Determine the algorithms that have a KSK/ZSK split
+  set<uint8_t> algoSEP, algoNoSEP;
+  vector<uint8_t> algoHasSeparateKSK;
+  for(const DNSBackend::KeyData &keydata : dbkeyset) {
     DNSSECPrivateKey dpk;
+    DNSKEYRecordContent dkrc;
+
+    dpk.setKey(shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::makeFromISCString(dkrc, keydata.content)));
 
+    if(keydata.active) {
+      if(keydata.flags == 257)
+        algoSEP.insert(dkrc.d_algorithm);
+      else
+        algoNoSEP.insert(dkrc.d_algorithm);
+    }
+  }
+  set_intersection(algoSEP.begin(), algoSEP.end(), algoNoSEP.begin(), algoNoSEP.end(), std::back_inserter(algoHasSeparateKSK));
+
+  for(DNSBackend::KeyData& kd : dbkeyset)
+  {
+    DNSSECPrivateKey dpk;
     DNSKEYRecordContent dkrc;
-    
+
     dpk.setKey(shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::makeFromISCString(dkrc, kd.content)));
-    
+
     dpk.d_flags = kd.flags;
     dpk.d_algorithm = dkrc.d_algorithm;
-    if(dpk.d_algorithm == 5 && getNSEC3PARAM(zone))
+    if(dpk.d_algorithm == 5 && getNSEC3PARAM(zone)) // XXX Needs to go, see #3267
       dpk.d_algorithm+=2;
-    
+
     KeyMetaData kmd;
 
     kmd.active = kd.active;
-    kmd.keyOrZone = (kd.flags == 257);
+    kmd.hasSEPBit = (kd.flags == 257);
     kmd.id = kd.id;
-    
-    if(boost::indeterminate(allOrKeyOrZone) || allOrKeyOrZone == kmd.keyOrZone)
-      retkeyset.push_back(make_pair(dpk, kmd));
-    allkeyset.push_back(make_pair(dpk, kmd));
+
+    if (find(algoHasSeparateKSK.begin(), algoHasSeparateKSK.end(), dpk.d_algorithm) == algoHasSeparateKSK.end())
+      kmd.keyType = CSK;
+    else if(kmd.hasSEPBit)
+      kmd.keyType = KSK;
+    else
+      kmd.keyType = ZSK;
+
+    retkeyset.push_back(make_pair(dpk, kmd));
   }
   sort(retkeyset.begin(), retkeyset.end(), keyCompareByKindAndID);
-  sort(allkeyset.begin(), allkeyset.end(), keyCompareByKindAndID);
-  
+
   KeyCacheEntry kce;
   kce.d_domain=zone;
-  kce.d_keys = allkeyset;
+  kce.d_keys = retkeyset;
   kce.d_ttd = now + 30;
   {
     WriteLock l(&s_keycachelock);
     replacing_insert(s_keycache, kce);
   }
-  
   return retkeyset;
 }
 
index c3fa3da751622ba475eb1ef09d7cc60cdcb731a5..8eab6177de99d8d098a7474a774298c459c851a4 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef PDNSDNSSECKEEPER_HH
-#define PDNSDNSSECKEEPER_HH
+#pragma once
 /*
     PowerDNS Versatile Database Driven Nameserver
     Copyright (C) 2002-2011  PowerDNS.COM BV
@@ -40,16 +39,105 @@ using namespace ::boost::multi_index;
 class DNSSECKeeper : public boost::noncopyable
 {
 public:
+  enum keytype_t { KSK, ZSK, CSK };
+  enum keyalgorithm_t : uint8_t {
+    RSAMD5=1,
+    DH=2,
+    DSA=3,
+    RSASHA1=5,
+    DSANSEC3SHA1=6,
+    RSASHA1NSEC3SHA1=7,
+    RSASHA256=8,
+    RSASHA512=10,
+    ECCGOST=12,
+    ECDSA256=13,
+    ECDSA384=14,
+    EXPERIMENTALED25519=250
+  };
+
   struct KeyMetaData
   {
     string fname;
     unsigned int id;
     bool active;
-    bool keyOrZone;
+    keytype_t keyType;
+    bool hasSEPBit;
   };
-  typedef std::pair<DNSSECPrivateKey, KeyMetaData> keymeta_t; 
+  typedef std::pair<DNSSECPrivateKey, KeyMetaData> keymeta_t;
   typedef std::vector<keymeta_t > keyset_t;
 
+  static string keyTypeToString(const keytype_t &keyType)
+  {
+    switch(keyType) {
+      case DNSSECKeeper::KSK:
+        return("KSK");
+      case DNSSECKeeper::ZSK:
+        return("ZSK");
+      case DNSSECKeeper::CSK:
+        return("CSK");
+      default:
+        return("UNKNOWN");
+    }
+  }
+
+  static int shorthand2algorithm(const string &algorithm)
+  {
+    if (!algorithm.compare("rsamd5")) return RSAMD5;
+    if (!algorithm.compare("dh")) return DH;
+    if (!algorithm.compare("dsa")) return DSA;
+    if (!algorithm.compare("rsasha1")) return RSASHA1;
+    if (!algorithm.compare("rsasha256")) return RSASHA256;
+    if (!algorithm.compare("rsasha512")) return RSASHA512;
+    if (!algorithm.compare("ecc-gost")) return ECCGOST;
+    if (!algorithm.compare("gost")) return ECCGOST;
+    if (!algorithm.compare("ecdsa256")) return ECDSA256;
+    if (!algorithm.compare("ecdsa384")) return ECDSA384;
+    if (!algorithm.compare("experimental-ed25519")) return EXPERIMENTALED25519;
+    return -1;
+  }
+
+  static string algorithm2name(uint8_t algo) {
+    switch(algo) {
+      case 0:
+      case 4:
+      case 9:
+      case 11:
+        return "Reserved";
+      case RSAMD5:
+        return "RSAMD5";
+      case DH:
+        return "DH";
+      case DSA:
+        return "DSA";
+      case RSASHA1:
+        return "RSASHA1";
+      case DSANSEC3SHA1:
+        return "DSA-NSEC3-SHA1";
+      case RSASHA1NSEC3SHA1:
+        return "RSASHA1-NSEC3-SHA1";
+      case RSASHA256:
+        return "RSASHA256";
+      case RSASHA512:
+        return "RSASHA512";
+      case ECCGOST:
+        return "ECC-GOST";
+      case ECDSA256:
+        return "ECDSAP256SHA256";
+      case ECDSA384:
+        return "ECDSAP384SHA384";
+      case EXPERIMENTALED25519:
+        return "ED25519SHA512";
+      case 252:
+        return "INDIRECT";
+      case 253:
+        return "PRIVATEDNS";
+      case 254:
+        return "PRIVATEOID";
+      default:
+        return "Unallocated/Reserved";
+    }
+  }
+
 private:
   UeberBackend* d_keymetadb;
   bool d_ourDB;
@@ -70,11 +158,11 @@ public:
       delete d_keymetadb;
   }
   bool isSecuredZone(const DNSName& zone);
-  static uint64_t dbdnssecCacheSizes(const std::string& str);  
+  static uint64_t dbdnssecCacheSizes(const std::string& str);
   keyset_t getEntryPoints(const DNSName& zname);
-  keyset_t getKeys(const DNSName& zone, boost::tribool allOrKeyOrZone = boost::indeterminate, bool useCache = true);
+  keyset_t getKeys(const DNSName& zone, bool useCache = true);
   DNSSECPrivateKey getKeyById(const DNSName& zone, unsigned int id);
-  bool addKey(const DNSName& zname, bool keyOrZone, int algorithm=5, int bits=0, bool active=true);
+  bool addKey(const DNSName& zname, bool setSEPBit, int algorithm, int bits=0, bool active=true);
   bool addKey(const DNSName& zname, const DNSSECPrivateKey& dpk, bool active=true);
   bool removeKey(const DNSName& zname, unsigned int id);
   bool activateKey(const DNSName& zname, unsigned int id);
@@ -179,4 +267,3 @@ bool editSOARecord(DNSResourceRecord& rr, const string& kind, const DNSName& qna
 // for SOA-EDIT-DNSUPDATE/API
 uint32_t calculateIncreaseSOA(SOAData sd, const string& increaseKind, const string& editKind);
 bool increaseSOARecord(DNSResourceRecord& rr, const string& increaseKind, const string& editKind);
-#endif
index 9b2e1f096b7cc7b8f790e40460945358a66f2d11..e315bbe98d27dca85da55dbadd68704512a668af 100644 (file)
@@ -50,41 +50,19 @@ int getRRSIGsForRRSET(DNSSECKeeper& dk, const DNSName& signer, const DNSName sig
   rrc.d_sigexpire=startOfWeek + 14*86400;
   rrc.d_signer = signer;
   rrc.d_tag = 0;
-  
-  // we sign the RRSET in toSign + the rrc w/o hash
-  
-  DNSSECKeeper::keyset_t keys = dk.getKeys(signer); // we don't want the . for the root!
-  set<int> algoHasKSK, algoHasZSK;
-  vector<DNSSECPrivateKey> signingKeys;
-
-  for(DNSSECKeeper::keyset_t::value_type& keymeta :  keys) {
-    if(keymeta.second.active) {
-      if(keymeta.second.keyOrZone)
-        algoHasKSK.insert(keymeta.first.d_algorithm);
-      else
-        algoHasZSK.insert(keymeta.first.d_algorithm);
-    }
-  }
 
-  for(DNSSECKeeper::keyset_t::value_type& keymeta :  keys) {
+  DNSSECKeeper::keyset_t keys = dk.getKeys(signer);
+
+  for(DNSSECKeeper::keyset_t::value_type& keymeta : keys) {
     if(!keymeta.second.active)
       continue;
 
-    if(signQType == QType::DNSKEY) {
-      // skip ZSK, if this algorithm has a KSK
-      if(!keymeta.second.keyOrZone && algoHasKSK.count(keymeta.first.d_algorithm))
-        continue;
-    } else {
-      // skip KSK, if this algorithm has a ZSK
-      if(keymeta.second.keyOrZone && algoHasZSK.count(keymeta.first.d_algorithm))
-        continue;
+    if((signQType == QType::DNSKEY && keymeta.second.keyType == DNSSECKeeper::ZSK) ||
+       (signQType != QType::DNSKEY && keymeta.second.keyType == DNSSECKeeper::KSK)) {
+      continue;
     }
 
-    signingKeys.push_back(keymeta.first);
-  }
-
-  for(DNSSECPrivateKey& dpk :  signingKeys) {
-    fillOutRRSIG(dpk, signQName, rrc, toSign);
+    fillOutRRSIG(keymeta.first, signQName, rrc, toSign);
     rrcs.push_back(rrc);
   }
   return 0;
index 614f6cd0cd25235e70722f228981dbf466b5cd4f..b1aeb6e0fa1e082a6bbc2df5de2f970bfe8c8667 100644 (file)
@@ -56,67 +56,6 @@ string humanTime(time_t t)
   return ret;
 }
 
-static void algorithm2name(uint8_t algo, string &name) {
-        switch(algo) {
-        case 0:
-           name = "Reserved"; return;
-        case 1:
-           name = "RSAMD5"; return;
-        case 2:
-           name = "DH"; return;
-        case 3:
-           name = "DSA"; return;
-        case 4:
-           name = "ECC"; return;
-        case 5:
-           name = "RSASHA1"; return;
-        case 6:
-           name = "DSA-NSEC3-SHA1"; return;
-        case 7:
-           name = "RSASHA1-NSEC3-SHA1"; return;
-        case 8:
-           name = "RSASHA256"; return;
-        case 9:
-           name = "Reserved"; return;
-        case 10:
-           name = "RSASHA512"; return;
-        case 11:
-           name = "Reserved"; return;
-        case 12:
-           name = "ECC-GOST"; return;
-        case 13:
-           name = "ECDSAP256SHA256"; return;
-        case 14:
-           name = "ECDSAP384SHA384"; return;
-        case 250:
-           name = "ED25519SHA512"; return;
-        case 252:
-           name = "INDIRECT"; return;
-        case 253:
-           name = "PRIVATEDNS"; return;
-        case 254:
-           name = "PRIVATEOID"; return;
-        default:
-           name = "Unallocated/Reserved"; return;
-        }
-};
-
-static int shorthand2algorithm(const string &algorithm)
-{
-  if (!algorithm.compare("rsamd5")) return 1;
-  if (!algorithm.compare("dh")) return 2;
-  if (!algorithm.compare("dsa")) return 3;
-  if (!algorithm.compare("ecc")) return 4;
-  if (!algorithm.compare("rsasha1")) return 5;
-  if (!algorithm.compare("rsasha256")) return 8;
-  if (!algorithm.compare("rsasha512")) return 10;
-  if (!algorithm.compare("gost")) return 12;
-  if (!algorithm.compare("ecdsa256")) return 13;
-  if (!algorithm.compare("ecdsa384")) return 14;
-  if (!algorithm.compare("experimental-ed25519")) return 250;
-  return -1;
-}
-
 void loadMainConfig(const std::string& configdir)
 {
   ::arg().set("config-dir","Location of configuration directory (pdns.conf)")=configdir;
@@ -797,7 +736,7 @@ void listKey(DomainInfo const &di, DNSSECKeeper& dk, bool printHeader = true) {
     else
       cout<<string(30 - di.zone.toStringNoDot().length(), ' ');
 
-    cout<<(key.second.keyOrZone ? "KSK" : "ZSK")<<"     ";
+    cout<<DNSSECKeeper::keyTypeToString(key.second.keyType)<<"     ";
 
     spacelen = (std::to_string(key.first.getKey()->getBits()).length() >= 8) ? 1 : 8 - std::to_string(key.first.getKey()->getBits()).length();
     if (key.first.getKey()->getBits() < 1) {
@@ -807,8 +746,7 @@ void listKey(DomainInfo const &di, DNSSECKeeper& dk, bool printHeader = true) {
       cout<<key.first.getKey()->getBits()<<string(spacelen, ' ');
     }
 
-    string algname;
-    algorithm2name(key.first.d_algorithm, algname);
+    string algname = DNSSECKeeper::algorithm2name(key.first.d_algorithm);
     spacelen = (algname.length() >= 13) ? 1 : 13 - algname.length();
     cout<<algname<<string(spacelen, ' ');
 
@@ -1140,11 +1078,6 @@ bool showZone(DNSSECKeeper& dk, const DNSName& zone)
   bool narrow;
   bool haveNSEC3=dk.getNSEC3PARAM(zone, &ns3pr, &narrow);
   
-  DNSSECKeeper::keyset_t entryPointKeys=dk.getEntryPoints(zone);
-  set<uint32_t> entryPointIds;
-  for (auto const& value : entryPointKeys)
-    entryPointIds.insert(value.second.id);
-
   DNSSECKeeper::keyset_t keyset=dk.getKeys(zone);
   if (B.getDomainMetadata(zone, "TSIG-ALLOW-AXFR", meta) && meta.size() > 0) {
      cerr << "Zone has following allowed TSIG key(s): " << boost::join(meta, ",") << endl;
@@ -1181,8 +1114,7 @@ bool showZone(DNSSECKeeper& dk, const DNSName& zone)
     reverse(keys.begin(),keys.end());
     bool shown=false;
     for(const auto& key : keys) {
-      string algname;
-      algorithm2name(key.d_algorithm,algname);
+      string algname = DNSSECKeeper::algorithm2name(key.d_algorithm);
       int bits;
       if (key.d_key[0] == 0)
         bits = *(uint16_t*)(key.d_key.c_str()+1);
@@ -1218,17 +1150,18 @@ bool showZone(DNSSECKeeper& dk, const DNSName& zone)
   
     cout << "keys: "<<endl;
     for(DNSSECKeeper::keyset_t::value_type value :  keyset) {
-      string algname;
-      algorithm2name(value.first.d_algorithm, algname);
+      string algname = DNSSECKeeper::algorithm2name(value.first.d_algorithm);
+      cout<<"ID = "<<value.second.id<<" ("<<DNSSECKeeper::keyTypeToString(value.second.keyType)<<")";
       if (value.first.getKey()->getBits() < 1) {
-        cout<<"ID = "<<value.second.id<<" ("<<(value.second.keyOrZone ? "KSK" : "ZSK")<<") <key missing or defunct>" <<endl;
+        cout<<" <key missing or defunct>" <<endl;
         continue;
       }
-      cout<<"ID = "<<value.second.id<<" ("<<(value.second.keyOrZone ? "KSK" : "ZSK")<<"), tag = "<<value.first.getDNSKEY().getTag();
+      cout<<", flags = "<<std::to_string(value.first.d_flags);
+      cout<<", tag = "<<value.first.getDNSKEY().getTag();
       cout<<", algo = "<<(int)value.first.d_algorithm<<", bits = "<<value.first.getKey()->getBits()<<"\t"<<((int)value.second.active == 1 ? "  A" : "Ina")<<"ctive ( " + algname + " ) "<<endl;
-      if(entryPointIds.count(value.second.id) > 0 || ::arg().mustDo("direct-dnskey"))
-        cout<<(value.second.keyOrZone ? "KSK" : "ZSK")<<" DNSKEY = "<<zone.toString()<<" IN DNSKEY "<< value.first.getDNSKEY().getZoneRepresentation() << " ; ( "  + algname + " )" << endl;
-      if(entryPointIds.count(value.second.id) > 0) {
+      if(value.second.keyType == DNSSECKeeper::KSK || value.second.keyType == DNSSECKeeper::CSK || ::arg().mustDo("direct-dnskey"))
+        cout<<DNSSECKeeper::keyTypeToString(value.second.keyType)<<" DNSKEY = "<<zone.toString()<<" IN DNSKEY "<< value.first.getDNSKEY().getZoneRepresentation() << " ; ( "  + algname + " )" << endl;
+      if(value.second.keyType == DNSSECKeeper::KSK || value.second.keyType == DNSSECKeeper::CSK) {
         cout<<"DS = "<<zone.toString()<<" IN DS "<<makeDSFromDNSKey(zone, value.first.getDNSKEY(), 1).getZoneRepresentation() << " ; ( SHA1 digest )" << endl;
         cout<<"DS = "<<zone.toString()<<" IN DS "<<makeDSFromDNSKey(zone, value.first.getDNSKEY(), 2).getZoneRepresentation() << " ; ( SHA256 digest )" << endl;
         try {
@@ -1300,18 +1233,14 @@ bool secureZone(DNSSECKeeper& dk, const DNSName& zone)
   else
     cout << "Securing zone with default key size" << endl;
 
-
-  DNSSECKeeper::keyset_t zskset=dk.getKeys(zone, false);
-
-  if(!zskset.empty())  {
-    cerr<<"There were ZSKs already for zone '"<<zone.toString()<<"', no need to add more"<<endl;
-    return false;
+  if (k_algos.empty()) { /* only a ZSK was requested by the defaults, set the SEP bit */
   }
 
+
   for(auto &k_algo: k_algos) {
-    cout << "Adding KSK with algorithm " << k_algo << endl;
+    cout << "Adding "<<(z_algos.empty()? "CSK" : "KSK")<<" with algorithm " << k_algo << endl;
 
-    int algo = shorthand2algorithm(k_algo);
+    int algo = DNSSECKeeper::shorthand2algorithm(k_algo);
 
     if(!dk.addKey(zone, true, algo, k_size, true)) {
       cerr<<"No backend was able to secure '"<<zone.toString()<<"', most likely because no DNSSEC"<<endl;
@@ -1324,11 +1253,11 @@ bool secureZone(DNSSECKeeper& dk, const DNSName& zone)
 
   for(auto &z_algo :  z_algos)
   {
-    cout << "Adding ZSK with algorithm " << z_algo << endl;
+    cout << "Adding "<<(k_algos.empty()? "CSK" : "ZSK")<<" with algorithm " << z_algo << endl;
 
-    int algo = shorthand2algorithm(z_algo);
+    int algo = DNSSECKeeper::shorthand2algorithm(z_algo);
 
-    if(!dk.addKey(zone, false, algo, z_size, true)) {
+    if(!dk.addKey(zone, k_algos.empty(), algo, z_size, true)) {
       cerr<<"No backend was able to secure '"<<zone.toString()<<"', most likely because no DNSSEC"<<endl;
       cerr<<"capable backends are loaded, or because the backends have DNSSEC disabled."<<endl;
       cerr<<"For the Generic SQL backends, set the 'gsqlite3-dnssec', 'gmysql-dnssec' or"<<endl;
@@ -1767,7 +1696,7 @@ seedRandom(::arg()["entropy-source"]);
         keyOrZone = false;
       else if(pdns_iequals(cmds[n], "ksk"))
         keyOrZone = true;
-      else if((tmp_algo = shorthand2algorithm(cmds[n]))>0) {
+      else if((tmp_algo = DNSSECKeeper::shorthand2algorithm(cmds[n]))>0) {
         algorithm = tmp_algo;
       } else if(pdns_iequals(cmds[n], "active")) {
         active=true;
@@ -2171,7 +2100,7 @@ seedRandom(::arg()["entropy-source"]);
         keyOrZone = false;
       else if(pdns_iequals(cmds[n], "ksk"))
         keyOrZone = true;
-      else if((tmp_algo = shorthand2algorithm(cmds[n]))>0) {
+      else if((tmp_algo = DNSSECKeeper::shorthand2algorithm(cmds[n]))>0) {
         algorithm = tmp_algo;
       } else if(pdns_stou(cmds[n]))
         bits = pdns_stou(cmds[n]);
@@ -2429,7 +2358,7 @@ seedRandom(::arg()["entropy-source"]);
         return 1;
       }
 
-      int algorithm = shorthand2algorithm(cmds[3]);
+      int algorithm = DNSSECKeeper::shorthand2algorithm(cmds[3]);
       if (algorithm<0) {
         cerr << "Unable to use unknown algorithm '" << cmds[3] << "'" << std::endl;
         return 1;
index 83501ac672b498fda4be56a5d9c6d693755cf7b1..88904bcc3012a6810d213b4504e94ac6af468428 100644 (file)
@@ -493,7 +493,7 @@ static void apiZoneCryptokeys(HttpRequest* req, HttpResponse* resp) {
   if(!B.getDomainInfo(zonename, di))
     throw ApiException("Could not find domain '"+zonename.toString()+"'");
 
-  DNSSECKeeper::keyset_t keyset=dk.getKeys(zonename, boost::indeterminate, false);
+  DNSSECKeeper::keyset_t keyset=dk.getKeys(zonename, false);
 
   if (keyset.empty())
     throw ApiException("No keys for zone '"+zonename.toString()+"'");
@@ -507,11 +507,19 @@ static void apiZoneCryptokeys(HttpRequest* req, HttpResponse* resp) {
         continue;
     }
 
+    string keyType;
+    switch(value.second.keyType){
+      case DNSSECKeeper::KSK: keyType="ksk"; break;
+      case DNSSECKeeper::ZSK: keyType="zsk"; break;
+      case DNSSECKeeper::CSK: keyType="csk"; break;
+    }
+
     Json::object key {
       { "type", "Cryptokey" },
       { "id", (int)value.second.id },
       { "active", value.second.active },
-      { "keytype", value.second.keyOrZone ? "ksk" : "zsk" },
+      { "keytype", keyType },
+      { "flags", (uint16_t)value.first.d_flags },
       { "dnskey", value.first.getDNSKEY().getZoneRepresentation() }
     };
 
@@ -520,7 +528,7 @@ static void apiZoneCryptokeys(HttpRequest* req, HttpResponse* resp) {
       key["content"] = dpk.getKey()->convertToISC();
     }
 
-    if (value.second.keyOrZone) {
+    if (value.second.keyType == DNSSECKeeper::KSK || value.second.keyType == DNSSECKeeper::CSK) {
       Json::array dses;
       for(const int keyid : { 1, 2, 3, 4 })
       try {
index a1018334d29ff8b23da61c586100ad58316c141f..02c6c146082b7ee4671ec1e79a9541022f61a6a7 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 
 if [ ! -d .venv ]; then
-       virtualenv .venv
+       virtualenv -p python2 .venv
 fi
 . .venv/bin/activate
 python -V
index 4d23ce333f1c88be37b8a1d73df6f8b0af1388c4..9415ac136c0274369741bbda88cd79f5e9fed5fa 100644 (file)
@@ -1300,10 +1300,12 @@ class AuthZoneKeys(ApiTestCase, AuthZonesHelperMixin):
 
         key0 = deepcopy(keys[0])
         del key0['dnskey']
+        del key0['ds']
         expected = {
             u'active': True,
             u'type': u'Cryptokey',
-            u'keytype': u'zsk',
+            u'keytype': u'csk',
+            u'flags': 257,
             u'id': 1}
         self.assertEquals(key0, expected)
 
index 1cb5a783d1637eed9169a9730d84d83d3e843d95..e001f9b04f0b492e21659581021953d248d7e6e1 100755 (executable)
@@ -6,7 +6,7 @@ for zone in $(grep 'zone ' named.conf  | cut -f2 -d\")
 do
        if [ "${zone: 0:16}" != "secure-delegated" ]
        then
-               drill -p $port -o rd -D dnskey $zone @$nameserver | grep $'DNSKEY\t256' | grep -v 'RRSIG' | grep -v '^;' | grep -v AwEAAarTiHhPgvD28WCN8UBXcEcf8f >> trustedkeys
+               drill -p $port -o rd -D dnskey $zone @$nameserver | grep $'DNSKEY\t257' | grep -v 'RRSIG' | grep -v '^;' | grep -v AwEAAarTiHhPgvD28WCN8UBXcEcf8f >> trustedkeys
        fi
        echo "stub-zone:" >> unbound-host.conf
        echo "  name: $zone" >> unbound-host.conf
@@ -21,4 +21,4 @@ echo '  trust-anchor-file: "trustedkeys"' >> unbound-host.conf
 if [ -e trustedkeys ]
 then
   cat trustedkeys | grep -c '.' # because wc -l is not portable enough!
-fi
\ No newline at end of file
+fi
index 1ca5f02a991b17ae01369c56fb5df9f7e0a4205d..f580f6c6e7d771c4962e7c38532982485759c80a 100644 (file)
@@ -10,7 +10,7 @@ dnssec-parent.com.    3600    IN      RRSIG   NS 13 2 3600 [expiry] [inception] [keytag] dnss
 dnssec-parent.com.     3600    IN      RRSIG   SOA 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
 dnssec-parent.com.     3600    IN      SOA     ns1.dnssec-parent.com. ahu.example.com. 2005092501 28800 7200 604800 86400
 dnssec-parent.com.     3600    IN      SOA     ns1.dnssec-parent.com. ahu.example.com. 2005092501 28800 7200 604800 86400
-dnssec-parent.com.     86400   IN      DNSKEY  256 3 13 ...
+dnssec-parent.com.     86400   IN      DNSKEY  257 3 13 ...
 dnssec-parent.com.     86400   IN      NSEC    insecure-delegated.ent.ent.auth-ent.dnssec-parent.com. A NS SOA RRSIG NSEC DNSKEY
 dnssec-parent.com.     86400   IN      RRSIG   DNSKEY 13 2 86400 [expiry] [inception] [keytag] dnssec-parent.com. ...
 dnssec-parent.com.     86400   IN      RRSIG   NSEC 13 2 86400 [expiry] [inception] [keytag] dnssec-parent.com. ...
index 7d0e03d6477a623284ddae04b336e18ef28468cf..ad2d86817327b24a06568cf56237429a5100da02 100644 (file)
@@ -12,7 +12,7 @@ dnssec-parent.com.    3600    IN      RRSIG   NS 13 2 3600 [expiry] [inception] [keytag] dnss
 dnssec-parent.com.     3600    IN      RRSIG   SOA 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
 dnssec-parent.com.     3600    IN      SOA     ns1.dnssec-parent.com. ahu.example.com. 2005092501 28800 7200 604800 86400
 dnssec-parent.com.     3600    IN      SOA     ns1.dnssec-parent.com. ahu.example.com. 2005092501 28800 7200 604800 86400
-dnssec-parent.com.     86400   IN      DNSKEY  256 3 13 ...
+dnssec-parent.com.     86400   IN      DNSKEY  257 3 13 ...
 dnssec-parent.com.     86400   IN      NSEC3   1 0 1 abcd [next owner] A NS SOA RRSIG DNSKEY NSEC3PARAM
 dnssec-parent.com.     86400   IN      NSEC3PARAM      1 0 1 abcd
 dnssec-parent.com.     86400   IN      RRSIG   DNSKEY 13 2 86400 [expiry] [inception] [keytag] dnssec-parent.com. ...
index 485fd2237fa82e940cec0c9abd1a837c2b757b3c..3e5178ff48c753f4bbd5766b722ccbf9d7ba1f3e 100644 (file)
@@ -10,7 +10,7 @@ dnssec-parent.com.    3600    IN      RRSIG   NS 13 2 3600 [expiry] [inception] [keytag] dnss
 dnssec-parent.com.     3600    IN      RRSIG   SOA 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
 dnssec-parent.com.     3600    IN      SOA     ns1.dnssec-parent.com. ahu.example.com. 2005092501 28800 7200 604800 86400
 dnssec-parent.com.     3600    IN      SOA     ns1.dnssec-parent.com. ahu.example.com. 2005092501 28800 7200 604800 86400
-dnssec-parent.com.     86400   IN      DNSKEY  256 3 13 ...
+dnssec-parent.com.     86400   IN      DNSKEY  257 3 13 ...
 dnssec-parent.com.     86400   IN      NSEC3   1 1 1 abcd [next owner] A NS SOA RRSIG DNSKEY NSEC3PARAM
 dnssec-parent.com.     86400   IN      NSEC3PARAM      1 0 1 abcd
 dnssec-parent.com.     86400   IN      RRSIG   DNSKEY 13 2 86400 [expiry] [inception] [keytag] dnssec-parent.com. ...
index 990c7cd43726ee945ec464d68e4901948113b964..6fa731dfed137ba14d4ae03e84cbed90f6bdad6d 100644 (file)
@@ -1,4 +1,4 @@
-0      example.com.    IN      DNSKEY  86400   256 3 13 ...
+0      example.com.    IN      DNSKEY  86400   257 3 13 ...
 0      example.com.    IN      RRSIG   86400   DNSKEY 13 2 86400 [expiry] [inception] [keytag] example.com. ...
 2      .       IN      OPT     32768   
 Rcode: 0 (No Error), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0