Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock
Dear Release Team, Please unblock package pdns 4.1.6-2, which has a security fix for CVE-2019-3871 (#924966), prepared and tested by Salvatore (and checked by me). unblock pdns/4.1.6-2 Thanks, Chris debdiff follows: diff -Nru pdns-4.1.6/debian/changelog pdns-4.1.6/debian/changelog --- pdns-4.1.6/debian/changelog 2019-02-03 14:20:23.000000000 +0000 +++ pdns-4.1.6/debian/changelog 2019-03-31 12:48:59.000000000 +0000 @@ -1,3 +1,11 @@ +pdns (4.1.6-2) unstable; urgency=high + + [ Salvatore Bonaccorso ] + * Insufficient validation in the HTTP remote backend (CVE-2019-3871) + (Closes: #924966) + + -- Chris Hofstaedtler <z...@debian.org> Sun, 31 Mar 2019 12:48:59 +0000 + pdns (4.1.6-1) unstable; urgency=medium * New upstream version 4.1.6 diff -Nru pdns-4.1.6/debian/patches/CVE-2019-3871-auth-4.1.6.patch pdns-4.1.6/debian/patches/CVE-2019-3871-auth-4.1.6.patch --- pdns-4.1.6/debian/patches/CVE-2019-3871-auth-4.1.6.patch 1970-01-01 00:00:00.000000000 +0000 +++ pdns-4.1.6/debian/patches/CVE-2019-3871-auth-4.1.6.patch 2019-03-31 12:48:59.000000000 +0000 @@ -0,0 +1,147 @@ +Description: Insufficient validation in the HTTP remote backend +Origin: upstream, https://downloads.powerdns.com/patches/2019-03/CVE-2019-3871-auth-4.1.6.patch +Bug: https://github.com/PowerDNS/pdns/issues/7573 +Bug-Debian: https://bugs.debian.org/924966 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-3871 +Forwarded: not-needed +Reviewed-by: Salvatore Bonaccorso <car...@debian.org> +Last-Update: 2019-03-29 +Applied-Upstream: 4.1.7 + +diff -ru pdns-4.1.6.orig/modules/remotebackend/httpconnector.cc pdns-4.1.6/modules/remotebackend/httpconnector.cc +--- pdns-4.1.6.orig/modules/remotebackend/httpconnector.cc 2019-01-31 10:17:33.000000000 +0100 ++++ pdns-4.1.6/modules/remotebackend/httpconnector.cc 2019-03-15 13:29:51.102891481 +0100 +@@ -35,7 +35,22 @@ + #endif + + HTTPConnector::HTTPConnector(std::map<std::string,std::string> options) { ++ ++ if (options.find("url") == options.end()) { ++ throw PDNSException("Cannot find 'url' option in the remote backend HTTP connector's parameters"); ++ } ++ + this->d_url = options.find("url")->second; ++ ++ try { ++ YaHTTP::URL url(d_url); ++ d_host = url.host; ++ d_port = url.port; ++ } ++ catch(const std::exception& e) { ++ throw PDNSException("Error parsing the 'url' option provided to the remote backend HTTP connector: " + std::string(e.what())); ++ } ++ + if (options.find("url-suffix") != options.end()) { + this->d_url_suffix = options.find("url-suffix")->second; + } else { +@@ -71,7 +86,7 @@ + void HTTPConnector::addUrlComponent(const Json ¶meters, const string& element, std::stringstream& ss) { + std::string sparam; + if (parameters[element] != Json()) +- ss << "/" << asString(parameters[element]); ++ ss << "/" << YaHTTP::Utility::encodeURL(asString(parameters[element]), false); + } + + std::string HTTPConnector::buildMemberListArgs(std::string prefix, const Json& args) { +@@ -81,9 +96,9 @@ + if (pair.second.is_bool()) { + stream << (pair.second.bool_value()?"1":"0"); + } else if (pair.second.is_null()) { +- stream << prefix << "[" << pair.first << "]="; ++ stream << prefix << "[" << YaHTTP::Utility::encodeURL(pair.first, false) << "]="; + } else { +- stream << prefix << "[" << pair.first << "]=" << this->asString(pair.second); ++ stream << prefix << "[" << YaHTTP::Utility::encodeURL(pair.first, false) << "]=" << YaHTTP::Utility::encodeURL(this->asString(pair.second), false); + } + stream << "&"; + } +@@ -334,45 +349,41 @@ + delete this->d_socket; + this->d_socket = NULL; + +- if (req.url.protocol == "unix") { +- // connect using unix socket +- } else { +- // connect using tcp +- struct addrinfo *gAddr, *gAddrPtr, hints; +- std::string sPort = std::to_string(req.url.port); +- memset(&hints,0,sizeof hints); +- hints.ai_family = AF_UNSPEC; +- hints.ai_flags = AI_ADDRCONFIG; +- hints.ai_socktype = SOCK_STREAM; +- hints.ai_protocol = 6; // tcp +- if ((ec = getaddrinfo(req.url.host.c_str(), sPort.c_str(), &hints, &gAddr)) == 0) { +- // try to connect to each address. +- gAddrPtr = gAddr; ++ // connect using tcp ++ struct addrinfo *gAddr, *gAddrPtr, hints; ++ std::string sPort = std::to_string(d_port); ++ memset(&hints,0,sizeof hints); ++ hints.ai_family = AF_UNSPEC; ++ hints.ai_flags = AI_ADDRCONFIG; ++ hints.ai_socktype = SOCK_STREAM; ++ hints.ai_protocol = 6; // tcp ++ if ((ec = getaddrinfo(d_host.c_str(), sPort.c_str(), &hints, &gAddr)) == 0) { ++ // try to connect to each address. ++ gAddrPtr = gAddr; + +- while(gAddrPtr) { +- try { +- d_socket = new Socket(gAddrPtr->ai_family, gAddrPtr->ai_socktype, gAddrPtr->ai_protocol); +- d_addr.setSockaddr(gAddrPtr->ai_addr, gAddrPtr->ai_addrlen); +- d_socket->connect(d_addr); +- d_socket->setNonBlocking(); +- d_socket->writenWithTimeout(out.str().c_str(), out.str().size(), timeout); +- rv = 1; +- } catch (NetworkError& ne) { +- L<<Logger::Error<<"While writing to HTTP endpoint "<<d_addr.toStringWithPort()<<": "<<ne.what()<<std::endl; +- } catch (...) { +- L<<Logger::Error<<"While writing to HTTP endpoint "<<d_addr.toStringWithPort()<<": exception caught"<<std::endl; +- } +- +- if (rv > -1) break; +- delete d_socket; +- d_socket = NULL; +- gAddrPtr = gAddrPtr->ai_next; +- ++ while(gAddrPtr) { ++ try { ++ d_socket = new Socket(gAddrPtr->ai_family, gAddrPtr->ai_socktype, gAddrPtr->ai_protocol); ++ d_addr.setSockaddr(gAddrPtr->ai_addr, gAddrPtr->ai_addrlen); ++ d_socket->connect(d_addr); ++ d_socket->setNonBlocking(); ++ d_socket->writenWithTimeout(out.str().c_str(), out.str().size(), timeout); ++ rv = 1; ++ } catch (NetworkError& ne) { ++ L<<Logger::Error<<"While writing to HTTP endpoint "<<d_addr.toStringWithPort()<<": "<<ne.what()<<std::endl; ++ } catch (...) { ++ L<<Logger::Error<<"While writing to HTTP endpoint "<<d_addr.toStringWithPort()<<": exception caught"<<std::endl; + } +- freeaddrinfo(gAddr); +- } else { +- L<<Logger::Error<<"Unable to resolve " << req.url.host << ": " << gai_strerror(ec) << std::endl; ++ ++ if (rv > -1) break; ++ delete d_socket; ++ d_socket = NULL; ++ gAddrPtr = gAddrPtr->ai_next; ++ + } ++ freeaddrinfo(gAddr); ++ } else { ++ L<<Logger::Error<<"Unable to resolve " << d_host << ": " << gai_strerror(ec) << std::endl; + } + + return rv; +diff -ru pdns-4.1.6.orig/modules/remotebackend/remotebackend.hh pdns-4.1.6/modules/remotebackend/remotebackend.hh +--- pdns-4.1.6.orig/modules/remotebackend/remotebackend.hh 2019-01-31 10:17:33.000000000 +0100 ++++ pdns-4.1.6/modules/remotebackend/remotebackend.hh 2019-03-15 13:29:51.102891481 +0100 +@@ -104,6 +104,8 @@ + std::string buildMemberListArgs(std::string prefix, const Json& args); + Socket* d_socket; + ComboAddress d_addr; ++ std::string d_host; ++ uint16_t d_port; + }; + + #ifdef REMOTEBACKEND_ZEROMQ diff -Nru pdns-4.1.6/debian/patches/series pdns-4.1.6/debian/patches/series --- pdns-4.1.6/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ pdns-4.1.6/debian/patches/series 2019-03-31 12:48:59.000000000 +0000 @@ -0,0 +1 @@ +CVE-2019-3871-auth-4.1.6.patch