Package: release.debian.org Severity: normal Tags: stretch User: release.debian....@packages.debian.org Usertags: pu
Dear Release Team, I've prepared an update for pdns-recursor, which fixes some CVE issues. As they are not critical bugs, security and me have agreed to do this via a normal stable update, if that's okay with you too. Sec bug: #913162 Thanks, Chris diff -Nru pdns-recursor-4.0.4/debian/changelog pdns-recursor-4.0.4/debian/changelog --- pdns-recursor-4.0.4/debian/changelog 2017-12-07 12:40:02.000000000 +0000 +++ pdns-recursor-4.0.4/debian/changelog 2018-11-10 16:05:33.000000000 +0000 @@ -1,3 +1,9 @@ +pdns-recursor (4.0.4-1+deb9u4) stretch-security; urgency=high + + * Security upload for CVE-2018-10851 CVE-2018-14626 CVE-2018-14644 (Closes: #913162). + + -- Chris Hofstaedtler <z...@debian.org> Sat, 10 Nov 2018 16:05:33 +0000 + pdns-recursor (4.0.4-1+deb9u3) stretch-security; urgency=high * Security upload, including fix for CVE-2017-15120. diff -Nru pdns-recursor-4.0.4/debian/patches/CVE-2018-10851-rec-4.0.8.patch pdns-recursor-4.0.4/debian/patches/CVE-2018-10851-rec-4.0.8.patch --- pdns-recursor-4.0.4/debian/patches/CVE-2018-10851-rec-4.0.8.patch 1970-01-01 00:00:00.000000000 +0000 +++ pdns-recursor-4.0.4/debian/patches/CVE-2018-10851-rec-4.0.8.patch 2018-11-10 16:05:33.000000000 +0000 @@ -0,0 +1,396 @@ +diff -ru pdns-recursor-4.0.8.orig/dnsparser.cc pdns-recursor-4.0.8/dnsparser.cc +--- pdns-recursor-4.0.8.orig/dnsparser.cc 2017-12-11 11:38:52.000000000 +0100 ++++ pdns-recursor-4.0.8/dnsparser.cc 2018-10-10 10:29:54.182145934 +0200 +@@ -121,54 +121,42 @@ + return ret; + } + +-DNSRecordContent* DNSRecordContent::mastermake(const DNSRecord &dr, +- PacketReader& pr) ++std::shared_ptr<DNSRecordContent> DNSRecordContent::mastermake(const DNSRecord &dr, ++ PacketReader& pr) + { + uint16_t searchclass = (dr.d_type == QType::OPT) ? 1 : dr.d_class; // class is invalid for OPT + + typemap_t::const_iterator i=getTypemap().find(make_pair(searchclass, dr.d_type)); + if(i==getTypemap().end() || !i->second) { +- return new UnknownRecordContent(dr, pr); ++ return std::make_shared<UnknownRecordContent>(dr, pr); + } + + return i->second(dr, pr); + } + +-DNSRecordContent* DNSRecordContent::mastermake(uint16_t qtype, uint16_t qclass, +- const string& content) ++std::shared_ptr<DNSRecordContent> DNSRecordContent::mastermake(uint16_t qtype, uint16_t qclass, ++ const string& content) + { + zmakermap_t::const_iterator i=getZmakermap().find(make_pair(qclass, qtype)); + if(i==getZmakermap().end()) { +- return new UnknownRecordContent(content); ++ return std::make_shared<UnknownRecordContent>(content); + } + + return i->second(content); + } + +-std::unique_ptr<DNSRecordContent> DNSRecordContent::makeunique(uint16_t qtype, uint16_t qclass, +- const string& content) +-{ +- zmakermap_t::const_iterator i=getZmakermap().find(make_pair(qclass, qtype)); +- if(i==getZmakermap().end()) { +- return std::unique_ptr<DNSRecordContent>(new UnknownRecordContent(content)); +- } +- +- return std::unique_ptr<DNSRecordContent>(i->second(content)); +-} +- +- +-DNSRecordContent* DNSRecordContent::mastermake(const DNSRecord &dr, PacketReader& pr, uint16_t oc) { ++std::shared_ptr<DNSRecordContent> DNSRecordContent::mastermake(const DNSRecord &dr, PacketReader& pr, uint16_t oc) { + // For opcode UPDATE and where the DNSRecord is an answer record, we don't care about content, because this is + // not used within the prerequisite section of RFC2136, so - we can simply use unknownrecordcontent. + // For section 3.2.3, we do need content so we need to get it properly. But only for the correct Qclasses. + if (oc == Opcode::Update && dr.d_place == DNSResourceRecord::ANSWER && dr.d_class != 1) +- return new UnknownRecordContent(dr, pr); ++ return std::make_shared<UnknownRecordContent>(dr, pr); + + uint16_t searchclass = (dr.d_type == QType::OPT) ? 1 : dr.d_class; // class is invalid for OPT + + typemap_t::const_iterator i=getTypemap().find(make_pair(searchclass, dr.d_type)); + if(i==getTypemap().end() || !i->second) { +- return new UnknownRecordContent(dr, pr); ++ return std::make_shared<UnknownRecordContent>(dr, pr); + } + + return i->second(dr, pr); +diff -ru pdns-recursor-4.0.8.orig/dnsparser.hh pdns-recursor-4.0.8/dnsparser.hh +--- pdns-recursor-4.0.8.orig/dnsparser.hh 2017-12-11 11:38:52.000000000 +0100 ++++ pdns-recursor-4.0.8/dnsparser.hh 2018-10-10 10:29:54.182145934 +0200 +@@ -166,10 +166,9 @@ + class DNSRecordContent + { + public: +- static DNSRecordContent* mastermake(const DNSRecord &dr, PacketReader& pr); +- static DNSRecordContent* mastermake(const DNSRecord &dr, PacketReader& pr, uint16_t opcode); +- static DNSRecordContent* mastermake(uint16_t qtype, uint16_t qclass, const string& zone); +- static std::unique_ptr<DNSRecordContent> makeunique(uint16_t qtype, uint16_t qclass, const string& content); ++ static std::shared_ptr<DNSRecordContent> mastermake(const DNSRecord &dr, PacketReader& pr); ++ static std::shared_ptr<DNSRecordContent> mastermake(const DNSRecord &dr, PacketReader& pr, uint16_t opcode); ++ static std::shared_ptr<DNSRecordContent> mastermake(uint16_t qtype, uint16_t qclass, const string& zone); + + virtual std::string getZoneRepresentation(bool noDot=false) const = 0; + virtual ~DNSRecordContent() {} +@@ -198,8 +197,8 @@ + + void doRecordCheck(const struct DNSRecord&){} + +- typedef DNSRecordContent* makerfunc_t(const struct DNSRecord& dr, PacketReader& pr); +- typedef DNSRecordContent* zmakerfunc_t(const string& str); ++ typedef std::shared_ptr<DNSRecordContent> makerfunc_t(const struct DNSRecord& dr, PacketReader& pr); ++ typedef std::shared_ptr<DNSRecordContent> zmakerfunc_t(const string& str); + + static void regist(uint16_t cl, uint16_t ty, makerfunc_t* f, zmakerfunc_t* z, const char* name) + { +diff -ru pdns-recursor-4.0.8.orig/dnsrecords.cc pdns-recursor-4.0.8/dnsrecords.cc +--- pdns-recursor-4.0.8.orig/dnsrecords.cc 2017-12-11 11:38:52.000000000 +0100 ++++ pdns-recursor-4.0.8/dnsrecords.cc 2018-10-10 10:29:54.182145934 +0200 +@@ -386,19 +386,19 @@ + { + regist(1, QType::EUI48, &make, &make, "EUI48"); + } +-DNSRecordContent* EUI48RecordContent::make(const DNSRecord &dr, PacketReader& pr) ++std::shared_ptr<DNSRecordContent> EUI48RecordContent::make(const DNSRecord &dr, PacketReader& pr) + { + if(dr.d_clen!=6) + throw MOADNSException("Wrong size for EUI48 record"); + +- EUI48RecordContent* ret=new EUI48RecordContent(); ++ auto ret=std::make_shared<EUI48RecordContent>(); + pr.copyRecord((uint8_t*) &ret->d_eui48, 6); + return ret; + } +-DNSRecordContent* EUI48RecordContent::make(const string& zone) ++std::shared_ptr<DNSRecordContent> EUI48RecordContent::make(const string& zone) + { + // try to parse +- EUI48RecordContent *ret=new EUI48RecordContent(); ++ auto ret=std::make_shared<EUI48RecordContent>(); + // format is 6 hex bytes and dashes + if (sscanf(zone.c_str(), "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx", + ret->d_eui48, ret->d_eui48+1, ret->d_eui48+2, +@@ -429,19 +429,19 @@ + { + regist(1, QType::EUI64, &make, &make, "EUI64"); + } +-DNSRecordContent* EUI64RecordContent::make(const DNSRecord &dr, PacketReader& pr) ++std::shared_ptr<DNSRecordContent> EUI64RecordContent::make(const DNSRecord &dr, PacketReader& pr) + { + if(dr.d_clen!=8) + throw MOADNSException("Wrong size for EUI64 record"); + +- EUI64RecordContent* ret=new EUI64RecordContent(); ++ auto ret=std::make_shared<EUI64RecordContent>(); + pr.copyRecord((uint8_t*) &ret->d_eui64, 8); + return ret; + } +-DNSRecordContent* EUI64RecordContent::make(const string& zone) ++std::shared_ptr<DNSRecordContent> EUI64RecordContent::make(const string& zone) + { + // try to parse +- EUI64RecordContent *ret=new EUI64RecordContent(); ++ auto ret=std::make_shared<EUI64RecordContent>(); + // format is 8 hex bytes and dashes + if (sscanf(zone.c_str(), "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx", + ret->d_eui64, ret->d_eui64+1, ret->d_eui64+2, +diff -ru pdns-recursor-4.0.8.orig/dnsrecords.hh pdns-recursor-4.0.8/dnsrecords.hh +--- pdns-recursor-4.0.8.orig/dnsrecords.hh 2017-12-11 11:38:52.000000000 +0100 ++++ pdns-recursor-4.0.8/dnsrecords.hh 2018-10-10 10:29:54.182145934 +0200 +@@ -33,8 +33,8 @@ + RNAME##RecordContent(const string& zoneData); \ + static void report(void); \ + static void unreport(void); \ +- static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr); \ +- static DNSRecordContent* make(const string& zonedata); \ ++ static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); \ ++ static std::shared_ptr<DNSRecordContent> make(const string& zonedata); \ + string getZoneRepresentation(bool noDot=false) const override; \ + void toPacket(DNSPacketWriter& pw) override; \ + uint16_t getType() const override { return QType::RNAME; } \ +@@ -467,8 +467,8 @@ + {} + NSECRecordContent(const string& content, const string& zone=""); //FIXME400: DNSName& zone? + +- static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr); +- static DNSRecordContent* make(const string& content); ++ static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); ++ static std::shared_ptr<DNSRecordContent> make(const string& content); + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + uint16_t getType() const override +@@ -488,8 +488,8 @@ + {} + NSEC3RecordContent(const string& content, const string& zone=""); //FIXME400: DNSName& zone? + +- static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr); +- static DNSRecordContent* make(const string& content); ++ static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); ++ static std::shared_ptr<DNSRecordContent> make(const string& content); + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + +@@ -517,8 +517,8 @@ + {} + NSEC3PARAMRecordContent(const string& content, const string& zone=""); // FIXME400: DNSName& zone? + +- static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr); +- static DNSRecordContent* make(const string& content); ++ static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); ++ static std::shared_ptr<DNSRecordContent> make(const string& content); + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + +@@ -542,8 +542,8 @@ + {} + LOCRecordContent(const string& content, const string& zone=""); + +- static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr); +- static DNSRecordContent* make(const string& content); ++ static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); ++ static std::shared_ptr<DNSRecordContent> make(const string& content); + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + +@@ -566,8 +566,8 @@ + {} + WKSRecordContent(const string& content, const string& zone=""); // FIXME400: DNSName& zone? + +- static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr); +- static DNSRecordContent* make(const string& content); ++ static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); ++ static std::shared_ptr<DNSRecordContent> make(const string& content); + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + +@@ -581,8 +581,8 @@ + public: + EUI48RecordContent() {}; + static void report(void); +- static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr); +- static DNSRecordContent* make(const string& zone); // FIXME400: DNSName& zone? ++ static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); ++ static std::shared_ptr<DNSRecordContent> make(const string& zone); // FIXME400: DNSName& zone? + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + uint16_t getType() const override { return QType::EUI48; } +@@ -596,8 +596,8 @@ + public: + EUI64RecordContent() {}; + static void report(void); +- static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr); +- static DNSRecordContent* make(const string& zone); // FIXME400: DNSName& zone? ++ static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); ++ static std::shared_ptr<DNSRecordContent> make(const string& zone); // FIXME400: DNSName& zone? + string getZoneRepresentation(bool noDot=false) const override; + void toPacket(DNSPacketWriter& pw) override; + uint16_t getType() const override { return QType::EUI64; } +@@ -644,9 +644,9 @@ + }; + + #define boilerplate(RNAME, RTYPE) \ +-RNAME##RecordContent::DNSRecordContent* RNAME##RecordContent::make(const DNSRecord& dr, PacketReader& pr) \ ++std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::make(const DNSRecord& dr, PacketReader& pr) \ + { \ +- return new RNAME##RecordContent(dr, pr); \ ++ return std::make_shared<RNAME##RecordContent>(dr, pr); \ + } \ + \ + RNAME##RecordContent::RNAME##RecordContent(const DNSRecord& dr, PacketReader& pr) \ +@@ -655,9 +655,9 @@ + xfrPacket(pr); \ + } \ + \ +-RNAME##RecordContent::DNSRecordContent* RNAME##RecordContent::make(const string& zonedata) \ ++std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::make(const string& zonedata) \ + { \ +- return new RNAME##RecordContent(zonedata); \ ++ return std::make_shared<RNAME##RecordContent>(zonedata); \ + } \ + \ + void RNAME##RecordContent::toPacket(DNSPacketWriter& pw) \ +diff -ru pdns-recursor-4.0.8.orig/nsecrecords.cc pdns-recursor-4.0.8/nsecrecords.cc +--- pdns-recursor-4.0.8.orig/nsecrecords.cc 2017-12-11 11:38:52.000000000 +0100 ++++ pdns-recursor-4.0.8/nsecrecords.cc 2018-10-10 10:29:54.182145934 +0200 +@@ -29,9 +29,9 @@ + regist(1, 47, &make, &make, "NSEC"); + } + +-DNSRecordContent* NSECRecordContent::make(const string& content) ++std::shared_ptr<DNSRecordContent> NSECRecordContent::make(const string& content) + { +- return new NSECRecordContent(content); ++ return std::make_shared<NSECRecordContent>(content); + } + + NSECRecordContent::NSECRecordContent(const string& content, const string& zone) +@@ -81,9 +81,9 @@ + pw.xfrBlob(tmp); + } + +-NSECRecordContent::DNSRecordContent* NSECRecordContent::make(const DNSRecord &dr, PacketReader& pr) ++std::shared_ptr<NSECRecordContent::DNSRecordContent> NSECRecordContent::make(const DNSRecord &dr, PacketReader& pr) + { +- NSECRecordContent* ret=new NSECRecordContent(); ++ auto ret=std::make_shared<NSECRecordContent>(); + pr.xfrName(ret->d_next); + string bitmap; + pr.xfrBlob(bitmap); +@@ -136,9 +136,9 @@ + regist(1, 50, &make, &make, "NSEC3"); + } + +-DNSRecordContent* NSEC3RecordContent::make(const string& content) ++std::shared_ptr<DNSRecordContent> NSEC3RecordContent::make(const string& content) + { +- return new NSEC3RecordContent(content); ++ return std::make_shared<NSEC3RecordContent>(content); + } + + NSEC3RecordContent::NSEC3RecordContent(const string& content, const string& zone) +@@ -203,9 +203,9 @@ + } + } + +-NSEC3RecordContent::DNSRecordContent* NSEC3RecordContent::make(const DNSRecord &dr, PacketReader& pr) ++std::shared_ptr<NSEC3RecordContent::DNSRecordContent> NSEC3RecordContent::make(const DNSRecord &dr, PacketReader& pr) + { +- NSEC3RecordContent* ret=new NSEC3RecordContent(); ++ auto ret=std::make_shared<NSEC3RecordContent>(); + pr.xfr8BitInt(ret->d_algorithm); + pr.xfr8BitInt(ret->d_flags); + pr.xfr16BitInt(ret->d_iterations); +@@ -273,9 +273,9 @@ + regist(254, 51, &make, &make, "NSEC3PARAM"); + } + +-DNSRecordContent* NSEC3PARAMRecordContent::make(const string& content) ++std::shared_ptr<DNSRecordContent> NSEC3PARAMRecordContent::make(const string& content) + { +- return new NSEC3PARAMRecordContent(content); ++ return std::make_shared<NSEC3PARAMRecordContent>(content); + } + + NSEC3PARAMRecordContent::NSEC3PARAMRecordContent(const string& content, const string& zone) +@@ -297,9 +297,9 @@ + pw.xfrBlob(d_salt); + } + +-NSEC3PARAMRecordContent::DNSRecordContent* NSEC3PARAMRecordContent::make(const DNSRecord &dr, PacketReader& pr) ++std::shared_ptr<NSEC3PARAMRecordContent::DNSRecordContent> NSEC3PARAMRecordContent::make(const DNSRecord &dr, PacketReader& pr) + { +- NSEC3PARAMRecordContent* ret=new NSEC3PARAMRecordContent(); ++ auto ret=std::make_shared<NSEC3PARAMRecordContent>(); + pr.xfr8BitInt(ret->d_algorithm); + pr.xfr8BitInt(ret->d_flags); + pr.xfr16BitInt(ret->d_iterations); +diff -ru pdns-recursor-4.0.8.orig/rec-lua-conf.cc pdns-recursor-4.0.8/rec-lua-conf.cc +--- pdns-recursor-4.0.8.orig/rec-lua-conf.cc 2017-12-11 11:38:52.000000000 +0100 ++++ pdns-recursor-4.0.8/rec-lua-conf.cc 2018-10-10 10:29:54.182145934 +0200 +@@ -35,7 +35,7 @@ + LuaConfigItems::LuaConfigItems() + { + for (const auto &dsRecord : rootDSs) { +- auto ds=unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make(dsRecord))); ++ auto ds=std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(dsRecord)); + dsAnchors[DNSName(".")].insert(*ds); + } + } +@@ -240,7 +240,7 @@ + + Lua.writeFunction("addDS", [&lci](const std::string& who, const std::string& what) { + DNSName zone(who); +- auto ds = unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make(what))); ++ auto ds=std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what)); + lci.dsAnchors[zone].insert(*ds); + }); + +diff -ru pdns-recursor-4.0.8.orig/rec_channel_rec.cc pdns-recursor-4.0.8/rec_channel_rec.cc +--- pdns-recursor-4.0.8.orig/rec_channel_rec.cc 2017-12-11 11:38:52.000000000 +0100 ++++ pdns-recursor-4.0.8/rec_channel_rec.cc 2018-10-10 10:29:54.182145934 +0200 +@@ -490,7 +490,7 @@ + try { + L<<Logger::Warning<<"Adding Trust Anchor for "<<who<<" with data '"<<what<<"', requested via control channel"; + g_luaconfs.modify([who, what](LuaConfigItems& lci) { +- auto ds = unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make(what))); ++ auto ds=std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what)); + lci.dsAnchors[who].insert(*ds); + }); + broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, who, true)); +diff -ru pdns-recursor-4.0.8.orig/sillyrecords.cc pdns-recursor-4.0.8/sillyrecords.cc +--- pdns-recursor-4.0.8.orig/sillyrecords.cc 2017-12-11 11:38:52.000000000 +0100 ++++ pdns-recursor-4.0.8/sillyrecords.cc 2018-10-10 10:29:54.182145934 +0200 +@@ -159,9 +159,9 @@ + regist(254, QType::LOC, &make, &make, "LOC"); + } + +-DNSRecordContent* LOCRecordContent::make(const string& content) ++std::shared_ptr<DNSRecordContent> LOCRecordContent::make(const string& content) + { +- return new LOCRecordContent(content); ++ return std::make_shared<LOCRecordContent>(content); + } + + +@@ -177,9 +177,9 @@ + pw.xfr32BitInt(d_altitude); + } + +-LOCRecordContent::DNSRecordContent* LOCRecordContent::make(const DNSRecord &dr, PacketReader& pr) ++std::shared_ptr<LOCRecordContent::DNSRecordContent> LOCRecordContent::make(const DNSRecord &dr, PacketReader& pr) + { +- LOCRecordContent* ret=new LOCRecordContent(); ++ auto ret=std::make_shared<LOCRecordContent>(); + pr.xfr8BitInt(ret->d_version); + pr.xfr8BitInt(ret->d_size); + pr.xfr8BitInt(ret->d_horizpre); diff -Nru pdns-recursor-4.0.4/debian/patches/CVE-2018-14626-rec-4.0.8.patch pdns-recursor-4.0.4/debian/patches/CVE-2018-14626-rec-4.0.8.patch --- pdns-recursor-4.0.4/debian/patches/CVE-2018-14626-rec-4.0.8.patch 1970-01-01 00:00:00.000000000 +0000 +++ pdns-recursor-4.0.4/debian/patches/CVE-2018-14626-rec-4.0.8.patch 2018-11-10 16:05:33.000000000 +0000 @@ -0,0 +1,238 @@ +diff -ru pdns-recursor-4.0.8.orig/pdns_recursor.cc pdns-recursor-4.0.8/pdns_recursor.cc +--- pdns-recursor-4.0.8.orig/pdns_recursor.cc 2017-12-11 11:38:52.000000000 +0100 ++++ pdns-recursor-4.0.8/pdns_recursor.cc 2018-10-09 17:14:58.052450425 +0200 +@@ -1134,7 +1134,7 @@ + if(sendmsg(dc->d_socket, &msgh, 0) < 0 && g_logCommonErrors) + L<<Logger::Warning<<"Sending UDP reply to client "<<dc->d_remote.toStringWithPort()<<" failed with: "<<strerror(errno)<<endl; + if(!SyncRes::s_nopacketcache && !variableAnswer && !sr.wasVariable() ) { +- t_packetCache->insertResponsePacket(dc->d_tag, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_query, ++ t_packetCache->insertResponsePacket(dc->d_tag, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass, dc->d_query, + string((const char*)&*packet.begin(), packet.size()), + g_now.tv_sec, + pw.getHeader()->rcode == RCode::ServFail ? SyncRes::s_packetcacheservfailttl : +diff -ru pdns-recursor-4.0.8.orig/recpacketcache.cc pdns-recursor-4.0.8/recpacketcache.cc +--- pdns-recursor-4.0.8.orig/recpacketcache.cc 2017-12-11 11:38:52.000000000 +0100 ++++ pdns-recursor-4.0.8/recpacketcache.cc 2018-10-09 17:08:20.176479437 +0200 +@@ -42,17 +42,59 @@ + return count; + } + ++static bool queryHeaderMatches(const std::string& cachedQuery, const std::string& query) ++{ ++ if (cachedQuery.size() != query.size()) { ++ return false; ++ } ++ ++ return (cachedQuery.compare(/* skip the ID */ 2, sizeof(dnsheader) - 2, query, 2, sizeof(dnsheader) - 2) == 0); ++} ++ ++bool RecursorPacketCache::queryMatches(const std::string& cachedQuery, const std::string& query, const DNSName& qname, uint16_t ecsBegin, uint16_t ecsEnd) ++{ ++ if (!queryHeaderMatches(cachedQuery, query)) { ++ return false; ++ } ++ ++ size_t pos = sizeof(dnsheader) + qname.wirelength(); ++ ++ if (ecsBegin != 0 && ecsBegin >= pos && ecsEnd > ecsBegin) { ++ if (cachedQuery.compare(pos, ecsBegin - pos, query, pos, ecsBegin - pos) != 0) { ++ return false; ++ } ++ ++ if (cachedQuery.compare(ecsEnd, cachedQuery.size() - ecsEnd, query, ecsEnd, query.size() - ecsEnd) != 0) { ++ return false; ++ } ++ } ++ else { ++ if (cachedQuery.compare(pos, cachedQuery.size() - pos, query, pos, query.size() - pos) != 0) { ++ return false; ++ } ++ } ++ ++ return true; ++} ++ + // one day this function could be really fast by doing only a case insensitive compare +-static bool qrMatch(const std::string& query, const std::string& response) ++bool RecursorPacketCache::qrMatch(const packetCache_t::index<HashTag>::type::iterator& iter, const std::string& queryPacket, uint16_t ecsBegin, uint16_t ecsEnd) + { +- uint16_t rqtype, rqclass, qqtype, qqclass; +- DNSName queryname(query.c_str(), query.length(), sizeof(dnsheader), false, &qqtype, &qqclass, 0); +- DNSName respname(response.c_str(), response.length(), sizeof(dnsheader), false, &rqtype, &rqclass, 0); +- // this ignores checking on the EDNS subnet flags! +- return queryname==respname && rqtype == qqtype && rqclass == qqclass; ++ uint16_t qqtype, qqclass; ++ DNSName queryname(queryPacket.c_str(), queryPacket.length(), sizeof(dnsheader), false, &qqtype, &qqclass, 0); ++ // this ignores checking on the EDNS subnet flags! ++ if (qqtype != iter->d_type || qqclass != iter->d_class || queryname != iter->d_name) { ++ return false; ++ } ++ ++ if (iter->d_ecsBegin != ecsBegin || iter->d_ecsEnd != ecsEnd) { ++ return false; ++ } ++ ++ return queryMatches(iter->d_query, queryPacket, queryname, ecsBegin, ecsEnd); + } + +-uint32_t RecursorPacketCache::canHashPacket(const std::string& origPacket) ++uint32_t RecursorPacketCache::canHashPacket(const std::string& origPacket, uint16_t* ecsBegin, uint16_t* ecsEnd) + { + // return 42; // should still work if you do this! + uint32_t ret=0; +@@ -68,6 +110,10 @@ + struct dnsheader* dh = (struct dnsheader*)origPacket.c_str(); + const char* skipBegin = p; + const char* skipEnd = p; ++ if (ecsBegin != nullptr && ecsEnd != nullptr) { ++ *ecsBegin = 0; ++ *ecsEnd = 0; ++ } + /* we need at least 1 (final empty label) + 2 (QTYPE) + 2 (QCLASS) + + OPT root label (1), type (2), class (2) and ttl (4) + + the OPT RR rdlen (2) +@@ -82,6 +128,10 @@ + if (res == 0) { + skipBegin = optionBegin; + skipEnd = optionBegin + optionLen; ++ if (ecsBegin != nullptr && ecsEnd != nullptr) { ++ *ecsBegin = optionBegin - origPacket.c_str(); ++ *ecsEnd = *ecsBegin + optionLen; ++ } + } + } + if (skipBegin > p) { +@@ -96,15 +146,11 @@ + } + + bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, time_t now, +- std::string* responsePacket, uint32_t* age) +-{ +- return getResponsePacket(tag, queryPacket, now, responsePacket, age, nullptr); +-} +- +-bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, time_t now, + std::string* responsePacket, uint32_t* age, RecProtoBufMessage* protobufMessage) + { +- uint32_t h = canHashPacket(queryPacket); ++ uint16_t ecsBegin = 0; ++ uint16_t ecsEnd = 0; ++ uint32_t h = canHashPacket(queryPacket, &ecsBegin, &ecsEnd); + auto& idx = d_packetCache.get<HashTag>(); + auto range = idx.equal_range(tie(tag,h)); + +@@ -115,8 +161,9 @@ + + for(auto iter = range.first ; iter != range.second ; ++ iter) { + // the possibility is VERY real that we get hits that are not right - birthday paradox +- if(!qrMatch(queryPacket, iter->d_packet)) ++ if(!qrMatch(iter, queryPacket, ecsBegin, ecsEnd)) { + continue; ++ } + if((uint32_t)now < iter->d_ttd) { // it is right, it is fresh! + *age = now - iter->d_creation; + *responsePacket = iter->d_packet; +@@ -153,27 +200,28 @@ + } + + +-void RecursorPacketCache::insertResponsePacket(unsigned int tag, const DNSName& qname, uint16_t qtype, const std::string& queryPacket, const std::string& responsePacket, time_t now, uint32_t ttl) ++void RecursorPacketCache::insertResponsePacket(unsigned int tag, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::string& queryPacket, const std::string& responsePacket, time_t now, uint32_t ttl, const RecProtoBufMessage* protobufMessage) + { +- insertResponsePacket(tag, qname, qtype, queryPacket, responsePacket, now, ttl, nullptr); +-} +- +-void RecursorPacketCache::insertResponsePacket(unsigned int tag, const DNSName& qname, uint16_t qtype, const std::string& queryPacket, const std::string& responsePacket, time_t now, uint32_t ttl, const RecProtoBufMessage* protobufMessage) +-{ +- auto qhash = canHashPacket(queryPacket); ++ uint16_t ecsBegin = 0; ++ uint16_t ecsEnd = 0; ++ auto qhash = canHashPacket(queryPacket, &ecsBegin, &ecsEnd); + auto& idx = d_packetCache.get<HashTag>(); + auto range = idx.equal_range(tie(tag,qhash)); + auto iter = range.first; + + for( ; iter != range.second ; ++iter) { +- if(iter->d_type != qtype) ++ if(iter->d_type != qtype || iter->d_class != qclass) { + continue; ++ } + // this only happens on insert which is relatively rare and does not need to be super fast + DNSName respname(iter->d_packet.c_str(), iter->d_packet.length(), sizeof(dnsheader), false, 0, 0, 0); + if(qname != respname) + continue; + moveCacheItemToBack(d_packetCache, iter); + iter->d_packet = responsePacket; ++ iter->d_query = queryPacket; ++ iter->d_ecsBegin = ecsBegin; ++ iter->d_ecsEnd = ecsEnd; + iter->d_ttd = now + ttl; + iter->d_creation = now; + #ifdef HAVE_PROTOBUF +@@ -188,9 +236,13 @@ + if(iter == range.second) { // nothing to refresh + struct Entry e; + e.d_packet = responsePacket; ++ e.d_query = queryPacket; + e.d_name = qname; + e.d_qhash = qhash; + e.d_type = qtype; ++ e.d_class = qclass; ++ e.d_ecsBegin = ecsBegin; ++ e.d_ecsEnd = ecsEnd; + e.d_ttd = now+ttl; + e.d_creation = now; + e.d_tag = tag; +diff -ru pdns-recursor-4.0.8.orig/recpacketcache.hh pdns-recursor-4.0.8/recpacketcache.hh +--- pdns-recursor-4.0.8.orig/recpacketcache.hh 2017-12-11 11:38:52.000000000 +0100 ++++ pdns-recursor-4.0.8/recpacketcache.hh 2018-10-09 17:14:58.052450425 +0200 +@@ -50,10 +50,8 @@ + { + public: + RecursorPacketCache(); +- bool getResponsePacket(unsigned int tag, const std::string& queryPacket, time_t now, std::string* responsePacket, uint32_t* age); +- void insertResponsePacket(unsigned int tag, const DNSName& qname, uint16_t qtype, const std::string& queryPacket, const std::string& responsePacket, time_t now, uint32_t ttd); + bool getResponsePacket(unsigned int tag, const std::string& queryPacket, time_t now, std::string* responsePacket, uint32_t* age, RecProtoBufMessage* protobufMessage); +- void insertResponsePacket(unsigned int tag, const DNSName& qname, uint16_t qtype, const std::string& queryPacket, const std::string& responsePacket, time_t now, uint32_t ttd, const RecProtoBufMessage* protobufMessage); ++ void insertResponsePacket(unsigned int tag, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::string& queryPacket, const std::string& responsePacket, time_t now, uint32_t ttd, const RecProtoBufMessage* protobufMessage); + void doPruneTo(unsigned int maxSize=250000); + uint64_t doDump(int fd); + int doWipePacketCache(const DNSName& name, uint16_t qtype=0xffff, bool subtree=false); +@@ -72,12 +70,16 @@ + mutable uint32_t d_creation; // so we can 'age' our packets + DNSName d_name; + uint16_t d_type; ++ uint16_t d_class; + mutable std::string d_packet; // "I know what I am doing" ++ mutable std::string d_query; + #ifdef HAVE_PROTOBUF + mutable RecProtoBufMessage d_protobufMessage; + #endif + uint32_t d_qhash; + uint32_t d_tag; ++ mutable uint16_t d_ecsBegin; ++ mutable uint16_t d_ecsEnd; + inline bool operator<(const struct Entry& rhs) const; + + uint32_t getTTD() const +@@ -85,7 +87,7 @@ + return d_ttd; + } + }; +- uint32_t canHashPacket(const std::string& origPacket); ++ + typedef multi_index_container< + Entry, + indexed_by < +@@ -96,6 +98,11 @@ + > packetCache_t; + + packetCache_t d_packetCache; ++ ++public: ++ static bool queryMatches(const std::string& cachedQuery, const std::string& query, const DNSName& qname, uint16_t ecsBegin, uint16_t ecsEnd); ++ static bool qrMatch(const packetCache_t::index<HashTag>::type::iterator& iter, const std::string& queryPacket, uint16_t ecsBegin, uint16_t ecsEnd); ++ static uint32_t canHashPacket(const std::string& origPacket, uint16_t* ecsBegin, uint16_t* ecsEnd); + }; + + #endif diff -Nru pdns-recursor-4.0.4/debian/patches/CVE-2018-14644-rec-4.0.4.patch pdns-recursor-4.0.4/debian/patches/CVE-2018-14644-rec-4.0.4.patch --- pdns-recursor-4.0.4/debian/patches/CVE-2018-14644-rec-4.0.4.patch 1970-01-01 00:00:00.000000000 +0000 +++ pdns-recursor-4.0.4/debian/patches/CVE-2018-14644-rec-4.0.4.patch 2018-11-10 16:05:33.000000000 +0000 @@ -0,0 +1,25 @@ +From a61af1fcec7f9c5fb94a8cdba7dc0ac1f3e4791c Mon Sep 17 00:00:00 2001 +From: Chris Hofstaedtler <chris.hofstaedt...@deduktiva.com> +Date: Sat, 10 Nov 2018 17:02:30 +0100 +Subject: [PATCH] rec: Refuse queries for all meta-types + +Backport be44629dd2ef0f6805826fb6794f7a996c34aab4 from 4.1.x to 4.0.x +--- + syncres.cc | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/syncres.cc b/syncres.cc +index f121cfac2d..f8b39ee8fb 100644 +--- a/syncres.cc ++++ b/syncres.cc +@@ -128,7 +128,9 @@ int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qcl + d_wasVariable=false; + d_wasOutOfBand=false; + +- if( (qtype.getCode() == QType::AXFR)) ++ auto qtypeCode = qtype.getCode(); ++ /* rfc6895 section 3.1 */ ++ if ((qtypeCode >= 128 && qtypeCode <= 254) || qtypeCode == QType::RRSIG || qtypeCode == QType::NSEC3 || qtypeCode == QType::OPT || qtypeCode == 65535) + return -1; + + static const DNSName arpa("1.0.0.127.in-addr.arpa."), localhost("localhost."), diff -Nru pdns-recursor-4.0.4/debian/patches/series pdns-recursor-4.0.4/debian/patches/series --- pdns-recursor-4.0.4/debian/patches/series 2017-12-07 12:40:02.000000000 +0000 +++ pdns-recursor-4.0.4/debian/patches/series 2018-11-10 16:05:33.000000000 +0000 @@ -4,3 +4,6 @@ CVE-2017-15093-4.0.6.patch CVE-2017-15094-4.0.6.patch CVE-2017-15120.patch +CVE-2018-10851-rec-4.0.8.patch +CVE-2018-14626-rec-4.0.8.patch +CVE-2018-14644-rec-4.0.4.patch