]> granicus.if.org Git - pdns/commitdiff
rec: Add a `nsec3-max-iterations` setting, default to 2500
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 9 May 2017 15:21:21 +0000 (17:21 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 26 Jun 2017 10:24:08 +0000 (12:24 +0200)
docs/markdown/recursor/settings.md
pdns/pdns_recursor.cc
pdns/syncres.cc
pdns/validate.cc
pdns/validate.hh

index 3c9b8771df7e34b2308fe3ba038431e05a3c7392..49bd3bbb80fb63bcac8c8f0ab6f8dbd4fb647427 100644 (file)
@@ -721,6 +721,14 @@ to continue serving your customers. Can be set at runtime using
 
 Number of milliseconds to wait for a remote authoritative server to respond.
 
+## `nsec3-max-iterations`
+* Integer
+* Default: 2500
+* Available since: 4.1
+
+Maximum number of iterations allowed for an NSEC3 record. If an answer containing an NSEC3 record
+with more iterations is received, its DNSSEC validation status is treated as Insecure.
+
 ## `packetcache-ttl`
 * Integer
 * Default: 3600
index 880358103834d332e545d8d9fff087502f9e9bf7..2220f192c8ec24e25e4fa2aaf7073a641a3ed141 100644 (file)
@@ -2732,6 +2732,7 @@ static int serviceMain(int argc, char*argv[])
   }
 
   g_dnssecLogBogus = ::arg().mustDo("dnssec-log-bogus");
+  g_maxNSEC3Iterations = ::arg().asNum("nsec3-max-iterations");
 
   try {
     loadRecursorLuaConfig(::arg()["lua-config-file"], ::arg().mustDo("daemon"));
@@ -3223,6 +3224,7 @@ int main(int argc, char **argv)
     ::arg().set("snmp-master-socket", "If set and snmp-agent is set, the socket to use to register to the SNMP master")="";
 
     ::arg().set("tcp-fast-open", "Enable TCP Fast Open support on the listening sockets, using the supplied numerical value as the queue size")="0";
+    ::arg().set("nsec3-max-iterations", "Maximum number of iterations allowed for an NSEC3 record")="2500";
 
     ::arg().setCmd("help","Provide a helpful message");
     ::arg().setCmd("version","Print version string");
index 60b4f49985c3b250b0d8b8d3d3efad3f16cbcc24..2ec5dd0bf9e33177c821362a3150431042d2a326 100644 (file)
@@ -1696,6 +1696,10 @@ void SyncRes::getDenialValidationState(NegCache::NegCacheEntry& ne, vState& stat
         updateValidationState(state, Insecure);
         return;
       }
+      else if (res == INSECURE) {
+        LOG("Insecure denial found for "<<ne.d_name<<", retuning Insecure"<<endl);
+        ne.d_validationState = Insecure;
+      }
       else {
         LOG("Invalid denial found for "<<ne.d_name<<", retuning Bogus"<<endl);
         ne.d_validationState = Bogus;
@@ -1787,7 +1791,7 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co
         harvestNXRecords(lwr.d_records, ne);
         cspmap_t csp = harvestCSPFromNE(ne);
         dState denialState = getDenial(csp, newauth, QType::DS);
-        if (denialState == NXQTYPE || denialState == OPTOUT) {
+        if (denialState == NXQTYPE || denialState == OPTOUT || denialState == INSECURE) {
           ne.d_validationState = Secure;
           rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
           LOG(prefix<<qname<<": got negative indication of DS record for '"<<newauth<<"'"<<endl);
index fe6661ee07aed379140975364c3bbfd284d03965..ef9620648a7f914c231ca04d951763ec93d3b01f 100644 (file)
@@ -5,6 +5,7 @@
 #include "base32.hh"
 #include "logger.hh"
 bool g_dnssecLOG{false};
+uint16_t g_maxNSEC3Iterations{0};
 
 #define LOG(x) if(g_dnssecLOG) { L <<Logger::Warning << x; }
 void dotEdge(DNSName zone, string type1, DNSName name1, string tag1, string type2, DNSName name2, string tag2, string color="");
@@ -82,6 +83,10 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
         if(!nsec3)
           continue;
 
+        if (g_maxNSEC3Iterations && nsec3->d_iterations > g_maxNSEC3Iterations) {
+          return INSECURE;
+        }
+
         string h = hashQNameWithSalt(nsec3->d_salt, nsec3->d_iterations, qname);
         //              cerr<<"Salt length: "<<nsec3->d_salt.length()<<", iterations: "<<nsec3->d_iterations<<", hashed: "<<qname<<endl;
         LOG("\tquery hash: "<<toBase32Hex(h)<<endl);
@@ -135,6 +140,10 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
           if(!nsec3)
             continue;
 
+          if (g_maxNSEC3Iterations && nsec3->d_iterations > g_maxNSEC3Iterations) {
+            return INSECURE;
+          }
+
           string h = hashQNameWithSalt(nsec3->d_salt, nsec3->d_iterations, sname);
           string beginHash=fromBase32Hex(v.first.first.getRawLabels()[0]);
 
@@ -167,6 +176,9 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
             auto nsec3 = std::dynamic_pointer_cast<NSEC3RecordContent>(r);
             if(!nsec3)
               continue;
+            if (g_maxNSEC3Iterations && nsec3->d_iterations > g_maxNSEC3Iterations) {
+              return INSECURE;
+            }
 
             string h = hashQNameWithSalt(nsec3->d_salt, nsec3->d_iterations, nextCloser);
             string beginHash=fromBase32Hex(v.first.first.getRawLabels()[0]);
index 540569786e4288074e4b69256e61ee8dc588186f..5713de9c7b6d83acdb246b753be9b91332283375 100644 (file)
@@ -28,6 +28,7 @@
 #include "dnsrecords.hh"
  
 extern bool g_dnssecLOG;
+extern uint16_t g_maxNSEC3Iterations;
 
 // 4033 5
 enum vState { Indeterminate, Bogus, Insecure, Secure, NTA, TA };