]> granicus.if.org Git - pdns/commitdiff
Add CDS publishing support
authorPieter Lexis <pieter.lexis@powerdns.com>
Tue, 21 Jul 2015 13:38:00 +0000 (15:38 +0200)
committerPieter Lexis <pieter.lexis@powerdns.com>
Fri, 2 Oct 2015 08:57:21 +0000 (10:57 +0200)
pdns/dbdnsseckeeper.cc
pdns/dnsseckeeper.hh
pdns/packethandler.cc
pdns/packethandler.hh
pdns/pdnssec.cc

index df9ad06e2b8eb7b60d676fb77a3ddd2078c1b3d0..1f69673a5ee89bbea73fd66b0492514d39cfe50c 100644 (file)
@@ -295,6 +295,35 @@ bool DNSSECKeeper::unsetPresigned(const DNSName& zname)
   return d_keymetadb->setDomainMetadata(zname, "PRESIGNED", vector<string>());
 }
 
+/**
+ * Add domainmetadata to allow publishing CDS records for zone zname
+ *
+ * @param zname        DNSName of the zone
+ * @param digestAlgos  string with comma-separated numbers that describe the
+ *                     used digest algorithms. This is copied to the database
+ *                     verbatim
+ * @return             true if the data was inserted, false otherwise
+ */
+bool DNSSECKeeper::setPublishCDS(const DNSName& zname, const string& digestAlgos)
+{
+  clearCaches(zname);
+  vector<string> meta;
+  meta.push_back(digestAlgos);
+  return d_keymetadb->setDomainMetadata(zname, "PUBLISH_CDS", meta);
+}
+
+/**
+ * Remove domainmetadata to stop publishing CDS records for zone zname
+ *
+ * @param zname        DNSName of the zone
+ * @return             true if the operation was successful, false otherwise
+ */
+bool DNSSECKeeper::unsetPublishCDS(const DNSName& zname)
+{
+  clearCaches(zname);
+  return d_keymetadb->setDomainMetadata(zname, "PUBLISH_CDS", vector<string>());
+}
+
 /**
  * Add domainmetadata to allow publishing CDNSKEY records.for zone zname
  *
index f2c0f87b6053e10468ce78867909bb931e58faa0..652865e8740f8f33d0af959c971b6584d94447f6 100644 (file)
@@ -92,6 +92,8 @@ public:
   bool unsetPresigned(const DNSName& zname);
   bool setPublishCDNSKEY(const DNSName& zname);
   bool unsetPublishCDNSKEY(const DNSName& zname);
+  bool setPublishCDS(const DNSName& zname, const string& digestAlgos);
+  bool unsetPublishCDS(const DNSName& zname);
 
   bool TSIGGrantsAccess(const DNSName& zone, const DNSName& keyname);
   bool getTSIGForAccess(const DNSName& zone, const string& master, DNSName* keyname);
index ebac6f702aafb81e09517d835bb15599f2fc20b1..dbb62a15b09887a7f454fa6e5f4febff5add0775 100644 (file)
@@ -184,6 +184,60 @@ bool PacketHandler::addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd, boo
   return haveOne;
 }
 
+/**
+ * This adds CDS records to the answer packet r.
+ *
+ * @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 CDS records sets should be added,
+ *            used to determine record TTL.
+ * @return    bool that shows if any records were added.
+**/
+bool PacketHandler::addCDS(DNSPacket *p, DNSPacket *r, const SOAData& sd)
+{
+  string publishCDS;
+  d_dk.getFromMeta(p->qdomain, "PUBLISH_CDS", publishCDS);
+  if (publishCDS.empty())
+    return false;
+
+  vector<string> digestAlgos;
+  stringtok(digestAlgos, publishCDS, ", ");
+
+  DNSResourceRecord rr;
+  rr.qtype=QType::CDS;
+  rr.ttl=sd.default_ttl;
+  rr.qname=p->qdomain;
+  rr.auth=true;
+
+  bool haveOne=false;
+  DNSSECPrivateKey dpk;
+
+  DNSSECKeeper::keyset_t keyset = d_dk.getKeys(p->qdomain);
+
+  for(auto value : keyset) {
+    if (!value.second.keyOrZone) {
+      // Don't send out CDS records for ZSKs
+      continue;
+    }
+    for(auto digestAlgo : digestAlgos){
+      rr.content=makeDSFromDNSKey(p->qdomain, value.first.getDNSKEY(), lexical_cast<int>(digestAlgo)).getZoneRepresentation();
+      r->addRecord(rr);
+      haveOne=true;
+    }
+  }
+
+  if(::arg().mustDo("direct-dnskey")) {
+    B.lookup(QType(QType::CDS), p->qdomain, p, sd.domain_id);
+
+    while(B.get(rr)) {
+      rr.ttl=sd.default_ttl;
+      r->addRecord(rr);
+      haveOne=true;
+    }
+  }
+
+  return haveOne;
+}
 
 /** This adds NSEC3PARAM records. Returns true if one was added */
 bool PacketHandler::addNSEC3PARAM(DNSPacket *p, DNSPacket *r, const SOAData& sd)
@@ -419,6 +473,10 @@ void PacketHandler::emitNSEC(DNSPacket *r, const SOAData& sd, const DNSName& nam
     d_dk.getFromMeta(name, "PUBLISH_CDNSKEY", publishCDNSKEY);
     if (publishCDNSKEY == "1")
       nrc.d_set.insert(QType::CDNSKEY);
+    string publishCDS;
+    d_dk.getFromMeta(name, "PUBLISH_CDS", publishCDS);
+    if (! publishCDS.empty())
+      nrc.d_set.insert(QType::CDS);
   }
 
   DNSResourceRecord rr;
@@ -459,6 +517,10 @@ void PacketHandler::emitNSEC3(DNSPacket *r, const SOAData& sd, const NSEC3PARAMR
       d_dk.getFromMeta(name, "PUBLISH_CDNSKEY", publishCDNSKEY);
       if (publishCDNSKEY == "1")
         n3rc.d_set.insert(QType::CDNSKEY);
+      string publishCDS;
+      d_dk.getFromMeta(name, "PUBLISH_CDS", publishCDS);
+      if (! publishCDS.empty())
+        n3rc.d_set.insert(QType::CDS);
     }
 
     B.lookup(QType(QType::ANY), name, NULL, sd.domain_id);
@@ -985,6 +1047,7 @@ void PacketHandler::completeANYRecords(DNSPacket *p, DNSPacket*r, SOAData& sd, c
   if(pdns_iequals(sd.qname, p->qdomain)) {
     addDNSKEY(p, r, sd);
     addDNSKEY(p, r, sd, true);
+    addCDS(p, r, sd);
     addNSEC3PARAM(p, r, sd);
   }
 }
@@ -1234,6 +1297,11 @@ DNSPacket *PacketHandler::questionOrRecurse(DNSPacket *p, bool *shouldRecurse)
         if(addDNSKEY(p,r, sd, true))
           goto sendit;
       }
+      else if(p->qtype.getCode() == QType::CDS)
+      {
+        if(addCDS(p,r, sd))
+          goto sendit;
+      }
       else if(p->qtype.getCode() == QType::NSEC3PARAM)
       {
         if(addNSEC3PARAM(p,r, sd))
index 7eca58b2dabb34515314d068089383f49c4fee2b..550358465aecb3f2f6e0e6ece8ce89cfe774fd93 100644 (file)
@@ -72,6 +72,7 @@ private:
   void addRootReferral(DNSPacket *r);
   int doChaosRequest(DNSPacket *p, DNSPacket *r, DNSName &target);
   bool addDNSKEY(DNSPacket *p, DNSPacket *r, const SOAData& sd, bool doCDNSKEY);
+  bool addCDS(DNSPacket *p, DNSPacket *r, const SOAData& sd);
   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 87422a2a7fb2b096d19489f612b54dc5bf8493b2..70918c739cef6228f9839e4322f3f0f1fb56f34e 100644 (file)
@@ -1364,12 +1364,15 @@ try
     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-publish-cds ZONE [DIGESTALGOS] Enable sending CDS responses for ZONE, using DIGESTALGOS as signature algirithms"<<endl;
+    cerr<<"                                   DIGESTALGORITHMS should be a comma separated list of numbers, is is '1,2' by default"<<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<<"unset-publish-cds ZONE             Disable sending CDS responses for ZONE"<<endl;
     cerr<<"test-schema ZONE                   Test DB schema - will create ZONE"<<endl;
     cerr<<desc<<endl;
     return 0;
@@ -1765,6 +1768,22 @@ try
     }
     return 0;
   }
+  else if(cmds[0]=="set-publish-cds") {
+    if(cmds.size() < 2) {
+      cerr<<"Syntax: pdnssec set-publish-cds ZONE [DIGESTALGOS]"<<endl;
+      return 0;
+    }
+
+    // If DIGESTALGOS is unset
+    if(cmds.size() == 2)
+      cmds.push_back("1,2");
+
+    if (! dk.setPublishCDS(cmds[1], cmds[2])) {
+      cerr << "Could not set publishing for CDS 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;
@@ -1787,6 +1806,17 @@ try
     }
     return 0;
   }
+  else if(cmds[0]=="unset-publish-cds") {
+    if(cmds.size() < 2) {
+      cerr<<"Syntax: pdnssec unset-publish-cds ZONE"<<endl;
+      return 0;
+    }
+    if (! dk.unsetPublishCDS(cmds[1])) {
+      cerr << "Could not unset publishing for CDS 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;