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@
CC=@CC@
CPPFLAGS=-I. @CPPFLAGS@
PYTHON_CPPFLAGS=-I. @PYTHON_CPPFLAGS@
PYTHON_CPPFLAGS=-I. -I$(srcdir) @PYTHON_CPPFLAGS@
CFLAGS=-DSRCDIR=$(srcdir) @CFLAGS@
LDFLAGS=@LDFLAGS@
LIBS=@LIBS@
@ -344,7 +344,18 @@ longcheck: longtest
test: unittest$(EXEEXT) testbound$(EXEEXT)
./unittest$(EXEEXT)
./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
longtest: tests
@ -556,7 +567,7 @@ pythonmod-install:
pyunbound-install:
$(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=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 ; \
done
$(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=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)/man5
$(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-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(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)/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)/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 \
$(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \

View File

@ -18,27 +18,45 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
print(sys.version.split()[[0]])"`
fi
#
# Check if you have distutils, else fail
#
AC_MSG_CHECKING([for the distutils Python package])
if ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`; then
# 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])
else
sysconfig_module="sysconfig"
# if yes, use sysconfig, because distutils is deprecated.
else
AC_MSG_RESULT([no])
AC_MSG_ERROR([cannot import Python module "distutils".
Please check your Python installation. The error was:
$ac_distutils_result])
PYTHON_VERSION=""
fi
# if no, try to use distutils
#
# Check if you have distutils, else fail
#
AC_MSG_CHECKING([for the distutils Python package])
if ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
AC_MSG_ERROR([cannot import Python module "distutils".
Please check your Python installation. The error was:
$ac_distutils_result])
PYTHON_VERSION=""
fi
sysconfig_module="distutils.sysconfig"
fi
#
# Check for Python include path
#
AC_MSG_CHECKING([for Python include path])
if test -z "$PYTHON_CPPFLAGS"; then
python_path=`$PYTHON -c "import distutils.sysconfig; \
print(distutils.sysconfig.get_python_inc());"`
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; \
print(distutils.sysconfig.get_python_inc());"`
fi
if test -n "${python_path}"; then
python_path="-I$python_path"
fi
@ -52,14 +70,14 @@ $ac_distutils_result])
#
AC_MSG_CHECKING([for Python library path])
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'));"`
fi
AC_MSG_RESULT([$PYTHON_LDFLAGS])
AC_SUBST([PYTHON_LDFLAGS])
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'));"`
fi
@ -68,8 +86,13 @@ $ac_distutils_result])
#
AC_MSG_CHECKING([for Python site-packages path])
if test -z "$PYTHON_SITE_PKG"; then
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
print(distutils.sysconfig.get_python_lib(1,0));"`
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; \
print(distutils.sysconfig.get_python_lib(1,0));"`
fi
fi
AC_MSG_RESULT([$PYTHON_SITE_PKG])
AC_SUBST([PYTHON_SITE_PKG])

View File

@ -4,7 +4,7 @@
# 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
# under the terms of the GNU General Public License as published by
@ -1151,16 +1151,27 @@ EOF
;;
x86_64:Linux:*:*)
set_cc_for_build
CPU=$UNAME_MACHINE
LIBCABI=$LIBC
if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_X32 >/dev/null
then
LIBCABI=${LIBC}x32
fi
ABI=64
sed 's/^ //' << EOF > "$dummy.c"
#ifdef __i386__
ABI=x86
#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
GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI
GUESS=$CPU-pc-linux-$LIBCABI
;;
xtensa*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
@ -1367,8 +1378,11 @@ EOF
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
GUESS=i586-pc-haiku
;;
x86_64:Haiku:*:*)
GUESS=x86_64-unknown-haiku
ppc:Haiku:*:*) # Haiku running on Apple PowerPC
GUESS=powerpc-apple-haiku
;;
*:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat)
GUESS=$UNAME_MACHINE-unknown-haiku
;;
SX-4:SUPER-UX:*:*)
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. */
#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. */
#undef const
@ -1150,7 +1154,7 @@
#include <ws2tcpip.h>
#endif
#ifndef USE_WINSOCK
#if !defined(USE_WINSOCK) || !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) || defined(__USE_MINGW_ANSI_STDIO)
#define ARG_LL "%ll"
#else
#define ARG_LL "%I64"

View File

@ -1,6 +1,6 @@
#! /bin/sh
# 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>.
#
@ -591,8 +591,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unbound'
PACKAGE_TARNAME='unbound'
PACKAGE_VERSION='1.15.0'
PACKAGE_STRING='unbound 1.15.0'
PACKAGE_VERSION='1.16.0'
PACKAGE_STRING='unbound 1.16.0'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
PACKAGE_URL=''
@ -813,6 +813,7 @@ infodir
docdir
oldincludedir
includedir
runstatedir
localstatedir
sharedstatedir
sysconfdir
@ -964,6 +965,7 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@ -1216,6 +1218,15 @@ do
| -silent | --silent | --silen | --sile | --sil)
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)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@ -1353,7 +1364,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir
libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# 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.
# This message is too long to be a string in the A/UX 3.1 sh.
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]...
@ -1506,6 +1517,7 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@ -1531,7 +1543,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of unbound 1.15.0:";;
short | recursive ) echo "Configuration of unbound 1.16.0:";;
esac
cat <<\_ACEOF
@ -1773,7 +1785,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
unbound configure 1.15.0
unbound configure 1.16.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -2482,7 +2494,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
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
$ $0 $@
@ -2832,13 +2844,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
UNBOUND_VERSION_MAJOR=1
UNBOUND_VERSION_MINOR=15
UNBOUND_VERSION_MINOR=16
UNBOUND_VERSION_MICRO=0
LIBUNBOUND_CURRENT=9
LIBUNBOUND_REVISION=15
LIBUNBOUND_REVISION=16
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@ -2921,6 +2933,7 @@ LIBUNBOUND_AGE=1
# 1.13.2 had 9:13:1
# 1.14.0 had 9:14: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
# Revision -- which iteration of the implementation of the binary
@ -17455,22 +17468,38 @@ fi
print(sys.version.split()[0])"`
fi
#
# Check if you have distutils, else fail
#
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the distutils Python package" >&5
$as_echo_n "checking for the distutils Python package... " >&6; }
if ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`; then
# 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; }
else
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; }
as_fn_error $? "cannot import Python module \"distutils\".
Please check your Python installation. The error was:
$ac_distutils_result" "$LINENO" 5
PYTHON_VERSION=""
fi
# if no, try to use distutils
#
# Check if you have distutils, else fail
#
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the distutils Python package" >&5
$as_echo_n "checking for the distutils Python package... " >&6; }
if ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
as_fn_error $? "cannot import Python module \"distutils\".
Please check your Python installation. The error was:
$ac_distutils_result" "$LINENO" 5
PYTHON_VERSION=""
fi
sysconfig_module="distutils.sysconfig"
fi
#
# Check for Python include path
@ -17478,8 +17507,13 @@ $ac_distutils_result" "$LINENO" 5
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python include path" >&5
$as_echo_n "checking for Python include path... " >&6; }
if test -z "$PYTHON_CPPFLAGS"; then
python_path=`$PYTHON -c "import distutils.sysconfig; \
print(distutils.sysconfig.get_python_inc());"`
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; \
print(distutils.sysconfig.get_python_inc());"`
fi
if test -n "${python_path}"; then
python_path="-I$python_path"
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_n "checking for Python library path... " >&6; }
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'));"`
fi
{ $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
PYTHON_LIBDIR=`$PYTHON -c "from distutils.sysconfig import *; \
PYTHON_LIBDIR=`$PYTHON -c "from $sysconfig_module import *; \
print(get_config_var('LIBDIR'));"`
fi
@ -17513,8 +17547,13 @@ $as_echo "$PYTHON_LDFLAGS" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python site-packages path" >&5
$as_echo_n "checking for Python site-packages path... " >&6; }
if test -z "$PYTHON_SITE_PKG"; then
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
print(distutils.sysconfig.get_python_lib(1,0));"`
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; \
print(distutils.sysconfig.get_python_lib(1,0));"`
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SITE_PKG" >&5
$as_echo "$PYTHON_SITE_PKG" >&6; }
@ -20181,6 +20220,9 @@ fi
WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o"
$as_echo "#define __USE_MINGW_ANSI_STDIO 1" >>confdefs.h
fi
if test $ac_cv_func_getaddrinfo = no; then
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"
fi
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"
if test "$dir" != "/usr"; then
CPPFLAGS="$CPPFLAGS -I$dir/include"
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
LDFLAGS="$LDFLAGS -L$dir/lib"
fi
{ $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'`
@ -22405,7 +22453,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
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
CONFIG_FILES = $CONFIG_FILES
@ -22471,7 +22519,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
unbound config.status 1.15.0
unbound config.status 1.16.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@ -10,7 +10,7 @@ sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[15])
m4_define([VERSION_MINOR],[16])
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_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
@ -18,7 +18,7 @@ AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
LIBUNBOUND_CURRENT=9
LIBUNBOUND_REVISION=15
LIBUNBOUND_REVISION=16
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@ -101,6 +101,7 @@ LIBUNBOUND_AGE=1
# 1.13.2 had 9:13:1
# 1.14.0 had 9:14: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
# 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)
WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o"
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
if test $ac_cv_func_getaddrinfo = no; then
AC_LIBOBJ([fake-rfc2553])
@ -1878,11 +1880,17 @@ case "$enable_ipset" in
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
fi
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"
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
CPPFLAGS="$CPPFLAGS -I$dir/include"
LDFLAGS="$LDFLAGS -L$dir/lib"
fi
AC_MSG_RESULT(found in $dir)
@ -2060,7 +2068,7 @@ dnl includes
#include <ws2tcpip.h>
#endif
#ifndef USE_WINSOCK
#if !defined(USE_WINSOCK) || !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) || defined(__USE_MINGW_ANSI_STDIO)
#define ARG_LL "%ll"
#else
#define ARG_LL "%I64"

View File

@ -487,3 +487,38 @@ acl_list_get_mem(struct acl_list* acl)
if(!acl) return 0;
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);
/*
* 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 */

View File

@ -47,10 +47,12 @@
#include "services/cache/rrset.h"
#include "services/cache/dns.h"
#include "services/cache/infra.h"
#include "services/outside_network.h"
#include "util/data/msgreply.h"
#include "util/regional.h"
#include "util/net_help.h"
#include "util/data/dname.h"
#include "util/config_file.h"
#include "iterator/iterator.h"
#include "iterator/iter_delegpt.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");
}
/* 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_details(ssl, worker, dp);
if(!ssl_printf(ssl, "cache delegation was "

View File

@ -98,7 +98,7 @@
/** ratelimit for error responses */
#define ERROR_RATELIMIT 100 /* qps */
/**
/**
* seconds to add to prefetch leeway. This is a TTL that expires old rrsets
* earlier than they should in order to put the new update into the cache.
* This additional value is to make sure that if not all TTLs are equal in
@ -484,6 +484,12 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
msg->rep, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad,
worker->env.now_tv))
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,
&msg->qinfo, id, flags, edns);
if(worker->stats.extended) {
@ -553,7 +559,7 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
return 1;
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;
/* 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,
worker->env.now_tv))
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,
qinfo, id, flags, edns);
rrset_array_unlock_touch(worker->env.rrset_cache,
@ -716,15 +728,25 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
if(!*partial_repp)
goto bail_out;
}
} else if(!reply_info_answer_encode(qinfo, encode_rep, id, flags,
repinfo->c->buffer, timenow, 1, worker->scratchpad,
udpsize, edns, (int)(edns->bits & EDNS_DO), *is_secure_answer)) {
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad,
worker->env.now_tv))
edns->opt_list_inplace_cb_out = NULL;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, id, flags, edns);
} 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,
udpsize, edns, (int)(edns->bits & EDNS_DO),
*is_secure_answer)) {
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo,
NULL, NULL, LDNS_RCODE_SERVFAIL, edns, repinfo,
worker->scratchpad, worker->env.now_tv))
edns->opt_list_inplace_cb_out = NULL;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, id, flags, edns);
}
}
/* cannot send the reply right now, because blocking network syscall
* is bad while holding locks. */
@ -741,10 +763,12 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
/** Reply to client and perform prefetch to keep cache up to date. */
static void
reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
uint16_t flags, struct comm_reply* repinfo, time_t leeway, int noreply)
reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
uint16_t flags, struct comm_reply* repinfo, time_t leeway, int noreply,
int rpz_passthru, struct edns_option* opt_list)
{
/* first send answer to client to keep its latency
(void)opt_list;
/* first send answer to client to keep its latency
* as small as a cachereply */
if(!noreply) {
if(repinfo->c->tcp_req_info) {
@ -755,13 +779,23 @@ reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
comm_point_send_reply(repinfo);
}
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
* client addrs waiting, which has the cache blacklisted (to bypass
* the cache and go to the network for the data). */
/* this (potentially) runs the mesh for the new query */
mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway +
PREFETCH_EXPIRY_ADD);
mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway +
PREFETCH_EXPIRY_ADD, rpz_passthru, NULL, NULL);
}
/**
@ -1012,32 +1046,178 @@ answer_notify(struct worker* w, struct query_info* qinfo,
static int
deny_refuse(struct comm_point* c, enum acl_access acl,
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(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);
if(worker->stats.extended)
worker->stats.unwanted_queries++;
return 0;
} else if(acl == refuse) {
log_addr(VERB_ALGO, "refused query from",
&repinfo->addr, repinfo->addrlen);
log_buf(VERB_ALGO, "refuse", c->buffer);
size_t opt_rr_mark;
if(verbosity >= VERB_ALGO) {
log_acl_action("refused", &repinfo->addr,
repinfo->addrlen, acl, acladdr);
log_buf(VERB_ALGO, "refuse", c->buffer);
}
if(worker->stats.extended)
worker->stats.unwanted_queries++;
if(worker_check_request(c->buffer, worker) == -1) {
comm_point_drop_reply(repinfo);
return 0; /* discard this */
}
sldns_buffer_set_limit(c->buffer, LDNS_HEADER_SIZE);
sldns_buffer_write_at(c->buffer, 4,
(uint8_t*)"\0\0\0\0\0\0\0\0", 8);
/* worker_check_request() above guarantees that the buffer contains at
* least a header and that qdcount == 1
*/
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_RCODE_SET(sldns_buffer_begin(c->buffer),
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_flip(c->buffer);
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_set_position(c->buffer, LDNS_HEADER_SIZE);
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;
@ -1045,16 +1225,20 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
static int
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
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
@ -1067,12 +1251,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
struct lruhash_entry* e;
struct query_info qinfo;
struct edns_data edns;
struct edns_option* original_edns_list = NULL;
enum acl_access acl;
struct acl_addr* acladdr;
int rc = 0;
int need_drop = 0;
int is_expired_answer = 0;
int is_secure_answer = 0;
int rpz_passthru = 0;
/* 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
* 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,
repinfo->addrlen);
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)
goto send_reply;
@ -1338,7 +1526,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
if(worker->env.auth_zones &&
rpz_callback_from_worker_request(worker->env.auth_zones,
&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);
if(sldns_buffer_limit(c->buffer) == 0) {
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
* 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);
if(ret == 1)
@ -1383,12 +1573,17 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
* ACLs allow the snooping. */
if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) &&
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,
*(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);
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->addr, repinfo->addrlen);
goto send_reply;
}
@ -1429,6 +1624,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
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 the cache. In case we chase an intermediate CNAME chain
* 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)
leeway = 0;
lock_rw_unlock(&e->lock);
reply_and_prefetch(worker, lookup_qinfo,
sldns_buffer_read_u16_at(c->buffer, 2),
repinfo, leeway,
(partial_rep || need_drop));
(partial_rep || need_drop),
rpz_passthru,
original_edns_list);
if(!partial_rep) {
rc = 0;
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");
lock_rw_unlock(&e->lock);
}
if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) {
if(answer_norec_from_cache(worker, &qinfo,
*(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 */
mesh_new_client(worker->env.mesh, &qinfo, cinfo,
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);
worker_mem_report(worker, NULL);
return 0;
@ -1591,6 +1796,9 @@ worker_sighandler(int sig, void* arg)
case SIGHUP:
comm_base_exit(worker->base);
break;
#endif
#ifdef SIGBREAK
case SIGBREAK:
#endif
case SIGINT:
worker->need_to_exit = 1;
@ -1709,6 +1917,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
if(do_sigs) {
#ifdef SIGHUP
ub_thread_sig_unblock(SIGHUP);
#endif
#ifdef SIGBREAK
ub_thread_sig_unblock(SIGBREAK);
#endif
ub_thread_sig_unblock(SIGINT);
#ifdef SIGQUIT
@ -1726,6 +1937,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
|| !comm_signal_bind(worker->comsig, SIGQUIT)
#endif
|| !comm_signal_bind(worker->comsig, SIGTERM)
#ifdef SIGBREAK
|| !comm_signal_bind(worker->comsig, SIGBREAK)
#endif
|| !comm_signal_bind(worker->comsig, SIGINT)) {
log_err("could not create signal handlers");
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
- 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
- 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
http://unbound.net

View File

@ -1,7 +1,7 @@
#
# 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.
@ -55,6 +55,10 @@ server:
# Socket options are not supported on all platforms. experimental.
# 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: 53
@ -811,6 +815,8 @@ server:
# Add system certs to the cert bundle, from the Windows Cert Store
# tls-win-cert: no
# and on other systems, the default openssl certificates
# tls-system-cert: no
# Pad queries over TLS upstreams
# pad-queries: yes
@ -897,6 +903,14 @@ server:
# the number of servers that will be used in the fast server selection.
# 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
# --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
.\"
@ -44,7 +44,7 @@
.B ub_ctx_zone_remove,
.B ub_ctx_data_add,
.B ub_ctx_data_remove
\- Unbound DNS validating resolver 1.15.0 functions.
\- Unbound DNS validating resolver 1.16.0 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.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
.\"

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
.\"

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
.\"
@ -289,20 +289,22 @@ just the ratelimited ips, with their estimated qps. The ratelimited
ips are dropped before checking the cache.
.TP
.B list_auth_zones
List the auth zones that are configured. Printed one per line with a
status, indicating if the zone is expired and current serial number.
List the auth zones that are configured. Printed one per line with a status,
indicating if the zone is expired and current serial number. Configured RPZ
zones are included.
.TP
.B auth_zone_reload \fIzone\fR
Reload the auth zone from zonefile. The zonefile is read in overwriting
the current contents of the zone in memory. This changes the auth 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
with \fBflush_zone\fR \fIzone\fR.
Reload the auth zone (or RPZ zone) from zonefile. The zonefile is read in
overwriting the current contents of the zone in memory. This changes the auth
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 with
\fBflush_zone\fR \fIzone\fR.
.TP
.B auth_zone_transfer \fIzone\fR
Transfer the auth zone from master. The auth zone probe sequence is started,
where the masters are probed to see if they have an updated zone (with the SOA
serial check). And then the zone is transferred for a newer zone version.
Transfer the auth zone (or RPZ zone) from master. The auth zone probe sequence
is started, where the masters are probed to see if they have an updated zone
(with the SOA serial check). And then the zone is transferred for a newer zone
version.
.TP
.B rpz_enable \fIzone\fR
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
.\"

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
.\"
@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
\- Unbound DNS validating resolver 1.15.0.
\- Unbound DNS validating resolver 1.16.0.
.SH "SYNOPSIS"
.B unbound
.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
.\"
@ -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
particular socket options. Default value is no.
.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>
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
@ -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
TCP wireformat. The other server must support this (see
\fBtls\-service\-key\fR).
If you enable this, also configure a tls\-cert\-bundle or use tls\-win\-cert to
load CA certs, otherwise the connections cannot be authenticated.
This option enables TLS for all of them, but if you do not set this you can
configure TLS specifically for some forward zones with forward\-tls\-upstream. And also with stub\-tls\-upstream.
If you enable this, also configure a tls\-cert\-bundle or use tls\-win\-cert or
tls\-system\-cert to load CA certs, otherwise the connections cannot be
authenticated. This option enables TLS for all of them, but if you do not set
this you can configure TLS specifically for some forward zones with
forward\-tls\-upstream. And also with stub\-tls\-upstream.
.TP
.B ssl\-upstream: \fI<yes or no>
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.
If no cert bundle, it uses only these certificates. Default is no.
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
.B tls\-additional\-port: \fI<portnr>
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
If you need more complicated authoritative data, with referrals, wildcards,
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
\h'5'\fIdeny\fR
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.
A value from the `Reserved for Local/Experimental` range (65001-65534) should
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"
In the
.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
the server for the change to take effect.
.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.
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

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. */
static void
ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
void
subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
struct module_qstate *qstate)
{
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
* want to sent out ECS. Only add option if it is not already
* set. */
if(!(sq->subnet_sent)) {
ecs_opt_list_append(&sq->ecs_server_out,
if(!edns_opt_list_find(qstate->edns_opts_back_out,
qstate->env->cfg->client_subnet_opcode)) {
subnet_ecs_opt_list_append(&sq->ecs_server_out,
&qstate->edns_opts_back_out, qstate);
sq->subnet_sent = 1;
}
sq->subnet_sent = 1;
}
else if(sq->subnet_sent) {
else {
/* Outgoing ECS option is set, but we don't want to sent it to
* this address, remove option. */
edns_opt_list_remove(&qstate->edns_opts_back_out,
qstate->env->cfg->client_subnet_opcode);
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,
qstate->env->cfg->client_subnet_opcode);
}
sq->subnet_sent = 0;
}
return 1;
@ -227,7 +231,7 @@ subnetmod_init(struct module_env *env, int id)
env->unique_mesh = 1;
if(!edns_register_option(env->cfg->client_subnet_opcode,
env->cfg->client_subnet_always_forward /* bypass cache */,
0 /* no aggregation */, env)) {
1 /* no aggregation */, env)) {
log_err("subnetcache: could not register opcode");
ecs_whitelist_delete(sn_env->whitelist);
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;
}
static void
void
subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
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");
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);
return;
}
@ -783,7 +787,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
sq->ecs_server_out.subnet_source_mask =
qstate->env->cfg->max_client_subnet_ipv6;
/* 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,
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);
if(qstate->ext_state[id] == module_finished &&
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->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 */
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 */

View File

@ -138,10 +138,10 @@ ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
static int
ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
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];
const char *s;
const char *ds, *qs;
int dlen, plen;
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");
return -1;
}
if (dname[dlen - 1] == '.') {
dlen--;
}
for (p = env->cfg->local_zones_ipset; p; p = p->next) {
ds = NULL;
qs = NULL;
plen = strlen(p->str);
if (dlen >= plen) {
s = dname + (dlen - plen);
if (strncasecmp(p->str, s, plen) == 0) {
d = (struct packed_rrset_data*)rrset->entry.data;
ipset_add_rrset_data(ie, mnl, d, setname,
af, dname);
break;
}
ds = dname + (dlen - plen);
}
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;
ipset_add_rrset_data(ie, mnl, d, setname,
af, dname);
break;
}
}
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;
size_t i;
const char *setname;
struct ub_packed_rrset_key *rrset;
int af;
static char qname[BUFF_LEN];
int qlen;
mnl = (struct mnl_socket *)ie->mnl;
if (!mnl) {
// retry to create mnl socket
/* retry to create mnl socket */
mnl = open_mnl_socket();
if (!mnl) {
return -1;
}
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;
rrset = return_msg->rep->rrsets[i];
if (rrset->rk.type == htons(LDNS_RR_TYPE_A)) {
if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A &&
ie->v4_enabled == 1) {
af = AF_INET;
if ((ie->v4_enabled == 1)) {
setname = ie->name_v4;
}
} else {
setname = ie->name_v4;
} else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA &&
ie->v6_enabled == 1) {
af = AF_INET6;
if ((ie->v6_enabled == 1)) {
setname = ie->name_v6;
}
setname = ie->name_v6;
}
if (setname) {
if(ipset_check_zones_for_rrset(env, ie, mnl, rrset,
setname, af) == -1)
qname, qlen, setname, af) == -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 (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;
return;

View File

@ -128,7 +128,7 @@ struct delegpt_ns {
uint8_t done_pside6;
/** the TLS authentication name, (if not NULL) to use. */
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. */
int port;
};

View File

@ -743,9 +743,10 @@ iter_mark_pside_cycle_targets(struct module_qstate* qstate, struct delegpt* dp)
int
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_addr* a;
/* check:
* o RD qflag is on.
* o no addresses are provided.
@ -758,13 +759,24 @@ iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
*/
if(!(qflags&BIT_RD))
return 0;
/* either available or unused targets */
if(dp->usable_list || dp->result_list)
return 0;
/* either available or unused targets,
* 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;
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 */
if( (qinfo->qtype == LDNS_RR_TYPE_A ||
qinfo->qtype == LDNS_RR_TYPE_AAAA) &&
if( ((qinfo->qtype == LDNS_RR_TYPE_A && supports_ipv4) ||
(qinfo->qtype == LDNS_RR_TYPE_AAAA && supports_ipv6)) &&
dname_subdomain_c(qinfo->qname, dp->name) &&
delegpt_find_ns(dp, qinfo->qname, qinfo->qname_len))
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 qflags: query flags with RD flag
* @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.
*/
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

View File

@ -1547,7 +1547,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
* same server reply) if useless-checked.
*/
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
iq->dp)) {
iq->dp, ie->supports_ipv4, ie->supports_ipv6)) {
struct delegpt* retdp = NULL;
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) {
if(retdp) {
@ -1831,6 +1831,23 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
int missing;
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)
return 0;
if(iq->depth > 0 && iq->target_count &&
@ -1850,20 +1867,6 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
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 */
log_assert(toget <= missing);
@ -2512,7 +2515,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
iq->response = forged_response;
next_state(iq, FINISHED_STATE);
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 0;
@ -2832,7 +2835,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
}
if(!qstate->no_cache_store)
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,
qstate->region, qstate->query_flags);
/* close down outstanding requests to be discarded */
@ -3067,7 +3072,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iq->response = forged_response;
next_state(iq, FINISHED_STATE);
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);
}
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 */
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);
return UB_NOMEM;
}
@ -730,7 +730,7 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
if(async_id)
*async_id = q->querynum;
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);
return UB_NOMEM;
}
@ -867,7 +867,7 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
q->w = w;
/* process new query */
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);
}
free(qinfo.qname);

View File

@ -833,8 +833,11 @@ static int
respip_use_rpz(struct resp_addr* raddr, struct rpz* r,
enum respip_action* action,
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) {
*is_rpz = 0;
return 1;
@ -848,6 +851,9 @@ respip_use_rpz(struct resp_addr* raddr, struct rpz* r,
*data = r->cname_override;
*rpz_cname_override = 1;
}
if(*action == respip_always_transparent /* RPZ_PASSTHRU_ACTION */
&& rpz_passthru)
*rpz_passthru = 1;
*rpz_log = r->log;
if(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,
struct reply_info** new_repp, struct respip_action_info* actinfo,
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;
size_t ctaglen;
@ -934,7 +940,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
ipset->tagname, ipset->num_tags);
}
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);
r = a->rpz;
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))) {
if(!respip_use_rpz(raddr, r, &action, &data,
&rpz_log, &log_name, &rpz_cname_override,
region, &rpz_used)) {
region, &rpz_used, rpz_passthru)) {
log_err("out of memory");
lock_rw_unlock(&raddr->lock);
lock_rw_unlock(&a->lock);
@ -964,7 +970,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
addr_to_str(&raddr->node.addr,
raddr->node.addrlen,
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
* 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,
qstate->client_info, qstate->return_msg->rep,
&new_rep, &actinfo, &alias_rrset, 0,
qstate->region, qstate->env->auth_zones)) {
qstate->region, qstate->env->auth_zones,
&qstate->rpz_passthru)) {
goto servfail;
}
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. */
if(!respip_rewrite_reply(qinfo, cinfo, tgt_rep, &tmp_rep, &actinfo,
&alias_rrset, 1, region, az))
&alias_rrset, 1, region, az, NULL))
return 0;
if(actinfo.action != respip_none) {
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));
if(respip_actinfo->rpz_log) {
txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen, "%s",
"RPZ applied ");
"rpz: applied ");
if(respip_actinfo->rpz_cname_override)
actionstr = rpz_action_to_string(
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.
* @param az: auth zones containing RPZ information.
* @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.
*/
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,
struct respip_action_info* actinfo,
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.

View File

@ -132,6 +132,7 @@ msg_create(struct regional* region, struct query_info* qinfo)
return NULL;
msg->rep->flags = (uint16_t)(BIT_QR | BIT_AA);
msg->rep->authoritative = 1;
msg->rep->reason_bogus = LDNS_EDE_NONE;
msg->rep->qdcount = 1;
/* rrsets is NULL, no rrsets yet */
return msg;
@ -1882,6 +1883,8 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
struct regional* region = NULL;
struct sldns_buffer* buf = NULL;
uint32_t soa_serial = 0;
char* unsupported_reason = NULL;
int only_unsupported = 1;
region = env->scratch;
regional_free_all(region);
buf = env->scratch_buffer;
@ -1911,6 +1914,7 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
&hashalgo, &hash, &hashlen)) {
/* malformed RR */
*reason = "ZONEMD rdata malformed";
only_unsupported = 0;
continue;
}
/* check for duplicates */
@ -1920,25 +1924,51 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
* is not allowed. */
*reason = "ZONEMD RRSet contains more than one RR "
"with the same scheme and hash algorithm";
only_unsupported = 0;
continue;
}
regional_free_all(region);
if(serial != soa_serial) {
*reason = "ZONEMD serial is wrong";
only_unsupported = 0;
continue;
}
*reason = NULL;
if(auth_zone_generate_zonemd_check(z, scheme, hashalgo,
hash, hashlen, region, buf, reason)) {
/* success */
if(*reason) {
if(!unsupported_reason)
unsupported_reason = *reason;
/* continue to check for valid ZONEMD */
if(verbosity >= VERB_ALGO) {
char zstr[255+1];
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);
verbose(VERB_ALGO, "auth-zone %s ZONEMD hash is correct", zstr);
if(!*reason)
verbose(VERB_ALGO, "auth-zone %s ZONEMD hash is correct", zstr);
}
return 1;
}
only_unsupported = 0;
/* 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 */
if(!*reason)
*reason = "no ZONEMD records found";
@ -4456,7 +4486,7 @@ chunkline_get_line_collated(struct auth_chunk** chunk, size_t* chunk_pos,
return 1;
}
/** process $ORIGIN for http */
/** process $ORIGIN for http, 0 nothing, 1 done, 2 error */
static int
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);
s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8),
pstate->origin, &pstate->origin_len);
if(s) pstate->origin_len = 0;
if(s) {
pstate->origin_len = 0;
return 2;
}
return 1;
}
return 0;
}
/** process $TTL for http */
/** process $TTL for http, 0 nothing, 1 done, 2 error */
static int
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 &&
isspace((unsigned char)line[4])) {
const char* end = NULL;
int overflow = 0;
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 0;
@ -4493,15 +4530,20 @@ static int
chunkline_non_comment_RR(struct auth_chunk** chunk, size_t* chunk_pos,
sldns_buffer* buf, struct sldns_file_parse_state* pstate)
{
int ret;
while(chunkline_get_line_collated(chunk, chunk_pos, buf)) {
if(chunkline_is_comment_line_or_empty(buf)) {
/* a comment, go to next line */
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 */
}
if(http_parse_ttl(buf, pstate)) {
if((ret=http_parse_ttl(buf, pstate))!=0) {
if(ret == 2)
return 0;
continue; /* $TTL has been handled */
}
return 1;
@ -5007,6 +5049,7 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z,
struct sldns_file_parse_state pstate;
struct auth_chunk* chunk;
size_t chunk_pos;
int ret;
memset(&pstate, 0, sizeof(pstate));
pstate.default_ttl = 3600;
if(xfr->namelen < sizeof(pstate.origin)) {
@ -5063,10 +5106,24 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z,
continue;
}
/* 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 */
}
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 */
}
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 */
lock_basic_unlock(&xfr->lock);
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);
log_err("out of memory lookup up master %s", master->host);
return 0;
@ -6561,7 +6618,7 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
* called straight away */
lock_basic_unlock(&xfr->lock);
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);
log_err("out of memory lookup up master %s", master->host);
return 0;
@ -7632,13 +7689,16 @@ int auth_zone_generate_zonemd_check(struct auth_zone* z, int scheme,
{
uint8_t gen[512];
size_t genlen = 0;
*reason = NULL;
if(!zonemd_hashalgo_supported(hashalgo)) {
/* allow it */
*reason = "unsupported algorithm";
return 0;
return 1;
}
if(!zonemd_scheme_supported(scheme)) {
/* allow it */
*reason = "unsupported scheme";
return 0;
return 1;
}
if(hashlen < 12) {
/* 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,
"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);
if(sec == sec_status_secure) {
return 1;
@ -8003,9 +8063,13 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
}
/* 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) {
*result = strdup("ZONEMD verification successful");
if(reason)
*result = strdup(reason);
else *result = strdup("ZONEMD verification successful");
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,
"zonemd: verify DNSKEY RRset with trust anchor");
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);
if(sec == sec_status_secure) {
/* 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.rrset_class = htons(z->dclass);
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,
why_bogus, NULL);
why_bogus, NULL, NULL);
regional_free_all(env->scratch);
if(sec == sec_status_secure) {
/* success */
@ -8340,7 +8405,7 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env)
/* the callback can be called straight away */
lock_rw_unlock(&z->lock);
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);
log_err("out of memory lookup of %s for zonemd",
(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 buf: temp buffer during canonicalisation.
* @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.
*/
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 */
msg->rep->flags = BIT_QR; /* with QR, no AA */
msg->rep->qdcount = 1;
msg->rep->reason_bogus = LDNS_EDE_NONE;
msg->rep->rrsets = (struct ub_packed_rrset_key**)
regional_alloc(region,
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));
if(!msg->rep)
return NULL;
msg->rep->reason_bogus = LDNS_EDE_NONE;
if(num > RR_COUNT_MAX)
return NULL; /* integer overflow protection */
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->rrset_count = r->rrset_count;
msg->rep->authoritative = r->authoritative;
msg->rep->reason_bogus = r->reason_bogus;
if(!rrset_array_lock(r->ref, r->rrset_count, now_control)) {
return NULL;
}
@ -632,6 +635,7 @@ rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
msg->rep->ns_numrrsets = 0;
msg->rep->ar_numrrsets = 0;
msg->rep->rrset_count = 1;
msg->rep->reason_bogus = LDNS_EDE_NONE;
msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now);
if(!msg->rep->rrsets[0]) /* copy CNAME */
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->ar_numrrsets = 0;
msg->rep->rrset_count = 1;
msg->rep->reason_bogus = LDNS_EDE_NONE;
msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now);
if(!msg->rep->rrsets[0]) /* copy DNAME */
return NULL;

View File

@ -47,6 +47,7 @@
#ifdef USE_TCP_FASTOPEN
#include <netinet/tcp.h>
#endif
#include <ctype.h>
#include "services/listen_dnsport.h"
#include "services/outside_network.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.
* If enabled, then ifname must be the wildcard name.
* @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 port: Port number to use (as string).
* @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) {
struct comm_point* cp = NULL;
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,
front->udp_buff, cb, cb_arg, ports->socket);
else if(ports->ftype == listen_type_tcp ||
ports->ftype == listen_type_tcp_dnscrypt)
} else if(ports->ftype == listen_type_tcp ||
ports->ftype == listen_type_tcp_dnscrypt) {
cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, tcp_idle_timeout,
harden_large_queries, 0, NULL,
tcp_conn_limit, bufsize, front->udp_buff,
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) {
cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, tcp_idle_timeout,
@ -1410,15 +1411,22 @@ listen_create(struct comm_base* base, struct listen_port* ports,
#endif
}
} 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,
front->udp_buff, cb, cb_arg, ports->socket);
}
if(!cp) {
log_err("can't create commpoint");
listen_delete(front);
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;
else
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. */
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) {
hints.ai_family = AF_INET6;
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
local_error_encode(struct query_info* qinfo, struct module_env* env,
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->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,
rcode, edns, repinfo, temp, env->now_tv))
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),
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;
local_error_encode(qinfo, env, edns, repinfo,
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;
}
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
|| lz_type == local_zone_always_refuse) {
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;
} else if(lz_type == local_zone_static ||
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)
return local_encode(qinfo, env, edns, repinfo, buf, temp,
z->soa_negative, 0, rcode);
local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode,
(rcode|BIT_AA));
local_error_encode(qinfo, env, edns, repinfo, buf, temp,
rcode, (rcode|BIT_AA), LDNS_EDE_NONE, NULL);
return 1;
} else if(lz_type == local_zone_typetransparent
|| 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,
&lrr, 1, LDNS_RCODE_NOERROR);
} else {
/* NODATA: No EDE needed */
local_error_encode(qinfo, env, edns, repinfo, buf,
temp, LDNS_RCODE_NOERROR,
(LDNS_RCODE_NOERROR|BIT_AA));
(LDNS_RCODE_NOERROR|BIT_AA), -1, NULL);
}
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)
return local_encode(qinfo, env, edns, repinfo, buf, temp,
z->soa_negative, 0, rcode);
/* NODATA: No EDE needed */
local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode,
(rcode|BIT_AA));
(rcode|BIT_AA), LDNS_EDE_NONE, NULL);
return 1;
}

View File

@ -64,6 +64,11 @@
#include "respip/respip.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 */
static void
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,
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;
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)
mesh_state_make_unique(s);
s->s.rpz_passthru = rpz_passthru;
/* copy the edns options we got from the front */
if(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
mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
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;
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)
mesh_state_make_unique(s);
s->s.rpz_passthru = rpz_passthru;
if(edns->opt_list_in) {
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in,
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
* will not be run recursively on top of the current state. */
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,
qflags&(BIT_RD|BIT_CD), 0, 0);
@ -732,15 +741,16 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
/* 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_list_insert(s, &mesh->forever_first,
&mesh->forever_last);
s->list_select = mesh_forever_list;
} else {
mesh_list_insert(s, &mesh->jostle_first,
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
@ -756,10 +766,114 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
mesh_run(mesh, s, module_event_new, NULL);
}
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, time_t leeway)
#ifdef CLIENT_SUBNET
/* 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,
@ -1234,7 +1348,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
(rep->security <= sec_status_bogus ||
rep->security == sec_status_secure_sentinel_fail)) {
rcode = LDNS_RCODE_SERVFAIL;
if(m->s.env->cfg->stat_extended)
if(m->s.env->cfg->stat_extended)
m->s.env->mesh->ans_bogus++;
}
if(rep && rep->security == sec_status_secure)
@ -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.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,
r->qflags, &r->edns);
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,
rep, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region, &r->start_time))
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,
&m->s.qinfo, r->qid, r->qflags, &r->edns);
}
@ -1524,7 +1670,7 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
struct comm_reply* rep, uint16_t qid, uint16_t qflags,
const struct query_info* qinfo)
{
struct mesh_reply* r = regional_alloc(s->s.region,
struct mesh_reply* r = regional_alloc(s->s.region,
sizeof(struct mesh_reply));
if(!r)
return 0;
@ -1693,6 +1839,7 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
if(mstate->s.curmod == 0) {
struct query_info* qinfo = NULL;
uint16_t qflags;
int rpz_p = 0;
mesh_query_done(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
* a prefetch after removing the current state, so
* 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);
rpz_p = mstate->s.rpz_passthru;
}
mesh_state_delete(&mstate->s);
if(qinfo) {
mesh_schedule_prefetch(mesh, qinfo, qflags,
0, 1);
0, 1, rpz_p);
}
return 0;
}
@ -1917,7 +2066,7 @@ apply_respip_action(struct module_qstate* qstate,
return 1;
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;
/* 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;
if(r->query_reply.c->tcp_req_info)
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 rep: where to reply to.
* @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,
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
@ -314,11 +317,13 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
* @param qid: query id to reply with.
* @param cb: callback function.
* @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.
*/
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 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.
@ -328,9 +333,15 @@ int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
* @param qinfo: query from client.
* @param qflags: flags from client query.
* @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,
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.

View File

@ -1994,6 +1994,9 @@ static int udp_connect_needs_log(int err)
# endif
# ifdef ENETDOWN
case ENETDOWN:
# endif
# ifdef EADDRNOTAVAIL
case EADDRNOTAVAIL:
# endif
case EPERM:
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);
log_assert(node && node != RBTREE_NULL); /* tree not empty */
/* 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;
count += tree_by_id_get_id(node);
/* perhaps select is between nodes */

View File

@ -526,13 +526,13 @@ rpz_create(struct config_auth* p)
size_t nmlen = sizeof(nm);
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");
goto err;
}
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);
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 */
}
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));
free(dname);
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) {
char str[255+1];
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));
return 0;
}
@ -1560,7 +1560,9 @@ rpz_local_encode(struct module_env* env, struct query_info* qinfo,
}
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;
while( cursor != NULL) {
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;
case RPZ_PASSTHRU_ACTION:
ret = NULL;
ms->rpz_passthru = 1;
break;
default:
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;
case RPZ_PASSTHRU_ACTION:
ret = NULL;
ms->rpz_passthru = 1;
break;
default:
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 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; }
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;
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; }
az = ms->env->auth_zones;
@ -2253,6 +2267,7 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
break;
case RPZ_PASSTHRU_ACTION:
ret = NULL;
ms->rpz_passthru = 1;
break;
default:
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,
sldns_buffer* buf, struct regional* temp,
/* 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;
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);
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 &&
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,
struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
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 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;
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(a) {
lock_rw_unlock(&a->lock);
@ -2357,6 +2376,10 @@ rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
} else {
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) {
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 taglen: length of taglist.
* @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
*/
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 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.

View File

@ -209,11 +209,13 @@ sldns_hexdigit_to_int(char ch)
}
uint32_t
sldns_str2period(const char *nptr, const char **endptr)
sldns_str2period(const char *nptr, const char **endptr, int* overflow)
{
int sign = 0;
uint32_t i = 0;
uint32_t seconds = 0;
const uint32_t maxint = 0xffffffff;
*overflow = 0;
for(*endptr = nptr; **endptr; (*endptr)++) {
switch (**endptr) {
@ -236,26 +238,46 @@ sldns_str2period(const char *nptr, const char **endptr)
break;
case 's':
case 'S':
if(seconds > maxint-i) {
*overflow = 1;
return 0;
}
seconds += i;
i = 0;
break;
case 'm':
case 'M':
if(i > maxint/60 || seconds > maxint-(i*60)) {
*overflow = 1;
return 0;
}
seconds += i * 60;
i = 0;
break;
case 'h':
case 'H':
if(i > maxint/(60*60) || seconds > maxint-(i*60*60)) {
*overflow = 1;
return 0;
}
seconds += i * 60 * 60;
i = 0;
break;
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;
i = 0;
break;
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;
i = 0;
break;
@ -269,15 +291,27 @@ sldns_str2period(const char *nptr, const char **endptr)
case '7':
case '8':
case '9':
if(i > maxint/10 || i*10 > maxint - (**endptr - '0')) {
*overflow = 1;
return 0;
}
i *= 10;
i += (**endptr - '0');
break;
default:
if(seconds > maxint-i) {
*overflow = 1;
return 0;
}
seconds += i;
/* disregard signedness */
return seconds;
}
}
if(seconds > maxint-i) {
*overflow = 1;
return 0;
}
seconds += i;
/* disregard signedness */
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.
* \param[in] nptr the start of the string
* \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
*/
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

View File

@ -97,18 +97,22 @@ extern "C" {
#define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+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 */
#define LDNS_ANCOUNT_OFF 6
#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 */
#define LDNS_NSCOUNT_OFF 8
#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 */
#define LDNS_ARCOUNT_OFF 10
#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

View File

@ -435,10 +435,42 @@ enum sldns_enum_edns_option
LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */
LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/
LDNS_EDNS_PADDING = 12, /* RFC7830 */
LDNS_EDNS_EDE = 15, /* RFC8914 */
LDNS_EDNS_CLIENT_TAG = 16 /* draft-bellis-dnsop-edns-tags-01 */
};
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
/** 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)
{
const char* endptr;
int overflow;
if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) {
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL,
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])) {
*not_there = 1;
@ -373,7 +378,8 @@ rrinternal_get_quoted(sldns_buffer* strbuf, const char** delimiters,
/* skip spaces */
while(sldns_buffer_remaining(strbuf) > 0 &&
*(sldns_buffer_current(strbuf)) == ' ') {
(*(sldns_buffer_current(strbuf)) == ' ' ||
*(sldns_buffer_current(strbuf)) == '\t')) {
sldns_buffer_skip(strbuf, 1);
}
@ -606,7 +612,7 @@ sldns_affix_token(sldns_buffer* strbuf, char* token, size_t* token_len,
/* add space */
/* when addlen < 2, the token buffer is full considering the NULL byte
* from strlen and will lead to buffer overflow with the second
* assignement below. */
* assignment below. */
if(addlen < 2) return 0;
token[*token_strlen] = ' ';
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);
/* 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
* or as a secondary, we default to secondary behavior and we ignore the
* sematic errors. */
* 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 */
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;
if((status=rrinternal_parse_unknown(strbuf, token,
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;
} else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) {
const char* end = NULL;
int overflow = 0;
strlcpy((char*)rr, line, *len);
*len = 0;
*dname_len = 0;
if(!parse_state) return LDNS_WIREPARSE_ERR_OK;
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) {
strlcpy((char*)rr, line, *len);
*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))
return SVCB_KEY_MANDATORY;
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;
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);
/* 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
* or as a secondary, we default to secondary behavior and we ignore the
* semantic errors. */
@ -1588,12 +1598,12 @@ static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_
if (*val_in == '"') {
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)) {
val_out++;
}
} 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)) {
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)
{
const char* end;
uint32_t p = sldns_str2period(str, &end);
int overflow;
uint32_t p = sldns_str2period(str, &end, &overflow);
if(*end != 0)
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)
return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
sldns_write_uint32(rd, p);

View File

@ -194,6 +194,7 @@ static sldns_lookup_table sldns_edns_options_data[] = {
{ 8, "edns-client-subnet" },
{ 11, "edns-tcp-keepalive"},
{ 12, "Padding" },
{ 15, "EDE"},
{ 0, NULL}
};
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 */
static void
aclchecks(struct config_file* cfg)
@ -608,6 +630,7 @@ morechecks(struct config_file* cfg)
warn_hosts("stub-host", cfg->stubs);
warn_hosts("forward-host", cfg->forwards);
interfacechecks(cfg);
ifautomaticportschecks(cfg->if_automatic_ports);
aclchecks(cfg);
tcpconnlimitchecks(cfg);

View File

@ -155,9 +155,9 @@ usage(void)
printf(" ratelimit_list [+a] list ratelimited domains\n");
printf(" ip_ratelimit_list [+a] list ratelimited ip addresses\n");
printf(" +a list all, also not ratelimited\n");
printf(" list_auth_zones list auth zones\n");
printf(" auth_zone_reload zone reload auth zone from zonefile\n");
printf(" auth_zone_transfer zone transfer auth zone from master\n");
printf(" list_auth_zones list auth zones (includes RPZ zones)\n");
printf(" auth_zone_reload zone reload auth zone (or RPZ zone) from zonefile\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_data view list local-data RRs 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 */
/** 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
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));
}
/* print the stats */
do_stats_shm(cfg, stats, shm_stat);
if(!quiet) {
/* print the stats */
do_stats_shm(cfg, stats, shm_stat);
}
/* shutdown */
shmdt(shm_stat);
@ -499,7 +502,7 @@ static void ssl_path_err(const char* s, const char *path)
{
unsigned long err;
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",
s, path, ERR_reason_error_string(err));
exit(1);
@ -541,11 +544,11 @@ setup_ctx(struct config_file* cfg)
#endif
if(!SSL_CTX_use_certificate_chain_file(ctx,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);
if (!SSL_CTX_check_private_key(ctx))
if(!SSL_CTX_check_private_key(ctx))
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",
s_cert);
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) {
printf("%s", buf);
was_error = 1;
} else if (!quiet)
} else if(!quiet) {
printf("%s", buf);
}
first_line = 0;
}
@ -987,7 +991,7 @@ int main(int argc, char* argv[])
#endif
}
if(argc >= 1 && strcmp(argv[0], "stats_shm")==0) {
print_stats_shm(cfgfile);
print_stats_shm(cfgfile, quiet);
return 0;
}
check_args_for_listcmd(argc, argv);

View File

@ -221,10 +221,10 @@ static void zonemd_check_test(void)
unit_assert(result && reason == NULL);
result = auth_zone_generate_zonemd_check(z, 241, hashalgo,
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,
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,
hash, 2, region, buf, &reason);
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
minimal-responses: no
nsid: "ascii_hopsa kidee"
ede: yes
stub-zone:
name: "."
@ -157,7 +158,7 @@ ENTRY_END
; recursion happens here.
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
MATCH all ede=9
REPLY QR RD RA DO SERVFAIL
SECTION QUESTION
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->do_daemonize = 1;
cfg->if_automatic = 0;
cfg->if_automatic_ports = NULL;
cfg->so_rcvbuf = 0;
cfg->so_sndbuf = 0;
cfg->so_reuseport = REUSEPORT_DEFAULT;
@ -267,6 +268,7 @@ config_create(void)
cfg->serve_expired_ttl_reset = 0;
cfg->serve_expired_reply_ttl = 30;
cfg->serve_expired_client_timeout = 0;
cfg->ede_serve_expired = 0;
cfg->serve_original_ttl = 0;
cfg->zonemd_permissive_mode = 0;
cfg->add_holddown = 30*24*3600;
@ -375,6 +377,7 @@ config_create(void)
cfg->ipset_name_v4 = NULL;
cfg->ipset_name_v6 = NULL;
#endif
cfg->ede = 0;
return cfg;
error_exit:
config_delete(cfg);
@ -476,7 +479,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else if(atoi(val) == 0)
return 0;
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 */
return 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("tls-cert-bundle:", tls_cert_bundle)
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-tls-port:", 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-notls-downstream:", http_notls_downstream)
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("do-daemonize:", do_daemonize)
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)
{ 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_YNO("ede:", ede)
else S_YNO("ede-serve-expired:", ede_serve_expired)
else S_YNO("serve-original-ttl:", serve_original_ttl)
else S_STR("val-nsec3-keysize-iterations:", val_nsec3_key_iterations)
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, "outgoing-interface", num_out_ifs, out_ifs)
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, "outgoing-range", outgoing_num_ports)
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, "tls-cert-bundle", tls_cert_bundle)
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-tls-port", 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_DEC(opt, "serve-expired-reply-ttl", serve_expired_reply_ttl)
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_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations)
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->logfile);
free(cfg->pidfile);
free(cfg->if_automatic_ports);
free(cfg->target_fetch_policy);
free(cfg->ssl_service_key);
free(cfg->ssl_service_pem);
@ -2482,7 +2494,7 @@ char* cfg_ptr_reverse(char* str)
while(*ip_end && isspace((unsigned char)*ip_end))
ip_end++;
if(name>ip_end) {
snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%.*s",
snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%.*s",
(int)(name-ip_end), ip_end);
}
snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), " PTR %s", name);
@ -2553,126 +2565,6 @@ void w_config_adjust_directory(struct config_file* cfg)
}
#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)
{
if(!cfg->remote_control_enable) return 0;

View File

@ -41,6 +41,7 @@
#ifndef UTIL_CONFIG_FILE_H
#define UTIL_CONFIG_FILE_H
#include "sldns/rrdef.h"
struct config_stub;
struct config_auth;
struct config_view;
@ -205,6 +206,8 @@ struct config_file {
/** automatic interface for incoming messages. Uses ipv6 remapping,
* and recvmsg/sendmsg ancillary data to detect interfaces, boolean */
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 */
size_t so_rcvbuf;
/** 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
* timeout (in milliseconds) is reached */
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 */
int serve_original_ttl;
/** nsec3 maximum iterations per key size, string */
@ -677,6 +682,8 @@ struct config_file {
char* ipset_name_v4;
char* ipset_name_v6;
#endif
/** respond with Extended DNS Errors (RFC8914) */
int ede;
};
/** 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);
/**
* 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
*/

View File

@ -252,6 +252,7 @@ tls-port{COLON} { YDVAR(1, VAR_SSL_PORT) }
ssl-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-system-cert{COLON} { YDVAR(1, VAR_TLS_WIN_CERT) }
additional-ssl-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) }
@ -273,6 +274,7 @@ interface{COLON} { YDVAR(1, VAR_INTERFACE) }
ip-address{COLON} { YDVAR(1, VAR_INTERFACE) }
outgoing-interface{COLON} { YDVAR(1, VAR_OUTGOING_INTERFACE) }
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-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) }
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-reply-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_REPLY_TTL) }
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) }
fake-dsa{COLON} { YDVAR(1, VAR_FAKE_DSA) }
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-opcode{COLON} { YDVAR(1, VAR_EDNS_CLIENT_STRING_OPCODE) }
nsid{COLON} { YDVAR(1, VAR_NSID ) }
ede{COLON} { YDVAR(1, VAR_EDE ) }
<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
/* 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_VIEW_FIRST VAR_SERVE_EXPIRED VAR_SERVE_EXPIRED_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_HIDE_HTTP_USER_AGENT VAR_HTTP_USER_AGENT
%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_EDNS_CLIENT_STRING_OPCODE VAR_NSID
%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 ;
@ -292,7 +293,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_serve_expired |
server_serve_expired_ttl | server_serve_expired_ttl_reset |
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_response_ip_tag | server_response_ip | server_response_ip_data |
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_edns_client_string_opcode | server_nsid |
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
@ -800,6 +802,13 @@ server_interface_automatic: VAR_INTERFACE_AUTOMATIC STRING_ARG
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
{
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);
}
;
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
{
OUTYY(("P(server_serve_original_ttl:%s)\n", $2));
@ -2167,7 +2185,7 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
&& strcmp($3, "noview")!=0
&& strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0
&& strcmp($3, "inform_redirect") != 0
&& strcmp($3, "ipset") != 0) {
&& strcmp($3, "ipset") != 0) {
yyerror("local-zone type: expected static, deny, "
"refuse, redirect, transparent, "
"typetransparent, inform, inform_deny, "
@ -2184,6 +2202,16 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
free($3);
#ifdef USE_IPSET
} 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->
local_zones_ipset, $2))
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]");
else cfg_parser->cfg->edns_client_string_opcode = atoi($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
@ -2982,6 +3018,16 @@ view_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
free($3);
#ifdef USE_IPSET
} 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->
local_zones_ipset, $2))
fatal_exit("out of memory adding local-zone");

View File

@ -1157,7 +1157,7 @@ skip_pkt_rr(sldns_buffer* pkt)
}
/** skip RRs from packet */
static int
int
skip_pkt_rrs(sldns_buffer* pkt, int num)
{
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,
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.
* @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->rrset_count = total;
rep->security = sec;
rep->reason_bogus = LDNS_EDE_NONE;
rep->authoritative = 0;
/* array starts after the refs */
if(region)
@ -989,6 +990,36 @@ parse_reply_in_temp_region(sldns_buffer* pkt, struct regional* region,
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,
uint8_t* data, struct regional* region)
{

View File

@ -43,6 +43,7 @@
#define UTIL_DATA_MSGREPLY_H
#include "util/storage/lruhash.h"
#include "util/data/packed_rrset.h"
#include "sldns/rrdef.h"
struct sldns_buffer;
struct comm_reply;
struct alloc_cache;
@ -167,6 +168,11 @@ struct reply_info {
*/
enum sec_status security;
/**
* EDE (rfc8914) code with reason for DNSSEC bogus status.
*/
sldns_ede_code reason_bogus;
/**
* Number of RRsets in each section.
* The answer section. Add up the RRs in every RRset to calculate
@ -528,7 +534,38 @@ void log_query_info(enum verbosity_value v, const char* str,
* @return false on failure.
*/
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.

View File

@ -40,6 +40,10 @@
#include "config.h"
#include "util/module.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*
strextstate(enum module_ext_state s)
@ -71,6 +75,144 @@ strmodulevent(enum module_ev e)
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
edns_known_options_init(struct module_env* env)
{

View File

@ -187,6 +187,15 @@ struct respip_addr_info;
/** Maximum number of known edns options */
#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 {
/* Inplace callbacks for when a resolved reply is ready to be sent to the
* front.*/
@ -624,8 +633,7 @@ struct module_qstate {
/** region for this query. Cleared when query process finishes. */
struct regional* region;
/** failure reason information if val-log-level is high */
struct config_strlist* errinf;
struct errinf_strlist* errinf;
/** which module is executing */
int curmod;
/** module states */
@ -667,6 +675,8 @@ struct module_qstate {
/** Extended result of response-ip action processing, mainly
* for logging purposes. */
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 */
int is_drop;
@ -759,6 +769,65 @@ const char* strextstate(enum module_ext_state s);
*/
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.
* @param env: the module environment.

View File

@ -1271,7 +1271,13 @@ void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert)
}
}
#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
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)
return 0; /* only squelch on low verbosity */
/* this is very specific, we could filter on ERR_GET_REASON()
* (the third element in ERR_PACK) */
if(err == ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GET_RECORD, SSL_R_HTTPS_PROXY_REQUEST) ||
err == ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GET_RECORD, SSL_R_HTTP_REQUEST) ||
err == ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER) ||
err == ERR_PACK(ERR_LIB_SSL, SSL_F_SSL3_READ_BYTES, SSL_R_SSLV3_ALERT_BAD_CERTIFICATE)
if(ERR_GET_LIB(err) == ERR_LIB_SSL &&
(ERR_GET_REASON(err) == SSL_R_HTTPS_PROXY_REQUEST ||
ERR_GET_REASON(err) == SSL_R_HTTP_REQUEST ||
ERR_GET_REASON(err) == SSL_R_WRONG_VERSION_NUMBER ||
ERR_GET_REASON(err) == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE
#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
#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 == ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_R_UNSUPPORTED_PROTOCOL)
|| ERR_GET_REASON(err) == SSL_R_UNKNOWN_PROTOCOL
|| ERR_GET_REASON(err) == SSL_R_UNSUPPORTED_PROTOCOL
# 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
)
))
return 1;
return 0;
}
@ -1278,6 +1277,12 @@ ssl_handshake(struct comm_point* c)
if(errno == ECONNRESET && verbosity < 2)
return 0; /* silence reset by peer */
#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)
log_err("SSL_handshake syscall: %s",
strerror(errno));
@ -2480,7 +2485,7 @@ http_nonchunk_segment(struct comm_point* c)
remainbufferlen = sldns_buffer_capacity(c->buffer) -
sldns_buffer_limit(c->buffer);
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);
sldns_buffer_clear(c->buffer);
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
llvalue = (unsigned long long)tp;
#endif
#ifndef USE_WINSOCK
snprintf(tempf, sizeof(tempf), "%s.%d-%d-%llx", fname, (int)getpid(),
snprintf(tempf, sizeof(tempf), "%s.%d-%d-" ARG_LL "x", fname, (int)getpid(),
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 */
verbose(VERB_ALGO, "autotrust: write to disk: %s", tempf);
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;
enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, rrset,
tp->ds_rrset, tp->dnskey_rrset, downprot?sigalg:NULL, &reason,
qstate);
NULL, qstate);
/* sigalg is ignored, it returns algorithms signalled to exist, but
* in 5011 there are no other rrsets to check. if downprot is
* 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
* revoked it can be removed. */
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);
}
@ -2397,7 +2392,7 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp)
qinfo.qclass);
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");
}
}

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) {
/* on malloc failure there is simply no reason string */
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);
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;
}
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*
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;
}
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 */
static int
key_entry_setup(struct regional* region,
@ -286,6 +303,7 @@ key_entry_create_null(struct regional* region,
d->ttl = now + ttl;
d->isbad = 0;
d->reason = NULL;
d->reason_bogus = LDNS_EDE_NONE;
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
d->rrset_data = NULL;
d->algo = NULL;
@ -306,6 +324,7 @@ key_entry_create_rrset(struct regional* region,
d->ttl = rd->ttl + now;
d->isbad = 0;
d->reason = NULL;
d->reason_bogus = LDNS_EDE_NONE;
d->rrset_type = ntohs(rrset->rk.type);
d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region,
rd, packed_rrset_sizeof(rd));
@ -332,6 +351,7 @@ key_entry_create_bad(struct regional* region,
d->ttl = now + ttl;
d->isbad = 1;
d->reason = NULL;
d->reason_bogus = LDNS_EDE_NONE;
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
d->rrset_data = NULL;
d->algo = NULL;

View File

@ -45,6 +45,7 @@ struct packed_rrset_data;
struct regional;
struct ub_packed_rrset_key;
#include "util/storage/lruhash.h"
#include "sldns/rrdef.h"
/**
* A key entry for the validator.
@ -80,6 +81,8 @@ struct key_entry_data {
struct packed_rrset_data* rrset_data;
/** not NULL sometimes to give reason why bogus */
char* reason;
/** not NULL to give reason why bogus */
sldns_ede_code reason_bogus;
/** list of algorithms signalled, ends with 0, or NULL */
uint8_t* algo;
/** 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);
/**
* 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.
* @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);
/**
* 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.
* @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)
return 1;
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) {
rrset_update_sec_status(env->rrset_cache, nsec, *env->now);
return 1;

View File

@ -1289,7 +1289,8 @@ nsec3_prove_wildcard(struct module_env* env, struct val_env* ve,
static int
list_is_secure(struct module_env* env, struct val_env* ve,
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;
size_t i;
@ -1303,7 +1304,7 @@ list_is_secure(struct module_env* env, struct val_env* ve,
if(d->security == sec_status_secure)
continue;
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) {
verbose(VERB_ALGO, "NSEC3 did not verify");
return 0;
@ -1317,7 +1318,7 @@ enum sec_status
nsec3_prove_nods(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key** list, size_t num,
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;
struct nsec3_filter flt;
@ -1330,8 +1331,10 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
*reason = "no valid NSEC3s";
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 */
}
rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */
filter_init(&flt, list, num, qinfo); /* init RR iterator */
if(!flt.zone) {

View File

@ -68,6 +68,7 @@
#define VALIDATOR_VAL_NSEC3_H
#include "util/rbtree.h"
#include "util/data/packed_rrset.h"
#include "sldns/rrdef.h"
struct val_env;
struct regional;
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 kkey: key entry that signed the NSEC3s.
* @param reason: string for bogus result.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param qstate: qstate with region.
* @return:
* 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,
struct ub_packed_rrset_key** list, size_t num,
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.

View File

@ -525,11 +525,19 @@ int algo_needs_missing(struct algo_needs* n)
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
dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
uint8_t* sigalg, char** reason, sldns_pkt_section section,
struct module_qstate* qstate)
uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate)
{
enum sec_status sec;
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 "
"signatures");
*reason = "no signatures";
if(reason_bogus)
*reason_bogus = LDNS_EDE_RRSIGS_MISSING;
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) {
verbose(VERB_QUERY, "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;
}
}
for(i=0; i<num; i++) {
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 */
if(sec == sec_status_secure) {
if(!sigalg)
@ -597,8 +610,8 @@ void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s)
enum sec_status
dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, char** reason, sldns_pkt_section section,
struct module_qstate* qstate)
size_t dnskey_idx, char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate)
{
enum sec_status sec;
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 "
"signatures");
*reason = "no signatures";
if(reason_bogus)
*reason_bogus = LDNS_EDE_RRSIGS_MISSING;
return sec_status_bogus;
}
for(i=0; i<num; i++) {
@ -620,10 +635,10 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
tag != rrset_get_sig_keytag(rrset, i))
continue;
buf_canon = 0;
sec = dnskey_verify_rrset_sig(env->scratch,
sec = dnskey_verify_rrset_sig(env->scratch,
env->scratch_buffer, ve, *env->now, rrset,
dnskey, dnskey_idx, i, &sortree, &buf_canon, reason,
section, qstate);
reason_bogus, section, qstate);
if(sec == sec_status_secure)
return sec;
numchecked ++;
@ -633,12 +648,13 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
return sec_status_bogus;
}
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)
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)
{
/* find matching keys and check them */
enum sec_status sec = sec_status_bogus;
@ -649,10 +665,12 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
int buf_canon = 0;
verbose(VERB_ALGO, "verify sig %d %d", (int)tag, 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");
return sec_status_insecure;
}
for(i=0; i<num; i++) {
/* see if key matches keytag and algo */
if(algo != dnskey_get_algo(dnskey, i) ||
@ -661,14 +679,17 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
numchecked ++;
/* see if key verifies */
sec = dnskey_verify_rrset_sig(env->scratch,
env->scratch_buffer, ve, now, rrset, dnskey, i,
sig_idx, sortree, &buf_canon, reason, section, qstate);
sec = dnskey_verify_rrset_sig(env->scratch,
env->scratch_buffer, ve, now, rrset, dnskey, i,
sig_idx, sortree, &buf_canon, reason, reason_bogus,
section, qstate);
if(sec == sec_status_secure)
return sec;
}
if(numchecked == 0) {
*reason = "signatures from unknown keys";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSKEY_MISSING;
verbose(VERB_QUERY, "verify: could not find appropriate key");
return sec_status_bogus;
}
@ -1361,8 +1382,8 @@ subtract_1982(uint32_t a, uint32_t b)
/** check rrsig dates */
static int
check_dates(struct val_env* ve, uint32_t unow,
uint8_t* expi_p, uint8_t* incep_p, char** reason)
check_dates(struct val_env* ve, uint32_t unow, uint8_t* expi_p,
uint8_t* incep_p, char** reason, sldns_ede_code *reason_bogus)
{
/* read out the dates */
uint32_t expi, incep, now;
@ -1386,6 +1407,14 @@ check_dates(struct val_env* ve, uint32_t unow,
sigdate_error("verify: inception after expiration, "
"signature bad", expi, incep, now);
*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;
}
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"
" before inception date", expi, incep, now);
*reason = "signature before inception date";
if(reason_bogus)
*reason_bogus = LDNS_EDE_SIGNATURE_NOT_YET_VALID;
return 0;
}
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,
incep, now);
*reason = "signature expired";
if(reason_bogus)
*reason_bogus = LDNS_EDE_SIGNATURE_EXPIRED;
return 0;
}
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 ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
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)
{
enum sec_status sec;
@ -1492,12 +1526,16 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
if(siglen < 2+20) {
verbose(VERB_QUERY, "verify: signature too short");
*reason = "signature too short";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus;
}
if(!(dnskey_get_flags(dnskey, dnskey_idx) & DNSKEY_BIT_ZSK)) {
verbose(VERB_QUERY, "verify: 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;
}
@ -1505,6 +1543,8 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
/* RFC 4034 says DNSKEY PROTOCOL MUST be 3 */
verbose(VERB_QUERY, "verify: dnskey has wrong key protocol");
*reason = "dnskey has wrong protocolnumber";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus;
}
@ -1514,17 +1554,23 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
if(!signer_len) {
verbose(VERB_QUERY, "verify: malformed signer name");
*reason = "signer name malformed";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus; /* signer name invalid */
}
if(!dname_subdomain_c(rrset->rk.dname, signer)) {
verbose(VERB_QUERY, "verify: signer name is off-tree");
*reason = "signer name off-tree";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus; /* signer name offtree */
}
sigblock = (unsigned char*)signer+signer_len;
if(siglen < 2+18+signer_len+1) {
verbose(VERB_QUERY, "verify: 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 */
}
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",
dnskey->rk.dname, 0, 0);
*reason = "signer name mismatches key name";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_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) {
verbose(VERB_QUERY, "verify: wrong type covered");
*reason = "signature covers wrong type";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus;
}
/* verify keytag and sig algo (possibly again) */
if((int)sig[2+2] != dnskey_get_algo(dnskey, dnskey_idx)) {
verbose(VERB_QUERY, "verify: wrong algorithm");
*reason = "signature has wrong algorithm";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus;
}
ktag = htons(dnskey_calc_keytag(dnskey, dnskey_idx));
if(memcmp(sig+2+16, &ktag, 2) != 0) {
verbose(VERB_QUERY, "verify: wrong keytag");
*reason = "signature has wrong keytag";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_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)) {
verbose(VERB_QUERY, "verify: labelcount out of range");
*reason = "signature labelcount out of range";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus;
}
@ -1598,7 +1654,8 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
/* verify inception, expiration dates
* Do this last so that if you ignore expired-sigs the
* 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;
}
}

View File

@ -45,6 +45,7 @@
#define VALIDATOR_VAL_SIGCRYPT_H
#include "util/data/packed_rrset.h"
#include "sldns/pkthdr.h"
#include "sldns/rrdef.h"
struct val_env;
struct module_env;
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
* algorithm is enough.
* @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 qstate: qstate with region.
* @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,
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);
/**
* verify rrset against one specific dnskey (from rrset)
* @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_idx: which key from the rrset to try.
* @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 qstate: qstate with region.
* @return secure if *this* key signs any of the signatures on rrset.
* unchecked on error or and bogus on bad signature.
*/
enum sec_status dnskey_verify_rrset(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t dnskey_idx, char** reason,
enum sec_status dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, char** reason, sldns_ede_code *reason_bogus,
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
* @param region: scratch region used for temporary allocation.
@ -323,17 +306,19 @@ enum sec_status dnskeyset_verify_rrset_sig(struct module_env* env,
* pass false at start. pass old value only for same rrset and same
* signature (but perhaps different key) for reuse.
* @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 qstate: qstate with region.
* @return secure if this key signs this signature. unchecked on error or
* bogus if it did not validate.
*/
enum sec_status dnskey_verify_rrset_sig(struct regional* region,
struct sldns_buffer* buf, struct val_env* ve, time_t now,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, size_t sig_idx,
struct rbtree_type** sortree, int* buf_canon, char** reason,
sldns_pkt_section section, struct module_qstate* qstate);
enum sec_status dnskey_verify_rrset_sig(struct regional* region,
struct sldns_buffer* buf, struct val_env* ve, time_t now,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, size_t sig_idx,
struct rbtree_type** sortree, int* buf_canon,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate);
/**
* canonical compare for two tree entries

View File

@ -332,11 +332,11 @@ rrset_get_ttl(struct ub_packed_rrset_key* rrset)
return d->ttl;
}
enum sec_status
static 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)
uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate)
{
enum sec_status sec;
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,
ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
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));
regional_free_all(env->scratch);
@ -392,7 +392,8 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
enum sec_status
val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
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 */
struct ub_packed_rrset_key dnskey;
@ -406,16 +407,16 @@ val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
dnskey.entry.key = &dnskey;
dnskey.entry.data = kd->rrset_data;
sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason,
section, qstate);
reason_bogus, section, qstate);
return sec;
}
/** verify that a DS RR hashes to a key and that key signs the set */
static enum sec_status
verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
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* 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;
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
* verifies *with this key* */
sec = dnskey_verify_rrset(env, ve, dnskey_rrset,
dnskey_rrset, i, reason, LDNS_SECTION_ANSWER, qstate);
sec = dnskey_verify_rrset(env, ve, dnskey_rrset, dnskey_rrset,
i, reason, reason_bogus, LDNS_SECTION_ANSWER, qstate);
if(sec == sec_status_secure) {
return sec;
}
@ -488,11 +489,12 @@ int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset)
return digest_algo;
}
enum sec_status
// @TODO change the use of this function to _ede function in authzone.c:8111
enum sec_status
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* 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
* 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,
ds_rrset, i, reason, qstate);
ds_rrset, i, reason, reason_bogus, qstate);
if(sec == sec_status_insecure)
continue;
@ -571,15 +573,16 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
return sec_status_bogus;
}
struct key_entry_key*
struct key_entry_key*
val_verify_new_DNSKEYs(struct regional* region, struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
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];
enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve,
dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason, qstate);
enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve,
dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason,
reason_bogus, qstate);
if(sec == sec_status_secure) {
return key_entry_create_rrset(region,
@ -597,12 +600,12 @@ val_verify_new_DNSKEYs(struct regional* region, struct module_env* env,
BOGUS_KEY_TTL, *env->now);
}
enum sec_status
enum sec_status
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* ta_ds,
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
* 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 "
"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;
}
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 "
"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;
}
@ -648,7 +655,7 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
continue;
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)
continue;
@ -688,7 +695,7 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
has_useful_ta = 1;
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(!sigalg || algo_needs_set_secure(&needs,
(uint8_t)dnskey_get_algo(ta_dnskey, i))) {
@ -723,24 +730,24 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
struct key_entry_key*
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_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];
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,
downprot?sigalg:NULL, reason, qstate);
downprot?sigalg:NULL, reason, reason_bogus, qstate);
if(sec == sec_status_secure) {
return key_entry_create_rrset(region,
return key_entry_create_rrset(region,
dnskey_rrset->rk.dname, dnskey_rrset->rk.dname_len,
ntohs(dnskey_rrset->rk.rrset_class), dnskey_rrset,
downprot?sigalg:NULL, *env->now);
} else if(sec == sec_status_insecure) {
return key_entry_create_null(region, dnskey_rrset->rk.dname,
dnskey_rrset->rk.dname_len,
dnskey_rrset->rk.dname_len,
ntohs(dnskey_rrset->rk.rrset_class),
rrset_get_ttl(dnskey_rrset), *env->now);
}
@ -749,7 +756,7 @@ val_verify_new_DNSKEYs_with_ta(struct regional* region, struct module_env* env,
BOGUS_KEY_TTL, *env->now);
}
int
int
val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset)
{
size_t i;
@ -776,6 +783,7 @@ val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset)
if(lt) snprintf(aerr, sizeof(aerr), "%s", lt->name);
else snprintf(aerr, sizeof(aerr), "%d",
(int)ds_get_key_algo(ds_rrset, 0));
verbose(VERB_ALGO, "DS unsupported, hash %s %s, "
"key algorithm %s %s", herr,
(ds_digest_algo_is_supported(ds_rrset, 0)?

View File

@ -43,6 +43,7 @@
#define VALIDATOR_VAL_UTILS_H
#include "util/data/packed_rrset.h"
#include "sldns/pkthdr.h"
#include "sldns/rrdef.h"
struct query_info;
struct reply_info;
struct val_env;
@ -113,24 +114,6 @@ void val_find_signer(enum val_classification subtype,
struct query_info* qinf, struct reply_info* rep,
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.
* @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 kkey: key_entry to verify with.
* @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 qstate: qstate with region.
* @return security status of verification.
*/
enum sec_status val_verify_rrset_entry(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct key_entry_key* kkey, char** reason, sldns_pkt_section section,
struct module_qstate* qstate);
struct key_entry_key* kkey, char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate);
/**
* Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but
@ -158,15 +142,16 @@ enum sec_status val_verify_rrset_entry(struct module_env* env,
* algorithm is enough. The list of signalled algorithms is returned,
* must have enough space for ALGO_NEEDS_MAX+1.
* @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.
* @return: sec_status_secure if a DS matches.
* sec_status_insecure if end of trust (i.e., unknown algorithms).
* sec_status_bogus if it fails.
*/
enum sec_status 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* ds_rrset, uint8_t* sigalg, char** reason,
struct module_qstate* qstate);
enum sec_status 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* ds_rrset, uint8_t* sigalg, char** reason,
sldns_ede_code *reason_bogus, struct module_qstate* qstate);
/**
* Verify DNSKEYs with DS and DNSKEY rrset. Like val_verify_DNSKEY_with_DS
@ -180,16 +165,17 @@ enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
* algorithm is enough. The list of signalled algorithms is returned,
* must have enough space for ALGO_NEEDS_MAX+1.
* @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.
* @return: sec_status_secure if a DS matches.
* sec_status_insecure if end of trust (i.e., unknown algorithms).
* sec_status_bogus if it fails.
*/
enum sec_status 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* ta_ds,
struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason,
struct module_qstate* qstate);
enum sec_status 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* ta_ds,
struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason,
sldns_ede_code *reason_bogus, struct module_qstate* qstate);
/**
* 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
* algorithm is enough.
* @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.
* @return a KeyEntry. This will either contain the now trusted
* dnskey_rrset, a "null" key entry indicating that this DS
@ -215,12 +202,11 @@ enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env,
* rrset.
* if downprot is set, a key entry with an algo list is made.
*/
struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason,
struct module_qstate* qstate);
struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason,
sldns_ede_code *reason_bogus, struct module_qstate* qstate);
/**
* 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
* algorithm is enough.
* @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.
* @return a KeyEntry. This will either contain the now trusted
* dnskey_rrset, a "null" key entry indicating that this DS
@ -246,11 +233,11 @@ struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
* if downprot is set, a key entry with an algo list is made.
*/
struct key_entry_key* 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 ub_packed_rrset_key* ta_ds_rrset,
struct ub_packed_rrset_key* ta_dnskey_rrset,
int downprot, char** reason, struct module_qstate* qstate);
struct module_env* env, 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_dnskey_rrset, int downprot,
char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate);
/**
* 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