From: Michał Kępień Date: Thu, 28 Jun 2018 11:38:39 +0000 (+0200) Subject: Verify mirror zone AXFRs X-Git-Tag: v9.13.2~7^2~18 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=d86f1d00ada08ef043e422b8a2e154b9d7554daa;p=thirdparty%2Fbind9.git Verify mirror zone AXFRs Update axfr_commit() so that all incoming versions of a mirror zone transferred using AXFR are verified before being used. If zone verification fails, discard the received version of the zone, wait until the next refresh and retry. --- diff --git a/bin/tests/system/mirror/clean.sh b/bin/tests/system/mirror/clean.sh index 983f1ac2734..e856da15213 100644 --- a/bin/tests/system/mirror/clean.sh +++ b/bin/tests/system/mirror/clean.sh @@ -8,5 +8,13 @@ # information regarding copyright ownership. rm -f */*.conf +rm -f */*.db +rm -f */*.mirror +rm -f */*.prev +rm -f */*.signed +rm -f */K* +rm -f */db-* +rm -f */dsset-* rm -f */named.memstats rm -f */named.run +rm -f dig.out.* diff --git a/bin/tests/system/mirror/ns2/named.conf.in b/bin/tests/system/mirror/ns2/named.conf.in index f8208e82a7a..04803c27acc 100644 --- a/bin/tests/system/mirror/ns2/named.conf.in +++ b/bin/tests/system/mirror/ns2/named.conf.in @@ -9,6 +9,15 @@ * information regarding copyright ownership. */ +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + options { query-source address 10.53.0.2; notify-source 10.53.0.2; @@ -19,3 +28,18 @@ options { listen-on-v6 { none; }; recursion no; }; + +zone "verify-axfr" { + type master; + file "verify-axfr.db.signed"; +}; + +zone "verify-unsigned" { + type master; + file "verify.db.in"; +}; + +zone "verify-untrusted" { + type master; + file "verify-untrusted.db.signed"; +}; diff --git a/bin/tests/system/mirror/ns2/sign.sh b/bin/tests/system/mirror/ns2/sign.sh new file mode 100644 index 00000000000..df40ab7165c --- /dev/null +++ b/bin/tests/system/mirror/ns2/sign.sh @@ -0,0 +1,48 @@ +#!/bin/sh -e +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +SYSTEMTESTTOP=../.. +. $SYSTEMTESTTOP/conf.sh + +keys_to_trust="" + +ORIGINAL_SERIAL=`awk '$2 == "SOA" {print $5}' verify.db.in` +UPDATED_SERIAL_BAD=`expr ${ORIGINAL_SERIAL} + 1` +UPDATED_SERIAL_GOOD=`expr ${ORIGINAL_SERIAL} + 2` + +for variant in axfr untrusted; do + zone=verify-$variant + infile=verify.db.in + zonefile=verify-$variant.db + + keyname1=`$KEYGEN -a RSASHA256 -f KSK $zone 2> /dev/null` + keyname2=`$KEYGEN -a RSASHA256 $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key > $zonefile + + # Prepare a properly signed version of the zone ("*.original.signed"). + $SIGNER -P -o $zone $zonefile > /dev/null + cp $zonefile.signed $zonefile.original.signed + # Prepare a version of the zone with a bogus SOA RRSIG ("*.bad.signed"). + sed "s/${ORIGINAL_SERIAL}/${UPDATED_SERIAL_BAD}/;" $zonefile.signed > $zonefile.bad.signed + # Prepare another properly signed version of the zone ("*.good.signed"). + sed "s/${ORIGINAL_SERIAL}/${UPDATED_SERIAL_GOOD}/;" $zonefile > $zonefile.good + $SIGNER -P -o $zone $zonefile.good > /dev/null + rm -f $zonefile.good + + # Except for the "verify-untrusted" zone, declare the KSK used for + # signing the zone to be a trust anchor for ns3. + if [ "$variant" != "untrusted" ]; then + keys_to_trust="$keys_to_trust $keyname1" + fi +done + +keyfile_to_trusted_keys $keys_to_trust > trusted-mirror.conf diff --git a/bin/tests/system/mirror/ns2/verify.db.in b/bin/tests/system/mirror/ns2/verify.db.in new file mode 100644 index 00000000000..dbee4c7ebd6 --- /dev/null +++ b/bin/tests/system/mirror/ns2/verify.db.in @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns2 hostmaster 2000010100 3600 1200 604800 3600 +@ NS ns2 +ns2 A 10.53.0.2 diff --git a/bin/tests/system/mirror/ns3/named.conf.in b/bin/tests/system/mirror/ns3/named.conf.in index 4d6b2ad5c5d..5452695f028 100644 --- a/bin/tests/system/mirror/ns3/named.conf.in +++ b/bin/tests/system/mirror/ns3/named.conf.in @@ -9,6 +9,15 @@ * information regarding copyright ownership. */ +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + options { query-source address 10.53.0.3; notify-source 10.53.0.3; @@ -24,3 +33,26 @@ zone "." { type hint; file "../../common/root.hint"; }; + +zone "verify-axfr" { + type slave; + masters { 10.53.0.2; }; + mirror yes; + file "verify-axfr.db.mirror"; +}; + +zone "verify-unsigned" { + type slave; + masters { 10.53.0.2; }; + mirror yes; + file "verify-unsigned.db.mirror"; +}; + +zone "verify-untrusted" { + type slave; + masters { 10.53.0.2; }; + mirror yes; + file "verify-untrusted.db.mirror"; +}; + +include "../ns2/trusted-mirror.conf"; diff --git a/bin/tests/system/mirror/setup.sh b/bin/tests/system/mirror/setup.sh index 5093722efe0..9204787cb6f 100644 --- a/bin/tests/system/mirror/setup.sh +++ b/bin/tests/system/mirror/setup.sh @@ -17,3 +17,8 @@ $SHELL clean.sh copy_setports ns1/named.conf.in ns1/named.conf copy_setports ns2/named.conf.in ns2/named.conf copy_setports ns3/named.conf.in ns3/named.conf + +( cd ns2 && $SHELL -e sign.sh ) + +cat ns2/verify-axfr.db.bad.signed > ns2/verify-axfr.db.signed +cat ns2/verify-untrusted.db.original.signed > ns2/verify-untrusted.db.signed diff --git a/bin/tests/system/mirror/tests.sh b/bin/tests/system/mirror/tests.sh index fdc0eda190e..a6e0417a969 100644 --- a/bin/tests/system/mirror/tests.sh +++ b/bin/tests/system/mirror/tests.sh @@ -12,6 +12,7 @@ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh +DIGOPTS="-p ${PORT} +dnssec +time=1 +tries=1 +multi" RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s" # Wait until the transfer of the given zone to ns3 either completes successfully @@ -51,5 +52,54 @@ reload_zone() { status=0 n=0 +ORIGINAL_SERIAL=`awk '$2 == "SOA" {print $5}' ns2/verify.db.in` +UPDATED_SERIAL_BAD=`expr ${ORIGINAL_SERIAL} + 1` +UPDATED_SERIAL_GOOD=`expr ${ORIGINAL_SERIAL} + 2` + +n=`expr $n + 1` +echo_i "checking that an unsigned mirror zone is rejected ($n)" +ret=0 +wait_for_transfer verify-unsigned +$DIG $DIGOPTS @10.53.0.3 +norec verify-unsigned SOA > dig.out.ns3.test$n 2>&1 || ret=1 +grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1 +nextpart ns3/named.run | grep "verify-unsigned.*Zone contains no DNSSEC keys" > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "checking that a mirror zone signed using an untrusted key is rejected ($n)" +ret=0 +nextpartreset ns3/named.run +wait_for_transfer verify-untrusted +$DIG $DIGOPTS @10.53.0.3 +norec verify-untrusted SOA > dig.out.ns3.test$n 2>&1 || ret=1 +grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1 +nextpart ns3/named.run | grep "verify-untrusted.*No trusted KSK DNSKEY found" > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "checking that an AXFR of an incorrectly signed mirror zone is rejected ($n)" +ret=0 +nextpartreset ns3/named.run +wait_for_transfer verify-axfr +$DIG $DIGOPTS @10.53.0.3 +norec verify-axfr SOA > dig.out.ns3.test$n 2>&1 || ret=1 +grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n > /dev/null && ret=1 +nextpart ns3/named.run | grep "No correct RSASHA256 signature for verify-axfr SOA" > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo_i "checking that an AXFR of an updated, correctly signed mirror zone is accepted ($n)" +ret=0 +nextpart ns3/named.run > /dev/null +cat ns2/verify-axfr.db.good.signed > ns2/verify-axfr.db.signed +reload_zone verify-axfr ${UPDATED_SERIAL_GOOD} +$RNDCCMD 10.53.0.3 retransfer verify-axfr > /dev/null 2>&1 +wait_for_transfer verify-axfr +$DIG $DIGOPTS @10.53.0.3 +norec verify-axfr SOA > dig.out.ns3.test$n 2>&1 || ret=1 +grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index b3186bc67e2..6fad0b84037 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -334,6 +334,7 @@ axfr_commit(dns_xfrin_ctx_t *xfr) { CHECK(axfr_apply(xfr)); CHECK(dns_db_endload(xfr->db, &xfr->axfr)); + CHECK(dns_zone_verifydb(xfr->zone, xfr->db, NULL)); result = ISC_R_SUCCESS; failure: diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 2f4f15464e1..667a83466e5 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15305,6 +15305,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) { goto same_master; case DNS_R_TOOMANYRECORDS: + case DNS_R_VERIFYFAILURE: DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime); inc_stats(zone, dns_zonestatscounter_xfrfail); break; diff --git a/util/copyrights b/util/copyrights index b87da463e4d..ef2bbb0a3d0 100644 --- a/util/copyrights +++ b/util/copyrights @@ -1599,6 +1599,8 @@ ./bin/tests/system/mirror/ns1/named.conf.in CONF-C 2018 ./bin/tests/system/mirror/ns1/root.db.in ZONE 2018 ./bin/tests/system/mirror/ns2/named.conf.in CONF-C 2018 +./bin/tests/system/mirror/ns2/sign.sh SH 2018 +./bin/tests/system/mirror/ns2/verify.db.in ZONE 2018 ./bin/tests/system/mirror/ns3/named.conf.in CONF-C 2018 ./bin/tests/system/mirror/setup.sh SH 2018 ./bin/tests/system/mirror/tests.sh SH 2018