1#!/bin/sh 2# 3# Copyright (C) Internet Systems Consortium, Inc. ("ISC") 4# 5# This Source Code Form is subject to the terms of the Mozilla Public 6# License, v. 2.0. If a copy of the MPL was not distributed with this 7# file, You can obtain one at http://mozilla.org/MPL/2.0/. 8# 9# See the COPYRIGHT file distributed with this work for additional 10# information regarding copyright ownership. 11 12SYSTEMTESTTOP=.. 13. $SYSTEMTESTTOP/conf.sh 14 15status=0 16n=0 17 18DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}" 19RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s" 20 21# convert private-type records to readable form 22showprivate () { 23 echo "-- $@ --" 24 $DIG $DIGOPTS +nodnssec +short @$2 -t type65534 $1 | cut -f3 -d' ' | 25 while read record; do 26 $PERL -e 'my $rdata = pack("H*", @ARGV[0]); 27 die "invalid record" unless length($rdata) == 5; 28 my ($alg, $key, $remove, $complete) = unpack("CnCC", $rdata); 29 my $action = "signing"; 30 $action = "removing" if $remove; 31 my $state = " (incomplete)"; 32 $state = " (complete)" if $complete; 33 print ("$action: alg: $alg, key: $key$state\n");' $record 34 done 35} 36 37# check that signing records are marked as complete 38checkprivate () { 39 _ret=0 40 expected="${3:-0}" 41 x=`showprivate "$@"` 42 echo $x | grep incomplete > /dev/null && _ret=1 43 44 if [ $_ret = $expected ]; then 45 return 0 46 fi 47 48 echo "$x" 49 echo_i "failed" 50 return 1 51} 52 53# wait until notifies for zone $1 are sent by server $2. This is an indication 54# that the zone is signed with the active keys, and the changes have been 55# committed. 56wait_for_notifies () { 57 wait_for_log 10 "zone ${1}/IN: sending notifies" "${2}/named.run" || return 1 58} 59 60freq() { 61 _file=$1 62 # remove first and last line that has incomplete set and skews the distribution 63 awk '$4 == "RRSIG" {print substr($9,1,8)}' < "$_file" | sort | uniq -c | sed '1d;$d' 64} 65# Check the signatures expiration times. First check how many signatures 66# there are in total ($rrsigs). Then see what the distribution of signature 67# expiration times is ($expiretimes). Ignore the time part for a better 68# modelled distribution. 69checkjitter () { 70 _file=$1 71 _ret=0 72 73 if ! command -v bc >/dev/null 2>&1; then 74 echo_i "skip: bc not available" 75 return 0 76 fi 77 78 freq "$_file" | cat_i 79 _expiretimes=$(freq "$_file" | awk '{print $1}') 80 81 _count=0 82 # Check if we have at least 5 days 83 # This number has been tuned for `sig-validity-interval 10 2`, as 84 # 1. 1. signature expiration dates should be spread out across at most 8 (10-2) days 85 # 2. we remove first and last day to remove frequency outlier, we are left with 6 (8-2) days 86 # 3. we subtract one more day to allow test pass on day boundaries, etc. leaving us with 5 (6-1) days 87 for _num in $_expiretimes 88 do 89 _count=$((_count+1)) 90 done 91 if [ "$_count" -lt 5 ]; then 92 echo_i "error: not enough categories" 93 return 1 94 fi 95 96 # Calculate mean 97 _total=0 98 for _num in $_expiretimes 99 do 100 _total=$((_total+_num)) 101 done 102 _mean=$(($_total / $_count)) 103 104 # Calculate stddev 105 _stddev=0 106 for _num in $_expiretimes 107 do 108 _stddev=$(echo "$_stddev + (($_num - $_mean) * ($_num - $_mean))" | bc) 109 done 110 _stddev=$(echo "sqrt($_stddev/$_count)" | bc) 111 112 # We expect the number of signatures not to exceed the mean +- 3 * stddev. 113 _limit=$((_stddev*3)) 114 _low=$((_mean-_limit)) 115 _high=$((_mean+_limit)) 116 # Find outliers. 117 echo_i "checking whether all frequencies fall into <$_low;$_high> range" 118 for _num in $_expiretimes 119 do 120 if [ $_num -gt $_high ]; then 121 echo_i "error: too many RRSIG records ($_num) in expiration bucket" 122 _ret=1 123 fi 124 if [ $_num -lt $_low ]; then 125 echo_i "error: too few RRSIG records ($_num) in expiration bucket" 126 _ret=1 127 fi 128 done 129 130 return $_ret 131} 132 133# 134# The NSEC record at the apex of the zone and its RRSIG records are 135# added as part of the last step in signing a zone. We wait for the 136# NSEC records to appear before proceeding with a counter to prevent 137# infinite loops if there is a error. 138# 139echo_i "waiting for autosign changes to take effect" 140i=0 141while [ $i -lt 30 ] 142do 143 ret=0 144 # 145 # Wait for the root DNSKEY RRset to be fully signed. 146 # 147 $DIG $DIGOPTS . @10.53.0.1 dnskey > dig.out.ns1.test$n || ret=1 148 grep "ANSWER: 10," dig.out.ns1.test$n > /dev/null || ret=1 149 for z in . 150 do 151 $DIG $DIGOPTS $z @10.53.0.1 nsec > dig.out.ns1.test$n || ret=1 152 grep "NS SOA" dig.out.ns1.test$n > /dev/null || ret=1 153 done 154 for z in bar. example. private.secure.example. 155 do 156 $DIG $DIGOPTS $z @10.53.0.2 nsec > dig.out.ns2.test$n || ret=1 157 grep "NS SOA" dig.out.ns2.test$n > /dev/null || ret=1 158 done 159 for z in bar. example. inacksk2.example. inacksk3.example \ 160 inaczsk2.example. inaczsk3.example 161 do 162 $DIG $DIGOPTS $z @10.53.0.3 nsec > dig.out.ns3.test$n || ret=1 163 grep "NS SOA" dig.out.ns3.test$n > /dev/null || ret=1 164 done 165 i=`expr $i + 1` 166 if [ $ret = 0 ]; then break; fi 167 echo_i "waiting ... ($i)" 168 sleep 2 169done 170n=`expr $n + 1` 171if [ $ret != 0 ]; then echo_i "done"; fi 172status=`expr $status + $ret` 173 174echo_i "Initial counts of RRSIG expiry fields values for auto signed zones" 175for z in . 176do 177 echo_i zone $z 178 $DIG $DIGOPTS $z @10.53.0.1 axfr | awk '$4 == "RRSIG" {print $9}' | sort | uniq -c | cat_i 179done 180for z in bar. example. private.secure.example. 181do 182 echo_i zone $z 183 $DIG $DIGOPTS $z @10.53.0.2 axfr | awk '$4 == "RRSIG" {print $9}' | sort | uniq -c | cat_i 184done 185for z in inacksk2.example. inacksk3.example inaczsk2.example. inaczsk3.example 186do 187 echo_i zone $z 188 $DIG $DIGOPTS $z @10.53.0.3 axfr | awk '$4 == "RRSIG" {print $9}' | sort | uniq -c | cat_i 189done 190 191# Set logfile offset for wait_for_log usage. 192nextpartreset ns3/named.run 193 194# 195# Check that DNSKEY is initially signed with a KSK and not a ZSK. 196# 197echo_i "check that zone with active and inactive KSK and active ZSK is properly" 198echo_ic "resigned after the active KSK is deleted - stage 1: Verify that DNSKEY" 199echo_ic "is initially signed with a KSK and not a ZSK. ($n)" 200ret=0 201 202$DIG $DIGOPTS @10.53.0.3 axfr inacksk3.example > dig.out.ns3.test$n 203 204zskid=`awk '$4 == "DNSKEY" && $5 == 256 { print }' dig.out.ns3.test$n | 205 $DSFROMKEY -A -2 -f - inacksk3.example | awk '{ print $4}'` 206grep "DNSKEY 7 2 " dig.out.ns3.test$n > /dev/null || ret=1 207 208pattern="DNSKEY 7 2 [0-9]* [0-9]* [0-9]* ${zskid} " 209grep "${pattern}" dig.out.ns3.test$n > /dev/null && ret=1 210 211count=`awk 'BEGIN { count = 0 } 212 $4 == "RRSIG" && $5 == "DNSKEY" { count++ } 213 END {print count}' dig.out.ns3.test$n` 214test $count -eq 1 || ret=1 215 216count=`awk 'BEGIN { count = 0 } 217 $4 == "DNSKEY" { count++ } 218 END {print count}' dig.out.ns3.test$n` 219test $count -eq 3 || ret=1 220 221awk='$4 == "RRSIG" && $5 == "DNSKEY" { printf "%05u\n", $11 }' 222id=`awk "${awk}" dig.out.ns3.test$n` 223 224$SETTIME -D now+5 ns3/Kinacksk3.example.+007+${id} > settime.out.test$n || ret=1 225($RNDCCMD 10.53.0.3 loadkeys inacksk3.example 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 226 227n=`expr $n + 1` 228if [ $ret != 0 ]; then echo_i "failed"; fi 229status=`expr $status + $ret` 230 231# 232# Check that zone is initially signed with a ZSK and not a KSK. 233# 234echo_i "check that zone with active and inactive ZSK and active KSK is properly" 235echo_ic "resigned after the active ZSK is deleted - stage 1: Verify that zone" 236echo_ic "is initially signed with a ZSK and not a KSK. ($n)" 237ret=0 238$DIG $DIGOPTS @10.53.0.3 axfr inaczsk3.example > dig.out.ns3.test$n 239kskid=`awk '$4 == "DNSKEY" && $5 == 257 { print }' dig.out.ns3.test$n | 240 $DSFROMKEY -2 -f - inaczsk3.example | awk '{ print $4}' ` 241grep "CNAME 7 3 " dig.out.ns3.test$n > /dev/null || ret=1 242grep "CNAME 7 3 [0-9]* [0-9]* [0-9]* ${kskid} " dig.out.ns3.test$n > /dev/null && ret=1 243count=`awk 'BEGIN { count = 0 } 244 $4 == "RRSIG" && $5 == "CNAME" { count++ } 245 END {print count}' dig.out.ns3.test$n` 246test $count -eq 1 || ret=1 247count=`awk 'BEGIN { count = 0 } 248 $4 == "DNSKEY" { count++ } 249 END {print count}' dig.out.ns3.test$n` 250test $count -eq 3 || ret=1 251id=`awk '$4 == "RRSIG" && $5 == "CNAME" { printf "%05u\n", $11 }' dig.out.ns3.test$n` 252$SETTIME -D now+5 ns3/Kinaczsk3.example.+007+${id} > settime.out.test$n || ret=1 253($RNDCCMD 10.53.0.3 loadkeys inaczsk3.example 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 254n=`expr $n + 1` 255if [ $ret != 0 ]; then echo_i "failed"; fi 256status=`expr $status + $ret` 257 258echo_i "checking NSEC->NSEC3 conversion prerequisites ($n)" 259ret=0 260# these commands should result in an empty file: 261$DIG $DIGOPTS +noall +answer nsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.1.test$n || ret=1 262grep "NSEC3PARAM" dig.out.ns3.1.test$n > /dev/null && ret=1 263$DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.2.test$n || ret=1 264grep "NSEC3PARAM" dig.out.ns3.2.test$n > /dev/null && ret=1 265n=`expr $n + 1` 266if [ $ret != 0 ]; then echo_i "failed"; fi 267status=`expr $status + $ret` 268 269echo_i "checking NSEC3->NSEC conversion prerequisites ($n)" 270ret=0 271$DIG $DIGOPTS +noall +answer nsec3-to-nsec.example. nsec3param @10.53.0.3 > dig.out.ns3.test$n || ret=1 272grep "NSEC3PARAM" dig.out.ns3.test$n > /dev/null || ret=1 273n=`expr $n + 1` 274if [ $ret != 0 ]; then echo_i "failed"; fi 275status=`expr $status + $ret` 276 277echo_i "converting zones from nsec to nsec3" 278$NSUPDATE > /dev/null 2>&1 <<END || status=1 279server 10.53.0.3 ${PORT} 280zone nsec3.nsec3.example. 281update add nsec3.nsec3.example. 3600 NSEC3PARAM 1 0 10 BEEF 282send 283zone optout.nsec3.example. 284update add optout.nsec3.example. 3600 NSEC3PARAM 1 1 10 BEEF 285send 286zone nsec3.example. 287update add nsec3.example. 3600 NSEC3PARAM 1 0 10 BEEF 288send 289zone autonsec3.example. 290update add autonsec3.example. 3600 NSEC3PARAM 1 0 20 DEAF 291send 292zone nsec3.optout.example. 293update add nsec3.optout.example. 3600 NSEC3PARAM 1 0 10 BEEF 294send 295zone optout.optout.example. 296update add optout.optout.example. 3600 NSEC3PARAM 1 1 10 BEEF 297send 298zone optout.example. 299update add optout.example. 3600 NSEC3PARAM 1 1 10 BEEF 300send 301END 302 303# try to convert nsec.example; this should fail due to non-NSEC key 304echo_i "preset nsec3param in unsigned zone via nsupdate ($n)" 305$NSUPDATE > nsupdate.out 2>&1 <<END 306server 10.53.0.3 ${PORT} 307zone nsec.example. 308update add nsec.example. 3600 NSEC3PARAM 1 0 10 BEEF 309send 310END 311 312echo_i "checking for nsec3param in unsigned zone ($n)" 313ret=0 314$DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.test$n || ret=1 315grep "NSEC3PARAM" dig.out.ns3.test$n > /dev/null && ret=1 316n=`expr $n + 1` 317if [ $ret != 0 ]; then echo_i "failed"; fi 318status=`expr $status + $ret` 319 320echo_i "checking for nsec3param signing record ($n)" 321ret=0 322$RNDCCMD 10.53.0.3 signing -list autonsec3.example. > signing.out.test$n 2>&1 323grep "Pending NSEC3 chain 1 0 20 DEAF" signing.out.test$n > /dev/null || ret=1 324n=`expr $n + 1` 325if [ $ret != 0 ]; then echo_i "failed"; fi 326status=`expr $status + $ret` 327 328echo_i "resetting nsec3param via rndc signing ($n)" 329ret=0 330$RNDCCMD 10.53.0.3 signing -clear all autonsec3.example. > /dev/null 2>&1 331$RNDCCMD 10.53.0.3 signing -nsec3param 1 1 10 beef autonsec3.example. > /dev/null 2>&1 332for i in 0 1 2 3 4 5 6 7 8 9; do 333 ret=0 334 $RNDCCMD 10.53.0.3 signing -list autonsec3.example. > signing.out.test$n 2>&1 335 grep "Pending NSEC3 chain 1 1 10 BEEF" signing.out.test$n > /dev/null || ret=1 336 num=`grep "Pending " signing.out.test$n | wc -l` 337 [ $num -eq 1 ] || ret=1 338 [ $ret -eq 0 ] && break 339 echo_i "waiting ... ($i)" 340 sleep 2 341done 342n=`expr $n + 1` 343if [ $ret != 0 ]; then echo_i "failed"; fi 344status=`expr $status + $ret` 345 346echo_i "signing preset nsec3 zone" 347zsk=`cat autozsk.key` 348ksk=`cat autoksk.key` 349$SETTIME -K ns3 -P now -A now $zsk > settime.out.test$n.zsk || ret=1 350$SETTIME -K ns3 -P now -A now $ksk > settime.out.test$n.ksk || ret=1 351($RNDCCMD 10.53.0.3 loadkeys autonsec3.example. 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 352 353echo_i "waiting for changes to take effect" 354sleep 3 355 356echo_i "converting zone from nsec3 to nsec" 357$NSUPDATE > /dev/null 2>&1 << END || status=1 358server 10.53.0.3 ${PORT} 359zone nsec3-to-nsec.example. 360update delete nsec3-to-nsec.example. NSEC3PARAM 361send 362END 363 364echo_i "waiting for change to take effect" 365sleep 3 366 367echo_i "checking that expired RRSIGs from missing key are not deleted ($n)" 368ret=0 369missing=$(keyfile_to_key_id "$(cat missingzsk.key)") 370$JOURNALPRINT ns3/nozsk.example.db.jnl | \ 371 awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {exit 1}} END {exit 0}' id=$missing || ret=1 372n=`expr $n + 1` 373if [ $ret != 0 ]; then echo_i "failed"; fi 374status=`expr $status + $ret` 375 376echo_i "checking that expired RRSIGs from inactive key are not deleted ($n)" 377ret=0 378inactive=$(keyfile_to_key_id "$(cat inactivezsk.key)") 379$JOURNALPRINT ns3/inaczsk.example.db.jnl | \ 380 awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {exit 1}} END {exit 0}' id=$inactive || ret=1 381n=`expr $n + 1` 382if [ $ret != 0 ]; then echo_i "failed"; fi 383status=`expr $status + $ret` 384 385echo_i "checking that non-replaceable RRSIGs are logged only once (missing private key) ($n)" 386ret=0 387loglines=`grep "Key nozsk.example/NSEC3RSASHA1/$missing .* retaining signatures" ns3/named.run | wc -l` 388[ "$loglines" -eq 1 ] || ret=1 389n=`expr $n + 1` 390if [ $ret != 0 ]; then echo_i "failed"; fi 391status=`expr $status + $ret` 392 393echo_i "checking that non-replaceable RRSIGs are logged only once (inactive private key) ($n)" 394ret=0 395loglines=`grep "Key inaczsk.example/NSEC3RSASHA1/$inactive .* retaining signatures" ns3/named.run | wc -l` 396[ "$loglines" -eq 1 ] || ret=1 397n=`expr $n + 1` 398if [ $ret != 0 ]; then echo_i "failed"; fi 399status=`expr $status + $ret` 400 401# Send rndc sync command to ns1, ns2 and ns3, to force the dynamically 402# signed zones to be dumped to their zone files 403echo_i "dumping zone files" 404($RNDCCMD 10.53.0.1 sync 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 405($RNDCCMD 10.53.0.2 sync 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1 406($RNDCCMD 10.53.0.3 sync 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 407 408now="$(TZ=UTC date +%Y%m%d%H%M%S)" 409check_expiry() ( 410 $DIG $DIGOPTS AXFR oldsigs.example @10.53.0.3 > dig.out.test$n 411 nearest_expiration="$(awk '$4 == "RRSIG" { print $9 }' < dig.out.test$n | sort -n | head -1)" 412 if [ "$nearest_expiration" -le "$now" ]; then 413 echo_i "failed: $nearest_expiration <= $now" 414 return 1 415 fi 416) 417 418echo_i "checking expired signatures were updated ($n)" 419retry 10 check_expiry || ret=1 420$DIG $DIGOPTS +noauth a.oldsigs.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1 421$DIG $DIGOPTS +noauth a.oldsigs.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1 422digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 423grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 424n=`expr $n + 1` 425if [ $ret != 0 ]; then echo_i "failed"; fi 426status=`expr $status + $ret` 427 428# Check jitter distribution. 429echo_i "checking expired signatures were jittered correctly ($n)" 430ret=0 431$DIG $DIGOPTS axfr oldsigs.example @10.53.0.3 > dig.out.ns3.test$n || ret=1 432checkjitter dig.out.ns3.test$n || ret=1 433n=`expr $n + 1` 434if [ $ret != 0 ]; then echo_i "failed"; fi 435status=`expr $status + $ret` 436 437echo_i "checking NSEC->NSEC3 conversion succeeded ($n)" 438ret=0 439$DIG $DIGOPTS nsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.ok.test$n || ret=1 440grep "status: NOERROR" dig.out.ns3.ok.test$n > /dev/null || ret=1 441$DIG $DIGOPTS +noauth q.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1 442$DIG $DIGOPTS +noauth q.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1 443digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 444grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 445grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 446n=`expr $n + 1` 447if [ $ret != 0 ]; then echo_i "failed"; fi 448status=`expr $status + $ret` 449 450echo_i "checking direct NSEC3 autosigning succeeded ($n)" 451ret=0 452$DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.ok.test$n || ret=1 453[ -s dig.out.ns3.ok.test$n ] || ret=1 454grep "NSEC3PARAM" dig.out.ns3.ok.test$n > /dev/null || ret=1 455$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1 456$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1 457digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 458grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 459grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 460n=`expr $n + 1` 461if [ $ret != 0 ]; then echo_i "failed"; fi 462status=`expr $status + $ret` 463 464echo_i "checking NSEC->NSEC3 conversion failed with NSEC-only key ($n)" 465ret=0 466grep "failed: REFUSED" nsupdate.out > /dev/null || ret=1 467n=`expr $n + 1` 468if [ $ret != 0 ]; then echo_i "failed"; fi 469status=`expr $status + $ret` 470 471echo_i "checking NSEC3->NSEC conversion succeeded ($n)" 472ret=0 473# this command should result in an empty file: 474$DIG $DIGOPTS +noall +answer nsec3-to-nsec.example. nsec3param @10.53.0.3 > dig.out.ns3.nx.test$n || ret=1 475grep "NSEC3PARAM" dig.out.ns3.nx.test$n > /dev/null && ret=1 476$DIG $DIGOPTS +noauth q.nsec3-to-nsec.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1 477$DIG $DIGOPTS +noauth q.nsec3-to-nsec.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1 478digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 479grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 480grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 481n=`expr $n + 1` 482if [ $ret != 0 ]; then echo_i "failed"; fi 483status=`expr $status + $ret` 484 485echo_i "checking NSEC3->NSEC conversion with 'rndc signing -nsec3param none' ($n)" 486ret=0 487$RNDCCMD 10.53.0.3 signing -nsec3param none autonsec3.example. > /dev/null 2>&1 488# this command should result in an empty file: 489no_nsec3param() ( 490 $DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.nx.test$n || return 1 491 grep "NSEC3PARAM" dig.out.ns3.nx.test$n > /dev/null && return 1 492 return 0 493) 494retry_quiet 10 no_nsec3param || ret=1 495$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1 496$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1 497digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 498grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 499grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 500n=`expr $n + 1` 501if [ $ret != 0 ]; then echo_i "failed"; fi 502status=`expr $status + $ret` 503 504echo_i "checking TTLs of imported DNSKEYs (no default) ($n)" 505ret=0 506$DIG $DIGOPTS +tcp +noall +answer dnskey ttl1.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1 507[ -s dig.out.ns3.test$n ] || ret=1 508(awk 'BEGIN {r=0} $2 != 300 {r=1; print "found TTL " $2} END {exit r}' dig.out.ns3.test$n | cat_i) || ret=1 509n=`expr $n + 1` 510if [ $ret != 0 ]; then echo_i "failed"; fi 511status=`expr $status + $ret` 512 513echo_i "checking TTLs of imported DNSKEYs (with default) ($n)" 514ret=0 515$DIG $DIGOPTS +tcp +noall +answer dnskey ttl2.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1 516[ -s dig.out.ns3.test$n ] || ret=1 517(awk 'BEGIN {r=0} $2 != 60 {r=1; print "found TTL " $2} END {exit r}' dig.out.ns3.test$n | cat_i) || ret=1 518n=`expr $n + 1` 519if [ $ret != 0 ]; then echo_i "failed"; fi 520status=`expr $status + $ret` 521 522echo_i "checking TTLs of imported DNSKEYs (mismatched) ($n)" 523ret=0 524$DIG $DIGOPTS +tcp +noall +answer dnskey ttl3.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1 525[ -s dig.out.ns3.test$n ] || ret=1 526(awk 'BEGIN {r=0} $2 != 30 {r=1; print "found TTL " $2} END {exit r}' dig.out.ns3.test$n | cat_i) || ret=1 527n=`expr $n + 1` 528if [ $ret != 0 ]; then echo_i "failed"; fi 529status=`expr $status + $ret` 530 531echo_i "checking TTLs of imported DNSKEYs (existing RRset) ($n)" 532ret=0 533$DIG $DIGOPTS +tcp +noall +answer dnskey ttl4.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1 534[ -s dig.out.ns3.test$n ] || ret=1 535(awk 'BEGIN {r=0} $2 != 30 {r=1; print "found TTL " $2} END {exit r}' dig.out.ns3.test$n | cat_i) || ret=1 536n=`expr $n + 1` 537if [ $ret != 0 ]; then echo_i "failed"; fi 538status=`expr $status + $ret` 539 540echo_i "checking positive validation NSEC ($n)" 541ret=0 542$DIG $DIGOPTS +noauth a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1 543$DIG $DIGOPTS +noauth a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1 544digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 545grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 546n=`expr $n + 1` 547if [ $ret != 0 ]; then echo_i "failed"; fi 548status=`expr $status + $ret` 549 550echo_i "checking positive validation NSEC3 ($n)" 551ret=0 552$DIG $DIGOPTS +noauth a.nsec3.example. \ 553 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 554$DIG $DIGOPTS +noauth a.nsec3.example. \ 555 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 556digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 557grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 558n=`expr $n + 1` 559if [ $ret != 0 ]; then echo_i "failed"; fi 560status=`expr $status + $ret` 561 562echo_i "checking positive validation OPTOUT ($n)" 563ret=0 564$DIG $DIGOPTS +noauth a.optout.example. \ 565 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 566$DIG $DIGOPTS +noauth a.optout.example. \ 567 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 568digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 569grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 570n=`expr $n + 1` 571if [ $ret != 0 ]; then echo_i "failed"; fi 572status=`expr $status + $ret` 573 574echo_i "checking negative validation NXDOMAIN NSEC ($n)" 575ret=0 576$DIG $DIGOPTS +noauth q.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1 577$DIG $DIGOPTS +noauth q.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1 578digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 579grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 580grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 581n=`expr $n + 1` 582if [ $ret != 0 ]; then echo_i "failed"; fi 583status=`expr $status + $ret` 584 585echo_i "checking negative validation NXDOMAIN NSEC3 ($n)" 586ret=0 587$DIG $DIGOPTS +noauth q.nsec3.example. \ 588 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 589$DIG $DIGOPTS +noauth q.nsec3.example. \ 590 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 591digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 592grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 593grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 594n=`expr $n + 1` 595if [ $ret != 0 ]; then echo_i "failed"; fi 596status=`expr $status + $ret` 597 598echo_i "checking negative validation NXDOMAIN OPTOUT ($n)" 599ret=0 600$DIG $DIGOPTS +noauth q.optout.example. \ 601 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 602$DIG $DIGOPTS +noauth q.optout.example. \ 603 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 604digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 605grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 606# Note - this is looking for failure, hence the && 607grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1 608n=`expr $n + 1` 609if [ $ret != 0 ]; then echo_i "failed"; fi 610status=`expr $status + $ret` 611 612echo_i "checking negative validation NODATA NSEC ($n)" 613ret=0 614$DIG $DIGOPTS +noauth a.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1 615$DIG $DIGOPTS +noauth a.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1 616digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 617grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 618grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 619grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1 620n=`expr $n + 1` 621if [ $ret != 0 ]; then echo_i "failed"; fi 622status=`expr $status + $ret` 623 624echo_i "checking negative validation NODATA NSEC3 ($n)" 625ret=0 626$DIG $DIGOPTS +noauth a.nsec3.example. \ 627 @10.53.0.3 txt > dig.out.ns3.test$n || ret=1 628$DIG $DIGOPTS +noauth a.nsec3.example. \ 629 @10.53.0.4 txt > dig.out.ns4.test$n || ret=1 630digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 631grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 632grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 633grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1 634n=`expr $n + 1` 635if [ $ret != 0 ]; then echo_i "failed"; fi 636status=`expr $status + $ret` 637 638echo_i "checking negative validation NODATA OPTOUT ($n)" 639ret=0 640$DIG $DIGOPTS +noauth a.optout.example. \ 641 @10.53.0.3 txt > dig.out.ns3.test$n || ret=1 642$DIG $DIGOPTS +noauth a.optout.example. \ 643 @10.53.0.4 txt > dig.out.ns4.test$n || ret=1 644digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 645grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 646grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 647grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1 648n=`expr $n + 1` 649if [ $ret != 0 ]; then echo_i "failed"; fi 650status=`expr $status + $ret` 651 652# Check the insecure.example domain 653 654echo_i "checking 1-server insecurity proof NSEC ($n)" 655ret=0 656$DIG $DIGOPTS +noauth a.insecure.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1 657$DIG $DIGOPTS +noauth a.insecure.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1 658digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 659grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 660# Note - this is looking for failure, hence the && 661grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1 662n=`expr $n + 1` 663if [ $ret != 0 ]; then echo_i "failed"; fi 664status=`expr $status + $ret` 665 666echo_i "checking 1-server negative insecurity proof NSEC ($n)" 667ret=0 668$DIG $DIGOPTS q.insecure.example. a @10.53.0.3 \ 669 > dig.out.ns3.test$n || ret=1 670$DIG $DIGOPTS q.insecure.example. a @10.53.0.4 \ 671 > dig.out.ns4.test$n || ret=1 672digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 673grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 674# Note - this is looking for failure, hence the && 675grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1 676n=`expr $n + 1` 677if [ $ret != 0 ]; then echo_i "failed"; fi 678status=`expr $status + $ret` 679 680# Check the secure.example domain 681 682echo_i "checking multi-stage positive validation NSEC/NSEC ($n)" 683ret=0 684$DIG $DIGOPTS +noauth a.secure.example. \ 685 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 686$DIG $DIGOPTS +noauth a.secure.example. \ 687 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 688digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 689grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 690grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 691n=`expr $n + 1` 692if [ $ret != 0 ]; then echo_i "failed"; fi 693status=`expr $status + $ret` 694 695echo_i "checking multi-stage positive validation NSEC/NSEC3 ($n)" 696ret=0 697$DIG $DIGOPTS +noauth a.nsec3.example. \ 698 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 699$DIG $DIGOPTS +noauth a.nsec3.example. \ 700 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 701digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 702grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 703grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 704n=`expr $n + 1` 705if [ $ret != 0 ]; then echo_i "failed"; fi 706status=`expr $status + $ret` 707 708echo_i "checking multi-stage positive validation NSEC/OPTOUT ($n)" 709ret=0 710$DIG $DIGOPTS +noauth a.optout.example. \ 711 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 712$DIG $DIGOPTS +noauth a.optout.example. \ 713 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 714digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 715grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 716grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 717n=`expr $n + 1` 718if [ $ret != 0 ]; then echo_i "failed"; fi 719status=`expr $status + $ret` 720 721echo_i "checking multi-stage positive validation NSEC3/NSEC ($n)" 722ret=0 723$DIG $DIGOPTS +noauth a.secure.nsec3.example. \ 724 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 725$DIG $DIGOPTS +noauth a.secure.nsec3.example. \ 726 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 727digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 728grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 729grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 730n=`expr $n + 1` 731if [ $ret != 0 ]; then echo_i "failed"; fi 732status=`expr $status + $ret` 733 734echo_i "checking multi-stage positive validation NSEC3/NSEC3 ($n)" 735ret=0 736$DIG $DIGOPTS +noauth a.nsec3.nsec3.example. \ 737 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 738$DIG $DIGOPTS +noauth a.nsec3.nsec3.example. \ 739 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 740digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 741grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 742grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 743n=`expr $n + 1` 744if [ $ret != 0 ]; then echo_i "failed"; fi 745status=`expr $status + $ret` 746 747echo_i "checking multi-stage positive validation NSEC3/OPTOUT ($n)" 748ret=0 749$DIG $DIGOPTS +noauth a.optout.nsec3.example. \ 750 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 751$DIG $DIGOPTS +noauth a.optout.nsec3.example. \ 752 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 753digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 754grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 755grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 756n=`expr $n + 1` 757if [ $ret != 0 ]; then echo_i "failed"; fi 758status=`expr $status + $ret` 759 760echo_i "checking multi-stage positive validation OPTOUT/NSEC ($n)" 761ret=0 762$DIG $DIGOPTS +noauth a.secure.optout.example. \ 763 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 764$DIG $DIGOPTS +noauth a.secure.optout.example. \ 765 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 766digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 767grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 768grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 769n=`expr $n + 1` 770if [ $ret != 0 ]; then echo_i "failed"; fi 771status=`expr $status + $ret` 772 773echo_i "checking multi-stage positive validation OPTOUT/NSEC3 ($n)" 774ret=0 775$DIG $DIGOPTS +noauth a.nsec3.optout.example. \ 776 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 777$DIG $DIGOPTS +noauth a.nsec3.optout.example. \ 778 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 779digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 780grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 781grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 782n=`expr $n + 1` 783if [ $ret != 0 ]; then echo_i "failed"; fi 784status=`expr $status + $ret` 785 786echo_i "checking multi-stage positive validation OPTOUT/OPTOUT ($n)" 787ret=0 788$DIG $DIGOPTS +noauth a.optout.optout.example. \ 789 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 790$DIG $DIGOPTS +noauth a.optout.optout.example. \ 791 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 792digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 793grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 794grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 795n=`expr $n + 1` 796if [ $ret != 0 ]; then echo_i "failed"; fi 797status=`expr $status + $ret` 798 799echo_i "checking empty NODATA OPTOUT ($n)" 800ret=0 801$DIG $DIGOPTS +noauth empty.optout.example. \ 802 @10.53.0.3 a > dig.out.ns3.test$n || ret=1 803$DIG $DIGOPTS +noauth empty.optout.example. \ 804 @10.53.0.4 a > dig.out.ns4.test$n || ret=1 805digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 806grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 807#grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 808n=`expr $n + 1` 809if [ $ret != 0 ]; then echo_i "failed"; fi 810status=`expr $status + $ret` 811 812# Check the insecure.secure.example domain (insecurity proof) 813 814echo_i "checking 2-server insecurity proof ($n)" 815ret=0 816$DIG $DIGOPTS +noauth a.insecure.secure.example. @10.53.0.2 a \ 817 > dig.out.ns2.test$n || ret=1 818$DIG $DIGOPTS +noauth a.insecure.secure.example. @10.53.0.4 a \ 819 > dig.out.ns4.test$n || ret=1 820digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 821grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 822# Note - this is looking for failure, hence the && 823grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1 824n=`expr $n + 1` 825if [ $ret != 0 ]; then echo_i "failed"; fi 826status=`expr $status + $ret` 827 828# Check a negative response in insecure.secure.example 829 830echo_i "checking 2-server insecurity proof with a negative answer ($n)" 831ret=0 832$DIG $DIGOPTS q.insecure.secure.example. @10.53.0.2 a > dig.out.ns2.test$n \ 833 || ret=1 834$DIG $DIGOPTS q.insecure.secure.example. @10.53.0.4 a > dig.out.ns4.test$n \ 835 || ret=1 836digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 837grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 838# Note - this is looking for failure, hence the && 839grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1 840n=`expr $n + 1` 841if [ $ret != 0 ]; then echo_i "failed"; fi 842status=`expr $status + $ret` 843 844echo_i "checking security root query ($n)" 845ret=0 846$DIG $DIGOPTS . @10.53.0.4 key > dig.out.ns4.test$n || ret=1 847grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 848grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 849n=`expr $n + 1` 850if [ $ret != 0 ]; then echo_i "failed"; fi 851status=`expr $status + $ret` 852 853echo_i "checking positive validation RSASHA256 NSEC ($n)" 854ret=0 855$DIG $DIGOPTS +noauth a.rsasha256.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1 856$DIG $DIGOPTS +noauth a.rsasha256.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1 857digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 858grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 859n=`expr $n + 1` 860if [ $ret != 0 ]; then echo_i "failed"; fi 861status=`expr $status + $ret` 862 863echo_i "checking positive validation RSASHA512 NSEC ($n)" 864ret=0 865$DIG $DIGOPTS +noauth a.rsasha512.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1 866$DIG $DIGOPTS +noauth a.rsasha512.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1 867digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 868grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 869n=`expr $n + 1` 870if [ $ret != 0 ]; then echo_i "failed"; fi 871status=`expr $status + $ret` 872 873echo_i "checking that positive validation in a privately secure zone works ($n)" 874ret=0 875$DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.2 \ 876 > dig.out.ns2.test$n || ret=1 877$DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.4 \ 878 > dig.out.ns4.test$n || ret=1 879digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 880grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 881grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 882n=`expr $n + 1` 883if [ $ret != 0 ]; then echo_i "failed"; fi 884status=`expr $status + $ret` 885 886echo_i "checking that negative validation in a privately secure zone works ($n)" 887ret=0 888$DIG $DIGOPTS +noauth q.private.secure.example. a @10.53.0.2 \ 889 > dig.out.ns2.test$n || ret=1 890$DIG $DIGOPTS +noauth q.private.secure.example. a @10.53.0.4 \ 891 > dig.out.ns4.test$n || ret=1 892digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 893grep "NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 894# Note - this is looking for failure, hence the && 895grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1 896n=`expr $n + 1` 897if [ $ret != 0 ]; then echo_i "failed"; fi 898status=`expr $status + $ret` 899 900echo_i "checking privately secure to nxdomain works ($n)" 901ret=0 902$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.4 > dig.out.ns4.test$n || ret=1 903grep "NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1 904grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 905n=`expr $n + 1` 906if [ $ret != 0 ]; then echo_i "failed"; fi 907status=`expr $status + $ret` 908 909# Try validating with a revoked trusted key. 910# This should fail. 911 912echo_i "checking that validation returns insecure due to revoked trusted key ($n)" 913ret=0 914$DIG $DIGOPTS example. soa @10.53.0.5 > dig.out.ns5.test$n || ret=1 915grep "flags:.*; QUERY" dig.out.ns5.test$n > /dev/null || ret=1 916grep "flags:.* ad.*; QUERY" dig.out.ns5.test$n > /dev/null && ret=1 917n=`expr $n + 1` 918if [ $ret != 0 ]; then echo_i "failed"; fi 919status=`expr $status + $ret` 920 921echo_i "checking that revoked key is present ($n)" 922ret=0 923id=`cat rev.key` 924$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1 925grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null || ret=1 926n=`expr $n + 1` 927if [ $ret != 0 ]; then echo_i "failed"; fi 928status=`expr $status + $ret` 929 930echo_i "checking that revoked key self-signs ($n)" 931ret=0 932id=`cat rev.key` 933$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1 934grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null || ret=1 935n=`expr $n + 1` 936if [ $ret != 0 ]; then echo_i "failed"; fi 937status=`expr $status + $ret` 938 939echo_i "checking for unpublished key ($n)" 940ret=0 941id=$(keyfile_to_key_id "$(cat unpub.key)") 942$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1 943grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null && ret=1 944n=`expr $n + 1` 945if [ $ret != 0 ]; then echo_i "failed"; fi 946status=`expr $status + $ret` 947 948echo_i "checking for activated but unpublished key ($n)" 949ret=0 950id=$(keyfile_to_key_id "$(cat activate-now-publish-1day.key)") 951$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1 952grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null && ret=1 953n=`expr $n + 1` 954if [ $ret != 0 ]; then echo_i "failed"; fi 955status=`expr $status + $ret` 956 957echo_i "checking that standby key does not sign records ($n)" 958ret=0 959id=$(keyfile_to_key_id "$(cat standby.key)") 960$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1 961grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null && ret=1 962n=`expr $n + 1` 963if [ $ret != 0 ]; then echo_i "failed"; fi 964status=`expr $status + $ret` 965 966echo_i "checking that deactivated key does not sign records ($n)" 967ret=0 968id=$(keyfile_to_key_id "$(cat inact.key)") 969$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1 970grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null && ret=1 971n=`expr $n + 1` 972if [ $ret != 0 ]; then echo_i "failed"; fi 973status=`expr $status + $ret` 974 975echo_i "checking insertion of public-only key ($n)" 976ret=0 977id=$(keyfile_to_key_id "$(cat nopriv.key)") 978file="ns1/`cat nopriv.key`.key" 979keydata=`grep DNSKEY $file` 980$NSUPDATE > /dev/null 2>&1 <<END || status=1 981server 10.53.0.1 ${PORT} 982zone . 983ttl 3600 984update add $keydata 985send 986END 987sleep 1 988$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1 989grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null && ret=1 990n=`expr $n + 1` 991if [ $ret != 0 ]; then echo_i "failed"; fi 992status=`expr $status + $ret` 993 994echo_i "checking key deletion ($n)" 995ret=0 996id=$(keyfile_to_key_id "$(cat del.key)") 997$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1 998grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null && ret=1 999n=`expr $n + 1` 1000if [ $ret != 0 ]; then echo_i "failed"; fi 1001status=`expr $status + $ret` 1002 1003echo_i "checking secure-to-insecure transition, nsupdate ($n)" 1004ret=0 1005$NSUPDATE > /dev/null 2>&1 <<END || status=1 1006server 10.53.0.3 ${PORT} 1007zone secure-to-insecure.example 1008update delete secure-to-insecure.example dnskey 1009send 1010END 1011for i in 0 1 2 3 4 5 6 7 8 9; do 1012 ret=0 1013 $DIG $DIGOPTS axfr secure-to-insecure.example @10.53.0.3 > dig.out.ns3.test$n || ret=1 1014 egrep '(RRSIG|DNSKEY|NSEC)' dig.out.ns3.test$n > /dev/null && ret=1 1015 [ $ret -eq 0 ] && break 1016 echo_i "waiting ... ($i)" 1017 sleep 2 1018done 1019n=`expr $n + 1` 1020if [ $ret != 0 ]; then echo_i "failed"; fi 1021status=`expr $status + $ret` 1022 1023echo_i "checking secure-to-insecure transition, scheduled ($n)" 1024ret=0 1025file="ns3/`cat del1.key`.key" 1026$SETTIME -I now -D now $file > settime.out.test$n.1 || ret=1 1027file="ns3/`cat del2.key`.key" 1028$SETTIME -I now -D now $file > settime.out.test$n.2 || ret=1 1029($RNDCCMD 10.53.0.3 sign secure-to-insecure2.example. 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 1030for i in 0 1 2 3 4 5 6 7 8 9; do 1031 ret=0 1032 $DIG $DIGOPTS axfr secure-to-insecure2.example @10.53.0.3 > dig.out.ns3.test$n || ret=1 1033 egrep '(RRSIG|DNSKEY|NSEC3)' dig.out.ns3.test$n > /dev/null && ret=1 1034 [ $ret -eq 0 ] && break 1035 echo_i "waiting ... ($i)" 1036 sleep 2 1037done 1038n=`expr $n + 1` 1039if [ $ret != 0 ]; then echo_i "failed"; fi 1040status=`expr $status + $ret` 1041 1042echo_i "checking jitter in a newly signed NSEC3 zone ($n)" 1043ret=0 1044# Use DNS UPDATE to add an NSEC3PARAM record into the zone. 1045$NSUPDATE > nsupdate.out.test$n 2>&1 <<END || ret=1 1046server 10.53.0.3 ${PORT} 1047zone jitter.nsec3.example. 1048update add jitter.nsec3.example. 3600 NSEC3PARAM 1 0 10 BEEF 1049send 1050END 1051[ $ret != 0 ] && echo_i "error: dynamic update add NSEC3PARAM failed" 1052# Create DNSSEC keys in the zone directory. 1053$KEYGEN -a rsasha1 -3 -q -K ns3 jitter.nsec3.example > /dev/null 1054# Trigger zone signing. 1055($RNDCCMD 10.53.0.3 sign jitter.nsec3.example. 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 1056# Wait until zone has been signed. 1057check_if_nsec3param_exists() { 1058 $DIG $DIGOPTS NSEC3PARAM jitter.nsec3.example @10.53.0.3 > dig.out.ns3.1.test$n || return 1 1059 grep -q "^jitter\.nsec3\.example\..*NSEC3PARAM" dig.out.ns3.1.test$n || return 1 1060} 1061retry_quiet 40 check_if_nsec3param_exists || { 1062 echo_i "error: NSEC3PARAM not present yet" 1063 ret=1 1064} 1065$DIG $DIGOPTS AXFR jitter.nsec3.example @10.53.0.3 > dig.out.ns3.2.test$n || ret=1 1066# Check jitter distribution. 1067checkjitter dig.out.ns3.2.test$n || ret=1 1068n=`expr $n + 1` 1069if [ $ret != 0 ]; then echo_i "failed"; fi 1070status=`expr $status + $ret` 1071 1072echo_i "checking that serial number and RRSIGs are both updated (rt21045) ($n)" 1073ret=0 1074oldserial=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '$0 !~ /SOA/ {print $3}'` 1075oldinception=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '/SOA/ {print $6}' | sort -u` 1076 1077$KEYGEN -a rsasha1 -3 -q -K ns3 -P 0 -A +6d -I +38d -D +45d prepub.example > /dev/null 1078 1079($RNDCCMD 10.53.0.3 sign prepub.example 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 1080newserial=$oldserial 1081try=0 1082while [ $oldserial -eq $newserial -a $try -lt 42 ] 1083do 1084 newserial=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | 1085 awk '$0 !~ /SOA/ {print $3}'` 1086 sleep 1 1087 try=`expr $try + 1` 1088done 1089newinception=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '/SOA/ {print $6}' | sort -u` 1090#echo "$oldserial : $newserial" 1091#echo "$oldinception : $newinception" 1092 1093[ "$oldserial" = "$newserial" ] && ret=1 1094[ "$oldinception" = "$newinception" ] && ret=1 1095n=`expr $n + 1` 1096if [ $ret != 0 ]; then echo_i "failed"; fi 1097status=`expr $status + $ret` 1098 1099echo_i "preparing to test key change corner cases" 1100echo_i "removing a private key file" 1101file="ns1/`cat vanishing.key`.private" 1102rm -f $file 1103 1104echo_i "preparing ZSK roll" 1105starttime=`$PERL -e 'print time(), "\n";'` 1106oldfile=`cat active.key` 1107oldid=$(keyfile_to_key_id "$(cat active.key)") 1108newfile=`cat standby.key` 1109newid=$(keyfile_to_key_id "$(cat standby.key)") 1110$SETTIME -K ns1 -I now+2s -D now+25 $oldfile > settime.out.test$n.1 || ret=1 1111$SETTIME -K ns1 -i 0 -S $oldfile $newfile > settime.out.test$n.2 || ret=1 1112 1113# note previous zone serial number 1114oldserial=`$DIG $DIGOPTS +short soa . @10.53.0.1 | awk '{print $3}'` 1115 1116($RNDCCMD 10.53.0.1 loadkeys . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 1117sleep 4 1118 1119echo_i "revoking key to duplicated key ID" 1120$SETTIME -R now -K ns2 Kbar.+005+30676.key > settime.out.test$n.3 || ret=1 1121 1122($RNDCCMD 10.53.0.2 loadkeys bar. 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1 1123 1124echo_i "waiting for changes to take effect" 1125sleep 5 1126 1127echo_i "checking former standby key $newid is now active ($n)" 1128ret=0 1129$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1 1130grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1 1131n=`expr $n + 1` 1132if [ $ret != 0 ]; then echo_i "failed"; fi 1133status=`expr $status + $ret` 1134 1135echo_i "checking former standby key has only signed incrementally ($n)" 1136ret=0 1137$DIG $DIGOPTS txt . @10.53.0.1 > dig.out.ns1.test$n || ret=1 1138grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null && ret=1 1139grep 'RRSIG.*'" $oldid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1 1140n=`expr $n + 1` 1141if [ $ret != 0 ]; then echo_i "failed"; fi 1142status=`expr $status + $ret` 1143 1144echo_i "checking that signing records have been marked as complete ($n)" 1145ret=0 1146checkprivate . 10.53.0.1 || ret=1 1147checkprivate bar 10.53.0.2 || ret=1 1148checkprivate example 10.53.0.2 || ret=1 1149checkprivate private.secure.example 10.53.0.3 || ret=1 1150checkprivate nsec3.example 10.53.0.3 || ret=1 1151checkprivate nsec3.nsec3.example 10.53.0.3 || ret=1 1152checkprivate nsec3.optout.example 10.53.0.3 || ret=1 1153checkprivate nsec3-to-nsec.example 10.53.0.3 || ret=1 1154checkprivate nsec.example 10.53.0.3 || ret=1 1155checkprivate oldsigs.example 10.53.0.3 || ret=1 1156checkprivate optout.example 10.53.0.3 || ret=1 1157checkprivate optout.nsec3.example 10.53.0.3 || ret=1 1158checkprivate optout.optout.example 10.53.0.3 || ret=1 1159checkprivate prepub.example 10.53.0.3 1 || ret=1 1160checkprivate rsasha256.example 10.53.0.3 || ret=1 1161checkprivate rsasha512.example 10.53.0.3 || ret=1 1162checkprivate secure.example 10.53.0.3 || ret=1 1163checkprivate secure.nsec3.example 10.53.0.3 || ret=1 1164checkprivate secure.optout.example 10.53.0.3 || ret=1 1165checkprivate secure-to-insecure2.example 10.53.0.3 || ret=1 1166checkprivate secure-to-insecure.example 10.53.0.3 || ret=1 1167checkprivate ttl1.example 10.53.0.3 || ret=1 1168checkprivate ttl2.example 10.53.0.3 || ret=1 1169checkprivate ttl3.example 10.53.0.3 || ret=1 1170checkprivate ttl4.example 10.53.0.3 || ret=1 1171n=`expr $n + 1` 1172status=`expr $status + $ret` 1173 1174echo_i "forcing full sign" 1175($RNDCCMD 10.53.0.1 sign . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 1176 1177echo_i "waiting for change to take effect" 1178sleep 5 1179 1180echo_i "checking former standby key has now signed fully ($n)" 1181ret=0 1182$DIG $DIGOPTS txt . @10.53.0.1 > dig.out.ns1.test$n || ret=1 1183grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1 1184n=`expr $n + 1` 1185if [ $ret != 0 ]; then echo_i "failed"; fi 1186status=`expr $status + $ret` 1187 1188echo_i "checking SOA serial number has been incremented ($n)" 1189ret=0 1190newserial=`$DIG $DIGOPTS +short soa . @10.53.0.1 | awk '{print $3}'` 1191[ "$newserial" != "$oldserial" ] || ret=1 1192n=`expr $n + 1` 1193if [ $ret != 0 ]; then echo_i "failed"; fi 1194status=`expr $status + $ret` 1195 1196echo_i "checking delayed key publication/activation ($n)" 1197ret=0 1198zsk=`cat delayzsk.key` 1199ksk=`cat delayksk.key` 1200# publication and activation times should be unset 1201$SETTIME -K ns3 -pA -pP $zsk > settime.out.test$n.zsk || ret=1 1202grep -v UNSET settime.out.test$n.zsk >/dev/null && ret=1 1203$SETTIME -K ns3 -pA -pP $ksk > settime.out.test$n.ksk || ret=1 1204grep -v UNSET settime.out.test$n.ksk >/dev/null && ret=1 1205$DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1 1206# DNSKEY not expected: 1207awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.test$n && ret=1 1208n=`expr $n + 1` 1209if [ $ret != 0 ]; then echo_i "failed"; fi 1210status=`expr $status + $ret` 1211 1212echo_i "checking scheduled key publication, not activation ($n)" 1213ret=0 1214# Ensure initial zone is loaded. 1215wait_for_notifies "delay.example" "ns3" || ret=1 1216$SETTIME -K ns3 -P now+3s -A none $zsk > settime.out.test$n.zsk || ret=1 1217$SETTIME -K ns3 -P now+3s -A none $ksk > settime.out.test$n.ksk || ret=1 1218($RNDCCMD 10.53.0.3 loadkeys delay.example. 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1 1219echo_i "waiting for changes to take effect" 1220sleep 3 1221wait_for_notifies "delay.example" "ns3" || ret=1 1222 1223$DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1 1224# DNSKEY expected: 1225awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.test$n || ret=1 1226# RRSIG not expected: 1227awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.test$n && ret=1 1228n=`expr $n + 1` 1229if [ $ret != 0 ]; then echo_i "failed"; fi 1230status=`expr $status + $ret` 1231 1232echo_i "checking scheduled key activation ($n)" 1233ret=0 1234$SETTIME -K ns3 -A now+3s $zsk > settime.out.test$n.zsk || ret=1 1235$SETTIME -K ns3 -A now+3s $ksk > settime.out.test$n.ksk || ret=1 1236($RNDCCMD 10.53.0.3 loadkeys delay.example. 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1 1237echo_i "waiting for changes to take effect" 1238sleep 3 1239wait_for_log 10 "add delay\.example\..*NSEC.a\.delay\.example\. NS SOA RRSIG NSEC DNSKEY" ns3/named.run 1240check_is_signed() { 1241 $DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.1.test$n || return 1 1242 # DNSKEY expected: 1243 awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.1.test$n || return 1 1244 # RRSIG expected: 1245 awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.1.test$n || return 1 1246 $DIG $DIGOPTS +noall +answer a a.delay.example. @10.53.0.3 > dig.out.ns3.2.test$n || return 1 1247 # A expected: 1248 awk 'BEGIN {r=1} $4=="A" {r=0} END {exit r}' dig.out.ns3.2.test$n || return 1 1249 # RRSIG expected: 1250 awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.2.test$n || return 1 1251 return 0 1252} 1253retry_quiet 5 check_is_signed || ret=1 1254n=`expr $n + 1` 1255if [ $ret != 0 ]; then echo_i "failed"; fi 1256status=`expr $status + $ret` 1257 1258echo_i "checking former active key was removed ($n)" 1259# 1260# Work out how long we need to sleep. Allow 4 seconds for the records 1261# to be removed. 1262# 1263now=`$PERL -e 'print time(), "\n";'` 1264sleep=`expr $starttime + 29 - $now` 1265case $sleep in 1266-*|0);; 1267*) echo_i "waiting for timer to have activated"; sleep $sleep;; 1268esac 1269ret=0 1270$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1 1271grep '; key id = '"$oldid"'$' dig.out.ns1.test$n > /dev/null && ret=1 1272n=`expr $n + 1` 1273if [ $ret != 0 ]; then echo_i "failed"; fi 1274status=`expr $status + $ret` 1275 1276echo_i "checking private key file removal caused no immediate harm ($n)" 1277ret=0 1278id=$(keyfile_to_key_id "$(cat vanishing.key)") 1279$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1 1280grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null || ret=1 1281n=`expr $n + 1` 1282if [ $ret != 0 ]; then echo_i "failed"; fi 1283status=`expr $status + $ret` 1284 1285echo_i "checking revoked key with duplicate key ID (failure expected) ($n)" 1286lret=0 1287id=30676 1288$DIG $DIGOPTS +multi dnskey bar @10.53.0.2 > dig.out.ns2.test$n || lret=1 1289grep '; key id = '"$id"'$' dig.out.ns2.test$n > /dev/null || lret=1 1290$DIG $DIGOPTS dnskey bar @10.53.0.4 > dig.out.ns4.test$n || lret=1 1291grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || lret=1 1292n=`expr $n + 1` 1293if [ $lret != 0 ]; then echo_i "not yet implemented"; fi 1294 1295echo_i "checking key event timers are always set ($n)" 1296# this is a regression test for a bug in which the next key event could 1297# be scheduled for the present moment, and then never fire. check for 1298# visible evidence of this error in the logs: 1299awk '/next key event/ {if ($1 == $8 && $2 == $9) exit 1}' */named.run || ret=1 1300n=`expr $n + 1` 1301if [ $ret != 0 ]; then echo_i "failed"; fi 1302status=`expr $status + $ret` 1303 1304# this confirms that key events are never scheduled more than 1305# 'dnssec-loadkeys-interval' minutes in the future, and that the 1306# event scheduled is within 10 seconds of expected interval. 1307check_interval () { 1308 awk '/next key event/ {print $2 ":" $9}' $1/named.run | 1309 sed -e 's/\.//g' -e 's/:0\{1,4\}/:/g' | 1310 awk -F: ' 1311 { 1312 x = ($6+ $5*60000 + $4*3600000) - ($3+ $2*60000 + $1*3600000); 1313 # abs(x) < 1000 ms treat as 'now' 1314 if (x < 1000 && x > -1000) 1315 x = 0; 1316 # convert to seconds 1317 x = x/1000; 1318 # handle end of day roll over 1319 if (x < 0) 1320 x = x + 24*3600; 1321 # handle log timestamp being a few milliseconds later 1322 if (x != int(x)) 1323 x = int(x + 1); 1324 if (int(x) > int(interval)) 1325 exit (1); 1326 } 1327 END { if (int(x) > int(interval) || int(x) < int(interval-10)) exit(1) }' interval=$2 1328 return $? 1329} 1330 1331echo_i "checking automatic key reloading interval ($n)" 1332ret=0 1333check_interval ns1 3600 || ret=1 1334check_interval ns2 1800 || ret=1 1335check_interval ns3 600 || ret=1 1336n=`expr $n + 1` 1337if [ $ret != 0 ]; then echo_i "failed"; fi 1338status=`expr $status + $ret` 1339 1340echo_i "checking for key reloading loops ($n)" 1341ret=0 1342# every key event should schedule a successor, so these should be equal 1343rekey_calls=`grep "reconfiguring zone keys" ns*/named.run | wc -l` 1344rekey_events=`grep "next key event" ns*/named.run | wc -l` 1345[ "$rekey_calls" = "$rekey_events" ] || ret=1 1346n=`expr $n + 1` 1347if [ $ret != 0 ]; then echo_i "failed"; fi 1348status=`expr $status + $ret` 1349 1350echo_i "forcing full sign with unreadable keys ($n)" 1351ret=0 1352chmod 0 ns1/K.+*+*.key ns1/K.+*+*.private || ret=1 1353($RNDCCMD 10.53.0.1 sign . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 1354$DIG $DIGOPTS . @10.53.0.1 dnskey > dig.out.ns1.test$n || ret=1 1355grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1 1356n=`expr $n + 1` 1357if [ $ret != 0 ]; then echo_i "failed"; fi 1358status=`expr $status + $ret` 1359 1360echo_i "test turning on auto-dnssec during reconfig ($n)" 1361ret=0 1362# first create a zone that doesn't have auto-dnssec 1363($RNDCCMD 10.53.0.3 addzone reconf.example '{ type master; file "reconf.example.db"; };' 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 1364rekey_calls=`grep "zone reconf.example.*next key event" ns3/named.run | wc -l` 1365[ "$rekey_calls" -eq 0 ] || ret=1 1366# ...then we add auto-dnssec and reconfigure 1367($RNDCCMD 10.53.0.3 modzone reconf.example '{ type master; file "reconf.example.db"; allow-update { any; }; auto-dnssec maintain; };' 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 1368rndc_reconfig ns3 10.53.0.3 1369for i in 0 1 2 3 4 5 6 7 8 9; do 1370 lret=0 1371 rekey_calls=`grep "zone reconf.example.*next key event" ns3/named.run | wc -l` 1372 [ "$rekey_calls" -gt 0 ] || lret=1 1373 if [ "$lret" -eq 0 ]; then break; fi 1374 echo_i "waiting ... ($i)" 1375 sleep 1 1376done 1377n=`expr $n + 1` 1378if [ "$lret" != 0 ]; then ret=$lret; fi 1379if [ $ret != 0 ]; then echo_i "failed"; fi 1380status=`expr $status + $ret` 1381 1382echo_i "test CDS and CDNSKEY auto generation ($n)" 1383ret=0 1384$DIG $DIGOPTS @10.53.0.3 sync.example cds > dig.out.ns3.cdstest$n 1385$DIG $DIGOPTS @10.53.0.3 sync.example cdnskey > dig.out.ns3.cdnskeytest$n 1386grep -i "sync.example.*in.cds.*[1-9][0-9]* " dig.out.ns3.cdstest$n > /dev/null || ret=1 1387grep -i "sync.example.*in.cdnskey.*257 " dig.out.ns3.cdnskeytest$n > /dev/null || ret=1 1388n=`expr $n + 1` 1389if [ $ret != 0 ]; then echo_i "failed"; fi 1390status=`expr $status + $ret` 1391 1392echo_i "test 'dnssec-dnskey-kskonly no' affects DNSKEY/CDS/CDNSKEY ($n)" 1393ret=0 1394$DIG $DIGOPTS @10.53.0.3 sync.example dnskey > dig.out.ns3.dnskeytest$n 1395$DIG $DIGOPTS @10.53.0.3 sync.example cdnskey > dig.out.ns3.cdnskeytest$n 1396$DIG $DIGOPTS @10.53.0.3 sync.example cds > dig.out.ns3.cdstest$n 1397lines=`awk '$4 == "RRSIG" && $5 == "DNSKEY" {print}' dig.out.ns3.dnskeytest$n | wc -l` 1398test ${lines:-0} -eq 2 || ret=1 1399lines=`awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.ns3.cdnskeytest$n | wc -l` 1400test ${lines:-0} -eq 2 || ret=1 1401lines=`awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.ns3.cdstest$n | wc -l` 1402test ${lines:-0} -eq 2 || ret=1 1403n=`expr $n + 1` 1404if [ $ret != 0 ]; then echo_i "failed"; fi 1405status=`expr $status + $ret` 1406 1407echo_i "test 'dnssec-dnskey-kskonly yes' affects DNSKEY/CDS/CDNSKEY ($n)" 1408ret=0 1409$DIG $DIGOPTS @10.53.0.3 kskonly.example dnskey > dig.out.ns3.dnskeytest$n 1410$DIG $DIGOPTS @10.53.0.3 kskonly.example cdnskey > dig.out.ns3.cdnskeytest$n 1411$DIG $DIGOPTS @10.53.0.3 kskonly.example cds > dig.out.ns3.cdstest$n 1412lines=`awk '$4 == "RRSIG" && $5 == "DNSKEY" {print}' dig.out.ns3.dnskeytest$n | wc -l` 1413test ${lines:-0} -eq 1 || ret=1 1414lines=`awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.ns3.cdnskeytest$n | wc -l` 1415test ${lines:-0} -eq 1 || ret=1 1416lines=`awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.ns3.cdstest$n | wc -l` 1417test ${lines:-0} -eq 1 || ret=1 1418n=`expr $n + 1` 1419if [ $ret != 0 ]; then echo_i "failed"; fi 1420status=`expr $status + $ret` 1421 1422echo_i "setting CDS and CDNSKEY deletion times and calling 'rndc loadkeys'" 1423$SETTIME -D sync now `cat sync.key` > settime.out.test$n || ret=1 1424($RNDCCMD 10.53.0.3 loadkeys sync.example | sed 's/^/ns3 /' | cat_i) || ret=1 1425 1426echo_i "checking that the CDS and CDNSKEY are deleted ($n)" 1427ret=0 1428ensure_cds_and_cdnskey_are_deleted() { 1429 $DIG $DIGOPTS @10.53.0.3 sync.example. CDS > dig.out.ns3.cdstest$n || return 1 1430 awk '$1 == "sync.example." && $4 == "CDS" { exit 1; }' dig.out.ns3.cdstest$n || return 1 1431 $DIG $DIGOPTS @10.53.0.3 sync.example. CDNSKEY > dig.out.ns3.cdnskeytest$n || return 1 1432 awk '$1 == "sync.example." && $4 == "CDNSKEY" { exit 1; }' dig.out.ns3.cdnskeytest$n || return 1 1433} 1434retry 10 ensure_cds_and_cdnskey_are_deleted || ret=1 1435n=`expr $n + 1` 1436if [ $ret != 0 ]; then echo_i "failed"; fi 1437status=`expr $status + $ret` 1438 1439echo_i "check that dnssec-settime -p Dsync works ($n)" 1440ret=0 1441$SETTIME -p Dsync `cat sync.key` > settime.out.test$n || ret=1 1442grep "SYNC Delete:" settime.out.test$n >/dev/null || ret=1 1443n=`expr $n + 1` 1444if [ $ret != 0 ]; then echo_i "failed"; fi 1445status=`expr $status + $ret` 1446 1447echo_i "check that dnssec-settime -p Psync works ($n)" 1448ret=0 1449$SETTIME -p Psync `cat sync.key` > settime.out.test$n || ret=1 1450grep "SYNC Publish:" settime.out.test$n >/dev/null || ret=1 1451n=`expr $n + 1` 1452if [ $ret != 0 ]; then echo_i "failed"; fi 1453status=`expr $status + $ret` 1454 1455echo_i "check that zone with inactive KSK and active ZSK is properly autosigned ($n)" 1456ret=0 1457$DIG $DIGOPTS @10.53.0.3 axfr inacksk2.example > dig.out.ns3.test$n 1458 1459zskid=`awk '$4 == "DNSKEY" && $5 == 256 { print }' dig.out.ns3.test$n | 1460 $DSFROMKEY -A -2 -f - inacksk2.example | awk '{ print $4}' ` 1461pattern="DNSKEY 7 2 [0-9]* [0-9]* [0-9]* ${zskid} " 1462grep "${pattern}" dig.out.ns3.test$n > /dev/null || ret=1 1463 1464kskid=`awk '$4 == "DNSKEY" && $5 == 257 { print }' dig.out.ns3.test$n | 1465 $DSFROMKEY -2 -f - inacksk2.example | awk '{ print $4}' ` 1466pattern="DNSKEY 7 2 [0-9]* [0-9]* [0-9]* ${kskid} " 1467grep "${pattern}" dig.out.ns3.test$n > /dev/null && ret=1 1468 1469n=`expr $n + 1` 1470if [ $ret != 0 ]; then echo_i "failed"; fi 1471status=`expr $status + $ret` 1472 1473echo_i "check that zone with inactive ZSK and active KSK is properly autosigned ($n)" 1474ret=0 1475$DIG $DIGOPTS @10.53.0.3 axfr inaczsk2.example > dig.out.ns3.test$n 1476grep "SOA 7 2" dig.out.ns3.test$n > /dev/null || ret=1 1477n=`expr $n + 1` 1478if [ $ret != 0 ]; then echo_i "failed"; fi 1479status=`expr $status + $ret` 1480 1481# 1482# Check that DNSKEY is now signed with the ZSK. 1483# 1484echo_i "check that zone with active and inactive KSK and active ZSK is properly" 1485echo_ic "resigned after the active KSK is deleted - stage 2: Verify that DNSKEY" 1486echo_ic "is now signed with the ZSK. ($n)" 1487ret=0 1488 1489$DIG $DIGOPTS @10.53.0.3 axfr inacksk3.example > dig.out.ns3.test$n 1490 1491zskid=`awk '$4 == "DNSKEY" && $5 == 256 { print }' dig.out.ns3.test$n | 1492 $DSFROMKEY -A -2 -f - inacksk3.example | awk '{ print $4}' ` 1493pattern="DNSKEY 7 2 [0-9]* [0-9]* [0-9]* ${zskid} " 1494grep "${pattern}" dig.out.ns3.test$n > /dev/null || ret=1 1495 1496count=`awk 'BEGIN { count = 0 } 1497 $4 == "RRSIG" && $5 == "DNSKEY" { count++ } 1498 END {print count}' dig.out.ns3.test$n` 1499test $count -eq 1 || ret=1 1500 1501count=`awk 'BEGIN { count = 0 } 1502 $4 == "DNSKEY" { count++ } 1503 END {print count}' dig.out.ns3.test$n` 1504test $count -eq 2 || ret=1 1505 1506n=`expr $n + 1` 1507if [ $ret != 0 ]; then echo_i "failed"; fi 1508status=`expr $status + $ret` 1509 1510# 1511# Check that zone is now signed with the KSK. 1512# 1513echo_i "check that zone with active and inactive ZSK and active KSK is properly" 1514echo_ic "resigned after the active ZSK is deleted - stage 2: Verify that zone" 1515echo_ic "is now signed with the KSK. ($n)" 1516ret=0 1517$DIG $DIGOPTS @10.53.0.3 axfr inaczsk3.example > dig.out.ns3.test$n 1518kskid=`awk '$4 == "DNSKEY" && $5 == 257 { print }' dig.out.ns3.test$n | 1519 $DSFROMKEY -2 -f - inaczsk3.example | awk '{ print $4}' ` 1520grep "CNAME 7 3 [0-9]* [0-9]* [0-9]* ${kskid} " dig.out.ns3.test$n > /dev/null || ret=1 1521count=`awk 'BEGIN { count = 0 } 1522 $4 == "RRSIG" && $5 == "CNAME" { count++ } 1523 END {print count}' dig.out.ns3.test$n` 1524test $count -eq 1 || ret=1 1525count=`awk 'BEGIN { count = 0 } 1526 $4 == "DNSKEY" { count++ } 1527 END {print count}' dig.out.ns3.test$n` 1528test $count -eq 2 || ret=1 1529n=`expr $n + 1` 1530if [ $ret != 0 ]; then echo_i "failed"; fi 1531status=`expr $status + $ret` 1532 1533echo_i "checking for out-of-zone NSEC3 records after ZSK removal ($n)" 1534ret=0 1535# Switch the zone over to NSEC3 and wait until the transition is complete. 1536$RNDCCMD 10.53.0.3 signing -nsec3param 1 1 10 12345678 delzsk.example. > signing.out.1.test$n 2>&1 || ret=1 1537for i in 0 1 2 3 4 5 6 7 8 9; do 1538 _ret=1 1539 $DIG $DIGOPTS delzsk.example NSEC3PARAM @10.53.0.3 > dig.out.ns3.1.test$n 2>&1 || ret=1 1540 grep "NSEC3PARAM.*12345678" dig.out.ns3.1.test$n > /dev/null 2>&1 1541 if [ $? -eq 0 ]; then 1542 $RNDCCMD 10.53.0.3 signing -list delzsk.example > signing.out.2.test$n 2>&1 1543 grep "Creating NSEC3 chain " signing.out.2.test$n > /dev/null 2>&1 1544 if [ $? -ne 0 ]; then 1545 _ret=0 1546 break 1547 fi 1548 fi 1549 sleep 1 1550done 1551if [ $_ret -ne 0 ]; then 1552 echo_i "timed out waiting for NSEC3 chain creation" 1553 ret=1 1554fi 1555# Mark the inactive ZSK as pending removal. 1556file="ns3/`cat delzsk.key`.key" 1557$SETTIME -D now-1h $file > settime.out.test$n || ret=1 1558# Trigger removal of the inactive ZSK and wait until its completion. 1559($RNDCCMD 10.53.0.3 loadkeys delzsk.example 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 1560for i in 0 1 2 3 4 5 6 7 8 9; do 1561 _ret=1 1562 $RNDCCMD 10.53.0.3 signing -list delzsk.example > signing.out.3.test$n 2>&1 1563 grep "Signing " signing.out.3.test$n > /dev/null 2>&1 1564 if [ $? -ne 0 ]; then 1565 if [ `grep "Done signing " signing.out.3.test$n | wc -l` -eq 2 ]; then 1566 _ret=0 1567 break 1568 fi 1569 fi 1570 sleep 1 1571done 1572if [ $_ret -ne 0 ]; then 1573 echo_i "timed out waiting for key removal" 1574 ret=1 1575fi 1576# Check whether key removal caused NSEC3 records to be erroneously created for 1577# glue records due to a secure delegation already being signed by the active key 1578# (i.e. a key other than the one being removed but using the same algorithm). 1579# 1580# For reference: 1581# 1582# $ nsec3hash 12345678 1 10 ns.sub.delzsk.example. 1583# 589R358VSPJUFVAJU949JPVF74D9PTGH (salt=12345678, hash=1, iterations=10) 1584# 1585$DIG $DIGOPTS delzsk.example AXFR @10.53.0.3 > dig.out.ns3.3.test$n || ret=1 1586grep "589R358VSPJUFVAJU949JPVF74D9PTGH" dig.out.ns3.3.test$n > /dev/null 2>&1 && ret=1 1587n=`expr $n + 1` 1588if [ $ret != 0 ]; then echo_i "failed"; fi 1589status=`expr $status + $ret` 1590 1591echo_i "check that DNAME at apex with NSEC3 is correctly signed (auto-dnssec maintain) ($n)" 1592ret=0 1593$DIG $DIGOPTS txt dname-at-apex-nsec3.example @10.53.0.3 > dig.out.ns3.test$n || ret=1 1594grep "RRSIG NSEC3 7 3 3600" dig.out.ns3.test$n > /dev/null || ret=1 1595n=`expr $n + 1` 1596if [ $ret != 0 ]; then echo_i "failed"; fi 1597status=`expr $status + $ret` 1598 1599echo_i "checking that DNAME is not treated as a delegation when signing ($n)" 1600ret=0 1601$DIG $DIGOPTS dname-and-txt.secure.example. DNAME @10.53.0.3 > dig.out.ns3.1.test$n || ret=1 1602grep "dname-and-txt.secure.example.*RRSIG.*DNAME" dig.out.ns3.1.test$n > /dev/null 2>&1 || ret=1 1603$DIG $DIGOPTS dname-and-txt.secure.example. TXT @10.53.0.3 > dig.out.ns3.2.test$n || ret=1 1604grep "dname-and-txt.secure.example.*RRSIG.*TXT" dig.out.ns3.2.test$n > /dev/null 2>&1 || ret=1 1605n=`expr $n + 1` 1606if [ $ret != 0 ]; then echo_i "failed"; fi 1607status=`expr $status + $ret` 1608 1609echo_i "checking key maintenance events were logged correctly ($n)" 1610ret=0 1611pub=`grep "DNSKEY .* is now published" ns1/named.run | wc -l` 1612[ "$pub" -eq 6 ] || ret=1 1613act=`grep "DNSKEY .* is now active" ns1/named.run | wc -l` 1614[ "$act" -eq 5 ] || ret=1 1615rev=`grep "DNSKEY .* is now revoked" ns1/named.run | wc -l` 1616[ "$rev" -eq 1 ] || ret=1 1617inac=`grep "DNSKEY .* is now inactive" ns1/named.run | wc -l` 1618[ "$inac" -eq 1 ] || ret=1 1619del=`grep "DNSKEY .* is now deleted" ns1/named.run | wc -l` 1620[ "$del" -eq 1 ] || ret=1 1621if [ $ret != 0 ]; then echo_i "failed"; fi 1622status=`expr $status + $ret` 1623 1624echo_i "exit status: $status" 1625[ $status -eq 0 ] || exit 1 1626