Hello community,

here is the log from the commit of package pdns-recursor for openSUSE:Factory 
checked in at 2019-01-24 14:12:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/pdns-recursor (Old)
 and      /work/SRC/openSUSE:Factory/.pdns-recursor.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "pdns-recursor"

Thu Jan 24 14:12:25 2019 rev:24 rq:667620 version:4.1.9

Changes:
--------
--- /work/SRC/openSUSE:Factory/pdns-recursor/pdns-recursor.changes      
2018-11-27 10:46:18.979955971 +0100
+++ /work/SRC/openSUSE:Factory/.pdns-recursor.new.28833/pdns-recursor.changes   
2019-01-24 14:12:26.763429558 +0100
@@ -1,0 +2,11 @@
+Mon Jan 21 14:02:26 UTC 2019 - adam.ma...@suse.de
+
+- update to 4.1.9
+  https://blog.powerdns.com/2019/01/21/powerdns-recursor-4-1-9-released/
+
+  - Fixes case when Lua hooks are not called over TCP
+    (CVE-2019-3806, bsc#1121887)
+  - Fixes DNSSEC validation is not performed for AA=0 responses
+    (CVE-2019-3807, bsc#1121889)
+
+-------------------------------------------------------------------

Old:
----
  pdns-recursor-4.1.8.tar.bz2
  pdns-recursor-4.1.8.tar.bz2.sig

New:
----
  pdns-recursor-4.1.9.tar.bz2
  pdns-recursor-4.1.9.tar.bz2.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ pdns-recursor.spec ++++++
--- /var/tmp/diff_new_pack.o45Du3/_old  2019-01-24 14:12:27.223429027 +0100
+++ /var/tmp/diff_new_pack.o45Du3/_new  2019-01-24 14:12:27.223429027 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package pdns-recursor
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -35,7 +35,7 @@
 %endif
 
 Name:           pdns-recursor
-Version:        4.1.8
+Version:        4.1.9
 Release:        0
 BuildRequires:  autoconf
 BuildRequires:  automake

++++++ pdns-recursor-4.1.8.tar.bz2 -> pdns-recursor-4.1.9.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pdns-recursor-4.1.8/.version 
new/pdns-recursor-4.1.9/.version
--- old/pdns-recursor-4.1.8/.version    2018-11-26 14:23:43.000000000 +0100
+++ new/pdns-recursor-4.1.9/.version    2019-01-21 10:28:55.000000000 +0100
@@ -1 +1 @@
-4.1.8
+4.1.9
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pdns-recursor-4.1.8/configure 
new/pdns-recursor-4.1.9/configure
--- old/pdns-recursor-4.1.8/configure   2018-11-26 14:23:42.000000000 +0100
+++ new/pdns-recursor-4.1.9/configure   2019-01-21 10:28:54.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-recursor 4.1.8.
+# Generated by GNU Autoconf 2.69 for pdns-recursor 4.1.9.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@
 # Identity of this package.
 PACKAGE_NAME='pdns-recursor'
 PACKAGE_TARNAME='pdns-recursor'
-PACKAGE_VERSION='4.1.8'
-PACKAGE_STRING='pdns-recursor 4.1.8'
+PACKAGE_VERSION='4.1.9'
+PACKAGE_STRING='pdns-recursor 4.1.9'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1445,7 +1445,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-recursor 4.1.8 to adapt to many kinds of systems.
+\`configure' configures pdns-recursor 4.1.9 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1515,7 +1515,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of pdns-recursor 4.1.8:";;
+     short | recursive ) echo "Configuration of pdns-recursor 4.1.9:";;
    esac
   cat <<\_ACEOF
 
@@ -1677,7 +1677,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-pdns-recursor configure 4.1.8
+pdns-recursor configure 4.1.9
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2270,7 +2270,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-recursor $as_me 4.1.8, which was
+It was created by pdns-recursor $as_me 4.1.9, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3133,7 +3133,7 @@
 
 # Define the identity of the package.
  PACKAGE='pdns-recursor'
- VERSION='4.1.8'
+ VERSION='4.1.9'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -21846,7 +21846,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by pdns-recursor $as_me 4.1.8, which was
+This file was extended by pdns-recursor $as_me 4.1.9, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -21912,7 +21912,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-recursor config.status 4.1.8
+pdns-recursor config.status 4.1.9
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pdns-recursor-4.1.8/pdns_recursor.1 
new/pdns-recursor-4.1.9/pdns_recursor.1
--- old/pdns-recursor-4.1.8/pdns_recursor.1     2018-11-26 14:24:33.000000000 
+0100
+++ new/pdns-recursor-4.1.9/pdns_recursor.1     2019-01-21 10:29:46.000000000 
+0100
@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH "PDNS_RECURSOR" "1" "Nov 26, 2018" "4.1" "PowerDNS Recursor"
+.TH "PDNS_RECURSOR" "1" "Jan 21, 2019" "4.1" "PowerDNS Recursor"
 .SH NAME
 pdns_recursor \- The PowerDNS Recursor binary
 .
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pdns-recursor-4.1.8/pdns_recursor.cc 
new/pdns-recursor-4.1.9/pdns_recursor.cc
--- old/pdns-recursor-4.1.8/pdns_recursor.cc    2018-11-26 14:23:30.000000000 
+0100
+++ new/pdns-recursor-4.1.9/pdns_recursor.cc    2019-01-21 10:28:41.000000000 
+0100
@@ -1542,9 +1542,9 @@
         dc->d_uuid = (*t_uuidGenerator)();
       }
 
+      const struct dnsheader* dh = (const struct dnsheader*) conn->data;
       if(luaconfsLocal->protobufServer) {
         try {
-          const struct dnsheader* dh = (const struct dnsheader*) conn->data;
 
           if (!luaconfsLocal->protobufTaggedOnly) {
             protobufLogQuery(luaconfsLocal->protobufServer, 
luaconfsLocal->protobufMaskV4, luaconfsLocal->protobufMaskV6, dc->d_uuid, 
conn->d_remote, dest, dc->d_ednssubnet.source, true, dh->id, conn->qlen, qname, 
qtype, qclass, dc->d_policyTags, dc->d_requestorId, dc->d_deviceId);
@@ -1556,6 +1556,16 @@
         }
       }
 #endif
+      if(t_pdl) {
+        if(t_pdl->ipfilter(dc->d_remote, dc->d_local, *dh)) {
+          delete dc;
+          if(!g_quiet)
+            L<<Logger::Notice<<t_id<<" 
["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] DROPPED TCP question from 
"<<conn->d_remote.toStringWithPort()<<" based on policy"<<endl;
+          g_stats.policyDrops++;
+          return;
+        }
+      }
+
       if(dc->d_mdp.d_header.qr) {
         delete dc;
         g_stats.ignoredCount++;
@@ -2310,27 +2320,14 @@
   }
 }
 
-// This function is only called by the distributor thread, when 
pdns-distributes-queries is set
-void distributeAsyncFunction(const string& packet, const pipefunc_t& func)
+static bool trySendingQueryToWorker(unsigned int target, ThreadMSG* tmsg)
 {
-  if (t_id != s_distributorThreadID) {
-    L<<Logger::Error<<"distributeAsyncFunction() has been called by a worker 
("<<t_id<<")"<<endl;
-    exit(1);
-  }
-
-  unsigned int hash = hashQuestion(packet.c_str(), packet.length(), 
g_disthashseed);
-  unsigned int target = 1 + (hash % (g_pipes.size()-1));
-
   if(target == static_cast<unsigned int>(s_distributorThreadID)) {
     L<<Logger::Error<<"distributeAsyncFunction() tried to assign a query to 
the distributor"<<endl;
     exit(1);
   }
 
   ThreadPipeSet& tps = g_pipes[target];
-  ThreadMSG* tmsg = new ThreadMSG();
-  tmsg->func = func;
-  tmsg->wantAnswer = false;
-
   ssize_t written = write(tps.writeQueriesToThread, &tmsg, sizeof(tmsg));
   if (written > 0) {
     if (static_cast<size_t>(written) != sizeof(tmsg)) {
@@ -2340,13 +2337,46 @@
   }
   else {
     int error = errno;
-    delete tmsg;
     if (error == EAGAIN || error == EWOULDBLOCK) {
-      g_stats.queryPipeFullDrops++;
+      /* the pipe is full, sorry */
+      return false;
     } else {
+      delete tmsg;
       unixDie("write to thread pipe returned wrong size or error:" + 
std::to_string(error));
     }
   }
+
+  return true;
+}
+
+// This function is only called by the distributor thread, when 
pdns-distributes-queries is set
+void distributeAsyncFunction(const string& packet, const pipefunc_t& func)
+{
+  if (t_id != s_distributorThreadID) {
+    L<<Logger::Error<<"distributeAsyncFunction() has been called by a worker 
("<<t_id<<")"<<endl;
+    exit(1);
+  }
+
+  unsigned int hash = hashQuestion(packet.c_str(), packet.length(), 
g_disthashseed);
+  unsigned int target = 1 + (hash % (g_pipes.size()-1));
+
+  ThreadMSG* tmsg = new ThreadMSG();
+  tmsg->func = func;
+  tmsg->wantAnswer = false;
+
+  if (!trySendingQueryToWorker(target, tmsg)) {
+    /* if this function failed but did not raise an exception, it means that 
the pipe
+       was full, let's try another one */
+    unsigned int newTarget = 0;
+    do {
+      newTarget = 1 + dns_random(g_pipes.size()-1);
+    } while (newTarget == target);
+
+    if (!trySendingQueryToWorker(newTarget, tmsg)) {
+      g_stats.queryPipeFullDrops++;
+      delete tmsg;
+    }
+  }
 }
 
 static void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var)
@@ -3258,7 +3288,7 @@
 #endif
   L<<Logger::Warning<<"Done priming cache with root hints"<<endl;
 
-  if(worker && (!g_weDistributeQueries || t_id != s_distributorThreadID)) {
+  if(worker) {
     try {
       if(!::arg()["lua-dns-script"].empty()) {
         t_pdl = std::make_shared<RecursorLua4>(::arg()["lua-dns-script"]);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pdns-recursor-4.1.8/rec_control.1 
new/pdns-recursor-4.1.9/rec_control.1
--- old/pdns-recursor-4.1.8/rec_control.1       2018-11-26 14:24:33.000000000 
+0100
+++ new/pdns-recursor-4.1.9/rec_control.1       2019-01-21 10:29:46.000000000 
+0100
@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH "REC_CONTROL" "1" "Nov 26, 2018" "4.1" "PowerDNS Recursor"
+.TH "REC_CONTROL" "1" "Jan 21, 2019" "4.1" "PowerDNS Recursor"
 .SH NAME
 rec_control \- Command line tool to control a running Recursor
 .
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pdns-recursor-4.1.8/syncres.cc 
new/pdns-recursor-4.1.9/syncres.cc
--- old/pdns-recursor-4.1.8/syncres.cc  2018-11-26 14:23:30.000000000 +0100
+++ new/pdns-recursor-4.1.9/syncres.cc  2019-01-21 10:28:41.000000000 +0100
@@ -1916,8 +1916,9 @@
   return Bogus;
 }
 
-RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& 
lwr, const DNSName& qname, const QType& qtype, const DNSName& auth, bool 
wasForwarded, const boost::optional<Netmask> ednsmask, vState& state, bool& 
needWildcardProof, unsigned int& wildcardLabelsCount)
+RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& 
lwr, const DNSName& qname, const QType& qtype, const DNSName& auth, bool 
wasForwarded, const boost::optional<Netmask> ednsmask, vState& state, bool& 
needWildcardProof, unsigned int& wildcardLabelsCount, bool rdQuery)
 {
+  bool wasForwardRecurse = wasForwarded && rdQuery;
   tcache_t tcache;
 
   string prefix;
@@ -2068,7 +2069,8 @@
        set the TC bit solely because these RRSIG RRs didn't fit."
     */
     bool isAA = lwr.d_aabit && i->first.place != DNSResourceRecord::ADDITIONAL;
-    if (isAA && isCNAMEAnswer && (i->first.place != DNSResourceRecord::ANSWER 
|| i->first.type != QType::CNAME || i->first.name != qname)) {
+    bool expectSignature = i->first.place == DNSResourceRecord::ANSWER || 
((lwr.d_aabit || wasForwardRecurse) && i->first.place != 
DNSResourceRecord::ADDITIONAL);
+    if (isCNAMEAnswer && (i->first.place != DNSResourceRecord::ANSWER || 
i->first.type != QType::CNAME || i->first.name != qname)) {
       /*
         rfc2181 states:
         Note that the answer section of an authoritative answer normally
@@ -2080,6 +2082,7 @@
         associated with the alias.
       */
       isAA = false;
+      expectSignature = false;
     }
 
     vState recordState = getValidationStatus(i->first.name, false);
@@ -2088,7 +2091,7 @@
     if (shouldValidate() && recordState == Secure) {
       vState initialState = recordState;
 
-      if (isAA) {
+      if (expectSignature) {
         if (i->first.place != DNSResourceRecord::ADDITIONAL) {
           /* the additional entries can be insecure,
              like glue:
@@ -2118,7 +2121,7 @@
         }
       }
 
-      if (initialState == Secure && state != recordState && isAA) {
+      if (initialState == Secure && state != recordState && expectSignature) {
         updateValidationState(state, recordState);
       }
     }
@@ -2508,7 +2511,7 @@
 
   bool needWildcardProof = false;
   unsigned int wildcardLabelsCount;
-  *rcode = updateCacheFromRecords(depth, lwr, qname, qtype, auth, 
wasForwarded, ednsmask, state, needWildcardProof, wildcardLabelsCount);
+  *rcode = updateCacheFromRecords(depth, lwr, qname, qtype, auth, 
wasForwarded, ednsmask, state, needWildcardProof, wildcardLabelsCount, 
sendRDQuery);
   if (*rcode != RCode::NoError) {
     return true;
   }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pdns-recursor-4.1.8/syncres.hh 
new/pdns-recursor-4.1.9/syncres.hh
--- old/pdns-recursor-4.1.8/syncres.hh  2018-11-26 14:23:30.000000000 +0100
+++ new/pdns-recursor-4.1.9/syncres.hh  2019-01-21 10:28:41.000000000 +0100
@@ -750,7 +750,7 @@
   bool throttledOrBlocked(const std::string& prefix, const ComboAddress& 
remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery);
 
   vector<ComboAddress> retrieveAddressesForNS(const std::string& prefix, const 
DNSName& qname, vector<DNSName >::const_iterator& tns, const unsigned int 
depth, set<GetBestNSAnswer>& beenthere, const vector<DNSName >& rnameservers, 
NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& 
flawedNSSet, bool cacheOnly);
-  RCode::rcodes_ updateCacheFromRecords(unsigned int depth, LWResult& lwr, 
const DNSName& qname, const QType& qtype, const DNSName& auth, bool 
wasForwarded, const boost::optional<Netmask>, vState& state, bool& 
needWildcardProof, unsigned int& wildcardLabelsCount);
+  RCode::rcodes_ updateCacheFromRecords(unsigned int depth, LWResult& lwr, 
const DNSName& qname, const QType& qtype, const DNSName& auth, bool 
wasForwarded, const boost::optional<Netmask>, vState& state, bool& 
needWildcardProof, unsigned int& wildcardLabelsCount, bool sendRDQuery);
   bool processRecords(const std::string& prefix, const DNSName& qname, const 
QType& qtype, const DNSName& auth, LWResult& lwr, const bool sendRDQuery, 
vector<DNSRecord>& ret, set<DNSName>& nsset, DNSName& newtarget, DNSName& 
newauth, bool& realreferral, bool& negindic, vState& state, const bool 
needWildcardProof, const unsigned int wildcardLabelsCount);
 
   bool doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const 
uint16_t qclass, vector<DNSRecord> &ret);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pdns-recursor-4.1.8/test-recursorcache_cc.cc 
new/pdns-recursor-4.1.9/test-recursorcache_cc.cc
--- old/pdns-recursor-4.1.8/test-recursorcache_cc.cc    2018-11-26 
14:23:30.000000000 +0100
+++ new/pdns-recursor-4.1.9/test-recursorcache_cc.cc    2019-01-21 
10:28:41.000000000 +0100
@@ -340,6 +340,46 @@
   }
 }
 
+BOOST_AUTO_TEST_CASE(test_RecursorCacheGhost) {
+  MemRecursorCache MRC;
+
+  std::vector<DNSRecord> records;
+  std::vector<std::shared_ptr<DNSRecord>> authRecords;
+  std::vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+  time_t now = time(nullptr);
+
+  BOOST_CHECK_EQUAL(MRC.size(), 0);
+
+  /* insert NS coming from a delegation */
+  time_t ttd = now + 30;
+  DNSName ghost("ghost.powerdns.com.");
+  DNSRecord ns1;
+  std::string ns1Content("ns1.ghost.powerdns.com.");
+  ns1.d_name = ghost;
+  ns1.d_type = QType::NS;
+  ns1.d_class = QClass::IN;
+  ns1.d_content = std::make_shared<NSRecordContent>(ns1Content);
+  ns1.d_ttl = static_cast<uint32_t>(ttd);
+  ns1.d_place = DNSResourceRecord::ANSWER;
+  records.push_back(ns1);
+  MRC.replace(now, ns1.d_name, QType(ns1.d_type), records, signatures, 
authRecords, true, boost::none);
+  BOOST_CHECK_EQUAL(MRC.size(), 1);
+
+  /* try to raise the TTL, simulating the delegated authoritative server
+     raising the TTL so the zone stays alive */
+  records.clear();
+  ns1.d_ttl = static_cast<uint32_t>(ttd + 3600);
+  records.push_back(ns1);
+  MRC.replace(now, ns1.d_name, QType(ns1.d_type), records, signatures, 
authRecords, true, boost::none);
+  BOOST_CHECK_EQUAL(MRC.size(), 1);
+
+  /* the TTL should not have been raisd */
+  std::vector<DNSRecord> retrieved;
+  BOOST_CHECK_EQUAL(MRC.get(now, ghost, QType(QType::NS), false, &retrieved, 
ComboAddress("192.0.2.2"), nullptr), (ttd-now));
+  BOOST_REQUIRE_EQUAL(retrieved.size(), 1);
+  BOOST_CHECK_EQUAL(retrieved.at(0).d_ttl, static_cast<uint32_t>(ttd));
+}
+
 BOOST_AUTO_TEST_CASE(test_RecursorCache_ExpungingExpiredEntries) {
   MemRecursorCache MRC;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pdns-recursor-4.1.8/test-syncres_cc.cc 
new/pdns-recursor-4.1.9/test-syncres_cc.cc
--- old/pdns-recursor-4.1.8/test-syncres_cc.cc  2018-11-26 14:23:30.000000000 
+0100
+++ new/pdns-recursor-4.1.9/test-syncres_cc.cc  2019-01-21 10:28:41.000000000 
+0100
@@ -233,17 +233,19 @@
   return false;
 }
 
-static void computeRRSIG(const DNSSECPrivateKey& dpk, const DNSName& signer, 
const DNSName& signQName, uint16_t signQType, uint32_t signTTL, uint32_t 
sigValidity, RRSIGRecordContent& rrc, vector<shared_ptr<DNSRecordContent> >& 
toSign, boost::optional<uint8_t> algo=boost::none, boost::optional<uint32_t> 
inception=boost::none)
+static void computeRRSIG(const DNSSECPrivateKey& dpk, const DNSName& signer, 
const DNSName& signQName, uint16_t signQType, uint32_t signTTL, uint32_t 
sigValidity, RRSIGRecordContent& rrc, vector<shared_ptr<DNSRecordContent> >& 
toSign, boost::optional<uint8_t> algo=boost::none, boost::optional<uint32_t> 
inception=boost::none, boost::optional<time_t> now=boost::none)
 {
-  time_t now = time(nullptr);
+  if (!now) {
+    now = time(nullptr);
+  }
   DNSKEYRecordContent drc = dpk.getDNSKEY();
   const std::shared_ptr<DNSCryptoKeyEngine> rc = dpk.getKey();
 
   rrc.d_type = signQType;
   rrc.d_labels = signQName.countLabels() - signQName.isWildcard();
   rrc.d_originalttl = signTTL;
-  rrc.d_siginception = inception ? *inception : (now - 10);
-  rrc.d_sigexpire = now + sigValidity;
+  rrc.d_siginception = inception ? *inception : (*now - 10);
+  rrc.d_sigexpire = *now + sigValidity;
   rrc.d_signer = signer;
   rrc.d_tag = 0;
   rrc.d_tag = drc.getTag();
@@ -256,7 +258,7 @@
 
 typedef std::unordered_map<DNSName, std::pair<DNSSECPrivateKey, 
DSRecordContent> > testkeysset_t;
 
-static bool addRRSIG(const testkeysset_t& keys, std::vector<DNSRecord>& 
records, const DNSName& signer, uint32_t sigValidity, bool broken=false, 
boost::optional<uint8_t> algo=boost::none, boost::optional<DNSName> 
wildcard=boost::none)
+static bool addRRSIG(const testkeysset_t& keys, std::vector<DNSRecord>& 
records, const DNSName& signer, uint32_t sigValidity, bool broken=false, 
boost::optional<uint8_t> algo=boost::none, boost::optional<DNSName> 
wildcard=boost::none, boost::optional<time_t> now=boost::none)
 {
   if (records.empty()) {
     return false;
@@ -279,7 +281,7 @@
   }
 
   RRSIGRecordContent rrc;
-  computeRRSIG(it->second.first, signer, wildcard ? *wildcard : 
records[recordsCount-1].d_name, records[recordsCount-1].d_type, 
records[recordsCount-1].d_ttl, sigValidity, rrc, recordcontents, algo);
+  computeRRSIG(it->second.first, signer, wildcard ? *wildcard : 
records[recordsCount-1].d_name, records[recordsCount-1].d_type, 
records[recordsCount-1].d_ttl, sigValidity, rrc, recordcontents, algo, 
boost::none, now);
   if (broken) {
     rrc.d_signature[0] ^= 42;
   }
@@ -4268,6 +4270,74 @@
   BOOST_CHECK_EQUAL(queriesCount, 2);
 }
 
+BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_sig_no_aa) {
+  std::unique_ptr<SyncRes> sr;
+  initSR(sr, true);
+
+  setDNSSECValidation(sr, DNSSECMode::ValidateAll);
+
+  primeHints();
+  const DNSName target(".");
+  testkeysset_t keys;
+
+  auto luaconfsCopy = g_luaconfs.getCopy();
+  luaconfsCopy.dsAnchors.clear();
+  generateKeyMaterial(g_rootdnsname, DNSSECKeeper::RSASHA512, 
DNSSECKeeper::SHA384, keys, luaconfsCopy.dsAnchors);
+
+  g_luaconfs.setState(luaconfsCopy);
+
+  size_t queriesCount = 0;
+
+  sr->setAsyncCallback([target,&queriesCount,keys](const ComboAddress& ip, 
const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, 
struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const 
ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, 
LWResult* res, bool* chained) {
+      queriesCount++;
+
+      if (domain == target && type == QType::NS) {
+
+        /* set AA=0 */
+        setLWResult(res, 0, false, false, true);
+        char addr[] = "a.root-servers.net.";
+        for (char idx = 'a'; idx <= 'm'; idx++) {
+          addr[0] = idx;
+          addRecordToLW(res, domain, QType::NS, std::string(addr), 
DNSResourceRecord::ANSWER, 3600);
+        }
+
+        addRRSIG(keys, res->d_records, domain, 300, true);
+
+        addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", 
DNSResourceRecord::ADDITIONAL, 3600);
+        addRecordToLW(res, "a.root-servers.net.", QType::AAAA, 
"2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600);
+
+        return 1;
+      } else if (domain == target && type == QType::DNSKEY) {
+
+        setLWResult(res, 0, true, false, true);
+
+        addDNSKEY(keys, domain, 300, res->d_records);
+        addRRSIG(keys, res->d_records, domain, 300);
+
+        return 1;
+      }
+
+      return 0;
+    });
+
+  vector<DNSRecord> ret;
+  int res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
+  BOOST_CHECK_EQUAL(res, RCode::NoError);
+  BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
+  /* 13 NS + 1 RRSIG */
+  BOOST_REQUIRE_EQUAL(ret.size(), 14);
+  BOOST_CHECK_EQUAL(queriesCount, 2);
+
+  /* again, to test the cache, but we will trigger a new outgoing query since
+     the answer did not have the AA bit set */
+  ret.clear();
+  res = sr->beginResolve(target, QType(QType::NS), QClass::IN, ret);
+  BOOST_CHECK_EQUAL(res, RCode::NoError);
+  BOOST_CHECK_EQUAL(sr->getValidationState(), Bogus);
+  BOOST_REQUIRE_EQUAL(ret.size(), 14);
+  BOOST_CHECK_EQUAL(queriesCount, 3);
+}
+
 BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_algo) {
   std::unique_ptr<SyncRes> sr;
   initSR(sr, true);
@@ -8853,8 +8923,9 @@
   g_luaconfs.setState(luaconfsCopy);
 
   size_t queriesCount = 0;
+  const time_t fixedNow = sr->getNow().tv_sec;
 
-  sr->setAsyncCallback([target,&queriesCount,keys](const ComboAddress& ip, 
const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, 
struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const 
ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, 
LWResult* res, bool* chained) {
+  sr->setAsyncCallback([target,&queriesCount,keys,fixedNow](const 
ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool 
sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& 
srcmask, boost::optional<const ResolveContext&> context, 
std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res, bool* chained) {
       queriesCount++;
 
       DNSName auth = domain;
@@ -8868,14 +8939,13 @@
         addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. 
pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", 
DNSResourceRecord::AUTHORITY, 3600);
         addRRSIG(keys, res->d_records, domain, 300);
         addNSECRecordToLW(domain, DNSName("z."), { QType::NSEC, QType::RRSIG 
}, 600, res->d_records);
-        addRRSIG(keys, res->d_records, domain, 1);
+        addRRSIG(keys, res->d_records, domain, 1, false, boost::none, 
boost::none, fixedNow);
         return 1;
       }
 
       return 0;
     });
 
-  const time_t now = sr->getNow().tv_sec;
   vector<DNSRecord> ret;
   int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
   BOOST_CHECK_EQUAL(res, RCode::NoError);
@@ -8887,7 +8957,7 @@
   NegCache::NegCacheEntry ne;
   BOOST_CHECK_EQUAL(SyncRes::t_sstorage.negcache.size(), 1);
   BOOST_REQUIRE_EQUAL(SyncRes::t_sstorage.negcache.get(target, 
QType(QType::A), sr->getNow(), ne), true);
-  BOOST_CHECK_EQUAL(ne.d_ttd, now + 1);
+  BOOST_CHECK_EQUAL(ne.d_ttd, fixedNow + 1);
   BOOST_CHECK_EQUAL(ne.d_validationState, Secure);
   BOOST_CHECK_EQUAL(ne.authoritySOA.records.size(), 1);
   BOOST_CHECK_EQUAL(ne.authoritySOA.signatures.size(), 1);



Reply via email to