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 17DIGOPTS="-p ${PORT} -b 10.53.0.1 +dnssec +time=2 +tries=1 +multi" 18RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s" 19 20# Wait until the transfer of the given zone to ns3 either completes 21# successfully or is aborted by a verification failure or a REFUSED response 22# from the primary. Note that matching on any transfer status is deliberately 23# avoided because some checks performed by this test cause transfer attempts to 24# end with the "IXFR failed" status, which is followed by an AXFR retry and 25# this test needs to check what the result of the latter transfer attempt is. 26wait_for_transfer() { 27 zone=$1 28 for i in 1 2 3 4 5 6 7 8 9 10; do 29 # Wait until a "freeing transfer context" message is logged 30 # after one of the transfer results we are looking for is 31 # logged. This is needed to prevent races when checking for 32 # "mirror zone is now in use" messages. 33 nextpartpeek ns3/named.run | \ 34 awk "matched; /'$zone\/IN'.*Transfer status: (success|verify failure|REFUSED)/ {matched=1}" | \ 35 grep "'$zone/IN'.*freeing transfer context" > /dev/null && return 36 sleep 1 37 done 38 echo_i "exceeded time limit waiting for proof of '$zone' being transferred to appear in ns3/named.run" 39 ret=1 40} 41 42# Wait until loading the given zone on the given server either completes 43# successfully for the specified serial number or fails. 44wait_for_load() { 45 zone=$1 46 serial=$2 47 log=$3 48 for i in 1 2 3 4 5 6 7 8 9 10; do 49 # Wait until a "zone_postload: (...): done" message is logged 50 # after one of the loading-related messages we are looking for 51 # is logged. This is needed to prevent races when checking for 52 # "mirror zone is now in use" messages. 53 nextpartpeek $log | \ 54 awk "matched; /$zone.*(loaded serial $serial|unable to load)/ {matched=1}" | \ 55 grep "zone_postload: zone $zone/IN: done" > /dev/null && return 56 sleep 1 57 done 58 echo_i "exceeded time limit waiting for proof of '$zone' being loaded to appear in $log" 59 ret=1 60} 61 62# Trigger a reload of ns2 and wait until loading the given zone completes. 63reload_zone() { 64 zone=$1 65 serial=$2 66 rndc_reload ns2 10.53.0.2 67 wait_for_load $zone $serial ns2/named.run 68} 69 70status=0 71n=0 72 73ORIGINAL_SERIAL=`awk '$2 == "SOA" {print $5}' ns2/verify.db.in` 74UPDATED_SERIAL_BAD=`expr ${ORIGINAL_SERIAL} + 1` 75UPDATED_SERIAL_GOOD=`expr ${ORIGINAL_SERIAL} + 2` 76 77n=`expr $n + 1` 78echo_i "checking that an unsigned mirror zone is rejected ($n)" 79ret=0 80wait_for_transfer verify-unsigned 81$DIG $DIGOPTS @10.53.0.3 +norec verify-unsigned SOA > dig.out.ns3.test$n 2>&1 || ret=1 82grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1 83grep "${ORIGINAL_SERIAL}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1 84nextpartpeek ns3/named.run | grep "verify-unsigned.*Zone contains no DNSSEC keys" > /dev/null || ret=1 85nextpartpeek ns3/named.run | grep "verify-unsigned.*mirror zone is now in use" > /dev/null && ret=1 86if [ $ret != 0 ]; then echo_i "failed"; fi 87status=`expr $status + $ret` 88 89n=`expr $n + 1` 90echo_i "checking that a mirror zone signed using an untrusted key is rejected ($n)" 91ret=0 92nextpartreset ns3/named.run 93wait_for_transfer verify-untrusted 94$DIG $DIGOPTS @10.53.0.3 +norec verify-untrusted SOA > dig.out.ns3.test$n 2>&1 || ret=1 95grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1 96grep "${ORIGINAL_SERIAL}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1 97nextpartpeek ns3/named.run | grep "verify-untrusted.*No trusted DNSKEY found" > /dev/null || ret=1 98nextpartpeek ns3/named.run | grep "verify-untrusted.*mirror zone is now in use" > /dev/null && ret=1 99if [ $ret != 0 ]; then echo_i "failed"; fi 100status=`expr $status + $ret` 101 102n=`expr $n + 1` 103echo_i "checking that a mirror zone signed using a CSK without the SEP bit set is accepted ($n)" 104ret=0 105nextpartreset ns3/named.run 106wait_for_transfer verify-csk 107$DIG $DIGOPTS @10.53.0.3 +norec verify-csk SOA > dig.out.ns3.test$n 2>&1 || ret=1 108grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1 109grep "${ORIGINAL_SERIAL}.*; serial" dig.out.ns3.test$n > /dev/null || ret=1 110nextpartpeek ns3/named.run | grep "verify-csk.*mirror zone is now in use" > /dev/null || ret=1 111if [ $ret != 0 ]; then echo_i "failed"; fi 112status=`expr $status + $ret` 113 114n=`expr $n + 1` 115echo_i "checking that an AXFR of an incorrectly signed mirror zone is rejected ($n)" 116ret=0 117nextpartreset ns3/named.run 118wait_for_transfer verify-axfr 119$DIG $DIGOPTS @10.53.0.3 +norec verify-axfr SOA > dig.out.ns3.test$n 2>&1 || ret=1 120grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1 121grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1 122nextpartpeek ns3/named.run | grep "No correct RSASHA256 signature for verify-axfr SOA" > /dev/null || ret=1 123nextpartpeek ns3/named.run | grep "verify-axfr.*mirror zone is now in use" > /dev/null && ret=1 124if [ $ret != 0 ]; then echo_i "failed"; fi 125status=`expr $status + $ret` 126 127n=`expr $n + 1` 128echo_i "checking that an AXFR of an updated, correctly signed mirror zone is accepted ($n)" 129ret=0 130nextpart ns3/named.run > /dev/null 131cat ns2/verify-axfr.db.good.signed > ns2/verify-axfr.db.signed 132reload_zone verify-axfr ${UPDATED_SERIAL_GOOD} 133$RNDCCMD 10.53.0.3 retransfer verify-axfr > /dev/null 2>&1 134wait_for_transfer verify-axfr 135$DIG $DIGOPTS @10.53.0.3 +norec verify-axfr SOA > dig.out.ns3.test$n 2>&1 || ret=1 136grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1 137grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n > /dev/null || ret=1 138nextpartpeek ns3/named.run | grep "verify-axfr.*mirror zone is now in use" > /dev/null || ret=1 139if [ $ret != 0 ]; then echo_i "failed"; fi 140status=`expr $status + $ret` 141 142n=`expr $n + 1` 143echo_i "checking that an IXFR of an incorrectly signed mirror zone is rejected ($n)" 144nextpartreset ns3/named.run 145ret=0 146wait_for_transfer verify-ixfr 147# Sanity check: the initial, properly signed version of the zone should have 148# been announced as coming into effect. 149nextpart ns3/named.run | grep "verify-ixfr.*mirror zone is now in use" > /dev/null || ret=1 150# Make a copy of the original zone file for reuse in journal tests below. 151cp ns2/verify-ixfr.db.signed ns3/verify-journal.db.mirror 152# Wait 1 second so that the zone file timestamp changes and the subsequent 153# invocation of "rndc reload" triggers a zone reload. 154sleep 1 155cat ns2/verify-ixfr.db.bad.signed > ns2/verify-ixfr.db.signed 156reload_zone verify-ixfr ${UPDATED_SERIAL_BAD} 157# Make a copy of the bad zone journal for reuse in journal tests below. 158cp ns2/verify-ixfr.db.signed.jnl ns3/verify-journal.db.bad.mirror.jnl 159# Trigger IXFR. 160$RNDCCMD 10.53.0.3 refresh verify-ixfr > /dev/null 2>&1 161wait_for_transfer verify-ixfr 162# Ensure the transfer was incremental as expected. 163if [ `nextpartpeek ns3/named.run | grep "verify-ixfr.*got incremental response" | wc -l` -eq 0 ]; then 164 echo_i "failed: did not get an incremental response" 165 ret=1 166fi 167# Ensure the new, bad version of the zone was not accepted. 168$DIG $DIGOPTS @10.53.0.3 +norec verify-ixfr SOA > dig.out.ns3.test$n 2>&1 || ret=1 169# A positive answer is expected as the original version of the "verify-ixfr" 170# zone should have been successfully verified. 171grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1 172grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1 173nextpartpeek ns3/named.run | grep "No correct RSASHA256 signature for verify-ixfr SOA" > /dev/null || ret=1 174# Despite the verification failure for this IXFR, this mirror zone should still 175# be in use as its previous version should have been verified successfully. 176nextpartpeek ns3/named.run | grep "verify-ixfr.*mirror zone is no longer in use" > /dev/null && ret=1 177if [ $ret != 0 ]; then echo_i "failed"; fi 178status=`expr $status + $ret` 179 180n=`expr $n + 1` 181echo_i "checking that an IXFR of an updated, correctly signed mirror zone is accepted after AXFR failover ($n)" 182ret=0 183nextpart ns3/named.run > /dev/null 184# Wait 1 second so that the zone file timestamp changes and the subsequent 185# invocation of "rndc reload" triggers a zone reload. 186sleep 1 187cat ns2/verify-ixfr.db.good.signed > ns2/verify-ixfr.db.signed 188reload_zone verify-ixfr ${UPDATED_SERIAL_GOOD} 189# Make a copy of the good zone journal for reuse in journal tests below. 190cp ns2/verify-ixfr.db.signed.jnl ns3/verify-journal.db.good.mirror.jnl 191# Trigger IXFR. 192$RNDCCMD 10.53.0.3 refresh verify-ixfr > /dev/null 2>&1 193wait_for_transfer verify-ixfr 194# Ensure the new, good version of the zone was accepted. 195$DIG $DIGOPTS @10.53.0.3 +norec verify-ixfr SOA > dig.out.ns3.test$n 2>&1 || ret=1 196grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1 197grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n > /dev/null || ret=1 198# The log message announcing the mirror zone coming into effect should not have 199# been logged this time since the mirror zone in question is expected to 200# already be in use before this test case is checked. 201nextpartpeek ns3/named.run | grep "verify-ixfr.*mirror zone is now in use" > /dev/null && ret=1 202if [ $ret != 0 ]; then echo_i "failed"; fi 203status=`expr $status + $ret` 204 205n=`expr $n + 1` 206echo_i "checking that loading an incorrectly signed mirror zone from disk fails ($n)" 207ret=0 208nextpartreset ns3/named.run 209wait_for_load verify-load ${UPDATED_SERIAL_BAD} ns3/named.run 210$DIG $DIGOPTS @10.53.0.3 +norec verify-load SOA > dig.out.ns3.test$n 2>&1 || ret=1 211grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1 212grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1 213nextpartpeek ns3/named.run | grep "No correct RSASHA256 signature for verify-load SOA" > /dev/null || ret=1 214nextpartpeek ns3/named.run | grep "verify-load.*mirror zone is now in use" > /dev/null && ret=1 215if [ $ret != 0 ]; then echo_i "failed"; fi 216status=`expr $status + $ret` 217 218n=`expr $n + 1` 219echo_i "ensuring trust anchor telemetry queries are sent upstream for a mirror zone ($n)" 220ret=0 221# ns3 is started with "-T tat=3", so TAT queries should have already been sent. 222grep "_ta-[-0-9a-f]*/NULL" ns1/named.run > /dev/null || ret=1 223if [ $ret != 0 ]; then echo_i "failed"; fi 224status=`expr $status + $ret` 225 226n=`expr $n + 1` 227echo_i "checking that loading a correctly signed mirror zone from disk succeeds ($n)" 228ret=0 229$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port ${CONTROLPORT} mirror ns3 230cat ns2/verify-load.db.good.signed > ns3/verify-load.db.mirror 231nextpart ns3/named.run > /dev/null 232$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} mirror ns3 233wait_for_load verify-load ${UPDATED_SERIAL_GOOD} ns3/named.run 234$DIG $DIGOPTS @10.53.0.3 +norec verify-load SOA > dig.out.ns3.test$n 2>&1 || ret=1 235grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1 236grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n > /dev/null || ret=1 237nextpartpeek ns3/named.run | grep "verify-load.*mirror zone is now in use" > /dev/null || ret=1 238if [ $ret != 0 ]; then echo_i "failed"; fi 239status=`expr $status + $ret` 240 241n=`expr $n + 1` 242echo_i "checking that loading a journal for an incorrectly signed mirror zone fails ($n)" 243ret=0 244$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port ${CONTROLPORT} mirror ns3 245cp ns3/verify-journal.db.mirror ns3/verify-ixfr.db.mirror 246cp ns3/verify-journal.db.bad.mirror.jnl ns3/verify-ixfr.db.mirror.jnl 247# Temporarily disable transfers of the "verify-ixfr" zone on ns2. This is 248# required to reliably test whether the message announcing the mirror zone 249# coming into effect is not logged after a failed journal verification since 250# otherwise a corrected version of the zone may be transferred after 251# verification fails but before we look for the aforementioned log message. 252# (NOTE: Keep the embedded newline in the sed function list below.) 253sed '/^zone "verify-ixfr" {$/,/^};$/ { 254 s/10.53.0.3/10.53.0.254/ 255}' ns2/named.conf > ns2/named.conf.modified 256mv ns2/named.conf.modified ns2/named.conf 257rndc_reconfig ns2 10.53.0.2 258nextpart ns3/named.run > /dev/null 259$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} mirror ns3 260wait_for_load verify-ixfr ${UPDATED_SERIAL_BAD} ns3/named.run 261$DIG $DIGOPTS @10.53.0.3 +norec verify-ixfr SOA > dig.out.ns3.test$n 2>&1 || ret=1 262grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1 263grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1 264nextpartpeek ns3/named.run | grep "No correct RSASHA256 signature for verify-ixfr SOA" > /dev/null || ret=1 265nextpartpeek ns3/named.run | grep "verify-ixfr.*mirror zone is now in use" > /dev/null && ret=1 266# Restore transfers for the "verify-ixfr" zone on ns2. 267# (NOTE: Keep the embedded newline in the sed function list below.) 268sed '/^zone "verify-ixfr" {$/,/^};$/ { 269 s/10.53.0.254/10.53.0.3/ 270}' ns2/named.conf > ns2/named.conf.modified 271mv ns2/named.conf.modified ns2/named.conf 272rndc_reconfig ns2 10.53.0.2 273if [ $ret != 0 ]; then echo_i "failed"; fi 274status=`expr $status + $ret` 275 276n=`expr $n + 1` 277echo_i "checking that loading a journal for a correctly signed mirror zone succeeds ($n)" 278ret=0 279$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port ${CONTROLPORT} mirror ns3 280cp ns3/verify-journal.db.mirror ns3/verify-ixfr.db.mirror 281cp ns3/verify-journal.db.good.mirror.jnl ns3/verify-ixfr.db.mirror.jnl 282nextpart ns3/named.run > /dev/null 283$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} mirror ns3 284wait_for_load verify-ixfr ${UPDATED_SERIAL_GOOD} ns3/named.run 285$DIG $DIGOPTS @10.53.0.3 +norec verify-ixfr SOA > dig.out.ns3.test$n 2>&1 || ret=1 286grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1 287grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n > /dev/null || ret=1 288nextpartpeek ns3/named.run | grep "verify-ixfr.*mirror zone is now in use" > /dev/null || ret=1 289if [ $ret != 0 ]; then echo_i "failed"; fi 290status=`expr $status + $ret` 291 292n=`expr $n + 1` 293echo_i "checking delegations sourced from a mirror zone ($n)" 294ret=0 295$DIG $DIGOPTS @10.53.0.3 foo.example A +norec > dig.out.ns3.test$n 2>&1 || ret=1 296# Check response code and flags in the answer. 297grep "NOERROR" dig.out.ns3.test$n > /dev/null || ret=1 298grep "flags:.* ad" dig.out.ns3.test$n > /dev/null && ret=1 299# Check that a delegation containing a DS RRset and glue is present. 300grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null || ret=1 301grep "example.*IN.*NS" dig.out.ns3.test$n > /dev/null || ret=1 302grep "example.*IN.*DS" dig.out.ns3.test$n > /dev/null || ret=1 303grep "ns2.example.*A.*10.53.0.2" dig.out.ns3.test$n > /dev/null || ret=1 304if [ $ret != 0 ]; then echo_i "failed"; fi 305status=`expr $status + $ret` 306 307n=`expr $n + 1` 308echo_i "checking that resolution involving a mirror zone works as expected ($n)" 309ret=0 310$DIG $DIGOPTS @10.53.0.3 foo.example A > dig.out.ns3.test$n 2>&1 || ret=1 311# Check response code and flags in the answer. 312grep "NOERROR" dig.out.ns3.test$n > /dev/null || ret=1 313grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1 314# Ensure ns1 was not queried. 315grep "query 'foo.example/A/IN'" ns1/named.run > /dev/null && ret=1 316if [ $ret != 0 ]; then echo_i "failed"; fi 317status=`expr $status + $ret` 318 319n=`expr $n + 1` 320echo_i "checking that non-recursive queries for names below mirror zone get responded from cache ($n)" 321ret=0 322# Issue a non-recursive query for an RRset which is expected to be in cache. 323$DIG $DIGOPTS @10.53.0.3 +norec foo.example. A > dig.out.ns3.test$n 2>&1 || ret=1 324# Check response code and flags in the answer. 325grep "NOERROR" dig.out.ns3.test$n > /dev/null || ret=1 326grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1 327# Ensure the response is not a delegation. 328grep "ANSWER: 0" dig.out.ns3.test$n > /dev/null && ret=1 329grep "foo.example.*IN.*A.*127.0.0.1" dig.out.ns3.test$n > /dev/null || ret=1 330if [ $ret != 0 ]; then echo_i "failed"; fi 331status=`expr $status + $ret` 332 333n=`expr $n + 1` 334echo_i "checking that delegations from cache which improve mirror zone delegations are properly handled ($n)" 335ret=0 336# First, issue a recursive query in order to cache an RRset which is not within 337# the mirror zone's bailiwick. 338$DIG $DIGOPTS @10.53.0.3 sub.example. NS > dig.out.ns3.test$n.1 2>&1 || ret=1 339# Ensure the child-side NS RRset is returned. 340grep "NOERROR" dig.out.ns3.test$n.1 > /dev/null || ret=1 341grep "ANSWER: 2" dig.out.ns3.test$n.1 > /dev/null || ret=1 342grep "sub.example.*IN.*NS" dig.out.ns3.test$n.1 > /dev/null || ret=1 343# Issue a non-recursive query for something below the cached zone cut. 344$DIG $DIGOPTS @10.53.0.3 +norec foo.sub.example. A > dig.out.ns3.test$n.2 2>&1 || ret=1 345# Ensure the cached NS RRset is returned in a delegation, along with the 346# parent-side DS RRset. 347grep "NOERROR" dig.out.ns3.test$n.2 > /dev/null || ret=1 348grep "ANSWER: 0" dig.out.ns3.test$n.2 > /dev/null || ret=1 349grep "sub.example.*IN.*NS" dig.out.ns3.test$n.2 > /dev/null || ret=1 350grep "sub.example.*IN.*DS" dig.out.ns3.test$n.2 > /dev/null || ret=1 351if [ $ret != 0 ]; then echo_i "failed"; fi 352status=`expr $status + $ret` 353 354n=`expr $n + 1` 355echo_i "checking flags set in a DNSKEY response sourced from a mirror zone ($n)" 356ret=0 357$DIG $DIGOPTS @10.53.0.3 . DNSKEY > dig.out.ns3.test$n 2>&1 || ret=1 358# Check response code and flags in the answer. 359grep "NOERROR" dig.out.ns3.test$n > /dev/null || ret=1 360grep "flags:.* aa" dig.out.ns3.test$n > /dev/null && ret=1 361grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1 362if [ $ret != 0 ]; then echo_i "failed"; fi 363status=`expr $status + $ret` 364 365n=`expr $n + 1` 366echo_i "checking flags set in a SOA response sourced from a mirror zone ($n)" 367ret=0 368$DIG $DIGOPTS @10.53.0.3 . SOA > dig.out.ns3.test$n 2>&1 || ret=1 369# Check response code and flags in the answer. 370grep "NOERROR" dig.out.ns3.test$n > /dev/null || ret=1 371grep "flags:.* aa" dig.out.ns3.test$n > /dev/null && ret=1 372grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1 373if [ $ret != 0 ]; then echo_i "failed"; fi 374status=`expr $status + $ret` 375 376n=`expr $n + 1` 377echo_i "checking that resolution succeeds with unavailable mirror zone data ($n)" 378ret=0 379wait_for_transfer initially-unavailable 380# Query for a record in a zone that is set up to be mirrored, but 381# untransferrable from the configured primary. Resolution should still succeed. 382$DIG $DIGOPTS @10.53.0.3 foo.initially-unavailable. A > dig.out.ns3.test$n.1 2>&1 || ret=1 383# Check response code and flags in the answer. 384grep "NOERROR" dig.out.ns3.test$n.1 > /dev/null || ret=1 385grep "flags:.* ad" dig.out.ns3.test$n.1 > /dev/null || ret=1 386# Sanity check: the authoritative server should have been queried. 387nextpart ns2/named.run | grep "query 'foo.initially-unavailable/A/IN'" > /dev/null || ret=1 388# Reconfigure ns2 so that the zone can be mirrored on ns3. 389sed '/^zone "initially-unavailable" {$/,/^};$/ { 390 s/10.53.0.254/10.53.0.3/ 391}' ns2/named.conf > ns2/named.conf.modified 392mv ns2/named.conf.modified ns2/named.conf 393rndc_reconfig ns2 10.53.0.2 394# Flush the cache on ns3 and retransfer the mirror zone. 395$RNDCCMD 10.53.0.3 flush > /dev/null 2>&1 396nextpart ns3/named.run > /dev/null 397$RNDCCMD 10.53.0.3 retransfer initially-unavailable > /dev/null 2>&1 398wait_for_transfer initially-unavailable 399# Query for the same record again. Resolution should still succeed. 400$DIG $DIGOPTS @10.53.0.3 foo.initially-unavailable. A > dig.out.ns3.test$n.2 2>&1 || ret=1 401# Check response code and flags in the answer. 402grep "NOERROR" dig.out.ns3.test$n.2 > /dev/null || ret=1 403grep "flags:.* ad" dig.out.ns3.test$n.2 > /dev/null || ret=1 404# Ensure the authoritative server was not queried. 405nextpart ns2/named.run | grep "query 'foo.initially-unavailable/A/IN'" > /dev/null && ret=1 406if [ $ret != 0 ]; then echo_i "failed"; fi 407status=`expr $status + $ret` 408 409n=`expr $n + 1` 410echo_i "checking that resolution succeeds with expired mirror zone data ($n)" 411ret=0 412# Reconfigure ns2 so that the zone from the previous test can no longer be 413# mirrored on ns3. 414sed '/^zone "initially-unavailable" {$/,/^};$/ { 415 s/10.53.0.3/10.53.0.254/ 416}' ns2/named.conf > ns2/named.conf.modified 417mv ns2/named.conf.modified ns2/named.conf 418rndc_reconfig ns2 10.53.0.2 419# Stop ns3, update the timestamp of the zone file to one far in the past, then 420# restart ns3. 421$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port ${CONTROLPORT} mirror ns3 422touch -t 200001010000 ns3/initially-unavailable.db.mirror 423nextpart ns3/named.run > /dev/null 424$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} mirror ns3 425# Ensure named attempts to retransfer the zone due to its expiry. 426wait_for_transfer initially-unavailable 427# Ensure the expected messages were logged. 428nextpartpeek ns3/named.run | grep "initially-unavailable.*expired" > /dev/null || ret=1 429nextpartpeek ns3/named.run | grep "initially-unavailable.*mirror zone is no longer in use" > /dev/null || ret=1 430# Query for a record in the expired zone. Resolution should still succeed. 431$DIG $DIGOPTS @10.53.0.3 foo.initially-unavailable. A > dig.out.ns3.test$n 2>&1 || ret=1 432# Check response code and flags in the answer. 433grep "NOERROR" dig.out.ns3.test$n > /dev/null || ret=1 434grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1 435# Sanity check: the authoritative server should have been queried. 436nextpart ns2/named.run | grep "query 'foo.initially-unavailable/A/IN'" > /dev/null || ret=1 437if [ $ret != 0 ]; then echo_i "failed"; fi 438status=`expr $status + $ret` 439 440n=`expr $n + 1` 441echo_i "checking that clients without cache access cannot retrieve mirror zone data ($n)" 442ret=0 443$DIG $DIGOPTS @10.53.0.3 -b 10.53.0.3 +norec . SOA > dig.out.ns3.test$n 2>&1 || ret=1 444# Check response code and flags in the answer. 445grep "REFUSED" dig.out.ns3.test$n > /dev/null || ret=1 446grep "flags:.* ad" dig.out.ns3.test$n > /dev/null && ret=1 447if [ $ret != 0 ]; then echo_i "failed"; fi 448status=`expr $status + $ret` 449 450n=`expr $n + 1` 451echo_i "checking that outgoing transfers of mirror zones are disabled by default ($n)" 452ret=0 453$DIG $DIGOPTS @10.53.0.3 . AXFR > dig.out.ns3.test$n 2>&1 || ret=1 454grep "; Transfer failed" dig.out.ns3.test$n > /dev/null || ret=1 455if [ $ret != 0 ]; then echo_i "failed"; fi 456status=`expr $status + $ret` 457 458n=`expr $n + 1` 459echo_i "checking that notifies are disabled by default for mirror zones ($n)" 460ret=0 461grep "initially-unavailable.*sending notifies" ns3/named.run > /dev/null && ret=1 462if [ $ret != 0 ]; then echo_i "failed"; fi 463status=`expr $status + $ret` 464 465n=`expr $n + 1` 466echo_i "checking output of \"rndc zonestatus\" for a mirror zone ($n)" 467ret=0 468$RNDCCMD 10.53.0.3 zonestatus . > rndc.out.ns3.test$n 2>&1 469grep "type: mirror" rndc.out.ns3.test$n > /dev/null || ret=1 470if [ $ret != 0 ]; then echo_i "failed"; fi 471status=`expr $status + $ret` 472 473n=`expr $n + 1` 474echo_i "checking that \"rndc reconfig\" properly handles a mirror -> secondary zone type change ($n)" 475ret=0 476# Sanity check before we start. 477$DIG $DIGOPTS @10.53.0.3 +norec verify-reconfig SOA > dig.out.ns3.test$n.1 2>&1 || ret=1 478grep "NOERROR" dig.out.ns3.test$n.1 > /dev/null || ret=1 479grep "flags:.* aa" dig.out.ns3.test$n.1 > /dev/null && ret=1 480grep "flags:.* ad" dig.out.ns3.test$n.1 > /dev/null || ret=1 481# Reconfigure the zone so that it is no longer a mirror zone. 482# (NOTE: Keep the embedded newline in the sed function list below.) 483sed '/^zone "verify-reconfig" {$/,/^};$/ { 484 s/type mirror;/type secondary;/ 485}' ns3/named.conf > ns3/named.conf.modified 486mv ns3/named.conf.modified ns3/named.conf 487nextpart ns3/named.run > /dev/null 488rndc_reconfig ns3 10.53.0.3 489# Zones whose type was changed should not be reusable, which means the tested 490# zone should have been reloaded from disk. 491wait_for_load verify-reconfig ${ORIGINAL_SERIAL} ns3/named.run 492# Ensure responses sourced from the reconfigured zone have AA=1 and AD=0. 493$DIG $DIGOPTS @10.53.0.3 +norec verify-reconfig SOA > dig.out.ns3.test$n.2 2>&1 || ret=1 494grep "NOERROR" dig.out.ns3.test$n.2 > /dev/null || ret=1 495grep "flags:.* aa" dig.out.ns3.test$n.2 > /dev/null || ret=1 496grep "flags:.* ad" dig.out.ns3.test$n.2 > /dev/null && ret=1 497if [ $ret != 0 ]; then echo_i "failed"; fi 498status=`expr $status + $ret` 499 500n=`expr $n + 1` 501echo_i "checking that \"rndc reconfig\" properly handles a secondary -> mirror zone type change ($n)" 502ret=0 503# Put an incorrectly signed version of the zone in the zone file used by ns3. 504nextpart ns3/named.run > /dev/null 505cat ns2/verify-reconfig.db.bad.signed > ns3/verify-reconfig.db.mirror 506# Reconfigure the zone so that it is a mirror zone again. 507# (NOTE: Keep the embedded newline in the sed function list below.) 508sed '/^zone "verify-reconfig" {$/,/^};$/ { 509 s/type secondary;/type mirror;/ 510}' ns3/named.conf > ns3/named.conf.modified 511mv ns3/named.conf.modified ns3/named.conf 512rndc_reconfig ns3 10.53.0.3 513# The reconfigured zone should fail verification. 514wait_for_load verify-reconfig ${UPDATED_SERIAL_BAD} ns3/named.run 515$DIG $DIGOPTS @10.53.0.3 +norec verify-reconfig SOA > dig.out.ns3.test$n 2>&1 || ret=1 516grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1 517nextpart ns3/named.run | grep "No correct RSASHA256 signature for verify-reconfig SOA" > /dev/null || ret=1 518if [ $ret != 0 ]; then echo_i "failed"; fi 519status=`expr $status + $ret` 520 521n=`expr $n + 1` 522echo_i "checking that a mirror zone can be added using rndc ($n)" 523ret=0 524# Sanity check: the zone should not exist in the root zone. 525$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA > dig.out.ns3.test$n.1 2>&1 || ret=1 526grep "NXDOMAIN" dig.out.ns3.test$n.1 > /dev/null || ret=1 527grep "flags:.* aa" dig.out.ns3.test$n.1 > /dev/null && ret=1 528grep "flags:.* ad" dig.out.ns3.test$n.1 > /dev/null || ret=1 529# Mirror a zone which does not exist in the root zone. 530nextpart ns3/named.run > /dev/null 531$RNDCCMD 10.53.0.3 addzone verify-addzone '{ type mirror; primaries { 10.53.0.2; }; };' > rndc.out.ns3.test$n 2>&1 || ret=1 532wait_for_transfer verify-addzone 533# Check whether the mirror zone was added and whether it behaves as expected. 534$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA > dig.out.ns3.test$n.2 2>&1 || ret=1 535grep "NOERROR" dig.out.ns3.test$n.2 > /dev/null || ret=1 536grep "flags:.* aa" dig.out.ns3.test$n.2 > /dev/null && ret=1 537grep "flags:.* ad" dig.out.ns3.test$n.2 > /dev/null || ret=1 538if [ $ret != 0 ]; then echo_i "failed"; fi 539status=`expr $status + $ret` 540 541n=`expr $n + 1` 542echo_i "checking that a mirror zone can be deleted using rndc ($n)" 543ret=0 544# Remove the mirror zone added in the previous test. 545nextpart ns3/named.run > /dev/null 546$RNDCCMD 10.53.0.3 delzone verify-addzone > rndc.out.ns3.test$n 2>&1 || ret=1 547wait_for_log 20 "zone verify-addzone/IN: mirror zone is no longer in use; reverting to normal recursion" ns3/named.run || ret=1 548# Check whether the mirror zone was removed. 549$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA > dig.out.ns3.test$n 2>&1 || ret=1 550grep "NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1 551grep "flags:.* aa" dig.out.ns3.test$n > /dev/null && ret=1 552grep "flags:.* ad" dig.out.ns3.test$n > /dev/null || ret=1 553if [ $ret != 0 ]; then echo_i "failed"; fi 554status=`expr $status + $ret` 555 556echo_i "exit status: $status" 557[ $status -eq 0 ] || exit 1 558