unbound: Vendor import 1.16.0

Merge commit '5f9f82264b91e041df7cba2406625146e7268ce4' into main

MFC after:	1 month
This commit is contained in:
Cy Schubert 2022-06-08 15:08:42 -07:00
commit a39a5a6905
102 changed files with 3984 additions and 672 deletions

View File

@ -57,7 +57,7 @@ LEX=@LEX@
STRIP=@STRIP@ STRIP=@STRIP@
CC=@CC@ CC=@CC@
CPPFLAGS=-I. @CPPFLAGS@ CPPFLAGS=-I. @CPPFLAGS@
PYTHON_CPPFLAGS=-I. @PYTHON_CPPFLAGS@ PYTHON_CPPFLAGS=-I. -I$(srcdir) @PYTHON_CPPFLAGS@
CFLAGS=-DSRCDIR=$(srcdir) @CFLAGS@ CFLAGS=-DSRCDIR=$(srcdir) @CFLAGS@
LDFLAGS=@LDFLAGS@ LDFLAGS=@LDFLAGS@
LIBS=@LIBS@ LIBS=@LIBS@
@ -344,7 +344,18 @@ longcheck: longtest
test: unittest$(EXEEXT) testbound$(EXEEXT) test: unittest$(EXEEXT) testbound$(EXEEXT)
./unittest$(EXEEXT) ./unittest$(EXEEXT)
./testbound$(EXEEXT) -s ./testbound$(EXEEXT) -s
for x in $(srcdir)/testdata/*.rpl; do printf "%s" "$$x "; if ./testbound$(EXEEXT) -p $$x >/dev/null 2>&1; then echo OK; else echo failed; exit 1; fi done for x in $(srcdir)/testdata/*.rpl; do \
printf "%s" "$$x "; \
if ./testbound$(EXEEXT) -p $$x >/dev/null 2>&1; then \
echo OK; \
else \
echo failed; \
./testbound$(EXEEXT) -p $$x -o -vvvvv; \
printf "%s" "$$x "; \
echo failed; \
exit 1; \
fi; \
done
@echo test OK @echo test OK
longtest: tests longtest: tests
@ -556,7 +567,7 @@ pythonmod-install:
pyunbound-install: pyunbound-install:
$(INSTALL) -m 755 -d $(DESTDIR)$(PYTHON_SITE_PKG) $(INSTALL) -m 755 -d $(DESTDIR)$(PYTHON_SITE_PKG)
$(INSTALL) -c -m 644 $(srcdir)/libunbound/python/unbound.py $(DESTDIR)$(PYTHON_SITE_PKG)/unbound.py $(INSTALL) -c -m 644 libunbound/python/unbound.py $(DESTDIR)$(PYTHON_SITE_PKG)/unbound.py
$(LIBTOOL) --mode=install cp _unbound.la $(DESTDIR)$(PYTHON_SITE_PKG) $(LIBTOOL) --mode=install cp _unbound.la $(DESTDIR)$(PYTHON_SITE_PKG)
$(LIBTOOL) --mode=finish $(DESTDIR)$(PYTHON_SITE_PKG) $(LIBTOOL) --mode=finish $(DESTDIR)$(PYTHON_SITE_PKG)
@ -583,6 +594,8 @@ install-lib: lib $(UNBOUND_EVENT_INSTALL)
echo ".so man3/libunbound.3" > $(DESTDIR)$(mandir)/man3/$$mpage.3 ; \ echo ".so man3/libunbound.3" > $(DESTDIR)$(mandir)/man3/$$mpage.3 ; \
done done
$(LIBTOOL) --mode=install cp unbound.h $(DESTDIR)$(includedir)/unbound.h $(LIBTOOL) --mode=install cp unbound.h $(DESTDIR)$(includedir)/unbound.h
$(INSTALL) -m 755 -d $(DESTDIR)$(libdir)/pkgconfig
$(INSTALL) -m 644 contrib/libunbound.pc $(DESTDIR)$(libdir)/pkgconfig
$(LIBTOOL) --mode=install cp libunbound.la $(DESTDIR)$(libdir) $(LIBTOOL) --mode=install cp libunbound.la $(DESTDIR)$(libdir)
$(LIBTOOL) --mode=finish $(DESTDIR)$(libdir) $(LIBTOOL) --mode=finish $(DESTDIR)$(libdir)
@ -592,8 +605,6 @@ install-all: all $(PYTHONMOD_INSTALL) $(PYUNBOUND_INSTALL) $(UNBOUND_EVENT_INSTA
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man8 $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man8
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man5 $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man5
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1 $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1
$(INSTALL) -m 755 -d $(DESTDIR)$(libdir)/pkgconfig
$(INSTALL) -m 644 contrib/libunbound.pc $(DESTDIR)$(libdir)/pkgconfig
$(LIBTOOL) --mode=install cp -f unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound$(EXEEXT) $(LIBTOOL) --mode=install cp -f unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound$(EXEEXT)
$(LIBTOOL) --mode=install cp -f unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT) $(LIBTOOL) --mode=install cp -f unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT)
$(LIBTOOL) --mode=install cp -f unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT) $(LIBTOOL) --mode=install cp -f unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT)
@ -1248,7 +1259,7 @@ cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h $(srcdir)/daemon
$(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h \ $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h \
$(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_utils.h \ $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_utils.h \
$(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \ $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/util/config_file.h $(srcdir)/services/outside_network.h
daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h \ daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h \
$(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \ $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \ $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \

View File

@ -18,6 +18,16 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
print(sys.version.split()[[0]])"` print(sys.version.split()[[0]])"`
fi fi
# Check if you have sysconfig
AC_MSG_CHECKING([for the sysconfig Python module])
if ac_sysconfig_result=`$PYTHON -c "import sysconfig" 2>&1`; then
AC_MSG_RESULT([yes])
sysconfig_module="sysconfig"
# if yes, use sysconfig, because distutils is deprecated.
else
AC_MSG_RESULT([no])
# if no, try to use distutils
# #
# Check if you have distutils, else fail # Check if you have distutils, else fail
# #
@ -27,18 +37,26 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
AC_MSG_ERROR([cannot import Python module "distutils". AC_MSG_ERROR([cannot import Python module "distutils".
Please check your Python installation. The error was: Please check your Python installation. The error was:
$ac_distutils_result]) $ac_distutils_result])
PYTHON_VERSION="" PYTHON_VERSION=""
fi fi
sysconfig_module="distutils.sysconfig"
fi
# #
# Check for Python include path # Check for Python include path
# #
AC_MSG_CHECKING([for Python include path]) AC_MSG_CHECKING([for Python include path])
if test -z "$PYTHON_CPPFLAGS"; then if test -z "$PYTHON_CPPFLAGS"; then
if test "$sysconfig_module" = "sysconfig"; then
python_path=`$PYTHON -c 'import sysconfig; \
print(sysconfig.get_path("include"));'`
else
python_path=`$PYTHON -c "import distutils.sysconfig; \ python_path=`$PYTHON -c "import distutils.sysconfig; \
print(distutils.sysconfig.get_python_inc());"` print(distutils.sysconfig.get_python_inc());"`
fi
if test -n "${python_path}"; then if test -n "${python_path}"; then
python_path="-I$python_path" python_path="-I$python_path"
fi fi
@ -52,14 +70,14 @@ $ac_distutils_result])
# #
AC_MSG_CHECKING([for Python library path]) AC_MSG_CHECKING([for Python library path])
if test -z "$PYTHON_LDFLAGS"; then if test -z "$PYTHON_LDFLAGS"; then
PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \ PYTHON_LDFLAGS=`$PYTHON -c "from $sysconfig_module import *; \
print('-L'+get_config_var('LIBDIR')+' -L'+get_config_var('LIBDEST')+' '+get_config_var('BLDLIBRARY'));"` print('-L'+get_config_var('LIBDIR')+' -L'+get_config_var('LIBDEST')+' '+get_config_var('BLDLIBRARY'));"`
fi fi
AC_MSG_RESULT([$PYTHON_LDFLAGS]) AC_MSG_RESULT([$PYTHON_LDFLAGS])
AC_SUBST([PYTHON_LDFLAGS]) AC_SUBST([PYTHON_LDFLAGS])
if test -z "$PYTHON_LIBDIR"; then if test -z "$PYTHON_LIBDIR"; then
PYTHON_LIBDIR=`$PYTHON -c "from distutils.sysconfig import *; \ PYTHON_LIBDIR=`$PYTHON -c "from $sysconfig_module import *; \
print(get_config_var('LIBDIR'));"` print(get_config_var('LIBDIR'));"`
fi fi
@ -68,9 +86,14 @@ $ac_distutils_result])
# #
AC_MSG_CHECKING([for Python site-packages path]) AC_MSG_CHECKING([for Python site-packages path])
if test -z "$PYTHON_SITE_PKG"; then if test -z "$PYTHON_SITE_PKG"; then
if test "$sysconfig_module" = "sysconfig"; then
PYTHON_SITE_PKG=`$PYTHON -c 'import sysconfig; \
print(sysconfig.get_path("platlib"));'`
else
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \ PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
print(distutils.sysconfig.get_python_lib(1,0));"` print(distutils.sysconfig.get_python_lib(1,0));"`
fi fi
fi
AC_MSG_RESULT([$PYTHON_SITE_PKG]) AC_MSG_RESULT([$PYTHON_SITE_PKG])
AC_SUBST([PYTHON_SITE_PKG]) AC_SUBST([PYTHON_SITE_PKG])

View File

@ -4,7 +4,7 @@
# shellcheck disable=SC2006,SC2268 # see below for rationale # shellcheck disable=SC2006,SC2268 # see below for rationale
timestamp='2022-01-09' timestamp='2022-05-25'
# This file is free software; you can redistribute it and/or modify it # This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by # under the terms of the GNU General Public License as published by
@ -1151,16 +1151,27 @@ EOF
;; ;;
x86_64:Linux:*:*) x86_64:Linux:*:*)
set_cc_for_build set_cc_for_build
CPU=$UNAME_MACHINE
LIBCABI=$LIBC LIBCABI=$LIBC
if test "$CC_FOR_BUILD" != no_compiler_found; then if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ ABI=64
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ sed 's/^ //' << EOF > "$dummy.c"
grep IS_X32 >/dev/null #ifdef __i386__
then ABI=x86
LIBCABI=${LIBC}x32 #else
#ifdef __ILP32__
ABI=x32
#endif
#endif
EOF
cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
eval "$cc_set_abi"
case $ABI in
x86) CPU=i686 ;;
x32) LIBCABI=${LIBC}x32 ;;
esac
fi fi
fi GUESS=$CPU-pc-linux-$LIBCABI
GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI
;; ;;
xtensa*:Linux:*:*) xtensa*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
@ -1367,8 +1378,11 @@ EOF
BePC:Haiku:*:*) # Haiku running on Intel PC compatible. BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
GUESS=i586-pc-haiku GUESS=i586-pc-haiku
;; ;;
x86_64:Haiku:*:*) ppc:Haiku:*:*) # Haiku running on Apple PowerPC
GUESS=x86_64-unknown-haiku GUESS=powerpc-apple-haiku
;;
*:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat)
GUESS=$UNAME_MACHINE-unknown-haiku
;; ;;
SX-4:SUPER-UX:*:*) SX-4:SUPER-UX:*:*)
GUESS=sx4-nec-superux$UNAME_RELEASE GUESS=sx4-nec-superux$UNAME_RELEASE

View File

@ -971,6 +971,10 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */ /* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE #undef _POSIX_SOURCE
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
compiled for windows. */
#undef __USE_MINGW_ANSI_STDIO
/* Define to empty if `const' does not conform to ANSI C. */ /* Define to empty if `const' does not conform to ANSI C. */
#undef const #undef const
@ -1150,7 +1154,7 @@
#include <ws2tcpip.h> #include <ws2tcpip.h>
#endif #endif
#ifndef USE_WINSOCK #if !defined(USE_WINSOCK) || !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) || defined(__USE_MINGW_ANSI_STDIO)
#define ARG_LL "%ll" #define ARG_LL "%ll"
#else #else
#define ARG_LL "%I64" #define ARG_LL "%I64"

View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for unbound 1.15.0. # Generated by GNU Autoconf 2.69 for unbound 1.16.0.
# #
# Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>. # Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>.
# #
@ -591,8 +591,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='unbound' PACKAGE_NAME='unbound'
PACKAGE_TARNAME='unbound' PACKAGE_TARNAME='unbound'
PACKAGE_VERSION='1.15.0' PACKAGE_VERSION='1.16.0'
PACKAGE_STRING='unbound 1.15.0' PACKAGE_STRING='unbound 1.16.0'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues' PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
PACKAGE_URL='' PACKAGE_URL=''
@ -813,6 +813,7 @@ infodir
docdir docdir
oldincludedir oldincludedir
includedir includedir
runstatedir
localstatedir localstatedir
sharedstatedir sharedstatedir
sysconfdir sysconfdir
@ -964,6 +965,7 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc' sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com' sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var' localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include' includedir='${prefix}/include'
oldincludedir='/usr/include' oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@ -1216,6 +1218,15 @@ do
| -silent | --silent | --silen | --sile | --sil) | -silent | --silent | --silen | --sile | --sil)
silent=yes ;; silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;; ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@ -1353,7 +1364,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \ datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir libdir localedir mandir runstatedir
do do
eval ac_val=\$$ac_var eval ac_val=\$$ac_var
# Remove trailing slashes. # Remove trailing slashes.
@ -1466,7 +1477,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # 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. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures unbound 1.15.0 to adapt to many kinds of systems. \`configure' configures unbound 1.16.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1506,6 +1517,7 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var] --localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib] --libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include] --includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include] --oldincludedir=DIR C header files for non-gcc [/usr/include]
@ -1531,7 +1543,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of unbound 1.15.0:";; short | recursive ) echo "Configuration of unbound 1.16.0:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1773,7 +1785,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
unbound configure 1.15.0 unbound configure 1.16.0
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
@ -2482,7 +2494,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by unbound $as_me 1.15.0, which was It was created by unbound $as_me 1.16.0, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@ -2832,13 +2844,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
UNBOUND_VERSION_MAJOR=1 UNBOUND_VERSION_MAJOR=1
UNBOUND_VERSION_MINOR=15 UNBOUND_VERSION_MINOR=16
UNBOUND_VERSION_MICRO=0 UNBOUND_VERSION_MICRO=0
LIBUNBOUND_CURRENT=9 LIBUNBOUND_CURRENT=9
LIBUNBOUND_REVISION=15 LIBUNBOUND_REVISION=16
LIBUNBOUND_AGE=1 LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0 # 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0 # 1.0.1 had 0:13:0
@ -2921,6 +2933,7 @@ LIBUNBOUND_AGE=1
# 1.13.2 had 9:13:1 # 1.13.2 had 9:13:1
# 1.14.0 had 9:14:1 # 1.14.0 had 9:14:1
# 1.15.0 had 9:15:1 # 1.15.0 had 9:15:1
# 1.16.0 had 9:16:1
# Current -- the number of the binary API that we're implementing # Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary # Revision -- which iteration of the implementation of the binary
@ -17455,6 +17468,19 @@ fi
print(sys.version.split()[0])"` print(sys.version.split()[0])"`
fi fi
# Check if you have sysconfig
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the sysconfig Python module" >&5
$as_echo_n "checking for the sysconfig Python module... " >&6; }
if ac_sysconfig_result=`$PYTHON -c "import sysconfig" 2>&1`; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
sysconfig_module="sysconfig"
# if yes, use sysconfig, because distutils is deprecated.
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
# if no, try to use distutils
# #
# Check if you have distutils, else fail # Check if you have distutils, else fail
# #
@ -17467,19 +17493,27 @@ $as_echo "yes" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; } $as_echo "no" >&6; }
as_fn_error $? "cannot import Python module \"distutils\". as_fn_error $? "cannot import Python module \"distutils\".
Please check your Python installation. The error was: Please check your Python installation. The error was:
$ac_distutils_result" "$LINENO" 5 $ac_distutils_result" "$LINENO" 5
PYTHON_VERSION="" PYTHON_VERSION=""
fi fi
sysconfig_module="distutils.sysconfig"
fi
# #
# Check for Python include path # Check for Python include path
# #
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python include path" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python include path" >&5
$as_echo_n "checking for Python include path... " >&6; } $as_echo_n "checking for Python include path... " >&6; }
if test -z "$PYTHON_CPPFLAGS"; then if test -z "$PYTHON_CPPFLAGS"; then
if test "$sysconfig_module" = "sysconfig"; then
python_path=`$PYTHON -c 'import sysconfig; \
print(sysconfig.get_path("include"));'`
else
python_path=`$PYTHON -c "import distutils.sysconfig; \ python_path=`$PYTHON -c "import distutils.sysconfig; \
print(distutils.sysconfig.get_python_inc());"` print(distutils.sysconfig.get_python_inc());"`
fi
if test -n "${python_path}"; then if test -n "${python_path}"; then
python_path="-I$python_path" python_path="-I$python_path"
fi fi
@ -17495,7 +17529,7 @@ $as_echo "$PYTHON_CPPFLAGS" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python library path" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python library path" >&5
$as_echo_n "checking for Python library path... " >&6; } $as_echo_n "checking for Python library path... " >&6; }
if test -z "$PYTHON_LDFLAGS"; then if test -z "$PYTHON_LDFLAGS"; then
PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \ PYTHON_LDFLAGS=`$PYTHON -c "from $sysconfig_module import *; \
print('-L'+get_config_var('LIBDIR')+' -L'+get_config_var('LIBDEST')+' '+get_config_var('BLDLIBRARY'));"` print('-L'+get_config_var('LIBDIR')+' -L'+get_config_var('LIBDEST')+' '+get_config_var('BLDLIBRARY'));"`
fi fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_LDFLAGS" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_LDFLAGS" >&5
@ -17503,7 +17537,7 @@ $as_echo "$PYTHON_LDFLAGS" >&6; }
if test -z "$PYTHON_LIBDIR"; then if test -z "$PYTHON_LIBDIR"; then
PYTHON_LIBDIR=`$PYTHON -c "from distutils.sysconfig import *; \ PYTHON_LIBDIR=`$PYTHON -c "from $sysconfig_module import *; \
print(get_config_var('LIBDIR'));"` print(get_config_var('LIBDIR'));"`
fi fi
@ -17513,9 +17547,14 @@ $as_echo "$PYTHON_LDFLAGS" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python site-packages path" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python site-packages path" >&5
$as_echo_n "checking for Python site-packages path... " >&6; } $as_echo_n "checking for Python site-packages path... " >&6; }
if test -z "$PYTHON_SITE_PKG"; then if test -z "$PYTHON_SITE_PKG"; then
if test "$sysconfig_module" = "sysconfig"; then
PYTHON_SITE_PKG=`$PYTHON -c 'import sysconfig; \
print(sysconfig.get_path("platlib"));'`
else
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \ PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
print(distutils.sysconfig.get_python_lib(1,0));"` print(distutils.sysconfig.get_python_lib(1,0));"`
fi fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SITE_PKG" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SITE_PKG" >&5
$as_echo "$PYTHON_SITE_PKG" >&6; } $as_echo "$PYTHON_SITE_PKG" >&6; }
@ -20181,6 +20220,9 @@ fi
WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o" WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o"
$as_echo "#define __USE_MINGW_ANSI_STDIO 1" >>confdefs.h
fi fi
if test $ac_cv_func_getaddrinfo = no; then if test $ac_cv_func_getaddrinfo = no; then
case " $LIBOBJS " in case " $LIBOBJS " in
@ -21678,10 +21720,16 @@ $as_echo_n "checking for libmnl... " >&6; }
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
fi fi
for dir in $withval ; do for dir in $withval ; do
if test -f "$dir/include/libmnl/libmnl.h"; then if test -f "$dir/include/libmnl/libmnl.h" -o -f "$dir/include/libmnl/libmnl/libmnl.h"; then
found_libmnl="yes" found_libmnl="yes"
extralibmnl=""
if test -f "$dir/include/libmnl/libmnl/libmnl.h"; then
extralibmnl="/libmnl"
fi
if test "$dir" != "/usr" -o -n "$extralibmnl"; then
CPPFLAGS="$CPPFLAGS -I$dir/include$extralibmnl"
fi
if test "$dir" != "/usr"; then if test "$dir" != "/usr"; then
CPPFLAGS="$CPPFLAGS -I$dir/include"
LDFLAGS="$LDFLAGS -L$dir/lib" LDFLAGS="$LDFLAGS -L$dir/lib"
fi fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5
@ -21886,7 +21934,7 @@ _ACEOF
version=1.15.0 version=1.16.0
date=`date +'%b %e, %Y'` date=`date +'%b %e, %Y'`
@ -22405,7 +22453,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by unbound $as_me 1.15.0, which was This file was extended by unbound $as_me 1.16.0, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -22471,7 +22519,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
unbound config.status 1.15.0 unbound config.status 1.16.0
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

@ -10,7 +10,7 @@ sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing # must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1]) m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[15]) m4_define([VERSION_MINOR],[16])
m4_define([VERSION_MICRO],[0]) m4_define([VERSION_MICRO],[0])
AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound]) AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound])
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR]) AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
@ -18,7 +18,7 @@ AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO]) AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
LIBUNBOUND_CURRENT=9 LIBUNBOUND_CURRENT=9
LIBUNBOUND_REVISION=15 LIBUNBOUND_REVISION=16
LIBUNBOUND_AGE=1 LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0 # 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0 # 1.0.1 had 0:13:0
@ -101,6 +101,7 @@ LIBUNBOUND_AGE=1
# 1.13.2 had 9:13:1 # 1.13.2 had 9:13:1
# 1.14.0 had 9:14:1 # 1.14.0 had 9:14:1
# 1.15.0 had 9:15:1 # 1.15.0 had 9:15:1
# 1.16.0 had 9:16:1
# Current -- the number of the binary API that we're implementing # Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary # Revision -- which iteration of the implementation of the binary
@ -1553,6 +1554,7 @@ if test "$USE_WINSOCK" = 1; then
AC_SUBST(WIN_CONTROL_OBJ_LINK) AC_SUBST(WIN_CONTROL_OBJ_LINK)
WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o" WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o"
AC_SUBST(WIN_CHECKCONF_OBJ_LINK) AC_SUBST(WIN_CHECKCONF_OBJ_LINK)
AC_DEFINE(__USE_MINGW_ANSI_STDIO, 1, [defined to use gcc ansi snprintf and sscanf that understands %lld when compiled for windows.])
fi fi
if test $ac_cv_func_getaddrinfo = no; then if test $ac_cv_func_getaddrinfo = no; then
AC_LIBOBJ([fake-rfc2553]) AC_LIBOBJ([fake-rfc2553])
@ -1878,11 +1880,17 @@ case "$enable_ipset" in
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
fi fi
for dir in $withval ; do for dir in $withval ; do
if test -f "$dir/include/libmnl/libmnl.h"; then if test -f "$dir/include/libmnl/libmnl.h" -o -f "$dir/include/libmnl/libmnl/libmnl.h"; then
found_libmnl="yes" found_libmnl="yes"
dnl assume /usr is in default path. dnl assume /usr is in default path.
extralibmnl=""
if test -f "$dir/include/libmnl/libmnl/libmnl.h"; then
extralibmnl="/libmnl"
fi
if test "$dir" != "/usr" -o -n "$extralibmnl"; then
CPPFLAGS="$CPPFLAGS -I$dir/include$extralibmnl"
fi
if test "$dir" != "/usr"; then if test "$dir" != "/usr"; then
CPPFLAGS="$CPPFLAGS -I$dir/include"
LDFLAGS="$LDFLAGS -L$dir/lib" LDFLAGS="$LDFLAGS -L$dir/lib"
fi fi
AC_MSG_RESULT(found in $dir) AC_MSG_RESULT(found in $dir)
@ -2060,7 +2068,7 @@ dnl includes
#include <ws2tcpip.h> #include <ws2tcpip.h>
#endif #endif
#ifndef USE_WINSOCK #if !defined(USE_WINSOCK) || !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) || defined(__USE_MINGW_ANSI_STDIO)
#define ARG_LL "%ll" #define ARG_LL "%ll"
#else #else
#define ARG_LL "%I64" #define ARG_LL "%I64"

View File

@ -487,3 +487,38 @@ acl_list_get_mem(struct acl_list* acl)
if(!acl) return 0; if(!acl) return 0;
return sizeof(*acl) + regional_get_mem(acl->region); return sizeof(*acl) + regional_get_mem(acl->region);
} }
const char* acl_access_to_str(enum acl_access acl)
{
switch(acl) {
case acl_deny: return "deny";
case acl_refuse: return "refuse";
case acl_deny_non_local: return "deny_non_local";
case acl_refuse_non_local: return "refuse_non_local";
case acl_allow: return "allow";
case acl_allow_snoop: return "allow_snoop";
case acl_allow_setrd: return "allow_setrd";
default: break;
}
return "unknown";
}
void
log_acl_action(const char* action, struct sockaddr_storage* addr,
socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr)
{
char a[128], n[128];
uint16_t port;
addr_to_str(addr, addrlen, a, sizeof(a));
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
if(acladdr) {
addr_to_str(&acladdr->node.addr, acladdr->node.addrlen,
n, sizeof(n));
verbose(VERB_ALGO, "%s query from %s port %d because of "
"%s/%d %s", action, a, (int)port, n, acladdr->node.net,
acl_access_to_str(acl));
} else {
verbose(VERB_ALGO, "%s query from %s port %d", action, a,
(int)port);
}
}

View File

@ -154,4 +154,15 @@ acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
*/ */
size_t acl_list_get_mem(struct acl_list* acl); size_t acl_list_get_mem(struct acl_list* acl);
/*
* Get string for acl access specification
* @param acl: access type value
* @return string
*/
const char* acl_access_to_str(enum acl_access acl);
/* log acl and addr for action */
void log_acl_action(const char* action, struct sockaddr_storage* addr,
socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr);
#endif /* DAEMON_ACL_LIST_H */ #endif /* DAEMON_ACL_LIST_H */

View File

@ -47,10 +47,12 @@
#include "services/cache/rrset.h" #include "services/cache/rrset.h"
#include "services/cache/dns.h" #include "services/cache/dns.h"
#include "services/cache/infra.h" #include "services/cache/infra.h"
#include "services/outside_network.h"
#include "util/data/msgreply.h" #include "util/data/msgreply.h"
#include "util/regional.h" #include "util/regional.h"
#include "util/net_help.h" #include "util/net_help.h"
#include "util/data/dname.h" #include "util/data/dname.h"
#include "util/config_file.h"
#include "iterator/iterator.h" #include "iterator/iterator.h"
#include "iterator/iter_delegpt.h" #include "iterator/iter_delegpt.h"
#include "iterator/iter_utils.h" #include "iterator/iter_utils.h"
@ -854,7 +856,9 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
"cache; goes to configured roots\n"); "cache; goes to configured roots\n");
} }
/* go up? */ /* go up? */
if(iter_dp_is_useless(&qinfo, BIT_RD, dp)) { if(iter_dp_is_useless(&qinfo, BIT_RD, dp,
(worker->env.cfg->do_ip4 && worker->back->num_ip4 != 0),
(worker->env.cfg->do_ip6 && worker->back->num_ip6 != 0))) {
print_dp_main(ssl, dp, msg); print_dp_main(ssl, dp, msg);
print_dp_details(ssl, worker, dp); print_dp_details(ssl, worker, dp);
if(!ssl_printf(ssl, "cache delegation was " if(!ssl_printf(ssl, "cache delegation was "

View File

@ -484,6 +484,12 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
msg->rep, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad, msg->rep, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad,
worker->env.now_tv)) worker->env.now_tv))
return 0; return 0;
/* TODO store the reason for the bogus reply in cache
* and implement in here instead of the hardcoded EDE */
if (worker->env.cfg->ede) {
EDNS_OPT_LIST_APPEND_EDE(&edns->opt_list_out,
worker->scratchpad, LDNS_EDE_DNSSEC_BOGUS, "");
}
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
&msg->qinfo, id, flags, edns); &msg->qinfo, id, flags, edns);
if(worker->stats.extended) { if(worker->stats.extended) {
@ -553,7 +559,7 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
return 1; return 1;
if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo, if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo,
alias_rrset, 0, worker->scratchpad, az)) alias_rrset, 0, worker->scratchpad, az, NULL))
return 0; return 0;
/* xxx_deny actions mean dropping the reply, unless the original reply /* xxx_deny actions mean dropping the reply, unless the original reply
@ -654,6 +660,12 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad,
worker->env.now_tv)) worker->env.now_tv))
goto bail_out; goto bail_out;
/* TODO store the reason for the bogus reply in cache
* and implement in here instead of the hardcoded EDE */
if (worker->env.cfg->ede) {
EDNS_OPT_LIST_APPEND_EDE(&edns->opt_list_out,
worker->scratchpad, LDNS_EDE_DNSSEC_BOGUS, "");
}
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, id, flags, edns); qinfo, id, flags, edns);
rrset_array_unlock_touch(worker->env.rrset_cache, rrset_array_unlock_touch(worker->env.rrset_cache,
@ -716,16 +728,26 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
if(!*partial_repp) if(!*partial_repp)
goto bail_out; goto bail_out;
} }
} else if(!reply_info_answer_encode(qinfo, encode_rep, id, flags, } else {
/* We don't check the global ede as this is a warning, not
* an error */
if (*is_expired_answer == 1 &&
worker->env.cfg->ede_serve_expired && worker->env.cfg->ede) {
EDNS_OPT_LIST_APPEND_EDE(&edns->opt_list_out,
worker->scratchpad, LDNS_EDE_STALE_ANSWER, "");
}
if(!reply_info_answer_encode(qinfo, encode_rep, id, flags,
repinfo->c->buffer, timenow, 1, worker->scratchpad, repinfo->c->buffer, timenow, 1, worker->scratchpad,
udpsize, edns, (int)(edns->bits & EDNS_DO), *is_secure_answer)) { udpsize, edns, (int)(edns->bits & EDNS_DO),
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL, *is_secure_answer)) {
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad, if(!inplace_cb_reply_servfail_call(&worker->env, qinfo,
worker->env.now_tv)) NULL, NULL, LDNS_RCODE_SERVFAIL, edns, repinfo,
worker->scratchpad, worker->env.now_tv))
edns->opt_list_inplace_cb_out = NULL; edns->opt_list_inplace_cb_out = NULL;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, id, flags, edns); qinfo, id, flags, edns);
} }
}
/* cannot send the reply right now, because blocking network syscall /* cannot send the reply right now, because blocking network syscall
* is bad while holding locks. */ * is bad while holding locks. */
rrset_array_unlock_touch(worker->env.rrset_cache, worker->scratchpad, rrset_array_unlock_touch(worker->env.rrset_cache, worker->scratchpad,
@ -742,8 +764,10 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
/** Reply to client and perform prefetch to keep cache up to date. */ /** Reply to client and perform prefetch to keep cache up to date. */
static void static void
reply_and_prefetch(struct worker* worker, struct query_info* qinfo, reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
uint16_t flags, struct comm_reply* repinfo, time_t leeway, int noreply) uint16_t flags, struct comm_reply* repinfo, time_t leeway, int noreply,
int rpz_passthru, struct edns_option* opt_list)
{ {
(void)opt_list;
/* first send answer to client to keep its latency /* first send answer to client to keep its latency
* as small as a cachereply */ * as small as a cachereply */
if(!noreply) { if(!noreply) {
@ -755,13 +779,23 @@ reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
comm_point_send_reply(repinfo); comm_point_send_reply(repinfo);
} }
server_stats_prefetch(&worker->stats, worker); server_stats_prefetch(&worker->stats, worker);
#ifdef CLIENT_SUBNET
/* Check if the subnet module is enabled. In that case pass over the
* comm_reply information for ECS generation later. The mesh states are
* unique when subnet is enabled. */
if(modstack_find(&worker->env.mesh->mods, "subnetcache") != -1
&& worker->env.unique_mesh) {
mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway +
PREFETCH_EXPIRY_ADD, rpz_passthru, repinfo, opt_list);
return;
}
#endif
/* create the prefetch in the mesh as a normal lookup without /* create the prefetch in the mesh as a normal lookup without
* client addrs waiting, which has the cache blacklisted (to bypass * client addrs waiting, which has the cache blacklisted (to bypass
* the cache and go to the network for the data). */ * the cache and go to the network for the data). */
/* this (potentially) runs the mesh for the new query */ /* this (potentially) runs the mesh for the new query */
mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway + mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway +
PREFETCH_EXPIRY_ADD); PREFETCH_EXPIRY_ADD, rpz_passthru, NULL, NULL);
} }
/** /**
@ -1012,49 +1046,199 @@ answer_notify(struct worker* w, struct query_info* qinfo,
static int static int
deny_refuse(struct comm_point* c, enum acl_access acl, deny_refuse(struct comm_point* c, enum acl_access acl,
enum acl_access deny, enum acl_access refuse, enum acl_access deny, enum acl_access refuse,
struct worker* worker, struct comm_reply* repinfo) struct worker* worker, struct comm_reply* repinfo,
struct acl_addr* acladdr, int ede)
{ {
if(acl == deny) { if(acl == deny) {
if(verbosity >= VERB_ALGO) {
log_acl_action("dropped", &repinfo->addr,
repinfo->addrlen, acl, acladdr);
log_buf(VERB_ALGO, "dropped", c->buffer);
}
comm_point_drop_reply(repinfo); comm_point_drop_reply(repinfo);
if(worker->stats.extended) if(worker->stats.extended)
worker->stats.unwanted_queries++; worker->stats.unwanted_queries++;
return 0; return 0;
} else if(acl == refuse) { } else if(acl == refuse) {
log_addr(VERB_ALGO, "refused query from", size_t opt_rr_mark;
&repinfo->addr, repinfo->addrlen);
if(verbosity >= VERB_ALGO) {
log_acl_action("refused", &repinfo->addr,
repinfo->addrlen, acl, acladdr);
log_buf(VERB_ALGO, "refuse", c->buffer); log_buf(VERB_ALGO, "refuse", c->buffer);
}
if(worker->stats.extended) if(worker->stats.extended)
worker->stats.unwanted_queries++; worker->stats.unwanted_queries++;
if(worker_check_request(c->buffer, worker) == -1) { if(worker_check_request(c->buffer, worker) == -1) {
comm_point_drop_reply(repinfo); comm_point_drop_reply(repinfo);
return 0; /* discard this */ return 0; /* discard this */
} }
sldns_buffer_set_limit(c->buffer, LDNS_HEADER_SIZE); /* worker_check_request() above guarantees that the buffer contains at
sldns_buffer_write_at(c->buffer, 4, * least a header and that qdcount == 1
(uint8_t*)"\0\0\0\0\0\0\0\0", 8); */
log_assert(sldns_buffer_limit(c->buffer) >= LDNS_HEADER_SIZE
&& LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) == 1);
sldns_buffer_skip(c->buffer, LDNS_HEADER_SIZE); /* skip header */
/* check additional section is present and that we respond with EDEs */
if(LDNS_ARCOUNT(sldns_buffer_begin(c->buffer)) != 1
|| !ede) {
LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_QR_SET(sldns_buffer_begin(c->buffer)); LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_REFUSED); LDNS_RCODE_REFUSED);
sldns_buffer_flip(c->buffer);
return 1;
}
if (!query_dname_len(c->buffer)) {
LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE); sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
sldns_buffer_flip(c->buffer); sldns_buffer_flip(c->buffer);
return 1; return 1;
} }
/* space available for query type and class? */
if (sldns_buffer_remaining(c->buffer) < 2 * sizeof(uint16_t)) {
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
sldns_buffer_flip(c->buffer);
return 1;
}
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_REFUSED);
sldns_buffer_skip(c->buffer, (ssize_t)sizeof(uint16_t)); /* skip qtype */
sldns_buffer_skip(c->buffer, (ssize_t)sizeof(uint16_t)); /* skip qclass */
/* The OPT RR to be returned should come directly after
* the query, so mark this spot.
*/
opt_rr_mark = sldns_buffer_position(c->buffer);
/* Skip through the RR records */
if(LDNS_ANCOUNT(sldns_buffer_begin(c->buffer)) != 0 ||
LDNS_NSCOUNT(sldns_buffer_begin(c->buffer)) != 0) {
if(!skip_pkt_rrs(c->buffer,
((int)LDNS_ANCOUNT(sldns_buffer_begin(c->buffer)))+
((int)LDNS_NSCOUNT(sldns_buffer_begin(c->buffer))))) {
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_set_position(c->buffer, opt_rr_mark);
sldns_buffer_flip(c->buffer);
return 1;
}
}
/* Do we have a valid OPT RR here? If not return REFUSED (could be a valid TSIG or something so no FORMERR) */
/* domain name must be the root of length 1. */
if(sldns_buffer_remaining(c->buffer) < 1 || *sldns_buffer_current(c->buffer) != 0) {
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_set_position(c->buffer, opt_rr_mark);
sldns_buffer_flip(c->buffer);
return 1;
} else {
sldns_buffer_skip(c->buffer, 1); /* skip root label */
}
if(sldns_buffer_remaining(c->buffer) < 2 ||
sldns_buffer_read_u16(c->buffer) != LDNS_RR_TYPE_OPT) {
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_set_position(c->buffer, opt_rr_mark);
sldns_buffer_flip(c->buffer);
return 1;
}
/* Write OPT RR directly after the query,
* so without the (possibly skipped) Answer and NS RRs
*/
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_clear(c->buffer); /* reset write limit */
sldns_buffer_set_position(c->buffer, opt_rr_mark);
/* Check if OPT record can be written
* 17 == root label (1) + RR type (2) + UDP Size (2)
* + Fields (4) + rdata len (2) + EDE Option code (2)
* + EDE Option length (2) + EDE info-code (2)
*/
if (sldns_buffer_available(c->buffer, 17) == 0) {
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_flip(c->buffer);
return 1;
}
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 1);
/* root label */
sldns_buffer_write_u8(c->buffer, 0);
sldns_buffer_write_u16(c->buffer, LDNS_RR_TYPE_OPT);
sldns_buffer_write_u16(c->buffer, EDNS_ADVERTISED_SIZE);
/* write OPT Record TTL Field */
sldns_buffer_write_u32(c->buffer, 0);
/* write rdata len: EDE option + length + info-code */
sldns_buffer_write_u16(c->buffer, 6);
/* write OPTIONS; add EDE option code */
sldns_buffer_write_u16(c->buffer, LDNS_EDNS_EDE);
/* write single EDE option length (for just 1 info-code) */
sldns_buffer_write_u16(c->buffer, 2);
/* write single EDE info-code */
sldns_buffer_write_u16(c->buffer, LDNS_EDE_PROHIBITED);
sldns_buffer_flip(c->buffer);
verbose(VERB_ALGO, "attached EDE code: %d", LDNS_EDE_PROHIBITED);
return 1;
}
return -1; return -1;
} }
static int static int
deny_refuse_all(struct comm_point* c, enum acl_access acl, deny_refuse_all(struct comm_point* c, enum acl_access acl,
struct worker* worker, struct comm_reply* repinfo) struct worker* worker, struct comm_reply* repinfo,
struct acl_addr* acladdr, int ede)
{ {
return deny_refuse(c, acl, acl_deny, acl_refuse, worker, repinfo); return deny_refuse(c, acl, acl_deny, acl_refuse, worker, repinfo,
acladdr, ede);
} }
static int static int
deny_refuse_non_local(struct comm_point* c, enum acl_access acl, deny_refuse_non_local(struct comm_point* c, enum acl_access acl,
struct worker* worker, struct comm_reply* repinfo) struct worker* worker, struct comm_reply* repinfo,
struct acl_addr* acladdr, int ede)
{ {
return deny_refuse(c, acl, acl_deny_non_local, acl_refuse_non_local, worker, repinfo); return deny_refuse(c, acl, acl_deny_non_local, acl_refuse_non_local,
worker, repinfo, acladdr, ede);
} }
int int
@ -1067,12 +1251,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
struct lruhash_entry* e; struct lruhash_entry* e;
struct query_info qinfo; struct query_info qinfo;
struct edns_data edns; struct edns_data edns;
struct edns_option* original_edns_list = NULL;
enum acl_access acl; enum acl_access acl;
struct acl_addr* acladdr; struct acl_addr* acladdr;
int rc = 0; int rc = 0;
int need_drop = 0; int need_drop = 0;
int is_expired_answer = 0; int is_expired_answer = 0;
int is_secure_answer = 0; int is_secure_answer = 0;
int rpz_passthru = 0;
/* We might have to chase a CNAME chain internally, in which case /* We might have to chase a CNAME chain internally, in which case
* we'll have up to two replies and combine them to build a complete * we'll have up to two replies and combine them to build a complete
* answer. These variables control this case. */ * answer. These variables control this case. */
@ -1145,7 +1331,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
acladdr = acl_addr_lookup(worker->daemon->acl, &repinfo->addr, acladdr = acl_addr_lookup(worker->daemon->acl, &repinfo->addr,
repinfo->addrlen); repinfo->addrlen);
acl = acl_get_control(acladdr); acl = acl_get_control(acladdr);
if((ret=deny_refuse_all(c, acl, worker, repinfo)) != -1)
if((ret=deny_refuse_all(c, acl, worker, repinfo, acladdr,
worker->env.cfg->ede)) != -1)
{ {
if(ret == 1) if(ret == 1)
goto send_reply; goto send_reply;
@ -1338,7 +1526,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
if(worker->env.auth_zones && if(worker->env.auth_zones &&
rpz_callback_from_worker_request(worker->env.auth_zones, rpz_callback_from_worker_request(worker->env.auth_zones,
&worker->env, &qinfo, &edns, c->buffer, worker->scratchpad, &worker->env, &qinfo, &edns, c->buffer, worker->scratchpad,
repinfo, acladdr->taglist, acladdr->taglen, &worker->stats)) { repinfo, acladdr->taglist, acladdr->taglen, &worker->stats,
&rpz_passthru)) {
regional_free_all(worker->scratchpad); regional_free_all(worker->scratchpad);
if(sldns_buffer_limit(c->buffer) == 0) { if(sldns_buffer_limit(c->buffer) == 0) {
comm_point_drop_reply(repinfo); comm_point_drop_reply(repinfo);
@ -1364,7 +1553,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
/* We've looked in our local zones. If the answer isn't there, we /* We've looked in our local zones. If the answer isn't there, we
* might need to bail out based on ACLs now. */ * might need to bail out based on ACLs now. */
if((ret=deny_refuse_non_local(c, acl, worker, repinfo)) != -1) if((ret=deny_refuse_non_local(c, acl, worker, repinfo, acladdr,
worker->env.cfg->ede)) != -1)
{ {
regional_free_all(worker->scratchpad); regional_free_all(worker->scratchpad);
if(ret == 1) if(ret == 1)
@ -1383,12 +1573,17 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
* ACLs allow the snooping. */ * ACLs allow the snooping. */
if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) && if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) &&
acl != acl_allow_snoop ) { acl != acl_allow_snoop ) {
if (worker->env.cfg->ede) {
EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out,
worker->scratchpad, LDNS_EDE_NOT_AUTHORITATIVE, "");
}
error_encode(c->buffer, LDNS_RCODE_REFUSED, &qinfo, error_encode(c->buffer, LDNS_RCODE_REFUSED, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer), *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), NULL); sldns_buffer_read_u16_at(c->buffer, 2), &edns);
regional_free_all(worker->scratchpad); regional_free_all(worker->scratchpad);
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from", log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->addr, repinfo->addrlen); &repinfo->addr, repinfo->addrlen);
goto send_reply; goto send_reply;
} }
@ -1429,6 +1624,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
cinfo = &cinfo_tmp; cinfo = &cinfo_tmp;
} }
/* Keep the original edns list around. The pointer could change if there is
* a cached answer (through the inplace callback function there).
* No need to actually copy the contents as they shouldn't change.
* Used while prefetching and subnet is enabled. */
original_edns_list = edns.opt_list_in;
lookup_cache: lookup_cache:
/* Lookup the cache. In case we chase an intermediate CNAME chain /* Lookup the cache. In case we chase an intermediate CNAME chain
* this is a two-pass operation, and lookup_qinfo is different for * this is a two-pass operation, and lookup_qinfo is different for
@ -1461,10 +1661,13 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
< *worker->env.now) < *worker->env.now)
leeway = 0; leeway = 0;
lock_rw_unlock(&e->lock); lock_rw_unlock(&e->lock);
reply_and_prefetch(worker, lookup_qinfo, reply_and_prefetch(worker, lookup_qinfo,
sldns_buffer_read_u16_at(c->buffer, 2), sldns_buffer_read_u16_at(c->buffer, 2),
repinfo, leeway, repinfo, leeway,
(partial_rep || need_drop)); (partial_rep || need_drop),
rpz_passthru,
original_edns_list);
if(!partial_rep) { if(!partial_rep) {
rc = 0; rc = 0;
regional_free_all(worker->scratchpad); regional_free_all(worker->scratchpad);
@ -1501,6 +1704,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
verbose(VERB_ALGO, "answer from the cache failed"); verbose(VERB_ALGO, "answer from the cache failed");
lock_rw_unlock(&e->lock); lock_rw_unlock(&e->lock);
} }
if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) { if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) {
if(answer_norec_from_cache(worker, &qinfo, if(answer_norec_from_cache(worker, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer), *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
@ -1527,7 +1731,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
/* grab a work request structure for this new request */ /* grab a work request structure for this new request */
mesh_new_client(worker->env.mesh, &qinfo, cinfo, mesh_new_client(worker->env.mesh, &qinfo, cinfo,
sldns_buffer_read_u16_at(c->buffer, 2), sldns_buffer_read_u16_at(c->buffer, 2),
&edns, repinfo, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer)); &edns, repinfo, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
rpz_passthru);
regional_free_all(worker->scratchpad); regional_free_all(worker->scratchpad);
worker_mem_report(worker, NULL); worker_mem_report(worker, NULL);
return 0; return 0;
@ -1591,6 +1796,9 @@ worker_sighandler(int sig, void* arg)
case SIGHUP: case SIGHUP:
comm_base_exit(worker->base); comm_base_exit(worker->base);
break; break;
#endif
#ifdef SIGBREAK
case SIGBREAK:
#endif #endif
case SIGINT: case SIGINT:
worker->need_to_exit = 1; worker->need_to_exit = 1;
@ -1709,6 +1917,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
if(do_sigs) { if(do_sigs) {
#ifdef SIGHUP #ifdef SIGHUP
ub_thread_sig_unblock(SIGHUP); ub_thread_sig_unblock(SIGHUP);
#endif
#ifdef SIGBREAK
ub_thread_sig_unblock(SIGBREAK);
#endif #endif
ub_thread_sig_unblock(SIGINT); ub_thread_sig_unblock(SIGINT);
#ifdef SIGQUIT #ifdef SIGQUIT
@ -1726,6 +1937,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
|| !comm_signal_bind(worker->comsig, SIGQUIT) || !comm_signal_bind(worker->comsig, SIGQUIT)
#endif #endif
|| !comm_signal_bind(worker->comsig, SIGTERM) || !comm_signal_bind(worker->comsig, SIGTERM)
#ifdef SIGBREAK
|| !comm_signal_bind(worker->comsig, SIGBREAK)
#endif
|| !comm_signal_bind(worker->comsig, SIGINT)) { || !comm_signal_bind(worker->comsig, SIGINT)) {
log_err("could not create signal handlers"); log_err("could not create signal handlers");
worker_delete(worker); worker_delete(worker);

View File

@ -1,5 +1,146 @@
27 May 2022: Wouter
- Fix #684: [FTBS] configure script error with libmnl on openSUSE 15.3 (and possibly other distributions)
- Version is set to 1.16.0 for release. Release tag 1.16.0rc1.
20 May 2022: Wouter
- Fix to silence test for ede error output to the console from the
test setup script.
- Fix ede test to not use default pidfile, and use local interface.
- Fix some lint type warnings.
18 May 2022: George
- Fix typos in config_set_option for the 'num-threads' and
'ede-serve-expired' options.
15 May 2022: George
- Fix #678: [FR] modify behaviour of unbound-control rpz_enable zone,
by updating unbound-control's documentation.
12 May 2022: George
- Fix #417: prefetch and ECS causing cache corruption when used
together.
12 May 2022: Wouter
- Merge #677: Allow using system certificates not only on Windows,
from pemensik.
- For #677: Added tls-system-cert to config parser and documentation.
11 May 2022: Wouter
- Fix #673: DNS over TLS: error: SSL_handshake syscall: No route to
host.
10 May 2022: George
- Fix Python build in non-source directory; based on patch by
Michael Tokarev.
6 May 2022: Tom
- Merge PR #604: Add basic support for EDE (RFC8914).
28 April 2022: Wouter
- Fix #670: SERVFAIL problems with unbound 1.15.0 running on
OpenBSD 7.1.
8 April 2022: Wouter
- Fix zonemd check to allow unsupported algorithms to load.
If there are only unsupported algorithms, or unsupported schemes,
and no failed or successful other ZONEMD records, or malformed
or bad ZONEMD records, the unsupported records allow the zone load.
- Fix zonemd unsupported algo check.
- Fix zonemd unsupported algo check reason to not copy to next record,
and check for success for debug printout.
- Fix zonemd unsupported algo check to print unsupported reason before
zeroing it.
- Fix zonemd unsupported algo check to set reason to NULL before the
check routine, but after malformed checks, to get the correct NULL
output when the digest matches.
25 March 2022: Wouter
- Fix spelling error in comment in sldns_str2wire_svcparam_key_lookup.
23 March 2022: Wouter
- Fix #651: [FR] Better logging for refused queries.
18 March 2022: George
- Merge PR #648 from eaglegai: fix -q doesn't work when use with
'unbound-control stats_shm'.
17 March 2022: Wouter
- Fix to describe auth-zone and other configuration at the local-zone
configuration option, to allow for more broadly view of the options.
16 March 2022: Wouter
- Fix to ensure uniform handling of spaces and tabs when parsing RRs.
9 March 2022: Wouter
- Merge #644: Make `install-lib` make target install the pkg-config
file.
7 March 2022: Wouter
- Fix configure for python to use sysutils, because distutils is
deprecated. It uses sysutils when available, distutils otherwise.
3 March 2022: Wouter
- Fix #637: Integer Overflow in sldns_str2period function.
- Fix for #637: fix integer overflow checks in sldns_str2period.
2 March 2022: George
- Merge PR #632 from scottrw93: Match cnames in ipset.
- Various fixes for #632: variable initialisation, convert the qinfo
to str once, accept trailing dot in the local-zone ipset option.
2 March 2022: Wouter
- Fix compile warnings for printf ll format on mingw compile.
1 March 2022: Wouter
- Fix pythonmod for change in iter_dp_is_useless function prototype.
28 February 2022: George
- Fix #630: Unify the RPZ log messages.
- Merge #623 from rex4539: Fix typos.
28 February 2022: Wouter
- Fix #633: Document unix domain socket support for unbound-control.
- Fix for #633: updated fix with new text.
- Fix edns client subnet to add the option based on the option list,
so that it is not state dependent, after the state fix of #605 for
double EDNS options.
- Fix for edns client subnet option add fix in removal code, from review.
25 February 2022: Wouter
- Fix to detect that no IPv6 support means that IPv6 addresses are
useless for delegation point lookups.
- update Makefile dependencies.
- Fix check interface existence for support detection in remote lookup.
18 February 2022: Wouter
- Fix that address not available is squelched from the logs for
udp connect failures. It is visible on verbosity 4 and more.
- Merge #631 from mollyim: Replace OpenSSL's ERR_PACK with
ERR_GET_REASON.
16 February 2022: Wouter
- Fix for #628: fix rpz-passthru for qname trigger by localzone type.
15 February 2022: Wouter
- Fix #628: A rpz-passthru action is not ending RPZ zone processing.
11 February 2022: Wouter
- Fix #624: Unable to stop Unbound in Windows console (does not
respond to CTRL+C command).
- Fix #618: enabling interface-automatic disables DNS-over-TLS.
Adds the option to list interface-automatic-ports.
- Remove debug info from #618 fix.
7 February 2022: Wouter
- Fix that TCP interface does not use TLS when TLS is also configured.
4 February 2022: Wouter
- Fix #412: cache invalidation issue with CNAME+A.
3 February 2022: Wouter 3 February 2022: Wouter
- Fix for #611: Integer overflow in sldns_wire2str_pkt_scan. - Fix for #611: Integer overflow in sldns_wire2str_pkt_scan.
- Tag for 1.15.0rc1 created. That became 1.15.0 on 10 feb 2022.
The repository continues with version 1.15.1.
2 February 2022: George 2 February 2022: George
- Merge PR #532 from Shchelk: Fix: buffer overflow bug. - Merge PR #532 from Shchelk: Fix: buffer overflow bug.

View File

@ -1,4 +1,4 @@
README for Unbound 1.15.0 README for Unbound 1.16.0
Copyright 2007 NLnet Labs Copyright 2007 NLnet Labs
http://unbound.net http://unbound.net

View File

@ -1,7 +1,7 @@
# #
# Example configuration file. # Example configuration file.
# #
# See unbound.conf(5) man page, version 1.15.0. # See unbound.conf(5) man page, version 1.16.0.
# #
# this is a comment. # this is a comment.
@ -55,6 +55,10 @@ server:
# Socket options are not supported on all platforms. experimental. # Socket options are not supported on all platforms. experimental.
# interface-automatic: no # interface-automatic: no
# instead of the default port, open additional ports separated by
# spaces when interface-automatic is enabled, by listing them here.
# interface-automatic-ports: ""
# port to answer queries from # port to answer queries from
# port: 53 # port: 53
@ -811,6 +815,8 @@ server:
# Add system certs to the cert bundle, from the Windows Cert Store # Add system certs to the cert bundle, from the Windows Cert Store
# tls-win-cert: no # tls-win-cert: no
# and on other systems, the default openssl certificates
# tls-system-cert: no
# Pad queries over TLS upstreams # Pad queries over TLS upstreams
# pad-queries: yes # pad-queries: yes
@ -897,6 +903,14 @@ server:
# the number of servers that will be used in the fast server selection. # the number of servers that will be used in the fast server selection.
# fast-server-num: 3 # fast-server-num: 3
# Enable to attach Extended DNS Error codes (RFC8914) to responses.
# ede: no
# Enable to attach an Extended DNS Error (RFC8914) Code 3 - Stale
# Answer as EDNS0 option to expired responses.
# Note that the ede option above needs to be enabled for this to work.
# ede-serve-expired: no
# Specific options for ipsecmod. Unbound needs to be configured with # Specific options for ipsecmod. Unbound needs to be configured with
# --enable-ipsecmod for these to take effect. # --enable-ipsecmod for these to take effect.
# #

View File

@ -1,4 +1,4 @@
.TH "libunbound" "3" "Feb 10, 2022" "NLnet Labs" "unbound 1.15.0" .TH "libunbound" "3" "Jun 2, 2022" "NLnet Labs" "unbound 1.16.0"
.\" .\"
.\" libunbound.3 -- unbound library functions manual .\" libunbound.3 -- unbound library functions manual
.\" .\"
@ -44,7 +44,7 @@
.B ub_ctx_zone_remove, .B ub_ctx_zone_remove,
.B ub_ctx_data_add, .B ub_ctx_data_add,
.B ub_ctx_data_remove .B ub_ctx_data_remove
\- Unbound DNS validating resolver 1.15.0 functions. \- Unbound DNS validating resolver 1.16.0 functions.
.SH "SYNOPSIS" .SH "SYNOPSIS"
.B #include <unbound.h> .B #include <unbound.h>
.LP .LP

View File

@ -1,4 +1,4 @@
.TH "unbound-anchor" "8" "Feb 10, 2022" "NLnet Labs" "unbound 1.15.0" .TH "unbound-anchor" "8" "Jun 2, 2022" "NLnet Labs" "unbound 1.16.0"
.\" .\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual .\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\" .\"

View File

@ -1,4 +1,4 @@
.TH "unbound-checkconf" "8" "Feb 10, 2022" "NLnet Labs" "unbound 1.15.0" .TH "unbound-checkconf" "8" "Jun 2, 2022" "NLnet Labs" "unbound 1.16.0"
.\" .\"
.\" unbound-checkconf.8 -- unbound configuration checker manual .\" unbound-checkconf.8 -- unbound configuration checker manual
.\" .\"

View File

@ -1,4 +1,4 @@
.TH "unbound-control" "8" "Feb 10, 2022" "NLnet Labs" "unbound 1.15.0" .TH "unbound-control" "8" "Jun 2, 2022" "NLnet Labs" "unbound 1.16.0"
.\" .\"
.\" unbound-control.8 -- unbound remote control manual .\" unbound-control.8 -- unbound remote control manual
.\" .\"
@ -289,20 +289,22 @@ just the ratelimited ips, with their estimated qps. The ratelimited
ips are dropped before checking the cache. ips are dropped before checking the cache.
.TP .TP
.B list_auth_zones .B list_auth_zones
List the auth zones that are configured. Printed one per line with a List the auth zones that are configured. Printed one per line with a status,
status, indicating if the zone is expired and current serial number. indicating if the zone is expired and current serial number. Configured RPZ
zones are included.
.TP .TP
.B auth_zone_reload \fIzone\fR .B auth_zone_reload \fIzone\fR
Reload the auth zone from zonefile. The zonefile is read in overwriting Reload the auth zone (or RPZ zone) from zonefile. The zonefile is read in
the current contents of the zone in memory. This changes the auth zone overwriting the current contents of the zone in memory. This changes the auth
contents itself, not the cache contents. Such cache contents exists if zone contents itself, not the cache contents. Such cache contents exists if
you set Unbound to validate with for-upstream yes and that can be cleared you set Unbound to validate with for-upstream yes and that can be cleared with
with \fBflush_zone\fR \fIzone\fR. \fBflush_zone\fR \fIzone\fR.
.TP .TP
.B auth_zone_transfer \fIzone\fR .B auth_zone_transfer \fIzone\fR
Transfer the auth zone from master. The auth zone probe sequence is started, Transfer the auth zone (or RPZ zone) from master. The auth zone probe sequence
where the masters are probed to see if they have an updated zone (with the SOA is started, where the masters are probed to see if they have an updated zone
serial check). And then the zone is transferred for a newer zone version. (with the SOA serial check). And then the zone is transferred for a newer zone
version.
.TP .TP
.B rpz_enable \fIzone\fR .B rpz_enable \fIzone\fR
Enable the RPZ zone if it had previously been disabled. Enable the RPZ zone if it had previously been disabled.

View File

@ -1,4 +1,4 @@
.TH "unbound\-host" "1" "Feb 10, 2022" "NLnet Labs" "unbound 1.15.0" .TH "unbound\-host" "1" "Jun 2, 2022" "NLnet Labs" "unbound 1.16.0"
.\" .\"
.\" unbound-host.1 -- unbound DNS lookup utility .\" unbound-host.1 -- unbound DNS lookup utility
.\" .\"

View File

@ -1,4 +1,4 @@
.TH "unbound" "8" "Feb 10, 2022" "NLnet Labs" "unbound 1.15.0" .TH "unbound" "8" "Jun 2, 2022" "NLnet Labs" "unbound 1.16.0"
.\" .\"
.\" unbound.8 -- unbound manual .\" unbound.8 -- unbound manual
.\" .\"
@ -9,7 +9,7 @@
.\" .\"
.SH "NAME" .SH "NAME"
.B unbound .B unbound
\- Unbound DNS validating resolver 1.15.0. \- Unbound DNS validating resolver 1.16.0.
.SH "SYNOPSIS" .SH "SYNOPSIS"
.B unbound .B unbound
.RB [ \-h ] .RB [ \-h ]

View File

@ -1,4 +1,4 @@
.TH "unbound.conf" "5" "Feb 10, 2022" "NLnet Labs" "unbound 1.15.0" .TH "unbound.conf" "5" "Jun 2, 2022" "NLnet Labs" "unbound 1.16.0"
.\" .\"
.\" unbound.conf.5 -- unbound.conf manual .\" unbound.conf.5 -- unbound.conf manual
.\" .\"
@ -140,6 +140,15 @@ ip\-transparent you can select which (future) interfaces Unbound provides
service on. This feature is experimental, and needs support in your OS for service on. This feature is experimental, and needs support in your OS for
particular socket options. Default value is no. particular socket options. Default value is no.
.TP .TP
.B interface\-automatic\-ports: \fI<string>
List the port numbers that interface-automatic listens on. If empty, the
default port is listened on. The port numbers are separated by spaces in the
string. Default is "".
.IP
This can be used to have interface automatic to deal with the interface,
and listen on the normal port number, by including it in the list, and
also https or dns over tls port numbers by putting them in the list as well.
.TP
.B outgoing\-interface: \fI<ip address or ip6 netblock> .B outgoing\-interface: \fI<ip address or ip6 netblock>
Interface to use to connect to the network. This interface is used to send Interface to use to connect to the network. This interface is used to send
queries to authoritative servers and receive their replies. Can be given queries to authoritative servers and receive their replies. Can be given
@ -499,10 +508,11 @@ Enabled or disable whether the upstream queries use TLS only for transport.
Default is no. Useful in tunneling scenarios. The TLS contains plain DNS in Default is no. Useful in tunneling scenarios. The TLS contains plain DNS in
TCP wireformat. The other server must support this (see TCP wireformat. The other server must support this (see
\fBtls\-service\-key\fR). \fBtls\-service\-key\fR).
If you enable this, also configure a tls\-cert\-bundle or use tls\-win\-cert to If you enable this, also configure a tls\-cert\-bundle or use tls\-win\-cert or
load CA certs, otherwise the connections cannot be authenticated. tls\-system\-cert to load CA certs, otherwise the connections cannot be
This option enables TLS for all of them, but if you do not set this you can authenticated. This option enables TLS for all of them, but if you do not set
configure TLS specifically for some forward zones with forward\-tls\-upstream. And also with stub\-tls\-upstream. this you can configure TLS specifically for some forward zones with
forward\-tls\-upstream. And also with stub\-tls\-upstream.
.TP .TP
.B ssl\-upstream: \fI<yes or no> .B ssl\-upstream: \fI<yes or no>
Alternate syntax for \fBtls\-upstream\fR. If both are present in the config Alternate syntax for \fBtls\-upstream\fR. If both are present in the config
@ -551,7 +561,12 @@ Alternate syntax for \fBtls\-cert\-bundle\fR.
Add the system certificates to the cert bundle certificates for authentication. Add the system certificates to the cert bundle certificates for authentication.
If no cert bundle, it uses only these certificates. Default is no. If no cert bundle, it uses only these certificates. Default is no.
On windows this option uses the certificates from the cert store. Use On windows this option uses the certificates from the cert store. Use
the tls\-cert\-bundle option on other systems. the tls\-cert\-bundle option on other systems. On other systems, this option
enables the system certificates.
.TP
.B tls\-system\-cert: \fI<yes or no>
This the same setting as the tls\-win\-cert setting, under a different name.
Because it is not windows specific.
.TP .TP
.B tls\-additional\-port: \fI<portnr> .B tls\-additional\-port: \fI<portnr>
List portnumbers as tls\-additional\-port, and when interfaces are defined, List portnumbers as tls\-additional\-port, and when interfaces are defined,
@ -1320,7 +1335,17 @@ are authoritative DNS answers. By default the zones are class IN.
.IP .IP
If you need more complicated authoritative data, with referrals, wildcards, If you need more complicated authoritative data, with referrals, wildcards,
CNAME/DNAME support, or DNSSEC authoritative service, setup a stub\-zone for CNAME/DNAME support, or DNSSEC authoritative service, setup a stub\-zone for
it as detailed in the stub zone section below. it as detailed in the stub zone section below. A stub\-zone can be used to
have unbound send queries to another server, an authoritative server, to
fetch the information. With a forward\-zone, unbound sends queries to a server
that is a recursive server to fetch the information. With an auth\-zone a
zone can be loaded from file and used, it can be used like a local\-zone
for users downstream, or the auth\-zone information can be used to fetch
information from when resolving like it is an upstream server. The
forward\-zone and auth\-zone options are described in their sections below.
If you want to perform filtering of the information that the users can fetch,
the local\-zone and local\-data statements allow for this, but also the
rpz functionality can be used, described in the RPZ section.
.TP 10 .TP 10
\h'5'\fIdeny\fR \h'5'\fIdeny\fR
Do not send an answer, drop the query. Do not send an answer, drop the query.
@ -1761,6 +1786,21 @@ option can be used multiple times. The most specific match will be used.
EDNS0 option code for the \fIedns\-client\-string\fR option, from 0 to 65535. EDNS0 option code for the \fIedns\-client\-string\fR option, from 0 to 65535.
A value from the `Reserved for Local/Experimental` range (65001-65534) should A value from the `Reserved for Local/Experimental` range (65001-65534) should
be used. Default is 65001. be used. Default is 65001.
.TP 5
.B ede: \fI<yes or no>
If enabled, Unbound will respond with Extended DNS Error codes (RFC8914).
These EDEs attach informative error messages to a response for various
errors. Default is "no".
When the \fBval-log-level\fR option is also set to \fB2\fR, responses with
Extended DNS Errors concerning DNSSEC failures that are not served from cache,
will also contain a descriptive text message about the reason for the failure.
.TP
.B ede\-serve\-expired: \fI<yes or no>
If enabled, Unbound will attach an Extended DNS Error (RFC8914) Code 3 - Stale
Answer as EDNS0 option to the expired response. Note that this will not attach
the EDE code without setting the global \fBede\fR option to "yes" as well.
Default is "no".
.SS "Remote Control Options" .SS "Remote Control Options"
In the In the
.B remote\-control: .B remote\-control:
@ -1784,7 +1824,7 @@ Use 0.0.0.0 and ::0 to listen to all interfaces.
If you change this and permissions have been dropped, you must restart If you change this and permissions have been dropped, you must restart
the server for the change to take effect. the server for the change to take effect.
.IP .IP
If you set it to an absolute path, a local socket is used. The local socket If you set it to an absolute path, a unix domain socket is used. This socket
does not use the certificates and keys, so those files need not be present. does not use the certificates and keys, so those files need not be present.
To restrict access, Unbound sets permissions on the file to the user and To restrict access, Unbound sets permissions on the file to the user and
group that is configured, the access bits are set to allow the group members group that is configured, the access bits are set to allow the group members

View File

@ -97,8 +97,8 @@ subnet_new_qstate(struct module_qstate *qstate, int id)
} }
/** Add ecs struct to edns list, after parsing it to wire format. */ /** Add ecs struct to edns list, after parsing it to wire format. */
static void void
ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list, subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
struct module_qstate *qstate) struct module_qstate *qstate)
{ {
size_t sn_octs, sn_octs_remainder; size_t sn_octs, sn_octs_remainder;
@ -162,17 +162,21 @@ int ecs_whitelist_check(struct query_info* qinfo,
/* Address on whitelist or client query contains ECS option, we /* Address on whitelist or client query contains ECS option, we
* want to sent out ECS. Only add option if it is not already * want to sent out ECS. Only add option if it is not already
* set. */ * set. */
if(!(sq->subnet_sent)) { if(!edns_opt_list_find(qstate->edns_opts_back_out,
ecs_opt_list_append(&sq->ecs_server_out, qstate->env->cfg->client_subnet_opcode)) {
subnet_ecs_opt_list_append(&sq->ecs_server_out,
&qstate->edns_opts_back_out, qstate); &qstate->edns_opts_back_out, qstate);
}
sq->subnet_sent = 1; sq->subnet_sent = 1;
} }
} else {
else if(sq->subnet_sent) {
/* Outgoing ECS option is set, but we don't want to sent it to /* Outgoing ECS option is set, but we don't want to sent it to
* this address, remove option. */ * this address, remove option. */
if(edns_opt_list_find(qstate->edns_opts_back_out,
qstate->env->cfg->client_subnet_opcode)) {
edns_opt_list_remove(&qstate->edns_opts_back_out, edns_opt_list_remove(&qstate->edns_opts_back_out,
qstate->env->cfg->client_subnet_opcode); qstate->env->cfg->client_subnet_opcode);
}
sq->subnet_sent = 0; sq->subnet_sent = 0;
} }
return 1; return 1;
@ -227,7 +231,7 @@ subnetmod_init(struct module_env *env, int id)
env->unique_mesh = 1; env->unique_mesh = 1;
if(!edns_register_option(env->cfg->client_subnet_opcode, if(!edns_register_option(env->cfg->client_subnet_opcode,
env->cfg->client_subnet_always_forward /* bypass cache */, env->cfg->client_subnet_always_forward /* bypass cache */,
0 /* no aggregation */, env)) { 1 /* no aggregation */, env)) {
log_err("subnetcache: could not register opcode"); log_err("subnetcache: could not register opcode");
ecs_whitelist_delete(sn_env->whitelist); ecs_whitelist_delete(sn_env->whitelist);
slabhash_delete(sn_env->subnet_msg_cache); slabhash_delete(sn_env->subnet_msg_cache);
@ -598,7 +602,7 @@ parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs)
return 1; return 1;
} }
static void void
subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs, subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
struct config_file* cfg) struct config_file* cfg)
{ {
@ -761,7 +765,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
verbose(VERB_QUERY, "subnetcache: answered from cache"); verbose(VERB_QUERY, "subnetcache: answered from cache");
qstate->ext_state[id] = module_finished; qstate->ext_state[id] = module_finished;
ecs_opt_list_append(&sq->ecs_client_out, subnet_ecs_opt_list_append(&sq->ecs_client_out,
&qstate->edns_opts_front_out, qstate); &qstate->edns_opts_front_out, qstate);
return; return;
} }
@ -783,7 +787,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
sq->ecs_server_out.subnet_source_mask = sq->ecs_server_out.subnet_source_mask =
qstate->env->cfg->max_client_subnet_ipv6; qstate->env->cfg->max_client_subnet_ipv6;
/* Safe to copy completely, even if the source is limited by the /* Safe to copy completely, even if the source is limited by the
* configuration. ecs_opt_list_append() will limit the address. * configuration. subnet_ecs_opt_list_append() will limit the address.
* */ * */
memcpy(&sq->ecs_server_out.subnet_addr, memcpy(&sq->ecs_server_out.subnet_addr,
sq->ecs_client_in.subnet_addr, INET6_SIZE); sq->ecs_client_in.subnet_addr, INET6_SIZE);
@ -807,7 +811,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
qstate->ext_state[id] = eval_response(qstate, id, sq); qstate->ext_state[id] = eval_response(qstate, id, sq);
if(qstate->ext_state[id] == module_finished && if(qstate->ext_state[id] == module_finished &&
qstate->return_msg) { qstate->return_msg) {
ecs_opt_list_append(&sq->ecs_client_out, subnet_ecs_opt_list_append(&sq->ecs_client_out,
&qstate->edns_opts_front_out, qstate); &qstate->edns_opts_front_out, qstate);
} }
qstate->no_cache_store = sq->started_no_cache_store; qstate->no_cache_store = sq->started_no_cache_store;

View File

@ -143,4 +143,11 @@ int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
/** mark subnet msg to be deleted */ /** mark subnet msg to be deleted */
void subnet_markdel(void* key); void subnet_markdel(void* key);
/** Add ecs struct to edns list, after parsing it to wire format. */
void subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
struct module_qstate *qstate);
/** Create ecs_data from the sockaddr_storage information. */
void subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
struct config_file* cfg);
#endif /* SUBNETMOD_H */ #endif /* SUBNETMOD_H */

View File

@ -138,10 +138,10 @@ ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
static int static int
ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie, ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
struct mnl_socket *mnl, struct ub_packed_rrset_key *rrset, struct mnl_socket *mnl, struct ub_packed_rrset_key *rrset,
const char *setname, int af) const char *qname, const int qlen, const char *setname, int af)
{ {
static char dname[BUFF_LEN]; static char dname[BUFF_LEN];
const char *s; const char *ds, *qs;
int dlen, plen; int dlen, plen;
struct config_strlist *p; struct config_strlist *p;
@ -152,70 +152,73 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
log_err("bad domain name"); log_err("bad domain name");
return -1; return -1;
} }
if (dname[dlen - 1] == '.') {
dlen--;
}
for (p = env->cfg->local_zones_ipset; p; p = p->next) { for (p = env->cfg->local_zones_ipset; p; p = p->next) {
ds = NULL;
qs = NULL;
plen = strlen(p->str); plen = strlen(p->str);
if (dlen >= plen) { if (dlen >= plen) {
s = dname + (dlen - plen); ds = dname + (dlen - plen);
}
if (strncasecmp(p->str, s, plen) == 0) { if (qlen >= plen) {
qs = qname + (qlen - plen);
}
if ((ds && strncasecmp(p->str, ds, plen) == 0)
|| (qs && strncasecmp(p->str, qs, plen) == 0)) {
d = (struct packed_rrset_data*)rrset->entry.data; d = (struct packed_rrset_data*)rrset->entry.data;
ipset_add_rrset_data(ie, mnl, d, setname, ipset_add_rrset_data(ie, mnl, d, setname,
af, dname); af, dname);
break; break;
} }
} }
}
return 0; return 0;
} }
static int ipset_update(struct module_env *env, struct dns_msg *return_msg, struct ipset_env *ie) { static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
struct query_info qinfo, struct ipset_env *ie)
{
struct mnl_socket *mnl; struct mnl_socket *mnl;
size_t i; size_t i;
const char *setname; const char *setname;
struct ub_packed_rrset_key *rrset; struct ub_packed_rrset_key *rrset;
int af; int af;
static char qname[BUFF_LEN];
int qlen;
mnl = (struct mnl_socket *)ie->mnl; mnl = (struct mnl_socket *)ie->mnl;
if (!mnl) { if (!mnl) {
// retry to create mnl socket /* retry to create mnl socket */
mnl = open_mnl_socket(); mnl = open_mnl_socket();
if (!mnl) { if (!mnl) {
return -1; return -1;
} }
ie->mnl = mnl; ie->mnl = mnl;
} }
for (i = 0; i < return_msg->rep->rrset_count; ++i) { qlen = sldns_wire2str_dname_buf(qinfo.qname, qinfo.qname_len,
qname, BUFF_LEN);
if(qlen == 0) {
log_err("bad domain name");
return -1;
}
for(i = 0; i < return_msg->rep->rrset_count; i++) {
setname = NULL; setname = NULL;
rrset = return_msg->rep->rrsets[i]; rrset = return_msg->rep->rrsets[i];
if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A &&
if (rrset->rk.type == htons(LDNS_RR_TYPE_A)) { ie->v4_enabled == 1) {
af = AF_INET; af = AF_INET;
if ((ie->v4_enabled == 1)) {
setname = ie->name_v4; setname = ie->name_v4;
} } else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA &&
} else { ie->v6_enabled == 1) {
af = AF_INET6; af = AF_INET6;
if ((ie->v6_enabled == 1)) {
setname = ie->name_v6; setname = ie->name_v6;
} }
}
if (setname) { if (setname) {
if(ipset_check_zones_for_rrset(env, ie, mnl, rrset, if(ipset_check_zones_for_rrset(env, ie, mnl, rrset,
setname, af) == -1) qname, qlen, setname, af) == -1)
return -1; return -1;
} }
} }
@ -311,7 +314,7 @@ void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id,
if (iq && (event == module_event_moddone)) { if (iq && (event == module_event_moddone)) {
if (qstate->return_msg && qstate->return_msg->rep) { if (qstate->return_msg && qstate->return_msg->rep) {
ipset_update(qstate->env, qstate->return_msg, ie); ipset_update(qstate->env, qstate->return_msg, qstate->qinfo, ie);
} }
qstate->ext_state[id] = module_finished; qstate->ext_state[id] = module_finished;
return; return;

View File

@ -128,7 +128,7 @@ struct delegpt_ns {
uint8_t done_pside6; uint8_t done_pside6;
/** the TLS authentication name, (if not NULL) to use. */ /** the TLS authentication name, (if not NULL) to use. */
char* tls_auth_name; char* tls_auth_name;
/** the port to use; it should mosty be the default 53 but configured /** the port to use; it should mostly be the default 53 but configured
* upstreams can provide nondefault ports. */ * upstreams can provide nondefault ports. */
int port; int port;
}; };

View File

@ -743,9 +743,10 @@ iter_mark_pside_cycle_targets(struct module_qstate* qstate, struct delegpt* dp)
int int
iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
struct delegpt* dp) struct delegpt* dp, int supports_ipv4, int supports_ipv6)
{ {
struct delegpt_ns* ns; struct delegpt_ns* ns;
struct delegpt_addr* a;
/* check: /* check:
* o RD qflag is on. * o RD qflag is on.
* o no addresses are provided. * o no addresses are provided.
@ -758,13 +759,24 @@ iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
*/ */
if(!(qflags&BIT_RD)) if(!(qflags&BIT_RD))
return 0; return 0;
/* either available or unused targets */ /* either available or unused targets,
if(dp->usable_list || dp->result_list) * if they exist, the dp is not useless. */
for(a = dp->usable_list; a; a = a->next_usable) {
if(!addr_is_ip6(&a->addr, a->addrlen) && supports_ipv4)
return 0; return 0;
else if(addr_is_ip6(&a->addr, a->addrlen) && supports_ipv6)
return 0;
}
for(a = dp->result_list; a; a = a->next_result) {
if(!addr_is_ip6(&a->addr, a->addrlen) && supports_ipv4)
return 0;
else if(addr_is_ip6(&a->addr, a->addrlen) && supports_ipv6)
return 0;
}
/* see if query is for one of the nameservers, which is glue */ /* see if query is for one of the nameservers, which is glue */
if( (qinfo->qtype == LDNS_RR_TYPE_A || if( ((qinfo->qtype == LDNS_RR_TYPE_A && supports_ipv4) ||
qinfo->qtype == LDNS_RR_TYPE_AAAA) && (qinfo->qtype == LDNS_RR_TYPE_AAAA && supports_ipv6)) &&
dname_subdomain_c(qinfo->qname, dp->name) && dname_subdomain_c(qinfo->qname, dp->name) &&
delegpt_find_ns(dp, qinfo->qname, qinfo->qname_len)) delegpt_find_ns(dp, qinfo->qname, qinfo->qname_len))
return 1; return 1;

View File

@ -175,10 +175,14 @@ void iter_mark_pside_cycle_targets(struct module_qstate* qstate,
* @param qinfo: query name and type * @param qinfo: query name and type
* @param qflags: query flags with RD flag * @param qflags: query flags with RD flag
* @param dp: delegpt to check. * @param dp: delegpt to check.
* @param supports_ipv4: if we support ipv4 for lookups to the target.
* if not, then the IPv4 addresses are useless.
* @param supports_ipv6: if we support ipv6 for lookups to the target.
* if not, then the IPv6 addresses are useless.
* @return true if dp is useless. * @return true if dp is useless.
*/ */
int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
struct delegpt* dp); struct delegpt* dp, int supports_ipv4, int supports_ipv6);
/** /**
* See if qname has DNSSEC needs. This is true if there is a trust anchor above * See if qname has DNSSEC needs. This is true if there is a trust anchor above

View File

@ -1547,7 +1547,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
* same server reply) if useless-checked. * same server reply) if useless-checked.
*/ */
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags, if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
iq->dp)) { iq->dp, ie->supports_ipv4, ie->supports_ipv6)) {
struct delegpt* retdp = NULL; struct delegpt* retdp = NULL;
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) { if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) {
if(retdp) { if(retdp) {
@ -1831,6 +1831,23 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
int missing; int missing;
int toget = 0; int toget = 0;
iter_mark_cycle_targets(qstate, iq->dp);
missing = (int)delegpt_count_missing_targets(iq->dp);
log_assert(maxtargets != 0); /* that would not be useful */
/* Generate target requests. Basically, any missing targets
* are queried for here, regardless if it is necessary to do
* so to continue processing. */
if(maxtargets < 0 || maxtargets > missing)
toget = missing;
else toget = maxtargets;
if(toget == 0) {
*num = 0;
return 1;
}
/* now that we are sure that a target query is going to be made,
* check the limits. */
if(iq->depth == ie->max_dependency_depth) if(iq->depth == ie->max_dependency_depth)
return 0; return 0;
if(iq->depth > 0 && iq->target_count && if(iq->depth > 0 && iq->target_count &&
@ -1850,20 +1867,6 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
return 0; return 0;
} }
iter_mark_cycle_targets(qstate, iq->dp);
missing = (int)delegpt_count_missing_targets(iq->dp);
log_assert(maxtargets != 0); /* that would not be useful */
/* Generate target requests. Basically, any missing targets
* are queried for here, regardless if it is necessary to do
* so to continue processing. */
if(maxtargets < 0 || maxtargets > missing)
toget = missing;
else toget = maxtargets;
if(toget == 0) {
*num = 0;
return 1;
}
/* select 'toget' items from the total of 'missing' items */ /* select 'toget' items from the total of 'missing' items */
log_assert(toget <= missing); log_assert(toget <= missing);
@ -2512,7 +2515,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
iq->response = forged_response; iq->response = forged_response;
next_state(iq, FINISHED_STATE); next_state(iq, FINISHED_STATE);
if(!iter_prepend(iq, qstate->return_msg, qstate->region)) { if(!iter_prepend(iq, qstate->return_msg, qstate->region)) {
log_err("rpz, prepend rrsets: out of memory"); log_err("rpz: prepend rrsets: out of memory");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL); return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
} }
return 0; return 0;
@ -2832,7 +2835,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
} }
if(!qstate->no_cache_store) if(!qstate->no_cache_store)
iter_dns_store(qstate->env, &iq->response->qinfo, iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 0, qstate->prefetch_leeway, iq->response->rep,
iq->qchase.qtype != iq->response->qinfo.qtype,
qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS, iq->dp&&iq->dp->has_parent_side_NS,
qstate->region, qstate->query_flags); qstate->region, qstate->query_flags);
/* close down outstanding requests to be discarded */ /* close down outstanding requests to be discarded */
@ -3067,7 +3072,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iq->response = forged_response; iq->response = forged_response;
next_state(iq, FINISHED_STATE); next_state(iq, FINISHED_STATE);
if(!iter_prepend(iq, qstate->return_msg, qstate->region)) { if(!iter_prepend(iq, qstate->return_msg, qstate->region)) {
log_err("rpz after cname, prepend rrsets: out of memory"); log_err("rpz: after cname, prepend rrsets: out of memory");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL); return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
} }
qstate->return_msg->qinfo = qstate->qinfo; qstate->return_msg->qinfo = qstate->qinfo;

View File

@ -650,7 +650,7 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
} }
/* process new query */ /* process new query */
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
w->back->udp_buff, qid, libworker_fg_done_cb, q)) { w->back->udp_buff, qid, libworker_fg_done_cb, q, 0)) {
free(qinfo.qname); free(qinfo.qname);
return UB_NOMEM; return UB_NOMEM;
} }
@ -730,7 +730,7 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
if(async_id) if(async_id)
*async_id = q->querynum; *async_id = q->querynum;
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
w->back->udp_buff, qid, libworker_event_done_cb, q)) { w->back->udp_buff, qid, libworker_event_done_cb, q, 0)) {
free(qinfo.qname); free(qinfo.qname);
return UB_NOMEM; return UB_NOMEM;
} }
@ -867,7 +867,7 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
q->w = w; q->w = w;
/* process new query */ /* process new query */
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
w->back->udp_buff, qid, libworker_bg_done_cb, q)) { w->back->udp_buff, qid, libworker_bg_done_cb, q, 0)) {
add_bg_result(w, q, NULL, UB_NOMEM, NULL, 0); add_bg_result(w, q, NULL, UB_NOMEM, NULL, 0);
} }
free(qinfo.qname); free(qinfo.qname);

View File

@ -833,8 +833,11 @@ static int
respip_use_rpz(struct resp_addr* raddr, struct rpz* r, respip_use_rpz(struct resp_addr* raddr, struct rpz* r,
enum respip_action* action, enum respip_action* action,
struct ub_packed_rrset_key** data, int* rpz_log, char** log_name, struct ub_packed_rrset_key** data, int* rpz_log, char** log_name,
int* rpz_cname_override, struct regional* region, int* is_rpz) int* rpz_cname_override, struct regional* region, int* is_rpz,
int* rpz_passthru)
{ {
if(rpz_passthru && *rpz_passthru)
return 0;
if(r->action_override == RPZ_DISABLED_ACTION) { if(r->action_override == RPZ_DISABLED_ACTION) {
*is_rpz = 0; *is_rpz = 0;
return 1; return 1;
@ -848,6 +851,9 @@ respip_use_rpz(struct resp_addr* raddr, struct rpz* r,
*data = r->cname_override; *data = r->cname_override;
*rpz_cname_override = 1; *rpz_cname_override = 1;
} }
if(*action == respip_always_transparent /* RPZ_PASSTHRU_ACTION */
&& rpz_passthru)
*rpz_passthru = 1;
*rpz_log = r->log; *rpz_log = r->log;
if(r->log_name) if(r->log_name)
if(!(*log_name = regional_strdup(region, r->log_name))) if(!(*log_name = regional_strdup(region, r->log_name)))
@ -861,7 +867,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
const struct respip_client_info* cinfo, const struct reply_info* rep, const struct respip_client_info* cinfo, const struct reply_info* rep,
struct reply_info** new_repp, struct respip_action_info* actinfo, struct reply_info** new_repp, struct respip_action_info* actinfo,
struct ub_packed_rrset_key** alias_rrset, int search_only, struct ub_packed_rrset_key** alias_rrset, int search_only,
struct regional* region, struct auth_zones* az) struct regional* region, struct auth_zones* az, int* rpz_passthru)
{ {
const uint8_t* ctaglist; const uint8_t* ctaglist;
size_t ctaglen; size_t ctaglen;
@ -934,7 +940,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
ipset->tagname, ipset->num_tags); ipset->tagname, ipset->num_tags);
} }
lock_rw_rdlock(&az->rpz_lock); lock_rw_rdlock(&az->rpz_lock);
for(a = az->rpz_first; a && !raddr; a = a->rpz_az_next) { for(a = az->rpz_first; a && !raddr && !(rpz_passthru && *rpz_passthru); a = a->rpz_az_next) {
lock_rw_rdlock(&a->lock); lock_rw_rdlock(&a->lock);
r = a->rpz; r = a->rpz;
if(!r->taglist || taglist_intersect(r->taglist, if(!r->taglist || taglist_intersect(r->taglist,
@ -943,7 +949,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
r->respip_set, &rrset_id, &rr_id))) { r->respip_set, &rrset_id, &rr_id))) {
if(!respip_use_rpz(raddr, r, &action, &data, if(!respip_use_rpz(raddr, r, &action, &data,
&rpz_log, &log_name, &rpz_cname_override, &rpz_log, &log_name, &rpz_cname_override,
region, &rpz_used)) { region, &rpz_used, rpz_passthru)) {
log_err("out of memory"); log_err("out of memory");
lock_rw_unlock(&raddr->lock); lock_rw_unlock(&raddr->lock);
lock_rw_unlock(&a->lock); lock_rw_unlock(&a->lock);
@ -964,7 +970,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
addr_to_str(&raddr->node.addr, addr_to_str(&raddr->node.addr,
raddr->node.addrlen, raddr->node.addrlen,
nm, sizeof(nm)); nm, sizeof(nm));
verbose(VERB_ALGO, "respip: rpz response-ip trigger %s/%d on %s %s with action %s", nm, raddr->node.net, qn, ip, rpz_action_to_string(respip_action_to_rpz_action(action))); verbose(VERB_ALGO, "respip: rpz: response-ip trigger %s/%d on %s %s with action %s", nm, raddr->node.net, qn, ip, rpz_action_to_string(respip_action_to_rpz_action(action)));
} }
/* break to make sure 'a' stays pointed /* break to make sure 'a' stays pointed
* to used auth_zone, and keeps lock */ * to used auth_zone, and keeps lock */
@ -1094,7 +1100,8 @@ respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
if(!respip_rewrite_reply(&qstate->qinfo, if(!respip_rewrite_reply(&qstate->qinfo,
qstate->client_info, qstate->return_msg->rep, qstate->client_info, qstate->return_msg->rep,
&new_rep, &actinfo, &alias_rrset, 0, &new_rep, &actinfo, &alias_rrset, 0,
qstate->region, qstate->env->auth_zones)) { qstate->region, qstate->env->auth_zones,
&qstate->rpz_passthru)) {
goto servfail; goto servfail;
} }
if(actinfo.action != respip_none) { if(actinfo.action != respip_none) {
@ -1169,7 +1176,7 @@ respip_merge_cname(struct reply_info* base_rep,
/* see if the target reply would be subject to a response-ip action. */ /* see if the target reply would be subject to a response-ip action. */
if(!respip_rewrite_reply(qinfo, cinfo, tgt_rep, &tmp_rep, &actinfo, if(!respip_rewrite_reply(qinfo, cinfo, tgt_rep, &tmp_rep, &actinfo,
&alias_rrset, 1, region, az)) &alias_rrset, 1, region, az, NULL))
return 0; return 0;
if(actinfo.action != respip_none) { if(actinfo.action != respip_none) {
log_info("CNAME target of redirect response-ip action would " log_info("CNAME target of redirect response-ip action would "
@ -1301,7 +1308,7 @@ respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
respip, sizeof(respip)); respip, sizeof(respip));
if(respip_actinfo->rpz_log) { if(respip_actinfo->rpz_log) {
txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen, "%s", txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen, "%s",
"RPZ applied "); "rpz: applied ");
if(respip_actinfo->rpz_cname_override) if(respip_actinfo->rpz_cname_override)
actionstr = rpz_action_to_string( actionstr = rpz_action_to_string(
RPZ_CNAME_OVERRIDE_ACTION); RPZ_CNAME_OVERRIDE_ACTION);

View File

@ -176,6 +176,8 @@ int respip_merge_cname(struct reply_info* base_rep,
* will be set (or intact) accordingly but the modified reply won't be built. * will be set (or intact) accordingly but the modified reply won't be built.
* @param az: auth zones containing RPZ information. * @param az: auth zones containing RPZ information.
* @param region: allocator to build *new_repp. * @param region: allocator to build *new_repp.
* @param rpz_passthru: keeps track of query state can have passthru that
* stops further rpz processing. Or NULL for cached answer processing.
* @return 1 on success, 0 on error. * @return 1 on success, 0 on error.
*/ */
int respip_rewrite_reply(const struct query_info* qinfo, int respip_rewrite_reply(const struct query_info* qinfo,
@ -183,7 +185,8 @@ int respip_rewrite_reply(const struct query_info* qinfo,
const struct reply_info *rep, struct reply_info** new_repp, const struct reply_info *rep, struct reply_info** new_repp,
struct respip_action_info* actinfo, struct respip_action_info* actinfo,
struct ub_packed_rrset_key** alias_rrset, struct ub_packed_rrset_key** alias_rrset,
int search_only, struct regional* region, struct auth_zones* az); int search_only, struct regional* region, struct auth_zones* az,
int* rpz_passthru);
/** /**
* Get the response-ip function block. * Get the response-ip function block.

View File

@ -132,6 +132,7 @@ msg_create(struct regional* region, struct query_info* qinfo)
return NULL; return NULL;
msg->rep->flags = (uint16_t)(BIT_QR | BIT_AA); msg->rep->flags = (uint16_t)(BIT_QR | BIT_AA);
msg->rep->authoritative = 1; msg->rep->authoritative = 1;
msg->rep->reason_bogus = LDNS_EDE_NONE;
msg->rep->qdcount = 1; msg->rep->qdcount = 1;
/* rrsets is NULL, no rrsets yet */ /* rrsets is NULL, no rrsets yet */
return msg; return msg;
@ -1882,6 +1883,8 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
struct regional* region = NULL; struct regional* region = NULL;
struct sldns_buffer* buf = NULL; struct sldns_buffer* buf = NULL;
uint32_t soa_serial = 0; uint32_t soa_serial = 0;
char* unsupported_reason = NULL;
int only_unsupported = 1;
region = env->scratch; region = env->scratch;
regional_free_all(region); regional_free_all(region);
buf = env->scratch_buffer; buf = env->scratch_buffer;
@ -1911,6 +1914,7 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
&hashalgo, &hash, &hashlen)) { &hashalgo, &hash, &hashlen)) {
/* malformed RR */ /* malformed RR */
*reason = "ZONEMD rdata malformed"; *reason = "ZONEMD rdata malformed";
only_unsupported = 0;
continue; continue;
} }
/* check for duplicates */ /* check for duplicates */
@ -1920,25 +1924,51 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
* is not allowed. */ * is not allowed. */
*reason = "ZONEMD RRSet contains more than one RR " *reason = "ZONEMD RRSet contains more than one RR "
"with the same scheme and hash algorithm"; "with the same scheme and hash algorithm";
only_unsupported = 0;
continue; continue;
} }
regional_free_all(region); regional_free_all(region);
if(serial != soa_serial) { if(serial != soa_serial) {
*reason = "ZONEMD serial is wrong"; *reason = "ZONEMD serial is wrong";
only_unsupported = 0;
continue; continue;
} }
*reason = NULL;
if(auth_zone_generate_zonemd_check(z, scheme, hashalgo, if(auth_zone_generate_zonemd_check(z, scheme, hashalgo,
hash, hashlen, region, buf, reason)) { hash, hashlen, region, buf, reason)) {
/* success */ /* success */
if(*reason) {
if(!unsupported_reason)
unsupported_reason = *reason;
/* continue to check for valid ZONEMD */
if(verbosity >= VERB_ALGO) { if(verbosity >= VERB_ALGO) {
char zstr[255+1]; char zstr[255+1];
dname_str(z->name, zstr); dname_str(z->name, zstr);
verbose(VERB_ALGO, "auth-zone %s ZONEMD %d %d is unsupported: %s", zstr, (int)scheme, (int)hashalgo, *reason);
}
*reason = NULL;
continue;
}
if(verbosity >= VERB_ALGO) {
char zstr[255+1];
dname_str(z->name, zstr);
if(!*reason)
verbose(VERB_ALGO, "auth-zone %s ZONEMD hash is correct", zstr); verbose(VERB_ALGO, "auth-zone %s ZONEMD hash is correct", zstr);
} }
return 1; return 1;
} }
only_unsupported = 0;
/* try next one */ /* try next one */
} }
/* have we seen no failures but only unsupported algo,
* and one unsupported algorithm, or more. */
if(only_unsupported && unsupported_reason) {
/* only unsupported algorithms, with valid serial, not
* malformed. Did not see supported algorithms, failed or
* successful ones. */
*reason = unsupported_reason;
return 1;
}
/* fail, we may have reason */ /* fail, we may have reason */
if(!*reason) if(!*reason)
*reason = "no ZONEMD records found"; *reason = "no ZONEMD records found";
@ -4456,7 +4486,7 @@ chunkline_get_line_collated(struct auth_chunk** chunk, size_t* chunk_pos,
return 1; return 1;
} }
/** process $ORIGIN for http */ /** process $ORIGIN for http, 0 nothing, 1 done, 2 error */
static int static int
http_parse_origin(sldns_buffer* buf, struct sldns_file_parse_state* pstate) http_parse_origin(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
{ {
@ -4467,13 +4497,16 @@ http_parse_origin(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
pstate->origin_len = sizeof(pstate->origin); pstate->origin_len = sizeof(pstate->origin);
s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8), s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8),
pstate->origin, &pstate->origin_len); pstate->origin, &pstate->origin_len);
if(s) pstate->origin_len = 0; if(s) {
pstate->origin_len = 0;
return 2;
}
return 1; return 1;
} }
return 0; return 0;
} }
/** process $TTL for http */ /** process $TTL for http, 0 nothing, 1 done, 2 error */
static int static int
http_parse_ttl(sldns_buffer* buf, struct sldns_file_parse_state* pstate) http_parse_ttl(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
{ {
@ -4481,8 +4514,12 @@ http_parse_ttl(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
if(strncmp(line, "$TTL", 4) == 0 && if(strncmp(line, "$TTL", 4) == 0 &&
isspace((unsigned char)line[4])) { isspace((unsigned char)line[4])) {
const char* end = NULL; const char* end = NULL;
int overflow = 0;
pstate->default_ttl = sldns_str2period( pstate->default_ttl = sldns_str2period(
sldns_strip_ws(line+5), &end); sldns_strip_ws(line+5), &end, &overflow);
if(overflow) {
return 2;
}
return 1; return 1;
} }
return 0; return 0;
@ -4493,15 +4530,20 @@ static int
chunkline_non_comment_RR(struct auth_chunk** chunk, size_t* chunk_pos, chunkline_non_comment_RR(struct auth_chunk** chunk, size_t* chunk_pos,
sldns_buffer* buf, struct sldns_file_parse_state* pstate) sldns_buffer* buf, struct sldns_file_parse_state* pstate)
{ {
int ret;
while(chunkline_get_line_collated(chunk, chunk_pos, buf)) { while(chunkline_get_line_collated(chunk, chunk_pos, buf)) {
if(chunkline_is_comment_line_or_empty(buf)) { if(chunkline_is_comment_line_or_empty(buf)) {
/* a comment, go to next line */ /* a comment, go to next line */
continue; continue;
} }
if(http_parse_origin(buf, pstate)) { if((ret=http_parse_origin(buf, pstate))!=0) {
if(ret == 2)
return 0;
continue; /* $ORIGIN has been handled */ continue; /* $ORIGIN has been handled */
} }
if(http_parse_ttl(buf, pstate)) { if((ret=http_parse_ttl(buf, pstate))!=0) {
if(ret == 2)
return 0;
continue; /* $TTL has been handled */ continue; /* $TTL has been handled */
} }
return 1; return 1;
@ -5007,6 +5049,7 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z,
struct sldns_file_parse_state pstate; struct sldns_file_parse_state pstate;
struct auth_chunk* chunk; struct auth_chunk* chunk;
size_t chunk_pos; size_t chunk_pos;
int ret;
memset(&pstate, 0, sizeof(pstate)); memset(&pstate, 0, sizeof(pstate));
pstate.default_ttl = 3600; pstate.default_ttl = 3600;
if(xfr->namelen < sizeof(pstate.origin)) { if(xfr->namelen < sizeof(pstate.origin)) {
@ -5063,10 +5106,24 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z,
continue; continue;
} }
/* parse line and add RR */ /* parse line and add RR */
if(http_parse_origin(scratch_buffer, &pstate)) { if((ret=http_parse_origin(scratch_buffer, &pstate))!=0) {
if(ret == 2) {
verbose(VERB_ALGO, "error parsing ORIGIN on line [%s:%d] %s",
xfr->task_transfer->master->file,
pstate.lineno,
sldns_buffer_begin(scratch_buffer));
return 0;
}
continue; /* $ORIGIN has been handled */ continue; /* $ORIGIN has been handled */
} }
if(http_parse_ttl(scratch_buffer, &pstate)) { if((ret=http_parse_ttl(scratch_buffer, &pstate))!=0) {
if(ret == 2) {
verbose(VERB_ALGO, "error parsing TTL on line [%s:%d] %s",
xfr->task_transfer->master->file,
pstate.lineno,
sldns_buffer_begin(scratch_buffer));
return 0;
}
continue; /* $TTL has been handled */ continue; /* $TTL has been handled */
} }
if(!http_parse_add_rr(xfr, z, scratch_buffer, &pstate)) { if(!http_parse_add_rr(xfr, z, scratch_buffer, &pstate)) {
@ -5370,7 +5427,7 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
* called straight away */ * called straight away */
lock_basic_unlock(&xfr->lock); lock_basic_unlock(&xfr->lock);
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
&auth_xfer_transfer_lookup_callback, xfr)) { &auth_xfer_transfer_lookup_callback, xfr, 0)) {
lock_basic_lock(&xfr->lock); lock_basic_lock(&xfr->lock);
log_err("out of memory lookup up master %s", master->host); log_err("out of memory lookup up master %s", master->host);
return 0; return 0;
@ -6561,7 +6618,7 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
* called straight away */ * called straight away */
lock_basic_unlock(&xfr->lock); lock_basic_unlock(&xfr->lock);
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
&auth_xfer_probe_lookup_callback, xfr)) { &auth_xfer_probe_lookup_callback, xfr, 0)) {
lock_basic_lock(&xfr->lock); lock_basic_lock(&xfr->lock);
log_err("out of memory lookup up master %s", master->host); log_err("out of memory lookup up master %s", master->host);
return 0; return 0;
@ -7632,13 +7689,16 @@ int auth_zone_generate_zonemd_check(struct auth_zone* z, int scheme,
{ {
uint8_t gen[512]; uint8_t gen[512];
size_t genlen = 0; size_t genlen = 0;
*reason = NULL;
if(!zonemd_hashalgo_supported(hashalgo)) { if(!zonemd_hashalgo_supported(hashalgo)) {
/* allow it */
*reason = "unsupported algorithm"; *reason = "unsupported algorithm";
return 0; return 1;
} }
if(!zonemd_scheme_supported(scheme)) { if(!zonemd_scheme_supported(scheme)) {
/* allow it */
*reason = "unsupported scheme"; *reason = "unsupported scheme";
return 0; return 1;
} }
if(hashlen < 12) { if(hashlen < 12) {
/* the ZONEMD draft requires digests to fail if too small */ /* the ZONEMD draft requires digests to fail if too small */
@ -7726,7 +7786,7 @@ static int zonemd_dnssec_verify_rrset(struct auth_zone* z,
auth_zone_log(z->name, VERB_ALGO, auth_zone_log(z->name, VERB_ALGO,
"zonemd: verify %s RRset with DNSKEY", typestr); "zonemd: verify %s RRset with DNSKEY", typestr);
} }
sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, sigalg, why_bogus, sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, sigalg, why_bogus, NULL,
LDNS_SECTION_ANSWER, NULL); LDNS_SECTION_ANSWER, NULL);
if(sec == sec_status_secure) { if(sec == sec_status_secure) {
return 1; return 1;
@ -8003,9 +8063,13 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
} }
/* success! log the success */ /* success! log the success */
auth_zone_log(z->name, VERB_ALGO, "ZONEMD verification successful"); if(reason)
auth_zone_log(z->name, VERB_ALGO, "ZONEMD %s", reason);
else auth_zone_log(z->name, VERB_ALGO, "ZONEMD verification successful");
if(result) { if(result) {
*result = strdup("ZONEMD verification successful"); if(reason)
*result = strdup(reason);
else *result = strdup("ZONEMD verification successful");
if(!*result) log_err("out of memory"); if(!*result) log_err("out of memory");
} }
} }
@ -8065,7 +8129,7 @@ zonemd_get_dnskey_from_anchor(struct auth_zone* z, struct module_env* env,
auth_zone_log(z->name, VERB_QUERY, auth_zone_log(z->name, VERB_QUERY,
"zonemd: verify DNSKEY RRset with trust anchor"); "zonemd: verify DNSKEY RRset with trust anchor");
sec = val_verify_DNSKEY_with_TA(env, ve, keystorage, anchor->ds_rrset, sec = val_verify_DNSKEY_with_TA(env, ve, keystorage, anchor->ds_rrset,
anchor->dnskey_rrset, NULL, why_bogus, NULL); anchor->dnskey_rrset, NULL, why_bogus, NULL, NULL);
regional_free_all(env->scratch); regional_free_all(env->scratch);
if(sec == sec_status_secure) { if(sec == sec_status_secure) {
/* success */ /* success */
@ -8123,8 +8187,9 @@ auth_zone_verify_zonemd_key_with_ds(struct auth_zone* z,
keystorage->rk.type = htons(LDNS_RR_TYPE_DNSKEY); keystorage->rk.type = htons(LDNS_RR_TYPE_DNSKEY);
keystorage->rk.rrset_class = htons(z->dclass); keystorage->rk.rrset_class = htons(z->dclass);
auth_zone_log(z->name, VERB_QUERY, "zonemd: verify zone DNSKEY with DS"); auth_zone_log(z->name, VERB_QUERY, "zonemd: verify zone DNSKEY with DS");
// @TODO add EDE here? we currently just pass NULL
sec = val_verify_DNSKEY_with_DS(env, ve, keystorage, ds, sigalg, sec = val_verify_DNSKEY_with_DS(env, ve, keystorage, ds, sigalg,
why_bogus, NULL); why_bogus, NULL, NULL);
regional_free_all(env->scratch); regional_free_all(env->scratch);
if(sec == sec_status_secure) { if(sec == sec_status_secure) {
/* success */ /* success */
@ -8340,7 +8405,7 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env)
/* the callback can be called straight away */ /* the callback can be called straight away */
lock_rw_unlock(&z->lock); lock_rw_unlock(&z->lock);
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
&auth_zonemd_dnskey_lookup_callback, z)) { &auth_zonemd_dnskey_lookup_callback, z, 0)) {
lock_rw_wrlock(&z->lock); lock_rw_wrlock(&z->lock);
log_err("out of memory lookup of %s for zonemd", log_err("out of memory lookup of %s for zonemd",
(fetch_ds?"DS":"DNSKEY")); (fetch_ds?"DS":"DNSKEY"));

View File

@ -747,6 +747,9 @@ int zonemd_scheme_supported(int scheme);
* @param region: temp region for allocs during canonicalisation. * @param region: temp region for allocs during canonicalisation.
* @param buf: temp buffer during canonicalisation. * @param buf: temp buffer during canonicalisation.
* @param reason: string returned with failure reason. * @param reason: string returned with failure reason.
* If the hash cannot be checked, but it is allowed, for unknown
* algorithms, the routine returns success, and the reason is nonNULL,
* with the allowance reason.
* @return false on failure. * @return false on failure.
*/ */
int auth_zone_generate_zonemd_check(struct auth_zone* z, int scheme, int auth_zone_generate_zonemd_check(struct auth_zone* z, int scheme,

View File

@ -428,6 +428,7 @@ dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype,
return NULL; /* integer overflow protection */ return NULL; /* integer overflow protection */
msg->rep->flags = BIT_QR; /* with QR, no AA */ msg->rep->flags = BIT_QR; /* with QR, no AA */
msg->rep->qdcount = 1; msg->rep->qdcount = 1;
msg->rep->reason_bogus = LDNS_EDE_NONE;
msg->rep->rrsets = (struct ub_packed_rrset_key**) msg->rep->rrsets = (struct ub_packed_rrset_key**)
regional_alloc(region, regional_alloc(region,
capacity*sizeof(struct ub_packed_rrset_key*)); capacity*sizeof(struct ub_packed_rrset_key*));
@ -524,6 +525,7 @@ gen_dns_msg(struct regional* region, struct query_info* q, size_t num)
sizeof(struct reply_info) - sizeof(struct rrset_ref)); sizeof(struct reply_info) - sizeof(struct rrset_ref));
if(!msg->rep) if(!msg->rep)
return NULL; return NULL;
msg->rep->reason_bogus = LDNS_EDE_NONE;
if(num > RR_COUNT_MAX) if(num > RR_COUNT_MAX)
return NULL; /* integer overflow protection */ return NULL; /* integer overflow protection */
msg->rep->rrsets = (struct ub_packed_rrset_key**) msg->rep->rrsets = (struct ub_packed_rrset_key**)
@ -577,6 +579,7 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
msg->rep->ar_numrrsets = r->ar_numrrsets; msg->rep->ar_numrrsets = r->ar_numrrsets;
msg->rep->rrset_count = r->rrset_count; msg->rep->rrset_count = r->rrset_count;
msg->rep->authoritative = r->authoritative; msg->rep->authoritative = r->authoritative;
msg->rep->reason_bogus = r->reason_bogus;
if(!rrset_array_lock(r->ref, r->rrset_count, now_control)) { if(!rrset_array_lock(r->ref, r->rrset_count, now_control)) {
return NULL; return NULL;
} }
@ -632,6 +635,7 @@ rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
msg->rep->ns_numrrsets = 0; msg->rep->ns_numrrsets = 0;
msg->rep->ar_numrrsets = 0; msg->rep->ar_numrrsets = 0;
msg->rep->rrset_count = 1; msg->rep->rrset_count = 1;
msg->rep->reason_bogus = LDNS_EDE_NONE;
msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now); msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now);
if(!msg->rep->rrsets[0]) /* copy CNAME */ if(!msg->rep->rrsets[0]) /* copy CNAME */
return NULL; return NULL;
@ -670,6 +674,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
msg->rep->ns_numrrsets = 0; msg->rep->ns_numrrsets = 0;
msg->rep->ar_numrrsets = 0; msg->rep->ar_numrrsets = 0;
msg->rep->rrset_count = 1; msg->rep->rrset_count = 1;
msg->rep->reason_bogus = LDNS_EDE_NONE;
msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now); msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now);
if(!msg->rep->rrsets[0]) /* copy DNAME */ if(!msg->rep->rrsets[0]) /* copy DNAME */
return NULL; return NULL;

View File

@ -47,6 +47,7 @@
#ifdef USE_TCP_FASTOPEN #ifdef USE_TCP_FASTOPEN
#include <netinet/tcp.h> #include <netinet/tcp.h>
#endif #endif
#include <ctype.h>
#include "services/listen_dnsport.h" #include "services/listen_dnsport.h"
#include "services/outside_network.h" #include "services/outside_network.h"
#include "util/netevent.h" #include "util/netevent.h"
@ -1157,7 +1158,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
* @param do_auto: use automatic interface detection. * @param do_auto: use automatic interface detection.
* If enabled, then ifname must be the wildcard name. * If enabled, then ifname must be the wildcard name.
* @param do_udp: if udp should be used. * @param do_udp: if udp should be used.
* @param do_tcp: if udp should be used. * @param do_tcp: if tcp should be used.
* @param hints: for getaddrinfo. family and flags have to be set by caller. * @param hints: for getaddrinfo. family and flags have to be set by caller.
* @param port: Port number to use (as string). * @param port: Port number to use (as string).
* @param list: list of open ports, appended to, changed to point to list head. * @param list: list of open ports, appended to, changed to point to list head.
@ -1369,17 +1370,17 @@ listen_create(struct comm_base* base, struct listen_port* ports,
while(ports) { while(ports) {
struct comm_point* cp = NULL; struct comm_point* cp = NULL;
if(ports->ftype == listen_type_udp || if(ports->ftype == listen_type_udp ||
ports->ftype == listen_type_udp_dnscrypt) ports->ftype == listen_type_udp_dnscrypt) {
cp = comm_point_create_udp(base, ports->fd, cp = comm_point_create_udp(base, ports->fd,
front->udp_buff, cb, cb_arg, ports->socket); front->udp_buff, cb, cb_arg, ports->socket);
else if(ports->ftype == listen_type_tcp || } else if(ports->ftype == listen_type_tcp ||
ports->ftype == listen_type_tcp_dnscrypt) ports->ftype == listen_type_tcp_dnscrypt) {
cp = comm_point_create_tcp(base, ports->fd, cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, tcp_idle_timeout, tcp_accept_count, tcp_idle_timeout,
harden_large_queries, 0, NULL, harden_large_queries, 0, NULL,
tcp_conn_limit, bufsize, front->udp_buff, tcp_conn_limit, bufsize, front->udp_buff,
ports->ftype, cb, cb_arg, ports->socket); ports->ftype, cb, cb_arg, ports->socket);
else if(ports->ftype == listen_type_ssl || } else if(ports->ftype == listen_type_ssl ||
ports->ftype == listen_type_http) { ports->ftype == listen_type_http) {
cp = comm_point_create_tcp(base, ports->fd, cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, tcp_idle_timeout, tcp_accept_count, tcp_idle_timeout,
@ -1410,15 +1411,22 @@ listen_create(struct comm_base* base, struct listen_port* ports,
#endif #endif
} }
} else if(ports->ftype == listen_type_udpancil || } else if(ports->ftype == listen_type_udpancil ||
ports->ftype == listen_type_udpancil_dnscrypt) ports->ftype == listen_type_udpancil_dnscrypt) {
cp = comm_point_create_udp_ancil(base, ports->fd, cp = comm_point_create_udp_ancil(base, ports->fd,
front->udp_buff, cb, cb_arg, ports->socket); front->udp_buff, cb, cb_arg, ports->socket);
}
if(!cp) { if(!cp) {
log_err("can't create commpoint"); log_err("can't create commpoint");
listen_delete(front); listen_delete(front);
return NULL; return NULL;
} }
if(http_notls && ports->ftype == listen_type_http) if((http_notls && ports->ftype == listen_type_http) ||
(ports->ftype == listen_type_tcp) ||
(ports->ftype == listen_type_udp) ||
(ports->ftype == listen_type_udpancil) ||
(ports->ftype == listen_type_tcp_dnscrypt) ||
(ports->ftype == listen_type_udp_dnscrypt) ||
(ports->ftype == listen_type_udpancil_dnscrypt))
cp->ssl = NULL; cp->ssl = NULL;
else else
cp->ssl = sslctx; cp->ssl = sslctx;
@ -1709,6 +1717,63 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
} }
/* create ip4 and ip6 ports so that return addresses are nice. */ /* create ip4 and ip6 ports so that return addresses are nice. */
if(do_auto || num_ifs == 0) { if(do_auto || num_ifs == 0) {
if(do_auto && cfg->if_automatic_ports &&
cfg->if_automatic_ports[0]!=0) {
char* now = cfg->if_automatic_ports;
while(now && *now) {
char* after;
int extraport;
while(isspace((unsigned char)*now))
now++;
if(!*now)
break;
after = now;
extraport = (int)strtol(now, &after, 10);
if(extraport < 0 || extraport > 65535) {
log_err("interface-automatic-ports port number out of range, at position %d of '%s'", (int)(now-cfg->if_automatic_ports)+1, cfg->if_automatic_ports);
listening_ports_free(list);
return NULL;
}
if(extraport == 0 && now == after) {
log_err("interface-automatic-ports could not be parsed, at position %d of '%s'", (int)(now-cfg->if_automatic_ports)+1, cfg->if_automatic_ports);
listening_ports_free(list);
return NULL;
}
now = after;
snprintf(portbuf, sizeof(portbuf), "%d", extraport);
if(do_ip6) {
hints.ai_family = AF_INET6;
if(!ports_create_if("::0",
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
}
if(do_ip4) {
hints.ai_family = AF_INET;
if(!ports_create_if("0.0.0.0",
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
cfg->https_port, reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
}
}
return list;
}
if(do_ip6) { if(do_ip6) {
hints.ai_family = AF_INET6; hints.ai_family = AF_INET6;
if(!ports_create_if(do_auto?"::0":"::1", if(!ports_create_if(do_auto?"::0":"::1",

View File

@ -1328,7 +1328,8 @@ local_encode(struct query_info* qinfo, struct module_env* env,
static void static void
local_error_encode(struct query_info* qinfo, struct module_env* env, local_error_encode(struct query_info* qinfo, struct module_env* env,
struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf, struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
struct regional* temp, int rcode, int r) struct regional* temp, int rcode, int r, int ede_code,
const char* ede_txt)
{ {
edns->edns_version = EDNS_ADVERTISED_VERSION; edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE; edns->udp_size = EDNS_ADVERTISED_SIZE;
@ -1338,6 +1339,12 @@ local_error_encode(struct query_info* qinfo, struct module_env* env,
if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL, if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
rcode, edns, repinfo, temp, env->now_tv)) rcode, edns, repinfo, temp, env->now_tv))
edns->opt_list_inplace_cb_out = NULL; edns->opt_list_inplace_cb_out = NULL;
if(ede_code != LDNS_EDE_NONE && env->cfg->ede) {
edns_opt_list_append_ede(&edns->opt_list_out, temp,
ede_code, ede_txt);
}
error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf), error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2), edns); sldns_buffer_read_u16_at(buf, 2), edns);
} }
@ -1535,7 +1542,9 @@ local_data_answer(struct local_zone* z, struct module_env* env,
qinfo->local_alias = NULL; qinfo->local_alias = NULL;
local_error_encode(qinfo, env, edns, repinfo, local_error_encode(qinfo, env, edns, repinfo,
buf, temp, LDNS_RCODE_YXDOMAIN, buf, temp, LDNS_RCODE_YXDOMAIN,
(LDNS_RCODE_YXDOMAIN|BIT_AA)); (LDNS_RCODE_YXDOMAIN|BIT_AA),
LDNS_EDE_OTHER,
"DNAME expansion became too large");
return 1; return 1;
} }
memset(&qinfo->local_alias->rrset->entry, 0, memset(&qinfo->local_alias->rrset->entry, 0,
@ -1638,7 +1647,8 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
} else if(lz_type == local_zone_refuse } else if(lz_type == local_zone_refuse
|| lz_type == local_zone_always_refuse) { || lz_type == local_zone_always_refuse) {
local_error_encode(qinfo, env, edns, repinfo, buf, temp, local_error_encode(qinfo, env, edns, repinfo, buf, temp,
LDNS_RCODE_REFUSED, (LDNS_RCODE_REFUSED|BIT_AA)); LDNS_RCODE_REFUSED, (LDNS_RCODE_REFUSED|BIT_AA),
LDNS_EDE_NONE, NULL);
return 1; return 1;
} else if(lz_type == local_zone_static || } else if(lz_type == local_zone_static ||
lz_type == local_zone_redirect || lz_type == local_zone_redirect ||
@ -1663,8 +1673,8 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
if(z != NULL && z->soa && z->soa_negative) if(z != NULL && z->soa && z->soa_negative)
return local_encode(qinfo, env, edns, repinfo, buf, temp, return local_encode(qinfo, env, edns, repinfo, buf, temp,
z->soa_negative, 0, rcode); z->soa_negative, 0, rcode);
local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode, local_error_encode(qinfo, env, edns, repinfo, buf, temp,
(rcode|BIT_AA)); rcode, (rcode|BIT_AA), LDNS_EDE_NONE, NULL);
return 1; return 1;
} else if(lz_type == local_zone_typetransparent } else if(lz_type == local_zone_typetransparent
|| lz_type == local_zone_always_transparent) { || lz_type == local_zone_always_transparent) {
@ -1705,9 +1715,10 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
return local_encode(qinfo, env, edns, repinfo, buf, temp, return local_encode(qinfo, env, edns, repinfo, buf, temp,
&lrr, 1, LDNS_RCODE_NOERROR); &lrr, 1, LDNS_RCODE_NOERROR);
} else { } else {
/* NODATA: No EDE needed */
local_error_encode(qinfo, env, edns, repinfo, buf, local_error_encode(qinfo, env, edns, repinfo, buf,
temp, LDNS_RCODE_NOERROR, temp, LDNS_RCODE_NOERROR,
(LDNS_RCODE_NOERROR|BIT_AA)); (LDNS_RCODE_NOERROR|BIT_AA), -1, NULL);
} }
return 1; return 1;
} }
@ -1720,8 +1731,9 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
if(z != NULL && z->soa && z->soa_negative) if(z != NULL && z->soa && z->soa_negative)
return local_encode(qinfo, env, edns, repinfo, buf, temp, return local_encode(qinfo, env, edns, repinfo, buf, temp,
z->soa_negative, 0, rcode); z->soa_negative, 0, rcode);
/* NODATA: No EDE needed */
local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode, local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode,
(rcode|BIT_AA)); (rcode|BIT_AA), LDNS_EDE_NONE, NULL);
return 1; return 1;
} }

View File

@ -64,6 +64,11 @@
#include "respip/respip.h" #include "respip/respip.h"
#include "services/listen_dnsport.h" #include "services/listen_dnsport.h"
#ifdef CLIENT_SUBNET
#include "edns-subnet/subnetmod.h"
#include "edns-subnet/edns-subnet.h"
#endif
/** subtract timers and the values do not overflow or become negative */ /** subtract timers and the values do not overflow or become negative */
static void static void
timeval_subtract(struct timeval* d, const struct timeval* end, const struct timeval* start) timeval_subtract(struct timeval* d, const struct timeval* end, const struct timeval* start)
@ -458,7 +463,8 @@ mesh_serve_expired_init(struct mesh_state* mstate, int timeout)
void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
struct respip_client_info* cinfo, uint16_t qflags, struct respip_client_info* cinfo, uint16_t qflags,
struct edns_data* edns, struct comm_reply* rep, uint16_t qid) struct edns_data* edns, struct comm_reply* rep, uint16_t qid,
int rpz_passthru)
{ {
struct mesh_state* s = NULL; struct mesh_state* s = NULL;
int unique = unique_mesh_state(edns->opt_list_in, mesh->env); int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
@ -513,6 +519,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
} }
if(unique) if(unique)
mesh_state_make_unique(s); mesh_state_make_unique(s);
s->s.rpz_passthru = rpz_passthru;
/* copy the edns options we got from the front */ /* copy the edns options we got from the front */
if(edns->opt_list_in) { if(edns->opt_list_in) {
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in, s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in,
@ -606,7 +613,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
int int
mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf, uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
uint16_t qid, mesh_cb_func_type cb, void* cb_arg) uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru)
{ {
struct mesh_state* s = NULL; struct mesh_state* s = NULL;
int unique = unique_mesh_state(edns->opt_list_in, mesh->env); int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
@ -632,6 +639,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
} }
if(unique) if(unique)
mesh_state_make_unique(s); mesh_state_make_unique(s);
s->s.rpz_passthru = rpz_passthru;
if(edns->opt_list_in) { if(edns->opt_list_in) {
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in, s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in,
s->s.region); s->s.region);
@ -686,7 +694,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
* 0 (false), in which case the new state is only made runnable so it * 0 (false), in which case the new state is only made runnable so it
* will not be run recursively on top of the current state. */ * will not be run recursively on top of the current state. */
static void mesh_schedule_prefetch(struct mesh_area* mesh, static void mesh_schedule_prefetch(struct mesh_area* mesh,
struct query_info* qinfo, uint16_t qflags, time_t leeway, int run) struct query_info* qinfo, uint16_t qflags, time_t leeway, int run,
int rpz_passthru)
{ {
struct mesh_state* s = mesh_area_find(mesh, NULL, qinfo, struct mesh_state* s = mesh_area_find(mesh, NULL, qinfo,
qflags&(BIT_RD|BIT_CD), 0, 0); qflags&(BIT_RD|BIT_CD), 0, 0);
@ -741,6 +750,7 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
s->list_select = mesh_jostle_list; s->list_select = mesh_jostle_list;
} }
} }
s->s.rpz_passthru = rpz_passthru;
if(!run) { if(!run) {
#ifdef UNBOUND_DEBUG #ifdef UNBOUND_DEBUG
@ -756,10 +766,114 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
mesh_run(mesh, s, module_event_new, NULL); mesh_run(mesh, s, module_event_new, NULL);
} }
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo, #ifdef CLIENT_SUBNET
uint16_t qflags, time_t leeway) /* Same logic as mesh_schedule_prefetch but tailored to the subnet module logic
* like passing along the comm_reply info. This will be faked into an EDNS
* option for processing by the subnet module if the client has not already
* attached its own ECS data. */
static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh,
struct query_info* qinfo, uint16_t qflags, time_t leeway, int run,
int rpz_passthru, struct comm_reply* rep, struct edns_option* edns_list)
{ {
mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1); struct mesh_state* s = NULL;
struct edns_option* opt = NULL;
#ifdef UNBOUND_DEBUG
struct rbnode_type* n;
#endif
if(!mesh_make_new_space(mesh, NULL)) {
verbose(VERB_ALGO, "Too many queries. dropped prefetch.");
mesh->stats_dropped ++;
return;
}
s = mesh_state_create(mesh->env, qinfo, NULL,
qflags&(BIT_RD|BIT_CD), 0, 0);
if(!s) {
log_err("prefetch_subnet mesh_state_create: out of memory");
return;
}
mesh_state_make_unique(s);
opt = edns_opt_list_find(edns_list, mesh->env->cfg->client_subnet_opcode);
if(opt) {
/* Use the client's ECS data */
if(!edns_opt_list_append(&s->s.edns_opts_front_in, opt->opt_code,
opt->opt_len, opt->opt_data, s->s.region)) {
log_err("prefetch_subnet edns_opt_list_append: out of memory");
return;
}
} else {
/* Fake the ECS data from the client's IP */
struct ecs_data ecs;
memset(&ecs, 0, sizeof(ecs));
subnet_option_from_ss(&rep->addr, &ecs, mesh->env->cfg);
if(ecs.subnet_validdata == 0) {
log_err("prefetch_subnet subnet_option_from_ss: invalid data");
return;
}
subnet_ecs_opt_list_append(&ecs, &s->s.edns_opts_front_in, &s->s);
if(!s->s.edns_opts_front_in) {
log_err("prefetch_subnet subnet_ecs_opt_list_append: out of memory");
return;
}
}
#ifdef UNBOUND_DEBUG
n =
#else
(void)
#endif
rbtree_insert(&mesh->all, &s->node);
log_assert(n != NULL);
/* set detached (it is now) */
mesh->num_detached_states++;
/* make it ignore the cache */
sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region);
s->s.prefetch_leeway = leeway;
if(s->list_select == mesh_no_list) {
/* move to either the forever or the jostle_list */
if(mesh->num_forever_states < mesh->max_forever_states) {
mesh->num_forever_states ++;
mesh_list_insert(s, &mesh->forever_first,
&mesh->forever_last);
s->list_select = mesh_forever_list;
} else {
mesh_list_insert(s, &mesh->jostle_first,
&mesh->jostle_last);
s->list_select = mesh_jostle_list;
}
}
s->s.rpz_passthru = rpz_passthru;
if(!run) {
#ifdef UNBOUND_DEBUG
n =
#else
(void)
#endif
rbtree_insert(&mesh->run, &s->run_node);
log_assert(n != NULL);
return;
}
mesh_run(mesh, s, module_event_new, NULL);
}
#endif /* CLIENT_SUBNET */
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, time_t leeway, int rpz_passthru,
struct comm_reply* rep, struct edns_option* opt_list)
{
(void)opt_list;
(void)rep;
#ifdef CLIENT_SUBNET
if(rep)
mesh_schedule_prefetch_subnet(mesh, qinfo, qflags, leeway, 1,
rpz_passthru, rep, opt_list);
else
#endif
mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1,
rpz_passthru);
} }
void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e, void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
@ -1290,6 +1404,36 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
&r->edns, &r->query_reply, m->s.region, &r->start_time)) &r->edns, &r->query_reply, m->s.region, &r->start_time))
r->edns.opt_list_inplace_cb_out = NULL; r->edns.opt_list_inplace_cb_out = NULL;
} }
/* Send along EDE BOGUS EDNS0 option when answer is bogus */
if(m->s.env->cfg->ede && rcode == LDNS_RCODE_SERVFAIL &&
m->s.env->need_to_validate && (!(r->qflags&BIT_CD) ||
m->s.env->cfg->ignore_cd) && rep &&
(rep->security <= sec_status_bogus ||
rep->security == sec_status_secure_sentinel_fail)) {
char *reason = m->s.env->cfg->val_log_level >= 2
? errinf_to_str_bogus(&m->s) : NULL;
/* During validation the EDE code can be received via two
* code paths. One code path fills the reply_info EDE, and
* the other fills it in the errinf_strlist. These paths
* intersect at some points, but where is opaque due to
* the complexity of the validator. At the time of writing
* we make the choice to prefer the EDE from errinf_strlist
* but a compelling reason to do otherwise is just as valid
*/
sldns_ede_code reason_bogus = errinf_to_reason_bogus(&m->s);
if ((reason_bogus == LDNS_EDE_DNSSEC_BOGUS &&
rep->reason_bogus != LDNS_EDE_NONE) ||
reason_bogus == LDNS_EDE_NONE) {
reason_bogus = rep->reason_bogus;
}
if(reason_bogus != LDNS_EDE_NONE) {
edns_opt_list_append_ede(&r->edns.opt_list_out,
m->s.region, reason_bogus, reason);
}
free(reason);
}
error_encode(r_buffer, rcode, &m->s.qinfo, r->qid, error_encode(r_buffer, rcode, &m->s.qinfo, r->qid,
r->qflags, &r->edns); r->qflags, &r->edns);
m->reply_list = NULL; m->reply_list = NULL;
@ -1313,6 +1457,8 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
rep, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region, &r->start_time)) rep, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region, &r->start_time))
r->edns.opt_list_inplace_cb_out = NULL; r->edns.opt_list_inplace_cb_out = NULL;
/* internal server error (probably malloc failure) so no
* EDE (RFC8914) needed */
error_encode(r_buffer, LDNS_RCODE_SERVFAIL, error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
&m->s.qinfo, r->qid, r->qflags, &r->edns); &m->s.qinfo, r->qid, r->qflags, &r->edns);
} }
@ -1693,6 +1839,7 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
if(mstate->s.curmod == 0) { if(mstate->s.curmod == 0) {
struct query_info* qinfo = NULL; struct query_info* qinfo = NULL;
uint16_t qflags; uint16_t qflags;
int rpz_p = 0;
mesh_query_done(mstate); mesh_query_done(mstate);
mesh_walk_supers(mesh, mstate); mesh_walk_supers(mesh, mstate);
@ -1701,13 +1848,15 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
* from an external DNS server, we'll need to schedule * from an external DNS server, we'll need to schedule
* a prefetch after removing the current state, so * a prefetch after removing the current state, so
* we need to make a copy of the query info here. */ * we need to make a copy of the query info here. */
if(mstate->s.need_refetch) if(mstate->s.need_refetch) {
mesh_copy_qinfo(mstate, &qinfo, &qflags); mesh_copy_qinfo(mstate, &qinfo, &qflags);
rpz_p = mstate->s.rpz_passthru;
}
mesh_state_delete(&mstate->s); mesh_state_delete(&mstate->s);
if(qinfo) { if(qinfo) {
mesh_schedule_prefetch(mesh, qinfo, qflags, mesh_schedule_prefetch(mesh, qinfo, qflags,
0, 1); 0, 1, rpz_p);
} }
return 0; return 0;
} }
@ -1917,7 +2066,7 @@ apply_respip_action(struct module_qstate* qstate,
return 1; return 1;
if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, actinfo, if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, actinfo,
alias_rrset, 0, qstate->region, az)) alias_rrset, 0, qstate->region, az, NULL))
return 0; return 0;
/* xxx_deny actions mean dropping the reply, unless the original reply /* xxx_deny actions mean dropping the reply, unless the original reply
@ -2042,6 +2191,14 @@ mesh_serve_expired_callback(void* arg)
} }
} }
/* Add EDE Stale Answer (RCF8914). Ignore global ede as this is
* warning instead of an error */
if (r->edns.edns_present && qstate->env->cfg->ede_serve_expired &&
qstate->env->cfg->ede) {
edns_opt_list_append_ede(&r->edns.opt_list_out,
mstate->s.region, LDNS_EDE_STALE_ANSWER, NULL);
}
r_buffer = r->query_reply.c->buffer; r_buffer = r->query_reply.c->buffer;
if(r->query_reply.c->tcp_req_info) if(r->query_reply.c->tcp_req_info)
r_buffer = r->query_reply.c->tcp_req_info->spool_buffer; r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;

View File

@ -296,10 +296,13 @@ void mesh_delete(struct mesh_area* mesh);
* @param edns: edns data from client query. * @param edns: edns data from client query.
* @param rep: where to reply to. * @param rep: where to reply to.
* @param qid: query id to reply with. * @param qid: query id to reply with.
* @param rpz_passthru: if true, the rpz passthru was previously found and
* further rpz processing is stopped.
*/ */
void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
struct respip_client_info* cinfo, uint16_t qflags, struct respip_client_info* cinfo, uint16_t qflags,
struct edns_data* edns, struct comm_reply* rep, uint16_t qid); struct edns_data* edns, struct comm_reply* rep, uint16_t qid,
int rpz_passthru);
/** /**
* New query with callback. Create new query state if needed, and * New query with callback. Create new query state if needed, and
@ -314,11 +317,13 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
* @param qid: query id to reply with. * @param qid: query id to reply with.
* @param cb: callback function. * @param cb: callback function.
* @param cb_arg: callback user arg. * @param cb_arg: callback user arg.
* @param rpz_passthru: if true, the rpz passthru was previously found and
* further rpz processing is stopped.
* @return 0 on error. * @return 0 on error.
*/ */
int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, struct sldns_buffer* buf, uint16_t qflags, struct edns_data* edns, struct sldns_buffer* buf,
uint16_t qid, mesh_cb_func_type cb, void* cb_arg); uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru);
/** /**
* New prefetch message. Create new query state if needed. * New prefetch message. Create new query state if needed.
@ -328,9 +333,15 @@ int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
* @param qinfo: query from client. * @param qinfo: query from client.
* @param qflags: flags from client query. * @param qflags: flags from client query.
* @param leeway: TTL leeway what to expire earlier for this update. * @param leeway: TTL leeway what to expire earlier for this update.
* @param rpz_passthru: if true, the rpz passthru was previously found and
* further rpz processing is stopped.
* @param rep: comm_reply for the client; to be used when subnet is enabled.
* @param opt_list: edns opt_list from the client; to be used when subnet is
* enabled.
*/ */
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo, void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, time_t leeway); uint16_t qflags, time_t leeway, int rpz_passthru,
struct comm_reply* rep, struct edns_option* opt_list);
/** /**
* Handle new event from the wire. A serviced query has returned. * Handle new event from the wire. A serviced query has returned.

View File

@ -1994,6 +1994,9 @@ static int udp_connect_needs_log(int err)
# endif # endif
# ifdef ENETDOWN # ifdef ENETDOWN
case ENETDOWN: case ENETDOWN:
# endif
# ifdef EADDRNOTAVAIL
case EADDRNOTAVAIL:
# endif # endif
case EPERM: case EPERM:
case EACCES: case EACCES:
@ -2294,7 +2297,7 @@ reuse_tcp_select_id(struct reuse_tcp* reuse, struct outside_network* outnet)
node = rbtree_first(&reuse->tree_by_id); node = rbtree_first(&reuse->tree_by_id);
log_assert(node && node != RBTREE_NULL); /* tree not empty */ log_assert(node && node != RBTREE_NULL); /* tree not empty */
/* see if select is before first node */ /* see if select is before first node */
if(select < tree_by_id_get_id(node)) if(select < (unsigned)tree_by_id_get_id(node))
return select; return select;
count += tree_by_id_get_id(node); count += tree_by_id_get_id(node);
/* perhaps select is between nodes */ /* perhaps select is between nodes */

View File

@ -526,13 +526,13 @@ rpz_create(struct config_auth* p)
size_t nmlen = sizeof(nm); size_t nmlen = sizeof(nm);
if(!p->rpz_cname) { if(!p->rpz_cname) {
log_err("RPZ override with cname action found, but no " log_err("rpz: override with cname action found, but no "
"rpz-cname-override configured"); "rpz-cname-override configured");
goto err; goto err;
} }
if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) { if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
log_err("cannot parse RPZ cname override: %s", log_err("rpz: cannot parse cname override: %s",
p->rpz_cname); p->rpz_cname);
goto err; goto err;
} }
@ -614,7 +614,7 @@ rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
return; /* no need to log these types as unsupported */ return; /* no need to log these types as unsupported */
} }
dname_str(dname, str); dname_str(dname, str);
verbose(VERB_ALGO, "RPZ: qname trigger, %s skipping unsupported action: %s", verbose(VERB_ALGO, "rpz: qname trigger, %s skipping unsupported action: %s",
str, rpz_action_to_string(a)); str, rpz_action_to_string(a));
free(dname); free(dname);
return; return;
@ -999,7 +999,7 @@ rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
rpz_action_to_respip_action(a) == respip_invalid) { rpz_action_to_respip_action(a) == respip_invalid) {
char str[255+1]; char str[255+1];
dname_str(dname, str); dname_str(dname, str);
verbose(VERB_ALGO, "RPZ: respip trigger, %s skipping unsupported action: %s", verbose(VERB_ALGO, "rpz: respip trigger, %s skipping unsupported action: %s",
str, rpz_action_to_string(a)); str, rpz_action_to_string(a));
return 0; return 0;
} }
@ -1560,7 +1560,9 @@ rpz_local_encode(struct module_env* env, struct query_info* qinfo,
} }
static struct local_rrset* static struct local_rrset*
rpz_find_synthesized_rrset(int qtype, struct clientip_synthesized_rr* data) { rpz_find_synthesized_rrset(uint16_t qtype,
struct clientip_synthesized_rr* data)
{
struct local_rrset* cursor = data->data; struct local_rrset* cursor = data->data;
while( cursor != NULL) { while( cursor != NULL) {
struct packed_rrset_key* packed_rrset = &cursor->rrset->rk; struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
@ -1997,6 +1999,7 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
break; break;
case RPZ_PASSTHRU_ACTION: case RPZ_PASSTHRU_ACTION:
ret = NULL; ret = NULL;
ms->rpz_passthru = 1;
break; break;
default: default:
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'", verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
@ -2051,6 +2054,7 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
break; break;
case RPZ_PASSTHRU_ACTION: case RPZ_PASSTHRU_ACTION:
ret = NULL; ret = NULL;
ms->rpz_passthru = 1;
break; break;
default: default:
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'", verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
@ -2114,6 +2118,11 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
struct local_zone* z = NULL; struct local_zone* z = NULL;
struct matched_delegation_point match = {0}; struct matched_delegation_point match = {0};
if(ms->rpz_passthru) {
verbose(VERB_ALGO, "query is rpz_passthru, no further processing");
return NULL;
}
if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; } if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
az = ms->env->auth_zones; az = ms->env->auth_zones;
@ -2179,6 +2188,11 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
enum localzone_type lzt; enum localzone_type lzt;
struct dns_msg* ret = NULL; struct dns_msg* ret = NULL;
if(ms->rpz_passthru) {
verbose(VERB_ALGO, "query is rpz_passthru, no further processing");
return NULL;
}
if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; } if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
az = ms->env->auth_zones; az = ms->env->auth_zones;
@ -2253,6 +2267,7 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
break; break;
case RPZ_PASSTHRU_ACTION: case RPZ_PASSTHRU_ACTION:
ret = NULL; ret = NULL;
ms->rpz_passthru = 1;
break; break;
default: default:
verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'", verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'",
@ -2270,7 +2285,8 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
uint8_t* taglist, size_t taglen, struct ub_server_stats* stats, uint8_t* taglist, size_t taglen, struct ub_server_stats* stats,
sldns_buffer* buf, struct regional* temp, sldns_buffer* buf, struct regional* temp,
/* output parameters */ /* output parameters */
struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out) struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out,
int* passthru)
{ {
int ret = 0; int ret = 0;
enum rpz_action client_action; enum rpz_action client_action;
@ -2278,7 +2294,9 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out); az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out);
client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action); client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action);
if(client_action == RPZ_PASSTHRU_ACTION) {
*passthru = 1;
}
if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION && if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
client_action != RPZ_PASSTHRU_ACTION)) { client_action != RPZ_PASSTHRU_ACTION)) {
if(client_action == RPZ_PASSTHRU_ACTION if(client_action == RPZ_PASSTHRU_ACTION
@ -2323,7 +2341,7 @@ int
rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env, rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf, struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist, struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist,
size_t taglen, struct ub_server_stats* stats) size_t taglen, struct ub_server_stats* stats, int* passthru)
{ {
struct rpz* r = NULL; struct rpz* r = NULL;
struct auth_zone* a = NULL; struct auth_zone* a = NULL;
@ -2332,7 +2350,8 @@ rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
enum localzone_type lzt; enum localzone_type lzt;
int clientip_trigger = rpz_apply_maybe_clientip_trigger(az, env, qinfo, int clientip_trigger = rpz_apply_maybe_clientip_trigger(az, env, qinfo,
edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r); edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r,
passthru);
if(clientip_trigger >= 0) { if(clientip_trigger >= 0) {
if(a) { if(a) {
lock_rw_unlock(&a->lock); lock_rw_unlock(&a->lock);
@ -2357,6 +2376,10 @@ rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
} else { } else {
lzt = rpz_action_to_localzone_type(r->action_override); lzt = rpz_action_to_localzone_type(r->action_override);
} }
if(r->action_override == RPZ_PASSTHRU_ACTION ||
lzt == local_zone_always_transparent /* RPZ_PASSTHRU_ACTION */) {
*passthru = 1;
}
if(verbosity >= VERB_ALGO) { if(verbosity >= VERB_ALGO) {
char nm[255+1], zn[255+1]; char nm[255+1], zn[255+1];

View File

@ -176,12 +176,14 @@ void rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
* @param taglist: taglist to lookup. * @param taglist: taglist to lookup.
* @param taglen: length of taglist. * @param taglen: length of taglist.
* @param stats: worker stats struct * @param stats: worker stats struct
* @param passthru: returns if the query can passthru further rpz processing.
* @return: 1 if client answer is ready, 0 to continue resolving * @return: 1 if client answer is ready, 0 to continue resolving
*/ */
int rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env, int rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf, struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
struct regional* temp, struct comm_reply* repinfo, struct regional* temp, struct comm_reply* repinfo,
uint8_t* taglist, size_t taglen, struct ub_server_stats* stats); uint8_t* taglist, size_t taglen, struct ub_server_stats* stats,
int* passthru);
/** /**
* Callback to process when the iterator module is about to send queries. * Callback to process when the iterator module is about to send queries.

View File

@ -209,11 +209,13 @@ sldns_hexdigit_to_int(char ch)
} }
uint32_t uint32_t
sldns_str2period(const char *nptr, const char **endptr) sldns_str2period(const char *nptr, const char **endptr, int* overflow)
{ {
int sign = 0; int sign = 0;
uint32_t i = 0; uint32_t i = 0;
uint32_t seconds = 0; uint32_t seconds = 0;
const uint32_t maxint = 0xffffffff;
*overflow = 0;
for(*endptr = nptr; **endptr; (*endptr)++) { for(*endptr = nptr; **endptr; (*endptr)++) {
switch (**endptr) { switch (**endptr) {
@ -236,26 +238,46 @@ sldns_str2period(const char *nptr, const char **endptr)
break; break;
case 's': case 's':
case 'S': case 'S':
if(seconds > maxint-i) {
*overflow = 1;
return 0;
}
seconds += i; seconds += i;
i = 0; i = 0;
break; break;
case 'm': case 'm':
case 'M': case 'M':
if(i > maxint/60 || seconds > maxint-(i*60)) {
*overflow = 1;
return 0;
}
seconds += i * 60; seconds += i * 60;
i = 0; i = 0;
break; break;
case 'h': case 'h':
case 'H': case 'H':
if(i > maxint/(60*60) || seconds > maxint-(i*60*60)) {
*overflow = 1;
return 0;
}
seconds += i * 60 * 60; seconds += i * 60 * 60;
i = 0; i = 0;
break; break;
case 'd': case 'd':
case 'D': case 'D':
if(i > maxint/(60*60*24) || seconds > maxint-(i*60*60*24)) {
*overflow = 1;
return 0;
}
seconds += i * 60 * 60 * 24; seconds += i * 60 * 60 * 24;
i = 0; i = 0;
break; break;
case 'w': case 'w':
case 'W': case 'W':
if(i > maxint/(60*60*24*7) || seconds > maxint-(i*60*60*24*7)) {
*overflow = 1;
return 0;
}
seconds += i * 60 * 60 * 24 * 7; seconds += i * 60 * 60 * 24 * 7;
i = 0; i = 0;
break; break;
@ -269,15 +291,27 @@ sldns_str2period(const char *nptr, const char **endptr)
case '7': case '7':
case '8': case '8':
case '9': case '9':
if(i > maxint/10 || i*10 > maxint - (**endptr - '0')) {
*overflow = 1;
return 0;
}
i *= 10; i *= 10;
i += (**endptr - '0'); i += (**endptr - '0');
break; break;
default: default:
if(seconds > maxint-i) {
*overflow = 1;
return 0;
}
seconds += i; seconds += i;
/* disregard signedness */ /* disregard signedness */
return seconds; return seconds;
} }
} }
if(seconds > maxint-i) {
*overflow = 1;
return 0;
}
seconds += i; seconds += i;
/* disregard signedness */ /* disregard signedness */
return seconds; return seconds;

View File

@ -74,9 +74,11 @@ struct tm * sldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct t
* converts a ttl value (like 5d2h) to a long. * converts a ttl value (like 5d2h) to a long.
* \param[in] nptr the start of the string * \param[in] nptr the start of the string
* \param[out] endptr points to the last char in case of error * \param[out] endptr points to the last char in case of error
* \param[out] overflow returns if the string causes integer overflow error,
* the number is too big, string of digits too long.
* \return the convert duration value * \return the convert duration value
*/ */
uint32_t sldns_str2period(const char *nptr, const char **endptr); uint32_t sldns_str2period(const char *nptr, const char **endptr, int* overflow);
/** /**
* Returns the int value of the given (hex) digit * Returns the int value of the given (hex) digit

View File

@ -97,18 +97,22 @@ extern "C" {
#define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF))) #define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF)))
*/ */
#define LDNS_QDCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_QDCOUNT_OFF)) #define LDNS_QDCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_QDCOUNT_OFF))
#define LDNS_QDCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_QDCOUNT_OFF, i))
/* Counter of the answer section */ /* Counter of the answer section */
#define LDNS_ANCOUNT_OFF 6 #define LDNS_ANCOUNT_OFF 6
#define LDNS_ANCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ANCOUNT_OFF)) #define LDNS_ANCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ANCOUNT_OFF))
#define LDNS_ANCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_ANCOUNT_OFF, i))
/* Counter of the authority section */ /* Counter of the authority section */
#define LDNS_NSCOUNT_OFF 8 #define LDNS_NSCOUNT_OFF 8
#define LDNS_NSCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_NSCOUNT_OFF)) #define LDNS_NSCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_NSCOUNT_OFF))
#define LDNS_NSCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_NSCOUNT_OFF, i))
/* Counter of the additional section */ /* Counter of the additional section */
#define LDNS_ARCOUNT_OFF 10 #define LDNS_ARCOUNT_OFF 10
#define LDNS_ARCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ARCOUNT_OFF)) #define LDNS_ARCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ARCOUNT_OFF))
#define LDNS_ARCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_ARCOUNT_OFF, i))
/** /**
* The sections of a packet * The sections of a packet

View File

@ -435,10 +435,42 @@ enum sldns_enum_edns_option
LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */ LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */
LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/ LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/
LDNS_EDNS_PADDING = 12, /* RFC7830 */ LDNS_EDNS_PADDING = 12, /* RFC7830 */
LDNS_EDNS_EDE = 15, /* RFC8914 */
LDNS_EDNS_CLIENT_TAG = 16 /* draft-bellis-dnsop-edns-tags-01 */ LDNS_EDNS_CLIENT_TAG = 16 /* draft-bellis-dnsop-edns-tags-01 */
}; };
typedef enum sldns_enum_edns_option sldns_edns_option; typedef enum sldns_enum_edns_option sldns_edns_option;
enum sldns_enum_ede_code
{
LDNS_EDE_NONE = -1, /* EDE undefined for internal use */
LDNS_EDE_OTHER = 0,
LDNS_EDE_UNSUPPORTED_DNSKEY_ALG = 1,
LDNS_EDE_UNSUPPORTED_DS_DIGEST = 2,
LDNS_EDE_STALE_ANSWER = 3,
LDNS_EDE_FORGED_ANSWER = 4,
LDNS_EDE_DNSSEC_INDETERMINATE = 5,
LDNS_EDE_DNSSEC_BOGUS = 6,
LDNS_EDE_SIGNATURE_EXPIRED = 7,
LDNS_EDE_SIGNATURE_NOT_YET_VALID = 8,
LDNS_EDE_DNSKEY_MISSING = 9,
LDNS_EDE_RRSIGS_MISSING = 10,
LDNS_EDE_NO_ZONE_KEY_BIT_SET = 11,
LDNS_EDE_NSEC_MISSING = 12,
LDNS_EDE_CACHED_ERROR = 13,
LDNS_EDE_NOT_READY = 14,
LDNS_EDE_BLOCKED = 15,
LDNS_EDE_CENSORED = 16,
LDNS_EDE_FILTERED = 17,
LDNS_EDE_PROHIBITED = 18,
LDNS_EDE_STALE_NXDOMAIN_ANSWER = 19,
LDNS_EDE_NOT_AUTHORITATIVE = 20,
LDNS_EDE_NOT_SUPPORTED = 21,
LDNS_EDE_NO_REACHABLE_AUTHORITY = 22,
LDNS_EDE_NETWORK_ERROR = 23,
LDNS_EDE_INVALID_DATA = 24,
};
typedef enum sldns_enum_ede_code sldns_ede_code;
#define LDNS_EDNS_MASK_DO_BIT 0x8000 #define LDNS_EDNS_MASK_DO_BIT 0x8000
/** TSIG and TKEY extended rcodes (16bit), 0-15 are the normal rcodes. */ /** TSIG and TKEY extended rcodes (16bit), 0-15 are the normal rcodes. */

View File

@ -249,11 +249,16 @@ rrinternal_get_ttl(sldns_buffer* strbuf, char* token, size_t token_len,
int* not_there, uint32_t* ttl, uint32_t default_ttl) int* not_there, uint32_t* ttl, uint32_t default_ttl)
{ {
const char* endptr; const char* endptr;
int overflow;
if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) {
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL, return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL,
sldns_buffer_position(strbuf)); sldns_buffer_position(strbuf));
} }
*ttl = (uint32_t) sldns_str2period(token, &endptr); *ttl = (uint32_t) sldns_str2period(token, &endptr, &overflow);
if(overflow) {
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW,
sldns_buffer_position(strbuf));
}
if (strlen(token) > 0 && !isdigit((unsigned char)token[0])) { if (strlen(token) > 0 && !isdigit((unsigned char)token[0])) {
*not_there = 1; *not_there = 1;
@ -373,7 +378,8 @@ rrinternal_get_quoted(sldns_buffer* strbuf, const char** delimiters,
/* skip spaces */ /* skip spaces */
while(sldns_buffer_remaining(strbuf) > 0 && while(sldns_buffer_remaining(strbuf) > 0 &&
*(sldns_buffer_current(strbuf)) == ' ') { (*(sldns_buffer_current(strbuf)) == ' ' ||
*(sldns_buffer_current(strbuf)) == '\t')) {
sldns_buffer_skip(strbuf, 1); sldns_buffer_skip(strbuf, 1);
} }
@ -606,7 +612,7 @@ sldns_affix_token(sldns_buffer* strbuf, char* token, size_t* token_len,
/* add space */ /* add space */
/* when addlen < 2, the token buffer is full considering the NULL byte /* when addlen < 2, the token buffer is full considering the NULL byte
* from strlen and will lead to buffer overflow with the second * from strlen and will lead to buffer overflow with the second
* assignement below. */ * assignment below. */
if(addlen < 2) return 0; if(addlen < 2) return 0;
token[*token_strlen] = ' '; token[*token_strlen] = ' ';
token[++(*token_strlen)] = 0; token[++(*token_strlen)] = 0;
@ -670,10 +676,10 @@ static int sldns_str2wire_check_svcbparams(uint8_t* rdata, uint16_t rdata_len)
,sldns_str2wire_svcparam_key_cmp); ,sldns_str2wire_svcparam_key_cmp);
/* The code below revolves around sematic errors in the SVCParam set. /* The code below revolves around semantic errors in the SVCParam set.
* So long as we do not distinguish between running Unbound as a primary * So long as we do not distinguish between running Unbound as a primary
* or as a secondary, we default to secondary behavior and we ignore the * or as a secondary, we default to secondary behavior and we ignore the
* sematic errors. */ * semantic errors. */
#ifdef SVCB_SEMANTIC_ERRORS #ifdef SVCB_SEMANTIC_ERRORS
{ {
@ -775,7 +781,8 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
/* unknown RR data */ /* unknown RR data */
if(token_strlen>=2 && strncmp(token, "\\#", 2) == 0 && if(token_strlen>=2 && strncmp(token, "\\#", 2) == 0 &&
!quoted && (token_strlen == 2 || token[2]==' ')) { !quoted && (token_strlen == 2 || token[2]==' ' ||
token[2]=='\t')) {
was_unknown_rr_format = 1; was_unknown_rr_format = 1;
if((status=rrinternal_parse_unknown(strbuf, token, if((status=rrinternal_parse_unknown(strbuf, token,
token_len, rr, rr_len, &rr_cur_len, token_len, rr, rr_len, &rr_cur_len,
@ -1055,12 +1062,15 @@ int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len,
return s; return s;
} else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) { } else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) {
const char* end = NULL; const char* end = NULL;
int overflow = 0;
strlcpy((char*)rr, line, *len); strlcpy((char*)rr, line, *len);
*len = 0; *len = 0;
*dname_len = 0; *dname_len = 0;
if(!parse_state) return LDNS_WIREPARSE_ERR_OK; if(!parse_state) return LDNS_WIREPARSE_ERR_OK;
parse_state->default_ttl = sldns_str2period( parse_state->default_ttl = sldns_str2period(
sldns_strip_ws(line+5), &end); sldns_strip_ws(line+5), &end, &overflow);
if(overflow)
return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW;
} else if (strncmp(line, "$INCLUDE", 8) == 0) { } else if (strncmp(line, "$INCLUDE", 8) == 0) {
strlcpy((char*)rr, line, *len); strlcpy((char*)rr, line, *len);
*len = 0; *len = 0;
@ -1117,7 +1127,7 @@ sldns_str2wire_svcparam_key_lookup(const char *key, size_t key_len)
if (!strncmp(key, "mandatory", sizeof("mandatory")-1)) if (!strncmp(key, "mandatory", sizeof("mandatory")-1))
return SVCB_KEY_MANDATORY; return SVCB_KEY_MANDATORY;
if (!strncmp(key, "echconfig", sizeof("echconfig")-1)) if (!strncmp(key, "echconfig", sizeof("echconfig")-1))
return SVCB_KEY_ECH; /* allow "echconfig as well as "ech" */ return SVCB_KEY_ECH; /* allow "echconfig" as well as "ech" */
break; break;
case sizeof("alpn")-1: case sizeof("alpn")-1:
@ -1356,7 +1366,7 @@ sldns_str2wire_svcbparam_mandatory(const char* val, uint8_t* rd, size_t* rd_len)
*/ */
qsort((void *)(rd + 4), count, sizeof(uint16_t), sldns_network_uint16_cmp); qsort((void *)(rd + 4), count, sizeof(uint16_t), sldns_network_uint16_cmp);
/* The code below revolves around sematic errors in the SVCParam set. /* The code below revolves around semantic errors in the SVCParam set.
* So long as we do not distinguish between running Unbound as a primary * So long as we do not distinguish between running Unbound as a primary
* or as a secondary, we default to secondary behavior and we ignore the * or as a secondary, we default to secondary behavior and we ignore the
* semantic errors. */ * semantic errors. */
@ -1588,12 +1598,12 @@ static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_
if (*val_in == '"') { if (*val_in == '"') {
val_in++; val_in++;
while (*val_in != '"' while (*val_in != '"'
&& (unsigned)(val_out - unescaped_val + 1) < sizeof(unescaped_val) && (size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val)
&& sldns_parse_char( (uint8_t*) val_out, &val_in)) { && sldns_parse_char( (uint8_t*) val_out, &val_in)) {
val_out++; val_out++;
} }
} else { } else {
while ((unsigned)(val_out - unescaped_val + 1) < sizeof(unescaped_val) while ((size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val)
&& sldns_parse_char( (uint8_t*) val_out, &val_in)) { && sldns_parse_char( (uint8_t*) val_out, &val_in)) {
val_out++; val_out++;
} }
@ -2157,9 +2167,13 @@ int sldns_str2wire_tsigtime_buf(const char* str, uint8_t* rd, size_t* len)
int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len) int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len)
{ {
const char* end; const char* end;
uint32_t p = sldns_str2period(str, &end); int overflow;
uint32_t p = sldns_str2period(str, &end, &overflow);
if(*end != 0) if(*end != 0)
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str); return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str);
if(overflow)
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW,
end-str);
if(*len < 4) if(*len < 4)
return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
sldns_write_uint32(rd, p); sldns_write_uint32(rd, p);

View File

@ -194,6 +194,7 @@ static sldns_lookup_table sldns_edns_options_data[] = {
{ 8, "edns-client-subnet" }, { 8, "edns-client-subnet" },
{ 11, "edns-tcp-keepalive"}, { 11, "edns-tcp-keepalive"},
{ 12, "Padding" }, { 12, "Padding" },
{ 15, "EDE"},
{ 0, NULL} { 0, NULL}
}; };
sldns_lookup_table* sldns_edns_options = sldns_edns_options_data; sldns_lookup_table* sldns_edns_options = sldns_edns_options_data;

View File

@ -408,6 +408,28 @@ interfacechecks(struct config_file* cfg)
} }
} }
/** check interface-automatic-ports */
static void
ifautomaticportschecks(char* ifautomaticports)
{
char* now = ifautomaticports;
while(now && *now) {
char* after;
int extraport;
while(isspace((unsigned char)*now))
now++;
if(!*now)
break;
after = now;
extraport = (int)strtol(now, &after, 10);
if(extraport < 0 || extraport > 65535)
fatal_exit("interface-automatic-ports: port out of range at position %d in '%s'", (int)(now-ifautomaticports)+1, ifautomaticports);
if(extraport == 0 && now == after)
fatal_exit("interface-automatic-ports: parse error at position %d in '%s'", (int)(now-ifautomaticports)+1, ifautomaticports);
now = after;
}
}
/** check acl ips */ /** check acl ips */
static void static void
aclchecks(struct config_file* cfg) aclchecks(struct config_file* cfg)
@ -608,6 +630,7 @@ morechecks(struct config_file* cfg)
warn_hosts("stub-host", cfg->stubs); warn_hosts("stub-host", cfg->stubs);
warn_hosts("forward-host", cfg->forwards); warn_hosts("forward-host", cfg->forwards);
interfacechecks(cfg); interfacechecks(cfg);
ifautomaticportschecks(cfg->if_automatic_ports);
aclchecks(cfg); aclchecks(cfg);
tcpconnlimitchecks(cfg); tcpconnlimitchecks(cfg);

View File

@ -155,9 +155,9 @@ usage(void)
printf(" ratelimit_list [+a] list ratelimited domains\n"); printf(" ratelimit_list [+a] list ratelimited domains\n");
printf(" ip_ratelimit_list [+a] list ratelimited ip addresses\n"); printf(" ip_ratelimit_list [+a] list ratelimited ip addresses\n");
printf(" +a list all, also not ratelimited\n"); printf(" +a list all, also not ratelimited\n");
printf(" list_auth_zones list auth zones\n"); printf(" list_auth_zones list auth zones (includes RPZ zones)\n");
printf(" auth_zone_reload zone reload auth zone from zonefile\n"); printf(" auth_zone_reload zone reload auth zone (or RPZ zone) from zonefile\n");
printf(" auth_zone_transfer zone transfer auth zone from master\n"); printf(" auth_zone_transfer zone transfer auth zone (or RPZ zone) from master\n");
printf(" view_list_local_zones view list local-zones in view\n"); printf(" view_list_local_zones view list local-zones in view\n");
printf(" view_list_local_data view list local-data RRs in view\n"); printf(" view_list_local_data view list local-data RRs in view\n");
printf(" view_local_zone view name type add local-zone in view\n"); printf(" view_local_zone view name type add local-zone in view\n");
@ -444,7 +444,7 @@ static void do_stats_shm(struct config_file* cfg, struct ub_stats_info* stats,
#endif /* HAVE_SHMGET */ #endif /* HAVE_SHMGET */
/** print statistics from shm memory segment */ /** print statistics from shm memory segment */
static void print_stats_shm(const char* cfgfile) static void print_stats_shm(const char* cfgfile, int quiet)
{ {
#ifdef HAVE_SHMGET #ifdef HAVE_SHMGET
struct config_file* cfg; struct config_file* cfg;
@ -474,8 +474,11 @@ static void print_stats_shm(const char* cfgfile)
fatal_exit("shmat(%d): %s", id_arr, strerror(errno)); fatal_exit("shmat(%d): %s", id_arr, strerror(errno));
} }
if(!quiet) {
/* print the stats */ /* print the stats */
do_stats_shm(cfg, stats, shm_stat); do_stats_shm(cfg, stats, shm_stat);
}
/* shutdown */ /* shutdown */
shmdt(shm_stat); shmdt(shm_stat);
@ -499,7 +502,7 @@ static void ssl_path_err(const char* s, const char *path)
{ {
unsigned long err; unsigned long err;
err = ERR_peek_error(); err = ERR_peek_error();
if (ERR_GET_LIB(err) == ERR_LIB_SYS) { if(ERR_GET_LIB(err) == ERR_LIB_SYS) {
fprintf(stderr, "error: %s\n%s: %s\n", fprintf(stderr, "error: %s\n%s: %s\n",
s, path, ERR_reason_error_string(err)); s, path, ERR_reason_error_string(err));
exit(1); exit(1);
@ -541,11 +544,11 @@ setup_ctx(struct config_file* cfg)
#endif #endif
if(!SSL_CTX_use_certificate_chain_file(ctx,c_cert)) if(!SSL_CTX_use_certificate_chain_file(ctx,c_cert))
ssl_path_err("Error setting up SSL_CTX client cert", c_cert); ssl_path_err("Error setting up SSL_CTX client cert", c_cert);
if (!SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM)) if(!SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM))
ssl_path_err("Error setting up SSL_CTX client key", c_key); ssl_path_err("Error setting up SSL_CTX client key", c_key);
if (!SSL_CTX_check_private_key(ctx)) if(!SSL_CTX_check_private_key(ctx))
ssl_err("Error setting up SSL_CTX client key"); ssl_err("Error setting up SSL_CTX client key");
if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1) if(SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1)
ssl_path_err("Error setting up SSL_CTX verify, server cert", ssl_path_err("Error setting up SSL_CTX verify, server cert",
s_cert); s_cert);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
@ -880,8 +883,9 @@ go_cmd(SSL* ssl, int fd, int quiet, int argc, char* argv[])
if(first_line && strncmp(buf, "error", 5) == 0) { if(first_line && strncmp(buf, "error", 5) == 0) {
printf("%s", buf); printf("%s", buf);
was_error = 1; was_error = 1;
} else if (!quiet) } else if(!quiet) {
printf("%s", buf); printf("%s", buf);
}
first_line = 0; first_line = 0;
} }
@ -987,7 +991,7 @@ int main(int argc, char* argv[])
#endif #endif
} }
if(argc >= 1 && strcmp(argv[0], "stats_shm")==0) { if(argc >= 1 && strcmp(argv[0], "stats_shm")==0) {
print_stats_shm(cfgfile); print_stats_shm(cfgfile, quiet);
return 0; return 0;
} }
check_args_for_listcmd(argc, argv); check_args_for_listcmd(argc, argv);

View File

@ -221,10 +221,10 @@ static void zonemd_check_test(void)
unit_assert(result && reason == NULL); unit_assert(result && reason == NULL);
result = auth_zone_generate_zonemd_check(z, 241, hashalgo, result = auth_zone_generate_zonemd_check(z, 241, hashalgo,
hash, hashlen, region, buf, &reason); hash, hashlen, region, buf, &reason);
unit_assert(!result && strcmp(reason, "unsupported scheme")==0); unit_assert(result && strcmp(reason, "unsupported scheme")==0);
result = auth_zone_generate_zonemd_check(z, scheme, 242, result = auth_zone_generate_zonemd_check(z, scheme, 242,
hash, hashlen, region, buf, &reason); hash, hashlen, region, buf, &reason);
unit_assert(!result && strcmp(reason, "unsupported algorithm")==0); unit_assert(result && strcmp(reason, "unsupported algorithm")==0);
result = auth_zone_generate_zonemd_check(z, scheme, hashalgo, result = auth_zone_generate_zonemd_check(z, scheme, hashalgo,
hash, 2, region, buf, &reason); hash, 2, region, buf, &reason);
unit_assert(!result && strcmp(reason, "digest length too small, less than 12")==0); unit_assert(!result && strcmp(reason, "digest length too small, less than 12")==0);

View File

@ -0,0 +1,184 @@
; config options
server:
target-fetch-policy: "0 0 0 0 0"
auth-zone:
name: "example.com."
## zonefile (or none).
## zonefile: "example.com.zone"
## master by IP address or hostname
## can list multiple masters, each on one line.
## master:
## url for http fetch
## url:
## queries from downstream clients get authoritative answers.
## for-downstream: yes
for-downstream: no
## queries are used to fetch authoritative answers from this zone,
## instead of unbound itself sending queries there.
## for-upstream: yes
for-upstream: yes
## on failures with for-upstream, fallback to sending queries to
## the authority servers
## fallback-enabled: no
zonemd-check: yes
## this line generates zonefile: \n"/tmp/xxx.example.com"\n
zonefile:
TEMPFILE_NAME example.com
## this is the inline file /tmp/xxx.example.com
## the tempfiles are deleted when the testrun is over.
TEMPFILE_CONTENTS example.com
example.com. IN SOA ns.example.com. hostmaster.example.com. 200154054 28800 7200 604800 3600
example.com. IN NS ns.example.com.
example.com. IN ZONEMD 200154054 1 22 EFAA5B78B38AB1C45DE57B8167BCCE906451D0E72118E1F5E80B5F0C3CF04BFFC65D53C011185528EAD439D6F3A02F511961E090E5E4E0DFA013BD276D728B22
example.com. IN ZONEMD 200154054 21 2 EFAA5B78B38AB1C45DE57B8167BCCE906451D0E72118E1F5E80B5F0C3CF04BFFC65D53C011185528EAD439D6F3A02F511961E090E5E4E0DFA013BD276D728B22
www.example.com. IN A 127.0.0.1
ns.example.com. IN A 127.0.0.1
bar.example.com. IN A 1.2.3.4
ding.example.com. IN A 1.2.3.4
foo.example.com. IN A 1.2.3.4
TEMPFILE_END
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test authority zone with ZONEMD with unknown algo from zonefile
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 100
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION ANSWER
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.44
ENTRY_END
RANGE_END
; ns.example.net.
RANGE_BEGIN 0 100
ADDRESS 1.2.3.44
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.net. IN NS
SECTION ANSWER
example.net. IN NS ns.example.net.
SECTION ADDITIONAL
ns.example.net. IN A 1.2.3.44
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN A
SECTION ANSWER
ns.example.net. IN A 1.2.3.44
SECTION AUTHORITY
example.net. IN NS ns.example.net.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.net. IN AAAA
SECTION AUTHORITY
example.net. IN NS ns.example.net.
SECTION ADDITIONAL
www.example.net. IN A 1.2.3.44
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION ANSWER
example.com. IN NS ns.example.net.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; recursion happens here.
STEP 20 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 127.0.0.1
ENTRY_END
SCENARIO_END

View File

@ -0,0 +1 @@
rm -f K* piece1 base expired notyetincepted trust-anchors dnssec-failures.test.signed dnskey-failures.test.signed nsec-failures.test.signed rrsig-failures.test.signed

View File

@ -0,0 +1,10 @@
$ORIGIN dnskey-failures.test.
@ SOA ns hostmaster (
1 ; serial
14400 ; refresh (4 hours)
1800 ; retry (30 minutes)
2419200 ; expire (4 weeks)
300 ; minimum (5 minutes)
)
A 192.0.2.1

View File

@ -0,0 +1,15 @@
$ORIGIN dnssec-failures.test.
@ SOA ns hostmaster (
1 ; serial
14400 ; refresh (4 hours)
1800 ; retry (30 minutes)
2419200 ; expire (4 weeks)
300 ; minimum (5 minutes)
)
NS ns
ns A 192.0.2.1
notyetincepted TXT "Not yet incepted"
expired TXT "Expired"
sigsinvalid TXT "Signatures invalid"
missingrrsigs TXT "Signatures missing"

View File

@ -0,0 +1,67 @@
#!/usr/bin/env bash
# create oudated zones
CSK=`ldns-keygen -a ECDSAP256SHA256 -k -r /dev/urandom dnssec-failures.test`
echo $CSK
echo ". IN DS 20326 8 2 e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d" | \
cat $CSK.ds - > bogus/trust-anchors
# differentiate for MacOS with "gdate"
DATE=date
which gdate > /dev/null 2>&1 && DATE=gdate
ONEMONTHAGO=`$DATE -d 'now - 1 month' +%Y%m%d`
YESTERDAY=`$DATE -d 'now - 2 days' +%Y%m%d`
TOMORROW=`$DATE -d 'now + 2 days' +%Y%m%d`
ldns-signzone -i $YESTERDAY -f - bogus/dnssec-failures.test $CSK | \
grep -v '^missingrrsigs\.dnssec-failures\.test\..*IN.*RRSIG.*TXT' | \
sed 's/Signatures invalid/Signatures INVALID/g' | \
grep -v '^notyetincepted\.dnssec-failures\.test\..*IN.*TXT' | \
grep -v '^notyetincepted\.dnssec-failures\.test\..*IN.*RRSIG.*TXT' | \
grep -v '^expired\.dnssec-failures\.test\..*IN.*TXT' | \
grep -v '^expired\.dnssec-failures\.test\..*IN.*RRSIG.*TXT' > base
ldns-signzone -i $ONEMONTHAGO -e $YESTERDAY -f - bogus/dnssec-failures.test $CSK | \
grep -v '[ ]NSEC[ ]' | \
grep '^expired\.dnssec-failures\.test\..*IN.*TXT' > expired
ldns-signzone -i $TOMORROW -f - bogus/dnssec-failures.test $CSK | \
grep -v '[ ]NSEC[ ]' | \
grep '^notyetincepted\.dnssec-failures\.test\..*IN.*TXT' > notyetincepted
cat base expired notyetincepted > bogus/dnssec-failures.test.signed
# cleanup old zone keys
rm -f $CSK.*
# create zone with DNSKEY missing
CSK=`ldns-keygen -a ECDSAP256SHA256 -k -r /dev/urandom dnskey-failures.test`
echo $CSK
cat $CSK.ds >> bogus/trust-anchors
ldns-signzone -f tmp.signed bogus/dnskey-failures.test $CSK
grep -v ' DNSKEY ' tmp.signed > bogus/dnskey-failures.test.signed
# cleanup old zone keys
rm -f $CSK.*
# create zone with NSEC missing
CSK=`ldns-keygen -a ECDSAP256SHA256 -k -r /dev/urandom nsec-failures.test`
echo $CSK
cat $CSK.ds >> bogus/trust-anchors
ldns-signzone -f tmp.signed bogus/nsec-failures.test $CSK
grep -v ' NSEC ' tmp.signed > bogus/nsec-failures.test.signed
# cleanup old zone keys
rm -f $CSK.*
# create zone with RRSIGs missing
CSK=`ldns-keygen -a ECDSAP256SHA256 -k -r /dev/urandom rrsig-failures.test`
echo $CSK
cat $CSK.ds >> bogus/trust-anchors
ldns-signzone -f tmp.signed bogus/rrsig-failures.test $CSK
grep -v ' RRSIG ' tmp.signed > bogus/rrsig-failures.test.signed
# cleanup
rm -f base expired notyetincepted tmp.signed $CSK.*

View File

@ -0,0 +1,10 @@
$ORIGIN nsec-failures.test.
@ SOA ns hostmaster (
1 ; serial
14400 ; refresh (4 hours)
1800 ; retry (30 minutes)
2419200 ; expire (4 weeks)
300 ; minimum (5 minutes)
)
A 192.0.2.1

View File

@ -0,0 +1,10 @@
$ORIGIN rrsig-failures.test.
@ SOA ns hostmaster (
1 ; serial
14400 ; refresh (4 hours)
1800 ; retry (30 minutes)
2419200 ; expire (4 weeks)
300 ; minimum (5 minutes)
)
A 192.0.2.1

View File

@ -0,0 +1,27 @@
server:
verbosity: 1
use-syslog: no
chroot: ""
username: ""
directory: ""
pidfile: "unbound2.pid"
local-zone: test nodefault
interface: 127.0.0.1
port: @PORT2@
auth-zone:
name: "dnssec-failures.test"
zonefile: "bogus/dnssec-failures.test.signed"
auth-zone:
name: "dnskey-failures.test"
zonefile: "bogus/dnskey-failures.test.signed"
auth-zone:
name: "nsec-failures.test"
zonefile: "bogus/nsec-failures.test.signed"
auth-zone:
name: "rrsig-failures.test"
zonefile: "bogus/rrsig-failures.test.signed"

View File

@ -0,0 +1,49 @@
server:
verbosity: 2
interface: 127.0.0.1
port: @PORT@
use-syslog: no
directory: .
pidfile: "unbound.pid"
chroot: ""
username: ""
directory: ""
val-log-level: 2
trust-anchor-file: "bogus/trust-anchors"
module-config: "respip validator iterator"
ede: yes
access-control: 127.0.0.2/32 refuse
access-control: 127.0.0.3/32 allow
local-zone: hopsa.kidee. always_refuse
local-data: "hopsa.kidee. TXT hela hola"
local-zone: nlnetlabs.nl transparent
local-data: "hopsa.nlnetlabs.nl. TXT hela hola"
local-zone: uva.nl. always_null
local-zone: example.com redirect
local-data: "example.com CNAME *.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaa."
local-zone: test nodefault
do-not-query-localhost: no
forward-zone:
name: "dnssec-failures.test"
forward-addr: 127.0.0.1@@PORT2@
forward-zone:
name: "dnskey-failures.test"
forward-addr: 127.0.0.1@@PORT2@
forward-zone:
name: "nsec-failures.test"
forward-addr: 127.0.0.1@@PORT2@
forward-zone:
name: "rrsig-failures.test"
forward-addr: 127.0.0.1@@PORT2@

View File

@ -0,0 +1,16 @@
BaseName: ede
Version: 1.0
Description: Test Extended DNS Errors (rfc8914)
CreationDate: Fri Aug 20 15:42:11 UTC 2021
Maintainer: Tom Carpay
Category:
Component:
CmdDepends:
Depends:
Help:
Pre: ede.pre
Post: ede.post
Test: ede.test
AuxFiles:
Passed:
Failure:

View File

@ -0,0 +1,10 @@
# #-- ede.post --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
# teardown
. ../common.sh
kill_pid $UNBOUND_PID
kill_pid $UNBOUND_PID2

View File

@ -0,0 +1,37 @@
# #-- ede.pre --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh
get_random_port 2
UNBOUND_PORT=$RND_PORT
UNBOUND_PORT2=$(($RND_PORT + 1))
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
echo "UNBOUND_PORT2=$UNBOUND_PORT2" >> .tpkg.var.test
# rewrite config file with created ports
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' < ede.conf > temp.conf
sed -e 's/@PORT2\@/'$UNBOUND_PORT2'/' < temp.conf > ub.conf
sed -e 's/@PORT2\@/'$UNBOUND_PORT2'/' < ede-auth.conf > ub2.conf
# create broken dnssec zone
bogus/make-broken-zone.sh
# start unbound in the background
PRE="../.."
$PRE/unbound -d -c ub.conf > unbound.log 2>&1 &
UNBOUND_PID=$!
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
# start authoritative unbound in the background
$PRE/unbound -d -c ub2.conf > unbound2.log 2>&1 &
UNBOUND_PID2=$!
echo "UNBOUND_PID2=$UNBOUND_PID2" >> .tpkg.var.test
cat .tpkg.var.test
wait_unbound_up unbound.log
wait_unbound_up unbound2.log

View File

@ -0,0 +1,72 @@
# #-- ede.test --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
# DNSSEC failure: Signature Expired or DNSKEY Missing (depending on the servfail configuration)
dig @127.0.0.1 -p $UNBOUND_PORT servfail.nl > servfail.txt
# DNSSEC failure: key not incepted
dig @127.0.0.1 -p $UNBOUND_PORT notyetincepted.dnssec-failures.test. TXT +dnssec > sig_notyetincepted.txt
if ! grep -q -e "OPT=15: 00 08" -e "EDE: 8" sig_notyetincepted.txt
then
echo "Signature not yet valid does not return EDE Signature Not Yet Valid"
cat sig_notyetincepted.txt
exit 1
fi
# DNSSEC failure: key expired
dig @127.0.0.1 -p $UNBOUND_PORT expired.dnssec-failures.test. TXT +dnssec > sig_expired.txt
if ! grep -q -e "OPT=15: 00 07" -e "EDE: 7" sig_expired.txt
then
echo "Expired signature does not return EDE Signature expired"
cat sig_expired.txt
exit 1
fi
# DNSSEC failure: missing rrsigs
dig @127.0.0.1 -p $UNBOUND_PORT missingrrsigs.dnssec-failures.test. TXT +dnssec > missingrrsigs.txt
if ! grep -q -e "OPT=15: 00 0a" -e "EDE: 10" missingrrsigs.txt
then
echo "Expired signature does not return EDE RRSIGs missing"
cat missingrrsigs.txt
exit 1
fi
# signed zone with DNSKEY missing
dig @127.0.0.1 -p $UNBOUND_PORT dnskey-failures.test > dnskey-failure.txt
if ! grep -q -e "OPT=15: 00 09" -e "EDE: 9" dnskey-failure.txt
then
echo "Expired signature does not return EDE DNSKEY missing"
cat dnskey-failure.txt
exit 1
fi
# signed zone with RRSIGs missing
dig @127.0.0.1 -p $UNBOUND_PORT rrsig-failures.test > rrsig-failure.txt
if ! grep -q -e "OPT=15: 00 0a" -e "EDE: 10" rrsig-failure.txt
then
echo "Expired signature does not return EDE RRSIGs missing"
cat rrsig-failure.txt
exit 1
fi
# signed zone with NSEC missing
dig @127.0.0.1 -p $UNBOUND_PORT abc.nsec-failures.test > nsec-failure.txt
if ! grep -q -e "OPT=15: 00 0c" -e "EDE: 12" nsec-failure.txt
then
echo "Expired signature does not return EDE NSEC missing"
cat nsec-failure.txt
exit 1
fi
# @TODO DNSSEC indeterminate when implemented

View File

@ -0,0 +1,35 @@
; config options
server:
access-control: 127.0.0.0/8 refuse
ede: yes
CONFIG_END
SCENARIO_BEGIN Test ede-acl-refused
; Scenario overview:
; - query for example.com. A record with EDNS
; - check that we get a refused answer with EDE (RFC8914) code 18 - Prohibited
; Query without RD flag
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
example.com. IN A
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
HEX_EDNSDATA_END
ENTRY_END
; Check that we got ede 18
STEP 2 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ede=18
REPLY QR RD REFUSED
SECTION QUESTION
example.com. IN A
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
HEX_EDNSDATA_END
ENTRY_END
SCENARIO_END

View File

@ -0,0 +1,33 @@
; config options
server:
ede: yes
CONFIG_END
SCENARIO_BEGIN Test ede-cache-snoop-not-authoritative
; Scenario overview:
; - query for example.com. A record with EDNS without the RD bit
; - check that we get a refused answer with EDE (RFC8914) code 20 - Not Authoritative
; Query without RD flag
STEP 1 QUERY
ENTRY_BEGIN
SECTION QUESTION
example.com. IN A
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
HEX_EDNSDATA_END
ENTRY_END
; Check that we got ede 20
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ede=20
REPLY QR RA REFUSED
SECTION QUESTION
example.com. IN A
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
HEX_EDNSDATA_END
ENTRY_END
SCENARIO_END

View File

@ -0,0 +1,37 @@
; config options
server:
local-zone: example.com redirect
local-data: "example.com CNAME *.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaa."
ede: yes
CONFIG_END
SCENARIO_BEGIN Test ede-localzone-dname-expansion
; Scenario overview:
; - query for www.qhqwer.qwer.qwer.h.example.com. (a large Qname) A record with EDNS
; - check that we get a YXDOMAIN answer with EDE (RFC8914) code 0 - Other (which adds a DNAME expansion message)
; Query with RD flag
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.qhqwer.qwer.qwer.h.example.com A
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
HEX_EDNSDATA_END
ENTRY_END
; Check that we got the correct answer (should be cached)
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ede=0
REPLY QR AA RD RA YXDOMAIN
SECTION QUESTION
www.qhqwer.qwer.qwer.h.example.com A
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
HEX_EDNSDATA_END
ENTRY_END
SCENARIO_END

View File

@ -0,0 +1,23 @@
server:
verbosity: 3
num-threads: 1
module-config: "ipset iterator"
outgoing-range: 16
interface: 127.0.0.1
port: @PORT@
use-syslog: no
directory: ""
pidfile: "unbound.pid"
chroot: ""
username: ""
do-not-query-localhost: no
local-zone: "example.net." ipset
stub-zone:
name: "example.net."
stub-addr: "127.0.0.1@@TOPORT@"
stub-zone:
name: "example.com."
stub-addr: "127.0.0.1@@TOPORT@"
ipset:
name-v4: atotallymadeupnamefor4
name-v6: atotallymadeupnamefor6

View File

@ -0,0 +1,16 @@
BaseName: ipset
Version: 1.0
Description: mock test ipset module
CreationDate: Wed Mar 2 13:00:38 CET 2022
Maintainer: George Thessalonikefs
Category:
Component:
CmdDepends:
Depends:
Help:
Pre: ipset.pre
Post: ipset.post
Test: ipset.test
AuxFiles:
Passed:
Failure:

View File

@ -0,0 +1,14 @@
# #-- ipset.post --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# source the test var file when it's there
[ -f .tpkg.var.test ] && source .tpkg.var.test
#
# do your teardown here
. ../common.sh
PRE="../.."
if grep "define USE_IPSET 1" $PRE/config.h; then echo test enabled; else echo test skipped; exit 0; fi
kill_pid $FWD_PID
kill_pid $UNBOUND_PID
cat unbound.log
exit 0

View File

@ -0,0 +1,33 @@
# #-- ipset.pre--#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh
PRE="../.."
if grep "define USE_IPSET 1" $PRE/config.h; then echo test enabled; else echo test skipped; exit 0; fi
get_random_port 2
UNBOUND_PORT=$RND_PORT
FWD_PORT=$(($RND_PORT + 1))
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test
# start forwarder
get_ldns_testns
$LDNS_TESTNS -p $FWD_PORT ipset.testns >fwd.log 2>&1 &
FWD_PID=$!
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
# make config file
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' < ipset.conf > ub.conf
# start unbound in the background
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
UNBOUND_PID=$!
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
cat .tpkg.var.test
wait_ldns_testns_up fwd.log
wait_unbound_up unbound.log

View File

@ -0,0 +1,155 @@
# #-- ipset.test --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh
PRE="../.."
if grep "define USE_IPSET 1" $PRE/config.h; then echo test enabled; else echo test skipped; exit 0; fi
# Make all the queries. They need to succeed by the way.
echo "> dig www.example.net."
dig @127.0.0.1 -p $UNBOUND_PORT www.example.net. | tee outfile
echo "> check answer"
if grep "1.1.1.1" outfile; then
echo "OK"
else
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> check ipset"
if grep "ipset: add 1.1.1.1 to atotallymadeupnamefor4 for www.example.net." unbound.log; then
echo "ipset OK"
else
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> dig www.example.net. AAAA"
dig @127.0.0.1 -p $UNBOUND_PORT www.example.net. AAAA | tee outfile
echo "> check answer"
if grep "::1" outfile; then
echo "OK"
else
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> check ipset"
if grep "ipset: add ::1 to atotallymadeupnamefor6 for www.example.net." unbound.log; then
echo "ipset OK"
else
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> dig cname.example.net."
dig @127.0.0.1 -p $UNBOUND_PORT cname.example.net. | tee outfile
echo "> check answer"
if grep "2.2.2.2" outfile; then
echo "OK"
else
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> check ipset"
if grep "ipset: add 2.2.2.2 to atotallymadeupnamefor4 for target.example.net." unbound.log; then
echo "ipset OK"
else
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> dig cname.example.net. AAAA"
dig @127.0.0.1 -p $UNBOUND_PORT cname.example.net. AAAA | tee outfile
echo "> check answer"
if grep "::2" outfile; then
echo "OK"
else
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> check ipset"
if grep "ipset: add ::2 to atotallymadeupnamefor6 for target.example.net." unbound.log; then
echo "ipset OK"
else
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> dig outsidecname.example.net."
dig @127.0.0.1 -p $UNBOUND_PORT outsidecname.example.net. | tee outfile
echo "> check answer"
if grep "3.3.3.3" outfile; then
echo "OK"
else
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> check ipset"
if grep "ipset: add 3.3.3.3 to atotallymadeupnamefor4 for target.example.com." unbound.log; then
echo "ipset OK"
else
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> dig outsidecname.example.net. AAAA"
dig @127.0.0.1 -p $UNBOUND_PORT outsidecname.example.net. AAAA | tee outfile
echo "> check answer"
if grep "::3" outfile; then
echo "OK"
else
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> check ipset"
if grep "ipset: add ::3 to atotallymadeupnamefor6 for target.example.com." unbound.log; then
echo "ipset OK"
else
echo "> cat logfiles"
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> cat logfiles"
cat tap.log
cat tap.errlog
cat fwd.log
echo "> OK"
exit 0

View File

@ -0,0 +1,103 @@
; nameserver test file
$ORIGIN example.net.
$TTL 3600
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
www IN A
SECTION ANSWER
www IN A 1.1.1.1
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
www IN AAAA
SECTION ANSWER
www IN AAAA ::1
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
cname IN A
SECTION ANSWER
cname IN CNAME target.example.net.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
cname IN AAAA
SECTION ANSWER
cname IN CNAME target.example.net.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
outsidecname IN A
SECTION ANSWER
outsidecname IN CNAME target.example.com.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
outsidecname IN AAAA
SECTION ANSWER
outsidecname IN CNAME target.example.com.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
target IN A
SECTION ANSWER
target IN A 2.2.2.2
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
target IN AAAA
SECTION ANSWER
target IN AAAA ::2
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
target.example.com. IN A
SECTION ANSWER
target.example.com. IN A 3.3.3.3
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
target.example.com. IN AAAA
SECTION ANSWER
target.example.com. IN AAAA ::3
ENTRY_END

View File

@ -0,0 +1,179 @@
; config options
server:
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: yes
module-config: "iterator"
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test cname chain resolution with qname minimisation.
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 100
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION ANSWER
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.44
ENTRY_END
RANGE_END
; ns.example.com.
RANGE_BEGIN 0 100
ADDRESS 1.2.3.44
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION ANSWER
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.44
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN A
SECTION ANSWER
ns.example.com. IN A 1.2.3.44
SECTION AUTHORITY
example.com. IN NS ns.example.com.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN AAAA
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
www.example.com. IN A 1.2.3.44
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 300 IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com IN A 1.2.3.44
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
c.example.com. IN A
SECTION ANSWER
c.example.com. 10 IN CNAME www.example.com.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
c.example.com. IN CNAME
SECTION ANSWER
c.example.com. 10 IN CNAME www.example.com.
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
c.example.com. IN CNAME
ENTRY_END
STEP 20 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
c.example.com. IN CNAME
SECTION ANSWER
c.example.com. 10 IN CNAME www.example.com.
ENTRY_END
STEP 30 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
c.example.com. IN A
ENTRY_END
STEP 40 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
c.example.com. IN A
SECTION ANSWER
c.example.com. 10 IN CNAME www.example.com.
www.example.com. 300 IN A 10.20.30.40
ENTRY_END
SCENARIO_END

View File

@ -0,0 +1,168 @@
; config options
server:
do-ip6: no
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test iterator when doip6 is no and dp is useless with only ip6
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 100
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION ANSWER
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
; short TTL here, so it can expire
ns.example.com. 1 IN A 1.2.3.4
ns.example.com. 100 IN AAAA ::53
ENTRY_END
RANGE_END
; ns.example.com.
RANGE_BEGIN 0 100
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION ANSWER
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
; short TTL here, so it can expire
ns.example.com. 1 IN A 1.2.3.4
ns.example.com. 100 IN AAAA ::53
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN A
SECTION ANSWER
; short TTL
ns.example.com. 1 IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN AAAA
SECTION ANSWER
ns.example.com. IN AAAA ::53
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
mail.example.com. IN A
SECTION ANSWER
mail.example.com. IN A 10.20.30.50
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; recursion happens here.
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
ENTRY_END
STEP 20 TIME_PASSES ELAPSE 5.0
STEP 30 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
mail.example.com. IN A
ENTRY_END
STEP 40 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
mail.example.com. IN A
SECTION ANSWER
mail.example.com. IN A 10.20.30.50
ENTRY_END
SCENARIO_END

View File

@ -9,6 +9,7 @@ server:
trust-anchor-signaling: no trust-anchor-signaling: no
minimal-responses: no minimal-responses: no
nsid: "ascii_hopsa kidee" nsid: "ascii_hopsa kidee"
ede: yes
stub-zone: stub-zone:
name: "." name: "."
@ -157,7 +158,7 @@ ENTRY_END
; recursion happens here. ; recursion happens here.
STEP 10 CHECK_ANSWER STEP 10 CHECK_ANSWER
ENTRY_BEGIN ENTRY_BEGIN
MATCH all MATCH all ede=9
REPLY QR RD RA DO SERVFAIL REPLY QR RD RA DO SERVFAIL
SECTION QUESTION SECTION QUESTION
www.example.com. IN A www.example.com. IN A

View File

@ -0,0 +1,154 @@
; config options
server:
module-config: "respip validator iterator"
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
access-control: 192.0.0.0/8 allow
rpz:
name: "rpz.example.com."
rpz-log: yes
rpz-log-name: "rpz.example.com"
rpz-action-override: passthru
zonefile:
TEMPFILE_NAME rpz.example.com
TEMPFILE_CONTENTS rpz.example.com
$ORIGIN example.com.
rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz.example.com.
3600 IN NS ns2.rpz.example.com.
$ORIGIN rpz.example.com.
c.a TXT "local data 1st zone"
d.a A 127.0.0.1
TEMPFILE_END
rpz:
name: "wl.example.com."
rpz-log: yes
rpz-log-name: "wl.example.com"
zonefile:
TEMPFILE_NAME wl.example.com
TEMPFILE_CONTENTS wl.example.com
$ORIGIN example.com.
wl 3600 IN SOA ns1.wl.example.com. hostmaster.wl.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.wl.example.com.
3600 IN NS ns2.wl.example.com.
$ORIGIN wl.example.com.
e.a CNAME rpz-passthru.
TEMPFILE_END
rpz:
name: "rpz2.example.com."
rpz-log: yes
rpz-log-name: "rpz2.example.com"
rpz-action-override: nxdomain
zonefile:
TEMPFILE_NAME rpz2.example.com
TEMPFILE_CONTENTS rpz2.example.com
$ORIGIN example.com.
rpz2 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz.example.com.
3600 IN NS ns2.rpz.example.com.
$ORIGIN rpz2.example.com.
c.a TXT "local data 2nd zone"
24.0.5.0.192.rpz-client-ip A 127.0.0.1
24.0.5.0.192.rpz-client-ip TXT "clientip 2nd zone"
24.0.3.2.1.rpz-ip A 127.0.0.2
TEMPFILE_END
stub-zone:
name: "a."
stub-addr: 10.20.30.40
CONFIG_END
SCENARIO_BEGIN Test RPZ passthru ends processing for later triggers.
; a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.40
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
c.a. IN TXT
SECTION ANSWER
c.a. IN TXT "answer from upstream ns"
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
d.a. IN A
SECTION ANSWER
d.a. IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
e.a. IN A
SECTION ANSWER
e.a. IN A 1.2.3.4
ENTRY_END
RANGE_END
STEP 10 QUERY ADDRESS 192.0.5.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
c.a. IN TXT
ENTRY_END
STEP 11 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
c.a. IN TXT
SECTION ANSWER
c.a. IN TXT "answer from upstream ns"
ENTRY_END
STEP 20 QUERY ADDRESS 192.0.2.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.a. IN A
ENTRY_END
STEP 21 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
d.a. IN A
SECTION ANSWER
d.a. IN A 1.2.3.4
ENTRY_END
STEP 30 QUERY ADDRESS 192.0.2.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
e.a. IN A
ENTRY_END
STEP 31 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
e.a. IN A
SECTION ANSWER
e.a. IN A 1.2.3.4
ENTRY_END
SCENARIO_END

View File

@ -0,0 +1,215 @@
; Check if the prefetch option works properly for messages stored in the global
; cache for non-ECS clients. The prefetch query needs to result in an ECS
; outgoing query based on the client's IP.
server:
trust-anchor-signaling: no
target-fetch-policy: "0 0 0 0 0"
send-client-subnet: 1.2.3.4
max-client-subnet-ipv4: 21
module-config: "subnetcache iterator"
verbosity: 3
access-control: 127.0.0.1 allow_snoop
qname-minimisation: no
minimal-responses: no
serve-expired: yes
prefetch: yes
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test prefetch option for global cache
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 100
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION ANSWER
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns.example.com.
RANGE_BEGIN 0 10
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION ANSWER
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
ENTRY_END
; response to query of interest
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns.example.com.
RANGE_BEGIN 11 100
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION ANSWER
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
ENTRY_END
; response to query of interest
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id copy_ednsdata_assume_clientsubnet
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
00 08 ; OPC
00 07 ; option length
00 01 ; Family
15 00 ; source mask, scopemask
7f 00 00 ; address
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; This answer should be in the global cache
STEP 2 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
; Try to trigger a prefetch
STEP 3 TIME_PASSES ELAPSE 11
STEP 11 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; This expired record came from the cache and a prefetch is triggered
STEP 12 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 30 IN A 10.20.30.40
SECTION AUTHORITY
example.com. 3589 IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. 3589 IN A 1.2.3.4
ENTRY_END
; Allow upstream to reply to the prefetch query.
; It can only be answered if correct ECS was derived from the client's IP.
; Otherwise the test will fail with "messages pending".
STEP 13 TRAFFIC
SCENARIO_END

View File

@ -0,0 +1,221 @@
; Check if the prefetch option works properly for messages stored in the global
; cache for ECS clients. The prefetch query needs to result in an ECS
; outgoing query using the client's ECS data.
server:
trust-anchor-signaling: no
target-fetch-policy: "0 0 0 0 0"
send-client-subnet: 1.2.3.4
max-client-subnet-ipv4: 21
module-config: "subnetcache iterator"
verbosity: 3
access-control: 127.0.0.1 allow_snoop
qname-minimisation: no
minimal-responses: no
serve-expired: yes
prefetch: yes
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test prefetch option for global cache
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 100
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION ANSWER
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns.example.com.
RANGE_BEGIN 0 10
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION ANSWER
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
ENTRY_END
; response to query of interest
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns.example.com.
RANGE_BEGIN 11 100
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION ANSWER
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
ENTRY_END
; response to query of interest
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id copy_ednsdata_assume_clientsubnet
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
00 08 ; OPC
00 05 ; option length
00 01 ; Family
08 00 ; source mask, scopemask
7f ; address
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; This answer should be in the global cache
STEP 2 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
; Try to trigger a prefetch
STEP 3 TIME_PASSES ELAPSE 11
STEP 11 QUERY
ENTRY_BEGIN
REPLY RD DO
SECTION QUESTION
www.example.com. IN A
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
00 08 00 05 ; OPC, optlen
00 01 08 00 ; ip4, source 8, scope 0
7f ; 127.0.0.0/8
HEX_EDNSDATA_END
ENTRY_END
; This expired record came from the cache and a prefetch is triggered
STEP 12 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA DO NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 30 IN A 10.20.30.40
SECTION AUTHORITY
example.com. 3589 IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. 3589 IN A 1.2.3.4
ENTRY_END
; Allow upstream to reply to the prefetch query.
; It can only be answered if correct ECS was derived from the client's IP.
; Otherwise the test will fail with "messages pending".
STEP 13 TRAFFIC
SCENARIO_END

View File

@ -195,6 +195,7 @@ config_create(void)
cfg->use_systemd = 0; cfg->use_systemd = 0;
cfg->do_daemonize = 1; cfg->do_daemonize = 1;
cfg->if_automatic = 0; cfg->if_automatic = 0;
cfg->if_automatic_ports = NULL;
cfg->so_rcvbuf = 0; cfg->so_rcvbuf = 0;
cfg->so_sndbuf = 0; cfg->so_sndbuf = 0;
cfg->so_reuseport = REUSEPORT_DEFAULT; cfg->so_reuseport = REUSEPORT_DEFAULT;
@ -267,6 +268,7 @@ config_create(void)
cfg->serve_expired_ttl_reset = 0; cfg->serve_expired_ttl_reset = 0;
cfg->serve_expired_reply_ttl = 30; cfg->serve_expired_reply_ttl = 30;
cfg->serve_expired_client_timeout = 0; cfg->serve_expired_client_timeout = 0;
cfg->ede_serve_expired = 0;
cfg->serve_original_ttl = 0; cfg->serve_original_ttl = 0;
cfg->zonemd_permissive_mode = 0; cfg->zonemd_permissive_mode = 0;
cfg->add_holddown = 30*24*3600; cfg->add_holddown = 30*24*3600;
@ -375,6 +377,7 @@ config_create(void)
cfg->ipset_name_v4 = NULL; cfg->ipset_name_v4 = NULL;
cfg->ipset_name_v6 = NULL; cfg->ipset_name_v6 = NULL;
#endif #endif
cfg->ede = 0;
return cfg; return cfg;
error_exit: error_exit:
config_delete(cfg); config_delete(cfg);
@ -476,7 +479,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else if(atoi(val) == 0) else if(atoi(val) == 0)
return 0; return 0;
else cfg->stat_interval = atoi(val); else cfg->stat_interval = atoi(val);
} else if(strcmp(opt, "num_threads:") == 0) { } else if(strcmp(opt, "num-threads:") == 0) {
/* not supported, library must have 1 thread in bgworker */ /* not supported, library must have 1 thread in bgworker */
return 0; return 0;
} else if(strcmp(opt, "outgoing-port-permit:") == 0) { } else if(strcmp(opt, "outgoing-port-permit:") == 0) {
@ -543,6 +546,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("ssl-cert-bundle:", tls_cert_bundle) else S_STR("ssl-cert-bundle:", tls_cert_bundle)
else S_STR("tls-cert-bundle:", tls_cert_bundle) else S_STR("tls-cert-bundle:", tls_cert_bundle)
else S_YNO("tls-win-cert:", tls_win_cert) else S_YNO("tls-win-cert:", tls_win_cert)
else S_YNO("tls-system-cert:", tls_win_cert)
else S_STRLIST("additional-ssl-port:", tls_additional_port) else S_STRLIST("additional-ssl-port:", tls_additional_port)
else S_STRLIST("additional-tls-port:", tls_additional_port) else S_STRLIST("additional-tls-port:", tls_additional_port)
else S_STRLIST("tls-additional-ports:", tls_additional_port) else S_STRLIST("tls-additional-ports:", tls_additional_port)
@ -559,6 +563,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("http-nodelay:", http_nodelay) else S_YNO("http-nodelay:", http_nodelay)
else S_YNO("http-notls-downstream:", http_notls_downstream) else S_YNO("http-notls-downstream:", http_notls_downstream)
else S_YNO("interface-automatic:", if_automatic) else S_YNO("interface-automatic:", if_automatic)
else S_STR("interface-automatic-ports:", if_automatic_ports)
else S_YNO("use-systemd:", use_systemd) else S_YNO("use-systemd:", use_systemd)
else S_YNO("do-daemonize:", do_daemonize) else S_YNO("do-daemonize:", do_daemonize)
else S_NUMBER_NONZERO("port:", port) else S_NUMBER_NONZERO("port:", port)
@ -668,6 +673,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
else if(strcmp(opt, "serve-expired-reply-ttl:") == 0) else if(strcmp(opt, "serve-expired-reply-ttl:") == 0)
{ IS_NUMBER_OR_ZERO; cfg->serve_expired_reply_ttl = atoi(val); SERVE_EXPIRED_REPLY_TTL=(time_t)cfg->serve_expired_reply_ttl;} { IS_NUMBER_OR_ZERO; cfg->serve_expired_reply_ttl = atoi(val); SERVE_EXPIRED_REPLY_TTL=(time_t)cfg->serve_expired_reply_ttl;}
else S_NUMBER_OR_ZERO("serve-expired-client-timeout:", serve_expired_client_timeout) else S_NUMBER_OR_ZERO("serve-expired-client-timeout:", serve_expired_client_timeout)
else S_YNO("ede:", ede)
else S_YNO("ede-serve-expired:", ede_serve_expired)
else S_YNO("serve-original-ttl:", serve_original_ttl) else S_YNO("serve-original-ttl:", serve_original_ttl)
else S_STR("val-nsec3-keysize-iterations:", val_nsec3_key_iterations) else S_STR("val-nsec3-keysize-iterations:", val_nsec3_key_iterations)
else S_YNO("zonemd-permissive-mode:", zonemd_permissive_mode) else S_YNO("zonemd-permissive-mode:", zonemd_permissive_mode)
@ -990,6 +997,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_IFC(opt, "interface", num_ifs, ifs) else O_IFC(opt, "interface", num_ifs, ifs)
else O_IFC(opt, "outgoing-interface", num_out_ifs, out_ifs) else O_IFC(opt, "outgoing-interface", num_out_ifs, out_ifs)
else O_YNO(opt, "interface-automatic", if_automatic) else O_YNO(opt, "interface-automatic", if_automatic)
else O_STR(opt, "interface-automatic-ports", if_automatic_ports)
else O_DEC(opt, "port", port) else O_DEC(opt, "port", port)
else O_DEC(opt, "outgoing-range", outgoing_num_ports) else O_DEC(opt, "outgoing-range", outgoing_num_ports)
else O_DEC(opt, "outgoing-num-tcp", outgoing_num_tcp) else O_DEC(opt, "outgoing-num-tcp", outgoing_num_tcp)
@ -1049,6 +1057,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_STR(opt, "ssl-cert-bundle", tls_cert_bundle) else O_STR(opt, "ssl-cert-bundle", tls_cert_bundle)
else O_STR(opt, "tls-cert-bundle", tls_cert_bundle) else O_STR(opt, "tls-cert-bundle", tls_cert_bundle)
else O_YNO(opt, "tls-win-cert", tls_win_cert) else O_YNO(opt, "tls-win-cert", tls_win_cert)
else O_YNO(opt, "tls-system-cert", tls_win_cert)
else O_LST(opt, "additional-ssl-port", tls_additional_port) else O_LST(opt, "additional-ssl-port", tls_additional_port)
else O_LST(opt, "additional-tls-port", tls_additional_port) else O_LST(opt, "additional-tls-port", tls_additional_port)
else O_LST(opt, "tls-additional-ports", tls_additional_port) else O_LST(opt, "tls-additional-ports", tls_additional_port)
@ -1108,6 +1117,8 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "serve-expired-ttl-reset", serve_expired_ttl_reset) else O_YNO(opt, "serve-expired-ttl-reset", serve_expired_ttl_reset)
else O_DEC(opt, "serve-expired-reply-ttl", serve_expired_reply_ttl) else O_DEC(opt, "serve-expired-reply-ttl", serve_expired_reply_ttl)
else O_DEC(opt, "serve-expired-client-timeout", serve_expired_client_timeout) else O_DEC(opt, "serve-expired-client-timeout", serve_expired_client_timeout)
else O_YNO(opt, "ede", ede)
else O_YNO(opt, "ede-serve-expired", ede_serve_expired)
else O_YNO(opt, "serve-original-ttl", serve_original_ttl) else O_YNO(opt, "serve-original-ttl", serve_original_ttl)
else O_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations) else O_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations)
else O_YNO(opt, "zonemd-permissive-mode", zonemd_permissive_mode) else O_YNO(opt, "zonemd-permissive-mode", zonemd_permissive_mode)
@ -1534,6 +1545,7 @@ config_delete(struct config_file* cfg)
free(cfg->directory); free(cfg->directory);
free(cfg->logfile); free(cfg->logfile);
free(cfg->pidfile); free(cfg->pidfile);
free(cfg->if_automatic_ports);
free(cfg->target_fetch_policy); free(cfg->target_fetch_policy);
free(cfg->ssl_service_key); free(cfg->ssl_service_key);
free(cfg->ssl_service_pem); free(cfg->ssl_service_pem);
@ -2553,126 +2565,6 @@ void w_config_adjust_directory(struct config_file* cfg)
} }
#endif /* UB_ON_WINDOWS */ #endif /* UB_ON_WINDOWS */
void errinf(struct module_qstate* qstate, const char* str)
{
struct config_strlist* p;
if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str)
return;
p = (struct config_strlist*)regional_alloc(qstate->region, sizeof(*p));
if(!p) {
log_err("malloc failure in validator-error-info string");
return;
}
p->next = NULL;
p->str = regional_strdup(qstate->region, str);
if(!p->str) {
log_err("malloc failure in validator-error-info string");
return;
}
/* add at end */
if(qstate->errinf) {
struct config_strlist* q = qstate->errinf;
while(q->next)
q = q->next;
q->next = p;
} else qstate->errinf = p;
}
void errinf_origin(struct module_qstate* qstate, struct sock_list *origin)
{
struct sock_list* p;
if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
return;
for(p=origin; p; p=p->next) {
char buf[256];
if(p == origin)
snprintf(buf, sizeof(buf), "from ");
else snprintf(buf, sizeof(buf), "and ");
if(p->len == 0)
snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf),
"cache");
else
addr_to_str(&p->addr, p->len, buf+strlen(buf),
sizeof(buf)-strlen(buf));
errinf(qstate, buf);
}
}
char* errinf_to_str_bogus(struct module_qstate* qstate)
{
char buf[20480];
char* p = buf;
size_t left = sizeof(buf);
struct config_strlist* s;
char dname[LDNS_MAX_DOMAINLEN+1];
char t[16], c[16];
sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
dname_str(qstate->qinfo.qname, dname);
snprintf(p, left, "validation failure <%s %s %s>:", dname, t, c);
left -= strlen(p); p += strlen(p);
if(!qstate->errinf)
snprintf(p, left, " misc failure");
else for(s=qstate->errinf; s; s=s->next) {
snprintf(p, left, " %s", s->str);
left -= strlen(p); p += strlen(p);
}
p = strdup(buf);
if(!p)
log_err("malloc failure in errinf_to_str");
return p;
}
char* errinf_to_str_servfail(struct module_qstate* qstate)
{
char buf[20480];
char* p = buf;
size_t left = sizeof(buf);
struct config_strlist* s;
char dname[LDNS_MAX_DOMAINLEN+1];
char t[16], c[16];
sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
dname_str(qstate->qinfo.qname, dname);
snprintf(p, left, "SERVFAIL <%s %s %s>:", dname, t, c);
left -= strlen(p); p += strlen(p);
if(!qstate->errinf)
snprintf(p, left, " misc failure");
else for(s=qstate->errinf; s; s=s->next) {
snprintf(p, left, " %s", s->str);
left -= strlen(p); p += strlen(p);
}
p = strdup(buf);
if(!p)
log_err("malloc failure in errinf_to_str");
return p;
}
void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr)
{
char buf[1024];
char dname[LDNS_MAX_DOMAINLEN+1];
char t[16], c[16];
if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !rr)
return;
sldns_wire2str_type_buf(ntohs(rr->rk.type), t, sizeof(t));
sldns_wire2str_class_buf(ntohs(rr->rk.rrset_class), c, sizeof(c));
dname_str(rr->rk.dname, dname);
snprintf(buf, sizeof(buf), "for <%s %s %s>", dname, t, c);
errinf(qstate, buf);
}
void errinf_dname(struct module_qstate* qstate, const char* str, uint8_t* dname)
{
char b[1024];
char buf[LDNS_MAX_DOMAINLEN+1];
if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str || !dname)
return;
dname_str(dname, buf);
snprintf(b, sizeof(b), "%s %s", str, buf);
errinf(qstate, b);
}
int options_remote_is_address(struct config_file* cfg) int options_remote_is_address(struct config_file* cfg)
{ {
if(!cfg->remote_control_enable) return 0; if(!cfg->remote_control_enable) return 0;

View File

@ -41,6 +41,7 @@
#ifndef UTIL_CONFIG_FILE_H #ifndef UTIL_CONFIG_FILE_H
#define UTIL_CONFIG_FILE_H #define UTIL_CONFIG_FILE_H
#include "sldns/rrdef.h"
struct config_stub; struct config_stub;
struct config_auth; struct config_auth;
struct config_view; struct config_view;
@ -205,6 +206,8 @@ struct config_file {
/** automatic interface for incoming messages. Uses ipv6 remapping, /** automatic interface for incoming messages. Uses ipv6 remapping,
* and recvmsg/sendmsg ancillary data to detect interfaces, boolean */ * and recvmsg/sendmsg ancillary data to detect interfaces, boolean */
int if_automatic; int if_automatic;
/** extra ports to open if if_automatic enabled, or NULL for default */
char* if_automatic_ports;
/** SO_RCVBUF size to set on port 53 UDP socket */ /** SO_RCVBUF size to set on port 53 UDP socket */
size_t so_rcvbuf; size_t so_rcvbuf;
/** SO_SNDBUF size to set on port 53 UDP socket */ /** SO_SNDBUF size to set on port 53 UDP socket */
@ -404,6 +407,8 @@ struct config_file {
/** serve expired entries only after trying to update the entries and this /** serve expired entries only after trying to update the entries and this
* timeout (in milliseconds) is reached */ * timeout (in milliseconds) is reached */
int serve_expired_client_timeout; int serve_expired_client_timeout;
/** serve EDE code 3 - Stale Answer (RFC8914) for expired entries */
int ede_serve_expired;
/** serve original TTLs rather than decrementing ones */ /** serve original TTLs rather than decrementing ones */
int serve_original_ttl; int serve_original_ttl;
/** nsec3 maximum iterations per key size, string */ /** nsec3 maximum iterations per key size, string */
@ -677,6 +682,8 @@ struct config_file {
char* ipset_name_v4; char* ipset_name_v4;
char* ipset_name_v6; char* ipset_name_v6;
#endif #endif
/** respond with Extended DNS Errors (RFC8914) */
int ede;
}; };
/** from cfg username, after daemonize setup performed */ /** from cfg username, after daemonize setup performed */
@ -1239,56 +1246,6 @@ char* fname_after_chroot(const char* fname, struct config_file* cfg,
*/ */
char* cfg_ptr_reverse(char* str); char* cfg_ptr_reverse(char* str);
/**
* Append text to the error info for validation.
* @param qstate: query state.
* @param str: copied into query region and appended.
* Failures to allocate are logged.
*/
void errinf(struct module_qstate* qstate, const char* str);
/**
* Append text to error info: from 1.2.3.4
* @param qstate: query state.
* @param origin: sock list with origin of trouble.
* Every element added.
* If NULL: nothing is added.
* if 0len element: 'from cache' is added.
*/
void errinf_origin(struct module_qstate* qstate, struct sock_list *origin);
/**
* Append text to error info: for RRset name type class
* @param qstate: query state.
* @param rr: rrset_key.
*/
void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr);
/**
* Append text to error info: str dname
* @param qstate: query state.
* @param str: explanation string
* @param dname: the dname.
*/
void errinf_dname(struct module_qstate* qstate, const char* str,
uint8_t* dname);
/**
* Create error info in string. For validation failures.
* @param qstate: query state.
* @return string or NULL on malloc failure (already logged).
* This string is malloced and has to be freed by caller.
*/
char* errinf_to_str_bogus(struct module_qstate* qstate);
/**
* Create error info in string. For other servfails.
* @param qstate: query state.
* @return string or NULL on malloc failure (already logged).
* This string is malloced and has to be freed by caller.
*/
char* errinf_to_str_servfail(struct module_qstate* qstate);
/** /**
* Used during options parsing * Used during options parsing
*/ */

View File

@ -252,6 +252,7 @@ tls-port{COLON} { YDVAR(1, VAR_SSL_PORT) }
ssl-cert-bundle{COLON} { YDVAR(1, VAR_TLS_CERT_BUNDLE) } ssl-cert-bundle{COLON} { YDVAR(1, VAR_TLS_CERT_BUNDLE) }
tls-cert-bundle{COLON} { YDVAR(1, VAR_TLS_CERT_BUNDLE) } tls-cert-bundle{COLON} { YDVAR(1, VAR_TLS_CERT_BUNDLE) }
tls-win-cert{COLON} { YDVAR(1, VAR_TLS_WIN_CERT) } tls-win-cert{COLON} { YDVAR(1, VAR_TLS_WIN_CERT) }
tls-system-cert{COLON} { YDVAR(1, VAR_TLS_WIN_CERT) }
additional-ssl-port{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) } additional-ssl-port{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) }
additional-tls-port{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) } additional-tls-port{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) }
tls-additional-ports{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) } tls-additional-ports{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) }
@ -273,6 +274,7 @@ interface{COLON} { YDVAR(1, VAR_INTERFACE) }
ip-address{COLON} { YDVAR(1, VAR_INTERFACE) } ip-address{COLON} { YDVAR(1, VAR_INTERFACE) }
outgoing-interface{COLON} { YDVAR(1, VAR_OUTGOING_INTERFACE) } outgoing-interface{COLON} { YDVAR(1, VAR_OUTGOING_INTERFACE) }
interface-automatic{COLON} { YDVAR(1, VAR_INTERFACE_AUTOMATIC) } interface-automatic{COLON} { YDVAR(1, VAR_INTERFACE_AUTOMATIC) }
interface-automatic-ports{COLON} { YDVAR(1, VAR_INTERFACE_AUTOMATIC_PORTS) }
so-rcvbuf{COLON} { YDVAR(1, VAR_SO_RCVBUF) } so-rcvbuf{COLON} { YDVAR(1, VAR_SO_RCVBUF) }
so-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) } so-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) }
so-reuseport{COLON} { YDVAR(1, VAR_SO_REUSEPORT) } so-reuseport{COLON} { YDVAR(1, VAR_SO_REUSEPORT) }
@ -402,6 +404,7 @@ serve-expired-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL) }
serve-expired-ttl-reset{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL_RESET) } serve-expired-ttl-reset{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL_RESET) }
serve-expired-reply-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_REPLY_TTL) } serve-expired-reply-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_REPLY_TTL) }
serve-expired-client-timeout{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_CLIENT_TIMEOUT) } serve-expired-client-timeout{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_CLIENT_TIMEOUT) }
ede-serve-expired{COLON} { YDVAR(1, VAR_EDE_SERVE_EXPIRED) }
serve-original-ttl{COLON} { YDVAR(1, VAR_SERVE_ORIGINAL_TTL) } serve-original-ttl{COLON} { YDVAR(1, VAR_SERVE_ORIGINAL_TTL) }
fake-dsa{COLON} { YDVAR(1, VAR_FAKE_DSA) } fake-dsa{COLON} { YDVAR(1, VAR_FAKE_DSA) }
fake-sha1{COLON} { YDVAR(1, VAR_FAKE_SHA1) } fake-sha1{COLON} { YDVAR(1, VAR_FAKE_SHA1) }
@ -553,6 +556,7 @@ tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) }
edns-client-string{COLON} { YDVAR(2, VAR_EDNS_CLIENT_STRING) } edns-client-string{COLON} { YDVAR(2, VAR_EDNS_CLIENT_STRING) }
edns-client-string-opcode{COLON} { YDVAR(1, VAR_EDNS_CLIENT_STRING_OPCODE) } edns-client-string-opcode{COLON} { YDVAR(1, VAR_EDNS_CLIENT_STRING_OPCODE) }
nsid{COLON} { YDVAR(1, VAR_NSID ) } nsid{COLON} { YDVAR(1, VAR_NSID ) }
ede{COLON} { YDVAR(1, VAR_EDE ) }
<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; } <INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
/* Quoted strings. Strip leading and ending quotes */ /* Quoted strings. Strip leading and ending quotes */

View File

@ -155,7 +155,8 @@ extern struct config_parser_state* cfg_parser;
%token VAR_ACCESS_CONTROL_TAG_DATA VAR_VIEW VAR_ACCESS_CONTROL_VIEW %token VAR_ACCESS_CONTROL_TAG_DATA VAR_VIEW VAR_ACCESS_CONTROL_VIEW
%token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_SERVE_EXPIRED_TTL %token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_SERVE_EXPIRED_TTL
%token VAR_SERVE_EXPIRED_TTL_RESET VAR_SERVE_EXPIRED_REPLY_TTL %token VAR_SERVE_EXPIRED_TTL_RESET VAR_SERVE_EXPIRED_REPLY_TTL
%token VAR_SERVE_EXPIRED_CLIENT_TIMEOUT VAR_SERVE_ORIGINAL_TTL VAR_FAKE_DSA %token VAR_SERVE_EXPIRED_CLIENT_TIMEOUT VAR_EDE_SERVE_EXPIRED
%token VAR_SERVE_ORIGINAL_TTL VAR_FAKE_DSA
%token VAR_FAKE_SHA1 VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR %token VAR_FAKE_SHA1 VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR
%token VAR_HIDE_HTTP_USER_AGENT VAR_HTTP_USER_AGENT %token VAR_HIDE_HTTP_USER_AGENT VAR_HTTP_USER_AGENT
%token VAR_TRUST_ANCHOR_SIGNALING VAR_AGGRESSIVE_NSEC VAR_USE_SYSTEMD %token VAR_TRUST_ANCHOR_SIGNALING VAR_AGGRESSIVE_NSEC VAR_USE_SYSTEMD
@ -188,7 +189,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_DYNLIB VAR_DYNLIB_FILE VAR_EDNS_CLIENT_STRING %token VAR_DYNLIB VAR_DYNLIB_FILE VAR_EDNS_CLIENT_STRING
%token VAR_EDNS_CLIENT_STRING_OPCODE VAR_NSID %token VAR_EDNS_CLIENT_STRING_OPCODE VAR_NSID
%token VAR_ZONEMD_PERMISSIVE_MODE VAR_ZONEMD_CHECK VAR_ZONEMD_REJECT_ABSENCE %token VAR_ZONEMD_PERMISSIVE_MODE VAR_ZONEMD_CHECK VAR_ZONEMD_REJECT_ABSENCE
%token VAR_RPZ_SIGNAL_NXDOMAIN_RA %token VAR_RPZ_SIGNAL_NXDOMAIN_RA VAR_INTERFACE_AUTOMATIC_PORTS VAR_EDE
%% %%
toplevelvars: /* empty */ | toplevelvars toplevelvar ; toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -292,7 +293,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_serve_expired | server_serve_expired |
server_serve_expired_ttl | server_serve_expired_ttl_reset | server_serve_expired_ttl | server_serve_expired_ttl_reset |
server_serve_expired_reply_ttl | server_serve_expired_client_timeout | server_serve_expired_reply_ttl | server_serve_expired_client_timeout |
server_serve_original_ttl | server_fake_dsa | server_ede_serve_expired | server_serve_original_ttl | server_fake_dsa |
server_log_identity | server_use_systemd | server_log_identity | server_use_systemd |
server_response_ip_tag | server_response_ip | server_response_ip_data | server_response_ip_tag | server_response_ip | server_response_ip_data |
server_shm_enable | server_shm_key | server_fake_sha1 | server_shm_enable | server_shm_key | server_fake_sha1 |
@ -311,7 +312,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_tls_use_sni | server_edns_client_string | server_tls_use_sni | server_edns_client_string |
server_edns_client_string_opcode | server_nsid | server_edns_client_string_opcode | server_nsid |
server_zonemd_permissive_mode | server_max_reuse_tcp_queries | server_zonemd_permissive_mode | server_max_reuse_tcp_queries |
server_tcp_reuse_timeout | server_tcp_auth_query_timeout server_tcp_reuse_timeout | server_tcp_auth_query_timeout |
server_interface_automatic_ports | server_ede
; ;
stubstart: VAR_STUB_ZONE stubstart: VAR_STUB_ZONE
@ -800,6 +802,13 @@ server_interface_automatic: VAR_INTERFACE_AUTOMATIC STRING_ARG
free($2); free($2);
} }
; ;
server_interface_automatic_ports: VAR_INTERFACE_AUTOMATIC_PORTS STRING_ARG
{
OUTYY(("P(server_interface_automatic_ports:%s)\n", $2));
free(cfg_parser->cfg->if_automatic_ports);
cfg_parser->cfg->if_automatic_ports = $2;
}
;
server_do_ip4: VAR_DO_IP4 STRING_ARG server_do_ip4: VAR_DO_IP4 STRING_ARG
{ {
OUTYY(("P(server_do_ip4:%s)\n", $2)); OUTYY(("P(server_do_ip4:%s)\n", $2));
@ -2026,6 +2035,15 @@ server_serve_expired_client_timeout: VAR_SERVE_EXPIRED_CLIENT_TIMEOUT STRING_ARG
free($2); free($2);
} }
; ;
server_ede_serve_expired: VAR_EDE_SERVE_EXPIRED STRING_ARG
{
OUTYY(("P(server_ede_serve_expired:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->ede_serve_expired = (strcmp($2, "yes")==0);
free($2);
}
;
server_serve_original_ttl: VAR_SERVE_ORIGINAL_TTL STRING_ARG server_serve_original_ttl: VAR_SERVE_ORIGINAL_TTL STRING_ARG
{ {
OUTYY(("P(server_serve_original_ttl:%s)\n", $2)); OUTYY(("P(server_serve_original_ttl:%s)\n", $2));
@ -2184,6 +2202,16 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
free($3); free($3);
#ifdef USE_IPSET #ifdef USE_IPSET
} else if(strcmp($3, "ipset")==0) { } else if(strcmp($3, "ipset")==0) {
size_t len = strlen($2);
/* Make sure to add the trailing dot.
* These are str compared to domain names. */
if($2[len-1] != '.') {
if(!($2 = realloc($2, len+2))) {
fatal_exit("out of memory adding local-zone");
}
$2[len] = '.';
$2[len+1] = 0;
}
if(!cfg_strlist_insert(&cfg_parser->cfg-> if(!cfg_strlist_insert(&cfg_parser->cfg->
local_zones_ipset, $2)) local_zones_ipset, $2))
fatal_exit("out of memory adding local-zone"); fatal_exit("out of memory adding local-zone");
@ -2713,7 +2741,15 @@ server_edns_client_string_opcode: VAR_EDNS_CLIENT_STRING_OPCODE STRING_ARG
yyerror("option code must be in interval [0, 65535]"); yyerror("option code must be in interval [0, 65535]");
else cfg_parser->cfg->edns_client_string_opcode = atoi($2); else cfg_parser->cfg->edns_client_string_opcode = atoi($2);
free($2); free($2);
}
;
server_ede: VAR_EDE STRING_ARG
{
OUTYY(("P(server_ede:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->ede = (strcmp($2, "yes")==0);
free($2);
} }
; ;
stub_name: VAR_NAME STRING_ARG stub_name: VAR_NAME STRING_ARG
@ -2982,6 +3018,16 @@ view_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
free($3); free($3);
#ifdef USE_IPSET #ifdef USE_IPSET
} else if(strcmp($3, "ipset")==0) { } else if(strcmp($3, "ipset")==0) {
size_t len = strlen($2);
/* Make sure to add the trailing dot.
* These are str compared to domain names. */
if($2[len-1] != '.') {
if(!($2 = realloc($2, len+2))) {
fatal_exit("out of memory adding local-zone");
}
$2[len] = '.';
$2[len+1] = 0;
}
if(!cfg_strlist_insert(&cfg_parser->cfg->views-> if(!cfg_strlist_insert(&cfg_parser->cfg->views->
local_zones_ipset, $2)) local_zones_ipset, $2))
fatal_exit("out of memory adding local-zone"); fatal_exit("out of memory adding local-zone");

View File

@ -1157,7 +1157,7 @@ skip_pkt_rr(sldns_buffer* pkt)
} }
/** skip RRs from packet */ /** skip RRs from packet */
static int int
skip_pkt_rrs(sldns_buffer* pkt, int num) skip_pkt_rrs(sldns_buffer* pkt, int num)
{ {
int i; int i;
@ -1235,3 +1235,4 @@ log_edns_opt_list(enum verbosity_value level, const char* info_str,
} }
} }
} }

View File

@ -293,6 +293,15 @@ int parse_packet(struct sldns_buffer* pkt, struct msg_parse* msg,
int parse_extract_edns_from_response_msg(struct msg_parse* msg, int parse_extract_edns_from_response_msg(struct msg_parse* msg,
struct edns_data* edns, struct regional* region); struct edns_data* edns, struct regional* region);
/**
* Skip RRs from packet
* @param pkt: the packet. position at start must be right after the query
* section. At end, right after EDNS data or no movement if failed.
* @param num: Limit of the number of records we want to parse.
* @return: 0 on success, 1 on failure.
*/
int skip_pkt_rrs(struct sldns_buffer* pkt, int num);
/** /**
* If EDNS data follows a query section, extract it and initialize edns struct. * If EDNS data follows a query section, extract it and initialize edns struct.
* @param pkt: the packet. position at start must be right after the query * @param pkt: the packet. position at start must be right after the query

View File

@ -117,6 +117,7 @@ construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd,
rep->ar_numrrsets = ar; rep->ar_numrrsets = ar;
rep->rrset_count = total; rep->rrset_count = total;
rep->security = sec; rep->security = sec;
rep->reason_bogus = LDNS_EDE_NONE;
rep->authoritative = 0; rep->authoritative = 0;
/* array starts after the refs */ /* array starts after the refs */
if(region) if(region)
@ -989,6 +990,36 @@ parse_reply_in_temp_region(sldns_buffer* pkt, struct regional* region,
return rep; return rep;
} }
int edns_opt_list_append_ede(struct edns_option** list, struct regional* region,
sldns_ede_code code, const char *txt)
{
struct edns_option** prevp;
struct edns_option* opt;
size_t txt_len = txt ? strlen(txt) : 0;
/* allocate new element */
opt = (struct edns_option*)regional_alloc(region, sizeof(*opt));
if(!opt)
return 0;
opt->next = NULL;
opt->opt_code = LDNS_EDNS_EDE;
opt->opt_len = txt_len + sizeof(uint16_t);
opt->opt_data = regional_alloc(region, txt_len + sizeof(uint16_t));
if(!opt->opt_data)
return 0;
sldns_write_uint16(opt->opt_data, (uint16_t)code);
if (txt_len)
memmove(opt->opt_data + 2, txt, txt_len);
/* append at end of list */
prevp = list;
while(*prevp != NULL)
prevp = &((*prevp)->next);
verbose(VERB_ALGO, "attached EDE code: %d with message: %s", code, txt);
*prevp = opt;
return 1;
}
int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len, int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
uint8_t* data, struct regional* region) uint8_t* data, struct regional* region)
{ {

View File

@ -43,6 +43,7 @@
#define UTIL_DATA_MSGREPLY_H #define UTIL_DATA_MSGREPLY_H
#include "util/storage/lruhash.h" #include "util/storage/lruhash.h"
#include "util/data/packed_rrset.h" #include "util/data/packed_rrset.h"
#include "sldns/rrdef.h"
struct sldns_buffer; struct sldns_buffer;
struct comm_reply; struct comm_reply;
struct alloc_cache; struct alloc_cache;
@ -167,6 +168,11 @@ struct reply_info {
*/ */
enum sec_status security; enum sec_status security;
/**
* EDE (rfc8914) code with reason for DNSSEC bogus status.
*/
sldns_ede_code reason_bogus;
/** /**
* Number of RRsets in each section. * Number of RRsets in each section.
* The answer section. Add up the RRs in every RRset to calculate * The answer section. Add up the RRs in every RRset to calculate
@ -530,6 +536,37 @@ void log_query_info(enum verbosity_value v, const char* str,
int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len, int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
uint8_t* data, struct regional* region); uint8_t* data, struct regional* region);
/**
* Append edns EDE option to edns options list
* @param LIST: the edns option list to append the edns option to.
* @param REGION: region to allocate the new edns option.
* @param CODE: the EDE code.
* @param TXT: Additional text for the option
*/
#define EDNS_OPT_LIST_APPEND_EDE(LIST, REGION, CODE, TXT) \
do { \
struct { \
uint16_t code; \
char text[sizeof(TXT) - 1]; \
} ede = { htons(CODE), TXT }; \
verbose(VERB_ALGO, "attached EDE code: %d with" \
" message: %s", CODE, TXT); \
edns_opt_list_append((LIST), LDNS_EDNS_EDE, \
sizeof(uint16_t) + sizeof(TXT) - 1, \
(void *)&ede, (REGION)); \
} while(0)
/**
* Append edns EDE option to edns options list
* @param list: the edns option list to append the edns option to.
* @param region: region to allocate the new edns option.
* @param code: the EDE code.
* @param txt: Additional text for the option
* @return false on failure.
*/
int edns_opt_list_append_ede(struct edns_option** list, struct regional* region,
sldns_ede_code code, const char *txt);
/** /**
* Remove any option found on the edns option list that matches the code. * Remove any option found on the edns option list that matches the code.
* @param list: the list of edns options. * @param list: the list of edns options.

View File

@ -40,6 +40,10 @@
#include "config.h" #include "config.h"
#include "util/module.h" #include "util/module.h"
#include "sldns/wire2str.h" #include "sldns/wire2str.h"
#include "util/config_file.h"
#include "util/regional.h"
#include "util/data/dname.h"
#include "util/net_help.h"
const char* const char*
strextstate(enum module_ext_state s) strextstate(enum module_ext_state s)
@ -71,6 +75,144 @@ strmodulevent(enum module_ev e)
return "bad_event_value"; return "bad_event_value";
} }
void errinf(struct module_qstate* qstate, const char* str)
{
errinf_ede(qstate, str, LDNS_EDE_NONE);
}
void errinf_ede(struct module_qstate* qstate,
const char* str, sldns_ede_code reason_bogus)
{
struct errinf_strlist* p;
if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str)
return;
p = (struct errinf_strlist*)regional_alloc(qstate->region, sizeof(*p));
if(!p) {
log_err("malloc failure in validator-error-info string");
return;
}
p->next = NULL;
p->str = regional_strdup(qstate->region, str);
p->reason_bogus = reason_bogus;
if(!p->str) {
log_err("malloc failure in validator-error-info string");
return;
}
/* add at end */
if(qstate->errinf) {
struct errinf_strlist* q = qstate->errinf;
while(q->next)
q = q->next;
q->next = p;
} else qstate->errinf = p;
}
void errinf_origin(struct module_qstate* qstate, struct sock_list *origin)
{
struct sock_list* p;
if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
return;
for(p=origin; p; p=p->next) {
char buf[256];
if(p == origin)
snprintf(buf, sizeof(buf), "from ");
else snprintf(buf, sizeof(buf), "and ");
if(p->len == 0)
snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf),
"cache");
else
addr_to_str(&p->addr, p->len, buf+strlen(buf),
sizeof(buf)-strlen(buf));
errinf(qstate, buf);
}
}
char* errinf_to_str_bogus(struct module_qstate* qstate)
{
char buf[20480];
char* p = buf;
size_t left = sizeof(buf);
struct errinf_strlist* s;
char dname[LDNS_MAX_DOMAINLEN+1];
char t[16], c[16];
sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
dname_str(qstate->qinfo.qname, dname);
snprintf(p, left, "validation failure <%s %s %s>:", dname, t, c);
left -= strlen(p); p += strlen(p);
if(!qstate->errinf)
snprintf(p, left, " misc failure");
else for(s=qstate->errinf; s; s=s->next) {
snprintf(p, left, " %s", s->str);
left -= strlen(p); p += strlen(p);
}
p = strdup(buf);
if(!p)
log_err("malloc failure in errinf_to_str");
return p;
}
sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate)
{
struct errinf_strlist* s;
for(s=qstate->errinf; s; s=s->next) {
if (s->reason_bogus != LDNS_EDE_NONE) {
return s->reason_bogus;
}
}
return LDNS_EDE_NONE;
}
char* errinf_to_str_servfail(struct module_qstate* qstate)
{
char buf[20480];
char* p = buf;
size_t left = sizeof(buf);
struct errinf_strlist* s;
char dname[LDNS_MAX_DOMAINLEN+1];
char t[16], c[16];
sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
dname_str(qstate->qinfo.qname, dname);
snprintf(p, left, "SERVFAIL <%s %s %s>:", dname, t, c);
left -= strlen(p); p += strlen(p);
if(!qstate->errinf)
snprintf(p, left, " misc failure");
else for(s=qstate->errinf; s; s=s->next) {
snprintf(p, left, " %s", s->str);
left -= strlen(p); p += strlen(p);
}
p = strdup(buf);
if(!p)
log_err("malloc failure in errinf_to_str");
return p;
}
void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr)
{
char buf[1024];
char dname[LDNS_MAX_DOMAINLEN+1];
char t[16], c[16];
if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !rr)
return;
sldns_wire2str_type_buf(ntohs(rr->rk.type), t, sizeof(t));
sldns_wire2str_class_buf(ntohs(rr->rk.rrset_class), c, sizeof(c));
dname_str(rr->rk.dname, dname);
snprintf(buf, sizeof(buf), "for <%s %s %s>", dname, t, c);
errinf(qstate, buf);
}
void errinf_dname(struct module_qstate* qstate, const char* str, uint8_t* dname)
{
char b[1024];
char buf[LDNS_MAX_DOMAINLEN+1];
if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str || !dname)
return;
dname_str(dname, buf);
snprintf(b, sizeof(b), "%s %s", str, buf);
errinf(qstate, b);
}
int int
edns_known_options_init(struct module_env* env) edns_known_options_init(struct module_env* env)
{ {

View File

@ -187,6 +187,15 @@ struct respip_addr_info;
/** Maximum number of known edns options */ /** Maximum number of known edns options */
#define MAX_KNOWN_EDNS_OPTS 256 #define MAX_KNOWN_EDNS_OPTS 256
struct errinf_strlist {
/** next item in list */
struct errinf_strlist* next;
/** config option string */
char* str;
/** EDE code companion to the error str */
int reason_bogus;
};
enum inplace_cb_list_type { enum inplace_cb_list_type {
/* Inplace callbacks for when a resolved reply is ready to be sent to the /* Inplace callbacks for when a resolved reply is ready to be sent to the
* front.*/ * front.*/
@ -624,8 +633,7 @@ struct module_qstate {
/** region for this query. Cleared when query process finishes. */ /** region for this query. Cleared when query process finishes. */
struct regional* region; struct regional* region;
/** failure reason information if val-log-level is high */ /** failure reason information if val-log-level is high */
struct config_strlist* errinf; struct errinf_strlist* errinf;
/** which module is executing */ /** which module is executing */
int curmod; int curmod;
/** module states */ /** module states */
@ -667,6 +675,8 @@ struct module_qstate {
/** Extended result of response-ip action processing, mainly /** Extended result of response-ip action processing, mainly
* for logging purposes. */ * for logging purposes. */
struct respip_action_info* respip_action_info; struct respip_action_info* respip_action_info;
/** if the query is rpz passthru, no further rpz processing for it */
int rpz_passthru;
/** whether the reply should be dropped */ /** whether the reply should be dropped */
int is_drop; int is_drop;
@ -759,6 +769,65 @@ const char* strextstate(enum module_ext_state s);
*/ */
const char* strmodulevent(enum module_ev e); const char* strmodulevent(enum module_ev e);
/**
* Append text to the error info for validation.
* @param qstate: query state.
* @param str: copied into query region and appended.
* Failures to allocate are logged.
*/
void errinf(struct module_qstate* qstate, const char* str);
void errinf_ede(struct module_qstate* qstate, const char* str,
sldns_ede_code reason_bogus);
/**
* Append text to error info: from 1.2.3.4
* @param qstate: query state.
* @param origin: sock list with origin of trouble.
* Every element added.
* If NULL: nothing is added.
* if 0len element: 'from cache' is added.
*/
void errinf_origin(struct module_qstate* qstate, struct sock_list *origin);
/**
* Append text to error info: for RRset name type class
* @param qstate: query state.
* @param rr: rrset_key.
*/
void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr);
/**
* Append text to error info: str dname
* @param qstate: query state.
* @param str: explanation string
* @param dname: the dname.
*/
void errinf_dname(struct module_qstate* qstate, const char* str,
uint8_t* dname);
/**
* Create error info in string. For validation failures.
* @param qstate: query state.
* @return string or NULL on malloc failure (already logged).
* This string is malloced and has to be freed by caller.
*/
char* errinf_to_str_bogus(struct module_qstate* qstate);
/**
* Check the sldns_ede_code of the qstate.
* @param qstate: query state.
* @return LDNS_EDE_DNSSEC_BOGUS by default, or the first explicitly set
* sldns_ede_code.
*/
sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate);
/**
* Create error info in string. For other servfails.
* @param qstate: query state.
* @return string or NULL on malloc failure (already logged).
* This string is malloced and has to be freed by caller.
*/
char* errinf_to_str_servfail(struct module_qstate* qstate);
/** /**
* Initialize the edns known options by allocating the required space. * Initialize the edns known options by allocating the required space.
* @param env: the module environment. * @param env: the module environment.

View File

@ -1271,7 +1271,13 @@ void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert)
} }
} }
#else #else
(void)wincert; if(wincert) {
if(!SSL_CTX_set_default_verify_paths(ctx)) {
log_crypto_err("error in default_verify_paths");
SSL_CTX_free(ctx);
return NULL;
}
}
#endif #endif
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
} }

View File

@ -1209,23 +1209,22 @@ squelch_err_ssl_handshake(unsigned long err)
{ {
if(verbosity >= VERB_QUERY) if(verbosity >= VERB_QUERY)
return 0; /* only squelch on low verbosity */ return 0; /* only squelch on low verbosity */
/* this is very specific, we could filter on ERR_GET_REASON() if(ERR_GET_LIB(err) == ERR_LIB_SSL &&
* (the third element in ERR_PACK) */ (ERR_GET_REASON(err) == SSL_R_HTTPS_PROXY_REQUEST ||
if(err == ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GET_RECORD, SSL_R_HTTPS_PROXY_REQUEST) || ERR_GET_REASON(err) == SSL_R_HTTP_REQUEST ||
err == ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GET_RECORD, SSL_R_HTTP_REQUEST) || ERR_GET_REASON(err) == SSL_R_WRONG_VERSION_NUMBER ||
err == ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER) || ERR_GET_REASON(err) == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE
err == ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_READ_BYTES, SSL_R_SSLV3_ALERT_BAD_CERTIFICATE)
#ifdef SSL_F_TLS_POST_PROCESS_CLIENT_HELLO #ifdef SSL_F_TLS_POST_PROCESS_CLIENT_HELLO
|| err == ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_POST_PROCESS_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER) || ERR_GET_REASON(err) == SSL_R_NO_SHARED_CIPHER
#endif #endif
#ifdef SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO #ifdef SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO
|| err == ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL) || ERR_GET_REASON(err) == SSL_R_UNKNOWN_PROTOCOL
|| err == ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_UNSUPPORTED_PROTOCOL) || ERR_GET_REASON(err) == SSL_R_UNSUPPORTED_PROTOCOL
# ifdef SSL_R_VERSION_TOO_LOW # ifdef SSL_R_VERSION_TOO_LOW
|| err == ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_VERSION_TOO_LOW) || ERR_GET_REASON(err) == SSL_R_VERSION_TOO_LOW
# endif # endif
#endif #endif
) ))
return 1; return 1;
return 0; return 0;
} }
@ -1278,6 +1277,12 @@ ssl_handshake(struct comm_point* c)
if(errno == ECONNRESET && verbosity < 2) if(errno == ECONNRESET && verbosity < 2)
return 0; /* silence reset by peer */ return 0; /* silence reset by peer */
#endif #endif
if(!tcp_connect_errno_needs_log(
(struct sockaddr*)&c->repinfo.addr,
c->repinfo.addrlen))
return 0; /* silence connect failures that
show up because after connect this is the
first system call that accesses the socket */
if(errno != 0) if(errno != 0)
log_err("SSL_handshake syscall: %s", log_err("SSL_handshake syscall: %s",
strerror(errno)); strerror(errno));
@ -2480,7 +2485,7 @@ http_nonchunk_segment(struct comm_point* c)
remainbufferlen = sldns_buffer_capacity(c->buffer) - remainbufferlen = sldns_buffer_capacity(c->buffer) -
sldns_buffer_limit(c->buffer); sldns_buffer_limit(c->buffer);
if(remainbufferlen+got_now >= c->tcp_byte_count || if(remainbufferlen+got_now >= c->tcp_byte_count ||
remainbufferlen >= (c->ssl?16384:2048)) { remainbufferlen >= (size_t)(c->ssl?16384:2048)) {
size_t total = sldns_buffer_limit(c->buffer); size_t total = sldns_buffer_limit(c->buffer);
sldns_buffer_clear(c->buffer); sldns_buffer_clear(c->buffer);
sldns_buffer_set_position(c->buffer, total); sldns_buffer_set_position(c->buffer, total);

View File

@ -1203,13 +1203,8 @@ void autr_write_file(struct module_env* env, struct trust_anchor* tp)
#else #else
llvalue = (unsigned long long)tp; llvalue = (unsigned long long)tp;
#endif #endif
#ifndef USE_WINSOCK snprintf(tempf, sizeof(tempf), "%s.%d-%d-" ARG_LL "x", fname, (int)getpid(),
snprintf(tempf, sizeof(tempf), "%s.%d-%d-%llx", fname, (int)getpid(),
env->worker?*(int*)env->worker:0, llvalue); env->worker?*(int*)env->worker:0, llvalue);
#else
snprintf(tempf, sizeof(tempf), "%s.%d-%d-%I64x", fname, (int)getpid(),
env->worker?*(int*)env->worker:0, llvalue);
#endif
#endif /* S_SPLINT_S */ #endif /* S_SPLINT_S */
verbose(VERB_ALGO, "autotrust: write to disk: %s", tempf); verbose(VERB_ALGO, "autotrust: write to disk: %s", tempf);
out = fopen(tempf, "w"); out = fopen(tempf, "w");
@ -1268,7 +1263,7 @@ verify_dnskey(struct module_env* env, struct val_env* ve,
int downprot = env->cfg->harden_algo_downgrade; int downprot = env->cfg->harden_algo_downgrade;
enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, rrset, enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, rrset,
tp->ds_rrset, tp->dnskey_rrset, downprot?sigalg:NULL, &reason, tp->ds_rrset, tp->dnskey_rrset, downprot?sigalg:NULL, &reason,
qstate); NULL, qstate);
/* sigalg is ignored, it returns algorithms signalled to exist, but /* sigalg is ignored, it returns algorithms signalled to exist, but
* in 5011 there are no other rrsets to check. if downprot is * in 5011 there are no other rrsets to check. if downprot is
* enabled, then it checks that the DNSKEY is signed with all * enabled, then it checks that the DNSKEY is signed with all
@ -1317,7 +1312,7 @@ rr_is_selfsigned_revoked(struct module_env* env, struct val_env* ve,
/* no algorithm downgrade protection necessary, if it is selfsigned /* no algorithm downgrade protection necessary, if it is selfsigned
* revoked it can be removed. */ * revoked it can be removed. */
sec = dnskey_verify_rrset(env, ve, dnskey_rrset, dnskey_rrset, i, sec = dnskey_verify_rrset(env, ve, dnskey_rrset, dnskey_rrset, i,
&reason, LDNS_SECTION_ANSWER, qstate); &reason, NULL, LDNS_SECTION_ANSWER, qstate);
return (sec == sec_status_secure); return (sec == sec_status_secure);
} }
@ -2397,7 +2392,7 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp)
qinfo.qclass); qinfo.qclass);
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
&probe_answer_cb, env)) { &probe_answer_cb, env, 0)) {
log_err("out of memory making 5011 probe"); log_err("out of memory making 5011 probe");
} }
} }

View File

@ -90,6 +90,7 @@ key_cache_insert(struct key_cache* kcache, struct key_entry_key* kkey,
qstate->env->cfg->val_log_level >= 2) { qstate->env->cfg->val_log_level >= 2) {
/* on malloc failure there is simply no reason string */ /* on malloc failure there is simply no reason string */
key_entry_set_reason(k, errinf_to_str_bogus(qstate)); key_entry_set_reason(k, errinf_to_str_bogus(qstate));
key_entry_set_reason_bogus(k, errinf_to_reason_bogus(qstate));
} }
key_entry_hash(k); key_entry_hash(k);
slabhash_insert(kcache->slab, k->entry.hash, &k->entry, slabhash_insert(kcache->slab, k->entry.hash, &k->entry,

View File

@ -244,6 +244,15 @@ key_entry_set_reason(struct key_entry_key* kkey, char* reason)
d->reason = reason; d->reason = reason;
} }
void
key_entry_set_reason_bogus(struct key_entry_key* kkey, sldns_ede_code ede)
{
struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
if (ede != LDNS_EDE_NONE) { /* reason_bogus init is LDNS_EDE_NONE already */
d->reason_bogus = ede;
}
}
char* char*
key_entry_get_reason(struct key_entry_key* kkey) key_entry_get_reason(struct key_entry_key* kkey)
{ {
@ -251,6 +260,14 @@ key_entry_get_reason(struct key_entry_key* kkey)
return d->reason; return d->reason;
} }
sldns_ede_code
key_entry_get_reason_bogus(struct key_entry_key* kkey)
{
struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
return d->reason_bogus;
}
/** setup key entry in region */ /** setup key entry in region */
static int static int
key_entry_setup(struct regional* region, key_entry_setup(struct regional* region,
@ -286,6 +303,7 @@ key_entry_create_null(struct regional* region,
d->ttl = now + ttl; d->ttl = now + ttl;
d->isbad = 0; d->isbad = 0;
d->reason = NULL; d->reason = NULL;
d->reason_bogus = LDNS_EDE_NONE;
d->rrset_type = LDNS_RR_TYPE_DNSKEY; d->rrset_type = LDNS_RR_TYPE_DNSKEY;
d->rrset_data = NULL; d->rrset_data = NULL;
d->algo = NULL; d->algo = NULL;
@ -306,6 +324,7 @@ key_entry_create_rrset(struct regional* region,
d->ttl = rd->ttl + now; d->ttl = rd->ttl + now;
d->isbad = 0; d->isbad = 0;
d->reason = NULL; d->reason = NULL;
d->reason_bogus = LDNS_EDE_NONE;
d->rrset_type = ntohs(rrset->rk.type); d->rrset_type = ntohs(rrset->rk.type);
d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region, d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region,
rd, packed_rrset_sizeof(rd)); rd, packed_rrset_sizeof(rd));
@ -332,6 +351,7 @@ key_entry_create_bad(struct regional* region,
d->ttl = now + ttl; d->ttl = now + ttl;
d->isbad = 1; d->isbad = 1;
d->reason = NULL; d->reason = NULL;
d->reason_bogus = LDNS_EDE_NONE;
d->rrset_type = LDNS_RR_TYPE_DNSKEY; d->rrset_type = LDNS_RR_TYPE_DNSKEY;
d->rrset_data = NULL; d->rrset_data = NULL;
d->algo = NULL; d->algo = NULL;

View File

@ -45,6 +45,7 @@ struct packed_rrset_data;
struct regional; struct regional;
struct ub_packed_rrset_key; struct ub_packed_rrset_key;
#include "util/storage/lruhash.h" #include "util/storage/lruhash.h"
#include "sldns/rrdef.h"
/** /**
* A key entry for the validator. * A key entry for the validator.
@ -80,6 +81,8 @@ struct key_entry_data {
struct packed_rrset_data* rrset_data; struct packed_rrset_data* rrset_data;
/** not NULL sometimes to give reason why bogus */ /** not NULL sometimes to give reason why bogus */
char* reason; char* reason;
/** not NULL to give reason why bogus */
sldns_ede_code reason_bogus;
/** list of algorithms signalled, ends with 0, or NULL */ /** list of algorithms signalled, ends with 0, or NULL */
uint8_t* algo; uint8_t* algo;
/** DNS RR type of the rrset data (host order) */ /** DNS RR type of the rrset data (host order) */
@ -150,6 +153,15 @@ int key_entry_isbad(struct key_entry_key* kkey);
*/ */
void key_entry_set_reason(struct key_entry_key* kkey, char* reason); void key_entry_set_reason(struct key_entry_key* kkey, char* reason);
/**
* Set the EDE (RFC8914) code why the key is bad, if it
* exists (so not LDNS_EDE_NONE).
* @param kkey: bad key.
* @param ede: EDE code to attach to this key.
*/
void key_entry_set_reason_bogus(struct key_entry_key* kkey, sldns_ede_code ede);
/** /**
* Get reason why a key is bad. * Get reason why a key is bad.
* @param kkey: bad key * @param kkey: bad key
@ -158,6 +170,13 @@ void key_entry_set_reason(struct key_entry_key* kkey, char* reason);
*/ */
char* key_entry_get_reason(struct key_entry_key* kkey); char* key_entry_get_reason(struct key_entry_key* kkey);
/**
* Get the EDE (RFC8914) code why a key is bad. Can return LDNS_EDE_NONE.
* @param kkey: bad key
* @return the ede code.
*/
sldns_ede_code key_entry_get_reason_bogus(struct key_entry_key* kkey);
/** /**
* Create a null entry, in the given region. * Create a null entry, in the given region.
* @param region: where to allocate * @param region: where to allocate

View File

@ -187,7 +187,7 @@ nsec_verify_rrset(struct module_env* env, struct val_env* ve,
if(d->security == sec_status_secure) if(d->security == sec_status_secure)
return 1; return 1;
d->security = val_verify_rrset_entry(env, ve, nsec, kkey, reason, d->security = val_verify_rrset_entry(env, ve, nsec, kkey, reason,
LDNS_SECTION_AUTHORITY, qstate); NULL, LDNS_SECTION_AUTHORITY, qstate);
if(d->security == sec_status_secure) { if(d->security == sec_status_secure) {
rrset_update_sec_status(env->rrset_cache, nsec, *env->now); rrset_update_sec_status(env->rrset_cache, nsec, *env->now);
return 1; return 1;

View File

@ -1289,7 +1289,8 @@ nsec3_prove_wildcard(struct module_env* env, struct val_env* ve,
static int static int
list_is_secure(struct module_env* env, struct val_env* ve, list_is_secure(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key** list, size_t num, struct ub_packed_rrset_key** list, size_t num,
struct key_entry_key* kkey, char** reason, struct module_qstate* qstate) struct key_entry_key* kkey, char** reason, sldns_ede_code *reason_bogus,
struct module_qstate* qstate)
{ {
struct packed_rrset_data* d; struct packed_rrset_data* d;
size_t i; size_t i;
@ -1303,7 +1304,7 @@ list_is_secure(struct module_env* env, struct val_env* ve,
if(d->security == sec_status_secure) if(d->security == sec_status_secure)
continue; continue;
d->security = val_verify_rrset_entry(env, ve, list[i], kkey, d->security = val_verify_rrset_entry(env, ve, list[i], kkey,
reason, LDNS_SECTION_AUTHORITY, qstate); reason, reason_bogus, LDNS_SECTION_AUTHORITY, qstate);
if(d->security != sec_status_secure) { if(d->security != sec_status_secure) {
verbose(VERB_ALGO, "NSEC3 did not verify"); verbose(VERB_ALGO, "NSEC3 did not verify");
return 0; return 0;
@ -1317,7 +1318,7 @@ enum sec_status
nsec3_prove_nods(struct module_env* env, struct val_env* ve, nsec3_prove_nods(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key** list, size_t num, struct ub_packed_rrset_key** list, size_t num,
struct query_info* qinfo, struct key_entry_key* kkey, char** reason, struct query_info* qinfo, struct key_entry_key* kkey, char** reason,
struct module_qstate* qstate) sldns_ede_code* reason_bogus, struct module_qstate* qstate)
{ {
rbtree_type ct; rbtree_type ct;
struct nsec3_filter flt; struct nsec3_filter flt;
@ -1330,8 +1331,10 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
*reason = "no valid NSEC3s"; *reason = "no valid NSEC3s";
return sec_status_bogus; /* no valid NSEC3s, bogus */ return sec_status_bogus; /* no valid NSEC3s, bogus */
} }
if(!list_is_secure(env, ve, list, num, kkey, reason, qstate)) if(!list_is_secure(env, ve, list, num, kkey, reason, reason_bogus, qstate)) {
*reason = "not all NSEC3 records secure";
return sec_status_bogus; /* not all NSEC3 records secure */ return sec_status_bogus; /* not all NSEC3 records secure */
}
rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */ rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */
filter_init(&flt, list, num, qinfo); /* init RR iterator */ filter_init(&flt, list, num, qinfo); /* init RR iterator */
if(!flt.zone) { if(!flt.zone) {

View File

@ -68,6 +68,7 @@
#define VALIDATOR_VAL_NSEC3_H #define VALIDATOR_VAL_NSEC3_H
#include "util/rbtree.h" #include "util/rbtree.h"
#include "util/data/packed_rrset.h" #include "util/data/packed_rrset.h"
#include "sldns/rrdef.h"
struct val_env; struct val_env;
struct regional; struct regional;
struct module_env; struct module_env;
@ -186,6 +187,7 @@ nsec3_prove_wildcard(struct module_env* env, struct val_env* ve,
* @param qinfo: query that is verified for. * @param qinfo: query that is verified for.
* @param kkey: key entry that signed the NSEC3s. * @param kkey: key entry that signed the NSEC3s.
* @param reason: string for bogus result. * @param reason: string for bogus result.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param qstate: qstate with region. * @param qstate: qstate with region.
* @return: * @return:
* sec_status SECURE of the proposition is proven by the NSEC3 RRs, * sec_status SECURE of the proposition is proven by the NSEC3 RRs,
@ -197,7 +199,7 @@ enum sec_status
nsec3_prove_nods(struct module_env* env, struct val_env* ve, nsec3_prove_nods(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key** list, size_t num, struct ub_packed_rrset_key** list, size_t num,
struct query_info* qinfo, struct key_entry_key* kkey, char** reason, struct query_info* qinfo, struct key_entry_key* kkey, char** reason,
struct module_qstate* qstate); sldns_ede_code* reason_bogus, struct module_qstate* qstate);
/** /**
* Prove NXDOMAIN or NODATA. * Prove NXDOMAIN or NODATA.

View File

@ -525,11 +525,19 @@ int algo_needs_missing(struct algo_needs* n)
return 0; return 0;
} }
static enum sec_status
dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
time_t now, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t sig_idx,
struct rbtree_type** sortree,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate);
enum sec_status enum sec_status
dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve, dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
uint8_t* sigalg, char** reason, sldns_pkt_section section, uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus,
struct module_qstate* qstate) sldns_pkt_section section, struct module_qstate* qstate)
{ {
enum sec_status sec; enum sec_status sec;
size_t i, num; size_t i, num;
@ -543,6 +551,8 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
verbose(VERB_QUERY, "rrset failed to verify due to a lack of " verbose(VERB_QUERY, "rrset failed to verify due to a lack of "
"signatures"); "signatures");
*reason = "no signatures"; *reason = "no signatures";
if(reason_bogus)
*reason_bogus = LDNS_EDE_RRSIGS_MISSING;
return sec_status_bogus; return sec_status_bogus;
} }
@ -551,12 +561,15 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
if(algo_needs_num_missing(&needs) == 0) { if(algo_needs_num_missing(&needs) == 0) {
verbose(VERB_QUERY, "zone has no known algorithms"); verbose(VERB_QUERY, "zone has no known algorithms");
*reason = "zone has no known algorithms"; *reason = "zone has no known algorithms";
if(reason_bogus)
*reason_bogus = LDNS_EDE_UNSUPPORTED_DNSKEY_ALG;
return sec_status_insecure; return sec_status_insecure;
} }
} }
for(i=0; i<num; i++) { for(i=0; i<num; i++) {
sec = dnskeyset_verify_rrset_sig(env, ve, *env->now, rrset, sec = dnskeyset_verify_rrset_sig(env, ve, *env->now, rrset,
dnskey, i, &sortree, reason, section, qstate); dnskey, i, &sortree, reason, reason_bogus,
section, qstate);
/* see which algorithm has been fixed up */ /* see which algorithm has been fixed up */
if(sec == sec_status_secure) { if(sec == sec_status_secure) {
if(!sigalg) if(!sigalg)
@ -597,8 +610,8 @@ void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s)
enum sec_status enum sec_status
dnskey_verify_rrset(struct module_env* env, struct val_env* ve, dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, char** reason, sldns_pkt_section section, size_t dnskey_idx, char** reason, sldns_ede_code *reason_bogus,
struct module_qstate* qstate) sldns_pkt_section section, struct module_qstate* qstate)
{ {
enum sec_status sec; enum sec_status sec;
size_t i, num, numchecked = 0; size_t i, num, numchecked = 0;
@ -612,6 +625,8 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
verbose(VERB_QUERY, "rrset failed to verify due to a lack of " verbose(VERB_QUERY, "rrset failed to verify due to a lack of "
"signatures"); "signatures");
*reason = "no signatures"; *reason = "no signatures";
if(reason_bogus)
*reason_bogus = LDNS_EDE_RRSIGS_MISSING;
return sec_status_bogus; return sec_status_bogus;
} }
for(i=0; i<num; i++) { for(i=0; i<num; i++) {
@ -623,7 +638,7 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
sec = dnskey_verify_rrset_sig(env->scratch, sec = dnskey_verify_rrset_sig(env->scratch,
env->scratch_buffer, ve, *env->now, rrset, env->scratch_buffer, ve, *env->now, rrset,
dnskey, dnskey_idx, i, &sortree, &buf_canon, reason, dnskey, dnskey_idx, i, &sortree, &buf_canon, reason,
section, qstate); reason_bogus, section, qstate);
if(sec == sec_status_secure) if(sec == sec_status_secure)
return sec; return sec;
numchecked ++; numchecked ++;
@ -633,12 +648,13 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
return sec_status_bogus; return sec_status_bogus;
} }
enum sec_status static enum sec_status
dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve, dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
time_t now, struct ub_packed_rrset_key* rrset, time_t now, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t sig_idx, struct ub_packed_rrset_key* dnskey, size_t sig_idx,
struct rbtree_type** sortree, char** reason, sldns_pkt_section section, struct rbtree_type** sortree,
struct module_qstate* qstate) char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate)
{ {
/* find matching keys and check them */ /* find matching keys and check them */
enum sec_status sec = sec_status_bogus; enum sec_status sec = sec_status_bogus;
@ -649,6 +665,8 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
int buf_canon = 0; int buf_canon = 0;
verbose(VERB_ALGO, "verify sig %d %d", (int)tag, algo); verbose(VERB_ALGO, "verify sig %d %d", (int)tag, algo);
if(!dnskey_algo_id_is_supported(algo)) { if(!dnskey_algo_id_is_supported(algo)) {
if(reason_bogus)
*reason_bogus = LDNS_EDE_UNSUPPORTED_DNSKEY_ALG;
verbose(VERB_QUERY, "verify sig: unknown algorithm"); verbose(VERB_QUERY, "verify sig: unknown algorithm");
return sec_status_insecure; return sec_status_insecure;
} }
@ -663,12 +681,15 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
/* see if key verifies */ /* see if key verifies */
sec = dnskey_verify_rrset_sig(env->scratch, sec = dnskey_verify_rrset_sig(env->scratch,
env->scratch_buffer, ve, now, rrset, dnskey, i, env->scratch_buffer, ve, now, rrset, dnskey, i,
sig_idx, sortree, &buf_canon, reason, section, qstate); sig_idx, sortree, &buf_canon, reason, reason_bogus,
section, qstate);
if(sec == sec_status_secure) if(sec == sec_status_secure)
return sec; return sec;
} }
if(numchecked == 0) { if(numchecked == 0) {
*reason = "signatures from unknown keys"; *reason = "signatures from unknown keys";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSKEY_MISSING;
verbose(VERB_QUERY, "verify: could not find appropriate key"); verbose(VERB_QUERY, "verify: could not find appropriate key");
return sec_status_bogus; return sec_status_bogus;
} }
@ -1361,8 +1382,8 @@ subtract_1982(uint32_t a, uint32_t b)
/** check rrsig dates */ /** check rrsig dates */
static int static int
check_dates(struct val_env* ve, uint32_t unow, check_dates(struct val_env* ve, uint32_t unow, uint8_t* expi_p,
uint8_t* expi_p, uint8_t* incep_p, char** reason) uint8_t* incep_p, char** reason, sldns_ede_code *reason_bogus)
{ {
/* read out the dates */ /* read out the dates */
uint32_t expi, incep, now; uint32_t expi, incep, now;
@ -1386,6 +1407,14 @@ check_dates(struct val_env* ve, uint32_t unow,
sigdate_error("verify: inception after expiration, " sigdate_error("verify: inception after expiration, "
"signature bad", expi, incep, now); "signature bad", expi, incep, now);
*reason = "signature inception after expiration"; *reason = "signature inception after expiration";
if(reason_bogus){
/* from RFC8914 on Signature Not Yet Valid: The resolver
* attempted to perform DNSSEC validation, but no
* signatures are presently valid and at least some are
* not yet valid. */
*reason_bogus = LDNS_EDE_SIGNATURE_NOT_YET_VALID;
}
return 0; return 0;
} }
if(compare_1982(incep, now) > 0) { if(compare_1982(incep, now) > 0) {
@ -1397,6 +1426,8 @@ check_dates(struct val_env* ve, uint32_t unow,
sigdate_error("verify: signature bad, current time is" sigdate_error("verify: signature bad, current time is"
" before inception date", expi, incep, now); " before inception date", expi, incep, now);
*reason = "signature before inception date"; *reason = "signature before inception date";
if(reason_bogus)
*reason_bogus = LDNS_EDE_SIGNATURE_NOT_YET_VALID;
return 0; return 0;
} }
sigdate_error("verify warning suspicious signature inception " sigdate_error("verify warning suspicious signature inception "
@ -1410,6 +1441,8 @@ check_dates(struct val_env* ve, uint32_t unow,
sigdate_error("verify: signature expired", expi, sigdate_error("verify: signature expired", expi,
incep, now); incep, now);
*reason = "signature expired"; *reason = "signature expired";
if(reason_bogus)
*reason_bogus = LDNS_EDE_SIGNATURE_EXPIRED;
return 0; return 0;
} }
sigdate_error("verify warning suspicious signature expiration " sigdate_error("verify warning suspicious signature expiration "
@ -1473,7 +1506,8 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
struct val_env* ve, time_t now, struct val_env* ve, time_t now,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, size_t sig_idx, size_t dnskey_idx, size_t sig_idx,
struct rbtree_type** sortree, int* buf_canon, char** reason, struct rbtree_type** sortree, int* buf_canon,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate) sldns_pkt_section section, struct module_qstate* qstate)
{ {
enum sec_status sec; enum sec_status sec;
@ -1492,12 +1526,16 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
if(siglen < 2+20) { if(siglen < 2+20) {
verbose(VERB_QUERY, "verify: signature too short"); verbose(VERB_QUERY, "verify: signature too short");
*reason = "signature too short"; *reason = "signature too short";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus; return sec_status_bogus;
} }
if(!(dnskey_get_flags(dnskey, dnskey_idx) & DNSKEY_BIT_ZSK)) { if(!(dnskey_get_flags(dnskey, dnskey_idx) & DNSKEY_BIT_ZSK)) {
verbose(VERB_QUERY, "verify: dnskey without ZSK flag"); verbose(VERB_QUERY, "verify: dnskey without ZSK flag");
*reason = "dnskey without ZSK flag"; *reason = "dnskey without ZSK flag";
if(reason_bogus)
*reason_bogus = LDNS_EDE_NO_ZONE_KEY_BIT_SET;
return sec_status_bogus; return sec_status_bogus;
} }
@ -1505,6 +1543,8 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
/* RFC 4034 says DNSKEY PROTOCOL MUST be 3 */ /* RFC 4034 says DNSKEY PROTOCOL MUST be 3 */
verbose(VERB_QUERY, "verify: dnskey has wrong key protocol"); verbose(VERB_QUERY, "verify: dnskey has wrong key protocol");
*reason = "dnskey has wrong protocolnumber"; *reason = "dnskey has wrong protocolnumber";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus; return sec_status_bogus;
} }
@ -1514,17 +1554,23 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
if(!signer_len) { if(!signer_len) {
verbose(VERB_QUERY, "verify: malformed signer name"); verbose(VERB_QUERY, "verify: malformed signer name");
*reason = "signer name malformed"; *reason = "signer name malformed";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus; /* signer name invalid */ return sec_status_bogus; /* signer name invalid */
} }
if(!dname_subdomain_c(rrset->rk.dname, signer)) { if(!dname_subdomain_c(rrset->rk.dname, signer)) {
verbose(VERB_QUERY, "verify: signer name is off-tree"); verbose(VERB_QUERY, "verify: signer name is off-tree");
*reason = "signer name off-tree"; *reason = "signer name off-tree";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus; /* signer name offtree */ return sec_status_bogus; /* signer name offtree */
} }
sigblock = (unsigned char*)signer+signer_len; sigblock = (unsigned char*)signer+signer_len;
if(siglen < 2+18+signer_len+1) { if(siglen < 2+18+signer_len+1) {
verbose(VERB_QUERY, "verify: too short, no signature data"); verbose(VERB_QUERY, "verify: too short, no signature data");
*reason = "signature too short, no signature data"; *reason = "signature too short, no signature data";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus; /* sig rdf is < 1 byte */ return sec_status_bogus; /* sig rdf is < 1 byte */
} }
sigblock_len = (unsigned int)(siglen - 2 - 18 - signer_len); sigblock_len = (unsigned int)(siglen - 2 - 18 - signer_len);
@ -1537,6 +1583,8 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
log_nametypeclass(VERB_QUERY, "the key name is", log_nametypeclass(VERB_QUERY, "the key name is",
dnskey->rk.dname, 0, 0); dnskey->rk.dname, 0, 0);
*reason = "signer name mismatches key name"; *reason = "signer name mismatches key name";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus; return sec_status_bogus;
} }
@ -1545,18 +1593,24 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
if(memcmp(sig+2, &rrset->rk.type, 2) != 0) { if(memcmp(sig+2, &rrset->rk.type, 2) != 0) {
verbose(VERB_QUERY, "verify: wrong type covered"); verbose(VERB_QUERY, "verify: wrong type covered");
*reason = "signature covers wrong type"; *reason = "signature covers wrong type";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus; return sec_status_bogus;
} }
/* verify keytag and sig algo (possibly again) */ /* verify keytag and sig algo (possibly again) */
if((int)sig[2+2] != dnskey_get_algo(dnskey, dnskey_idx)) { if((int)sig[2+2] != dnskey_get_algo(dnskey, dnskey_idx)) {
verbose(VERB_QUERY, "verify: wrong algorithm"); verbose(VERB_QUERY, "verify: wrong algorithm");
*reason = "signature has wrong algorithm"; *reason = "signature has wrong algorithm";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus; return sec_status_bogus;
} }
ktag = htons(dnskey_calc_keytag(dnskey, dnskey_idx)); ktag = htons(dnskey_calc_keytag(dnskey, dnskey_idx));
if(memcmp(sig+2+16, &ktag, 2) != 0) { if(memcmp(sig+2+16, &ktag, 2) != 0) {
verbose(VERB_QUERY, "verify: wrong keytag"); verbose(VERB_QUERY, "verify: wrong keytag");
*reason = "signature has wrong keytag"; *reason = "signature has wrong keytag";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus; return sec_status_bogus;
} }
@ -1564,6 +1618,8 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
if((int)sig[2+3] > dname_signame_label_count(rrset->rk.dname)) { if((int)sig[2+3] > dname_signame_label_count(rrset->rk.dname)) {
verbose(VERB_QUERY, "verify: labelcount out of range"); verbose(VERB_QUERY, "verify: labelcount out of range");
*reason = "signature labelcount out of range"; *reason = "signature labelcount out of range";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus; return sec_status_bogus;
} }
@ -1598,7 +1654,8 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
/* verify inception, expiration dates /* verify inception, expiration dates
* Do this last so that if you ignore expired-sigs the * Do this last so that if you ignore expired-sigs the
* rest is sure to be OK. */ * rest is sure to be OK. */
if(!check_dates(ve, now, sig+2+8, sig+2+12, reason)) { if(!check_dates(ve, now, sig+2+8, sig+2+12,
reason, reason_bogus)) {
return sec_status_bogus; return sec_status_bogus;
} }
} }

View File

@ -45,6 +45,7 @@
#define VALIDATOR_VAL_SIGCRYPT_H #define VALIDATOR_VAL_SIGCRYPT_H
#include "util/data/packed_rrset.h" #include "util/data/packed_rrset.h"
#include "sldns/pkthdr.h" #include "sldns/pkthdr.h"
#include "sldns/rrdef.h"
struct val_env; struct val_env;
struct module_env; struct module_env;
struct module_qstate; struct module_qstate;
@ -256,6 +257,7 @@ uint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx);
* @param sigalg: if nonNULL provide downgrade protection otherwise one * @param sigalg: if nonNULL provide downgrade protection otherwise one
* algorithm is enough. * algorithm is enough.
* @param reason: if bogus, a string returned, fixed or alloced in scratch. * @param reason: if bogus, a string returned, fixed or alloced in scratch.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param section: section of packet where this rrset comes from. * @param section: section of packet where this rrset comes from.
* @param qstate: qstate with region. * @param qstate: qstate with region.
* @return SECURE if one key in the set verifies one rrsig. * @return SECURE if one key in the set verifies one rrsig.
@ -264,9 +266,11 @@ uint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx);
*/ */
enum sec_status dnskeyset_verify_rrset(struct module_env* env, enum sec_status dnskeyset_verify_rrset(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset, struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, uint8_t* sigalg, char** reason, struct ub_packed_rrset_key* dnskey, uint8_t* sigalg,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate); sldns_pkt_section section, struct module_qstate* qstate);
/** /**
* verify rrset against one specific dnskey (from rrset) * verify rrset against one specific dnskey (from rrset)
* @param env: module environment, scratch space is used. * @param env: module environment, scratch space is used.
@ -275,38 +279,17 @@ enum sec_status dnskeyset_verify_rrset(struct module_env* env,
* @param dnskey: DNSKEY rrset, keyset. * @param dnskey: DNSKEY rrset, keyset.
* @param dnskey_idx: which key from the rrset to try. * @param dnskey_idx: which key from the rrset to try.
* @param reason: if bogus, a string returned, fixed or alloced in scratch. * @param reason: if bogus, a string returned, fixed or alloced in scratch.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param section: section of packet where this rrset comes from. * @param section: section of packet where this rrset comes from.
* @param qstate: qstate with region. * @param qstate: qstate with region.
* @return secure if *this* key signs any of the signatures on rrset. * @return secure if *this* key signs any of the signatures on rrset.
* unchecked on error or and bogus on bad signature. * unchecked on error or and bogus on bad signature.
*/ */
enum sec_status dnskey_verify_rrset(struct module_env* env, enum sec_status dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
struct val_env* ve, struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
struct ub_packed_rrset_key* dnskey, size_t dnskey_idx, char** reason, size_t dnskey_idx, char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate); sldns_pkt_section section, struct module_qstate* qstate);
/**
* verify rrset, with dnskey rrset, for a specific rrsig in rrset
* @param env: module environment, scratch space is used.
* @param ve: validator environment, date settings.
* @param now: current time for validation (can be overridden).
* @param rrset: to be validated.
* @param dnskey: DNSKEY rrset, keyset to try.
* @param sig_idx: which signature to try to validate.
* @param sortree: reused sorted order. Stored in region. Pass NULL at start,
* and for a new rrset.
* @param reason: if bogus, a string returned, fixed or alloced in scratch.
* @param section: section of packet where this rrset comes from.
* @param qstate: qstate with region.
* @return secure if any key signs *this* signature. bogus if no key signs it,
* or unchecked on error.
*/
enum sec_status dnskeyset_verify_rrset_sig(struct module_env* env,
struct val_env* ve, time_t now, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t sig_idx,
struct rbtree_type** sortree, char** reason, sldns_pkt_section section,
struct module_qstate* qstate);
/** /**
* verify rrset, with specific dnskey(from set), for a specific rrsig * verify rrset, with specific dnskey(from set), for a specific rrsig
* @param region: scratch region used for temporary allocation. * @param region: scratch region used for temporary allocation.
@ -323,6 +306,7 @@ enum sec_status dnskeyset_verify_rrset_sig(struct module_env* env,
* pass false at start. pass old value only for same rrset and same * pass false at start. pass old value only for same rrset and same
* signature (but perhaps different key) for reuse. * signature (but perhaps different key) for reuse.
* @param reason: if bogus, a string returned, fixed or alloced in scratch. * @param reason: if bogus, a string returned, fixed or alloced in scratch.
* @param reason_bogus: EDE (8914) code paired with the reason of failure.
* @param section: section of packet where this rrset comes from. * @param section: section of packet where this rrset comes from.
* @param qstate: qstate with region. * @param qstate: qstate with region.
* @return secure if this key signs this signature. unchecked on error or * @return secure if this key signs this signature. unchecked on error or
@ -332,7 +316,8 @@ enum sec_status dnskey_verify_rrset_sig(struct regional* region,
struct sldns_buffer* buf, struct val_env* ve, time_t now, struct sldns_buffer* buf, struct val_env* ve, time_t now,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey, struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, size_t sig_idx, size_t dnskey_idx, size_t sig_idx,
struct rbtree_type** sortree, int* buf_canon, char** reason, struct rbtree_type** sortree, int* buf_canon,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate); sldns_pkt_section section, struct module_qstate* qstate);
/** /**

View File

@ -332,11 +332,11 @@ rrset_get_ttl(struct ub_packed_rrset_key* rrset)
return d->ttl; return d->ttl;
} }
enum sec_status static enum sec_status
val_verify_rrset(struct module_env* env, struct val_env* ve, val_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys, struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
uint8_t* sigalg, char** reason, sldns_pkt_section section, uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus,
struct module_qstate* qstate) sldns_pkt_section section, struct module_qstate* qstate)
{ {
enum sec_status sec; enum sec_status sec;
struct packed_rrset_data* d = (struct packed_rrset_data*)rrset-> struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
@ -359,7 +359,7 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname, log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname,
ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class)); ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
sec = dnskeyset_verify_rrset(env, ve, rrset, keys, sigalg, reason, sec = dnskeyset_verify_rrset(env, ve, rrset, keys, sigalg, reason,
section, qstate); reason_bogus, section, qstate);
verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec)); verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec));
regional_free_all(env->scratch); regional_free_all(env->scratch);
@ -392,7 +392,8 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
enum sec_status enum sec_status
val_verify_rrset_entry(struct module_env* env, struct val_env* ve, val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey, struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey,
char** reason, sldns_pkt_section section, struct module_qstate* qstate) char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate)
{ {
/* temporary dnskey rrset-key */ /* temporary dnskey rrset-key */
struct ub_packed_rrset_key dnskey; struct ub_packed_rrset_key dnskey;
@ -406,7 +407,7 @@ val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
dnskey.entry.key = &dnskey; dnskey.entry.key = &dnskey;
dnskey.entry.data = kd->rrset_data; dnskey.entry.data = kd->rrset_data;
sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason, sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason,
section, qstate); reason_bogus, section, qstate);
return sec; return sec;
} }
@ -415,7 +416,7 @@ static enum sec_status
verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve, verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason, struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason,
struct module_qstate* qstate) sldns_ede_code *reason_bogus, struct module_qstate* qstate)
{ {
enum sec_status sec = sec_status_bogus; enum sec_status sec = sec_status_bogus;
size_t i, num, numchecked = 0, numhashok = 0, numsizesupp = 0; size_t i, num, numchecked = 0, numhashok = 0, numsizesupp = 0;
@ -450,8 +451,8 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
/* Otherwise, we have a match! Make sure that the DNSKEY /* Otherwise, we have a match! Make sure that the DNSKEY
* verifies *with this key* */ * verifies *with this key* */
sec = dnskey_verify_rrset(env, ve, dnskey_rrset, sec = dnskey_verify_rrset(env, ve, dnskey_rrset, dnskey_rrset,
dnskey_rrset, i, reason, LDNS_SECTION_ANSWER, qstate); i, reason, reason_bogus, LDNS_SECTION_ANSWER, qstate);
if(sec == sec_status_secure) { if(sec == sec_status_secure) {
return sec; return sec;
} }
@ -488,11 +489,12 @@ int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset)
return digest_algo; return digest_algo;
} }
// @TODO change the use of this function to _ede function in authzone.c:8111
enum sec_status enum sec_status
val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve, val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason, struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason,
struct module_qstate* qstate) sldns_ede_code *reason_bogus, struct module_qstate* qstate)
{ {
/* as long as this is false, we can consider this DS rrset to be /* as long as this is false, we can consider this DS rrset to be
* equivalent to no DS rrset. */ * equivalent to no DS rrset. */
@ -529,7 +531,7 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
} }
sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset, sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
ds_rrset, i, reason, qstate); ds_rrset, i, reason, reason_bogus, qstate);
if(sec == sec_status_insecure) if(sec == sec_status_insecure)
continue; continue;
@ -575,11 +577,12 @@ struct key_entry_key*
val_verify_new_DNSKEYs(struct regional* region, struct module_env* env, val_verify_new_DNSKEYs(struct regional* region, struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason, struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason,
struct module_qstate* qstate) sldns_ede_code *reason_bogus, struct module_qstate* qstate)
{ {
uint8_t sigalg[ALGO_NEEDS_MAX+1]; uint8_t sigalg[ALGO_NEEDS_MAX+1];
enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve, enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve,
dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason, qstate); dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason,
reason_bogus, qstate);
if(sec == sec_status_secure) { if(sec == sec_status_secure) {
return key_entry_create_rrset(region, return key_entry_create_rrset(region,
@ -602,7 +605,7 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ta_ds, struct ub_packed_rrset_key* ta_ds,
struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason, struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason,
struct module_qstate* qstate) sldns_ede_code *reason_bogus, struct module_qstate* qstate)
{ {
/* as long as this is false, we can consider this anchor to be /* as long as this is false, we can consider this anchor to be
* equivalent to no anchor. */ * equivalent to no anchor. */
@ -617,6 +620,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset " verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset "
"by name"); "by name");
*reason = "DNSKEY RRset did not match DS RRset by name"; *reason = "DNSKEY RRset did not match DS RRset by name";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSKEY_MISSING;
return sec_status_bogus; return sec_status_bogus;
} }
if(ta_dnskey && (dnskey_rrset->rk.dname_len != ta_dnskey->rk.dname_len if(ta_dnskey && (dnskey_rrset->rk.dname_len != ta_dnskey->rk.dname_len
@ -625,6 +630,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
verbose(VERB_QUERY, "DNSKEY RRset did not match anchor RRset " verbose(VERB_QUERY, "DNSKEY RRset did not match anchor RRset "
"by name"); "by name");
*reason = "DNSKEY RRset did not match anchor RRset by name"; *reason = "DNSKEY RRset did not match anchor RRset by name";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSKEY_MISSING;
return sec_status_bogus; return sec_status_bogus;
} }
@ -648,7 +655,7 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
continue; continue;
sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset, sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
ta_ds, i, reason, qstate); ta_ds, i, reason, reason_bogus, qstate);
if(sec == sec_status_insecure) if(sec == sec_status_insecure)
continue; continue;
@ -688,7 +695,7 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
has_useful_ta = 1; has_useful_ta = 1;
sec = dnskey_verify_rrset(env, ve, dnskey_rrset, sec = dnskey_verify_rrset(env, ve, dnskey_rrset,
ta_dnskey, i, reason, LDNS_SECTION_ANSWER, qstate); ta_dnskey, i, reason, NULL, LDNS_SECTION_ANSWER, qstate);
if(sec == sec_status_secure) { if(sec == sec_status_secure) {
if(!sigalg || algo_needs_set_secure(&needs, if(!sigalg || algo_needs_set_secure(&needs,
(uint8_t)dnskey_get_algo(ta_dnskey, i))) { (uint8_t)dnskey_get_algo(ta_dnskey, i))) {
@ -726,12 +733,12 @@ val_verify_new_DNSKEYs_with_ta(struct regional* region, struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ta_ds_rrset, struct ub_packed_rrset_key* ta_ds_rrset,
struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot, struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot,
char** reason, struct module_qstate* qstate) char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate)
{ {
uint8_t sigalg[ALGO_NEEDS_MAX+1]; uint8_t sigalg[ALGO_NEEDS_MAX+1];
enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve,
dnskey_rrset, ta_ds_rrset, ta_dnskey_rrset, dnskey_rrset, ta_ds_rrset, ta_dnskey_rrset,
downprot?sigalg:NULL, reason, qstate); downprot?sigalg:NULL, reason, reason_bogus, qstate);
if(sec == sec_status_secure) { if(sec == sec_status_secure) {
return key_entry_create_rrset(region, return key_entry_create_rrset(region,
@ -776,6 +783,7 @@ val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset)
if(lt) snprintf(aerr, sizeof(aerr), "%s", lt->name); if(lt) snprintf(aerr, sizeof(aerr), "%s", lt->name);
else snprintf(aerr, sizeof(aerr), "%d", else snprintf(aerr, sizeof(aerr), "%d",
(int)ds_get_key_algo(ds_rrset, 0)); (int)ds_get_key_algo(ds_rrset, 0));
verbose(VERB_ALGO, "DS unsupported, hash %s %s, " verbose(VERB_ALGO, "DS unsupported, hash %s %s, "
"key algorithm %s %s", herr, "key algorithm %s %s", herr,
(ds_digest_algo_is_supported(ds_rrset, 0)? (ds_digest_algo_is_supported(ds_rrset, 0)?

View File

@ -43,6 +43,7 @@
#define VALIDATOR_VAL_UTILS_H #define VALIDATOR_VAL_UTILS_H
#include "util/data/packed_rrset.h" #include "util/data/packed_rrset.h"
#include "sldns/pkthdr.h" #include "sldns/pkthdr.h"
#include "sldns/rrdef.h"
struct query_info; struct query_info;
struct reply_info; struct reply_info;
struct val_env; struct val_env;
@ -113,24 +114,6 @@ void val_find_signer(enum val_classification subtype,
struct query_info* qinf, struct reply_info* rep, struct query_info* qinf, struct reply_info* rep,
size_t cname_skip, uint8_t** signer_name, size_t* signer_len); size_t cname_skip, uint8_t** signer_name, size_t* signer_len);
/**
* Verify RRset with keys
* @param env: module environment (scratch buffer)
* @param ve: validator environment (verification settings)
* @param rrset: what to verify
* @param keys: dnskey rrset to verify with.
* @param sigalg: if nonNULL provide downgrade protection otherwise one
* algorithm is enough. Algo list is constructed in here.
* @param reason: reason of failure. Fixed string or alloced in scratch.
* @param section: section of packet where this rrset comes from.
* @param qstate: qstate with region.
* @return security status of verification.
*/
enum sec_status val_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
uint8_t* sigalg, char** reason, sldns_pkt_section section,
struct module_qstate* qstate);
/** /**
* Verify RRset with keys from a keyset. * Verify RRset with keys from a keyset.
* @param env: module environment (scratch buffer) * @param env: module environment (scratch buffer)
@ -138,14 +121,15 @@ enum sec_status val_verify_rrset(struct module_env* env, struct val_env* ve,
* @param rrset: what to verify * @param rrset: what to verify
* @param kkey: key_entry to verify with. * @param kkey: key_entry to verify with.
* @param reason: reason of failure. Fixed string or alloced in scratch. * @param reason: reason of failure. Fixed string or alloced in scratch.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param section: section of packet where this rrset comes from. * @param section: section of packet where this rrset comes from.
* @param qstate: qstate with region. * @param qstate: qstate with region.
* @return security status of verification. * @return security status of verification.
*/ */
enum sec_status val_verify_rrset_entry(struct module_env* env, enum sec_status val_verify_rrset_entry(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset, struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct key_entry_key* kkey, char** reason, sldns_pkt_section section, struct key_entry_key* kkey, char** reason, sldns_ede_code *reason_bogus,
struct module_qstate* qstate); sldns_pkt_section section, struct module_qstate* qstate);
/** /**
* Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but * Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but
@ -158,6 +142,7 @@ enum sec_status val_verify_rrset_entry(struct module_env* env,
* algorithm is enough. The list of signalled algorithms is returned, * algorithm is enough. The list of signalled algorithms is returned,
* must have enough space for ALGO_NEEDS_MAX+1. * must have enough space for ALGO_NEEDS_MAX+1.
* @param reason: reason of failure. Fixed string or alloced in scratch. * @param reason: reason of failure. Fixed string or alloced in scratch.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param qstate: qstate with region. * @param qstate: qstate with region.
* @return: sec_status_secure if a DS matches. * @return: sec_status_secure if a DS matches.
* sec_status_insecure if end of trust (i.e., unknown algorithms). * sec_status_insecure if end of trust (i.e., unknown algorithms).
@ -166,7 +151,7 @@ enum sec_status val_verify_rrset_entry(struct module_env* env,
enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env, enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason, struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason,
struct module_qstate* qstate); sldns_ede_code *reason_bogus, struct module_qstate* qstate);
/** /**
* Verify DNSKEYs with DS and DNSKEY rrset. Like val_verify_DNSKEY_with_DS * Verify DNSKEYs with DS and DNSKEY rrset. Like val_verify_DNSKEY_with_DS
@ -180,6 +165,7 @@ enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
* algorithm is enough. The list of signalled algorithms is returned, * algorithm is enough. The list of signalled algorithms is returned,
* must have enough space for ALGO_NEEDS_MAX+1. * must have enough space for ALGO_NEEDS_MAX+1.
* @param reason: reason of failure. Fixed string or alloced in scratch. * @param reason: reason of failure. Fixed string or alloced in scratch.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param qstate: qstate with region. * @param qstate: qstate with region.
* @return: sec_status_secure if a DS matches. * @return: sec_status_secure if a DS matches.
* sec_status_insecure if end of trust (i.e., unknown algorithms). * sec_status_insecure if end of trust (i.e., unknown algorithms).
@ -189,7 +175,7 @@ enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ta_ds, struct ub_packed_rrset_key* ta_ds,
struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason, struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason,
struct module_qstate* qstate); sldns_ede_code *reason_bogus, struct module_qstate* qstate);
/** /**
* Verify new DNSKEYs with DS rrset. The DS contains hash values that should * Verify new DNSKEYs with DS rrset. The DS contains hash values that should
@ -204,6 +190,7 @@ enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env,
* @param downprot: if true provide downgrade protection otherwise one * @param downprot: if true provide downgrade protection otherwise one
* algorithm is enough. * algorithm is enough.
* @param reason: reason of failure. Fixed string or alloced in scratch. * @param reason: reason of failure. Fixed string or alloced in scratch.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param qstate: qstate with region. * @param qstate: qstate with region.
* @return a KeyEntry. This will either contain the now trusted * @return a KeyEntry. This will either contain the now trusted
* dnskey_rrset, a "null" key entry indicating that this DS * dnskey_rrset, a "null" key entry indicating that this DS
@ -219,8 +206,7 @@ struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
struct module_env* env, struct val_env* ve, struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason, struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason,
struct module_qstate* qstate); sldns_ede_code *reason_bogus, struct module_qstate* qstate);
/** /**
* Verify rrset with trust anchor: DS and DNSKEY rrset. * Verify rrset with trust anchor: DS and DNSKEY rrset.
@ -234,6 +220,7 @@ struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
* @param downprot: if true provide downgrade protection otherwise one * @param downprot: if true provide downgrade protection otherwise one
* algorithm is enough. * algorithm is enough.
* @param reason: reason of failure. Fixed string or alloced in scratch. * @param reason: reason of failure. Fixed string or alloced in scratch.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param qstate: qstate with region. * @param qstate: qstate with region.
* @return a KeyEntry. This will either contain the now trusted * @return a KeyEntry. This will either contain the now trusted
* dnskey_rrset, a "null" key entry indicating that this DS * dnskey_rrset, a "null" key entry indicating that this DS
@ -249,8 +236,8 @@ struct key_entry_key* val_verify_new_DNSKEYs_with_ta(struct regional* region,
struct module_env* env, struct val_env* ve, struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ta_ds_rrset, struct ub_packed_rrset_key* ta_ds_rrset,
struct ub_packed_rrset_key* ta_dnskey_rrset, struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot,
int downprot, char** reason, struct module_qstate* qstate); char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate);
/** /**
* Determine if DS rrset is usable for validator or not. * Determine if DS rrset is usable for validator or not.

Some files were not shown because too many files have changed in this diff Show More