Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package pdns-recursor for openSUSE:Factory checked in at 2022-04-12 21:51:10 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pdns-recursor (Old) and /work/SRC/openSUSE:Factory/.pdns-recursor.new.1900 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pdns-recursor" Tue Apr 12 21:51:10 2022 rev:53 rq:969514 version:4.6.2 Changes: -------- --- /work/SRC/openSUSE:Factory/pdns-recursor/pdns-recursor.changes 2022-03-29 18:16:07.087175009 +0200 +++ /work/SRC/openSUSE:Factory/.pdns-recursor.new.1900/pdns-recursor.changes 2022-04-12 21:52:01.969810841 +0200 @@ -1,0 +2,31 @@ +Mon Apr 4 16:41:19 UTC 2022 - Michael Str??der <[email protected]> + +- update to 4.6.2 + * Improvements + - Allow disabling of processing the root hints. + - References: #11283, pull request 11360 + - Log an error if pdns.DROP is used as rcode in Lua callbacks. + - References: #11288, pull request 11361 + - A CNAME answer on DS query should abort DS retrieval. + - References: #11245, pull request 11358 + - Reject non-apex NSEC(3)s that have both the NS and SOA bits set. + - References: #11225, pull request 11357 + - Fix build with OpenSSL 3.0.0. + - References: pull request 11260 + - Shorter thread names. + - References: #11137, pull request 11170 + - Two more features to print (DoT and scrypt). + - References: #11109, pull request 11169 + * Bug Fixes + - Be more careful using refresh mode only for the record asked. + - References: #11371, pull request 11418 + - Use the Lua context stored in SyncRes when calling hooks. + - References: #11300, pull request 11380 + - QType ADDR is supposed to be used internally only. + - References: #11338, pull request 11363 + - If we get NODATA on an AAAA in followCNAMERecords, try native dns64. + - References: #11327, pull request 11362 + - Initialize isNew before calling a exception throwing function. + - References: #11257, pull request 11359 + +------------------------------------------------------------------- Old: ---- pdns-recursor-4.6.1.tar.bz2 pdns-recursor-4.6.1.tar.bz2.sig New: ---- pdns-recursor-4.6.2.tar.bz2 pdns-recursor-4.6.2.tar.bz2.sig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pdns-recursor.spec ++++++ --- /var/tmp/diff_new_pack.YEa0cB/_old 2022-04-12 21:52:02.677802889 +0200 +++ /var/tmp/diff_new_pack.YEa0cB/_new 2022-04-12 21:52:02.681802845 +0200 @@ -25,7 +25,7 @@ %endif Name: pdns-recursor -Version: 4.6.1 +Version: 4.6.2 Release: 0 BuildRequires: autoconf BuildRequires: automake ++++++ pdns-recursor-4.6.1.tar.bz2 -> pdns-recursor-4.6.2.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/configure new/pdns-recursor-4.6.2/configure --- old/pdns-recursor-4.6.1/configure 2022-03-21 09:06:06.000000000 +0100 +++ new/pdns-recursor-4.6.2/configure 2022-03-30 15:30:59.000000000 +0200 @@ -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.6.1. +# Generated by GNU Autoconf 2.69 for pdns-recursor 4.6.2. # # # 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.6.1' -PACKAGE_STRING='pdns-recursor 4.6.1' +PACKAGE_VERSION='4.6.2' +PACKAGE_STRING='pdns-recursor 4.6.2' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1552,7 +1552,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.6.1 to adapt to many kinds of systems. +\`configure' configures pdns-recursor 4.6.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1623,7 +1623,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pdns-recursor 4.6.1:";; + short | recursive ) echo "Configuration of pdns-recursor 4.6.2:";; esac cat <<\_ACEOF @@ -1810,7 +1810,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pdns-recursor configure 4.6.1 +pdns-recursor configure 4.6.2 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2527,7 +2527,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.6.1, which was +It was created by pdns-recursor $as_me 4.6.2, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3395,7 +3395,7 @@ # Define the identity of the package. PACKAGE='pdns-recursor' - VERSION='4.6.1' + VERSION='4.6.2' cat >>confdefs.h <<_ACEOF @@ -28087,7 +28087,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.6.1, which was +This file was extended by pdns-recursor $as_me 4.6.2, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -28153,7 +28153,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.6.1 +pdns-recursor config.status 4.6.2 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.6.1/configure.ac new/pdns-recursor-4.6.2/configure.ac --- old/pdns-recursor-4.6.1/configure.ac 2022-03-21 09:05:54.000000000 +0100 +++ new/pdns-recursor-4.6.2/configure.ac 2022-03-30 15:30:44.000000000 +0200 @@ -1,6 +1,6 @@ AC_PREREQ([2.69]) -AC_INIT([pdns-recursor], [4.6.1]) +AC_INIT([pdns-recursor], [4.6.2]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip tar-ustar -Wno-portability subdir-objects parallel-tests 1.11]) AM_SILENT_RULES([yes]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/credentials.cc new/pdns-recursor-4.6.2/credentials.cc --- old/pdns-recursor-4.6.1/credentials.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/credentials.cc 2022-03-30 13:10:51.000000000 +0200 @@ -31,6 +31,7 @@ #ifdef HAVE_EVP_PKEY_CTX_SET1_SCRYPT_SALT #include <openssl/evp.h> #include <openssl/kdf.h> +#include <openssl/opensslv.h> #include <openssl/rand.h> #endif @@ -105,8 +106,13 @@ throw std::runtime_error("Error intializing the scrypt context to hash the supplied password"); } - // OpenSSL 3.0 changed the string arg to const unsigned char*, other versions use const char *, so cast to const void * to satisfy both - if (EVP_PKEY_CTX_set1_pbe_pass(pctx.get(), reinterpret_cast<const void*>(password.data()), password.size()) <= 0) { + // OpenSSL 3.0 changed the string arg to const unsigned char*, other versions use const char * +#if OPENSSL_VERSION_MAJOR >= 3 + auto passwordData = reinterpret_cast<const char*>(password.data()); +#else + auto passwordData = reinterpret_cast<const unsigned char*>(password.data()); +#endif + if (EVP_PKEY_CTX_set1_pbe_pass(pctx.get(), passwordData, password.size()) <= 0) { throw std::runtime_error("Error adding the password to the scrypt context to hash the supplied password"); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/effective_tld_names.dat new/pdns-recursor-4.6.2/effective_tld_names.dat --- old/pdns-recursor-4.6.1/effective_tld_names.dat 2022-03-21 09:07:30.000000000 +0100 +++ new/pdns-recursor-4.6.2/effective_tld_names.dat 2022-03-30 15:33:30.000000000 +0200 @@ -7131,7 +7131,7 @@ // newGTLDs -// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2022-02-18T15:13:38Z +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2022-03-27T15:13:38Z // This list is auto-generated, don't edit it manually. // aaa : 2015-02-26 American Automobile Association, Inc. aaa @@ -7334,7 +7334,7 @@ // audible : 2015-06-25 Amazon Registry Services, Inc. audible -// audio : 2014-03-20 UNR Corp. +// audio : 2014-03-20 XYZ.COM LLC audio // auspost : 2015-08-13 Australian Postal Corporation @@ -7703,7 +7703,7 @@ // chintai : 2015-06-11 CHINTAI Corporation chintai -// christmas : 2013-11-21 UNR Corp. +// christmas : 2013-11-21 XYZ.COM LLC christmas // chrome : 2014-07-24 Charleston Road Registry Inc. @@ -7952,7 +7952,7 @@ // diamonds : 2013-09-22 Binky Moon, LLC diamonds -// diet : 2014-06-26 UNR Corp. +// diet : 2014-06-26 XYZ.COM LLC diet // digital : 2014-03-06 Binky Moon, LLC @@ -8198,7 +8198,7 @@ // florist : 2013-11-07 Binky Moon, LLC florist -// flowers : 2014-10-09 UNR Corp. +// flowers : 2014-10-09 XYZ.COM LLC flowers // fly : 2014-05-08 Charleston Road Registry Inc. @@ -8285,7 +8285,7 @@ // gallup : 2015-02-19 Gallup, Inc. gallup -// game : 2015-05-28 UNR Corp. +// game : 2015-05-28 XYZ.COM LLC game // games : 2015-05-28 Dog Beach, LLC @@ -8420,7 +8420,7 @@ // guide : 2013-09-13 Binky Moon, LLC guide -// guitars : 2013-11-14 UNR Corp. +// guitars : 2013-11-14 XYZ.COM LLC guitars // guru : 2013-08-27 Binky Moon, LLC @@ -8468,7 +8468,7 @@ // hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc. hgtv -// hiphop : 2014-03-06 UNR Corp. +// hiphop : 2014-03-06 Dot Hip Hop, LLC hiphop // hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc. @@ -8516,7 +8516,7 @@ // host : 2014-04-17 Radix FZC host -// hosting : 2014-05-29 UNR Corp. +// hosting : 2014-05-29 XYZ.COM LLC hosting // hot : 2015-08-27 Amazon Registry Services, Inc. @@ -8885,7 +8885,7 @@ // loft : 2015-07-30 Annco, Inc. loft -// lol : 2015-01-30 UNR Corp. +// lol : 2015-01-30 XYZ.COM LLC lol // london : 2013-11-14 Dot London Domains Limited @@ -9041,7 +9041,7 @@ // moi : 2014-12-18 Amazon Registry Services, Inc. moi -// mom : 2015-04-16 UNR Corp. +// mom : 2015-04-16 XYZ.COM LLC mom // monash : 2013-09-30 Monash University @@ -9320,7 +9320,7 @@ // physio : 2014-05-01 PhysBiz Pty Ltd physio -// pics : 2013-11-14 UNR Corp. +// pics : 2013-11-14 XYZ.COM LLC pics // pictet : 2014-06-26 Pictet Europe S.A. @@ -9995,7 +9995,7 @@ // toshiba : 2014-04-10 TOSHIBA Corporation toshiba -// total : 2015-08-06 Total SA +// total : 2015-08-06 TOTAL SE total // tours : 2015-01-22 Binky Moon, LLC @@ -10633,6 +10633,12 @@ // Submitted by Przemyslaw Plewa <[email protected]> beep.pl +// Airkit : https://www.airkit.com/ +// Submitted by Grant Cooksey <[email protected]> +airkitapps.com +airkitapps-au.com +airkitapps.eu + // Aiven: https://aiven.io/ // Submitted by Etienne Stalmans <[email protected]> aivencloud.com @@ -11663,6 +11669,11 @@ mytuleap.com tuleap-partners.com +// Encoretivity AB: https://encore.dev +// Submitted by Andr?? Eriksson <[email protected]> +encr.app +encoreapi.com + // ECG Robotics, Inc: https://ecgrobotics.org // Submitted by <[email protected]> onred.one @@ -11987,6 +11998,7 @@ independent-review.uk public-inquiry.uk royal-commission.uk +campaign.gov.uk service.gov.uk // CDDO : https://www.gov.uk/guidance/get-an-api-domain-on-govuk @@ -12656,6 +12668,10 @@ // Submitted by Victor Velchev <[email protected]> we.bs +// Localcert : https://localcert.dev +// Submitted by Lann Martin <[email protected]> +*.user.localcert.dev + // localzone.xyz // Submitted by Kenny Niehage <[email protected]> localzone.xyz diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/lua-base4.cc new/pdns-recursor-4.6.2/lua-base4.cc --- old/pdns-recursor-4.6.1/lua-base4.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/lua-base4.cc 2022-03-30 13:10:52.000000000 +0200 @@ -244,7 +244,8 @@ {"YXRRSET", RCode::YXRRSet }, {"NXRRSET", RCode::NXRRSet }, {"NOTAUTH", RCode::NotAuth }, - {"NOTZONE", RCode::NotZone }}; + {"NOTZONE", RCode::NotZone }, + {"DROP", -2 }}; // To give backport-incompatibility warning for(const auto& rcode : rcodes) d_pd.push_back({rcode.first, rcode.second}); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/lua-recursor4.cc new/pdns-recursor-4.6.2/lua-recursor4.cc --- old/pdns-recursor-4.6.1/lua-recursor4.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/lua-recursor4.cc 2022-03-30 13:10:52.000000000 +0200 @@ -495,6 +495,15 @@ features.emplace_back("PR8001_devicename", true); } +static void warnDrop(const RecursorLua4::DNSQuestion& dq) +{ + if (dq.rcode == -2) { + g_log << Logger::Error << "Returning -2 (pdns.DROP) is not supported anymore, see https://docs.powerdns.com/recursor/lua-scripting/hooks.html#hooksemantics" << endl; + // We *could* set policy here, but that would also mean interfering with rcode and the return code of the hook. + // So leave it at the error message. + } +} + void RecursorLua4::maintenance() const { if (d_maintenance) { @@ -510,6 +519,7 @@ et.add(RecEventTrace::LuaPreRPZ); bool ok = genhook(d_prerpz, dq, ret); et.add(RecEventTrace::LuaPreRPZ, ok, false); + warnDrop(dq); return ok; } @@ -521,6 +531,7 @@ et.add(RecEventTrace::LuaPreResolve); bool ok = genhook(d_preresolve, dq, ret); et.add(RecEventTrace::LuaPreResolve, ok, false); + warnDrop(dq); return ok; } @@ -532,6 +543,7 @@ et.add(RecEventTrace::LuaNXDomain); bool ok = genhook(d_nxdomain, dq, ret); et.add(RecEventTrace::LuaNXDomain, ok, false); + warnDrop(dq); return ok; } @@ -543,6 +555,7 @@ et.add(RecEventTrace::LuaNoData); bool ok = genhook(d_nodata, dq, ret); et.add(RecEventTrace::LuaNoData, ok, false); + warnDrop(dq); return ok; } @@ -554,6 +567,7 @@ et.add(RecEventTrace::LuaPostResolve); bool ok = genhook(d_postresolve, dq, ret); et.add(RecEventTrace::LuaPostResolve, ok, false); + warnDrop(dq); return ok; } @@ -571,6 +585,7 @@ et.add(RecEventTrace::LuaPreOutQuery); bool ok = genhook(d_preoutquery, dq, ret); et.add(RecEventTrace::LuaPreOutQuery, ok, false); + warnDrop(dq); return ok; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/lwres.cc new/pdns-recursor-4.6.2/lwres.cc --- old/pdns-recursor-4.6.1/lwres.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/lwres.cc 2022-03-30 13:10:52.000000000 +0200 @@ -434,32 +434,33 @@ ret = arecvfrom(buf, 0, ip, &len, qid, domain, type, queryfd, now); } else { - bool isNew; - do { - try { - // If we get a new (not re-used) TCP connection that does not - // work, we give up. For reused connections, we assume the - // peer has closed it on error, so we retry. At some point we - // *will* get a new connection, so this loop is not endless. - isNew = tcpconnect(*now, ip, connection, dnsOverTLS); - ret = tcpsendrecv(ip, connection, localip, vpacket, len, buf); + bool isNew; + do { + try { + // If we get a new (not re-used) TCP connection that does not + // work, we give up. For reused connections, we assume the + // peer has closed it on error, so we retry. At some point we + // *will* get a new connection, so this loop is not endless. + isNew = true; // tcpconnect() might throw for new connections. In that case, we want to break the loop + isNew = tcpconnect(*now, ip, connection, dnsOverTLS); + ret = tcpsendrecv(ip, connection, localip, vpacket, len, buf); #ifdef HAVE_FSTRM - if (fstrmQEnabled) { - logFstreamQuery(fstrmLoggers, queryTime, localip, ip, !dnsOverTLS ? DnstapMessage::ProtocolType::DoTCP : DnstapMessage::ProtocolType::DoT, context ? context->d_auth : boost::none, vpacket); - } -#endif /* HAVE_FSTRM */ - if (ret == LWResult::Result::Success) { - break; - } - connection.d_handler->close(); - } - catch (const NetworkError&) { - ret = LWResult::Result::OSLimitError; // OS limits error + if (fstrmQEnabled) { + logFstreamQuery(fstrmLoggers, queryTime, localip, ip, !dnsOverTLS ? DnstapMessage::ProtocolType::DoTCP : DnstapMessage::ProtocolType::DoT, context ? context->d_auth : boost::none, vpacket); } - catch (const runtime_error&) { - ret = LWResult::Result::OSLimitError; // OS limits error (PermanentError is transport related) +#endif /* HAVE_FSTRM */ + if (ret == LWResult::Result::Success) { + break; } - } while (!isNew); + connection.d_handler->close(); + } + catch (const NetworkError&) { + ret = LWResult::Result::OSLimitError; // OS limits error + } + catch (const runtime_error&) { + ret = LWResult::Result::OSLimitError; // OS limits error (PermanentError is transport related) + } + } while (!isNew); } lwr->d_usec=dt.udiff(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/pdns_recursor.1 new/pdns-recursor-4.6.2/pdns_recursor.1 --- old/pdns-recursor-4.6.1/pdns_recursor.1 2022-03-21 09:07:29.000000000 +0100 +++ new/pdns-recursor-4.6.2/pdns_recursor.1 2022-03-30 15:33:29.000000000 +0200 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "PDNS_RECURSOR" "1" "Mar 21, 2022" "" "PowerDNS Recursor" +.TH "PDNS_RECURSOR" "1" "Mar 30, 2022" "" "PowerDNS Recursor" .SH NAME pdns_recursor \- The PowerDNS Recursor binary .SH SYNOPSIS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/pdns_recursor.cc new/pdns-recursor-4.6.2/pdns_recursor.cc --- old/pdns-recursor-4.6.1/pdns_recursor.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/pdns_recursor.cc 2022-03-30 13:10:52.000000000 +0200 @@ -293,11 +293,11 @@ //! used to send information to a newborn mthread struct DNSComboWriter { - DNSComboWriter(const std::string& query, const struct timeval& now): d_mdp(true, query), d_now(now), d_query(query) + DNSComboWriter(const std::string& query, const struct timeval& now, shared_ptr<RecursorLua4> luaContext): d_mdp(true, query), d_now(now), d_query(query), d_luaContext(luaContext) { } - DNSComboWriter(const std::string& query, const struct timeval& now, std::unordered_set<std::string>&& policyTags, LuaContext::LuaObject&& data, std::vector<DNSRecord>&& records): d_mdp(true, query), d_now(now), d_query(query), d_policyTags(std::move(policyTags)), d_records(std::move(records)), d_data(std::move(data)) + DNSComboWriter(const std::string& query, const struct timeval& now, std::unordered_set<std::string>&& policyTags, shared_ptr<RecursorLua4> luaContext, LuaContext::LuaObject&& data, std::vector<DNSRecord>&& records): d_mdp(true, query), d_now(now), d_query(query), d_policyTags(std::move(policyTags)), d_records(std::move(records)), d_luaContext(luaContext), d_data(std::move(data)) { } @@ -359,7 +359,11 @@ std::unordered_set<std::string> d_policyTags; std::string d_routingTag; std::vector<DNSRecord> d_records; + + // d_data is tied to this LuaContext so we need to keep it alive and use it, not a newer one, as long as d_data exists + shared_ptr<RecursorLua4> d_luaContext; LuaContext::LuaObject d_data; + EDNSSubnetOpts d_ednssubnet; shared_ptr<TCPConnection> d_tcpConnection; boost::optional<uint16_t> d_extendedErrorCode{boost::none}; @@ -1469,6 +1473,8 @@ } #endif /* NOD_ENABLED */ +static bool answerIsNOData(uint16_t requestedType, int rcode, const std::vector<DNSRecord>& records); + int followCNAMERecords(vector<DNSRecord>& ret, const QType qtype, int rcode) { vector<DNSRecord> resolved; @@ -1489,8 +1495,14 @@ rcode = directResolve(target, qtype, QClass::IN, resolved, t_pdl); - for(DNSRecord& rr : resolved) { - ret.push_back(std::move(rr)); + if (g_dns64Prefix && qtype == QType::AAAA && answerIsNOData(qtype, rcode, resolved)) { + rcode = getFakeAAAARecords(target, *g_dns64Prefix, resolved); + } + + for (DNSRecord& rr : resolved) { + if (rr.d_place == DNSResourceRecord::ANSWER) { + ret.push_back(std::move(rr)); + } } return rcode; } @@ -1733,8 +1745,8 @@ sr.setId(MT->getTid()); bool DNSSECOK=false; - if(t_pdl) { - sr.setLuaEngine(t_pdl); + if(dc->d_luaContext) { + sr.setLuaEngine(dc->d_luaContext); } if(g_dnssecmode != DNSSECMode::Off) { sr.setDoDNSSEC(true); @@ -1827,8 +1839,8 @@ sr.setCacheOnly(); } - if (t_pdl) { - t_pdl->prerpz(dq, res, sr.d_eventTrace); + if (dc->d_luaContext) { + dc->d_luaContext->prerpz(dq, res, sr.d_eventTrace); } // Check if the client has a policy attached to it @@ -1875,7 +1887,7 @@ } // if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve - if (!t_pdl || !t_pdl->preresolve(dq, res, sr.d_eventTrace)) { + if (!dc->d_luaContext || !dc->d_luaContext->preresolve(dq, res, sr.d_eventTrace)) { if (!g_dns64PrefixReverse.empty() && dq.qtype == QType::PTR && dq.qname.isPartOf(g_dns64PrefixReverse)) { res = getFakePTRRecords(dq.qname, ret); @@ -1886,7 +1898,7 @@ if (wantsRPZ && appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { - if (t_pdl && t_pdl->policyHitEventFilter(dc->d_source, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_tcp, appliedPolicy, dc->d_policyTags, sr.d_discardedPolicies)) { + if (dc->d_luaContext && dc->d_luaContext->policyHitEventFilter(dc->d_source, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_tcp, appliedPolicy, dc->d_policyTags, sr.d_discardedPolicies)) { /* reset to no match */ appliedPolicy = DNSFilterEngine::Policy(); } @@ -1961,10 +1973,10 @@ } } - if (t_pdl || (g_dns64Prefix && dq.qtype == QType::AAAA && !vStateIsBogus(dq.validationState))) { + if (dc->d_luaContext || (g_dns64Prefix && dq.qtype == QType::AAAA && !vStateIsBogus(dq.validationState))) { if (res == RCode::NoError) { if (answerIsNOData(dc->d_mdp.d_qtype, res, ret)) { - if (t_pdl && t_pdl->nodata(dq, res, sr.d_eventTrace)) { + if (dc->d_luaContext && dc->d_luaContext->nodata(dq, res, sr.d_eventTrace)) { shouldNotValidate = true; auto policyResult = handlePolicyHit(appliedPolicy, dc, sr, res, ret, pw); if (policyResult == PolicyResult::HaveAnswer) { @@ -1980,7 +1992,7 @@ } } } - else if (res == RCode::NXDomain && t_pdl && t_pdl->nxdomain(dq, res, sr.d_eventTrace)) { + else if (res == RCode::NXDomain && dc->d_luaContext && dc->d_luaContext->nxdomain(dq, res, sr.d_eventTrace)) { shouldNotValidate = true; auto policyResult = handlePolicyHit(appliedPolicy, dc, sr, res, ret, pw); if (policyResult == PolicyResult::HaveAnswer) { @@ -1991,7 +2003,7 @@ } } - if (t_pdl && t_pdl->postresolve(dq, res, sr.d_eventTrace)) { + if (dc->d_luaContext && dc->d_luaContext->postresolve(dq, res, sr.d_eventTrace)) { shouldNotValidate = true; auto policyResult = handlePolicyHit(appliedPolicy, dc, sr, res, ret, pw); // haveAnswer case redundant @@ -2001,7 +2013,7 @@ } } } - else if (t_pdl) { + else if (dc->d_luaContext) { // preresolve returned true shouldNotValidate = true; auto policyResult = handlePolicyHit(appliedPolicy, dc, sr, res, ret, pw); @@ -2781,7 +2793,7 @@ conn->state = TCPConnection::BYTE0; std::unique_ptr<DNSComboWriter> dc; try { - dc = std::make_unique<DNSComboWriter>(conn->data, g_now); + dc = std::make_unique<DNSComboWriter>(conn->data, g_now, t_pdl); } catch(const MOADNSException &mde) { g_stats.clientParseError++; @@ -3328,7 +3340,7 @@ return 0; } - auto dc = std::make_unique<DNSComboWriter>(question, g_now, std::move(policyTags), std::move(data), std::move(records)); + auto dc = std::make_unique<DNSComboWriter>(question, g_now, std::move(policyTags), t_pdl, std::move(data), std::move(records)); dc->setSocket(fd); dc->d_tag=ctag; dc->d_qhash=qhash; @@ -3948,10 +3960,10 @@ // Divide by 12 to get the original 2 hour cycle if s_maxcachettl is default (1 day) if (now.tv_sec - last_rootupdate > max(SyncRes::s_maxcachettl / 12, 10U)) { int res = SyncRes::getRootNS(g_now, nullptr, 0); - if (!res) { + if (res == 0) { last_rootupdate=now.tv_sec; try { - primeRootNSZones(g_dnssecmode != DNSSECMode::Off, 0); + primeRootNSZones(g_dnssecmode, 0); } catch (const std::exception& e) { g_log<<Logger::Error<<"Exception while priming the root NS zones: "<<e.what()<<endl; @@ -5716,7 +5728,7 @@ g_log<<Logger::Critical<<"Priming cache failed, stopping"<<endl; return nullptr; } - g_log<<Logger::Warning<<"Done priming cache with root hints"<<endl; + g_log<<Logger::Debug<<"Done priming cache with root hints"<<endl; } t_packetCache = std::make_unique<RecursorPacketCache>(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/pubsuffix.cc new/pdns-recursor-4.6.2/pubsuffix.cc --- old/pdns-recursor-4.6.1/pubsuffix.cc 2022-03-21 09:07:30.000000000 +0100 +++ new/pdns-recursor-4.6.2/pubsuffix.cc 2022-03-30 15:33:30.000000000 +0200 @@ -5546,6 +5546,9 @@ "hlx.page", "hlx3.page", "beep.pl", +"airkitapps.com", +"airkitapps-au.com", +"airkitapps.eu", "aivencloud.com", "barsy.ca", "kasserver.com", @@ -6158,6 +6161,8 @@ "en-root.fr", "mytuleap.com", "tuleap-partners.com", +"encr.app", +"encoreapi.com", "onred.one", "staging.onred.one", "eu.encoway.cloud", @@ -6373,6 +6378,7 @@ "independent-review.uk", "public-inquiry.uk", "royal-commission.uk", +"campaign.gov.uk", "service.gov.uk", "api.gov.uk", "gehirn.ne.jp", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/rec-taskqueue.cc new/pdns-recursor-4.6.2/rec-taskqueue.cc --- old/pdns-recursor-4.6.1/rec-taskqueue.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/rec-taskqueue.cc 2022-03-30 13:10:52.000000000 +0200 @@ -76,6 +76,14 @@ void pushAlmostExpiredTask(const DNSName& qname, uint16_t qtype, time_t deadline) { ++s_almost_expired_tasks_pushed; + switch (qtype) { + // Internal types + case QType::ENT: + case QType::ADDR: + case QType::ALIAS: + case QType::LUA: + return; + } pdns::ResolveTask task{qname, qtype, deadline, true, resolve}; t_taskQueue.push(std::move(task)); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/rec_control.1 new/pdns-recursor-4.6.2/rec_control.1 --- old/pdns-recursor-4.6.1/rec_control.1 2022-03-21 09:07:29.000000000 +0100 +++ new/pdns-recursor-4.6.2/rec_control.1 2022-03-30 15:33:29.000000000 +0200 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "REC_CONTROL" "1" "Mar 21, 2022" "" "PowerDNS Recursor" +.TH "REC_CONTROL" "1" "Mar 30, 2022" "" "PowerDNS Recursor" .SH NAME rec_control \- Command line tool to control a running Recursor .SH SYNOPSIS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/recursor_cache.cc new/pdns-recursor-4.6.2/recursor_cache.cc --- old/pdns-recursor-4.6.1/recursor_cache.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/recursor_cache.cc 2022-03-30 13:10:52.000000000 +0200 @@ -248,7 +248,13 @@ } else { if (!entry->d_submitted) { - pushAlmostExpiredTask(qname, qtype, entry->d_ttd); + if (qtype == QType::ADDR) { + pushAlmostExpiredTask(qname, QType::A, entry->d_ttd); + pushAlmostExpiredTask(qname, QType::AAAA, entry->d_ttd); + } + else { + pushAlmostExpiredTask(qname, qtype, entry->d_ttd); + } entry->d_submitted = true; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/reczones.cc new/pdns-recursor-4.6.2/reczones.cc --- old/pdns-recursor-4.6.1/reczones.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/reczones.cc 2022-03-30 13:10:52.000000000 +0200 @@ -53,7 +53,12 @@ time_t now = time(nullptr); - if (::arg()["hint-file"].empty()) { + const string hintfile = ::arg()["hint-file"]; + if (hintfile == "no") { + g_log << Logger::Debug << "Priming root disabled by hint-file=no" << endl; + return true; + } + if (hintfile.empty()) { DNSRecord arr, aaaarr, nsrr; nsrr.d_name = g_rootdnsname; arr.d_type = QType::A; @@ -97,7 +102,7 @@ } } else { - ZoneParserTNG zpt(::arg()["hint-file"]); + ZoneParserTNG zpt(hintfile); zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps")); zpt.setMaxIncludes(::arg().asNum("max-include-depth")); DNSResourceRecord rr; @@ -168,16 +173,14 @@ // servers are authoritative for root-servers.net, and some // implementations reply not with a delegation on a root-servers.net // DS query, but with a NODATA response (the domain is unsigned). -void primeRootNSZones(bool dnssecmode, unsigned int depth) +void primeRootNSZones(DNSSECMode mode, unsigned int depth) { struct timeval now; gettimeofday(&now, 0); SyncRes sr(now); - if (dnssecmode) { - sr.setDoDNSSEC(true); - sr.setDNSSECValidationRequested(true); - } + sr.setDoDNSSEC(mode != DNSSECMode::Off); + sr.setDNSSECValidationRequested(mode != DNSSECMode::Off && mode != DNSSECMode::ProcessNoValidate); // beginResolve() can yield to another mthread that could trigger t_rootNSZones updates, // so make a local copy diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/syncres.cc new/pdns-recursor-4.6.2/syncres.cc --- old/pdns-recursor-4.6.1/syncres.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/syncres.cc 2022-03-30 13:10:52.000000000 +0200 @@ -1094,14 +1094,14 @@ try { // First look for both A and AAAA in the cache and be satisfied if we find anything res_t cset; - if (s_doIPv4 && g_recCache->get(d_now.tv_sec, qname, QType::A, false, &cset, d_cacheRemote, d_refresh, d_routingTag) > 0) { + if (s_doIPv4 && g_recCache->get(d_now.tv_sec, qname, QType::A, false, &cset, d_cacheRemote, false, d_routingTag) > 0) { for (const auto &i : cset) { if (auto rec = getRR<ARecordContent>(i)) { ret.push_back(rec->getCA(53)); } } } - if (s_doIPv6 && g_recCache->get(d_now.tv_sec, qname, QType::AAAA, false, &cset, d_cacheRemote, d_refresh, d_routingTag) > 0) { + if (s_doIPv6 && g_recCache->get(d_now.tv_sec, qname, QType::AAAA, false, &cset, d_cacheRemote, false, d_routingTag) > 0) { for (const auto &i : cset) { if (auto rec = getRR<AAAARecordContent>(i)) { ret.push_back(rec->getCA(53)); @@ -1139,7 +1139,7 @@ // We have some IPv4 records, don't bother with going out to get IPv6, but do consult the cache, we might have // encountered some IPv6 glue cset.clear(); - if (g_recCache->get(d_now.tv_sec, qname, QType::AAAA, false, &cset, d_cacheRemote, d_refresh, d_routingTag) > 0) { + if (g_recCache->get(d_now.tv_sec, qname, QType::AAAA, false, &cset, d_cacheRemote, false, d_routingTag) > 0) { for (const auto &i : cset) { if (auto rec = getRR<AAAARecordContent>(i)) { ret.push_back(rec->getCA(53)); @@ -1222,7 +1222,7 @@ vector<DNSRecord> ns; *flawedNSSet = false; - if(g_recCache->get(d_now.tv_sec, subdomain, QType::NS, false, &ns, d_cacheRemote, d_refresh, d_routingTag) > 0) { + if(g_recCache->get(d_now.tv_sec, subdomain, QType::NS, false, &ns, d_cacheRemote, false, d_routingTag) > 0) { bestns.reserve(ns.size()); for(auto k=ns.cbegin();k!=ns.cend(); ++k) { @@ -1238,7 +1238,7 @@ const DNSRecord& dr=*k; auto nrr = getRR<NSRecordContent>(dr); if(nrr && (!nrr->getNS().isPartOf(subdomain) || g_recCache->get(d_now.tv_sec, nrr->getNS(), nsqt, - false, doLog() ? &aset : 0, d_cacheRemote, d_refresh, d_routingTag) > 5)) { + false, doLog() ? &aset : 0, d_cacheRemote, false, d_routingTag) > 5)) { bestns.push_back(dr); LOG(prefix<<qname<<": NS (with ip, or non-glue) in cache for '"<<subdomain<<"' -> '"<<nrr->getNS()<<"'"<<endl); LOG(prefix<<qname<<": within bailiwick: "<< nrr->getNS().isPartOf(subdomain)); @@ -1292,7 +1292,7 @@ LOG(prefix<<qname<<": reprimed the root"<<endl); /* let's prevent an infinite loop */ if (!d_updatingRootNS) { - primeRootNSZones(g_dnssecmode != DNSSECMode::Off, depth); + primeRootNSZones(g_dnssecmode, depth); getRootNS(d_now, d_asyncResolve, depth); } } @@ -2860,12 +2860,18 @@ state = vState::BogusSelfSignedDS; dsFailed = true; } - else if (qtype == QType::DS && signer == qname && !signer.isRoot() && (type == QType::SOA || type == QType::NSEC || type == QType::NSEC3)) { + else if (qtype == QType::DS && signer == qname && !signer.isRoot()) { + if (type == QType::SOA || type == QType::NSEC || type == QType::NSEC3) { /* if we are trying to validate the DS or more likely NSEC(3)s proving that it does not exist, we have a problem. In that case let's go Bogus (we will check later if we missed a cut) */ - state = vState::BogusSelfSignedDS; - dsFailed = true; + state = vState::BogusSelfSignedDS; + dsFailed = true; + } + else if (type == QType::CNAME) { + state = vState::BogusUnableToGetDSs; + dsFailed = true; + } } else if (qtype == QType::DNSKEY && signer == qname) { /* that actually does happen when a server returns NS records in authority @@ -4614,9 +4620,9 @@ sr.setAsyncCallback(asyncCallback); vector<DNSRecord> ret; - int res=-1; + int res = -1; try { - res=sr.beginResolve(g_rootdnsname, QType::NS, 1, ret, depth + 1); + res = sr.beginResolve(g_rootdnsname, QType::NS, 1, ret, depth + 1); if (g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate) { auto state = sr.getValidationState(); if (vStateIsBogus(state)) { @@ -4641,11 +4647,11 @@ g_log<<Logger::Error<<"Failed to update . records, got an exception"<<endl; } - if(!res) { - g_log<<Logger::Notice<<"Refreshed . records"<<endl; + if (res == 0) { + g_log<<Logger::Debug<<"Refreshed . records"<<endl; + } + else { + g_log<<Logger::Warning<<"Failed to update root NS records, RCODE="<<res<<endl; } - else - g_log<<Logger::Warning<<"Failed to update . records, RCODE="<<res<<endl; - return res; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/syncres.hh new/pdns-recursor-4.6.2/syncres.hh --- old/pdns-recursor-4.6.1/syncres.hh 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/syncres.hh 2022-03-30 13:10:52.000000000 +0200 @@ -45,7 +45,7 @@ #include <boost/tuple/tuple_comparison.hpp> #include "mtasker.hh" #include "iputils.hh" -#include "validate.hh" +#include "validate-recursor.hh" #include "ednssubnet.hh" #include "filterpo.hh" #include "negcache.hh" @@ -1194,7 +1194,7 @@ uint64_t* pleaseGetPacketCacheSize(); void doCarbonDump(void*); bool primeHints(time_t now = time(nullptr)); -void primeRootNSZones(bool, unsigned int depth); +void primeRootNSZones(DNSSECMode, unsigned int depth); struct WipeCacheResult { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/test-syncres_cc.cc new/pdns-recursor-4.6.2/test-syncres_cc.cc --- old/pdns-recursor-4.6.1/test-syncres_cc.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/test-syncres_cc.cc 2022-03-30 13:10:52.000000000 +0200 @@ -27,7 +27,7 @@ return theArg; } -void primeRootNSZones(bool, unsigned int) +void primeRootNSZones(DNSSECMode, unsigned int) { } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/test-syncres_cc6.cc new/pdns-recursor-4.6.2/test-syncres_cc6.cc --- old/pdns-recursor-4.6.1/test-syncres_cc6.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/test-syncres_cc6.cc 2022-03-30 13:10:52.000000000 +0200 @@ -1767,4 +1767,116 @@ BOOST_CHECK_EQUAL(queriesCount, 6U); } +BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_broken_cname_ds) +{ + /* Test an Insecure domain that responds with a CNAME on a DS query */ + std::unique_ptr<SyncRes> sr; + initSR(sr, true); + + setDNSSECValidation(sr, DNSSECMode::ValidateAll); + + primeHints(); + const DNSName target("www.sub.powerdns.com."); + const ComboAddress targetAddr("192.0.2.42"); + testkeysset_t keys, pdnskeys; + + auto luaconfsCopy = g_luaconfs.getCopy(); + luaconfsCopy.dsAnchors.clear(); + + // We have two set of keys as powerdns.com and sub.powerdns.com are Insecure but still have RRSIGS + generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors); + generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys); + + generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, pdnskeys); + generateKeyMaterial(DNSName("sub.powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, pdnskeys); + + g_luaconfs.setState(luaconfsCopy); + + size_t queriesCount = 0; + + sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, pdnskeys](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, LWResult* res, bool* chained) { + queriesCount++; + + if (type == QType::DS) { + // Return a signed CNAME on a DS query for powerdns.com and sub.powerdns.com + if (domain == DNSName("powerdns.com.") || domain == DNSName("sub.powerdns.com.")) { + setLWResult(res, 0, true, false, true); + addRecordToLW(res, domain, QType::CNAME, "some.name", DNSResourceRecord::ANSWER, 300); + addRRSIG(pdnskeys, res->d_records, domain, 300); + return LWResult::Result::Success; + } + else { + return genericDSAndDNSKEYHandler(res, domain, domain, type, keys); + } + } + else if (type == QType::DNSKEY) { + if (domain == DNSName("powerdns.com.") || domain == DNSName("sub.powerdns.com.")) { + return genericDSAndDNSKEYHandler(res, domain, domain, type, pdnskeys); + } + else { + return genericDSAndDNSKEYHandler(res, domain, domain, type, keys); + } + } + else { + if (isRootServer(ip)) { + setLWResult(res, 0, false, false, true); + addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600); + addDS(DNSName("com."), 300, res->d_records, keys); + addRRSIG(keys, res->d_records, DNSName("."), 300); + addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); + return LWResult::Result::Success; + } + else if (ip == ComboAddress("192.0.2.1:53")) { + if (domain == DNSName("com.")) { + setLWResult(res, 0, true, false, true); + addRecordToLW(res, DNSName("com."), QType::NS, "a.gtld-servers.com."); + addRRSIG(keys, res->d_records, DNSName("com."), 300); + addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); + } + else { + setLWResult(res, 0, false, false, true); + addRecordToLW(res, DNSName("powerdns.com."), QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600); + addNSECRecordToLW(DNSName("powerdns.com."), DNSName("z.powerdns.com."), {QType::NS, QType::RRSIG}, 600, res->d_records); + addRRSIG(keys, res->d_records, DNSName("com."), 300); + addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600); + } + return LWResult::Result::Success; + } + else if (ip == ComboAddress("192.0.2.2:53")) { + setLWResult(res, 0, false, false, true); + addRecordToLW(res, DNSName("sub.powerdns.com."), QType::NS, "ns1.sub.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600); + addRRSIG(pdnskeys, res->d_records, DNSName("powerdns.com."), 300); + + addRecordToLW(res, "ns1.sub.powerdns.com.", QType::A, "192.0.2.3", DNSResourceRecord::ADDITIONAL, 3600); + return LWResult::Result::Success; + } + else if (ip == ComboAddress("192.0.2.3:53")) { + setLWResult(res, 0, true, false, true); + addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600); + addRRSIG(pdnskeys, res->d_records, DNSName("sub.powerdns.com."), 300); + return LWResult::Result::Success; + } + } + + return LWResult::Result::Timeout; + }); + + vector<DNSRecord> ret; + int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure); + BOOST_REQUIRE_EQUAL(ret.size(), 2U); + BOOST_CHECK(ret[0].d_type == QType::A); + BOOST_CHECK_EQUAL(queriesCount, 8U); + + /* again, to test the cache */ + ret.clear(); + res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure); + BOOST_REQUIRE_EQUAL(ret.size(), 2U); + BOOST_CHECK(ret[0].d_type == QType::A); + BOOST_CHECK_EQUAL(queriesCount, 8U); +} + BOOST_AUTO_TEST_SUITE_END() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/test-syncres_cc8.cc new/pdns-recursor-4.6.2/test-syncres_cc8.cc --- old/pdns-recursor-4.6.1/test-syncres_cc8.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/test-syncres_cc8.cc 2022-03-30 13:10:52.000000000 +0200 @@ -332,6 +332,46 @@ BOOST_CHECK_EQUAL(denialState, dState::NODENIAL); } +BOOST_AUTO_TEST_CASE(test_nsec_insecure_delegation_denial_soa) +{ + initSR(); + + testkeysset_t keys; + generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys); + + vector<DNSRecord> records; + + sortedRecords_t recordContents; + vector<shared_ptr<RRSIGRecordContent>> signatureContents; + + /* + * RFC 5155 section 8.9: + * If there is an NSEC3 RR present in the response that matches the + * delegation name, then the validator MUST ensure that the NS bit is + * set and that the DS bit is not set in the Type Bit Maps field of the + * NSEC3 RR. + */ + /* + The RRSIG from "." denies the existence of any type at a except NS and SOA. + NS has to be set since it is proving an insecure delegation, but SOA should NOT! + */ + addNSECRecordToLW(DNSName("a."), DNSName("b."), {QType::NS, QType::SOA}, 600, records); + recordContents.insert(records.at(0).d_content); + addRRSIG(keys, records, DNSName("."), 300); + signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1))); + records.clear(); + + ContentSigPair pair; + pair.records = recordContents; + pair.signatures = signatureContents; + cspmap_t denialMap; + denialMap[std::pair(DNSName("a."), QType::NSEC)] = pair; + + /* Insecure because both NS and SOA are set, so this is not a proper delegation */ + dState denialState = getDenial(denialMap, DNSName("a."), QType::DS, true, true); + BOOST_CHECK_EQUAL(denialState, dState::NODENIAL); +} + BOOST_AUTO_TEST_CASE(test_nsec_nxqtype_cname) { initSR(); @@ -873,6 +913,46 @@ dState denialState = getDenial(denialMap, DNSName("a."), QType::DS, true, true); BOOST_CHECK_EQUAL(denialState, dState::NODENIAL); } + +BOOST_AUTO_TEST_CASE(test_nsec3_insecure_delegation_denial_soa) +{ + initSR(); + + testkeysset_t keys; + generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys); + + vector<DNSRecord> records; + + sortedRecords_t recordContents; + vector<shared_ptr<RRSIGRecordContent>> signatureContents; + + /* + * RFC 5155 section 8.9: + * If there is an NSEC3 RR present in the response that matches the + * delegation name, then the validator MUST ensure that the NS bit is + * set and that the DS bit is not set in the Type Bit Maps field of the + * NSEC3 RR. + */ + /* + The RRSIG from "." denies the existence of any type at a except NS and SOA. + NS has to be set since it is proving an insecure delegation, but SOA should NOT! + */ + addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", {QType::NS, QType::SOA}, 600, records); + recordContents.insert(records.at(0).d_content); + addRRSIG(keys, records, DNSName("."), 300); + signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1))); + + ContentSigPair pair; + pair.records = recordContents; + pair.signatures = signatureContents; + cspmap_t denialMap; + denialMap[std::pair(records.at(0).d_name, records.at(0).d_type)] = pair; + records.clear(); + + /* Insecure because both NS and SOA are set, so it is not a proper delegation */ + dState denialState = getDenial(denialMap, DNSName("a."), QType::DS, true, true); + BOOST_CHECK_EQUAL(denialState, dState::NODENIAL); +} BOOST_AUTO_TEST_CASE(test_nsec3_ent_opt_out) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/threadname.cc new/pdns-recursor-4.6.2/threadname.cc --- old/pdns-recursor-4.6.1/threadname.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/threadname.cc 2022-03-30 13:10:52.000000000 +0200 @@ -39,7 +39,7 @@ #include "threadname.hh" -void setThreadName(const std::string& threadName) { +static int trySetThreadName(const std::string& threadName) { int retval = 0; #ifdef HAVE_PTHREAD_SETNAME_NP_2 @@ -58,6 +58,16 @@ retval = pthread_setname_np(pthread_self(), threadName.c_str(), nullptr); #endif + return retval; +} + +void setThreadName(const std::string& threadName) { + int retval = trySetThreadName(threadName); + if (retval == ERANGE) { + const std::string shortThreadName(threadName.substr(0, 15)); + retval = trySetThreadName(shortThreadName); + } + if (retval != 0) { #ifdef DNSDIST warnlog("Could not set thread name %s for thread: %s", threadName, strerror(retval)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/validate.cc new/pdns-recursor-4.6.2/validate.cc --- old/pdns-recursor-4.6.1/validate.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/validate.cc 2022-03-30 13:10:52.000000000 +0200 @@ -512,6 +512,16 @@ continue; } + /* The NSEC is either a delegation one, from the parent zone, and + * must have the NS bit set but not the SOA one, or a regular NSEC + * either at apex (signer == owner) or with the SOA or NS bits clear. + */ + const bool notApex = signer.countLabels() < owner.countLabels(); + if (notApex && nsec->isSet(QType::NS) && nsec->isSet(QType::SOA)) { + LOG("However, that NSEC is not at the apex and has both the NS and the SOA bits set!"<<endl); + continue; + } + /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs": Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume nonexistence of any RRs below that zone cut, which include all RRs at @@ -546,9 +556,11 @@ * attention. Bits corresponding to the delegation NS RRset and any * RRsets for which the parent zone has authoritative data MUST be set */ - if (referralToUnsigned && qtype == QType::DS && !nsec->isSet(QType::NS)) { - LOG("However, no NS record exists at this level!"<<endl); - return dState::NODENIAL; + if (referralToUnsigned && qtype == QType::DS) { + if (!nsec->isSet(QType::NS)) { + LOG("However, no NS record exists at this level!"<<endl); + return dState::NODENIAL; + } } /* we know that the name exists (but this qtype doesn't) so except @@ -641,9 +653,10 @@ continue; } + const DNSName& hashedOwner = v.first.first; const DNSName signer = getSigner(v.second.signatures); - if (!v.first.first.isPartOf(signer)) { - LOG("Owner "<<v.first.first<<" is not part of the signer "<<signer<<", ignoring"<<endl); + if (!hashedOwner.isPartOf(signer)) { + LOG("Owner "<<hashedOwner<<" is not part of the signer "<<signer<<", ignoring"<<endl); continue; } @@ -661,18 +674,28 @@ nsec3Seen = true; LOG("\tquery hash: "<<toBase32Hex(h)<<endl); - string beginHash=fromBase32Hex(v.first.first.getRawLabels()[0]); + string beginHash = fromBase32Hex(hashedOwner.getRawLabels()[0]); // If the name exists, check if the qtype is denied if (beginHash == h) { + /* The NSEC3 is either a delegation one, from the parent zone, and + * must have the NS bit set but not the SOA one, or a regular NSEC3 + * either at apex (signer == owner) or with the SOA or NS bits clear. + */ + const bool notApex = signer.countLabels() < qname.countLabels(); + if (notApex && nsec3->isSet(QType::NS) && nsec3->isSet(QType::SOA)) { + LOG("However, that NSEC3 is not at the apex and has both the NS and the SOA bits set!"<<endl); + continue; + } + /* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs": Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume nonexistence of any RRs below that zone cut, which include all RRs at that (original) owner name other than DS RRs, and all RRs below that owner name regardless of type. */ - if (qtype != QType::DS && isNSEC3AncestorDelegation(signer, v.first.first, nsec3)) { + if (qtype != QType::DS && isNSEC3AncestorDelegation(signer, qname, nsec3)) { /* this is an "ancestor delegation" NSEC3 RR */ LOG("An ancestor delegation NSEC3 RR can only deny the existence of a DS"<<endl); return dState::NODENIAL; @@ -692,9 +715,11 @@ * set and that the DS bit is not set in the Type Bit Maps field of the * NSEC3 RR. */ - if (referralToUnsigned && qtype == QType::DS && !nsec3->isSet(QType::NS)) { - LOG("However, no NS record exists at this level!"<<endl); - return dState::NODENIAL; + if (referralToUnsigned && qtype == QType::DS) { + if (!nsec3->isSet(QType::NS)) { + LOG("However, no NS record exists at this level!"<<endl); + return dState::NODENIAL; + } } return dState::NXQTYPE; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pdns-recursor-4.6.1/version.cc new/pdns-recursor-4.6.2/version.cc --- old/pdns-recursor-4.6.1/version.cc 2022-03-21 09:05:17.000000000 +0100 +++ new/pdns-recursor-4.6.2/version.cc 2022-03-30 13:10:52.000000000 +0200 @@ -138,6 +138,12 @@ #ifdef HAVE_LIBCURL "curl " << #endif +#ifdef HAVE_DNS_OVER_TLS + "DoT " << +#endif +#ifdef HAVE_EVP_PKEY_CTX_SET1_SCRYPT_SALT + "scrypt " << +#endif #ifdef VERBOSELOG "verboselog" << #endif
