xref: /netbsd-src/external/mpl/bind/dist/bin/tests/system/dnssec/tests.sh (revision 9fb66d812c00ebfb445c0b47dea128f32aa6fe96)
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 1
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 1
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 1
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 1
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_i "checking that a key using an unsupported algorithm cannot be generated ($n)"
1398ret=0
1399zone=example
1400# If dnssec-keygen fails, the test script will exit immediately.  Prevent that
1401# from happening, and also trigger a test failure if dnssec-keygen unexpectedly
1402# succeeds, by using "&& ret=1".
1403$KEYGEN -a 255 $zone > dnssectools.out.test$n 2>&1 && ret=1
1404grep -q "unsupported algorithm: 255" dnssectools.out.test$n || ret=1
1405n=$((n+1))
1406test "$ret" -eq 0 || echo_i "failed"
1407status=$((status+ret))
1408
1409echo_i "checking that a DS record cannot be generated for a key using an unsupported algorithm ($n)"
1410ret=0
1411zone=example
1412# Fake an unsupported algorithm key
1413unsupportedkey=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
1414awk '$3 == "DNSKEY" { $6 = 255 } { print }' ${unsupportedkey}.key > ${unsupportedkey}.tmp
1415mv ${unsupportedkey}.tmp ${unsupportedkey}.key
1416# If dnssec-dsfromkey fails, the test script will exit immediately.  Prevent
1417# that from happening, and also trigger a test failure if dnssec-dsfromkey
1418# unexpectedly succeeds, by using "&& ret=1".
1419$DSFROMKEY ${unsupportedkey} > dnssectools.out.test$n 2>&1 && ret=1
1420grep -q "algorithm is unsupported" dnssectools.out.test$n || ret=1
1421n=$((n+1))
1422test "$ret" -eq 0 || echo_i "failed"
1423status=$((status+ret))
1424
1425echo_i "checking that a zone cannot be signed with a key using an unsupported algorithm ($n)"
1426ret=0
1427ret=0
1428cat signer/example.db.in "${unsupportedkey}.key" > signer/example.db
1429# If dnssec-signzone fails, the test script will exit immediately.  Prevent that
1430# from happening, and also trigger a test failure if dnssec-signzone
1431# unexpectedly succeeds, by using "&& ret=1".
1432$SIGNER -o example signer/example.db ${unsupportedkey} > dnssectools.out.test$n 2>&1 && ret=1
1433grep -q "algorithm is unsupported" dnssectools.out.test$n || ret=1
1434n=$((n+1))
1435test "$ret" -eq 0 || echo_i "failed"
1436status=$((status+ret))
1437
1438get_rsasha1_key_ids_from_sigs() {
1439	tr -d '\r' < signer/example.db.signed | \
1440	awk '
1441		NF < 8 { next }
1442		$(NF-5) != "RRSIG" { next }
1443		$(NF-3) != "5" { next }
1444		$NF != "(" { next }
1445		{
1446			getline;
1447			print $3;
1448		}
1449	' | \
1450	sort -u
1451}
1452
1453echo_i "checking that we can sign a zone with out-of-zone records ($n)"
1454ret=0
1455zone=example
1456key1=$($KEYGEN -K signer -q -a NSEC3RSASHA1 -b 1024 -n zone $zone)
1457key2=$($KEYGEN -K signer -q -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone)
1458(
1459cd signer || exit 1
1460cat example.db.in "$key1.key" "$key2.key" > example.db
1461$SIGNER -o example -f example.db example.db > /dev/null
1462) || ret=1
1463n=$((n+1))
1464test "$ret" -eq 0 || echo_i "failed"
1465status=$((status+ret))
1466
1467echo_i "checking that we can sign a zone (NSEC3) with out-of-zone records ($n)"
1468ret=0
1469zone=example
1470key1=$($KEYGEN -K signer -q -a NSEC3RSASHA1 -b 1024 -n zone $zone)
1471key2=$($KEYGEN -K signer -q -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone)
1472(
1473cd signer || exit 1
1474cat example.db.in "$key1.key" "$key2.key" > example.db
1475$SIGNER -3 - -H 10 -o example -f example.db example.db > /dev/null
1476awk '/^IQF9LQTLK/ {
1477		printf("%s", $0);
1478		while (!index($0, ")")) {
1479			if (getline <= 0)
1480				break;
1481			printf (" %s", $0);
1482		}
1483		printf("\n");
1484	}' example.db | sed 's/[ 	][ 	]*/ /g' > nsec3param.out
1485
1486grep "IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG.example. 0 IN NSEC3 1 0 10 - ( IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG A NS SOA RRSIG DNSKEY NSEC3PARAM )" nsec3param.out > /dev/null
1487) || ret=1
1488n=$((n+1))
1489test "$ret" -eq 0 || echo_i "failed"
1490status=$((status+ret))
1491
1492echo_i "checking NSEC3 signing with empty nonterminals above a delegation ($n)"
1493ret=0
1494zone=example
1495key1=$($KEYGEN -K signer -q -a NSEC3RSASHA1 -b 1024 -n zone $zone)
1496key2=$($KEYGEN -K signer -q -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone)
1497(
1498cd signer || exit 1
1499cat example.db.in "$key1.key" "$key2.key" > example3.db
1500echo "some.empty.nonterminal.nodes.example 60 IN NS ns.example.tld" >> example3.db
1501$SIGNER -3 - -A -H 10 -o example -f example3.db example3.db > /dev/null
1502awk '/^IQF9LQTLK/ {
1503		printf("%s", $0);
1504		while (!index($0, ")")) {
1505			if (getline <= 0)
1506				break;
1507			printf (" %s", $0);
1508		}
1509		printf("\n");
1510	}' example.db | sed 's/[ 	][ 	]*/ /g' > nsec3param.out
1511
1512grep "IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG.example. 0 IN NSEC3 1 0 10 - ( IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG A NS SOA RRSIG DNSKEY NSEC3PARAM )" nsec3param.out > /dev/null
1513) || ret=1
1514n=$((n+1))
1515test "$ret" -eq 0 || echo_i "failed"
1516status=$((status+ret))
1517
1518echo_i "checking that dnssec-signzone updates originalttl on ttl changes ($n)"
1519ret=0
1520zone=example
1521key1=$($KEYGEN -K signer -q -a RSASHA1 -b 1024 -n zone $zone)
1522key2=$($KEYGEN -K signer -q -f KSK -a RSASHA1 -b 1024 -n zone $zone)
1523(
1524cd signer || exit 1
1525cat example.db.in "$key1.key" "$key2.key" > example.db
1526$SIGNER -o example -f example.db.before example.db > /dev/null
1527sed 's/60.IN.SOA./50 IN SOA /' example.db.before > example.db.changed
1528$SIGNER -o example -f example.db.after example.db.changed > /dev/null
1529)
1530grep "SOA 5 1 50" signer/example.db.after > /dev/null || ret=1
1531n=$((n+1))
1532test "$ret" -eq 0 || echo_i "failed"
1533status=$((status+ret))
1534
1535echo_i "checking dnssec-signzone keeps valid signatures from removed keys ($n)"
1536ret=0
1537zone=example
1538key1=$($KEYGEN -K signer -q -f KSK -a RSASHA1 -b 1024 -n zone $zone)
1539key2=$($KEYGEN -K signer -q -a RSASHA1 -b 1024 -n zone $zone)
1540keyid2=$(keyfile_to_key_id "$key2")
1541key3=$($KEYGEN -K signer -q -a RSASHA1 -b 1024 -n zone $zone)
1542keyid3=$(keyfile_to_key_id "$key3")
1543(
1544cd signer || exit 1
1545cat example.db.in "$key1.key" "$key2.key" > example.db
1546$SIGNER -D -o example example.db > /dev/null
1547
1548# now switch out key2 for key3 and resign the zone
1549cat example.db.in "$key1.key" "$key3.key" > example.db
1550echo "\$INCLUDE \"example.db.signed\"" >> example.db
1551$SIGNER -D -o example example.db > /dev/null
1552) || ret=1
1553get_rsasha1_key_ids_from_sigs | grep "^$keyid2$" > /dev/null || ret=1
1554get_rsasha1_key_ids_from_sigs | grep "^$keyid3$" > /dev/null || ret=1
1555n=$((n+1))
1556test "$ret" -eq 0 || echo_i "failed"
1557status=$((status+ret))
1558
1559echo_i "checking dnssec-signzone -R purges signatures from removed keys ($n)"
1560ret=0
1561(
1562cd signer || exit 1
1563$SIGNER -RD -o example example.db > /dev/null
1564) || ret=1
1565get_rsasha1_key_ids_from_sigs | grep "^$keyid2$" > /dev/null && ret=1
1566get_rsasha1_key_ids_from_sigs | grep "^$keyid3$" > /dev/null || ret=1
1567n=$((n+1))
1568test "$ret" -eq 0 || echo_i "failed"
1569status=$((status+ret))
1570
1571echo_i "checking dnssec-signzone keeps valid signatures from inactive keys ($n)"
1572ret=0
1573zone=example
1574(
1575cd signer || exit 1
1576cp -f example.db.in example.db
1577$SIGNER -SD -o example example.db > /dev/null
1578echo "\$INCLUDE \"example.db.signed\"" >> example.db
1579# now retire key2 and resign the zone
1580$SETTIME -I now "$key2" > /dev/null 2>&1
1581$SIGNER -SD -o example example.db > /dev/null
1582) || ret=1
1583get_rsasha1_key_ids_from_sigs | grep "^$keyid2$" > /dev/null || ret=1
1584get_rsasha1_key_ids_from_sigs | grep "^$keyid3$" > /dev/null || ret=1
1585n=$((n+1))
1586test "$ret" -eq 0 || echo_i "failed"
1587status=$((status+ret))
1588
1589echo_i "checking dnssec-signzone -Q purges signatures from inactive keys ($n)"
1590ret=0
1591(
1592cd signer || exit 1
1593$SIGNER -SDQ -o example example.db > /dev/null
1594) || ret=1
1595get_rsasha1_key_ids_from_sigs | grep "^$keyid2$" > /dev/null && ret=1
1596get_rsasha1_key_ids_from_sigs | grep "^$keyid3$" > /dev/null || ret=1
1597n=$((n+1))
1598test "$ret" -eq 0 || echo_i "failed"
1599status=$((status+ret))
1600
1601echo_i "checking dnssec-signzone retains unexpired signatures ($n)"
1602ret=0
1603(
1604cd signer || exit 1
1605$SIGNER -Sxt -o example example.db > signer.out.1
1606$SIGNER -Sxt -o example -f example.db.signed example.db.signed > signer.out.2
1607) || ret=1
1608gen1=$(awk '/generated/ {print $3}' signer/signer.out.1)
1609retain1=$(awk '/retained/ {print $3}' signer/signer.out.1)
1610gen2=$(awk '/generated/ {print $3}' signer/signer.out.2)
1611retain2=$(awk '/retained/ {print $3}' signer/signer.out.2)
1612drop2=$(awk '/dropped/ {print $3}' signer/signer.out.2)
1613[ "$retain2" -eq $((gen1+retain1)) ] || ret=1
1614[ "$gen2" -eq 0 ] || ret=1
1615[ "$drop2" -eq 0 ] || ret=1
1616n=$((n+1))
1617test "$ret" -eq 0 || echo_i "failed"
1618status=$((status+ret))
1619
1620echo_i "checking dnssec-signzone purges RRSIGs from formerly-owned glue (nsec) ($n)"
1621ret=0
1622(
1623cd signer || exit 1
1624# remove NSEC-only keys
1625rm -f Kexample.+005*
1626cp -f example.db.in example2.db
1627cat << EOF >> example2.db
1628sub1.example. IN A 10.53.0.1
1629ns.sub2.example. IN A 10.53.0.2
1630EOF
1631echo "\$INCLUDE \"example2.db.signed\"" >> example2.db
1632touch example2.db.signed
1633$SIGNER -DS -O full -f example2.db.signed -o example example2.db > /dev/null
1634) || ret=1
1635grep "^sub1\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 || ret=1
1636grep "^ns\\.sub2\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 || ret=1
1637(
1638cd signer || exit 1
1639cp -f example.db.in example2.db
1640cat << EOF >> example2.db
1641sub1.example. IN NS sub1.example.
1642sub1.example. IN A 10.53.0.1
1643sub2.example. IN NS ns.sub2.example.
1644ns.sub2.example. IN A 10.53.0.2
1645EOF
1646echo "\$INCLUDE \"example2.db.signed\"" >> example2.db
1647$SIGNER -DS -O full -f example2.db.signed -o example example2.db > /dev/null
1648) || ret=1
1649grep "^sub1\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 && ret=1
1650grep "^ns\\.sub2\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 && ret=1
1651n=$((n+1))
1652test "$ret" -eq 0 || echo_i "failed"
1653status=$((status+ret))
1654
1655echo_i "checking dnssec-signzone purges RRSIGs from formerly-owned glue (nsec3) ($n)"
1656ret=0
1657(
1658cd signer || exit 1
1659rm -f example2.db.signed
1660cp -f example.db.in example2.db
1661cat << EOF >> example2.db
1662sub1.example. IN A 10.53.0.1
1663ns.sub2.example. IN A 10.53.0.2
1664EOF
1665echo "\$INCLUDE \"example2.db.signed\"" >> example2.db
1666touch example2.db.signed
1667$SIGNER -DS -3 feedabee -O full -f example2.db.signed -o example example2.db > /dev/null
1668) || ret=1
1669grep "^sub1\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 || ret=1
1670grep "^ns\\.sub2\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 || ret=1
1671(
1672cd signer || exit 1
1673cp -f example.db.in example2.db
1674cat << EOF >> example2.db
1675sub1.example. IN NS sub1.example.
1676sub1.example. IN A 10.53.0.1
1677sub2.example. IN NS ns.sub2.example.
1678ns.sub2.example. IN A 10.53.0.2
1679EOF
1680echo "\$INCLUDE \"example2.db.signed\"" >> example2.db
1681$SIGNER -DS -3 feedabee -O full -f example2.db.signed -o example example2.db > /dev/null
1682) || ret=1
1683grep "^sub1\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 && ret=1
1684grep "^ns\\.sub2\\.example\\..*RRSIG[ 	]A[ 	]" signer/example2.db.signed > /dev/null 2>&1 && ret=1
1685n=$((n+1))
1686test "$ret" -eq 0 || echo_i "failed"
1687status=$((status+ret))
1688
1689echo_i "checking dnssec-signzone output format ($n)"
1690ret=0
1691(
1692cd signer || exit 1
1693$SIGNER -O full -f - -Sxt -o example example.db > signer.out.3 2> /dev/null
1694$SIGNER -O text -f - -Sxt -o example example.db > signer.out.4 2> /dev/null
1695$SIGNER -O raw -f signer.out.5 -Sxt -o example example.db > /dev/null
1696$SIGNER -O raw=0 -f signer.out.6 -Sxt -o example example.db > /dev/null
1697$SIGNER -O raw -f - -Sxt -o example example.db > signer.out.7 2> /dev/null
1698) || ret=1
1699awk '/IN *SOA/ {if (NF != 11) exit(1)}' signer/signer.out.3 || ret=1
1700awk '/IN *SOA/ {if (NF != 7) exit(1)}' signer/signer.out.4 || ret=1
1701israw1 signer/signer.out.5 || ret=1
1702israw0 signer/signer.out.6 || ret=1
1703israw1 signer/signer.out.7 || ret=1
1704n=$((n+1))
1705test "$ret" -eq 0 || echo_i "failed"
1706status=$((status+ret))
1707
1708echo_i "checking TTLs are capped by dnssec-signzone -M ($n)"
1709ret=0
1710(
1711cd signer || exit 1
1712$SIGNER -O full -f signer.out.8 -S -M 30 -o example example.db > /dev/null
1713) || ret=1
1714awk '/^;/ { next; } $2 > 30 { exit 1; }' signer/signer.out.8 || ret=1
1715n=$((n+1))
1716test "$ret" -eq 0 || echo_i "failed"
1717status=$((status+ret))
1718
1719echo_i "checking dnssec-signzone -N date ($n)"
1720ret=0
1721(
1722cd signer || exit 1
1723TZ=UTC $SIGNER -O full -f signer.out.9 -S -N date -o example example2.db > /dev/null
1724) || ret=1
1725# shellcheck disable=SC2016
1726now=$(TZ=UTC $PERL -e '@lt=localtime(); printf "%.4d%0.2d%0.2d00\n",$lt[5]+1900,$lt[4]+1,$lt[3];')
1727serial=$(awk '/^;/ { next; } $4 == "SOA" { print $7 }' signer/signer.out.9)
1728[ "$now" -eq "$serial" ] || ret=1
1729n=$((n+1))
1730test "$ret" -eq 0 || echo_i "failed"
1731status=$((status+ret))
1732
1733echo_i "checking validated data are not cached longer than originalttl ($n)"
1734ret=0
1735dig_with_opts +ttl +noauth a.ttlpatch.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
1736dig_with_opts +ttl +noauth a.ttlpatch.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
1737grep "3600.IN" dig.out.ns3.test$n > /dev/null || ret=1
1738grep "300.IN" dig.out.ns3.test$n > /dev/null && ret=1
1739grep "300.IN" dig.out.ns4.test$n > /dev/null || ret=1
1740grep "3600.IN" dig.out.ns4.test$n > /dev/null && ret=1
1741n=$((n+1))
1742test "$ret" -eq 0 || echo_i "failed"
1743status=$((status+ret))
1744
1745# Test that "rndc secroots" is able to dump trusted keys
1746echo_i "checking rndc secroots ($n)"
1747ret=0
1748keyid=$(cat ns1/managed.key.id)
1749rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i
1750cp ns4/named.secroots named.secroots.test$n
1751check_secroots_layout named.secroots.test$n || ret=1
1752linecount=$(grep -c "./${DEFAULT_ALGORITHM}/$keyid ; static" named.secroots.test$n || true)
1753[ "$linecount" -eq 1 ] || ret=1
1754linecount=$(< named.secroots.test$n wc -l)
1755[ "$linecount" -eq 9 ] || ret=1
1756n=$((n+1))
1757test "$ret" -eq 0 || echo_i "failed"
1758status=$((status+ret))
1759
1760# Check direct query for RRSIG.  If we first ask for normal (non RRSIG)
1761# record, the corresponding RRSIG should be cached and subsequent query
1762# for RRSIG will be returned with the cached record.
1763echo_i "checking RRSIG query from cache ($n)"
1764ret=0
1765dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 a > /dev/null || ret=1
1766ans=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.4 rrsig) || ret=1
1767expect=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.3 rrsig | grep '^A' ) || ret=1
1768test "$ans" = "$expect" || ret=1
1769# also check that RA is set
1770dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 rrsig > dig.out.ns4.test$n || ret=1
1771grep "flags:.*ra.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
1772n=$((n+1))
1773test "$ret" -eq 0 || echo_i "failed"
1774status=$((status+ret))
1775
1776# Check direct query for RRSIG: If it's not cached with other records,
1777# it should result in an empty response.
1778echo_i "checking RRSIG query not in cache ($n)"
1779ret=0
1780ans=$(dig_with_opts +short rrsigonly.secure.example. @10.53.0.4 rrsig) || ret=1
1781test -z "$ans" || ret=1
1782# also check that RA is cleared
1783dig_with_opts rrsigonly.secure.example. @10.53.0.4 rrsig > dig.out.ns4.test$n || ret=1
1784grep "flags:.*ra.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
1785n=$((n+1))
1786test "$ret" -eq 0 || echo_i "failed"
1787status=$((status+ret))
1788
1789#
1790# RT21868 regression test.
1791#
1792echo_i "checking NSEC3 zone with mismatched NSEC3PARAM / NSEC parameters ($n)"
1793ret=0
1794dig_with_opts non-exist.badparam. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
1795grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
1796n=$((n+1))
1797test "$ret" -eq 0 || echo_i "failed"
1798status=$((status+ret))
1799
1800#
1801# RT22007 regression test.
1802#
1803echo_i "checking optout NSEC3 referral with only insecure delegations ($n)"
1804ret=0
1805dig_with_opts +norec delegation.single-nsec3. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
1806grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
1807grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n > /dev/null || ret=1
1808n=$((n+1))
1809test "$ret" -eq 0 || echo_i "failed"
1810status=$((status+ret))
1811
1812echo_i "checking optout NSEC3 NXDOMAIN with only insecure delegations ($n)"
1813ret=0
1814dig_with_opts +norec nonexist.single-nsec3. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
1815grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1
1816grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n > /dev/null || ret=1
1817n=$((n+1))
1818test "$ret" -eq 0 || echo_i "failed"
1819
1820status=$((status+ret))
1821echo_i "checking optout NSEC3 nodata with only insecure delegations ($n)"
1822ret=0
1823dig_with_opts +norec single-nsec3. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
1824grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
1825grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n > /dev/null || ret=1
1826n=$((n+1))
1827test "$ret" -eq 0 || echo_i "failed"
1828status=$((status+ret))
1829
1830echo_i "checking that a zone finishing the transition from $ALTERNATIVE_ALGORITHM to $DEFAULT_ALGORITHM validates secure ($n)"
1831ret=0
1832dig_with_opts ns algroll. @10.53.0.4 > dig.out.ns4.test$n || ret=1
1833grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1834grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n > /dev/null || ret=1
1835n=$((n+1))
1836test "$ret" -eq 0 || echo_i "failed"
1837status=$((status+ret))
1838
1839echo_i "checking validate-except in an insecure local domain ($n)"
1840ret=0
1841dig_with_opts ns www.corp @10.53.0.4 > dig.out.ns4.test$n || ret=1
1842grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
1843grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n > /dev/null && ret=1
1844n=$((n+1))
1845test "$ret" -eq 0 || echo_i "failed"
1846status=$((status+ret))
1847
1848echo_i "checking positive and negative validation with negative trust anchors ($n)"
1849ret=0
1850
1851#
1852# check correct initial behavior
1853#
1854dig_with_opts a.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.1 || ret=1
1855grep "status: SERVFAIL" dig.out.ns4.test$n.1 > /dev/null || ret=1
1856dig_with_opts badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
1857grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null || ret=1
1858dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1
1859grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1
1860grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null || ret=1
1861
1862if [ "$ret" -ne 0 ]; then echo_i "failed - checking initial state"; fi
1863status=$((status+ret))
1864ret=0
1865
1866#
1867# add negative trust anchors
1868#
1869rndccmd 10.53.0.4 nta -f -l 20s bogus.example 2>&1 | sed 's/^/ns4 /' | cat_i
1870rndccmd 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
1871# reconfig should maintain NTAs
1872rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
1873rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1
1874lines=$(wc -l < rndc.out.ns4.test$n.1)
1875[ "$lines" -eq 2 ] || ret=1
1876rndccmd 10.53.0.4 nta secure.example 2>&1 | sed 's/^/ns4 /' | cat_i
1877rndccmd 10.53.0.4 nta fakenode.secure.example 2>&1 | sed 's/^/ns4 /' | cat_i
1878# reload should maintain NTAs
1879rndc_reload ns4 10.53.0.4
1880rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.2
1881lines=$(wc -l < rndc.out.ns4.test$n.2)
1882[ "$lines" -eq 4 ] || ret=1
1883# shellcheck disable=SC2016
1884start=$($PERL -e 'print time()."\n";')
1885
1886if [ "$ret" -ne 0 ]; then echo_i "failed - adding NTA's failed"; fi
1887status=$((status+ret))
1888ret=0
1889
1890#
1891# check behavior with NTA's in place
1892#
1893dig_with_opts a.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.4 || ret=1
1894grep "status: SERVFAIL" dig.out.ns4.test$n.4 > /dev/null && ret=1
1895grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 > /dev/null && ret=1
1896dig_with_opts badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.5 || ret=1
1897grep "status: SERVFAIL" dig.out.ns4.test$n.5 > /dev/null && ret=1
1898grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.5 > /dev/null && ret=1
1899dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.6 || ret=1
1900grep "status: SERVFAIL" dig.out.ns4.test$n.6 > /dev/null && ret=1
1901grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.6 > /dev/null && ret=1
1902dig_with_opts a.fakenode.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.7 || ret=1
1903grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.7 > /dev/null && ret=1
1904echo_i "dumping secroots"
1905rndccmd 10.53.0.4 secroots | sed 's/^/ns4 /' | cat_i
1906cp ns4/named.secroots named.secroots.test$n
1907check_secroots_layout named.secroots.test$n || ret=1
1908grep "bogus.example: expiry" named.secroots.test$n > /dev/null || ret=1
1909grep "badds.example: expiry" named.secroots.test$n > /dev/null || ret=1
1910grep "secure.example: expiry" named.secroots.test$n > /dev/null || ret=1
1911grep "fakenode.secure.example: expiry" named.secroots.test$n > /dev/null || ret=1
1912
1913if [ "$ret" -ne 0 ]; then echo_i "failed - with NTA's in place failed"; fi
1914status=$((status+ret))
1915ret=0
1916
1917echo_i "waiting for NTA rechecks/expirations"
1918
1919#
1920# secure.example and badds.example used default nta-duration
1921# (configured as 12s in ns4/named1.conf), but nta recheck interval
1922# is configured to 9s, so at t=10 the NTAs for secure.example and
1923# fakenode.secure.example should both be lifted, but badds.example
1924# should still be going.
1925#
1926# shellcheck disable=SC2016
1927$PERL -e 'my $delay =  '"$start"' + 10 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
1928dig_with_opts b.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.8 || ret=1
1929grep "status: SERVFAIL" dig.out.ns4.test$n.8 > /dev/null && ret=1
1930grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.8 > /dev/null || ret=1
1931dig_with_opts b.fakenode.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.9 || ret=1
1932grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.9 > /dev/null || ret=1
1933grep "status: NXDOMAIN" dig.out.ns4.test$n.9 > /dev/null || ret=1
1934dig_with_opts badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.10 || ret=1
1935grep "status: SERVFAIL" dig.out.ns4.test$n.10 > /dev/null && ret=1
1936grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.10 > /dev/null && ret=1
1937
1938if [ "$ret" -ne 0 ]; then echo_i "failed - checking that default nta's were lifted due to recheck"; fi
1939status=$((status+ret))
1940ret=0
1941
1942#
1943# bogus.example was set to expire in 20s, so at t=13
1944# it should still be NTA'd, but badds.example used the default
1945# lifetime of 12s, so it should revert to SERVFAIL now.
1946#
1947# shellcheck disable=SC2016
1948$PERL -e 'my $delay = '"$start"' + 13 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
1949# check nta table
1950rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n._11
1951lines=$(grep -c " expiry " rndc.out.ns4.test$n._11 || true)
1952[ "$lines" -le 2 ] || ret=1
1953grep "bogus.example/_default: expiry" rndc.out.ns4.test$n._11 > /dev/null || ret=1
1954grep "badds.example/_default: expiry" rndc.out.ns4.test$n._11 > /dev/null && ret=1
1955dig_with_opts b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.11 || ret=1
1956grep "status: SERVFAIL" dig.out.ns4.test$n.11 > /dev/null && ret=1
1957dig_with_opts a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.12 || ret=1
1958grep "status: SERVFAIL" dig.out.ns4.test$n.12 > /dev/null || ret=1
1959grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.12 > /dev/null && ret=1
1960dig_with_opts c.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.13 || ret=1
1961grep "status: SERVFAIL" dig.out.ns4.test$n.13 > /dev/null && ret=1
1962grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.13 > /dev/null || ret=1
1963
1964if [ "$ret" -ne 0 ]; then echo_i "failed - checking that default nta's were lifted due to lifetime"; fi
1965status=$((status+ret))
1966ret=0
1967
1968#
1969# at t=21, all the NTAs should have expired.
1970#
1971# shellcheck disable=SC2016
1972$PERL -e 'my $delay = '"$start"' + 21 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
1973# check correct behavior after bogus.example expiry
1974dig_with_opts d.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.14 || ret=1
1975grep "status: SERVFAIL" dig.out.ns4.test$n.14 > /dev/null && ret=1
1976grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.14 > /dev/null || ret=1
1977dig_with_opts c.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.15 || ret=1
1978grep "status: SERVFAIL" dig.out.ns4.test$n.15 > /dev/null || ret=1
1979# check nta table has been cleaned up now
1980rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.3
1981lines=$(grep -c " expiry " rndc.out.ns4.test$n.3 || true)
1982[ "$lines" -eq 0 ] || ret=1
1983n=$((n+1))
1984if [ "$ret" -ne 0 ]; then echo_i "failed - checking that all nta's have been lifted"; fi
1985status=$((status+ret))
1986ret=0
1987
1988echo_i "testing NTA removals ($n)"
1989rndccmd 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
1990rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1
1991grep "badds.example/_default: expiry" rndc.out.ns4.test$n.1 > /dev/null || ret=1
1992dig_with_opts a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.1 || ret=1
1993grep "status: SERVFAIL" dig.out.ns4.test$n.1 > /dev/null && ret=1
1994grep "^a.badds.example." dig.out.ns4.test$n.1 > /dev/null || ret=1
1995rndccmd 10.53.0.4 nta -remove badds.example > rndc.out.ns4.test$n.2
1996grep "Negative trust anchor removed: badds.example/_default" rndc.out.ns4.test$n.2 > /dev/null || ret=1
1997rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.3
1998grep "badds.example/_default: expiry" rndc.out.ns4.test$n.3 > /dev/null && ret=1
1999dig_with_opts a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
2000grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null || ret=1
2001test "$ret" -eq 0 || echo_i "failed"
2002status=$((status+ret))
2003ret=0
2004
2005echo_i "remove non-existent NTA three times"
2006rndccmd 10.53.0.4 nta -r foo > rndc.out.ns4.test$n.4 2>&1
2007rndccmd 10.53.0.4 nta -remove foo > rndc.out.ns4.test$n.5 2>&1
2008rndccmd 10.53.0.4 nta -r foo > rndc.out.ns4.test$n.6 2>&1
2009grep "not found" rndc.out.ns4.test$n.6 > /dev/null || ret=1
2010test "$ret" -eq 0 || echo_i "failed"
2011status=$((status+ret))
2012ret=0
2013
2014n=$((n+1))
2015echo_i "testing NTA with bogus lifetimes ($n)"
2016echo_i "check with no nta lifetime specified"
2017rndccmd 10.53.0.4 nta -l "" foo > rndc.out.ns4.test$n.1 2>&1 || true
2018grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.1 > /dev/null || ret=1
2019test "$ret" -eq 0 || echo_i "failed"
2020status=$((status+ret))
2021ret=0
2022
2023echo_i "check with bad nta lifetime"
2024rndccmd 10.53.0.4 nta -l garbage foo > rndc.out.ns4.test$n.2 2>&1 || true
2025grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.2 > /dev/null || ret=1
2026test "$ret" -eq 0 || echo_i "failed"
2027status=$((status+ret))
2028ret=0
2029
2030echo_i "check with too long nta lifetime"
2031rndccmd 10.53.0.4 nta -l 7d1h foo > rndc.out.ns4.test$n.3 2>&1 || true
2032grep "'nta' failed: out of range" rndc.out.ns4.test$n.3 > /dev/null || ret=1
2033test "$ret" -eq 0 || echo_i "failed"
2034status=$((status+ret))
2035ret=0
2036
2037#
2038# check NTA persistence across restarts
2039#
2040n=$((n+1))
2041echo_i "testing NTA persistence across restarts ($n)"
2042rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1
2043lines=$(grep -c " expiry " rndc.out.ns4.test$n.1 || true)
2044[ "$lines" -eq 0 ] || ret=1
2045rndccmd 10.53.0.4 nta -f -l 30s bogus.example 2>&1 | sed 's/^/ns4 /' | cat_i
2046rndccmd 10.53.0.4 nta -f -l 10s badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
2047rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.2
2048lines=$(grep -c " expiry " rndc.out.ns4.test$n.2 || true)
2049[ "$lines" -eq 2 ] || ret=1
2050# shellcheck disable=SC2016
2051start=$($PERL -e 'print time()."\n";')
2052
2053if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: adding NTA's failed"; fi
2054status=$((status+ret))
2055ret=0
2056
2057echo_i "killing ns4 with SIGTERM"
2058$KILL -TERM "$(cat ns4/named.pid)"
2059rm -f ns4/named.pid
2060
2061#
2062# ns4 has now shutdown. wait until t=14 when badds.example's NTA
2063# (lifetime=10s) would have expired, and then restart ns4.
2064#
2065echo_i "waiting till 14s have passed since NTAs were added before restarting ns4"
2066# shellcheck disable=SC2016
2067$PERL -e 'my $delay = '"$start"' + 14 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
2068
2069if
2070    $PERL "$SYSTEMTESTTOP/start.pl" --noclean --restart --port "$PORT" dnssec ns4
2071then
2072    echo_i "restarted server ns4"
2073else
2074    echo_i "could not restart server ns4"
2075    exit 1
2076fi
2077
2078echo_i "sleeping for an additional 4 seconds for ns4 to fully startup"
2079sleep 4
2080
2081#
2082# ns4 should be back up now. The NTA for bogus.example should still be
2083# valid, whereas badds.example should not have been added during named
2084# startup (as it had already expired), the fact that it's ignored should
2085# be logged.
2086#
2087rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.3
2088lines=$(wc -l < rndc.out.ns4.test$n.3)
2089[ "$lines" -eq 1 ] || ret=1
2090grep "bogus.example/_default: expiry" rndc.out.ns4.test$n.3 > /dev/null || ret=1
2091dig_with_opts b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.4 || ret=1
2092grep "status: SERVFAIL" dig.out.ns4.test$n.4 > /dev/null && ret=1
2093grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 > /dev/null && ret=1
2094dig_with_opts a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.5 || ret=1
2095grep "status: SERVFAIL" dig.out.ns4.test$n.5 > /dev/null || ret=1
2096grep "ignoring expired NTA at badds.example" ns4/named.run > /dev/null || ret=1
2097
2098# cleanup
2099rndccmd 10.53.0.4 nta -remove bogus.example > rndc.out.ns4.test$n.6
2100
2101if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: restoring NTA failed"; fi
2102status=$((status+ret))
2103ret=0
2104
2105#
2106# check "regular" attribute in NTA file works as expected at named
2107# startup.
2108#
2109n=$((n+1))
2110echo_i "testing loading regular attribute from NTA file ($n)"
2111rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1 2>/dev/null
2112lines=$(wc -l < rndc.out.ns4.test$n.1)
2113[ "$lines" -eq 0 ] || ret=1
2114# initially, secure.example. validates with AD=1
2115dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
2116grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null && ret=1
2117grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 > /dev/null || ret=1
2118
2119echo_i "killing ns4 with SIGTERM"
2120$KILL -TERM "$(cat ns4/named.pid)"
2121rm -f ns4/named.pid
2122
2123echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown"
2124sleep 4
2125
2126#
2127# ns4 has now shutdown. add NTA for secure.example. directly into the
2128# _default.nta file with the regular attribute and some future timestamp.
2129#
2130future="$(($(date +%Y)+20))0101010000"
2131echo "secure.example. regular $future" > ns4/_default.nta
2132# shellcheck disable=SC2016
2133start=$($PERL -e 'print time()."\n";')
2134
2135if
2136    $PERL "$SYSTEMTESTTOP/start.pl" --noclean --restart --port "$PORT" dnssec ns4
2137then
2138    echo_i "restarted server ns4"
2139else
2140    echo_i "could not restart server ns4"
2141    exit 1
2142fi
2143
2144# nta-recheck is configured as 9s, so at t=12 the NTAs for
2145# secure.example. should be lifted as it is not a forced NTA.
2146echo_i "waiting till 12s have passed after ns4 was restarted"
2147# shellcheck disable=SC2016
2148$PERL -e 'my $delay = '"$start"' + 12 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
2149
2150# secure.example. should now return an AD=1 answer (still validates) as
2151# the NTA has been lifted.
2152dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1
2153grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1
2154grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null || ret=1
2155
2156# cleanup
2157rndccmd 10.53.0.4 nta -remove secure.example > rndc.out.ns4.test$n.4 2>/dev/null
2158
2159if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: loading regular NTAs failed"; fi
2160status=$((status+ret))
2161ret=0
2162
2163#
2164# check "forced" attribute in NTA file works as expected at named
2165# startup.
2166#
2167n=$((n+1))
2168echo_i "testing loading forced attribute from NTA file ($n)"
2169rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1 2>/dev/null
2170lines=$(wc -l < rndc.out.ns4.test$n.1)
2171[ "$lines" -eq 0 ] || ret=1
2172# initially, secure.example. validates with AD=1
2173dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1
2174grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null && ret=1
2175grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 > /dev/null || ret=1
2176
2177echo_i "killing ns4 with SIGTERM"
2178$KILL -TERM "$(cat ns4/named.pid)"
2179rm -f named.pid
2180
2181echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown"
2182sleep 4
2183
2184#
2185# ns4 has now shutdown. add NTA for secure.example. directly into the
2186# _default.nta file with the forced attribute and some future timestamp.
2187#
2188echo "secure.example. forced $future" > ns4/_default.nta
2189start=$($PERL -e 'print time()."\n";')
2190
2191if
2192    $PERL "$SYSTEMTESTTOP/start.pl" --noclean --restart --port "$PORT" dnssec ns4
2193then
2194    echo_i "restarted server ns4"
2195else
2196    echo_i "could not restart server ns4"
2197    exit 1
2198fi
2199
2200# nta-recheck is configured as 9s, but even at t=12 the NTAs for
2201# secure.example. should not be lifted as it is a forced NTA.
2202echo_i "waiting till 12s have passed after ns4 was restarted"
2203# shellcheck disable=SC2016
2204$PERL -e 'my $delay = '"$start"' + 12 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
2205
2206# secure.example. should now return an AD=0 answer (non-authenticated)
2207# as the NTA is still there.
2208dig_with_opts a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1
2209grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1
2210grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null && ret=1
2211
2212# cleanup
2213rndccmd 10.53.0.4 nta -remove secure.example > rndc.out.ns4.test$n.4 2>/dev/null
2214
2215if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: loading forced NTAs failed"; fi
2216status=$((status+ret))
2217ret=0
2218
2219#
2220# check that NTA lifetime read from file is clamped to 1 week.
2221#
2222n=$((n+1))
2223echo_i "testing loading out of bounds lifetime from NTA file ($n)"
2224
2225echo_i "killing ns4 with SIGTERM"
2226$KILL -TERM "$(cat ns4/named.pid)"
2227rm -f ns4/named.pid
2228
2229echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown"
2230sleep 4
2231
2232#
2233# ns4 has now shutdown. add NTA for secure.example. directly into the
2234# _default.nta file with a lifetime well into the future.
2235#
2236echo "secure.example. forced $future" > ns4/_default.nta
2237added=$($PERL -e 'print time()."\n";')
2238
2239if
2240    $PERL "$SYSTEMTESTTOP/start.pl" --noclean --restart --port "$PORT" dnssec ns4
2241then
2242    echo_i "restarted server ns4"
2243else
2244    echo_i "could not restart server ns4"
2245    exit 1
2246fi
2247
2248echo_i "sleeping for an additional 4 seconds for ns4 to fully startup"
2249sleep 4
2250
2251# dump the NTA to a file (omit validate-except entries)
2252echo_i "testing 'rndc nta'"
2253rndccmd 10.53.0.4 nta -d > rndc.out.ns4.test$n.1 2>/dev/null
2254# "corp" is configured as a validate-except domain and thus should be
2255# omitted. only "secure.example" should be in the dump at this point.
2256lines=$(wc -l < rndc.out.ns4.test$n.1)
2257[ "$lines" -eq 1 ] || ret=1
2258grep 'secure.example' rndc.out.ns4.test$n.1 > /dev/null || ret=1
2259ts=$(awk '{print $3" "$4}' < rndc.out.ns4.test$n.1)
2260# rndc nta outputs localtime, so append the timezone
2261ts_with_zone="$ts $(date +%z)"
2262echo "ts=$ts" > rndc.out.ns4.test$n.2
2263echo "ts_with_zone=$ts_with_zone" >> rndc.out.ns4.test$n.2
2264echo "added=$added" >> rndc.out.ns4.test$n.2
2265if $PERL -e 'use Time::Piece; use Time::Seconds;' 2>/dev/null
2266then
2267    # ntadiff.pl computes $ts_with_zone - ($added + 1week)
2268    d=$($PERL ./ntadiff.pl "$ts_with_zone" "$added")
2269    echo "d=$d" >> rndc.out.ns4.test$n.2
2270    # diff from $added(now) + 1week to the clamped NTA lifetime should be
2271    # less than a few seconds (handle daylight saving changes by adding 3600).
2272    [ "$d" -lt 3610 ] || ret=1
2273else
2274    echo_i "skipped ntadiff test; install PERL module Time::Piece"
2275fi
2276
2277# cleanup
2278rndccmd 10.53.0.4 nta -remove secure.example > rndc.out.ns4.test$n.3 2>/dev/null
2279
2280n=$((n+1))
2281if [ "$ret" -ne 0 ]; then echo_i "failed - NTA lifetime clamping failed"; fi
2282status=$((status+ret))
2283
2284echo_i "checking that NTAs work with 'forward only;' to a validating resolver ($n)"
2285ret=0
2286# Sanity check behavior without an NTA in place.
2287dig_with_opts @10.53.0.9 badds.example. SOA > dig.out.ns9.test$n.1 || ret=1
2288grep "SERVFAIL" dig.out.ns9.test$n.1 > /dev/null || ret=1
2289grep "ANSWER: 0" dig.out.ns9.test$n.1 > /dev/null || ret=1
2290grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.1 > /dev/null && ret=1
2291# Add an NTA, expecting that to cause resolution to succeed.
2292rndccmd 10.53.0.9 nta badds.example > rndc.out.ns9.test$n.1 2>&1 || ret=1
2293dig_with_opts @10.53.0.9 badds.example. SOA > dig.out.ns9.test$n.2 || ret=1
2294grep "NOERROR" dig.out.ns9.test$n.2 > /dev/null || ret=1
2295grep "ANSWER: 2" dig.out.ns9.test$n.2 > /dev/null || ret=1
2296grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.2 > /dev/null && ret=1
2297# Remove the NTA, expecting that to cause resolution to fail again.
2298rndccmd 10.53.0.9 nta -remove badds.example > rndc.out.ns9.test$n.2 2>&1 || ret=1
2299dig_with_opts @10.53.0.9 badds.example. SOA > dig.out.ns9.test$n.3 || ret=1
2300grep "SERVFAIL" dig.out.ns9.test$n.3 > /dev/null || ret=1
2301grep "ANSWER: 0" dig.out.ns9.test$n.3 > /dev/null || ret=1
2302grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.3 > /dev/null && ret=1
2303if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
2304status=$((status+ret))
2305
2306echo_i "completed NTA tests"
2307
2308# Run a minimal update test if possible.  This is really just
2309# a regression test for RT #2399; more tests should be added.
2310
2311if $PERL -e 'use Net::DNS;' 2>/dev/null
2312then
2313    echo_i "running DNSSEC update test"
2314    ret=0
2315    output=$($PERL dnssec_update_test.pl -s 10.53.0.3 -p "$PORT" dynamic.example.)
2316    test "$?" -eq 0 || ret=1
2317    echo "$output" | cat_i
2318    [ $ret -eq 1 ] && status=1
2319else
2320    echo_i "The DNSSEC update test requires the Net::DNS library." >&2
2321fi
2322
2323n=$((n+1))
2324echo_i "checking managed key maintenance has not started yet ($n)"
2325ret=0
2326[ -f "ns4/managed-keys.bind.jnl" ] && ret=1
2327n=$((n+1))
2328test "$ret" -eq 0 || echo_i "failed"
2329status=$((status+ret))
2330
2331# Reconfigure caching server to use "dnssec-validation auto", and repeat
2332# some of the DNSSEC validation tests to ensure that it works correctly.
2333echo_i "switching to automatic root key configuration"
2334copy_setports ns4/named2.conf.in ns4/named.conf
2335rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
2336sleep 5
2337
2338echo_i "checking managed key maintenance timer has now started ($n)"
2339ret=0
2340[ -f "ns4/managed-keys.bind.jnl" ] || ret=1
2341n=$((n+1))
2342test "$ret" -eq 0 || echo_i "failed"
2343status=$((status+ret))
2344
2345echo_i "checking positive validation NSEC ($n)"
2346ret=0
2347dig_with_opts +noauth a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
2348dig_with_opts +noauth a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
2349digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
2350grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
2351n=$((n+1))
2352test "$ret" -eq 0 || echo_i "failed"
2353status=$((status+ret))
2354
2355echo_i "checking positive validation NSEC3 ($n)"
2356ret=0
2357dig_with_opts +noauth a.nsec3.example. \
2358	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
2359dig_with_opts +noauth a.nsec3.example. \
2360	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
2361digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
2362grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
2363n=$((n+1))
2364test "$ret" -eq 0 || echo_i "failed"
2365status=$((status+ret))
2366
2367echo_i "checking positive validation OPTOUT ($n)"
2368ret=0
2369dig_with_opts +noauth a.optout.example. \
2370	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
2371dig_with_opts +noauth a.optout.example. \
2372	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
2373digcomp dig.out.ns3.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 negative validation ($n)"
2380ret=0
2381dig_with_opts +noauth q.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
2382dig_with_opts +noauth q.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
2383digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
2384grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
2385grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
2386n=$((n+1))
2387test "$ret" -eq 0 || echo_i "failed"
2388status=$((status+ret))
2389
2390echo_i "checking that root DS queries validate ($n)"
2391ret=0
2392dig_with_opts +noauth . @10.53.0.1 ds > dig.out.ns1.test$n || ret=1
2393dig_with_opts +noauth . @10.53.0.4 ds > dig.out.ns4.test$n || ret=1
2394digcomp dig.out.ns1.test$n dig.out.ns4.test$n || ret=1
2395grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
2396grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2397n=$((n+1))
2398test "$ret" -eq 0 || echo_i "failed"
2399status=$((status+ret))
2400
2401echo_i "checking that DS at a RFC 1918 empty zone lookup succeeds ($n)"
2402ret=0
2403dig_with_opts +noauth 10.in-addr.arpa ds @10.53.0.2 >dig.out.ns2.test$n || ret=1
2404dig_with_opts +noauth 10.in-addr.arpa ds @10.53.0.4 >dig.out.ns6.test$n || ret=1
2405digcomp dig.out.ns2.test$n dig.out.ns6.test$n || ret=1
2406grep "status: NOERROR" dig.out.ns6.test$n > /dev/null || ret=1
2407n=$((n+1))
2408test "$ret" -eq 0 || echo_i "failed"
2409status=$((status+ret))
2410
2411echo_i "checking expired signatures remain with "'"allow-update { none; };"'" and no keys available ($n)"
2412ret=0
2413dig_with_opts +noauth expired.example. +dnssec @10.53.0.3 soa > dig.out.ns3.test$n || ret=1
2414grep "RRSIG.SOA" dig.out.ns3.test$n > /dev/null || ret=1
2415n=$((n+1))
2416test "$ret" -eq 0 || echo_i "failed"
2417
2418status=$((status+ret))
2419echo_i "checking expired signatures do not validate ($n)"
2420ret=0
2421dig_with_opts +noauth expired.example. +dnssec @10.53.0.4 soa > dig.out.ns4.test$n || ret=1
2422grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
2423grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
2424grep "expired.example/.*: RRSIG has expired" ns4/named.run > /dev/null || ret=1
2425n=$((n+1))
2426test "$ret" -eq 0 || echo_i "failed"
2427status=$((status+ret))
2428
2429echo_i "checking that the NSEC3 record for the apex is properly signed when a DNSKEY is added via UPDATE ($n)"
2430ret=0
2431(
2432cd ns3 || exit 1
2433kskname=$($KEYGEN -q -3 -a RSASHA1 -fk update-nsec3.example)
2434(
2435echo zone update-nsec3.example
2436echo server 10.53.0.3 "$PORT"
2437grep DNSKEY "${kskname}.key" | sed -e 's/^/update add /' -e 's/IN/300 IN/'
2438echo send
2439) | $NSUPDATE
2440)
2441dig_with_opts +dnssec a update-nsec3.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2442grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2443grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
2444grep "NSEC3 .* TYPE65534" dig.out.ns4.test$n > /dev/null || ret=1
2445n=$((n+1))
2446test "$ret" -eq 0 || echo_i "failed"
2447status=$((status+ret))
2448
2449echo_i "checking that the NSEC record is properly generated when DNSKEY are added via auto-dnssec ($n)"
2450ret=0
2451dig_with_opts +dnssec a auto-nsec.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2452grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2453grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
2454grep "IN.NSEC[^3].* DNSKEY" dig.out.ns4.test$n > /dev/null || ret=1
2455n=$((n+1))
2456test "$ret" -eq 0 || echo_i "failed"
2457status=$((status+ret))
2458
2459echo_i "checking that the NSEC3 record is properly generated when DNSKEY are added via auto-dnssec ($n)"
2460ret=0
2461dig_with_opts +dnssec a auto-nsec3.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2462grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2463grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
2464grep "IN.NSEC3 .* DNSKEY" dig.out.ns4.test$n > /dev/null || ret=1
2465n=$((n+1))
2466test "$ret" -eq 0 || echo_i "failed"
2467status=$((status+ret))
2468
2469echo_i "checking that signing records have been marked as complete ($n)"
2470ret=0
2471checkprivate dynamic.example 10.53.0.3 || ret=1
2472checkprivate update-nsec3.example 10.53.0.3 || ret=1
2473checkprivate auto-nsec3.example 10.53.0.3 || ret=1
2474checkprivate expiring.example 10.53.0.3 || ret=1
2475checkprivate auto-nsec.example 10.53.0.3 || ret=1
2476n=$((n+1))
2477test "$ret" -eq 0 || echo_i "failed"
2478status=$((status+ret))
2479
2480echo_i "check that 'rndc signing' without arguments is handled ($n)"
2481ret=0
2482rndccmd 10.53.0.3 signing > /dev/null 2>&1 && ret=1
2483rndccmd 10.53.0.3 status > /dev/null || ret=1
2484n=$((n+1))
2485test "$ret" -eq 0 || echo_i "failed"
2486status=$((status+ret))
2487
2488echo_i "check that 'rndc signing -list' without zone is handled ($n)"
2489ret=0
2490rndccmd 10.53.0.3 signing -list > /dev/null 2>&1 && ret=1
2491rndccmd 10.53.0.3 status > /dev/null || ret=1
2492n=$((n+1))
2493test "$ret" -eq 0 || echo_i "failed"
2494status=$((status+ret))
2495
2496echo_i "check that 'rndc signing -clear' without additional arguments is handled ($n)"
2497ret=0
2498rndccmd 10.53.0.3 signing -clear > /dev/null 2>&1 && ret=1
2499rndccmd 10.53.0.3 status > /dev/null || ret=1
2500n=$((n+1))
2501test "$ret" -eq 0 || echo_i "failed"
2502status=$((status+ret))
2503
2504echo_i "check that 'rndc signing -clear all' without zone is handled ($n)"
2505ret=0
2506rndccmd 10.53.0.3 signing -clear all > /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 -nsec3param' without additional arguments is handled ($n)"
2513ret=0
2514rndccmd 10.53.0.3 signing -nsec3param > /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 -nsec3param none' without zone is handled ($n)"
2521ret=0
2522rndccmd 10.53.0.3 signing -nsec3param none > /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 -nsec3param 1' without additional arguments is handled ($n)"
2529ret=0
2530rndccmd 10.53.0.3 signing -nsec3param 1 > /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 1 0' without additional arguments is handled ($n)"
2537ret=0
2538rndccmd 10.53.0.3 signing -nsec3param 1 0 > /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 1 0 0' without additional arguments is handled ($n)"
2545ret=0
2546rndccmd 10.53.0.3 signing -nsec3param 1 0 0 > /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 0 0 -' without zone is handled ($n)"
2553ret=0
2554rndccmd 10.53.0.3 signing -nsec3param 1 0 0 - > /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' works with salt ($n)"
2561ret=0
2562rndccmd 10.53.0.3 signing -nsec3param 1 0 0 ffff inline.example > /dev/null 2>&1 || ret=1
2563rndccmd 10.53.0.3 status > /dev/null || ret=1
2564for i in 1 2 3 4 5 6 7 8 9 10 ; do
2565        salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
2566	if [ "$salt" = "FFFF" ]; then
2567		break;
2568	fi
2569	echo_i "sleeping ...."
2570	sleep 1
2571done;
2572[ "$salt" = "FFFF" ] || ret=1
2573n=$((n+1))
2574test "$ret" -eq 0 || echo_i "failed"
2575status=$((status+ret))
2576
2577echo_i "check that 'rndc signing -nsec3param' works without salt ($n)"
2578ret=0
2579rndccmd 10.53.0.3 signing -nsec3param 1 0 0 - inline.example > /dev/null 2>&1 || ret=1
2580rndccmd 10.53.0.3 status > /dev/null || ret=1
2581for i in 1 2 3 4 5 6 7 8 9 10 ; do
2582	salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
2583	if [ "$salt" = "-" ]; then
2584		break;
2585	fi
2586	echo_i "sleeping ...."
2587	sleep 1
2588done;
2589[ "$salt" = "-" ] || ret=1
2590n=$((n+1))
2591test "$ret" -eq 0 || echo_i "failed"
2592status=$((status+ret))
2593
2594echo_i "check that 'rndc signing -nsec3param' works with 'auto' as salt ($n)"
2595ret=0
2596rndccmd 10.53.0.3 signing -nsec3param 1 0 0 auto inline.example > /dev/null 2>&1 || ret=1
2597rndccmd 10.53.0.3 status > /dev/null || ret=1
2598for i in 1 2 3 4 5 6 7 8 9 10 ; do
2599	salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
2600	[ -n "$salt" ] && [ "$salt" != "-" ] && break
2601	echo_i "sleeping ...."
2602	sleep 1
2603done;
2604[ "$salt" != "-" ] || ret=1
2605[ "${#salt}" -eq 16 ] || ret=1
2606n=$((n+1))
2607test "$ret" -eq 0 || echo_i "failed"
2608status=$((status+ret))
2609
2610echo_i "check that 'rndc signing -nsec3param' with 'auto' as salt again generates a different salt ($n)"
2611ret=0
2612oldsalt=$salt
2613rndccmd 10.53.0.3 signing -nsec3param 1 0 0 auto inline.example > /dev/null 2>&1 || ret=1
2614rndccmd 10.53.0.3 status > /dev/null || ret=1
2615for i in 1 2 3 4 5 6 7 8 9 10 ; do
2616	salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
2617	[ -n "$salt" ] && [ "$salt" != "$oldsalt" ] && break
2618	echo_i "sleeping ...."
2619	sleep 1
2620done;
2621[ "$salt" != "$oldsalt" ] || ret=1
2622[ "${#salt}" -eq 16 ] || ret=1
2623n=$((n+1))
2624test "$ret" -eq 0 || echo_i "failed"
2625status=$((status+ret))
2626
2627echo_i "check rndc signing -list output ($n)"
2628ret=0
2629{ rndccmd 10.53.0.3 signing -list dynamic.example > signing.out; } 2>&1
2630grep -q "No signing records found" signing.out || {
2631        ret=1
2632        sed 's/^/ns3 /' signing.out | cat_i
2633}
2634{ rndccmd 10.53.0.3 signing -list update-nsec3.example > signing.out; } 2>&1
2635grep -q "Done signing with key .*/NSEC3RSASHA1" signing.out || {
2636        ret=1
2637        sed 's/^/ns3 /' signing.out | cat_i
2638}
2639n=$((n+1))
2640test "$ret" -eq 0 || echo_i "failed"
2641status=$((status+ret))
2642
2643echo_i "clear signing records ($n)"
2644{ rndccmd 10.53.0.3 signing -clear all update-nsec3.example > /dev/null; } 2>&1 || ret=1
2645check_no_signing_record_found() {
2646  { rndccmd 10.53.0.3 signing -list update-nsec3.example > signing.out; } 2>&1
2647  grep -q "No signing records found" signing.out || {
2648    sed 's/^/ns3 /' signing.out | cat_i
2649    return 1
2650  }
2651  return 0
2652}
2653retry_quiet 5 check_no_signing_record_found || ret=1
2654n=$((n+1))
2655test "$ret" -eq 0 || echo_i "failed"
2656status=$((status+ret))
2657
2658echo_i "checking that a insecure zone beneath a cname resolves ($n)"
2659ret=0
2660dig_with_opts soa insecure.below-cname.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2661grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2662grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
2663n=$((n+1))
2664test "$ret" -eq 0 || echo_i "failed"
2665status=$((status+ret))
2666
2667echo_i "checking that a secure zone beneath a cname resolves ($n)"
2668ret=0
2669dig_with_opts soa secure.below-cname.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2670grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2671grep "ANSWER: 2," dig.out.ns4.test$n > /dev/null || ret=1
2672grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
2673n=$((n+1))
2674test "$ret" -eq 0 || echo_i "failed"
2675status=$((status+ret))
2676
2677my_dig() {
2678    "$DIG" +noadd +nosea +nostat +noquest +nocomm +nocmd -p "$PORT" @10.53.0.4 "$@"
2679}
2680
2681echo_i "checking DNSKEY query with no data still gets put in cache ($n)"
2682ret=0
2683firstVal=$(my_dig insecure.example. dnskey| awk '$1 != ";;" { print $2 }')
2684sleep 1
2685secondVal=$(my_dig insecure.example. dnskey| awk '$1 != ";;" { print $2 }')
2686if [ "${firstVal:-0}" -eq "${secondVal:-0}" ]
2687then
2688	sleep 1
2689	thirdVal=$(my_dig insecure.example. dnskey|awk '$1 != ";;" { print $2 }')
2690	if [ "${firstVal:-0}" -eq "${thirdVal:-0}" ]
2691	then
2692		echo_i "cannot confirm query answer still in cache"
2693		ret=1
2694	fi
2695fi
2696n=$((n+1))
2697test "$ret" -eq 0 || echo_i "failed"
2698status=$((status+ret))
2699
2700echo_i "check that a split dnssec dnssec-signzone work ($n)"
2701ret=0
2702dig_with_opts soa split-dnssec.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2703grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2704grep "ANSWER: 2," dig.out.ns4.test$n > /dev/null || ret=1
2705grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
2706n=$((n+1))
2707test "$ret" -eq 0 || echo_i "failed"
2708status=$((status+ret))
2709
2710echo_i "check that a smart split dnssec dnssec-signzone work ($n)"
2711ret=0
2712dig_with_opts soa split-smart.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
2713grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
2714grep "ANSWER: 2," dig.out.ns4.test$n > /dev/null || ret=1
2715grep "flags:.* ad[ ;]" dig.out.ns4.test$n > /dev/null || ret=1
2716n=$((n+1))
2717test "$ret" -eq 0 || echo_i "failed"
2718status=$((status+ret))
2719
2720echo_i "check that NOTIFY is sent at the end of NSEC3 chain generation ($n)"
2721ret=0
2722(
2723echo zone nsec3chain-test
2724echo server 10.53.0.2 "$PORT"
2725echo update add nsec3chain-test. 0 nsec3param 1 0 1 123456
2726echo send
2727) | $NSUPDATE
2728for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
2729do
2730	dig_with_opts nsec3param nsec3chain-test @10.53.0.2 > dig.out.ns2.test$n || ret=1
2731	if grep "ANSWER: 3," dig.out.ns2.test$n >/dev/null
2732	then
2733		break;
2734	fi
2735	echo_i "sleeping ...."
2736	sleep 3
2737done
2738grep "ANSWER: 3," dig.out.ns2.test$n > /dev/null || ret=1
2739if [ "$ret" -ne 0 ]; then echo_i "nsec3 chain generation not complete"; fi
2740dig_with_opts +noauth +nodnssec soa nsec3chain-test @10.53.0.2 > dig.out.ns2.test$n || ret=1
2741s2=$(awk '$4 == "SOA" { print $7}' dig.out.ns2.test$n)
2742for i in 1 2 3 4 5 6 7 8 9 10
2743do
2744	dig_with_opts +noauth +nodnssec soa nsec3chain-test @10.53.0.3 > dig.out.ns3.test$n || ret=1
2745	s3=$(awk '$4 == "SOA" { print $7}' dig.out.ns3.test$n)
2746	test "$s2" = "$s3" && break
2747	sleep 1
2748done
2749digcomp dig.out.ns2.test$n dig.out.ns3.test$n || ret=1
2750n=$((n+1))
2751test "$ret" -eq 0 || echo_i "failed"
2752status=$((status+ret))
2753
2754echo_i "check dnssec-dsfromkey from stdin ($n)"
2755ret=0
2756dig_with_opts dnskey algroll. @10.53.0.2 | \
2757        $DSFROMKEY -f - algroll. > dig.out.ns2.test$n || ret=1
2758NF=$(awk '{print NF}' dig.out.ns2.test$n | sort -u)
2759[ "${NF}" = 7 ] || ret=1
2760# make canonical
2761awk '{
2762	for (i=1;i<7;i++) printf("%s ", $i);
2763	for (i=7;i<=NF;i++) printf("%s", $i);
2764	printf("\n");
2765}' < dig.out.ns2.test$n > canonical1.$n || ret=1
2766awk '{
2767	for (i=1;i<7;i++) printf("%s ", $i);
2768	for (i=7;i<=NF;i++) printf("%s", $i);
2769	printf("\n");
2770}' < ns1/dsset-algroll$TP > canonical2.$n || ret=1
2771$DIFF -b canonical1.$n canonical2.$n > /dev/null 2>&1 || ret=1
2772n=$((n+1))
2773test "$ret" -eq 0 || echo_i "failed"
2774status=$((status+ret))
2775
2776# Intentionally strip ".key" from keyfile name to ensure the error message
2777# includes it anyway to avoid confusion (RT #21731)
2778echo_i "check dnssec-dsfromkey error message when keyfile is not found ($n)"
2779ret=0
2780key=$($KEYGEN -a RSASHA1 -q example.) || ret=1
2781mv "$key.key" "$key"
2782$DSFROMKEY "$key" > dsfromkey.out.$n 2>&1 && ret=1
2783grep "$key.key: file not found" dsfromkey.out.$n > /dev/null || ret=1
2784n=$((n+1))
2785test "$ret" -eq 0 || echo_i "failed"
2786status=$((status+ret))
2787
2788echo_i "testing soon-to-expire RRSIGs without a replacement private key ($n)"
2789ret=0
2790dig_with_answeropts +nottlid expiring.example ns @10.53.0.3 | grep RRSIG > dig.out.ns3.test$n 2>&1
2791# there must be a signature here
2792[ -s dig.out.ns3.test$n ] || ret=1
2793n=$((n+1))
2794test "$ret" -eq 0 || echo_i "failed"
2795status=$((status+ret))
2796
2797echo_i "testing new records are signed with 'no-resign' ($n)"
2798ret=0
2799(
2800echo zone nosign.example
2801echo server 10.53.0.3 "$PORT"
2802echo update add new.nosign.example 300 in txt "hi there"
2803echo send
2804) | $NSUPDATE
2805sleep 1
2806dig_with_answeropts +nottlid txt new.nosign.example @10.53.0.3 \
2807        > dig.out.ns3.test$n 2>&1
2808grep RRSIG dig.out.ns3.test$n > /dev/null 2>&1 || ret=1
2809n=$((n+1))
2810test "$ret" -eq 0 || echo_i "failed"
2811status=$((status+ret))
2812
2813echo_i "testing expiring records aren't resigned with 'no-resign' ($n)"
2814ret=0
2815dig_with_answeropts +nottlid nosign.example ns @10.53.0.3 | \
2816        grep RRSIG | sed 's/[ 	][ 	]*/ /g' > dig.out.ns3.test$n 2>&1
2817# the NS RRSIG should not be changed
2818$DIFF nosign.before dig.out.ns3.test$n > /dev/null|| ret=1
2819n=$((n+1))
2820test "$ret" -eq 0 || echo_i "failed"
2821status=$((status+ret))
2822
2823echo_i "testing updates fail with no private key ($n)"
2824ret=0
2825rm -f ns3/Knosign.example.*.private
2826(
2827echo zone nosign.example
2828echo server 10.53.0.3 "$PORT"
2829echo update add fail.nosign.example 300 in txt "reject me"
2830echo send
2831) | $NSUPDATE > /dev/null 2>&1 && ret=1
2832dig_with_answeropts +nottlid fail.nosign.example txt @10.53.0.3 \
2833        > dig.out.ns3.test$n 2>&1
2834[ -s dig.out.ns3.test$n ] && ret=1
2835n=$((n+1))
2836test "$ret" -eq 0 || echo_i "failed"
2837status=$((status+ret))
2838
2839echo_i "testing legacy upper case signer name validation ($n)"
2840ret=0
2841$DIG +tcp +noadd +noauth +dnssec -p "$PORT" soa upper.example @10.53.0.4 \
2842        > dig.out.ns4.test$n 2>&1
2843grep "flags:.* ad;" dig.out.ns4.test$n > /dev/null || ret=1
2844grep "RRSIG.*SOA.* UPPER\\.EXAMPLE\\. " dig.out.ns4.test$n > /dev/null || ret=1
2845n=$((n+1))
2846test "$ret" -eq 0 || echo_i "failed"
2847status=$((status+ret))
2848
2849echo_i "testing that we lower case signer name ($n)"
2850ret=0
2851$DIG +tcp +noadd +noauth +dnssec -p "$PORT" soa LOWER.EXAMPLE @10.53.0.4 \
2852        > dig.out.ns4.test$n 2>&1
2853grep "flags:.* ad;" dig.out.ns4.test$n > /dev/null || ret=1
2854grep "RRSIG.*SOA.* lower\\.example\\. " dig.out.ns4.test$n > /dev/null || ret=1
2855n=$((n+1))
2856test "$ret" -eq 0 || echo_i "failed"
2857status=$((status+ret))
2858
2859echo_i "testing TTL is capped at RRSIG expiry time ($n)"
2860ret=0
2861rndccmd 10.53.0.3 freeze expiring.example 2>&1 | sed 's/^/ns3 /' | cat_i
2862(
2863cd ns3 || exit 1
2864for file in K*.moved; do
2865  mv "$file" "$(basename "$file" .moved)"
2866done
2867$SIGNER -S -N increment -e now+1mi -o expiring.example expiring.example.db > /dev/null
2868) || ret=1
2869rndc_reload ns3 10.53.0.3 expiring.example
2870
2871rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
2872dig_with_answeropts +cd expiring.example soa @10.53.0.4 > dig.out.ns4.1.$n
2873dig_with_answeropts expiring.example soa @10.53.0.4 > dig.out.ns4.2.$n
2874ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
2875ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
2876for ttl in ${ttls:-0}; do
2877    [ "${ttl}" -eq 300 ] || ret=1
2878done
2879for ttl in ${ttls2:-0}; do
2880    [ "${ttl}" -le 60 ] || ret=1
2881done
2882n=$((n+1))
2883test "$ret" -eq 0 || echo_i "failed"
2884status=$((status+ret))
2885
2886echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section (NS) ($n)"
2887ret=0
2888rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
2889sleep 1
2890dig_with_additionalopts +cd expiring.example ns @10.53.0.4 > dig.out.ns4.1.$n
2891dig_with_additionalopts expiring.example ns @10.53.0.4 > dig.out.ns4.2.$n
2892ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
2893ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
2894for ttl in ${ttls:-300}; do
2895    [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1
2896done
2897for ttl in ${ttls2:-0}; do
2898    [ "$ttl" -le 60 ] || ret=1
2899done
2900n=$((n+1))
2901test "$ret" -eq 0 || echo_i "failed"
2902status=$((status+ret))
2903
2904echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section (MX) ($n)"
2905ret=0
2906rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
2907sleep 1
2908dig_with_additionalopts +cd expiring.example mx @10.53.0.4 > dig.out.ns4.1.$n
2909dig_with_additionalopts expiring.example mx @10.53.0.4 > dig.out.ns4.2.$n
2910ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
2911ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
2912for ttl in ${ttls:-300}; do
2913    [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1
2914done
2915for ttl in ${ttls2:-0}; do
2916    [ "$ttl" -le 60 ] || ret=1
2917done
2918n=$((n+1))
2919test "$ret" -eq 0 || echo_i "failed"
2920status=$((status+ret))
2921
2922copy_setports ns4/named3.conf.in ns4/named.conf
2923rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
2924sleep 3
2925
2926echo_i "testing TTL of about to expire RRsets with dnssec-accept-expired yes; ($n)"
2927ret=0
2928rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
2929dig_with_answeropts +cd expiring.example soa @10.53.0.4 > dig.out.ns4.1.$n
2930dig_with_answeropts expiring.example soa @10.53.0.4 > dig.out.ns4.2.$n
2931ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
2932ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
2933for ttl in ${ttls:-0}; do
2934    [ "$ttl" -eq 300 ] || ret=1
2935done
2936for ttl in ${ttls2:-0}; do
2937    [ "$ttl" -eq 120 ] || ret=1
2938done
2939n=$((n+1))
2940test "$ret" -eq 0 || echo_i "failed"
2941status=$((status+ret))
2942
2943echo_i "testing TTL of expired RRsets with dnssec-accept-expired yes; ($n)"
2944ret=0
2945dig_with_answeropts +cd expired.example soa @10.53.0.4 > dig.out.ns4.1.$n
2946dig_with_answeropts expired.example soa @10.53.0.4 > dig.out.ns4.2.$n
2947ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
2948ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
2949for ttl in ${ttls:-0}; do
2950    [ "$ttl" -eq 300 ] || ret=1
2951done
2952for ttl in ${ttls2:-0}; do
2953    [ "$ttl" -eq 120 ] || ret=1
2954done
2955n=$((n+1))
2956test "$ret" -eq 0 || echo_i "failed"
2957status=$((status+ret))
2958
2959echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section with dnssec-accept-expired yes; ($n)"
2960ret=0
2961rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
2962dig_with_additionalopts +cd expiring.example mx @10.53.0.4 > dig.out.ns4.1.$n
2963dig_with_additionalopts expiring.example mx @10.53.0.4 > dig.out.ns4.2.$n
2964ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
2965ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
2966for ttl in ${ttls:-300}; do
2967    [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1
2968done
2969for ttl in ${ttls2:-0}; do
2970    [ "$ttl" -le 120 ] && [ "$ttl" -gt 60 ] || ret=1
2971done
2972n=$((n+1))
2973test "$ret" -eq 0 || echo_i "failed"
2974status=$((status+ret))
2975
2976echo_i "testing DNSKEY lookup via CNAME ($n)"
2977ret=0
2978dig_with_opts +noauth cnameandkey.secure.example. \
2979	@10.53.0.3 dnskey > dig.out.ns3.test$n || ret=1
2980dig_with_opts +noauth cnameandkey.secure.example. \
2981	@10.53.0.4 dnskey > dig.out.ns4.test$n || ret=1
2982digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
2983grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
2984grep "CNAME" dig.out.ns4.test$n > /dev/null || ret=1
2985n=$((n+1))
2986test "$ret" -eq 0 || echo_i "failed"
2987status=$((status+ret))
2988
2989echo_i "testing KEY lookup at CNAME (present) ($n)"
2990ret=0
2991dig_with_opts +noauth cnameandkey.secure.example. \
2992	@10.53.0.3 key > dig.out.ns3.test$n || ret=1
2993dig_with_opts +noauth cnameandkey.secure.example. \
2994	@10.53.0.4 key > dig.out.ns4.test$n || ret=1
2995digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
2996grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
2997grep "CNAME" dig.out.ns4.test$n > /dev/null && ret=1
2998n=$((n+1))
2999test "$ret" -eq 0 || echo_i "failed"
3000status=$((status+ret))
3001
3002echo_i "testing KEY lookup at CNAME (not present) ($n)"
3003ret=0
3004dig_with_opts +noauth cnamenokey.secure.example. \
3005	@10.53.0.3 key > dig.out.ns3.test$n || ret=1
3006dig_with_opts +noauth cnamenokey.secure.example. \
3007	@10.53.0.4 key > dig.out.ns4.test$n || ret=1
3008digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
3009grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3010grep "CNAME" dig.out.ns4.test$n > /dev/null && ret=1
3011n=$((n+1))
3012test "$ret" -eq 0 || echo_i "failed"
3013status=$((status+ret))
3014
3015echo_i "testing DNSKEY lookup via DNAME ($n)"
3016ret=0
3017dig_with_opts a.dnameandkey.secure.example. \
3018	@10.53.0.3 dnskey > dig.out.ns3.test$n || ret=1
3019dig_with_opts a.dnameandkey.secure.example. \
3020	@10.53.0.4 dnskey > dig.out.ns4.test$n || ret=1
3021digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
3022grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3023grep "CNAME" dig.out.ns4.test$n > /dev/null || ret=1
3024grep "DNAME" dig.out.ns4.test$n > /dev/null || ret=1
3025n=$((n+1))
3026test "$ret" -eq 0 || echo_i "failed"
3027status=$((status+ret))
3028
3029echo_i "testing KEY lookup via DNAME ($n)"
3030ret=0
3031dig_with_opts b.dnameandkey.secure.example. \
3032	@10.53.0.3 key > dig.out.ns3.test$n || ret=1
3033dig_with_opts b.dnameandkey.secure.example. \
3034	@10.53.0.4 key > dig.out.ns4.test$n || ret=1
3035digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
3036grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3037grep "DNAME" dig.out.ns4.test$n > /dev/null || ret=1
3038n=$((n+1))
3039test "$ret" -eq 0 || echo_i "failed"
3040status=$((status+ret))
3041
3042echo_i "check that named doesn't loop when all private keys are not available ($n)"
3043ret=0
3044lines=$(grep -c "reading private key file expiring.example" ns3/named.run || true)
3045test "${lines:-1000}" -lt 15 || ret=1
3046n=$((n+1))
3047test "$ret" -eq 0 || echo_i "failed"
3048status=$((status+ret))
3049
3050echo_i "check against against missing nearest provable proof ($n)"
3051dig_with_opts +norec b.c.d.optout-tld. \
3052	@10.53.0.6 ds > dig.out.ds.ns6.test$n || ret=1
3053nsec3=$(grep -c "IN.NSEC3" dig.out.ds.ns6.test$n || true)
3054[ "$nsec3" -eq 2 ] || ret=1
3055dig_with_opts +norec b.c.d.optout-tld. \
3056	@10.53.0.6 A > dig.out.ns6.test$n || ret=1
3057nsec3=$(grep -c "IN.NSEC3" dig.out.ns6.test$n || true)
3058[ "$nsec3" -eq 1 ] || ret=1
3059dig_with_opts optout-tld. \
3060	@10.53.0.4 SOA > dig.out.soa.ns4.test$n || ret=1
3061grep "flags:.*ad.*QUERY" dig.out.soa.ns4.test$n > /dev/null || ret=1
3062dig_with_opts b.c.d.optout-tld. \
3063	@10.53.0.4 A > dig.out.ns4.test$n || ret=1
3064grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
3065grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
3066n=$((n+1))
3067test "$ret" -eq 0 || echo_i "failed"
3068status=$((status+ret))
3069
3070echo_i "check that key id are logged when dumping the cache ($n)"
3071ret=0
3072rndc_dumpdb ns4
3073grep "; key id = " ns4/named_dump.db.test$n > /dev/null || ret=1
3074n=$((n+1))
3075test "$ret" -eq 0 || echo_i "failed"
3076status=$((status+ret))
3077
3078echo_i "check KEYDATA records are printed in human readable form in key zone ($n)"
3079# force the managed-keys zone to be written out
3080rndccmd 10.53.0.4 managed-keys sync 2>&1 | sed 's/^/ns4 /' | cat_i
3081for i in 1 2 3 4 5 6 7 8 9
3082do
3083    ret=0
3084    if test -f ns4/managed-keys.bind
3085    then
3086	grep KEYDATA ns4/managed-keys.bind > /dev/null &&
3087	grep "next refresh:" ns4/managed-keys.bind > /dev/null &&
3088	break
3089    fi
3090    ret=1
3091    sleep 1
3092done
3093n=$((n+1))
3094test "$ret" -eq 0 || echo_i "failed"
3095status=$((status+ret))
3096
3097echo_i "check dig's +nocrypto flag ($n)"
3098ret=0
3099dig_with_opts +norec +nocrypto DNSKEY . \
3100	@10.53.0.1 > dig.out.dnskey.ns1.test$n || ret=1
3101grep -E "256 [0-9]+ $DEFAULT_ALGORITHM_NUMBER \\[key id = [1-9][0-9]*]" dig.out.dnskey.ns1.test$n > /dev/null || ret=1
3102grep -E "RRSIG.* \\[omitted]" dig.out.dnskey.ns1.test$n > /dev/null || ret=1
3103dig_with_opts +norec +nocrypto DS example \
3104	@10.53.0.1 > dig.out.ds.ns1.test$n || ret=1
3105grep -E "DS.* [0-9]+ [12] \[omitted]" dig.out.ds.ns1.test$n > /dev/null || ret=1
3106n=$((n+1))
3107test "$ret" -eq 0 || echo_i "failed"
3108status=$((status+ret))
3109
3110echo_i "check simultaneous inactivation and publishing of dnskeys removes inactive signature ($n)"
3111ret=0
3112cnt=0
3113while :
3114do
3115dig_with_opts publish-inactive.example @10.53.0.3 dnskey > dig.out.ns3.test$n
3116keys=$(awk '$5 == 257 { print; }' dig.out.ns3.test$n | wc -l)
3117test "$keys" -gt 2 && break
3118cnt=$((cnt+1))
3119test "$cnt" -gt 120 && break
3120sleep 1
3121done
3122test "$keys" -gt 2 || ret=1
3123sigs=$(grep -c RRSIG dig.out.ns3.test$n || true)
3124n=$((n+1))
3125test "$sigs" -eq 2 || ret=1
3126if test "$ret" -ne 0 ; then echo_i "failed"; fi
3127status=$((status+ret))
3128
3129echo_i "check that increasing the sig-validity-interval resigning triggers re-signing ($n)"
3130ret=0
3131before=$($DIG axfr siginterval.example -p "$PORT" @10.53.0.3 | grep RRSIG.SOA)
3132cp ns3/siginterval2.conf ns3/siginterval.conf
3133rndccmd 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
3134i=10
3135while [ "$i" -ge 0 ]; do
3136after=$($DIG axfr siginterval.example -p "$PORT" @10.53.0.3 | grep RRSIG.SOA)
3137test "$before" != "$after" && break
3138sleep 1
3139i=$((i-1))
3140done
3141n=$((n+1))
3142if test "$before" = "$after" ; then echo_i "failed"; ret=1; fi
3143status=$((status+ret))
3144
3145if [ -x "$PYTHON" ]; then
3146    echo_i "check dnskey-sig-validity sets longer expiry for DNSKEY ($n)"
3147    ret=0
3148    rndccmd 10.53.0.3 sign siginterval.example 2>&1 | sed 's/^/ns3 /' | cat_i
3149    # convert expiry date to a comma-separated list of integers python can
3150    # use as input to date(). strip leading 0s in months and days so
3151    # python3 will recognize them as integers.
3152    $DIG +dnssec +short -p "$PORT" @10.53.0.3 soa siginterval.example > dig.out.soa.test$n
3153    soaexpire=$(awk '$1 ~ /SOA/ { print $5 }' dig.out.soa.test$n |
3154	       sed 's/\(....\)\(..\)\(..\).*/\1, \2, \3/' |
3155	       sed 's/ 0/ /g')
3156    $DIG +dnssec +short -p "$PORT" @10.53.0.3 dnskey siginterval.example > dig.out.dnskey.test$n
3157    dnskeyexpire=$(awk '$1 ~ /DNSKEY/ { print $5; exit 0 }' dig.out.dnskey.test$n |
3158		  sed 's/\(....\)\(..\)\(..\).*/\1, \2, \3/' |
3159		  sed 's/ 0/ /g')
3160    $PYTHON > python.out.$n <<EOF
3161from datetime import date;
3162ke=date($dnskeyexpire)
3163se=date($soaexpire)
3164print((ke-se).days);
3165EOF
3166    diff=$(cat python.out.$n)
3167    [ "$diff" -ge 55 ] || ret=1
3168    n=$((n+1))
3169    test "$ret" -eq 0 || echo_i "failed"
3170    status=$((status+ret))
3171fi
3172
3173copy_setports ns4/named4.conf.in ns4/named.conf
3174rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
3175sleep 3
3176
3177echo_i "check insecure delegation between static-stub zones ($n)"
3178ret=0
3179dig_with_opts ns insecure.secure.example \
3180	@10.53.0.4 > dig.out.ns4.1.test$n || ret=1
3181grep "SERVFAIL" dig.out.ns4.1.test$n > /dev/null && ret=1
3182dig_with_opts ns secure.example \
3183	@10.53.0.4 > dig.out.ns4.2.test$n || ret=1
3184grep "SERVFAIL" dig.out.ns4.2.test$n > /dev/null && ret=1
3185n=$((n+1))
3186test "$ret" -eq 0 || echo_i "failed"
3187status=$((status+ret))
3188
3189echo_i "check the acceptance of seconds as inception and expiration times ($n)"
3190ret=0
3191in="NSEC 8 0 86400 1390003200 1389394800 33655 . NYWjZYBV1b+h4j0yu/SmPOOylR8P4IXKDzHX3NwEmU1SUp27aJ91dP+i+UBcnPmBib0hck4DrFVvpflCEpCnVQd2DexcN0GX+3PM7XobxhtDlmnU X1L47zJlbdHNwTqHuPaMM6Xy9HGMXps7O5JVyfggVhTz2C+G5OVxBdb2rOo="
3192
3193exp="NSEC 8 0 86400 20140118000000 20140110230000 33655 . NYWjZYBV1b+h4j0yu/SmPOOylR8P4IXKDzHX3NwEmU1SUp27aJ91dP+i +UBcnPmBib0hck4DrFVvpflCEpCnVQd2DexcN0GX+3PM7XobxhtDlmnU X1L47zJlbdHNwTqHuPaMM6Xy9HGMXps7O5JVyfggVhTz2C+G5OVxBdb2 rOo="
3194
3195out=$(echo "IN RRSIG $in" | $RRCHECKER -p | sed 's/^IN.RRSIG.//')
3196[ "$out" = "$exp" ] || ret=1
3197n=$((n+1))
3198test "$ret" -eq 0 || echo_i "failed"
3199status=$((status+ret))
3200
3201echo_i "check the correct resigning time is reported in zonestatus ($n)"
3202ret=0
3203rndccmd 10.53.0.3 \
3204		zonestatus secure.example > rndc.out.ns3.test$n
3205# next resign node: secure.example/DNSKEY
3206qname=$(awk '/next resign node:/ { print $4 }' rndc.out.ns3.test$n | sed 's,/.*,,')
3207qtype=$(awk '/next resign node:/ { print $4 }' rndc.out.ns3.test$n | sed 's,.*/,,')
3208# next resign time: Thu, 24 Apr 2014 10:38:16 GMT
3209time=$(awk 'BEGIN { m["Jan"] = "01"; m["Feb"] = "02"; m["Mar"] = "03";
3210		   m["Apr"] = "04"; m["May"] = "05"; m["Jun"] = "06";
3211		   m["Jul"] = "07"; m["Aug"] = "08"; m["Sep"] = "09";
3212		   m["Oct"] = "10"; m["Nov"] = "11"; m["Dec"] = "12";}
3213	 /next resign time:/ { printf "%d%s%02d%s\n", $7, m[$6], $5, $8 }' rndc.out.ns3.test$n | sed 's/://g')
3214dig_with_opts +noall +answer "$qname" "$qtype" @10.53.0.3 > dig.out.test$n
3215expire=$(awk '$4 == "RRSIG" { print $9 }' dig.out.test$n)
3216inception=$(awk '$4 == "RRSIG" { print $10 }' dig.out.test$n)
3217$PERL -e 'exit(0) if ("'"$time"'" lt "'"$expire"'" && "'"$time"'" gt "'"$inception"'"); exit(1);' || ret=1
3218n=$((n+1))
3219test "$ret" -eq 0 || echo_i "failed"
3220status=$((status+ret))
3221
3222echo_i "check that split rrsigs are handled ($n)"
3223ret=0
3224dig_with_opts split-rrsig soa @10.53.0.7 > dig.out.test$n || ret=1
3225awk 'BEGIN { ok=0; } $4 == "SOA" { if ($7 > 1) ok=1; } END { if (!ok) exit(1); }' dig.out.test$n || ret=1
3226n=$((n+1))
3227test "$ret" -eq 0 || echo_i "failed"
3228status=$((status+ret))
3229
3230echo_i "check that 'dnssec-keygen -S' works for all supported algorithms ($n)"
3231ret=0
3232alg=1
3233until test $alg -eq 256
3234do
3235    zone="keygen-$alg."
3236    case $alg in
3237	2) # Diffie Helman
3238	    alg=$((alg+1))
3239	    continue;;
3240	157|160|161|162|163|164|165) # private - non standard
3241	    alg=$((alg+1))
3242	    continue;;
3243	1|5|7|8|10) # RSA algorithms
3244	    key1=$($KEYGEN -a "$alg" -b "1024" -n zone "$zone" 2> "keygen-$alg.err" || true)
3245	    ;;
3246	15|16)
3247	    key1=$($KEYGEN -a "$alg" -n zone "$zone" 2> "keygen-$alg.err" || true)
3248	    # Soft-fail	in case HSM doesn't support Edwards curves
3249	    if grep "not found" "keygen-$alg.err" > /dev/null && [ "$CRYPTO" = "pkcs11" ]; then
3250		echo_i "Algorithm $alg not supported by HSM: skipping"
3251		alg=$((alg+1))
3252		continue
3253	    fi
3254	    ;;
3255	*)
3256	    key1=$($KEYGEN -a "$alg" -n zone "$zone" 2> "keygen-$alg.err" || true)
3257    esac
3258    if grep "unsupported algorithm" "keygen-$alg.err" > /dev/null
3259    then
3260	alg=$((alg+1))
3261	continue
3262    fi
3263    if test -z "$key1"
3264    then
3265	echo_i "'$KEYGEN -a $alg': failed"
3266	cat "keygen-$alg.err"
3267	ret=1
3268	alg=$((alg+1))
3269	continue
3270    fi
3271    $SETTIME -I now+4d "$key1.private" > /dev/null
3272    key2=$($KEYGEN -v 10 -i 3d -S "$key1.private" 2> /dev/null)
3273    test -f "$key2.key" -a -f "$key2.private" || {
3274	ret=1
3275	echo_i "'dnssec-keygen -S' failed for algorithm: $alg"
3276    }
3277    alg=$((alg+1))
3278done
3279n=$((n+1))
3280test "$ret" -eq 0 || echo_i "failed"
3281status=$((status+ret))
3282
3283echo_i "check that CDS records are signed using KSK by dnssec-signzone ($n)"
3284ret=0
3285dig_with_opts +noall +answer @10.53.0.2 cds cds.secure > dig.out.test$n
3286lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3287test "$lines" -eq 2 || ret=1
3288n=$((n+1))
3289test "$ret" -eq 0 || echo_i "failed"
3290status=$((status+ret))
3291
3292echo_i "check that CDS records are not signed using ZSK by dnssec-signzone -x ($n)"
3293ret=0
3294dig_with_opts +noall +answer @10.53.0.2 cds cds-x.secure > dig.out.test$n
3295lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3296test "$lines" -eq 2 || ret=1
3297n=$((n+1))
3298test "$ret" -eq 0 || echo_i "failed"
3299status=$((status+ret))
3300
3301echo_i "checking that positive unknown NSEC3 hash algorithm does validate ($n)"
3302ret=0
3303dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example SOA > dig.out.ns3.test$n
3304dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 nsec3-unknown.example SOA > dig.out.ns4.test$n
3305grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3306grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
3307grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3308grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
3309n=$((n+1))
3310test "$ret" -eq 0 || echo_i "failed"
3311status=$((status+ret))
3312
3313echo_i "check that CDS records are signed using KSK by with dnssec-auto ($n)"
3314ret=0
3315dig_with_opts +noall +answer @10.53.0.2 cds cds-auto.secure > dig.out.test$n
3316lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3317test "$lines" -eq 2 || ret=1
3318n=$((n+1))
3319test "$ret" -eq 0 || echo_i "failed"
3320status=$((status+ret))
3321
3322echo_i "check that a lone non matching CDS record is rejected ($n)"
3323ret=0
3324(
3325echo zone cds-update.secure
3326echo server 10.53.0.2 "$PORT"
3327echo update delete cds-update.secure CDS
3328dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
3329grep "DNSKEY.257" | sed 's/DNSKEY.257/DNSKEY 258/' |
3330$DSFROMKEY -C -A -f - -T 1 cds-update.secure |
3331sed "s/^/update add /"
3332echo send
3333) | $NSUPDATE > nsupdate.out.test$n 2>&1 || true
3334grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
3335dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
3336lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
3337test "${lines:-10}" -eq 0 || ret=1
3338n=$((n+1))
3339test "$ret" -eq 0 || echo_i "failed"
3340status=$((status+ret))
3341
3342echo_i "check that a CDS deletion record is accepted ($n)"
3343ret=0
3344(
3345echo zone cds-update.secure
3346echo server 10.53.0.2 "$PORT"
3347echo update delete cds-update.secure CDS
3348echo update add cds-update.secure 0 CDS 0 0 0 00
3349echo send
3350) | $NSUPDATE > nsupdate.out.test$n 2>&1
3351dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
3352lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
3353test "${lines:-10}" -eq 1 || ret=1
3354lines=$(tr -d '\r' < dig.out.test$n | awk '$4 == "CDS" && $5 == "0" && $6 == "0" && $7 == "0" && $8 == "00" {print}' | wc -l)
3355test "$lines" -eq 1 || ret=1
3356n=$((n+1))
3357test "$ret" -eq 0 || echo_i "failed"
3358status=$((status+ret))
3359
3360echo_i "check that CDS records are signed using KSK when added by nsupdate ($n)"
3361ret=0
3362(
3363echo zone cds-update.secure
3364echo server 10.53.0.2 "$PORT"
3365echo update delete cds-update.secure CDS
3366echo send
3367dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
3368grep "DNSKEY.257" |
3369$DSFROMKEY -12 -C -f - -T 1 cds-update.secure |
3370sed "s/^/update add /"
3371echo send
3372) | $NSUPDATE
3373dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
3374lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3375test "$lines" -eq 2 || ret=1
3376lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
3377test "$lines" -eq 2 || ret=1
3378n=$((n+1))
3379test "$ret" -eq 0 || echo_i "failed"
3380status=$((status+ret))
3381
3382echo_i "check that CDS records are signed only using KSK when added by"
3383echo_ic "nsupdate when dnssec-dnskey-kskonly is yes ($n)"
3384ret=0
3385keyid=$(cat ns2/cds-kskonly.secure.id)
3386(
3387echo zone cds-kskonly.secure
3388echo server 10.53.0.2 "$PORT"
3389echo update delete cds-kskonly.secure CDS
3390echo send
3391dig_with_opts +noall +answer @10.53.0.2 dnskey cds-kskonly.secure |
3392grep "DNSKEY.257" |
3393$DSFROMKEY -12 -C -f - -T 1 cds-kskonly.secure |
3394sed "s/^/update add /"
3395echo send
3396) | $NSUPDATE
3397dig_with_opts +noall +answer @10.53.0.2 cds cds-kskonly.secure > dig.out.test$n
3398lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3399test "$lines" -eq 1 || ret=1
3400lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDS" && $11 == id {print}' dig.out.test$n | wc -l)
3401test "$lines" -eq 1 || ret=1
3402lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
3403test "$lines" -eq 2 || ret=1
3404n=$((n+1))
3405test "$ret" -eq 0 || echo_i "failed"
3406status=$((status+ret))
3407
3408echo_i "check that CDS deletion records are signed only using KSK when added by"
3409echo_ic "nsupdate when dnssec-dnskey-kskonly is yes ($n)"
3410ret=0
3411keyid=$(cat ns2/cds-kskonly.secure.id)
3412(
3413echo zone cds-kskonly.secure
3414echo server 10.53.0.2 "$PORT"
3415echo update delete cds-kskonly.secure CDS
3416echo update add cds-kskonly.secure 0 CDS 0 0 0 00
3417echo send
3418) | $NSUPDATE
3419dig_with_opts +noall +answer @10.53.0.2 cds cds-kskonly.secure > dig.out.test$n
3420lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3421test "$lines" -eq 1 || ret=1
3422lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDS" && $11 == id {print}' dig.out.test$n | wc -l)
3423test "$lines" -eq 1 || ret=1
3424lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
3425test "$lines" -eq 1 || ret=1
3426lines=$(tr -d '\r' < dig.out.test$n | awk '$4 == "CDS" && $5 == "0" && $6 == "0" && $7 == "0" && $8 == "00" {print}' | wc -l)
3427test "$lines" -eq 1 || ret=1
3428n=$((n+1))
3429test "$ret" -eq 0 || echo_i "failed"
3430status=$((status+ret))
3431
3432echo_i "checking that positive unknown NSEC3 hash algorithm with OPTOUT does validate ($n)"
3433ret=0
3434dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example SOA > dig.out.ns3.test$n
3435dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 optout-unknown.example SOA > dig.out.ns4.test$n
3436grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3437grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
3438grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3439grep "ANSWER: 1," dig.out.ns4.test$n > /dev/null || ret=1
3440n=$((n+1))
3441test "$ret" -eq 0 || echo_i "failed"
3442status=$((status+ret))
3443
3444echo_i "check that a non matching CDS record is accepted with a matching CDS record ($n)"
3445ret=0
3446(
3447echo zone cds-update.secure
3448echo server 10.53.0.2 "$PORT"
3449echo update delete cds-update.secure CDS
3450echo send
3451dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
3452grep "DNSKEY.257" |
3453$DSFROMKEY -12 -C -f - -T 1 cds-update.secure |
3454sed "s/^/update add /"
3455dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure |
3456grep "DNSKEY.257" | sed 's/DNSKEY.257/DNSKEY 258/' |
3457$DSFROMKEY -12 -C -A -f - -T 1 cds-update.secure |
3458sed "s/^/update add /"
3459echo send
3460) | $NSUPDATE
3461dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
3462lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l)
3463test "$lines" -eq 2 || ret=1
3464lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l)
3465test "$lines" -eq 4 || ret=1
3466n=$((n+1))
3467test "$ret" -eq 0 || echo_i "failed"
3468status=$((status+ret))
3469
3470echo_i "checking that negative unknown NSEC3 hash algorithm does not validate ($n)"
3471ret=0
3472dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example A > dig.out.ns3.test$n
3473dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 nsec3-unknown.example A > dig.out.ns4.test$n
3474grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3475grep "status: SERVFAIL," dig.out.ns4.test$n > /dev/null || ret=1
3476n=$((n+1))
3477test "$ret" -eq 0 || echo_i "failed"
3478status=$((status+ret))
3479
3480echo_i "check that CDNSKEY records are signed using KSK by dnssec-signzone ($n)"
3481ret=0
3482dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey.secure > dig.out.test$n
3483lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3484test "$lines" -eq 2 || ret=1
3485n=$((n+1))
3486test "$ret" -eq 0 || echo_i "failed"
3487status=$((status+ret))
3488
3489echo_i "check that CDNSKEY records are not signed using ZSK by dnssec-signzone -x ($n)"
3490ret=0
3491dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-x.secure > dig.out.test$n
3492lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3493test "$lines" -eq 2 || ret=1
3494n=$((n+1))
3495test "$ret" -eq 0 || echo_i "failed"
3496status=$((status+ret))
3497
3498echo_i "checking that negative unknown NSEC3 hash algorithm with OPTOUT does not validate ($n)"
3499ret=0
3500dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example A > dig.out.ns3.test$n
3501dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 optout-unknown.example A > dig.out.ns4.test$n
3502grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3503grep "status: SERVFAIL," dig.out.ns4.test$n > /dev/null || ret=1
3504n=$((n+1))
3505test "$ret" -eq 0 || echo_i "failed"
3506status=$((status+ret))
3507
3508echo_i "check that CDNSKEY records are signed using KSK by with dnssec-auto ($n)"
3509ret=0
3510dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-auto.secure > dig.out.test$n
3511lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3512test "$lines" -eq 2 || ret=1
3513n=$((n+1))
3514test "$ret" -eq 0 || echo_i "failed"
3515status=$((status+ret))
3516
3517echo_i "checking that unknown DNSKEY algorithm validates as insecure ($n)"
3518ret=0
3519dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unknown.example A > dig.out.ns3.test$n
3520dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unknown.example A > dig.out.ns4.test$n
3521grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3522grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
3523grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
3524n=$((n+1))
3525test "$ret" -eq 0 || echo_i "failed"
3526status=$((status+ret))
3527
3528echo_i "checking that unsupported DNSKEY algorithm validates as insecure ($n)"
3529ret=0
3530dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported.example A > dig.out.ns3.test$n
3531dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unsupported.example A > dig.out.ns4.test$n
3532grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3533grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
3534grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
3535n=$((n+1))
3536test "$ret" -eq 0 || echo_i "failed"
3537status=$((status+ret))
3538
3539echo_i "checking that unsupported DNSKEY algorithm is in DNSKEY RRset ($n)"
3540ret=0
3541dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported-2.example DNSKEY > dig.out.test$n
3542grep "status: NOERROR," dig.out.test$n > /dev/null || ret=1
3543grep "dnskey-unsupported-2\.example\..*IN.*DNSKEY.*257 3 255" dig.out.test$n > /dev/null || ret=1
3544n=$((n+1))
3545test "$ret" -eq 0 || echo_i "failed"
3546status=$((status+ret))
3547
3548# TODO: test case for GL #1689.
3549# If we allow the dnssec tools to use deprecated algorithms (such as RSAMD5)
3550# we could write a test that signs a zone with supported and unsupported
3551# algorithm, apply a fixed rrset order such that the unsupported algorithm
3552# precedes the supported one in the DNSKEY RRset, and verify the result still
3553# validates succesfully.
3554
3555echo_i "check that a lone non matching CDNSKEY record is rejected ($n)"
3556ret=0
3557(
3558echo zone cdnskey-update.secure
3559echo server 10.53.0.2 "$PORT"
3560echo update delete cdnskey-update.secure CDNSKEY
3561echo send
3562dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
3563sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 258/p'
3564echo send
3565) | $NSUPDATE > nsupdate.out.test$n 2>&1 || true
3566grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
3567dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
3568lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3569test "${lines:-10}" -eq 0 || ret=1
3570n=$((n+1))
3571test "$ret" -eq 0 || echo_i "failed"
3572status=$((status+ret))
3573
3574echo_i "check that a CDNSKEY deletion record is accepted ($n)"
3575ret=0
3576(
3577echo zone cdnskey-update.secure
3578echo server 10.53.0.2 "$PORT"
3579echo update delete cdnskey-update.secure CDNSKEY
3580echo update add cdnskey-update.secure 0 CDNSKEY 0 3 0 AA==
3581echo send
3582) | $NSUPDATE > nsupdate.out.test$n 2>&1
3583dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
3584lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3585test "${lines:-10}" -eq 1 || ret=1
3586lines=$(tr -d '\r' < dig.out.test$n | awk '$4 == "CDNSKEY" && $5 == "0" && $6 == "3" && $7 == "0" && $8 == "AA==" {print}' | wc -l)
3587test "${lines:-10}" -eq 1 || ret=1
3588n=$((n+1))
3589test "$ret" -eq 0 || echo_i "failed"
3590status=$((status+ret))
3591
3592echo_i "checking that unknown DNSKEY algorithm + unknown NSEC3 has algorithm validates as insecure ($n)"
3593ret=0
3594dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-nsec3-unknown.example A > dig.out.ns3.test$n
3595dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-nsec3-unknown.example A > dig.out.ns4.test$n
3596grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3597grep "status: NOERROR," dig.out.ns4.test$n > /dev/null || ret=1
3598grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
3599n=$((n+1))
3600test "$ret" -eq 0 || echo_i "failed"
3601status=$((status+ret))
3602
3603echo_i "check that CDNSKEY records are signed using KSK when added by nsupdate ($n)"
3604ret=0
3605(
3606echo zone cdnskey-update.secure
3607echo server 10.53.0.2 "$PORT"
3608echo update delete cdnskey-update.secure CDNSKEY
3609dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
3610sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p'
3611echo send
3612) | $NSUPDATE
3613dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
3614lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3615test "$lines" -eq 2 || ret=1
3616lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3617test "$lines" -eq 1 || ret=1
3618n=$((n+1))
3619test "$ret" -eq 0 || echo_i "failed"
3620status=$((status+ret))
3621
3622echo_i "check that CDNSKEY records are signed only using KSK when added by"
3623echo_ic "nsupdate when dnssec-dnskey-kskonly is yes ($n)"
3624ret=0
3625keyid=$(cat ns2/cdnskey-kskonly.secure.id)
3626(
3627echo zone cdnskey-kskonly.secure
3628echo server 10.53.0.2 "$PORT"
3629echo update delete cdnskey-kskonly.secure CDNSKEY
3630dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-kskonly.secure |
3631sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p'
3632echo send
3633) | $NSUPDATE
3634dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-kskonly.secure > dig.out.test$n
3635lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3636test "$lines" -eq 1 || ret=1
3637lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDNSKEY" && $11 == id {print}' dig.out.test$n | wc -l)
3638test "$lines" -eq 1 || ret=1
3639lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3640test "$lines" -eq 1 || ret=1
3641n=$((n+1))
3642test "$ret" -eq 0 || echo_i "failed"
3643status=$((status+ret))
3644
3645echo_i "check that CDNSKEY deletion records are signed only using KSK when added by"
3646echo_ic "nsupdate when dnssec-dnskey-kskonly is yes ($n)"
3647ret=0
3648keyid=$(cat ns2/cdnskey-kskonly.secure.id)
3649(
3650echo zone cdnskey-kskonly.secure
3651echo server 10.53.0.2 "$PORT"
3652echo update delete cdnskey-kskonly.secure CDNSKEY
3653echo update add cdnskey-kskonly.secure 0 CDNSKEY 0 3 0 AA==
3654echo send
3655) | $NSUPDATE
3656dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-kskonly.secure > dig.out.test$n
3657lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3658test "$lines" -eq 1 || ret=1
3659lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDNSKEY" && $11 == id {print}' dig.out.test$n | wc -l)
3660test "$lines" -eq 1 || ret=1
3661lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3662test "$lines" -eq 1 || ret=1
3663lines=$(tr -d '\r' < dig.out.test$n | awk '$4 == "CDNSKEY" && $5 == "0" && $6 == "3" && $7 == "0" && $8 == "AA==" {print}' | wc -l)
3664test "${lines:-10}" -eq 1 || ret=1
3665n=$((n+1))
3666test "$ret" -eq 0 || echo_i "failed"
3667status=$((status+ret))
3668
3669echo_i "checking initialization with a revoked managed key ($n)"
3670ret=0
3671copy_setports ns5/named2.conf.in ns5/named.conf
3672rndccmd 10.53.0.5 reconfig 2>&1 | sed 's/^/ns5 /' | cat_i
3673sleep 3
3674dig_with_opts +dnssec @10.53.0.5 SOA . > dig.out.ns5.test$n
3675grep "status: SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
3676n=$((n+1))
3677test "$ret" -eq 0 || echo_i "failed"
3678status=$((status+ret))
3679
3680echo_i "check that a non matching CDNSKEY record is accepted with a matching CDNSKEY record ($n)"
3681ret=0
3682(
3683echo zone cdnskey-update.secure
3684echo server 10.53.0.2 "$PORT"
3685echo update delete cdnskey-update.secure CDNSKEY
3686dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
3687sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p'
3688dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
3689sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 258/p'
3690echo send
3691) | $NSUPDATE
3692dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
3693lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3694test "$lines" -eq 2 || ret=1
3695lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l)
3696test "$lines" -eq 2 || ret=1
3697n=$((n+1))
3698test "$ret" -eq 0 || echo_i "failed"
3699status=$((status+ret))
3700
3701echo_i "check that RRSIGs are correctly removed from apex when RRset is removed  NSEC ($n)"
3702ret=0
3703# generate signed zone with MX and AAAA records at apex.
3704(
3705cd signer || exit 1
3706$KEYGEN -q -a RSASHA1 -3 -fK remove > /dev/null
3707$KEYGEN -q -a RSASHA1 -33 remove > /dev/null
3708echo > remove.db.signed
3709$SIGNER -S -o remove -D -f remove.db.signed remove.db.in > signer.out.1.$n
3710)
3711grep "RRSIG MX" signer/remove.db.signed > /dev/null || {
3712	ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.pre$n;
3713}
3714# re-generate signed zone without MX and AAAA records at apex.
3715(
3716cd signer || exit 1
3717$SIGNER -S -o remove -D -f remove.db.signed remove2.db.in > signer.out.2.$n
3718)
3719grep "RRSIG MX" signer/remove.db.signed > /dev/null &&  {
3720	ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.post$n;
3721}
3722n=$((n+1))
3723test "$ret" -eq 0 || echo_i "failed"
3724status=$((status+ret))
3725
3726echo_i "check that RRSIGs are correctly removed from apex when RRset is removed  NSEC3 ($n)"
3727ret=0
3728# generate signed zone with MX and AAAA records at apex.
3729(
3730cd signer || exit 1
3731echo > remove.db.signed
3732$SIGNER -3 - -S -o remove -D -f remove.db.signed remove.db.in > signer.out.1.$n
3733)
3734grep "RRSIG MX" signer/remove.db.signed > /dev/null || {
3735	ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.pre$n;
3736}
3737# re-generate signed zone without MX and AAAA records at apex.
3738(
3739cd signer || exit 1
3740$SIGNER -3 - -S -o remove -D -f remove.db.signed remove2.db.in > signer.out.2.$n
3741)
3742grep "RRSIG MX" signer/remove.db.signed > /dev/null &&  {
3743	ret=1 ; cp signer/remove.db.signed signer/remove.db.signed.post$n;
3744}
3745n=$((n+1))
3746test "$ret" -eq 0 || echo_i "failed"
3747status=$((status+ret))
3748
3749echo_i "check that a named managed zone that was signed 'in-the-future' is re-signed when loaded ($n)"
3750ret=0
3751dig_with_opts managed-future.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
3752grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
3753grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
3754n=$((n+1))
3755test "$ret" -eq 0 || echo_i "failed"
3756status=$((status+ret))
3757
3758echo_i "check that trust-anchor-telemetry queries are logged ($n)"
3759ret=0
3760grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/NULL" ns6/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-XXXX trust-anchor-telemetry queries are logged ($n)"
3766ret=0
3767grep "trust-anchor-telemetry '_ta-[0-9a-f]*/IN' from" 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 _ta-AAAA trust-anchor-telemetry are not sent when disabled ($n)"
3773ret=0
3774grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/IN" ns1/named.run > /dev/null && ret=1
3775n=$((n+1))
3776test "$ret" -eq 0 || echo_i "failed"
3777status=$((status+ret))
3778
3779echo_i "check that KEY-TAG trust-anchor-telemetry queries are logged ($n)"
3780ret=0
3781dig_with_opts . dnskey +ednsopt=KEY-TAG:ffff @10.53.0.1 > dig.out.ns1.test$n || ret=1
3782grep "trust-anchor-telemetry './IN' from .* 65535" ns1/named.run > /dev/null || ret=1
3783n=$((n+1))
3784test "$ret" -eq 0 || echo_i "failed"
3785status=$((status+ret))
3786
3787echo_i "check that multiple KEY-TAG trust-anchor-telemetry options don't leak memory ($n)"
3788ret=0
3789dig_with_opts . dnskey +ednsopt=KEY-TAG:fffe +ednsopt=KEY-TAG:fffd @10.53.0.1 > dig.out.ns1.test$n || ret=1
3790grep "trust-anchor-telemetry './IN' from .* 65534" ns1/named.run > /dev/null || ret=1
3791grep "trust-anchor-telemetry './IN' from .* 65533" ns1/named.run > /dev/null && ret=1
3792$PERL $SYSTEMTESTTOP/stop.pl dnssec ns1 || ret=1
3793nextpart ns1/named.run > /dev/null
3794$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} dnssec ns1 || ret=1
3795n=$(($n+1))
3796test "$ret" -eq 0 || echo_i "failed"
3797status=$((status+ret))
3798
3799echo_i "waiting for root server to finish reloading ($n)"
3800ret=0
3801wait_for_log 20 "all zones loaded" ns1/named.run || ret=1
3802n=$(($n+1))
3803test "$ret" -eq 0 || echo_i "failed"
3804status=$((status+ret))
3805
3806echo_i "check that the view is logged in messages from the validator when using views ($n)"
3807ret=0
3808grep "view rec: *validat" ns4/named.run > /dev/null || ret=1
3809n=$((n+1))
3810test "$ret" -eq 0 || echo_i "failed"
3811status=$((status+ret))
3812
3813echo_i "check that DNAME at apex with NSEC3 is correctly signed (dnssec-signzone) ($n)"
3814ret=0
3815dig_with_opts txt dname-at-apex-nsec3.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
3816grep "RRSIG.NSEC3 ${DEFAULT_ALGORITHM_NUMBER} 3 3600" dig.out.ns3.test$n > /dev/null || ret=1
3817n=$((n+1))
3818test "$ret" -eq 0 || echo_i "failed"
3819status=$((status+ret))
3820
3821echo_i "check that DNSKEY and other occluded data are excluded from the delegating bitmap ($n)"
3822ret=0
3823dig_with_opts axfr occluded.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
3824grep "^delegation.occluded.example..*NSEC.*NS KEY DS RRSIG NSEC$" dig.out.ns3.test$n > /dev/null || ret=1
3825grep "^delegation.occluded.example..*DNSKEY.*" dig.out.ns3.test$n > /dev/null || ret=1
3826grep "^delegation.occluded.example..*AAAA.*" dig.out.ns3.test$n > /dev/null || ret=1
3827n=$((n+1))
3828test "$ret" -eq 0 || echo_i "failed"
3829status=$((status+ret))
3830
3831echo_i "checking DNSSEC records are occluded from ANY in an insecure zone ($n)"
3832ret=0
3833dig_with_opts any x.insecure.example. @10.53.0.3 > dig.out.ns3.1.test$n || ret=1
3834grep "status: NOERROR" dig.out.ns3.1.test$n > /dev/null || ret=1
3835grep "ANSWER: 0," dig.out.ns3.1.test$n > /dev/null || ret=1
3836dig_with_opts any zz.secure.example. @10.53.0.3 > dig.out.ns3.2.test$n || ret=1
3837grep "status: NOERROR" dig.out.ns3.2.test$n > /dev/null || ret=1
3838# DNSKEY+RRSIG, NSEC+RRSIG
3839grep "ANSWER: 4," dig.out.ns3.2.test$n > /dev/null || ret=1
3840n=$((n+1))
3841test "$ret" -eq 0 || echo_i "failed"
3842status=$((status+ret))
3843
3844#
3845# DNSSEC tests related to unsupported, disabled and revoked trust anchors.
3846#
3847
3848# This nameserver (ns8) is loaded with a bunch of trust anchors.  Some of
3849# them are good (enabled.managed, enabled.trusted, secure.managed,
3850# secure.trusted), and some of them are bad (disabled.managed,
3851# revoked.managed, unsupported.managed, disabled.trusted, revoked.trusted,
3852# unsupported.trusted).  Make sure that the bad trust anchors are ignored.
3853# This is tested by looking for the corresponding lines in the logfile.
3854echo_i "checking that keys with unsupported algorithms and disabled algorithms are ignored ($n)"
3855ret=0
3856grep -q "ignoring static-key for 'disabled\.trusted\.': algorithm is disabled" ns8/named.run || ret=1
3857grep -q "ignoring static-key for 'unsupported\.trusted\.': algorithm is unsupported" ns8/named.run || ret=1
3858grep -q "ignoring static-key for 'revoked\.trusted\.': bad key type" ns8/named.run || ret=1
3859grep -q "ignoring initial-key for 'disabled\.managed\.': algorithm is disabled" ns8/named.run || ret=1
3860grep -q "ignoring initial-key for 'unsupported\.managed\.': algorithm is unsupported" ns8/named.run || ret=1
3861grep -q "ignoring initial-key for 'revoked\.managed\.': bad key type" ns8/named.run || ret=1
3862n=$((n+1))
3863test "$ret" -eq 0 || echo_i "failed"
3864status=$((status+ret))
3865
3866# The next two tests are fairly normal DNSSEC queries to signed zones with a
3867# default algorithm.  First, a query is made against the server that is
3868# authoritative for the given zone (ns3).  Second, a query is made against a
3869# resolver with trust anchors for the given zone (ns8).  Both are expected to
3870# return an authentic data positive response.
3871echo_i "checking that a trusted key using a supported algorithm validates as secure ($n)"
3872ret=0
3873dig_with_opts @10.53.0.3 a.secure.trusted A > dig.out.ns3.test$n
3874dig_with_opts @10.53.0.8 a.secure.trusted A > dig.out.ns8.test$n
3875grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3876grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3877grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null || ret=1
3878n=$((n+1))
3879test "$ret" -eq 0 || echo_i "failed"
3880status=$((status+ret))
3881
3882echo_i "checking that a managed key using a supported algorithm validates as secure ($n)"
3883ret=0
3884dig_with_opts @10.53.0.3 a.secure.managed A > dig.out.ns3.test$n
3885dig_with_opts @10.53.0.8 a.secure.managed A > dig.out.ns8.test$n
3886grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3887grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3888grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null || ret=1
3889n=$((n+1))
3890test "$ret" -eq 0 || echo_i "failed"
3891status=$((status+ret))
3892
3893# The next two queries ensure that a zone signed with a DNSKEY with an unsupported
3894# algorithm will yield insecure positive responses.  These trust anchors in ns8 are
3895# ignored and so this domain is treated as insecure.  The AD bit should not be set
3896# in the response.
3897echo_i "checking that a trusted key using an unsupported algorithm validates as insecure ($n)"
3898ret=0
3899dig_with_opts @10.53.0.3 a.unsupported.trusted A > dig.out.ns3.test$n
3900dig_with_opts @10.53.0.8 a.unsupported.trusted A > dig.out.ns8.test$n
3901grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3902grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3903grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
3904n=$((n+1))
3905test "$ret" -eq 0 || echo_i "failed"
3906status=$((status+ret))
3907
3908echo_i "checking that a managed key using an unsupported algorithm validates as insecure ($n)"
3909ret=0
3910dig_with_opts @10.53.0.3 a.unsupported.managed A > dig.out.ns3.test$n
3911dig_with_opts @10.53.0.8 a.unsupported.managed A > dig.out.ns8.test$n
3912grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3913grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3914grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
3915n=$((n+1))
3916test "$ret" -eq 0 || echo_i "failed"
3917status=$((status+ret))
3918
3919# The next two queries ensure that a zone signed with a DNSKEY that the nameserver
3920# has a disabled algorithm match for will yield insecure positive responses.
3921# These trust anchors in ns8 are ignored and so this domain is treated as insecure.
3922# The AD bit should not be set in the response.
3923echo_i "checking that a trusted key using a disabled algorithm validates as insecure ($n)"
3924ret=0
3925dig_with_opts @10.53.0.3 a.disabled.trusted A > dig.out.ns3.test$n
3926dig_with_opts @10.53.0.8 a.disabled.trusted A > dig.out.ns8.test$n
3927grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3928grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3929grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
3930n=$((n+1))
3931test "$ret" -eq 0 || echo_i "failed"
3932status=$((status+ret))
3933
3934echo_i "checking that a managed key using a disabled algorithm validates as insecure ($n)"
3935ret=0
3936dig_with_opts @10.53.0.3 a.disabled.managed A > dig.out.ns3.test$n
3937dig_with_opts @10.53.0.8 a.disabled.managed A > dig.out.ns8.test$n
3938grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3939grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3940grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
3941n=$((n+1))
3942test "$ret" -eq 0 || echo_i "failed"
3943status=$((status+ret))
3944
3945# The next two queries ensure that a zone signed with a DNSKEY that the
3946# nameserver has a disabled algorithm for, but for a different domain, will
3947# yield secure positive responses.  Since "enabled.trusted." and
3948# "enabled.managed." do not match the "disable-algorithms" option, no
3949# special rules apply and these zones should validate as secure, with the AD
3950# bit set.
3951echo_i "checking that a trusted key using an algorithm disabled for another domain validates as secure ($n)"
3952ret=0
3953dig_with_opts @10.53.0.3 a.enabled.trusted A > dig.out.ns3.test$n
3954dig_with_opts @10.53.0.8 a.enabled.trusted A > dig.out.ns8.test$n
3955grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3956grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3957grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null || ret=1
3958n=$((n+1))
3959test "$ret" -eq 0 || echo_i "failed"
3960status=$((status+ret))
3961
3962echo_i "checking that a managed key using an algorithm disabled for another domain validates as secure ($n)"
3963ret=0
3964dig_with_opts @10.53.0.3 a.enabled.managed A > dig.out.ns3.test$n
3965dig_with_opts @10.53.0.8 a.enabled.managed A > dig.out.ns8.test$n
3966grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3967grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3968grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null || ret=1
3969n=$((n+1))
3970test "$ret" -eq 0 || echo_i "failed"
3971status=$((status+ret))
3972
3973# A configured revoked trust anchor is ignored and thus the two queries below
3974# should result in insecure responses, since no trust points for the
3975# "revoked.trusted." and "revoked.managed." zones are created.
3976echo_i "checking that a trusted key that is revoked validates as insecure ($n)"
3977ret=0
3978dig_with_opts @10.53.0.3 a.revoked.trusted A > dig.out.ns3.test$n
3979dig_with_opts @10.53.0.8 a.revoked.trusted A > dig.out.ns8.test$n
3980grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3981grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3982grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
3983n=$((n+1))
3984test "$ret" -eq 0 || echo_i "failed"
3985status=$((status+ret))
3986
3987echo_i "checking that a managed key that is revoked validates as insecure ($n)"
3988ret=0
3989dig_with_opts @10.53.0.3 a.revoked.managed A > dig.out.ns3.test$n
3990dig_with_opts @10.53.0.8 a.revoked.managed A > dig.out.ns8.test$n
3991grep "status: NOERROR," dig.out.ns3.test$n > /dev/null || ret=1
3992grep "status: NOERROR," dig.out.ns8.test$n > /dev/null || ret=1
3993grep "flags:.*ad.*QUERY" dig.out.ns8.test$n > /dev/null && ret=1
3994n=$((n+1))
3995test "$ret" -eq 0 || echo_i "failed"
3996status=$((status+ret))
3997
3998###
3999### Additional checks for when the KSK is offline.
4000###
4001
4002# Save some useful information
4003zone="updatecheck-kskonly.secure"
4004KSK=`cat ns2/${zone}.ksk.key`
4005ZSK=`cat ns2/${zone}.zsk.key`
4006KSK_ID=`cat ns2/${zone}.ksk.id`
4007ZSK_ID=`cat ns2/${zone}.zsk.id`
4008SECTIONS="+answer +noauthority +noadditional"
4009echo_i "testing zone $zone KSK=$KSK_ID ZSK=$ZSK_ID"
4010
4011# Print IDs of keys used for generating RRSIG records for RRsets of type $1
4012# found in dig output file $2.
4013get_keys_which_signed() {
4014	qtype=$1
4015	output=$2
4016	# The key ID is the 11th column of the RRSIG record line.
4017	awk -v qt="$qtype" '$4 == "RRSIG" && $5 == qt {print $11}' < "$output"
4018}
4019
4020# Basic checks to make sure everything is fine before the KSK is made offline.
4021for qtype in "DNSKEY" "CDNSKEY" "CDS"
4022do
4023  echo_i "checking $qtype RRset is signed with KSK only (update-check-ksk, dnssec-ksk-only) ($n)"
4024  ret=0
4025  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4026  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4027  test "$lines" -eq 1 || ret=1
4028  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null || ret=1
4029  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4030  n=$((n+1))
4031  test "$ret" -eq 0 || echo_i "failed"
4032  status=$((status+ret))
4033done
4034
4035echo_i "checking SOA RRset is signed with ZSK only (update-check-ksk and dnssec-ksk-only) ($n)"
4036ret=0
4037dig_with_opts $SECTIONS @10.53.0.2 soa $zone > dig.out.test$n
4038lines=$(get_keys_which_signed "SOA" dig.out.test$n | wc -l)
4039test "$lines" -eq 1 || ret=1
4040get_keys_which_signed "SOA" dig.out.test$n | grep "^$KSK_ID$" > /dev/null && ret=1
4041get_keys_which_signed "SOA" dig.out.test$n | grep "^$ZSK_ID$" > /dev/null || ret=1
4042n=$((n+1))
4043test "$ret" -eq 0 || echo_i "failed"
4044status=$((status+ret))
4045
4046# Roll the ZSK.
4047zsk2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -K ns2 -n zone "$zone")
4048keyfile_to_key_id "$zsk2" > ns2/$zone.zsk.id2
4049ZSK_ID2=`cat ns2/$zone.zsk.id2`
4050
4051echo_i "load new ZSK $ZSK_ID2 for $zone ($n)"
4052ret=0
4053dnssec_loadkeys_on 2 $zone || ret=1
4054n=$((n+1))
4055test "$ret" -eq 0 || echo_i "failed"
4056status=$((status+ret))
4057
4058# Make new ZSK active.
4059echo_i "make ZSK $ZSK_ID inactive and make new ZSK $ZSK_ID2 active for zone $zone ($n)"
4060ret=0
4061$SETTIME -I now -K ns2 $ZSK > /dev/null
4062$SETTIME -A now -K ns2 $zsk2 > /dev/null
4063dnssec_loadkeys_on 2 $zone || ret=1
4064n=$((n+1))
4065test "$ret" -eq 0 || echo_i "failed"
4066status=$((status+ret))
4067
4068# Remove the KSK from disk.
4069echo_i "remove the KSK $KSK_ID for zone $zone from disk"
4070mv ns2/$KSK.key ns2/$KSK.key.bak
4071mv ns2/$KSK.private ns2/$KSK.private.bak
4072
4073# Update the zone that requires a resign of the SOA RRset.
4074echo_i "update the zone with $zone IN TXT nsupdate added me"
4075(
4076echo zone $zone
4077echo server 10.53.0.2 "$PORT"
4078echo update add $zone. 300 in txt "nsupdate added me"
4079echo send
4080) | $NSUPDATE
4081
4082# Redo the tests now that the zone is updated and the KSK is offline.
4083for qtype in "DNSKEY" "CDNSKEY" "CDS"
4084do
4085  echo_i "checking $qtype RRset is signed with KSK only, KSK offline (update-check-ksk, dnssec-ksk-only) ($n)"
4086  ret=0
4087  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4088  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4089  test "$lines" -eq 1 || ret=1
4090  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null || ret=1
4091  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4092  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null && ret=1
4093  n=$((n+1))
4094  test "$ret" -eq 0 || echo_i "failed"
4095  status=$((status+ret))
4096done
4097
4098for qtype in "SOA" "TXT"
4099do
4100  echo_i "checking $qtype RRset is signed with ZSK only, KSK offline (update-check-ksk and dnssec-ksk-only) ($n)"
4101  ret=0
4102  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4103  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4104  test "$lines" -eq 1 || ret=1
4105  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null && ret=1
4106  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4107  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null || ret=1
4108  n=$((n+1))
4109  test "$ret" -eq 0 || echo_i "failed"
4110  status=$((status+ret))
4111done
4112
4113# Put back the KSK.
4114echo_i "put back the KSK $KSK_ID for zone $zone from disk"
4115mv ns2/$KSK.key.bak ns2/$KSK.key
4116mv ns2/$KSK.private.bak ns2/$KSK.private
4117
4118# Roll the ZSK again.
4119zsk3=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -K ns2 -n zone "$zone")
4120keyfile_to_key_id "$zsk3" > ns2/$zone.zsk.id3
4121ZSK_ID3=`cat ns2/$zone.zsk.id3`
4122
4123# Schedule the new ZSK (ZSK3) to become active.
4124echo_i "delete old ZSK $ZSK_ID schedule ZSK $ZSK_ID2 inactive and new ZSK $ZSK_ID3 active for zone $zone ($n)"
4125$SETTIME -D now -K ns2 $ZSK > /dev/null
4126$SETTIME -I +3600 -K ns2 $zsk2 > /dev/null
4127$SETTIME -A +3600 -K ns2 $zsk3 > /dev/null
4128dnssec_loadkeys_on 2 $zone || ret=1
4129n=$((n+1))
4130test "$ret" -eq 0 || echo_i "failed"
4131status=$((status+ret))
4132
4133# Remove the KSK from disk.
4134echo_i "remove the KSK $KSK_ID for zone $zone from disk"
4135mv ns2/$KSK.key ns2/$KSK.key.bak
4136mv ns2/$KSK.private ns2/$KSK.private.bak
4137
4138# Update the zone that requires a resign of the SOA RRset.
4139echo_i "update the zone with $zone IN TXT nsupdate added me again"
4140(
4141echo zone $zone
4142echo server 10.53.0.2 "$PORT"
4143echo update add $zone. 300 in txt "nsupdate added me again"
4144echo send
4145) | $NSUPDATE
4146
4147# Redo the tests now that the ZSK roll has deleted the old key.
4148for qtype in "DNSKEY" "CDNSKEY" "CDS"
4149do
4150  echo_i "checking $qtype RRset is signed with KSK only, old ZSK deleted (update-check-ksk, dnssec-ksk-only) ($n)"
4151  ret=0
4152  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4153  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4154  test "$lines" -eq 1 || ret=1
4155  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null || ret=1
4156  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4157  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null && ret=1
4158  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" > /dev/null && ret=1
4159  n=$((n+1))
4160  test "$ret" -eq 0 || echo_i "failed"
4161  status=$((status+ret))
4162done
4163
4164for qtype in "SOA" "TXT"
4165do
4166  echo_i "checking $qtype RRset is signed with ZSK only, old ZSK deleted (update-check-ksk and dnssec-ksk-only) ($n)"
4167  ret=0
4168  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4169  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4170  test "$lines" -eq 1 || ret=1
4171  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null && ret=1
4172  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4173  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null || ret=1
4174  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" > /dev/null && ret=1
4175  n=$((n+1))
4176  test "$ret" -eq 0 || echo_i "failed"
4177  status=$((status+ret))
4178done
4179
4180# Make the new ZSK (ZSK3) active.
4181echo_i "make new ZSK $ZSK_ID3 active for zone $zone ($n)"
4182$SETTIME -I +1 -K ns2 $zsk2 > /dev/null
4183$SETTIME -A +1 -K ns2 $zsk3 > /dev/null
4184dnssec_loadkeys_on 2 $zone || ret=1
4185n=$((n+1))
4186test "$ret" -eq 0 || echo_i "failed"
4187status=$((status+ret))
4188
4189# Wait for newest ZSK to become active.
4190echo_i "wait until new ZSK $ZSK_ID3 active and ZSK $ZSK_ID2 inactive"
4191for i in 1 2 3 4 5 6 7 8 9 10; do
4192    ret=0
4193    grep "DNSKEY $zone/$DEFAULT_ALGORITHM/$ZSK_ID3 (ZSK) is now active" ns2/named.run > /dev/null || ret=1
4194    grep "DNSKEY $zone/$DEFAULT_ALGORITHM/$ZSK_ID2 (ZSK) is now inactive" ns2/named.run > /dev/null || ret=1
4195    [ "$ret" -eq 0 ] && break
4196    sleep 1
4197done
4198n=$((n+1))
4199test "$ret" -eq 0 || echo_i "failed"
4200status=$((status+ret))
4201
4202# Update the zone that requires a resign of the SOA RRset.
4203echo_i "update the zone with $zone IN TXT nsupdate added me one more time"
4204(
4205echo zone $zone
4206echo server 10.53.0.2 "$PORT"
4207echo update add $zone. 300 in txt "nsupdate added me one more time"
4208echo send
4209) | $NSUPDATE
4210n=$((n+1))
4211test "$ret" -eq 0 || echo_i "failed"
4212status=$((status+ret))
4213
4214# Redo the tests one more time.
4215for qtype in "DNSKEY" "CDNSKEY" "CDS"
4216do
4217  echo_i "checking $qtype RRset is signed with KSK only, new ZSK active (update-check-ksk, dnssec-ksk-only) ($n)"
4218  ret=0
4219  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4220  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4221  test "$lines" -eq 1 || ret=1
4222  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null || ret=1
4223  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4224  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null && ret=1
4225  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" > /dev/null && ret=1
4226  n=$((n+1))
4227  test "$ret" -eq 0 || echo_i "failed"
4228  status=$((status+ret))
4229done
4230
4231for qtype in "SOA" "TXT"
4232do
4233  echo_i "checking $qtype RRset is signed with ZSK only, new ZSK active (update-check-ksk and dnssec-ksk-only) ($n)"
4234  ret=0
4235  dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone > dig.out.test$n
4236  lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l)
4237  test "$lines" -eq 1 || ret=1
4238  get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" > /dev/null && ret=1
4239  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" > /dev/null && ret=1
4240  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" > /dev/null && ret=1
4241  get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" > /dev/null || ret=1
4242  n=$((n+1))
4243  test "$ret" -eq 0 || echo_i "failed"
4244  status=$((status+ret))
4245done
4246
4247echo_i "checking secroots output with multiple views ($n)"
4248ret=0
4249rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i
4250cp ns4/named.secroots named.secroots.test$n
4251check_secroots_layout named.secroots.test$n || ret=1
4252n=$((n+1))
4253test "$ret" -eq 0 || echo_i "failed"
4254status=$((status+ret))
4255
4256echo_i "checking sig-validity-interval second field hours vs days ($n)"
4257ret=0
4258# zone configured with 'sig-validity-interval 500 499;'
4259# 499 days in the future w/ a 20 minute runtime to now allowance
4260min=$(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];')
4261dig_with_opts @10.53.0.2 hours-vs-days AXFR > dig.out.ns2.test$n
4262awk -v min=$min '$4 == "RRSIG" { if ($9 < min) { exit(1); } }' dig.out.ns2.test$n || ret=1
4263n=$((n+1))
4264test "$ret" -eq 0 || echo_i "failed"
4265status=$((status+ret))
4266
4267echo_i "checking validation succeeds during transition to signed ($n)"
4268ret=0
4269dig_with_opts @10.53.0.4 inprogress A > dig.out.ns4.test$n || ret=1
4270grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
4271grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
4272grep 'A.10\.53\.0\.10' dig.out.ns4.test$n >/dev/null || ret=1
4273n=$((n+1))
4274test "$ret" -eq 0 || echo_i "failed"
4275status=$((status+ret))
4276
4277echo_i "exit status: $status"
4278[ $status -eq 0 ] || exit 1
4279