]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: Account for the NSEC(3) denial TTL in expanded wildcard answers
authorRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 13 Jan 2021 11:10:03 +0000 (12:10 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 13 Jan 2021 11:39:44 +0000 (12:39 +0100)
pdns/syncres.cc
pdns/syncres.hh

index 16eb0ca0f453fc77b3b4db6e552f5574d634d71f..eb9d010458e480b44ac0006087d693b1c98892bf 100644 (file)
@@ -2312,11 +2312,12 @@ bool SyncRes::validationEnabled() const
   return g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate;
 }
 
-uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL) const
+uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs) const
 {
   uint32_t lowestTTD = std::numeric_limits<uint32_t>::max();
-  for(const auto& record : records)
+  for (const auto& record : records) {
     lowestTTD = min(lowestTTD, record.d_ttl);
+  }
 
   /* even if it was not requested for that request (Process, and neither AD nor DO set),
      it might be requested at a later time so we need to be careful with the TTL. */
@@ -2327,12 +2328,27 @@ uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const
 
     for(const auto& sig : signatures) {
       if (isRRSIGNotExpired(d_now.tv_sec, sig)) {
-        // we don't decerement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
+        // we don't decrement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
         lowestTTD = min(lowestTTD, static_cast<uint32_t>(sig->d_sigexpire));
       }
     }
   }
 
+  for (const auto& entry : authorityRecs) {
+    /* be careful, this is still a TTL here */
+    lowestTTD = min(lowestTTD, static_cast<uint32_t>(entry->d_ttl + d_now.tv_sec));
+
+    if (entry->d_type == QType::RRSIG && validationEnabled()) {
+      auto rrsig = getRR<RRSIGRecordContent>(*entry);
+      if (rrsig) {
+        if (isRRSIGNotExpired(d_now.tv_sec, rrsig)) {
+          // we don't decrement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
+          lowestTTD = min(lowestTTD, static_cast<uint32_t>(rrsig->d_sigexpire));
+        }
+      }
+    }
+  }
+
   return lowestTTD;
 }
 
@@ -3099,12 +3115,13 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& lwr
   }
 
   // supplant
-  for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
-    if((i->second.records.size() + i->second.signatures.size()) > 1) {  // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2)
-      uint32_t lowestTTD=computeLowestTTD(i->second.records, i->second.signatures, i->second.signaturesTTL);
+  for (auto& entry : tcache) {
+    if ((entry.second.records.size() + entry.second.signatures.size() + authorityRecs.size()) > 1) {  // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2)
+      uint32_t lowestTTD = computeLowestTTD(entry.second.records, entry.second.signatures, entry.second.signaturesTTL, authorityRecs);
 
-      for(auto& record : i->second.records)
+      for (auto& record : entry.second.records) {
         record.d_ttl = lowestTTD; // boom
+      }
     }
 
 //             cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.name;
index 491cb9f1f20be9978443fd35806eaea908d4e1bb..1ee7eb1a8e644efa0ae2df18f39f49632e383b5c 100644 (file)
@@ -848,7 +848,7 @@ private:
   boost::optional<Netmask> getEDNSSubnetMask(const DNSName&dn, const ComboAddress& rem);
 
   bool validationEnabled() const;
-  uint32_t computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL) const;
+  uint32_t computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs) const;
   void updateValidationState(vState& state, const vState stateUpdate);
   vState validateRecordsWithSigs(unsigned int depth, const DNSName& qname, const QType& qtype, const DNSName& name, const QType& type, const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures);
   vState validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, unsigned int depth);