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