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