Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock
Dear Release Team, upstream asked me nicely to update pdns to their just released bug-fix release (3.4.0 -> 3.4.1). 3.4.1 has, depending on how you count, two or three bug fixes. From upstreams changelog: - honor SOA-EDIT while considering "empty IXFR" fallback, This fixes slaving of signed zones to IXFR-aware slaves like NSD or BIND. - Use transaction for pdnssec increase-serial (fixes partially modified zones after a failed increase-serial) - Don't empty ordername during pdnssec increase-serial (fixes broken DNSSEC zones after increase-serial) Also included: - upstream applied a patch that I had previously included in 3.4.0-2. - security status polling feature I also noticed that the shipped pdns.conf was quite out of date, so I resynced that (my oversight for 3.4.0). I'm attaching a regular debdiff between 3.4.0-2 (in testing) and 3.4.1-1, plus a diff between 3.4.0-2 with the previously mentioned patch already applied (reduces the diff by a bit). Please consider unblocking pdns 3.4.1-1 (it's not "yet" built everywhere): unblock pdns/3.4.1-1 Thanks, Christian
diff -Nru pdns-3.4.0/build-scripts/redhat/pdns-server-test.spec pdns-3.4.1/build-scripts/redhat/pdns-server-test.spec --- pdns-3.4.0/build-scripts/redhat/pdns-server-test.spec 2014-09-30 11:23:37.000000000 +0200 +++ pdns-3.4.1/build-scripts/redhat/pdns-server-test.spec 2014-10-30 11:18:22.000000000 +0100 @@ -9,7 +9,7 @@ Epoch: 0 License: GPL Group: System/Servers -Source: http://downloads.powerdns.com/releases/pdns-3.4.0.tar.bz2 +Source: http://downloads.powerdns.com/releases/pdns-3.4.1.tar.bz2 BuildRequires: autoconf automake BuildRequires: gcc gcc-c++ @@ -30,7 +30,7 @@ PowerDNS testbuild %prep -%setup -q -n pdns-3.4.0 +%setup -q -n pdns-3.4.1 %build %configure \ diff -Nru pdns-3.4.0/configure pdns-3.4.1/configure --- pdns-3.4.0/configure 2014-09-30 11:23:48.000000000 +0200 +++ pdns-3.4.1/configure 2014-10-30 11:18:31.000000000 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for pdns 3.4.0. +# Generated by GNU Autoconf 2.69 for pdns 3.4.1. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -587,8 +587,8 @@ # Identity of this package. PACKAGE_NAME='pdns' PACKAGE_TARNAME='pdns' -PACKAGE_VERSION='3.4.0' -PACKAGE_STRING='pdns 3.4.0' +PACKAGE_VERSION='3.4.1' +PACKAGE_STRING='pdns 3.4.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1471,7 +1471,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pdns 3.4.0 to adapt to many kinds of systems. +\`configure' configures pdns 3.4.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1541,7 +1541,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pdns 3.4.0:";; + short | recursive ) echo "Configuration of pdns 3.4.1:";; esac cat <<\_ACEOF @@ -1737,7 +1737,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pdns configure 3.4.0 +pdns configure 3.4.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2344,7 +2344,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pdns $as_me 3.4.0, which was +It was created by pdns $as_me 3.4.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3167,7 +3167,7 @@ # Define the identity of the package. PACKAGE='pdns' - VERSION='3.4.0' + VERSION='3.4.1' cat >>confdefs.h <<_ACEOF @@ -21020,7 +21020,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pdns $as_me 3.4.0, which was +This file was extended by pdns $as_me 3.4.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -21086,7 +21086,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -pdns config.status 3.4.0 +pdns config.status 3.4.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru pdns-3.4.0/configure.ac pdns-3.4.1/configure.ac --- pdns-3.4.0/configure.ac 2014-09-30 11:23:37.000000000 +0200 +++ pdns-3.4.1/configure.ac 2014-10-30 11:18:22.000000000 +0100 @@ -1,7 +1,7 @@ AC_PREREQ([2.61]) dnl The following lines may be patched by set-version-auth. -AC_INIT([pdns], [3.4.0]) +AC_INIT([pdns], [3.4.1]) AC_SUBST([DIST_HOST], [jenk...@autotest.powerdns.com]) dnl End patch area. diff -Nru pdns-3.4.0/debian/changelog pdns-3.4.1/debian/changelog --- pdns-3.4.0/debian/changelog 2014-10-15 08:34:22.000000000 +0200 +++ pdns-3.4.1/debian/changelog 2014-11-01 23:13:12.000000000 +0100 @@ -1,3 +1,18 @@ +pdns (3.4.1-1) unstable; urgency=medium + + * Imported Upstream version 3.4.1, a bug fix release, that: + * Fixes slaving of DNSSEC-signed zones to NSD or BIND. + * Fixes pdnssec increase-serial to not break SOA records + in DNSSEC zones. + * Adds security status polling. (We set the package vendor + and version for this.) + * Remove patch 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custom, + which has been applied upstream. + * Resync pdns.conf with upstream + * Update debian/watch file, as upstream has changed to bz2 files. + + -- Christian Hofstaedtler <z...@debian.org> Sat, 01 Nov 2014 23:08:08 +0100 + pdns (3.4.0-2) unstable; urgency=medium * Apply patch from upstream switching API auth to a static key. diff -Nru pdns-3.4.0/debian/config/pdns.conf pdns-3.4.1/debian/config/pdns.conf --- pdns-3.4.0/debian/config/pdns.conf 2014-08-30 02:30:22.000000000 +0200 +++ pdns-3.4.1/debian/config/pdns.conf 2014-11-01 23:06:52.000000000 +0100 @@ -1,17 +1,12 @@ ################################# -# add-superfluous-nsec3-for-old-bind Add superfluous NSEC3 record to positive wildcard response -# -# add-superfluous-nsec3-for-old-bind=yes - -################################# -# allow-2136-from A global setting to allow RFC2136 from these IP ranges. +# allow-axfr-ips Allow zonetransfers only to these subnets # -# allow-2136-from=0.0.0.0/0 +# allow-axfr-ips=127.0.0.0/8,::1 ################################# -# allow-axfr-ips Allow zonetransfers only to these subnets +# allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. # -# allow-axfr-ips=0.0.0.0/0,::/0 +# allow-dnsupdate-from=127.0.0.0/8,::1 ################################# # allow-recursion List of subnets that are allowed to recurse @@ -104,7 +99,7 @@ # default-zsk-algorithms=rsasha256 ################################# -# default-zsk-size Default KSK size (0 means default) +# default-zsk-size Default ZSK size (0 means default) # # default-zsk-size=0 @@ -149,6 +144,11 @@ # entropy-source=/dev/urandom ################################# +# experimental-api-key REST API Static authentication key (required for API use) +# +# experimental-api-key= + +################################# # experimental-api-readonly If the JSON API should disallow data modification # # experimental-api-readonly=no @@ -159,6 +159,11 @@ # experimental-dname-processing=no ################################# +# experimental-dnsupdate Enable/Disable DNS update (RFC2136) support. Default is no. +# +# experimental-dnsupdate=no + +################################# # experimental-json-interface If the webserver should serve JSON data # # experimental-json-interface=no @@ -169,19 +174,9 @@ # experimental-logfile=/var/log/pdns.log ################################# -# experimental-rfc2136 Enable/Disable RFC2136 (Dynamic DNS) support. Default is no. +# forward-dnsupdate A global setting to allow DNS update packages that are for a Slave domain, to be forwarded to the master. # -# experimental-rfc2136=no - -################################# -# fancy-records Process URL and MBOXFW records -# -# fancy-records=no - -################################# -# forward-2136 A global setting to allow RFC2136 packages that are for a Slave domain, to be forwarded to the master. -# -# forward-2136=yes +# forward-dnsupdate=yes ################################# # guardian Run within a guardian process @@ -271,11 +266,21 @@ # max-ent-entries=100000 ################################# +# max-nsec3-iterations Limit the number of NSEC3 hash iterations +# +# max-nsec3-iterations=500 + +################################# # max-queue-length Maximum queuelength before considering situation lost # # max-queue-length=5000 ################################# +# max-signature-cache-entries Maximum number of signatures cache entries +# +# max-signature-cache-entries= + +################################# # max-tcp-connections Maximum number of TCP connections # # max-tcp-connections=10 @@ -371,6 +376,11 @@ # reuseport=no ################################# +# security-poll-suffix Domain name from which to query security update notifications +# +# security-poll-suffix=secpoll.powerdns.com. + +################################# # send-root-referral Send out old-fashioned root-referral instead of ServFail in case of no authority # # send-root-referral=no @@ -411,11 +421,6 @@ # slave-renotify=no ################################# -# smtpredirector Our smtpredir MX host -# -# smtpredirector=a.misconfigured.powerdns.smtp.server - -################################# # soa-expire-default Default SOA expire # # soa-expire-default=604800 @@ -436,11 +441,6 @@ # soa-retry-default=3600 ################################# -# soa-serial-offset Make sure that no SOA serial is less than this number -# -# soa-serial-offset=0 - -################################# # socket-dir Where the controlsocket will live # # socket-dir=/var/run @@ -481,11 +481,6 @@ # udp-truncation-threshold=1680 ################################# -# urlredirector Where we send hosts to that need to be url redirected -# -# urlredirector=127.0.0.1 - -################################# # version-string PowerDNS version in packets - full, anonymous, powerdns or custom # # version-string=full @@ -501,6 +496,11 @@ # webserver-address=127.0.0.1 ################################# +# webserver-allow-from Webserver access is only allowed from these subnets +# +# webserver-allow-from=0.0.0.0/0,::/0 + +################################# # webserver-password Password required for accessing the webserver # # webserver-password= @@ -515,9 +515,4 @@ # # webserver-print-arguments=no -################################# -# wildcard-url Process URL and MBOXFW records -# -# wildcard-url=no - diff -Nru pdns-3.4.0/debian/patches/0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.1/debian/patches/0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch --- pdns-3.4.0/debian/patches/0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch 2014-10-12 22:00:27.000000000 +0200 +++ pdns-3.4.1/debian/patches/0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch 1970-01-01 01:00:00.000000000 +0100 @@ -1,310 +0,0 @@ -From bbef8f04823bcd8b5f7bba9e319016d7df4359d0 Mon Sep 17 00:00:00 2001 -From: Christian Hofstaedtler <christ...@hofstaedtler.name> -Date: Mon, 6 Oct 2014 23:51:01 +0200 -Subject: [PATCH] API: Replace HTTP Basic auth with static key in custom - header - -Given that the key is sent in a custom header, this should prevent -any possible CSRF attacks. - -Fixes #1769. ---- - pdns/common_startup.cc | 1 + - pdns/docs/pdns.xml | 8 ++++ - pdns/pdns.conf-dist | 5 ++ - pdns/pdns_recursor.cc | 1 + - pdns/webserver.cc | 93 ++++++++++++++++++++++++++----------- - pdns/webserver.hh | 11 ++++- - pdns/ws-auth.cc | 6 +-- - pdns/ws-recursor.cc | 2 +- - pdns/ws-recursor.hh | 4 +- - 13 files changed, 114 insertions(+), 54 deletions(-) - -diff --git a/pdns/common_startup.cc b/pdns/common_startup.cc -index ada2c88..7fdf047 100644 ---- a/pdns/common_startup.cc -+++ b/pdns/common_startup.cc -@@ -61,6 +61,7 @@ void declareArguments() - ::arg().set("retrieval-threads", "Number of AXFR-retrieval threads for slave operation")="2"; - ::arg().setSwitch("experimental-json-interface", "If the webserver should serve JSON data")="no"; - ::arg().setSwitch("experimental-api-readonly", "If the JSON API should disallow data modification")="no"; -+ ::arg().set("experimental-api-key", "REST API Static authentication key (required for API use)")=""; - ::arg().setSwitch("experimental-dname-processing", "If we should support DNAME records")="no"; - - ::arg().setCmd("help","Provide a helpful message"); -diff --git a/pdns/pdns.conf-dist b/pdns/pdns.conf-dist -index ec203c0..bc5ae5d 100644 ---- a/pdns/pdns.conf-dist -+++ b/pdns/pdns.conf-dist -@@ -145,6 +145,11 @@ - # entropy-source=/dev/urandom - - ################################# -+# experimental-api-key REST API Static authentication key (required for API use) -+# -+# experimental-api-key= -+ -+################################# - # experimental-api-readonly If the JSON API should disallow data modification - # - # experimental-api-readonly=no -diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc -index d5cae24..2a4b8ae 100644 ---- a/pdns/pdns_recursor.cc -+++ b/pdns/pdns_recursor.cc -@@ -2101,6 +2101,7 @@ int main(int argc, char **argv) - ::arg().set("experimental-webserver-password", "Password required for accessing the webserver") = ""; - ::arg().set("webserver-allow-from","Webserver access is only allowed from these subnets")="0.0.0.0/0,::/0"; - ::arg().set("experimental-api-config-dir", "Directory where REST API stores config and zones") = ""; -+ ::arg().set("experimental-api-key", "REST API Static authentication key (required for API use)") = ""; - ::arg().set("carbon-ourname", "If set, overrides our reported hostname for carbon stats")=""; - ::arg().set("carbon-server", "If set, send metrics in carbon (graphite) format to this server")=""; - ::arg().set("carbon-interval", "Number of seconds between carbon (graphite) updates")="30"; -diff --git a/pdns/webserver.cc b/pdns/webserver.cc -index 6bcda50..cf993a1 100644 ---- a/pdns/webserver.cc -+++ b/pdns/webserver.cc -@@ -48,6 +48,37 @@ void HttpRequest::json(rapidjson::Document& document) - } - } - -+bool HttpRequest::compareAuthorization(const string &expected_password) -+{ -+ // validate password -+ YaHTTP::strstr_map_t::iterator header = headers.find("authorization"); -+ bool auth_ok = false; -+ if (header != headers.end() && toLower(header->second).find("basic ") == 0) { -+ string cookie = header->second.substr(6); -+ -+ string plain; -+ B64Decode(cookie, plain); -+ -+ vector<string> cparts; -+ stringtok(cparts, plain, ":"); -+ -+ // this gets rid of terminating zeros -+ auth_ok = (cparts.size()==2 && (0==strcmp(cparts[1].c_str(), expected_password.c_str()))); -+ } -+ return auth_ok; -+} -+ -+bool HttpRequest::compareHeader(const string &header_name, const string &expected_value) -+{ -+ YaHTTP::strstr_map_t::iterator header = headers.find(header_name); -+ if (header == headers.end()) -+ return false; -+ -+ // this gets rid of terminating zeros -+ return (0==strcmp(header->second.c_str(), expected_value.c_str())); -+} -+ -+ - void HttpResponse::setBody(rapidjson::Document& document) - { - this->body = makeStringFromDocument(document); -@@ -58,19 +89,30 @@ int WebServer::B64Decode(const std::string& strInput, std::string& strOutput) - return ::B64Decode(strInput, strOutput); - } - --static void handlerWrapper(WebServer::HandlerFunction handler, YaHTTP::Request* req, YaHTTP::Response* resp) -+static void bareHandlerWrapper(WebServer::HandlerFunction handler, YaHTTP::Request* req, YaHTTP::Response* resp) - { - // wrapper to convert from YaHTTP::* to our subclasses - handler(static_cast<HttpRequest*>(req), static_cast<HttpResponse*>(resp)); - } - --void WebServer::registerHandler(const string& url, HandlerFunction handler) -+void WebServer::registerBareHandler(const string& url, HandlerFunction handler) - { -- YaHTTP::THandlerFunction f = boost::bind(&handlerWrapper, handler, _1, _2); -+ YaHTTP::THandlerFunction f = boost::bind(&bareHandlerWrapper, handler, _1, _2); - YaHTTP::Router::Any(url, f); - } - - static void apiWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp) { -+ const string& api_key = arg()["experimental-api-key"]; -+ if (api_key.empty()) { -+ L<<Logger::Debug<<"HTTP API Request \"" << req->url.path << "\": Authentication failed, API Key missing in config" << endl; -+ throw HttpUnauthorizedException(); -+ } -+ bool auth_ok = req->compareHeader("x-api-key", api_key); -+ if (!auth_ok) { -+ L<<Logger::Debug<<"HTTP Request \"" << req->url.path << "\": Authentication by API Key failed" << endl; -+ throw HttpUnauthorizedException(); -+ } -+ - resp->headers["Access-Control-Allow-Origin"] = "*"; - resp->headers["Content-Type"] = "application/json"; - -@@ -108,7 +150,25 @@ static void apiWrapper(WebServer::HandlerFunction handler, HttpRequest* req, Htt - - void WebServer::registerApiHandler(const string& url, HandlerFunction handler) { - HandlerFunction f = boost::bind(&apiWrapper, handler, _1, _2); -- registerHandler(url, f); -+ registerBareHandler(url, f); -+} -+ -+static void webWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp) { -+ const string& web_password = arg()["webserver-password"]; -+ if (!web_password.empty()) { -+ bool auth_ok = req->compareAuthorization(web_password); -+ if (!auth_ok) { -+ L<<Logger::Debug<<"HTTP Request \"" << req->url.path << "\": Web Authentication failed" << endl; -+ throw HttpUnauthorizedException(); -+ } -+ } -+ -+ handler(req, resp); -+} -+ -+void WebServer::registerWebHandler(const string& url, HandlerFunction handler) { -+ HandlerFunction f = boost::bind(&webWrapper, handler, _1, _2); -+ registerBareHandler(url, f); - } - - static void *WebServerConnectionThreadStart(void *p) { -@@ -148,28 +208,6 @@ HttpResponse WebServer::handleRequest(HttpRequest req) - } - } - -- if (!d_password.empty()) { -- // validate password -- header = req.headers.find("authorization"); -- bool auth_ok = false; -- if (header != req.headers.end() && toLower(header->second).find("basic ") == 0) { -- string cookie = header->second.substr(6); -- -- string plain; -- B64Decode(cookie, plain); -- -- vector<string> cparts; -- stringtok(cparts, plain, ":"); -- -- // this gets rid of terminating zeros -- auth_ok = (cparts.size()==2 && (0==strcmp(cparts[1].c_str(), d_password.c_str()))); -- } -- if (!auth_ok) { -- L<<Logger::Debug<<"HTTP Request \"" << req.url.path << "\": Authentication failed" << endl; -- throw HttpUnauthorizedException(); -- } -- } -- - YaHTTP::THandlerFunction handler; - if (!YaHTTP::Router::Route(&req, handler)) { - L<<Logger::Debug<<"HTTP: No route found for \"" << req.url.path << "\"" << endl; -@@ -268,11 +306,10 @@ catch(...) { - L<<Logger::Error<<"HTTP: Unknown exception"<<endl; - } - --WebServer::WebServer(const string &listenaddress, int port, const string &password) : d_server(NULL) -+WebServer::WebServer(const string &listenaddress, int port) : d_server(NULL) - { - d_listenaddress=listenaddress; - d_port=port; -- d_password=password; - } - - void WebServer::bind() -diff --git a/pdns/webserver.hh b/pdns/webserver.hh -index 5b33767..bac4a88 100644 ---- a/pdns/webserver.hh -+++ b/pdns/webserver.hh -@@ -32,6 +32,8 @@ - #include "namespaces.hh" - #include "sstuff.hh" - -+class WebServer; -+ - class HttpRequest : public YaHTTP::Request { - public: - HttpRequest() : YaHTTP::Request(), accept_json(false), accept_html(false), complete(false) { }; -@@ -40,6 +42,10 @@ public: - bool accept_html; - bool complete; - void json(rapidjson::Document& document); -+ -+ // checks password _only_. -+ bool compareAuthorization(const string &expected_password); -+ bool compareHeader(const string &header_name, const string &expected_value); - }; - - class HttpResponse: public YaHTTP::Response { -@@ -125,7 +131,7 @@ protected: - class WebServer : public boost::noncopyable - { - public: -- WebServer(const string &listenaddress, int port, const string &password=""); -+ WebServer(const string &listenaddress, int port); - void bind(); - void go(); - -@@ -133,12 +139,13 @@ public: - HttpResponse handleRequest(HttpRequest request); - - typedef boost::function<void(HttpRequest* req, HttpResponse* resp)> HandlerFunction; -- void registerHandler(const string& url, HandlerFunction handler); - void registerApiHandler(const string& url, HandlerFunction handler); -+ void registerWebHandler(const string& url, HandlerFunction handler); - - protected: - static char B64Decode1(char cInChar); - static int B64Decode(const std::string& strInput, std::string& strOutput); -+ void registerBareHandler(const string& url, HandlerFunction handler); - - virtual Server* createServer() { - return new Server(d_listenaddress, d_port); -diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc -index 12c7a5c..69d27a6 100644 ---- a/pdns/ws-auth.cc -+++ b/pdns/ws-auth.cc -@@ -61,7 +61,7 @@ AuthWebServer::AuthWebServer() - d_ws = 0; - d_tid = 0; - if(arg().mustDo("webserver")) { -- d_ws = new WebServer(arg()["webserver-address"], arg().asNum("webserver-port"),arg()["webserver-password"]); -+ d_ws = new WebServer(arg()["webserver-address"], arg().asNum("webserver-port")); - d_ws->bind(); - } - } -@@ -1255,8 +1255,8 @@ void AuthWebServer::webThread() - // legacy dispatch - d_ws->registerApiHandler("/jsonstat", boost::bind(&AuthWebServer::jsonstat, this, _1, _2)); - } -- d_ws->registerHandler("/style.css", boost::bind(&AuthWebServer::cssfunction, this, _1, _2)); -- d_ws->registerHandler("/", boost::bind(&AuthWebServer::indexfunction, this, _1, _2)); -+ d_ws->registerWebHandler("/style.css", boost::bind(&AuthWebServer::cssfunction, this, _1, _2)); -+ d_ws->registerWebHandler("/", boost::bind(&AuthWebServer::indexfunction, this, _1, _2)); - d_ws->go(); - } - catch(...) { -diff --git a/pdns/ws-recursor.cc b/pdns/ws-recursor.cc -index 73c6f57..be8f494 100644 ---- a/pdns/ws-recursor.cc -+++ b/pdns/ws-recursor.cc -@@ -421,7 +421,7 @@ RecursorWebServer::RecursorWebServer(FDMultiplexer* fdm) - { - RecursorControlParser rcp; // inits - -- d_ws = new AsyncWebServer(fdm, arg()["experimental-webserver-address"], arg().asNum("experimental-webserver-port"), arg()["experimental-webserver-password"]); -+ d_ws = new AsyncWebServer(fdm, arg()["experimental-webserver-address"], arg().asNum("experimental-webserver-port")); - d_ws->bind(); - - // legacy dispatch -diff --git a/pdns/ws-recursor.hh b/pdns/ws-recursor.hh -index ffcad30..3f2fc84 100644 ---- a/pdns/ws-recursor.hh -+++ b/pdns/ws-recursor.hh -@@ -45,8 +45,8 @@ private: - class AsyncWebServer : public WebServer - { - public: -- AsyncWebServer(FDMultiplexer* fdm, const string &listenaddress, int port, const string &password="") : -- WebServer(listenaddress, port, password), d_fdm(fdm) { }; -+ AsyncWebServer(FDMultiplexer* fdm, const string &listenaddress, int port) : -+ WebServer(listenaddress, port), d_fdm(fdm) { }; - void go(); - - private: --- -2.1.1 - diff -Nru pdns-3.4.0/debian/patches/series pdns-3.4.1/debian/patches/series --- pdns-3.4.0/debian/patches/series 2014-10-12 21:53:12.000000000 +0200 +++ pdns-3.4.1/debian/patches/series 2014-11-01 23:06:52.000000000 +0100 @@ -1 +1 @@ -0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch + diff -Nru pdns-3.4.0/debian/rules pdns-3.4.1/debian/rules --- pdns-3.4.0/debian/rules 2014-08-31 06:54:54.000000000 +0200 +++ pdns-3.4.1/debian/rules 2014-11-01 23:06:31.000000000 +0100 @@ -1,5 +1,9 @@ #!/usr/bin/make -f +# Vendor and version +version := $(shell dpkg-parsechangelog -S Version).$(shell dpkg-vendor --query Vendor) +CXXFLAGS += -DPACKAGEVERSION='"$(version)"' + # Backends backends := bind ldap pipe gmysql gpgsql gsqlite3 geo lua lmdb mydns remote diff -Nru pdns-3.4.0/debian/watch pdns-3.4.1/debian/watch --- pdns-3.4.0/debian/watch 2014-08-30 02:30:22.000000000 +0200 +++ pdns-3.4.1/debian/watch 2014-11-01 22:01:17.000000000 +0100 @@ -3,4 +3,4 @@ # to check for upstream updates and more. # Site Directory Pattern Version Script version=3 -http://downloads.powerdns.com/releases/ pdns-(.*)\.tar\.gz debian uupdate +http://downloads.powerdns.com/releases/ pdns-([0-9]+.*)\.tar\.(gz|bz2) debian uupdate diff -Nru pdns-3.4.0/debian-pdns/changelog pdns-3.4.1/debian-pdns/changelog --- pdns-3.4.0/debian-pdns/changelog 2014-09-30 11:23:37.000000000 +0200 +++ pdns-3.4.1/debian-pdns/changelog 2014-10-30 11:18:22.000000000 +0100 @@ -1,4 +1,4 @@ -pdns (3.4.0-1) unstable; urgency=medium +pdns (3.4.1-1) unstable; urgency=medium * fill in the blanks diff -Nru pdns-3.4.0/pdns/common_startup.cc pdns-3.4.1/pdns/common_startup.cc --- pdns-3.4.0/pdns/common_startup.cc 2014-09-22 12:32:05.000000000 +0200 +++ pdns-3.4.1/pdns/common_startup.cc 2014-10-28 13:51:22.000000000 +0100 @@ -21,6 +21,7 @@ */ #include "common_startup.hh" #include "ws-auth.hh" +#include "secpoll-auth.hh" bool g_anyToTcp; typedef Distributor<DNSPacket,DNSPacket,PacketHandler> DNSDistributor; @@ -61,6 +62,7 @@ ::arg().set("retrieval-threads", "Number of AXFR-retrieval threads for slave operation")="2"; ::arg().setSwitch("experimental-json-interface", "If the webserver should serve JSON data")="no"; ::arg().setSwitch("experimental-api-readonly", "If the JSON API should disallow data modification")="no"; + ::arg().set("experimental-api-key", "REST API Static authentication key (required for API use)")=""; ::arg().setSwitch("experimental-dname-processing", "If we should support DNAME records")="no"; ::arg().setCmd("help","Provide a helpful message"); @@ -159,6 +161,7 @@ ::arg().set("max-nsec3-iterations","Limit the number of NSEC3 hash iterations")="500"; // RFC5155 10.3 ::arg().set("include-dir","Include *.conf files from this directory"); + ::arg().set("security-poll-suffix","Domain name from which to query security update notifications")="secpoll.powerdns.com."; } void declareStats(void) @@ -198,7 +201,7 @@ S.declare("servfail-packets","Number of times a server-failed packet was sent out"); S.declare("latency","Average number of microseconds needed to answer a question"); S.declare("timedout-packets","Number of packets which weren't answered within timeout set"); - + S.declare("security-status", "Security status based on regular polling"); S.declareRing("queries","UDP Queries Received"); S.declareRing("nxdomain-queries","Queries for non-existent records within existent domains"); S.declareRing("noerror-queries","Queries for existing records, but for type we don't have"); @@ -362,6 +365,9 @@ DNSPacket::s_udpTruncationThreshold = std::max(512, ::arg().asNum("udp-truncation-threshold")); DNSPacket::s_doEDNSSubnetProcessing = ::arg().mustDo("edns-subnet-processing"); + + doSecPoll(true); // this must be BEFORE chroot + if(!::arg()["chroot"].empty()) { if(::arg().mustDo("master") || ::arg().mustDo("slave")) gethostbyname("a.root-servers.net"); // this forces all lookup libraries to be loaded @@ -399,13 +405,19 @@ TN->go(); // tcp nameserver launch pthread_create(&qtid,0,carbonDumpThread, 0); // runs even w/o carbon, might change @ runtime + // fork(); (this worked :-)) unsigned int max_rthreads= ::arg().asNum("receiver-threads", 1); for(unsigned int n=0; n < max_rthreads; ++n) pthread_create(&qtid,0,qthread, reinterpret_cast<void *>(n)); // receives packets - void *p; - pthread_join(qtid, &p); + for(;;) { + sleep(1800); + try { + doSecPoll(false); + } + catch(...){} + } L<<Logger::Error<<"Mainthread exiting - should never happen"<<endl; } diff -Nru pdns-3.4.0/pdns/docs/dnsdist.1 pdns-3.4.1/pdns/docs/dnsdist.1 --- pdns-3.4.0/pdns/docs/dnsdist.1 2014-09-30 11:24:27.000000000 +0200 +++ pdns-3.4.1/pdns/docs/dnsdist.1 2014-10-30 11:19:09.000000000 +0100 @@ -2,12 +2,12 @@ .\" Title: dnsdist .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/> -.\" Date: 09/30/2014 +.\" Date: 10/30/2014 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "DNSDIST" "1" "09/30/2014" "\ \&" "\ \&" +.TH "DNSDIST" "1" "10/30/2014" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru pdns-3.4.0/pdns/docs/dnstcpbench.1 pdns-3.4.1/pdns/docs/dnstcpbench.1 --- pdns-3.4.0/pdns/docs/dnstcpbench.1 2014-09-30 11:24:26.000000000 +0200 +++ pdns-3.4.1/pdns/docs/dnstcpbench.1 2014-10-30 11:19:07.000000000 +0100 @@ -2,12 +2,12 @@ .\" Title: dnstcpbench .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/> -.\" Date: 09/30/2014 +.\" Date: 10/30/2014 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "DNSTCPBENCH" "1" "09/30/2014" "\ \&" "\ \&" +.TH "DNSTCPBENCH" "1" "10/30/2014" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru pdns-3.4.0/pdns/Makefile.am pdns-3.4.1/pdns/Makefile.am --- pdns-3.4.0/pdns/Makefile.am 2014-08-29 16:02:13.000000000 +0200 +++ pdns-3.4.1/pdns/Makefile.am 2014-10-30 11:18:22.000000000 +0100 @@ -58,7 +58,7 @@ bindparser.cc bindlexer.c \ backends/gsql/gsqlbackend.cc \ backends/gsql/gsqlbackend.hh backends/gsql/ssql.hh \ -base64.cc sillyrecords.cc \ +base64.cc sillyrecords.cc secpoll-auth.cc secpoll-auth.hh \ base64.hh zoneparser-tng.cc dnsrecords.cc dnswriter.cc \ rcpgenerator.cc dnsparser.cc dns_random.hh dns_random.cc\ randomhelper.cc namespaces.hh nsecrecords.cc base32.cc dbdnsseckeeper.cc dnssecinfra.cc \ diff -Nru pdns-3.4.0/pdns/Makefile.in pdns-3.4.1/pdns/Makefile.in --- pdns-3.4.0/pdns/Makefile.in 2014-09-30 11:23:53.000000000 +0200 +++ pdns-3.4.1/pdns/Makefile.in 2014-10-30 11:18:39.000000000 +0100 @@ -326,11 +326,12 @@ utility.hh iputils.hh common_startup.hh unix_semaphore.cc \ bind-dnssec.schema.sqlite3.sql.h bindparser.cc bindlexer.c \ backends/gsql/gsqlbackend.cc backends/gsql/gsqlbackend.hh \ - backends/gsql/ssql.hh base64.cc sillyrecords.cc base64.hh \ - zoneparser-tng.cc dnsrecords.cc dnswriter.cc rcpgenerator.cc \ - dnsparser.cc dns_random.hh dns_random.cc randomhelper.cc \ - namespaces.hh nsecrecords.cc base32.cc dbdnsseckeeper.cc \ - dnssecinfra.cc dnsseckeeper.hh dnssecinfra.hh base32.hh dns.cc \ + backends/gsql/ssql.hh base64.cc sillyrecords.cc \ + secpoll-auth.cc secpoll-auth.hh base64.hh zoneparser-tng.cc \ + dnsrecords.cc dnswriter.cc rcpgenerator.cc dnsparser.cc \ + dns_random.hh dns_random.cc randomhelper.cc namespaces.hh \ + nsecrecords.cc base32.cc dbdnsseckeeper.cc dnssecinfra.cc \ + dnsseckeeper.hh dnssecinfra.hh base32.hh dns.cc \ dnssecsigner.cc polarrsakeyinfra.cc sha.hh md5.hh \ signingpipe.cc signingpipe.hh dnslabeltext.cc lua-pdns.cc \ lua-auth.cc lua-auth.hh serialtweaker.cc ednssubnet.cc \ @@ -357,7 +358,7 @@ unix_utility.$(OBJEXT) common_startup.$(OBJEXT) \ unix_semaphore.$(OBJEXT) bindparser.$(OBJEXT) \ bindlexer.$(OBJEXT) backends/gsql/gsqlbackend.$(OBJEXT) \ - base64.$(OBJEXT) sillyrecords.$(OBJEXT) \ + base64.$(OBJEXT) sillyrecords.$(OBJEXT) secpoll-auth.$(OBJEXT) \ zoneparser-tng.$(OBJEXT) dnsrecords.$(OBJEXT) \ dnswriter.$(OBJEXT) rcpgenerator.$(OBJEXT) dnsparser.$(OBJEXT) \ dns_random.$(OBJEXT) randomhelper.$(OBJEXT) \ @@ -961,18 +962,18 @@ unix_semaphore.cc bind-dnssec.schema.sqlite3.sql.h \ bindparser.cc bindlexer.c backends/gsql/gsqlbackend.cc \ backends/gsql/gsqlbackend.hh backends/gsql/ssql.hh base64.cc \ - sillyrecords.cc base64.hh zoneparser-tng.cc dnsrecords.cc \ - dnswriter.cc rcpgenerator.cc dnsparser.cc dns_random.hh \ - dns_random.cc randomhelper.cc namespaces.hh nsecrecords.cc \ - base32.cc dbdnsseckeeper.cc dnssecinfra.cc dnsseckeeper.hh \ - dnssecinfra.hh base32.hh dns.cc dnssecsigner.cc \ - polarrsakeyinfra.cc sha.hh md5.hh signingpipe.cc \ - signingpipe.hh dnslabeltext.cc lua-pdns.cc lua-auth.cc \ - lua-auth.hh serialtweaker.cc ednssubnet.cc ednssubnet.hh \ - cachecleaner.hh json.cc json.hh version.hh version.cc \ - rfc2136handler.cc responsestats.cc responsestats.hh comment.hh \ - auth-carbon.cc $(am__append_5) $(am__append_7) $(am__append_9) \ - $(am__append_11) $(am__append_13) + sillyrecords.cc secpoll-auth.cc secpoll-auth.hh base64.hh \ + zoneparser-tng.cc dnsrecords.cc dnswriter.cc rcpgenerator.cc \ + dnsparser.cc dns_random.hh dns_random.cc randomhelper.cc \ + namespaces.hh nsecrecords.cc base32.cc dbdnsseckeeper.cc \ + dnssecinfra.cc dnsseckeeper.hh dnssecinfra.hh base32.hh dns.cc \ + dnssecsigner.cc polarrsakeyinfra.cc sha.hh md5.hh \ + signingpipe.cc signingpipe.hh dnslabeltext.cc lua-pdns.cc \ + lua-auth.cc lua-auth.hh serialtweaker.cc ednssubnet.cc \ + ednssubnet.hh cachecleaner.hh json.cc json.hh version.hh \ + version.cc rfc2136handler.cc responsestats.cc responsestats.hh \ + comment.hh auth-carbon.cc $(am__append_5) $(am__append_7) \ + $(am__append_9) $(am__append_11) $(am__append_13) pdns_server_LDFLAGS = @moduleobjects@ @modulelibs@ $(DYNLINKFLAGS) @LIBDL@ $(THREADFLAGS) $(BOOST_SERIALIZATION_LDFLAGS) -rdynamic pdns_server_LDADD = $(POLARSSL_LIBS) $(BOOST_SERIALIZATION_LIBS) \ $(LUA_LIBS) $(SQLITE3_LIBS) $(YAHTTP_LIBS) $(am__append_6) \ @@ -1498,6 +1499,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rfc2136handler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/saxfr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdig.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/secpoll-auth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/selectmplexer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serialtweaker.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signingpipe.Po@am__quote@ diff -Nru pdns-3.4.0/pdns/pdns.conf-dist pdns-3.4.1/pdns/pdns.conf-dist --- pdns-3.4.0/pdns/pdns.conf-dist 2014-08-12 13:32:10.000000000 +0200 +++ pdns-3.4.1/pdns/pdns.conf-dist 2014-10-28 11:41:09.000000000 +0100 @@ -145,6 +145,11 @@ # entropy-source=/dev/urandom ################################# +# experimental-api-key REST API Static authentication key (required for API use) +# +# experimental-api-key= + +################################# # experimental-api-readonly If the JSON API should disallow data modification # # experimental-api-readonly=no @@ -370,6 +375,11 @@ # reuseport=no ################################# +# security-poll-suffix Domain name from which to query security update notifications +# +# security-poll-suffix=secpoll.powerdns.com. + +################################# # send-root-referral Send out old-fashioned root-referral instead of ServFail in case of no authority # # send-root-referral=no diff -Nru pdns-3.4.0/pdns/pdns_recursor.cc pdns-3.4.1/pdns/pdns_recursor.cc --- pdns-3.4.0/pdns/pdns_recursor.cc 2014-09-25 13:42:01.000000000 +0200 +++ pdns-3.4.1/pdns/pdns_recursor.cc 2014-10-30 11:18:22.000000000 +0100 @@ -2101,6 +2101,7 @@ ::arg().set("experimental-webserver-password", "Password required for accessing the webserver") = ""; ::arg().set("webserver-allow-from","Webserver access is only allowed from these subnets")="0.0.0.0/0,::/0"; ::arg().set("experimental-api-config-dir", "Directory where REST API stores config and zones") = ""; + ::arg().set("experimental-api-key", "REST API Static authentication key (required for API use)") = ""; ::arg().set("carbon-ourname", "If set, overrides our reported hostname for carbon stats")=""; ::arg().set("carbon-server", "If set, send metrics in carbon (graphite) format to this server")=""; ::arg().set("carbon-interval", "Number of seconds between carbon (graphite) updates")="30"; diff -Nru pdns-3.4.0/pdns/pdnssec.cc pdns-3.4.1/pdns/pdnssec.cc --- pdns-3.4.0/pdns/pdnssec.cc 2014-07-29 14:58:22.000000000 +0200 +++ pdns-3.4.1/pdns/pdnssec.cc 2014-10-30 11:18:22.000000000 +0100 @@ -612,10 +612,37 @@ } rrs[0].content = serializeSOAData(sd); + sd.db->startTransaction("", -1); + if (! sd.db->replaceRRSet(sd.domain_id, zone, rr.qtype, rrs)) { + sd.db->abortTransaction(); cerr<<"Backend did not replace SOA record. Backend might not support this operation."<<endl; return -1; } + + if (sd.db->doesDNSSEC()) { + NSEC3PARAMRecordContent ns3pr; + bool narrow; + bool haveNSEC3=dk.getNSEC3PARAM(zone, &ns3pr, &narrow); + + if(haveNSEC3) + { + if(!narrow) { + string hashed=toBase32Hex(hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rrs[0].qname)); + if(g_verbose) + cerr<<"'"<<rrs[0].qname<<"' -> '"<< hashed <<"'"<<endl; + sd.db->updateDNSSECOrderAndAuthAbsolute(sd.domain_id, rrs[0].qname, hashed, 1); + } + else { + sd.db->nullifyDNSSECOrderNameAndUpdateAuth(sd.domain_id, rrs[0].qname, 1); + } + } else { + sd.db->updateDNSSECOrderAndAuth(sd.domain_id, zone, rrs[0].qname, 1); + } + } + + sd.db->commitTransaction(); + cout<<"SOA serial for zone "<<zone<<" set to "<<sd.serial<<endl; return 0; } diff -Nru pdns-3.4.0/pdns/secpoll-auth.cc pdns-3.4.1/pdns/secpoll-auth.cc --- pdns-3.4.0/pdns/secpoll-auth.cc 1970-01-01 01:00:00.000000000 +0100 +++ pdns-3.4.1/pdns/secpoll-auth.cc 2014-10-22 20:51:18.000000000 +0200 @@ -0,0 +1,168 @@ +#include "secpoll-auth.hh" + +#include "logger.hh" +#include "arguments.hh" +#include "version.hh" +#include "version_generated.h" +#include "dnsparser.hh" +#include "misc.hh" +#include <boost/foreach.hpp> +#include "sstuff.hh" +#include "dnswriter.hh" +#include "dns_random.hh" +#include "namespaces.hh" +#include "statbag.hh" +#include <stdint.h> +#ifndef PACKAGEVERSION +#define PACKAGEVERSION PDNS_VERSION +#endif + +string g_security_message; + +extern StatBag S; + +static vector<ComboAddress> parseResolveConf() +{ + vector<ComboAddress> ret; + ifstream ifs("/etc/resolv.conf"); + if(!ifs) + return ret; + + string line; + while(std::getline(ifs, line)) { + boost::trim_right_if(line, is_any_of(" \r\n\x1a")); + boost::trim_left(line); // leading spaces, let's be nice + + string::size_type tpos = line.find_first_of(";#"); + if(tpos != string::npos) + line.resize(tpos); + + if(boost::starts_with(line, "nameserver ") || boost::starts_with(line, "nameserver\t")) { + vector<string> parts; + stringtok(parts, line, " \t,"); // be REALLY nice + for(vector<string>::const_iterator iter = parts.begin()+1; iter != parts.end(); ++iter) { + + try { + ret.push_back(ComboAddress(*iter, 53)); + } + catch(...) + { + } + } + } + + } + + return ret; +} + +int doResolve(const string& qname, uint16_t qtype, vector<DNSResourceRecord>& ret) +{ + vector<uint8_t> packet; + + DNSPacketWriter pw(packet, qname, qtype); + pw.getHeader()->id=dns_random(0xffff); + pw.getHeader()->rd=1; + + static vector<ComboAddress> s_servers; + vector<ComboAddress> servers = parseResolveConf(); + if(!servers.empty()) + s_servers = servers; // in case we chrooted in the meantime + + if(s_servers.empty()) + L<<Logger::Warning<<"Unable to poll PowerDNS security status, did not get any servers from resolv.conf"<<endl; + + BOOST_FOREACH(ComboAddress& dest, s_servers) { + Socket sock(dest.sin4.sin_family, SOCK_DGRAM); + sock.setNonBlocking(); + sock.sendTo(string((char*)&*packet.begin(), (char*)&*packet.end()), dest); + + string reply; + + waitForData(sock.getHandle(), 2, 0); + try { + retry: + sock.recvFrom(reply, dest); + if(reply.size() > sizeof(struct dnsheader)) { + struct dnsheader d; + memcpy(&d, reply.c_str(), sizeof(d)); + if(d.id != pw.getHeader()->id) + goto retry; + } + } + catch(...) { + continue; + } + MOADNSParser mdp(reply); + if(mdp.d_header.rcode == RCode::ServFail) + continue; + + + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { + if(i->first.d_place == 1 && i->first.d_type==QType::TXT) { + DNSResourceRecord rr; + rr.qname = i->first.d_label; + rr.qtype = QType(i->first.d_type); + rr.content = i->first.d_content->getZoneRepresentation(); + rr.ttl=i->first.d_ttl; + ret.push_back(rr); + } + } + + return mdp.d_header.rcode; + } + return RCode::ServFail; +} + +void doSecPoll(bool first) +{ + if(::arg()["security-poll-suffix"].empty()) + return; + + struct timeval now; + gettimeofday(&now, 0); + + string query = "auth-" PACKAGEVERSION ".security-status."+::arg()["security-poll-suffix"]; + + if(*query.rbegin()!='.') + query+='.'; + + boost::replace_all(query, "+", "_"); + + vector<DNSResourceRecord> ret; + + int res=doResolve(query, QType::TXT, ret); + + int security_status=0; + + if(!res && !ret.empty()) { + string content=ret.begin()->content; + if(!content.empty() && content[0]=='"' && content[content.size()-1]=='"') { + content=content.substr(1, content.length()-2); + } + + pair<string, string> split = splitField(content, ' '); + + security_status = atoi(split.first.c_str()); + g_security_message = split.second; + + } + else { + L<<Logger::Warning<<"Could not retrieve security status update for '" PACKAGEVERSION "' on '"+query+"', RCODE = "<< RCode::to_s(res)<<endl; + if(security_status == 1) // it was ok, not it is unknown + security_status = 0; + } + + if(security_status == 1 && first) { + L<<Logger::Warning << "Polled security status of version "<<PACKAGEVERSION<<" at startup, no known issues reported: " <<g_security_message<<endl; + } + if(security_status == 2) { + L<<Logger::Error<<"PowerDNS Security Update Recommended: "<<g_security_message<<endl; + } + else if(security_status == 3) { + L<<Logger::Error<<"PowerDNS Security Update Mandatory: "<<g_security_message<<endl; + } + + S.set("security-status",security_status); + +} diff -Nru pdns-3.4.0/pdns/secpoll-auth.hh pdns-3.4.1/pdns/secpoll-auth.hh --- pdns-3.4.0/pdns/secpoll-auth.hh 1970-01-01 01:00:00.000000000 +0100 +++ pdns-3.4.1/pdns/secpoll-auth.hh 2014-10-22 17:01:25.000000000 +0200 @@ -0,0 +1,9 @@ +#ifndef PDNS_SECPOLL_AUTH_HH +#define PDNS_SECPOLL_AUTH_HH +#include <time.h> +#include "namespaces.hh" + +void doSecPoll(bool first); +extern std::string g_security_message; + +#endif diff -Nru pdns-3.4.0/pdns/tcpreceiver.cc pdns-3.4.1/pdns/tcpreceiver.cc --- pdns-3.4.0/pdns/tcpreceiver.cc 2014-08-12 13:32:10.000000000 +0200 +++ pdns-3.4.1/pdns/tcpreceiver.cc 2014-10-21 13:31:14.000000000 +0200 @@ -1008,7 +1008,10 @@ sendPacket(outpacket,outsock); return 0; } - if (!rfc1982LessThan(serial, sd.serial)) { + + string soaedit; + dk.getFromMeta(target, "SOA-EDIT", soaedit); + if (!rfc1982LessThan(serial, calculateEditSOA(sd, soaedit))) { TSIGRecordContent trc; string tsigkeyname, tsigsecret; diff -Nru pdns-3.4.0/pdns/webserver.cc pdns-3.4.1/pdns/webserver.cc --- pdns-3.4.0/pdns/webserver.cc 2014-07-30 16:42:05.000000000 +0200 +++ pdns-3.4.1/pdns/webserver.cc 2014-10-30 11:18:22.000000000 +0100 @@ -48,6 +48,37 @@ } } +bool HttpRequest::compareAuthorization(const string &expected_password) +{ + // validate password + YaHTTP::strstr_map_t::iterator header = headers.find("authorization"); + bool auth_ok = false; + if (header != headers.end() && toLower(header->second).find("basic ") == 0) { + string cookie = header->second.substr(6); + + string plain; + B64Decode(cookie, plain); + + vector<string> cparts; + stringtok(cparts, plain, ":"); + + // this gets rid of terminating zeros + auth_ok = (cparts.size()==2 && (0==strcmp(cparts[1].c_str(), expected_password.c_str()))); + } + return auth_ok; +} + +bool HttpRequest::compareHeader(const string &header_name, const string &expected_value) +{ + YaHTTP::strstr_map_t::iterator header = headers.find(header_name); + if (header == headers.end()) + return false; + + // this gets rid of terminating zeros + return (0==strcmp(header->second.c_str(), expected_value.c_str())); +} + + void HttpResponse::setBody(rapidjson::Document& document) { this->body = makeStringFromDocument(document); @@ -58,19 +89,30 @@ return ::B64Decode(strInput, strOutput); } -static void handlerWrapper(WebServer::HandlerFunction handler, YaHTTP::Request* req, YaHTTP::Response* resp) +static void bareHandlerWrapper(WebServer::HandlerFunction handler, YaHTTP::Request* req, YaHTTP::Response* resp) { // wrapper to convert from YaHTTP::* to our subclasses handler(static_cast<HttpRequest*>(req), static_cast<HttpResponse*>(resp)); } -void WebServer::registerHandler(const string& url, HandlerFunction handler) +void WebServer::registerBareHandler(const string& url, HandlerFunction handler) { - YaHTTP::THandlerFunction f = boost::bind(&handlerWrapper, handler, _1, _2); + YaHTTP::THandlerFunction f = boost::bind(&bareHandlerWrapper, handler, _1, _2); YaHTTP::Router::Any(url, f); } static void apiWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp) { + const string& api_key = arg()["experimental-api-key"]; + if (api_key.empty()) { + L<<Logger::Debug<<"HTTP API Request \"" << req->url.path << "\": Authentication failed, API Key missing in config" << endl; + throw HttpUnauthorizedException(); + } + bool auth_ok = req->compareHeader("x-api-key", api_key); + if (!auth_ok) { + L<<Logger::Debug<<"HTTP Request \"" << req->url.path << "\": Authentication by API Key failed" << endl; + throw HttpUnauthorizedException(); + } + resp->headers["Access-Control-Allow-Origin"] = "*"; resp->headers["Content-Type"] = "application/json"; @@ -108,7 +150,25 @@ void WebServer::registerApiHandler(const string& url, HandlerFunction handler) { HandlerFunction f = boost::bind(&apiWrapper, handler, _1, _2); - registerHandler(url, f); + registerBareHandler(url, f); +} + +static void webWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp) { + const string& web_password = arg()["webserver-password"]; + if (!web_password.empty()) { + bool auth_ok = req->compareAuthorization(web_password); + if (!auth_ok) { + L<<Logger::Debug<<"HTTP Request \"" << req->url.path << "\": Web Authentication failed" << endl; + throw HttpUnauthorizedException(); + } + } + + handler(req, resp); +} + +void WebServer::registerWebHandler(const string& url, HandlerFunction handler) { + HandlerFunction f = boost::bind(&webWrapper, handler, _1, _2); + registerBareHandler(url, f); } static void *WebServerConnectionThreadStart(void *p) { @@ -148,28 +208,6 @@ } } - if (!d_password.empty()) { - // validate password - header = req.headers.find("authorization"); - bool auth_ok = false; - if (header != req.headers.end() && toLower(header->second).find("basic ") == 0) { - string cookie = header->second.substr(6); - - string plain; - B64Decode(cookie, plain); - - vector<string> cparts; - stringtok(cparts, plain, ":"); - - // this gets rid of terminating zeros - auth_ok = (cparts.size()==2 && (0==strcmp(cparts[1].c_str(), d_password.c_str()))); - } - if (!auth_ok) { - L<<Logger::Debug<<"HTTP Request \"" << req.url.path << "\": Authentication failed" << endl; - throw HttpUnauthorizedException(); - } - } - YaHTTP::THandlerFunction handler; if (!YaHTTP::Router::Route(&req, handler)) { L<<Logger::Debug<<"HTTP: No route found for \"" << req.url.path << "\"" << endl; @@ -268,11 +306,10 @@ L<<Logger::Error<<"HTTP: Unknown exception"<<endl; } -WebServer::WebServer(const string &listenaddress, int port, const string &password) : d_server(NULL) +WebServer::WebServer(const string &listenaddress, int port) : d_server(NULL) { d_listenaddress=listenaddress; d_port=port; - d_password=password; } void WebServer::bind() diff -Nru pdns-3.4.0/pdns/webserver.hh pdns-3.4.1/pdns/webserver.hh --- pdns-3.4.0/pdns/webserver.hh 2014-06-24 14:22:01.000000000 +0200 +++ pdns-3.4.1/pdns/webserver.hh 2014-10-21 14:34:39.000000000 +0200 @@ -32,6 +32,8 @@ #include "namespaces.hh" #include "sstuff.hh" +class WebServer; + class HttpRequest : public YaHTTP::Request { public: HttpRequest() : YaHTTP::Request(), accept_json(false), accept_html(false), complete(false) { }; @@ -40,6 +42,10 @@ bool accept_html; bool complete; void json(rapidjson::Document& document); + + // checks password _only_. + bool compareAuthorization(const string &expected_password); + bool compareHeader(const string &header_name, const string &expected_value); }; class HttpResponse: public YaHTTP::Response { @@ -125,7 +131,7 @@ class WebServer : public boost::noncopyable { public: - WebServer(const string &listenaddress, int port, const string &password=""); + WebServer(const string &listenaddress, int port); void bind(); void go(); @@ -133,12 +139,13 @@ HttpResponse handleRequest(HttpRequest request); typedef boost::function<void(HttpRequest* req, HttpResponse* resp)> HandlerFunction; - void registerHandler(const string& url, HandlerFunction handler); void registerApiHandler(const string& url, HandlerFunction handler); + void registerWebHandler(const string& url, HandlerFunction handler); protected: static char B64Decode1(char cInChar); static int B64Decode(const std::string& strInput, std::string& strOutput); + void registerBareHandler(const string& url, HandlerFunction handler); virtual Server* createServer() { return new Server(d_listenaddress, d_port); diff -Nru pdns-3.4.0/pdns/ws-auth.cc pdns-3.4.1/pdns/ws-auth.cc --- pdns-3.4.0/pdns/ws-auth.cc 2014-08-12 13:32:10.000000000 +0200 +++ pdns-3.4.1/pdns/ws-auth.cc 2014-10-30 11:18:22.000000000 +0100 @@ -61,7 +61,7 @@ d_ws = 0; d_tid = 0; if(arg().mustDo("webserver")) { - d_ws = new WebServer(arg()["webserver-address"], arg().asNum("webserver-port"),arg()["webserver-password"]); + d_ws = new WebServer(arg()["webserver-address"], arg().asNum("webserver-port")); d_ws->bind(); } } @@ -1255,8 +1255,8 @@ // legacy dispatch d_ws->registerApiHandler("/jsonstat", boost::bind(&AuthWebServer::jsonstat, this, _1, _2)); } - d_ws->registerHandler("/style.css", boost::bind(&AuthWebServer::cssfunction, this, _1, _2)); - d_ws->registerHandler("/", boost::bind(&AuthWebServer::indexfunction, this, _1, _2)); + d_ws->registerWebHandler("/style.css", boost::bind(&AuthWebServer::cssfunction, this, _1, _2)); + d_ws->registerWebHandler("/", boost::bind(&AuthWebServer::indexfunction, this, _1, _2)); d_ws->go(); } catch(...) { diff -Nru pdns-3.4.0/pdns/ws-recursor.cc pdns-3.4.1/pdns/ws-recursor.cc --- pdns-3.4.0/pdns/ws-recursor.cc 2014-06-24 14:22:01.000000000 +0200 +++ pdns-3.4.1/pdns/ws-recursor.cc 2014-10-30 11:18:22.000000000 +0100 @@ -421,7 +421,7 @@ { RecursorControlParser rcp; // inits - d_ws = new AsyncWebServer(fdm, arg()["experimental-webserver-address"], arg().asNum("experimental-webserver-port"), arg()["experimental-webserver-password"]); + d_ws = new AsyncWebServer(fdm, arg()["experimental-webserver-address"], arg().asNum("experimental-webserver-port")); d_ws->bind(); // legacy dispatch diff -Nru pdns-3.4.0/pdns/ws-recursor.hh pdns-3.4.1/pdns/ws-recursor.hh --- pdns-3.4.0/pdns/ws-recursor.hh 2014-03-27 12:22:04.000000000 +0100 +++ pdns-3.4.1/pdns/ws-recursor.hh 2014-10-21 14:34:39.000000000 +0200 @@ -45,8 +45,8 @@ class AsyncWebServer : public WebServer { public: - AsyncWebServer(FDMultiplexer* fdm, const string &listenaddress, int port, const string &password="") : - WebServer(listenaddress, port, password), d_fdm(fdm) { }; + AsyncWebServer(FDMultiplexer* fdm, const string &listenaddress, int port) : + WebServer(listenaddress, port), d_fdm(fdm) { }; void go(); private: diff -Nru pdns-3.4.0/pdns.spec pdns-3.4.1/pdns.spec --- pdns-3.4.0/pdns.spec 2014-09-30 11:23:37.000000000 +0200 +++ pdns-3.4.1/pdns.spec 2014-10-30 11:18:22.000000000 +0100 @@ -1,6 +1,6 @@ BuildRoot: /tmp/pdns Name: pdns-static -Version: 3.4.0 +Version: 3.4.1 Release: 1 Summary: extremely powerful and versatile nameserver License: GPL
diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/build-scripts/redhat/pdns-server-test.spec pdns/build-scripts/redhat/pdns-server-test.spec --- pdns-3.4.0/build-scripts/redhat/pdns-server-test.spec 2014-09-30 11:23:37.000000000 +0200 +++ pdns/build-scripts/redhat/pdns-server-test.spec 2014-11-01 22:02:44.119097948 +0100 @@ -9,7 +9,7 @@ Epoch: 0 License: GPL Group: System/Servers -Source: http://downloads.powerdns.com/releases/pdns-3.4.0.tar.bz2 +Source: http://downloads.powerdns.com/releases/pdns-3.4.1.tar.bz2 BuildRequires: autoconf automake BuildRequires: gcc gcc-c++ @@ -30,7 +30,7 @@ PowerDNS testbuild %prep -%setup -q -n pdns-3.4.0 +%setup -q -n pdns-3.4.1 %build %configure \ diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/configure pdns/configure --- pdns-3.4.0/configure 2014-09-30 11:23:48.000000000 +0200 +++ pdns/configure 2014-11-01 23:05:58.621872827 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for pdns 3.4.0. +# Generated by GNU Autoconf 2.69 for pdns 3.4.1. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -587,8 +587,8 @@ # Identity of this package. PACKAGE_NAME='pdns' PACKAGE_TARNAME='pdns' -PACKAGE_VERSION='3.4.0' -PACKAGE_STRING='pdns 3.4.0' +PACKAGE_VERSION='3.4.1' +PACKAGE_STRING='pdns 3.4.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1471,7 +1471,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pdns 3.4.0 to adapt to many kinds of systems. +\`configure' configures pdns 3.4.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1541,7 +1541,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pdns 3.4.0:";; + short | recursive ) echo "Configuration of pdns 3.4.1:";; esac cat <<\_ACEOF @@ -1737,7 +1737,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pdns configure 3.4.0 +pdns configure 3.4.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2344,7 +2344,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pdns $as_me 3.4.0, which was +It was created by pdns $as_me 3.4.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3167,7 +3167,7 @@ # Define the identity of the package. PACKAGE='pdns' - VERSION='3.4.0' + VERSION='3.4.1' cat >>confdefs.h <<_ACEOF @@ -21020,7 +21020,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pdns $as_me 3.4.0, which was +This file was extended by pdns $as_me 3.4.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -21086,7 +21086,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -pdns config.status 3.4.0 +pdns config.status 3.4.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/configure.ac pdns/configure.ac --- pdns-3.4.0/configure.ac 2014-09-30 11:23:37.000000000 +0200 +++ pdns/configure.ac 2014-11-01 22:02:44.119097948 +0100 @@ -1,7 +1,7 @@ AC_PREREQ([2.61]) dnl The following lines may be patched by set-version-auth. -AC_INIT([pdns], [3.4.0]) +AC_INIT([pdns], [3.4.1]) AC_SUBST([DIST_HOST], [jenk...@autotest.powerdns.com]) dnl End patch area. diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/debian/changelog pdns/debian/changelog --- pdns-3.4.0/debian/changelog 2014-10-15 08:34:22.000000000 +0200 +++ pdns/debian/changelog 2014-11-01 23:13:12.303578094 +0100 @@ -1,3 +1,18 @@ +pdns (3.4.1-1) unstable; urgency=medium + + * Imported Upstream version 3.4.1, a bug fix release, that: + * Fixes slaving of DNSSEC-signed zones to NSD or BIND. + * Fixes pdnssec increase-serial to not break SOA records + in DNSSEC zones. + * Adds security status polling. (We set the package vendor + and version for this.) + * Remove patch 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custom, + which has been applied upstream. + * Resync pdns.conf with upstream + * Update debian/watch file, as upstream has changed to bz2 files. + + -- Christian Hofstaedtler <z...@debian.org> Sat, 01 Nov 2014 23:08:08 +0100 + pdns (3.4.0-2) unstable; urgency=medium * Apply patch from upstream switching API auth to a static key. diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/debian/config/pdns.conf pdns/debian/config/pdns.conf --- pdns-3.4.0/debian/config/pdns.conf 2014-08-30 02:30:22.000000000 +0200 +++ pdns/debian/config/pdns.conf 2014-11-01 23:06:52.734085767 +0100 @@ -1,17 +1,12 @@ ################################# -# add-superfluous-nsec3-for-old-bind Add superfluous NSEC3 record to positive wildcard response -# -# add-superfluous-nsec3-for-old-bind=yes - -################################# -# allow-2136-from A global setting to allow RFC2136 from these IP ranges. +# allow-axfr-ips Allow zonetransfers only to these subnets # -# allow-2136-from=0.0.0.0/0 +# allow-axfr-ips=127.0.0.0/8,::1 ################################# -# allow-axfr-ips Allow zonetransfers only to these subnets +# allow-dnsupdate-from A global setting to allow DNS updates from these IP ranges. # -# allow-axfr-ips=0.0.0.0/0,::/0 +# allow-dnsupdate-from=127.0.0.0/8,::1 ################################# # allow-recursion List of subnets that are allowed to recurse @@ -104,7 +99,7 @@ # default-zsk-algorithms=rsasha256 ################################# -# default-zsk-size Default KSK size (0 means default) +# default-zsk-size Default ZSK size (0 means default) # # default-zsk-size=0 @@ -149,6 +144,11 @@ # entropy-source=/dev/urandom ################################# +# experimental-api-key REST API Static authentication key (required for API use) +# +# experimental-api-key= + +################################# # experimental-api-readonly If the JSON API should disallow data modification # # experimental-api-readonly=no @@ -159,6 +159,11 @@ # experimental-dname-processing=no ################################# +# experimental-dnsupdate Enable/Disable DNS update (RFC2136) support. Default is no. +# +# experimental-dnsupdate=no + +################################# # experimental-json-interface If the webserver should serve JSON data # # experimental-json-interface=no @@ -169,19 +174,9 @@ # experimental-logfile=/var/log/pdns.log ################################# -# experimental-rfc2136 Enable/Disable RFC2136 (Dynamic DNS) support. Default is no. +# forward-dnsupdate A global setting to allow DNS update packages that are for a Slave domain, to be forwarded to the master. # -# experimental-rfc2136=no - -################################# -# fancy-records Process URL and MBOXFW records -# -# fancy-records=no - -################################# -# forward-2136 A global setting to allow RFC2136 packages that are for a Slave domain, to be forwarded to the master. -# -# forward-2136=yes +# forward-dnsupdate=yes ################################# # guardian Run within a guardian process @@ -271,11 +266,21 @@ # max-ent-entries=100000 ################################# +# max-nsec3-iterations Limit the number of NSEC3 hash iterations +# +# max-nsec3-iterations=500 + +################################# # max-queue-length Maximum queuelength before considering situation lost # # max-queue-length=5000 ################################# +# max-signature-cache-entries Maximum number of signatures cache entries +# +# max-signature-cache-entries= + +################################# # max-tcp-connections Maximum number of TCP connections # # max-tcp-connections=10 @@ -371,6 +376,11 @@ # reuseport=no ################################# +# security-poll-suffix Domain name from which to query security update notifications +# +# security-poll-suffix=secpoll.powerdns.com. + +################################# # send-root-referral Send out old-fashioned root-referral instead of ServFail in case of no authority # # send-root-referral=no @@ -411,11 +421,6 @@ # slave-renotify=no ################################# -# smtpredirector Our smtpredir MX host -# -# smtpredirector=a.misconfigured.powerdns.smtp.server - -################################# # soa-expire-default Default SOA expire # # soa-expire-default=604800 @@ -436,11 +441,6 @@ # soa-retry-default=3600 ################################# -# soa-serial-offset Make sure that no SOA serial is less than this number -# -# soa-serial-offset=0 - -################################# # socket-dir Where the controlsocket will live # # socket-dir=/var/run @@ -481,11 +481,6 @@ # udp-truncation-threshold=1680 ################################# -# urlredirector Where we send hosts to that need to be url redirected -# -# urlredirector=127.0.0.1 - -################################# # version-string PowerDNS version in packets - full, anonymous, powerdns or custom # # version-string=full @@ -501,6 +496,11 @@ # webserver-address=127.0.0.1 ################################# +# webserver-allow-from Webserver access is only allowed from these subnets +# +# webserver-allow-from=0.0.0.0/0,::/0 + +################################# # webserver-password Password required for accessing the webserver # # webserver-password= @@ -515,9 +515,4 @@ # # webserver-print-arguments=no -################################# -# wildcard-url Process URL and MBOXFW records -# -# wildcard-url=no - diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/debian/patches/series pdns/debian/patches/series --- pdns-3.4.0/debian/patches/series 2014-10-12 21:53:12.000000000 +0200 +++ pdns/debian/patches/series 2014-11-01 23:06:52.714085692 +0100 @@ -1 +1 @@ -0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch + diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/debian/rules pdns/debian/rules --- pdns-3.4.0/debian/rules 2014-08-31 06:54:54.000000000 +0200 +++ pdns/debian/rules 2014-11-01 23:06:31.214001085 +0100 @@ -1,5 +1,9 @@ #!/usr/bin/make -f +# Vendor and version +version := $(shell dpkg-parsechangelog -S Version).$(shell dpkg-vendor --query Vendor) +CXXFLAGS += -DPACKAGEVERSION='"$(version)"' + # Backends backends := bind ldap pipe gmysql gpgsql gsqlite3 geo lua lmdb mydns remote diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/debian/source/local-options pdns/debian/source/local-options --- pdns-3.4.0/debian/source/local-options 1970-01-01 01:00:00.000000000 +0100 +++ pdns/debian/source/local-options 2014-11-01 22:00:31.030636313 +0100 @@ -0,0 +1 @@ +unapply-patches diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/debian/watch pdns/debian/watch --- pdns-3.4.0/debian/watch 2014-08-30 02:30:22.000000000 +0200 +++ pdns/debian/watch 2014-11-01 22:01:17.310796734 +0100 @@ -3,4 +3,4 @@ # to check for upstream updates and more. # Site Directory Pattern Version Script version=3 -http://downloads.powerdns.com/releases/ pdns-(.*)\.tar\.gz debian uupdate +http://downloads.powerdns.com/releases/ pdns-([0-9]+.*)\.tar\.(gz|bz2) debian uupdate diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/debian-pdns/changelog pdns/debian-pdns/changelog --- pdns-3.4.0/debian-pdns/changelog 2014-09-30 11:23:37.000000000 +0200 +++ pdns/debian-pdns/changelog 2014-11-01 22:02:44.119097948 +0100 @@ -1,4 +1,4 @@ -pdns (3.4.0-1) unstable; urgency=medium +pdns (3.4.1-1) unstable; urgency=medium * fill in the blanks diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/pdns/common_startup.cc pdns/pdns/common_startup.cc --- pdns-3.4.0/pdns/common_startup.cc 2014-11-01 23:21:49.000000000 +0100 +++ pdns/pdns/common_startup.cc 2014-11-01 22:02:44.119097948 +0100 @@ -21,6 +21,7 @@ */ #include "common_startup.hh" #include "ws-auth.hh" +#include "secpoll-auth.hh" bool g_anyToTcp; typedef Distributor<DNSPacket,DNSPacket,PacketHandler> DNSDistributor; @@ -160,6 +161,7 @@ ::arg().set("max-nsec3-iterations","Limit the number of NSEC3 hash iterations")="500"; // RFC5155 10.3 ::arg().set("include-dir","Include *.conf files from this directory"); + ::arg().set("security-poll-suffix","Domain name from which to query security update notifications")="secpoll.powerdns.com."; } void declareStats(void) @@ -199,7 +201,7 @@ S.declare("servfail-packets","Number of times a server-failed packet was sent out"); S.declare("latency","Average number of microseconds needed to answer a question"); S.declare("timedout-packets","Number of packets which weren't answered within timeout set"); - + S.declare("security-status", "Security status based on regular polling"); S.declareRing("queries","UDP Queries Received"); S.declareRing("nxdomain-queries","Queries for non-existent records within existent domains"); S.declareRing("noerror-queries","Queries for existing records, but for type we don't have"); @@ -363,6 +365,9 @@ DNSPacket::s_udpTruncationThreshold = std::max(512, ::arg().asNum("udp-truncation-threshold")); DNSPacket::s_doEDNSSubnetProcessing = ::arg().mustDo("edns-subnet-processing"); + + doSecPoll(true); // this must be BEFORE chroot + if(!::arg()["chroot"].empty()) { if(::arg().mustDo("master") || ::arg().mustDo("slave")) gethostbyname("a.root-servers.net"); // this forces all lookup libraries to be loaded @@ -400,13 +405,19 @@ TN->go(); // tcp nameserver launch pthread_create(&qtid,0,carbonDumpThread, 0); // runs even w/o carbon, might change @ runtime + // fork(); (this worked :-)) unsigned int max_rthreads= ::arg().asNum("receiver-threads", 1); for(unsigned int n=0; n < max_rthreads; ++n) pthread_create(&qtid,0,qthread, reinterpret_cast<void *>(n)); // receives packets - void *p; - pthread_join(qtid, &p); + for(;;) { + sleep(1800); + try { + doSecPoll(false); + } + catch(...){} + } L<<Logger::Error<<"Mainthread exiting - should never happen"<<endl; } diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/pdns/docs/dnsdist.1 pdns/pdns/docs/dnsdist.1 --- pdns-3.4.0/pdns/docs/dnsdist.1 2014-09-30 11:24:27.000000000 +0200 +++ pdns/pdns/docs/dnsdist.1 2014-11-01 22:02:44.119097948 +0100 @@ -2,12 +2,12 @@ .\" Title: dnsdist .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/> -.\" Date: 09/30/2014 +.\" Date: 10/30/2014 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "DNSDIST" "1" "09/30/2014" "\ \&" "\ \&" +.TH "DNSDIST" "1" "10/30/2014" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/pdns/docs/dnstcpbench.1 pdns/pdns/docs/dnstcpbench.1 --- pdns-3.4.0/pdns/docs/dnstcpbench.1 2014-09-30 11:24:26.000000000 +0200 +++ pdns/pdns/docs/dnstcpbench.1 2014-11-01 22:02:44.119097948 +0100 @@ -2,12 +2,12 @@ .\" Title: dnstcpbench .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/> -.\" Date: 09/30/2014 +.\" Date: 10/30/2014 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "DNSTCPBENCH" "1" "09/30/2014" "\ \&" "\ \&" +.TH "DNSTCPBENCH" "1" "10/30/2014" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/pdns/Makefile.am pdns/pdns/Makefile.am --- pdns-3.4.0/pdns/Makefile.am 2014-08-29 16:02:13.000000000 +0200 +++ pdns/pdns/Makefile.am 2014-11-01 22:02:44.119097948 +0100 @@ -58,7 +58,7 @@ bindparser.cc bindlexer.c \ backends/gsql/gsqlbackend.cc \ backends/gsql/gsqlbackend.hh backends/gsql/ssql.hh \ -base64.cc sillyrecords.cc \ +base64.cc sillyrecords.cc secpoll-auth.cc secpoll-auth.hh \ base64.hh zoneparser-tng.cc dnsrecords.cc dnswriter.cc \ rcpgenerator.cc dnsparser.cc dns_random.hh dns_random.cc\ randomhelper.cc namespaces.hh nsecrecords.cc base32.cc dbdnsseckeeper.cc dnssecinfra.cc \ diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/pdns/Makefile.in pdns/pdns/Makefile.in --- pdns-3.4.0/pdns/Makefile.in 2014-09-30 11:23:53.000000000 +0200 +++ pdns/pdns/Makefile.in 2014-11-01 23:05:58.625872843 +0100 @@ -326,11 +326,12 @@ utility.hh iputils.hh common_startup.hh unix_semaphore.cc \ bind-dnssec.schema.sqlite3.sql.h bindparser.cc bindlexer.c \ backends/gsql/gsqlbackend.cc backends/gsql/gsqlbackend.hh \ - backends/gsql/ssql.hh base64.cc sillyrecords.cc base64.hh \ - zoneparser-tng.cc dnsrecords.cc dnswriter.cc rcpgenerator.cc \ - dnsparser.cc dns_random.hh dns_random.cc randomhelper.cc \ - namespaces.hh nsecrecords.cc base32.cc dbdnsseckeeper.cc \ - dnssecinfra.cc dnsseckeeper.hh dnssecinfra.hh base32.hh dns.cc \ + backends/gsql/ssql.hh base64.cc sillyrecords.cc \ + secpoll-auth.cc secpoll-auth.hh base64.hh zoneparser-tng.cc \ + dnsrecords.cc dnswriter.cc rcpgenerator.cc dnsparser.cc \ + dns_random.hh dns_random.cc randomhelper.cc namespaces.hh \ + nsecrecords.cc base32.cc dbdnsseckeeper.cc dnssecinfra.cc \ + dnsseckeeper.hh dnssecinfra.hh base32.hh dns.cc \ dnssecsigner.cc polarrsakeyinfra.cc sha.hh md5.hh \ signingpipe.cc signingpipe.hh dnslabeltext.cc lua-pdns.cc \ lua-auth.cc lua-auth.hh serialtweaker.cc ednssubnet.cc \ @@ -357,7 +358,7 @@ unix_utility.$(OBJEXT) common_startup.$(OBJEXT) \ unix_semaphore.$(OBJEXT) bindparser.$(OBJEXT) \ bindlexer.$(OBJEXT) backends/gsql/gsqlbackend.$(OBJEXT) \ - base64.$(OBJEXT) sillyrecords.$(OBJEXT) \ + base64.$(OBJEXT) sillyrecords.$(OBJEXT) secpoll-auth.$(OBJEXT) \ zoneparser-tng.$(OBJEXT) dnsrecords.$(OBJEXT) \ dnswriter.$(OBJEXT) rcpgenerator.$(OBJEXT) dnsparser.$(OBJEXT) \ dns_random.$(OBJEXT) randomhelper.$(OBJEXT) \ @@ -961,18 +962,18 @@ unix_semaphore.cc bind-dnssec.schema.sqlite3.sql.h \ bindparser.cc bindlexer.c backends/gsql/gsqlbackend.cc \ backends/gsql/gsqlbackend.hh backends/gsql/ssql.hh base64.cc \ - sillyrecords.cc base64.hh zoneparser-tng.cc dnsrecords.cc \ - dnswriter.cc rcpgenerator.cc dnsparser.cc dns_random.hh \ - dns_random.cc randomhelper.cc namespaces.hh nsecrecords.cc \ - base32.cc dbdnsseckeeper.cc dnssecinfra.cc dnsseckeeper.hh \ - dnssecinfra.hh base32.hh dns.cc dnssecsigner.cc \ - polarrsakeyinfra.cc sha.hh md5.hh signingpipe.cc \ - signingpipe.hh dnslabeltext.cc lua-pdns.cc lua-auth.cc \ - lua-auth.hh serialtweaker.cc ednssubnet.cc ednssubnet.hh \ - cachecleaner.hh json.cc json.hh version.hh version.cc \ - rfc2136handler.cc responsestats.cc responsestats.hh comment.hh \ - auth-carbon.cc $(am__append_5) $(am__append_7) $(am__append_9) \ - $(am__append_11) $(am__append_13) + sillyrecords.cc secpoll-auth.cc secpoll-auth.hh base64.hh \ + zoneparser-tng.cc dnsrecords.cc dnswriter.cc rcpgenerator.cc \ + dnsparser.cc dns_random.hh dns_random.cc randomhelper.cc \ + namespaces.hh nsecrecords.cc base32.cc dbdnsseckeeper.cc \ + dnssecinfra.cc dnsseckeeper.hh dnssecinfra.hh base32.hh dns.cc \ + dnssecsigner.cc polarrsakeyinfra.cc sha.hh md5.hh \ + signingpipe.cc signingpipe.hh dnslabeltext.cc lua-pdns.cc \ + lua-auth.cc lua-auth.hh serialtweaker.cc ednssubnet.cc \ + ednssubnet.hh cachecleaner.hh json.cc json.hh version.hh \ + version.cc rfc2136handler.cc responsestats.cc responsestats.hh \ + comment.hh auth-carbon.cc $(am__append_5) $(am__append_7) \ + $(am__append_9) $(am__append_11) $(am__append_13) pdns_server_LDFLAGS = @moduleobjects@ @modulelibs@ $(DYNLINKFLAGS) @LIBDL@ $(THREADFLAGS) $(BOOST_SERIALIZATION_LDFLAGS) -rdynamic pdns_server_LDADD = $(POLARSSL_LIBS) $(BOOST_SERIALIZATION_LIBS) \ $(LUA_LIBS) $(SQLITE3_LIBS) $(YAHTTP_LIBS) $(am__append_6) \ @@ -1498,6 +1499,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rfc2136handler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/saxfr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdig.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/secpoll-auth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/selectmplexer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serialtweaker.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signingpipe.Po@am__quote@ diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/pdns/pdns.conf-dist pdns/pdns/pdns.conf-dist --- pdns-3.4.0/pdns/pdns.conf-dist 2014-11-01 23:21:49.000000000 +0100 +++ pdns/pdns/pdns.conf-dist 2014-11-01 22:02:44.119097948 +0100 @@ -375,6 +375,11 @@ # reuseport=no ################################# +# security-poll-suffix Domain name from which to query security update notifications +# +# security-poll-suffix=secpoll.powerdns.com. + +################################# # send-root-referral Send out old-fashioned root-referral instead of ServFail in case of no authority # # send-root-referral=no diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/pdns/pdnssec.cc pdns/pdns/pdnssec.cc --- pdns-3.4.0/pdns/pdnssec.cc 2014-07-29 14:58:22.000000000 +0200 +++ pdns/pdns/pdnssec.cc 2014-11-01 22:02:44.123097956 +0100 @@ -612,10 +612,37 @@ } rrs[0].content = serializeSOAData(sd); + sd.db->startTransaction("", -1); + if (! sd.db->replaceRRSet(sd.domain_id, zone, rr.qtype, rrs)) { + sd.db->abortTransaction(); cerr<<"Backend did not replace SOA record. Backend might not support this operation."<<endl; return -1; } + + if (sd.db->doesDNSSEC()) { + NSEC3PARAMRecordContent ns3pr; + bool narrow; + bool haveNSEC3=dk.getNSEC3PARAM(zone, &ns3pr, &narrow); + + if(haveNSEC3) + { + if(!narrow) { + string hashed=toBase32Hex(hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rrs[0].qname)); + if(g_verbose) + cerr<<"'"<<rrs[0].qname<<"' -> '"<< hashed <<"'"<<endl; + sd.db->updateDNSSECOrderAndAuthAbsolute(sd.domain_id, rrs[0].qname, hashed, 1); + } + else { + sd.db->nullifyDNSSECOrderNameAndUpdateAuth(sd.domain_id, rrs[0].qname, 1); + } + } else { + sd.db->updateDNSSECOrderAndAuth(sd.domain_id, zone, rrs[0].qname, 1); + } + } + + sd.db->commitTransaction(); + cout<<"SOA serial for zone "<<zone<<" set to "<<sd.serial<<endl; return 0; } diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/pdns/secpoll-auth.cc pdns/pdns/secpoll-auth.cc --- pdns-3.4.0/pdns/secpoll-auth.cc 1970-01-01 01:00:00.000000000 +0100 +++ pdns/pdns/secpoll-auth.cc 2014-11-01 22:02:44.123097956 +0100 @@ -0,0 +1,168 @@ +#include "secpoll-auth.hh" + +#include "logger.hh" +#include "arguments.hh" +#include "version.hh" +#include "version_generated.h" +#include "dnsparser.hh" +#include "misc.hh" +#include <boost/foreach.hpp> +#include "sstuff.hh" +#include "dnswriter.hh" +#include "dns_random.hh" +#include "namespaces.hh" +#include "statbag.hh" +#include <stdint.h> +#ifndef PACKAGEVERSION +#define PACKAGEVERSION PDNS_VERSION +#endif + +string g_security_message; + +extern StatBag S; + +static vector<ComboAddress> parseResolveConf() +{ + vector<ComboAddress> ret; + ifstream ifs("/etc/resolv.conf"); + if(!ifs) + return ret; + + string line; + while(std::getline(ifs, line)) { + boost::trim_right_if(line, is_any_of(" \r\n\x1a")); + boost::trim_left(line); // leading spaces, let's be nice + + string::size_type tpos = line.find_first_of(";#"); + if(tpos != string::npos) + line.resize(tpos); + + if(boost::starts_with(line, "nameserver ") || boost::starts_with(line, "nameserver\t")) { + vector<string> parts; + stringtok(parts, line, " \t,"); // be REALLY nice + for(vector<string>::const_iterator iter = parts.begin()+1; iter != parts.end(); ++iter) { + + try { + ret.push_back(ComboAddress(*iter, 53)); + } + catch(...) + { + } + } + } + + } + + return ret; +} + +int doResolve(const string& qname, uint16_t qtype, vector<DNSResourceRecord>& ret) +{ + vector<uint8_t> packet; + + DNSPacketWriter pw(packet, qname, qtype); + pw.getHeader()->id=dns_random(0xffff); + pw.getHeader()->rd=1; + + static vector<ComboAddress> s_servers; + vector<ComboAddress> servers = parseResolveConf(); + if(!servers.empty()) + s_servers = servers; // in case we chrooted in the meantime + + if(s_servers.empty()) + L<<Logger::Warning<<"Unable to poll PowerDNS security status, did not get any servers from resolv.conf"<<endl; + + BOOST_FOREACH(ComboAddress& dest, s_servers) { + Socket sock(dest.sin4.sin_family, SOCK_DGRAM); + sock.setNonBlocking(); + sock.sendTo(string((char*)&*packet.begin(), (char*)&*packet.end()), dest); + + string reply; + + waitForData(sock.getHandle(), 2, 0); + try { + retry: + sock.recvFrom(reply, dest); + if(reply.size() > sizeof(struct dnsheader)) { + struct dnsheader d; + memcpy(&d, reply.c_str(), sizeof(d)); + if(d.id != pw.getHeader()->id) + goto retry; + } + } + catch(...) { + continue; + } + MOADNSParser mdp(reply); + if(mdp.d_header.rcode == RCode::ServFail) + continue; + + + for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { + if(i->first.d_place == 1 && i->first.d_type==QType::TXT) { + DNSResourceRecord rr; + rr.qname = i->first.d_label; + rr.qtype = QType(i->first.d_type); + rr.content = i->first.d_content->getZoneRepresentation(); + rr.ttl=i->first.d_ttl; + ret.push_back(rr); + } + } + + return mdp.d_header.rcode; + } + return RCode::ServFail; +} + +void doSecPoll(bool first) +{ + if(::arg()["security-poll-suffix"].empty()) + return; + + struct timeval now; + gettimeofday(&now, 0); + + string query = "auth-" PACKAGEVERSION ".security-status."+::arg()["security-poll-suffix"]; + + if(*query.rbegin()!='.') + query+='.'; + + boost::replace_all(query, "+", "_"); + + vector<DNSResourceRecord> ret; + + int res=doResolve(query, QType::TXT, ret); + + int security_status=0; + + if(!res && !ret.empty()) { + string content=ret.begin()->content; + if(!content.empty() && content[0]=='"' && content[content.size()-1]=='"') { + content=content.substr(1, content.length()-2); + } + + pair<string, string> split = splitField(content, ' '); + + security_status = atoi(split.first.c_str()); + g_security_message = split.second; + + } + else { + L<<Logger::Warning<<"Could not retrieve security status update for '" PACKAGEVERSION "' on '"+query+"', RCODE = "<< RCode::to_s(res)<<endl; + if(security_status == 1) // it was ok, not it is unknown + security_status = 0; + } + + if(security_status == 1 && first) { + L<<Logger::Warning << "Polled security status of version "<<PACKAGEVERSION<<" at startup, no known issues reported: " <<g_security_message<<endl; + } + if(security_status == 2) { + L<<Logger::Error<<"PowerDNS Security Update Recommended: "<<g_security_message<<endl; + } + else if(security_status == 3) { + L<<Logger::Error<<"PowerDNS Security Update Mandatory: "<<g_security_message<<endl; + } + + S.set("security-status",security_status); + +} diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/pdns/secpoll-auth.hh pdns/pdns/secpoll-auth.hh --- pdns-3.4.0/pdns/secpoll-auth.hh 1970-01-01 01:00:00.000000000 +0100 +++ pdns/pdns/secpoll-auth.hh 2014-11-01 22:02:44.123097956 +0100 @@ -0,0 +1,9 @@ +#ifndef PDNS_SECPOLL_AUTH_HH +#define PDNS_SECPOLL_AUTH_HH +#include <time.h> +#include "namespaces.hh" + +void doSecPoll(bool first); +extern std::string g_security_message; + +#endif diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/pdns/tcpreceiver.cc pdns/pdns/tcpreceiver.cc --- pdns-3.4.0/pdns/tcpreceiver.cc 2014-08-12 13:32:10.000000000 +0200 +++ pdns/pdns/tcpreceiver.cc 2014-11-01 22:02:44.123097956 +0100 @@ -1008,7 +1008,10 @@ sendPacket(outpacket,outsock); return 0; } - if (!rfc1982LessThan(serial, sd.serial)) { + + string soaedit; + dk.getFromMeta(target, "SOA-EDIT", soaedit); + if (!rfc1982LessThan(serial, calculateEditSOA(sd, soaedit))) { TSIGRecordContent trc; string tsigkeyname, tsigsecret; diff -Nru '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/pdns.spec pdns/pdns.spec --- pdns-3.4.0/pdns.spec 2014-09-30 11:23:37.000000000 +0200 +++ pdns/pdns.spec 2014-11-01 22:02:44.119097948 +0100 @@ -1,6 +1,6 @@ BuildRoot: /tmp/pdns Name: pdns-static -Version: 3.4.0 +Version: 3.4.1 Release: 1 Summary: extremely powerful and versatile nameserver License: GPL