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