git: e2b44c401cc2 - stable/14 - unbound: Vendor import 1.19.1
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 17 Feb 2024 13:45:44 UTC
The branch stable/14 has been updated by cy:
URL: https://cgit.FreeBSD.org/src/commit/?id=e2b44c401cc2a59da8c4c0515c6bcb533d09cc73
commit e2b44c401cc2a59da8c4c0515c6bcb533d09cc73
Author: Cy Schubert <cy@FreeBSD.org>
AuthorDate: 2023-11-13 19:44:16 +0000
Commit: Cy Schubert <cy@FreeBSD.org>
CommitDate: 2024-02-17 13:44:30 +0000
unbound: Vendor import 1.19.1
Release notes at
https://www.nlnetlabs.nl/news/2024/Feb/13/unbound-1.19.1-released/
Security: CVE-2023-50387, CVE-2023-50868
(cherry picked from commit b76ef9a7cb8a7c62d10ae8101f41014f34819174)
---
contrib/unbound/config.guess | 11 +-
contrib/unbound/config.sub | 29 +-
contrib/unbound/configure | 25 +-
contrib/unbound/configure.ac | 5 +-
contrib/unbound/doc/README | 2 +-
contrib/unbound/doc/example.conf.in | 2 +-
contrib/unbound/doc/libunbound.3.in | 4 +-
contrib/unbound/doc/unbound-anchor.8.in | 2 +-
contrib/unbound/doc/unbound-checkconf.8.in | 2 +-
contrib/unbound/doc/unbound-control.8.in | 2 +-
contrib/unbound/doc/unbound-host.1.in | 2 +-
contrib/unbound/doc/unbound.8.in | 4 +-
contrib/unbound/doc/unbound.conf.5.in | 2 +-
contrib/unbound/services/authzone.c | 3 +-
contrib/unbound/services/cache/dns.c | 22 ++
contrib/unbound/services/cache/dns.h | 9 +
contrib/unbound/testdata/val_any_negcache.rpl | 3 +
contrib/unbound/util/fptr_wlist.c | 1 +
contrib/unbound/validator/val_nsec.c | 3 +-
contrib/unbound/validator/val_nsec3.c | 316 ++++++++++++----
contrib/unbound/validator/val_nsec3.h | 60 +++-
contrib/unbound/validator/val_sigcrypt.c | 37 +-
contrib/unbound/validator/val_sigcrypt.h | 3 +-
contrib/unbound/validator/val_utils.c | 22 +-
contrib/unbound/validator/val_utils.h | 4 +-
contrib/unbound/validator/validator.c | 499 ++++++++++++++++++++++----
contrib/unbound/validator/validator.h | 18 +
lib/libunbound/config.h | 4 +-
28 files changed, 889 insertions(+), 207 deletions(-)
diff --git a/contrib/unbound/config.guess b/contrib/unbound/config.guess
index cdfc4392047c..f6d217a49f8f 100755
--- a/contrib/unbound/config.guess
+++ b/contrib/unbound/config.guess
@@ -1,10 +1,10 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2023 Free Software Foundation, Inc.
+# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
-timestamp='2023-08-22'
+timestamp='2024-01-01'
# 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
@@ -60,7 +60,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2023 Free Software Foundation, Inc.
+Copyright 1992-2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -165,6 +165,8 @@ Linux|GNU|GNU/*)
LIBC=dietlibc
#elif defined(__GLIBC__)
LIBC=gnu
+ #elif defined(__LLVM_LIBC__)
+ LIBC=llvm
#else
#include <stdarg.h>
/* First heuristic to detect musl libc. */
@@ -1593,6 +1595,9 @@ EOF
*:Unleashed:*:*)
GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
;;
+ *:Ironclad:*:*)
+ GUESS=$UNAME_MACHINE-unknown-ironclad
+ ;;
esac
# Do we have a guess based on uname results?
diff --git a/contrib/unbound/config.sub b/contrib/unbound/config.sub
index defe52c0c874..2c6a07ab3c34 100755
--- a/contrib/unbound/config.sub
+++ b/contrib/unbound/config.sub
@@ -1,10 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2023 Free Software Foundation, Inc.
+# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
-timestamp='2023-09-19'
+timestamp='2024-01-01'
# 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
@@ -76,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2023 Free Software Foundation, Inc.
+Copyright 1992-2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -1222,6 +1222,7 @@ case $cpu-$vendor in
| moxie \
| mt \
| msp430 \
+ | nanomips* \
| nds32 | nds32le | nds32be \
| nfp \
| nios | nios2 | nios2eb | nios2el \
@@ -1253,6 +1254,7 @@ case $cpu-$vendor in
| ubicom32 \
| v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
| vax \
+ | vc4 \
| visium \
| w65 \
| wasm32 | wasm64 \
@@ -1597,7 +1599,7 @@ case $cpu-$vendor in
os=
obj=elf
;;
- mips*-*)
+ mips*-*|nanomips*-*)
os=
obj=elf
;;
@@ -1721,7 +1723,7 @@ fi
case $os in
# Sometimes we do "kernel-libc", so those need to count as OSes.
- musl* | newlib* | relibc* | uclibc*)
+ llvm* | musl* | newlib* | relibc* | uclibc*)
;;
# Likewise for "kernel-abi"
eabi* | gnueabi*)
@@ -1766,12 +1768,19 @@ case $os in
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* | mlibc* | cos* | mbr* )
+ | fiwix* | mlibc* | cos* | mbr* | ironclad* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
;;
+ # This refers to builds using the UEFI calling convention
+ # (which depends on the architecture) and PE file format.
+ # Note that this is both a different calling convention and
+ # different file format than that of GNU-EFI
+ # (x86_64-w64-mingw32).
+ uefi)
+ ;;
none)
;;
kernel* | msvc* )
@@ -1818,8 +1827,9 @@ esac
# As a final step for OS-related things, validate the OS-kernel combination
# (given a valid OS), if there is a kernel.
case $kernel-$os-$obj in
- linux-gnu*- | linux-dietlibc*- | linux-android*- | linux-newlib*- \
- | linux-musl*- | linux-relibc*- | linux-uclibc*- | linux-mlibc*- )
+ linux-gnu*- | linux-android*- | linux-dietlibc*- | linux-llvm*- \
+ | linux-mlibc*- | linux-musl*- | linux-newlib*- \
+ | linux-relibc*- | linux-uclibc*- )
;;
uclinux-uclibc*- )
;;
@@ -1827,7 +1837,8 @@ case $kernel-$os-$obj in
;;
windows*-msvc*-)
;;
- -dietlibc*- | -newlib*- | -musl*- | -relibc*- | -uclibc*- | -mlibc*- )
+ -dietlibc*- | -llvm*- | -mlibc*- | -musl*- | -newlib*- | -relibc*- \
+ | -uclibc*- )
# These are just libc implementations, not actual OSes, and thus
# require a kernel.
echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2
diff --git a/contrib/unbound/configure b/contrib/unbound/configure
index fbe6f8697742..c87c669c8435 100755
--- a/contrib/unbound/configure
+++ b/contrib/unbound/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for unbound 1.19.0.
+# Generated by GNU Autoconf 2.69 for unbound 1.19.1.
#
# 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.19.0'
-PACKAGE_STRING='unbound 1.19.0'
+PACKAGE_VERSION='1.19.1'
+PACKAGE_STRING='unbound 1.19.1'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
PACKAGE_URL=''
@@ -1477,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.19.0 to adapt to many kinds of systems.
+\`configure' configures unbound 1.19.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1543,7 +1543,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of unbound 1.19.0:";;
+ short | recursive ) echo "Configuration of unbound 1.19.1:";;
esac
cat <<\_ACEOF
@@ -1785,7 +1785,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-unbound configure 1.19.0
+unbound configure 1.19.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2494,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.19.0, which was
+It was created by unbound $as_me 1.19.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2846,11 +2846,11 @@ UNBOUND_VERSION_MAJOR=1
UNBOUND_VERSION_MINOR=19
-UNBOUND_VERSION_MICRO=0
+UNBOUND_VERSION_MICRO=1
LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=23
+LIBUNBOUND_REVISION=24
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -2941,6 +2941,7 @@ LIBUNBOUND_AGE=1
# 1.17.1 had 9:21:1
# 1.18.0 had 9:22:1
# 1.19.0 had 9:23:1
+# 1.19.1 had 9:24:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -21894,7 +21895,7 @@ _ACEOF
-version=1.19.0
+version=1.19.1
date=`date +'%b %e, %Y'`
@@ -22413,7 +22414,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.19.0, which was
+This file was extended by unbound $as_me 1.19.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -22479,7 +22480,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.19.0
+unbound config.status 1.19.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/contrib/unbound/configure.ac b/contrib/unbound/configure.ac
index 1b999596d09a..70fc7e7fdf49 100644
--- a/contrib/unbound/configure.ac
+++ b/contrib/unbound/configure.ac
@@ -11,14 +11,14 @@ sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[19])
-m4_define([VERSION_MICRO],[0])
+m4_define([VERSION_MICRO],[1])
AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound])
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=23
+LIBUNBOUND_REVISION=24
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -109,6 +109,7 @@ LIBUNBOUND_AGE=1
# 1.17.1 had 9:21:1
# 1.18.0 had 9:22:1
# 1.19.0 had 9:23:1
+# 1.19.1 had 9:24:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
diff --git a/contrib/unbound/doc/README b/contrib/unbound/doc/README
index 592a9f4ae8d2..eef91ce02836 100644
--- a/contrib/unbound/doc/README
+++ b/contrib/unbound/doc/README
@@ -1,4 +1,4 @@
-README for Unbound 1.19.0
+README for Unbound 1.19.1
Copyright 2007 NLnet Labs
http://unbound.net
diff --git a/contrib/unbound/doc/example.conf.in b/contrib/unbound/doc/example.conf.in
index fe0dde69fa19..fcfb1da815db 100644
--- a/contrib/unbound/doc/example.conf.in
+++ b/contrib/unbound/doc/example.conf.in
@@ -1,7 +1,7 @@
#
# Example configuration file.
#
-# See unbound.conf(5) man page, version 1.19.0.
+# See unbound.conf(5) man page, version 1.19.1.
#
# this is a comment.
diff --git a/contrib/unbound/doc/libunbound.3.in b/contrib/unbound/doc/libunbound.3.in
index fa090d58186f..4a55eaa9e2ca 100644
--- a/contrib/unbound/doc/libunbound.3.in
+++ b/contrib/unbound/doc/libunbound.3.in
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Nov 8, 2023" "NLnet Labs" "unbound 1.19.0"
+.TH "libunbound" "3" "Feb 13, 2024" "NLnet Labs" "unbound 1.19.1"
.\"
.\" 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.19.0 functions.
+\- Unbound DNS validating resolver 1.19.1 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
diff --git a/contrib/unbound/doc/unbound-anchor.8.in b/contrib/unbound/doc/unbound-anchor.8.in
index a108db9faa72..fee56e9dfa51 100644
--- a/contrib/unbound/doc/unbound-anchor.8.in
+++ b/contrib/unbound/doc/unbound-anchor.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Nov 8, 2023" "NLnet Labs" "unbound 1.19.0"
+.TH "unbound-anchor" "8" "Feb 13, 2024" "NLnet Labs" "unbound 1.19.1"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
diff --git a/contrib/unbound/doc/unbound-checkconf.8.in b/contrib/unbound/doc/unbound-checkconf.8.in
index b80c723cd3f0..9a14ef06bc3d 100644
--- a/contrib/unbound/doc/unbound-checkconf.8.in
+++ b/contrib/unbound/doc/unbound-checkconf.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Nov 8, 2023" "NLnet Labs" "unbound 1.19.0"
+.TH "unbound-checkconf" "8" "Feb 13, 2024" "NLnet Labs" "unbound 1.19.1"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
diff --git a/contrib/unbound/doc/unbound-control.8.in b/contrib/unbound/doc/unbound-control.8.in
index 44e73c93dfd5..e747ec47e25a 100644
--- a/contrib/unbound/doc/unbound-control.8.in
+++ b/contrib/unbound/doc/unbound-control.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Nov 8, 2023" "NLnet Labs" "unbound 1.19.0"
+.TH "unbound-control" "8" "Feb 13, 2024" "NLnet Labs" "unbound 1.19.1"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
diff --git a/contrib/unbound/doc/unbound-host.1.in b/contrib/unbound/doc/unbound-host.1.in
index 36f22ee9b6d1..9c9e9e2bf4a0 100644
--- a/contrib/unbound/doc/unbound-host.1.in
+++ b/contrib/unbound/doc/unbound-host.1.in
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Nov 8, 2023" "NLnet Labs" "unbound 1.19.0"
+.TH "unbound\-host" "1" "Feb 13, 2024" "NLnet Labs" "unbound 1.19.1"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
diff --git a/contrib/unbound/doc/unbound.8.in b/contrib/unbound/doc/unbound.8.in
index 3d56b7bfa190..4967a22d328c 100644
--- a/contrib/unbound/doc/unbound.8.in
+++ b/contrib/unbound/doc/unbound.8.in
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Nov 8, 2023" "NLnet Labs" "unbound 1.19.0"
+.TH "unbound" "8" "Feb 13, 2024" "NLnet Labs" "unbound 1.19.1"
.\"
.\" unbound.8 -- unbound manual
.\"
@@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
-\- Unbound DNS validating resolver 1.19.0.
+\- Unbound DNS validating resolver 1.19.1.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
diff --git a/contrib/unbound/doc/unbound.conf.5.in b/contrib/unbound/doc/unbound.conf.5.in
index ac8fa7953f3c..79ca04904c96 100644
--- a/contrib/unbound/doc/unbound.conf.5.in
+++ b/contrib/unbound/doc/unbound.conf.5.in
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Nov 8, 2023" "NLnet Labs" "unbound 1.19.0"
+.TH "unbound.conf" "5" "Feb 13, 2024" "NLnet Labs" "unbound 1.19.1"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
diff --git a/contrib/unbound/services/authzone.c b/contrib/unbound/services/authzone.c
index 87844870a25a..761bcc6d9a75 100644
--- a/contrib/unbound/services/authzone.c
+++ b/contrib/unbound/services/authzone.c
@@ -7774,6 +7774,7 @@ static int zonemd_dnssec_verify_rrset(struct auth_zone* z,
enum sec_status sec;
struct val_env* ve;
int m;
+ int verified = 0;
m = modstack_find(mods, "validator");
if(m == -1) {
auth_zone_log(z->name, VERB_ALGO, "zonemd dnssec verify: have "
@@ -7797,7 +7798,7 @@ static int zonemd_dnssec_verify_rrset(struct auth_zone* z,
"zonemd: verify %s RRset with DNSKEY", typestr);
}
sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, sigalg, why_bogus, NULL,
- LDNS_SECTION_ANSWER, NULL);
+ LDNS_SECTION_ANSWER, NULL, &verified);
if(sec == sec_status_secure) {
return 1;
}
diff --git a/contrib/unbound/services/cache/dns.c b/contrib/unbound/services/cache/dns.c
index 9b4ad5888721..7bc1b7b47bf1 100644
--- a/contrib/unbound/services/cache/dns.c
+++ b/contrib/unbound/services/cache/dns.c
@@ -690,6 +690,28 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
return msg;
}
+struct dns_msg*
+dns_msg_deepcopy_region(struct dns_msg* origin, struct regional* region)
+{
+ size_t i;
+ struct dns_msg* res = NULL;
+ res = gen_dns_msg(region, &origin->qinfo, origin->rep->rrset_count);
+ if(!res) return NULL;
+ *res->rep = *origin->rep;
+ if(origin->rep->reason_bogus_str) {
+ res->rep->reason_bogus_str = regional_strdup(region,
+ origin->rep->reason_bogus_str);
+ }
+ for(i=0; i<res->rep->rrset_count; i++) {
+ res->rep->rrsets[i] = packed_rrset_copy_region(
+ origin->rep->rrsets[i], region, 0);
+ if(!res->rep->rrsets[i]) {
+ return NULL;
+ }
+ }
+ return res;
+}
+
/** synthesize RRset-only response from cached RRset item */
static struct dns_msg*
rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
diff --git a/contrib/unbound/services/cache/dns.h b/contrib/unbound/services/cache/dns.h
index 147f992cbc74..c2bf23c6de54 100644
--- a/contrib/unbound/services/cache/dns.h
+++ b/contrib/unbound/services/cache/dns.h
@@ -164,6 +164,15 @@ struct dns_msg* tomsg(struct module_env* env, struct query_info* q,
struct reply_info* r, struct regional* region, time_t now,
int allow_expired, struct regional* scratch);
+/**
+ * Deep copy a dns_msg to a region.
+ * @param origin: the dns_msg to copy.
+ * @param region: the region to copy all the data to.
+ * @return the new dns_msg or NULL on malloc error.
+ */
+struct dns_msg* dns_msg_deepcopy_region(struct dns_msg* origin,
+ struct regional* region);
+
/**
* Find cached message
* @param env: module environment with the DNS cache.
diff --git a/contrib/unbound/testdata/val_any_negcache.rpl b/contrib/unbound/testdata/val_any_negcache.rpl
index 77aacba8cc13..8800a2140219 100644
--- a/contrib/unbound/testdata/val_any_negcache.rpl
+++ b/contrib/unbound/testdata/val_any_negcache.rpl
@@ -199,6 +199,9 @@ SECTION QUESTION
example.com. IN ANY
ENTRY_END
+; Allow validation resuming for the RRSIGs
+STEP 21 TIME_PASSES ELAPSE 0.05
+
; recursion happens here.
STEP 30 CHECK_ANSWER
ENTRY_BEGIN
diff --git a/contrib/unbound/util/fptr_wlist.c b/contrib/unbound/util/fptr_wlist.c
index 43d38dc3797d..a792a3429549 100644
--- a/contrib/unbound/util/fptr_wlist.c
+++ b/contrib/unbound/util/fptr_wlist.c
@@ -131,6 +131,7 @@ fptr_whitelist_comm_timer(void (*fptr)(void*))
else if(fptr == &pending_udp_timer_delay_cb) return 1;
else if(fptr == &worker_stat_timer_cb) return 1;
else if(fptr == &worker_probe_timer_cb) return 1;
+ else if(fptr == &validate_suspend_timer_cb) return 1;
#ifdef UB_ON_WINDOWS
else if(fptr == &wsvc_cron_cb) return 1;
#endif
diff --git a/contrib/unbound/validator/val_nsec.c b/contrib/unbound/validator/val_nsec.c
index 17c90d83f594..d0cc67ff5d0b 100644
--- a/contrib/unbound/validator/val_nsec.c
+++ b/contrib/unbound/validator/val_nsec.c
@@ -181,6 +181,7 @@ nsec_verify_rrset(struct module_env* env, struct val_env* ve,
{
struct packed_rrset_data* d = (struct packed_rrset_data*)
nsec->entry.data;
+ int verified = 0;
if(!d) return 0;
if(d->security == sec_status_secure)
return 1;
@@ -188,7 +189,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,
- reason_bogus, LDNS_SECTION_AUTHORITY, qstate);
+ reason_bogus, LDNS_SECTION_AUTHORITY, qstate, &verified);
if(d->security == sec_status_secure) {
rrset_update_sec_status(env->rrset_cache, nsec, *env->now);
return 1;
diff --git a/contrib/unbound/validator/val_nsec3.c b/contrib/unbound/validator/val_nsec3.c
index a2b3794f6019..95d1e4d7e4fe 100644
--- a/contrib/unbound/validator/val_nsec3.c
+++ b/contrib/unbound/validator/val_nsec3.c
@@ -57,6 +57,19 @@
/* we include nsec.h for the bitmap_has_type function */
#include "validator/val_nsec.h"
#include "sldns/sbuffer.h"
+#include "util/config_file.h"
+
+/**
+ * Max number of NSEC3 calculations at once, suspend query for later.
+ * 8 is low enough and allows for cases where multiple proofs are needed.
+ */
+#define MAX_NSEC3_CALCULATIONS 8
+/**
+ * When all allowed NSEC3 calculations at once resulted in error treat as
+ * bogus. NSEC3 hash errors are not cached and this helps breaks loops with
+ * erroneous data.
+ */
+#define MAX_NSEC3_ERRORS -1
/**
* This function we get from ldns-compat or from base system
@@ -532,6 +545,17 @@ nsec3_hash_cmp(const void* c1, const void* c2)
return memcmp(s1, s2, s1len);
}
+int
+nsec3_cache_table_init(struct nsec3_cache_table* ct, struct regional* region)
+{
+ if(ct->ct) return 1;
+ ct->ct = (rbtree_type*)regional_alloc(region, sizeof(*ct->ct));
+ if(!ct->ct) return 0;
+ ct->region = region;
+ rbtree_init(ct->ct, &nsec3_hash_cmp);
+ return 1;
+}
+
size_t
nsec3_get_hashed(sldns_buffer* buf, uint8_t* nm, size_t nmlen, int algo,
size_t iter, uint8_t* salt, size_t saltlen, uint8_t* res, size_t max)
@@ -646,7 +670,7 @@ nsec3_hash_name(rbtree_type* table, struct regional* region, sldns_buffer* buf,
c = (struct nsec3_cached_hash*)rbtree_search(table, &looki);
if(c) {
*hash = c;
- return 1;
+ return 2;
}
/* create a new entry */
c = (struct nsec3_cached_hash*)regional_alloc(region, sizeof(*c));
@@ -658,10 +682,10 @@ nsec3_hash_name(rbtree_type* table, struct regional* region, sldns_buffer* buf,
c->dname_len = dname_len;
r = nsec3_calc_hash(region, buf, c);
if(r != 1)
- return r;
+ return r; /* returns -1 or 0 */
r = nsec3_calc_b32(region, buf, c);
if(r != 1)
- return r;
+ return r; /* returns 0 */
#ifdef UNBOUND_DEBUG
n =
#else
@@ -704,6 +728,7 @@ nsec3_hash_matches_owner(struct nsec3_filter* flt,
struct nsec3_cached_hash* hash, struct ub_packed_rrset_key* s)
{
uint8_t* nm = s->rk.dname;
+ if(!hash) return 0; /* please clang */
/* compare, does hash of name based on params in this NSEC3
* match the owner name of this NSEC3?
* name must be: <hashlength>base32 . zone name
@@ -730,34 +755,50 @@ nsec3_hash_matches_owner(struct nsec3_filter* flt,
* @param nmlen: length of name.
* @param rrset: nsec3 that matches is returned here.
* @param rr: rr number in nsec3 rrset that matches.
+ * @param calculations: current hash calculations.
* @return true if a matching NSEC3 is found, false if not.
*/
static int
find_matching_nsec3(struct module_env* env, struct nsec3_filter* flt,
- rbtree_type* ct, uint8_t* nm, size_t nmlen,
- struct ub_packed_rrset_key** rrset, int* rr)
+ struct nsec3_cache_table* ct, uint8_t* nm, size_t nmlen,
+ struct ub_packed_rrset_key** rrset, int* rr,
+ int* calculations)
{
size_t i_rs;
int i_rr;
struct ub_packed_rrset_key* s;
struct nsec3_cached_hash* hash = NULL;
int r;
+ int calc_errors = 0;
/* this loop skips other-zone and unknown NSEC3s, also non-NSEC3 RRs */
for(s=filter_first(flt, &i_rs, &i_rr); s;
s=filter_next(flt, &i_rs, &i_rr)) {
+ /* check if we are allowed more calculations */
+ if(*calculations >= MAX_NSEC3_CALCULATIONS) {
+ if(calc_errors == *calculations) {
+ *calculations = MAX_NSEC3_ERRORS;
+ }
+ break;
+ }
/* get name hashed for this NSEC3 RR */
- r = nsec3_hash_name(ct, env->scratch, env->scratch_buffer,
+ r = nsec3_hash_name(ct->ct, ct->region, env->scratch_buffer,
s, i_rr, nm, nmlen, &hash);
if(r == 0) {
log_err("nsec3: malloc failure");
break; /* alloc failure */
- } else if(r != 1)
- continue; /* malformed NSEC3 */
- else if(nsec3_hash_matches_owner(flt, hash, s)) {
- *rrset = s; /* rrset with this name */
- *rr = i_rr; /* matches hash with these parameters */
- return 1;
+ } else if(r < 0) {
+ /* malformed NSEC3 */
+ calc_errors++;
+ (*calculations)++;
+ continue;
+ } else {
+ if(r == 1) (*calculations)++;
+ if(nsec3_hash_matches_owner(flt, hash, s)) {
+ *rrset = s; /* rrset with this name */
+ *rr = i_rr; /* matches hash with these parameters */
+ return 1;
+ }
}
}
*rrset = NULL;
@@ -775,6 +816,7 @@ nsec3_covers(uint8_t* zone, struct nsec3_cached_hash* hash,
if(!nsec3_get_nextowner(rrset, rr, &next, &nextlen))
return 0; /* malformed RR proves nothing */
+ if(!hash) return 0; /* please clang */
/* check the owner name is a hashed value . apex
* base32 encoded values must have equal length.
* hash_value and next hash value must have equal length. */
@@ -823,35 +865,51 @@ nsec3_covers(uint8_t* zone, struct nsec3_cached_hash* hash,
* @param nmlen: length of name.
* @param rrset: covering NSEC3 rrset is returned here.
* @param rr: rr of cover is returned here.
+ * @param calculations: current hash calculations.
* @return true if a covering NSEC3 is found, false if not.
*/
static int
find_covering_nsec3(struct module_env* env, struct nsec3_filter* flt,
- rbtree_type* ct, uint8_t* nm, size_t nmlen,
- struct ub_packed_rrset_key** rrset, int* rr)
+ struct nsec3_cache_table* ct, uint8_t* nm, size_t nmlen,
+ struct ub_packed_rrset_key** rrset, int* rr,
+ int* calculations)
{
size_t i_rs;
int i_rr;
struct ub_packed_rrset_key* s;
struct nsec3_cached_hash* hash = NULL;
int r;
+ int calc_errors = 0;
/* this loop skips other-zone and unknown NSEC3s, also non-NSEC3 RRs */
for(s=filter_first(flt, &i_rs, &i_rr); s;
s=filter_next(flt, &i_rs, &i_rr)) {
+ /* check if we are allowed more calculations */
+ if(*calculations >= MAX_NSEC3_CALCULATIONS) {
+ if(calc_errors == *calculations) {
+ *calculations = MAX_NSEC3_ERRORS;
+ }
+ break;
+ }
/* get name hashed for this NSEC3 RR */
- r = nsec3_hash_name(ct, env->scratch, env->scratch_buffer,
+ r = nsec3_hash_name(ct->ct, ct->region, env->scratch_buffer,
s, i_rr, nm, nmlen, &hash);
if(r == 0) {
log_err("nsec3: malloc failure");
break; /* alloc failure */
- } else if(r != 1)
- continue; /* malformed NSEC3 */
- else if(nsec3_covers(flt->zone, hash, s, i_rr,
- env->scratch_buffer)) {
- *rrset = s; /* rrset with this name */
- *rr = i_rr; /* covers hash with these parameters */
- return 1;
+ } else if(r < 0) {
+ /* malformed NSEC3 */
+ calc_errors++;
+ (*calculations)++;
+ continue;
+ } else {
+ if(r == 1) (*calculations)++;
+ if(nsec3_covers(flt->zone, hash, s, i_rr,
+ env->scratch_buffer)) {
+ *rrset = s; /* rrset with this name */
+ *rr = i_rr; /* covers hash with these parameters */
+ return 1;
+ }
}
}
*rrset = NULL;
@@ -869,11 +927,13 @@ find_covering_nsec3(struct module_env* env, struct nsec3_filter* flt,
* @param ct: cached hashes table.
* @param qinfo: query that is verified for.
* @param ce: closest encloser information is returned in here.
+ * @param calculations: current hash calculations.
* @return true if a closest encloser candidate is found, false if not.
*/
static int
-nsec3_find_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
- rbtree_type* ct, struct query_info* qinfo, struct ce_response* ce)
+nsec3_find_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
+ struct nsec3_cache_table* ct, struct query_info* qinfo,
+ struct ce_response* ce, int* calculations)
{
uint8_t* nm = qinfo->qname;
size_t nmlen = qinfo->qname_len;
@@ -888,8 +948,12 @@ nsec3_find_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
* may be the case. */
while(dname_subdomain_c(nm, flt->zone)) {
+ if(*calculations >= MAX_NSEC3_CALCULATIONS ||
+ *calculations == MAX_NSEC3_ERRORS) {
+ return 0;
+ }
if(find_matching_nsec3(env, flt, ct, nm, nmlen,
- &ce->ce_rrset, &ce->ce_rr)) {
+ &ce->ce_rrset, &ce->ce_rr, calculations)) {
ce->ce = nm;
ce->ce_len = nmlen;
return 1;
@@ -933,22 +997,38 @@ next_closer(uint8_t* qname, size_t qnamelen, uint8_t* ce,
* If set true, and the return value is true, then you can be
* certain that the ce.nc_rrset and ce.nc_rr are set properly.
* @param ce: closest encloser information is returned in here.
+ * @param calculations: pointer to the current NSEC3 hash calculations.
* @return bogus if no closest encloser could be proven.
* secure if a closest encloser could be proven, ce is set.
* insecure if the closest-encloser candidate turns out to prove
* that an insecure delegation exists above the qname.
+ * unchecked if no more hash calculations are allowed at this point.
*/
static enum sec_status
-nsec3_prove_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
- rbtree_type* ct, struct query_info* qinfo, int prove_does_not_exist,
- struct ce_response* ce)
+nsec3_prove_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
+ struct nsec3_cache_table* ct, struct query_info* qinfo,
+ int prove_does_not_exist, struct ce_response* ce, int* calculations)
{
uint8_t* nc;
size_t nc_len;
/* robust: clean out ce, in case it gets abused later */
memset(ce, 0, sizeof(*ce));
- if(!nsec3_find_closest_encloser(env, flt, ct, qinfo, ce)) {
+ if(!nsec3_find_closest_encloser(env, flt, ct, qinfo, ce, calculations)) {
+ if(*calculations == MAX_NSEC3_ERRORS) {
+ verbose(VERB_ALGO, "nsec3 proveClosestEncloser: could "
+ "not find a candidate for the closest "
+ "encloser; all attempted hash calculations "
+ "were erroneous; bogus");
+ return sec_status_bogus;
+ } else if(*calculations >= MAX_NSEC3_CALCULATIONS) {
+ verbose(VERB_ALGO, "nsec3 proveClosestEncloser: could "
+ "not find a candidate for the closest "
+ "encloser; reached MAX_NSEC3_CALCULATIONS "
+ "(%d); unchecked still",
+ MAX_NSEC3_CALCULATIONS);
+ return sec_status_unchecked;
+ }
verbose(VERB_ALGO, "nsec3 proveClosestEncloser: could "
"not find a candidate for the closest encloser.");
return sec_status_bogus;
@@ -989,9 +1069,23 @@ nsec3_prove_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
/* Otherwise, we need to show that the next closer name is covered. */
next_closer(qinfo->qname, qinfo->qname_len, ce->ce, &nc, &nc_len);
if(!find_covering_nsec3(env, flt, ct, nc, nc_len,
- &ce->nc_rrset, &ce->nc_rr)) {
+ &ce->nc_rrset, &ce->nc_rr, calculations)) {
+ if(*calculations == MAX_NSEC3_ERRORS) {
+ verbose(VERB_ALGO, "nsec3: Could not find proof that the "
+ "candidate encloser was the closest encloser; "
+ "all attempted hash calculations were "
+ "erroneous; bogus");
+ return sec_status_bogus;
+ } else if(*calculations >= MAX_NSEC3_CALCULATIONS) {
+ verbose(VERB_ALGO, "nsec3: Could not find proof that the "
+ "candidate encloser was the closest encloser; "
+ "reached MAX_NSEC3_CALCULATIONS (%d); "
+ "unchecked still",
+ MAX_NSEC3_CALCULATIONS);
+ return sec_status_unchecked;
+ }
verbose(VERB_ALGO, "nsec3: Could not find proof that the "
- "candidate encloser was the closest encloser");
+ "candidate encloser was the closest encloser");
return sec_status_bogus;
}
return sec_status_secure;
@@ -1019,8 +1113,8 @@ nsec3_ce_wildcard(struct regional* region, uint8_t* ce, size_t celen,
/** Do the name error proof */
static enum sec_status
-nsec3_do_prove_nameerror(struct module_env* env, struct nsec3_filter* flt,
- rbtree_type* ct, struct query_info* qinfo)
+nsec3_do_prove_nameerror(struct module_env* env, struct nsec3_filter* flt,
+ struct nsec3_cache_table* ct, struct query_info* qinfo, int* calc)
{
struct ce_response ce;
uint8_t* wc;
@@ -1032,11 +1126,15 @@ nsec3_do_prove_nameerror(struct module_env* env, struct nsec3_filter* flt,
/* First locate and prove the closest encloser to qname. We will
* use the variant that fails if the closest encloser turns out
* to be qname. */
- sec = nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce);
+ sec = nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce, calc);
if(sec != sec_status_secure) {
if(sec == sec_status_bogus)
verbose(VERB_ALGO, "nsec3 nameerror proof: failed "
"to prove a closest encloser");
+ else if(sec == sec_status_unchecked)
+ verbose(VERB_ALGO, "nsec3 nameerror proof: will "
+ "continue proving closest encloser after "
+ "suspend");
else verbose(VERB_ALGO, "nsec3 nameerror proof: closest "
"nsec3 is an insecure delegation");
return sec;
@@ -1046,9 +1144,27 @@ nsec3_do_prove_nameerror(struct module_env* env, struct nsec3_filter* flt,
/* At this point, we know that qname does not exist. Now we need
* to prove that the wildcard does not exist. */
log_assert(ce.ce);
- wc = nsec3_ce_wildcard(env->scratch, ce.ce, ce.ce_len, &wclen);
- if(!wc || !find_covering_nsec3(env, flt, ct, wc, wclen,
- &wc_rrset, &wc_rr)) {
+ wc = nsec3_ce_wildcard(ct->region, ce.ce, ce.ce_len, &wclen);
+ if(!wc) {
+ verbose(VERB_ALGO, "nsec3 nameerror proof: could not prove "
+ "that the applicable wildcard did not exist.");
+ return sec_status_bogus;
+ }
+ if(!find_covering_nsec3(env, flt, ct, wc, wclen, &wc_rrset, &wc_rr, calc)) {
+ if(*calc == MAX_NSEC3_ERRORS) {
+ verbose(VERB_ALGO, "nsec3 nameerror proof: could not prove "
+ "that the applicable wildcard did not exist; "
+ "all attempted hash calculations were "
+ "erroneous; bogus");
+ return sec_status_bogus;
+ } else if(*calc >= MAX_NSEC3_CALCULATIONS) {
+ verbose(VERB_ALGO, "nsec3 nameerror proof: could not prove "
+ "that the applicable wildcard did not exist; "
+ "reached MAX_NSEC3_CALCULATIONS (%d); "
+ "unchecked still",
+ MAX_NSEC3_CALCULATIONS);
+ return sec_status_unchecked;
+ }
verbose(VERB_ALGO, "nsec3 nameerror proof: could not prove "
"that the applicable wildcard did not exist.");
return sec_status_bogus;
@@ -1064,14 +1180,13 @@ nsec3_do_prove_nameerror(struct module_env* env, struct nsec3_filter* flt,
enum sec_status
nsec3_prove_nameerror(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)
+ struct query_info* qinfo, struct key_entry_key* kkey,
+ struct nsec3_cache_table* ct, int* calc)
{
- rbtree_type ct;
struct nsec3_filter flt;
if(!list || num == 0 || !kkey || !key_entry_isgood(kkey))
return sec_status_bogus; /* no valid NSEC3s, bogus */
- rbtree_init(&ct, &nsec3_hash_cmp); /* init names-to-hash cache */
filter_init(&flt, list, num, qinfo); /* init RR iterator */
if(!flt.zone)
return sec_status_bogus; /* no RRs */
@@ -1079,7 +1194,7 @@ nsec3_prove_nameerror(struct module_env* env, struct val_env* ve,
return sec_status_insecure; /* iteration count too high */
log_nametypeclass(VERB_ALGO, "start nsec3 nameerror proof, zone",
flt.zone, 0, 0);
- return nsec3_do_prove_nameerror(env, &flt, &ct, qinfo);
+ return nsec3_do_prove_nameerror(env, &flt, ct, qinfo, calc);
}
/*
@@ -1089,8 +1204,9 @@ nsec3_prove_nameerror(struct module_env* env, struct val_env* ve,
/** Do the nodata proof */
static enum sec_status
-nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
- rbtree_type* ct, struct query_info* qinfo)
+nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
+ struct nsec3_cache_table* ct, struct query_info* qinfo,
+ int* calc)
{
struct ce_response ce;
uint8_t* wc;
@@ -1100,7 +1216,7 @@ nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
enum sec_status sec;
if(find_matching_nsec3(env, flt, ct, qinfo->qname, qinfo->qname_len,
- &rrset, &rr)) {
+ &rrset, &rr, calc)) {
/* cases 1 and 2 */
if(nsec3_has_type(rrset, rr, qinfo->qtype)) {
verbose(VERB_ALGO, "proveNodata: Matching NSEC3 "
@@ -1144,11 +1260,23 @@ nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
}
return sec_status_secure;
}
+ if(*calc == MAX_NSEC3_ERRORS) {
+ verbose(VERB_ALGO, "proveNodata: all attempted hash "
+ "calculations were erroneous while finding a matching "
+ "NSEC3, bogus");
+ return sec_status_bogus;
+ } else if(*calc >= MAX_NSEC3_CALCULATIONS) {
+ verbose(VERB_ALGO, "proveNodata: reached "
+ "MAX_NSEC3_CALCULATIONS (%d) while finding a "
+ "matching NSEC3; unchecked still",
*** 1722 LINES SKIPPED ***