]> granicus.if.org Git - pdns/commitdiff
Add CDNSKEY support
authorPieter Lexis <pieter.lexis@powerdns.com>
Tue, 21 Jul 2015 13:37:11 +0000 (15:37 +0200)
committerPieter Lexis <pieter.lexis@powerdns.com>
Fri, 2 Oct 2015 08:57:21 +0000 (10:57 +0200)
This commit adds support to the packethandler, the dnssec infrastructure
and pdnssec for the CDNSKEY record.

Users can now use the domain metadata "PUBLISH_CDNSKEY" to reply to
CDNSKEY queries with their active DNSKEYs that are KSKs.

pdns/dbdnsseckeeper.cc
pdns/dnsseckeeper.hh
pdns/packethandler.cc
pdns/packethandler.hh
pdns/pdnssec.cc

index 591208575040da4069d096b0175244d5f79cb067..df9ad06e2b8eb7b60d676fb77a3ddd2078c1b3d0 100644 (file)
@@ -295,6 +295,31 @@ bool DNSSECKeeper::unsetPresigned(const DNSName& zname)
   return d_keymetadb->setDomainMetadata(zname, "PRESIGNED", vector<string>());
 }
 
+/**
+ * Add domainmetadata to allow publishing CDNSKEY records.for zone zname
+ *
+ * @param zname        DNSName of the zone
+ * @return             true if the data was inserted, false otherwise
+ */
+bool DNSSECKeeper::setPublishCDNSKEY(const DNSName& zname)
+{
+  clearCaches(zname);
+  vector<string> meta;
+  meta.push_back("1");
+  return d_keymetadb->setDomainMetadata(zname, "PUBLISH_CDNSKEY", meta);
+}
+
+/**
+ * Remove domainmetadata to stop publishing CDNSKEY records for zone zname
+ *
+ * @param zname        DNSName of the zone
+ * @return             true if the operation was successful, false otherwise
+ */
+bool DNSSECKeeper::unsetPublishCDNSKEY(const DNSName& zname)
+{
+  clearCaches(zname);
+  return d_keymetadb->setDomainMetadata(zname, "PUBLISH_CDNSKEY", vector<string>());
+}
 
 DNSSECKeeper::keyset_t DNSSECKeeper::getKeys(const DNSName& zone, boost::tribool allOrKeyOrZone, bool useCache)
 {
index 3643c60d23d8d99f081524f9b145ea149e2d2406..f2c0f87b6053e10468ce78867909bb931e58faa0 100644 (file)
@@ -90,6 +90,8 @@ public:
   bool isPresigned(const DNSName& zname);
   bool setPresigned(const DNSName& zname);
   bool unsetPresigned(const DNSName& zname);
+  bool setPublishCDNSKEY(const DNSName& zname);
+  bool unsetPublishCDNSKEY(const DNSName& zname);
 
   bool TSIGGrantsAccess(const DNSName& zone, const DNSName& keyname);
   bool getTSIGForAccess(const DNSName& zone, const string& master, DNSName* keyname);
index b84c48ae9b43529f4b64097a5366bfdba7d61e86..ebac6f702aafb81e09517d835bb15599f2fc20b1 100644 (file)
@@ -131,16 +131,35 @@ void PacketHandler::addRootReferral(DNSPacket* r)
   }
 }
 
-/** This adds DNSKEY records. Returns true if one was added */
-bool PacketHandler::addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd)
+/**
+ * This adds DNSKEY records to the answer packet. Returns true if one was added.
+ * The optional doCDNSKEY parameter signifies that we need to add a CDNSKEY (RFC 7344)
+ * instead of DNSKEY.
+ *
+ * @param p          Pointer to the DNSPacket containing the original question
+ * @param r          Pointer to the DNSPacket where the records should be inserted into
+ * @param sd         SOAData of the zone for which DNSKEY records sets should be added
+ * @param doCDNSKEY  When set to true, add CDNSKEYs instead of DNSKEYs
+ * @return           bool that shows if any records were added
+**/
+bool PacketHandler::addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd, bool doCDNSKEY=false)
 {
+  string publishCDNSKEY;
+  d_dk.getFromMeta(p->qdomain, "PUBLISH_CDNSKEY", publishCDNSKEY);
+  if (doCDNSKEY && publishCDNSKEY != "1")
+    return false;
+
   DNSResourceRecord rr;
   bool haveOne=false;
   DNSSECPrivateKey dpk;
 
   DNSSECKeeper::keyset_t keyset = d_dk.getKeys(p->qdomain);
   for(const auto& value: keyset) {
-    rr.qtype=QType::DNSKEY;
+    if (doCDNSKEY && !value.second.keyOrZone) {
+      // Don't send out CDNSKEY records for ZSKs
+      continue;
+    }
+    rr.qtype=doCDNSKEY ? QType::CDNSKEY : QType::DNSKEY;
     rr.ttl=sd.default_ttl;
     rr.qname=p->qdomain;
     rr.content=value.first.getDNSKEY().getZoneRepresentation();
@@ -150,7 +169,11 @@ bool PacketHandler::addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd)
   }
 
   if(::arg().mustDo("direct-dnskey")) {
-    B.lookup(QType(QType::DNSKEY), p->qdomain, p, sd.domain_id);
+    if(doCDNSKEY)
+      B.lookup(QType(QType::CDNSKEY), p->qdomain, p, sd.domain_id);
+    else
+      B.lookup(QType(QType::DNSKEY), p->qdomain, p, sd.domain_id);
+
     while(B.get(rr)) {
       rr.ttl=sd.default_ttl;
       r->addRecord(rr);
@@ -392,6 +415,10 @@ void PacketHandler::emitNSEC(DNSPacket *r, const SOAData& sd, const DNSName& nam
   if(sd.qname == name) {
     nrc.d_set.insert(QType::SOA); // 1dfd8ad SOA can live outside the records table
     nrc.d_set.insert(QType::DNSKEY);
+    string publishCDNSKEY;
+    d_dk.getFromMeta(name, "PUBLISH_CDNSKEY", publishCDNSKEY);
+    if (publishCDNSKEY == "1")
+      nrc.d_set.insert(QType::CDNSKEY);
   }
 
   DNSResourceRecord rr;
@@ -428,6 +455,10 @@ void PacketHandler::emitNSEC3(DNSPacket *r, const SOAData& sd, const NSEC3PARAMR
       n3rc.d_set.insert(QType::SOA); // 1dfd8ad SOA can live outside the records table
       n3rc.d_set.insert(QType::NSEC3PARAM);
       n3rc.d_set.insert(QType::DNSKEY);
+      string publishCDNSKEY;
+      d_dk.getFromMeta(name, "PUBLISH_CDNSKEY", publishCDNSKEY);
+      if (publishCDNSKEY == "1")
+        n3rc.d_set.insert(QType::CDNSKEY);
     }
 
     B.lookup(QType(QType::ANY), name, NULL, sd.domain_id);
@@ -953,6 +984,7 @@ void PacketHandler::completeANYRecords(DNSPacket *p, DNSPacket*r, SOAData& sd, c
   addNSECX(p, r, target, "", sd.qname, 5);
   if(pdns_iequals(sd.qname, p->qdomain)) {
     addDNSKEY(p, r, sd);
+    addDNSKEY(p, r, sd, true);
     addNSEC3PARAM(p, r, sd);
   }
 }
@@ -1197,6 +1229,11 @@ DNSPacket *PacketHandler::questionOrRecurse(DNSPacket *p, bool *shouldRecurse)
         if(addDNSKEY(p, r, sd))
           goto sendit;
       }
+      else if(p->qtype.getCode() == QType::CDNSKEY)
+      {
+        if(addDNSKEY(p,r, sd, true))
+          goto sendit;
+      }
       else if(p->qtype.getCode() == QType::NSEC3PARAM)
       {
         if(addNSEC3PARAM(p,r, sd))
index 2c52f781bbac46b48acb3ff8e2ddf8cefa0c0b5c..7eca58b2dabb34515314d068089383f49c4fee2b 100644 (file)
@@ -71,7 +71,7 @@ private:
   int processNotify(DNSPacket *);
   void addRootReferral(DNSPacket *r);
   int doChaosRequest(DNSPacket *p, DNSPacket *r, DNSName &target);
-  bool addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd);
+  bool addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd, bool doCDNSKEY);
   bool addNSEC3PARAM(DNSPacket *p, DNSPacket *r, const SOAData& sd);
   int doAdditionalProcessingAndDropAA(DNSPacket *p, DNSPacket *r, const SOAData& sd, bool retargeted);
   void addNSECX(DNSPacket *p, DNSPacket* r, const DNSName &target, const DNSName &wildcard, const DNSName &auth, int mode);
index 758ef2d28a3d8fb17b1dac362fb7fcd97e6c984d..87422a2a7fb2b096d19489f612b54dc5bf8493b2 100644 (file)
@@ -1363,11 +1363,13 @@ try
     cerr<<"secure-zone ZONE [ZONE ..]         Add KSK and two ZSKs"<<endl;
     cerr<<"set-nsec3 ZONE ['params' [narrow]] Enable NSEC3 with PARAMs. Optionally narrow"<<endl;
     cerr<<"set-presigned ZONE                 Use presigned RRSIGs from storage"<<endl;
+    cerr<<"set-publish-cdnskey ZONE           Enable sending CDNSKEY responses for ZONE"<<endl;
     cerr<<"set-meta ZONE KIND [value value ..]"<<endl;
     cerr<<"                                   Set zone metadata, optionally providing a value. Empty clears meta."<<endl;
     cerr<<"show-zone ZONE                     Show DNSSEC (public) key details about a zone"<<endl;
     cerr<<"unset-nsec3 ZONE                   Switch back to NSEC"<<endl;
     cerr<<"unset-presigned ZONE               No longer use presigned RRSIGs"<<endl;
+    cerr<<"unset-publish-cdnskey ZONE         Disable sending CDNSKEY responses for ZONE"<<endl;
     cerr<<"test-schema ZONE                   Test DB schema - will create ZONE"<<endl;
     cerr<<desc<<endl;
     return 0;
@@ -1752,6 +1754,17 @@ try
     }
     return 0;
   }
+  else if(cmds[0]=="set-publish-cdnskey") {
+    if(cmds.size() < 2) {
+      cerr<<"Syntax: pdnssec set-publish-cdnskey ZONE"<<endl;
+      return 0;
+    }
+    if (! dk.setPublishCDNSKEY(cmds[1])) {
+      cerr << "Could not set publishing for CDNSKEY records for "<< cmds[1]<<endl;
+      return 1;
+    }
+    return 0;
+  }
   else if(cmds[0]=="unset-presigned") {
     if(cmds.size() < 2) {
       cerr<<"Syntax: pdnssec unset-presigned ZONE"<<endl;
@@ -1763,6 +1776,17 @@ try
     }
     return 0;
   }
+  else if(cmds[0]=="unset-publish-cdnskey") {
+    if(cmds.size() < 2) {
+      cerr<<"Syntax: pdnssec unset-publish-cdnskey ZONE"<<endl;
+      return 0;
+    }
+    if (! dk.unsetPublishCDNSKEY(cmds[1])) {
+      cerr << "Could not unset publishing for CDNSKEY records for "<< cmds[1]<<endl;
+      return 1;
+    }
+    return 0;
+  }
   else if(cmds[0]=="hash-zone-record") {
     if(cmds.size() < 3) {
       cerr<<"Syntax: pdnssec hash-zone-record ZONE RNAME"<<endl;