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 https://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 15DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}" 16RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s" 17 18status=0 19n=0 20 21n=$((n+1)) 22echo_i "testing basic zone transfer functionality (from primary) ($n)" 23tmp=0 24$DIG $DIGOPTS example. @10.53.0.2 axfr > dig.out.ns2.test$n || tmp=1 25grep "^;" dig.out.ns2.test$n | cat_i 26digcomp dig1.good dig.out.ns2.test$n || tmp=1 27if test $tmp != 0 ; then echo_i "failed"; fi 28status=$((status+tmp)) 29 30n=$((n+1)) 31echo_i "testing basic zone transfer functionality (from secondary) ($n)" 32tmp=0 33# 34# Spin to allow the zone to transfer. 35# 36wait_for_xfer () { 37 $DIG $DIGOPTS example. @10.53.0.3 axfr > dig.out.ns3.test$n || return 1 38 grep "^;" dig.out.ns3.test$n > /dev/null && return 1 39 return 0 40} 41retry_quiet 25 wait_for_xfer || tmp=1 42grep "^;" dig.out.ns3.test$n | cat_i 43digcomp dig1.good dig.out.ns3.test$n || tmp=1 44if test $tmp != 0 ; then echo_i "failed"; fi 45status=$((status+tmp)) 46 47n=$((n+1)) 48echo_i "testing TSIG signed zone transfers ($n)" 49tmp=0 50$DIG $DIGOPTS tsigzone. @10.53.0.2 axfr -y tsigzone.:1234abcd8765 > dig.out.ns2.test$n || tmp=1 51grep "^;" dig.out.ns2.test$n | cat_i 52 53# 54# Spin to allow the zone to transfer. 55# 56wait_for_xfer_tsig () { 57 $DIG $DIGOPTS tsigzone. @10.53.0.3 axfr -y tsigzone.:1234abcd8765 > dig.out.ns3.test$n || return 1 58 grep "^;" dig.out.ns3.test$n > /dev/null && return 1 59 return 0 60} 61retry_quiet 25 wait_for_xfer_tsig || tmp=1 62grep "^;" dig.out.ns3.test$n | cat_i 63digcomp dig.out.ns2.test$n dig.out.ns3.test$n || tmp=1 64if test $tmp != 0 ; then echo_i "failed"; fi 65status=$((status+tmp)) 66 67echo_i "reload servers for in preparation for ixfr-from-differences tests" 68 69rndc_reload ns1 10.53.0.1 70rndc_reload ns2 10.53.0.2 71rndc_reload ns3 10.53.0.3 72rndc_reload ns6 10.53.0.6 73rndc_reload ns7 10.53.0.7 74 75sleep 2 76 77echo_i "updating primary zones for ixfr-from-differences tests" 78 79$PERL -i -p -e ' 80 s/0\.0\.0\.0/0.0.0.1/; 81 s/1397051952/1397051953/ 82' ns1/sec.db 83 84rndc_reload ns1 10.53.0.1 85 86$PERL -i -p -e ' 87 s/0\.0\.0\.0/0.0.0.1/; 88 s/1397051952/1397051953/ 89' ns2/example.db 90 91rndc_reload ns2 10.53.0.2 92 93$PERL -i -p -e ' 94 s/0\.0\.0\.0/0.0.0.1/; 95 s/1397051952/1397051953/ 96' ns6/primary.db 97 98rndc_reload ns6 10.53.0.6 99 100$PERL -i -p -e ' 101 s/0\.0\.0\.0/0.0.0.1/; 102 s/1397051952/1397051953/ 103' ns7/primary2.db 104 105rndc_reload ns7 10.53.0.7 106 107sleep 3 108 109n=$((n+1)) 110echo_i "testing zone is dumped after successful transfer ($n)" 111tmp=0 112$DIG $DIGOPTS +noall +answer +multi @10.53.0.2 \ 113 secondary. soa > dig.out.ns2.test$n || tmp=1 114grep "1397051952 ; serial" dig.out.ns2.test$n > /dev/null 2>&1 || tmp=1 115grep "1397051952 ; serial" ns2/sec.db > /dev/null 2>&1 || tmp=1 116if test $tmp != 0 ; then echo_i "failed"; fi 117status=$((status+tmp)) 118 119n=$((n+1)) 120echo_i "testing ixfr-from-differences yes; ($n)" 121tmp=0 122 123echo_i "wait for reloads..." 124wait_for_reloads() ( 125 $DIG $DIGOPTS @10.53.0.6 +noall +answer soa primary > dig.out.soa1.ns6.test$n 126 grep "1397051953" dig.out.soa1.ns6.test$n > /dev/null || return 1 127 $DIG $DIGOPTS @10.53.0.1 +noall +answer soa secondary > dig.out.soa2.ns1.test$n 128 grep "1397051953" dig.out.soa2.ns1.test$n > /dev/null || return 1 129 $DIG $DIGOPTS @10.53.0.2 +noall +answer soa example > dig.out.soa3.ns2.test$n 130 grep "1397051953" dig.out.soa3.ns2.test$n > /dev/null || return 1 131 return 0 132) 133retry_quiet 20 wait_for_reloads || tmp=1 134 135echo_i "wait for transfers..." 136wait_for_transfers() ( 137 a=0 b=0 c=0 d=0 138 $DIG $DIGOPTS @10.53.0.3 +noall +answer soa example > dig.out.soa1.ns3.test$n 139 grep "1397051953" dig.out.soa1.ns3.test$n > /dev/null && a=1 140 $DIG $DIGOPTS @10.53.0.3 +noall +answer soa primary > dig.out.soa2.ns3.test$n 141 grep "1397051953" dig.out.soa2.ns3.test$n > /dev/null && b=1 142 $DIG $DIGOPTS @10.53.0.6 +noall +answer soa secondary > dig.out.soa3.ns6.test$n 143 grep "1397051953" dig.out.soa3.ns6.test$n > /dev/null && c=1 144 [ $a -eq 1 -a $b -eq 1 -a $c -eq 1 ] && return 0 145 146 # re-notify if necessary 147 $RNDCCMD 10.53.0.6 notify primary 2>&1 | sed 's/^/ns6 /' | cat_i 148 $RNDCCMD 10.53.0.1 notify secondary 2>&1 | sed 's/^/ns1 /' | cat_i 149 $RNDCCMD 10.53.0.2 notify example 2>&1 | sed 's/^/ns2 /' | cat_i 150 return 1 151) 152retry_quiet 20 wait_for_transfers || tmp=1 153 154$DIG $DIGOPTS example. \ 155 @10.53.0.3 axfr > dig.out.ns3.test$n || tmp=1 156grep "^;" dig.out.ns3.test$n | cat_i 157 158digcomp dig2.good dig.out.ns3.test$n || tmp=1 159 160# ns3 has a journal iff it received an IXFR. 161test -f ns3/example.bk || tmp=1 162test -f ns3/example.bk.jnl || tmp=1 163 164if test $tmp != 0 ; then echo_i "failed"; fi 165status=$((status+tmp)) 166 167n=$((n+1)) 168echo_i "testing ixfr-from-differences primary; (primary zone) ($n)" 169tmp=0 170 171$DIG $DIGOPTS primary. \ 172 @10.53.0.6 axfr > dig.out.ns6.test$n || tmp=1 173grep "^;" dig.out.ns6.test$n | cat_i 174 175$DIG $DIGOPTS primary. \ 176 @10.53.0.3 axfr > dig.out.ns3.test$n || tmp=1 177grep "^;" dig.out.ns3.test$n > /dev/null && cat_i dig.out.ns3.test$n 178 179digcomp dig.out.ns6.test$n dig.out.ns3.test$n || tmp=1 180 181# ns3 has a journal iff it received an IXFR. 182test -f ns3/primary.bk || tmp=1 183test -f ns3/primary.bk.jnl || tmp=1 184 185if test $tmp != 0 ; then echo_i "failed"; fi 186status=$((status+tmp)) 187 188n=$((n+1)) 189echo_i "testing ixfr-from-differences primary; (secondary zone) ($n)" 190tmp=0 191 192$DIG $DIGOPTS secondary. \ 193 @10.53.0.6 axfr > dig.out.ns6.test$n || tmp=1 194grep "^;" dig.out.ns6.test$n | cat_i 195 196$DIG $DIGOPTS secondary. \ 197 @10.53.0.1 axfr > dig.out.ns1.test$n || tmp=1 198grep "^;" dig.out.ns1.test$n | cat_i 199 200digcomp dig.out.ns6.test$n dig.out.ns1.test$n || tmp=1 201 202# ns6 has a journal iff it received an IXFR. 203test -f ns6/sec.bk || tmp=1 204test -f ns6/sec.bk.jnl && tmp=1 205 206if test $tmp != 0 ; then echo_i "failed"; fi 207status=$((status+tmp)) 208 209n=$((n+1)) 210echo_i "testing ixfr-from-differences secondary; (secondary zone) ($n)" 211tmp=0 212 213# ns7 has a journal iff it generates an IXFR. 214test -f ns7/primary2.db || tmp=1 215test -f ns7/primary2.db.jnl && tmp=1 216 217if test $tmp != 0 ; then echo_i "failed"; fi 218status=$((status+tmp)) 219 220n=$((n+1)) 221echo_i "testing ixfr-from-differences secondary; (secondary zone) ($n)" 222tmp=0 223 224$DIG $DIGOPTS secondary. \ 225 @10.53.0.1 axfr > dig.out.ns1.test$n || tmp=1 226grep "^;" dig.out.ns1.test$n | cat_i 227 228$DIG $DIGOPTS secondary. \ 229 @10.53.0.7 axfr > dig.out.ns7.test$n || tmp=1 230grep "^;" dig.out.ns7.test$n | cat_i 231 232digcomp dig.out.ns7.test$n dig.out.ns1.test$n || tmp=1 233 234# ns7 has a journal iff it generates an IXFR. 235test -f ns7/sec.bk || tmp=1 236test -f ns7/sec.bk.jnl || tmp=1 237 238if test $tmp != 0 ; then echo_i "failed"; fi 239status=$((status+tmp)) 240 241n=$((n+1)) 242echo_i "check that a multi-message uncompressable zone transfers ($n)" 243$DIG axfr . -p ${PORT} @10.53.0.4 | grep SOA > axfr.out 244if test `wc -l < axfr.out` != 2 245then 246 echo_i "failed" 247 status=$((status+1)) 248fi 249 250# now we test transfers with assorted TSIG glitches 251DIGCMD="$DIG $DIGOPTS @10.53.0.4" 252SENDCMD="$PERL ../send.pl 10.53.0.5 $EXTRAPORT1" 253 254echo_i "testing that incorrectly signed transfers will fail..." 255n=$((n+1)) 256echo_i "initial correctly-signed transfer should succeed ($n)" 257 258$SENDCMD < ans5/goodaxfr 259 260# Initially, ns4 is not authoritative for anything. 261# Now that ans is up and running with the right data, we make ns4 262# a secondary for nil. 263 264cat <<EOF >>ns4/named.conf 265zone "nil" { 266 type secondary; 267 file "nil.db"; 268 primaries { 10.53.0.5 key tsig_key; }; 269}; 270EOF 271 272nextpart ns4/named.run >/dev/null 273 274rndc_reload ns4 10.53.0.4 275 276wait_for_soa() ( 277 $DIGCMD nil. SOA > dig.out.ns4.test$n 278 grep SOA dig.out.ns4.test$n > /dev/null 279) 280retry_quiet 10 wait_for_soa 281 282nextpart ns4/named.run | grep "Transfer status: success" > /dev/null || { 283 echo_i "failed: expected status was not logged" 284 status=$((status+1)) 285} 286 287$DIGCMD nil. TXT | grep 'initial AXFR' >/dev/null || { 288 echo_i "failed" 289 status=$((status+1)) 290} 291 292n=$((n+1)) 293echo_i "unsigned transfer ($n)" 294 295$SENDCMD < ans5/unsigned 296 297$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i 298 299sleep 2 300 301nextpart ns4/named.run | grep "Transfer status: expected a TSIG or SIG(0)" > /dev/null || { 302 echo_i "failed: expected status was not logged" 303 status=$((status+1)) 304} 305 306$DIGCMD nil. TXT | grep 'unsigned AXFR' >/dev/null && { 307 echo_i "failed" 308 status=$((status+1)) 309} 310 311n=$((n+1)) 312echo_i "bad keydata ($n)" 313 314$SENDCMD < ans5/badkeydata 315 316$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i 317 318sleep 2 319 320nextpart ns4/named.run | grep "Transfer status: tsig verify failure" > /dev/null || { 321 echo_i "failed: expected status was not logged" 322 status=$((status+1)) 323} 324 325$DIGCMD nil. TXT | grep 'bad keydata AXFR' >/dev/null && { 326 echo_i "failed" 327 status=$((status+1)) 328} 329 330n=$((n+1)) 331echo_i "partially-signed transfer ($n)" 332 333$SENDCMD < ans5/partial 334 335$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i 336 337sleep 2 338 339nextpart ns4/named.run | grep "Transfer status: expected a TSIG or SIG(0)" > /dev/null || { 340 echo_i "failed: expected status was not logged" 341 status=$((status+1)) 342} 343 344$DIGCMD nil. TXT | grep 'partially signed AXFR' >/dev/null && { 345 echo_i "failed" 346 status=$((status+1)) 347} 348 349n=$((n+1)) 350echo_i "unknown key ($n)" 351 352$SENDCMD < ans5/unknownkey 353 354$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i 355 356sleep 2 357 358nextpart ns4/named.run | grep "tsig key 'tsig_key': key name and algorithm do not match" > /dev/null || { 359 echo_i "failed: expected status was not logged" 360 status=$((status+1)) 361} 362 363$DIGCMD nil. TXT | grep 'unknown key AXFR' >/dev/null && { 364 echo_i "failed" 365 status=$((status+1)) 366} 367 368n=$((n+1)) 369echo_i "incorrect key ($n)" 370 371$SENDCMD < ans5/wrongkey 372 373$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i 374 375sleep 2 376 377nextpart ns4/named.run | grep "tsig key 'tsig_key': key name and algorithm do not match" > /dev/null || { 378 echo_i "failed: expected status was not logged" 379 status=$((status+1)) 380} 381 382$DIGCMD nil. TXT | grep 'incorrect key AXFR' >/dev/null && { 383 echo_i "failed" 384 status=$((status+1)) 385} 386 387n=$((n+1)) 388echo_i "bad message id ($n)" 389 390$SENDCMD < ans5/badmessageid 391 392# Uncomment to see AXFR stream with mismatching IDs. 393# $DIG $DIGOPTS @10.53.0.5 -y tsig_key:LSAnCU+Z nil. AXFR +all 394 395$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i 396 397sleep 2 398 399msg="detected message ID mismatch on incoming AXFR stream, transfer will fail in BIND 9.17.2 and later if AXFR source is not fixed" 400nextpart ns4/named.run | grep "$msg" > /dev/null || { 401 echo_i "failed: expected status was not logged" 402 status=$((status+1)) 403} 404 405$DIGCMD nil. TXT | grep 'bad message id' >/dev/null || { 406 echo_i "failed" 407 status=$((status+1)) 408} 409 410n=$((n+1)) 411echo_i "mismatched SOA ($n)" 412 413${SENDCMD} < ans5/soamismatch 414 415$RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i 416 417sleep 2 418 419nextpart ns4/named.run | grep "Transfer status: FORMERR" > /dev/null || { 420 echo_i "failed: expected status was not logged" 421 status=$((status+1)) 422} 423 424$DIGCMD nil. TXT | grep 'SOA mismatch AXFR' >/dev/null && { 425 echo_i "failed" 426 status=$((status+1)) 427} 428 429n=$((n+1)) 430echo_i "check that we ask for and get a EDNS EXPIRE response ($n)" 431# force a refresh query 432$RNDCCMD 10.53.0.7 refresh edns-expire 2>&1 | sed 's/^/ns7 /' | cat_i 433sleep 10 434 435# there may be multiple log entries so get the last one. 436expire=`awk '/edns-expire\/IN: got EDNS EXPIRE of/ { x=$9 } END { print x }' ns7/named.run` 437test ${expire:-0} -gt 0 -a ${expire:-0} -lt 1814400 || { 438 echo_i "failed (expire=${expire:-0})" 439 status=$((status+1)) 440} 441 442n=$((n+1)) 443echo_i "test smaller transfer TCP message size ($n)" 444$DIG $DIGOPTS example. @10.53.0.8 axfr \ 445 -y key1.:1234abcd8765 > dig.out.msgsize.test$n || status=1 446 447$DOS2UNIX dig.out.msgsize.test$n >/dev/null 2>&1 448 449bytes=`wc -c < dig.out.msgsize.test$n` 450if [ $bytes -ne 459357 ]; then 451 echo_i "failed axfr size check" 452 status=$((status+1)) 453fi 454 455num_messages=`cat ns8/named.run | grep "sending TCP message of" | wc -l` 456if [ $num_messages -le 300 ]; then 457 echo_i "failed transfer message count check" 458 status=$((status+1)) 459fi 460 461n=$((n+1)) 462echo_i "test mapped zone with out of zone data ($n)" 463tmp=0 464$DIG -p ${PORT} txt mapped @10.53.0.3 > dig.out.1.test$n 465grep "status: NOERROR," dig.out.1.test$n > /dev/null || tmp=1 466$PERL $SYSTEMTESTTOP/stop.pl xfer ns3 467$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} xfer ns3 468check_mapped () { 469 $DIG -p ${PORT} txt mapped @10.53.0.3 > dig.out.2.test$n 470 grep "status: NOERROR," dig.out.2.test$n > /dev/null || return 1 471 $DIG -p ${PORT} axfr mapped @10.53.0.3 > dig.out.3.test$n 472 digcomp knowngood.mapped dig.out.3.test$n || return 1 473 return 0 474} 475retry_quiet 10 check_mapped || tmp=1 476[ "$tmp" -ne 0 ] && echo_i "failed" 477status=$((status+tmp)) 478 479n=$((n+1)) 480echo_i "test that a zone with too many records is rejected (AXFR) ($n)" 481tmp=0 482grep "'axfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null || tmp=1 483if test $tmp != 0 ; then echo_i "failed"; fi 484status=$((status+tmp)) 485 486n=$((n+1)) 487echo_i "test that a zone with too many records is rejected (IXFR) ($n)" 488tmp=0 489nextpart ns6/named.run > /dev/null 490$NSUPDATE << EOF 491zone ixfr-too-big 492server 10.53.0.1 ${PORT} 493update add the-31st-record.ixfr-too-big 0 TXT this is it 494send 495EOF 496msg="'ixfr-too-big/IN' from 10.53.0.1#${PORT}: Transfer status: too many records" 497wait_for_log 10 "$msg" ns6/named.run || tmp=1 498if test $tmp != 0 ; then echo_i "failed"; fi 499status=$((status+tmp)) 500 501n=$((n+1)) 502echo_i "checking whether dig calculates AXFR statistics correctly ($n)" 503tmp=0 504# Loop until the secondary server manages to transfer the "xfer-stats" zone so 505# that we can both check dig output and immediately proceed with the next test. 506# Use -b so that we can discern between incoming and outgoing transfers in ns3 507# logs later on. 508wait_for_xfer() ( 509 $DIG $DIGOPTS +noedns +stat -b 10.53.0.2 @10.53.0.3 xfer-stats. AXFR > dig.out.ns3.test$n 510 grep "; Transfer failed" dig.out.ns3.test$n > /dev/null || return 0 511 return 1 512) 513if retry_quiet 10 wait_for_xfer; then 514 get_dig_xfer_stats dig.out.ns3.test$n > stats.dig 515 diff axfr-stats.good stats.dig || tmp=1 516else 517 echo_i "timed out waiting for zone transfer" 518fi 519if test $tmp != 0 ; then echo_i "failed"; fi 520status=$((status+tmp)) 521 522# Note: in the next two tests, we use ns3 logs for checking both incoming and 523# outgoing transfer statistics as ns3 is both a secondary server (for ns1) and a 524# primary server (for dig queries from the previous test) for "xfer-stats". 525n=$((n+1)) 526echo_i "checking whether named calculates incoming AXFR statistics correctly ($n)" 527tmp=0 528get_named_xfer_stats ns3/named.run 10.53.0.1 xfer-stats "Transfer completed" > stats.incoming 529diff axfr-stats.good stats.incoming || tmp=1 530if test $tmp != 0 ; then echo_i "failed"; fi 531status=$((status+tmp)) 532 533n=$((n+1)) 534echo_i "checking whether named calculates outgoing AXFR statistics correctly ($n)" 535tmp=0 536check_xfer_stats() { 537 get_named_xfer_stats ns3/named.run 10.53.0.2 xfer-stats "AXFR ended" > stats.outgoing 538 diff axfr-stats.good stats.outgoing > /dev/null 539} 540retry_quiet 10 check_xfer_stats || tmp=1 541if test $tmp != 0 ; then echo_i "failed"; fi 542status=$((status+tmp)) 543 544echo_i "exit status: $status" 545[ $status -eq 0 ] || exit 1 546