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