Compare commits

..
54 changed files with 670 additions and 1235 deletions
+2 -4
View File
@@ -17,9 +17,7 @@ You can learn more about Unbound by reading our
## Compiling
Make sure you have the C toolchain, OpenSSL and its include files, and libexpat
installed.
If building from the repository source you also need flex and bison installed.
Unbound can be compiled and installed using:
installed. Unbound can be compiled and installed using:
```
./configure && make && make install
@@ -29,7 +27,7 @@ You can use libevent if you want. libevent is useful when using many (10000)
outgoing ports. By default max 256 ports are opened at the same time and the
builtin alternative is equally capable and a little faster.
Use the `--with-libevent` configure option to compile Unbound with libevent
Use the `--with-libevent=dir` configure option to compile Unbound with libevent
support.
## Unbound configuration
-5
View File
@@ -815,11 +815,6 @@ cachedb_handle_response(struct module_qstate* qstate,
qstate->ext_state[id] = module_finished;
return;
}
if(qstate->env->cfg->cachedb_no_store) {
/* do not store the item in the external cache */
qstate->ext_state[id] = module_finished;
return;
}
/* store the item into the backend cache */
cachedb_extcache_store(qstate, ie);
Vendored
+15 -17
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.19.2.
# Generated by GNU Autoconf 2.69 for unbound 1.18.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.2'
PACKAGE_STRING='unbound 1.19.2'
PACKAGE_VERSION='1.18.1'
PACKAGE_STRING='unbound 1.18.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.2 to adapt to many kinds of systems.
\`configure' configures unbound 1.18.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.2:";;
short | recursive ) echo "Configuration of unbound 1.18.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.2
unbound configure 1.18.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.2, which was
It was created by unbound $as_me 1.18.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2844,13 +2844,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
UNBOUND_VERSION_MAJOR=1
UNBOUND_VERSION_MINOR=19
UNBOUND_VERSION_MINOR=18
UNBOUND_VERSION_MICRO=2
UNBOUND_VERSION_MICRO=1
LIBUNBOUND_CURRENT=9
LIBUNBOUND_REVISION=25
LIBUNBOUND_REVISION=23
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -2940,9 +2940,7 @@ LIBUNBOUND_AGE=1
# 1.17.0 had 9:20: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
# 1.19.2 had 9:25:1
# 1.18.1 had 9:23:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -21342,7 +21340,7 @@ if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
else
as_fn_error $? "The protobuf-c library was not found. Please install the development libraries for protobuf-c!" "$LINENO" 5
as_fn_error $? "The protobuf-c library was not found. Please install protobuf-c!" "$LINENO" 5
fi
@@ -21896,7 +21894,7 @@ _ACEOF
version=1.19.2
version=1.18.1
date=`date +'%b %e, %Y'`
@@ -22415,7 +22413,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.2, which was
This file was extended by unbound $as_me 1.18.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -22481,7 +22479,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.2
unbound config.status 1.18.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+4 -6
View File
@@ -10,15 +10,15 @@ 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],[2])
m4_define([VERSION_MINOR],[18])
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=25
LIBUNBOUND_REVISION=23
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -108,9 +108,7 @@ LIBUNBOUND_AGE=1
# 1.17.0 had 9:20: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
# 1.19.2 had 9:25:1
# 1.18.1 had 9:23:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
+1 -1
View File
@@ -41,7 +41,7 @@ AC_DEFUN([dt_DNSTAP],
fi
])
AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
AC_MSG_ERROR([The protobuf-c library was not found. Please install the development libraries for protobuf-c!]))
AC_MSG_ERROR([The protobuf-c library was not found. Please install protobuf-c!]))
$2
else
$3
+1 -35
View File
@@ -1,37 +1,3 @@
2 November 2023: Wouter
- Set version number to 1.19.0.
- Tag for 1.19.0rc1 release.
1 November 2023: George
- Mention flex and bison in README.md when building from repository
source.
1 November 2023: Wouter
- Fix SSL compile failure for definition in log_crypto_err_io_code_arg.
- Fix SSL compile failure for other missing definitions in
log_crypto_err_io_code_arg.
- Fix compilation without openssl, remove unused function warning.
31 October 2023: George
- Fix #941: dnscrypt doesn't work after upgrade to 1.18 with
suggestion by dukeartem to also fix the udp_ancil with dnscrypt.
30 October 2023: George
- Merge #930 from Stuart Henderson: add void to
log_ident_revert_to_default declaration.
30 October 2023: Wouter
- autoconf.
24 October 2023: George
- Clearer configure text for missing protobuf-c development libraries.
20 October 2023: Wouter
- Merge #951: Cachedb no store. The cachedb-no-store: yes option is
used to stop cachedb from writing messages to the backend storage.
It reads messages when data is available from the backend. The
default is no.
19 October 2023: Wouter
- Fix to print detailed errors when an SSL IO routine fails via
SSL_get_error.
@@ -4899,7 +4865,7 @@
- Fix that with openssl 1.1 control-use-cert: no uses less cpu, by
using no encryption over the unix socket.
22 November 2016: Ralph
22 Novenber 2016: Ralph
- Make access-control-tag-data RDATA absolute. This makes the RDATA
origin consistent between local-data and access-control-tag-data.
- Fix NSEC ENT wildcard check. Matching wildcard does not have to be a
-2
View File
@@ -1226,8 +1226,6 @@ remote-control:
# backend: "testframe"
# # secret seed string to calculate hashed keys
# secret-seed: "default"
# # if the backend should be read from, but not written to.
# cachedb-no-store: no
#
# # For "redis" backend:
# # (to enable, use --with-libhiredis to configure before compiling)
-5
View File
@@ -2681,11 +2681,6 @@ operationally.
If the backend database is shared by multiple Unbound instances,
all instances must use the same secret seed.
This option defaults to "default".
.TP
.B cachedb-no-store: \fI<yes or no>\fR
If the backend should be read from, but not written to. This makes this
instance not store dns messages in the backend. But if data is available it
is retrieved. The default is no.
.P
The following
.B cachedb
+122 -25
View File
@@ -6345,6 +6345,16 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
/* get master addr */
if(xfr->task_probe->scan_addr) {
/* parse the host string to get the auth name for scan_addr */
if(xfr->task_probe->scan_specific &&
xfr->task_probe->scan_specific->host &&
!authextstrtoaddr(xfr->task_probe->scan_specific->host, &addr, &addrlen, &auth_name)) {
char zname[255+1];
dname_str(xfr->name, zname);
log_err("%s: failed lookup, cannot probe to master %s",
zname, master->host);
return 0;
}
addrlen = xfr->task_probe->scan_addr->addrlen;
memmove(&addr, &xfr->task_probe->scan_addr->addr, addrlen);
} else {
@@ -6358,18 +6368,6 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
zname, master->host);
return 0;
}
if (auth_name != NULL) {
if (addr.ss_family == AF_INET
&& (int)ntohs(((struct sockaddr_in *)&addr)->sin_port)
== env->cfg->ssl_port)
((struct sockaddr_in *)&addr)->sin_port
= htons((uint16_t)env->cfg->port);
else if (addr.ss_family == AF_INET6
&& (int)ntohs(((struct sockaddr_in6 *)&addr)->sin6_port)
== env->cfg->ssl_port)
((struct sockaddr_in6 *)&addr)->sin6_port
= htons((uint16_t)env->cfg->port);
}
}
/* create packet */
@@ -6379,11 +6377,12 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
xfr->task_probe->id = GET_RANDOM_ID(env->rnd);
xfr_create_soa_probe_packet(xfr, env->scratch_buffer,
xfr->task_probe->id);
/* we need to remove the cp if we have a different ip4/ip6 type now */
/* we need to remove the cp if we have a different ip4/ip6 type now.
* And also for tls probes to get a new tcp commpoint. */
if(xfr->task_probe->cp &&
((xfr->task_probe->cp_is_ip6 && !addr_is_ip6(&addr, addrlen)) ||
(!xfr->task_probe->cp_is_ip6 && addr_is_ip6(&addr, addrlen)))
) {
(!xfr->task_probe->cp_is_ip6 && addr_is_ip6(&addr, addrlen)) ||
auth_name != NULL)) {
comm_point_delete(xfr->task_probe->cp);
xfr->task_probe->cp = NULL;
}
@@ -6391,14 +6390,19 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
if(addr_is_ip6(&addr, addrlen))
xfr->task_probe->cp_is_ip6 = 1;
else xfr->task_probe->cp_is_ip6 = 0;
xfr->task_probe->cp = outnet_comm_point_for_udp(env->outnet,
auth_xfer_probe_udp_callback, xfr, &addr, addrlen);
if(auth_name != NULL)
xfr->task_probe->cp = outnet_comm_point_for_tcp(env->outnet,
auth_xfer_probe_tcp_callback, xfr, &addr, addrlen, env->scratch_buffer, -1, auth_name != NULL, auth_name);
else
xfr->task_probe->cp = outnet_comm_point_for_udp(env->outnet,
auth_xfer_probe_udp_callback, xfr, &addr, addrlen);
if(!xfr->task_probe->cp) {
char zname[255+1], as[256];
dname_str(xfr->name, zname);
addr_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "cannot create udp cp for "
"probe %s to %s", zname, as);
verbose(VERB_ALGO, "cannot create %s cp for "
"probe %s to %s", (auth_name?"tcp":"udp"),
zname, as);
return 0;
}
}
@@ -6411,8 +6415,9 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
}
}
/* send udp packet */
if(!comm_point_send_udp_msg(xfr->task_probe->cp, env->scratch_buffer,
/* send udp packet, for an UDP commpoint. */
if(auth_name == NULL &&
!comm_point_send_udp_msg(xfr->task_probe->cp, env->scratch_buffer,
(struct sockaddr*)&addr, addrlen, 0)) {
char zname[255+1], as[256];
dname_str(xfr->name, zname);
@@ -6421,13 +6426,18 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
zname, as);
return 0;
}
/* for a TCP commpoint, the packet is waiting to be sent in the
* TCP commpoint buffer. The callback returns when there is a reply. */
if(verbosity >= VERB_ALGO) {
char zname[255+1], as[256];
dname_str(xfr->name, zname);
addr_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "auth zone %s soa probe sent to %s", zname,
as);
verbose(VERB_ALGO, "auth zone %s soa probe sent to %s%s%s",
zname, as, (auth_name?"#":""),
(auth_name?auth_name:""));
}
if(auth_name != NULL)
timeout *= 10; /* TCP and TLS get a longer timeout */
xfr->task_probe->timeout = timeout;
#ifndef S_SPLINT_S
t.tv_sec = timeout/1000;
@@ -6565,6 +6575,94 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
return 0;
}
/** callback for task_probe tcp replies */
int
auth_xfer_probe_tcp_callback(struct comm_point* c, void* arg, int err,
struct comm_reply* ATTR_UNUSED(repinfo))
{
struct auth_xfer* xfr = (struct auth_xfer*)arg;
struct module_env* env;
log_assert(xfr->task_probe);
lock_basic_lock(&xfr->lock);
env = xfr->task_probe->env;
if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return 0; /* stop on quit */
}
/* stop the timer */
comm_timer_disable(xfr->task_probe->timer);
/* see if we got a reply and what that means */
if(err == NETEVENT_NOERROR) {
uint32_t serial = 0;
if(check_packet_ok(c->buffer, LDNS_RR_TYPE_SOA, xfr,
&serial)) {
/* successful lookup */
if(verbosity >= VERB_ALGO) {
char buf[256];
dname_str(xfr->name, buf);
verbose(VERB_ALGO, "auth zone %s: soa probe "
"serial is %u", buf, (unsigned)serial);
}
/* see if this serial indicates that the zone has
* to be updated */
if(xfr_serial_means_update(xfr, serial)) {
/* if updated, start the transfer task, if needed */
verbose(VERB_ALGO, "auth_zone updated, start transfer");
if(xfr->task_transfer->worker == NULL) {
struct auth_master* master =
xfr_probe_current_master(xfr);
/* if we have download URLs use them
* in preference to this master we
* just probed the SOA from */
if(xfr->task_transfer->masters &&
xfr->task_transfer->masters->http)
master = NULL;
xfr_probe_disown(xfr);
xfr_start_transfer(xfr, env, master);
return 0;
}
/* other tasks are running, we don't do this anymore */
xfr_probe_disown(xfr);
lock_basic_unlock(&xfr->lock);
/* return, we don't sent a reply to this udp packet,
* and we setup the tasks to do next */
return 0;
} else {
verbose(VERB_ALGO, "auth_zone master reports unchanged soa serial");
/* we if cannot find updates amongst the
* masters, this means we then have a new lease
* on the zone */
xfr->task_probe->have_new_lease = 1;
}
} else {
if(verbosity >= VERB_ALGO) {
char buf[256];
dname_str(xfr->name, buf);
verbose(VERB_ALGO, "auth zone %s: bad reply to soa probe", buf);
}
}
} else {
if(verbosity >= VERB_ALGO) {
char buf[256];
dname_str(xfr->name, buf);
verbose(VERB_ALGO, "auth zone %s: soa probe failed", buf);
}
}
/* failed lookup or not an update */
/* delete commpoint so a new one is created, with a fresh port nr */
comm_point_delete(xfr->task_probe->cp);
xfr->task_probe->cp = NULL;
/* if the result was not a successful probe, we need
* to send the next one */
xfr_probe_nextmaster(xfr);
xfr_probe_send_or_end(xfr, env);
return 0;
}
/** lookup a host name for its addresses, if needed */
static int
xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
@@ -7774,7 +7872,6 @@ 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 "
@@ -7798,7 +7895,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, &verified);
LDNS_SECTION_ANSWER, NULL);
if(sec == sec_status_secure) {
return 1;
}
+3
View File
@@ -678,6 +678,9 @@ void auth_xfer_timer(void* arg);
/** callback for commpoint udp replies to task_probe */
int auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
struct comm_reply* repinfo);
/** callback for commpoint tcp replies to task_probe */
int auth_xfer_probe_tcp_callback(struct comm_point* c, void* arg, int err,
struct comm_reply* repinfo);
/** callback for task_transfer tcp connections */
int auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err,
struct comm_reply* repinfo);
-22
View File
@@ -690,28 +690,6 @@ 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,
-9
View File
@@ -164,15 +164,6 @@ 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.
+3 -4
View File
@@ -180,7 +180,6 @@ verifytest_rrset(struct module_env* env, struct val_env* ve,
enum sec_status sec;
char* reason = NULL;
uint8_t sigalg[ALGO_NEEDS_MAX+1];
int verified = 0;
if(vsig) {
log_nametypeclass(VERB_QUERY, "verify of rrset",
rrset->rk.dname, ntohs(rrset->rk.type),
@@ -189,7 +188,7 @@ verifytest_rrset(struct module_env* env, struct val_env* ve,
setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */
/* ok to give null as qstate here, won't be used for answer section. */
sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason, NULL,
LDNS_SECTION_ANSWER, NULL, &verified);
LDNS_SECTION_ANSWER, NULL);
if(vsig) {
printf("verify outcome is: %s %s\n", sec_status_to_string(sec),
reason?reason:"");
@@ -443,9 +442,9 @@ nsec3_hash_test_entry(struct entry* e, rbtree_type* ct,
ret = nsec3_hash_name(ct, region, buf, nsec3, 0, qname,
qinfo.qname_len, &hash);
if(ret < 1) {
if(ret != 1) {
printf("Bad nsec3_hash_name retcode %d\n", ret);
unit_assert(ret == 1 || ret == 2);
unit_assert(ret == 1);
}
unit_assert(hash->dname && hash->hash && hash->hash_len &&
hash->b32 && hash->b32_len);
+22
View File
@@ -0,0 +1,22 @@
server:
verbosity: 7
# num-threads: 1
interface: 127.0.0.1
port: @PORT@
use-syslog: no
directory: ""
pidfile: "unbound.pid"
chroot: ""
username: ""
do-not-query-localhost: no
use-caps-for-id: no
tls-cert-bundle: "unbound_server.pem"
auth-zone:
name: "example.com"
for-upstream: yes
for-downstream: yes
master: "127.0.0.1@@TOPORT@#unbound"
# if queries escape, send them to localhost
forward-zone:
name: "."
forward-addr: 127.0.0.1@@PORT@
+22
View File
@@ -0,0 +1,22 @@
server:
verbosity: 5
logfile: "/dev/stderr"
xfrdfile: "xfrd.state"
zonesdir: ""
username: ""
chroot: ""
pidfile: "nsd.pid"
database: ""
zonelistfile: "zone.list"
interface: 127.0.0.1@@AUTH_PORT@
tls-service-key: "unbound_server.key"
tls-service-pem: "unbound_server.pem"
tls-port: @AUTH_PORT@
zone:
name: "example.com"
zonefile: "example.com.zone"
provide-xfr: 127.0.0.0/8 NOKEY
provide-xfr: ::1 NOKEY
provide-xfr: ::ffff:127.0.0.1 NOKEY
notify: 127.0.0.1@@PORT@ NOKEY
+16
View File
@@ -0,0 +1,16 @@
BaseName: auth_axfr_tls
Version: 1.0
Description: Perform AXFR for authority zone using TLS
CreationDate: Thu 19 Oct 09:25:40 CEST 2023
Maintainer: dr. W.C.A. Wijngaards
Category:
Component:
CmdDepends:
Depends:
Help:
Pre: auth_axfr_tls.pre
Post: auth_axfr_tls.post
Test: auth_axfr_tls.test
AuxFiles:
Passed:
Failure:
+16
View File
@@ -0,0 +1,16 @@
# #-- auth_axfr_tls.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
kill_pid $AUTH_PID
kill_pid $UNBOUND_PID
if test -f nsd.log; then
cat nsd.log
fi
if test -f unbound.log; then
cat unbound.log
fi
+51
View File
@@ -0,0 +1,51 @@
# #-- auth_axfr_tls.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
# see if we have NSD as an auth server to serve xfr over tls.
NSD=nsd
if which nsd 2>/dev/null; then
echo "NSD=$NSD"
else
NSD=""
for d in ".." "../.." "../../.." "../../../.." ; do
if test -z "$NSD" -o ! -f "$NSD"; then
if test -d "$d/nsd" && test -f "$d/nsd/nsd"; then
NSD="$d/nsd/nsd"
break;
fi
fi
done
fi
if test -z "$NSD"; then
skip_test "Need nsd for auth server, skip test"
fi
echo "NSD=$NSD" >> .tpkg.var.test
get_random_port 2
UNBOUND_PORT=$RND_PORT
AUTH_PORT=$(($RND_PORT + 1))
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
echo "AUTH_PORT=$AUTH_PORT" >> .tpkg.var.test
# start auth server
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@AUTH_PORT\@/'$AUTH_PORT'/' < auth_axfr_tls.conf2 > nsd.conf
$NSD -d -c nsd.conf >nsd.log 2>&1 &
AUTH_PID=$!
echo "AUTH_PID=$AUTH_PID" >> .tpkg.var.test
# make config file
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$AUTH_PORT'/' < auth_axfr_tls.conf > ub.conf
# 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
cat .tpkg.var.test
wait_nsd_up nsd.log
wait_unbound_up unbound.log
+87
View File
@@ -0,0 +1,87 @@
# #-- auth_axfr_tls.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="../.."
# do the test
echo "> dig www.example.com."
dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
# try again if it needs time to do the zone transfer.
if grep SERVFAIL outfile; then
echo "> try again"
dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
fi
if grep SERVFAIL outfile; then
echo "> try again"
sleep 1
dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
fi
if grep SERVFAIL outfile; then
echo "> try again"
sleep 1
dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
fi
if grep SERVFAIL outfile; then
echo "> try again"
sleep 1
dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
fi
echo "> check answer"
if grep "1.2.3.4" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
# update the zone
mv example.com.zone example.com.zone.old
mv example.com.zone2 example.com.zone
touch example.com.zone
kill -1 $AUTH_PID
#it would need to wait for the line to appear twice.
#wait_server_up nsd.log "zone example.com read with success"
echo "> auth server updated"
echo "> dig www.example.com."
dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
# try again if it needs time to do the zone transfer.
if grep SERVFAIL outfile || grep "1.2.3.4" outfile; then
echo "> try again"
dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
fi
if grep SERVFAIL outfile || grep "1.2.3.4" outfile; then
echo "> try again"
sleep 1
dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
fi
if grep SERVFAIL outfile || grep "1.2.3.4" outfile; then
echo "> try again"
sleep 1
dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
fi
if grep SERVFAIL outfile || grep "1.2.3.4" outfile; then
echo "> try again"
sleep 1
dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
fi
echo "> check answer"
if grep "1.2.3.5" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
if grep "auth zone example.com. soa probe sent to 127.0.0.1#unbound" unbound.log; then
echo "SOA sent over TLS"
else
echo "SOA not sent over TLS"
echo "Not OK"
exit 1
fi
exit 0
+2
View File
@@ -0,0 +1,2 @@
example.com. IN SOA nibbler.example.com. leela.example.com. 4 3600 3600 7200 300
www.example.com. IN A 1.2.3.4
+2
View File
@@ -0,0 +1,2 @@
example.com. IN SOA nibbler.example.com. leela.example.com. 8 3600 3600 7200 300
www.example.com. IN A 1.2.3.5
+39
View File
@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
MIIG4gIBAAKCAYEAstEp+Pyh8XGrtZ77A4FhYjvbeB3dMa7Q2rGWxobzlA9przhA
1aChAvUtCOAuM+rB6NTNB8YWfZJbQHawyMNpmC77cg6vXLYCGUQHZyAqidN049RJ
F5T7j4N8Vniv17LiRdr0S6swy4PRvEnIPPV43EQHZqC5jVvHsKkhIfmBF/Dj5TXR
ypeawWV/m5jeU6/4HRYMfytBZdO1mPXuWLh0lgbQ4SCbgrOUVD3rniMk1yZIbQOm
vlDHYqekjDb/vOW2KxUQLG04aZMJ1mWfdbwG0CKQkSjISEDZ1l76vhM6mTM0fwXb
IvyFZ9yPPCle1mF5aSlxS2cmGuGVSRQaw8XF9fe3a9ACJJTr33HdSpyaZkKRAUzL
cKqLCl323daKv3NwwAT03Tj4iQM416ASMoiyfFa/2GWTKQVjddu8Crar7tGaf5xr
lig4DBmrBvdYA3njy72/RD71hLwmlRoCGU7dRuDr9O6KASUm1Ri91ONZ/qdjMvov
15l2vj4GV+KXR00dAgMBAAECggGAHepIL1N0dEQkCdpy+/8lH54L9WhpnOo2HqAf
LU9eaKK7d4jdr9+TkD8cLaPzltPrZNxVALvu/0sA4SP6J1wpyj/x6P7z73qzly5+
Xo5PD4fEwmi9YaiW/UduAblnEZrnp/AddptJKoL/D5T4XtpiQddPtael4zQ7kB57
YIexRSQTvEDovA/o3/nvA0TrzOxfgd4ycQP3iOWGN/TMzyLsvjydrUwbOB567iz9
whL3Etdgvnwh5Sz2blbFfH+nAR8ctvFFz+osPvuIVR21VMEI6wm7kTpSNnQ6sh/c
lrLb/bTADn4g7z/LpIZJ+MrLvyEcoqValrLYeFBhM9CV8woPxvkO2P3pU47HVGax
tC7GV6a/kt5RoKFd/TNdiA3OC7NGZtaeXv9VkPf4fVwBtSO9d5ZZXTGEynDD/rUQ
U4KFJe6OD23APjse08HiiKqTPhsOneOONU67iqoaTdIkT2R4EdlkVEDpXVtWb+G9
Q+IqYzVljlzuyHrhWXLJw/FMa2aBAoHBAOnZbi4gGpH+P6886WDWVgIlTccuXoyc
Mg9QQYk9UDeXxL0AizR5bZy49Sduegz9vkHpAiZARQsUnizHjZ8YlRcrmn4t6tx3
ahTIKAjdprnxJfYINM580j8CGbXvX5LhIlm3O267D0Op+co3+7Ujy+cjsIuFQrP+
1MqMgXSeBjzC1APivmps7HeFE+4w0k2PfN5wSMDNCzLo99PZuUG5XZ93OVOS5dpN
b+WskdcD8NOoJy/X/5A08veEI/jYO/DyqQKBwQDDwUQCOWf41ecvJLtBHKmEnHDz
ftzHino9DRKG8a9XaN4rmetnoWEaM2vHGX3pf3mwH+dAe8vJdAQueDhBKYeEpm6C
TYNOpou1+Zs5s99BilCTNYo8fkMOAyqwRwmz9zgHS6QxXuPwsghKefLJGt6o6RFF
tfWVTfLlYJ+I3GQe3ySsk3wjVz4oUTKiyiq5+KzD+HhEkS7u+RQ7Z0ZI2xd2cF8Y
aN2hjKDpcOiFf3CDoqka5D1qMNLgIHO52AHww1UCgcA1h7o7AMpURRka6hyaODY0
A4oMYEbwdQjYjIyT998W+rzkbu1us6UtzQEBZ760npkgyU/epbOoV63lnkCC/MOU
LD0PST+L/CHiY/cWIHb79YG1EifUZKpUFg0Aoq0EGFkepF0MefGCkbRGYA5UZr9U
R80wAu9D+L+JJiS0J0BSRF74DL196zUuHt5zFeXuLzxsRtPAnq9DliS08BACRYZy
7H3I7cWD9Vn5/0jbKWHFcaaWwyETR6uekTcSzZzbCRECgcBeoE3/xUA9SSk34Mmj
7/cB4522Ft0imA3+9RK/qJTZ7Bd5fC4PKjOGNtUiqW/0L2rjeIiQ40bfWvWqgPKw
jSK1PL6uvkl6+4cNsFsYyZpiVDoe7wKju2UuoNlB3RUTqa2r2STFuNj2wRjA57I1
BIgdnox65jqQsd14g/yaa+75/WP9CE45xzKEyrtvdcqxm0Pod3OrsYK+gikFjiar
kT0GQ8u0QPzh2tjt/2ZnIfOBrl+QYERP0MofDZDjhUdq2wECgcB0Lu841+yP5cdR
qbJhXO4zJNh7oWNcJlOuQp3ZMNFrA1oHpe9pmLukiROOy01k9WxIMQDzU5GSqRv3
VLkYOIcbhJ3kClKAcM3j95SkKbU2H5/RENb3Ck52xtl4pNU1x/3PnVFZfDVuuHO9
MZ9YBcIeK98MyP2jr5JtFKnOyPE7xKq0IHIhXadpbc2wjje5FtZ1cUtMyEECCXNa
C1TpXebHGyXGpY9WdWXhjdE/1jPvfS+uO5WyuDpYPr339gsdq1g=
-----END RSA PRIVATE KEY-----
+22
View File
@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDszCCAhsCFGD5193whHQ2bVdzbaQfdf1gc4SkMA0GCSqGSIb3DQEBCwUAMBIx
EDAOBgNVBAMMB3VuYm91bmQwHhcNMjAwNzA4MTMzMjMwWhcNNDAwMzI1MTMzMjMw
WjAaMRgwFgYDVQQDDA91bmJvdW5kLWNvbnRyb2wwggGiMA0GCSqGSIb3DQEBAQUA
A4IBjwAwggGKAoIBgQCy0Sn4/KHxcau1nvsDgWFiO9t4Hd0xrtDasZbGhvOUD2mv
OEDVoKEC9S0I4C4z6sHo1M0HxhZ9kltAdrDIw2mYLvtyDq9ctgIZRAdnICqJ03Tj
1EkXlPuPg3xWeK/XsuJF2vRLqzDLg9G8Scg89XjcRAdmoLmNW8ewqSEh+YEX8OPl
NdHKl5rBZX+bmN5Tr/gdFgx/K0Fl07WY9e5YuHSWBtDhIJuCs5RUPeueIyTXJkht
A6a+UMdip6SMNv+85bYrFRAsbThpkwnWZZ91vAbQIpCRKMhIQNnWXvq+EzqZMzR/
Bdsi/IVn3I88KV7WYXlpKXFLZyYa4ZVJFBrDxcX197dr0AIklOvfcd1KnJpmQpEB
TMtwqosKXfbd1oq/c3DABPTdOPiJAzjXoBIyiLJ8Vr/YZZMpBWN127wKtqvu0Zp/
nGuWKDgMGasG91gDeePLvb9EPvWEvCaVGgIZTt1G4Ov07ooBJSbVGL3U41n+p2My
+i/XmXa+PgZX4pdHTR0CAwEAATANBgkqhkiG9w0BAQsFAAOCAYEAd++Wen6l8Ifj
4h3p/y16PhSsWJWuJ4wdNYy3/GM84S26wGjzlEEwiW76HpH6VJzPOiBAeWnFKE83
hFyetEIxgJeIPbcs9ZP/Uoh8GZH9tRISBSN9Hgk2Slr9llo4t1H0g/XTgA5HqMQU
9YydlBh43G7Vw3FVwh09OM6poNOGQKNc/tq2/QdKeUMtyBbLWpRmjH5XcCT35fbn
ZiVOUldqSHD4kKrFO4nJYXZyipRbcXybsLiX9GP0GLemc3IgIvOXyJ2RPp06o/SJ
pzlMlkcAfLJaSuEW57xRakhuNK7m051TKKzJzIEX+NFYOVdafFHS8VwGrYsdrFvD
72tMfu+Fu55y3awdWWGc6YlaGogZiuMnJkvQphwgn+5qE/7CGEckoKEsH601rqIZ
muaIc85+nEcHJeijd/ZlBN9zeltjFoMuqTUENgmv8+tUAdVm/UMY9Vjme6b43ydP
uv6DS02+k9z8toxXworLiPr94BGaiGV1NxgwZKLZigYJt/Fi2Qte
-----END CERTIFICATE-----
+39
View File
@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
MIIG5AIBAAKCAYEAvjSVSN2QMXudpzukdLCqgg/IOhCX8KYkD0FFFfWcQjgKq5wI
0x41iG32a6wbGanre4IX7VxaSPu9kkHfnGgynCk5nwDRedE/FLFhAU78PoT0+Nqq
GRS7XVQ24vLmIz9Hqc2Ozx1um1BXBTmIT0UfN2e22I0LWQ6a3seZlEDRj45gnk7Z
uh9MDgotaBdm+v1JAbupSf6Zis4VEH3JNdvVGE3O1DHEIeuuz/3BDhpf6WBDH+8K
WaBe1ca4TZHr9ThL2gEMEfAQl0wXDwRWRoi3NjNMH+mw0L1rjwThI5GXqNIee7o5
FzUReSXZuTdFMyGe3Owcx+XoYnwi6cplSNoGsDBu4B9bKKglR9YleJVw4L4Xi8xP
q6O9UPj4+nypHk/DOoC7DIM3ufN0yxPBsFo5TVowxfhdjZXJbbftd2TZv7AH8+XL
A5UoZgRzXgzECelXSCTBFlMTnT48LfA9pMLydyjAz2UdPHs5Iv+TK5nnI+aJoeaP
7kFZSngxdy1+A/bNAgMBAAECggGBALpTOIqQwVg4CFBylL/a8K1IWJTI/I65sklf
XxYL7G7SB2HlEJ//z+E+F0+S4Vlao1vyLQ5QkgE82pAUB8FoMWvY1qF0Y8A5wtm6
iZSGk4OLK488ZbT8Ii9i+AGKgPe2XbVxsJwj8N4k7Zooqec9hz73Up8ATEWJkRz7
2u7oMGG4z91E0PULA64dOi3l/vOQe5w/Aa+CwVbAWtI05o7kMvQEBMDJn6C7CByo
MB5op9wueJMnz7PM7hns+U7Dy6oE4ljuolJUy51bDzFWwoM54cRoQqLFNHd8JVQj
WxldCkbfF43iyprlsEcUrTyUjtdA+ZeiG39vg/mtdmgNpGmdupHJZQvSuG8IcVlz
O+eMSeQS1QXPD6Ik8UK4SU0h+zOl8xIWtRrsxQuh4fnTN40udm/YUWl/6gOebsBI
IrVLlKGqJSfB3tMjpCRqdTzJ0dA9keVpkqm2ugZkxEf1+/efq/rFIQ2pUBLCqNTN
qpNqruK8y8FphP30I2uI4Ej2UIB8AQKBwQDd2Yptj2FyDyaXCycsyde0wYkNyzGU
dRnzdibfHnMZwjgTjwAwgIUBVIS8H0/z7ZJQKN7osJfddMrtjJtYYUk9g/dCpHXs
bNh2QSoWah3FdzNGuWd0iRf9+LFxhjAAMo/FS8zFJAJKrFsBdCGTfFUMdsLC0bjr
YjiWBuvV72uKf8XIZX5KIZruKdWBBcWukcb21R1UDyFYyXRBsly5XHaIYKZql3km
7pV7MKWO0IYgHbHIqGUqPQlzZ/lkunS1jKECgcEA23wHffD6Ou9/x3okPx2AWpTr
gh8rgqbyo6hQkBW5Y90Wz824cqaYebZDaBR/xlVx/YwjKkohv8Bde2lpH/ZxRZ1Z
5Sk2s6GJ/vU0L9RsJZgCgj4L6Coal1NMxuZtCXAlnOpiCdxSZgfqbshbTVz30KsG
ZJG361Cua1ScdAHxlZBxT52/1Sm0zRC2hnxL7h4qo7Idmtzs40LAJvYOKekR0pPN
oWeJfra7vgx/jVNvMFWoOoSLpidVO4g+ot4ery6tAoHAdW3rCic1C2zdnmH28Iw+
s50l8Lk3mz+I5wgJd1zkzCO0DxZIoWPGA3g7cmCYr6N3KRsZMs4W9NAXgjpFGDkW
zYsG3K21BdpvkdjYcFjnPVjlOXB2RIc0vehf9Jl02wXoeCSxVUDEPcaRvWk9RJYx
ZpGOchUU7vNkxHURbIJ4yCzuAi9G8/Jp0dsu+kaV5tufF5SjG5WOrzKjaQsCbdN1
oqaWMCHRrTvov/Z2C+xwsptFOdN5CSyZzg6hQiI4GMlBAoHAXyb6KINcOEi0YMp3
BFXJ23tMTnEs78tozcKeipigcsbaqORK3omS+NEnj+uzKUzJyl4CsMbKstK2tFYS
mSTCHqgE3PBtIpsZtEqhgUraR8IK9GPpzZDTTl9ynZgwFTNlWw3RyuyVXF56J+T8
kCGJ3hEHCHqT/ZRQyX85BKIDFhA0z4tYKxWVqIFiYBNq56R0X9tMMmMs36mEnF93
7Ht6mowxTZQRa7nU0qOgeKh/P7ki4Zus3y+WJ+T9IqahLtlRAoHBAIhqMrcxSAB8
RpB9jukJlAnidw2jCMPgrFE8tP0khhVvGrXMldxAUsMKntDIo8dGCnG1KTcWDI0O
jepvSPHSsxVLFugL79h0eVIS5z4huW48i9xgU8VlHdgAcgEPIAOFcOw2BCu/s0Vp
O+MM/EyUOdo3NsibB3qc/GJI6iNBYS7AljYEVo6rXo5V/MZvZUF4vClen6Obzsre
MTTb+4sJjfqleWuvr1XNMeu2mBfXBQkWGZP1byBK0MvD/aQ2PWq92A==
-----END RSA PRIVATE KEY-----
+22
View File
@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDqzCCAhMCFBHWXeQ6ZIa9QcQbXLFfC6tj+KA+MA0GCSqGSIb3DQEBCwUAMBIx
EDAOBgNVBAMMB3VuYm91bmQwHhcNMjAwNzA4MTMzMjI5WhcNNDAwMzI1MTMzMjI5
WjASMRAwDgYDVQQDDAd1bmJvdW5kMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
igKCAYEAvjSVSN2QMXudpzukdLCqgg/IOhCX8KYkD0FFFfWcQjgKq5wI0x41iG32
a6wbGanre4IX7VxaSPu9kkHfnGgynCk5nwDRedE/FLFhAU78PoT0+NqqGRS7XVQ2
4vLmIz9Hqc2Ozx1um1BXBTmIT0UfN2e22I0LWQ6a3seZlEDRj45gnk7Zuh9MDgot
aBdm+v1JAbupSf6Zis4VEH3JNdvVGE3O1DHEIeuuz/3BDhpf6WBDH+8KWaBe1ca4
TZHr9ThL2gEMEfAQl0wXDwRWRoi3NjNMH+mw0L1rjwThI5GXqNIee7o5FzUReSXZ
uTdFMyGe3Owcx+XoYnwi6cplSNoGsDBu4B9bKKglR9YleJVw4L4Xi8xPq6O9UPj4
+nypHk/DOoC7DIM3ufN0yxPBsFo5TVowxfhdjZXJbbftd2TZv7AH8+XLA5UoZgRz
XgzECelXSCTBFlMTnT48LfA9pMLydyjAz2UdPHs5Iv+TK5nnI+aJoeaP7kFZSngx
dy1+A/bNAgMBAAEwDQYJKoZIhvcNAQELBQADggGBABunf93MKaCUHiZgnoOTinsW
84/EgInrgtKzAyH+BhnKkJOhhR0kkIAx5d9BpDlaSiRTACFon9moWCgDIIsK/Ar7
JE0Kln9cV//wiiNoFU0O4mnzyGUIMvlaEX6QHMJJQYvL05+w/3AAcf5XmMJtR5ca
fJ8FqvGC34b2WxX9lTQoyT52sRt+1KnQikiMEnEyAdKktMG+MwKsFDdOwDXyZhZg
XZhRrfX3/NVJolqB6EahjWIGXDeKuSSKZVtCyib6LskyeMzN5lcRfvubKDdlqFVF
qlD7rHBsKhQUWK/IO64mGf7y/de+CgHtED5vDvr/p2uj/9sABATfbrOQR3W/Of25
sLBj4OEfrJ7lX8hQgFaxkMI3x6VFT3W8dTCp7xnQgb6bgROWB5fNEZ9jk/gjSRmD
yIU+r0UbKe5kBk/CmZVFXL2TyJ92V5NYEQh8V4DGy19qZ6u/XKYyNJL4ocs35GGe
CA8SBuyrmdhx38h1RHErR2Skzadi1S7MwGf1y431fQ==
-----END CERTIFICATE-----
-29
View File
@@ -1,29 +0,0 @@
server:
verbosity: 4
interface: 127.0.0.1
port: @PORT@
use-syslog: no
directory: ""
pidfile: "unbound.pid"
chroot: ""
username: ""
module-config: "cachedb iterator"
do-not-query-localhost: no
qname-minimisation: no
forward-zone:
name: "."
forward-addr: 127.0.0.1@@TOPORT@
stub-zone:
name: "example.com"
stub-addr: 127.0.0.1@@TOPORT@
remote-control:
control-enable: yes
control-interface: @CONTROL_PATH@/controlpipe.@CONTROL_PID@
control-use-cert: no
cachedb:
backend: "testframe"
secret-seed: "testvalue"
-16
View File
@@ -1,16 +0,0 @@
BaseName: cachedb_no_store
Version: 1.0
Description: cachedb test the cachedb-no-store option
CreationDate: Wed 11 Oct 11:00:00 CEST 2023
Maintainer: dr. W.C.A. Wijngaards
Category:
Component:
CmdDepends:
Depends:
Help:
Pre: cachedb_no_store.pre
Post: cachedb_no_store.post
Test: cachedb_no_store.test
AuxFiles:
Passed:
Failure:
-20
View File
@@ -1,20 +0,0 @@
# #-- cachedb_no_store.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
PRE="../.."
. ../common.sh
echo "> cat logfiles"
cat fwd.log
if test -f fwd2.log; then cat fwd2.log; else echo "no fwd2.log"; fi
if test -f fwd3.log; then cat fwd3.log; else echo "no fwd3.log"; fi
if test -f fwd4.log; then cat fwd4.log; else echo "no fwd4.log"; fi
cat unbound.log
if test -f unbound2.log; then cat unbound2.log; else echo "no unbound2.log"; fi
kill_pid $FWD_PID
kill_pid `cat unbound.pid`
rm -f $CONTROL_PATH/controlpipe.$CONTROL_PID
-36
View File
@@ -1,36 +0,0 @@
# #-- cachedb_no_store.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
PRE="../.."
. ../common.sh
if grep "define USE_CACHEDB 1" $PRE/config.h; then echo test enabled; else skip_test "test skipped"; 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 cachedb_no_store.testns >fwd.log 2>&1 &
FWD_PID=$!
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
# make config file
CONTROL_PATH=/tmp
CONTROL_PID=$$
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' -e 's?@CONTROL_PATH\@?'$CONTROL_PATH'?' -e 's/@CONTROL_PID@/'$CONTROL_PID'/' < cachedb_no_store.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
echo "CONTROL_PATH=$CONTROL_PATH" >> .tpkg.var.test
echo "CONTROL_PID=$CONTROL_PID" >> .tpkg.var.test
cat .tpkg.var.test
wait_ldns_testns_up fwd.log
wait_unbound_up unbound.log
@@ -1,8 +0,0 @@
ENTRY_BEGIN
MATCH opcode
ADJUST copy_id copy_query
REPLY QR AA SERVFAIL
SECTION QUESTION
txt1.example.com. IN TXT
SECTION ANSWER
ENTRY_END
-132
View File
@@ -1,132 +0,0 @@
# #-- cachedb_no_store.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
PRE="../.."
. ../common.sh
# do the test
get_ldns_testns
# query for a text record that is stored by unbound's cache and cachedb
# in the testframe cache.
echo "> dig txt1.example.com."
dig @localhost -p $UNBOUND_PORT txt1.example.com. TXT | tee outfile
if grep "example text message" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
# stop the forwarder with servfail, to check the answer came from the cache
echo "> stop ldns-testns"
kill_pid $FWD_PID
echo "> start ldns-testns with servfails"
$LDNS_TESTNS -p $FWD_PORT cachedb_no_store.servfail.testns >fwd2.log 2>&1 &
FWD_PID=$!
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
wait_ldns_testns_up fwd2.log
echo "> dig txt1.example.com. from unbound cache"
dig @localhost -p $UNBOUND_PORT txt1.example.com. TXT | tee outfile
if grep "example text message" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
# clear the cache of unbound, but not cachedb testframe cache
echo "> unbound-control flush"
$PRE/unbound-control -c ub.conf flush_type txt1.example.com. TXT
if test $? -ne 0; then
echo "wrong exit value."
exit 1
else
echo "exit value: OK"
fi
echo "> dig txt1.example.com. from cachedb"
dig @localhost -p $UNBOUND_PORT txt1.example.com. TXT | tee outfile
if grep "example text message" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
# start the forwarder again.
echo "> stop ldns-testns"
kill_pid $FWD_PID
echo "> start ldns-testns"
$LDNS_TESTNS -p $FWD_PORT cachedb_no_store.testns >fwd3.log 2>&1 &
FWD_PID=$!
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
wait_ldns_testns_up fwd3.log
# stop unbound to flush the cachedb cache
echo "> stop unbound"
kill_pid `cat unbound.pid`
echo ""
echo "> config unbound with cachedb-no-store: yes"
echo "cachedb: cachedb-no-store: yes" >> ub.conf
# start unbound again.
echo "> start unbound"
$PRE/unbound -d -c ub.conf >unbound2.log 2>&1 &
UNBOUND_PID=$!
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
wait_unbound_up unbound2.log
echo ""
echo "> dig txt1.example.com."
dig @localhost -p $UNBOUND_PORT txt1.example.com. TXT | tee outfile
if grep "example text message" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
# stop the forwarder with servfail, to check the answer came from the cache
echo "> stop ldns-testns"
kill_pid $FWD_PID
echo "> start ldns-testns with servfails"
$LDNS_TESTNS -p $FWD_PORT cachedb_no_store.servfail.testns >fwd4.log 2>&1 &
FWD_PID=$!
echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
wait_ldns_testns_up fwd4.log
echo "> dig txt1.example.com. from unbound cache"
dig @localhost -p $UNBOUND_PORT txt1.example.com. TXT | tee outfile
if grep "example text message" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
# clear the cache of unbound, but not cachedb testframe cache
echo "> unbound-control flush"
$PRE/unbound-control -c ub.conf flush_type txt1.example.com. TXT
if test $? -ne 0; then
echo "wrong exit value."
exit 1
else
echo "exit value: OK"
fi
echo "> dig txt1.example.com. from cachedb, but that has no message stored"
dig @localhost -p $UNBOUND_PORT txt1.example.com. TXT | tee outfile
if grep "SERVFAIL" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
exit 0
@@ -1,9 +0,0 @@
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
txt1.example.com. IN TXT
SECTION ANSWER
txt1.example.com. IN TXT "example text message"
ENTRY_END
-3
View File
@@ -162,9 +162,6 @@ SECTION QUESTION
example.com. IN ANY
ENTRY_END
; Allow validation resuming for the RRSIGs
STEP 2 TIME_PASSES ELAPSE 0.05
; recursion happens here.
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
-3
View File
@@ -164,9 +164,6 @@ SECTION QUESTION
example.com. IN ANY
ENTRY_END
; Allow validation resuming for the RRSIGs
STEP 2 TIME_PASSES ELAPSE 0.05
; recursion happens here.
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
-3
View File
@@ -199,9 +199,6 @@ 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
-3
View File
@@ -156,9 +156,6 @@ SECTION QUESTION
www.example.com. IN A
ENTRY_END
; Allow validation resuming for NSEC3 hash calculations
STEP 2 TIME_PASSES ELAPSE 0.05
; recursion happens here.
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
-5
View File
@@ -382,7 +382,6 @@ config_create(void)
#ifdef USE_CACHEDB
if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit;
if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit;
cfg->cachedb_no_store = 0;
#ifdef USE_REDIS
if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
cfg->redis_server_path = NULL;
@@ -823,9 +822,6 @@ int config_set_option(struct config_file* cfg, const char* opt,
{ IS_NUMBER_OR_ZERO; cfg->ipsecmod_max_ttl = atoi(val); }
else S_YNO("ipsecmod-strict:", ipsecmod_strict)
#endif
#ifdef USE_CACHEDB
else S_YNO("cachedb-no-store:", cachedb_no_store)
#endif /* USE_CACHEDB */
else if(strcmp(opt, "define-tag:") ==0) {
return config_add_tag(cfg, val);
/* val_sig_skew_min, max and val_max_restart are copied into val_env
@@ -1314,7 +1310,6 @@ config_get_option(struct config_file* cfg, const char* opt,
#ifdef USE_CACHEDB
else O_STR(opt, "backend", cachedb_backend)
else O_STR(opt, "secret-seed", cachedb_secret)
else O_YNO(opt, "cachedb-no-store", cachedb_no_store)
#ifdef USE_REDIS
else O_STR(opt, "redis-server-host", redis_server_host)
else O_DEC(opt, "redis-server-port", redis_server_port)
-2
View File
@@ -701,8 +701,6 @@ struct config_file {
char* cachedb_backend;
/** secret seed for hash key calculation */
char* cachedb_secret;
/** cachedb that does not store, but only reads from database, if on */
int cachedb_no_store;
#ifdef USE_REDIS
/** redis server's IP address or host name */
char* redis_server_host;
-1
View File
@@ -558,7 +558,6 @@ ipsecmod-strict{COLON} { YDVAR(1, VAR_IPSECMOD_STRICT) }
cachedb{COLON} { YDVAR(0, VAR_CACHEDB) }
backend{COLON} { YDVAR(1, VAR_CACHEDB_BACKEND) }
secret-seed{COLON} { YDVAR(1, VAR_CACHEDB_SECRETSEED) }
cachedb-no-store{COLON} { YDVAR(1, VAR_CACHEDB_NO_STORE) }
redis-server-host{COLON} { YDVAR(1, VAR_CACHEDB_REDISHOST) }
redis-server-port{COLON} { YDVAR(1, VAR_CACHEDB_REDISPORT) }
redis-server-path{COLON} { YDVAR(1, VAR_CACHEDB_REDISPATH) }
+2 -15
View File
@@ -199,7 +199,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_INTERFACE_ACTION VAR_INTERFACE_VIEW VAR_INTERFACE_TAG
%token VAR_INTERFACE_TAG_ACTION VAR_INTERFACE_TAG_DATA
%token VAR_PROXY_PROTOCOL_PORT VAR_STATISTICS_INHIBIT_ZERO
%token VAR_HARDEN_UNKNOWN_ADDITIONAL VAR_DISABLE_EDNS_DO VAR_CACHEDB_NO_STORE
%token VAR_HARDEN_UNKNOWN_ADDITIONAL VAR_DISABLE_EDNS_DO
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -3712,7 +3712,7 @@ contents_cachedb: contents_cachedb content_cachedb
content_cachedb: cachedb_backend_name | cachedb_secret_seed |
redis_server_host | redis_server_port | redis_timeout |
redis_expire_records | redis_server_path | redis_server_password |
cachedb_no_store | redis_logical_db
redis_logical_db
;
cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
{
@@ -3738,19 +3738,6 @@ cachedb_secret_seed: VAR_CACHEDB_SECRETSEED STRING_ARG
#endif
}
;
cachedb_no_store: VAR_CACHEDB_NO_STORE STRING_ARG
{
#ifdef USE_CACHEDB
OUTYY(("P(cachedb_no_store:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->cachedb_no_store = (strcmp($2, "yes")==0);
#else
OUTYY(("P(Compiled without cachedb, ignoring)\n"));
#endif
free($2);
}
;
redis_server_host: VAR_CACHEDB_REDISHOST STRING_ARG
{
#if defined(USE_CACHEDB) && defined(USE_REDIS)
-3
View File
@@ -886,9 +886,6 @@ ede_trim_text(struct edns_option** list)
curr->opt_len = 2;
prev = curr;
curr = curr->next;
} else {
prev = curr;
curr = curr->next;
}
} else {
/* continue */
+1 -1
View File
@@ -108,6 +108,7 @@ fptr_whitelist_comm_point(comm_point_callback_type *fptr)
else if(fptr == &outnet_tcp_cb) return 1;
else if(fptr == &tube_handle_listen) return 1;
else if(fptr == &auth_xfer_probe_udp_callback) return 1;
else if(fptr == &auth_xfer_probe_tcp_callback) return 1;
else if(fptr == &auth_xfer_transfer_tcp_callback) return 1;
else if(fptr == &auth_xfer_transfer_http_callback) return 1;
return 0;
@@ -131,7 +132,6 @@ 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
+1 -1
View File
@@ -187,7 +187,7 @@ void log_ident_set_default(const char* id)
default_ident = id;
}
void log_ident_revert_to_default(void)
void log_ident_revert_to_default()
{
ident = default_ident;
}
+7 -8
View File
@@ -952,11 +952,11 @@ void log_crypto_err_code(const char* str, unsigned long err)
#endif /* HAVE_SSL */
}
#ifdef HAVE_SSL
/** Print crypt erro with SSL_get_error want code and err_get_error code */
static void log_crypto_err_io_code_arg(const char* str, int r,
unsigned long err, int err_present)
{
#ifdef HAVE_SSL
int print_errno = 0, print_crypto_err = 0;
const char* inf = NULL;
@@ -982,21 +982,15 @@ static void log_crypto_err_io_code_arg(const char* str, int r,
case SSL_ERROR_WANT_X509_LOOKUP:
inf = "want X509 lookup";
break;
#ifdef SSL_ERROR_WANT_ASYNC
case SSL_ERROR_WANT_ASYNC:
inf = "want async";
break;
#endif
#ifdef SSL_ERROR_WANT_ASYNC_JOB
case SSL_ERROR_WANT_ASYNC_JOB:
inf = "want async job";
break;
#endif
#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
case SSL_ERROR_WANT_CLIENT_HELLO_CB:
inf = "want client hello cb";
break;
#endif
case SSL_ERROR_SYSCALL:
print_errno = 1;
inf = "syscall";
@@ -1033,8 +1027,13 @@ static void log_crypto_err_io_code_arg(const char* str, int r,
log_err("str: %s", inf);
}
}
}
#else
(void)str;
(void)r;
(void)err;
(void)err_present;
#endif /* HAVE_SSL */
}
void log_crypto_err_io(const char* str, int r)
{
+1 -7
View File
@@ -1070,13 +1070,7 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
fptr_ok(fptr_whitelist_comm_point(rep.c->callback));
if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) {
/* send back immediate reply */
struct sldns_buffer *buffer;
#ifdef USE_DNSCRYPT
buffer = rep.c->dnscrypt_buffer;
#else
buffer = rep.c->buffer;
#endif
(void)comm_point_send_udp_msg_if(rep.c, buffer,
(void)comm_point_send_udp_msg_if(rep.c, rep.c->buffer,
(struct sockaddr*)&rep.remote_addr,
rep.remote_addrlen, &rep);
}
+1 -2
View File
@@ -181,7 +181,6 @@ 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;
@@ -189,7 +188,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, &verified);
reason_bogus, LDNS_SECTION_AUTHORITY, qstate);
if(d->security == sec_status_secure) {
rrset_update_sec_status(env->rrset_cache, nsec, *env->now);
return 1;
+70 -246
View File
@@ -57,19 +57,6 @@
/* 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
@@ -545,17 +532,6 @@ 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)
@@ -670,7 +646,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 2;
return 1;
}
/* create a new entry */
c = (struct nsec3_cached_hash*)regional_alloc(region, sizeof(*c));
@@ -682,10 +658,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; /* returns -1 or 0 */
return r;
r = nsec3_calc_b32(region, buf, c);
if(r != 1)
return r; /* returns 0 */
return r;
#ifdef UNBOUND_DEBUG
n =
#else
@@ -728,7 +704,6 @@ 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
@@ -755,50 +730,34 @@ 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,
struct nsec3_cache_table* ct, uint8_t* nm, size_t nmlen,
struct ub_packed_rrset_key** rrset, int* rr,
int* calculations)
rbtree_type* ct, uint8_t* nm, size_t nmlen,
struct ub_packed_rrset_key** rrset, int* rr)
{
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->ct, ct->region, env->scratch_buffer,
r = nsec3_hash_name(ct, env->scratch, env->scratch_buffer,
s, i_rr, nm, nmlen, &hash);
if(r == 0) {
log_err("nsec3: malloc failure");
break; /* alloc failure */
} 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;
}
} 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;
}
}
*rrset = NULL;
@@ -816,7 +775,6 @@ 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. */
@@ -865,51 +823,35 @@ 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,
struct nsec3_cache_table* ct, uint8_t* nm, size_t nmlen,
struct ub_packed_rrset_key** rrset, int* rr,
int* calculations)
rbtree_type* ct, uint8_t* nm, size_t nmlen,
struct ub_packed_rrset_key** rrset, int* rr)
{
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->ct, ct->region, env->scratch_buffer,
r = nsec3_hash_name(ct, env->scratch, env->scratch_buffer,
s, i_rr, nm, nmlen, &hash);
if(r == 0) {
log_err("nsec3: malloc failure");
break; /* alloc failure */
} 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;
}
} 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;
}
}
*rrset = NULL;
@@ -927,13 +869,11 @@ 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,
struct nsec3_cache_table* ct, struct query_info* qinfo,
struct ce_response* ce, int* calculations)
nsec3_find_closest_encloser(struct module_env* env, struct nsec3_filter* flt,
rbtree_type* ct, struct query_info* qinfo, struct ce_response* ce)
{
uint8_t* nm = qinfo->qname;
size_t nmlen = qinfo->qname_len;
@@ -948,12 +888,8 @@ 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, calculations)) {
&ce->ce_rrset, &ce->ce_rr)) {
ce->ce = nm;
ce->ce_len = nmlen;
return 1;
@@ -997,38 +933,22 @@ 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,
struct nsec3_cache_table* ct, struct query_info* qinfo,
int prove_does_not_exist, struct ce_response* ce, int* calculations)
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)
{
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, 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;
}
if(!nsec3_find_closest_encloser(env, flt, ct, qinfo, ce)) {
verbose(VERB_ALGO, "nsec3 proveClosestEncloser: could "
"not find a candidate for the closest encloser.");
return sec_status_bogus;
@@ -1069,23 +989,9 @@ 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, 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;
}
&ce->nc_rrset, &ce->nc_rr)) {
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;
@@ -1113,8 +1019,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,
struct nsec3_cache_table* ct, struct query_info* qinfo, int* calc)
nsec3_do_prove_nameerror(struct module_env* env, struct nsec3_filter* flt,
rbtree_type* ct, struct query_info* qinfo)
{
struct ce_response ce;
uint8_t* wc;
@@ -1126,15 +1032,11 @@ 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, calc);
sec = nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce);
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;
@@ -1144,27 +1046,9 @@ 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(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;
}
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)) {
verbose(VERB_ALGO, "nsec3 nameerror proof: could not prove "
"that the applicable wildcard did not exist.");
return sec_status_bogus;
@@ -1180,13 +1064,14 @@ 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 nsec3_cache_table* ct, int* calc)
struct query_info* qinfo, struct key_entry_key* kkey)
{
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 */
@@ -1194,7 +1079,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, calc);
return nsec3_do_prove_nameerror(env, &flt, &ct, qinfo);
}
/*
@@ -1204,9 +1089,8 @@ 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,
struct nsec3_cache_table* ct, struct query_info* qinfo,
int* calc)
nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
rbtree_type* ct, struct query_info* qinfo)
{
struct ce_response ce;
uint8_t* wc;
@@ -1216,7 +1100,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, calc)) {
&rrset, &rr)) {
/* cases 1 and 2 */
if(nsec3_has_type(rrset, rr, qinfo->qtype)) {
verbose(VERB_ALGO, "proveNodata: Matching NSEC3 "
@@ -1260,23 +1144,11 @@ 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",
MAX_NSEC3_CALCULATIONS);
return sec_status_unchecked;
}
/* For cases 3 - 5, we need the proven closest encloser, and it
* can't match qname. Although, at this point, we know that it
* won't since we just checked that. */
sec = nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce, calc);
sec = nsec3_prove_closest_encloser(env, flt, ct, qinfo, 1, &ce);
if(sec == sec_status_bogus) {
verbose(VERB_ALGO, "proveNodata: did not match qname, "
"nor found a proven closest encloser.");
@@ -1285,17 +1157,14 @@ nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
verbose(VERB_ALGO, "proveNodata: closest nsec3 is insecure "
"delegation.");
return sec_status_insecure;
} else if(sec==sec_status_unchecked) {
return sec_status_unchecked;
}
/* Case 3: removed */
/* Case 4: */
log_assert(ce.ce);
wc = nsec3_ce_wildcard(ct->region, ce.ce, ce.ce_len, &wclen);
if(wc && find_matching_nsec3(env, flt, ct, wc, wclen, &rrset, &rr,
calc)) {
wc = nsec3_ce_wildcard(env->scratch, ce.ce, ce.ce_len, &wclen);
if(wc && find_matching_nsec3(env, flt, ct, wc, wclen, &rrset, &rr)) {
/* found wildcard */
if(nsec3_has_type(rrset, rr, qinfo->qtype)) {
verbose(VERB_ALGO, "nsec3 nodata proof: matching "
@@ -1326,18 +1195,6 @@ nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
}
return sec_status_secure;
}
if(*calc == MAX_NSEC3_ERRORS) {
verbose(VERB_ALGO, "nsec3 nodata proof: all attempted hash "
"calculations were erroneous while matching "
"wildcard, bogus");
return sec_status_bogus;
} else if(*calc >= MAX_NSEC3_CALCULATIONS) {
verbose(VERB_ALGO, "nsec3 nodata proof: reached "
"MAX_NSEC3_CALCULATIONS (%d) while matching "
"wildcard, unchecked still",
MAX_NSEC3_CALCULATIONS);
return sec_status_unchecked;
}
/* Case 5: */
/* Due to forwarders, cnames, and other collating effects, we
@@ -1366,27 +1223,28 @@ nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
enum sec_status
nsec3_prove_nodata(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 nsec3_cache_table* ct, int* calc)
struct query_info* qinfo, struct key_entry_key* kkey)
{
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 */
if(nsec3_iteration_count_high(ve, &flt, kkey))
return sec_status_insecure; /* iteration count too high */
return nsec3_do_prove_nodata(env, &flt, ct, qinfo, calc);
return nsec3_do_prove_nodata(env, &flt, &ct, qinfo);
}
enum sec_status
nsec3_prove_wildcard(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, uint8_t* wc,
struct nsec3_cache_table* ct, int* calc)
struct query_info* qinfo, struct key_entry_key* kkey, uint8_t* wc)
{
rbtree_type ct;
struct nsec3_filter flt;
struct ce_response ce;
uint8_t* nc;
@@ -1396,6 +1254,7 @@ nsec3_prove_wildcard(struct module_env* env, struct val_env* ve,
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 */
@@ -1413,22 +1272,8 @@ nsec3_prove_wildcard(struct module_env* env, struct val_env* ve,
/* Now we still need to prove that the original data did not exist.
* 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, calc)) {
if(*calc == MAX_NSEC3_ERRORS) {
verbose(VERB_ALGO, "proveWildcard: did not find a "
"covering NSEC3 that covered the next closer "
"name; all attempted hash calculations were "
"erroneous; bogus");
return sec_status_bogus;
} else if(*calc >= MAX_NSEC3_CALCULATIONS) {
verbose(VERB_ALGO, "proveWildcard: did not find a "
"covering NSEC3 that covered the next closer "
"name; reached MAX_NSEC3_CALCULATIONS "
"(%d); unchecked still",
MAX_NSEC3_CALCULATIONS);
return sec_status_unchecked;
}
if(!find_covering_nsec3(env, &flt, &ct, nc, nc_len,
&ce.nc_rrset, &ce.nc_rr)) {
verbose(VERB_ALGO, "proveWildcard: did not find a covering "
"NSEC3 that covered the next closer name.");
return sec_status_bogus;
@@ -1449,7 +1294,6 @@ list_is_secure(struct module_env* env, struct val_env* ve,
{
struct packed_rrset_data* d;
size_t i;
int verified = 0;
for(i=0; i<num; i++) {
d = (struct packed_rrset_data*)list[i]->entry.data;
if(list[i]->rk.type != htons(LDNS_RR_TYPE_NSEC3))
@@ -1460,8 +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, reason_bogus, LDNS_SECTION_AUTHORITY, qstate,
&verified);
reason, reason_bogus, LDNS_SECTION_AUTHORITY, qstate);
if(d->security != sec_status_secure) {
verbose(VERB_ALGO, "NSEC3 did not verify");
return 0;
@@ -1475,16 +1318,13 @@ 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,
sldns_ede_code* reason_bogus, struct module_qstate* qstate,
struct nsec3_cache_table* ct)
sldns_ede_code* reason_bogus, struct module_qstate* qstate)
{
rbtree_type ct;
struct nsec3_filter flt;
struct ce_response ce;
struct ub_packed_rrset_key* rrset;
int rr;
int calc = 0;
enum sec_status sec;
log_assert(qinfo->qtype == LDNS_RR_TYPE_DS);
if(!list || num == 0 || !kkey || !key_entry_isgood(kkey)) {
@@ -1495,6 +1335,7 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
*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) {
*reason = "no NSEC3 records";
@@ -1505,8 +1346,8 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
/* Look for a matching NSEC3 to qname -- this is the normal
* NODATA case. */
if(find_matching_nsec3(env, &flt, ct, qinfo->qname, qinfo->qname_len,
&rrset, &rr, &calc)) {
if(find_matching_nsec3(env, &flt, &ct, qinfo->qname, qinfo->qname_len,
&rrset, &rr)) {
/* If the matching NSEC3 has the SOA bit set, it is from
* the wrong zone (the child instead of the parent). If
* it has the DS bit set, then we were lied to. */
@@ -1529,24 +1370,10 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
/* Otherwise, this proves no DS. */
return sec_status_secure;
}
if(calc == MAX_NSEC3_ERRORS) {
verbose(VERB_ALGO, "nsec3 provenods: 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, "nsec3 provenods: reached "
"MAX_NSEC3_CALCULATIONS (%d) while finding a "
"matching NSEC3, unchecked still",
MAX_NSEC3_CALCULATIONS);
return sec_status_unchecked;
}
/* Otherwise, we are probably in the opt-out case. */
sec = nsec3_prove_closest_encloser(env, &flt, ct, qinfo, 1, &ce, &calc);
if(sec == sec_status_unchecked) {
return sec_status_unchecked;
} else if(sec != sec_status_secure) {
if(nsec3_prove_closest_encloser(env, &flt, &ct, qinfo, 1, &ce)
!= sec_status_secure) {
/* an insecure delegation *above* the qname does not prove
* anything about this qname exactly, and bogus is bogus */
verbose(VERB_ALGO, "nsec3 provenods: did not match qname, "
@@ -1580,16 +1407,17 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
enum sec_status
nsec3_prove_nxornodata(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, int* nodata,
struct nsec3_cache_table* ct, int* calc)
struct ub_packed_rrset_key** list, size_t num,
struct query_info* qinfo, struct key_entry_key* kkey, int* nodata)
{
enum sec_status sec, secnx;
rbtree_type ct;
struct nsec3_filter flt;
*nodata = 0;
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 */
@@ -1599,20 +1427,16 @@ nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve,
/* try nxdomain and nodata after another, while keeping the
* hash cache intact */
secnx = nsec3_do_prove_nameerror(env, &flt, ct, qinfo, calc);
secnx = nsec3_do_prove_nameerror(env, &flt, &ct, qinfo);
if(secnx==sec_status_secure)
return sec_status_secure;
else if(secnx == sec_status_unchecked)
return sec_status_unchecked;
sec = nsec3_do_prove_nodata(env, &flt, ct, qinfo, calc);
sec = nsec3_do_prove_nodata(env, &flt, &ct, qinfo);
if(sec==sec_status_secure) {
*nodata = 1;
} else if(sec == sec_status_insecure) {
*nodata = 1;
} else if(secnx == sec_status_insecure) {
sec = sec_status_insecure;
} else if(sec == sec_status_unchecked) {
return sec_status_unchecked;
}
return sec;
}
+12 -48
View File
@@ -98,15 +98,6 @@ struct sldns_buffer;
/** The SHA1 hash algorithm for NSEC3 */
#define NSEC3_HASH_SHA1 0x01
/**
* Cache table for NSEC3 hashes.
* It keeps a *pointer* to the region its items are allocated.
*/
struct nsec3_cache_table {
rbtree_type* ct;
struct regional* region;
};
/**
* Determine if the set of NSEC3 records provided with a response prove NAME
* ERROR. This means that the NSEC3s prove a) the closest encloser exists,
@@ -119,18 +110,14 @@ struct nsec3_cache_table {
* @param num: number of RRsets in the array to examine.
* @param qinfo: query that is verified for.
* @param kkey: key entry that signed the NSEC3s.
* @param ct: cached hashes table.
* @param calc: current hash calculations.
* @return:
* sec_status SECURE of the Name Error is proven by the NSEC3 RRs,
* BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored,
* UNCHECKED if no more hash calculations are allowed at this point.
* BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored.
*/
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 nsec3_cache_table* ct, int* calc);
struct query_info* qinfo, struct key_entry_key* kkey);
/**
* Determine if the NSEC3s provided in a response prove the NOERROR/NODATA
@@ -157,18 +144,15 @@ nsec3_prove_nameerror(struct module_env* env, struct val_env* ve,
* @param num: number of RRsets in the array to examine.
* @param qinfo: query that is verified for.
* @param kkey: key entry that signed the NSEC3s.
* @param ct: cached hashes table.
* @param calc: current hash calculations.
* @return:
* sec_status SECURE of the proposition is proven by the NSEC3 RRs,
* BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored,
* UNCHECKED if no more hash calculations are allowed at this point.
* BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored.
*/
enum sec_status
nsec3_prove_nodata(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 nsec3_cache_table* ct, int* calc);
struct query_info* qinfo, struct key_entry_key* kkey);
/**
* Prove that a positive wildcard match was appropriate (no direct match
@@ -182,18 +166,14 @@ nsec3_prove_nodata(struct module_env* env, struct val_env* ve,
* @param kkey: key entry that signed the NSEC3s.
* @param wc: The purported wildcard that matched. This is the wildcard name
* as *.wildcard.name., with the *. label already removed.
* @param ct: cached hashes table.
* @param calc: current hash calculations.
* @return:
* sec_status SECURE of the proposition is proven by the NSEC3 RRs,
* BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored,
* UNCHECKED if no more hash calculations are allowed at this point.
* BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored.
*/
enum sec_status
nsec3_prove_wildcard(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, uint8_t* wc,
struct nsec3_cache_table* ct, int* calc);
struct query_info* qinfo, struct key_entry_key* kkey, uint8_t* wc);
/**
* Prove that a DS response either had no DS, or wasn't a delegation point.
@@ -209,20 +189,17 @@ nsec3_prove_wildcard(struct module_env* env, struct val_env* ve,
* @param reason: string for bogus result.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param qstate: qstate with region.
* @param ct: cached hashes table.
* @return:
* sec_status SECURE of the proposition is proven by the NSEC3 RRs,
* BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored.
* or if there was no DS in an insecure (i.e., opt-in) way,
* INDETERMINATE if it was clear that this wasn't a delegation point,
* UNCHECKED if no more hash calculations are allowed at this point.
* INDETERMINATE if it was clear that this wasn't a delegation point.
*/
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,
sldns_ede_code* reason_bogus, struct module_qstate* qstate,
struct nsec3_cache_table* ct);
sldns_ede_code* reason_bogus, struct module_qstate* qstate);
/**
* Prove NXDOMAIN or NODATA.
@@ -235,18 +212,14 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
* @param kkey: key entry that signed the NSEC3s.
* @param nodata: if return value is secure, this indicates if nodata or
* nxdomain was proven.
* @param ct: cached hashes table.
* @param calc: current hash calculations.
* @return:
* sec_status SECURE of the proposition is proven by the NSEC3 RRs,
* BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored,
* UNCHECKED if no more hash calculations are allowed at this point.
* BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored.
*/
enum sec_status
nsec3_prove_nxornodata(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, int* nodata,
struct nsec3_cache_table* ct, int* calc);
struct query_info* qinfo, struct key_entry_key* kkey, int* nodata);
/**
* The NSEC3 hash result storage.
@@ -283,14 +256,6 @@ struct nsec3_cached_hash {
*/
int nsec3_hash_cmp(const void* c1, const void* c2);
/**
* Initialise the NSEC3 cache table.
* @param ct: the nsec3 cache table.
* @param region: the region where allocations for the table will happen.
* @return true on success, false on malloc error.
*/
int nsec3_cache_table_init(struct nsec3_cache_table* ct, struct regional* region);
/**
* Obtain the hash of an owner name.
* Used internally by the nsec3 proof functions in this file.
@@ -307,8 +272,7 @@ int nsec3_cache_table_init(struct nsec3_cache_table* ct, struct regional* region
* @param dname_len: the length of the name.
* @param hash: the hash node is returned on success.
* @return:
* 2 on success, hash from cache is returned.
* 1 on success, newly computed hash is returned.
* 1 on success, either from cache or newly hashed hash is returned.
* 0 on a malloc failure.
* -1 if the NSEC3 rr was badly formatted (i.e. formerr).
*/
+3 -34
View File
@@ -79,9 +79,6 @@
#include <openssl/engine.h>
#endif
/** Maximum number of RRSIG validations for an RRset. */
#define MAX_VALIDATE_RRSIGS 8
/** return number of rrs in an rrset */
static size_t
rrset_get_count(struct ub_packed_rrset_key* rrset)
@@ -545,8 +542,6 @@ int algo_needs_missing(struct algo_needs* n)
* @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.
* @param numverified: incremented when the number of RRSIG validations
* increases.
* @return secure if any key signs *this* signature. bogus if no key signs it,
* unchecked on error, or indeterminate if all keys are not supported by
* the crypto library (openssl3+ only).
@@ -557,8 +552,7 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
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,
int* numverified)
sldns_pkt_section section, struct module_qstate* qstate)
{
/* find matching keys and check them */
enum sec_status sec = sec_status_bogus;
@@ -582,7 +576,6 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
tag != dnskey_calc_keytag(dnskey, i))
continue;
numchecked ++;
(*numverified)++;
/* see if key verifies */
sec = dnskey_verify_rrset_sig(env->scratch,
@@ -593,13 +586,6 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
return sec;
else if(sec == sec_status_indeterminate)
numindeterminate ++;
if(*numverified > MAX_VALIDATE_RRSIGS) {
*reason = "too many RRSIG validations";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
verbose(VERB_ALGO, "verify sig: too many RRSIG validations");
return sec_status_bogus;
}
}
if(numchecked == 0) {
*reason = "signatures from unknown keys";
@@ -623,7 +609,7 @@ 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_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate, int* verified)
sldns_pkt_section section, struct module_qstate* qstate)
{
enum sec_status sec;
size_t i, num;
@@ -631,7 +617,6 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
/* make sure that for all DNSKEY algorithms there are valid sigs */
struct algo_needs needs;
int alg;
*verified = 0;
num = rrset_get_sigcount(rrset);
if(num == 0) {
@@ -656,7 +641,7 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
for(i=0; i<num; i++) {
sec = dnskeyset_verify_rrset_sig(env, ve, *env->now, rrset,
dnskey, i, &sortree, reason, reason_bogus,
section, qstate, verified);
section, qstate);
/* see which algorithm has been fixed up */
if(sec == sec_status_secure) {
if(!sigalg)
@@ -668,13 +653,6 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
algo_needs_set_bogus(&needs,
(uint8_t)rrset_get_sig_algo(rrset, i));
}
if(*verified > MAX_VALIDATE_RRSIGS) {
verbose(VERB_QUERY, "rrset failed to verify, too many RRSIG validations");
*reason = "too many RRSIG validations";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus;
}
}
if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
verbose(VERB_ALGO, "rrset failed to verify: "
@@ -713,7 +691,6 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
int buf_canon = 0;
uint16_t tag = dnskey_calc_keytag(dnskey, dnskey_idx);
int algo = dnskey_get_algo(dnskey, dnskey_idx);
int numverified = 0;
num = rrset_get_sigcount(rrset);
if(num == 0) {
@@ -737,16 +714,8 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
if(sec == sec_status_secure)
return sec;
numchecked ++;
numverified ++;
if(sec == sec_status_indeterminate)
numindeterminate ++;
if(numverified > MAX_VALIDATE_RRSIGS) {
verbose(VERB_QUERY, "rrset failed to verify, too many RRSIG validations");
*reason = "too many RRSIG validations";
if(reason_bogus)
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec_status_bogus;
}
}
verbose(VERB_ALGO, "rrset failed to verify: all signatures are bogus");
if(!numchecked) {
+1 -2
View File
@@ -260,7 +260,6 @@ uint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx);
* @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.
* @param verified: if not NULL the number of RRSIG validations is returned.
* @return SECURE if one key in the set verifies one rrsig.
* UNCHECKED on allocation errors, unsupported algorithms, malformed data,
* and BOGUS on verification failures (no keys match any signatures).
@@ -269,7 +268,7 @@ 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_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate, int* verified);
sldns_pkt_section section, struct module_qstate* qstate);
/**
+4 -18
View File
@@ -58,10 +58,6 @@
#include "sldns/wire2str.h"
#include "sldns/parseutil.h"
/** Maximum allowed digest match failures per DS, for DNSKEYs with the same
* properties */
#define MAX_DS_MATCH_FAILURES 4
enum val_classification
val_classify_response(uint16_t query_flags, struct query_info* origqinf,
struct query_info* qinf, struct reply_info* rep, size_t skip)
@@ -340,8 +336,7 @@ 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_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate,
int *verified)
sldns_pkt_section section, struct module_qstate* qstate)
{
enum sec_status sec;
struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
@@ -351,7 +346,6 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
log_nametypeclass(VERB_ALGO, "verify rrset cached",
rrset->rk.dname, ntohs(rrset->rk.type),
ntohs(rrset->rk.rrset_class));
*verified = 0;
return d->security;
}
/* check in the cache if verification has already been done */
@@ -360,13 +354,12 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
log_nametypeclass(VERB_ALGO, "verify rrset from cache",
rrset->rk.dname, ntohs(rrset->rk.type),
ntohs(rrset->rk.rrset_class));
*verified = 0;
return d->security;
}
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,
reason_bogus, section, qstate, verified);
reason_bogus, section, qstate);
verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec));
regional_free_all(env->scratch);
@@ -400,8 +393,7 @@ 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_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate,
int* verified)
sldns_pkt_section section, struct module_qstate* qstate)
{
/* temporary dnskey rrset-key */
struct ub_packed_rrset_key dnskey;
@@ -415,7 +407,7 @@ 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,
reason_bogus, section, qstate, verified);
reason_bogus, section, qstate);
return sec;
}
@@ -447,12 +439,6 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
if(!ds_digest_match_dnskey(env, dnskey_rrset, i, ds_rrset,
ds_idx)) {
verbose(VERB_ALGO, "DS match attempt failed");
if(numchecked > numhashok + MAX_DS_MATCH_FAILURES) {
verbose(VERB_ALGO, "DS match attempt reached "
"MAX_DS_MATCH_FAILURES (%d); bogus",
MAX_DS_MATCH_FAILURES);
return sec_status_bogus;
}
continue;
}
numhashok++;
+1 -3
View File
@@ -124,14 +124,12 @@ void val_find_signer(enum val_classification subtype,
* @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.
* @param verified: if not NULL, the number of RRSIG validations is returned.
* @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_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate,
int* verified);
sldns_pkt_section section, struct module_qstate* qstate);
/**
* Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but
+75 -424
View File
@@ -64,15 +64,10 @@
#include "sldns/wire2str.h"
#include "sldns/str2wire.h"
/** Max number of RRSIGs to validate at once, suspend query for later. */
#define MAX_VALIDATE_AT_ONCE 8
/** Max number of validation suspends allowed, error out otherwise. */
#define MAX_VALIDATION_SUSPENDS 16
/* forward decl for cache response and normal super inform calls of a DS */
static void process_ds_response(struct module_qstate* qstate,
struct val_qstate* vq, int id, int rcode, struct dns_msg* msg,
struct query_info* qinfo, struct sock_list* origin, int* suspend);
struct query_info* qinfo, struct sock_list* origin);
/* Updates the suplied EDE (RFC8914) code selectively so we don't lose
@@ -297,21 +292,6 @@ val_new(struct module_qstate* qstate, int id)
return val_new_getmsg(qstate, vq);
}
/** reset validator query state for query restart */
static void
val_restart(struct val_qstate* vq)
{
struct comm_timer* temp_timer;
int restart_count;
if(!vq) return;
temp_timer = vq->suspend_timer;
restart_count = vq->restart_count+1;
memset(vq, 0, sizeof(*vq));
vq->suspend_timer = temp_timer;
vq->restart_count = restart_count;
vq->state = VAL_INIT_STATE;
}
/**
* Exit validation with an error status
*
@@ -618,42 +598,30 @@ prime_trust_anchor(struct module_qstate* qstate, struct val_qstate* vq,
* completed.
*
* @param qstate: query state.
* @param vq: validator query state.
* @param env: module env for verify.
* @param ve: validator env for verify.
* @param qchase: query that was made.
* @param chase_reply: answer to validate.
* @param key_entry: the key entry, which is trusted, and which matches
* the signer of the answer. The key entry isgood().
* @param suspend: returned true if the task takes too long and needs to
* suspend to continue the effort later.
* @return false if any of the rrsets in the an or ns sections of the message
* fail to verify. The message is then set to bogus.
*/
static int
validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
struct module_env* env, struct val_env* ve, struct query_info* qchase,
struct reply_info* chase_reply, struct key_entry_key* key_entry,
int* suspend)
validate_msg_signatures(struct module_qstate* qstate, struct module_env* env,
struct val_env* ve, struct query_info* qchase,
struct reply_info* chase_reply, struct key_entry_key* key_entry)
{
uint8_t* sname;
size_t i, slen;
struct ub_packed_rrset_key* s;
enum sec_status sec;
int dname_seen = 0, num_verifies = 0, verified, have_state = 0;
int dname_seen = 0;
char* reason = NULL;
sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
*suspend = 0;
if(vq->msg_signatures_state) {
/* Pick up the state, and reset it, may not be needed now. */
vq->msg_signatures_state = 0;
have_state = 1;
}
/* validate the ANSWER section */
for(i=0; i<chase_reply->an_numrrsets; i++) {
if(have_state && i <= vq->msg_signatures_index)
continue;
s = chase_reply->rrsets[i];
/* Skip the CNAME following a (validated) DNAME.
* Because of the normalization routines in the iterator,
@@ -672,7 +640,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
/* Verify the answer rrset */
sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason,
&reason_bogus, LDNS_SECTION_ANSWER, qstate, &verified);
&reason_bogus, LDNS_SECTION_ANSWER, qstate);
/* If the (answer) rrset failed to validate, then this
* message is BAD. */
if(sec != sec_status_secure) {
@@ -697,33 +665,14 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME) {
dname_seen = 1;
}
num_verifies += verified;
if(num_verifies > MAX_VALIDATE_AT_ONCE &&
i+1 < (env->cfg->val_clean_additional?
chase_reply->an_numrrsets+chase_reply->ns_numrrsets:
chase_reply->rrset_count)) {
/* If the number of RRSIGs exceeds the maximum in
* one go, suspend. Only suspend if there is a next
* rrset to verify, i+1<loopmax. Store where to
* continue later. */
*suspend = 1;
vq->msg_signatures_state = 1;
vq->msg_signatures_index = i;
verbose(VERB_ALGO, "msg signature validation "
"suspended");
return 0;
}
}
/* validate the AUTHORITY section */
for(i=chase_reply->an_numrrsets; i<chase_reply->an_numrrsets+
chase_reply->ns_numrrsets; i++) {
if(have_state && i <= vq->msg_signatures_index)
continue;
s = chase_reply->rrsets[i];
sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason,
&reason_bogus, LDNS_SECTION_AUTHORITY, qstate,
&verified);
&reason_bogus, LDNS_SECTION_AUTHORITY, qstate);
/* If anything in the authority section fails to be secure,
* we have a bad message. */
if(sec != sec_status_secure) {
@@ -737,18 +686,6 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
update_reason_bogus(chase_reply, reason_bogus);
return 0;
}
num_verifies += verified;
if(num_verifies > MAX_VALIDATE_AT_ONCE &&
i+1 < (env->cfg->val_clean_additional?
chase_reply->an_numrrsets+chase_reply->ns_numrrsets:
chase_reply->rrset_count)) {
*suspend = 1;
vq->msg_signatures_state = 1;
vq->msg_signatures_index = i;
verbose(VERB_ALGO, "msg signature validation "
"suspended");
return 0;
}
}
/* If set, the validator should clean the additional section of
@@ -758,103 +695,22 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
/* attempt to validate the ADDITIONAL section rrsets */
for(i=chase_reply->an_numrrsets+chase_reply->ns_numrrsets;
i<chase_reply->rrset_count; i++) {
if(have_state && i <= vq->msg_signatures_index)
continue;
s = chase_reply->rrsets[i];
/* only validate rrs that have signatures with the key */
/* leave others unchecked, those get removed later on too */
val_find_rrset_signer(s, &sname, &slen);
verified = 0;
if(sname && query_dname_compare(sname, key_entry->name)==0)
(void)val_verify_rrset_entry(env, ve, s, key_entry,
&reason, NULL, LDNS_SECTION_ADDITIONAL, qstate,
&verified);
&reason, NULL, LDNS_SECTION_ADDITIONAL, qstate);
/* the additional section can fail to be secure,
* it is optional, check signature in case we need
* to clean the additional section later. */
num_verifies += verified;
if(num_verifies > MAX_VALIDATE_AT_ONCE &&
i+1 < chase_reply->rrset_count) {
*suspend = 1;
vq->msg_signatures_state = 1;
vq->msg_signatures_index = i;
verbose(VERB_ALGO, "msg signature validation "
"suspended");
return 0;
}
}
return 1;
}
void
validate_suspend_timer_cb(void* arg)
{
struct module_qstate* qstate = (struct module_qstate*)arg;
verbose(VERB_ALGO, "validate_suspend timer, continue");
mesh_run(qstate->env->mesh, qstate->mesh_info, module_event_pass,
NULL);
}
/** Setup timer to continue validation of msg signatures later */
static int
validate_suspend_setup_timer(struct module_qstate* qstate,
struct val_qstate* vq, int id, enum val_state resume_state)
{
struct timeval tv;
int usec, slack, base;
if(vq->suspend_count >= MAX_VALIDATION_SUSPENDS) {
verbose(VERB_ALGO, "validate_suspend timer: "
"reached MAX_VALIDATION_SUSPENDS (%d); error out",
MAX_VALIDATION_SUSPENDS);
errinf(qstate, "max validation suspends reached, "
"too many RRSIG validations");
return 0;
}
verbose(VERB_ALGO, "validate_suspend timer, set for suspend");
vq->state = resume_state;
qstate->ext_state[id] = module_wait_reply;
if(!vq->suspend_timer) {
vq->suspend_timer = comm_timer_create(
qstate->env->worker_base,
validate_suspend_timer_cb, qstate);
if(!vq->suspend_timer) {
log_err("validate_suspend_setup_timer: "
"out of memory for comm_timer_create");
return 0;
}
}
/* The timer is activated later, after other events in the event
* loop have been processed. The query state can also be deleted,
* when the list is full and query states are dropped. */
/* Extend wait time if there are a lot of queries or if this one
* is taking long, to keep around cpu time for ordinary queries. */
usec = 50000; /* 50 msec */
slack = 0;
if(qstate->env->mesh->all.count >= qstate->env->mesh->max_reply_states)
slack += 3;
else if(qstate->env->mesh->all.count >= qstate->env->mesh->max_reply_states/2)
slack += 2;
else if(qstate->env->mesh->all.count >= qstate->env->mesh->max_reply_states/4)
slack += 1;
if(vq->suspend_count > 3)
slack += 3;
else if(vq->suspend_count > 0)
slack += vq->suspend_count;
if(slack != 0 && slack <= 12 /* No numeric overflow. */) {
usec = usec << slack;
}
/* Spread such timeouts within 90%-100% of the original timer. */
base = usec * 9/10;
usec = base + ub_random_max(qstate->env->rnd, usec-base);
tv.tv_usec = (usec % 1000000);
tv.tv_sec = (usec / 1000000);
vq->suspend_count ++;
comm_timer_set(vq->suspend_timer, &tv);
return 1;
}
/**
* Detect wrong truncated response (say from BIND 9.6.1 that is forwarding
* and saw the NS record without signatures from a referral).
@@ -953,17 +809,11 @@ remove_spurious_authority(struct reply_info* chase_reply,
* @param chase_reply: answer to that query to validate.
* @param kkey: the key entry, which is trusted, and which matches
* the signer of the answer. The key entry isgood().
* @param qstate: query state for the region.
* @param vq: validator state for the nsec3 cache table.
* @param nsec3_calculations: current nsec3 hash calculations.
* @param suspend: returned true if the task takes too long and needs to
* suspend to continue the effort later.
*/
static void
validate_positive_response(struct module_env* env, struct val_env* ve,
struct query_info* qchase, struct reply_info* chase_reply,
struct key_entry_key* kkey, struct module_qstate* qstate,
struct val_qstate* vq, int* nsec3_calculations, int* suspend)
struct key_entry_key* kkey)
{
uint8_t* wc = NULL;
size_t wl;
@@ -972,7 +822,6 @@ validate_positive_response(struct module_env* env, struct val_env* ve,
int nsec3s_seen = 0;
size_t i;
struct ub_packed_rrset_key* s;
*suspend = 0;
/* validate the ANSWER section - this will be the answer itself */
for(i=0; i<chase_reply->an_numrrsets; i++) {
@@ -1024,23 +873,17 @@ validate_positive_response(struct module_env* env, struct val_env* ve,
/* If this was a positive wildcard response that we haven't already
* proven, and we have NSEC3 records, try to prove it using the NSEC3
* records. */
if(wc != NULL && !wc_NSEC_ok && nsec3s_seen &&
nsec3_cache_table_init(&vq->nsec3_cache_table, qstate->region)) {
enum sec_status sec = nsec3_prove_wildcard(env, ve,
if(wc != NULL && !wc_NSEC_ok && nsec3s_seen) {
enum sec_status sec = nsec3_prove_wildcard(env, ve,
chase_reply->rrsets+chase_reply->an_numrrsets,
chase_reply->ns_numrrsets, qchase, kkey, wc,
&vq->nsec3_cache_table, nsec3_calculations);
chase_reply->ns_numrrsets, qchase, kkey, wc);
if(sec == sec_status_insecure) {
verbose(VERB_ALGO, "Positive wildcard response is "
"insecure");
chase_reply->security = sec_status_insecure;
return;
} else if(sec == sec_status_secure) {
} else if(sec == sec_status_secure)
wc_NSEC_ok = 1;
} else if(sec == sec_status_unchecked) {
*suspend = 1;
return;
}
}
/* If after all this, we still haven't proven the positive wildcard
@@ -1072,17 +915,11 @@ validate_positive_response(struct module_env* env, struct val_env* ve,
* @param chase_reply: answer to that query to validate.
* @param kkey: the key entry, which is trusted, and which matches
* the signer of the answer. The key entry isgood().
* @param qstate: query state for the region.
* @param vq: validator state for the nsec3 cache table.
* @param nsec3_calculations: current nsec3 hash calculations.
* @param suspend: returned true if the task takes too long and needs to
* suspend to continue the effort later.
*/
static void
validate_nodata_response(struct module_env* env, struct val_env* ve,
struct query_info* qchase, struct reply_info* chase_reply,
struct key_entry_key* kkey, struct module_qstate* qstate,
struct val_qstate* vq, int* nsec3_calculations, int* suspend)
struct key_entry_key* kkey)
{
/* Since we are here, there must be nothing in the ANSWER section to
* validate. */
@@ -1099,7 +936,6 @@ validate_nodata_response(struct module_env* env, struct val_env* ve,
int nsec3s_seen = 0; /* nsec3s seen */
struct ub_packed_rrset_key* s;
size_t i;
*suspend = 0;
for(i=chase_reply->an_numrrsets; i<chase_reply->an_numrrsets+
chase_reply->ns_numrrsets; i++) {
@@ -1138,23 +974,16 @@ validate_nodata_response(struct module_env* env, struct val_env* ve,
}
}
if(!has_valid_nsec && nsec3s_seen &&
nsec3_cache_table_init(&vq->nsec3_cache_table, qstate->region)) {
if(!has_valid_nsec && nsec3s_seen) {
enum sec_status sec = nsec3_prove_nodata(env, ve,
chase_reply->rrsets+chase_reply->an_numrrsets,
chase_reply->ns_numrrsets, qchase, kkey,
&vq->nsec3_cache_table, nsec3_calculations);
chase_reply->ns_numrrsets, qchase, kkey);
if(sec == sec_status_insecure) {
verbose(VERB_ALGO, "NODATA response is insecure");
chase_reply->security = sec_status_insecure;
return;
} else if(sec == sec_status_secure) {
} else if(sec == sec_status_secure)
has_valid_nsec = 1;
} else if(sec == sec_status_unchecked) {
/* check is incomplete; suspend */
*suspend = 1;
return;
}
}
if(!has_valid_nsec) {
@@ -1186,18 +1015,11 @@ validate_nodata_response(struct module_env* env, struct val_env* ve,
* @param kkey: the key entry, which is trusted, and which matches
* the signer of the answer. The key entry isgood().
* @param rcode: adjusted RCODE, in case of RCODE/proof mismatch leniency.
* @param qstate: query state for the region.
* @param vq: validator state for the nsec3 cache table.
* @param nsec3_calculations: current nsec3 hash calculations.
* @param suspend: returned true if the task takes too long and needs to
* suspend to continue the effort later.
*/
static void
validate_nameerror_response(struct module_env* env, struct val_env* ve,
struct query_info* qchase, struct reply_info* chase_reply,
struct key_entry_key* kkey, int* rcode,
struct module_qstate* qstate, struct val_qstate* vq,
int* nsec3_calculations, int* suspend)
struct key_entry_key* kkey, int* rcode)
{
int has_valid_nsec = 0;
int has_valid_wnsec = 0;
@@ -1207,7 +1029,6 @@ validate_nameerror_response(struct module_env* env, struct val_env* ve,
uint8_t* ce;
int ce_labs = 0;
int prev_ce_labs = 0;
*suspend = 0;
for(i=chase_reply->an_numrrsets; i<chase_reply->an_numrrsets+
chase_reply->ns_numrrsets; i++) {
@@ -1237,18 +1058,13 @@ validate_nameerror_response(struct module_env* env, struct val_env* ve,
nsec3s_seen = 1;
}
if((!has_valid_nsec || !has_valid_wnsec) && nsec3s_seen &&
nsec3_cache_table_init(&vq->nsec3_cache_table, qstate->region)) {
if((!has_valid_nsec || !has_valid_wnsec) && nsec3s_seen) {
/* use NSEC3 proof, both answer and auth rrsets, in case
* NSEC3s end up in the answer (due to qtype=NSEC3 or so) */
chase_reply->security = nsec3_prove_nameerror(env, ve,
chase_reply->rrsets, chase_reply->an_numrrsets+
chase_reply->ns_numrrsets, qchase, kkey,
&vq->nsec3_cache_table, nsec3_calculations);
if(chase_reply->security == sec_status_unchecked) {
*suspend = 1;
return;
} else if(chase_reply->security != sec_status_secure) {
chase_reply->ns_numrrsets, qchase, kkey);
if(chase_reply->security != sec_status_secure) {
verbose(VERB_QUERY, "NameError response failed nsec, "
"nsec3 proof was %s", sec_status_to_string(
chase_reply->security));
@@ -1260,34 +1076,26 @@ validate_nameerror_response(struct module_env* env, struct val_env* ve,
/* If the message fails to prove either condition, it is bogus. */
if(!has_valid_nsec) {
validate_nodata_response(env, ve, qchase, chase_reply, kkey,
qstate, vq, nsec3_calculations, suspend);
if(*suspend) return;
verbose(VERB_QUERY, "NameError response has failed to prove: "
"qname does not exist");
chase_reply->security = sec_status_bogus;
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
/* Be lenient with RCODE in NSEC NameError responses */
if(chase_reply->security == sec_status_secure) {
validate_nodata_response(env, ve, qchase, chase_reply, kkey);
if (chase_reply->security == sec_status_secure)
*rcode = LDNS_RCODE_NOERROR;
} else {
chase_reply->security = sec_status_bogus;
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
}
return;
}
if(!has_valid_wnsec) {
validate_nodata_response(env, ve, qchase, chase_reply, kkey,
qstate, vq, nsec3_calculations, suspend);
if(*suspend) return;
verbose(VERB_QUERY, "NameError response has failed to prove: "
"covering wildcard does not exist");
chase_reply->security = sec_status_bogus;
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
/* Be lenient with RCODE in NSEC NameError responses */
if (chase_reply->security == sec_status_secure) {
validate_nodata_response(env, ve, qchase, chase_reply, kkey);
if (chase_reply->security == sec_status_secure)
*rcode = LDNS_RCODE_NOERROR;
} else {
chase_reply->security = sec_status_bogus;
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
}
return;
}
@@ -1347,17 +1155,11 @@ validate_referral_response(struct reply_info* chase_reply)
* @param chase_reply: answer to that query to validate.
* @param kkey: the key entry, which is trusted, and which matches
* the signer of the answer. The key entry isgood().
* @param qstate: query state for the region.
* @param vq: validator state for the nsec3 cache table.
* @param nsec3_calculations: current nsec3 hash calculations.
* @param suspend: returned true if the task takes too long and needs to
* suspend to continue the effort later.
*/
static void
validate_any_response(struct module_env* env, struct val_env* ve,
struct query_info* qchase, struct reply_info* chase_reply,
struct key_entry_key* kkey, struct module_qstate* qstate,
struct val_qstate* vq, int* nsec3_calculations, int* suspend)
struct key_entry_key* kkey)
{
/* all answer and auth rrsets already verified */
/* but check if a wildcard response is given, then check NSEC/NSEC3
@@ -1368,7 +1170,6 @@ validate_any_response(struct module_env* env, struct val_env* ve,
int nsec3s_seen = 0;
size_t i;
struct ub_packed_rrset_key* s;
*suspend = 0;
if(qchase->qtype != LDNS_RR_TYPE_ANY) {
log_err("internal error: ANY validation called for non-ANY");
@@ -1423,25 +1224,19 @@ validate_any_response(struct module_env* env, struct val_env* ve,
/* If this was a positive wildcard response that we haven't already
* proven, and we have NSEC3 records, try to prove it using the NSEC3
* records. */
if(wc != NULL && !wc_NSEC_ok && nsec3s_seen &&
nsec3_cache_table_init(&vq->nsec3_cache_table, qstate->region)) {
if(wc != NULL && !wc_NSEC_ok && nsec3s_seen) {
/* look both in answer and auth section for NSEC3s */
enum sec_status sec = nsec3_prove_wildcard(env, ve,
enum sec_status sec = nsec3_prove_wildcard(env, ve,
chase_reply->rrsets,
chase_reply->an_numrrsets+chase_reply->ns_numrrsets,
qchase, kkey, wc, &vq->nsec3_cache_table,
nsec3_calculations);
chase_reply->an_numrrsets+chase_reply->ns_numrrsets,
qchase, kkey, wc);
if(sec == sec_status_insecure) {
verbose(VERB_ALGO, "Positive ANY wildcard response is "
"insecure");
chase_reply->security = sec_status_insecure;
return;
} else if(sec == sec_status_secure) {
} else if(sec == sec_status_secure)
wc_NSEC_ok = 1;
} else if(sec == sec_status_unchecked) {
*suspend = 1;
return;
}
}
/* If after all this, we still haven't proven the positive wildcard
@@ -1474,17 +1269,11 @@ validate_any_response(struct module_env* env, struct val_env* ve,
* @param chase_reply: answer to that query to validate.
* @param kkey: the key entry, which is trusted, and which matches
* the signer of the answer. The key entry isgood().
* @param qstate: query state for the region.
* @param vq: validator state for the nsec3 cache table.
* @param nsec3_calculations: current nsec3 hash calculations.
* @param suspend: returned true if the task takes too long and needs to
* suspend to continue the effort later.
*/
static void
validate_cname_response(struct module_env* env, struct val_env* ve,
struct query_info* qchase, struct reply_info* chase_reply,
struct key_entry_key* kkey, struct module_qstate* qstate,
struct val_qstate* vq, int* nsec3_calculations, int* suspend)
struct key_entry_key* kkey)
{
uint8_t* wc = NULL;
size_t wl;
@@ -1492,7 +1281,6 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
int nsec3s_seen = 0;
size_t i;
struct ub_packed_rrset_key* s;
*suspend = 0;
/* validate the ANSWER section - this will be the CNAME (+DNAME) */
for(i=0; i<chase_reply->an_numrrsets; i++) {
@@ -1557,23 +1345,17 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
/* If this was a positive wildcard response that we haven't already
* proven, and we have NSEC3 records, try to prove it using the NSEC3
* records. */
if(wc != NULL && !wc_NSEC_ok && nsec3s_seen &&
nsec3_cache_table_init(&vq->nsec3_cache_table, qstate->region)) {
enum sec_status sec = nsec3_prove_wildcard(env, ve,
if(wc != NULL && !wc_NSEC_ok && nsec3s_seen) {
enum sec_status sec = nsec3_prove_wildcard(env, ve,
chase_reply->rrsets+chase_reply->an_numrrsets,
chase_reply->ns_numrrsets, qchase, kkey, wc,
&vq->nsec3_cache_table, nsec3_calculations);
chase_reply->ns_numrrsets, qchase, kkey, wc);
if(sec == sec_status_insecure) {
verbose(VERB_ALGO, "wildcard CNAME response is "
"insecure");
chase_reply->security = sec_status_insecure;
return;
} else if(sec == sec_status_secure) {
} else if(sec == sec_status_secure)
wc_NSEC_ok = 1;
} else if(sec == sec_status_unchecked) {
*suspend = 1;
return;
}
}
/* If after all this, we still haven't proven the positive wildcard
@@ -1604,17 +1386,11 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
* @param chase_reply: answer to that query to validate.
* @param kkey: the key entry, which is trusted, and which matches
* the signer of the answer. The key entry isgood().
* @param qstate: query state for the region.
* @param vq: validator state for the nsec3 cache table.
* @param nsec3_calculations: current nsec3 hash calculations.
* @param suspend: returned true if the task takes too long and needs to
* suspend to continue the effort later.
*/
static void
validate_cname_noanswer_response(struct module_env* env, struct val_env* ve,
struct query_info* qchase, struct reply_info* chase_reply,
struct key_entry_key* kkey, struct module_qstate* qstate,
struct val_qstate* vq, int* nsec3_calculations, int* suspend)
struct key_entry_key* kkey)
{
int nodata_valid_nsec = 0; /* If true, then NODATA has been proven.*/
uint8_t* ce = NULL; /* for wildcard nodata responses. This is the
@@ -1628,7 +1404,6 @@ validate_cname_noanswer_response(struct module_env* env, struct val_env* ve,
uint8_t* nsec_ce; /* Used to find the NSEC with the longest ce */
int ce_labs = 0;
int prev_ce_labs = 0;
*suspend = 0;
/* the AUTHORITY section */
for(i=chase_reply->an_numrrsets; i<chase_reply->an_numrrsets+
@@ -1694,13 +1469,11 @@ validate_cname_noanswer_response(struct module_env* env, struct val_env* ve,
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
return;
}
if(!nodata_valid_nsec && !nxdomain_valid_nsec && nsec3s_seen &&
nsec3_cache_table_init(&vq->nsec3_cache_table, qstate->region)) {
if(!nodata_valid_nsec && !nxdomain_valid_nsec && nsec3s_seen) {
int nodata;
enum sec_status sec = nsec3_prove_nxornodata(env, ve,
chase_reply->rrsets+chase_reply->an_numrrsets,
chase_reply->ns_numrrsets, qchase, kkey, &nodata,
&vq->nsec3_cache_table, nsec3_calculations);
chase_reply->ns_numrrsets, qchase, kkey, &nodata);
if(sec == sec_status_insecure) {
verbose(VERB_ALGO, "CNAMEchain to noanswer response "
"is insecure");
@@ -1710,9 +1483,6 @@ validate_cname_noanswer_response(struct module_env* env, struct val_env* ve,
if(nodata)
nodata_valid_nsec = 1;
else nxdomain_valid_nsec = 1;
} else if(sec == sec_status_unchecked) {
*suspend = 1;
return;
}
}
@@ -2056,37 +1826,13 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
* Uses negative cache for NSEC3 lookup of DS responses. */
/* only if cache not blacklisted, of course */
struct dns_msg* msg;
int suspend;
if(vq->sub_ds_msg) {
/* We have a suspended DS reply from a sub-query;
* process it. */
verbose(VERB_ALGO, "Process suspended sub DS response");
msg = vq->sub_ds_msg;
process_ds_response(qstate, vq, id, LDNS_RCODE_NOERROR,
msg, &msg->qinfo, NULL, &suspend);
if(suspend) {
/* we'll come back here later to continue */
if(!validate_suspend_setup_timer(qstate, vq,
id, VAL_FINDKEY_STATE))
return val_error(qstate, id);
return 0;
}
vq->sub_ds_msg = NULL;
return 1; /* continue processing ds-response results */
} else if(!qstate->blacklist && !vq->chain_blacklist &&
if(!qstate->blacklist && !vq->chain_blacklist &&
(msg=val_find_DS(qstate->env, target_key_name,
target_key_len, vq->qchase.qclass, qstate->region,
vq->key_entry->name)) ) {
verbose(VERB_ALGO, "Process cached DS response");
process_ds_response(qstate, vq, id, LDNS_RCODE_NOERROR,
msg, &msg->qinfo, NULL, &suspend);
if(suspend) {
/* we'll come back here later to continue */
if(!validate_suspend_setup_timer(qstate, vq,
id, VAL_FINDKEY_STATE))
return val_error(qstate, id);
return 0;
}
msg, &msg->qinfo, NULL);
return 1; /* continue processing ds-response results */
}
if(!generate_request(qstate, id, target_key_name,
@@ -2129,7 +1875,7 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
struct val_env* ve, int id)
{
enum val_classification subtype;
int rcode, suspend, nsec3_calculations = 0;
int rcode;
if(!vq->key_entry) {
verbose(VERB_ALGO, "validate: no key entry, failed");
@@ -2186,14 +1932,8 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
/* check signatures in the message;
* answer and authority must be valid, additional is only checked. */
if(!validate_msg_signatures(qstate, vq, qstate->env, ve, &vq->qchase,
vq->chase_reply, vq->key_entry, &suspend)) {
if(suspend) {
if(!validate_suspend_setup_timer(qstate, vq,
id, VAL_VALIDATE_STATE))
return val_error(qstate, id);
return 0;
}
if(!validate_msg_signatures(qstate, qstate->env, ve, &vq->qchase,
vq->chase_reply, vq->key_entry)) {
/* workaround bad recursor out there that truncates (even
* with EDNS4k) to 512 by removing RRSIG from auth section
* for positive replies*/
@@ -2222,14 +1962,7 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
case VAL_CLASS_POSITIVE:
verbose(VERB_ALGO, "Validating a positive response");
validate_positive_response(qstate->env, ve,
&vq->qchase, vq->chase_reply, vq->key_entry,
qstate, vq, &nsec3_calculations, &suspend);
if(suspend) {
if(!validate_suspend_setup_timer(qstate,
vq, id, VAL_VALIDATE_STATE))
return val_error(qstate, id);
return 0;
}
&vq->qchase, vq->chase_reply, vq->key_entry);
verbose(VERB_DETAIL, "validate(positive): %s",
sec_status_to_string(
vq->chase_reply->security));
@@ -2238,14 +1971,7 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
case VAL_CLASS_NODATA:
verbose(VERB_ALGO, "Validating a nodata response");
validate_nodata_response(qstate->env, ve,
&vq->qchase, vq->chase_reply, vq->key_entry,
qstate, vq, &nsec3_calculations, &suspend);
if(suspend) {
if(!validate_suspend_setup_timer(qstate,
vq, id, VAL_VALIDATE_STATE))
return val_error(qstate, id);
return 0;
}
&vq->qchase, vq->chase_reply, vq->key_entry);
verbose(VERB_DETAIL, "validate(nodata): %s",
sec_status_to_string(
vq->chase_reply->security));
@@ -2255,14 +1981,7 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
rcode = (int)FLAGS_GET_RCODE(vq->orig_msg->rep->flags);
verbose(VERB_ALGO, "Validating a nxdomain response");
validate_nameerror_response(qstate->env, ve,
&vq->qchase, vq->chase_reply, vq->key_entry, &rcode,
qstate, vq, &nsec3_calculations, &suspend);
if(suspend) {
if(!validate_suspend_setup_timer(qstate,
vq, id, VAL_VALIDATE_STATE))
return val_error(qstate, id);
return 0;
}
&vq->qchase, vq->chase_reply, vq->key_entry, &rcode);
verbose(VERB_DETAIL, "validate(nxdomain): %s",
sec_status_to_string(
vq->chase_reply->security));
@@ -2273,14 +1992,7 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
case VAL_CLASS_CNAME:
verbose(VERB_ALGO, "Validating a cname response");
validate_cname_response(qstate->env, ve,
&vq->qchase, vq->chase_reply, vq->key_entry,
qstate, vq, &nsec3_calculations, &suspend);
if(suspend) {
if(!validate_suspend_setup_timer(qstate,
vq, id, VAL_VALIDATE_STATE))
return val_error(qstate, id);
return 0;
}
&vq->qchase, vq->chase_reply, vq->key_entry);
verbose(VERB_DETAIL, "validate(cname): %s",
sec_status_to_string(
vq->chase_reply->security));
@@ -2290,14 +2002,7 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
verbose(VERB_ALGO, "Validating a cname noanswer "
"response");
validate_cname_noanswer_response(qstate->env, ve,
&vq->qchase, vq->chase_reply, vq->key_entry,
qstate, vq, &nsec3_calculations, &suspend);
if(suspend) {
if(!validate_suspend_setup_timer(qstate,
vq, id, VAL_VALIDATE_STATE))
return val_error(qstate, id);
return 0;
}
&vq->qchase, vq->chase_reply, vq->key_entry);
verbose(VERB_DETAIL, "validate(cname_noanswer): %s",
sec_status_to_string(
vq->chase_reply->security));
@@ -2314,15 +2019,8 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
case VAL_CLASS_ANY:
verbose(VERB_ALGO, "Validating a positive ANY "
"response");
validate_any_response(qstate->env, ve, &vq->qchase,
vq->chase_reply, vq->key_entry, qstate, vq,
&nsec3_calculations, &suspend);
if(suspend) {
if(!validate_suspend_setup_timer(qstate,
vq, id, VAL_VALIDATE_STATE))
return val_error(qstate, id);
return 0;
}
validate_any_response(qstate->env, ve, &vq->qchase,
vq->chase_reply, vq->key_entry);
verbose(VERB_DETAIL, "validate(positive_any): %s",
sec_status_to_string(
vq->chase_reply->security));
@@ -2431,13 +2129,16 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
if(vq->orig_msg->rep->security == sec_status_bogus) {
/* see if we can try again to fetch data */
if(vq->restart_count < ve->max_restart) {
int restart_count = vq->restart_count+1;
verbose(VERB_ALGO, "validation failed, "
"blacklist and retry to fetch data");
val_blacklist(&qstate->blacklist, qstate->region,
qstate->reply_origin, 0);
qstate->reply_origin = NULL;
qstate->errinf = NULL;
val_restart(vq);
memset(vq, 0, sizeof(*vq));
vq->restart_count = restart_count;
vq->state = VAL_INIT_STATE;
verbose(VERB_ALGO, "pass back to next module");
qstate->ext_state[id] = module_restart_next;
return 0;
@@ -2764,10 +2465,7 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
* DS response indicated an end to secure space, is_good if the DS
* validated. It returns ke=NULL if the DS response indicated that the
* request wasn't a delegation point.
* @return
* 0 on success,
* 1 on servfail error (malloc failure),
* 2 on NSEC3 suspend.
* @return 0 on servfail error (malloc failure).
*/
static int
ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
@@ -2778,7 +2476,6 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
char* reason = NULL;
sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
enum val_classification subtype;
int verified;
if(rcode != LDNS_RCODE_NOERROR) {
char rc[16];
rc[0]=0;
@@ -2809,7 +2506,7 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
/* Verify only returns BOGUS or SECURE. If the rrset is
* bogus, then we are done. */
sec = val_verify_rrset_entry(qstate->env, ve, ds,
vq->key_entry, &reason, &reason_bogus, LDNS_SECTION_ANSWER, qstate, &verified);
vq->key_entry, &reason, &reason_bogus, LDNS_SECTION_ANSWER, qstate);
if(sec != sec_status_secure) {
verbose(VERB_DETAIL, "DS rrset in DS response did "
"not verify");
@@ -2827,7 +2524,7 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
ub_packed_rrset_ttl(ds),
LDNS_EDE_UNSUPPORTED_DS_DIGEST, NULL,
*qstate->env->now);
return (*ke) == NULL;
return (*ke) != NULL;
}
/* Otherwise, we return the positive response. */
@@ -2835,7 +2532,7 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
*ke = key_entry_create_rrset(qstate->region,
qinfo->qname, qinfo->qname_len, qinfo->qclass, ds,
NULL, LDNS_EDE_NONE, NULL, *qstate->env->now);
return (*ke) == NULL;
return (*ke) != NULL;
} else if(subtype == VAL_CLASS_NODATA ||
subtype == VAL_CLASS_NAMEERROR) {
/* NODATA means that the qname exists, but that there was
@@ -2869,12 +2566,12 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
qinfo->qclass, proof_ttl,
LDNS_EDE_NONE, NULL,
*qstate->env->now);
return (*ke) == NULL;
return (*ke) != NULL;
case sec_status_insecure:
verbose(VERB_DETAIL, "NSEC RRset for the "
"referral proved not a delegation point");
*ke = NULL;
return 0;
return 1;
case sec_status_bogus:
verbose(VERB_DETAIL, "NSEC RRset for the "
"referral did not prove no DS.");
@@ -2886,17 +2583,10 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
break;
}
if(!nsec3_cache_table_init(&vq->nsec3_cache_table, qstate->region)) {
log_err("malloc failure in ds_response_to_ke for "
"NSEC3 cache");
reason = "malloc failure";
errinf_ede(qstate, reason, 0);
goto return_bogus;
}
sec = nsec3_prove_nods(qstate->env, ve,
msg->rep->rrsets + msg->rep->an_numrrsets,
msg->rep->ns_numrrsets, qinfo, vq->key_entry, &reason,
&reason_bogus, qstate, &vq->nsec3_cache_table);
&reason_bogus, qstate);
switch(sec) {
case sec_status_insecure:
/* case insecure also continues to unsigned
@@ -2910,19 +2600,18 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
qinfo->qclass, proof_ttl,
LDNS_EDE_NONE, NULL,
*qstate->env->now);
return (*ke) == NULL;
return (*ke) != NULL;
case sec_status_indeterminate:
verbose(VERB_DETAIL, "NSEC3s for the "
"referral proved no delegation");
*ke = NULL;
return 0;
return 1;
case sec_status_bogus:
verbose(VERB_DETAIL, "NSEC3s for the "
"referral did not prove no DS.");
errinf_ede(qstate, reason, reason_bogus);
goto return_bogus;
case sec_status_unchecked:
return 2;
default:
/* NSEC3 proof did not work */
break;
@@ -2963,13 +2652,13 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
}
sec = val_verify_rrset_entry(qstate->env, ve, cname,
vq->key_entry, &reason, &reason_bogus,
LDNS_SECTION_ANSWER, qstate, &verified);
LDNS_SECTION_ANSWER, qstate);
if(sec == sec_status_secure) {
verbose(VERB_ALGO, "CNAME validated, "
"proof that DS does not exist");
/* and that it is not a referral point */
*ke = NULL;
return 0;
return 1;
}
errinf(qstate, "CNAME in DS response was not secure.");
errinf_ede(qstate, reason, reason_bogus);
@@ -2993,7 +2682,7 @@ return_bogus:
*ke = key_entry_create_bad(qstate->region, qinfo->qname,
qinfo->qname_len, qinfo->qclass, BOGUS_KEY_TTL,
reason_bogus, reason, *qstate->env->now);
return (*ke) == NULL;
return (*ke) != NULL;
}
/**
@@ -3014,31 +2703,17 @@ return_bogus:
static void
process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,
int id, int rcode, struct dns_msg* msg, struct query_info* qinfo,
struct sock_list* origin, int* suspend)
struct sock_list* origin)
{
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
struct key_entry_key* dske = NULL;
uint8_t* olds = vq->empty_DS_name;
int ret;
*suspend = 0;
vq->empty_DS_name = NULL;
ret = ds_response_to_ke(qstate, vq, id, rcode, msg, qinfo, &dske);
if(ret != 0) {
switch(ret) {
case 1:
if(!ds_response_to_ke(qstate, vq, id, rcode, msg, qinfo, &dske)) {
log_err("malloc failure in process_ds_response");
vq->key_entry = NULL; /* make it error */
vq->state = VAL_VALIDATE_STATE;
return;
case 2:
*suspend = 1;
return;
default:
log_err("unhandled error value for ds_response_to_ke");
vq->key_entry = NULL; /* make it error */
vq->state = VAL_VALIDATE_STATE;
return;
}
}
if(dske == NULL) {
vq->empty_DS_name = regional_alloc_init(qstate->region,
@@ -3290,26 +2965,9 @@ val_inform_super(struct module_qstate* qstate, int id,
return;
}
if(qstate->qinfo.qtype == LDNS_RR_TYPE_DS) {
int suspend;
process_ds_response(super, vq, id, qstate->return_rcode,
qstate->return_msg, &qstate->qinfo,
qstate->reply_origin, &suspend);
/* If NSEC3 was needed during validation, NULL the NSEC3 cache;
* it will be re-initiated if needed later on.
* Validation (and the cache table) are happening/allocated in
* the super qstate whilst the RRs are allocated (and pointed
* to) in this sub qstate. */
if(vq->nsec3_cache_table.ct) {
vq->nsec3_cache_table.ct = NULL;
}
if(suspend) {
/* deep copy the return_msg to vq->sub_ds_msg; it will
* be resumed later in the super state with the caveat
* that the initial calculations will be re-caclulated
* and re-suspended there before continuing. */
vq->sub_ds_msg = dns_msg_deepcopy_region(
qstate->return_msg, super->region);
}
qstate->return_msg, &qstate->qinfo,
qstate->reply_origin);
return;
} else if(qstate->qinfo.qtype == LDNS_RR_TYPE_DNSKEY) {
process_dnskey_response(super, vq, id, qstate->return_rcode,
@@ -3323,15 +2981,8 @@ val_inform_super(struct module_qstate* qstate, int id,
void
val_clear(struct module_qstate* qstate, int id)
{
struct val_qstate* vq;
if(!qstate)
return;
vq = (struct val_qstate*)qstate->minfo[id];
if(vq) {
if(vq->suspend_timer) {
comm_timer_delete(vq->suspend_timer);
}
}
/* everything is allocated in the region, so assign NULL */
qstate->minfo[id] = NULL;
}
-18
View File
@@ -45,13 +45,11 @@
#include "util/module.h"
#include "util/data/msgreply.h"
#include "validator/val_utils.h"
#include "validator/val_nsec3.h"
struct val_anchors;
struct key_cache;
struct key_entry_key;
struct val_neg_cache;
struct config_strlist;
struct comm_timer;
/**
* This is the TTL to use when a trust anchor fails to prime. A trust anchor
@@ -217,19 +215,6 @@ struct val_qstate {
/** true if this state is waiting to prime a trust anchor */
int wait_prime_ta;
/** State to continue with RRSIG validation in a message later */
int msg_signatures_state;
/** The rrset index for the msg signatures to continue from */
size_t msg_signatures_index;
/** Cache table for NSEC3 hashes */
struct nsec3_cache_table nsec3_cache_table;
/** DS message from sub if it got suspended from NSEC3 calculations */
struct dns_msg* sub_ds_msg;
/** The timer to resume processing msg signatures */
struct comm_timer* suspend_timer;
/** Number of suspends */
int suspend_count;
};
/**
@@ -277,7 +262,4 @@ void val_clear(struct module_qstate* qstate, int id);
*/
size_t val_get_mem(struct module_env* env, int id);
/** Timer callback for msg signatures continue timer */
void validate_suspend_timer_cb(void* arg);
#endif /* VALIDATOR_VALIDATOR_H */