]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Process denial of ZONEMD in the NSEC3 case
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 24 Jan 2022 12:18:17 +0000 (13:18 +0100)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 24 Jan 2022 12:18:17 +0000 (13:18 +0100)
pdns/recursordist/rec-zonetocache.cc
pdns/zonemd.cc
pdns/zonemd.hh

index fbcc221184d2a59522c8fb1e5148b9b08b2c9715..2aee2c31913e2cb54bad4253744add94c6a0c2c0 100644 (file)
@@ -287,9 +287,9 @@ vState ZoneData::dnssecValidate(pdns::ZoneMD& zonemd, size_t& zonemdCount) const
       nsecValidationStatus = validateWithKeySet(d_now, d_zone, nsecs.records, nsecs.signatures, validKeys);
       csp.emplace(std::make_pair(d_zone, QType::NSEC), nsecs);
     }
-    else if (nsec3s.records.size() > 0 && nsec3s.signatures.size() > 0) {
-      nsecValidationStatus = validateWithKeySet(d_now, d_zone, nsec3s.records, nsec3s.signatures, validKeys);
-      csp.emplace(std::make_pair(d_zone, QType::NSEC3), nsec3s);
+    else if (nsec3s.records.size() > 0 && nsec3s.signatures.size() > 0 && !zonemd.getNSEC3Label().empty()) {
+      nsecValidationStatus = validateWithKeySet(d_now, zonemd.getNSEC3Label(), nsec3s.records, nsec3s.signatures, validKeys);
+      csp.emplace(std::make_pair(zonemd.getNSEC3Label(), QType::NSEC3), nsec3s);
     }
     else {
       d_log->info("No NSEC(3) records and/or RRSIGS found to deny ZONEMD");
index 8aa876a1c4304ef237d14b7b5584d5e2fa40e639..5a604fb1e2128159c9b8ed5052388493a08be38b 100644 (file)
@@ -4,6 +4,7 @@
 #include "dnssecinfra.hh"
 #include "sha.hh"
 #include "zoneparser-tng.hh"
+#include "base32.hh"
 
 void pdns::ZoneMD::readRecords(ZoneParserTNG& zpt)
 {
@@ -61,10 +62,12 @@ void pdns::ZoneMD::readRecords(ZoneParserTNG& zpt)
         d_nsecs.records.emplace(std::dynamic_pointer_cast<NSECRecordContent>(drc));
         break;
       case QType::NSEC3:
-        d_nsecs3.records.emplace(std::dynamic_pointer_cast<NSEC3RecordContent>(drc));
         break;
       }
     }
+    if (dnsResourceRecord.qtype == QType::NSEC3) {
+        d_nsecs3.records.emplace(std::dynamic_pointer_cast<NSEC3RecordContent>(drc));
+    }
     RRSetKey_t key = std::pair(dnsResourceRecord.qname, dnsResourceRecord.qtype);
     d_resourceRecordSets[key].push_back(drc);
     d_resourceRecordSetTTLs[key] = dnsResourceRecord.ttl;
@@ -118,9 +121,28 @@ void pdns::ZoneMD::readRecord(const DNSRecord& record)
     case QType::NSEC:
       d_nsecs.records.emplace(std::dynamic_pointer_cast<NSECRecordContent>(record.d_content));
       break;
+    case QType::NSEC3:
+      // Handled below
+      break;
+    case QType::NSEC3PARAM:
+      auto param = *std::dynamic_pointer_cast<NSEC3PARAMRecordContent>(record.d_content);
+      d_nsec3label = d_zone;
+      d_nsec3label.prependRawLabel(toBase32Hex(hashQNameWithSalt(param, d_zone)));
+      // XXX We could filter the collected NSEC3 and their RRSIGs in d_nsecs3 at this point as we now know the right label
+      break;
+    }
+  }
+  if (d_nsec3label.empty() || record.d_name == d_nsec3label) {
+    switch (record.d_type) {
     case QType::NSEC3:
       d_nsecs3.records.emplace(std::dynamic_pointer_cast<NSEC3RecordContent>(record.d_content));
       break;
+    case  QType::RRSIG:
+      auto rrsig = std::dynamic_pointer_cast<RRSIGRecordContent>(record.d_content);
+      if (rrsig->d_type == QType::NSEC3) {
+        d_nsecs3.signatures.emplace_back(rrsig);
+      }
+      break;
     }
   }
   RRSetKey_t key = std::pair(record.d_name, record.d_type);
index ea76663aae67870233b084b6a871940c2b78e058..df834130c1d5cc0d74f89c855c939526c190dc9e 100644 (file)
@@ -92,6 +92,10 @@ public:
     return d_nsecs3;
   }
 
+  const DNSName& getNSEC3Label() const {
+    return d_nsec3label;
+  }
+
 private:
   typedef std::pair<DNSName, QType> RRSetKey_t;
   typedef std::vector<std::shared_ptr<DNSRecordContent>> RRVector_t;
@@ -130,6 +134,7 @@ private:
   std::vector<shared_ptr<RRSIGRecordContent>> d_rrsigs;
   ContentSigPair d_nsecs;
   ContentSigPair d_nsecs3;
+  DNSName d_nsec3label;
   const DNSName d_zone;
 };