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