Version in base suite: 4.9.16-0+deb13u1 Base version: pdns_4.9.16-0+deb13u1 Target version: pdns_4.9.17-0+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/pdns/pdns_4.9.16-0+deb13u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/pdns/pdns_4.9.17-0+deb13u1.dsc configure | 20 ++++++++++---------- configure.ac | 2 +- debian/changelog | 7 +++++++ docs/calidns.1 | 2 +- docs/dnsbulktest.1 | 2 +- docs/dnsgram.1 | 2 +- docs/dnspcap2calidns.1 | 2 +- docs/dnspcap2protobuf.1 | 2 +- docs/dnsreplay.1 | 2 +- docs/dnsscan.1 | 2 +- docs/dnsscope.1 | 2 +- docs/dnstcpbench.1 | 2 +- docs/dnswasher.1 | 2 +- docs/dumresp.1 | 2 +- docs/ixfrdist.1 | 2 +- docs/ixfrdist.yml.5 | 2 +- docs/ixplore.1 | 2 +- docs/nproxy.1 | 2 +- docs/nsec3dig.1 | 2 +- docs/pdns_control.1 | 2 +- docs/pdns_notify.1 | 2 +- docs/pdns_server.1 | 2 +- docs/pdnsutil.1 | 2 +- docs/saxfr.1 | 2 +- docs/sdig.1 | 2 +- docs/zone2json.1 | 2 +- docs/zone2ldap.1 | 2 +- docs/zone2sql.1 | 2 +- ext/lmdb-safe/lmdb-safe.cc | 34 +++++++++++++++++----------------- modules/geoipbackend/geoipbackend.cc | 17 ++++++++++++++--- pdns/dnsname.cc | 13 +++++++++---- pdns/iputils.cc | 7 ++++++- pdns/iputils.hh | 9 +++++++-- pdns/misc.cc | 24 ++++++++++++++++++++++++ pdns/misc.hh | 18 ++++++++++++++++++ pdns/test-dnsname_cc.cc | 11 +++++++++++ pdns/test-iputils_hh.cc | 23 +++++++++++++++++++++++ 37 files changed, 172 insertions(+), 63 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpd85xlu6a/pdns_4.9.16-0+deb13u1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpd85xlu6a/pdns_4.9.17-0+deb13u1.dsc: no acceptable signature found diff -Nru pdns-4.9.16/configure pdns-4.9.17/configure --- pdns-4.9.16/configure 2026-06-10 12:57:09.000000000 +0000 +++ pdns-4.9.17/configure 2026-08-05 13:25:02.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 4.9.16. +# Generated by GNU Autoconf 2.71 for pdns 4.9.17. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, @@ -618,8 +618,8 @@ # Identity of this package. PACKAGE_NAME='pdns' PACKAGE_TARNAME='pdns' -PACKAGE_VERSION='4.9.16' -PACKAGE_STRING='pdns 4.9.16' +PACKAGE_VERSION='4.9.17' +PACKAGE_STRING='pdns 4.9.17' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1698,7 +1698,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 4.9.16 to adapt to many kinds of systems. +\`configure' configures pdns 4.9.17 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1769,7 +1769,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pdns 4.9.16:";; + short | recursive ) echo "Configuration of pdns 4.9.17:";; esac cat <<\_ACEOF @@ -2040,7 +2040,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pdns configure 4.9.16 +pdns configure 4.9.17 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2529,7 +2529,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pdns $as_me 4.9.16, which was +It was created by pdns $as_me 4.9.17, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -4027,7 +4027,7 @@ # Define the identity of the package. PACKAGE='pdns' - VERSION='4.9.16' + VERSION='4.9.17' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -32469,7 +32469,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pdns $as_me 4.9.16, which was +This file was extended by pdns $as_me 4.9.17, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -32537,7 +32537,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -pdns config.status 4.9.16 +pdns config.status 4.9.17 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff -Nru pdns-4.9.16/configure.ac pdns-4.9.17/configure.ac --- pdns-4.9.16/configure.ac 2026-06-10 12:56:56.000000000 +0000 +++ pdns-4.9.17/configure.ac 2026-08-05 13:24:54.000000000 +0000 @@ -1,6 +1,6 @@ AC_PREREQ([2.69]) -AC_INIT([pdns], [4.9.16]) +AC_INIT([pdns], [4.9.17]) 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-4.9.16/debian/changelog pdns-4.9.17/debian/changelog --- pdns-4.9.16/debian/changelog 2026-06-16 21:55:19.000000000 +0000 +++ pdns-4.9.17/debian/changelog 2026-08-06 19:04:06.000000000 +0000 @@ -1,3 +1,10 @@ +pdns (4.9.17-0+deb13u1) trixie-security; urgency=medium + + * New upstream version 4.9.17, fixing security issue + CVE-2026-52682 + + -- Chris Hofstaedtler Thu, 06 Aug 2026 21:04:06 +0200 + pdns (4.9.16-0+deb13u1) trixie-security; urgency=medium * New upstream version 4.9.16, fixing security issue diff -Nru pdns-4.9.16/docs/calidns.1 pdns-4.9.17/docs/calidns.1 --- pdns-4.9.16/docs/calidns.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/calidns.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "CALIDNS" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "CALIDNS" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME calidns \- A DNS recursor testing tool .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/dnsbulktest.1 pdns-4.9.17/docs/dnsbulktest.1 --- pdns-4.9.16/docs/dnsbulktest.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/dnsbulktest.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "DNSBULKTEST" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "DNSBULKTEST" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME dnsbulktest \- A debugging tool for intermittent resolver failures .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/dnsgram.1 pdns-4.9.17/docs/dnsgram.1 --- pdns-4.9.16/docs/dnsgram.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/dnsgram.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "DNSGRAM" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "DNSGRAM" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME dnsgram \- A debugging tool for intermittent resolver failures .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/dnspcap2calidns.1 pdns-4.9.17/docs/dnspcap2calidns.1 --- pdns-4.9.16/docs/dnspcap2calidns.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/dnspcap2calidns.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "DNSPCAP2CALIDNS" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "DNSPCAP2CALIDNS" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME dnspcap2calidns \- A tool to convert PCAPs of DNS traffic to calidns input .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/dnspcap2protobuf.1 pdns-4.9.17/docs/dnspcap2protobuf.1 --- pdns-4.9.16/docs/dnspcap2protobuf.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/dnspcap2protobuf.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "DNSPCAP2PROTOBUF" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "DNSPCAP2PROTOBUF" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME dnspcap2protobuf \- A tool to convert PCAPs of DNS traffic to PowerDNS Protobuf .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/dnsreplay.1 pdns-4.9.17/docs/dnsreplay.1 --- pdns-4.9.16/docs/dnsreplay.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/dnsreplay.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "DNSREPLAY" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "DNSREPLAY" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME dnsreplay \- A PowerDNS nameserver debugging tool .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/dnsscan.1 pdns-4.9.17/docs/dnsscan.1 --- pdns-4.9.16/docs/dnsscan.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/dnsscan.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "DNSSCAN" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "DNSSCAN" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME dnsscan \- List the amount of queries per qtype in a pcap .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/dnsscope.1 pdns-4.9.17/docs/dnsscope.1 --- pdns-4.9.16/docs/dnsscope.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/dnsscope.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "DNSSCOPE" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "DNSSCOPE" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME dnsscope \- A PowerDNS nameserver debugging tool .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/dnstcpbench.1 pdns-4.9.17/docs/dnstcpbench.1 --- pdns-4.9.16/docs/dnstcpbench.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/dnstcpbench.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "DNSTCPBENCH" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "DNSTCPBENCH" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME dnstcpbench \- tool to perform TCP benchmarking of nameservers .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/dnswasher.1 pdns-4.9.17/docs/dnswasher.1 --- pdns-4.9.16/docs/dnswasher.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/dnswasher.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "DNSWASHER" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "DNSWASHER" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME dnswasher \- A PowerDNS nameserver debugging tool .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/dumresp.1 pdns-4.9.17/docs/dumresp.1 --- pdns-4.9.16/docs/dumresp.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/dumresp.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "DUMRESP" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "DUMRESP" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME dumresp \- A dumb DNS responder .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/ixfrdist.1 pdns-4.9.17/docs/ixfrdist.1 --- pdns-4.9.16/docs/ixfrdist.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/ixfrdist.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "IXFRDIST" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "IXFRDIST" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME ixfrdist \- An IXFR/AXFR-only server that re-distributes zones .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/ixfrdist.yml.5 pdns-4.9.17/docs/ixfrdist.yml.5 --- pdns-4.9.16/docs/ixfrdist.yml.5 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/ixfrdist.yml.5 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "IXFRDIST.YML" "5" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "IXFRDIST.YML" "5" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME ixfrdist.yml \- The ixfrdist configuration file .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/ixplore.1 pdns-4.9.17/docs/ixplore.1 --- pdns-4.9.16/docs/ixplore.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/ixplore.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "IXPLORE" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "IXPLORE" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME ixplore \- A tool that provides insights into IXFRs .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/nproxy.1 pdns-4.9.17/docs/nproxy.1 --- pdns-4.9.16/docs/nproxy.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/nproxy.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "NPROXY" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "NPROXY" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME nproxy \- DNS notification proxy .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/nsec3dig.1 pdns-4.9.17/docs/nsec3dig.1 --- pdns-4.9.16/docs/nsec3dig.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/nsec3dig.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "NSEC3DIG" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "NSEC3DIG" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME nsec3dig \- Show and validate NSEC3 proofs .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/pdns_control.1 pdns-4.9.17/docs/pdns_control.1 --- pdns-4.9.16/docs/pdns_control.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/pdns_control.1 2026-08-05 13:26:01.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_CONTROL" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "PDNS_CONTROL" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME pdns_control \- Control the PowerDNS nameserver .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/pdns_notify.1 pdns-4.9.17/docs/pdns_notify.1 --- pdns-4.9.16/docs/pdns_notify.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/pdns_notify.1 2026-08-05 13:26:01.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_NOTIFY" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "PDNS_NOTIFY" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME pdns_notify \- A simple DNS NOTIFY sender .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/pdns_server.1 pdns-4.9.17/docs/pdns_server.1 --- pdns-4.9.16/docs/pdns_server.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/pdns_server.1 2026-08-05 13:26:01.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_SERVER" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "PDNS_SERVER" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME pdns_server \- The PowerDNS Authoritative Nameserver .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/pdnsutil.1 pdns-4.9.17/docs/pdnsutil.1 --- pdns-4.9.16/docs/pdnsutil.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/pdnsutil.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "PDNSUTIL" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "PDNSUTIL" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME pdnsutil \- PowerDNS record and DNSSEC command and control .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/saxfr.1 pdns-4.9.17/docs/saxfr.1 --- pdns-4.9.16/docs/saxfr.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/saxfr.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SAXFR" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "SAXFR" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME saxfr \- Perform AXFRs and show information about it .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/sdig.1 pdns-4.9.17/docs/sdig.1 --- pdns-4.9.16/docs/sdig.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/sdig.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "SDIG" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "SDIG" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME sdig \- Perform a DNS query and show the results .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/zone2json.1 pdns-4.9.17/docs/zone2json.1 --- pdns-4.9.16/docs/zone2json.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/zone2json.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "ZONE2JSON" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "ZONE2JSON" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME zone2json \- convert BIND zones to JSON .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/zone2ldap.1 pdns-4.9.17/docs/zone2ldap.1 --- pdns-4.9.16/docs/zone2ldap.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/zone2ldap.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "ZONE2LDAP" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "ZONE2LDAP" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME zone2ldap \- convert zonefiles to ldif .SH SYNOPSIS diff -Nru pdns-4.9.16/docs/zone2sql.1 pdns-4.9.17/docs/zone2sql.1 --- pdns-4.9.16/docs/zone2sql.1 2026-06-10 12:58:16.000000000 +0000 +++ pdns-4.9.17/docs/zone2sql.1 2026-08-05 13:26:01.000000000 +0000 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "ZONE2SQL" "1" "Jun 10, 2026" "" "PowerDNS Authoritative Server" +.TH "ZONE2SQL" "1" "Aug 05, 2026" "" "PowerDNS Authoritative Server" .SH NAME zone2sql \- convert BIND zones to SQL .SH SYNOPSIS diff -Nru pdns-4.9.16/ext/lmdb-safe/lmdb-safe.cc pdns-4.9.17/ext/lmdb-safe/lmdb-safe.cc --- pdns-4.9.16/ext/lmdb-safe/lmdb-safe.cc 2026-06-10 12:56:41.000000000 +0000 +++ pdns-4.9.17/ext/lmdb-safe/lmdb-safe.cc 2026-08-05 13:24:42.000000000 +0000 @@ -263,28 +263,28 @@ void MDBRWTransactionImpl::commit() { closeRORWCursors(); - if (!d_txn) { - return; - } - - if(int rc = mdb_txn_commit(d_txn)) { - throw std::runtime_error("committing: " + std::string(mdb_strerror(rc))); + if (d_txn != nullptr) { + int retCode = mdb_txn_commit(d_txn); + // Upon failure, mdb_txn_commit() performs an mdb_txn_abort() call, + // so we need to consider the transaction aborted and correctly + // deallocated. + d_txn = nullptr; + environment().decRWTX(); + if (retCode != 0) { + throw std::runtime_error("committing: " + std::string(mdb_strerror(retCode))); + } } - environment().decRWTX(); - d_txn = nullptr; } void MDBRWTransactionImpl::abort() { closeRORWCursors(); - if (!d_txn) { - return; + if (d_txn != nullptr) { + mdb_txn_abort(d_txn); + d_txn = nullptr; + // prevent the RO destructor from cleaning up the transaction itself + environment().decRWTX(); } - - mdb_txn_abort(d_txn); - // prevent the RO destructor from cleaning up the transaction itself - environment().decRWTX(); - d_txn = nullptr; } MDBROTransactionImpl::MDBROTransactionImpl(MDBEnv *parent, MDB_txn *txn): @@ -338,7 +338,7 @@ { closeROCursors(); // if d_txn is non-nullptr here, either the transaction object was invalidated earlier (e.g. by moving from it), or it is an RW transaction which has already cleaned up the d_txn pointer (with an abort). - if (d_txn) { + if (d_txn != nullptr) { d_parent->decROTX(); mdb_txn_abort(d_txn); // this appears to work better than abort for r/o database opening d_txn = nullptr; @@ -349,7 +349,7 @@ { closeROCursors(); // if d_txn is non-nullptr here, either the transaction object was invalidated earlier (e.g. by moving from it), or it is an RW transaction which has already cleaned up the d_txn pointer (with an abort). - if (d_txn) { + if (d_txn != nullptr) { d_parent->decROTX(); mdb_txn_commit(d_txn); // this appears to work better than abort for r/o database opening d_txn = nullptr; diff -Nru pdns-4.9.16/modules/geoipbackend/geoipbackend.cc pdns-4.9.17/modules/geoipbackend/geoipbackend.cc --- pdns-4.9.16/modules/geoipbackend/geoipbackend.cc 2026-06-10 12:56:41.000000000 +0000 +++ pdns-4.9.17/modules/geoipbackend/geoipbackend.cc 2026-08-05 13:24:42.000000000 +0000 @@ -1073,9 +1073,20 @@ globfree(&glob_result); pathname.str(""); pathname << getArg("dnssec-keydir") << "/" << dom.domain.toStringNoDot() << "." << key.flags << "." << nextid << "." << (key.active ? "1" : "0") << ".key"; - ofstream ofs(pathname.str().c_str()); - ofs.write(key.content.c_str(), key.content.size()); - ofs.close(); + auto keyFile = pdns::openFileForWriting(pathname.str(), 0600, true, false); + if (!keyFile) { + int error = errno; + g_log << Logger::Error << "Cannot create key file " << pathname.str() << ": " << stringerror(error) << endl; + return false; + } + if (fwrite(key.content.c_str(), 1, key.content.size(), keyFile.get()) != key.content.size()) { + int error = errno; + g_log << Logger::Error << "Cannot write key file " << pathname.str() << ": " << stringerror(error) << endl; + keyFile.reset(); + unlink(pathname.str().c_str()); + return false; + } + keyFile.reset(); id = nextid; return true; } diff -Nru pdns-4.9.16/pdns/dnsname.cc pdns-4.9.17/pdns/dnsname.cc --- pdns-4.9.16/pdns/dnsname.cc 2026-06-10 12:56:41.000000000 +0000 +++ pdns-4.9.17/pdns/dnsname.cc 2026-08-05 13:24:42.000000000 +0000 @@ -127,6 +127,8 @@ size_t DNSName::parsePacketUncompressed(const UnsignedCharView& view, size_t pos, bool uncompress) { const size_t initialPos = pos; + auto existingSize = d_storage.size(); + const size_t neededSizeForFinalLabel = /* final empty label length */ (existingSize == 0 ? 1U : 0U); size_t totalLength = 0; unsigned char labellen = 0; @@ -151,24 +153,27 @@ throw std::range_error("Found an invalid label length in qname (only one of the first two bits is set)"); } checkLabelLength(labellen); - // reserve one byte for the label length - if (totalLength + labellen > s_maxDNSNameLength - 1) { + + // reserve one byte for the label length, plus one byte for the final empty label if we were empty before + if ((existingSize + totalLength + labellen + 1U + neededSizeForFinalLabel) > s_maxDNSNameLength) { throw std::range_error("name too long to append"); } if (pos + labellen >= view.size()) { throw std::range_error("Found an invalid label length in qname"); } pos += labellen; - totalLength += 1 + labellen; + totalLength += 1U + labellen; } while (pos < view.size()); if (totalLength != 0) { - auto existingSize = d_storage.size(); if (existingSize > 0) { // remove the last label count, we are about to override it */ --existingSize; } + if ((existingSize + totalLength + 1U) > s_maxDNSNameLength) { + throw std::range_error("name too long to append"); + } d_storage.reserve(existingSize + totalLength + 1); d_storage.resize(existingSize + totalLength); memcpy(&d_storage.at(existingSize), &view.at(initialPos), totalLength); diff -Nru pdns-4.9.16/pdns/iputils.cc pdns-4.9.17/pdns/iputils.cc --- pdns-4.9.16/pdns/iputils.cc 2026-06-10 12:56:41.000000000 +0000 +++ pdns-4.9.17/pdns/iputils.cc 2026-08-05 13:24:42.000000000 +0000 @@ -358,7 +358,12 @@ memset(start + len - tozero/8, 0, tozero/8); // blot out the whole bytes on the right - auto bitsleft=tozero % 8; // 2 bits left to clear + auto bitsleft = tozero % 8; // 2 bits left to clear + if (bitsleft == 0) { + // the memset() above cleared whole bytes only, and for 0 bits the byte we + // would look at is the one before the address + return; + } // a b c d, to truncate to 22 bits, we just zeroed 'd' and need to zero 2 bits from c // so and by '11111100', which is ~((1<<2)-1) = ~3 diff -Nru pdns-4.9.16/pdns/iputils.hh pdns-4.9.17/pdns/iputils.hh --- pdns-4.9.16/pdns/iputils.hh 2026-06-10 12:56:41.000000000 +0000 +++ pdns-4.9.17/pdns/iputils.hh 2026-08-05 13:24:42.000000000 +0000 @@ -596,8 +596,13 @@ } } // still here, now match remaining bits - uint8_t bits= d_bits % 8; - uint8_t mask= (uint8_t) ~(0xFF>>bits); + uint8_t bits = d_bits % 8; + if (bits == 0) { + // no partial byte left to match, and lhs[index] would be one past the + // address for a /128 + return true; + } + auto mask = static_cast(~(0xFF >> bits)); return((us[n]) == (them[n] & mask)); } diff -Nru pdns-4.9.16/pdns/misc.cc pdns-4.9.17/pdns/misc.cc --- pdns-4.9.16/pdns/misc.cc 2026-06-10 12:56:41.000000000 +0000 +++ pdns-4.9.17/pdns/misc.cc 2026-08-05 13:24:42.000000000 +0000 @@ -1757,4 +1757,28 @@ return std::nullopt; } + +UniqueFilePtr openFileForWriting(const std::string& filePath, mode_t permissions, bool mustNotExist, bool appendIfExists) +{ + int flags = O_WRONLY | O_CREAT; + if (mustNotExist) { + flags |= O_EXCL; + } + else if (appendIfExists) { + flags |= O_APPEND; + } + int fileDesc = open(filePath.c_str(), flags, permissions); + if (fileDesc == -1) { + return UniqueFilePtr(nullptr); + } + auto filePtr = pdns::UniqueFilePtr(fdopen(fileDesc, appendIfExists ? "a" : "w")); + if (!filePtr) { + auto error = errno; + close(fileDesc); + errno = error; + return UniqueFilePtr(nullptr); + } + return filePtr; +} + } diff -Nru pdns-4.9.16/pdns/misc.hh pdns-4.9.17/pdns/misc.hh --- pdns-4.9.16/pdns/misc.hh 2026-06-10 12:56:41.000000000 +0000 +++ pdns-4.9.17/pdns/misc.hh 2026-08-05 13:24:42.000000000 +0000 @@ -836,4 +836,22 @@ namespace pdns { [[nodiscard]] std::optional visit_directory(const std::string& directory, const std::function& visitor); + +struct FilePtrDeleter +{ + /* using a deleter instead of decltype(&fclose) has two big advantages: + - the deleter is included in the type and does not have to be passed + when creating a new object (easier to use, less memory usage, in theory + better inlining) + - we avoid the annoying "ignoring attributes on template argument ‘int (*)(FILE*)’" + warning from the compiler, which is there because fclose is tagged as __nonnull((1)) + */ + void operator()(FILE* filePtr) const noexcept { + fclose(filePtr); + } +}; + +using UniqueFilePtr = std::unique_ptr; + +UniqueFilePtr openFileForWriting(const std::string& filePath, mode_t permissions, bool mustNotExist = true, bool appendIfExists = false); } diff -Nru pdns-4.9.16/pdns/test-dnsname_cc.cc pdns-4.9.17/pdns/test-dnsname_cc.cc --- pdns-4.9.16/pdns/test-dnsname_cc.cc 2026-06-10 12:56:41.000000000 +0000 +++ pdns-4.9.17/pdns/test-dnsname_cc.cc 2026-08-05 13:24:42.000000000 +0000 @@ -847,6 +847,17 @@ BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 0, true), std::range_error); } +BOOST_AUTO_TEST_CASE(test_name_length_too_long_from_wire) { + + string name("\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x05""stats""\x05""stats""\x02""fr""\x00", 256); + BOOST_CHECK_THROW(DNSName(name.c_str(), name.size(), 0, true), std::range_error); +} + +BOOST_AUTO_TEST_CASE(test_name_length_too_long_from_wire_compressed) { + string name("\x0a""wwwwwwwwww""\x00""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x03""www""\x05""stats""\x05""stats""\x02""fr""\xc0""\x00", 265); + BOOST_CHECK_THROW(DNSName(name.c_str(), name.size(), 12, true), std::range_error); +} + BOOST_AUTO_TEST_CASE(test_compression) { // Compression test string name("\x03""com\x00""\x07""example\xc0""\x00""\x03""www\xc0""\x05", 21); diff -Nru pdns-4.9.16/pdns/test-iputils_hh.cc pdns-4.9.17/pdns/test-iputils_hh.cc --- pdns-4.9.16/pdns/test-iputils_hh.cc 2026-06-10 12:56:41.000000000 +0000 +++ pdns-4.9.17/pdns/test-iputils_hh.cc 2026-08-05 13:24:42.000000000 +0000 @@ -144,6 +144,19 @@ ca6.truncate(8); BOOST_CHECK_EQUAL(ca6.toString(), "2000::"); + /* truncating to 0 bits leaves no partial byte, so nothing before the address + may be touched */ + ca4 = ComboAddress("130.161.252.29", 53); + ca4.truncate(0); + BOOST_CHECK_EQUAL(ca4.toString(), "0.0.0.0"); + BOOST_CHECK_EQUAL(ca4.sin4.sin_port, htons(53)); + + ca6 = ComboAddress("2001:888:2000:1d::2", 53); + ca6.sin6.sin6_flowinfo = htonl(0x0badcafe); + ca6.truncate(0); + BOOST_CHECK_EQUAL(ca6.toString(), "::"); + BOOST_CHECK_EQUAL(ca6.sin6.sin6_flowinfo, htonl(0x0badcafe)); + orig=ca6=ComboAddress("2001:888:2000:1d::2"); for(int n=128; n; --n) { @@ -218,6 +231,16 @@ BOOST_CHECK(nmp6.match("fe80::92fb:a6ff:fe4a:51da")); BOOST_CHECK(!nmp6.match("fe81::92fb:a6ff:fe4a:51db")); + /* a /128 leaves no partial byte to compare, so the scope id sitting right + after the address must not be taken into account */ + ComboAddress scoped("fe80::92fb:a6ff:fe4a:51da"); + scoped.sin6.sin6_scope_id = 1; + Netmask nmscoped(scoped); + BOOST_CHECK_EQUAL(nmscoped.getBits(), 128); + BOOST_CHECK(nmscoped.match(scoped)); + BOOST_CHECK(nmscoped.match("fe80::92fb:a6ff:fe4a:51da")); + BOOST_CHECK(!nmscoped.match("fe80::92fb:a6ff:fe4a:51db")); + Netmask all("0.0.0.0/0"); BOOST_CHECK(all.match(local) && all.match(remote));