xref: /netbsd-src/external/mpl/bind/dist/bin/tests/system/dnssec/tests.sh (revision dd3ee07da436799d8de85f3055253118b76bf345)
1#!/bin/sh
2#
3# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
4#
5# This Source Code Form is subject to the terms of the Mozilla Public
6# License, v. 2.0. If a copy of the MPL was not distributed with this
7# file, you can obtain one at https://mozilla.org/MPL/2.0/.
8#
9# See the COPYRIGHT file distributed with this work for additional
10# information regarding copyright ownership.
11
12# shellcheck source=conf.sh
13SYSTEMTESTTOP=..
14. "$SYSTEMTESTTOP/conf.sh"
15
16set -e
17
18status=0
19n=1
20
21rm -f dig.out.*
22
23dig_with_opts() {
24    "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@"
25}
26
27dig_with_additionalopts() {
28    "$DIG" +noall +additional +dnssec -p "$PORT" "$@"
29}
30
31dig_with_answeropts() {
32    "$DIG" +noall +answer +dnssec -p "$PORT" "$@"
33}
34
35delv_with_opts() {
36    "$DELV" -a ns1/trusted.conf -p "$PORT" "$@"
37}
38
39rndccmd() {
40    "$RNDC" -c "$SYSTEMTESTTOP/common/rndc.conf" -p "$CONTROLPORT" -s "$@"
41}
42
43# TODO: Move loadkeys_on to conf.sh.common
44dnssec_loadkeys_on() {
45	nsidx=$1
46	zone=$2
47	nextpart ns${nsidx}/named.run > /dev/null
48	rndccmd 10.53.0.${nsidx} loadkeys ${zone} | sed "s/^/ns${nsidx} /" | cat_i
49	wait_for_log 20 "next key event" ns${nsidx}/named.run || return 1
50}
51
52# convert private-type records to readable form
53showprivate () {
54    echo "-- $* --"
55    dig_with_opts +nodnssec +short "@$2" -t type65534 "$1" | cut -f3 -d' ' |
56        while read -r record; do
57	    # shellcheck disable=SC2016
58            $PERL -e 'my $rdata = pack("H*", @ARGV[0]);
59                die "invalid record" unless length($rdata) == 5;
60                my ($alg, $key, $remove, $complete) = unpack("CnCC", $rdata);
61                my $action = "signing";
62                $action = "removing" if $remove;
63                my $state = " (incomplete)";
64                $state = " (complete)" if $complete;
65                print ("$action: alg: $alg, key: $key$state\n");' "$record"
66        done
67}
68
69# check that signing records are marked as complete
70checkprivate () {
71    for i in 1 2 3 4 5 6 7 8 9 10; do
72        showprivate "$@" | grep -q incomplete || return 0
73	sleep 1
74    done
75    echo_d "$1 signing incomplete"
76    return 1
77}
78
79# check that a zone file is raw format, version 0
80israw0 () {
81    # shellcheck disable=SC2016
82    < "$1" $PERL -e 'binmode STDIN;
83	             read(STDIN, $input, 8);
84	             ($style, $version) = unpack("NN", $input);
85	             exit 1 if ($style != 2 || $version != 0);'
86    return $?
87}
88
89# check that a zone file is raw format, version 1
90israw1 () {
91    # shellcheck disable=SC2016
92    < "$1" $PERL -e 'binmode STDIN;
93		     read(STDIN, $input, 8);
94                     ($style, $version) = unpack("NN", $input);
95                     exit 1 if ($style != 2 || $version != 1);'
96    return $?
97}
98
99# strip NS and RRSIG NS from input
100stripns () {
101    awk '($4 == "NS") || ($4 == "RRSIG" && $5 == "NS") { next} { print }' "$1"
102}
103
104#
105# Ensure there is not multiple consecutive blank lines.
106# Ensure there is a blank line before "Start view" and
107# "Negative trust anchors:".
108# Ensure there is not a blank line before "Secure roots:".
109#
110check_secroots_layout () {
111	tr -d '\r' < "$1" | \
112	awk '$0 == "" { if (empty) exit(1); empty=1; next }
113	     /Start view/ { if (!empty) exit(1) }
114	     /Secure roots:/ { if (empty) exit(1) }
115	     /Negative trust anchors:/ { if (!empty) exit(1) }
116	     { empty=0 }'
117	return $?
118}
119
120# Check that for a query against a validating resolver where the
121# authoritative zone is unsigned (insecure delegation), glue is returned
122# in the additional section
123echo_i "checking that additional glue is returned for unsigned delegation ($n)"
124ret=0
125$DIG +tcp +dnssec -p "$PORT" a.insecure.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
126grep "ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2" dig.out.ns4.test$n > /dev/null || ret=1
127grep "ns\\.insecure\\.example\\..*A.10\\.53\\.0\\.3" dig.out.ns4.test$n > /dev/null || ret=1
128n=$((n+1))
129if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
130status=$((status+ret))
131
132# Check the example. domain
133
134echo_i "checking that zone transfer worked ($n)"
135for i in 1 2 3 4 5 6 7 8 9
136do
137	ret=0
138	dig_with_opts a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
139	dig_with_opts a.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
140	$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns3.test$n > /dev/null || ret=1
141	[ "$ret" -eq 0 ] && break
142	sleep 1
143done
144digcomp dig.out.ns2.test$n dig.out.ns3.test$n > /dev/null || ret=1
145n=$((n+1))
146test "$ret" -eq 0 || echo_i "failed"
147status=$((status+ret))
148
149# test AD bit:
150#  - dig +adflag asks for authentication (ad in response)
151echo_i "checking AD bit asking for validation ($n)"
152ret=0
153dig_with_opts +noauth +noadd +nodnssec +adflag a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
154dig_with_opts +noauth +noadd +nodnssec +adflag a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
155digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
156grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
157n=$((n+1))
158test "$ret" -eq 0 || echo_i "failed"
159status=$((status+ret))
160
161# test AD bit:
162#  - dig +noadflag
163echo_i "checking that AD is not set without +adflag or +dnssec ($n)"
164ret=0
165dig_with_opts +noauth +noadd +nodnssec +noadflag a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
166dig_with_opts +noauth +noadd +nodnssec +noadflag a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
167digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
168grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
169n=$((n+1))
170test "$ret" -eq 0 || echo_i "failed"
171status=$((status+ret))
172
173echo_i "checking for AD in authoritative answer ($n)"
174ret=0
175dig_with_opts a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
176grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
177n=$((n+1))
178test "$ret" -eq 0 || echo_i "failed"
179status=$((status+ret))
180
181echo_i "checking positive validation NSEC ($n)"
182ret=0
183dig_with_opts +noauth a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
184dig_with_opts +noauth a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
185digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
186grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
187n=$((n+1))
188test "$ret" -eq 0 || echo_i "failed"
189status=$((status+ret))
190
191echo_i "checking that 'example/DS' from the referral was used in previous validation ($n)"
192ret=0
193grep "query 'example/DS/IN' approved" ns1/named.run > /dev/null && ret=1
194grep "fetch: example/DS" ns4/named.run > /dev/null && ret=1
195grep "validating example/DS: starting" ns4/named.run > /dev/null || ret=1
196n=$((n+1))
197test "$ret" -eq 0 || echo_i "failed"
198status=$((status+ret))
199
200if [ -x ${DELV} ] ; then
201   ret=0
202   echo_i "checking positive validation NSEC using dns_client ($n)"
203   delv_with_opts @10.53.0.4 a a.example > delv.out$n || ret=1
204   grep "a.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
205   grep "a.example..*.RRSIG.A [0-9][0-9]* 2 300 .*" delv.out$n > /dev/null || ret=1
206   n=$((n+1))
207   test "$ret" -eq 0 || echo_i "failed"
208   status=$((status+ret))
209
210   ret=0
211   echo_i "checking positive validation NSEC using dns_client (trusted-keys) ($n)"
212   "$DELV" -a ns1/trusted.keys -p "$PORT" @10.53.0.4 a a.example > delv.out$n || ret=1
213   grep "a.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
214   grep "a.example..*.RRSIG.A [0-9][0-9]* 2 300 .*" delv.out$n > /dev/null || ret=1
215   n=$((n+1))
216   test "$ret" -eq 0 || echo_i "failed"
217   status=$((status+ret))
218fi
219
220echo_i "checking positive validation NSEC3 ($n)"
221ret=0
222dig_with_opts +noauth a.nsec3.example. \
223	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
224dig_with_opts +noauth a.nsec3.example. \
225	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
226digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
227grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
228n=$((n+1))
229test "$ret" -eq 0 || echo_i "failed"
230status=$((status+ret))
231
232if [ -x ${DELV} ] ; then
233   ret=0
234   echo_i "checking positive validation NSEC3 using dns_client ($n)"
235   delv_with_opts @10.53.0.4 a a.nsec3.example > delv.out$n || ret=1
236   grep "a.nsec3.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
237   grep "a.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n > /dev/null || ret=1
238   n=$((n+1))
239   test "$ret" -eq 0 || echo_i "failed"
240   status=$((status+ret))
241fi
242
243echo_i "checking positive validation OPTOUT ($n)"
244ret=0
245dig_with_opts +noauth a.optout.example. \
246	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
247dig_with_opts +noauth a.optout.example. \
248	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
249digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
250grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
251n=$((n+1))
252test "$ret" -eq 0 || echo_i "failed"
253status=$((status+ret))
254
255SP="[[:space:]]+"
256
257if [ -x ${DELV} ] ; then
258   ret=0
259   echo_i "checking positive validation OPTOUT using dns_client ($n)"
260   delv_with_opts @10.53.0.4 a a.optout.example > delv.out$n || ret=1
261   grep -Eq "^a\\.optout\\.example\\.""$SP""[0-9]+""$SP""IN""$SP""A""$SP""10.0.0.1" delv.out$n || ret=1
262   grep -Eq "^a\\.optout\\.example\\.""$SP""[0-9]+""$SP""IN""$SP""RRSIG""$SP""A""$SP""$DEFAULT_ALGORITHM_NUMBER""$SP""3""$SP""300" delv.out$n || ret=1
263   n=$((n+1))
264   test "$ret" -eq 0 || echo_i "failed"
265   status=$((status+ret))
266fi
267
268echo_i "checking positive wildcard validation NSEC ($n)"
269ret=0
270dig_with_opts a.wild.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
271dig_with_opts a.wild.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
272stripns dig.out.ns3.test$n > dig.out.ns3.stripped.test$n
273stripns dig.out.ns4.test$n > dig.out.ns4.stripped.test$n
274digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1
275grep "\\*\\.wild\\.example\\..*RRSIG	NSEC" dig.out.ns4.test$n > /dev/null || ret=1
276grep "\\*\\.wild\\.example\\..*NSEC	z\\.example" dig.out.ns4.test$n > /dev/null || ret=1
277grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
278grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
279n=$((n+1))
280test "$ret" -eq 0 || echo_i "failed"
281status=$((status+ret))
282
283if [ -x ${DELV} ] ; then
284   ret=0
285   echo_i "checking positive wildcard validation NSEC using dns_client ($n)"
286   delv_with_opts @10.53.0.4 a a.wild.example > delv.out$n || ret=1
287   grep "a.wild.example..*10.0.0.27" delv.out$n > /dev/null || ret=1
288   grep -E "a.wild.example..*RRSIG.A [0-9]+ 2 300.*" delv.out$n > /dev/null || ret=1
289   n=$((n+1))
290   test "$ret" -eq 0 || echo_i "failed"
291   status=$((status+ret))
292fi
293
294echo_i "checking positive wildcard answer NSEC3 ($n)"
295ret=0
296dig_with_opts a.wild.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
297grep "AUTHORITY: 4," dig.out.ns3.test$n > /dev/null || ret=1
298grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
299n=$((n+1))
300test "$ret" -eq 0 || echo_i "failed"
301status=$((status+ret))
302
303echo_i "checking positive wildcard answer NSEC3 ($n)"
304ret=0
305dig_with_opts a.wild.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
306grep "AUTHORITY: 4," dig.out.ns4.test$n > /dev/null || ret=1
307grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
308n=$((n+1))
309test "$ret" -eq 0 || echo_i "failed"
310status=$((status+ret))
311
312echo_i "checking positive wildcard validation NSEC3 ($n)"
313ret=0
314dig_with_opts a.wild.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
315dig_with_opts a.wild.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
316stripns dig.out.ns3.test$n > dig.out.ns3.stripped.test$n
317stripns dig.out.ns4.test$n > dig.out.ns4.stripped.test$n
318digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1
319grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
320grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
321n=$((n+1))
322test "$ret" -eq 0 || echo_i "failed"
323status=$((status+ret))
324
325if [ -x ${DELV} ] ; then
326   ret=0
327   echo_i "checking positive wildcard validation NSEC3 using dns_client ($n)"
328   delv_with_opts @10.53.0.4 a a.wild.nsec3.example > delv.out$n || ret=1
329   grep -E "a.wild.nsec3.example..*10.0.0.6" delv.out$n > /dev/null || ret=1
330   grep -E "a.wild.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n > /dev/null || ret=1
331   n=$((n+1))
332   test "$ret" -eq 0 || echo_i "failed"
333   status=$((status+ret))
334fi
335
336echo_i "checking positive wildcard validation OPTOUT ($n)"
337ret=0
338dig_with_opts a.wild.optout.example. \
339	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
340dig_with_opts a.wild.optout.example. \
341	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
342stripns dig.out.ns3.test$n > dig.out.ns3.stripped.test$n
343stripns dig.out.ns4.test$n > dig.out.ns4.stripped.test$n
344digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1
345grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
346grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
347n=$((n+1))
348test "$ret" -eq 0 || echo_i "failed"
349status=$((status+ret))
350
351if [ -x ${DELV} ] ; then
352   ret=0
353   echo_i "checking positive wildcard validation OPTOUT using dns_client ($n)"
354   delv_with_opts @10.53.0.4 a a.wild.optout.example > delv.out$n || ret=1
355   grep "a.wild.optout.example..*10.0.0.6" delv.out$n > /dev/null || ret=1
356   grep "a.wild.optout.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n > /dev/null || ret=1
357   n=$((n+1))
358   test "$ret" -eq 0 || echo_i "failed"
359   status=$((status+ret))
360fi
361
362echo_i "checking negative validation NXDOMAIN NSEC ($n)"
363ret=0
364dig_with_opts +noauth q.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
365dig_with_opts +noauth q.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
366digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
367grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
368grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
369n=$((n+1))
370test "$ret" -eq 0 || echo_i "failed"
371status=$((status+ret))
372
373if [ -x ${DELV} ] ; then
374   ret=0
375   echo_i "checking negative validation NXDOMAIN NSEC using dns_client ($n)"
376   delv_with_opts @10.53.0.4 a q.example > delv.out$n 2>&1 || ret=1
377   grep "resolution failed: ncache nxdomain" delv.out$n > /dev/null || ret=1
378   n=$((n+1))
379   test "$ret" -eq 0 || echo_i "failed"
380   status=$((status+ret))
381fi
382
383echo_i "checking negative validation NXDOMAIN NSEC3 ($n)"
384ret=0
385dig_with_opts +noauth q.nsec3.example. \
386	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
387dig_with_opts +noauth q.nsec3.example. \
388	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
389digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
390grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
391grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
392n=$((n+1))
393test "$ret" -eq 0 || echo_i "failed"
394status=$((status+ret))
395
396if [ -x ${DELV} ] ; then
397   ret=0
398   echo_i "checking negative validation NXDOMAIN NSEC3 using dns_client ($n)"
399   delv_with_opts @10.53.0.4 a q.nsec3.example > delv.out$n 2>&1 || ret=1
400   grep "resolution failed: ncache nxdomain" delv.out$n > /dev/null || ret=1
401   n=$((n+1))
402   test "$ret" -eq 0 || echo_i "failed"
403   status=$((status+ret))
404fi
405
406echo_i "checking negative validation NXDOMAIN OPTOUT ($n)"
407ret=0
408dig_with_opts +noauth q.optout.example. \
409	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
410dig_with_opts +noauth q.optout.example. \
411	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
412digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
413grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
414# Note - this is looking for failure, hence the &&
415grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
416n=$((n+1))
417test "$ret" -eq 0 || echo_i "failed"
418status=$((status+ret))
419
420if [ -x ${DELV} ] ; then
421   ret=0
422   echo_i "checking negative validation NXDOMAIN OPTOUT using dns_client ($n)"
423   delv_with_opts @10.53.0.4 a q.optout.example > delv.out$n 2>&1 || ret=1
424   grep "resolution failed: ncache nxdomain" delv.out$n > /dev/null || ret=1
425   n=$((n+1))
426   test "$ret" -eq 0 || echo_i "failed"
427   status=$((status+ret))
428fi
429
430echo_i "checking negative validation NODATA NSEC ($n)"
431ret=0
432dig_with_opts +noauth a.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
433dig_with_opts +noauth a.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
434digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
435grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
436grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
437grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
438n=$((n+1))
439test "$ret" -eq 0 || echo_i "failed"
440status=$((status+ret))
441
442if [ -x ${DELV} ] ; then
443   ret=0
444   echo_i "checking negative validation NODATA OPTOUT using dns_client ($n)"
445   delv_with_opts @10.53.0.4 txt a.example > delv.out$n 2>&1 || ret=1
446   grep "resolution failed: ncache nxrrset" delv.out$n > /dev/null || ret=1
447   n=$((n+1))
448   test "$ret" -eq 0 || echo_i "failed"
449   status=$((status+ret))
450fi
451
452echo_i "checking negative validation NODATA NSEC3 ($n)"
453ret=0
454dig_with_opts +noauth a.nsec3.example. \
455	@10.53.0.3 txt > dig.out.ns3.test$n || ret=1
456dig_with_opts +noauth a.nsec3.example. \
457	@10.53.0.4 txt > dig.out.ns4.test$n || ret=1
458digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
459grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
460grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
461grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
462n=$((n+1))
463test "$ret" -eq 0 || echo_i "failed"
464status=$((status+ret))
465
466if [ -x ${DELV} ] ; then
467   ret=0
468   echo_i "checking negative validation NODATA NSEC3 using dns_client ($n)"
469   delv_with_opts @10.53.0.4 txt a.nsec3.example > delv.out$n 2>&1 || ret=1
470   grep "resolution failed: ncache nxrrset" delv.out$n > /dev/null || ret=1
471   n=$((n+1))
472   test "$ret" -eq 0 || echo_i "failed"
473   status=$((status+ret))
474fi
475
476echo_i "checking negative validation NODATA OPTOUT ($n)"
477ret=0
478dig_with_opts +noauth a.optout.example. \
479	@10.53.0.3 txt > dig.out.ns3.test$n || ret=1
480dig_with_opts +noauth a.optout.example. \
481	@10.53.0.4 txt > dig.out.ns4.test$n || ret=1
482digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
483grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
484grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
485grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
486n=$((n+1))
487test "$ret" -eq 0 || echo_i "failed"
488status=$((status+ret))
489
490if [ -x ${DELV} ] ; then
491   ret=0
492   echo_i "checking negative validation NODATA OPTOUT using dns_client ($n)"
493   delv_with_opts @10.53.0.4 txt a.optout.example > delv.out$n 2>&1 || ret=1
494   grep "resolution failed: ncache nxrrset" delv.out$n > /dev/null || ret=1
495   n=$((n+1))
496   test "$ret" -eq 0 || echo_i "failed"
497   status=$((status+ret))
498fi
499
500echo_i "checking negative wildcard validation NSEC ($n)"
501ret=0
502dig_with_opts b.wild.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
503dig_with_opts b.wild.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
504digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
505grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
506grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
507n=$((n+1))
508test "$ret" -eq 0 || echo_i "failed"
509status=$((status+ret))
510
511if [ -x ${DELV} ] ; then
512   ret=0
513   echo_i "checking negative wildcard validation NSEC using dns_client ($n)"
514   delv_with_opts @10.53.0.4 txt b.wild.example > delv.out$n 2>&1 || ret=1
515   grep "resolution failed: ncache nxrrset" delv.out$n > /dev/null || ret=1
516   n=$((n+1))
517   test "$ret" -eq 0 || echo_i "failed"
518   status=$((status+ret))
519fi
520
521echo_i "checking negative wildcard validation NSEC3 ($n)"
522ret=0
523dig_with_opts b.wild.nsec3.example. @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
524dig_with_opts b.wild.nsec3.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
525digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
526grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
527n=$((n+1))
528test "$ret" -eq 0 || echo_i "failed"
529status=$((status+ret))
530
531if [ -x ${DELV} ] ; then
532   ret=0
533   echo_i "checking negative wildcard validation NSEC3 using dns_client ($n)"
534   delv_with_opts @10.53.0.4 txt b.wild.nsec3.example > delv.out$n 2>&1 || ret=1
535   grep "resolution failed: ncache nxrrset" delv.out$n > /dev/null || ret=1
536   n=$((n+1))
537   test "$ret" -eq 0 || echo_i "failed"
538   status=$((status+ret))
539fi
540
541echo_i "checking negative wildcard validation OPTOUT ($n)"
542ret=0
543dig_with_opts b.wild.optout.example. \
544	@10.53.0.3 txt > dig.out.ns3.test$n || ret=1
545dig_with_opts b.wild.optout.example. \
546	@10.53.0.4 txt > dig.out.ns4.test$n || ret=1
547digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
548grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
549# Note - this is looking for failure, hence the &&
550grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
551n=$((n+1))
552test "$ret" -eq 0 || echo_i "failed"
553status=$((status+ret))
554
555if [ -x ${DELV} ] ; then
556   ret=0
557   echo_i "checking negative wildcard validation OPTOUT using dns_client ($n)"
558   delv_with_opts @10.53.0.4 txt b.optout.nsec3.example > delv.out$n 2>&1 || ret=1
559   grep "resolution failed: ncache nxrrset" delv.out$n > /dev/null || ret=1
560   n=$((n+1))
561   test "$ret" -eq 0 || echo_i "failed"
562   status=$((status+ret))
563fi
564
565# Check the insecure.example domain
566
567echo_i "checking 1-server insecurity proof NSEC ($n)"
568ret=0
569dig_with_opts +noauth a.insecure.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
570dig_with_opts +noauth a.insecure.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
571digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
572grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
573# Note - this is looking for failure, hence the &&
574grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
575n=$((n+1))
576test "$ret" -eq 0 || echo_i "failed"
577status=$((status+ret))
578
579if [ -x ${DELV} ] ; then
580   ret=0
581   echo_i "checking 1-server insecurity proof NSEC using dns_client ($n)"
582   delv_with_opts @10.53.0.4 a a.insecure.example > delv.out$n || ret=1
583   grep "a.insecure.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
584   n=$((n+1))
585   test "$ret" -eq 0 || echo_i "failed"
586   status=$((status+ret))
587fi
588
589echo_i "checking 1-server insecurity proof NSEC3 ($n)"
590ret=0
591dig_with_opts +noauth a.insecure.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
592dig_with_opts +noauth a.insecure.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
593digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
594grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
595# Note - this is looking for failure, hence the &&
596grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
597n=$((n+1))
598test "$ret" -eq 0 || echo_i "failed"
599status=$((status+ret))
600
601if [ -x ${DELV} ] ; then
602   ret=0
603   echo_i "checking 1-server insecurity proof NSEC3 using dns_client ($n)"
604   delv_with_opts @10.53.0.4 a a.insecure.nsec3.example > delv.out$n || ret=1
605   grep "a.insecure.nsec3.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
606   n=$((n+1))
607   test "$ret" -eq 0 || echo_i "failed"
608   status=$((status+ret))
609fi
610
611echo_i "checking 1-server insecurity proof OPTOUT ($n)"
612ret=0
613dig_with_opts +noauth a.insecure.optout.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
614dig_with_opts +noauth a.insecure.optout.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
615digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
616grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
617# Note - this is looking for failure, hence the &&
618grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
619n=$((n+1))
620test "$ret" -eq 0 || echo_i "failed"
621status=$((status+ret))
622
623if [ -x ${DELV} ] ; then
624   ret=0
625   echo_i "checking 1-server insecurity proof OPTOUT using dns_client ($n)"
626   delv_with_opts @10.53.0.4 a a.insecure.optout.example > delv.out$n || ret=1
627   grep "a.insecure.optout.example..*10.0.0.1" delv.out$n > /dev/null || ret=1
628   n=$((n+1))
629   test "$ret" -eq 0 || echo_i "failed"
630   status=$((status+ret))
631fi
632
633echo_i "checking 1-server negative insecurity proof NSEC ($n)"
634ret=0
635dig_with_opts q.insecure.example. a @10.53.0.3 \
636	> dig.out.ns3.test$n || ret=1
637dig_with_opts q.insecure.example. a @10.53.0.4 \
638	> dig.out.ns4.test$n || ret=1
639digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
640grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
641# Note - this is looking for failure, hence the &&
642grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
643n=$((n+1))
644test "$ret" -eq 0 || echo_i "failed"
645status=$((status+ret))
646
647if [ -x ${DELV} ] ; then
648   ret=0
649   echo_i "checking 1-server negative insecurity proof NSEC using dns_client ($n)"
650   delv_with_opts @10.53.0.4 a q.insecure.example > delv.out$n 2>&1 || ret=1
651   grep "resolution failed: ncache nxdomain" delv.out$n > /dev/null || ret=1
652   n=$((n+1))
653   test "$ret" -eq 0 || echo_i "failed"
654   status=$((status+ret))
655fi
656
657echo_i "checking 1-server negative insecurity proof NSEC3 ($n)"
658ret=0
659dig_with_opts q.insecure.nsec3.example. a @10.53.0.3 \
660	> dig.out.ns3.test$n || ret=1
661dig_with_opts q.insecure.nsec3.example. a @10.53.0.4 \
662	> dig.out.ns4.test$n || ret=1
663digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
664grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
665# Note - this is looking for failure, hence the &&
666grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
667n=$((n+1))
668test "$ret" -eq 0 || echo_i "failed"
669status=$((status+ret))
670
671if [ -x ${DELV} ] ; then
672   ret=0
673   echo_i "checking 1-server negative insecurity proof NSEC3 using dns_client ($n)"
674   delv_with_opts @10.53.0.4 a q.insecure.nsec3.example > delv.out$n 2>&1 || ret=1
675   grep "resolution failed: ncache nxdomain" delv.out$n > /dev/null || ret=1
676   n=$((n+1))
677   test "$ret" -eq 0 || echo_i "failed"
678   status=$((status+ret))
679fi
680
681echo_i "checking 1-server negative insecurity proof OPTOUT ($n)"
682ret=0
683dig_with_opts q.insecure.optout.example. a @10.53.0.3 \
684	> dig.out.ns3.test$n || ret=1
685dig_with_opts q.insecure.optout.example. a @10.53.0.4 \
686	> dig.out.ns4.test$n || ret=1
687digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
688grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
689# Note - this is looking for failure, hence the &&
690grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
691n=$((n+1))
692test "$ret" -eq 0 || echo_i "failed"
693status=$((status+ret))
694
695if [ -x ${DELV} ] ; then
696   ret=0
697   echo_i "checking 1-server negative insecurity proof OPTOUT using dns_client ($n)"
698   delv_with_opts @10.53.0.4 a q.insecure.optout.example > delv.out$n 2>&1 || ret=1
699   grep "resolution failed: ncache nxdomain" delv.out$n > /dev/null || ret=1
700   n=$((n+1))
701   test "$ret" -eq 0 || echo_i "failed"
702   status=$((status+ret))
703fi
704
705echo_i "checking 1-server negative insecurity proof with SOA hack NSEC ($n)"
706ret=0
707dig_with_opts r.insecure.example. soa @10.53.0.3 \
708	> dig.out.ns3.test$n || ret=1
709dig_with_opts r.insecure.example. soa @10.53.0.4 \
710	> dig.out.ns4.test$n || ret=1
711digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
712grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
713grep "0	IN	SOA" dig.out.ns4.test$n > /dev/null || ret=1
714# Note - this is looking for failure, hence the &&
715grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
716n=$((n+1))
717test "$ret" -eq 0 || echo_i "failed"
718status=$((status+ret))
719
720echo_i "checking 1-server negative insecurity proof with SOA hack NSEC3 ($n)"
721ret=0
722dig_with_opts r.insecure.nsec3.example. soa @10.53.0.3 \
723	> dig.out.ns3.test$n || ret=1
724dig_with_opts r.insecure.nsec3.example. soa @10.53.0.4 \
725	> dig.out.ns4.test$n || ret=1
726digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
727grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
728grep "0	IN	SOA" dig.out.ns4.test$n > /dev/null || ret=1
729# Note - this is looking for failure, hence the &&
730grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
731n=$((n+1))
732test "$ret" -eq 0 || echo_i "failed"
733status=$((status+ret))
734
735echo_i "checking 1-server negative insecurity proof with SOA hack OPTOUT ($n)"
736ret=0
737dig_with_opts r.insecure.optout.example. soa @10.53.0.3 \
738	> dig.out.ns3.test$n || ret=1
739dig_with_opts r.insecure.optout.example. soa @10.53.0.4 \
740	> dig.out.ns4.test$n || ret=1
741digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
742grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
743grep "0	IN	SOA" dig.out.ns4.test$n > /dev/null || ret=1
744# Note - this is looking for failure, hence the &&
745grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
746n=$((n+1))
747test "$ret" -eq 0 || echo_i "failed"
748status=$((status+ret))
749
750# Check the secure.example domain
751
752echo_i "checking multi-stage positive validation NSEC/NSEC ($n)"
753ret=0
754dig_with_opts +noauth a.secure.example. \
755	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
756dig_with_opts +noauth a.secure.example. \
757	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
758digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
759grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
760grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
761n=$((n+1))
762test "$ret" -eq 0 || echo_i "failed"
763status=$((status+ret))
764
765echo_i "checking multi-stage positive validation NSEC/NSEC3 ($n)"
766ret=0
767dig_with_opts +noauth a.nsec3.example. \
768	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
769dig_with_opts +noauth a.nsec3.example. \
770	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
771digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
772grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
773grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
774n=$((n+1))
775test "$ret" -eq 0 || echo_i "failed"
776status=$((status+ret))
777
778echo_i "checking multi-stage positive validation NSEC/OPTOUT ($n)"
779ret=0
780dig_with_opts +noauth a.optout.example. \
781	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
782dig_with_opts +noauth a.optout.example. \
783	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
784digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
785grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
786grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
787n=$((n+1))
788test "$ret" -eq 0 || echo_i "failed"
789status=$((status+ret))
790
791echo_i "checking multi-stage positive validation NSEC3/NSEC ($n)"
792ret=0
793dig_with_opts +noauth a.secure.nsec3.example. \
794	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
795dig_with_opts +noauth a.secure.nsec3.example. \
796	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
797digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
798grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
799grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
800n=$((n+1))
801test "$ret" -eq 0 || echo_i "failed"
802status=$((status+ret))
803
804echo_i "checking multi-stage positive validation NSEC3/NSEC3 ($n)"
805ret=0
806dig_with_opts +noauth a.nsec3.nsec3.example. \
807	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
808dig_with_opts +noauth a.nsec3.nsec3.example. \
809	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
810digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
811grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
812grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
813n=$((n+1))
814test "$ret" -eq 0 || echo_i "failed"
815status=$((status+ret))
816
817echo_i "checking multi-stage positive validation NSEC3/OPTOUT ($n)"
818ret=0
819dig_with_opts +noauth a.optout.nsec3.example. \
820	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
821dig_with_opts +noauth a.optout.nsec3.example. \
822	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
823digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
824grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
825grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
826n=$((n+1))
827test "$ret" -eq 0 || echo_i "failed"
828status=$((status+ret))
829
830echo_i "checking multi-stage positive validation OPTOUT/NSEC ($n)"
831ret=0
832dig_with_opts +noauth a.secure.optout.example. \
833	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
834dig_with_opts +noauth a.secure.optout.example. \
835	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
836digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
837grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
838grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
839n=$((n+1))
840test "$ret" -eq 0 || echo_i "failed"
841status=$((status+ret))
842
843echo_i "checking multi-stage positive validation OPTOUT/NSEC3 ($n)"
844ret=0
845dig_with_opts +noauth a.nsec3.optout.example. \
846	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
847dig_with_opts +noauth a.nsec3.optout.example. \
848	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
849digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
850grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
851grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
852n=$((n+1))
853test "$ret" -eq 0 || echo_i "failed"
854status=$((status+ret))
855
856echo_i "checking multi-stage positive validation OPTOUT/OPTOUT ($n)"
857ret=0
858dig_with_opts +noauth a.optout.optout.example. \
859	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
860dig_with_opts +noauth a.optout.optout.example. \
861	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
862digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
863grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
864grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
865n=$((n+1))
866test "$ret" -eq 0 || echo_i "failed"
867status=$((status+ret))
868
869echo_i "checking empty NODATA OPTOUT ($n)"
870ret=0
871dig_with_opts +noauth empty.optout.example. \
872	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
873dig_with_opts +noauth empty.optout.example. \
874	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
875digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
876grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
877#grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
878n=$((n+1))
879test "$ret" -eq 0 || echo_i "failed"
880status=$((status+ret))
881
882# Check the bogus domain
883
884echo_i "checking failed validation ($n)"
885ret=0
886dig_with_opts a.bogus.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
887grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
888n=$((n+1))
889test "$ret" -eq 0 || echo_i "failed"
890status=$((status+ret))
891
892if [ -x ${DELV} ] ; then
893   ret=0
894   echo_i "checking failed validation using dns_client ($n)"
895   delv_with_opts +cd @10.53.0.4 a a.bogus.example > delv.out$n 2>&1 || ret=1
896   grep "resolution failed: RRSIG failed to verify" delv.out$n > /dev/null || ret=1
897   n=$((n+1))
898   test "$ret" -eq 0 || echo_i "failed"
899   status=$((status+ret))
900fi
901
902# Try validating with a bad trusted key.
903# This should fail.
904
905echo_i "checking that validation fails with a misconfigured trusted key ($n)"
906ret=0
907dig_with_opts example. soa @10.53.0.5 > dig.out.ns5.test$n || ret=1
908grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
909n=$((n+1))
910test "$ret" -eq 0 || echo_i "failed"
911status=$((status+ret))
912
913echo_i "checking that negative validation fails with a misconfigured trusted key ($n)"
914ret=0
915dig_with_opts example. ptr @10.53.0.5 > dig.out.ns5.test$n || ret=1
916grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
917n=$((n+1))
918test "$ret" -eq 0 || echo_i "failed"
919status=$((status+ret))
920
921echo_i "checking that insecurity proofs fail with a misconfigured trusted key ($n)"
922ret=0
923dig_with_opts a.insecure.example. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
924grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
925n=$((n+1))
926test "$ret" -eq 0 || echo_i "failed"
927status=$((status+ret))
928
929echo_i "checking that validation fails when key record is missing ($n)"
930ret=0
931dig_with_opts a.b.keyless.example. a @10.53.0.4 > dig.out.ns4.test$n || ret=1
932grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
933n=$((n+1))
934test "$ret" -eq 0 || echo_i "failed"
935status=$((status+ret))
936
937if [ -x ${DELV} ] ; then
938   ret=0
939   echo_i "checking that validation fails when key record is missing using dns_client ($n)"
940   delv_with_opts +cd @10.53.0.4 a a.b.keyless.example > delv.out$n 2>&1 || ret=1
941   grep "resolution failed: broken trust chain" delv.out$n > /dev/null || ret=1
942   n=$((n+1))
943   test "$ret" -eq 0 || echo_i "failed"
944   status=$((status+ret))
945fi
946
947echo_i "checking that validation succeeds when a revoked key is encountered ($n)"
948ret=0
949dig_with_opts revkey.example soa @10.53.0.4 > dig.out.ns4.test$n || ret=1
950grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
951grep "flags: .* ad" dig.out.ns4.test$n > /dev/null || ret=1
952n=$((n+1))
953test "$ret" -eq 0 || echo_i "failed"
954status=$((status+ret))
955
956if [ -x ${DELV} ] ; then
957   ret=0
958   echo_i "checking that validation succeeds when a revoked key is encountered using dns_client ($n)"
959   delv_with_opts +cd @10.53.0.4 soa revkey.example > delv.out$n 2>&1 || ret=1
960   grep "fully validated" delv.out$n > /dev/null || ret=1
961   n=$((n+1))
962   test "$ret" -eq 0 || echo_i "failed"
963   status=$((status+ret))
964fi
965
966echo_i "Checking that a bad CNAME signature is caught after a +CD query ($n)"
967ret=0
968#prime
969dig_with_opts +cd bad-cname.example. @10.53.0.4 > dig.out.ns4.prime$n || ret=1
970#check: requery with +CD.  pending data should be returned even if it's bogus
971expect="a.example.
97210.0.0.1"
973ans=$(dig_with_opts +cd +nodnssec +short bad-cname.example. @10.53.0.4) || ret=1
974test "$ans" = "$expect" || ret=1
975test "$ret" -eq 0 || echo_i "failed, got '$ans', expected '$expect'"
976#check: requery without +CD.  bogus cached data should be rejected.
977dig_with_opts +nodnssec bad-cname.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
978grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
979n=$((n+1))
980test "$ret" -eq 0 || echo_i "failed"
981status=$((status+ret))
982
983echo_i "Checking that a bad DNAME signature is caught after a +CD query ($n)"
984ret=0
985#prime
986dig_with_opts +cd a.bad-dname.example. @10.53.0.4 > dig.out.ns4.prime$n || ret=1
987#check: requery with +CD.  pending data should be returned even if it's bogus
988expect="example.
989a.example.
99010.0.0.1"
991ans=$(dig_with_opts +cd +nodnssec +short a.bad-dname.example. @10.53.0.4) || ret=1
992test "$ans" = "$expect" || ret=1
993test "$ret" -eq 0 || echo_i "failed, got '$ans', expected '$expect'"
994#check: requery without +CD.  bogus cached data should be rejected.
995dig_with_opts +nodnssec a.bad-dname.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
996grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
997n=$((n+1))
998test "$ret" -eq 0 || echo_i "failed"
999status=$((status+ret))
1000
1001# Check the insecure.secure.example domain (insecurity proof)
1002
1003echo_i "checking 2-server insecurity proof ($n)"
1004ret=0
1005dig_with_opts +noauth a.insecure.secure.example. @10.53.0.2 a \
1006	> dig.out.ns2.test$n || ret=1
1007dig_with_opts +noauth a.insecure.secure.example. @10.53.0.4 a \
1008	> dig.out.ns4.test$n || ret=1
1009digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
1010grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1011# Note - this is looking for failure, hence the &&
1012grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
1013n=$((n+1))
1014test "$ret" -eq 0 || echo_i "failed"
1015status=$((status+ret))
1016
1017# Check a negative response in insecure.secure.example
1018
1019echo_i "checking 2-server insecurity proof with a negative answer ($n)"
1020ret=0
1021dig_with_opts q.insecure.secure.example. @10.53.0.2 a > dig.out.ns2.test$n \
1022	|| ret=1
1023dig_with_opts q.insecure.secure.example. @10.53.0.4 a > dig.out.ns4.test$n \
1024	|| ret=1
1025digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
1026grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
1027# Note - this is looking for failure, hence the &&
1028grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
1029n=$((n+1))
1030test "$ret" -eq 0 || echo_i "failed"
1031status=$((status+ret))
1032
1033echo_i "checking 2-server insecurity proof with a negative answer and SOA hack ($n)"
1034ret=0
1035dig_with_opts r.insecure.secure.example. @10.53.0.2 soa > dig.out.ns2.test$n \
1036	|| ret=1
1037dig_with_opts r.insecure.secure.example. @10.53.0.4 soa > dig.out.ns4.test$n \
1038	|| ret=1
1039digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
1040grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
1041# Note - this is looking for failure, hence the &&
1042grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
1043n=$((n+1))
1044test "$ret" -eq 0 || echo_i "failed"
1045status=$((status+ret))
1046
1047# Check that the query for a security root is successful and has ad set
1048
1049echo_i "checking security root query ($n)"
1050ret=0
1051dig_with_opts . @10.53.0.4 key > dig.out.ns4.test$n || ret=1
1052grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1053grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
1054n=$((n+1))
1055test "$ret" -eq 0 || echo_i "failed"
1056status=$((status+ret))
1057
1058# Check that the setting the cd bit works
1059
1060echo_i "checking cd bit on a positive answer ($n)"
1061ret=0
1062dig_with_opts +noauth example. soa @10.53.0.4 \
1063	> dig.out.ns4.test$n || ret=1
1064dig_with_opts +noauth +cdflag example. soa @10.53.0.5 \
1065	> dig.out.ns5.test$n || ret=1
1066digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
1067grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
1068# Note - this is looking for failure, hence the &&
1069grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
1070n=$((n+1))
1071test "$ret" -eq 0 || echo_i "failed"
1072status=$((status+ret))
1073
1074echo_i "checking cd bit on a negative answer ($n)"
1075ret=0
1076dig_with_opts q.example. soa @10.53.0.4 > dig.out.ns4.test$n || ret=1
1077dig_with_opts +cdflag q.example. soa @10.53.0.5 > dig.out.ns5.test$n || ret=1
1078digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
1079grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
1080# Note - this is looking for failure, hence the &&
1081grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
1082n=$((n+1))
1083test "$ret" -eq 0 || echo_i "failed"
1084status=$((status+ret))
1085
1086echo_i "checking insecurity proof works using negative cache ($n)"
1087ret=0
1088rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
1089dig_with_opts +cd @10.53.0.4 insecure.example. ds > dig.out.ns4.test$n.1 || ret=1
1090for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
1091do
1092        dig_with_opts @10.53.0.4 nonexistent.insecure.example. > dig.out.ns4.test$n.2 || ret=1
1093	if grep "status: NXDOMAIN" dig.out.ns4.test$n.2 >/dev/null; then
1094		break
1095	fi
1096	sleep 1
1097done
1098grep "status: NXDOMAIN" dig.out.ns4.test$n.2 >/dev/null || ret=1
1099n=$((n+1))
1100test "$ret" -eq 0 || echo_i "failed"
1101status=$((status+ret))
1102
1103echo_i "checking positive validation RSASHA256 NSEC ($n)"
1104ret=0
1105dig_with_opts +noauth a.rsasha256.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
1106dig_with_opts +noauth a.rsasha256.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
1107digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
1108grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
1109n=$((n+1))
1110test "$ret" -eq 0 || echo_i "failed"
1111status=$((status+ret))
1112
1113echo_i "checking positive validation RSASHA512 NSEC ($n)"
1114ret=0
1115dig_with_opts +noauth a.rsasha512.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
1116dig_with_opts +noauth a.rsasha512.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
1117digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
1118grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
1119n=$((n+1))
1120test "$ret" -eq 0 || echo_i "failed"
1121status=$((status+ret))
1122
1123echo_i "checking positive validation with KSK-only DNSKEY signature ($n)"
1124ret=0
1125dig_with_opts +noauth a.kskonly.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
1126dig_with_opts +noauth a.kskonly.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
1127digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
1128grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
1129n=$((n+1))
1130test "$ret" -eq 0 || echo_i "failed"
1131status=$((status+ret))
1132
1133echo_i "checking cd bit on a query that should fail ($n)"
1134ret=0
1135dig_with_opts a.bogus.example. soa @10.53.0.4 \
1136	> dig.out.ns4.test$n || ret=1
1137dig_with_opts +cdflag a.bogus.example. soa @10.53.0.5 \
1138	> dig.out.ns5.test$n || ret=1
1139digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
1140grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
1141# Note - this is looking for failure, hence the &&
1142grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
1143n=$((n+1))
1144test "$ret" -eq 0 || echo_i "failed"
1145status=$((status+ret))
1146
1147echo_i "checking cd bit on an insecurity proof ($n)"
1148ret=0
1149dig_with_opts +noauth a.insecure.example. soa @10.53.0.4 \
1150	> dig.out.ns4.test$n || ret=1
1151dig_with_opts +noauth +cdflag a.insecure.example. soa @10.53.0.5 \
1152	> dig.out.ns5.test$n || ret=1
1153digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
1154grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1155# Note - these are looking for failure, hence the &&
1156grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
1157grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
1158n=$((n+1))
1159test "$ret" -eq 0 || echo_i "failed"
1160status=$((status+ret))
1161
1162echo_i "checking cd bit on a negative insecurity proof ($n)"
1163ret=0
1164dig_with_opts q.insecure.example. a @10.53.0.4 \
1165	> dig.out.ns4.test$n || ret=1
1166dig_with_opts +cdflag q.insecure.example. a @10.53.0.5 \
1167	> dig.out.ns5.test$n || ret=1
1168digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
1169grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
1170# Note - these are looking for failure, hence the &&
1171grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
1172grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
1173n=$((n+1))
1174test "$ret" -eq 0 || echo_i "failed"
1175status=$((status+ret))
1176
1177echo_i "checking that validation of an ANY query works ($n)"
1178ret=0
1179dig_with_opts +noauth foo.example. any @10.53.0.2 > dig.out.ns2.test$n || ret=1
1180dig_with_opts +noauth foo.example. any @10.53.0.4 > dig.out.ns4.test$n || ret=1
1181digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
1182grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1183# 2 records in the zone, 1 NXT, 3 SIGs
1184grep "ANSWER: 6" dig.out.ns4.test$n > /dev/null || ret=1
1185n=$((n+1))
1186test "$ret" -eq 0 || echo_i "failed"
1187status=$((status+ret))
1188
1189echo_i "checking that validation of a query returning a CNAME works ($n)"
1190ret=0
1191dig_with_opts +noauth cname1.example. txt @10.53.0.2 \
1192	> dig.out.ns2.test$n || ret=1
1193dig_with_opts +noauth cname1.example. txt @10.53.0.4 \
1194	> dig.out.ns4.test$n || ret=1
1195digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
1196grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1197# the CNAME & its sig, the TXT and its SIG
1198grep "ANSWER: 4" dig.out.ns4.test$n > /dev/null || ret=1
1199n=$((n+1))
1200test "$ret" -eq 0 || echo_i "failed"
1201status=$((status+ret))
1202
1203echo_i "checking that validation of a query returning a DNAME works ($n)"
1204ret=0
1205dig_with_opts +noauth foo.dname1.example. txt @10.53.0.2 \
1206	> dig.out.ns2.test$n || ret=1
1207dig_with_opts +noauth foo.dname1.example. txt @10.53.0.4 \
1208	> dig.out.ns4.test$n || ret=1
1209digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
1210grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1211# The DNAME & its sig, the TXT and its SIG, and the synthesized CNAME.
1212# It would be nice to test that the CNAME is being synthesized by the
1213# recursive server and not cached, but I don't know how.
1214grep "ANSWER: 5" dig.out.ns4.test$n > /dev/null || ret=1
1215n=$((n+1))
1216test "$ret" -eq 0 || echo_i "failed"
1217status=$((status+ret))
1218
1219echo_i "checking that validation of an ANY query returning a CNAME works ($n)"
1220ret=0
1221dig_with_opts +noauth cname2.example. any @10.53.0.2 \
1222	> dig.out.ns2.test$n || ret=1
1223dig_with_opts +noauth cname2.example. any @10.53.0.4 \
1224	> dig.out.ns4.test$n || ret=1
1225digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
1226grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1227# The CNAME, NXT, and their SIGs
1228grep "ANSWER: 4" dig.out.ns4.test$n > /dev/null || ret=1
1229n=$((n+1))
1230test "$ret" -eq 0 || echo_i "failed"
1231status=$((status+ret))
1232
1233echo_i "checking that validation of an ANY query returning a DNAME works ($n)"
1234ret=0
1235dig_with_opts +noauth foo.dname2.example. any @10.53.0.2 \
1236	> dig.out.ns2.test$n || ret=1
1237dig_with_opts +noauth foo.dname2.example. any @10.53.0.4 \
1238	> dig.out.ns4.test$n || ret=1
1239digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
1240grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1241n=$((n+1))
1242test "$ret" -eq 0 || echo_i "failed"
1243status=$((status+ret))
1244
1245echo_i "checking that lookups succeed after disabling an algorithm ($n)"
1246ret=0
1247dig_with_opts +noauth example. SOA @10.53.0.2 \
1248	> dig.out.ns2.test$n || ret=1
1249dig_with_opts +noauth example. SOA @10.53.0.6 \
1250	> dig.out.ns6.test$n || ret=1
1251digcomp dig.out.ns2.test$n dig.out.ns6.test$n || ret=1
1252# Note - this is looking for failure, hence the &&
1253grep "flags:.*ad.*QUERY" dig.out.ns6.test$n > /dev/null && ret=1
1254n=$((n+1))
1255test "$ret" -eq 0 || echo_i "failed"
1256status=$((status+ret))
1257
1258echo_i "checking a non-cachable NODATA works ($n)"
1259ret=0
1260dig_with_opts +noauth a.nosoa.secure.example. txt @10.53.0.7 \
1261	> dig.out.ns7.test$n || ret=1
1262grep "AUTHORITY: 0" dig.out.ns7.test$n > /dev/null || ret=1
1263dig_with_opts +noauth a.nosoa.secure.example. txt @10.53.0.4 \
1264	> dig.out.ns4.test$n || ret=1
1265grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1266n=$((n+1))
1267test "$ret" -eq 0 || echo_i "failed"
1268status=$((status+ret))
1269
1270echo_i "checking a non-cachable NXDOMAIN works ($n)"
1271ret=0
1272dig_with_opts +noauth b.nosoa.secure.example. txt @10.53.0.7 \
1273	> dig.out.ns7.test$n || ret=1
1274grep "AUTHORITY: 0" dig.out.ns7.test$n > /dev/null || ret=1
1275dig_with_opts +noauth b.nosoa.secure.example. txt @10.53.0.4 \
1276	> dig.out.ns4.test$n || ret=1
1277grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
1278n=$((n+1))
1279test "$ret" -eq 0 || echo_i "failed"
1280status=$((status+ret))
1281
1282echo_i "checking that we can load a rfc2535 signed zone ($n)"
1283ret=0
1284dig_with_opts rfc2535.example. SOA @10.53.0.2 \
1285	> dig.out.ns2.test$n || ret=1
1286grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
1287n=$((n+1))
1288test "$ret" -eq 0 || echo_i "failed"
1289status=$((status+ret))
1290
1291echo_i "checking that we can transfer a rfc2535 signed zone ($n)"
1292ret=0
1293dig_with_opts rfc2535.example. SOA @10.53.0.3 \
1294	> dig.out.ns3.test$n || ret=1
1295grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
1296n=$((n+1))
1297test "$ret" -eq 0 || echo_i "failed"
1298status=$((status+ret))
1299
1300echo_i "basic dnssec-signzone checks:"
1301echo_ic "two DNSKEYs ($n)"
1302ret=0
1303(
1304cd signer/general || exit 1
1305rm -f signed.zone
1306$SIGNER -f signed.zone -o example.com. test1.zone > signer.out.$n
1307test -f signed.zone
1308) || ret=1
1309n=$((n+1))
1310test "$ret" -eq 0 || echo_i "failed"
1311status=$((status+ret))
1312
1313echo_ic "one non-KSK DNSKEY ($n)"
1314ret=0
1315(
1316cd signer/general || exit 0
1317rm -f signed.zone
1318$SIGNER -f signed.zone -o example.com. test2.zone > signer.out.$n
1319test -f signed.zone
1320) && ret=1
1321n=$((n+1))
1322test "$ret" -eq 0 || echo_i "failed"
1323status=$((status+ret))
1324
1325echo_ic "one KSK DNSKEY ($n)"
1326ret=0
1327(
1328cd signer/general || exit 0
1329rm -f signed.zone
1330$SIGNER -f signed.zone -o example.com. test3.zone > signer.out.$n
1331test -f signed.zone
1332) && ret=1
1333n=$((n+1))
1334test "$ret" -eq 0 || echo_i "failed"
1335status=$((status+ret))
1336
1337echo_ic "three DNSKEY ($n)"
1338ret=0
1339(
1340cd signer/general || exit 1
1341rm -f signed.zone
1342$SIGNER -f signed.zone -o example.com. test4.zone > signer.out.$n
1343test -f signed.zone
1344) || ret=1
1345n=$((n+1))
1346test "$ret" -eq 0 || echo_i "failed"
1347status=$((status+ret))
1348
1349echo_ic "three DNSKEY, one private key missing ($n)"
1350ret=0
1351(
1352cd signer/general || exit 1
1353rm -f signed.zone
1354$SIGNER -f signed.zone -o example.com. test5.zone > signer.out.$n
1355test -f signed.zone
1356) || ret=1
1357n=$((n+1))
1358test "$ret" -eq 0 || echo_i "failed"
1359status=$((status+ret))
1360
1361echo_ic "four DNSKEY ($n)"
1362ret=0
1363(
1364cd signer/general || exit 1
1365rm -f signed.zone
1366$SIGNER -f signed.zone -o example.com. test6.zone > signer.out.$n
1367test -f signed.zone
1368) || ret=1
1369n=$((n+1))
1370test "$ret" -eq 0 || echo_i "failed"
1371status=$((status+ret))
1372
1373echo_ic "two DNSKEY, both private keys missing ($n)"
1374ret=0
1375(
1376cd signer/general || exit 0
1377rm -f signed.zone
1378$SIGNER -f signed.zone -o example.com. test7.zone > signer.out.$n
1379test -f signed.zone
1380) && ret=1
1381n=$((n+1))
1382test "$ret" -eq 0 || echo_i "failed"
1383status=$((status+ret))
1384
1385echo_ic "two DNSKEY, one private key missing ($n)"
1386ret=0
1387(
1388cd signer/general || exit 0
1389rm -f signed.zone
1390$SIGNER -f signed.zone -o example.com. test8.zone > signer.out.$n
1391test -f signed.zone
1392) && ret=1
1393n=$((n+1))
1394test "$ret" -eq 0 || echo_i "failed"
1395status=$((status+ret))
1396
1397echo_ic "check that dnssec-signzone rejects excessive NSEC3 iterations ($n)"
1398ret=0
1399(
1400cd signer/general || exit 0
1401rm -f signed.zone
1402$SIGNER -f signed.zone -3 - -H 151 -o example.com. test9.zone > signer.out.$n
1403test -f signed.zone
1404) && ret=1
1405n=$((n+1))
1406test "$ret" -eq 0 || echo_i "failed"
1407status=$((status+ret))
1408
1409echo_ic "check that dnssec-signzone accepts maximum NSEC3 iterations ($n)"
1410ret=0
1411(
1412cd signer/general || exit 1
1413rm -f signed.zone
1414$SIGNER -f signed.zone -3 - -H 150 -o example.com. test9.zone > signer.out.$n
1415test -f signed.zone
1416) || ret=1
1417n=$((n+1))
1418test "$ret" -eq 0 || echo_i "failed"
1419status=$((status+ret))
1420
1421echo_i "checking that a key using an unsupported algorithm cannot be generated ($n)"
1422ret=0
1423zone=example
1424# If dnssec-keygen fails, the test script will exit immediately.  Prevent that
1425# from happening, and also trigger a test failure if dnssec-keygen unexpectedly
1426# succeeds, by using "&& ret=1".
1427$KEYGEN -a 255 $zone > dnssectools.out.test$n 2>&1 && ret=1
1428grep -q "unsupported algorithm: 255" dnssectools.out.test$n || ret=1
1429n=$((n+1))
1430test "$ret" -eq 0 || echo_i "failed"
1431status=$((status+ret))
1432
1433echo_i "checking that a DS record cannot be generated for a key using an unsupported algorithm ($n)"
1434ret=0
1435zone=example
1436# Fake an unsupported algorithm key
1437unsupportedkey=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
1438awk '$3 == "DNSKEY" { $6 = 255 } { print }' ${unsupportedkey}.key > ${unsupportedkey}.tmp
1439mv ${unsupportedkey}.tmp ${unsupportedkey}.key
1440# If dnssec-dsfromkey fails, the test script will exit immediately.  Prevent
1441# that from happening, and also trigger a test failure if dnssec-dsfromkey
1442# unexpectedly succeeds, by using "&& ret=1".
1443$DSFROMKEY ${unsupportedkey} > dnssectools.out.test$n 2>&1 && ret=1
1444grep -q "algorithm is unsupported" dnssectools.out.test$n || ret=1
1445n=$((n+1))
1446test "$ret" -eq 0 || echo_i "failed"
1447status=$((status+ret))
1448
1449echo_i "checking that a zone cannot be signed with a key using an unsupported algorithm ($n)"
1450ret=0
1451ret=0
1452cat signer/example.db.in "${unsupportedkey}.key" > signer/example.db
1453# If dnssec-signzone fails, the test script will exit immediately.  Prevent that
1454# from happening, and also trigger a test failure if dnssec-signzone
1455# unexpectedly succeeds, by using "&& ret=1".
1456$SIGNER -o example signer/example.db ${unsupportedkey} > dnssectools.out.test$n 2>&1 && ret=1
1457grep -q "algorithm is unsupported" dnssectools.out.test$n || ret=1
1458n=$((n+1))
1459test "$ret" -eq 0 || echo_i "failed"
1460status=$((status+ret))
1461
1462get_rsasha1_key_ids_from_sigs() {
1463	tr -d '\r' < signer/example.db.signed | \
1464	awk '
1465		NF < 8 { next }
1466		$(NF-5) != "RRSIG" { next }
1467		$(NF-3) != "5" { next }
1468		$NF != "(" { next }
1469		{
1470			getline;
1471			print $3;
1472		}
1473	' | \
1474	sort -u
1475}
1476
1477echo_i "checking that we can sign a zone with out-of-zone records ($n)"
1478ret=0
1479zone=example
1480key1=$($KEYGEN -K signer -q -a NSEC3RSASHA1 -b 1024 -n zone $zone)
1481key2=$($KEYGEN -K signer -q -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone)
1482(
1483cd signer || exit 1
1484cat example.db.in "$key1.key" "$key2.key" > example.db
1485$SIGNER -o example -f example.db example.db > /dev/null
1486) || ret=1
1487n=$((n+1))
1488test "$ret" -eq 0 || echo_i "failed"
1489status=$((status+ret))
1490
1491echo_i "checking that we can sign a zone (NSEC3) with out-of-zone records ($n)"
1492ret=0
1493zone=example
1494key1=$($KEYGEN -K signer -q -a NSEC3RSASHA1 -b 1024 -n zone $zone)
1495key2=$($KEYGEN -K signer -q -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone)
1496(
1497cd signer || exit 1
1498cat example.db.in "$key1.key" "$key2.key" > example.db
1499$SIGNER -3 - -H 10 -o example -f example.db example.db > /dev/null
1500awk '/^IQF9LQTLK/ {
1501		printf("%s", $0);
1502		while (!index($0, ")")) {
1503			if (getline <= 0)
1504				break;
1505			printf (" %s", $0);
1506		}
1507		printf("\n");
1508	}' example.db | sed 's/[ 	][ 	]*/ /g' > nsec3param.out
1509
1510grep "IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG.example. 0 IN NSEC3 1 0 10 - ( IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG A NS SOA RRSIG DNSKEY NSEC3PARAM )" nsec3param.out > /dev/null
1511) || ret=1
1512n=$((n+1))
1513test "$ret" -eq 0 || echo_i "failed"
1514status=$((status+ret))
1515
1516echo_i "checking NSEC3 signing with empty nonterminals above a delegation ($n)"
1517ret=0
1518zone=example
1519key1=$($KEYGEN -K signer -q -a NSEC3RSASHA1 -b 1024 -n zone $zone)
1520key2=$($KEYGEN -K signer -q -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone)
1521(
1522cd signer || exit 1
1523cat example.db.in "$key1.key" "$key2.key" > example3.db
1524echo "some.empty.nonterminal.nodes.example 60 IN NS ns.example.tld" >> example3.db
1525$SIGNER -3 - -A -H 10 -o example -f example3.db example3.db > /dev/null
1526awk '/^IQF9LQTLK/ {
1527		printf("%s", $0);
1528		while (!index($0, ")")) {
1529			if (getline <= 0)
1530				break;
1531			printf (" %s", $0);
1532		}
1533		printf("\n");
1534	}' example.db | sed 's/[ 	][ 	]*/ /g' > nsec3param.out
1535
1536grep "IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG.example. 0 IN NSEC3 1 0 10 - ( IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG A NS SOA RRSIG DNSKEY NSEC3PARAM )" nsec3param.out > /dev/null
1537) || ret=1
1538n=$((n+1))
1539test "$ret" -eq 0 || echo_i "failed"
1540status=$((status+ret))
1541
1542echo_i "checking that dnssec-signzone updates originalttl on ttl changes ($n)"
1543ret=0
1544zone=example
1545key1=$($KEYGEN -K signer -q -a RSASHA1 -b 1024 -n zone $zone)
1546key2=$($KEYGEN -K signer -q -f KSK -a RSASHA1 -b 1024 -n zone $zone)
1547(
1548cd signer || exit 1
1549cat example.db.in "$key1.key" "$key2.key" > example.db
1550$SIGNER -o example -f example.db.before example.db > /dev/null
1551sed 's/60.IN.SOA./50 IN SOA /' example.db.before > example.db.changed
1552$SIGNER -o example -f example.db.after example.db.changed > /dev/null
1553)
1554grep "SOA 5 1 50" signer/example.db.after > /dev/null || ret=1
1555n=$((n+1))
1556test "$ret" -eq 0 || echo_i "failed"
1557status=$((status+ret))
1558
1559echo_i "checking dnssec-signzone keeps valid signatures from removed keys ($n)"
1560ret=0
1561zone=example
1562key1=$($KEYGEN -K signer -q -f KSK -a RSASHA1 -b 1024 -n zone $zone)
1563key2=$($KEYGEN -K signer -q -a RSASHA1 -b 1024 -n zone $zone)
1564keyid2=$(keyfile_to_key_id "$key2")
1565key3=$($KEYGEN -K signer -q -a RSASHA1 -b 1024 -n zone $zone)
1566keyid3=$(keyfile_to_key_id "$key3")
1567(
1568cd signer || exit 1
1569cat example.db.in "$key1.key" "$key2.key" > example.db
1570$SIGNER -D -o example example.db > /dev/null
1571
1572# now switch out key2 for key3 and resign the zone
1573cat example.db.in "$key1.key" "$key3.key" > example.db
1574echo "\$INCLUDE \"example.db.signed\"" >> example.db
1575$SIGNER -D -o example example.db > /dev/null
1576) || ret=1
1577get_rsasha1_key_ids_from_sigs | grep "^$keyid2$" > /dev/null || ret=1
1578get_rsasha1_key_ids_from_sigs | grep "^$keyid3$" > /dev/null || ret=1
1579n=$((n+1))
1580test "$ret" -eq 0 || echo_i "failed"
1581status=$((status+ret))
1582
1583echo_i "checking dnssec-signzone -R purges signatures from removed keys ($n)"
1584ret=0
1585(
1586cd signer || exit 1
1587$SIGNER -RD -o example example.db > /dev/null
1588) || ret=1
1589get_rsasha1_key_ids_from_sigs | grep "^$keyid2$" > /dev/null && ret=1
1590get_rsasha1_key_ids_from_sigs | grep "^$keyid3$" > /dev/null || ret=1
1591n=$((n+1))
1592test "$ret" -eq 0 || echo_i "failed"
1593status=$((status+ret))
1594
1595echo_i "checking dnssec-signzone keeps valid signatures from inactive keys ($n)"
1596ret=0
1597zone=example
1598(
1599cd signer || exit 1
1600cp -f example.db.in example.db
1601$SIGNER -SD -o example example.db > /dev/null
1602echo "\$INCLUDE \"example.db.signed\"" >> example.db
1603# now retire key2 and resign the zone
1604$SETTIME -I now "$key2" > /dev/null 2>&1
1605$SIGNER -SD -o example example.db > /dev/null
1606) || ret=1
1607get_rsasha1_key_ids_from_sigs | grep "^$keyid2$" > /dev/null || ret=1
1608get_rsasha1_key_ids_from_sigs | grep "^$keyid3$" > /dev/null || ret=1
1609n=$((n+1))
1610test "$ret" -eq 0 || echo_i "failed"
1611status=$((status+ret))
1612
1613echo_i "checking dnssec-signzone -Q purges signatures from inactive keys ($n)"
1614ret=0
1615(
1616cd signer || exit 1
1617$SIGNER -SDQ -o example example.db > /dev/null
1618) || ret=1
1619get_rsasha1_key_ids_from_sigs | grep "^$keyid2$" > /dev/null && ret=1
1620get_rsasha1_key_ids_from_sigs | grep "^$keyid3$" > /dev/null || ret=1
1621n=$((n+1))
1622test "$ret" -eq 0 || echo_i "failed"
1623status=$((status+ret))
1624
1625echo_i "checking dnssec-signzone retains unexpired signatures ($n)"
1626ret=0
1627(
1628cd signer || exit 1
1629$SIGNER -Sxt -o example example.db > signer.out.1
1630$SIGNER -Sxt -o example -f example.db.signed example.db.signed > signer.out.2
1631) || ret=1
1632gen1=$(awk '/generated/ {print $3}' signer/signer.out.1)
1633retain1=$(awk '/retained/ {print $3}' signer/signer.out.1)
1634gen2=$(awk '/generated/ {print $3}' signer/signer.out.2)
1635retain2=$(awk '/retained/ {print $3}' signer/signer.out.2)
1636drop2=$(awk '/dropped/ {print $3}' signer/signer.out.2)
1637[ "$retain2" -eq $((gen1+retain1)) ] || ret=1
1638[ "$gen2" -eq 0 ] || ret=1
1639[ "$drop2" -eq 0 ] || ret=1
1640n=$((n+1))
1641test "$ret" -eq 0 || echo_i "failed"
1642status=$((status+ret))
1643
1644echo_i "checking dnssec-signzone purges RRSIGs from formerly-owned glue (nsec) ($n)"
1645ret=0
1646(
1647cd signer || exit 1
1648# remove NSEC-only keys
1649rm -f Kexample.+005*
1650cp -f example.db.in example2.db
1651cat << EOF >> example2.db
1652sub1.example. IN A 10.53.0.1
1653ns.sub2.example. IN A 10.53.0.2
1654EOF
1655echo "\$INCLUDE \"example2.db.signed\"" >> example2.db
1656touch example2.db.signed
1657$SIGNER -DS -O full -f example2.db.signed -o example example2.db > /dev/null
1658) || ret=1
1659grep "^sub1\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 || ret=1
1660grep "^ns\\.sub2\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 || ret=1
1661(
1662cd signer || exit 1
1663cp -f example.db.in example2.db
1664cat << EOF >> example2.db
1665sub1.example. IN NS sub1.example.
1666sub1.example. IN A 10.53.0.1
1667sub2.example. IN NS ns.sub2.example.
1668ns.sub2.example. IN A 10.53.0.2
1669EOF
1670echo "\$INCLUDE \"example2.db.signed\"" >> example2.db
1671$SIGNER -DS -O full -f example2.db.signed -o example example2.db > /dev/null
1672) || ret=1
1673grep "^sub1\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 && ret=1
1674grep "^ns\\.sub2\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 && ret=1
1675n=$((n+1))
1676test "$ret" -eq 0 || echo_i "failed"
1677status=$((status+ret))
1678
1679echo_i "checking dnssec-signzone purges RRSIGs from formerly-owned glue (nsec3) ($n)"
1680ret=0
1681(
1682cd signer || exit 1
1683rm -f example2.db.signed
1684cp -f example.db.in example2.db
1685cat << EOF >> example2.db
1686sub1.example. IN A 10.53.0.1
1687ns.sub2.example. IN A 10.53.0.2
1688EOF
1689echo "\$INCLUDE \"example2.db.signed\"" >> example2.db
1690touch example2.db.signed
1691$SIGNER -DS -3 feedabee -O full -f example2.db.signed -o example example2.db > /dev/null
1692) || ret=1
1693grep "^sub1\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 || ret=1
1694grep "^ns\\.sub2\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 || ret=1
1695(
1696cd signer || exit 1
1697cp -f example.db.in example2.db
1698cat << EOF >> example2.db
1699sub1.example. IN NS sub1.example.
1700sub1.example. IN A 10.53.0.1
1701sub2.example. IN NS ns.sub2.example.
1702ns.sub2.example. IN A 10.53.0.2
1703EOF
1704echo "\$INCLUDE \"example2.db.signed\"" >> example2.db
1705$SIGNER -DS -3 feedabee -O full -f example2.db.signed -o example example2.db > /dev/null
1706) || ret=1
1707grep "^sub1\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 && ret=1
1708grep "^ns\\.sub2\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 && ret=1
1709n=$((n+1))
1710test "$ret" -eq 0 || echo_i "failed"
1711status=$((status+ret))
1712
1713echo_i "checking dnssec-signzone output format ($n)"
1714ret=0
1715(
1716cd signer || exit 1
1717$SIGNER -O full -f - -Sxt -o example example.db > signer.out.3 2> /dev/null
1718$SIGNER -O text -f - -Sxt -o example example.db > signer.out.4 2> /dev/null
1719$SIGNER -O raw -f signer.out.5 -Sxt -o example example.db > /dev/null
1720$SIGNER -O raw=0 -f signer.out.6 -Sxt -o example example.db > /dev/null
1721$SIGNER -O raw -f - -Sxt -o example example.db > signer.out.7 2> /dev/null
1722) || ret=1
1723awk '/IN *SOA/ {if (NF != 11) exit(1)}' signer/signer.out.3 || ret=1
1724awk '/IN *SOA/ {if (NF != 7) exit(1)}' signer/signer.out.4 || ret=1
1725israw1 signer/signer.out.5 || ret=1
1726israw0 signer/signer.out.6 || ret=1
1727israw1 signer/signer.out.7 || ret=1
1728n=$((n+1))
1729test "$ret" -eq 0 || echo_i "failed"
1730status=$((status+ret))
1731
1732echo_i "checking TTLs are capped by dnssec-signzone -M ($n)"
1733ret=0
1734(
1735cd signer || exit 1
1736$SIGNER -O full -f signer.out.8 -S -M 30 -o example example.db > /dev/null
1737) || ret=1
1738awk '/^;/ { next; } $2 > 30 { exit 1; }' signer/signer.out.8 || ret=1
1739n=$((n+1))
1740test "$ret" -eq 0 || echo_i "failed"
1741status=$((status+ret))
1742
1743echo_i "checking dnssec-signzone -N date ($n)"
1744ret=0
1745(
1746cd signer || exit 1
1747TZ=UTC $SIGNER -O full -f signer.out.9 -S -N date -o example example2.db > /dev/null
1748) || ret=1
1749# shellcheck disable=SC2016
1750now=$(TZ=UTC $PERL -e '@lt=localtime(); printf "%.4d%0.2d%0.2d00\n",$lt[5]+1900,$lt[4]+1,$lt[3];')
1751serial=$(awk '/^;/ { next; } $4 == "SOA" { print $7 }' signer/signer.out.9)
1752[ "$now" -eq "$serial" ] || ret=1
1753n=$((n+1))
1754test "$ret" -eq 0 || echo_i "failed"
1755status=$((status+ret))
1756
1757echo_i "checking validated data are not cached longer than originalttl ($n)"
1758ret=0
1759dig_with_opts +ttl +noauth a.ttlpatch.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
1760dig_with_opts +ttl +noauth a.ttlpatch.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
1761grep "3600.IN" dig.out.ns3.test$n > /dev/null || ret=1
1762grep "300.IN" dig.out.ns3.test$n > /dev/null && ret=1
1763grep "300.IN" dig.out.ns4.test$n > /dev/null || ret=1
1764grep "3600.IN" dig.out.ns4.test$n > /dev/null && ret=1
1765n=$((n+1))
1766test "$ret" -eq 0 || echo_i "failed"
1767status=$((status+ret))
1768
1769# Test that "rndc secroots" is able to dump trusted keys
1770echo_i "checking rndc secroots ($n)"
1771ret=0
1772keyid=$(cat ns1/managed.key.id)
1773rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i
1774cp ns4/named.secroots named.secroots.test$n
1775check_secroots_layout named.secroots.test$n || ret=1
1776linecount=$(grep -c "./${DEFAULT_ALGORITHM}/$keyid ; static" named.secroots.test$n || true)
1777[ "$linecount" -eq 1 ] || ret=1
1778linecount=$(< named.secroots.test$n wc -l)
1779[ "$linecount" -eq 9 ] || ret=1
1780n=$((n+1))
1781test "$ret" -eq 0 || echo_i "failed"
1782status=$((status+ret))
1783
1784# Check direct query for RRSIG.  If we first ask for normal (non RRSIG)
1785# record, the corresponding RRSIG should be cached and subsequent query
1786# for RRSIG will be returned with the cached record.
1787echo_i "checking RRSIG query from cache ($n)"
1788ret=0
1789dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 a > /dev/null || ret=1
1790ans=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.4 rrsig) || ret=1
1791expect=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.3 rrsig | grep '^A' ) || ret=1
1792test "$ans" = "$expect" || ret=1
1793# also check that RA is set
1794dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 rrsig > dig.out.ns4.test$n || ret=1
1795grep "flags:.*ra.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
1796n=$((n+1))
1797test "$ret" -eq 0 || echo_i "failed"
1798status=$((status+ret))
1799
1800# Check direct query for RRSIG: If it's not cached with other records,
1801# it should result in an empty response.
1802echo_i "checking RRSIG query not in cache ($n)"
1803ret=0
1804ans=$(dig_with_opts +short rrsigonly.secure.example. @10.53.0.4 rrsig) || ret=1
1805test -z "$ans" || ret=1
1806# also check that RA is cleared
1807dig_with_opts rrsigonly.secure.example. @10.53.0.4 rrsig > dig.out.ns4.test$n || ret=1
1808grep "flags:.*ra.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
1809n=$((n+1))
1810test "$ret" -eq 0 || echo_i "failed"
1811status=$((status+ret))
1812
1813#
1814# RT21868 regression test.
1815#
1816echo_i "checking NSEC3 zone with mismatched NSEC3PARAM / NSEC parameters ($n)"
1817ret=0
1818dig_with_opts non-exist.badparam. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
1819grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
1820n=$((n+1))
1821test "$ret" -eq 0 || echo_i "failed"
1822status=$((status+ret))
1823
1824#
1825# RT22007 regression test.
1826#
1827echo_i "checking optout NSEC3 referral with only insecure delegations ($n)"
1828ret=0
1829dig_with_opts +norec delegation.single-nsec3. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
1830grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
1831grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n > /dev/null || ret=1
1832n=$((n+1))
1833test "$ret" -eq 0 || echo_i "failed"
1834status=$((status+ret))
1835
1836echo_i "checking optout NSEC3 NXDOMAIN with only insecure delegations ($n)"
1837ret=0
1838dig_with_opts +norec nonexist.single-nsec3. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
1839grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
1840grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n > /dev/null || ret=1
1841n=$((n+1))
1842test "$ret" -eq 0 || echo_i "failed"
1843
1844status=$((status+ret))
1845echo_i "checking optout NSEC3 nodata with only insecure delegations ($n)"
1846ret=0
1847dig_with_opts +norec single-nsec3. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
1848grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
1849grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n > /dev/null || ret=1
1850n=$((n+1))
1851test "$ret" -eq 0 || echo_i "failed"
1852status=$((status+ret))
1853
1854echo_i "checking that a zone finishing the transition from $ALTERNATIVE_ALGORITHM to $DEFAULT_ALGORITHM validates secure ($n)"
1855ret=0
1856dig_with_opts ns algroll. @10.53.0.4 > dig.out.ns4.test$n || ret=1
1857grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1858grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n > /dev/null || ret=1
1859n=$((n+1))
1860test "$ret" -eq 0 || echo_i "failed"
1861status=$((status+ret))
1862
1863echo_i "checking validate-except in an insecure local domain ($n)"
1864ret=0
1865dig_with_opts ns www.corp @10.53.0.4 > dig.out.ns4.test$n || ret=1
1866grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1867grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n > /dev/null && ret=1
1868n=$((n+1))
1869test "$ret" -eq 0 || echo_i "failed"
1870status=$((status+ret))
1871
1872echo_i "checking positive and negative validation with negative trust anchors ($n)"
1873ret=0
1874
1875#
1876# check correct initial behavior
1877#
1878dig_with_opts a.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.1 || ret=1
1879grep "status: SERVFAIL" dig.out.ns4.test$n.1 > /dev/null || ret=1
1880dig_with_opts badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
1881grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null || ret=1
1882dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1
1883grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1
1884grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null || ret=1
1885
1886if [ "$ret" -ne 0 ]; then echo_i "failed - checking initial state"; fi
1887status=$((status+ret))
1888ret=0
1889
1890#
1891# add negative trust anchors
1892#
1893rndccmd 10.53.0.4 nta -f -l 20s bogus.example 2>&1 | sed 's/^/ns4 /' | cat_i
1894rndccmd 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
1895# reconfig should maintain NTAs
1896rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
1897rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1
1898lines=$(wc -l < rndc.out.ns4.test$n.1)
1899[ "$lines" -eq 2 ] || ret=1
1900rndccmd 10.53.0.4 nta secure.example 2>&1 | sed 's/^/ns4 /' | cat_i
1901rndccmd 10.53.0.4 nta fakenode.secure.example 2>&1 | sed 's/^/ns4 /' | cat_i
1902# reload should maintain NTAs
1903rndc_reload ns4 10.53.0.4
1904rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.2
1905lines=$(wc -l < rndc.out.ns4.test$n.2)
1906[ "$lines" -eq 4 ] || ret=1
1907# shellcheck disable=SC2016
1908start=$($PERL -e 'print time()."\n";')
1909
1910if [ "$ret" -ne 0 ]; then echo_i "failed - adding NTA's failed"; fi
1911status=$((status+ret))
1912ret=0
1913
1914#
1915# check behavior with NTA's in place
1916#
1917dig_with_opts a.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.4 || ret=1
1918grep "status: SERVFAIL" dig.out.ns4.test$n.4 > /dev/null && ret=1
1919grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 > /dev/null && ret=1
1920dig_with_opts badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.5 || ret=1
1921grep "status: SERVFAIL" dig.out.ns4.test$n.5 > /dev/null && ret=1
1922grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.5 > /dev/null && ret=1
1923dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.6 || ret=1
1924grep "status: SERVFAIL" dig.out.ns4.test$n.6 > /dev/null && ret=1
1925grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.6 > /dev/null && ret=1
1926dig_with_opts a.fakenode.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.7 || ret=1
1927grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.7 > /dev/null && ret=1
1928echo_i "dumping secroots"
1929rndccmd 10.53.0.4 secroots | sed 's/^/ns4 /' | cat_i
1930cp ns4/named.secroots named.secroots.test$n
1931check_secroots_layout named.secroots.test$n || ret=1
1932grep "bogus.example: expiry" named.secroots.test$n > /dev/null || ret=1
1933grep "badds.example: expiry" named.secroots.test$n > /dev/null || ret=1
1934grep "secure.example: expiry" named.secroots.test$n > /dev/null || ret=1
1935grep "fakenode.secure.example: expiry" named.secroots.test$n > /dev/null || ret=1
1936
1937if [ "$ret" -ne 0 ]; then echo_i "failed - with NTA's in place failed"; fi
1938status=$((status+ret))
1939ret=0
1940
1941echo_i "waiting for NTA rechecks/expirations"
1942
1943#
1944# secure.example and badds.example used default nta-duration
1945# (configured as 12s in ns4/named1.conf), but nta recheck interval
1946# is configured to 9s, so at t=10 the NTAs for secure.example and
1947# fakenode.secure.example should both be lifted, but badds.example
1948# should still be going.
1949#
1950# shellcheck disable=SC2016
1951$PERL -e 'my $delay =  '"$start"' + 10 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
1952dig_with_opts b.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.8 || ret=1
1953grep "status: SERVFAIL" dig.out.ns4.test$n.8 > /dev/null && ret=1
1954grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.8 > /dev/null || ret=1
1955dig_with_opts b.fakenode.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.9 || ret=1
1956grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.9 > /dev/null || ret=1
1957grep "status: NXDOMAIN" dig.out.ns4.test$n.9 > /dev/null || ret=1
1958dig_with_opts badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.10 || ret=1
1959grep "status: SERVFAIL" dig.out.ns4.test$n.10 > /dev/null && ret=1
1960grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.10 > /dev/null && ret=1
1961
1962if [ "$ret" -ne 0 ]; then echo_i "failed - checking that default nta's were lifted due to recheck"; fi
1963status=$((status+ret))
1964ret=0
1965
1966#
1967# bogus.example was set to expire in 20s, so at t=13
1968# it should still be NTA'd, but badds.example used the default
1969# lifetime of 12s, so it should revert to SERVFAIL now.
1970#
1971# shellcheck disable=SC2016
1972$PERL -e 'my $delay = '"$start"' + 13 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
1973# check nta table
1974rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n._11
1975lines=$(grep -c " expiry " rndc.out.ns4.test$n._11 || true)
1976[ "$lines" -le 2 ] || ret=1
1977grep "bogus.example/_default: expiry" rndc.out.ns4.test$n._11 > /dev/null || ret=1
1978grep "badds.example/_default: expiry" rndc.out.ns4.test$n._11 > /dev/null && ret=1
1979dig_with_opts b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.11 || ret=1
1980grep "status: SERVFAIL" dig.out.ns4.test$n.11 > /dev/null && ret=1
1981dig_with_opts a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.12 || ret=1
1982grep "status: SERVFAIL" dig.out.ns4.test$n.12 > /dev/null || ret=1
1983grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.12 > /dev/null && ret=1
1984dig_with_opts c.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.13 || ret=1
1985grep "status: SERVFAIL" dig.out.ns4.test$n.13 > /dev/null && ret=1
1986grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.13 > /dev/null || ret=1
1987
1988if [ "$ret" -ne 0 ]; then echo_i "failed - checking that default nta's were lifted due to lifetime"; fi
1989status=$((status+ret))
1990ret=0
1991
1992#
1993# at t=21, all the NTAs should have expired.
1994#
1995# shellcheck disable=SC2016
1996$PERL -e 'my $delay = '"$start"' + 21 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
1997# check correct behavior after bogus.example expiry
1998dig_with_opts d.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.14 || ret=1
1999grep "status: SERVFAIL" dig.out.ns4.test$n.14 > /dev/null && ret=1
2000grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.14 > /dev/null || ret=1
2001dig_with_opts c.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.15 || ret=1
2002grep "status: SERVFAIL" dig.out.ns4.test$n.15 > /dev/null || ret=1
2003# check nta table has been cleaned up now
2004rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.3
2005lines=$(grep -c " expiry " rndc.out.ns4.test$n.3 || true)
2006[ "$lines" -eq 0 ] || ret=1
2007n=$((n+1))
2008if [ "$ret" -ne 0 ]; then echo_i "failed - checking that all nta's have been lifted"; fi
2009status=$((status+ret))
2010ret=0
2011
2012echo_i "testing NTA removals ($n)"
2013rndccmd 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
2014rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1
2015grep "badds.example/_default: expiry" rndc.out.ns4.test$n.1 > /dev/null || ret=1
2016dig_with_opts a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.1 || ret=1
2017grep "status: SERVFAIL" dig.out.ns4.test$n.1 > /dev/null && ret=1
2018grep "^a.badds.example." dig.out.ns4.test$n.1 > /dev/null || ret=1
2019rndccmd 10.53.0.4 nta -remove badds.example > rndc.out.ns4.test$n.2
2020grep "Negative trust anchor removed: badds.example/_default" rndc.out.ns4.test$n.2 > /dev/null || ret=1
2021rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.3
2022grep "badds.example/_default: expiry" rndc.out.ns4.test$n.3 > /dev/null && ret=1
2023dig_with_opts a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
2024grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null || ret=1
2025test "$ret" -eq 0 || echo_i "failed"
2026status=$((status+ret))
2027ret=0
2028
2029echo_i "remove non-existent NTA three times"
2030rndccmd 10.53.0.4 nta -r foo > rndc.out.ns4.test$n.4 2>&1
2031rndccmd 10.53.0.4 nta -remove foo > rndc.out.ns4.test$n.5 2>&1
2032rndccmd 10.53.0.4 nta -r foo > rndc.out.ns4.test$n.6 2>&1
2033grep "not found" rndc.out.ns4.test$n.6 > /dev/null || ret=1
2034test "$ret" -eq 0 || echo_i "failed"
2035status=$((status+ret))
2036ret=0
2037
2038n=$((n+1))
2039echo_i "testing NTA with bogus lifetimes ($n)"
2040echo_i "check with no nta lifetime specified"
2041rndccmd 10.53.0.4 nta -l "" foo > rndc.out.ns4.test$n.1 2>&1 || true
2042grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.1 > /dev/null || ret=1
2043test "$ret" -eq 0 || echo_i "failed"
2044status=$((status+ret))
2045ret=0
2046
2047echo_i "check with bad nta lifetime"
2048rndccmd 10.53.0.4 nta -l garbage foo > rndc.out.ns4.test$n.2 2>&1 || true
2049grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.2 > /dev/null || ret=1
2050test "$ret" -eq 0 || echo_i "failed"
2051status=$((status+ret))
2052ret=0
2053
2054echo_i "check with too long nta lifetime"
2055rndccmd 10.53.0.4 nta -l 7d1h foo > rndc.out.ns4.test$n.3 2>&1 || true
2056grep "'nta' failed: out of range" rndc.out.ns4.test$n.3 > /dev/null || ret=1
2057test "$ret" -eq 0 || echo_i "failed"
2058status=$((status+ret))
2059ret=0
2060
2061#
2062# check NTA persistence across restarts
2063#
2064n=$((n+1))
2065echo_i "testing NTA persistence across restarts ($n)"
2066rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1
2067lines=$(grep -c " expiry " rndc.out.ns4.test$n.1 || true)
2068[ "$lines" -eq 0 ] || ret=1
2069rndccmd 10.53.0.4 nta -f -l 30s bogus.example 2>&1 | sed 's/^/ns4 /' | cat_i
2070rndccmd 10.53.0.4 nta -f -l 10s badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
2071rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.2
2072lines=$(grep -c " expiry " rndc.out.ns4.test$n.2 || true)
2073[ "$lines" -eq 2 ] || ret=1
2074# shellcheck disable=SC2016
2075start=$($PERL -e 'print time()."\n";')
2076
2077if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: adding NTA's failed"; fi
2078status=$((status+ret))
2079ret=0
2080
2081echo_i "killing ns4 with SIGTERM"
2082$KILL -TERM "$(cat ns4/named.pid)"
2083rm -f ns4/named.pid
2084
2085#
2086# ns4 has now shutdown. wait until t=14 when badds.example's NTA
2087# (lifetime=10s) would have expired, and then restart ns4.
2088#
2089echo_i "waiting till 14s have passed since NTAs were added before restarting ns4"
2090# shellcheck disable=SC2016
2091$PERL -e 'my $delay = '"$start"' + 14 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
2092
2093if
2094    $PERL "$SYSTEMTESTTOP/start.pl" --noclean --restart --port "$PORT" dnssec ns4
2095then
2096    echo_i "restarted server ns4"
2097else
2098    echo_i "could not restart server ns4"
2099    exit 1
2100fi
2101
2102echo_i "sleeping for an additional 4 seconds for ns4 to fully startup"
2103sleep 4
2104
2105#
2106# ns4 should be back up now. The NTA for bogus.example should still be
2107# valid, whereas badds.example should not have been added during named
2108# startup (as it had already expired), the fact that it's ignored should
2109# be logged.
2110#
2111rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.3
2112lines=$(wc -l < rndc.out.ns4.test$n.3)
2113[ "$lines" -eq 1 ] || ret=1
2114grep "bogus.example/_default: expiry" rndc.out.ns4.test$n.3 > /dev/null || ret=1
2115dig_with_opts b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.4 || ret=1
2116grep "status: SERVFAIL" dig.out.ns4.test$n.4 > /dev/null && ret=1
2117grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 > /dev/null && ret=1
2118dig_with_opts a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.5 || ret=1
2119grep "status: SERVFAIL" dig.out.ns4.test$n.5 > /dev/null || ret=1
2120grep "ignoring expired NTA at badds.example" ns4/named.run > /dev/null || ret=1
2121
2122# cleanup
2123rndccmd 10.53.0.4 nta -remove bogus.example > rndc.out.ns4.test$n.6
2124
2125if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: restoring NTA failed"; fi
2126status=$((status+ret))
2127ret=0
2128
2129#
2130# check "regular" attribute in NTA file works as expected at named
2131# startup.
2132#
2133n=$((n+1))
2134echo_i "testing loading regular attribute from NTA file ($n)"
2135rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1 2>/dev/null
2136lines=$(wc -l < rndc.out.ns4.test$n.1)
2137[ "$lines" -eq 0 ] || ret=1
2138# initially, secure.example. validates with AD=1
2139dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
2140grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null && ret=1
2141grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 > /dev/null || ret=1
2142
2143echo_i "killing ns4 with SIGTERM"
2144$KILL -TERM "$(cat ns4/named.pid)"
2145rm -f ns4/named.pid
2146
2147echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown"
2148sleep 4
2149
2150#
2151# ns4 has now shutdown. add NTA for secure.example. directly into the
2152# _default.nta file with the regular attribute and some future timestamp.
2153#
2154future="$(($(date +%Y)+20))0101010000"
2155echo "secure.example. regular $future" > ns4/_default.nta
2156# shellcheck disable=SC2016
2157start=$($PERL -e 'print time()."\n";')
2158
2159if
2160    $PERL "$SYSTEMTESTTOP/start.pl" --noclean --restart --port "$PORT" dnssec ns4
2161then
2162    echo_i "restarted server ns4"
2163else
2164    echo_i "could not restart server ns4"
2165    exit 1
2166fi
2167
2168# nta-recheck is configured as 9s, so at t=12 the NTAs for
2169# secure.example. should be lifted as it is not a forced NTA.
2170echo_i "waiting till 12s have passed after ns4 was restarted"
2171# shellcheck disable=SC2016
2172$PERL -e 'my $delay = '"$start"' + 12 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
2173
2174# secure.example. should now return an AD=1 answer (still validates) as
2175# the NTA has been lifted.
2176dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1
2177grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1
2178grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null || ret=1
2179
2180# cleanup
2181rndccmd 10.53.0.4 nta -remove secure.example > rndc.out.ns4.test$n.4 2>/dev/null
2182
2183if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: loading regular NTAs failed"; fi
2184status=$((status+ret))
2185ret=0
2186
2187#
2188# check "forced" attribute in NTA file works as expected at named
2189# startup.
2190#
2191n=$((n+1))
2192echo_i "testing loading forced attribute from NTA file ($n)"
2193rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1 2>/dev/null
2194lines=$(wc -l < rndc.out.ns4.test$n.1)
2195[ "$lines" -eq 0 ] || ret=1
2196# initially, secure.example. validates with AD=1
2197dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
2198grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null && ret=1
2199grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 > /dev/null || ret=1
2200
2201echo_i "killing ns4 with SIGTERM"
2202$KILL -TERM "$(cat ns4/named.pid)"
2203rm -f named.pid
2204
2205echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown"
2206sleep 4
2207
2208#
2209# ns4 has now shutdown. add NTA for secure.example. directly into the
2210# _default.nta file with the forced attribute and some future timestamp.
2211#
2212echo "secure.example. forced $future" > ns4/_default.nta
2213start=$($PERL -e 'print time()."\n";')
2214
2215if
2216    $PERL "$SYSTEMTESTTOP/start.pl" --noclean --restart --port "$PORT" dnssec ns4
2217then
2218    echo_i "restarted server ns4"
2219else
2220    echo_i "could not restart server ns4"
2221    exit 1
2222fi
2223
2224# nta-recheck is configured as 9s, but even at t=12 the NTAs for
2225# secure.example. should not be lifted as it is a forced NTA.
2226echo_i "waiting till 12s have passed after ns4 was restarted"
2227# shellcheck disable=SC2016
2228$PERL -e 'my $delay = '"$start"' + 12 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
2229
2230# secure.example. should now return an AD=0 answer (non-authenticated)
2231# as the NTA is still there.
2232dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1
2233grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1
2234grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null && ret=1
2235
2236# cleanup
2237rndccmd 10.53.0.4 nta -remove secure.example > rndc.out.ns4.test$n.4 2>/dev/null
2238
2239if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: loading forced NTAs failed"; fi
2240status=$((status+ret))
2241ret=0
2242
2243#
2244# check that NTA lifetime read from file is clamped to 1 week.
2245#
2246n=$((n+1))
2247echo_i "testing loading out of bounds lifetime from NTA file ($n)"
2248
2249echo_i "killing ns4 with SIGTERM"
2250$KILL -TERM "$(cat ns4/named.pid)"
2251rm -f ns4/named.pid
2252
2253echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown"
2254sleep 4
2255
2256#
2257# ns4 has now shutdown. add NTA for secure.example. directly into the
2258# _default.nta file with a lifetime well into the future.
2259#
2260echo "secure.example. forced $future" > ns4/_default.nta
2261added=$($PERL -e 'print time()."\n";')
2262
2263if
2264    $PERL "$SYSTEMTESTTOP/start.pl" --noclean --restart --port "$PORT" dnssec ns4
2265then
2266    echo_i "restarted server ns4"
2267else
2268    echo_i "could not restart server ns4"
2269    exit 1
2270fi
2271
2272echo_i "sleeping for an additional 4 seconds for ns4 to fully startup"
2273sleep 4
2274
2275# dump the NTA to a file (omit validate-except entries)
2276echo_i "testing 'rndc nta'"
2277rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1 2>/dev/null
2278# "corp" is configured as a validate-except domain and thus should be
2279# omitted. only "secure.example" should be in the dump at this point.
2280lines=$(wc -l < rndc.out.ns4.test$n.1)
2281[ "$lines" -eq 1 ] || ret=1
2282grep 'secure.example' rndc.out.ns4.test$n.1 > /dev/null || ret=1
2283ts=$(awk '{print $3" "$4}' < rndc.out.ns4.test$n.1)
2284# rndc nta outputs localtime, so append the timezone
2285ts_with_zone="$ts $(date +%z)"
2286echo "ts=$ts" > rndc.out.ns4.test$n.2
2287echo "ts_with_zone=$ts_with_zone" >> rndc.out.ns4.test$n.2
2288echo "added=$added" >> rndc.out.ns4.test$n.2
2289if $PERL -e 'use Time::Piece; use Time::Seconds;' 2>/dev/null
2290then
2291    # ntadiff.pl computes $ts_with_zone - ($added + 1week)
2292    d=$($PERL ./ntadiff.pl "$ts_with_zone" "$added")
2293    echo "d=$d" >> rndc.out.ns4.test$n.2
2294    # diff from $added(now) + 1week to the clamped NTA lifetime should be
2295    # less than a few seconds (handle daylight saving changes by adding 3600).
2296    [ "$d" -lt 3610 ] || ret=1
2297else
2298    echo_i "skipped ntadiff test; install PERL module Time::Piece"
2299fi
2300
2301# cleanup
2302rndccmd 10.53.0.4 nta -remove secure.example > rndc.out.ns4.test$n.3 2>/dev/null
2303
2304n=$((n+1))
2305if [ "$ret" -ne 0 ]; then echo_i "failed - NTA lifetime clamping failed"; fi
2306status=$((status+ret))
2307
2308echo_i "checking that NTAs work with 'forward only;' to a validating resolver ($n)"
2309ret=0
2310# Sanity check behavior without an NTA in place.
2311dig_with_opts @10.53.0.9 badds.example. SOA > dig.out.ns9.test$n.1 || ret=1
2312grep "SERVFAIL" dig.out.ns9.test$n.1 > /dev/null || ret=1
2313grep "ANSWER: 0" dig.out.ns9.test$n.1 > /dev/null || ret=1
2314grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.1 > /dev/null && ret=1
2315# Add an NTA, expecting that to cause resolution to succeed.
2316rndccmd 10.53.0.9 nta badds.example > rndc.out.ns9.test$n.1 2>&1 || ret=1
2317dig_with_opts @10.53.0.9 badds.example. SOA > dig.out.ns9.test$n.2 || ret=1
2318grep "NOERROR" dig.out.ns9.test$n.2 > /dev/null || ret=1
2319grep "ANSWER: 2" dig.out.ns9.test$n.2 > /dev/null || ret=1
2320grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.2 > /dev/null && ret=1
2321# Remove the NTA, expecting that to cause resolution to fail again.
2322rndccmd 10.53.0.9 nta -remove badds.example > rndc.out.ns9.test$n.2 2>&1 || ret=1
2323dig_with_opts @10.53.0.9 badds.example. SOA > dig.out.ns9.test$n.3 || ret=1
2324grep "SERVFAIL" dig.out.ns9.test$n.3 > /dev/null || ret=1
2325grep "ANSWER: 0" dig.out.ns9.test$n.3 > /dev/null || ret=1
2326grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.3 > /dev/null && ret=1
2327if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
2328status=$((status+ret))
2329
2330echo_i "completed NTA tests"
2331
2332# Run a minimal update test if possible.  This is really just
2333# a regression test for RT #2399; more tests should be added.
2334
2335if $PERL -e 'use Net::DNS;' 2>/dev/null
2336then
2337    echo_i "running DNSSEC update test"
2338    ret=0
2339    output=$($PERL dnssec_update_test.pl -s 10.53.0.3 -p "$PORT" dynamic.example.)
2340    test "$?" -eq 0 || ret=1
2341    echo "$output" | cat_i
2342    [ $ret -eq 1 ] && status=1
2343else
2344    echo_i "The DNSSEC update test requires the Net::DNS library." >&2
2345fi
2346
2347n=$((n+1))
2348echo_i "checking managed key maintenance has not started yet ($n)"
2349ret=0
2350[ -f "ns4/managed-keys.bind.jnl" ] && ret=1
2351n=$((n+1))
2352test "$ret" -eq 0 || echo_i "failed"
2353status=$((status+ret))
2354
2355# Reconfigure caching server to use "dnssec-validation auto", and repeat
2356# some of the DNSSEC validation tests to ensure that it works correctly.
2357echo_i "switching to automatic root key configuration"
2358copy_setports ns4/named2.conf.in ns4/named.conf
2359rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
2360sleep 5
2361
2362echo_i "checking managed key maintenance timer has now started ($n)"
2363ret=0
2364[ -f "ns4/managed-keys.bind.jnl" ] || ret=1
2365n=$((n+1))
2366test "$ret" -eq 0 || echo_i "failed"
2367status=$((status+ret))
2368
2369echo_i "checking positive validation NSEC ($n)"
2370ret=0
2371dig_with_opts +noauth a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
2372dig_with_opts +noauth a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
2373digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
2374grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
2375n=$((n+1))
2376test "$ret" -eq 0 || echo_i "failed"
2377status=$((status+ret))
2378
2379echo_i "checking positive validation NSEC3 ($n)"
2380ret=0
2381dig_with_opts +noauth a.nsec3.example. \
2382	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
2383dig_with_opts +noauth a.nsec3.example. \
2384	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
2385digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
2386grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
2387n=$((n+1))
2388test "$ret" -eq 0 || echo_i "failed"
2389status=$((status+ret))
2390
2391echo_i "checking positive validation OPTOUT ($n)"
2392ret=0
2393dig_with_opts +noauth a.optout.example. \
2394	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
2395dig_with_opts +noauth a.optout.example. \
2396	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
2397digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
2398grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
2399n=$((n+1))
2400test "$ret" -eq 0 || echo_i "failed"
2401status=$((status+ret))
2402
2403echo_i "checking negative validation ($n)"
2404ret=0
2405dig_with_opts +noauth q.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
2406dig_with_opts +noauth q.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
2407digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
2408grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
2409grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
2410n=$((n+1))
2411test "$ret" -eq 0 || echo_i "failed"
2412status=$((status+ret))
2413
2414echo_i "checking that root DS queries validate ($n)"
2415ret=0
2416dig_with_opts +noauth . @10.53.0.1 ds > dig.out.ns1.test$n || ret=1
2417dig_with_opts +noauth . @10.53.0.4 ds > dig.out.ns4.test$n || ret=1
2418digcomp dig.out.ns1.test$n dig.out.ns4.test$n || ret=1
2419grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
2420grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2421n=$((n+1))
2422test "$ret" -eq 0 || echo_i "failed"
2423status=$((status+ret))
2424
2425echo_i "checking that DS at a RFC 1918 empty zone lookup succeeds ($n)"
2426ret=0
2427dig_with_opts +noauth 10.in-addr.arpa ds @10.53.0.2 >dig.out.ns2.test$n || ret=1
2428dig_with_opts +noauth 10.in-addr.arpa ds @10.53.0.4 >dig.out.ns6.test$n || ret=1
2429digcomp dig.out.ns2.test$n dig.out.ns6.test$n || ret=1
2430grep "status: NOERROR" dig.out.ns6.test$n > /dev/null || ret=1
2431n=$((n+1))
2432test "$ret" -eq 0 || echo_i "failed"
2433status=$((status+ret))
2434
2435echo_i "checking expired signatures remain with "'"allow-update { none; };"'" and no keys available ($n)"
2436ret=0
2437dig_with_opts +noauth expired.example. +dnssec @10.53.0.3 soa > dig.out.ns3.test$n || ret=1
2438grep "RRSIG.SOA" dig.out.ns3.test$n > /dev/null || ret=1
2439n=$((n+1))
2440test "$ret" -eq 0 || echo_i "failed"
2441
2442status=$((status+ret))
2443echo_i "checking expired signatures do not validate ($n)"
2444ret=0
2445dig_with_opts +noauth expired.example. +dnssec @10.53.0.4 soa > dig.out.ns4.test$n || ret=1
2446grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
2447grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
2448grep "expired.example/.*: RRSIG has expired" ns4/named.run > /dev/null || ret=1
2449n=$((n+1))
2450test "$ret" -eq 0 || echo_i "failed"
2451status=$((status+ret))
2452
2453echo_i "checking that the NSEC3 record for the apex is properly signed when a DNSKEY is added via UPDATE ($n)"
2454ret=0
2455(
2456cd ns3 || exit 1
2457kskname=$($KEYGEN -q -3 -a RSASHA1 -fk update-nsec3.example)
2458(
2459echo zone update-nsec3.example
2460echo server 10.53.0.3 "$PORT"
2461grep DNSKEY "${kskname}.key" | sed -e 's/^/update add /' -e 's/IN/300 IN/'
2462echo send
2463) | $NSUPDATE
2464)
2465dig_with_opts +dnssec a update-nsec3.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2466grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2467grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
2468grep "NSEC3 .* TYPE65534" dig.out.ns4.test$n > /dev/null || ret=1
2469n=$((n+1))
2470test "$ret" -eq 0 || echo_i "failed"
2471status=$((status+ret))
2472
2473echo_i "checking that the NSEC record is properly generated when DNSKEY are added via auto-dnssec ($n)"
2474ret=0
2475dig_with_opts +dnssec a auto-nsec.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2476grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2477grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
2478grep "IN.NSEC[^3].* DNSKEY" dig.out.ns4.test$n > /dev/null || ret=1
2479n=$((n+1))
2480test "$ret" -eq 0 || echo_i "failed"
2481status=$((status+ret))
2482
2483echo_i "checking that the NSEC3 record is properly generated when DNSKEY are added via auto-dnssec ($n)"
2484ret=0
2485dig_with_opts +dnssec a auto-nsec3.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2486grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2487grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
2488grep "IN.NSEC3 .* DNSKEY" dig.out.ns4.test$n > /dev/null || ret=1
2489n=$((n+1))
2490test "$ret" -eq 0 || echo_i "failed"
2491status=$((status+ret))
2492
2493echo_i "checking that signing records have been marked as complete ($n)"
2494ret=0
2495checkprivate dynamic.example 10.53.0.3 || ret=1
2496checkprivate update-nsec3.example 10.53.0.3 || ret=1
2497checkprivate auto-nsec3.example 10.53.0.3 || ret=1
2498checkprivate expiring.example 10.53.0.3 || ret=1
2499checkprivate auto-nsec.example 10.53.0.3 || ret=1
2500n=$((n+1))
2501test "$ret" -eq 0 || echo_i "failed"
2502status=$((status+ret))
2503
2504echo_i "check that 'rndc signing' without arguments is handled ($n)"
2505ret=0
2506rndccmd 10.53.0.3 signing > /dev/null 2>&1 && ret=1
2507rndccmd 10.53.0.3 status > /dev/null || ret=1
2508n=$((n+1))
2509test "$ret" -eq 0 || echo_i "failed"
2510status=$((status+ret))
2511
2512echo_i "check that 'rndc signing -list' without zone is handled ($n)"
2513ret=0
2514rndccmd 10.53.0.3 signing -list > /dev/null 2>&1 && ret=1
2515rndccmd 10.53.0.3 status > /dev/null || ret=1
2516n=$((n+1))
2517test "$ret" -eq 0 || echo_i "failed"
2518status=$((status+ret))
2519
2520echo_i "check that 'rndc signing -clear' without additional arguments is handled ($n)"
2521ret=0
2522rndccmd 10.53.0.3 signing -clear > /dev/null 2>&1 && ret=1
2523rndccmd 10.53.0.3 status > /dev/null || ret=1
2524n=$((n+1))
2525test "$ret" -eq 0 || echo_i "failed"
2526status=$((status+ret))
2527
2528echo_i "check that 'rndc signing -clear all' without zone is handled ($n)"
2529ret=0
2530rndccmd 10.53.0.3 signing -clear all > /dev/null 2>&1 && ret=1
2531rndccmd 10.53.0.3 status > /dev/null || ret=1
2532n=$((n+1))
2533test "$ret" -eq 0 || echo_i "failed"
2534status=$((status+ret))
2535
2536echo_i "check that 'rndc signing -nsec3param' without additional arguments is handled ($n)"
2537ret=0
2538rndccmd 10.53.0.3 signing -nsec3param > /dev/null 2>&1 && ret=1
2539rndccmd 10.53.0.3 status > /dev/null || ret=1
2540n=$((n+1))
2541test "$ret" -eq 0 || echo_i "failed"
2542status=$((status+ret))
2543
2544echo_i "check that 'rndc signing -nsec3param none' without zone is handled ($n)"
2545ret=0
2546rndccmd 10.53.0.3 signing -nsec3param none > /dev/null 2>&1 && ret=1
2547rndccmd 10.53.0.3 status > /dev/null || ret=1
2548n=$((n+1))
2549test "$ret" -eq 0 || echo_i "failed"
2550status=$((status+ret))
2551
2552echo_i "check that 'rndc signing -nsec3param 1' without additional arguments is handled ($n)"
2553ret=0
2554rndccmd 10.53.0.3 signing -nsec3param 1 > /dev/null 2>&1 && ret=1
2555rndccmd 10.53.0.3 status > /dev/null || ret=1
2556n=$((n+1))
2557test "$ret" -eq 0 || echo_i "failed"
2558status=$((status+ret))
2559
2560echo_i "check that 'rndc signing -nsec3param 1 0' without additional arguments is handled ($n)"
2561ret=0
2562rndccmd 10.53.0.3 signing -nsec3param 1 0 > /dev/null 2>&1 && ret=1
2563rndccmd 10.53.0.3 status > /dev/null || ret=1
2564n=$((n+1))
2565test "$ret" -eq 0 || echo_i "failed"
2566status=$((status+ret))
2567
2568echo_i "check that 'rndc signing -nsec3param 1 0 0' without additional arguments is handled ($n)"
2569ret=0
2570rndccmd 10.53.0.3 signing -nsec3param 1 0 0 > /dev/null 2>&1 && ret=1
2571rndccmd 10.53.0.3 status > /dev/null || ret=1
2572n=$((n+1))
2573test "$ret" -eq 0 || echo_i "failed"
2574status=$((status+ret))
2575
2576echo_i "check that 'rndc signing -nsec3param 1 0 0 -' without zone is handled ($n)"
2577ret=0
2578rndccmd 10.53.0.3 signing -nsec3param 1 0 0 - > /dev/null 2>&1 && ret=1
2579rndccmd 10.53.0.3 status > /dev/null || ret=1
2580n=$((n+1))
2581test "$ret" -eq 0 || echo_i "failed"
2582status=$((status+ret))
2583
2584echo_i "check that 'rndc signing -nsec3param' works with salt ($n)"
2585ret=0
2586rndccmd 10.53.0.3 signing -nsec3param 1 0 0 ffff inline.example > /dev/null 2>&1 || ret=1
2587rndccmd 10.53.0.3 status > /dev/null || ret=1
2588for i in 1 2 3 4 5 6 7 8 9 10 ; do
2589        salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
2590	if [ "$salt" = "FFFF" ]; then
2591		break;
2592	fi
2593	echo_i "sleeping ...."
2594	sleep 1
2595done;
2596[ "$salt" = "FFFF" ] || ret=1
2597n=$((n+1))
2598test "$ret" -eq 0 || echo_i "failed"
2599status=$((status+ret))
2600
2601echo_i "check that 'rndc signing -nsec3param' works without salt ($n)"
2602ret=0
2603rndccmd 10.53.0.3 signing -nsec3param 1 0 0 - inline.example > /dev/null 2>&1 || ret=1
2604rndccmd 10.53.0.3 status > /dev/null || ret=1
2605for i in 1 2 3 4 5 6 7 8 9 10 ; do
2606	salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
2607	if [ "$salt" = "-" ]; then
2608		break;
2609	fi
2610	echo_i "sleeping ...."
2611	sleep 1
2612done;
2613[ "$salt" = "-" ] || ret=1
2614n=$((n+1))
2615test "$ret" -eq 0 || echo_i "failed"
2616status=$((status+ret))
2617
2618echo_i "check that 'rndc signing -nsec3param' works with 'auto' as salt ($n)"
2619ret=0
2620rndccmd 10.53.0.3 signing -nsec3param 1 0 0 auto inline.example > /dev/null 2>&1 || ret=1
2621rndccmd 10.53.0.3 status > /dev/null || ret=1
2622for i in 1 2 3 4 5 6 7 8 9 10 ; do
2623	salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
2624	[ -n "$salt" ] && [ "$salt" != "-" ] && break
2625	echo_i "sleeping ...."
2626	sleep 1
2627done;
2628[ "$salt" != "-" ] || ret=1
2629[ "${#salt}" -eq 16 ] || ret=1
2630n=$((n+1))
2631test "$ret" -eq 0 || echo_i "failed"
2632status=$((status+ret))
2633
2634echo_i "check that 'rndc signing -nsec3param' with 'auto' as salt again generates a different salt ($n)"
2635ret=0
2636oldsalt=$salt
2637rndccmd 10.53.0.3 signing -nsec3param 1 0 0 auto inline.example > /dev/null 2>&1 || ret=1
2638rndccmd 10.53.0.3 status > /dev/null || ret=1
2639for i in 1 2 3 4 5 6 7 8 9 10 ; do
2640	salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
2641	[ -n "$salt" ] && [ "$salt" != "$oldsalt" ] && break
2642	echo_i "sleeping ...."
2643	sleep 1
2644done;
2645[ "$salt" != "$oldsalt" ] || ret=1
2646[ "${#salt}" -eq 16 ] || ret=1
2647n=$((n+1))
2648test "$ret" -eq 0 || echo_i "failed"
2649status=$((status+ret))
2650
2651echo_i "check rndc signing -list output ($n)"
2652ret=0
2653{ rndccmd 10.53.0.3 signing -list dynamic.example > signing.out; } 2>&1
2654grep -q "No signing records found" signing.out || {
2655        ret=1
2656        sed 's/^/ns3 /' signing.out | cat_i
2657}
2658{ rndccmd 10.53.0.3 signing -list update-nsec3.example > signing.out; } 2>&1
2659grep -q "Done signing with key .*/NSEC3RSASHA1" signing.out || {
2660        ret=1
2661        sed 's/^/ns3 /' signing.out | cat_i
2662}
2663n=$((n+1))
2664test "$ret" -eq 0 || echo_i "failed"
2665status=$((status+ret))
2666
2667echo_i "clear signing records ($n)"
2668{ rndccmd 10.53.0.3 signing -clear all update-nsec3.example > /dev/null; } 2>&1 || ret=1
2669check_no_signing_record_found() {
2670  { rndccmd 10.53.0.3 signing -list update-nsec3.example > signing.out; } 2>&1
2671  grep -q "No signing records found" signing.out || {
2672    sed 's/^/ns3 /' signing.out | cat_i
2673    return 1
2674  }
2675  return 0
2676}
2677retry_quiet 5 check_no_signing_record_found || ret=1
2678n=$((n+1))
2679test "$ret" -eq 0 || echo_i "failed"
2680status=$((status+ret))
2681
2682echo_i "checking that a insecure zone beneath a cname resolves ($n)"
2683ret=0
2684dig_with_opts soa insecure.below-cname.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2685grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2686grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
2687n=$((n+1))
2688test "$ret" -eq 0 || echo_i "failed"
2689status=$((status+ret))
2690
2691echo_i "checking that a secure zone beneath a cname resolves ($n)"
2692ret=0
2693dig_with_opts soa secure.below-cname.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2694grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2695grep "ANSWER: 2," dig.out.ns4.test$n > /dev/null || ret=1
2696grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
2697n=$((n+1))
2698test "$ret" -eq 0 || echo_i "failed"
2699status=$((status+ret))
2700
2701my_dig() {
2702    "$DIG" +noadd +nosea +nostat +noquest +nocomm +nocmd -p "$PORT" @10.53.0.4 "$@"
2703}
2704
2705echo_i "checking DNSKEY query with no data still gets put in cache ($n)"
2706ret=0
2707firstVal=$(my_dig insecure.example. dnskey| awk '$1 != ";;" { print $2 }')
2708sleep 1
2709secondVal=$(my_dig insecure.example. dnskey| awk '$1 != ";;" { print $2 }')
2710if [ "${firstVal:-0}" -eq "${secondVal:-0}" ]
2711then
2712	sleep 1
2713	thirdVal=$(my_dig insecure.example. dnskey|awk '$1 != ";;" { print $2 }')
2714	if [ "${firstVal:-0}" -eq "${thirdVal:-0}" ]
2715	then
2716		echo_i "cannot confirm query answer still in cache"
2717		ret=1
2718	fi
2719fi
2720n=$((n+1))
2721test "$ret" -eq 0 || echo_i "failed"
2722status=$((status+ret))
2723
2724echo_i "check that a split dnssec dnssec-signzone work ($n)"
2725ret=0
2726dig_with_opts soa split-dnssec.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2727grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2728grep "ANSWER: 2," dig.out.ns4.test$n > /dev/null || ret=1
2729grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
2730n=$((n+1))
2731test "$ret" -eq 0 || echo_i "failed"
2732status=$((status+ret))
2733
2734echo_i "check that a smart split dnssec dnssec-signzone work ($n)"
2735ret=0
2736dig_with_opts soa split-smart.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2737grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2738grep "ANSWER: 2," dig.out.ns4.test$n > /dev/null || ret=1
2739grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
2740n=$((n+1))
2741test "$ret" -eq 0 || echo_i "failed"
2742status=$((status+ret))
2743
2744echo_i "check that NOTIFY is sent at the end of NSEC3 chain generation ($n)"
2745ret=0
2746(
2747echo zone nsec3chain-test
2748echo server 10.53.0.2 "$PORT"
2749echo update add nsec3chain-test. 0 nsec3param 1 0 1 123456
2750echo send
2751) | $NSUPDATE
2752for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
2753do
2754	dig_with_opts nsec3param nsec3chain-test @10.53.0.2 > dig.out.ns2.test$n || ret=1
2755	if grep "ANSWER: 3," dig.out.ns2.test$n >/dev/null
2756	then
2757		break;
2758	fi
2759	echo_i "sleeping ...."
2760	sleep 3
2761done
2762grep "ANSWER: 3," dig.out.ns2.test$n > /dev/null || ret=1
2763if [ "$ret" -ne 0 ]; then echo_i "nsec3 chain generation not complete"; fi
2764dig_with_opts +noauth +nodnssec soa nsec3chain-test @10.53.0.2 > dig.out.ns2.test$n || ret=1
2765s2=$(awk '$4 == "SOA" { print $7}' dig.out.ns2.test$n)
2766for i in 1 2 3 4 5 6 7 8 9 10
2767do
2768	dig_with_opts +noauth +nodnssec soa nsec3chain-test @10.53.0.3 > dig.out.ns3.test$n || ret=1
2769	s3=$(awk '$4 == "SOA" { print $7}' dig.out.ns3.test$n)
2770	test "$s2" = "$s3" && break
2771	sleep 1
2772done
2773digcomp dig.out.ns2.test$n dig.out.ns3.test$n || ret=1
2774n=$((n+1))
2775test "$ret" -eq 0 || echo_i "failed"
2776status=$((status+ret))
2777
2778echo_i "check dnssec-dsfromkey from stdin ($n)"
2779ret=0
2780dig_with_opts dnskey algroll. @10.53.0.2 | \
2781        $DSFROMKEY -f - algroll. > dig.out.ns2.test$n || ret=1
2782NF=$(awk '{print NF}' dig.out.ns2.test$n | sort -u)
2783[ "${NF}" = 7 ] || ret=1
2784# make canonical
2785awk '{
2786	for (i=1;i<7;i++) printf("%s ", $i);
2787	for (i=7;i<=NF;i++) printf("%s", $i);
2788	printf("\n");
2789}' < dig.out.ns2.test$n > canonical1.$n || ret=1
2790awk '{
2791	for (i=1;i<7;i++) printf("%s ", $i);
2792	for (i=7;i<=NF;i++) printf("%s", $i);
2793	printf("\n");
2794}' < ns1/dsset-algroll$TP > canonical2.$n || ret=1
2795$DIFF -b canonical1.$n canonical2.$n > /dev/null 2>&1 || ret=1
2796n=$((n+1))
2797test "$ret" -eq 0 || echo_i "failed"
2798status=$((status+ret))
2799
2800# Intentionally strip ".key" from keyfile name to ensure the error message
2801# includes it anyway to avoid confusion (RT #21731)
2802echo_i "check dnssec-dsfromkey error message when keyfile is not found ($n)"
2803ret=0
2804key=$($KEYGEN -a RSASHA1 -q example.) || ret=1
2805mv "$key.key" "$key"
2806$DSFROMKEY "$key" > dsfromkey.out.$n 2>&1 && ret=1
2807grep "$key.key: file not found" dsfromkey.out.$n > /dev/null || ret=1
2808n=$((n+1))
2809test "$ret" -eq 0 || echo_i "failed"
2810status=$((status+ret))
2811
2812echo_i "testing soon-to-expire RRSIGs without a replacement private key ($n)"
2813ret=0
2814dig_with_answeropts +nottlid expiring.example ns @10.53.0.3 | grep RRSIG > dig.out.ns3.test$n 2>&1
2815# there must be a signature here
2816[ -s dig.out.ns3.test$n ] || ret=1
2817n=$((n+1))
2818test "$ret" -eq 0 || echo_i "failed"
2819status=$((status+ret))
2820
2821echo_i "testing new records are signed with 'no-resign' ($n)"
2822ret=0
2823(
2824echo zone nosign.example
2825echo server 10.53.0.3 "$PORT"
2826echo update add new.nosign.example 300 in txt "hi there"
2827echo send
2828) | $NSUPDATE
2829sleep 1
2830dig_with_answeropts +nottlid txt new.nosign.example @10.53.0.3 \
2831        > dig.out.ns3.test$n 2>&1
2832grep RRSIG dig.out.ns3.test$n > /dev/null 2>&1 || ret=1
2833n=$((n+1))
2834test "$ret" -eq 0 || echo_i "failed"
2835status=$((status+ret))
2836
2837echo_i "testing expiring records aren't resigned with 'no-resign' ($n)"
2838ret=0
2839dig_with_answeropts +nottlid nosign.example ns @10.53.0.3 | \
2840        grep RRSIG | sed 's/[ 	][ 	]*/ /g' > dig.out.ns3.test$n 2>&1
2841# the NS RRSIG should not be changed
2842$DIFF nosign.before dig.out.ns3.test$n > /dev/null|| ret=1
2843n=$((n+1))
2844test "$ret" -eq 0 || echo_i "failed"
2845status=$((status+ret))
2846
2847echo_i "testing updates fail with no private key ($n)"
2848ret=0
2849rm -f ns3/Knosign.example.*.private
2850(
2851echo zone nosign.example
2852echo server 10.53.0.3 "$PORT"
2853echo update add fail.nosign.example 300 in txt "reject me"
2854echo send
2855) | $NSUPDATE > /dev/null 2>&1 && ret=1
2856dig_with_answeropts +nottlid fail.nosign.example txt @10.53.0.3 \
2857        > dig.out.ns3.test$n 2>&1
2858[ -s dig.out.ns3.test$n ] && ret=1
2859n=$((n+1))
2860test "$ret" -eq 0 || echo_i "failed"
2861status=$((status+ret))
2862
2863echo_i "testing legacy upper case signer name validation ($n)"
2864ret=0
2865$DIG +tcp +noadd +noauth +dnssec -p "$PORT" soa upper.example @10.53.0.4 \
2866        > dig.out.ns4.test$n 2>&1
2867grep "flags:.* ad;" dig.out.ns4.test$n > /dev/null || ret=1
2868grep "RRSIG.*SOA.* UPPER\\.EXAMPLE\\. " dig.out.ns4.test$n > /dev/null || ret=1
2869n=$((n+1))
2870test "$ret" -eq 0 || echo_i "failed"
2871status=$((status+ret))
2872
2873echo_i "testing that we lower case signer name ($n)"
2874ret=0
2875$DIG +tcp +noadd +noauth +dnssec -p "$PORT" soa LOWER.EXAMPLE @10.53.0.4 \
2876        > dig.out.ns4.test$n 2>&1
2877grep "flags:.* ad;" dig.out.ns4.test$n > /dev/null || ret=1
2878grep "RRSIG.*SOA.* lower\\.example\\. " dig.out.ns4.test$n > /dev/null || ret=1
2879n=$((n+1))
2880test "$ret" -eq 0 || echo_i "failed"
2881status=$((status+ret))
2882
2883echo_i "testing TTL is capped at RRSIG expiry time ($n)"
2884ret=0
2885rndccmd 10.53.0.3 freeze expiring.example 2>&1 | sed 's/^/ns3 /' | cat_i
2886(
2887cd ns3 || exit 1
2888for file in K*.moved; do
2889  mv "$file" "$(basename "$file" .moved)"
2890done
2891$SIGNER -S -N increment -e now+1mi -o expiring.example expiring.example.db > /dev/null
2892) || ret=1
2893rndc_reload ns3 10.53.0.3 expiring.example
2894
2895rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
2896dig_with_answeropts +cd expiring.example soa @10.53.0.4 > dig.out.ns4.1.$n
2897dig_with_answeropts expiring.example soa @10.53.0.4 > dig.out.ns4.2.$n
2898ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
2899ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
2900for ttl in ${ttls:-0}; do
2901    [ "${ttl}" -eq 300 ] || ret=1
2902done
2903for ttl in ${ttls2:-0}; do
2904    [ "${ttl}" -le 60 ] || ret=1
2905done
2906n=$((n+1))
2907test "$ret" -eq 0 || echo_i "failed"
2908status=$((status+ret))
2909
2910echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section (NS) ($n)"
2911ret=0
2912rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
2913sleep 1
2914dig_with_additionalopts +cd expiring.example ns @10.53.0.4 > dig.out.ns4.1.$n
2915dig_with_additionalopts expiring.example ns @10.53.0.4 > dig.out.ns4.2.$n
2916ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
2917ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
2918for ttl in ${ttls:-300}; do
2919    [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1
2920done
2921for ttl in ${ttls2:-0}; do
2922    [ "$ttl" -le 60 ] || ret=1
2923done
2924n=$((n+1))
2925test "$ret" -eq 0 || echo_i "failed"
2926status=$((status+ret))
2927
2928echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section (MX) ($n)"
2929ret=0
2930rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
2931sleep 1
2932dig_with_additionalopts +cd expiring.example mx @10.53.0.4 > dig.out.ns4.1.$n
2933dig_with_additionalopts expiring.example mx @10.53.0.4 > dig.out.ns4.2.$n
2934ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
2935ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
2936for ttl in ${ttls:-300}; do
2937    [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1
2938done
2939for ttl in ${ttls2:-0}; do
2940    [ "$ttl" -le 60 ] || ret=1
2941done
2942n=$((n+1))
2943test "$ret" -eq 0 || echo_i "failed"
2944status=$((status+ret))
2945
2946copy_setports ns4/named3.conf.in ns4/named.conf
2947rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
2948sleep 3
2949
2950echo_i "testing TTL of about to expire RRsets with dnssec-accept-expired yes; ($n)"
2951ret=0
2952rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
2953dig_with_answeropts +cd expiring.example soa @10.53.0.4 > dig.out.ns4.1.$n
2954dig_with_answeropts expiring.example soa @10.53.0.4 > dig.out.ns4.2.$n
2955ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
2956ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
2957for ttl in ${ttls:-0}; do
2958    [ "$ttl" -eq 300 ] || ret=1
2959done
2960for ttl in ${ttls2:-0}; do
2961    [ "$ttl" -eq 120 ] || ret=1
2962done
2963n=$((n+1))
2964test "$ret" -eq 0 || echo_i "failed"
2965status=$((status+ret))
2966
2967echo_i "testing TTL of expired RRsets with dnssec-accept-expired yes; ($n)"
2968ret=0
2969dig_with_answeropts +cd expired.example soa @10.53.0.4 > dig.out.ns4.1.$n
2970dig_with_answeropts expired.example soa @10.53.0.4 > dig.out.ns4.2.$n
2971ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
2972ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
2973for ttl in ${ttls:-0}; do
2974    [ "$ttl" -eq 300 ] || ret=1
2975done
2976for ttl in ${ttls2:-0}; do
2977    [ "$ttl" -eq 120 ] || ret=1
2978done
2979n=$((n+1))
2980test "$ret" -eq 0 || echo_i "failed"
2981status=$((status+ret))
2982
2983echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section with dnssec-accept-expired yes; ($n)"
2984ret=0
2985rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
2986dig_with_additionalopts +cd expiring.example mx @10.53.0.4 > dig.out.ns4.1.$n
2987dig_with_additionalopts expiring.example mx @10.53.0.4 > dig.out.ns4.2.$n
2988ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
2989ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
2990for ttl in ${ttls:-300}; do
2991    [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1
2992done
2993for ttl in ${ttls2:-0}; do
2994    [ "$ttl" -le 120 ] && [ "$ttl" -gt 60 ] || ret=1
2995done
2996n=$((n+1))
2997test "$ret" -eq 0 || echo_i "failed"
2998status=$((status+ret))
2999
3000echo_i "testing DNSKEY lookup via CNAME ($n)"
3001ret=0
3002dig_with_opts +noauth cnameandkey.secure.example. \
3003	@10.53.0.3 dnskey > dig.out.ns3.test$n || ret=1
3004dig_with_opts +noauth cnameandkey.secure.example. \
3005	@10.53.0.4 dnskey > dig.out.ns4.test$n || ret=1
3006digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
3007grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3008grep "CNAME" dig.out.ns4.test$n > /dev/null || ret=1
3009n=$((n+1))
3010test "$ret" -eq 0 || echo_i "failed"
3011status=$((status+ret))
3012
3013echo_i "testing KEY lookup at CNAME (present) ($n)"
3014ret=0
3015dig_with_opts +noauth cnameandkey.secure.example. \
3016	@10.53.0.3 key > dig.out.ns3.test$n || ret=1
3017dig_with_opts +noauth cnameandkey.secure.example. \
3018	@10.53.0.4 key > dig.out.ns4.test$n || ret=1
3019digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
3020grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3021grep "CNAME" dig.out.ns4.test$n > /dev/null && ret=1
3022n=$((n+1))
3023test "$ret" -eq 0 || echo_i "failed"
3024status=$((status+ret))
3025
3026echo_i "testing KEY lookup at CNAME (not present) ($n)"
3027ret=0
3028dig_with_opts +noauth cnamenokey.secure.example. \
3029	@10.53.0.3 key > dig.out.ns3.test$n || ret=1
3030dig_with_opts +noauth cnamenokey.secure.example. \
3031	@10.53.0.4 key > dig.out.ns4.test$n || ret=1
3032digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
3033grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3034grep "CNAME" dig.out.ns4.test$n > /dev/null && ret=1
3035n=$((n+1))
3036test "$ret" -eq 0 || echo_i "failed"
3037status=$((status+ret))
3038
3039echo_i "testing DNSKEY lookup via DNAME ($n)"
3040ret=0
3041dig_with_opts a.dnameandkey.secure.example. \
3042	@10.53.0.3 dnskey > dig.out.ns3.test$n || ret=1
3043dig_with_opts a.dnameandkey.secure.example. \
3044	@10.53.0.4 dnskey > dig.out.ns4.test$n || ret=1
3045digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
3046grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3047grep "CNAME" dig.out.ns4.test$n > /dev/null || ret=1
3048grep "DNAME" dig.out.ns4.test$n > /dev/null || ret=1
3049n=$((n+1))
3050test "$ret" -eq 0 || echo_i "failed"
3051status=$((status+ret))
3052
3053echo_i "testing KEY lookup via DNAME ($n)"
3054ret=0
3055dig_with_opts b.dnameandkey.secure.example. \
3056	@10.53.0.3 key > dig.out.ns3.test$n || ret=1
3057dig_with_opts b.dnameandkey.secure.example. \
3058	@10.53.0.4 key > dig.out.ns4.test$n || ret=1
3059digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
3060grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3061grep "DNAME" dig.out.ns4.test$n > /dev/null || ret=1
3062n=$((n+1))
3063test "$ret" -eq 0 || echo_i "failed"
3064status=$((status+ret))
3065
3066echo_i "check that named doesn't loop when all private keys are not available ($n)"
3067ret=0
3068lines=$(grep -c "reading private key file expiring.example" ns3/named.run || true)
3069test "${lines:-1000}" -lt 15 || ret=1
3070n=$((n+1))
3071test "$ret" -eq 0 || echo_i "failed"
3072status=$((status+ret))
3073
3074echo_i "check against against missing nearest provable proof ($n)"
3075dig_with_opts +norec b.c.d.optout-tld. \
3076	@10.53.0.6 ds > dig.out.ds.ns6.test$n || ret=1
3077nsec3=$(grep -c "IN.NSEC3" dig.out.ds.ns6.test$n || true)
3078[ "$nsec3" -eq 2 ] || ret=1
3079dig_with_opts +norec b.c.d.optout-tld. \
3080	@10.53.0.6 A > dig.out.ns6.test$n || ret=1
3081nsec3=$(grep -c "IN.NSEC3" dig.out.ns6.test$n || true)
3082[ "$nsec3" -eq 1 ] || ret=1
3083dig_with_opts optout-tld. \
3084	@10.53.0.4 SOA > dig.out.soa.ns4.test$n || ret=1
3085grep "flags:.*ad.*QUERY" dig.out.soa.ns4.test$n > /dev/null || ret=1
3086dig_with_opts b.c.d.optout-tld. \
3087	@10.53.0.4 A > dig.out.ns4.test$n || ret=1
3088grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
3089grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
3090n=$((n+1))
3091test "$ret" -eq 0 || echo_i "failed"
3092status=$((status+ret))
3093
3094echo_i "check that key id are logged when dumping the cache ($n)"
3095ret=0
3096rndc_dumpdb ns4
3097grep "; key id = " ns4/named_dump.db.test$n > /dev/null || ret=1
3098n=$((n+1))
3099test "$ret" -eq 0 || echo_i "failed"
3100status=$((status+ret))
3101
3102echo_i "check KEYDATA records are printed in human readable form in key zone ($n)"
3103# force the managed-keys zone to be written out
3104rndccmd 10.53.0.4 managed-keys sync 2>&1 | sed 's/^/ns4 /' | cat_i
3105for i in 1 2 3 4 5 6 7 8 9
3106do
3107    ret=0
3108    if test -f ns4/managed-keys.bind
3109    then
3110	grep KEYDATA ns4/managed-keys.bind > /dev/null &&
3111	grep "next refresh:" ns4/managed-keys.bind > /dev/null &&
3112	break
3113    fi
3114    ret=1
3115    sleep 1
3116done
3117n=$((n+1))
3118test "$ret" -eq 0 || echo_i "failed"
3119status=$((status+ret))
3120
3121echo_i "check dig's +nocrypto flag ($n)"
3122ret=0
3123dig_with_opts +norec +nocrypto DNSKEY . \
3124	@10.53.0.1 > dig.out.dnskey.ns1.test$n || ret=1
3125grep -E "256 [0-9]+ $DEFAULT_ALGORITHM_NUMBER \\[key id = [1-9][0-9]*]" dig.out.dnskey.ns1.test$n > /dev/null || ret=1
3126grep -E "RRSIG.* \\[omitted]" dig.out.dnskey.ns1.test$n > /dev/null || ret=1
3127dig_with_opts +norec +nocrypto DS example \
3128	@10.53.0.1 > dig.out.ds.ns1.test$n || ret=1
3129grep -E "DS.* [0-9]+ [12] \[omitted]" dig.out.ds.ns1.test$n > /dev/null || ret=1
3130n=$((n+1))
3131test "$ret" -eq 0 || echo_i "failed"
3132status=$((status+ret))
3133
3134echo_i "check simultaneous inactivation and publishing of dnskeys removes inactive signature ($n)"
3135ret=0
3136cnt=0
3137while :
3138do
3139dig_with_opts publish-inactive.example @10.53.0.3 dnskey > dig.out.ns3.test$n
3140keys=$(awk '$5 == 257 { print; }' dig.out.ns3.test$n | wc -l)
3141test "$keys" -gt 2 && break
3142cnt=$((cnt+1))
3143test "$cnt" -gt 120 && break
3144sleep 1
3145done
3146test "$keys" -gt 2 || ret=1
3147sigs=$(grep -c RRSIG dig.out.ns3.test$n || true)
3148n=$((n+1))
3149test "$sigs" -eq 2 || ret=1
3150if test "$ret" -ne 0 ; then echo_i "failed"; fi
3151status=$((status+ret))
3152
3153echo_i "check that increasing the sig-validity-interval resigning triggers re-signing ($n)"
3154ret=0
3155before=$($DIG axfr siginterval.example -p "$PORT" @10.53.0.3 | grep RRSIG.SOA)
3156cp ns3/siginterval2.conf ns3/siginterval.conf
3157rndccmd 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
3158i=10
3159while [ "$i" -ge 0 ]; do
3160after=$($DIG axfr siginterval.example -p "$PORT" @10.53.0.3 | grep RRSIG.SOA)
3161test "$before" != "$after" && break
3162sleep 1
3163i=$((i-1))
3164done
3165n=$((n+1))
3166if test "$before" = "$after" ; then echo_i "failed"; ret=1; fi
3167status=$((status+ret))
3168
3169if [ -x "$PYTHON" ]; then
3170    echo_i "check dnskey-sig-validity sets longer expiry for DNSKEY ($n)"
3171    ret=0
3172    rndccmd 10.53.0.3 sign siginterval.example 2>&1 | sed 's/^/ns3 /' | cat_i
3173    # convert expiry date to a comma-separated list of integers python can
3174    # use as input to date(). strip leading 0s in months and days so
3175    # python3 will recognize them as integers.
3176    $DIG +dnssec +short -p "$PORT" @10.53.0.3 soa siginterval.example > dig.out.soa.test$n
3177    soaexpire=$(awk '$1 ~ /SOA/ { print $5 }' dig.out.soa.test$n |
3178	       sed 's/\(....\)\(..\)\(..\).*/\1, \2, \3/' |
3179	       sed 's/ 0/ /g')
3180    $DIG +dnssec +short -p "$PORT" @10.53.0.3 dnskey siginterval.example > dig.out.dnskey.test$n
3181    dnskeyexpire=$(awk '$1 ~ /DNSKEY/ { print $5; exit 0 }' dig.out.dnskey.test$n |
3182		  sed 's/\(....\)\(..\)\(..\).*/\1, \2, \3/' |
3183		  sed 's/ 0/ /g')
3184    $PYTHON > python.out.$n <<EOF
3185from datetime import date;
3186ke=date($dnskeyexpire)
3187se=date($soaexpire)
3188print((ke-se).days);
3189EOF
3190    diff=$(cat python.out.$n)
3191    [ "$diff" -ge 55 ] || ret=1
3192    n=$((n+1))
3193    test "$ret" -eq 0 || echo_i "failed"
3194    status=$((status+ret))
3195fi
3196
3197copy_setports ns4/named4.conf.in ns4/named.conf
3198rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
3199sleep 3
3200
3201echo_i "check insecure delegation between static-stub zones ($n)"
3202ret=0
3203dig_with_opts ns insecure.secure.example \
3204	@10.53.0.4 > dig.out.ns4.1.test$n || ret=1
3205grep "SERVFAIL" dig.out.ns4.1.test$n > /dev/null && ret=1
3206dig_with_opts ns secure.example \
3207	@10.53.0.4 > dig.out.ns4.2.test$n || ret=1
3208grep "SERVFAIL" dig.out.ns4.2.test$n > /dev/null && ret=1
3209n=$((n+1))
3210test "$ret" -eq 0 || echo_i "failed"
3211status=$((status+ret))
3212
3213echo_i "check the acceptance of seconds as inception and expiration times ($n)"
3214ret=0
3215in="NSEC 8 0 86400 1390003200 1389394800 33655 . NYWjZYBV1b+h4j0yu/SmPOOylR8P4IXKDzHX3NwEmU1SUp27aJ91dP+i+UBcnPmBib0hck4DrFVvpflCEpCnVQd2DexcN0GX+3PM7XobxhtDlmnU X1L47zJlbdHNwTqHuPaMM6Xy9HGMXps7O5JVyfggVhTz2C+G5OVxBdb2rOo="
3216
3217exp="NSEC 8 0 86400 20140118000000 20140110230000 33655 . NYWjZYBV1b+h4j0yu/SmPOOylR8P4IXKDzHX3NwEmU1SUp27aJ91dP+i +UBcnPmBib0hck4DrFVvpflCEpCnVQd2DexcN0GX+3PM7XobxhtDlmnU X1L47zJlbdHNwTqHuPaMM6Xy9HGMXps7O5JVyfggVhTz2C+G5OVxBdb2 rOo="
3218
3219out=$(echo "IN RRSIG $in" | $RRCHECKER -p | sed 's/^IN.RRSIG.//')
3220[ "$out" = "$exp" ] || ret=1
3221n=$((n+1))
3222test "$ret" -eq 0 || echo_i "failed"
3223status=$((status+ret))
3224
3225echo_i "check the correct resigning time is reported in zonestatus ($n)"
3226ret=0
3227rndccmd 10.53.0.3 \
3228		zonestatus secure.example > rndc.out.ns3.test$n
3229# next resign node: secure.example/DNSKEY
3230qname=$(awk '/next resign node:/ { print $4 }' rndc.out.ns3.test$n | sed 's,/.*,,')
3231qtype=$(awk '/next resign node:/ { print $4 }' rndc.out.ns3.test$n | sed 's,.*/,,')
3232# next resign time: Thu, 24 Apr 2014 10:38:16 GMT
3233time=$(awk 'BEGIN { m["Jan"] = "01"; m["Feb"] = "02"; m["Mar"] = "03";
3234		   m["Apr"] = "04"; m["May"] = "05"; m["Jun"] = "06";
3235		   m["Jul"] = "07"; m["Aug"] = "08"; m["Sep"] = "09";
3236		   m["Oct"] = "10"; m["Nov"] = "11"; m["Dec"] = "12";}
3237	 /next resign time:/ { printf "%d%s%02d%s\n", $7, m[$6], $5, $8 }' rndc.out.ns3.test$n | sed 's/://g')
3238dig_with_opts +noall +answer "$qname" "$qtype" @10.53.0.3 > dig.out.test$n
3239expire=$(awk '$4 == "RRSIG" { print $9 }' dig.out.test$n)
3240inception=$(awk '$4 == "RRSIG" { print $10 }' dig.out.test$n)
3241$PERL -e 'exit(0) if ("'"$time"'" lt "'"$expire"'" && "'"$time"'" gt "'"$inception"'"); exit(1);' || ret=1
3242n=$((n+1))
3243test "$ret" -eq 0 || echo_i "failed"
3244status=$((status+ret))
3245
3246echo_i "check that split rrsigs are handled ($n)"
3247ret=0
3248dig_with_opts split-rrsig soa @10.53.0.7 > dig.out.test$n || ret=1
3249awk 'BEGIN { ok=0; } $4 == "SOA" { if ($7 > 1) ok=1; } END { if (!ok) exit(1); }' dig.out.test$n || ret=1
3250n=$((n+1))
3251test "$ret" -eq 0 || echo_i "failed"
3252status=$((status+ret))
3253
3254echo_i "check that not-at-zone-apex RRSIG(SOA) RRsets are removed from the zone after load ($n)"
3255ret=0
3256dig_with_opts split-rrsig AXFR @10.53.0.7 > dig.out.test$n || ret=1
3257grep -q "not-at-zone-apex.*RRSIG.*SOA" dig.out.test$n && ret=1
3258n=$((n+1))
3259test "$ret" -eq 0 || echo_i "failed"
3260status=$((status+ret))
3261
3262echo_i "check that 'dnssec-keygen -S' works for all supported algorithms ($n)"
3263ret=0
3264alg=1
3265until test $alg -eq 256
3266do
3267    zone="keygen-$alg."
3268    case $alg in
3269	2) # Diffie Helman
3270	    alg=$((alg+1))
3271	    continue;;
3272	157|160|161|162|163|164|165) # private - non standard
3273	    alg=$((alg+1))
3274	    continue;;
3275	1|5|7|8|10) # RSA algorithms
3276	    key1=$($KEYGEN -a "$alg" -b "1024" -n zone "$zone" 2> "keygen-$alg.err" || true)
3277	    ;;
3278	15|16)
3279	    key1=$($KEYGEN -a "$alg" -n zone "$zone" 2> "keygen-$alg.err" || true)
3280	    # Soft-fail	in case HSM doesn't support Edwards curves
3281	    if grep "not found" "keygen-$alg.err" > /dev/null && [ "$CRYPTO" = "pkcs11" ]; then
3282		echo_i "Algorithm $alg not supported by HSM: skipping"
3283		alg=$((alg+1))
3284		continue
3285	    fi
3286	    ;;
3287	*)
3288	    key1=$($KEYGEN -a "$alg" -n zone "$zone" 2> "keygen-$alg.err" || true)
3289    esac
3290    if grep "unsupported algorithm" "keygen-$alg.err" > /dev/null
3291    then
3292	alg=$((alg+1))
3293	continue
3294    fi
3295    if test -z "$key1"
3296    then
3297	echo_i "'$KEYGEN -a $alg': failed"
3298	cat "keygen-$alg.err"
3299	ret=1
3300	alg=$((alg+1))
3301	continue
3302    fi
3303    $SETTIME -I now+4d "$key1.private" > /dev/null
3304    key2=$($KEYGEN -v 10 -i 3d -S "$key1.private" 2> /dev/null)
3305    test -f "$key2.key" -a -f "$key2.private" || {
3306	ret=1
3307	echo_i "'dnssec-keygen -S' failed for algorithm: $alg"
3308    }
3309    alg=$((alg+1))
3310done
3311n=$((n+1))
3312test "$ret" -eq 0 || echo_i "failed"
3313status=$((status+ret))
3314
3315echo_i "check that CDS records are signed using KSK by dnssec-signzone ($n)"
3316ret=0
3317dig_with_opts +noall +answer @10.53.0.2 cds cds.secure > dig.out.test$n
3318lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3319test "$lines" -eq 2 || ret=1
3320n=$((n+1))
3321test "$ret" -eq 0 || echo_i "failed"
3322status=$((status+ret))
3323
3324echo_i "check that CDS records are not signed using ZSK by dnssec-signzone -x ($n)"
3325ret=0
3326dig_with_opts +noall +answer @10.53.0.2 cds cds-x.secure > dig.out.test$n
3327lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3328test "$lines" -eq 2 || ret=1
3329n=$((n+1))
3330test "$ret" -eq 0 || echo_i "failed"
3331status=$((status+ret))
3332
3333echo_i "checking that positive unknown NSEC3 hash algorithm does validate ($n)"
3334ret=0
3335dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example SOA > dig.out.ns3.test$n
3336dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 nsec3-unknown.example SOA > dig.out.ns4.test$n
3337grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3338grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
3339grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3340grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
3341n=$((n+1))
3342test "$ret" -eq 0 || echo_i "failed"
3343status=$((status+ret))
3344
3345echo_i "check that CDS records are signed using KSK by with dnssec-auto ($n)"
3346ret=0
3347dig_with_opts +noall +answer @10.53.0.2 cds cds-auto.secure > dig.out.test$n
3348lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3349test "$lines" -eq 2 || ret=1
3350n=$((n+1))
3351test "$ret" -eq 0 || echo_i "failed"
3352status=$((status+ret))
3353
3354echo_i "check that a CDS deletion record is accepted ($n)"
3355ret=0
3356(
3357echo zone cds-update.secure
3358echo server 10.53.0.2 "$PORT"
3359echo update delete cds-update.secure CDS
3360echo update add cds-update.secure 0 CDS 0 0 0 00
3361echo send
3362) | $NSUPDATE > nsupdate.out.test$n 2>&1
3363dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
3364lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
3365test "${lines:-10}" -eq 1 || ret=1
3366lines=$(tr -d '\r' < dig.out.test$n | awk '$4 == "CDS" && $5 == "0" && $6 == "0" && $7 == "0" && $8 == "00" {print}' | wc -l)
3367test "$lines" -eq 1 || ret=1
3368n=$((n+1))
3369test "$ret" -eq 0 || echo_i "failed"
3370status=$((status+ret))
3371
3372echo_i "check that CDS records are signed using KSK when added by nsupdate ($n)"
3373ret=0
3374(
3375echo zone cds-update.secure
3376echo server 10.53.0.2 "$PORT"
3377echo update delete cds-update.secure CDS
3378echo send
3379dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
3380grep "DNSKEY.257" |
3381$DSFROMKEY -12 -C -f - -T 1 cds-update.secure |
3382sed "s/^/update add /"
3383echo send
3384) | $NSUPDATE
3385dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
3386lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3387test "$lines" -eq 2 || ret=1
3388lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
3389test "$lines" -eq 2 || ret=1
3390n=$((n+1))
3391test "$ret" -eq 0 || echo_i "failed"
3392status=$((status+ret))
3393
3394echo_i "check that CDS records are signed only using KSK when added by"
3395echo_ic "nsupdate when dnssec-dnskey-kskonly is yes ($n)"
3396ret=0
3397keyid=$(cat ns2/cds-kskonly.secure.id)
3398(
3399echo zone cds-kskonly.secure
3400echo server 10.53.0.2 "$PORT"
3401echo update delete cds-kskonly.secure CDS
3402echo send
3403dig_with_opts +noall +answer @10.53.0.2 dnskey cds-kskonly.secure |
3404grep "DNSKEY.257" |
3405$DSFROMKEY -12 -C -f - -T 1 cds-kskonly.secure |
3406sed "s/^/update add /"
3407echo send
3408) | $NSUPDATE
3409dig_with_opts +noall +answer @10.53.0.2 cds cds-kskonly.secure > dig.out.test$n
3410lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3411test "$lines" -eq 1 || ret=1
3412lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDS" && $11 == id {print}' dig.out.test$n | wc -l)
3413test "$lines" -eq 1 || ret=1
3414lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
3415test "$lines" -eq 2 || ret=1
3416n=$((n+1))
3417test "$ret" -eq 0 || echo_i "failed"
3418status=$((status+ret))
3419
3420echo_i "check that CDS deletion records are signed only using KSK when added by"
3421echo_ic "nsupdate when dnssec-dnskey-kskonly is yes ($n)"
3422ret=0
3423keyid=$(cat ns2/cds-kskonly.secure.id)
3424(
3425echo zone cds-kskonly.secure
3426echo server 10.53.0.2 "$PORT"
3427echo update delete cds-kskonly.secure CDS
3428echo update add cds-kskonly.secure 0 CDS 0 0 0 00
3429echo send
3430) | $NSUPDATE
3431dig_with_opts +noall +answer @10.53.0.2 cds cds-kskonly.secure > dig.out.test$n
3432lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3433test "$lines" -eq 1 || ret=1
3434lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDS" && $11 == id {print}' dig.out.test$n | wc -l)
3435test "$lines" -eq 1 || ret=1
3436lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
3437test "$lines" -eq 1 || ret=1
3438lines=$(tr -d '\r' < dig.out.test$n | awk '$4 == "CDS" && $5 == "0" && $6 == "0" && $7 == "0" && $8 == "00" {print}' | wc -l)
3439test "$lines" -eq 1 || ret=1
3440n=$((n+1))
3441test "$ret" -eq 0 || echo_i "failed"
3442status=$((status+ret))
3443
3444echo_i "checking that positive unknown NSEC3 hash algorithm with OPTOUT does validate ($n)"
3445ret=0
3446dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example SOA > dig.out.ns3.test$n
3447dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 optout-unknown.example SOA > dig.out.ns4.test$n
3448grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3449grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
3450grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3451grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
3452n=$((n+1))
3453test "$ret" -eq 0 || echo_i "failed"
3454status=$((status+ret))
3455
3456echo_i "check that a non matching CDS record is accepted with a matching CDS record ($n)"
3457ret=0
3458(
3459echo zone cds-update.secure
3460echo server 10.53.0.2 "$PORT"
3461echo update delete cds-update.secure CDS
3462echo send
3463dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
3464grep "DNSKEY.257" |
3465$DSFROMKEY -12 -C -f - -T 1 cds-update.secure |
3466sed "s/^/update add /"
3467dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
3468grep "DNSKEY.257" | sed 's/DNSKEY.257/DNSKEY 258/' |
3469$DSFROMKEY -12 -C -A -f - -T 1 cds-update.secure |
3470sed "s/^/update add /"
3471echo send
3472) | $NSUPDATE
3473dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
3474lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3475test "$lines" -eq 2 || ret=1
3476lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
3477test "$lines" -eq 4 || ret=1
3478n=$((n+1))
3479test "$ret" -eq 0 || echo_i "failed"
3480status=$((status+ret))
3481
3482echo_i "checking that negative unknown NSEC3 hash algorithm does not validate ($n)"
3483ret=0
3484dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example A > dig.out.ns3.test$n
3485dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 nsec3-unknown.example A > dig.out.ns4.test$n
3486grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3487grep "status: SERVFAIL," dig.out.ns4.test$n > /dev/null || ret=1
3488n=$((n+1))
3489test "$ret" -eq 0 || echo_i "failed"
3490status=$((status+ret))
3491
3492echo_i "check that CDNSKEY records are signed using KSK by dnssec-signzone ($n)"
3493ret=0
3494dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey.secure > dig.out.test$n
3495lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3496test "$lines" -eq 2 || ret=1
3497n=$((n+1))
3498test "$ret" -eq 0 || echo_i "failed"
3499status=$((status+ret))
3500
3501echo_i "check that CDNSKEY records are not signed using ZSK by dnssec-signzone -x ($n)"
3502ret=0
3503dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-x.secure > dig.out.test$n
3504lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3505test "$lines" -eq 2 || ret=1
3506n=$((n+1))
3507test "$ret" -eq 0 || echo_i "failed"
3508status=$((status+ret))
3509
3510echo_i "checking that negative unknown NSEC3 hash algorithm with OPTOUT does not validate ($n)"
3511ret=0
3512dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example A > dig.out.ns3.test$n
3513dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 optout-unknown.example A > dig.out.ns4.test$n
3514grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3515grep "status: SERVFAIL," dig.out.ns4.test$n > /dev/null || ret=1
3516n=$((n+1))
3517test "$ret" -eq 0 || echo_i "failed"
3518status=$((status+ret))
3519
3520echo_i "check that CDNSKEY records are signed using KSK by with dnssec-auto ($n)"
3521ret=0
3522dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-auto.secure > dig.out.test$n
3523lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3524test "$lines" -eq 2 || ret=1
3525n=$((n+1))
3526test "$ret" -eq 0 || echo_i "failed"
3527status=$((status+ret))
3528
3529echo_i "checking that unknown DNSKEY algorithm validates as insecure ($n)"
3530ret=0
3531dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unknown.example A > dig.out.ns3.test$n
3532dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unknown.example A > dig.out.ns4.test$n
3533grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3534grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
3535grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
3536n=$((n+1))
3537test "$ret" -eq 0 || echo_i "failed"
3538status=$((status+ret))
3539
3540echo_i "checking that unsupported DNSKEY algorithm validates as insecure ($n)"
3541ret=0
3542dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported.example A > dig.out.ns3.test$n
3543dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unsupported.example A > dig.out.ns4.test$n
3544grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3545grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
3546grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
3547n=$((n+1))
3548test "$ret" -eq 0 || echo_i "failed"
3549status=$((status+ret))
3550
3551echo_i "checking that unsupported DNSKEY algorithm is in DNSKEY RRset ($n)"
3552ret=0
3553dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported-2.example DNSKEY > dig.out.test$n
3554grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
3555grep "dnskey-unsupported-2\.example\..*IN.*DNSKEY.*257 3 255" dig.out.test$n > /dev/null || ret=1
3556n=$((n+1))
3557test "$ret" -eq 0 || echo_i "failed"
3558status=$((status+ret))
3559
3560# TODO: test case for GL #1689.
3561# If we allow the dnssec tools to use deprecated algorithms (such as RSAMD5)
3562# we could write a test that signs a zone with supported and unsupported
3563# algorithm, apply a fixed rrset order such that the unsupported algorithm
3564# precedes the supported one in the DNSKEY RRset, and verify the result still
3565# validates succesfully.
3566
3567echo_i "check that a CDNSKEY deletion record is accepted ($n)"
3568ret=0
3569(
3570echo zone cdnskey-update.secure
3571echo server 10.53.0.2 "$PORT"
3572echo update delete cdnskey-update.secure CDNSKEY
3573echo update add cdnskey-update.secure 0 CDNSKEY 0 3 0 AA==
3574echo send
3575) | $NSUPDATE > nsupdate.out.test$n 2>&1
3576dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
3577lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3578test "${lines:-10}" -eq 1 || ret=1
3579lines=$(tr -d '\r' < dig.out.test$n | awk '$4 == "CDNSKEY" && $5 == "0" && $6 == "3" && $7 == "0" && $8 == "AA==" {print}' | wc -l)
3580test "${lines:-10}" -eq 1 || ret=1
3581n=$((n+1))
3582test "$ret" -eq 0 || echo_i "failed"
3583status=$((status+ret))
3584
3585echo_i "checking that unknown DNSKEY algorithm + unknown NSEC3 has algorithm validates as insecure ($n)"
3586ret=0
3587dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-nsec3-unknown.example A > dig.out.ns3.test$n
3588dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-nsec3-unknown.example A > dig.out.ns4.test$n
3589grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3590grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
3591grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
3592n=$((n+1))
3593test "$ret" -eq 0 || echo_i "failed"
3594status=$((status+ret))
3595
3596echo_i "check that CDNSKEY records are signed using KSK when added by nsupdate ($n)"
3597ret=0
3598(
3599echo zone cdnskey-update.secure
3600echo server 10.53.0.2 "$PORT"
3601echo update delete cdnskey-update.secure CDNSKEY
3602dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
3603sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p'
3604echo send
3605) | $NSUPDATE
3606dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
3607lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3608test "$lines" -eq 2 || ret=1
3609lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3610test "$lines" -eq 1 || ret=1
3611n=$((n+1))
3612test "$ret" -eq 0 || echo_i "failed"
3613status=$((status+ret))
3614
3615echo_i "check that CDNSKEY records are signed only using KSK when added by"
3616echo_ic "nsupdate when dnssec-dnskey-kskonly is yes ($n)"
3617ret=0
3618keyid=$(cat ns2/cdnskey-kskonly.secure.id)
3619(
3620echo zone cdnskey-kskonly.secure
3621echo server 10.53.0.2 "$PORT"
3622echo update delete cdnskey-kskonly.secure CDNSKEY
3623dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-kskonly.secure |
3624sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p'
3625echo send
3626) | $NSUPDATE
3627dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-kskonly.secure > dig.out.test$n
3628lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3629test "$lines" -eq 1 || ret=1
3630lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDNSKEY" && $11 == id {print}' dig.out.test$n | wc -l)
3631test "$lines" -eq 1 || ret=1
3632lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3633test "$lines" -eq 1 || ret=1
3634n=$((n+1))
3635test "$ret" -eq 0 || echo_i "failed"
3636status=$((status+ret))
3637
3638echo_i "check that CDNSKEY deletion records are signed only using KSK when added by"
3639echo_ic "nsupdate when dnssec-dnskey-kskonly is yes ($n)"
3640ret=0
3641keyid=$(cat ns2/cdnskey-kskonly.secure.id)
3642(
3643echo zone cdnskey-kskonly.secure
3644echo server 10.53.0.2 "$PORT"
3645echo update delete cdnskey-kskonly.secure CDNSKEY
3646echo update add cdnskey-kskonly.secure 0 CDNSKEY 0 3 0 AA==
3647echo send
3648) | $NSUPDATE
3649dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-kskonly.secure > dig.out.test$n
3650lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3651test "$lines" -eq 1 || ret=1
3652lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDNSKEY" && $11 == id {print}' dig.out.test$n | wc -l)
3653test "$lines" -eq 1 || ret=1
3654lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3655test "$lines" -eq 1 || ret=1
3656lines=$(tr -d '\r' < dig.out.test$n | awk '$4 == "CDNSKEY" && $5 == "0" && $6 == "3" && $7 == "0" && $8 == "AA==" {print}' | wc -l)
3657test "${lines:-10}" -eq 1 || ret=1
3658n=$((n+1))
3659test "$ret" -eq 0 || echo_i "failed"
3660status=$((status+ret))
3661
3662echo_i "checking initialization with a revoked managed key ($n)"
3663ret=0
3664copy_setports ns5/named2.conf.in ns5/named.conf
3665rndccmd 10.53.0.5 reconfig 2>&1 | sed 's/^/ns5 /' | cat_i
3666sleep 3
3667dig_with_opts +dnssec @10.53.0.5 SOA . > dig.out.ns5.test$n
3668grep "status: SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
3669n=$((n+1))
3670test "$ret" -eq 0 || echo_i "failed"
3671status=$((status+ret))
3672
3673echo_i "check that a non matching CDNSKEY record is accepted with a matching CDNSKEY record ($n)"
3674ret=0
3675(
3676echo zone cdnskey-update.secure
3677echo server 10.53.0.2 "$PORT"
3678echo update delete cdnskey-update.secure CDNSKEY
3679dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
3680sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p'
3681dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
3682sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 258/p'
3683echo send
3684) | $NSUPDATE
3685dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
3686lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3687test "$lines" -eq 2 || ret=1
3688lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3689test "$lines" -eq 2 || ret=1
3690n=$((n+1))
3691test "$ret" -eq 0 || echo_i "failed"
3692status=$((status+ret))
3693
3694echo_i "check that RRSIGs are correctly removed from apex when RRset is removed  NSEC ($n)"
3695ret=0
3696# generate signed zone with MX and AAAA records at apex.
3697(
3698cd signer || exit 1
3699$KEYGEN -q -a RSASHA1 -3 -fK remove > /dev/null
3700$KEYGEN -q -a RSASHA1 -33 remove > /dev/null
3701echo > remove.db.signed
3702$SIGNER -S -o remove -D -f remove.db.signed remove.db.in > signer.out.1.$n
3703)
3704grep "RRSIG MX" signer/remove.db.signed > /dev/null || {
3705	ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.pre$n;
3706}
3707# re-generate signed zone without MX and AAAA records at apex.
3708(
3709cd signer || exit 1
3710$SIGNER -S -o remove -D -f remove.db.signed remove2.db.in > signer.out.2.$n
3711)
3712grep "RRSIG MX" signer/remove.db.signed > /dev/null &&  {
3713	ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.post$n;
3714}
3715n=$((n+1))
3716test "$ret" -eq 0 || echo_i "failed"
3717status=$((status+ret))
3718
3719echo_i "check that RRSIGs are correctly removed from apex when RRset is removed  NSEC3 ($n)"
3720ret=0
3721# generate signed zone with MX and AAAA records at apex.
3722(
3723cd signer || exit 1
3724echo > remove.db.signed
3725$SIGNER -3 - -S -o remove -D -f remove.db.signed remove.db.in > signer.out.1.$n
3726)
3727grep "RRSIG MX" signer/remove.db.signed > /dev/null || {
3728	ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.pre$n;
3729}
3730# re-generate signed zone without MX and AAAA records at apex.
3731(
3732cd signer || exit 1
3733$SIGNER -3 - -S -o remove -D -f remove.db.signed remove2.db.in > signer.out.2.$n
3734)
3735grep "RRSIG MX" signer/remove.db.signed > /dev/null &&  {
3736	ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.post$n;
3737}
3738n=$((n+1))
3739test "$ret" -eq 0 || echo_i "failed"
3740status=$((status+ret))
3741
3742echo_i "check that a named managed zone that was signed 'in-the-future' is re-signed when loaded ($n)"
3743ret=0
3744dig_with_opts managed-future.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
3745grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3746grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
3747n=$((n+1))
3748test "$ret" -eq 0 || echo_i "failed"
3749status=$((status+ret))
3750
3751echo_i "check that trust-anchor-telemetry queries are logged ($n)"
3752ret=0
3753grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/NULL" ns6/named.run > /dev/null || ret=1
3754n=$((n+1))
3755test "$ret" -eq 0 || echo_i "failed"
3756status=$((status+ret))
3757
3758echo_i "check that _ta-XXXX trust-anchor-telemetry queries are logged ($n)"
3759ret=0
3760grep "trust-anchor-telemetry '_ta-[0-9a-f]*/IN' from" ns1/named.run > /dev/null || ret=1
3761n=$((n+1))
3762test "$ret" -eq 0 || echo_i "failed"
3763status=$((status+ret))
3764
3765echo_i "check that _ta-AAAA trust-anchor-telemetry are not sent when disabled ($n)"
3766ret=0
3767grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/IN" ns1/named.run > /dev/null && ret=1
3768n=$((n+1))
3769test "$ret" -eq 0 || echo_i "failed"
3770status=$((status+ret))
3771
3772echo_i "check that KEY-TAG trust-anchor-telemetry queries are logged ($n)"
3773ret=0
3774dig_with_opts . dnskey +ednsopt=KEY-TAG:ffff @10.53.0.1 > dig.out.ns1.test$n || ret=1
3775grep "trust-anchor-telemetry './IN' from .* 65535" ns1/named.run > /dev/null || ret=1
3776n=$((n+1))
3777test "$ret" -eq 0 || echo_i "failed"
3778status=$((status+ret))
3779
3780echo_i "check that multiple KEY-TAG trust-anchor-telemetry options don't leak memory ($n)"
3781ret=0
3782dig_with_opts . dnskey +ednsopt=KEY-TAG:fffe +ednsopt=KEY-TAG:fffd @10.53.0.1 > dig.out.ns1.test$n || ret=1
3783grep "trust-anchor-telemetry './IN' from .* 65534" ns1/named.run > /dev/null || ret=1
3784grep "trust-anchor-telemetry './IN' from .* 65533" ns1/named.run > /dev/null && ret=1
3785$PERL $SYSTEMTESTTOP/stop.pl dnssec ns1 || ret=1
3786nextpart ns1/named.run > /dev/null
3787$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} dnssec ns1 || ret=1
3788n=$(($n+1))
3789test "$ret" -eq 0 || echo_i "failed"
3790status=$((status+ret))
3791
3792echo_i "waiting for root server to finish reloading ($n)"
3793ret=0
3794wait_for_log 20 "all zones loaded" ns1/named.run || ret=1
3795n=$(($n+1))
3796test "$ret" -eq 0 || echo_i "failed"
3797status=$((status+ret))
3798
3799echo_i "check that the view is logged in messages from the validator when using views ($n)"
3800ret=0
3801grep "view rec: *validat" ns4/named.run > /dev/null || ret=1
3802n=$((n+1))
3803test "$ret" -eq 0 || echo_i "failed"
3804status=$((status+ret))
3805
3806echo_i "check that DNAME at apex with NSEC3 is correctly signed (dnssec-signzone) ($n)"
3807ret=0
3808dig_with_opts txt dname-at-apex-nsec3.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
3809grep "RRSIG.NSEC3 ${DEFAULT_ALGORITHM_NUMBER} 3 600" dig.out.ns3.test$n > /dev/null || ret=1
3810n=$((n+1))
3811test "$ret" -eq 0 || echo_i "failed"
3812status=$((status+ret))
3813
3814echo_i "check that DNSKEY and other occluded data are excluded from the delegating bitmap ($n)"
3815ret=0
3816dig_with_opts axfr occluded.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
3817grep "^delegation.occluded.example..*NSEC.*NS KEY DS RRSIG NSEC$" dig.out.ns3.test$n > /dev/null || ret=1
3818grep "^delegation.occluded.example..*DNSKEY.*" dig.out.ns3.test$n > /dev/null || ret=1
3819grep "^delegation.occluded.example..*AAAA.*" dig.out.ns3.test$n > /dev/null || ret=1
3820n=$((n+1))
3821test "$ret" -eq 0 || echo_i "failed"
3822status=$((status+ret))
3823
3824echo_i "checking DNSSEC records are occluded from ANY in an insecure zone ($n)"
3825ret=0
3826dig_with_opts any x.insecure.example. @10.53.0.3 > dig.out.ns3.1.test$n || ret=1
3827grep "status: NOERROR" dig.out.ns3.1.test$n > /dev/null || ret=1
3828grep "ANSWER: 0," dig.out.ns3.1.test$n > /dev/null || ret=1
3829dig_with_opts any zz.secure.example. @10.53.0.3 > dig.out.ns3.2.test$n || ret=1
3830grep "status: NOERROR" dig.out.ns3.2.test$n > /dev/null || ret=1
3831# DNSKEY+RRSIG, NSEC+RRSIG
3832grep "ANSWER: 4," dig.out.ns3.2.test$n > /dev/null || ret=1
3833n=$((n+1))
3834test "$ret" -eq 0 || echo_i "failed"
3835status=$((status+ret))
3836
3837#
3838# DNSSEC tests related to unsupported, disabled and revoked trust anchors.
3839#
3840
3841# This nameserver (ns8) is loaded with a bunch of trust anchors.  Some of
3842# them are good (enabled.managed, enabled.trusted, secure.managed,
3843# secure.trusted), and some of them are bad (disabled.managed,
3844# revoked.managed, unsupported.managed, disabled.trusted, revoked.trusted,
3845# unsupported.trusted).  Make sure that the bad trust anchors are ignored.
3846# This is tested by looking for the corresponding lines in the logfile.
3847echo_i "checking that keys with unsupported algorithms and disabled algorithms are ignored ($n)"
3848ret=0
3849grep -q "ignoring static-key for 'disabled\.trusted\.': algorithm is disabled" ns8/named.run || ret=1
3850grep -q "ignoring static-key for 'unsupported\.trusted\.': algorithm is unsupported" ns8/named.run || ret=1
3851grep -q "ignoring static-key for 'revoked\.trusted\.': bad key type" ns8/named.run || ret=1
3852grep -q "ignoring initial-key for 'disabled\.managed\.': algorithm is disabled" ns8/named.run || ret=1
3853grep -q "ignoring initial-key for 'unsupported\.managed\.': algorithm is unsupported" ns8/named.run || ret=1
3854grep -q "ignoring initial-key for 'revoked\.managed\.': bad key type" ns8/named.run || ret=1
3855n=$((n+1))
3856test "$ret" -eq 0 || echo_i "failed"
3857status=$((status+ret))
3858
3859# The next two tests are fairly normal DNSSEC queries to signed zones with a
3860# default algorithm.  First, a query is made against the server that is
3861# authoritative for the given zone (ns3).  Second, a query is made against a
3862# resolver with trust anchors for the given zone (ns8).  Both are expected to
3863# return an authentic data positive response.
3864echo_i "checking that a trusted key using a supported algorithm validates as secure ($n)"
3865ret=0
3866dig_with_opts @10.53.0.3 a.secure.trusted A > dig.out.ns3.test$n
3867dig_with_opts @10.53.0.8 a.secure.trusted A > dig.out.ns8.test$n
3868grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3869grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3870grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null || ret=1
3871n=$((n+1))
3872test "$ret" -eq 0 || echo_i "failed"
3873status=$((status+ret))
3874
3875echo_i "checking that a managed key using a supported algorithm validates as secure ($n)"
3876ret=0
3877dig_with_opts @10.53.0.3 a.secure.managed A > dig.out.ns3.test$n
3878dig_with_opts @10.53.0.8 a.secure.managed A > dig.out.ns8.test$n
3879grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3880grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3881grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null || ret=1
3882n=$((n+1))
3883test "$ret" -eq 0 || echo_i "failed"
3884status=$((status+ret))
3885
3886# The next two queries ensure that a zone signed with a DNSKEY with an unsupported
3887# algorithm will yield insecure positive responses.  These trust anchors in ns8 are
3888# ignored and so this domain is treated as insecure.  The AD bit should not be set
3889# in the response.
3890echo_i "checking that a trusted key using an unsupported algorithm validates as insecure ($n)"
3891ret=0
3892dig_with_opts @10.53.0.3 a.unsupported.trusted A > dig.out.ns3.test$n
3893dig_with_opts @10.53.0.8 a.unsupported.trusted A > dig.out.ns8.test$n
3894grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3895grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3896grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
3897n=$((n+1))
3898test "$ret" -eq 0 || echo_i "failed"
3899status=$((status+ret))
3900
3901echo_i "checking that a managed key using an unsupported algorithm validates as insecure ($n)"
3902ret=0
3903dig_with_opts @10.53.0.3 a.unsupported.managed A > dig.out.ns3.test$n
3904dig_with_opts @10.53.0.8 a.unsupported.managed A > dig.out.ns8.test$n
3905grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3906grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3907grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
3908n=$((n+1))
3909test "$ret" -eq 0 || echo_i "failed"
3910status=$((status+ret))
3911
3912# The next two queries ensure that a zone signed with a DNSKEY that the nameserver
3913# has a disabled algorithm match for will yield insecure positive responses.
3914# These trust anchors in ns8 are ignored and so this domain is treated as insecure.
3915# The AD bit should not be set in the response.
3916echo_i "checking that a trusted key using a disabled algorithm validates as insecure ($n)"
3917ret=0
3918dig_with_opts @10.53.0.3 a.disabled.trusted A > dig.out.ns3.test$n
3919dig_with_opts @10.53.0.8 a.disabled.trusted A > dig.out.ns8.test$n
3920grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3921grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3922grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
3923n=$((n+1))
3924test "$ret" -eq 0 || echo_i "failed"
3925status=$((status+ret))
3926
3927echo_i "checking that a managed key using a disabled algorithm validates as insecure ($n)"
3928ret=0
3929dig_with_opts @10.53.0.3 a.disabled.managed A > dig.out.ns3.test$n
3930dig_with_opts @10.53.0.8 a.disabled.managed A > dig.out.ns8.test$n
3931grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3932grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3933grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
3934n=$((n+1))
3935test "$ret" -eq 0 || echo_i "failed"
3936status=$((status+ret))
3937
3938# The next two queries ensure that a zone signed with a DNSKEY that the
3939# nameserver has a disabled algorithm for, but for a different domain, will
3940# yield secure positive responses.  Since "enabled.trusted." and
3941# "enabled.managed." do not match the "disable-algorithms" option, no
3942# special rules apply and these zones should validate as secure, with the AD
3943# bit set.
3944echo_i "checking that a trusted key using an algorithm disabled for another domain validates as secure ($n)"
3945ret=0
3946dig_with_opts @10.53.0.3 a.enabled.trusted A > dig.out.ns3.test$n
3947dig_with_opts @10.53.0.8 a.enabled.trusted A > dig.out.ns8.test$n
3948grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3949grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3950grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null || ret=1
3951n=$((n+1))
3952test "$ret" -eq 0 || echo_i "failed"
3953status=$((status+ret))
3954
3955echo_i "checking that a managed key using an algorithm disabled for another domain validates as secure ($n)"
3956ret=0
3957dig_with_opts @10.53.0.3 a.enabled.managed A > dig.out.ns3.test$n
3958dig_with_opts @10.53.0.8 a.enabled.managed A > dig.out.ns8.test$n
3959grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3960grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3961grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null || ret=1
3962n=$((n+1))
3963test "$ret" -eq 0 || echo_i "failed"
3964status=$((status+ret))
3965
3966# A configured revoked trust anchor is ignored and thus the two queries below
3967# should result in insecure responses, since no trust points for the
3968# "revoked.trusted." and "revoked.managed." zones are created.
3969echo_i "checking that a trusted key that is revoked validates as insecure ($n)"
3970ret=0
3971dig_with_opts @10.53.0.3 a.revoked.trusted A > dig.out.ns3.test$n
3972dig_with_opts @10.53.0.8 a.revoked.trusted A > dig.out.ns8.test$n
3973grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3974grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3975grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
3976n=$((n+1))
3977test "$ret" -eq 0 || echo_i "failed"
3978status=$((status+ret))
3979
3980echo_i "checking that a managed key that is revoked validates as insecure ($n)"
3981ret=0
3982dig_with_opts @10.53.0.3 a.revoked.managed A > dig.out.ns3.test$n
3983dig_with_opts @10.53.0.8 a.revoked.managed A > dig.out.ns8.test$n
3984grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3985grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3986grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
3987n=$((n+1))
3988test "$ret" -eq 0 || echo_i "failed"
3989status=$((status+ret))
3990
3991###
3992### Additional checks for when the KSK is offline.
3993###
3994
3995# Save some useful information
3996zone="updatecheck-kskonly.secure"
3997KSK=`cat ns2/${zone}.ksk.key`
3998ZSK=`cat ns2/${zone}.zsk.key`
3999KSK_ID=`cat ns2/${zone}.ksk.id`
4000ZSK_ID=`cat ns2/${zone}.zsk.id`
4001SECTIONS="+answer +noauthority +noadditional"
4002echo_i "testing zone $zone KSK=$KSK_ID ZSK=$ZSK_ID"
4003
4004# Print IDs of keys used for generating RRSIG records for RRsets of type $1
4005# found in dig output file $2.
4006get_keys_which_signed() {
4007	qtype=$1
4008	output=$2
4009	# The key ID is the 11th column of the RRSIG record line.
4010	awk -v qt="$qtype" '$4 == "RRSIG" && $5 == qt {print $11}' < "$output"
4011}
4012
4013# Basic checks to make sure everything is fine before the KSK is made offline.
4014for qtype in "DNSKEY" "CDNSKEY" "CDS"
4015do
4016  echo_i "checking $qtype RRset is signed with KSK only (update-check-ksk, dnssec-ksk-only) ($n)"
4017  ret=0
4018  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4019  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4020  test "$lines" -eq 1 || ret=1
4021  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null || ret=1
4022  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4023  n=$((n+1))
4024  test "$ret" -eq 0 || echo_i "failed"
4025  status=$((status+ret))
4026done
4027
4028echo_i "checking SOA RRset is signed with ZSK only (update-check-ksk and dnssec-ksk-only) ($n)"
4029ret=0
4030dig_with_opts $SECTIONS @10.53.0.2 soa $zone > dig.out.test$n
4031lines=$(get_keys_which_signed "SOA" dig.out.test$n | wc -l)
4032test "$lines" -eq 1 || ret=1
4033get_keys_which_signed "SOA" dig.out.test$n | grep "^$KSK_ID$" > /dev/null && ret=1
4034get_keys_which_signed "SOA" dig.out.test$n | grep "^$ZSK_ID$" > /dev/null || ret=1
4035n=$((n+1))
4036test "$ret" -eq 0 || echo_i "failed"
4037status=$((status+ret))
4038
4039# Roll the ZSK.
4040zsk2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -K ns2 -n zone "$zone")
4041keyfile_to_key_id "$zsk2" > ns2/$zone.zsk.id2
4042ZSK_ID2=`cat ns2/$zone.zsk.id2`
4043
4044echo_i "load new ZSK $ZSK_ID2 for $zone ($n)"
4045ret=0
4046dnssec_loadkeys_on 2 $zone || ret=1
4047n=$((n+1))
4048test "$ret" -eq 0 || echo_i "failed"
4049status=$((status+ret))
4050
4051# Make new ZSK active.
4052echo_i "make ZSK $ZSK_ID inactive and make new ZSK $ZSK_ID2 active for zone $zone ($n)"
4053ret=0
4054$SETTIME -I now -K ns2 $ZSK > /dev/null
4055$SETTIME -A now -K ns2 $zsk2 > /dev/null
4056dnssec_loadkeys_on 2 $zone || ret=1
4057n=$((n+1))
4058test "$ret" -eq 0 || echo_i "failed"
4059status=$((status+ret))
4060
4061# Remove the KSK from disk.
4062echo_i "remove the KSK $KSK_ID for zone $zone from disk"
4063mv ns2/$KSK.key ns2/$KSK.key.bak
4064mv ns2/$KSK.private ns2/$KSK.private.bak
4065
4066# Update the zone that requires a resign of the SOA RRset.
4067echo_i "update the zone with $zone IN TXT nsupdate added me"
4068(
4069echo zone $zone
4070echo server 10.53.0.2 "$PORT"
4071echo update add $zone. 300 in txt "nsupdate added me"
4072echo send
4073) | $NSUPDATE
4074
4075# Redo the tests now that the zone is updated and the KSK is offline.
4076for qtype in "DNSKEY" "CDNSKEY" "CDS"
4077do
4078  echo_i "checking $qtype RRset is signed with KSK only, KSK offline (update-check-ksk, dnssec-ksk-only) ($n)"
4079  ret=0
4080  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4081  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4082  test "$lines" -eq 1 || ret=1
4083  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null || ret=1
4084  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4085  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null && ret=1
4086  n=$((n+1))
4087  test "$ret" -eq 0 || echo_i "failed"
4088  status=$((status+ret))
4089done
4090
4091for qtype in "SOA" "TXT"
4092do
4093  echo_i "checking $qtype RRset is signed with ZSK only, KSK offline (update-check-ksk and dnssec-ksk-only) ($n)"
4094  ret=0
4095  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4096  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4097  test "$lines" -eq 1 || ret=1
4098  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null && ret=1
4099  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4100  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null || ret=1
4101  n=$((n+1))
4102  test "$ret" -eq 0 || echo_i "failed"
4103  status=$((status+ret))
4104done
4105
4106# Put back the KSK.
4107echo_i "put back the KSK $KSK_ID for zone $zone from disk"
4108mv ns2/$KSK.key.bak ns2/$KSK.key
4109mv ns2/$KSK.private.bak ns2/$KSK.private
4110
4111# Roll the ZSK again.
4112zsk3=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -K ns2 -n zone "$zone")
4113keyfile_to_key_id "$zsk3" > ns2/$zone.zsk.id3
4114ZSK_ID3=`cat ns2/$zone.zsk.id3`
4115
4116# Schedule the new ZSK (ZSK3) to become active.
4117echo_i "delete old ZSK $ZSK_ID schedule ZSK $ZSK_ID2 inactive and new ZSK $ZSK_ID3 active for zone $zone ($n)"
4118$SETTIME -D now -K ns2 $ZSK > /dev/null
4119$SETTIME -I +3600 -K ns2 $zsk2 > /dev/null
4120$SETTIME -A +3600 -K ns2 $zsk3 > /dev/null
4121dnssec_loadkeys_on 2 $zone || ret=1
4122n=$((n+1))
4123test "$ret" -eq 0 || echo_i "failed"
4124status=$((status+ret))
4125
4126# Remove the KSK from disk.
4127echo_i "remove the KSK $KSK_ID for zone $zone from disk"
4128mv ns2/$KSK.key ns2/$KSK.key.bak
4129mv ns2/$KSK.private ns2/$KSK.private.bak
4130
4131# Update the zone that requires a resign of the SOA RRset.
4132echo_i "update the zone with $zone IN TXT nsupdate added me again"
4133(
4134echo zone $zone
4135echo server 10.53.0.2 "$PORT"
4136echo update add $zone. 300 in txt "nsupdate added me again"
4137echo send
4138) | $NSUPDATE
4139
4140# Redo the tests now that the ZSK roll has deleted the old key.
4141for qtype in "DNSKEY" "CDNSKEY" "CDS"
4142do
4143  echo_i "checking $qtype RRset is signed with KSK only, old ZSK deleted (update-check-ksk, dnssec-ksk-only) ($n)"
4144  ret=0
4145  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4146  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4147  test "$lines" -eq 1 || ret=1
4148  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null || ret=1
4149  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4150  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null && ret=1
4151  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" > /dev/null && ret=1
4152  n=$((n+1))
4153  test "$ret" -eq 0 || echo_i "failed"
4154  status=$((status+ret))
4155done
4156
4157for qtype in "SOA" "TXT"
4158do
4159  echo_i "checking $qtype RRset is signed with ZSK only, old ZSK deleted (update-check-ksk and dnssec-ksk-only) ($n)"
4160  ret=0
4161  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4162  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4163  test "$lines" -eq 1 || ret=1
4164  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null && ret=1
4165  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4166  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null || ret=1
4167  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" > /dev/null && ret=1
4168  n=$((n+1))
4169  test "$ret" -eq 0 || echo_i "failed"
4170  status=$((status+ret))
4171done
4172
4173# Make the new ZSK (ZSK3) active.
4174echo_i "make new ZSK $ZSK_ID3 active for zone $zone ($n)"
4175$SETTIME -I +1 -K ns2 $zsk2 > /dev/null
4176$SETTIME -A +1 -K ns2 $zsk3 > /dev/null
4177dnssec_loadkeys_on 2 $zone || ret=1
4178n=$((n+1))
4179test "$ret" -eq 0 || echo_i "failed"
4180status=$((status+ret))
4181
4182# Wait for newest ZSK to become active.
4183echo_i "wait until new ZSK $ZSK_ID3 active and ZSK $ZSK_ID2 inactive"
4184for i in 1 2 3 4 5 6 7 8 9 10; do
4185    ret=0
4186    grep "DNSKEY $zone/$DEFAULT_ALGORITHM/$ZSK_ID3 (ZSK) is now active" ns2/named.run > /dev/null || ret=1
4187    grep "DNSKEY $zone/$DEFAULT_ALGORITHM/$ZSK_ID2 (ZSK) is now inactive" ns2/named.run > /dev/null || ret=1
4188    [ "$ret" -eq 0 ] && break
4189    sleep 1
4190done
4191n=$((n+1))
4192test "$ret" -eq 0 || echo_i "failed"
4193status=$((status+ret))
4194
4195# Update the zone that requires a resign of the SOA RRset.
4196echo_i "update the zone with $zone IN TXT nsupdate added me one more time"
4197(
4198echo zone $zone
4199echo server 10.53.0.2 "$PORT"
4200echo update add $zone. 300 in txt "nsupdate added me one more time"
4201echo send
4202) | $NSUPDATE
4203n=$((n+1))
4204test "$ret" -eq 0 || echo_i "failed"
4205status=$((status+ret))
4206
4207# Redo the tests one more time.
4208for qtype in "DNSKEY" "CDNSKEY" "CDS"
4209do
4210  echo_i "checking $qtype RRset is signed with KSK only, new ZSK active (update-check-ksk, dnssec-ksk-only) ($n)"
4211  ret=0
4212  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4213  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4214  test "$lines" -eq 1 || ret=1
4215  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null || ret=1
4216  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4217  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null && ret=1
4218  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" > /dev/null && ret=1
4219  n=$((n+1))
4220  test "$ret" -eq 0 || echo_i "failed"
4221  status=$((status+ret))
4222done
4223
4224for qtype in "SOA" "TXT"
4225do
4226  echo_i "checking $qtype RRset is signed with ZSK only, new ZSK active (update-check-ksk and dnssec-ksk-only) ($n)"
4227  ret=0
4228  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4229  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4230  test "$lines" -eq 1 || ret=1
4231  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null && ret=1
4232  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4233  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null && ret=1
4234  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" > /dev/null || ret=1
4235  n=$((n+1))
4236  test "$ret" -eq 0 || echo_i "failed"
4237  status=$((status+ret))
4238done
4239
4240echo_i "checking secroots output with multiple views ($n)"
4241ret=0
4242rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i
4243cp ns4/named.secroots named.secroots.test$n
4244check_secroots_layout named.secroots.test$n || ret=1
4245n=$((n+1))
4246test "$ret" -eq 0 || echo_i "failed"
4247status=$((status+ret))
4248
4249echo_i "checking sig-validity-interval second field hours vs days ($n)"
4250ret=0
4251# zone configured with 'sig-validity-interval 500 499;'
4252# 499 days in the future w/ a 20 minute runtime to now allowance
4253min=$(TZ=UTC $PERL -e '@lt=localtime(time() + 499*3600*24 - 20*60); printf "%.4d%0.2d%0.2d%0.2d%0.2d%0.2d\n",$lt[5]+1900,$lt[4]+1,$lt[3],$lt[2],$lt[1],$lt[0];')
4254dig_with_opts @10.53.0.2 hours-vs-days AXFR > dig.out.ns2.test$n
4255awk -v min=$min '$4 == "RRSIG" { if ($9 < min) { exit(1); } }' dig.out.ns2.test$n || ret=1
4256n=$((n+1))
4257test "$ret" -eq 0 || echo_i "failed"
4258status=$((status+ret))
4259
4260echo_i "checking validation succeeds during transition to signed ($n)"
4261ret=0
4262dig_with_opts @10.53.0.4 inprogress A > dig.out.ns4.test$n || ret=1
4263grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
4264grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
4265grep 'A.10\.53\.0\.10' dig.out.ns4.test$n >/dev/null || ret=1
4266n=$((n+1))
4267test "$ret" -eq 0 || echo_i "failed"
4268status=$((status+ret))
4269
4270echo_i "checking excessive NSEC3 iteration warnings in named.run ($n)"
4271ret=0
4272grep "zone too-many-iterations/IN: excessive NSEC3PARAM iterations [0-9]* > 150" ns2/named.run >/dev/null 2>&1 || ret=1
4273grep "zone too-many-iterations/IN: excessive NSEC3PARAM iterations [0-9]* > 150" ns3/named.run >/dev/null 2>&1 || ret=1
4274n=$((n+1))
4275test "$ret" -eq 0 || echo_i "failed"
4276status=$((status+ret))
4277
4278# Check that the validating resolver will fallback to insecure if the answer
4279# contains NSEC3 records with high iteration count.
4280echo_i "checking fallback to insecure when NSEC3 iterations is too high (nxdomain) ($n)"
4281ret=0
4282dig_with_opts @10.53.0.2 does-not-exist.too-many-iterations > dig.out.ns2.test$n || ret=1
4283dig_with_opts @10.53.0.4 does-not-exist.too-many-iterations > dig.out.ns4.test$n || ret=1
4284digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
4285grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
4286grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
4287grep "ANSWER: 0, AUTHORITY: 6" dig.out.ns4.test$n > /dev/null || ret=1
4288n=$((n+1))
4289test "$ret" -eq 0 || echo_i "failed"
4290status=$((status+ret))
4291
4292echo_i "checking fallback to insecure when NSEC3 iterations is too high (nodata) ($n)"
4293ret=0
4294dig_with_opts @10.53.0.2 a.too-many-iterations txt > dig.out.ns2.test$n || ret=1
4295dig_with_opts @10.53.0.4 a.too-many-iterations txt > dig.out.ns4.test$n || ret=1
4296digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
4297grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
4298grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
4299grep "ANSWER: 0, AUTHORITY: 4" dig.out.ns4.test$n > /dev/null || ret=1
4300n=$((n+1))
4301test "$ret" -eq 0 || echo_i "failed"
4302status=$((status+ret))
4303
4304echo_i "checking fallback to insecure when NSEC3 iterations is too high (wildcard) ($n)"
4305ret=0
4306dig_with_opts @10.53.0.2 wild.a.too-many-iterations > dig.out.ns2.test$n || ret=1
4307dig_with_opts @10.53.0.4 wild.a.too-many-iterations > dig.out.ns4.test$n || ret=1
4308digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
4309grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
4310grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
4311grep 'wild\.a\.too-many-iterations\..*A.10\.0\.0\.3' dig.out.ns4.test$n >/dev/null || ret=1
4312grep "ANSWER: 2, AUTHORITY: 4" dig.out.ns4.test$n > /dev/null || ret=1
4313n=$((n+1))
4314test "$ret" -eq 0 || echo_i "failed"
4315status=$((status+ret))
4316
4317echo_i "checking fallback to insecure when NSEC3 iterations is too high (wildcard nodata) ($n)"
4318ret=0
4319dig_with_opts @10.53.0.2 type100 wild.a.too-many-iterations > dig.out.ns2.test$n || ret=1
4320dig_with_opts @10.53.0.4 type100 wild.a.too-many-iterations > dig.out.ns4.test$n || ret=1
4321digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
4322grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
4323grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
4324grep "ANSWER: 0, AUTHORITY: 8" dig.out.ns4.test$n > /dev/null || ret=1
4325n=$((n+1))
4326test "$ret" -eq 0 || echo_i "failed"
4327status=$((status+ret))
4328
4329echo_i "exit status: $status"
4330[ $status -eq 0 ] || exit 1
4331