summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStuart Henderson <sthen@cvs.openbsd.org>2021-08-13 19:55:26 +0000
committerStuart Henderson <sthen@cvs.openbsd.org>2021-08-13 19:55:26 +0000
commitb186aed10fe44790988cd0b583f77841c91ad6ff (patch)
tree2c1fc83f53461e1bc8dc8d0bec719a0a76118d56
parentb8fa4b5134a93cf2d362a0475e772da7c52c6068 (diff)
import unbound 1.13.2, ok florian@
-rw-r--r--usr.sbin/unbound/dnstap/dnstap.h12
-rw-r--r--usr.sbin/unbound/dnstap/unbound-dnstap-socket.c26
-rw-r--r--usr.sbin/unbound/services/rpz.c26
-rw-r--r--usr.sbin/unbound/testcode/delayer.c6
-rwxr-xr-xusr.sbin/unbound/testcode/do-tests.sh12
-rw-r--r--usr.sbin/unbound/testcode/dohclient.c23
-rw-r--r--usr.sbin/unbound/testcode/fake_event.c29
-rwxr-xr-xusr.sbin/unbound/testcode/mini_tdir.sh45
-rw-r--r--usr.sbin/unbound/testcode/petal.c3
-rw-r--r--usr.sbin/unbound/testcode/readzone.c158
-rw-r--r--usr.sbin/unbound/testcode/replay.c25
-rw-r--r--usr.sbin/unbound/testcode/replay.h3
-rw-r--r--usr.sbin/unbound/testcode/streamtcp.c10
-rw-r--r--usr.sbin/unbound/testcode/testbound.c9
-rw-r--r--usr.sbin/unbound/testcode/unitauth.c18
-rw-r--r--usr.sbin/unbound/testcode/unitldns.c2
-rw-r--r--usr.sbin/unbound/testcode/unitmain.c49
-rw-r--r--usr.sbin/unbound/testcode/unitmain.h4
-rw-r--r--usr.sbin/unbound/testcode/unittcpreuse.c236
-rw-r--r--usr.sbin/unbound/testcode/unitzonemd.c537
20 files changed, 1110 insertions, 123 deletions
diff --git a/usr.sbin/unbound/dnstap/dnstap.h b/usr.sbin/unbound/dnstap/dnstap.h
index 783b8c51430..449fae727ea 100644
--- a/usr.sbin/unbound/dnstap/dnstap.h
+++ b/usr.sbin/unbound/dnstap/dnstap.h
@@ -123,12 +123,14 @@ dt_delete(struct dt_env *env);
* Create and send a new dnstap "Message" event of type CLIENT_QUERY.
* @param env: dnstap environment object.
* @param qsock: address/port of client.
+ * @param rsock: local (service) address/port.
* @param cptype: comm_udp or comm_tcp.
* @param qmsg: query message.
*/
void
dt_msg_send_client_query(struct dt_env *env,
struct sockaddr_storage *qsock,
+ struct sockaddr_storage *rsock,
enum comm_point_type cptype,
struct sldns_buffer *qmsg);
@@ -136,12 +138,14 @@ dt_msg_send_client_query(struct dt_env *env,
* Create and send a new dnstap "Message" event of type CLIENT_RESPONSE.
* @param env: dnstap environment object.
* @param qsock: address/port of client.
+ * @param rsock: local (service) address/port.
* @param cptype: comm_udp or comm_tcp.
* @param rmsg: response message.
*/
void
dt_msg_send_client_response(struct dt_env *env,
struct sockaddr_storage *qsock,
+ struct sockaddr_storage *rsock,
enum comm_point_type cptype,
struct sldns_buffer *rmsg);
@@ -150,7 +154,8 @@ dt_msg_send_client_response(struct dt_env *env,
* FORWARDER_QUERY. The type used is dependent on the value of the RD bit
* in the query header.
* @param env: dnstap environment object.
- * @param rsock: address/port of server the query is being sent to.
+ * @param rsock: address/port of server (upstream) the query is being sent to.
+ * @param qsock: address/port of server (local) the query is being sent from.
* @param cptype: comm_udp or comm_tcp.
* @param zone: query zone.
* @param zone_len: length of zone.
@@ -159,6 +164,7 @@ dt_msg_send_client_response(struct dt_env *env,
void
dt_msg_send_outside_query(struct dt_env *env,
struct sockaddr_storage *rsock,
+ struct sockaddr_storage *qsock,
enum comm_point_type cptype,
uint8_t *zone, size_t zone_len,
struct sldns_buffer *qmsg);
@@ -168,7 +174,8 @@ dt_msg_send_outside_query(struct dt_env *env,
* FORWARDER_RESPONSE. The type used is dependent on the value of the RD bit
* in the query header.
* @param env: dnstap environment object.
- * @param rsock: address/port of server the response was received from.
+ * @param rsock: address/port of server (upstream) the response was received from.
+ * @param qsock: address/port of server (local) the response was received to.
* @param cptype: comm_udp or comm_tcp.
* @param zone: query zone.
* @param zone_len: length of zone.
@@ -181,6 +188,7 @@ dt_msg_send_outside_query(struct dt_env *env,
void
dt_msg_send_outside_response(struct dt_env *env,
struct sockaddr_storage *rsock,
+ struct sockaddr_storage *qsock,
enum comm_point_type cptype,
uint8_t *zone, size_t zone_len,
uint8_t *qbuf, size_t qbuf_len,
diff --git a/usr.sbin/unbound/dnstap/unbound-dnstap-socket.c b/usr.sbin/unbound/dnstap/unbound-dnstap-socket.c
index 8e28be4e89e..3de8ab3f089 100644
--- a/usr.sbin/unbound/dnstap/unbound-dnstap-socket.c
+++ b/usr.sbin/unbound/dnstap/unbound-dnstap-socket.c
@@ -1012,6 +1012,7 @@ void dtio_tap_callback(int fd, short ATTR_UNUSED(bits), void* arg)
if(verbosity) log_info("bidirectional stream");
if(!reply_with_accept(data)) {
tap_data_free(data);
+ return;
}
} else if(data->len >= 4 && sldns_read_uint32(data->frame) ==
FSTRM_CONTROL_FRAME_STOP && data->is_bidirectional) {
@@ -1166,8 +1167,13 @@ int sig_quit = 0;
/** signal handler for user quit */
static RETSIGTYPE main_sigh(int sig)
{
- if(!sig_quit)
- fprintf(stderr, "exit on signal %d\n", sig);
+ if(!sig_quit) {
+ char str[] = "exit on signal \n";
+ str[15] = '0' + (sig/10)%10;
+ str[16] = '0' + sig%10;
+ /* simple cast to void will not silence Wunused-result */
+ (void)!write(STDERR_FILENO, str, strlen(str));
+ }
if(sig_base) {
ub_event_base_loopexit(sig_base);
sig_base = NULL;
@@ -1375,14 +1381,6 @@ int worker_handle_request(struct comm_point* ATTR_UNUSED(c),
return 0;
}
-int worker_handle_reply(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(reply_info))
-{
- log_assert(0);
- return 0;
-}
-
int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply* ATTR_UNUSED(reply_info))
@@ -1456,14 +1454,6 @@ struct outbound_entry* libworker_send_query(
return 0;
}
-int libworker_handle_reply(struct comm_point* ATTR_UNUSED(c),
- void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
- struct comm_reply* ATTR_UNUSED(reply_info))
-{
- log_assert(0);
- return 0;
-}
-
int libworker_handle_service_reply(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply* ATTR_UNUSED(reply_info))
diff --git a/usr.sbin/unbound/services/rpz.c b/usr.sbin/unbound/services/rpz.c
index 2b6b0ac3fcc..3a1ec00d7d3 100644
--- a/usr.sbin/unbound/services/rpz.c
+++ b/usr.sbin/unbound/services/rpz.c
@@ -162,6 +162,7 @@ rpz_rr_to_action(uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
case LDNS_RR_TYPE_RRSIG:
case LDNS_RR_TYPE_NSEC:
case LDNS_RR_TYPE_NSEC3:
+ case LDNS_RR_TYPE_NSEC3PARAM:
return RPZ_INVALID_ACTION;
case LDNS_RR_TYPE_CNAME:
break;
@@ -479,8 +480,21 @@ rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
int newzone = 0;
if(a == RPZ_TCP_ONLY_ACTION || a == RPZ_INVALID_ACTION) {
- verbose(VERB_ALGO, "RPZ: skipping unsupported action: %s",
- rpz_action_to_string(a));
+ char str[255+1];
+ if(rrtype == LDNS_RR_TYPE_SOA || rrtype == LDNS_RR_TYPE_NS ||
+ rrtype == LDNS_RR_TYPE_DNAME ||
+ rrtype == LDNS_RR_TYPE_DNSKEY ||
+ rrtype == LDNS_RR_TYPE_RRSIG ||
+ rrtype == LDNS_RR_TYPE_NSEC ||
+ rrtype == LDNS_RR_TYPE_NSEC3PARAM ||
+ rrtype == LDNS_RR_TYPE_NSEC3 ||
+ rrtype == LDNS_RR_TYPE_DS) {
+ free(dname);
+ return; /* no need to log these types as unsupported */
+ }
+ dname_str(dname, str);
+ verbose(VERB_ALGO, "RPZ: qname trigger, %s skipping unsupported action: %s",
+ str, rpz_action_to_string(a));
free(dname);
return;
}
@@ -552,8 +566,10 @@ rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
if(a == RPZ_TCP_ONLY_ACTION || a == RPZ_INVALID_ACTION ||
respa == respip_invalid) {
- verbose(VERB_ALGO, "RPZ: skipping unsupported action: %s",
- rpz_action_to_string(a));
+ char str[255+1];
+ dname_str(dname, str);
+ verbose(VERB_ALGO, "RPZ: respip trigger, %s skipping unsupported action: %s",
+ str, rpz_action_to_string(a));
return 0;
}
@@ -702,7 +718,7 @@ rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass,
* zone match, append '*' to that and do another lookup. */
ce = dname_get_shared_topdomain(z->name, qname);
- if(!ce /* should not happen */ || !*ce /* root */) {
+ if(!ce /* should not happen */) {
lock_rw_unlock(&z->lock);
if(zones_keep_lock) {
lock_rw_unlock(&r->local_zones->lock);
diff --git a/usr.sbin/unbound/testcode/delayer.c b/usr.sbin/unbound/testcode/delayer.c
index 54175dbe3ec..e915961f5ae 100644
--- a/usr.sbin/unbound/testcode/delayer.c
+++ b/usr.sbin/unbound/testcode/delayer.c
@@ -347,7 +347,11 @@ static volatile int do_quit = 0;
/** signal handler for user quit */
static RETSIGTYPE delayer_sigh(int sig)
{
- printf("exit on signal %d\n", sig);
+ char str[] = "exit on signal \n";
+ str[15] = '0' + (sig/10)%10;
+ str[16] = '0' + sig%10;
+ /* simple cast to void will not silence Wunused-result */
+ (void)!write(STDOUT_FILENO, str, strlen(str));
do_quit = 1;
}
diff --git a/usr.sbin/unbound/testcode/do-tests.sh b/usr.sbin/unbound/testcode/do-tests.sh
index effb7c16a5b..2a1cfc4c96e 100755
--- a/usr.sbin/unbound/testcode/do-tests.sh
+++ b/usr.sbin/unbound/testcode/do-tests.sh
@@ -1,5 +1,11 @@
#!/usr/bin/env bash
. testdata/common.sh
+quiet=0
+if test "$1" = "-q"; then
+ quiet=1
+ tdirarg="-q"
+ shift
+fi
NEED_SPLINT='00-lint.tdir'
NEED_DOXYGEN='01-doc.tdir'
@@ -33,7 +39,7 @@ fi
export -n NOTIFY_SOCKET
cd testdata;
-sh ../testcode/mini_tdir.sh clean
+sh ../testcode/mini_tdir.sh $tdirarg clean
rm -f .perfstats.txt
for test in `ls -d *.tdir`; do
SKIP=0
@@ -57,10 +63,10 @@ for test in `ls -d *.tdir`; do
fi
if test $SKIP -eq 0; then
echo $test
- sh ../testcode/mini_tdir.sh -a ../.. exe $test
+ sh ../testcode/mini_tdir.sh -a ../.. $tdirarg exe $test
else
echo "skip $test"
fi
done
-sh ../testcode/mini_tdir.sh report
+sh ../testcode/mini_tdir.sh $tdirarg report
cat .perfstats.txt
diff --git a/usr.sbin/unbound/testcode/dohclient.c b/usr.sbin/unbound/testcode/dohclient.c
index 263418049be..93d84a83550 100644
--- a/usr.sbin/unbound/testcode/dohclient.c
+++ b/usr.sbin/unbound/testcode/dohclient.c
@@ -423,6 +423,7 @@ http2_session_create()
if(nghttp2_session_callbacks_new(&callbacks) == NGHTTP2_ERR_NOMEM) {
log_err("failed to initialize nghttp2 callback");
+ free(h2_session);
return NULL;
}
nghttp2_session_callbacks_set_recv_callback(callbacks, http2_recv_cb);
@@ -501,7 +502,9 @@ run(struct http2_session* h2_session, int port, int no_tls, int count, char** q)
if(!no_tls) {
ctx = connect_sslctx_create(NULL, NULL, NULL, 0);
if(!ctx) fatal_exit("cannot create ssl ctx");
+#ifdef HAVE_SSL_CTX_SET_ALPN_PROTOS
SSL_CTX_set_alpn_protos(ctx, (const unsigned char *)"\x02h2", 3);
+#endif
ssl = outgoing_ssl_fd(ctx, fd);
if(!ssl) {
printf("cannot create ssl\n");
@@ -620,7 +623,25 @@ int main(int argc, char** argv)
return 1;
}
-
+ if(!no_tls) {
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
+ ERR_load_SSL_strings();
+#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
+# ifndef S_SPLINT_S
+ OpenSSL_add_all_algorithms();
+# endif
+#else
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
+ | OPENSSL_INIT_ADD_ALL_DIGESTS
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
+ (void)SSL_library_init();
+#else
+ (void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
+#endif
+ }
run(h2_session, port, no_tls, argc, argv);
checklock_stop();
diff --git a/usr.sbin/unbound/testcode/fake_event.c b/usr.sbin/unbound/testcode/fake_event.c
index b8166c45ce0..5f81b9eb808 100644
--- a/usr.sbin/unbound/testcode/fake_event.c
+++ b/usr.sbin/unbound/testcode/fake_event.c
@@ -451,6 +451,8 @@ fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
struct comm_reply repinfo;
memset(&repinfo, 0, sizeof(repinfo));
repinfo.c = (struct comm_point*)calloc(1, sizeof(struct comm_point));
+ if(!repinfo.c)
+ fatal_exit("out of memory in fake_front_query");
repinfo.addrlen = (socklen_t)sizeof(struct sockaddr_in);
if(todo->addrlen != 0) {
repinfo.addrlen = todo->addrlen;
@@ -597,7 +599,7 @@ autotrust_check(struct replay_runtime* runtime, struct replay_moment* mom)
log_err("should be: %s", p->str);
fatal_exit("autotrust_check failed");
}
- if(line[0]) line[strlen(line)-1] = 0; /* remove newline */
+ strip_end_white(line);
expanded = macro_process(runtime->vars, runtime, p->str);
if(!expanded)
fatal_exit("could not expand macro line %d", lineno);
@@ -650,7 +652,7 @@ tempfile_check(struct replay_runtime* runtime, struct replay_moment* mom)
log_err("should be: %s", p->str);
fatal_exit("tempfile_check failed");
}
- if(line[0]) line[strlen(line)-1] = 0; /* remove newline */
+ strip_end_white(line);
expanded = macro_process(runtime->vars, runtime, p->str);
if(!expanded)
fatal_exit("could not expand macro line %d", lineno);
@@ -909,6 +911,8 @@ comm_base_create(int ATTR_UNUSED(sigs))
/* we return the runtime structure instead. */
struct replay_runtime* runtime = (struct replay_runtime*)
calloc(1, sizeof(struct replay_runtime));
+ if(!runtime)
+ fatal_exit("out of memory in fake_event.c:comm_base_create");
runtime->scenario = saved_scenario;
runtime->vars = macro_store_create();
if(!runtime->vars) fatal_exit("out of memory");
@@ -1046,7 +1050,9 @@ outside_network_create(struct comm_base* base, size_t bufsize,
void (*unwanted_action)(void*), void* ATTR_UNUSED(unwanted_param),
int ATTR_UNUSED(do_udp), void* ATTR_UNUSED(sslctx),
int ATTR_UNUSED(delayclose), int ATTR_UNUSED(tls_use_sni),
- struct dt_env* ATTR_UNUSED(dtenv), int ATTR_UNUSED(udp_connect))
+ struct dt_env* ATTR_UNUSED(dtenv), int ATTR_UNUSED(udp_connect),
+ int ATTR_UNUSED(max_reuse_tcp_queries), int ATTR_UNUSED(tcp_reuse_timeout),
+ int ATTR_UNUSED(tcp_auth_query_timeout))
{
struct replay_runtime* runtime = (struct replay_runtime*)base;
struct outside_network* outnet = calloc(1,
@@ -1306,8 +1312,9 @@ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
log_info("double delete of pending serviced query");
}
-int resolve_interface_names(struct config_file* ATTR_UNUSED(cfg),
- char*** ATTR_UNUSED(resif), int* ATTR_UNUSED(num_resif))
+int resolve_interface_names(char** ATTR_UNUSED(ifs), int ATTR_UNUSED(num_ifs),
+ struct config_strlist* ATTR_UNUSED(list), char*** ATTR_UNUSED(resif),
+ int* ATTR_UNUSED(num_resif))
{
return 1;
}
@@ -1531,6 +1538,8 @@ struct comm_timer* comm_timer_create(struct comm_base* base,
{
struct replay_runtime* runtime = (struct replay_runtime*)base;
struct fake_timer* t = (struct fake_timer*)calloc(1, sizeof(*t));
+ if(!t)
+ fatal_exit("out of memory in fake_event.c:comm_timer_create");
t->cb = cb;
t->cb_arg = cb_arg;
fptr_ok(fptr_whitelist_comm_timer(t->cb)); /* check in advance */
@@ -1629,7 +1638,8 @@ int create_udp_sock(int ATTR_UNUSED(family), int ATTR_UNUSED(socktype),
struct comm_point* comm_point_create_udp(struct comm_base *ATTR_UNUSED(base),
int ATTR_UNUSED(fd), sldns_buffer* ATTR_UNUSED(buffer),
comm_point_callback_type* ATTR_UNUSED(callback),
- void* ATTR_UNUSED(callback_arg))
+ void* ATTR_UNUSED(callback_arg),
+ struct unbound_socket* ATTR_UNUSED(socket))
{
log_assert(0);
return NULL;
@@ -1707,7 +1717,7 @@ struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
addr_to_str((struct sockaddr_storage*)to_addr, to_addrlen,
addrbuf, sizeof(addrbuf));
if(verbosity >= VERB_ALGO) {
- if(buf[0] != 0) buf[strlen(buf)-1] = 0; /* del newline*/
+ strip_end_white(buf);
log_info("tcp to %s: %s", addrbuf, buf);
}
log_assert(sldns_buffer_limit(query)-LDNS_HEADER_SIZE >= 2);
@@ -1739,7 +1749,7 @@ struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
struct comm_point* outnet_comm_point_for_http(struct outside_network* outnet,
comm_point_callback_type* cb, void* cb_arg,
struct sockaddr_storage* to_addr, socklen_t to_addrlen, int timeout,
- int ssl, char* host, char* path)
+ int ssl, char* host, char* path, struct config_file* cfg)
{
struct replay_runtime* runtime = (struct replay_runtime*)
outnet->base;
@@ -1761,6 +1771,7 @@ struct comm_point* outnet_comm_point_for_http(struct outside_network* outnet,
(void)ssl;
(void)host;
(void)path;
+ (void)cfg;
/* handle http comm point and return contents from test script */
return (struct comm_point*)fc;
@@ -1797,7 +1808,7 @@ int comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
addr_to_str((struct sockaddr_storage*)addr, addrlen,
addrbuf, sizeof(addrbuf));
if(verbosity >= VERB_ALGO) {
- if(buf[0] != 0) buf[strlen(buf)-1] = 0; /* del newline*/
+ strip_end_white(buf);
log_info("udp to %s: %s", addrbuf, buf);
}
log_assert(sldns_buffer_limit(packet)-LDNS_HEADER_SIZE >= 2);
diff --git a/usr.sbin/unbound/testcode/mini_tdir.sh b/usr.sbin/unbound/testcode/mini_tdir.sh
index 5f02b0862ee..0457a95e709 100755
--- a/usr.sbin/unbound/testcode/mini_tdir.sh
+++ b/usr.sbin/unbound/testcode/mini_tdir.sh
@@ -5,14 +5,23 @@ if test "$1" = "-a"; then
shift
shift
fi
-
+quiet=0
+if test "$1" = "-q"; then
+ quiet=1
+ shift
+fi
+
if test "$1" = "clean"; then
- echo "rm -f result.* .done* .tdir.var.master .tdir.var.test"
+ if test $quiet = 0; then
+ echo "rm -f result.* .done* .tdir.var.master .tdir.var.test"
+ fi
rm -f result.* .done* .tdir.var.master .tdir.var.test
exit 0
fi
if test "$1" = "fake"; then
- echo "minitdir fake $2"
+ if test $quiet = 0; then
+ echo "minitdir fake $2"
+ fi
echo "fake" > .done-`basename $2 .tdir`
exit 0
fi
@@ -37,7 +46,7 @@ if test "$1" = "-f" && test "$2" = "report"; then
desc=`grep ^Description: "result.$name" | sed -e 's/Description: //'`
fi
if test -f ".done-$name"; then
- if test "$1" != "-q"; then
+ if test $quiet = 0; then
echo "** PASSED ** $timelen $name: $desc"
pass=`expr $pass + 1`
fi
@@ -65,7 +74,7 @@ if test "$1" = "report" || test "$2" = "report"; then
for result in *.tdir; do
name=`basename $result .tdir`
if test -f ".done-$name"; then
- if test "$1" != "-q"; then
+ if test $quiet = 0; then
echo "** PASSED ** : $name"
fi
else
@@ -82,9 +91,9 @@ fi
if test "$1" != 'exe'; then
# usage
echo "mini tdir. Reduced functionality for old shells."
- echo " tdir exe <file>"
- echo " tdir fake <file>"
- echo " tdir clean"
+ echo " tdir [-q] exe <file>"
+ echo " tdir [-q] fake <file>"
+ echo " tdir [-q] clean"
echo " tdir [-q|-f] report"
exit 1
fi
@@ -117,7 +126,9 @@ if test -f .done-$name; then
fi
# Copy
-echo "minitdir copy $1 to $dir"
+if test $quiet = 0; then
+ echo "minitdir copy $1 to $dir"
+fi
mkdir $dir
if cp --help 2>&1 | grep -- "-a" >/dev/null; then
cp -a $name.tdir/* $dir/
@@ -131,7 +142,9 @@ echo "minitdir exe $name" > $result
grep "Description:" $name.dsc >> $result 2>&1
echo "DateRunStart: "`date "+%s" 2>/dev/null` >> $result
if test -f $name.pre; then
- echo "minitdir exe $name.pre"
+ if test $quiet = 0; then
+ echo "minitdir exe $name.pre"
+ fi
echo "minitdir exe $name.pre" >> $result
$shell $name.pre $args >> $result
if test $? -ne 0; then
@@ -139,7 +152,9 @@ if test -f $name.pre; then
fi
fi
if test -f $name.test; then
- echo "minitdir exe $name.test"
+ if test $quiet = 0; then
+ echo "minitdir exe $name.test"
+ fi
echo "minitdir exe $name.test" >> $result
$shell $name.test $args >>$result 2>&1
if test $? -ne 0; then
@@ -149,12 +164,16 @@ if test -f $name.test; then
else
echo "$name: PASSED" >> $result
echo "$name: PASSED" > ../.done-$name
- echo "$name: PASSED"
+ if test $quiet = 0; then
+ echo "$name: PASSED"
+ fi
success="yes"
fi
fi
if test -f $name.post; then
- echo "minitdir exe $name.post"
+ if test $quiet = 0; then
+ echo "minitdir exe $name.post"
+ fi
echo "minitdir exe $name.post" >> $result
$shell $name.post $args >> $result
if test $? -ne 0; then
diff --git a/usr.sbin/unbound/testcode/petal.c b/usr.sbin/unbound/testcode/petal.c
index 123684aab52..a1a37615518 100644
--- a/usr.sbin/unbound/testcode/petal.c
+++ b/usr.sbin/unbound/testcode/petal.c
@@ -238,6 +238,9 @@ setup_ctx(char* key, char* cert)
(void)SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
#endif
(void)SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
+#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
+ SSL_CTX_set_security_level(ctx, 0); /* for keys in tests */
+#endif
if(!SSL_CTX_use_certificate_chain_file(ctx, cert))
print_exit("cannot read cert");
if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM))
diff --git a/usr.sbin/unbound/testcode/readzone.c b/usr.sbin/unbound/testcode/readzone.c
new file mode 100644
index 00000000000..94511e5771f
--- /dev/null
+++ b/usr.sbin/unbound/testcode/readzone.c
@@ -0,0 +1,158 @@
+/*
+ * testcode/readzone.c - readzone tool reads zonefiles
+ *
+ * Copyright (c) 2021, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * \file
+ * Command to read and echo a zonefile.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <stdint.h>
+#include "sldns/str2wire.h"
+#include "sldns/wire2str.h"
+
+int print_usage(FILE *out, const char *progname)
+{
+ fprintf(out, "usage: %s [ -u ] <zonefile> [<origin>]\n", progname);
+ fprintf(out, "\t-u\tprint in unknown type (RFC3597) format\n");
+ return out == stdout ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+int main(int argc, char *const *argv)
+{
+ char *progname = argv[0];
+ uint8_t rr[LDNS_RR_BUF_SIZE];
+ char *str = malloc(1024 * 1024);
+ size_t str_len = sizeof(str);
+ struct sldns_file_parse_state state;
+ FILE *in = NULL;
+ int s = -1;
+ int opt;
+ int print_in_unknown_type_format = 0;
+
+ while ((opt = getopt(argc, argv, "hu")) != -1) {
+ switch (opt) {
+ case 'h':
+ free(str);
+ return print_usage(stdout, progname);
+ case 'u':
+ print_in_unknown_type_format = 1;
+ break;
+ default:
+ free(str);
+ return print_usage(stderr, progname);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ memset(&state, 0, sizeof(state));
+ state.default_ttl = 3600;
+ state.lineno = 1;
+ if (argc == 2) {
+ state.origin_len = sizeof(state.origin);
+ s = sldns_str2wire_dname_buf(argv[1], state.origin
+ , &state.origin_len);
+ if (s) {
+ fprintf(stderr, "Error parsing origin: %s\n"
+ , sldns_get_errorstr_parse(s));
+ free(str);
+ return EXIT_FAILURE;
+ }
+ s = -1;
+ }
+ if (!str)
+ fprintf(stderr, "Memory allocation error: %s\n"
+ , strerror(errno));
+
+ else if (argc != 1 && argc != 2) {
+ free(str);
+ return print_usage(stderr, progname);
+ }
+
+ else if (!(in = fopen(argv[0], "r")))
+ fprintf(stderr, "Error opening \"%s\": %s\n"
+ , argv[0], strerror(errno));
+ else while (!feof(in)) {
+ size_t rr_len = sizeof(rr), dname_len = 0;
+ size_t written;
+
+ s = sldns_fp2wire_rr_buf(in, rr, &rr_len, &dname_len, &state);
+ if (s) {
+ fprintf( stderr, "parse error %d:%d: %s\n"
+ , state.lineno, LDNS_WIREPARSE_OFFSET(s)
+ , sldns_get_errorstr_parse(s));
+ break;
+ }
+ if (rr_len == 0)
+ continue;
+
+ if (print_in_unknown_type_format)
+ written = sldns_wire2str_rr_unknown_buf(
+ rr, rr_len, str, str_len);
+ else
+ written = sldns_wire2str_rr_buf(
+ rr, rr_len, str, str_len);
+
+ if (written > str_len) {
+ while (written > str_len)
+ str_len *= 2;
+ free(str);
+ if (!(str = malloc(str_len))) {
+ fprintf(stderr, "Memory allocation error: %s\n"
+ , strerror(errno));
+ s = -1;
+ break;
+ }
+ if (print_in_unknown_type_format)
+ (void) sldns_wire2str_rr_unknown_buf(
+ rr, rr_len, str, str_len);
+ else
+ (void) sldns_wire2str_rr_buf(
+ rr, rr_len, str, str_len);
+ }
+ fprintf(stdout, "%s", str);
+ }
+ if (in)
+ fclose(in);
+ free(str);
+ return !in || s ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/usr.sbin/unbound/testcode/replay.c b/usr.sbin/unbound/testcode/replay.c
index 84ce50441b1..2487c146f7a 100644
--- a/usr.sbin/unbound/testcode/replay.c
+++ b/usr.sbin/unbound/testcode/replay.c
@@ -124,8 +124,7 @@ replay_range_delete(struct replay_range* rng)
free(rng);
}
-/** strip whitespace from end of string */
-static void
+void
strip_end_white(char* p)
{
size_t i;
@@ -227,7 +226,7 @@ read_file_content(FILE* in, int* lineno, struct replay_moment* mom)
if(strncmp(line, "FILE_END", 8) == 0) {
return;
}
- if(line[0]) line[strlen(line)-1] = 0; /* remove newline */
+ strip_end_white(line);
if(!cfg_strlist_insert(last, strdup(line)))
fatal_exit("malloc failure");
last = &( (*last)->next );
@@ -249,7 +248,7 @@ read_assign_step(char* remain, struct replay_moment* mom)
if(eq != '=')
fatal_exit("no '=' in assign: %s", remain);
remain += skip;
- if(remain[0]) remain[strlen(remain)-1]=0; /* remove newline */
+ strip_end_white(remain);
mom->string = strdup(remain);
if(!mom->variable || !mom->string)
fatal_exit("out of memory");
@@ -318,8 +317,7 @@ replay_moment_read(char* remain, FILE* in, const char* name,
mom->evt_type = repevt_autotrust_check;
while(isspace((unsigned char)*remain))
remain++;
- if(strlen(remain)>0 && remain[strlen(remain)-1]=='\n')
- remain[strlen(remain)-1] = 0;
+ strip_end_white(remain);
mom->autotrust_id = strdup(remain);
if(!mom->autotrust_id) fatal_exit("out of memory");
read_file_content(in, &pstate->lineno, mom);
@@ -327,8 +325,7 @@ replay_moment_read(char* remain, FILE* in, const char* name,
mom->evt_type = repevt_tempfile_check;
while(isspace((unsigned char)*remain))
remain++;
- if(strlen(remain)>0 && remain[strlen(remain)-1]=='\n')
- remain[strlen(remain)-1] = 0;
+ strip_end_white(remain);
mom->autotrust_id = strdup(remain);
if(!mom->autotrust_id) fatal_exit("out of memory");
read_file_content(in, &pstate->lineno, mom);
@@ -359,8 +356,7 @@ replay_moment_read(char* remain, FILE* in, const char* name,
m++;
if(!extstrtoaddr(s, &mom->addr, &mom->addrlen))
fatal_exit("bad infra_rtt address %s", s);
- if(strlen(m)>0 && m[strlen(m)-1]=='\n')
- m[strlen(m)-1] = 0;
+ strip_end_white(m);
mom->variable = strdup(remain);
mom->string = strdup(m);
if(!mom->string) fatal_exit("out of memory");
@@ -375,8 +371,7 @@ replay_moment_read(char* remain, FILE* in, const char* name,
if(parse_keyword(&remain, "ADDRESS")) {
while(isspace((unsigned char)*remain))
remain++;
- if(strlen(remain) > 0) /* remove \n */
- remain[strlen(remain)-1] = 0;
+ strip_end_white(remain);
if(!extstrtoaddr(remain, &mom->addr, &mom->addrlen)) {
log_err("line %d: could not parse ADDRESS: %s",
pstate->lineno, remain);
@@ -693,7 +688,11 @@ do_macro_ctime(char* arg)
return NULL;
}
ctime_r(&tt, buf);
- if(buf[0]) buf[strlen(buf)-1]=0; /* remove trailing newline */
+#ifdef USE_WINSOCK
+ if(strlen(buf) > 10 && buf[7]==' ' && buf[8]=='0')
+ buf[8]=' '; /* fix error in windows ctime */
+#endif
+ strip_end_white(buf);
return strdup(buf);
}
diff --git a/usr.sbin/unbound/testcode/replay.h b/usr.sbin/unbound/testcode/replay.h
index 5132cdacbd4..0271dff0393 100644
--- a/usr.sbin/unbound/testcode/replay.h
+++ b/usr.sbin/unbound/testcode/replay.h
@@ -425,6 +425,9 @@ int replay_var_compare(const void* a, const void* b);
/** get oldest enabled fake timer */
struct fake_timer* replay_get_oldest_timer(struct replay_runtime* runtime);
+/** strip whitespace from end of string */
+void strip_end_white(char* p);
+
/**
* Create variable storage
* @return new or NULL on failure.
diff --git a/usr.sbin/unbound/testcode/streamtcp.c b/usr.sbin/unbound/testcode/streamtcp.c
index ffdddbe9db4..2bd076ee5db 100644
--- a/usr.sbin/unbound/testcode/streamtcp.c
+++ b/usr.sbin/unbound/testcode/streamtcp.c
@@ -397,11 +397,17 @@ send_em(const char* svr, int udp, int usessl, int noanswer, int onarrival,
/** SIGPIPE handler */
static RETSIGTYPE sigh(int sig)
{
+ char str[] = "Got unhandled signal \n";
if(sig == SIGPIPE) {
- printf("got SIGPIPE, remote connection gone\n");
+ char* strpipe = "got SIGPIPE, remote connection gone\n";
+ /* simple cast to void will not silence Wunused-result */
+ (void)!write(STDOUT_FILENO, strpipe, strlen(strpipe));
exit(1);
}
- printf("Got unhandled signal %d\n", sig);
+ str[21] = '0' + (sig/10)%10;
+ str[22] = '0' + sig%10;
+ /* simple cast to void will not silence Wunused-result */
+ (void)!write(STDOUT_FILENO, str, strlen(str));
exit(1);
}
#endif /* SIGPIPE */
diff --git a/usr.sbin/unbound/testcode/testbound.c b/usr.sbin/unbound/testcode/testbound.c
index 5e10779fcde..c9290014287 100644
--- a/usr.sbin/unbound/testcode/testbound.c
+++ b/usr.sbin/unbound/testcode/testbound.c
@@ -168,7 +168,7 @@ spool_temp_file_name(int* lineno, FILE* cfg, char* id)
id++;
if(*id == '\0')
fatal_exit("TEMPFILE_NAME must have id, line %d", *lineno);
- id[strlen(id)-1]=0; /* remove newline */
+ strip_end_white(id);
fake_temp_file("_temp_", id, line, sizeof(line));
fprintf(cfg, "\"%s\"\n", line);
}
@@ -185,7 +185,7 @@ spool_temp_file(FILE* in, int* lineno, char* id)
id++;
if(*id == '\0')
fatal_exit("TEMPFILE_CONTENTS must have id, line %d", *lineno);
- id[strlen(id)-1]=0; /* remove newline */
+ strip_end_white(id);
fake_temp_file("_temp_", id, line, sizeof(line));
/* open file and spool to it */
spool = fopen(line, "w");
@@ -205,7 +205,7 @@ spool_temp_file(FILE* in, int* lineno, char* id)
char* tid = parse+17;
while(isspace((unsigned char)*tid))
tid++;
- tid[strlen(tid)-1]=0; /* remove newline */
+ strip_end_white(tid);
fake_temp_file("_temp_", tid, l2, sizeof(l2));
snprintf(line, sizeof(line), "$INCLUDE %s\n", l2);
}
@@ -230,7 +230,7 @@ spool_auto_file(FILE* in, int* lineno, FILE* cfg, char* id)
id++;
if(*id == '\0')
fatal_exit("AUTROTRUST_FILE must have id, line %d", *lineno);
- id[strlen(id)-1]=0; /* remove newline */
+ strip_end_white(id);
fake_temp_file("_auto_", id, line, sizeof(line));
/* add option for the file */
fprintf(cfg, "server: auto-trust-anchor-file: \"%s\"\n", line);
@@ -279,6 +279,7 @@ setup_config(FILE* in, int* lineno, int* pass_argc, char* pass_argv[])
fprintf(cfg, " username: \"\"\n");
fprintf(cfg, " pidfile: \"\"\n");
fprintf(cfg, " val-log-level: 2\n");
+ fprintf(cfg, " log-servfail: yes\n");
fprintf(cfg, "remote-control: control-enable: no\n");
while(fgets(line, MAX_LINE_LEN-1, in)) {
parse = line;
diff --git a/usr.sbin/unbound/testcode/unitauth.c b/usr.sbin/unbound/testcode/unitauth.c
index 4b3410c9ef7..d193526b8c2 100644
--- a/usr.sbin/unbound/testcode/unitauth.c
+++ b/usr.sbin/unbound/testcode/unitauth.c
@@ -468,8 +468,13 @@ tmpfilecleanup(void)
int i;
char buf[256];
for(i=0; i<tempno; i++) {
+#ifdef USE_WINSOCK
+ snprintf(buf, sizeof(buf), "unbound.unittest.%u.%d",
+ (unsigned)getpid(), i);
+#else
snprintf(buf, sizeof(buf), "/tmp/unbound.unittest.%u.%d",
(unsigned)getpid(), i);
+#endif
if(vbmp) printf("cleanup: unlink %s\n", buf);
unlink(buf);
}
@@ -483,8 +488,13 @@ create_tmp_file(const char* s)
char *fname;
FILE *out;
size_t r;
+#ifdef USE_WINSOCK
+ snprintf(buf, sizeof(buf), "unbound.unittest.%u.%d",
+ (unsigned)getpid(), tempno++);
+#else
snprintf(buf, sizeof(buf), "/tmp/unbound.unittest.%u.%d",
(unsigned)getpid(), tempno++);
+#endif
fname = strdup(buf);
if(!fname) fatal_exit("out of memory");
/* if no string, just make the name */
@@ -517,8 +527,8 @@ del_tmp_file(char* fname)
}
/** Add zone from file for testing */
-static struct auth_zone*
-addzone(struct auth_zones* az, const char* name, char* fname)
+struct auth_zone*
+authtest_addzone(struct auth_zones* az, const char* name, char* fname)
{
struct auth_zone* z;
size_t nmlen;
@@ -593,7 +603,7 @@ check_read_exact(const char* name, const char* zone)
az = auth_zones_create();
unit_assert(az);
- z = addzone(az, name, fname);
+ z = authtest_addzone(az, name, fname);
unit_assert(z);
outf = create_tmp_file(NULL);
if(!auth_zone_write_file(z, outf)) {
@@ -844,7 +854,7 @@ check_queries(const char* name, const char* zone, struct q_ans* queries)
fname = create_tmp_file(zone);
az = auth_zones_create();
if(!az) fatal_exit("out of memory");
- z = addzone(az, name, fname);
+ z = authtest_addzone(az, name, fname);
if(!z) fatal_exit("could not read zone for queries test");
del_tmp_file(fname);
diff --git a/usr.sbin/unbound/testcode/unitldns.c b/usr.sbin/unbound/testcode/unitldns.c
index 22c9ed94558..6397f29dbe2 100644
--- a/usr.sbin/unbound/testcode/unitldns.c
+++ b/usr.sbin/unbound/testcode/unitldns.c
@@ -47,7 +47,7 @@
#include "sldns/parseutil.h"
/** verbose this unit test */
-static int vbmp = 0;
+static int vbmp = 0;
/** print buffer to hex into string */
static void
diff --git a/usr.sbin/unbound/testcode/unitmain.c b/usr.sbin/unbound/testcode/unitmain.c
index c61026f2680..c18be7be3a0 100644
--- a/usr.sbin/unbound/testcode/unitmain.c
+++ b/usr.sbin/unbound/testcode/unitmain.c
@@ -839,52 +839,6 @@ static void respip_test(void)
respip_conf_actions_test();
}
-#include "services/outside_network.h"
-/** add number of new IDs to the reuse tree, randomly chosen */
-static void tcpid_addmore(struct reuse_tcp* reuse,
- struct outside_network* outnet, unsigned int addnum)
-{
- unsigned int i;
- struct waiting_tcp* w;
- for(i=0; i<addnum; i++) {
- uint16_t id = reuse_tcp_select_id(reuse, outnet);
- unit_assert(!reuse_tcp_by_id_find(reuse, id));
- w = calloc(1, sizeof(*w));
- unit_assert(w);
- w->id = id;
- w->outnet = outnet;
- w->next_waiting = (void*)reuse->pending;
- reuse_tree_by_id_insert(reuse, w);
- }
-}
-
-/** fill up the reuse ID tree and test assertions */
-static void tcpid_fillup(struct reuse_tcp* reuse,
- struct outside_network* outnet)
-{
- int t, numtest=3;
- for(t=0; t<numtest; t++) {
- rbtree_init(&reuse->tree_by_id, reuse_id_cmp);
- tcpid_addmore(reuse, outnet, 65535);
- reuse_del_readwait(&reuse->tree_by_id);
- }
-}
-
-/** test TCP ID selection */
-static void tcpid_test(void)
-{
- struct pending_tcp pend;
- struct outside_network outnet;
- unit_show_func("services/outside_network.c", "reuse_tcp_select_id");
- memset(&pend, 0, sizeof(pend));
- pend.reuse.pending = &pend;
- memset(&outnet, 0, sizeof(outnet));
- outnet.rnd = ub_initstate(NULL);
- rbtree_init(&pend.reuse.tree_by_id, reuse_id_cmp);
- tcpid_fillup(&pend.reuse, &outnet);
- ub_randfree(outnet.rnd);
-}
-
void unit_show_func(const char* file, const char* func)
{
printf("test %s:%s\n", file, func);
@@ -952,8 +906,9 @@ main(int argc, char* argv[])
slabhash_test();
infra_test();
ldns_test();
+ zonemd_test();
+ tcpreuse_test();
msgparse_test();
- tcpid_test();
#ifdef CLIENT_SUBNET
ecs_test();
#endif /* CLIENT_SUBNET */
diff --git a/usr.sbin/unbound/testcode/unitmain.h b/usr.sbin/unbound/testcode/unitmain.h
index e5c6109a2aa..adcd74f77b5 100644
--- a/usr.sbin/unbound/testcode/unitmain.h
+++ b/usr.sbin/unbound/testcode/unitmain.h
@@ -80,5 +80,9 @@ void ecs_test(void);
void ldns_test(void);
/** unit test for auth zone functions */
void authzone_test(void);
+/** unit test for zonemd functions */
+void zonemd_test(void);
+/** unit test for tcp_reuse functions */
+void tcpreuse_test(void);
#endif /* TESTCODE_UNITMAIN_H */
diff --git a/usr.sbin/unbound/testcode/unittcpreuse.c b/usr.sbin/unbound/testcode/unittcpreuse.c
new file mode 100644
index 00000000000..087c6c1b9d5
--- /dev/null
+++ b/usr.sbin/unbound/testcode/unittcpreuse.c
@@ -0,0 +1,236 @@
+/*
+ * testcode/unittcpreuse.c - unit test for tcp_reuse.
+ *
+ * Copyright (c) 2021, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * \file
+ * Tests the tcp_reuse functionality.
+ */
+
+#include "config.h"
+#include "testcode/unitmain.h"
+#include "util/log.h"
+#include "util/random.h"
+#include "services/outside_network.h"
+
+/** add number of new IDs to the reuse tree, randomly chosen */
+static void tcpid_addmore(struct reuse_tcp* reuse,
+ struct outside_network* outnet, unsigned int addnum)
+{
+ unsigned int i;
+ struct waiting_tcp* w;
+ for(i=0; i<addnum; i++) {
+ uint16_t id = reuse_tcp_select_id(reuse, outnet);
+ unit_assert(!reuse_tcp_by_id_find(reuse, id));
+ w = calloc(1, sizeof(*w));
+ unit_assert(w);
+ w->id = id;
+ w->outnet = outnet;
+ w->next_waiting = (void*)reuse->pending;
+ reuse_tree_by_id_insert(reuse, w);
+ }
+}
+
+/** fill up the reuse ID tree and test assertions */
+static void tcpid_fillup(struct reuse_tcp* reuse,
+ struct outside_network* outnet)
+{
+ int t, numtest=3;
+ for(t=0; t<numtest; t++) {
+ rbtree_init(&reuse->tree_by_id, reuse_id_cmp);
+ tcpid_addmore(reuse, outnet, 65535);
+ reuse_del_readwait(&reuse->tree_by_id);
+ }
+}
+
+/** test TCP ID selection */
+static void tcpid_test(void)
+{
+ struct pending_tcp pend;
+ struct outside_network outnet;
+ unit_show_func("services/outside_network.c", "reuse_tcp_select_id");
+ memset(&pend, 0, sizeof(pend));
+ pend.reuse.pending = &pend;
+ memset(&outnet, 0, sizeof(outnet));
+ outnet.rnd = ub_initstate(NULL);
+ rbtree_init(&pend.reuse.tree_by_id, reuse_id_cmp);
+ tcpid_fillup(&pend.reuse, &outnet);
+ ub_randfree(outnet.rnd);
+}
+
+/** check that the tree has present number of nodes and the LRU is linked
+ * properly. */
+static void check_tree_and_list(struct outside_network* outnet, int present)
+{
+ int i;
+ struct reuse_tcp *reuse, *next_reuse;
+ unit_assert(present == (int)outnet->tcp_reuse.count);
+ if(present < 1) {
+ unit_assert(outnet->tcp_reuse_first == NULL);
+ unit_assert(outnet->tcp_reuse_last == NULL);
+ return;
+ }
+ unit_assert(outnet->tcp_reuse_first->item_on_lru_list);
+ unit_assert(!outnet->tcp_reuse_first->lru_prev);
+ reuse = outnet->tcp_reuse_first;
+ for(i=0; i<present-1; i++) {
+ unit_assert(reuse->item_on_lru_list);
+ unit_assert(reuse->lru_next);
+ unit_assert(reuse->lru_next != reuse);
+ next_reuse = reuse->lru_next;
+ unit_assert(next_reuse->lru_prev == reuse);
+ reuse = next_reuse;
+ }
+ unit_assert(!reuse->lru_next);
+ unit_assert(outnet->tcp_reuse_last->item_on_lru_list);
+ unit_assert(outnet->tcp_reuse_last == reuse);
+}
+
+/** creates pending_tcp. Copy of outside_network.c:create_pending_tcp without
+ * the comm_point creation */
+static int create_pending_tcp(struct outside_network* outnet)
+{
+ size_t i;
+ if(outnet->num_tcp == 0)
+ return 1; /* no tcp needed, nothing to do */
+ if(!(outnet->tcp_conns = (struct pending_tcp **)calloc(
+ outnet->num_tcp, sizeof(struct pending_tcp*))))
+ return 0;
+ for(i=0; i<outnet->num_tcp; i++) {
+ if(!(outnet->tcp_conns[i] = (struct pending_tcp*)calloc(1,
+ sizeof(struct pending_tcp))))
+ return 0;
+ outnet->tcp_conns[i]->next_free = outnet->tcp_free;
+ outnet->tcp_free = outnet->tcp_conns[i];
+ }
+ return 1;
+}
+
+/** empty the tcp_reuse tree and LRU list */
+static void empty_tree(struct outside_network* outnet)
+{
+ size_t i;
+ struct reuse_tcp* reuse;
+ reuse = outnet->tcp_reuse_first;
+ i = outnet->tcp_reuse.count;
+ while(reuse) {
+ reuse_tcp_remove_tree_list(outnet, reuse);
+ check_tree_and_list(outnet, --i);
+ reuse = outnet->tcp_reuse_first;
+ }
+}
+
+/** check removal of the LRU element on the given position of total elements */
+static void check_removal(struct outside_network* outnet, int position, int total)
+{
+ int i;
+ struct reuse_tcp* reuse;
+ empty_tree(outnet);
+ for(i=0; i<total; i++) {
+ reuse_tcp_insert(outnet, outnet->tcp_conns[i]);
+ }
+ check_tree_and_list(outnet, total);
+ reuse = outnet->tcp_reuse_first;
+ for(i=0; i<position; i++) reuse = reuse->lru_next;
+ reuse_tcp_remove_tree_list(outnet, reuse);
+ check_tree_and_list(outnet, total-1);
+}
+
+/** check snipping off the last element of the LRU with total elements */
+static void check_snip(struct outside_network* outnet, int total)
+{
+ int i;
+ struct reuse_tcp* reuse;
+ empty_tree(outnet);
+ for(i=0; i<total; i++) {
+ reuse_tcp_insert(outnet, outnet->tcp_conns[i]);
+ }
+ check_tree_and_list(outnet, total);
+ reuse = reuse_tcp_lru_snip(outnet);
+ while(reuse) {
+ reuse_tcp_remove_tree_list(outnet, reuse);
+ check_tree_and_list(outnet, --total);
+ reuse = reuse_tcp_lru_snip(outnet);
+ }
+ unit_assert(outnet->tcp_reuse_first == NULL);
+ unit_assert(outnet->tcp_reuse_last == NULL);
+ unit_assert(outnet->tcp_reuse.count == 0);
+}
+
+/** test tcp_reuse tree and LRU list functions */
+static void tcp_reuse_tree_list_test(void)
+{
+ size_t i;
+ struct outside_network outnet;
+ struct reuse_tcp* reuse;
+ memset(&outnet, 0, sizeof(outnet));
+ rbtree_init(&outnet.tcp_reuse, reuse_cmp);
+ outnet.num_tcp = 5;
+ outnet.tcp_reuse_max = outnet.num_tcp;
+ if(!create_pending_tcp(&outnet)) fatal_exit("out of memory");
+ /* add all to the tree */
+ unit_show_func("services/outside_network.c", "reuse_tcp_insert");
+ for(i=0; i<outnet.num_tcp; i++) {
+ reuse_tcp_insert(&outnet, outnet.tcp_conns[i]);
+ check_tree_and_list(&outnet, i+1);
+ }
+ /* check touching */
+ unit_show_func("services/outside_network.c", "reuse_tcp_lru_touch");
+ for(i=0; i<outnet.tcp_reuse.count; i++) {
+ for(reuse = outnet.tcp_reuse_first; reuse->lru_next; reuse = reuse->lru_next);
+ reuse_tcp_lru_touch(&outnet, reuse);
+ check_tree_and_list(&outnet, outnet.num_tcp);
+ }
+ /* check removal */
+ unit_show_func("services/outside_network.c", "reuse_tcp_remove_tree_list");
+ check_removal(&outnet, 2, 5);
+ check_removal(&outnet, 1, 3);
+ check_removal(&outnet, 1, 2);
+ /* check snip */
+ unit_show_func("services/outside_network.c", "reuse_tcp_lru_snip");
+ check_snip(&outnet, 4);
+
+ for(i=0; i<outnet.num_tcp; i++)
+ if(outnet.tcp_conns[i]) {
+ free(outnet.tcp_conns[i]);
+ }
+ free(outnet.tcp_conns);
+}
+
+void tcpreuse_test(void)
+{
+ unit_show_feature("tcp_reuse");
+ tcpid_test();
+ tcp_reuse_tree_list_test();
+}
diff --git a/usr.sbin/unbound/testcode/unitzonemd.c b/usr.sbin/unbound/testcode/unitzonemd.c
new file mode 100644
index 00000000000..5caa68a102c
--- /dev/null
+++ b/usr.sbin/unbound/testcode/unitzonemd.c
@@ -0,0 +1,537 @@
+/*
+ * testcode/unitzonemd.c - unit test for zonemd.
+ *
+ * Copyright (c) 2020, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * \file
+ * Unit tests for ZONEMD functionality.
+ */
+
+#include "config.h"
+#include <ctype.h>
+#include "util/log.h"
+#include "testcode/unitmain.h"
+#include "sldns/str2wire.h"
+#include "services/authzone.h"
+#include "util/data/dname.h"
+#include "util/regional.h"
+#include "validator/val_anchor.h"
+
+#define xstr(s) str(s)
+#define str(s) #s
+#define SRCDIRSTR xstr(SRCDIR)
+
+/** Add zone from file for testing */
+struct auth_zone* authtest_addzone(struct auth_zones* az, const char* name,
+ char* fname);
+
+/** zonemd unit test, generate a zonemd digest and check if correct */
+static void zonemd_generate_test(const char* zname, char* zfile,
+ int scheme, int hashalgo, const char* digest)
+{
+ uint8_t zonemd_hash[512];
+ size_t hashlen = 0;
+ char output[1024+1];
+ size_t i;
+ struct auth_zones* az;
+ struct auth_zone* z;
+ int result;
+ struct regional* region = NULL;
+ struct sldns_buffer* buf = NULL;
+ char* reason = NULL;
+ char* digestdup;
+
+ if(!zonemd_hashalgo_supported(hashalgo))
+ return; /* cannot test unsupported algo */
+
+ /* setup environment */
+ az = auth_zones_create();
+ unit_assert(az);
+ region = regional_create();
+ unit_assert(region);
+ buf = sldns_buffer_new(65535);
+ unit_assert(buf);
+
+ /* read file */
+ z = authtest_addzone(az, zname, zfile);
+ unit_assert(z);
+ lock_rw_wrlock(&z->lock);
+ z->zonemd_check = 1;
+ lock_rw_unlock(&z->lock);
+
+ /* create zonemd digest */
+ result = auth_zone_generate_zonemd_hash(z, scheme, hashalgo,
+ zonemd_hash, sizeof(zonemd_hash), &hashlen, region, buf,
+ &reason);
+ if(reason) printf("zonemd failure reason: %s\n", reason);
+ unit_assert(result);
+
+ /* check digest */
+ unit_assert(hashlen*2+1 <= sizeof(output));
+ for(i=0; i<hashlen; i++) {
+ const char* hexl = "0123456789ABCDEF";
+ output[i*2] = hexl[(zonemd_hash[i]&0xf0)>>4];
+ output[i*2+1] = hexl[zonemd_hash[i]&0xf];
+ }
+ output[hashlen*2] = 0;
+ digestdup = strdup(digest);
+ unit_assert(digestdup);
+ for(i=0; i<strlen(digestdup); i++) {
+ digestdup[i] = toupper(digestdup[i]);
+ }
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(z->name, zname);
+ printf("zonemd generated for %s in %s with "
+ "scheme=%d hashalgo=%d\n", zname, z->zonefile,
+ scheme, hashalgo);
+ printf("digest %s\n", output);
+ printf("wanted %s\n", digestdup);
+ }
+ unit_assert(strcmp(output, digestdup) == 0);
+
+ /* delete environment */
+ free(digestdup);
+ auth_zones_delete(az);
+ regional_destroy(region);
+ sldns_buffer_free(buf);
+
+ if(verbosity >= VERB_ALGO) {
+ printf("\n");
+ }
+}
+
+/** loop over files and test generated zonemd digest */
+static void zonemd_generate_tests(void)
+{
+ unit_show_func("services/authzone.c", "auth_zone_generate_zonemd_hash");
+ zonemd_generate_test("example.org", SRCDIRSTR "/testdata/zonemd.example1.zone",
+ 1, 2, "20564D10F50A0CEBEC856C64032B7DFB53D3C449A421A5BC7A21F7627B4ACEA4DF29F2C6FE82ED9C23ADF6F4D420D5DD63EF6E6349D60FDAB910B65DF8D481B7");
+
+ /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12
+ * from section A.1 */
+ zonemd_generate_test("example", SRCDIRSTR "/testdata/zonemd.example_a1.zone",
+ 1, 1, "c68090d90a7aed716bc459f9340e3d7c1370d4d24b7e2fc3a1ddc0b9a87153b9a9713b3c9ae5cc27777f98b8e730044c");
+
+ /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12
+ * from section A.2 */
+ zonemd_generate_test("example", SRCDIRSTR "/testdata/zonemd.example_a2.zone",
+ 1, 1, "31cefb03814f5062ad12fa951ba0ef5f8da6ae354a415767246f7dc932ceb1e742a2108f529db6a33a11c01493de358d");
+
+ /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12
+ * from section A.3 SHA384 digest */
+ zonemd_generate_test("example", SRCDIRSTR "/testdata/zonemd.example_a3.zone",
+ 1, 1, "62e6cf51b02e54b9b5f967d547ce43136792901f9f88e637493daaf401c92c279dd10f0edb1c56f8080211f8480ee306");
+
+ /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12
+ * from section A.3 SHA512 digest*/
+ zonemd_generate_test("example", SRCDIRSTR "/testdata/zonemd.example_a3.zone",
+ 1, 2, "08cfa1115c7b948c4163a901270395ea226a930cd2cbcf2fa9a5e6eb85f37c8a4e114d884e66f176eab121cb02db7d652e0cc4827e7a3204f166b47e5613fd27");
+
+ /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12
+ * from section A.4 */
+ zonemd_generate_test("uri.arpa", SRCDIRSTR "/testdata/zonemd.example_a4.zone",
+ 1, 1, "1291b78ddf7669b1a39d014d87626b709b55774c5d7d58fadc556439889a10eaf6f11d615900a4f996bd46279514e473");
+
+ /* https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-12
+ * from section A.5 */
+ zonemd_generate_test("root-servers.net", SRCDIRSTR "/testdata/zonemd.example_a5.zone",
+ 1, 1, "f1ca0ccd91bd5573d9f431c00ee0101b2545c97602be0a978a3b11dbfc1c776d5b3e86ae3d973d6b5349ba7f04340f79");
+}
+
+/** test the zonemd check routine */
+static void zonemd_check_test(void)
+{
+ const char* zname = "example.org";
+ char* zfile = SRCDIRSTR "/testdata/zonemd.example1.zone";
+ int scheme = 1;
+ int hashalgo = 2;
+ const char* digest = "20564D10F50A0CEBEC856C64032B7DFB53D3C449A421A5BC7A21F7627B4ACEA4DF29F2C6FE82ED9C23ADF6F4D420D5DD63EF6E6349D60FDAB910B65DF8D481B7";
+ const char* digestwrong = "20564D10F50A0CEBEC856C64032B7DFB53D3C449A421A5BC7A21F7627B4ACEA4DF29F2C6FE82ED9C23ADF6F4D420D5DD63EF6E6349D60FDAB910B65DF8D48100";
+ uint8_t hash[512], hashwrong[512];
+ size_t hashlen = 0, hashwronglen = 0;
+ struct auth_zones* az;
+ struct auth_zone* z;
+ int result;
+ struct regional* region = NULL;
+ struct sldns_buffer* buf = NULL;
+ char* reason = NULL;
+
+ if(!zonemd_hashalgo_supported(hashalgo))
+ return; /* cannot test unsupported algo */
+ unit_show_func("services/authzone.c", "auth_zone_generate_zonemd_check");
+
+ /* setup environment */
+ az = auth_zones_create();
+ unit_assert(az);
+ region = regional_create();
+ unit_assert(region);
+ buf = sldns_buffer_new(65535);
+ unit_assert(buf);
+
+ /* read file */
+ z = authtest_addzone(az, zname, zfile);
+ unit_assert(z);
+ lock_rw_wrlock(&z->lock);
+ z->zonemd_check = 1;
+ lock_rw_unlock(&z->lock);
+ hashlen = sizeof(hash);
+ if(sldns_str2wire_hex_buf(digest, hash, &hashlen) != 0) {
+ unit_assert(0); /* parse failure */
+ }
+ hashwronglen = sizeof(hashwrong);
+ if(sldns_str2wire_hex_buf(digestwrong, hashwrong, &hashwronglen) != 0) {
+ unit_assert(0); /* parse failure */
+ }
+
+ /* check return values of the check routine */
+ result = auth_zone_generate_zonemd_check(z, scheme, hashalgo,
+ hash, hashlen, region, buf, &reason);
+ unit_assert(result && reason == NULL);
+ result = auth_zone_generate_zonemd_check(z, 241, hashalgo,
+ hash, hashlen, region, buf, &reason);
+ unit_assert(!result && strcmp(reason, "unsupported scheme")==0);
+ result = auth_zone_generate_zonemd_check(z, scheme, 242,
+ hash, hashlen, region, buf, &reason);
+ unit_assert(!result && strcmp(reason, "unsupported algorithm")==0);
+ result = auth_zone_generate_zonemd_check(z, scheme, hashalgo,
+ hash, 2, region, buf, &reason);
+ unit_assert(!result && strcmp(reason, "digest length too small, less than 12")==0);
+ result = auth_zone_generate_zonemd_check(z, scheme, hashalgo,
+ hashwrong, hashwronglen, region, buf, &reason);
+ unit_assert(!result && strcmp(reason, "incorrect digest")==0);
+ result = auth_zone_generate_zonemd_check(z, scheme, hashalgo,
+ hashwrong, hashwronglen-3, region, buf, &reason);
+ unit_assert(!result && strcmp(reason, "incorrect digest length")==0);
+
+ /* delete environment */
+ auth_zones_delete(az);
+ regional_destroy(region);
+ sldns_buffer_free(buf);
+
+ if(verbosity >= VERB_ALGO) {
+ printf("\n");
+ }
+}
+
+/** zonemd test verify */
+static void zonemd_verify_test(char* zname, char* zfile, char* tastr,
+ char* date_override, char* result_wanted)
+{
+ time_t now = 0;
+ struct module_stack mods;
+ struct module_env env;
+ char* result = NULL;
+ struct auth_zone* z;
+
+ /* setup test harness */
+ memset(&mods, 0, sizeof(mods));
+ memset(&env, 0, sizeof(env));
+ env.scratch = regional_create();
+ if(!env.scratch)
+ fatal_exit("out of memory");
+ env.scratch_buffer = sldns_buffer_new(65553);
+ if(!env.scratch_buffer)
+ fatal_exit("out of memory");
+ env.cfg = config_create();
+ if(!env.cfg)
+ fatal_exit("out of memory");
+ env.now = &now;
+ env.cfg->val_date_override = cfg_convert_timeval(date_override);
+ if(!env.cfg->val_date_override)
+ fatal_exit("could not parse datetime %s", date_override);
+ if(env.cfg->module_conf)
+ free(env.cfg->module_conf);
+ env.cfg->module_conf = strdup("validator iterator");
+ if(!env.cfg->module_conf)
+ fatal_exit("out of memory");
+ if(tastr) {
+ if(!cfg_strlist_insert(&env.cfg->trust_anchor_list,
+ strdup(tastr)))
+ fatal_exit("out of memory");
+ }
+ env.anchors = anchors_create();
+ if(!env.anchors)
+ fatal_exit("out of memory");
+ env.auth_zones = auth_zones_create();
+ if(!env.auth_zones)
+ fatal_exit("out of memory");
+ modstack_init(&mods);
+ if(!modstack_setup(&mods, env.cfg->module_conf, &env))
+ fatal_exit("could not modstack_setup");
+ env.mesh = mesh_create(&mods, &env);
+ if(!env.mesh)
+ fatal_exit("out of memory");
+
+ /* load data */
+ z = authtest_addzone(env.auth_zones, zname, zfile);
+ if(!z)
+ fatal_exit("could not addzone %s %s", zname, zfile);
+
+ /* test */
+ lock_rw_wrlock(&z->lock);
+ z->zonemd_check = 1;
+ auth_zone_verify_zonemd(z, &env, &mods, &result, 1, 0);
+ lock_rw_unlock(&z->lock);
+ if(verbosity >= VERB_ALGO) {
+ printf("auth zone %s: ZONEMD verification %s: %s\n", zname,
+ (strcmp(result, "ZONEMD verification successful")==0?"successful":"failed"),
+ result);
+ }
+ if(!result)
+ fatal_exit("out of memory");
+ unit_assert(strcmp(result, result_wanted) == 0);
+ if(strcmp(result, "ZONEMD verification successful") == 0 ||
+ strcmp(result, "DNSSEC verified nonexistence of ZONEMD") == 0 ||
+ strcmp(result, "no ZONEMD present") == 0) {
+ lock_rw_rdlock(&z->lock);
+ unit_assert(!z->zone_expired);
+ lock_rw_unlock(&z->lock);
+ } else {
+ lock_rw_rdlock(&z->lock);
+ unit_assert(z->zone_expired);
+ lock_rw_unlock(&z->lock);
+ }
+ free(result);
+
+ /* desetup test harness */
+ mesh_delete(env.mesh);
+ modstack_desetup(&mods, &env);
+ auth_zones_delete(env.auth_zones);
+ anchors_delete(env.anchors);
+ config_delete(env.cfg);
+ regional_destroy(env.scratch);
+ sldns_buffer_free(env.scratch_buffer);
+
+ if(verbosity >= VERB_ALGO) {
+ printf("\n");
+ }
+}
+
+/** zonemd test verify suite */
+static void zonemd_verify_tests(void)
+{
+ unit_show_func("services/authzone.c", "auth_zone_verify_zonemd");
+ /* give trustanchor for unsigned zone, should fail */
+ zonemd_verify_test("example.org",
+ SRCDIRSTR "/testdata/zonemd.example1.zone",
+ "example.org. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20180302005009",
+ "verify DNSKEY RRset with trust anchor failed: have trust anchor, but zone has no DNSKEY");
+ /* unsigned zone without ZONEMD in it */
+ zonemd_verify_test("example.org",
+ SRCDIRSTR "/testdata/zonemd.example1.zone",
+ NULL,
+ "20180302005009",
+ "no ZONEMD present");
+ /* no trust anchor, so it succeeds for zone with a correct ZONEMD */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example2.zone",
+ NULL,
+ "20180302005009",
+ "ZONEMD verification successful");
+ /* trust anchor for another zone, so it is indeterminate */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example2.zone",
+ "example.org. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20180302005009",
+ "ZONEMD verification successful");
+
+ /* load a DNSSEC signed zone, but no trust anchor */
+ /* this zonefile has an incorrect ZONEMD digest, with correct
+ * DNSSEC signature. */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example3.zone",
+ NULL,
+ "20180302005009",
+ "incorrect digest");
+ /* load a DNSSEC zone with NSEC3, but no trust anchor */
+ /* this zonefile has an incorrect ZONEMD digest, with correct
+ * DNSSEC signature. */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example4.zone",
+ NULL,
+ "20180302005009",
+ "incorrect digest");
+ /* valid zonemd, in dnssec signed zone, no trust anchor*/
+ /* this zonefile has a correct ZONEMD digest and
+ * correct DNSSEC signature */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example5.zone",
+ NULL,
+ "20180302005009",
+ "ZONEMD verification successful");
+ /* valid zonemd, in dnssec NSEC3 zone, no trust anchor*/
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example6.zone",
+ NULL,
+ "20180302005009",
+ "ZONEMD verification successful");
+
+ /* load a DNSSEC signed zone with a trust anchor, valid ZONEMD */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example5.zone",
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20201020135527",
+ "ZONEMD verification successful");
+ /* load a DNSSEC NSEC3 signed zone with a trust anchor, valid ZONEMD */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example6.zone",
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20201020135527",
+ "ZONEMD verification successful");
+
+ /* load a DNSSEC NSEC zone without ZONEMD */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example7.zone",
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20201020135527",
+ "DNSSEC verified nonexistence of ZONEMD");
+ /* load a DNSSEC NSEC3 zone without ZONEMD */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example8.zone",
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20201020135527",
+ "DNSSEC verified nonexistence of ZONEMD");
+
+ /* load DNSSEC zone but RRSIG on ZONEMD is wrong */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example9.zone",
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20201020135527",
+#ifdef HAVE_SSL
+ "DNSSEC verify failed for ZONEMD RRset: signature crypto failed"
+#else /* HAVE_NETTLE */
+ "DNSSEC verify failed for ZONEMD RRset: RSA signature verification failed"
+#endif
+ );
+ /* load DNSSEC zone but RRSIG on SOA is wrong */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example10.zone",
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20201020135527",
+#ifdef HAVE_SSL
+ "DNSSEC verify failed for SOA RRset: signature crypto failed"
+#else /* HAVE_NETTLE */
+ "DNSSEC verify failed for SOA RRset: RSA signature verification failed"
+#endif
+ );
+
+ /* load DNSSEC zone without ZONEMD, but NSEC bitmap says it exists */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example11.zone",
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20201020135527",
+ "DNSSEC NSEC bitmap says type ZONEMD exists");
+ /* load DNSSEC zone without ZONEMD, but NSEC3 bitmap says it exists */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example12.zone",
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20201020135527",
+ "DNSSEC NSEC3 bitmap says type ZONEMD exists");
+
+ /* load DNSSEC zone without ZONEMD, but RRSIG on NSEC not okay */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example13.zone",
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20201020135527",
+#ifdef HAVE_SSL
+ "DNSSEC verify failed for NSEC RRset: signature crypto failed"
+#else /* HAVE_NETTLE */
+ "DNSSEC verify failed for NSEC RRset: RSA signature verification failed"
+#endif
+ );
+ /* load DNSSEC zone without ZONEMD, but RRSIG on NSEC3 not okay */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example14.zone",
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20201020135527",
+#ifdef HAVE_SSL
+ "DNSSEC verify failed for NSEC3 RRset: signature crypto failed"
+#else /* HAVE_NETTLE */
+ "DNSSEC verify failed for NSEC3 RRset: RSA signature verification failed"
+#endif
+ );
+
+ /* load DNSSEC zone, with ZONEMD, but DNSKEY RRSIG is not okay. */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example15.zone",
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ "20201020135527",
+#ifdef HAVE_SSL
+ "verify DNSKEY RRset with trust anchor failed: signature crypto failed"
+#else /* HAVE_NETTLE */
+ "verify DNSKEY RRset with trust anchor failed: RSA signature verification failed"
+#endif
+ );
+ /* load DNSSEC zone, but trust anchor mismatches DNSKEY */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example5.zone",
+ /* okay anchor is
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af", */
+ "example.com. IN DS 55566 8 2 0000000000111111222223333444444dfcf92595148022f2c2fd98e5deee90af",
+ "20201020135527",
+ "verify DNSKEY RRset with trust anchor failed: DS hash mismatches key");
+ /* load DNSSEC zone, but trust anchor fails because the zone
+ * has expired signatures. We set the date for it */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example5.zone",
+ "example.com. IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af",
+ /* okay date: "20201020135527", */
+ "20221020135527",
+ "verify DNSKEY RRset with trust anchor failed: signature expired");
+
+ /* duplicate zonemd with same scheme and algorithm */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example16.zone",
+ NULL,
+ "20180302005009",
+ "ZONEMD RRSet contains more than one RR with the same scheme and hash algorithm");
+ /* different capitalisation of ns name and owner names, should
+ * be canonicalized. */
+ zonemd_verify_test("example.com",
+ SRCDIRSTR "/testdata/zonemd.example17.zone",
+ NULL,
+ "20180302005009",
+ "ZONEMD verification successful");
+}
+
+/** zonemd unit tests */
+void zonemd_test(void)
+{
+ unit_show_feature("zonemd");
+ zonemd_generate_tests();
+ zonemd_check_test();
+ zonemd_verify_tests();
+}