]> granicus.if.org Git - pdns/commitdiff
make nxdomains/noerror responses work. We validate the NSEC/NSEC3 records, but don...
authorbert hubert <bert.hubert@netherlabs.nl>
Sat, 28 Nov 2015 11:38:05 +0000 (12:38 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Sat, 28 Nov 2015 11:38:05 +0000 (12:38 +0100)
pdns/syncres.cc
pdns/syncres.hh

index 31ab17f04283f97959a6a6ff957e0c11d89aab1d..7684066060edc2b1ca74b6d2a1139719a3667cd4 100644 (file)
@@ -39,6 +39,7 @@
 #include <utility>
 #include <deque>
 #include "logger.hh"
+#include "validate.hh"
 #include "misc.hh"
 #include "arguments.hh"
 #include "lwres.hh"
@@ -748,6 +749,14 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSR
          giveNegative=true;
          sqname=ni->d_qname;
          sqt=QType::SOA;
+         if(d_doDNSSEC) {
+           for(const auto& p : ni->d_dnssecProof) {
+             for(const auto& rec: p.second.records) 
+               ret.push_back(rec);
+             for(const auto& rec: p.second.signatures) 
+               ret.push_back(rec);
+           }
+         }
          moveCacheItemToBack(t_sstorage->negcache, ni);
          break;
        }
@@ -789,7 +798,7 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSR
       dr.d_name=sqname;
       dr.d_ttl=ttl; 
       dr.d_content=signature;
-      dr.d_place=DNSResourceRecord::ANSWER;
+      dr.d_place= giveNegative ? DNSResourceRecord::AUTHORITY : DNSResourceRecord::ANSWER;
       dr.d_class=1;
       ret.push_back(dr);
     }
@@ -863,6 +872,37 @@ static bool magicAddrMatch(const QType& query, const QType& answer)
   return answer.getCode() == QType::A || answer.getCode() == QType::AAAA;
 }
 
+
+recsig_t harvestRecords(const vector<DNSRecord>& records, const set<uint16_t>& types)
+{
+  recsig_t ret;
+  for(const auto& rec : records) {
+    if(rec.d_type == QType::RRSIG) {
+      auto rrs=getRR<RRSIGRecordContent>(rec);
+      if(types.count(rrs->d_type))
+       ret[make_pair(rec.d_name, rrs->d_type)].signatures.push_back(rec);
+    }
+    else if(types.count(rec.d_type))
+      ret[make_pair(rec.d_name, rec.d_type)].records.push_back(rec);
+  }
+  return ret;
+}
+
+static void addNXNSECS(vector<DNSRecord>&ret, const vector<DNSRecord>& records)
+{
+  auto csp = harvestRecords(records, {QType::NSEC, QType::NSEC3, QType::SOA});
+  for(const auto& c : csp) {
+    if(c.first.second == QType::NSEC || c.first.second == QType::NSEC3 || c.first.second == QType::SOA) {
+      if(c.first.second !=QType::SOA) {
+       for(const auto& rec : c.second.records)
+         ret.push_back(rec);
+      }
+      for(const auto& rec : c.second.signatures)
+       ret.push_back(rec);
+    }
+  }
+}
+
 /** returns -1 in case of no results, rcode otherwise */
 int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
                          vector<DNSRecord>&ret,
@@ -1199,7 +1239,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
            ne.d_ttd=d_now.tv_sec + rec.d_ttl;
            ne.d_name=qname;
            ne.d_qtype=QType(0); // this encodes 'whole record'
-           
+           ne.d_dnssecProof = harvestRecords(lwr.d_records, {QType::NSEC, QType::NSEC3});
            replacing_insert(t_sstorage->negcache, ne);
            if(s_rootNXTrust && auth.isRoot()) {
              ne.d_name = getLastLabel(ne.d_name);
@@ -1261,6 +1301,7 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
              ne.d_ttd=d_now.tv_sec + rec.d_ttl;
              ne.d_name=qname;
              ne.d_qtype=qtype;
+             ne.d_dnssecProof = harvestRecords(lwr.d_records, {QType::NSEC, QType::NSEC3});
              if(qtype.getCode()) {  // prevents us from blacking out a whole domain
                replacing_insert(t_sstorage->negcache, ne);
              }
@@ -1290,10 +1331,14 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
       }
       if(lwr.d_rcode==RCode::NXDomain) {
         LOG(prefix<<qname.toString()<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl);
+
+       addNXNSECS(ret, lwr.d_records);
+
         return RCode::NXDomain;
       }
       if(nsset.empty() && !lwr.d_rcode && (negindic || lwr.d_aabit)) {
         LOG(prefix<<qname.toString()<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA) " : "")<<(lwr.d_aabit ? "(have aa bit) " : "")<<endl);
+       addNXNSECS(ret, lwr.d_records);
         return 0;
       }
       else if(realreferral) {
index 313db996a81659c38532f7a02b8c15b8834cb22a..3988c082f1670da5099fa3153b5bdc51e5951585 100644 (file)
@@ -28,6 +28,17 @@ extern DNSFilterEngine g_dfe;
 
 void primeHints(void);
 class RecursorLua;
+
+struct BothRecordsAndSignatures
+{
+  vector<DNSRecord> records;
+  vector<DNSRecord> signatures;
+};
+typedef map<pair<DNSName,uint16_t>, BothRecordsAndSignatures> recsig_t;
+
+recsig_t harvestRecords(const std::vector<DNSRecord>& records, const std::set<uint16_t>& types);
+
+
 struct NegCacheEntry
 {
   DNSName d_name;
@@ -38,6 +49,7 @@ struct NegCacheEntry
   {
     return d_ttd;
   }
+  recsig_t d_dnssecProof;
 };