Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.0:Update
pdns
CVE-2018-14626-auth-4.1.4.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File CVE-2018-14626-auth-4.1.4.patch of Package pdns
diff -ru pdns-4.1.4.orig/pdns/auth-packetcache.cc pdns-4.1.4/pdns/auth-packetcache.cc --- pdns-4.1.4.orig/pdns/auth-packetcache.cc 2018-08-29 16:07:05.000000000 +0200 +++ pdns-4.1.4/pdns/auth-packetcache.cc 2018-10-09 16:21:00.048215463 +0200 @@ -72,7 +72,7 @@ return false; } - uint32_t hash = canHashPacket(p->getString(), false); + uint32_t hash = canHashPacket(p->getString()); p->setHash(hash); string value; @@ -86,7 +86,7 @@ return false; } - haveSomething = getEntryLocked(mc.d_map, hash, p->qdomain, p->qtype.getCode(), p->d_tcp, now, value); + haveSomething = getEntryLocked(mc.d_map, p->getString(), hash, p->qdomain, p->qtype.getCode(), p->d_tcp, now, value); } if (!haveSomething) { @@ -106,6 +106,11 @@ return true; } +bool AuthPacketCache::entryMatches(cmap_t::index<HashTag>::type::iterator& iter, const std::string& query, const DNSName& qname, uint16_t qtype, bool tcp) +{ + return iter->tcp == tcp && iter->qtype == qtype && iter->qname == qname && queryMatches(iter->query, query, qname); +} + void AuthPacketCache::insert(DNSPacket *q, DNSPacket *r, unsigned int maxTTL) { cleanupIfNeeded(); @@ -132,6 +137,7 @@ entry.qtype = q->qtype.getCode(); entry.value = r->getString(); entry.tcp = r->d_tcp; + entry.query = q->getString(); auto& mc = getMap(entry.qname); { @@ -146,8 +152,9 @@ auto iter = range.first; for( ; iter != range.second ; ++iter) { - if (iter->tcp != entry.tcp || iter->qtype != entry.qtype || iter->qname != entry.qname) + if (!entryMatches(iter, entry.query, entry.qname, entry.qtype, entry.tcp)) { continue; + } iter->value = entry.value; iter->ttd = now + ourttl; @@ -161,7 +168,7 @@ } } -bool AuthPacketCache::getEntryLocked(cmap_t& map, uint32_t hash, const DNSName &qname, uint16_t qtype, bool tcp, time_t now, string& value) +bool AuthPacketCache::getEntryLocked(cmap_t& map, const std::string& query, uint32_t hash, const DNSName &qname, uint16_t qtype, bool tcp, time_t now, string& value) { auto& idx = map.get<HashTag>(); auto range = idx.equal_range(hash); @@ -170,8 +177,9 @@ if (iter->ttd < now) continue; - if (iter->tcp != tcp || iter->qtype != qtype || iter->qname != qname) + if (!entryMatches(iter, query, qname, qtype, tcp)) { continue; + } value = iter->value; return true; diff -ru pdns-4.1.4.orig/pdns/auth-packetcache.hh pdns-4.1.4/pdns/auth-packetcache.hh --- pdns-4.1.4.orig/pdns/auth-packetcache.hh 2018-08-29 16:07:04.000000000 +0200 +++ pdns-4.1.4/pdns/auth-packetcache.hh 2018-10-09 16:21:32.301227673 +0200 @@ -75,6 +75,7 @@ struct CacheEntry { + mutable string query; mutable string value; DNSName qname; @@ -109,7 +110,8 @@ return d_maps[name.hash() % d_maps.size()]; } - bool getEntryLocked(cmap_t& map, uint32_t hash, const DNSName &qname, uint16_t qtype, bool tcp, time_t now, string& entry); + static bool entryMatches(cmap_t::index<HashTag>::type::iterator& iter, const std::string& query, const DNSName& qname, uint16_t qtype, bool tcp); + bool getEntryLocked(cmap_t& map, const std::string& query, uint32_t hash, const DNSName &qname, uint16_t qtype, bool tcp, time_t now, string& entry); void cleanupIfNeeded(); AtomicCounter d_ops{0}; diff -ru pdns-4.1.4.orig/pdns/packetcache.hh pdns-4.1.4/pdns/packetcache.hh --- pdns-4.1.4.orig/pdns/packetcache.hh 2018-08-29 16:07:05.000000000 +0200 +++ pdns-4.1.4/pdns/packetcache.hh 2018-10-09 15:44:57.646908242 +0200 @@ -28,13 +28,13 @@ class PacketCache : public boost::noncopyable { -protected: - static uint32_t canHashPacket(const std::string& packet, bool skipECS=true) +public: + static uint32_t canHashPacket(const std::string& packet, uint16_t* ecsBegin, uint16_t* ecsEnd) { uint32_t ret = 0; - ret=burtle((const unsigned char*)packet.c_str() + 2, 10, ret); // rest of dnsheader, skip id + ret = burtle(reinterpret_cast<const unsigned char*>(packet.c_str()) + 2, sizeof(dnsheader) - 2, ret); // rest of dnsheader, skip id size_t packetSize = packet.size(); - size_t pos = 12; + size_t pos = sizeof(dnsheader); const char* end = packet.c_str() + packetSize; const char* p = packet.c_str() + pos; @@ -43,36 +43,110 @@ ret=burtle(&l, 1, ret); } // XXX the embedded 0 in the qname will break the subnet stripping - struct dnsheader* dh = (struct dnsheader*)packet.c_str(); + const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(packet.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) = 16 */ - if(skipECS && ntohs(dh->arcount)==1 && (pos+16) < packetSize) { + if(ntohs(dh->arcount)==1 && (pos+16) < packetSize) { char* optionBegin = nullptr; size_t optionLen = 0; /* skip the final empty label (1), the qtype (2), qclass (2) */ /* root label (1), type (2), class (2) and ttl (4) */ - int res = getEDNSOption((char*) p + 14, end - (p + 14), EDNSOptionCode::ECS, &optionBegin, &optionLen); + int res = getEDNSOption(const_cast<char*>(reinterpret_cast<const char*>(p)) + 14, end - (p + 14), EDNSOptionCode::ECS, &optionBegin, &optionLen); if (res == 0) { skipBegin = optionBegin; skipEnd = optionBegin + optionLen; + if (ecsBegin != nullptr && ecsEnd != nullptr) { + *ecsBegin = optionBegin - packet.c_str(); + *ecsEnd = *ecsBegin + optionLen; + } } } if (skipBegin > p) { - // cerr << "Hashing from " << (p-packet.c_str()) << " for " << skipBegin-p << "bytes, end is at "<< end-packet.c_str() << endl; - ret = burtle((const unsigned char*)p, skipBegin-p, ret); + ret = burtle(reinterpret_cast<const unsigned char*>(p), skipBegin-p, ret); } if (skipEnd < end) { - // cerr << "Hashing from " << (skipEnd-packet.c_str()) << " for " << end-skipEnd << "bytes, end is at " << end-packet.c_str() << endl; - ret = burtle((const unsigned char*) skipEnd, end-skipEnd, ret); + ret = burtle(reinterpret_cast<const unsigned char*>(skipEnd), end-skipEnd, ret); } return ret; } + + static uint32_t canHashPacket(const std::string& packet) + { + uint32_t ret = 0; + ret = burtle(reinterpret_cast<const unsigned char*>(packet.c_str()) + 2, sizeof(dnsheader) - 2, ret); // rest of dnsheader, skip id + size_t packetSize = packet.size(); + size_t pos = sizeof(dnsheader); + const char* end = packet.c_str() + packetSize; + const char* p = packet.c_str() + pos; + + for(; p < end && *p; ++p) { // XXX if you embed a 0 in your qname we'll stop lowercasing there + const unsigned char l = dns_tolower(*p); // label lengths can safely be lower cased + ret=burtle(&l, 1, ret); + } // XXX the embedded 0 in the qname will break the subnet stripping + + if (p < end) { + ret = burtle(reinterpret_cast<const unsigned char*>(p), end-p, ret); + } + + return ret; + } + + 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); + } + + static bool queryMatches(const std::string& cachedQuery, const std::string& query, const DNSName& qname) + { + if (!queryHeaderMatches(cachedQuery, query)) { + return false; + } + + size_t pos = sizeof(dnsheader) + qname.wirelength(); + + return (cachedQuery.compare(pos, cachedQuery.size() - pos, query, pos, query.size() - pos) == 0); + } + + static bool 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; + } + }; #endif /* PACKETCACHE_HH */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor