From: Remi Gacogne Date: Mon, 25 Apr 2016 15:27:44 +0000 (+0200) Subject: rec: Drop non-IN records from auths, check for invalid record content X-Git-Tag: rec-4.0.0-alpha3~36^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F3768%2Fhead;p=thirdparty%2Fpdns.git rec: Drop non-IN records from auths, check for invalid record content Fix a crash in case of a bogus response from an authoritative server. --- diff --git a/pdns/filterpo.cc b/pdns/filterpo.cc index 259350d3a7..d3d6115f66 100644 --- a/pdns/filterpo.cc +++ b/pdns/filterpo.cc @@ -80,10 +80,16 @@ DNSFilterEngine::Policy DNSFilterEngine::getPostPolicy(const vector& for(const auto& r : records) { if(r.d_place != DNSResourceRecord::ANSWER) continue; - if(r.d_type == QType::A) - ca = std::dynamic_pointer_cast(r.d_content)->getCA(); - else if(r.d_type == QType::AAAA) - ca = std::dynamic_pointer_cast(r.d_content)->getCA(); + if(r.d_type == QType::A) { + if (auto rec = getRR(r)) { + ca = rec->getCA(); + } + } + else if(r.d_type == QType::AAAA) { + if (auto rec = getRR(r)) { + ca = rec->getCA(); + } + } else continue; diff --git a/pdns/ixfr.cc b/pdns/ixfr.cc index 2170a70456..7e53f938b0 100644 --- a/pdns/ixfr.cc +++ b/pdns/ixfr.cc @@ -73,23 +73,24 @@ vector, vector > > 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(r.first.d_content); - if(!masterSOA) { - if(sr->d_st.serial == std::dynamic_pointer_cast(oursr.d_content)->d_st.serial) // we are up to date + auto sr = getRR(r.first); + if(sr) { + if(!masterSOA) { + if(sr->d_st.serial == std::dynamic_pointer_cast(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[pos].d_content); + auto sr = getRR(records[pos]); vector remove, add; if(!sr) { // this is an actual AXFR! return {{remove, records}}; @@ -102,7 +103,7 @@ vector, vector > > 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(records[pos].d_content); + sr = getRR(records[pos]); add.push_back(records[pos]); // this adds the new SOA for(pos++; pos < records.size() && records[pos].d_type != QType::SOA; ++pos) { diff --git a/pdns/lua-recursor4.cc b/pdns/lua-recursor4.cc index adc1c49840..76ab32149a 100644 --- a/pdns/lua-recursor4.cc +++ b/pdns/lua-recursor4.cc @@ -61,8 +61,11 @@ static int followCNAMERecords(vector& ret, const QType& qtype) DNSName target; for(const DNSRecord& rr : ret) { if(rr.d_type == QType::CNAME) { - target=getRR(rr)->getTarget(); - break; + auto rec = getRR(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(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(prefixAddress); - rr.d_type = QType::AAAA; + if(auto rec = getRR(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(prefixAddress); + rr.d_type = QType::AAAA; + } } } return rcode; diff --git a/pdns/reczones.cc b/pdns/reczones.cc index c1e8453d45..2bc781c5d1 100644 --- a/pdns/reczones.cc +++ b/pdns/reczones.cc @@ -319,7 +319,7 @@ void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, const std:: sleep(refresh); - L<(dr.d_content)->d_st.serial<(dr)->d_st.serial<, vector > > 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(rr.d_content); - if(oldsr->d_st.serial == oursr->d_st.serial) { + auto oldsr = getRR(rr); + if(oldsr && oldsr->d_st.serial == oursr->d_st.serial) { // cout<<"Got good removal of SOA serial "<d_st.serial<(rr.d_content); + auto newsr = getRR(rr); // L<d_st.serial< src=std::dynamic_pointer_cast(drc.first.d_content); - *theirSerial=src->d_st.serial; - gotSOA = true; + shared_ptr src=getRR(drc.first); + if (src) { + *theirSerial=src->d_st.serial; + gotSOA = true; + } } if(drc.first.d_type == QType::RRSIG) { - shared_ptr rrc=std::dynamic_pointer_cast(drc.first.d_content); - if(rrc->d_type == QType::SOA) { + shared_ptr rrc=getRR(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* records) // checkTSIG = true; if(answer.first.d_type == QType::TSIG) { - shared_ptr trc = std::dynamic_pointer_cast(answer.first.d_content); - theirMac = trc->d_mac; - d_trc.d_time = trc->d_time; - checkTSIG = true; + shared_ptr trc = getRR(answer.first); + if(trc) { + theirMac = trc->d_mac; + d_trc.d_time = trc->d_time; + checkTSIG = true; + } } } diff --git a/pdns/rpzloader.cc b/pdns/rpzloader.cc index 6be490f9fd..4c27a8f3c5 100644 --- a/pdns/rpzloader.cc +++ b/pdns/rpzloader.cc @@ -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(dr.d_content)->getTarget(); + auto crc = getRR(dr); + if (!crc) { + return; + } + auto target=crc->getTarget(); if(defpol) { pol=*defpol; } @@ -118,7 +126,7 @@ shared_ptr loadRPZFromServer(const ComboAddress& master, const dr.d_name.makeUsRelative(zone); if(dr.d_type==QType::SOA) { - sr = std::dynamic_pointer_cast(dr.d_content); + sr = getRR(dr); continue; } diff --git a/pdns/syncres.cc b/pdns/syncres.cc index 668ebfb17d..da0482d492 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -504,8 +504,10 @@ vector SyncRes::getAddrs(const DNSName &qname, int depth, setget(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(k->d_content)->getCA(53); - ret.push_back(ca); + if (auto drc = std::dynamic_pointer_cast(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 aset; const DNSRecord& dr=*k; - auto nrr = std::dynamic_pointer_cast(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(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< '"<getNS()<<"'"<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(dr.d_content)->getNS())); + answer.bestns.insert(make_pair(dr.d_name, getRR(dr)->getNS())); if(beenthere.count(answer)) { brokeloop=true; @@ -892,7 +894,7 @@ recsig_t harvestRecords(const vector& records, const set& t for(const auto& rec : records) { if(rec.d_type == QType::RRSIG) { auto rrs=getRR(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(rec.d_content); - // cerr<<"Got an RRSIG for "<d_type)<<" with name '"<d_type, rec.d_place}].signatures.push_back(rrsig); + auto rrsig = getRR(rec); + if (rrsig) { + // cerr<<"Got an RRSIG for "<d_type)<<" with name '"<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<(rec.d_content)->getTarget(); + if (auto content = getRR(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< '"<getZoneRepresentation()<<"', had '"<(rec.d_content)->getNS()); + if (auto content = getRR(rec)) { + nsset.insert(content->getNS()); + } } else if(rec.d_place==DNSResourceRecord::AUTHORITY && qname.isPartOf(rec.d_name) && rec.d_type==QType::DS) { LOG(prefix< '"<getZoneRepresentation()<<"'"<& recs) if(rec.d_type == QType::RRSIG) { auto rrc = getRR(rec); - cspmap[{rec.d_name,rrc->d_type}].signatures.push_back(getRR(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 (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 (rec); - tkeys.insert(*drc); - // cerr<<"Inserting key with tag "<getTag()<<": "<getZoneRepresentation()<getTag()), (boost::format("tag=%d, algo=%d") % drc->getTag() % static_cast(drc->d_algorithm)).str()); + if(drc) { + tkeys.insert(*drc); + // cerr<<"Inserting key with tag "<getTag()<<": "<getZoneRepresentation()<getTag()), (boost::format("tag=%d, algo=%d") % drc->getTag() % static_cast(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 "<getZoneRepresentation()<(r); - if(v.first.first == qname && !nsec->d_set.count(QType::DS)) - return Insecure; - else { - LOG("Did not deny existence of DS, "<d_set.count(QType::DS)<d_set.count(QType::DS)) + return Insecure; + else { + LOG("Did not deny existence of DS, "<d_set.count(QType::DS)<second.records.cbegin(); j!=cspiter->second.records.cend(); j++) { const auto dsrc=std::dynamic_pointer_cast(*j); - dsmap.insert(make_pair(dsrc->d_tag, *dsrc)); - // dotEdge(keyqname, - // "DNSKEY", keyqname, , - // "DS", qname, std::to_string(dsrc.d_tag)); - // cout<<" "< "<d_tag, *dsrc)); + // dotEdge(keyqname, + // "DNSKEY", keyqname, , + // "DS", qname, std::to_string(dsrc.d_tag)); + // cout<<" "< "<