]> granicus.if.org Git - pdns/commitdiff
Make the negcache forwarded zones aware
authorPieter Lexis <pieter.lexis@powerdns.com>
Mon, 29 Aug 2016 09:05:17 +0000 (11:05 +0200)
committerPieter Lexis <pieter.lexis@powerdns.com>
Thu, 20 Oct 2016 12:00:42 +0000 (14:00 +0200)
Because of DNSSEC (without NTAs configured), we 'leak' the forwarded
name to the cache when looking for the DNSKEY. This resulted in NXDOMAIN
answers for actual NXDOMAINs, but with the root SOA record. Leading to
inconsistent answers to the client.

pdns/syncres.cc

index 2f10ae52e421ea524fe6e04adc2828e5a160baed..a3455f057119ccfecdbfdc8acd2c4c473f08e8cc 100644 (file)
@@ -758,9 +758,13 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSR
   pair<negcache_t::const_iterator, negcache_t::const_iterator> range;
   QType qtnull(0);
 
+  DNSName authname(qname);
+  bool wasForwardedOrAuth = (getBestAuthZone(&authname) != t_sstorage->domainmap->end());
+
   if(s_rootNXTrust &&
      (range.first=t_sstorage->negcache.find(tie(getLastLabel(qname), qtnull))) != t_sstorage->negcache.end() &&
-      range.first->d_qname.isRoot() && (uint32_t)d_now.tv_sec < range.first->d_ttd ) {
+      !(wasForwardedOrAuth && !authname.isRoot()) && // when forwarding, the root may only neg-cache if it was forwarded to.
+      range.first->d_qname.isRoot() && (uint32_t)d_now.tv_sec < range.first->d_ttd) {
     sttl=range.first->d_ttd - d_now.tv_sec;
 
     LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<range.first->d_name<<"' & '"<<range.first->d_qname<<"' for another "<<sttl<<" seconds"<<endl);
@@ -776,7 +780,8 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSR
     negcache_t::iterator ni;
     for(ni=range.first; ni != range.second; ni++) {
       // we have something
-      if(ni->d_qtype.getCode() == 0 || ni->d_qtype == qtype) {
+      if(!(wasForwardedOrAuth && ni->d_qname != authname) && // Only the authname nameserver can neg cache entries
+         (ni->d_qtype.getCode() == 0 || ni->d_qtype == qtype)) {
        res=0;
        if((uint32_t)d_now.tv_sec < ni->d_ttd) {
          sttl=ni->d_ttd - d_now.tv_sec;