]> granicus.if.org Git - pdns/commitdiff
rec: Drop non-IN records from auths, check for invalid record content
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 25 Apr 2016 15:27:44 +0000 (17:27 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 26 Apr 2016 09:17:48 +0000 (11:17 +0200)
Fix a crash in case of a bogus response from an authoritative
server.

pdns/filterpo.cc
pdns/ixfr.cc
pdns/lua-recursor4.cc
pdns/reczones.cc
pdns/resolver.cc
pdns/rpzloader.cc
pdns/syncres.cc
pdns/validate.cc

index 259350d3a78ef38099c1ae9e75b4b4aea336a217..d3d6115f66ea32c96e7bf684598e669a4e2debab 100644 (file)
@@ -80,10 +80,16 @@ DNSFilterEngine::Policy DNSFilterEngine::getPostPolicy(const vector<DNSRecord>&
   for(const auto& r : records) {
     if(r.d_place != DNSResourceRecord::ANSWER) 
       continue;
-    if(r.d_type == QType::A) 
-      ca = std::dynamic_pointer_cast<ARecordContent>(r.d_content)->getCA();
-    else if(r.d_type == QType::AAAA) 
-      ca = std::dynamic_pointer_cast<AAAARecordContent>(r.d_content)->getCA();
+    if(r.d_type == QType::A) {
+      if (auto rec = getRR<ARecordContent>(r)) {
+        ca = rec->getCA();
+      }
+    }
+    else if(r.d_type == QType::AAAA) {
+      if (auto rec = getRR<AAAARecordContent>(r)) {
+        ca = rec->getCA();
+      }
+    }
     else
       continue;
 
index 2170a7045695c0c5513b091c5308bfd6564ac939..7e53f938b0d292846b526e88cc03994facd15f87 100644 (file)
@@ -73,23 +73,24 @@ vector<pair<vector<DNSRecord>, vector<DNSRecord> > > getIXFRDeltas(const ComboAd
       r.first.d_name = r.first.d_name.makeRelative(zone);
       records.push_back(r.first);
       if(r.first.d_type == QType::SOA) {
-       auto sr = std::dynamic_pointer_cast<SOARecordContent>(r.first.d_content);
-       if(!masterSOA) {
-         if(sr->d_st.serial == std::dynamic_pointer_cast<SOARecordContent>(oursr.d_content)->d_st.serial) // we are up to date
+       auto sr = getRR<SOARecordContent>(r.first);
+       if(sr) {
+         if(!masterSOA) {
+           if(sr->d_st.serial == std::dynamic_pointer_cast<SOARecordContent>(oursr.d_content)->d_st.serial) { // we are up to date
+             goto done;
+           }
+           masterSOA=sr;
+         }
+         else if(sr->d_st.serial == masterSOA->d_st.serial)
            goto done;
-         masterSOA=sr;
-
        }
-       else if(sr->d_st.serial == masterSOA->d_st.serial)
-         goto done;
-
       }
     }
   }
   //  cout<<"Got "<<records.size()<<" records"<<endl;
  done:;
   for(unsigned int pos = 1;pos < records.size();) {
-    auto sr = std::dynamic_pointer_cast<SOARecordContent>(records[pos].d_content);
+    auto sr = getRR<SOARecordContent>(records[pos]);
     vector<DNSRecord> remove, add;
     if(!sr) { // this is an actual AXFR!
       return {{remove, records}};
@@ -102,7 +103,7 @@ vector<pair<vector<DNSRecord>, vector<DNSRecord> > > getIXFRDeltas(const ComboAd
     for(pos++; pos < records.size() && records[pos].d_type != QType::SOA; ++pos) {
       remove.push_back(records[pos]);
     }
-    sr = std::dynamic_pointer_cast<SOARecordContent>(records[pos].d_content);
+    sr = getRR<SOARecordContent>(records[pos]);
 
     add.push_back(records[pos]); // this adds the new SOA
     for(pos++; pos < records.size() && records[pos].d_type != QType::SOA; ++pos)  {
index adc1c49840aaa4ec6ddb2e9393c37c421fec78b5..76ab32149ab964e4a65bf7d0c6034e96146f7b29 100644 (file)
@@ -61,8 +61,11 @@ static int followCNAMERecords(vector<DNSRecord>& ret, const QType& qtype)
   DNSName target;
   for(const DNSRecord& rr :  ret) {
     if(rr.d_type == QType::CNAME) {
-      target=getRR<CNAMERecordContent>(rr)->getTarget();
-      break;
+      auto rec = getRR<CNAMERecordContent>(rr);
+      if(rec) {
+        target=rec->getTarget();
+        break;
+      }
     }
   }
   if(target.empty())
@@ -86,13 +89,15 @@ static int getFakeAAAARecords(const DNSName& qname, const std::string& prefix, v
   for(DNSRecord& rr :  ret)
   {
     if(rr.d_type == QType::A && rr.d_place==DNSResourceRecord::ANSWER) {
-      ComboAddress ipv4(getRR<ARecordContent>(rr)->getCA());
-      uint32_t tmp;
-      memcpy((void*)&tmp, &ipv4.sin4.sin_addr.s_addr, 4);
-      // tmp=htonl(tmp);
-      memcpy(((char*)&prefixAddress.sin6.sin6_addr.s6_addr)+12, &tmp, 4);
-      rr.d_content = std::make_shared<AAAARecordContent>(prefixAddress);
-      rr.d_type = QType::AAAA;
+      if(auto rec = getRR<ARecordContent>(rr)) {
+        ComboAddress ipv4(rec->getCA());
+        uint32_t tmp;
+        memcpy((void*)&tmp, &ipv4.sin4.sin_addr.s_addr, 4);
+        // tmp=htonl(tmp);
+        memcpy(((char*)&prefixAddress.sin6.sin6_addr.s6_addr)+12, &tmp, 4);
+        rr.d_content = std::make_shared<AAAARecordContent>(prefixAddress);
+        rr.d_type = QType::AAAA;
+      }
     }
   }
   return rcode;
index c1e8453d456dc7557ae75a49066b3b10ec71f631..2bc781c5d130a684ced100f0f22be3172ac96a67 100644 (file)
@@ -319,7 +319,7 @@ void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, const std::
 
     sleep(refresh);
     
-    L<<Logger::Info<<"Getting IXFR deltas for "<<zone<<" from "<<master.toStringWithPort()<<", our serial: "<<std::dynamic_pointer_cast<SOARecordContent>(dr.d_content)->d_st.serial<<endl;
+    L<<Logger::Info<<"Getting IXFR deltas for "<<zone<<" from "<<master.toStringWithPort()<<", our serial: "<<getRR<SOARecordContent>(dr)->d_st.serial<<endl;
     vector<pair<vector<DNSRecord>, vector<DNSRecord> > > deltas;
     try {
       deltas = getIXFRDeltas(master, zone, dr, tt);
@@ -343,8 +343,8 @@ void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, const std::
       for(const auto& rr : remove) { // should always contain the SOA
        totremove++;
        if(rr.d_type == QType::SOA) {
-         auto oldsr = std::dynamic_pointer_cast<SOARecordContent>(rr.d_content);
-         if(oldsr->d_st.serial == oursr->d_st.serial) {
+         auto oldsr = getRR<SOARecordContent>(rr);
+         if(oldsr && oldsr->d_st.serial == oursr->d_st.serial) {
            //      cout<<"Got good removal of SOA serial "<<oldsr->d_st.serial<<endl;
          }
          else
@@ -359,9 +359,11 @@ void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, const std::
       for(const auto& rr : add) { // should always contain the new SOA
        totadd++;
        if(rr.d_type == QType::SOA) {
-         auto newsr = std::dynamic_pointer_cast<SOARecordContent>(rr.d_content);
+         auto newsr = getRR<SOARecordContent>(rr);
          //      L<<Logger::Info<<"New SOA serial for "<<zone<<": "<<newsr->d_st.serial<<endl;
-         oursr = newsr;
+         if (newsr) {
+           oursr = newsr;
+         }
        }
        else {
          L<<Logger::Info<<"Had addition of "<<rr.d_name<<endl;
index c7e3f192f4dd81be63e466e53465c4d9e8a7f28a..97bba89a530c50a657b36aad270eeb5642a010d2 100644 (file)
@@ -266,13 +266,15 @@ bool Resolver::tryGetSOASerial(DNSName *domain, uint32_t *theirSerial, uint32_t
   bool gotSOA=false;
   for(const MOADNSParser::answers_t::value_type& drc :  mdp.d_answers) {
     if(drc.first.d_type == QType::SOA) {
-      shared_ptr<SOARecordContent> src=std::dynamic_pointer_cast<SOARecordContent>(drc.first.d_content);
-      *theirSerial=src->d_st.serial;
-      gotSOA = true;
+      shared_ptr<SOARecordContent> src=getRR<SOARecordContent>(drc.first);
+      if (src) {
+        *theirSerial=src->d_st.serial;
+        gotSOA = true;
+      }
     }
     if(drc.first.d_type == QType::RRSIG) {
-      shared_ptr<RRSIGRecordContent> rrc=std::dynamic_pointer_cast<RRSIGRecordContent>(drc.first.d_content);
-      if(rrc->d_type == QType::SOA) {
+      shared_ptr<RRSIGRecordContent> rrc=getRR<RRSIGRecordContent>(drc.first);
+      if(rrc && rrc->d_type == QType::SOA) {
         *theirInception= std::max(*theirInception, rrc->d_siginception);
         *theirExpire = std::max(*theirExpire, rrc->d_sigexpire);
       }
@@ -480,10 +482,12 @@ int AXFRRetriever::getChunk(Resolver::res_t &res, vector<DNSRecord>* records) //
         checkTSIG = true;
       
       if(answer.first.d_type == QType::TSIG) {
-        shared_ptr<TSIGRecordContent> trc = std::dynamic_pointer_cast<TSIGRecordContent>(answer.first.d_content);
-        theirMac = trc->d_mac;
-        d_trc.d_time = trc->d_time;
-        checkTSIG = true;
+        shared_ptr<TSIGRecordContent> trc = getRR<TSIGRecordContent>(answer.first);
+        if(trc) {
+          theirMac = trc->d_mac;
+          d_trc.d_time = trc->d_time;
+          checkTSIG = true;
+        }
       }
     }
 
index 6be490f9fdc30434c7c0c3dbd04b126785e746bb..4c27a8f3c5ba89eb04180d3532e60575d363ae71 100644 (file)
@@ -23,8 +23,16 @@ void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, const std::
 
   DNSFilterEngine::Policy pol{DNSFilterEngine::PolicyKind::NoAction, nullptr, polName, 0};
 
+  if(dr.d_class != QClass::IN) {
+    return;
+  }
+
   if(dr.d_type == QType::CNAME) {
-    auto target=std::dynamic_pointer_cast<CNAMERecordContent>(dr.d_content)->getTarget();
+    auto crc = getRR<CNAMERecordContent>(dr);
+    if (!crc) {
+      return;
+    }
+    auto target=crc->getTarget();
     if(defpol) {
       pol=*defpol;
     }
@@ -118,7 +126,7 @@ shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const
 
       dr.d_name.makeUsRelative(zone);
       if(dr.d_type==QType::SOA) {
-       sr = std::dynamic_pointer_cast<SOARecordContent>(dr.d_content);
+       sr = getRR<SOARecordContent>(dr);
        continue;
       }
 
index 668ebfb17dae1886a585443a279dcfe41c020eed..da0482d492aefccdfa19831892767d8f7c52b05c 100644 (file)
@@ -504,8 +504,10 @@ vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, int depth, set<GetB
        if(t_RC->get(d_now.tv_sec, qname, QType(QType::AAAA), &cset, d_requestor) > 0) {
          for(auto k=cset.cbegin();k!=cset.cend();++k) {
            if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
-             ComboAddress ca=std::dynamic_pointer_cast<AAAARecordContent>(k->d_content)->getCA(53);
-             ret.push_back(ca);
+             if (auto drc = std::dynamic_pointer_cast<AAAARecordContent>(k->d_content)) {
+               ComboAddress ca=drc->getCA(53);
+               ret.push_back(ca);
+             }
            }
          }
        }
@@ -556,9 +558,9 @@ void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, vecto
           vector<DNSRecord> aset;
 
           const DNSRecord& dr=*k;
-         auto nrr = std::dynamic_pointer_cast<NSRecordContent>(dr.d_content);
-          if(!nrr->getNS().isPartOf(subdomain) || t_RC->get(d_now.tv_sec, nrr->getNS(), s_doIPv6 ? QType(QType::ADDR) : QType(QType::A),
-                                                            doLog() ? &aset : 0, d_requestor) > 5) {
+         auto nrr = getRR<NSRecordContent>(dr);
+          if(nrr && (!nrr->getNS().isPartOf(subdomain) || t_RC->get(d_now.tv_sec, nrr->getNS(), s_doIPv6 ? QType(QType::ADDR) : QType(QType::A),
+                                                                    doLog() ? &aset : 0, d_requestor) > 5)) {
             bestns.push_back(dr);
             LOG(prefix<<qname.toString()<<": NS (with ip, or non-glue) in cache for '"<<subdomain.toString()<<"' -> '"<<nrr->getNS()<<"'"<<endl);
             LOG(prefix<<qname.toString()<<": within bailiwick: "<< nrr->getNS().isPartOf(subdomain));
@@ -580,7 +582,7 @@ void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, vecto
         answer.qname=qname;
        answer.qtype=qtype.getCode();
        for(const auto& dr : bestns)
-         answer.bestns.insert(make_pair(dr.d_name, std::dynamic_pointer_cast<NSRecordContent>(dr.d_content)->getNS()));
+         answer.bestns.insert(make_pair(dr.d_name, getRR<NSRecordContent>(dr)->getNS()));
 
         if(beenthere.count(answer)) {
          brokeloop=true;
@@ -892,7 +894,7 @@ recsig_t harvestRecords(const vector<DNSRecord>& records, const set<uint16_t>& t
   for(const auto& rec : records) {
     if(rec.d_type == QType::RRSIG) {
       auto rrs=getRR<RRSIGRecordContent>(rec);
-      if(types.count(rrs->d_type))
+      if(rrs && 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))
@@ -1151,9 +1153,11 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con
 
       for(const auto& rec : lwr.d_records) {
         if(rec.d_type == QType::RRSIG) {
-          auto rrsig = std::dynamic_pointer_cast<RRSIGRecordContent>(rec.d_content);
-          //       cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
-          tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
+          auto rrsig = getRR<RRSIGRecordContent>(rec);
+          if (rrsig) {
+            //     cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
+            tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
+          }
         }
       }
 
@@ -1244,6 +1248,9 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con
       DNSName newtarget;
 
       for(auto& rec : lwr.d_records) {
+        if (rec.d_type!=QType::OPT && rec.d_class!=QClass::IN)
+          continue;
+
         if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
            lwr.d_rcode==RCode::NXDomain && qname.isPartOf(rec.d_name) && rec.d_name.isPartOf(auth)) {
           LOG(prefix<<qname.toString()<<": got negative caching indication for name '"<<qname.toString()+"' (accept="<<rec.d_name.isPartOf(auth)<<"), newtarget='"<<(newtarget.empty()?string("<empty>"):newtarget.toString())<<"'"<<endl);
@@ -1270,7 +1277,9 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con
         }
         else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_name == qname && rec.d_type==QType::CNAME && (!(qtype==QType(QType::CNAME)))) {
           ret.push_back(rec);
-          newtarget=std::dynamic_pointer_cast<CNAMERecordContent>(rec.d_content)->getTarget();
+          if (auto content = getRR<CNAMERecordContent>(rec)) {
+            newtarget=content->getTarget();
+          }
         }
        else if((rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::ANSWER){
          if(rec.d_type != QType::RRSIG || rec.d_name == qname)
@@ -1298,7 +1307,9 @@ int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, con
           else {
             LOG(prefix<<qname.toString()<<": got upwards/level NS record '"<<rec.d_name.toString()<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth.toString()<<"'"<<endl);
          }
-          nsset.insert(std::dynamic_pointer_cast<NSRecordContent>(rec.d_content)->getNS());
+          if (auto content = getRR<NSRecordContent>(rec)) {
+            nsset.insert(content->getNS());
+          }
         }
         else if(rec.d_place==DNSResourceRecord::AUTHORITY && qname.isPartOf(rec.d_name) && rec.d_type==QType::DS) {
          LOG(prefix<<qname.toString()<<": got DS record '"<<rec.d_name.toString()<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
index fda7ec32e65c58b376d8b861663a9a747ad71188..63e39f85b82645c3569068890b2c8645433a9224 100644 (file)
@@ -150,7 +150,9 @@ cspmap_t harvestCSPFromRecs(const vector<DNSRecord>& recs)
     
     if(rec.d_type == QType::RRSIG) {
       auto rrc = getRR<RRSIGRecordContent>(rec);
-      cspmap[{rec.d_name,rrc->d_type}].signatures.push_back(getRR<RRSIGRecordContent>(rec));
+      if (rrc) {
+        cspmap[{rec.d_name,rrc->d_type}].signatures.push_back(rrc);
+      }
     }
     else {
       cspmap[{rec.d_name, rec.d_type}].records.push_back(rec.d_content);
@@ -200,19 +202,21 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset)
       if(rec.d_type == QType::RRSIG)
       {
         auto rrc=getRR<RRSIGRecordContent> (rec);
-        if(rrc->d_type != QType::DNSKEY)
+        if(rrc && rrc->d_type != QType::DNSKEY)
           continue;
         sigs.push_back(*rrc);
       }
       else if(rec.d_type == QType::DNSKEY)
       {
         auto drc=getRR<DNSKEYRecordContent> (rec);
-        tkeys.insert(*drc);
-       //      cerr<<"Inserting key with tag "<<drc->getTag()<<": "<<drc->getZoneRepresentation()<<endl;
-       dotNode("DNSKEY", qname, std::to_string(drc->getTag()), (boost::format("tag=%d, algo=%d") % drc->getTag() % static_cast<int>(drc->d_algorithm)).str());
+        if(drc) {
+          tkeys.insert(*drc);
+          //   cerr<<"Inserting key with tag "<<drc->getTag()<<": "<<drc->getZoneRepresentation()<<endl;
+          dotNode("DNSKEY", qname, std::to_string(drc->getTag()), (boost::format("tag=%d, algo=%d") % drc->getTag() % static_cast<int>(drc->d_algorithm)).str());
 
-        toSign.push_back(rec.d_content);
-        toSignTags.push_back(drc->getTag());
+          toSign.push_back(rec.d_content);
+          toSignTags.push_back(drc->getTag());
+        }
       }
     }
     //    cerr<<"got "<<tkeys.size()<<" keys and "<<sigs.size()<<" sigs from server"<<endl;
@@ -339,10 +343,12 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset)
             for(const auto& r : v.second.records) {
               LOG("\t"<<r->getZoneRepresentation()<<endl);
               auto nsec = std::dynamic_pointer_cast<NSECRecordContent>(r);
-              if(v.first.first == qname && !nsec->d_set.count(QType::DS))
-                return Insecure;
-              else {
-                LOG("Did not deny existence of DS, "<<v.first.first<<"?="<<qname<<", "<<nsec->d_set.count(QType::DS)<<endl);
+              if(nsec) {
+                if(v.first.first == qname && !nsec->d_set.count(QType::DS))
+                  return Insecure;
+                else {
+                  LOG("Did not deny existence of DS, "<<v.first.first<<"?="<<qname<<", "<<nsec->d_set.count(QType::DS)<<endl);
+                }
               }
             }
 
@@ -354,11 +360,13 @@ vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, keyset_t &keyset)
         for(auto j=cspiter->second.records.cbegin(); j!=cspiter->second.records.cend(); j++)
         {
           const auto dsrc=std::dynamic_pointer_cast<DSRecordContent>(*j);
-          dsmap.insert(make_pair(dsrc->d_tag, *dsrc));
-          // dotEdge(keyqname,
-          //         "DNSKEY", keyqname, ,
-          //         "DS", qname, std::to_string(dsrc.d_tag));
-          // cout<<"    "<<dotEscape("DNSKEY "+keyqname)<<" -> "<<dotEscape("DS "+qname)<<";"<<endl;
+          if(dsrc) {
+            dsmap.insert(make_pair(dsrc->d_tag, *dsrc));
+            // dotEdge(keyqname,
+            //         "DNSKEY", keyqname, ,
+            //         "DS", qname, std::to_string(dsrc.d_tag));
+            // cout<<"    "<<dotEscape("DNSKEY "+keyqname)<<" -> "<<dotEscape("DS "+qname)<<";"<<endl;
+          }
         }
       }
       if(!dsmap.size()) {