]> git.ipfire.org Git - thirdparty/pdns.git/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>
Wed, 31 Aug 2016 14:52:28 +0000 (16:52 +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 2894f1701dd995280b10cf6b3932060ea2139c5c..7ad3503ab247939c6369ef5ee9df986b91dbdd17 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;