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