Version in base suite: 5.2.4-2 Version in overlay suite: 5.2.4-2+deb13u1 Base version: pdns-recursor_5.2.4-2+deb13u1 Target version: pdns-recursor_5.2.6-0+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/pdns-recursor/pdns-recursor_5.2.4-2+deb13u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/pdns-recursor/pdns-recursor_5.2.6-0+deb13u1.dsc configure | 92 ++++++++++++++++++--- configure.ac | 2 debian/changelog | 6 + effective_tld_names.dat | 208 ++++++++++++++++++++++++++++-------------------- lua-recursor4.cc | 8 + m4/boost.m4 | 13 ++- pdns_recursor.1 | 2 pubsuffix.cc | 129 +++++++++++++++++------------ rec-zonetocache.cc | 10 +- rec_control.1 | 2 syncres.cc | 81 ++++++++++++------ syncres.hh | 4 test-rec-zonetocache.cc | 1 test-syncres_cc1.cc | 89 ++++++++++++++++++++ test-syncres_cc4.cc | 8 - 15 files changed, 461 insertions(+), 194 deletions(-) diff -Nru pdns-recursor-5.2.4/configure pdns-recursor-5.2.6/configure --- pdns-recursor-5.2.4/configure 2025-07-17 12:21:47.000000000 +0000 +++ pdns-recursor-5.2.6/configure 2025-09-25 09:53:42.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for pdns-recursor 5.2.4. +# Generated by GNU Autoconf 2.71 for pdns-recursor 5.2.6. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, @@ -618,8 +618,8 @@ # Identity of this package. PACKAGE_NAME='pdns-recursor' PACKAGE_TARNAME='pdns-recursor' -PACKAGE_VERSION='5.2.4' -PACKAGE_STRING='pdns-recursor 5.2.4' +PACKAGE_VERSION='5.2.6' +PACKAGE_STRING='pdns-recursor 5.2.6' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1588,7 +1588,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 5.2.4 to adapt to many kinds of systems. +\`configure' configures pdns-recursor 5.2.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1659,7 +1659,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pdns-recursor 5.2.4:";; + short | recursive ) echo "Configuration of pdns-recursor 5.2.6:";; esac cat <<\_ACEOF @@ -1859,7 +1859,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pdns-recursor configure 5.2.4 +pdns-recursor configure 5.2.6 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2348,7 +2348,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 5.2.4, which was +It was created by pdns-recursor $as_me 5.2.6, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3844,7 +3844,7 @@ # Define the identity of the package. PACKAGE='pdns-recursor' - VERSION='5.2.4' + VERSION='5.2.6' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -20713,7 +20713,7 @@ LIBS="$OLD_LIBS" -echo "$as_me: this is boost.m4 serial 38" >&5 +echo "$as_me: this is boost.m4 serial 39" >&5 boost_save_IFS=$IFS boost_version_req=1.54 IFS=. @@ -20876,7 +20876,7 @@ grep -v '^[[:space:]]*$' | tr -d '\r' | tr -s '\n' ' ' | - $SED -n -e "/^boost-lib-version = /{s///;s/[\" ]//g;p;q;}" >conftest.i 2>&1 + $SED -n -e "/^.*boost-lib-version = /{s///;s/[\" ]//g;p;q;}" >conftest.i 2>&1 then : boost_cv_lib_version=`cat conftest.i` fi @@ -21377,7 +21377,39 @@ boost_thread_save_CPPFLAGS=$CPPFLAGS # Link-time dependency from thread to system was added as of 1.49.0. if test $boost_major_version -ge 149; then -if test x"$boost_cv_inc_path" = xno; then + +if test $boost_major_version -ge 170; then + if test x"$boost_cv_inc_path" = xno; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Boost not available, not searching for boost/system/error_code.hpp" >&5 +printf "%s\n" "$as_me: Boost not available, not searching for boost/system/error_code.hpp" >&6;} +else +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +ac_fn_cxx_check_header_compile "$LINENO" "boost/system/error_code.hpp" "ac_cv_header_boost_system_error_code_hpp" "$ac_includes_default" +if test "x$ac_cv_header_boost_system_error_code_hpp" = xyes +then : + +printf "%s\n" "#define HAVE_BOOST_SYSTEM_ERROR_CODE_HPP 1" >>confdefs.h + +else $as_nop + as_fn_error $? "cannot find boost/system/error_code.hpp" "$LINENO" 5 +fi + +CPPFLAGS=$boost_save_CPPFLAGS +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +fi + +else + if test x"$boost_cv_inc_path" = xno; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Boost not available, not searching for the Boost system library" >&5 printf "%s\n" "$as_me: Boost not available, not searching for the Boost system library" >&6;} else @@ -21692,6 +21724,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu fi +fi fi # end of the Boost.System check. @@ -26898,6 +26931,38 @@ # added as of 1.35.0. If we have a version <1.35, we must not attempt to # find Boost.System as it didn't exist by then. if test $boost_major_version -ge 135; then + +if test $boost_major_version -ge 170; then + if test x"$boost_cv_inc_path" = xno; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Boost not available, not searching for boost/system/error_code.hpp" >&5 +printf "%s\n" "$as_me: Boost not available, not searching for boost/system/error_code.hpp" >&6;} +else +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +ac_fn_cxx_check_header_compile "$LINENO" "boost/system/error_code.hpp" "ac_cv_header_boost_system_error_code_hpp" "$ac_includes_default" +if test "x$ac_cv_header_boost_system_error_code_hpp" = xyes +then : + +printf "%s\n" "#define HAVE_BOOST_SYSTEM_ERROR_CODE_HPP 1" >>confdefs.h + +else $as_nop + as_fn_error $? "cannot find boost/system/error_code.hpp" "$LINENO" 5 +fi + +CPPFLAGS=$boost_save_CPPFLAGS +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +fi + +else if test x"$boost_cv_inc_path" = xno; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Boost not available, not searching for the Boost system library" >&5 printf "%s\n" "$as_me: Boost not available, not searching for the Boost system library" >&6;} @@ -27213,6 +27278,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu fi +fi fi # end of the Boost.System check. @@ -30947,7 +31013,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 5.2.4, which was +This file was extended by pdns-recursor $as_me 5.2.6, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -31015,7 +31081,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -pdns-recursor config.status 5.2.4 +pdns-recursor config.status 5.2.6 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff -Nru pdns-recursor-5.2.4/configure.ac pdns-recursor-5.2.6/configure.ac --- pdns-recursor-5.2.4/configure.ac 2025-07-17 12:21:38.000000000 +0000 +++ pdns-recursor-5.2.6/configure.ac 2025-09-25 09:53:35.000000000 +0000 @@ -1,6 +1,6 @@ AC_PREREQ([2.69]) -AC_INIT([pdns-recursor], [5.2.4]) +AC_INIT([pdns-recursor], [5.2.6]) 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 -Nru pdns-recursor-5.2.4/debian/changelog pdns-recursor-5.2.6/debian/changelog --- pdns-recursor-5.2.4/debian/changelog 2025-09-07 11:22:57.000000000 +0000 +++ pdns-recursor-5.2.6/debian/changelog 2025-10-22 16:15:32.000000000 +0000 @@ -1,3 +1,9 @@ +pdns-recursor (5.2.6-0+deb13u1) trixie-security; urgency=medium + + * New upstream version 5.2.6, fixing CVE-2025-59023. + + -- Chris Hofstaedtler Wed, 22 Oct 2025 18:15:32 +0200 + pdns-recursor (5.2.4-2+deb13u1) trixie; urgency=medium * d/gbp.conf: update for trixie branch diff -Nru pdns-recursor-5.2.4/effective_tld_names.dat pdns-recursor-5.2.6/effective_tld_names.dat --- pdns-recursor-5.2.4/effective_tld_names.dat 2025-07-17 12:22:43.000000000 +0000 +++ pdns-recursor-5.2.6/effective_tld_names.dat 2025-09-25 09:54:23.000000000 +0000 @@ -5,8 +5,8 @@ // Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat, // rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported. -// VERSION: 2025-07-16_21-41-22_UTC -// COMMIT: f0e36343e894c3094e4a1f6e88d68496c95ab8c3 +// VERSION: 2025-09-23_13-07-02_UTC +// COMMIT: 6defc0e19dbbe27dc2a0798256077d0b82d9c455 // Instructions on pulling and using this list can be found at https://publicsuffix.org/list/. @@ -239,7 +239,7 @@ // au : https://www.iana.org/domains/root/db/au.html // https://www.auda.org.au/ -// Confirmed by registry 2024-11-17 +// Confirmed by registry 2025-07-16 au // 2LDs asn.au @@ -282,7 +282,7 @@ wa.gov.au // 4LDs // education.tas.edu.au - Removed at the request of the Department of Education Tasmania -schools.nsw.edu.au +// schools.nsw.edu.au - Removed at the request of the New South Wales Department of Education. // aw : https://www.iana.org/domains/root/db/aw.html aw @@ -502,6 +502,7 @@ am.br anani.br aparecida.br +api.br app.br arq.br art.br @@ -587,6 +588,7 @@ sp.gov.br to.gov.br gru.br +ia.br imb.br ind.br inf.br @@ -647,6 +649,7 @@ sjc.br slg.br slz.br +social.br sorocaba.br srv.br taxi.br @@ -663,6 +666,7 @@ vix.br vlog.br wiki.br +xyz.br zlg.br // bs : http://www.nic.bs/rules.html @@ -924,7 +928,9 @@ tm.cy // cz : https://www.iana.org/domains/root/db/cz.html +// Confirmed by registry 2025-08-06 cz +gov.cz // de : https://www.iana.org/domains/root/db/de.html // Confirmed by registry (with technical @@ -6170,95 +6176,93 @@ lib.dc.us cc.de.us cc.fl.us +lib.fl.us cc.ga.us +lib.ga.us cc.gu.us +lib.gu.us cc.hi.us +lib.hi.us cc.ia.us +lib.ia.us cc.id.us +lib.id.us cc.il.us +lib.il.us cc.in.us +lib.in.us cc.ks.us +lib.ks.us cc.ky.us +lib.ky.us cc.la.us +lib.la.us cc.ma.us +lib.ma.us cc.md.us +lib.md.us cc.me.us +lib.me.us cc.mi.us +lib.mi.us cc.mn.us +lib.mn.us cc.mo.us +lib.mo.us cc.ms.us cc.mt.us +lib.mt.us cc.nc.us +lib.nc.us cc.nd.us +lib.nd.us cc.ne.us +lib.ne.us cc.nh.us +lib.nh.us cc.nj.us +lib.nj.us cc.nm.us +lib.nm.us cc.nv.us +lib.nv.us cc.ny.us +lib.ny.us cc.oh.us +lib.oh.us cc.ok.us +lib.ok.us cc.or.us +lib.or.us cc.pa.us +lib.pa.us cc.pr.us +lib.pr.us cc.ri.us +lib.ri.us cc.sc.us +lib.sc.us cc.sd.us +lib.sd.us cc.tn.us +lib.tn.us cc.tx.us +lib.tx.us cc.ut.us +lib.ut.us cc.va.us +lib.va.us cc.vi.us +lib.vi.us cc.vt.us +lib.vt.us cc.wa.us +lib.wa.us cc.wi.us +lib.wi.us cc.wv.us cc.wy.us k12.wy.us -// lib.de.us - Issue #243 - Moved to Private section at request of Ed Moore -lib.fl.us -lib.ga.us -lib.gu.us -lib.hi.us -lib.ia.us -lib.id.us -lib.il.us -lib.in.us -lib.ks.us -lib.ky.us -lib.la.us -lib.ma.us -lib.md.us -lib.me.us -lib.mi.us -lib.mn.us -lib.mo.us -lib.ms.us -lib.mt.us -lib.nc.us -lib.nd.us -lib.ne.us -lib.nh.us -lib.nj.us -lib.nm.us -lib.nv.us -lib.ny.us -lib.oh.us -lib.ok.us -lib.or.us -lib.pa.us -lib.pr.us -lib.ri.us -lib.sc.us -lib.sd.us -lib.tn.us -lib.tx.us -lib.ut.us -lib.va.us -lib.vi.us -lib.vt.us -lib.wa.us -lib.wi.us // lib.wv.us - Bug 941670 - Removed at request of Larry W Arnold lib.wy.us // k12.ma.us contains school districts in Massachusetts. The 4LDs are @@ -6792,7 +6796,7 @@ // newGTLDs -// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2025-07-16T15:22:08Z +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2025-08-27T15:19:08Z // This list is auto-generated, don't edit it manually. // aaa : American Automobile Association, Inc. // https://www.iana.org/domains/root/db/aaa.html @@ -9402,7 +9406,7 @@ // https://www.iana.org/domains/root/db/nowtv.html nowtv -// nra : NRA Holdings Company, INC. +// nra : National Rifle Association of America // https://www.iana.org/domains/root/db/nra.html nra @@ -9762,10 +9766,6 @@ // https://www.iana.org/domains/root/db/red.html red -// redstone : Redstone Haute Couture Co., Ltd. -// https://www.iana.org/domains/root/db/redstone.html -redstone - // redumbrella : Travelers TLD, LLC // https://www.iana.org/domains/root/db/redumbrella.html redumbrella @@ -11256,10 +11256,6 @@ wroc.pl zakopane.pl -// .US -// Submitted by Ed Moore -lib.de.us - // 12CHARS : https://12chars.com // Submitted by Kenny Niehage 12chars.dev @@ -11272,7 +11268,7 @@ inf.ua ltd.ua -// 611 blockchain domain name system : https://611project.net/ +// 611 blockchain domain name system : https://sixone.one/ 611.to // A2 Hosting @@ -11324,12 +11320,6 @@ // Submitted by Przemyslaw Plewa beep.pl -// Airkit : https://www.airkit.com/ -// Submitted by Grant Cooksey -airkitapps.com -airkitapps-au.com -airkitapps.eu - // Aiven : https://aiven.io/ // Submitted by Aiven Security Team aiven.app @@ -12426,6 +12416,7 @@ // Brendly : https://brendly.rs // Submitted by Dusan Radovanovic +shop.brendly.ba shop.brendly.hr shop.brendly.rs @@ -12773,13 +12764,11 @@ // Dfinity Foundation: https://dfinity.org/ // Submitted by Dfinity Team -caffeine.ai -id.ai -icp-api.io icp0.io *.raw.icp0.io icp1.io *.raw.icp1.io +*.icp.net caffeine.site // dhosting.pl Sp. z o.o. : https://dhosting.pl/ @@ -12837,10 +12826,6 @@ // Submitted by Infra Team durumis.com -// Drobo : http://www.drobo.com/ -// Submitted by Ricardo Padilha -mydrobo.com - // DuckDNS : http://www.duckdns.org/ // Submitted by Richard Harper duckdns.org @@ -13580,10 +13565,6 @@ gitapp.si gitpage.si -// Glitch, Inc : https://glitch.com -// Submitted by Mads Hartmann -glitch.me - // Global NOG Alliance : https://nogalliance.org/ // Submitted by Sander Steffann nog.community @@ -13763,6 +13744,10 @@ günstigbestellen.de günstigliefern.de +// Hackclub Nest : https://hackclub.app +// Submitted by Cyteon +hackclub.app + // Häkkinen.fi : https://www.häkkinen.fi/ // Submitted by Eero Häkkinen häkkinen.fi @@ -13818,6 +13803,11 @@ development.run ravendb.run +// HiDNS : https://www.hidoha.net +// Submitted by ifeng +hidns.co +hidns.vip + // home.pl S.A. : https://home.pl // Submitted by Krzysztof Wolski homesklep.pl @@ -13835,7 +13825,6 @@ // HOSTBIP REGISTRY : https://www.hostbip.com/ // Submitted by Atanunu Igbunuroghene orx.biz -biz.gl biz.ng co.biz.ng dl.biz.ng @@ -14097,7 +14086,10 @@ // Jotelulu S.L. : https://jotelulu.com // Submitted by Daniel Fariña +jote.cloud jotelulu.cloud +jote-dr-lt1.com +jote-rd-lt1.com // JouwWeb B.V. : https://www.jouwweb.nl // Submitted by Camilo Sperberg @@ -14153,9 +14145,16 @@ // Submitted by DisposaBoy oya.to +// KV GmbH : https://www.nic.co.de +// Submitted by KV GmbH +// Abuse reports to +co.de + // Laravel Holdings, Inc. : https://laravel.com -// Submitted by André Valentin +// Submitted by André Valentin & James Brooks laravel.cloud +on-forge.com +on-vapor.com // LCube - Professional hosting e.K. : https://www.lcube-webhosting.de // Submitted by Lars Laehn @@ -14247,14 +14246,12 @@ // Submitted by Heiki Lõhmus lohmus.me -// Lokalized : https://lokalized.nl -// Submitted by Noah Taheij -servers.run - // Lovable : https://lovable.dev // Submitted by Fabian Hedin lovable.app lovableproject.com +lovable.run +lovable.sh // LubMAN UMCS Sp. z o.o : https://lubman.pl/ // Submitted by Ireneusz Maliszewski @@ -14421,6 +14418,11 @@ routingthecloud.net routingthecloud.org +// Million Software, Inc : https://million.dev/ +// Submitted by Rayhan Noufal Arayilakath +same-app.com +same-preview.com + // minion.systems : http://minion.systems // Submitted by Robert Böttinger csx.cc @@ -14842,6 +14844,10 @@ // Submitted by Kenneth Van Alstyne perspecta.cloud +// Plain : https://www.plain.com/ +// Submitted by Jesús Hernández +support.site + // Planet-Work : https://www.planet-work.com/ // Submitted by Frédéric VANNIÈRE on-web.fr @@ -14908,6 +14914,10 @@ // Submitted by Martin Meier protonet.io +// PT Ekossistim Indo Digital : https://e.id +// Submitted by Eid Team +e.id + // Publication Presse Communication SARL : https://ppcom.fr // Submitted by Yaacov Akiba Slama chirurgiens-dentistes-en-france.fr @@ -14952,6 +14962,11 @@ // Submitted by Vasyl Tsalko ladesk.com +// Qualy : https://qualyhq.com +// Submitted by Raphael Arias +*.qualyhqpartner.com +*.qualyhqportal.com + // QuickBackend : https://www.quickbackend.com // Submitted by Dani Biro qbuser.com @@ -14986,6 +15001,10 @@ myrdbx.io site.rb-hosting.io +// Railway Corporation : https://railway.com +// Submitted by Phineas Walton +up.railway.app + // Rancher Labs, Inc : https://rancher.com // Submitted by Vincent Fiduccia *.on-rancher.cloud @@ -15510,8 +15529,10 @@ temp-dns.com // Supabase : https://supabase.io -// Submitted by Inian Parameshwaran +// Submitted by Supabase Security supabase.co +realtime.supabase.co +storage.supabase.co supabase.in supabase.net @@ -15548,6 +15569,11 @@ // Submitted by Bjoern Henke taifun-dns.de +// Tailor Inc. : https://www.tailor.tech +// Submitted by Ryuzo Yamamoto +erp.dev +web.erp.dev + // Tailscale Inc. : https://www.tailscale.com // Submitted by David Anderson ts.net @@ -15588,6 +15614,10 @@ telebit.io *.telebit.xyz +// Teleport : https://goteleport.com +// Submitted by Rob Picard +teleport.sh + // Thingdust AG : https://thingdust.com/ // Submitted by Adrian Imboden *.firenet.ch @@ -15680,7 +15710,6 @@ // Uberspace : https://uberspace.de // Submitted by Moritz Werner -*.uberspace.de uber.space // UDR Limited : http://www.udr.hk.com @@ -15780,6 +15809,10 @@ // Submitted by Masayuki Note wafflecell.com +// Walrus : https://walrus.xyz +// Submitted by Max Spector +wal.app + // Webflow, Inc. : https://www.webflow.com // Submitted by Webflow Security Team webflow.io @@ -15832,6 +15865,8 @@ // William Harrison : https://wharrison.com.au // Submitted by William Harrison wdh.app +hrsn.au +vps.hrsn.au hrsn.dev // Windsurf : https://windsurf.com @@ -15898,6 +15933,7 @@ yandexcloud.net storage.yandexcloud.net website.yandexcloud.net +sourcecraft.site // YesCourse Pty Ltd : https://yescourse.com // Submitted by Atul Bhouraskar @@ -15944,4 +15980,8 @@ // Submitted by Gx1.org zone.id +// ZoneABC : https://zoneabc.net +// Submitted by ZoneABC Team +zabc.net + // ===END PRIVATE DOMAINS=== diff -Nru pdns-recursor-5.2.4/lua-recursor4.cc pdns-recursor-5.2.6/lua-recursor4.cc --- pdns-recursor-5.2.4/lua-recursor4.cc 2025-07-17 12:20:08.000000000 +0000 +++ pdns-recursor-5.2.6/lua-recursor4.cc 2025-09-25 09:52:40.000000000 +0000 @@ -33,6 +33,7 @@ #include "filterpo.hh" #include "rec-snmp.hh" #include "rec-main.hh" +#include "arguments.hh" boost::optional RecursorLua4::DNSQuestion::getDH() const { @@ -515,6 +516,13 @@ thread.detach(); }); + d_lw->writeFunction("getConfigDirAndName", []() -> std::tuple { + std::string dir = ::arg()["config-dir"]; + cleanSlashes(dir); + std::string name = ::arg()["config-name"]; + return {dir, name}; + }); + if (!d_include_path.empty()) { includePath(d_include_path); diff -Nru pdns-recursor-5.2.4/m4/boost.m4 pdns-recursor-5.2.6/m4/boost.m4 --- pdns-recursor-5.2.4/m4/boost.m4 2025-07-17 12:20:08.000000000 +0000 +++ pdns-recursor-5.2.6/m4/boost.m4 2025-09-25 09:52:40.000000000 +0000 @@ -22,7 +22,7 @@ # along with this program. If not, see . m4_define([_BOOST_SERIAL], [m4_translit([ -# serial 38 +# serial 39 ], [# ], [])]) @@ -226,7 +226,7 @@ AC_CACHE_CHECK([for Boost's header version], [boost_cv_lib_version], [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl - _BOOST_SED_CPP([[/^boost-lib-version = /{s///;s/[\" ]//g;p;q;}]], + _BOOST_SED_CPP([[/^.*boost-lib-version = /{s///;s/[\" ]//g;p;q;}]], [#include boost-lib-version = BOOST_LIB_VERSION], [boost_cv_lib_version=`cat conftest.i`])]) @@ -1332,11 +1332,16 @@ # -------------------------------- # Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. This library was introduced in Boost -# 1.35.0. +# 1.35.0 and is header only since 1.70. BOOST_DEFUN([System], -[BOOST_FIND_LIB([system], [$1], +[ +if test $boost_major_version -ge 170; then + BOOST_FIND_HEADER([boost/system/error_code.hpp]) +else + BOOST_FIND_LIB([system], [$1], [boost/system/error_code.hpp], [boost::system::error_code e; e.clear();], [], [], [$2]) +fi ])# BOOST_SYSTEM diff -Nru pdns-recursor-5.2.4/pdns_recursor.1 pdns-recursor-5.2.6/pdns_recursor.1 --- pdns-recursor-5.2.4/pdns_recursor.1 2025-07-17 12:22:43.000000000 +0000 +++ pdns-recursor-5.2.6/pdns_recursor.1 2025-09-25 09:54:23.000000000 +0000 @@ -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" "Jul 17, 2025" "" "PowerDNS Recursor" +.TH "PDNS_RECURSOR" "1" "Sep 25, 2025" "" "PowerDNS Recursor" .SH NAME pdns_recursor \- The PowerDNS Recursor binary .SH SYNOPSIS diff -Nru pdns-recursor-5.2.4/pubsuffix.cc pdns-recursor-5.2.6/pubsuffix.cc --- pdns-recursor-5.2.4/pubsuffix.cc 2025-07-17 12:22:43.000000000 +0000 +++ pdns-recursor-5.2.6/pubsuffix.cc 2025-09-25 09:54:23.000000000 +0000 @@ -193,7 +193,6 @@ "tas.gov.au", "vic.gov.au", "wa.gov.au", -"schools.nsw.edu.au", "com.aw", "biz.az", "co.az", @@ -352,6 +351,7 @@ "am.br", "anani.br", "aparecida.br", +"api.br", "app.br", "arq.br", "art.br", @@ -436,6 +436,7 @@ "sp.gov.br", "to.gov.br", "gru.br", +"ia.br", "imb.br", "ind.br", "inf.br", @@ -495,6 +496,7 @@ "sjc.br", "slg.br", "slz.br", +"social.br", "sorocaba.br", "srv.br", "taxi.br", @@ -511,6 +513,7 @@ "vix.br", "vlog.br", "wiki.br", +"xyz.br", "zlg.br", "com.bs", "edu.bs", @@ -660,6 +663,7 @@ "press.cy", "pro.cy", "tm.cy", +"gov.cz", "co.dm", "com.dm", "edu.dm", @@ -4889,94 +4893,93 @@ "lib.dc.us", "cc.de.us", "cc.fl.us", +"lib.fl.us", "cc.ga.us", +"lib.ga.us", "cc.gu.us", +"lib.gu.us", "cc.hi.us", +"lib.hi.us", "cc.ia.us", +"lib.ia.us", "cc.id.us", +"lib.id.us", "cc.il.us", +"lib.il.us", "cc.in.us", +"lib.in.us", "cc.ks.us", +"lib.ks.us", "cc.ky.us", +"lib.ky.us", "cc.la.us", +"lib.la.us", "cc.ma.us", +"lib.ma.us", "cc.md.us", +"lib.md.us", "cc.me.us", +"lib.me.us", "cc.mi.us", +"lib.mi.us", "cc.mn.us", +"lib.mn.us", "cc.mo.us", +"lib.mo.us", "cc.ms.us", "cc.mt.us", +"lib.mt.us", "cc.nc.us", +"lib.nc.us", "cc.nd.us", +"lib.nd.us", "cc.ne.us", +"lib.ne.us", "cc.nh.us", +"lib.nh.us", "cc.nj.us", +"lib.nj.us", "cc.nm.us", +"lib.nm.us", "cc.nv.us", +"lib.nv.us", "cc.ny.us", +"lib.ny.us", "cc.oh.us", +"lib.oh.us", "cc.ok.us", +"lib.ok.us", "cc.or.us", +"lib.or.us", "cc.pa.us", +"lib.pa.us", "cc.pr.us", +"lib.pr.us", "cc.ri.us", +"lib.ri.us", "cc.sc.us", +"lib.sc.us", "cc.sd.us", +"lib.sd.us", "cc.tn.us", +"lib.tn.us", "cc.tx.us", +"lib.tx.us", "cc.ut.us", +"lib.ut.us", "cc.va.us", +"lib.va.us", "cc.vi.us", +"lib.vi.us", "cc.vt.us", +"lib.vt.us", "cc.wa.us", +"lib.wa.us", "cc.wi.us", +"lib.wi.us", "cc.wv.us", "cc.wy.us", "k12.wy.us", -"lib.fl.us", -"lib.ga.us", -"lib.gu.us", -"lib.hi.us", -"lib.ia.us", -"lib.id.us", -"lib.il.us", -"lib.in.us", -"lib.ks.us", -"lib.ky.us", -"lib.la.us", -"lib.ma.us", -"lib.md.us", -"lib.me.us", -"lib.mi.us", -"lib.mn.us", -"lib.mo.us", -"lib.ms.us", -"lib.mt.us", -"lib.nc.us", -"lib.nd.us", -"lib.ne.us", -"lib.nh.us", -"lib.nj.us", -"lib.nm.us", -"lib.nv.us", -"lib.ny.us", -"lib.oh.us", -"lib.ok.us", -"lib.or.us", -"lib.pa.us", -"lib.pr.us", -"lib.ri.us", -"lib.sc.us", -"lib.sd.us", -"lib.tn.us", -"lib.tx.us", -"lib.ut.us", -"lib.va.us", -"lib.vi.us", -"lib.vt.us", -"lib.wa.us", -"lib.wi.us", "lib.wy.us", "chtr.k12.ma.us", "paroch.k12.ma.us", @@ -5167,7 +5170,6 @@ "poznan.pl", "wroc.pl", "zakopane.pl", -"lib.de.us", "12chars.dev", "12chars.it", "12chars.pro", @@ -5195,9 +5197,6 @@ "adobeioruntime.net", "africa.com", "beep.pl", -"airkitapps.com", -"airkitapps-au.com", -"airkitapps.eu", "aiven.app", "aivencloud.com", "akadns.net", @@ -5983,6 +5982,7 @@ "square7.net", "brave.app", "brave.io", +"shop.brendly.ba", "shop.brendly.hr", "shop.brendly.rs", "browsersafetymark.io", @@ -6158,9 +6158,6 @@ "dedyn.io", "deta.app", "deta.dev", -"caffeine.ai", -"id.ai", -"icp-api.io", "icp0.io", "icp1.io", "caffeine.site", @@ -6182,7 +6179,6 @@ "shoparena.pl", "dreamhosters.com", "durumis.com", -"mydrobo.com", "duckdns.org", "dy.fi", "tunk.org", @@ -6741,7 +6737,6 @@ "gitlab.io", "gitapp.si", "gitpage.si", -"glitch.me", "nog.community", "co.ro", "shop.ro", @@ -6873,6 +6868,7 @@ "gov.nl", "grafana-dev.net", "grayjayleagues.com", +"hackclub.app", "hashbang.sh", "hasura.app", "hasura-app.io", @@ -6895,10 +6891,11 @@ "ravendb.community", "development.run", "ravendb.run", +"hidns.co", +"hidns.vip", "homesklep.pl", "hoplix.shop", "orx.biz", -"biz.gl", "biz.ng", "co.biz.ng", "dl.biz.ng", @@ -7066,7 +7063,10 @@ "phx.enscaled.us", "mircloud.us", "myjino.ru", +"jote.cloud", "jotelulu.cloud", +"jote-dr-lt1.com", +"jote-rd-lt1.com", "webadorsite.com", "jouwweb.site", "js.org", @@ -7083,7 +7083,10 @@ "webthings.io", "krellian.net", "oya.to", +"co.de", "laravel.cloud", +"on-forge.com", +"on-vapor.com", "git-repos.de", "lcube-server.de", "svn-repos.de", @@ -7122,9 +7125,10 @@ "loginline.services", "loginline.site", "lohmus.me", -"servers.run", "lovable.app", "lovableproject.com", +"lovable.run", +"lovable.sh", "krasnik.pl", "leczna.pl", "lubartow.pl", @@ -7219,6 +7223,8 @@ "sn.mynetname.net", "routingthecloud.net", "routingthecloud.org", +"same-app.com", +"same-preview.com", "csx.cc", "mydbserver.com", "webspaceconfig.de", @@ -7440,6 +7446,7 @@ "lk3.ru", "mypep.link", "perspecta.cloud", +"support.site", "on-web.fr", "upsunapp.com", "ent.platform.sh", @@ -7464,6 +7471,7 @@ "vki.kr", "dev.project-study.com", "protonet.io", +"e.id", "chirurgiens-dentistes-en-france.fr", "byen.site", "pubtls.org", @@ -7492,6 +7500,7 @@ "in.net", "myrdbx.io", "site.rb-hosting.io", +"up.railway.app", "ravpage.co.il", "readthedocs-hosted.com", "readthedocs.io", @@ -7769,6 +7778,8 @@ "utwente.io", "temp-dns.com", "supabase.co", +"realtime.supabase.co", +"storage.supabase.co", "supabase.in", "supabase.net", "syncloud.it", @@ -7792,6 +7803,8 @@ "mytabit.co.il", "tabitorder.co.il", "taifun-dns.de", +"erp.dev", +"web.erp.dev", "ts.net", "gda.pl", "gdansk.pl", @@ -7807,6 +7820,7 @@ "s3.teckids.org", "telebit.app", "telebit.io", +"teleport.sh", "reservd.com", "thingdustdata.com", "cust.dev.thingdust.io", @@ -7894,6 +7908,7 @@ "deus-canvas.com", "voorloper.cloud", "wafflecell.com", +"wal.app", "webflow.io", "webflowtest.io", "bookonline.app", @@ -7915,6 +7930,8 @@ "beta.wmcloud.org", "wmflabs.org", "wdh.app", +"hrsn.au", +"vps.hrsn.au", "hrsn.dev", "windsurf.app", "windsurf.build", @@ -7947,6 +7964,7 @@ "yandexcloud.net", "storage.yandexcloud.net", "website.yandexcloud.net", +"sourcecraft.site", "official.academy", "yolasite.com", "ynh.fr", @@ -7961,4 +7979,5 @@ "virtualserver.io", "enterprisecloud.nu", "zone.id", +"zabc.net", 0}; diff -Nru pdns-recursor-5.2.4/rec-zonetocache.cc pdns-recursor-5.2.6/rec-zonetocache.cc --- pdns-recursor-5.2.4/rec-zonetocache.cc 2025-07-17 12:20:08.000000000 +0000 +++ pdns-recursor-5.2.6/rec-zonetocache.cc 2025-09-25 09:52:40.000000000 +0000 @@ -418,10 +418,12 @@ sigsrr = iter->second; } bool auth = isRRSetAuth(qname, qtype); - // Same decision as updateCacheFromRecords() (we do not test for NSEC since we skip those completely) - if (auth || (qtype == QType::NS || qtype == QType::A || qtype == QType::AAAA || qtype == QType::DS)) { - g_recCache->replace(d_now, qname, qtype, v, sigsrr, - std::vector>(), auth, d_zone); + // Same list as updateCacheFromRecords() (we do not test for NSEC since we skip those completely) + // Issue #15651 + bool storeNonAuth = !SyncRes::isRecursiveForward(qname); + if (auth || (storeNonAuth && (qtype == QType::NS || qtype == QType::A || qtype == QType::AAAA || qtype == QType::DS))) { + g_recCache->replace(d_now, qname, qtype, v, sigsrr, {}, + auth, d_zone); } break; } diff -Nru pdns-recursor-5.2.4/rec_control.1 pdns-recursor-5.2.6/rec_control.1 --- pdns-recursor-5.2.4/rec_control.1 2025-07-17 12:22:43.000000000 +0000 +++ pdns-recursor-5.2.6/rec_control.1 2025-09-25 09:54:23.000000000 +0000 @@ -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" "Jul 17, 2025" "" "PowerDNS Recursor" +.TH "REC_CONTROL" "1" "Sep 25, 2025" "" "PowerDNS Recursor" .SH NAME rec_control \- Command line tool to control a running Recursor .SH SYNOPSIS diff -Nru pdns-recursor-5.2.4/syncres.cc pdns-recursor-5.2.6/syncres.cc --- pdns-recursor-5.2.4/syncres.cc 2025-07-17 12:20:08.000000000 +0000 +++ pdns-recursor-5.2.6/syncres.cc 2025-09-25 09:52:40.000000000 +0000 @@ -1089,6 +1089,13 @@ return iter != t_sstorage.domainmap->end() && (iter->second.isAuth() || iter->second.shouldRecurse()); } +bool SyncRes::isRecursiveForward(const DNSName& qname) +{ + DNSName authname(qname); + const auto iter = getBestAuthZone(&authname); + return iter != t_sstorage.domainmap->end() && iter->second.shouldRecurse(); +} + bool SyncRes::isForwardOrAuth(const DNSName& qname) { DNSName authname(qname); @@ -1980,14 +1987,20 @@ // we will get the records from the cache, resulting in a small overhead. // This might be a real problem if we had a RPZ hit, though, because we do not want the processing to continue, since // RPZ rules will not be evaluated anymore (we already matched). - const bool stoppedByPolicyHit = d_appliedPolicy.wasHit(); - + bool stoppedByPolicyHit = d_appliedPolicy.wasHit(); + if (stoppedByPolicyHit && d_appliedPolicy.d_kind == DNSFilterEngine::PolicyKind::Custom && d_appliedPolicy.d_custom) { + // if the custom RPZ record was a CNAME we still need a full chase + // tested by unit test test_following_cname_chain_with_rpz + if (!d_appliedPolicy.d_custom->empty() && d_appliedPolicy.d_custom->at(0)->getType() == QType::CNAME) { + stoppedByPolicyHit = false; + } + } if (fromCache != nullptr && (!d_cacheonly || stoppedByPolicyHit)) { *fromCache = true; } /* Apply Post filtering policies */ - if (d_wantsRPZ && !stoppedByPolicyHit) { + if (d_wantsRPZ && !d_appliedPolicy.wasHit()) { auto luaLocal = g_luaconfs.getLocal(); if (luaLocal->dfe.getPostPolicy(ret, d_discardedPolicies, d_appliedPolicy)) { mergePolicyTags(d_policyTags, d_appliedPolicy.getTags()); @@ -2291,6 +2304,16 @@ return ret; } +bool SyncRes::canUseRecords(const std::string& prefix, const DNSName& qname, const DNSName& name, QType qtype, vState state) +{ + if (vStateIsBogus(state)) { + LOG(prefix << qname << ": Cannot use " << name << '/' << qtype << " records from cache: Bogus" << endl); + return false; + } + // We could validate Indeterminate authoritative records here. + return true; +} + void SyncRes::getBestNSFromCache(const DNSName& qname, const QType qtype, vector& bestns, bool* flawedNSSet, unsigned int depth, const string& prefix, set& beenthere, const boost::optional& cutOffDomain) // NOLINT(readability-function-cognitive-complexity) { DNSName subdomain(qname); @@ -2309,7 +2332,8 @@ vector nsVector; *flawedNSSet = false; - if (bool isAuth = false; g_recCache->get(d_now.tv_sec, subdomain, QType::NS, flags, &nsVector, d_cacheRemote, d_routingTag, nullptr, nullptr, nullptr, nullptr, &isAuth) > 0) { + vState state{vState::Indeterminate}; + if (bool isAuth = false; g_recCache->get(d_now.tv_sec, subdomain, QType::NS, flags, &nsVector, d_cacheRemote, d_routingTag, nullptr, nullptr, nullptr, &state, &isAuth) > 0 && canUseRecords(prefix, qname, subdomain, QType::NS, state)) { if (s_maxnsperresolve > 0 && nsVector.size() > s_maxnsperresolve) { vector selected; selected.reserve(s_maxnsperresolve); @@ -2331,7 +2355,12 @@ } auto nrr = getRR(nsRecord); - if (nrr && (!nrr->getNS().isPartOf(subdomain) || g_recCache->get(d_now.tv_sec, nrr->getNS(), nsqt, flags, doLog() ? &aset : nullptr, d_cacheRemote, d_routingTag) > 0)) { + state = vState::Indeterminate; + if (nrr && (!nrr->getNS().isPartOf(subdomain) || g_recCache->get(d_now.tv_sec, nrr->getNS(), nsqt, flags, doLog() ? &aset : nullptr, d_cacheRemote, d_routingTag, nullptr, nullptr, nullptr, &state) > 0)) { + // We make use of the fact that if get() is not called the state is still Indeterminate + if (!canUseRecords(prefix, qname, nrr->getNS(), nsqt, state)) { + continue; + } bestns.push_back(nsRecord); LOG(prefix << qname << ": NS (with ip, or non-glue) in cache for '" << subdomain << "' -> '" << nrr->getNS() << "'"); LOG(", within bailiwick: " << nrr->getNS().isPartOf(subdomain)); @@ -4258,8 +4287,8 @@ std::unordered_set allowedAnswerNames = {qname}; bool cnameSeen = false; bool haveAnswers = false; - bool isNXDomain = false; - bool isNXQType = false; + bool acceptDelegation = false; + bool soaInAuth = false; std::vector skipvec(lwr.d_records.size(), false); unsigned int counter = 0; @@ -4350,9 +4379,9 @@ ++skipCount; continue; } - if (rec->d_type == QType::NS && !d_updatingRootNS && rec->d_name == g_rootdnsname) { + if (rec->d_type == QType::NS && (!rec->d_name.isPartOf(auth) || (rec->d_name == auth && !d_updatingRootNS) || !qname.isPartOf(rec->d_name))) { /* - * We don't want to pick up root NS records in AUTHORITY and their associated ADDITIONAL sections of random queries. + * We don't want to pick up irrelevant NS records in AUTHORITY and their associated ADDITIONAL sections. * So remove them and don't add them to allowedAdditionals. */ LOG(prefix << qname << ": Removing NS record '" << rec->toString() << "' in the AUTHORITY section of a response received from " << auth << endl); @@ -4376,17 +4405,7 @@ ++skipCount; continue; } - - if (!haveAnswers) { - switch (lwr.d_rcode) { - case RCode::NXDomain: - isNXDomain = true; - break; - case RCode::NoError: - isNXQType = true; - break; - } - } + soaInAuth = true; } } /* dealing with records in additional */ @@ -4400,10 +4419,14 @@ } } // end of first loop, handled answer and most of authority section - sanitizeRecordsPass2(prefix, lwr, qname, qtype, auth, allowedAnswerNames, allowedAdditionals, cnameSeen, isNXDomain, isNXQType, skipvec, skipCount); + if (!haveAnswers && lwr.d_rcode == RCode::NoError) { + acceptDelegation = true; + } + + sanitizeRecordsPass2(prefix, lwr, qname, qtype, auth, allowedAnswerNames, allowedAdditionals, cnameSeen, acceptDelegation && !soaInAuth, skipvec, skipCount); } -void SyncRes::sanitizeRecordsPass2(const std::string& prefix, LWResult& lwr, const DNSName& qname, const QType qtype, const DNSName& auth, std::unordered_set& allowedAnswerNames, std::unordered_set& allowedAdditionals, bool cnameSeen, bool isNXDomain, bool isNXQType, std::vector& skipvec, unsigned int& skipCount) +void SyncRes::sanitizeRecordsPass2(const std::string& prefix, LWResult& lwr, const DNSName& qname, const QType qtype, const DNSName& auth, std::unordered_set& allowedAnswerNames, std::unordered_set& allowedAdditionals, bool cnameSeen, bool acceptDelegation, std::vector& skipvec, unsigned int& skipCount) { // Second loop, we know now if the answer was NxDomain or NoData unsigned int counter = 0; @@ -4432,13 +4455,13 @@ } } if (rec->d_place == DNSResourceRecord::AUTHORITY && rec->d_type == QType::NS) { - if (isNXDomain || isNXQType) { + if (!acceptDelegation) { /* - * We don't want to pick up NS records in AUTHORITY and their ADDITIONAL sections of NXDomain answers + * We don't want to pick up NS records in AUTHORITY and their ADDITIONAL sections of NXDomain answers and answers with answer records * because they are somewhat easy to insert into a large, fragmented UDP response * for an off-path attacker by injecting spoofed UDP fragments. So do not add these to allowedAdditionals. */ - LOG(prefix << qname << ": Removing NS record '" << rec->toString() << "' in the AUTHORITY section of a " << (isNXDomain ? "NXD" : "NXQTYPE") << " response received from " << auth << endl); + LOG(prefix << qname << ": Removing NS record '" << rec->toString() << "' in the AUTHORITY section of a response received from " << auth << endl); skipvec[counter] = true; ++skipCount; continue; @@ -4707,6 +4730,7 @@ } } + bool seenBogusRRSet = false; for (auto tCacheEntry = tcache.begin(); tCacheEntry != tcache.end(); ++tCacheEntry) { if (tCacheEntry->second.records.empty()) { // this happens when we did store signatures, but passed on the records themselves @@ -4811,6 +4835,7 @@ } if (vStateIsBogus(recordState)) { + seenBogusRRSet = true; /* this is a TTD by now, be careful */ for (auto& record : tCacheEntry->second.records) { auto newval = std::min(record.d_ttl, static_cast(s_maxbogusttl + d_now.tv_sec)); @@ -4831,7 +4856,11 @@ if (tCacheEntry->first.type != QType::NSEC3 && (tCacheEntry->first.type == QType::DS || tCacheEntry->first.type == QType::NS || tCacheEntry->first.type == QType::A || tCacheEntry->first.type == QType::AAAA || isAA || wasForwardRecurse)) { bool doCache = true; - if (tCacheEntry->first.place == DNSResourceRecord::ANSWER && ednsmask) { + if (!isAA && seenBogusRRSet) { + LOG(prefix << qname << ": Not caching non-authoritative rrsets received with Bogus answer" << endl); + doCache = false; + } + if (doCache && tCacheEntry->first.place == DNSResourceRecord::ANSWER && ednsmask) { const bool isv4 = ednsmask->isIPv4(); if ((isv4 && s_ecsipv4nevercache) || (!isv4 && s_ecsipv6nevercache)) { doCache = false; diff -Nru pdns-recursor-5.2.4/syncres.hh pdns-recursor-5.2.6/syncres.hh --- pdns-recursor-5.2.4/syncres.hh 2025-07-17 12:20:08.000000000 +0000 +++ pdns-recursor-5.2.6/syncres.hh 2025-09-25 09:52:40.000000000 +0000 @@ -296,6 +296,7 @@ { return t_sstorage.domainmap; } + static bool isRecursiveForward(const DNSName& qname); static void setECSScopeZeroAddress(const Netmask& scopeZeroMask) { @@ -647,6 +648,7 @@ static domainmap_t::const_iterator getBestAuthZone(DNSName* qname); bool doCNAMECacheCheck(const DNSName& qname, QType qtype, vector& ret, unsigned int depth, const string& prefix, int& res, Context& context, bool wasAuthZone, bool wasForwardRecurse, bool checkForDups); bool doCacheCheck(const DNSName& qname, const DNSName& authname, bool wasForwardedOrAuthZone, bool wasAuthZone, bool wasForwardRecurse, QType qtype, vector& ret, unsigned int depth, const string& prefix, int& res, Context& context); + bool canUseRecords(const std::string& prefix, const DNSName& qname, const DNSName& name, QType qtype, vState state); void getBestNSFromCache(const DNSName& qname, QType qtype, vector& bestns, bool* flawedNSSet, unsigned int depth, const string& prefix, set& beenthere, const boost::optional& cutOffDomain = boost::none); DNSName getBestNSNamesFromCache(const DNSName& qname, QType qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, const string& prefix, set& beenthere); @@ -664,7 +666,7 @@ vector retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, vector>::const_iterator& tns, unsigned int depth, set& beenthere, const vector>& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet, bool cacheOnly, unsigned int& nretrieveAddressesForNS); void sanitizeRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, const DNSName& auth, bool wasForwarded, bool rdQuery); - void sanitizeRecordsPass2(const std::string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, const DNSName& auth, std::unordered_set& allowedAnswerNames, std::unordered_set& allowedAdditionals, bool cnameSeen, bool isNXDomain, bool isNXQType, std::vector& skipvec, unsigned int& skipCount); + void sanitizeRecordsPass2(const std::string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, const DNSName& auth, std::unordered_set& allowedAnswerNames, std::unordered_set& allowedAdditionals, bool cnameSeen, bool delegationAccepted, std::vector& skipvec, unsigned int& skipCount); /* This function will check whether the answer should have the AA bit set, and will set if it should be set and isn't. This is unfortunately needed to deal with very crappy so-called DNS servers */ void fixupAnswer(const std::string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, const DNSName& auth, bool wasForwarded, bool rdQuery); diff -Nru pdns-recursor-5.2.4/test-rec-zonetocache.cc pdns-recursor-5.2.6/test-rec-zonetocache.cc --- pdns-recursor-5.2.4/test-rec-zonetocache.cc 2025-07-17 12:20:08.000000000 +0000 +++ pdns-recursor-5.2.6/test-rec-zonetocache.cc 2025-09-25 09:52:40.000000000 +0000 @@ -172,6 +172,7 @@ BOOST_AUTO_TEST_CASE(test_zonetocachegeneric) { + SyncRes::setDomainMap(std::make_shared()); g_log.setLoglevel(Logger::Critical); g_log.toConsole(Logger::Critical); zonemdGenericTest(genericTest, pdns::ZoneMD::Config::Require, pdns::ZoneMD::Config::Ignore, 4U); diff -Nru pdns-recursor-5.2.4/test-syncres_cc1.cc pdns-recursor-5.2.6/test-syncres_cc1.cc --- pdns-recursor-5.2.4/test-syncres_cc1.cc 2025-07-17 12:20:08.000000000 +0000 +++ pdns-recursor-5.2.6/test-syncres_cc1.cc 2025-09-25 09:52:40.000000000 +0000 @@ -1568,6 +1568,95 @@ BOOST_CHECK_EQUAL(ret[2].getContent()->getZoneRepresentation(), "192.0.2.2"); } +BOOST_AUTO_TEST_CASE(test_following_cname_chain_with_rpz) +{ + std::unique_ptr resolver; + initSR(resolver); + resolver->setQNameMinimization(true); + + primeHints(); + + const DNSName target("rpzhit.powerdns.com."); + const DNSName cnameTargeta("cname-targeta.powerdns.com"); + const DNSName cnameTargetb("cname-targetb.powerdns.com"); + + resolver->setAsyncCallback([&](const ComboAddress& address, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional& /* srcmask */, const ResolveContext& /* context */, LWResult* res, bool* /* chained */) { + if (isRootServer(address)) { + setLWResult(res, 0, false, false, true); + addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); + addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); + return LWResult::Result::Success; + } + if (address == ComboAddress("192.0.2.1:53")) { + + if (domain == cnameTargeta) { + setLWResult(res, 0, true, false, false); + addRecordToLW(res, cnameTargeta, QType::CNAME, cnameTargetb.toString()); + return LWResult::Result::Success; + } + if (domain == cnameTargetb) { + setLWResult(res, 0, true, false, false); + addRecordToLW(res, domain, QType::A, "192.0.2.2", DNSResourceRecord::ANSWER, 10); + } + + return LWResult::Result::Success; + } + + return LWResult::Result::Timeout; + }); + + DNSFilterEngine::Policy pol; + pol.d_ttl = 600; + pol.d_kind = DNSFilterEngine::PolicyKind::Custom; + auto customRecord = DNSRecordContent::make(QType::CNAME, QClass::IN, cnameTargeta.toString()); + std::vector> custom = {customRecord}; + pol.setCustom(custom); + std::shared_ptr zone = std::make_shared(); + zone->setName("Unit test policy 0"); + zone->addQNameTrigger(target, std::move(pol)); + auto luaconfsCopy = g_luaconfs.getCopy(); + luaconfsCopy.dfe.clearZones(); + luaconfsCopy.dfe.addZone(zone); + g_luaconfs.setState(luaconfsCopy); + + time_t now = time(nullptr); + + vector ret; + int res = resolver->beginResolve(target, QType(QType::A), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_REQUIRE_EQUAL(ret.size(), 3U); + BOOST_CHECK(ret[0].d_type == QType::CNAME); + BOOST_CHECK_EQUAL(ret[0].d_name, target); + BOOST_CHECK_EQUAL(ret[0].getContent()->getZoneRepresentation(), cnameTargeta.toString()); + BOOST_CHECK(ret[1].d_type == QType::CNAME); + BOOST_CHECK_EQUAL(ret[1].d_name, cnameTargeta); + BOOST_CHECK_EQUAL(ret[1].getContent()->getZoneRepresentation(), cnameTargetb.toString()); + BOOST_CHECK(ret[2].d_type == QType::A); + BOOST_CHECK_EQUAL(ret[2].d_name, cnameTargetb); + BOOST_CHECK_EQUAL(ret[2].getContent()->getZoneRepresentation(), "192.0.2.2"); + + // Let the final record expire. If an RPZ producing a custom CNAME was hit, we used to not follow + // the CNAME as aggressively as needed. The symptom being the final record missing from the + // result. + resolver->setNow(timeval{now + 20, 0}); + resolver->setQNameMinimization(true); // XXX find out why this is needed + + ret.clear(); + resolver->d_appliedPolicy = DNSFilterEngine::Policy(); + res = resolver->beginResolve(target, QType(QType::A), QClass::IN, ret); + BOOST_CHECK_EQUAL(res, RCode::NoError); + BOOST_REQUIRE_EQUAL(ret.size(), 3U); + BOOST_CHECK(ret[0].d_type == QType::CNAME); + BOOST_CHECK_EQUAL(ret[0].d_name, target); + BOOST_CHECK_EQUAL(ret[0].getContent()->getZoneRepresentation(), cnameTargeta.toString()); + BOOST_CHECK(ret[1].d_type == QType::CNAME); + BOOST_CHECK_EQUAL(ret[1].d_name, cnameTargeta); + BOOST_CHECK_EQUAL(ret[1].getContent()->getZoneRepresentation(), cnameTargetb.toString()); + BOOST_CHECK(ret[2].d_type == QType::A); + BOOST_CHECK_EQUAL(ret[2].d_name, cnameTargetb); + BOOST_CHECK_EQUAL(ret[2].getContent()->getZoneRepresentation(), "192.0.2.2"); +} + BOOST_AUTO_TEST_CASE(test_cname_nxdomain) { std::unique_ptr sr; diff -Nru pdns-recursor-5.2.4/test-syncres_cc4.cc pdns-recursor-5.2.6/test-syncres_cc4.cc --- pdns-recursor-5.2.4/test-syncres_cc4.cc 2025-07-17 12:20:08.000000000 +0000 +++ pdns-recursor-5.2.6/test-syncres_cc4.cc 2025-09-25 09:52:40.000000000 +0000 @@ -1908,7 +1908,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds) { std::unique_ptr sr; - initSR(sr, true); + initSR(sr, true, false); setDNSSECValidation(sr, DNSSECMode::ValidateAll); @@ -1968,7 +1968,7 @@ BOOST_CHECK_EQUAL(res, RCode::NoError); BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG); BOOST_REQUIRE_EQUAL(ret.size(), 2U); - BOOST_CHECK_EQUAL(queriesCount, 3U); + BOOST_CHECK_EQUAL(queriesCount, 4U); /* again, to test the cache */ ret.clear(); @@ -1976,7 +1976,7 @@ BOOST_CHECK_EQUAL(res, RCode::NoError); BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG); BOOST_REQUIRE_EQUAL(ret.size(), 2U); - BOOST_CHECK_EQUAL(queriesCount, 3U); + BOOST_CHECK_EQUAL(queriesCount, 4U); /* now we ask directly for the DS */ ret.clear(); @@ -1984,7 +1984,7 @@ BOOST_CHECK_EQUAL(res, RCode::NoError); BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG); BOOST_REQUIRE_EQUAL(ret.size(), 1U); - BOOST_CHECK_EQUAL(queriesCount, 3U); + BOOST_CHECK_EQUAL(queriesCount, 4U); } BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds_direct)