[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#767700: marked as done (unblock: pdns/3.4.1-1)



Your message dated Sat, 8 Nov 2014 11:51:17 +0000
with message-id <20141108115117.GB2077@betterave.cristau.org>
and subject line Re: Bug#767700: unblock: pdns/3.4.1-1
has caused the Debian Bug report #767700,
regarding unblock: pdns/3.4.1-1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
767700: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=767700
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian.org@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], [jenkins@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 <zeha@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 <christian@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], [jenkins@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 <zeha@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

--- End Message ---
--- Begin Message ---
On Tue, Nov  4, 2014 at 15:13:57 +0100, Christian Hofstaedtler wrote:

> +pdns (3.4.1-2) unstable; urgency=medium

unblocked.

Cheers,
Julien

Attachment: signature.asc
Description: Digital signature


--- End Message ---

Reply to: