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