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

Bug#767700: unblock: pdns/3.4.1-1



Turns out the dpkg-parsechangelog -S I've introduced in 3.4.1-1
needs a newer dpkg(-dev); fixed that in 3.4.1-2.

New diffs attached.

Thank you,
-- 
 ,''`.  Christian Hofstaedtler <zeha@debian.org>
: :' :  Debian Developer
`. `'   7D1A CFFA D9E0 806C 9C4C  D392 5C13 D6DB 9305 2E03
  `-

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-03 18:58:14.000000000 +0100
@@ -1,3 +1,25 @@
+pdns (3.4.1-2) unstable; urgency=medium
+
+  * Bump dpkg-dev dependency for dpkg-parsechangelog -S, which
+    is used to pass the package version to the build process.
+
+ -- Christian Hofstaedtler <zeha@debian.org>  Mon, 03 Nov 2014 18:57:24 +0100
+
+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-03 18:56:28.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/control pdns-3.4.1/debian/control
--- pdns-3.4.0/debian/control	2014-10-15 08:34:03.000000000 +0200
+++ pdns-3.4.1/debian/control	2014-11-03 18:56:48.000000000 +0100
@@ -4,7 +4,7 @@
 Standards-Version: 3.9.6
 Maintainer: Debian PowerDNS Maintainers <pkg-pdns-maintainers@lists.alioth.debian.org>
 Uploaders: Matthijs Möhlmann <matthijs@cacholong.nl>, Marc Haber <mh+debian-packages@zugschlus.de>, Christian Hofstaedtler <zeha@debian.org>
-Build-Depends: debhelper (>= 9~), dh-autoreconf, dh-systemd, po-debconf, libtool, flex, bison, libmysqlclient-dev, libpq-dev, libssl-dev, libpolarssl-dev, libgdbm-dev, libldap2-dev, libsqlite3-dev, dpkg-dev (>= 1.10.17), libboost-dev, libboost-serialization-dev, libboost-program-options-dev, libboost-test-dev, autotools-dev, automake, autoconf, liblua5.1-0-dev, pkg-config, libcrypto++-dev, ragel, libgmp-dev, libbotan1.10-dev, libcurl4-openssl-dev, libzmq-dev, liblmdb-dev
+Build-Depends: debhelper (>= 9~), dh-autoreconf, dh-systemd, po-debconf, libtool, flex, bison, libmysqlclient-dev, libpq-dev, libssl-dev, libpolarssl-dev, libgdbm-dev, libldap2-dev, libsqlite3-dev, dpkg-dev (>= 1.17.0~), libboost-dev, libboost-serialization-dev, libboost-program-options-dev, libboost-test-dev, autotools-dev, automake, autoconf, liblua5.1-0-dev, pkg-config, libcrypto++-dev, ragel, libgmp-dev, libbotan1.10-dev, libcurl4-openssl-dev, libzmq-dev, liblmdb-dev
 Vcs-Git: git://anonscm.debian.org/pkg-pdns/pdns.git
 Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-pdns/pdns.git
 Homepage: http://www.powerdns.com/
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-03 18:56:28.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-03 18:56:28.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-03 18:56:28.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-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 '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch 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 '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch 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 '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch 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-03 18:58:14.000000000 +0100
@@ -1,3 +1,25 @@
+pdns (3.4.1-2) unstable; urgency=medium
+
+  * Bump dpkg-dev dependency for dpkg-parsechangelog -S, which
+    is used to pass the package version to the build process.
+
+ -- Christian Hofstaedtler <zeha@debian.org>  Mon, 03 Nov 2014 18:57:24 +0100
+
+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-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-03 18:56:28.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 '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch pdns-3.4.0/debian/control pdns-3.4.1/debian/control
--- pdns-3.4.0/debian/control	2014-10-15 08:34:03.000000000 +0200
+++ pdns-3.4.1/debian/control	2014-11-03 18:56:48.000000000 +0100
@@ -4,7 +4,7 @@
 Standards-Version: 3.9.6
 Maintainer: Debian PowerDNS Maintainers <pkg-pdns-maintainers@lists.alioth.debian.org>
 Uploaders: Matthijs Möhlmann <matthijs@cacholong.nl>, Marc Haber <mh+debian-packages@zugschlus.de>, Christian Hofstaedtler <zeha@debian.org>
-Build-Depends: debhelper (>= 9~), dh-autoreconf, dh-systemd, po-debconf, libtool, flex, bison, libmysqlclient-dev, libpq-dev, libssl-dev, libpolarssl-dev, libgdbm-dev, libldap2-dev, libsqlite3-dev, dpkg-dev (>= 1.10.17), libboost-dev, libboost-serialization-dev, libboost-program-options-dev, libboost-test-dev, autotools-dev, automake, autoconf, liblua5.1-0-dev, pkg-config, libcrypto++-dev, ragel, libgmp-dev, libbotan1.10-dev, libcurl4-openssl-dev, libzmq-dev, liblmdb-dev
+Build-Depends: debhelper (>= 9~), dh-autoreconf, dh-systemd, po-debconf, libtool, flex, bison, libmysqlclient-dev, libpq-dev, libssl-dev, libpolarssl-dev, libgdbm-dev, libldap2-dev, libsqlite3-dev, dpkg-dev (>= 1.17.0~), libboost-dev, libboost-serialization-dev, libboost-program-options-dev, libboost-test-dev, autotools-dev, automake, autoconf, liblua5.1-0-dev, pkg-config, libcrypto++-dev, ragel, libgmp-dev, libbotan1.10-dev, libcurl4-openssl-dev, libzmq-dev, liblmdb-dev
 Vcs-Git: git://anonscm.debian.org/pkg-pdns/pdns.git
 Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-pdns/pdns.git
 Homepage: http://www.powerdns.com/
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-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-03 18:56:28.000000000 +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-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-03 18:56:28.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 '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch 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-03 18:56:28.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 '--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-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 '--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-3.4.1/pdns/common_startup.cc
--- pdns-3.4.0/pdns/common_startup.cc	2014-11-04 14:29:51.000000000 +0100
+++ 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;
@@ -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-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 '--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-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 '--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-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 '--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-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 '--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-3.4.1/pdns/pdns.conf-dist
--- pdns-3.4.0/pdns/pdns.conf-dist	2014-11-04 14:29:51.000000000 +0100
+++ pdns-3.4.1/pdns/pdns.conf-dist	2014-10-28 11:41:09.000000000 +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-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 '--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-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 '--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-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 '--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-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 '--exclude=.git' '--exclude=.pc' --exclude 0001-API-Replace-HTTP-Basic-auth-with-static-key-in-custo.patch 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

Reply to: