PDNS_ENABLE_BOTAN
PDNS_CHECK_LIBSODIUM
-AX_CHECK_OPENSSL([
+PDNS_CHECK_LIBCRYPTO([
],[
- AC_MSG_ERROR([OpenSSL not found])
+ AC_MSG_ERROR([OpenSSL/libcrypto not found])
]
)
+PDNS_CHECK_LIBCRYPTO_ECDSA
PDNS_CHECK_RAGEL
PDNS_CHECK_CLOCK_GETTIME
AM_CONDITIONAL([HAVE_BOOST_GE_148], [test "$boost_major_version" -ge 148])
BOOST_PROGRAM_OPTIONS([mt])
+AS_IF([test "$boost_cv_lib_program_options" = "no"], [
+ AC_MSG_ERROR([Boost Program Options library not found])
+])
PDNS_ENABLE_UNIT_TESTS
PDNS_ENABLE_REPRODUCIBLE
AC_MSG_NOTICE([Built-in modules: $modules])
AC_MSG_NOTICE([Dynamic modules: $dynmodules])
AC_MSG_NOTICE([])
-AS_IF([test "x$openssl_ecdsa" = "xyes"],
+AS_IF([test "x$libcrypto_ecdsa" == "xyes"],
[AC_MSG_NOTICE([OpenSSL ecdsa: yes])],
[AC_MSG_NOTICE([OpenSSL ecdsa: no])]
)
: Add a Negative Trust Anchor for *DOMAIN*, suffixed optionally with *REASON*.
add-ta *DOMAIN* *DSRECORD*
-: Add a Trust Anchor for *DOMAIN* with DS record data *DSRECORD*.
+: Add a Trust Anchor for *DOMAIN* with DS record data *DSRECORD*. This adds the
+ new Trust Anchor to the existing set of Trust Anchors for *DOMAIN*.
current-queries
: Shows the currently active queries.
* `tcp6-answers-bytes`: Total number of answer bytes sent over TCPv6 (since 4.0.0)
* `tcp6-answers`: Number of answers sent out over TCPv6
* `tcp6-queries`: Number of questions received over TCPv6
-* `timedout-questions`: Amount of packets that were dropped because they had to wait too long internally
+* `timedout-packets`: Amount of packets that were dropped because they had to wait too long internally
* `udp-answers-bytes`: Total number of answer bytes sent over UDP
* `udp-answers`: Number of answers sent out over UDP
* `udp-do-queries`: Number of queries received with the DO (DNSSEC OK) bit set
**Note**: Beyond PowerDNS 2.9.20, the Authoritative Server and Recursor are released separately.
# PowerDNS Recursor 4.0.1
-UNRELEASED
+Released July 29th 2016
-This release improves interoperability with DNSSEC clients that expect an AD-bit on validated data when they query with only the DO-bit set.
+This release has several improvements with regards to DNSSEC validation and it improves interoperability with DNSSEC clients that expect an AD-bit on validated data when they query with only the DO-bit set.
## Bug fixes
+ - [#4119](https://github.com/PowerDNS/pdns/pull/4119) Improve DNSSEC record skipping for non dnssec queries (Kees Monshouwer)
- [#4162](https://github.com/PowerDNS/pdns/pull/4162) Don't validate zones from the local auth store, go one level down while validating when there is a CNAME
- [#4187](https://github.com/PowerDNS/pdns/pull/4187):
* Don't go bogus on islands of security
* Check all possible chains for Insecures
* Don't go Bogus on a CNAME at the apex
+ - [#4215](https://github.com/PowerDNS/pdns/pull/4215) RPZ: default policy should also override local data RRs
+ - [#4243](https://github.com/PowerDNS/pdns/pull/4243) Fix a crash when the next name in a chained query is empty and `rec_control current-queries` is invoked
## Improvements
+ - [#4056](https://github.com/PowerDNS/pdns/pull/4056) OpenSSL 1.1.0 support (Christian Hofstaedtler)
+ - [#4133](https://github.com/PowerDNS/pdns/pull/4133) Add limits to the size of received {A,I}XFR (CVE-2016-6172)
+ - [#4140](https://github.com/PowerDNS/pdns/pull/4140) Fix warnings with gcc on musl-libc (James Taylor)
- [#4160](https://github.com/PowerDNS/pdns/pull/4160) Also validate on +DO
+ - [#4164](https://github.com/PowerDNS/pdns/pull/4164) Fail to start when the lua-dns-script does not exist
+ - [#4168](https://github.com/PowerDNS/pdns/pull/4168) Add more Netmask methods for Lua (Aki Tuomi)
+ - [#4210](https://github.com/PowerDNS/pdns/pull/4210) Validate DNSSEC for security polling
+ - [#4217](https://github.com/PowerDNS/pdns/pull/4217) Turn on root-nx-trust by default and log-common-errors=off
+ - [#4207](https://github.com/PowerDNS/pdns/pull/4207) Allow for multiple trust anchors per zone
+ - [#4242](https://github.com/PowerDNS/pdns/pull/4242) Fix compilation warning when building without Protobuf
+
+# PowerDNS Authoritative Server 4.0.1
+Released July 29th 2016
+
+This release fixes two small issues and adds a setting to limit AXFR and IXFR sizes, in response to [CVE-2016-6172](http://www.openwall.com/lists/oss-security/2016/07/06/4).
+
+## Bug fixes
+
+ - [#4126](https://github.com/PowerDNS/pdns/pull/4126) Wait for the connection to the carbon server to be established
+ - [#4206](https://github.com/PowerDNS/pdns/pull/4206) Don't try to deallocate empty PG statements
+ - [#4245](https://github.com/PowerDNS/pdns/pull/4245) Send the correct response when queried for an NSEC directly (Kees Monshouwer)
+ - [#4252](https://github.com/PowerDNS/pdns/pull/4252) Don't include bind files if length <= 2 or > sizeof(filename)
+ - [#4255](https://github.com/PowerDNS/pdns/pull/4255) Catch runtime_error when parsing a broken MNAME
+
+## Improvements
+
+ - [#4044](https://github.com/PowerDNS/pdns/pull/4044) Make DNSPacket return a ComboAddress for local and remote (Aki Tuomi)
+ - [#4056](https://github.com/PowerDNS/pdns/pull/4056) OpenSSL 1.1.0 support (Christian Hofstaedtler)
+ - [#4169](https://github.com/PowerDNS/pdns/pull/4169) Fix typos in a logmessage and exception (Christian Hofsteadtler)
+ - [#4183](https://github.com/PowerDNS/pdns/pull/4183) pdnsutil: Remove checking of ctime and always diff the changes (Hannu Ylitalo)
+ - [#4192](https://github.com/PowerDNS/pdns/pull/4192) dnsreplay: Only add Client Subnet stamp when asked
+ - [#4250](https://github.com/PowerDNS/pdns/pull/4250) Use toLogString() for ringAccount (Kees Monshouwer)
+
+## Additions
+
+ - [#4133](https://github.com/PowerDNS/pdns/pull/4133) Add limits to the size of received {A,I}XFR (CVE-2016-6172)
+ - [#4142](https://github.com/PowerDNS/pdns/pull/4142) Add used filedescriptor statistic (Kees Monshouwer)
# PowerDNS Recursor 4.0.0
Released July 11th 2016
To convert an address to human-friendly representation, use `:toString()` or
`:toStringWithPort()`. To get only the port number, use `:getPort()`.
+Other functions that can be called on a ComboAddress are:
+ * `isIpv4` - true if the address is an IPv4 address
+ * `isIpv6` - true if the address is an IPv6 address
+ * `getBits` - the number of bits in the address
+
### DNSName
DNSNames are passed to various functions, and they sport the following methods:
--- /dev/null
+Before upgrading, it is advised to read the [changelog](../changelog.md).
+When upgrading several versions, please read **all** notes applying to the upgrade.
+
+# 4.0.0 to 4.0.1
+Two settings have changed defaults, these new defaults decrease CPU usage:
+
+ - [`root-nx-trust`](settings.md#root-nx-trust) changed from `no` to `yes`
+ - [`log-common-errors`](settings.md#log-common-errors) changed from `yes` to `no`
- Deprecated Backends: authoritative/backend-deprecated.md
- Recursor:
- Introduction: recursor/index.md
+ - Upgrade Notes: recursor/upgrading.md
- Security of the Recursor: recursor/security.md
- DNSSEC in the Recursor: recursor/dnssec.md
- Recursor Statistics: recursor/stats.md
-@ 86400 IN SOA pdns-public-ns1.powerdns.com. pieter\.lexis.powerdns.com. 2016072001 10800 3600 604800 10800
+@ 86400 IN SOA pdns-public-ns1.powerdns.com. pieter\.lexis.powerdns.com. 2016072801 10800 3600 604800 10800
@ 3600 IN NS pdns-public-ns1.powerdns.com.
@ 3600 IN NS pdns-public-ns2.powerdns.com.
; Auth
auth-4.0.0-rc1.security-status 60 IN TXT "2 Unsupported pre-release (no known vulnerabilities). Please upgrade to final, see https://blog.powerdns.com/2016/07/11/powerdns-authoritative-server-4-0-0-released/"
auth-4.0.0-rc2.security-status 60 IN TXT "2 Unsupported pre-release (no known vulnerabilities). Please upgrade to final, see https://blog.powerdns.com/2016/07/11/powerdns-authoritative-server-4-0-0-released/"
auth-4.0.0.security-status 60 IN TXT "1 OK"
+auth-4.0.1.security-status 60 IN TXT "1 OK"
; Auth Debian
auth-3.4.1-2.debian.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/md/security/powerdns-advisory-2015-01/ and https://doc.powerdns.com/md/security/powerdns-advisory-2015-02/"
recursor-4.0.0-beta1.security-status 60 IN TXT "2 Unsupported pre-release (no known vulnerabilities). Please upgrade to final, see https://blog.powerdns.com/2016/07/11/powerdns-recursor-4-0-0-released/"
recursor-4.0.0-rc1.security-status 60 IN TXT "2 Unsupported pre-release (no known vulnerabilities). Please upgrade to final, see https://blog.powerdns.com/2016/07/11/powerdns-recursor-4-0-0-released/"
recursor-4.0.0.security-status 60 IN TXT "1 OK"
+recursor-4.0.1.security-status 60 IN TXT "1 OK"
; Recursor Debian
recursor-3.6.2-2.debian.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/md/security/powerdns-advisory-2015-01/"
-# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_check_openssl.html
-# ===========================================================================
-#
# SYNOPSIS
#
-# AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]])
+# PDNS_CHECK_LIBCRYPTO([action-if-found[, action-if-not-found]])
#
# DESCRIPTION
#
-# Look for OpenSSL in a number of default spots, or in a user-selected
-# spot (via --with-openssl). Sets
+# Look for OpenSSL's libcrypto in a number of default spots, or in a
+# user-selected spot (via --with-libcrypto). Sets
#
-# OPENSSL_INCLUDES to the include directives required
-# OPENSSL_LIBS to the -l directives required
-# OPENSSL_LDFLAGS to the -L or -R flags required
+# LIBCRYPTO_INCLUDES to the include directives required
+# LIBCRYPTO_LIBS to the -l directives required
+# LIBCRYPTO_LDFLAGS to the -L or -R flags required
#
# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately
#
-# This macro sets OPENSSL_INCLUDES such that source files should use the
+# This macro sets LIBCRYPTO_INCLUDES such that source files should use the
# openssl/ directory in include directives:
#
# #include <openssl/hmac.h>
#
# LICENSE
#
+# Taken and modified from AX_CHECK_OPENSSL by:
# Copyright (c) 2009,2010 Zmanda Inc. <http://www.zmanda.com/>
# Copyright (c) 2009,2010 Dustin J. Mitchell <dustin@zmanda.com>
#
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 8 (PowerDNS modified)
+#serial 1
-AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL])
-AC_DEFUN([AX_CHECK_OPENSSL], [
+AU_ALIAS([CHECK_LIBCRYPTO], [PDNS_CHECK_LIBCRYPTO])
+AC_DEFUN([PDNS_CHECK_LIBCRYPTO], [
found=false
- AC_ARG_WITH([openssl],
- [AS_HELP_STRING([--with-openssl=DIR],
+ AC_ARG_WITH([libcrypto],
+ [AS_HELP_STRING([--with-libcrypto=DIR],
[root of the OpenSSL directory])],
[
case "$withval" in
"" | y | ye | yes | n | no)
- AC_MSG_ERROR([Invalid --with-openssl value])
+ AC_MSG_ERROR([Invalid --with-libcrypto value])
;;
*) ssldirs="$withval"
;;
], [
# if pkg-config is installed and openssl has installed a .pc file,
# then use that information and don't search ssldirs
- AC_PATH_PROG([PKG_CONFIG], [pkg-config])
+ AC_CHECK_TOOL([PKG_CONFIG], [pkg-config])
if test x"$PKG_CONFIG" != x""; then
- OPENSSL_LDFLAGS=`$PKG_CONFIG libcrypto --libs-only-L 2>/dev/null`
+ LIBCRYPTO_LDFLAGS=`$PKG_CONFIG libcrypto --libs-only-L 2>/dev/null`
if test $? = 0; then
- OPENSSL_LIBS=`$PKG_CONFIG libcrypto --libs-only-l 2>/dev/null`
- OPENSSL_INCLUDES=`$PKG_CONFIG libcrypto --cflags-only-I 2>/dev/null`
+ LIBCRYPTO_LIBS=`$PKG_CONFIG libcrypto --libs-only-l 2>/dev/null`
+ LIBCRYPTO_INCLUDES=`$PKG_CONFIG libcrypto --cflags-only-I 2>/dev/null`
found=true
fi
fi
# an 'openssl' subdirectory
if ! $found; then
- OPENSSL_INCLUDES=
+ LIBCRYPTO_INCLUDES=
for ssldir in $ssldirs; do
AC_MSG_CHECKING([for openssl/crypto.h in $ssldir])
if test -f "$ssldir/include/openssl/crypto.h"; then
- OPENSSL_INCLUDES="-I$ssldir/include"
- OPENSSL_LDFLAGS="-L$ssldir/lib"
- OPENSSL_LIBS="-lcrypto"
+ LIBCRYPTO_INCLUDES="-I$ssldir/include"
+ LIBCRYPTO_LDFLAGS="-L$ssldir/lib"
+ LIBCRYPTO_LIBS="-lcrypto"
found=true
AC_MSG_RESULT([yes])
break
# try the preprocessor and linker with our new flags,
# being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS
- AC_MSG_CHECKING([whether compiling and linking against OpenSSL works])
- echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \
- "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&AS_MESSAGE_LOG_FD
+ AC_MSG_CHECKING([whether compiling and linking against OpenSSL's libcrypto works])
+ echo "Trying link with LIBCRYPTO_LDFLAGS=$LIBCRYPTO_LDFLAGS;" \
+ "LIBCRYPTO_LIBS=$LIBCRYPTO_LIBS; LIBCRYPTO_INCLUDES=$LIBCRYPTO_INCLUDES" >&AS_MESSAGE_LOG_FD
save_LIBS="$LIBS"
save_LDFLAGS="$LDFLAGS"
save_CPPFLAGS="$CPPFLAGS"
- LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
- LIBS="$OPENSSL_LIBS $LIBS"
- CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
+ LDFLAGS="$LDFLAGS $LIBCRYPTO_LDFLAGS"
+ LIBS="$LIBCRYPTO_LIBS $LIBS"
+ CPPFLAGS="$LIBCRYPTO_INCLUDES $CPPFLAGS"
AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([#include <openssl/crypto.h>], [CRYPTO_free(NULL)])],
+ [AC_LANG_PROGRAM([#include <openssl/crypto.h>], [ERR_load_CRYPTO_strings()])],
[
AC_MSG_RESULT([yes])
- openssl_ecdsa=yes
- AC_CHECK_FUNC(ECDSA_do_sign,
- [
- AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [ : ], [ openssl_ecdsa=no ], [AC_INCLUDES_DEFAULT
-#include <openssl/evp.h>
- ])
- ], [
- openssl_ecdsa=no
- ])
- AS_IF([test "x$openssl_ecdsa" = "xyes"], [
- AC_DEFINE([HAVE_OPENSSL_ECDSA], [1], [define to 1 if OpenSSL ecdsa support is avalable.])
- ])
$1
], [
AC_MSG_RESULT([no])
LDFLAGS="$save_LDFLAGS"
LIBS="$save_LIBS"
- AC_SUBST([OPENSSL_INCLUDES])
- AC_SUBST([OPENSSL_LIBS])
- AC_SUBST([OPENSSL_LDFLAGS])
+ AC_SUBST([LIBCRYPTO_INCLUDES])
+ AC_SUBST([LIBCRYPTO_LIBS])
+ AC_SUBST([LIBCRYPTO_LDFLAGS])
])
--- /dev/null
+AC_DEFUN([PDNS_CHECK_LIBCRYPTO_ECDSA], [
+ AC_REQUIRE([PDNS_CHECK_LIBCRYPTO])
+ libcrypto_ecdsa=yes
+ AC_CHECK_HEADER([openssl/ecdsa.h], [
+ AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [ : ], [
+ libcrypto_ecdsa=no
+ ], [AC_INCLUDES_DEFAULT
+#include <openssl/evp.h>
+ ])
+ ], [
+ libcrypto_ecdsa=no
+ ])
+
+ AS_IF([test "x$libcrypto_ecdsa" = "xyes"], [
+ AC_DEFINE([HAVE_LIBCRYPTO_ECDSA], [1], [define to 1 if OpenSSL ecdsa support is avalable.])
+ ])
+])
AS_IF([test "x$enable_unit_tests" != "xno" || test "x$enable_backend_unit_tests" != "xno"], [
BOOST_TEST([mt])
+ AS_IF([test "$boost_cv_lib_unit_test_framework" = "no"], [
+ AC_MSG_ERROR([Boost Unit Test library not found])
+ ])
])
])
AM_CPPFLAGS += \
-I$(top_srcdir)/ext/json11 \
$(YAHTTP_CFLAGS) \
- $(OPENSSL_CFLAGS) \
+ $(LIBCRYPTO_CFLAGS) \
$(LIBZMQ_CFLAGS)
AM_LDFLAGS = $(THREADFLAGS)
libtestremotebackend_la_LIBADD = \
$(YAHTTP_LIBS) \
- $(OPENSSL_LIBS) \
+ $(LIBCRYPTO_LIBS) \
$(BOOST_UNIT_TEST_FRAMEWORK_LIBS) \
$(BOOST_PROGRAM_OPTIONS_LIBS) \
$(LIBDL) $(JSON11_LIBS)
-I$(top_srcdir)/ext/json11 \
$(YAHTTP_CFLAGS) \
$(LIBEDIT_CFLAGS) \
- $(OPENSSL_INCLUDES) \
+ $(LIBCRYPTO_INCLUDES) \
$(SYSTEMD_CFLAGS)
AM_CXXFLAGS = \
pdns_server_LDFLAGS = \
$(AM_LDFLAGS) \
$(DYNLINKFLAGS) \
- $(OPENSSL_LDFLAGS)
+ $(LIBCRYPTO_LDFLAGS)
pdns_server_LDADD = \
@moduleobjects@ \
$(LIBDL) \
$(YAHTTP_LIBS) \
$(JSON11_LIBS) \
- $(OPENSSL_LIBS) \
+ $(LIBCRYPTO_LIBS) \
$(SYSTEMD_LIBS)
if BOTAN110
$(AM_LDFLAGS) \
$(DYNLINKFLAGS) \
$(BOOST_PROGRAM_OPTIONS_LDFLAGS) \
- $(OPENSSL_LDFLAGS)
+ $(LIBCRYPTO_LDFLAGS)
pdnsutil_LDADD = \
@moduleobjects@ \
$(JSON11_LIBS) \
$(LIBDL) \
$(BOOST_PROGRAM_OPTIONS_LIBS) \
- $(OPENSSL_LIBS)
+ $(LIBCRYPTO_LIBS)
if BOTAN110
pdnsutil_SOURCES += botan110signers.cc
zone2sql.cc \
zoneparser-tng.cc
-zone2sql_LDADD = $(OPENSSL_LIBS) $(JSON11_LIBS)
-zone2sql_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS)
+zone2sql_LDADD = $(LIBCRYPTO_LIBS) $(JSON11_LIBS)
+zone2sql_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS)
zone2json_SOURCES = \
arguments.cc \
zone2json.cc \
zoneparser-tng.cc
-zone2json_LDADD = $(OPENSSL_LIBS) $(JSON11_LIBS)
-zone2json_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS)
+zone2json_LDADD = $(LIBCRYPTO_LIBS) $(JSON11_LIBS)
+zone2json_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS)
# pkglib_LTLIBRARIES = iputils.la
# iputils_la_SOURCES = lua-iputils.cc
zone2ldap.cc \
zoneparser-tng.cc
-zone2ldap_LDADD = $(OPENSSL_LIBS)
-zone2ldap_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS)
+zone2ldap_LDADD = $(LIBCRYPTO_LIBS)
+zone2ldap_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS)
sdig_SOURCES = \
base32.cc \
statbag.cc \
unix_utility.cc
-sdig_LDADD = $(OPENSSL_LIBS)
-sdig_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS)
+sdig_LDADD = $(LIBCRYPTO_LIBS)
+sdig_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS)
calidns_SOURCES = \
base32.cc \
statbag.cc \
unix_utility.cc
-calidns_LDADD = $(OPENSSL_LIBS)
-calidns_LDFLAGS = $(AM_LDFLAGS) $(THREADFLAGS) $(OPENSSL_LDFLAGS)
+calidns_LDADD = $(LIBCRYPTO_LIBS)
+calidns_LDFLAGS = $(AM_LDFLAGS) $(THREADFLAGS) $(LIBCRYPTO_LDFLAGS)
dumresp_SOURCES = \
dnslabeltext.cc \
stubquery.cc \
unix_utility.cc
-stubquery_LDADD = $(OPENSSL_LIBS)
-stubquery_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS)
+stubquery_LDADD = $(LIBCRYPTO_LIBS)
+stubquery_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS)
saxfr_SOURCES = \
base32.cc \
statbag.cc \
unix_utility.cc
-saxfr_LDADD = $(OPENSSL_LIBS)
-saxfr_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS)
+saxfr_LDADD = $(LIBCRYPTO_LIBS)
+saxfr_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS)
if PKCS11
saxfr_SOURCES += pkcs11signers.cc pkcs11signers.hh
statbag.cc \
unix_utility.cc zoneparser-tng.cc
-ixplore_LDADD = $(OPENSSL_LIBS)
-ixplore_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS)
+ixplore_LDADD = $(LIBCRYPTO_LIBS)
+ixplore_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS)
if PKCS11
ixplore_SOURCES += pkcs11signers.cc pkcs11signers.hh
dnstcpbench_LDFLAGS = \
$(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS) \
+ $(LIBCRYPTO_LDFLAGS) \
$(BOOST_PROGRAM_OPTIONS_LDFLAGS)
dnstcpbench_LDADD = \
- $(OPENSSL_LIBS) \
+ $(LIBCRYPTO_LIBS) \
$(BOOST_PROGRAM_OPTIONS_LIBS)
nsec3dig_SOURCES = \
statbag.cc \
unix_utility.cc
-nsec3dig_LDADD = $(OPENSSL_LIBS)
-nsec3dig_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS)
+nsec3dig_LDADD = $(LIBCRYPTO_LIBS)
+nsec3dig_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS)
if PKCS11
nsec3dig_SOURCES += pkcs11signers.cc pkcs11signers.hh
toysdig_LDFLAGS = $(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS)
-toysdig_LDADD = $(OPENSSL_LIBS)
+ $(LIBCRYPTO_LDFLAGS)
+toysdig_LDADD = $(LIBCRYPTO_LIBS)
if GSS_TSIG
toysdig_LDADD += $(GSS_LIBS)
tsig-tests.cc \
unix_utility.cc
-tsig_tests_LDADD = $(OPENSSL_LIBS)
-tsig_tests_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS)
+tsig_tests_LDADD = $(LIBCRYPTO_LIBS)
+tsig_tests_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS)
if PKCS11
tsig_tests_SOURCES += pkcs11signers.cc pkcs11signers.hh
statbag.cc \
unix_utility.cc
-speedtest_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS)
-speedtest_LDADD = $(OPENSSL_LIBS) \
+speedtest_LDFLAGS = $(AM_LDFLAGS) $(LIBCRYPTO_LDFLAGS)
+speedtest_LDADD = $(LIBCRYPTO_LIBS) \
$(RT_LIBS)
dnswasher_SOURCES = \
dnsbulktest_LDFLAGS = \
$(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS) \
+ $(LIBCRYPTO_LDFLAGS) \
$(BOOST_PROGRAM_OPTIONS_LDFLAGS)
dnsbulktest_LDADD = \
- $(OPENSSL_LIBS) \
+ $(LIBCRYPTO_LIBS) \
$(BOOST_PROGRAM_OPTIONS_LIBS)
comfun_SOURCES = \
comfun_LDFLAGS = \
$(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS) \
+ $(LIBCRYPTO_LDFLAGS) \
$(BOOST_PROGRAM_OPTIONS_LDFLAGS)
comfun_LDADD = \
- $(OPENSSL_LIBS) \
+ $(LIBCRYPTO_LIBS) \
$(BOOST_PROGRAM_OPTIONS_LIBS)
dnsscan_LDFLAGS = \
$(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS)
+ $(LIBCRYPTO_LDFLAGS)
-dnsscan_LDADD = $(OPENSSL_LIBS)
+dnsscan_LDADD = $(LIBCRYPTO_LIBS)
dnsreplay_SOURCES = \
anadns.hh \
dnsreplay_LDFLAGS = \
$(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS) \
+ $(LIBCRYPTO_LDFLAGS) \
$(BOOST_PROGRAM_OPTIONS_LDFLAGS)
dnsreplay_LDADD = \
- $(OPENSSL_LIBS) \
+ $(LIBCRYPTO_LIBS) \
$(BOOST_PROGRAM_OPTIONS_LIBS)
nproxy_SOURCES = \
nproxy_LDFLAGS = \
$(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS) \
+ $(LIBCRYPTO_LDFLAGS) \
$(BOOST_PROGRAM_OPTIONS_LDFLAGS)
nproxy_LDADD = \
- $(OPENSSL_LIBS) \
+ $(LIBCRYPTO_LIBS) \
$(BOOST_PROGRAM_OPTIONS_LIBS)
pdns_notify_SOURCES = \
pdns_notify_LDFLAGS = \
$(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS) \
+ $(LIBCRYPTO_LDFLAGS) \
$(BOOST_PROGRAM_OPTIONS_LDFLAGS)
pdns_notify_LDADD = \
- $(OPENSSL_LIBS) \
+ $(LIBCRYPTO_LIBS) \
$(BOOST_PROGRAM_OPTIONS_LIBS)
dnsscope_SOURCES = \
dnsscope_LDFLAGS = \
$(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS) \
+ $(LIBCRYPTO_LDFLAGS) \
$(BOOST_PROGRAM_OPTIONS_LDFLAGS)
dnsscope_LDADD = \
- $(OPENSSL_LIBS) \
+ $(LIBCRYPTO_LIBS) \
$(BOOST_PROGRAM_OPTIONS_LIBS)
dnsgram_SOURCES = \
dnsgram_LDFLAGS = \
$(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS)
+ $(LIBCRYPTO_LDFLAGS)
dnsgram_LDADD = \
- $(OPENSSL_LIBS)
+ $(LIBCRYPTO_LIBS)
dnsdemog_SOURCES = \
base32.cc \
dnsdemog_LDFLAGS = \
$(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS)
+ $(LIBCRYPTO_LDFLAGS)
dnsdemog_LDADD = \
- $(OPENSSL_LIBS)
+ $(LIBCRYPTO_LIBS)
if HAVE_PROTOBUF
if HAVE_PROTOC
dnspcap2protobuf_LDFLAGS = \
$(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS) \
+ $(LIBCRYPTO_LDFLAGS) \
$(BOOST_PROGRAM_OPTIONS_LDFLAGS)
dnspcap2protobuf_LDADD = \
- $(OPENSSL_LIBS) \
+ $(LIBCRYPTO_LIBS) \
$(PROTOBUF_LIBS) \
$(BOOST_PROGRAM_OPTIONS_LIBS)
endif
testrunner_LDFLAGS = \
$(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS) \
+ $(LIBCRYPTO_LDFLAGS) \
$(BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS)
testrunner_LDADD = \
- $(OPENSSL_LIBS) \
+ $(LIBCRYPTO_LIBS) \
$(BOOST_UNIT_TEST_FRAMEWORK_LIBS) \
$(RT_LIBS) \
$(LIBDL)
char filename[1024];
if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
{
- fprintf( stderr, "Includes nested too deeply" );
+ fprintf( stderr, "Includes nested too deeply\n" );
exit( 1 );
}
+ if (strlen(yytext) <= 2) {
+ fprintf( stderr, "Empty include directive\n" );
+ exit( 1 );
+ }
+
yytext[strlen(yytext)-2]=0;
include_stack[include_stack_ptr]=YY_CURRENT_BUFFER;
include_stack_name[include_stack_ptr]=current_filename=strdup(yytext+1);
include_stack_ln[include_stack_ptr++]=linenumber;
linenumber=1;
- if(*(yytext+1)=='/')
+
+ if(*(yytext+1)=='/') {
+ if (strlen(yytext+1) >= sizeof(filename)) {
+ fprintf( stderr, "Filename '%s' is too long\n",yytext+1);
+ exit( 1 );
+ }
strcpy(filename,yytext+1);
+ }
else {
+ size_t bind_directory_len = strlen(bind_directory);
+ if (bind_directory_len >= sizeof(filename) ||
+ strlen(yytext+1) + 2 >= sizeof(filename) - bind_directory_len) {
+ fprintf( stderr, "Filename '%s' is too long\n",yytext+1);
+ exit( 1 );
+ }
strcpy(filename,bind_directory);
strcat(filename,"/");
strcat(filename,yytext+1);
}
+ filename[sizeof(filename)-1]='\0';
- if (*yytext &&!(yyin=fopen(filename,"r"))) {
+ if (!(yyin=fopen(filename,"r"))) {
fprintf( stderr, "Unable to open '%s': %s\n",filename,strerror(errno));
exit( 1 );
}
if(P->d.qr)
continue;
- S.ringAccount("queries", P->qdomain.toString()+"/"+P->qtype.getName());
+ S.ringAccount("queries", P->qdomain.toLogString()+"/"+P->qtype.getName());
S.ringAccount("remotes",P->d_remote);
if(logDNSQueries) {
string remote;
a->setRcode(RCode::ServFail);
S.inc("servfail-packets");
- S.ringAccount("servfail-queries",QD->Q->qdomain.toString());
+ S.ringAccount("servfail-queries",QD->Q->qdomain.toLogString());
delete QD->Q;
} else {
a->setRcode(RCode::ServFail);
S.inc("servfail-packets");
- S.ringAccount("servfail-queries",QD->Q->qdomain.toString());
+ S.ringAccount("servfail-queries",QD->Q->qdomain.toLogString());
delete QD->Q;
} else {
a->setRcode(RCode::ServFail);
S.inc("servfail-packets");
- S.ringAccount("servfail-queries",q->qdomain.toString());
+ S.ringAccount("servfail-queries",q->qdomain.toLogString());
} else {
L<<Logger::Error<<"Backend error (retry once): "<<e.reason<<endl;
goto retry;
a->setRcode(RCode::ServFail);
S.inc("servfail-packets");
- S.ringAccount("servfail-queries",q->qdomain.toString());
+ S.ringAccount("servfail-queries",q->qdomain.toLogString());
} else {
L<<Logger::Error<<"Caught unknown exception in Distributor thread "<<(unsigned long)pthread_self()<<" (retry once)"<<endl;
goto retry;
#include "config.h"
#endif
#include <openssl/aes.h>
+#if OPENSSL_VERSION_NUMBER > 0x1000100fL
+// Older OpenSSL does not have CRYPTO_ctr128_encrypt. Before 1.1.0 the header
+// file did not have the necessary extern "C" wrapper. In 1.1.0, AES_ctr128_encrypt
+// was removed.
+#include <openssl/modes.h>
+#endif
#include <iostream>
#include <cstdlib>
#include <cstring>
if(!g_initialized)
abort();
uint32_t out;
+#if OPENSSL_VERSION_NUMBER > 0x1000100fL
+ CRYPTO_ctr128_encrypt((const unsigned char*)&g_in, (unsigned char*) &out, sizeof(g_in), &aes_key, g_counter, g_stream, &g_offset, (block128_f) AES_encrypt);
+#else
AES_ctr128_encrypt((const unsigned char*)&g_in, (unsigned char*) &out, sizeof(g_in), &aes_key, g_counter, g_stream, &g_offset);
+#endif
return out % n;
}
)
BOOST_REQUIRE([$boost_required_version])
-BOOST_FOREACH
PDNS_ENABLE_UNIT_TESTS
PDNS_CHECK_RE2
unsigned int udiffSign= dt.udiff()/100, udiffVerify;
dckeVerify->fromPublicKeyString(dckeSign->getPublicKeyString());
-
+ if (dckeVerify->getPublicKeyString().compare(dckeSign->getPublicKeyString())) {
+ throw runtime_error("Comparison of public key loaded into verifier produced by signer failed");
+ }
dt.set();
if(dckeVerify->verify(message, signature)) {
udiffVerify = dt.udiff();
#include "config.h"
#endif
#include <openssl/obj_mac.h>
-#ifdef HAVE_OPENSSL_ECDSA
+#ifdef HAVE_LIBCRYPTO_ECDSA
#include <openssl/ecdsa.h>
#endif
#include <openssl/sha.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
+#include <openssl/opensslv.h>
#include "opensslsigners.hh"
#include "dnssecinfra.hh"
-
-/* pthread locking */
-
+#if OPENSSL_VERSION_NUMBER < 0x1010000fL
+/* OpenSSL < 1.1.0 needs support for threading/locking in the calling application. */
static pthread_mutex_t *openssllocks;
extern "C" {
OPENSSL_free(openssllocks);
}
+/* compat helpers. These DO NOT do any of the checking that the libssl 1.1 functions do. */
+static inline void RSA_get0_key(const RSA* rsakey, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d) {
+ *n = rsakey->n;
+ *e = rsakey->e;
+ *d = rsakey->d;
+}
+
+static inline int RSA_set0_key(RSA* rsakey, BIGNUM* n, BIGNUM* e, BIGNUM* d) {
+ if (n) {
+ BN_clear_free(rsakey->n);
+ rsakey->n = n;
+ }
+ if (e) {
+ BN_clear_free(rsakey->e);
+ rsakey->e = e;
+ }
+ if (d) {
+ BN_clear_free(rsakey->d);
+ rsakey->d = d;
+ }
+ return 1;
+}
+
+static inline void RSA_get0_factors(const RSA* rsakey, const BIGNUM** p, const BIGNUM** q) {
+ *p = rsakey->p;
+ *q = rsakey->q;
+}
+
+static inline int RSA_set0_factors(RSA* rsakey, BIGNUM* p, BIGNUM* q) {
+ BN_clear_free(rsakey->p);
+ rsakey->p = p;
+ BN_clear_free(rsakey->q);
+ rsakey->q = q;
+ return 1;
+}
+
+static inline void RSA_get0_crt_params(const RSA* rsakey, const BIGNUM** dmp1, const BIGNUM** dmq1, const BIGNUM** iqmp) {
+ *dmp1 = rsakey->dmp1;
+ *dmq1 = rsakey->dmq1;
+ *iqmp = rsakey->iqmp;
+}
+
+static inline int RSA_set0_crt_params(RSA* rsakey, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp) {
+ BN_clear_free(rsakey->dmp1);
+ rsakey->dmp1 = dmp1;
+ BN_clear_free(rsakey->dmq1);
+ rsakey->dmq1 = dmq1;
+ BN_clear_free(rsakey->iqmp);
+ rsakey->iqmp = iqmp;
+ return 1;
+}
+
+static inline void ECDSA_SIG_get0(const ECDSA_SIG* signature, const BIGNUM** pr, const BIGNUM** ps) {
+ *pr = signature->r;
+ *ps = signature->s;
+}
+
+static inline int ECDSA_SIG_set0(ECDSA_SIG* signature, BIGNUM* pr, BIGNUM* ps) {
+ BN_clear_free(signature->r);
+ BN_clear_free(signature->s);
+ signature->r = pr;
+ signature->s = ps;
+ return 1;
+}
+#else
+void openssl_thread_setup() {}
+void openssl_thread_cleanup() {}
+#endif
+
/* seeding PRNG */
RSA_free(d_key);
}
- string getName() const { return "OpenSSL RSA"; }
- int getBits() const { return RSA_size(d_key) << 3; }
+ string getName() const override { return "OpenSSL RSA"; }
+ int getBits() const override { return RSA_size(d_key) << 3; }
- void create(unsigned int bits);
- storvector_t convertToISCVector() const;
- std::string hash(const std::string& hash) const;
- std::string sign(const std::string& hash) const;
- bool verify(const std::string& hash, const std::string& signature) const;
- std::string getPubKeyHash() const;
- std::string getPublicKeyString() const;
- void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap);
- void fromPublicKeyString(const std::string& content);
+ void create(unsigned int bits) override;
+ storvector_t convertToISCVector() const override;
+ std::string hash(const std::string& hash) const override;
+ std::string sign(const std::string& hash) const override;
+ bool verify(const std::string& hash, const std::string& signature) const override;
+ std::string getPubKeyHash() const override;
+ std::string getPublicKeyString() const override;
+ void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
+ void fromPublicKeyString(const std::string& content) override;
bool checkKey() const override;
static DNSCryptoKeyEngine* maker(unsigned int algorithm)
storvector_t storvect;
typedef vector<pair<string, const BIGNUM*> > outputs_t;
outputs_t outputs;
- outputs.push_back(make_pair("Modulus", d_key->n));
- outputs.push_back(make_pair("PublicExponent",d_key->e));
- outputs.push_back(make_pair("PrivateExponent",d_key->d));
- outputs.push_back(make_pair("Prime1",d_key->p));
- outputs.push_back(make_pair("Prime2",d_key->q));
- outputs.push_back(make_pair("Exponent1",d_key->dmp1));
- outputs.push_back(make_pair("Exponent2",d_key->dmq1));
- outputs.push_back(make_pair("Coefficient",d_key->iqmp));
+ const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
+ RSA_get0_key(d_key, &n, &e, &d);
+ RSA_get0_factors(d_key, &p, &q);
+ RSA_get0_crt_params(d_key, &dmp1, &dmq1, &iqmp);
+ outputs.push_back(make_pair("Modulus", n));
+ outputs.push_back(make_pair("PublicExponent", e));
+ outputs.push_back(make_pair("PrivateExponent", d));
+ outputs.push_back(make_pair("Prime1", p));
+ outputs.push_back(make_pair("Prime2", q));
+ outputs.push_back(make_pair("Exponent1", dmp1));
+ outputs.push_back(make_pair("Exponent2", dmq1));
+ outputs.push_back(make_pair("Coefficient", iqmp));
string algorithm=std::to_string(d_algorithm);
switch(d_algorithm) {
std::string OpenSSLRSADNSCryptoKeyEngine::getPubKeyHash() const
{
- unsigned char tmp[std::max(BN_num_bytes(d_key->e), BN_num_bytes(d_key->n))];
+ const BIGNUM *n, *e, *d;
+ RSA_get0_key(d_key, &n, &e, &d);
+ unsigned char tmp[std::max(BN_num_bytes(e), BN_num_bytes(n))];
unsigned char hash[SHA_DIGEST_LENGTH];
SHA_CTX ctx;
throw runtime_error(getName()+" failed to init hash context for generating the public key hash");
}
- int len = BN_bn2bin(d_key->e, tmp);
+ int len = BN_bn2bin(e, tmp);
res = SHA1_Update(&ctx, tmp, len);
if (res != 1) {
throw runtime_error(getName()+" failed to update hash context for generating the public key hash");
}
- len = BN_bn2bin(d_key->n, tmp);
+ len = BN_bn2bin(n, tmp);
res = SHA1_Update(&ctx, tmp, len);
if (res != 1) {
throw runtime_error(getName()+" failed to update hash context for generating the public key hash");
std::string OpenSSLRSADNSCryptoKeyEngine::getPublicKeyString() const
{
+ const BIGNUM *n, *e, *d;
+ RSA_get0_key(d_key, &n, &e, &d);
string keystring;
- unsigned char tmp[std::max(BN_num_bytes(d_key->e), BN_num_bytes(d_key->n))];
+ unsigned char tmp[std::max(BN_num_bytes(e), BN_num_bytes(n))];
- int len = BN_bn2bin(d_key->e, tmp);
+ int len = BN_bn2bin(e, tmp);
if (len < 255) {
keystring.assign(1, (char) (unsigned int) len);
} else {
}
keystring.append((char *) tmp, len);
- len = BN_bn2bin(d_key->n, tmp);
+ len = BN_bn2bin(n, tmp);
keystring.append((char *) tmp, len);
return keystring;
throw runtime_error(getName()+" allocation of key structure failed");
}
- places["Modulus"]=&key->n;
- places["PublicExponent"]=&key->e;
- places["PrivateExponent"]=&key->d;
- places["Prime1"]=&key->p;
- places["Prime2"]=&key->q;
- places["Exponent1"]=&key->dmp1;
- places["Exponent2"]=&key->dmq1;
- places["Coefficient"]=&key->iqmp;
+ BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
+ n = BN_new();
+ if (n == NULL) {
+ RSA_free(key);
+ throw runtime_error(getName()+" allocation of BIGNUM n failed");
+ }
+ e = BN_new();
+ if (e == NULL) {
+ RSA_free(key);
+ BN_clear_free(n);
+ throw runtime_error(getName()+" allocation of BIGNUM e failed");
+ }
+ d = BN_new();
+ if (d == NULL) {
+ RSA_free(key);
+ BN_clear_free(n);
+ BN_clear_free(e);
+ throw runtime_error(getName()+" allocation of BIGNUM d failed");
+ }
+ RSA_set0_key(key, n, e, d);
+
+ p = BN_new();
+ if (p == NULL) {
+ RSA_free(key);
+ throw runtime_error(getName()+" allocation of BIGNUM p failed");
+ }
+ q = BN_new();
+ if (q == NULL) {
+ RSA_free(key);
+ BN_clear_free(p);
+ throw runtime_error(getName()+" allocation of BIGNUM q failed");
+ }
+ RSA_set0_factors(key, p, q);
+
+ dmp1 = BN_new();
+ if (dmp1 == NULL) {
+ RSA_free(key);
+ throw runtime_error(getName()+" allocation of BIGNUM dmp1 failed");
+ }
+ dmq1 = BN_new();
+ if (dmq1 == NULL) {
+ RSA_free(key);
+ BN_clear_free(dmp1);
+ throw runtime_error(getName()+" allocation of BIGNUM dmq1 failed");
+ }
+ iqmp = BN_new();
+ if (iqmp == NULL) {
+ RSA_free(key);
+ BN_clear_free(dmq1);
+ BN_clear_free(iqmp);
+ throw runtime_error(getName()+" allocation of BIGNUM iqmp failed");
+ }
+ RSA_set0_crt_params(key, dmp1, dmq1, iqmp);
+
+ places["Modulus"]=&n;
+ places["PublicExponent"]=&e;
+ places["PrivateExponent"]=&d;
+ places["Prime1"]=&p;
+ places["Prime2"]=&q;
+ places["Exponent1"]=&dmp1;
+ places["Exponent2"]=&dmq1;
+ places["Coefficient"]=&iqmp;
drc.d_algorithm = pdns_stou(stormap["algorithm"]);
if (!val.second)
continue;
- if (*val.second)
- BN_clear_free(*val.second);
-
- *val.second = BN_bin2bn((unsigned char*) raw.c_str(), raw.length(), NULL);
+ *val.second = BN_bin2bn((unsigned char*) raw.c_str(), raw.length(), *val.second);
if (!*val.second) {
RSA_free(key);
throw runtime_error(getName()+" error loading " + val.first);
throw runtime_error(getName()+" allocation of key structure failed");
}
- key->e = BN_bin2bn((unsigned char*)exponent.c_str(), exponent.length(), NULL);
- if (!key->e) {
+ BIGNUM *e = BN_bin2bn((unsigned char*)exponent.c_str(), exponent.length(), NULL);
+ if (!e) {
RSA_free(key);
throw runtime_error(getName()+" error loading e value of public key");
}
- key->n = BN_bin2bn((unsigned char*)modulus.c_str(), modulus.length(), NULL);
- if (!key->n) {
+ BIGNUM *n = BN_bin2bn((unsigned char*)modulus.c_str(), modulus.length(), NULL);
+ if (!n) {
RSA_free(key);
throw runtime_error(getName()+" error loading n value of public key");
}
if (d_key)
RSA_free(d_key);
+ RSA_set0_key(key, n, e, NULL);
d_key = key;
}
-#ifdef HAVE_OPENSSL_ECDSA
+#ifdef HAVE_LIBCRYPTO_ECDSA
class OpenSSLECDSADNSCryptoKeyEngine : public DNSCryptoKeyEngine
{
public:
BN_CTX_free(d_ctx);
}
- string getName() const { return "OpenSSL ECDSA"; }
- int getBits() const { return d_len << 3; }
+ string getName() const override { return "OpenSSL ECDSA"; }
+ int getBits() const override { return d_len << 3; }
- void create(unsigned int bits);
- storvector_t convertToISCVector() const;
- std::string hash(const std::string& hash) const;
- std::string sign(const std::string& hash) const;
- bool verify(const std::string& hash, const std::string& signature) const;
- std::string getPubKeyHash() const;
- std::string getPublicKeyString() const;
- void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap);
- void fromPublicKeyString(const std::string& content);
+ void create(unsigned int bits) override;
+ storvector_t convertToISCVector() const override;
+ std::string hash(const std::string& hash) const override;
+ std::string sign(const std::string& hash) const override;
+ bool verify(const std::string& hash, const std::string& signature) const override;
+ std::string getPubKeyHash() const override;
+ std::string getPublicKeyString() const override;
+ void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
+ void fromPublicKeyString(const std::string& content) override;
bool checkKey() const override;
static DNSCryptoKeyEngine* maker(unsigned int algorithm)
string ret;
unsigned char tmp[d_len];
- int len = BN_bn2bin(signature->r, tmp);
+ const BIGNUM *pr, *ps;
+ ECDSA_SIG_get0(signature, &pr, &ps);
+ int len = BN_bn2bin(pr, tmp);
if (d_len - len)
ret.append(d_len - len, 0x00);
ret.append(string((char*) tmp, len));
- len = BN_bn2bin(signature->s, tmp);
+ len = BN_bn2bin(ps, tmp);
if (d_len - len)
ret.append(d_len - len, 0x00);
ret.append(string((char*) tmp, len));
throw runtime_error(getName()+" allocation of signature structure failed");
}
- sig->r = BN_bin2bn((unsigned char*) signature.c_str(), d_len, sig->r);
- sig->s = BN_bin2bn((unsigned char*) signature.c_str() + d_len, d_len, sig->s);
- if (!sig->r || !sig->s) {
+ BIGNUM *r, *s;
+ r = BN_bin2bn((unsigned char*) signature.c_str(), d_len, NULL);
+ s = BN_bin2bn((unsigned char*) signature.c_str() + d_len, d_len, NULL);
+ if (!r || !s) {
+ if (r) {
+ BN_clear_free(r);
+ }
+ if (s) {
+ BN_clear_free(s);
+ }
ECDSA_SIG_free(sig);
throw runtime_error(getName()+" invalid signature");
}
+ ECDSA_SIG_set0(sig, r, s);
int ret = ECDSA_do_verify((unsigned char*) hash.c_str(), hash.length(), sig, d_eckey);
ECDSA_SIG_free(sig);
DNSCryptoKeyEngine::report(7, &OpenSSLRSADNSCryptoKeyEngine::maker);
DNSCryptoKeyEngine::report(8, &OpenSSLRSADNSCryptoKeyEngine::maker);
DNSCryptoKeyEngine::report(10, &OpenSSLRSADNSCryptoKeyEngine::maker);
-#ifdef HAVE_OPENSSL_ECDSA
+#ifdef HAVE_LIBCRYPTO_ECDSA
DNSCryptoKeyEngine::report(13, &OpenSSLECDSADNSCryptoKeyEngine::maker);
DNSCryptoKeyEngine::report(14, &OpenSSLECDSADNSCryptoKeyEngine::maker);
#endif
DNSName before,after;
sd.db->getBeforeAndAfterNames(sd.domain_id, auth, target, before, after);
- emitNSEC(r, sd, before, after, mode);
+ if (mode != 5 || before == target)
+ emitNSEC(r, sd, before, after, mode);
if (mode == 2 || mode == 4) {
// wildcard NO-DATA or wildcard denial
int PacketHandler::trySuperMasterSynchronous(DNSPacket *p, const DNSName& tsigkeyname)
{
+ string remote = p->getRemote().toString();
+ if(p->hasEDNSSubnet() && ::arg().contains("trusted-notification-proxy", remote)) {
+ remote = p->getRealRemote().toStringNoMask();
+ }
+
Resolver::res_t nsset;
try {
Resolver resolver;
uint32_t theirserial;
- resolver.getSoaSerial(p->getRemote().toString(),p->qdomain, &theirserial);
- resolver.resolve(p->getRemote().toString(), p->qdomain, QType::NS, &nsset);
+ resolver.getSoaSerial(remote,p->qdomain, &theirserial);
+ resolver.resolve(remote, p->qdomain, QType::NS, &nsset);
}
catch(ResolverException &re) {
- L<<Logger::Error<<"Error resolving SOA or NS for "<<p->qdomain<<" at: "<< p->getRemote() <<": "<<re.reason<<endl;
+ L<<Logger::Error<<"Error resolving SOA or NS for "<<p->qdomain<<" at: "<< remote <<": "<<re.reason<<endl;
return RCode::ServFail;
}
}
if(!haveNS) {
- L<<Logger::Error<<"While checking for supermaster, did not find NS for "<<p->qdomain<<" at: "<< p->getRemote()<<endl;
+ L<<Logger::Error<<"While checking for supermaster, did not find NS for "<<p->qdomain<<" at: "<< remote <<endl;
return RCode::ServFail;
}
DNSBackend *db;
if (!::arg().mustDo("allow-unsigned-supermaster") && tsigkeyname.empty()) {
- L<<Logger::Error<<"Received unsigned NOTIFY for "<<p->qdomain<<" from potential supermaster "<<p->getRemote()<<". Refusing."<<endl;
+ L<<Logger::Error<<"Received unsigned NOTIFY for "<<p->qdomain<<" from potential supermaster "<<remote<<". Refusing."<<endl;
return RCode::Refused;
}
- if(!B.superMasterBackend(p->getRemote().toString(), p->qdomain, nsset, &nameserver, &account, &db)) {
- L<<Logger::Error<<"Unable to find backend willing to host "<<p->qdomain<<" for potential supermaster "<<p->getRemote()<<". Remote nameservers: "<<endl;
+ if(!B.superMasterBackend(remote, p->qdomain, nsset, &nameserver, &account, &db)) {
+ L<<Logger::Error<<"Unable to find backend willing to host "<<p->qdomain<<" for potential supermaster "<<remote<<". Remote nameservers: "<<endl;
for(const auto& rr: nsset) {
if(rr.qtype.getCode()==QType::NS)
L<<Logger::Error<<rr.content<<endl;
}
}
catch(PDNSException& ae) {
- L<<Logger::Error<<"Database error trying to create "<<p->qdomain<<" for potential supermaster "<<p->getRemote()<<": "<<ae.reason<<endl;
+ L<<Logger::Error<<"Database error trying to create "<<p->qdomain<<" for potential supermaster "<<remote<<": "<<ae.reason<<endl;
return RCode::ServFail;
}
- L<<Logger::Warning<<"Created new slave zone '"<<p->qdomain<<"' from supermaster "<<p->getRemote()<<endl;
+ L<<Logger::Warning<<"Created new slave zone '"<<p->qdomain<<"' from supermaster "<<remote<<endl;
return RCode::NoError;
}
if(d_dk.isSecuredZone(sd.qname))
addNSECX(p, r, target, wildcard, sd.qname, mode);
- S.ringAccount("noerror-queries",p->qdomain.toString()+"/"+p->qtype.getName());
+ S.ringAccount("noerror-queries",p->qdomain.toLogString()+"/"+p->qtype.getName());
}
// this TRUMPS a cname!
if(p->qtype.getCode() == QType::NSEC && d_dk.isSecuredZone(sd.qname) && !d_dk.getNSEC3PARAM(sd.qname, 0)) {
addNSEC(p, r, target, DNSName(), sd.qname, 5);
- goto sendit;
+ if (!r->isEmpty())
+ goto sendit;
}
// this TRUMPS a cname!
r=p->replyPacket(); // generate an empty reply packet
r->setRcode(RCode::ServFail);
S.inc("servfail-packets");
- S.ringAccount("servfail-queries",p->qdomain.toString());
+ S.ringAccount("servfail-queries",p->qdomain.toLogString());
}
catch(PDNSException &e) {
L<<Logger::Error<<"Backend reported permanent error which prevented lookup ("+e.reason+"), aborting"<<endl;
r=p->replyPacket(); // generate an empty reply packet
r->setRcode(RCode::ServFail);
S.inc("servfail-packets");
- S.ringAccount("servfail-queries",p->qdomain.toString());
+ S.ringAccount("servfail-queries",p->qdomain.toLogString());
}
return r;
{
#ifdef HAVE_PROTOBUF
return d_message.DebugString();
+#else
+ return std::string();
#endif /* HAVE_PROTOBUF */
}
#include "rpzloader.hh"
#include "base64.hh"
#include "remote_logger.hh"
+#include "validate.hh"
GlobalStateHolder<LuaConfigItems> g_luaconfs;
LuaConfigItems::LuaConfigItems()
{
- auto ds=std::unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make("19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5")));
- // this hurts physically
- dsAnchors[DNSName(".")] = *ds;
+ auto ds=unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make("19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5")));
+ dsAnchors[DNSName(".")].insert(*ds);
}
/* DID YOU READ THE STORY ABOVE? */
});
Lua.writeFunction("addDS", [&lci](const std::string& who, const std::string& what) {
- lci.dsAnchors[DNSName(who)]= *std::unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make(what)));
- });
+ DNSName zone(who);
+ auto ds = unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make(what)));
+ lci.dsAnchors[zone].insert(*ds);
+ });
Lua.writeFunction("clearDS", [&lci](boost::optional<string> who) {
if(who)
#include "sortlist.hh"
#include "filterpo.hh"
#include "remote_logger.hh"
+#include "validate.hh"
class LuaConfigItems
{
LuaConfigItems();
SortList sortlist;
DNSFilterEngine dfe;
- map<DNSName,DSRecordContent> dsAnchors;
+ map<DNSName,dsmap_t> dsAnchors;
map<DNSName,std::string> negAnchors;
std::shared_ptr<RemoteLogger> protobufServer{nullptr};
uint8_t protobufMaskV4{32};
try {
L<<Logger::Warning<<"Adding Trust Anchor for "<<who<<" with data '"<<what<<"', requested via control channel";
g_luaconfs.modify([who, what](LuaConfigItems& lci) {
- lci.dsAnchors[who] = *std::unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make(what)));
+ auto ds = unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make(what)));
+ lci.dsAnchors[who].insert(*ds);
});
broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, who, true));
L<<Logger::Warning<<endl;
{
string ret("Configured Trust Anchors:\n");
auto luaconf = g_luaconfs.getLocal();
- for (auto anchor : luaconf->dsAnchors)
- ret += anchor.first.toLogString() + "\t" + anchor.second.getZoneRepresentation() + "\n";
+ for (auto anchor : luaconf->dsAnchors) {
+ ret += anchor.first.toLogString() + "\n";
+ for (auto e : anchor.second) {
+ ret+="\t\t"+e.getZoneRepresentation() + "\n";
+ }
+ }
+
return ret;
}
for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end() && n < 100; ++mthread, ++n) {
const PacketID& pident = mthread->key;
ostr << (fmt
- % pident.domain.toString() /* ?? */ % DNSRecordContent::NumberToType(pident.type)
+ % pident.domain.toLogString() /* ?? */ % DNSRecordContent::NumberToType(pident.type)
% pident.remote.toString() % (pident.sock ? 'Y' : 'n')
% (pident.fd == -1 ? 'Y' : 'n')
);
-I$(top_srcdir)/ext/json11 \
-I$(top_srcdir)/ext/rapidjson/include \
$(YAHTTP_CFLAGS) \
- $(OPENSSL_INCLUDES)
+ $(LIBCRYPTO_INCLUDES)
AM_CXXFLAGS = \
-DSYSCONFDIR=\"$(sysconfdir)\" \
pdns_recursor_LDADD = \
$(YAHTTP_LIBS) \
$(JSON11_LIBS) \
- $(OPENSSL_LIBS) \
+ $(LIBCRYPTO_LIBS) \
$(BOOST_CONTEXT_LIBS) \
$(SYSTEMD_LIBS) \
$(RT_LIBS)
pdns_recursor_LDFLAGS = $(AM_LDFLAGS) \
- $(OPENSSL_LDFLAGS)
+ $(LIBCRYPTO_LDFLAGS)
if BOTAN110
pdns_recursor_SOURCES += \
# Crypto libraries
PDNS_ENABLE_BOTAN
-AX_CHECK_OPENSSL([
+PDNS_CHECK_LIBCRYPTO([
],[
- AC_MSG_ERROR([OpenSSL not found])
-])
+ AC_MSG_ERROR([OpenSSL/libcrypto not found])
+ ]
+)
+PDNS_CHECK_LIBCRYPTO_ECDSA
# check for tools we might need
PDNS_CHECK_RAGEL
[AC_MSG_NOTICE([LuaJit: $LUAJITPC])],
[AC_MSG_NOTICE([Lua/LuaJit: no])])
])
+AC_MSG_NOTICE([OpenSSL ECDSA: $libcrypto_ecdsa])
AS_IF([test "x$PROTOBUF_LIBS" != "x" -a x"$PROTOC" != "x"],
[AC_MSG_NOTICE([Protobuf: yes])],
[AC_MSG_NOTICE([Protobuf: no])]
+++ /dev/null
-../../../m4/ax_check_openssl.m4
\ No newline at end of file
--- /dev/null
+../../../m4/pdns_check_libcrypto.m4
\ No newline at end of file
--- /dev/null
+../../../m4/pdns_check_libcrypto_ecdsa.m4
\ No newline at end of file
if(p.d.aa) {
if (p.d.rcode==RCode::NXDomain)
- S.ringAccount("nxdomain-queries",p.qdomain.toString()+"/"+p.qtype.getName());
+ S.ringAccount("nxdomain-queries",p.qdomain.toLogString()+"/"+p.qtype.getName());
} else if (p.isEmpty()) {
- S.ringAccount("unauth-queries",p.qdomain.toString()+"/"+p.qtype.getName());
+ S.ringAccount("unauth-queries",p.qdomain.toLogString()+"/"+p.qtype.getName());
S.ringAccount("remotes-unauth",p.d_remote);
}
#include "logger.hh"
#include "arguments.hh"
#include "version.hh"
+#include "validate-recursor.hh"
#include <stdint.h>
#ifndef PACKAGEVERSION
if(::arg()["security-poll-suffix"].empty())
return;
+ string pkgv(PACKAGEVERSION);
struct timeval now;
gettimeofday(&now, 0);
SyncRes sr(now);
- sr.d_doDNSSEC=true;
+ if (g_dnssecmode != DNSSECMode::Off)
+ sr.d_doDNSSEC=true;
vector<DNSRecord> ret;
- string version = "recursor-" +string(PACKAGEVERSION);
+ string version = "recursor-" +pkgv;
string qstring(version.substr(0, 63)+ ".security-status."+::arg()["security-poll-suffix"]);
if(*qstring.rbegin()!='.')
boost::replace_all(qstring, "+", "_");
boost::replace_all(qstring, "~", "_");
+ vState state = Indeterminate;
DNSName query(qstring);
int res=sr.beginResolve(query, QType(QType::TXT), 1, ret);
+
+ if (g_dnssecmode != DNSSECMode::Off && res)
+ state = validateRecords(ret);
+
+ if(state == Bogus) {
+ L<<Logger::Error<<"Could not retrieve security status update for '" +pkgv+ "' on '"<<query<<"', DNSSEC validation result was Bogus!"<<endl;
+ if(g_security_status == 1) // If we were OK, go to unknown
+ g_security_status = 0;
+ return;
+ }
+
if(!res && !ret.empty()) {
string content=ret.begin()->d_content->getZoneRepresentation();
if(!content.empty() && content[0]=='"' && content[content.size()-1]=='"') {
*last_secpoll=now.tv_sec;
}
else {
- string pkgv(PACKAGEVERSION);
if(pkgv.find("0.0."))
L<<Logger::Warning<<"Could not retrieve security status update for '" +pkgv+ "' on '"<<query<<"', RCODE = "<< RCode::to_s(res)<<endl;
else
- L<<Logger::Warning<<"Not validating response for security status update, this a non-release version."<<endl;
+ L<<Logger::Warning<<"Ignoring response for security status update, this a non-release version."<<endl;
- if(g_security_status == 1) // it was ok, not it is unknown
+ if(g_security_status == 1) // it was ok, now it is unknown
g_security_status = 0;
- if(res == RCode::NXDomain) // if we had servfail, keep on trying more more frequently
+ if(res == RCode::NXDomain) // if we had NXDOMAIN, keep on trying more more frequently
*last_secpoll=now.tv_sec;
}
LuaConfigItems::LuaConfigItems()
{
auto ds=std::unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make("19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5")));
- // this hurts physically
- dsAnchors[DNSName(".")] = *ds;
+ dsAnchors[DNSName(".")].insert(*ds);
}
DNSFilterEngine::DNSFilterEngine() {}
vector<string> labels = zone.getRawLabels();
- typedef std::multimap<uint16_t, DSRecordContent> dsmap_t;
dsmap_t dsmap;
keyset_t validkeys;
while(zone.isPartOf(qname))
{
- if(auto ds = rplookup(luaLocal->dsAnchors, qname))
- {
- dsmap.insert(make_pair(ds->d_tag, *ds));
- }
-
+ dsmap_t* tmp = (dsmap_t*) rplookup(luaLocal->dsAnchors, qname);
+ if (tmp)
+ dsmap = *tmp;
+
vector<RRSIGRecordContent> sigs;
vector<shared_ptr<DNSRecordContent> > toSign;
vector<uint16_t> toSignTags;
keyset_t tkeys; // tentative keys
validkeys.clear();
-
+
// start of this iteration
// we can trust that dsmap has valid DS records for qname
}
LOG("got "<<tkeys.size()<<" keys and "<<sigs.size()<<" sigs from server"<<endl);
- for(dsmap_t::const_iterator i=dsmap.begin(); i!=dsmap.end(); i++)
+ for(auto const& dsrc : dsmap)
{
- DSRecordContent dsrc=i->second;
- auto r = getByTag(tkeys, i->first);
+ auto r = getByTag(tkeys, dsrc.d_tag);
// cerr<<"looking at DS with tag "<<dsrc.d_tag<<"/"<<i->first<<", got "<<r.size()<<" DNSKEYs for tag"<<endl;
- for(const auto& drc : r)
+ for(const auto& drc : r)
{
bool isValid = false;
DSRecordContent dsrc2;
}
if(isValid) {
- LOG("got valid DNSKEY (it matches the DS) with tag "<<dsrc.d_tag<<"/"<<i->first<<" for "<<qname<<endl);
+ LOG("got valid DNSKEY (it matches the DS) with tag "<<dsrc.d_tag<<" for "<<qname<<endl);
validkeys.insert(drc);
dotNode("DS", qname, "" /*std::to_string(dsrc.d_tag)*/, (boost::format("tag=%d, digest algo=%d, algo=%d") % dsrc.d_tag % static_cast<int>(dsrc.d_digesttype) % static_cast<int>(dsrc.d_algorithm)).str());
{
const auto dsrc=std::dynamic_pointer_cast<DSRecordContent>(*j);
if(dsrc) {
- dsmap.insert(make_pair(dsrc->d_tag, *dsrc));
+ dsmap.insert(*dsrc);
// dotEdge(keyqname,
// "DNSKEY", keyqname, ,
// "DS", qname, std::to_string(dsrc.d_tag));
// ponder adding a validate method that accepts a key
};
typedef map<pair<DNSName,uint16_t>, ContentSigPair> cspmap_t;
+typedef std::set<DSRecordContent> dsmap_t;
void validateWithKeySet(const cspmap_t& rrsets, cspmap_t& validated, const std::set<DNSKEYRecordContent>& keys);
cspmap_t harvestCSPFromRecs(const vector<DNSRecord>& recs);
vState getKeysFor(DNSRecordOracle& dro, const DNSName& zone, std::set<DNSKEYRecordContent> &keyset);
if(recparts.size() > 7)
throw PDNSException("SOA record contents for "+rr.qname.toString()+" contains too many parts");
if(recparts.size() > 1) {
- recparts[0]=toCanonic(d_zonename, recparts[0]).toStringRootDot();
- recparts[1]=toCanonic(d_zonename, recparts[1]).toStringRootDot();
+ try {
+ recparts[0]=toCanonic(d_zonename, recparts[0]).toStringRootDot();
+ recparts[1]=toCanonic(d_zonename, recparts[1]).toStringRootDot();
+ } catch (runtime_error &re) {
+ throw PDNSException(re.what());
+ }
}
rr.content.clear();
for(string::size_type n = 0; n < recparts.size(); ++n) {
--- /dev/null
+#!/bin/sh
+cleandig host-1234x.example.com NSEC dnssec
--- /dev/null
+Make sure we send a proper denial for nonexistent NSEC records
--- /dev/null
+1 example.com. IN SOA 86400 ns1.example.com. ahu.example.com. 2847484148 28800 7200 604800 86400
+2 . IN OPT 32768
+Rcode: 3 (Non-Existent domain), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='host-1234x.example.com.', qtype=NSEC
--- /dev/null
+1 example.com. IN NSEC 86400 double.example.com. NS SOA MX RRSIG NSEC DNSKEY
+1 example.com. IN RRSIG 86400 NSEC 13 2 86400 [expiry] [inception] [keytag] example.com. ...
+1 example.com. IN RRSIG 86400 SOA 13 2 100000 [expiry] [inception] [keytag] example.com. ...
+1 example.com. IN SOA 86400 ns1.example.com. ahu.example.com. 2847484148 28800 7200 604800 86400
+1 host-12349.example.com. IN NSEC 86400 host-1235.example.com. A RRSIG NSEC
+1 host-12349.example.com. IN RRSIG 86400 NSEC 13 3 86400 [expiry] [inception] [keytag] example.com. ...
+2 . IN OPT 32768
+Rcode: 3 (Non-Existent domain), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='host-1234x.example.com.', qtype=NSEC
--- /dev/null
+1 4jiv8rrf3verm9rp51f55587fbfms5g9.example.com. IN NSEC3 86400 1 [flags] 1 abcd 4JIV8RRF3VERM9RP51F55587FBFMS5GB
+1 4jiv8rrf3verm9rp51f55587fbfms5g9.example.com. IN RRSIG 86400 NSEC3 13 3 86400 [expiry] [inception] [keytag] example.com. ...
+1 9fag9508oqu3m22qac0u5eqgg45v8cf0.example.com. IN NSEC3 86400 1 [flags] 1 abcd 9FAG9508OQU3M22QAC0U5EQGG45V8CF2
+1 9fag9508oqu3m22qac0u5eqgg45v8cf0.example.com. IN RRSIG 86400 NSEC3 13 3 86400 [expiry] [inception] [keytag] example.com. ...
+1 example.com. IN RRSIG 86400 SOA 13 2 100000 [expiry] [inception] [keytag] example.com. ...
+1 example.com. IN SOA 86400 ns1.example.com. ahu.example.com. 2847484148 28800 7200 604800 86400
+1 vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com. IN NSEC3 86400 1 [flags] 1 abcd VTNQ6OCN2VKUIV3NJU14OQTAEN2MT5SL NS SOA MX RRSIG DNSKEY NSEC3PARAM
+1 vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com. IN RRSIG 86400 NSEC3 13 3 86400 [expiry] [inception] [keytag] example.com. ...
+2 . IN OPT 32768
+Rcode: 3 (Non-Existent domain), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='host-1234x.example.com.', qtype=NSEC
--- /dev/null
+1 4j9ti2b4c7iibemvegh99nmoe5m72rb6.example.com. IN NSEC3 86400 1 [flags] 1 abcd 4JKT13JQPK715SGVL9KSRFVACKO95SV4 A RRSIG
+1 4j9ti2b4c7iibemvegh99nmoe5m72rb6.example.com. IN RRSIG 86400 NSEC3 13 3 86400 [expiry] [inception] [keytag] example.com. ...
+1 9f8hti7cc7oqnqjv84klnp89glqrss3r.example.com. IN NSEC3 86400 1 [flags] 1 abcd 9FDAOFPLLN0FQFU9DP274GOU59QFHSLD A RRSIG
+1 9f8hti7cc7oqnqjv84klnp89glqrss3r.example.com. IN RRSIG 86400 NSEC3 13 3 86400 [expiry] [inception] [keytag] example.com. ...
+1 example.com. IN RRSIG 86400 SOA 13 2 100000 [expiry] [inception] [keytag] example.com. ...
+1 example.com. IN SOA 86400 ns1.example.com. ahu.example.com. 2847484148 28800 7200 604800 86400
+1 vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com. IN NSEC3 86400 1 [flags] 1 abcd VTP9NUQBEH436S7J0K8TI2A32MMKCUUL NS SOA MX RRSIG DNSKEY NSEC3PARAM
+1 vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com. IN RRSIG 86400 NSEC3 13 3 86400 [expiry] [inception] [keytag] example.com. ...
+2 . IN OPT 32768
+Rcode: 3 (Non-Existent domain), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='host-1234x.example.com.', qtype=NSEC