diff --git a/CHANGES b/CHANGES index 42c817c08c..0cd2051c12 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,11 @@ - --- 9.13.7 released --- +5168. [bug] Do not crash on shutdown when RPZ fails to load. Also, + keep previous version of the database if RPZ fails to + load. [GL #813] + +5167. [bug] nxdomain-redirect could sometimes lookup the wrong + redirect name. [GL #892] + +5166. [placeholder] 5165. [contrib] Removed SDB drivers from contrib; they're obsolete. [GL #428] diff --git a/bin/tests/system/rpz/README b/bin/tests/system/rpz/README new file mode 100644 index 0000000000..51517b2fc7 --- /dev/null +++ b/bin/tests/system/rpz/README @@ -0,0 +1,29 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +See COPYRIGHT in the source root or http://isc.org/copyright.html for terms. + +The test setup for the RPZ tests prepares a query perf tool and sets up +policy zones. + +Name servers +------------ + +ns1 is the root server. + +ns2 and ns4 are authoritative servers for the various test domains. + +ns3 is the main rewriting resolver. + +ns5 and ns7 are additional rewriting resolvers. + +ns6 is a forwarding server. + + +Updating the response policy zones +---------------------------------- + +test1, test2, test3, test4, test5, and test6 are dynamic update files. These +updates are made against ns3. The script function "start_group" is called to +start an new batch of tests that may depend on certain server updates. The +function takes an optional file name and if provided the server updates are +performed before executing the test batch. diff --git a/bin/tests/system/rpz/clean.sh b/bin/tests/system/rpz/clean.sh index cf38807b6a..e0bdf5a74c 100644 --- a/bin/tests/system/rpz/clean.sh +++ b/bin/tests/system/rpz/clean.sh @@ -30,6 +30,7 @@ fi rm -f ns*/*.key ns*/*.private rm -f ns2/tld2s.db ns2/bl.tld2.db rm -f ns3/bl*.db ns*/empty.db +rm -f ns3/manual-update-rpz.db rm -f ns5/example.db ns5/bl.db rm -f */policy2.db rm -f */*.jnl diff --git a/bin/tests/system/rpz/ns3/broken.db.in b/bin/tests/system/rpz/ns3/broken.db.in new file mode 100644 index 0000000000..671ed38a7f --- /dev/null +++ b/bin/tests/system/rpz/ns3/broken.db.in @@ -0,0 +1,16 @@ +; 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. + +; RPZ test +; This basic file is copied to several zone files before being used. +; Its contents are also changed with nsupdate + + +; broken zone +foobar diff --git a/bin/tests/system/rpz/ns3/manual-update-rpz-2.db.in b/bin/tests/system/rpz/ns3/manual-update-rpz-2.db.in new file mode 100644 index 0000000000..5c82651802 --- /dev/null +++ b/bin/tests/system/rpz/ns3/manual-update-rpz-2.db.in @@ -0,0 +1,20 @@ +; 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. + +; RPZ test +; This basic file is copied to several zone files before being used. +; Its contents are also changed with nsupdate + + +$TTL 300 +@ SOA bl-reload. hostmaster.ns.bl-reload. ( 2 3600 1200 604800 60 ) + NS ns.tld3. + +walled.tld2.bl-reload. 300 A 10.0.0.2 + diff --git a/bin/tests/system/rpz/ns3/manual-update-rpz.db.in b/bin/tests/system/rpz/ns3/manual-update-rpz.db.in new file mode 100644 index 0000000000..81fa1f0754 --- /dev/null +++ b/bin/tests/system/rpz/ns3/manual-update-rpz.db.in @@ -0,0 +1,20 @@ +; 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. + +; RPZ test +; This basic file is copied to several zone files before being used. +; Its contents are also changed with nsupdate + + +$TTL 300 +@ SOA manual-update-rpz. hostmaster.ns.manual-rpz-update. ( 1 3600 1200 604800 60 ) + NS ns.tld3. + +walled.tld2.manual-update-rpz. 300 A 10.0.0.1 + diff --git a/bin/tests/system/rpz/ns3/named.conf.in b/bin/tests/system/rpz/ns3/named.conf.in index 851a055bc9..bd1a7103c3 100644 --- a/bin/tests/system/rpz/ns3/named.conf.in +++ b/bin/tests/system/rpz/ns3/named.conf.in @@ -44,6 +44,7 @@ options { zone "bl-drop" policy drop; zone "bl-tcp-only" policy tcp-only; zone "bl.tld2"; + zone "manual-update-rpz"; } min-ns-dots 0 qname-wait-recurse yes @@ -102,3 +103,9 @@ zone "bl.tld2." {type slave; file "bl.tld2.db"; masters {10.53.0.2;}; zone "crash1.tld2" {type master; file "crash1"; notify no;}; zone "crash2.tld3." {type master; file "crash2"; notify no;}; + +zone "manual-update-rpz." { + type master; + file "manual-update-rpz.db"; + notify no; +}; diff --git a/bin/tests/system/rpz/setup.sh b/bin/tests/system/rpz/setup.sh index b873f2aaf9..0a6665c1fd 100644 --- a/bin/tests/system/rpz/setup.sh +++ b/bin/tests/system/rpz/setup.sh @@ -68,8 +68,13 @@ test -z "`grep 'dnsrps-enable yes' dnsrps.conf`" && TEST_DNSRPS= for NM in '' -2 -given -disabled -passthru -no-op -nodata -nxdomain -cname -wildcname -garden -drop -tcp-only; do sed -e "/SOA/s/blx/bl$NM/g" ns3/base.db >ns3/bl$NM.db done +# bl zones are dynamically updated. Add one zone that is updated manually. +cp ns3/manual-update-rpz.db.in ns3/manual-update-rpz.db -# $1=directory, $2=domain name, $3=input zone file, $4=output file +# $1=directory +# $2=domain name +# $3=input zone file +# $4=output file signzone () { KEYNAME=`$KEYGEN -q -a rsasha256 -K $1 $2` cat $1/$3 $1/$KEYNAME.key > $1/tmp @@ -80,7 +85,6 @@ signzone () { } signzone ns2 tld2s. base-tld2s.db tld2s.db - # Performance and a few other checks. cat <ns5/rpz-switch response-policy { diff --git a/bin/tests/system/rpz/tests.sh b/bin/tests/system/rpz/tests.sh index 40f303e477..b6ba574360 100644 --- a/bin/tests/system/rpz/tests.sh +++ b/bin/tests/system/rpz/tests.sh @@ -106,7 +106,8 @@ setret () { } # set $SN to the SOA serial number of a zone -# $1=domain $2=DNS server and client IP address +# $1=domain +# $2=DNS server and client IP address get_sn() { SOA=`$DIG -p ${PORT} +short +norecurse soa "$1" "@$2" "-b$2"` SN=`expr "$SOA" : '[^ ]* [^ ]* \([^ ]*\) .*'` @@ -125,7 +126,8 @@ get_sn_fast () { } # check that dnsrpzd has loaded its zones -# $1=domain $2=DNS server IP address +# $1=domain +# $2=DNS server IP address FZONES=`sed -n -e 's/^zone "\(.*\)".*\(10.53.0..\).*/Z=\1;M=\2/p' dnsrpzd.conf` dnsrps_loaded() { test "$mode" = dnsrps || return @@ -150,8 +152,10 @@ dnsrps_loaded() { } # check the serial number in an SOA to ensure that a policy zone has -# been (re)loaded -# $1=serial number $2=domain $3=DNS server +# been (re)loaded +# $1=serial number +# $2=domain +# $3=DNS server ck_soa() { n=0 while true; do @@ -186,6 +190,9 @@ load_db () { fi } +# restart name server +# $1 ns number +# $2 rebuild bl rpz zones if "rebuild-bl-rpz" restart () { # try to ensure that the server really has stopped # and won't mess with ns$1/name.pid @@ -201,17 +208,20 @@ restart () { fi fi rm -f ns$1/*.jnl - if test -f ns$1/base.db; then - for NM in ns$1/bl*.db; do - cp -f ns$1/base.db $NM - done + if [ "$2" == "rebuild-bl-rpz" ]; then + if test -f ns$1/base.db; then + for NM in ns$1/bl*.db; do + cp -f ns$1/base.db $NM + done + fi fi $PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} rpz ns$1 load_db dnsrps_loaded } -# $1=server and irrelevant args $2=error message +# $1=server and irrelevant args +# $2=error message ckalive () { CKALIVE_NS=`expr "$1" : '.*@ns\([1-9]\).*'` if test -z "$CKALIVE_NS"; then @@ -222,7 +232,7 @@ ckalive () { HAVE_CORE=yes setret "$2" # restart the server to avoid stalling waiting for it to stop - restart $CKALIVE_NS + restart $CKALIVE_NS "rebuild-bl-rpz" return 1 } @@ -264,7 +274,8 @@ ckstatsrange () { eval "${NSDIR}_CNT=$NEW_CNT" } -# $1=message $2=optional test file name +# $1=message +# $2=optional test file name start_group () { ret=0 t=`expr $t + 1` @@ -299,7 +310,8 @@ clean_result () { fi } -# $1=dig args $2=other dig output file +# $1=dig args +# $2=other dig output file ckresult () { #ckalive "$1" "server crashed by 'dig $1'" || return 1 if grep "flags:.* aa .*ad;" $DIGNM; then @@ -322,7 +334,8 @@ ckresult () { } # check only that the server does not crash -# $1=target domain $2=optional query type +# $1=target domain +# $2=optional query type nocrash () { digcmd $* >/dev/null ckalive "$*" "server crashed by 'dig $*'" @@ -330,7 +343,8 @@ nocrash () { # check rewrite to NXDOMAIN -# $1=target domain $2=optional query type +# $1=target domain +# $2=optional query type nxdomain () { make_dignm digcmd $* \ @@ -341,7 +355,8 @@ nxdomain () { } # check rewrite to NODATA -# $1=target domain $2=optional query type +# $1=target domain +# $2=optional query type nodata () { make_dignm digcmd $* \ @@ -351,7 +366,9 @@ nodata () { # check rewrite to an address # modify the output so that it is easily compared, but save the original line -# $1=IPv4 address $2=digcmd args $3=optional TTL +# $1=IPv4 address +# $2=digcmd args +# $3=optional TTL addr () { ADDR=$1 make_dignm @@ -373,7 +390,8 @@ addr () { # Check that a response is not rewritten # Use $ns1 instead of the authority for most test domains, $ns2 to prevent # spurious differences for `dig +norecurse` -# $1=optional "TCP" remaining args for dig +# $1=optional "TCP" +# remaining args for dig nochange () { make_dignm digcmd $* >$DIGNM @@ -455,102 +473,104 @@ for mode in native dnsrps; do digcmd txt-only.tld2 @$ns2 >proto.nodata start_group "QNAME rewrites" test1 - nochange . # 1 do not crash or rewrite root - nxdomain a0-1.tld2 # 2 - nodata a3-1.tld2 # 3 - nodata a3-2.tld2 # 4 nodata at DNAME itself - nochange sub.a3-2.tld2 # 5 miss where DNAME might work - nxdomain a4-2.tld2 # 6 rewrite based on CNAME target - nxdomain a4-2-cname.tld2 # 7 - nodata a4-3-cname.tld2 # 8 - addr 12.12.12.12 a4-1.sub1.tld2 # 9 A replacement - addr 12.12.12.12 a4-1.sub2.tld2 # 10 A replacement with wildcard - addr 12.12.12.12 nxc1.sub1.tld2 # 11 replace NXDOMAIN with CNAME - addr 12.12.12.12 nxc2.sub1.tld2 # 12 replace NXDOMAIN with CNAME chain - addr 127.4.4.1 a4-4.tld2 # 13 prefer 1st conflicting QNAME zone - nochange a6-1.tld2 # 14 - addr 127.6.2.1 a6-2.tld2 # 15 - addr 56.56.56.56 a3-6.tld2 # 16 wildcard CNAME - addr 57.57.57.57 a3-7.sub1.tld2 # 17 wildcard CNAME - addr 127.0.0.16 a4-5-cname3.tld2 # 18 CNAME chain - addr 127.0.0.17 a4-6-cname3.tld2 # 19 stop short in CNAME chain - nochange a5-2.tld2 +norecurse # 20 check that RD=1 is required - nochange a5-3.tld2 +norecurse # 21 - nochange a5-4.tld2 +norecurse # 22 - nochange sub.a5-4.tld2 +norecurse # 23 - nxdomain c1.crash2.tld3 # 24 assert in rbtdb.c - nxdomain a0-1.tld2 +dnssec # 25 simple DO=1 without signatures - nxdomain a0-1.tld2s +nodnssec # 26 simple DO=0 with signatures - nochange a0-1.tld2s +dnssec # 27 simple DO=1 with signatures - nxdomain a0-1s-cname.tld2s +dnssec # 28 DNSSEC too early in CNAME chain - nochange a0-1-scname.tld2 +dnssec # 29 DNSSEC on target in CNAME chain - nochange a0-1.tld2s srv +auth +dnssec # 30 no write for DNSSEC and no record - nxdomain a0-1.tld2s srv +nodnssec # 31 - drop a3-8.tld2 any # 32 drop - nochange tcp a3-9.tld2 # 33 tcp-only - here x.servfail <<'EOF' # 34 qname-wait-recurse yes + nochange . # 1 do not crash or rewrite root + nxdomain a0-1.tld2 # 2 + nodata a3-1.tld2 # 3 + nodata a3-2.tld2 # 4 nodata at DNAME itself + nochange sub.a3-2.tld2 # 5 miss where DNAME might work + nxdomain a4-2.tld2 # 6 rewrite based on CNAME target + nxdomain a4-2-cname.tld2 # 7 + nodata a4-3-cname.tld2 # 8 + addr 12.12.12.12 a4-1.sub1.tld2 # 9 A replacement + addr 12.12.12.12 a4-1.sub2.tld2 # 10 A replacement with wildcard + addr 12.12.12.12 nxc1.sub1.tld2 # 11 replace NXDOMAIN with CNAME + addr 12.12.12.12 nxc2.sub1.tld2 # 12 replace NXDOMAIN with CNAME chain + addr 127.4.4.1 a4-4.tld2 # 13 prefer 1st conflicting QNAME zone + nochange a6-1.tld2 # 14 + addr 127.6.2.1 a6-2.tld2 # 15 + addr 56.56.56.56 a3-6.tld2 # 16 wildcard CNAME + addr 57.57.57.57 a3-7.sub1.tld2 # 17 wildcard CNAME + addr 127.0.0.16 a4-5-cname3.tld2 # 18 CNAME chain + addr 127.0.0.17 a4-6-cname3.tld2 # 19 stop short in CNAME chain + nochange a5-2.tld2 +norecurse # 20 check that RD=1 is required + nochange a5-3.tld2 +norecurse # 21 + nochange a5-4.tld2 +norecurse # 22 + nochange sub.a5-4.tld2 +norecurse # 23 + nxdomain c1.crash2.tld3 # 24 assert in rbtdb.c + nxdomain a0-1.tld2 +dnssec # 25 simple DO=1 without signatures + nxdomain a0-1.tld2s +nodnssec # 26 simple DO=0 with signatures + nochange a0-1.tld2s +dnssec # 27 simple DO=1 with signatures + nxdomain a0-1s-cname.tld2s +dnssec # 28 DNSSEC too early in CNAME chain + nochange a0-1-scname.tld2 +dnssec # 29 DNSSEC on target in CNAME chain + nochange a0-1.tld2s srv +auth +dnssec # 30 no write for DNSSEC and no record + nxdomain a0-1.tld2s srv +nodnssec # 31 + drop a3-8.tld2 any # 32 drop + nochange tcp a3-9.tld2 # 33 tcp-only + here x.servfail <<'EOF' # 34 qname-wait-recurse yes ;; status: SERVFAIL, x EOF - addr 35.35.35.35 "x.servfail @$ns5" # 35 qname-wait-recurse no + addr 35.35.35.35 "x.servfail @$ns5" # 35 qname-wait-recurse no end_group ckstats $ns3 test1 ns3 22 ckstats $ns5 test1 ns5 1 ckstats $ns6 test1 ns6 0 start_group "NXDOMAIN/NODATA action on QNAME trigger" test1 - nxdomain a0-1.tld2 @$ns6 # 1 - nodata a3-1.tld2 @$ns6 # 2 - nodata a3-2.tld2 @$ns6 # 3 nodata at DNAME itself - nxdomain a4-2.tld2 @$ns6 # 4 rewrite based on CNAME target - nxdomain a4-2-cname.tld2 @$ns6 # 5 - nodata a4-3-cname.tld2 @$ns6 # 6 - addr 12.12.12.12 "a4-1.sub1.tld2 @$ns6" # 7 A replacement - addr 12.12.12.12 "a4-1.sub2.tld2 @$ns6" # 8 A replacement with wildcard - addr 127.4.4.1 "a4-4.tld2 @$ns6" # 9 prefer 1st conflicting QNAME zone - addr 12.12.12.12 "nxc1.sub1.tld2 @$ns6" # 10 replace NXDOMAIN w/ CNAME - addr 12.12.12.12 "nxc2.sub1.tld2 @$ns6" # 11 replace NXDOMAIN w/ CNAME chain - addr 127.6.2.1 "a6-2.tld2 @$ns6" # 12 - addr 56.56.56.56 "a3-6.tld2 @$ns6" # 13 wildcard CNAME - addr 57.57.57.57 "a3-7.sub1.tld2 @$ns6" # 14 wildcard CNAME - addr 127.0.0.16 "a4-5-cname3.tld2 @$ns6" # 15 CNAME chain - addr 127.0.0.17 "a4-6-cname3.tld2 @$ns6" # 16 stop short in CNAME chain - nxdomain c1.crash2.tld3 @$ns6 # 17 assert in rbtdb.c - nxdomain a0-1.tld2 +dnssec @$ns6 # 18 simple DO=1 without sigs - nxdomain a0-1s-cname.tld2s +dnssec @$ns6 # 19 - drop a3-8.tld2 any @$ns6 # 20 drop + nxdomain a0-1.tld2 @$ns6 # 1 + nodata a3-1.tld2 @$ns6 # 2 + nodata a3-2.tld2 @$ns6 # 3 nodata at DNAME itself + nxdomain a4-2.tld2 @$ns6 # 4 rewrite based on CNAME target + nxdomain a4-2-cname.tld2 @$ns6 # 5 + nodata a4-3-cname.tld2 @$ns6 # 6 + addr 12.12.12.12 "a4-1.sub1.tld2 @$ns6" # 7 A replacement + addr 12.12.12.12 "a4-1.sub2.tld2 @$ns6" # 8 A replacement with wildcard + addr 127.4.4.1 "a4-4.tld2 @$ns6" # 9 prefer 1st conflicting QNAME zone + addr 12.12.12.12 "nxc1.sub1.tld2 @$ns6" # 10 replace NXDOMAIN w/ CNAME + addr 12.12.12.12 "nxc2.sub1.tld2 @$ns6" # 11 replace NXDOMAIN w/ CNAME chain + addr 127.6.2.1 "a6-2.tld2 @$ns6" # 12 + addr 56.56.56.56 "a3-6.tld2 @$ns6" # 13 wildcard CNAME + addr 57.57.57.57 "a3-7.sub1.tld2 @$ns6" # 14 wildcard CNAME + addr 127.0.0.16 "a4-5-cname3.tld2 @$ns6" # 15 CNAME chain + addr 127.0.0.17 "a4-6-cname3.tld2 @$ns6" # 16 stop short in CNAME chain + nxdomain c1.crash2.tld3 @$ns6 # 17 assert in rbtdb.c + nxdomain a0-1.tld2 +dnssec @$ns6 # 18 simple DO=1 without sigs + nxdomain a0-1s-cname.tld2s +dnssec @$ns6 # 19 + drop a3-8.tld2 any @$ns6 # 20 drop end_group ckstatsrange $ns3 test1 ns3 22 30 ckstats $ns5 test1 ns5 0 ckstats $ns6 test1 ns6 0 start_group "IP rewrites" test2 - nodata a3-1.tld2 # 1 NODATA - nochange a3-2.tld2 # 2 no policy record so no change - nochange a4-1.tld2 # 3 obsolete PASSTHRU record style - nxdomain a4-2.tld2 # 4 - nochange a4-2.tld2 -taaaa # 5 no A => no policy rewrite - nochange a4-2.tld2 -ttxt # 6 no A => no policy rewrite - nxdomain a4-2.tld2 -tany # 7 no A => no policy rewrite - nodata a4-3.tld2 # 8 - nxdomain a3-1.tld2 -taaaa # 9 IPv6 policy - nochange a4-1-aaaa.tld2 -taaaa # 10 - addr 127.0.0.1 a5-1-2.tld2 # 11 prefer smallest policy address - addr 127.0.0.1 a5-3.tld2 # 12 prefer first conflicting IP zone - nochange a5-4.tld2 +norecurse # 13 check that RD=1 is required for #14 - addr 14.14.14.14 a5-4.tld2 # 14 prefer QNAME to IP - nochange a4-4.tld2 # 15 PASSTHRU - nxdomain c2.crash2.tld3 # 16 assert in rbtdb.c - addr 127.0.0.17 "a4-4.tld2 -b $ns1" # 17 client-IP address trigger - nxdomain a7-1.tld2 # 18 slave policy zone (RT34450) + nodata a3-1.tld2 # 1 NODATA + nochange a3-2.tld2 # 2 no policy record so no change + nochange a4-1.tld2 # 3 obsolete PASSTHRU record style + nxdomain a4-2.tld2 # 4 + nochange a4-2.tld2 -taaaa # 5 no A => no policy rewrite + nochange a4-2.tld2 -ttxt # 6 no A => no policy rewrite + nxdomain a4-2.tld2 -tany # 7 no A => no policy rewrite + nodata a4-3.tld2 # 8 + nxdomain a3-1.tld2 -taaaa # 9 IPv6 policy + nochange a4-1-aaaa.tld2 -taaaa # 10 + addr 127.0.0.1 a5-1-2.tld2 # 11 prefer smallest policy address + addr 127.0.0.1 a5-3.tld2 # 12 prefer first conflicting IP zone + nochange a5-4.tld2 +norecurse # 13 check that RD=1 is required for #14 + addr 14.14.14.14 a5-4.tld2 # 14 prefer QNAME to IP + nochange a4-4.tld2 # 15 PASSTHRU + nxdomain c2.crash2.tld3 # 16 assert in rbtdb.c + addr 127.0.0.17 "a4-4.tld2 -b $ns1" # 17 client-IP address trigger + nxdomain a7-1.tld2 # 18 slave policy zone (RT34450) + # updating an response zone policy cp ns2/blv2.tld2.db.in ns2/bl.tld2.db rndc_reload ns2 $ns2 bl.tld2 ck_soa 2 bl.tld2 $ns3 - nochange a7-1.tld2 # 19 PASSTHRU - sleep 1 # ensure that a clock tick has occured so that named will do the reload + nochange a7-1.tld2 # 19 PASSTHRU + # ensure that a clock tick has occured so that named will do the reload + sleep 1 cp ns2/blv3.tld2.db.in ns2/bl.tld2.db rndc_reload ns2 $ns2 bl.tld2 ck_soa 3 bl.tld2 $ns3 - nxdomain a7-1.tld2 # 20 slave policy zone (RT34450) + nxdomain a7-1.tld2 # 20 slave policy zone (RT34450) end_group ckstats $ns3 test2 ns3 12 @@ -572,20 +592,20 @@ EOF # these tests assume "min-ns-dots 0" start_group "NSDNAME rewrites" test3 - nochange a3-1.tld2 # 1 - nochange a3-1.tld2 +dnssec # 2 this once caused problems + nochange a3-1.tld2 # 1 + nochange a3-1.tld2 +dnssec # 2 this once caused problems nxdomain a3-1.sub1.tld2 # 3 NXDOMAIN *.sub1.tld2 by NSDNAME - nxdomain a3-1.subsub.sub1.tld2 - nxdomain a3-1.subsub.sub1.tld2 -tany + nxdomain a3-1.subsub.sub1.tld2 # 4 + nxdomain a3-1.subsub.sub1.tld2 -tany # 5 addr 12.12.12.12 a4-2.subsub.sub2.tld2 # 6 walled garden for *.sub2.tld2 - nochange a3-2.tld2. # 7 exempt rewrite by name - nochange a0-1.tld2. # 8 exempt rewrite by address block - addr 12.12.12.12 a4-1.tld2 # 9 prefer QNAME policy to NSDNAME - addr 127.0.0.1 a3-1.sub3.tld2 # 10 prefer policy for largest NSDNAME - addr 127.0.0.2 a3-1.subsub.sub3.tld2 - nxdomain xxx.crash1.tld2 # 12 dns_db_detachnode() crash + nochange a3-2.tld2. # 7 exempt rewrite by name + nochange a0-1.tld2. # 8 exempt rewrite by address block + addr 12.12.12.12 a4-1.tld2 # 9 prefer QNAME policy to NSDNAME + addr 127.0.0.1 a3-1.sub3.tld2 # 10 prefer policy for largest NSDNAME + addr 127.0.0.2 a3-1.subsub.sub3.tld2 # 11 + nxdomain xxx.crash1.tld2 # 12 dns_db_detachnode() crash if [ "$mode" = dnsrps ]; then - addr 12.12.12.12 as-ns.tld5. # 13 qname-as-ns + addr 12.12.12.12 as-ns.tld5. # 13 qname-as-ns fi end_group if [ "$mode" = dnsrps ]; then @@ -596,19 +616,19 @@ EOF # these tests assume "min-ns-dots 0" start_group "NSIP rewrites" test4 - nxdomain a3-1.tld2 # 1 NXDOMAIN for all of tld2 - nochange a3-2.tld2. # 2 exempt rewrite by name - nochange a0-1.tld2. # 3 exempt rewrite by address block - nochange a3-1.tld4 # 4 different NS IP address + nxdomain a3-1.tld2 # 1 NXDOMAIN for all of tld2 + nochange a3-2.tld2. # 2 exempt rewrite by name + nochange a0-1.tld2. # 3 exempt rewrite by address block + nochange a3-1.tld4 # 4 different NS IP address if [ "$mode" = dnsrps ]; then - addr 12.12.12.12 as-ns.tld5. # 5 ip-as-ns + addr 12.12.12.12 as-ns.tld5. # 5 ip-as-ns fi end_group start_group "walled garden NSIP rewrites" test4a - addr 41.41.41.41 a3-1.tld2 # 1 walled garden for all of tld2 - addr 2041::41 'a3-1.tld2 AAAA' # 2 walled garden for all of tld2 - here a3-1.tld2 TXT <<'EOF' # 3 text message for all of tld2 + addr 41.41.41.41 a3-1.tld2 # 1 walled garden for all of tld2 + addr 2041::41 'a3-1.tld2 AAAA' # 2 walled garden for all of tld2 + here a3-1.tld2 TXT <<'EOF' # 3 text message for all of tld2 ;; status: NOERROR, x a3-1.tld2. x IN TXT "NSIP walled garden" EOF @@ -620,30 +640,30 @@ EOF fi # policies in ./test5 overridden by response-policy{} in ns3/named.conf - # and in ns5/named.conf + # and in ns5/named.conf start_group "policy overrides" test5 - addr 127.0.0.1 a3-1.tld2 # 1 bl-given - nochange a3-2.tld2 # 2 bl-passthru - nochange a3-3.tld2 # 3 bl-no-op obsolete for passthru - nochange a3-4.tld2 # 4 bl-disabled - nodata a3-5.tld2 # 5 bl-nodata zone recursive-only no - nodata a3-5.tld2 +norecurse # 6 bl-nodata zone recursive-only no - nodata a3-5.tld2 # 7 bl-nodata not needed - nxdomain a3-5.tld2 +norecurse @$ns5 # 8 bl-nodata global recursive-only no - nxdomain a3-5.tld2s @$ns5 # 9 bl-nodata global break-dnssec - nxdomain a3-5.tld2s +dnssec @$ns5 # 10 bl-nodata global break-dnssec - nxdomain a3-6.tld2 # 11 bl-nxdomain - here a3-7.tld2 -tany <<'EOF' + addr 127.0.0.1 a3-1.tld2 # 1 bl-given + nochange a3-2.tld2 # 2 bl-passthru + nochange a3-3.tld2 # 3 bl-no-op (obsolete for passthru) + nochange a3-4.tld2 # 4 bl-disabled + nodata a3-5.tld2 # 5 bl-nodata zone recursive-only no + nodata a3-5.tld2 +norecurse # 6 bl-nodata zone recursive-only no + nodata a3-5.tld2 # 7 bl-nodata not needed + nxdomain a3-5.tld2 +norecurse @$ns5 # 8 bl-nodata global recursive-only no + nxdomain a3-5.tld2s @$ns5 # 9 bl-nodata global break-dnssec + nxdomain a3-5.tld2s +dnssec @$ns5 # 10 bl-nodata global break-dnssec + nxdomain a3-6.tld2 # 11 bl-nxdomain + here a3-7.tld2 -tany <<'EOF' # 12 ;; status: NOERROR, x a3-7.tld2. x IN CNAME txt-only.tld2. txt-only.tld2. x IN TXT "txt-only-tld2" EOF - addr 58.58.58.58 a3-8.tld2 # 13 bl_wildcname + addr 58.58.58.58 a3-8.tld2 # 13 bl_wildcname addr 59.59.59.59 a3-9.sub9.tld2 # 14 bl_wildcname - addr 12.12.12.12 a3-15.tld2 # 15 bl-garden via CNAME to a12.tld2 - addr 127.0.0.16 a3-16.tld2 100 # 16 bl max-policy-ttl 100 - addr 17.17.17.17 "a3-17.tld2 @$ns5" 90 # 17 ns5 bl max-policy-ttl 90 - drop a3-18.tld2 any # 18 bl-drop + addr 12.12.12.12 a3-15.tld2 # 15 bl-garden via CNAME to a12.tld2 + addr 127.0.0.16 a3-16.tld2 100 # 16 bl max-policy-ttl 100 + addr 17.17.17.17 "a3-17.tld2 @$ns5" 90 # 17 ns5 bl max-policy-ttl 90 + drop a3-18.tld2 any # 18 bl-drop nxdomain TCP a3-19.tld2 # 19 bl-tcp-only end_group ckstats $ns3 test5 ns3 12 @@ -666,7 +686,6 @@ EOF end_group ckstats $ns3 bugs ns3 8 - # superficial test for major performance bugs QPERF=`sh qperf.sh` if test -n "$QPERF"; then @@ -742,7 +761,7 @@ EOF # restart the main test RPZ server to see if that creates a core file if test -z "$HAVE_CORE"; then $PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port ${CONTROLPORT} rpz ns3 - restart 3 + restart 3 "rebuild-bl-rpz" HAVE_CORE=`find ns* -name '*core*' -print` test -z "$HAVE_CORE" || setret "found $HAVE_CORE; memory leak?" fi @@ -757,6 +776,28 @@ EOF fi done + # restart the main test RPZ server with a bad zone. + t=`expr $t + 1` + echo_i "checking that ns3 with broken rpz does not crash (${t})" + $PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port ${CONTROLPORT} rpz ns3 + cp ns3/broken.db.in ns3/bl.db + restart 3 # do not rebuild rpz zones + nocrash a3-1.tld2 -tA + $PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port ${CONTROLPORT} rpz ns3 + restart 3 "rebuild-bl-rpz" + + # reload a RPZ zone that is now deliberately broken. + t=`expr $t + 1` + echo_i "checking rpz failed update will keep previous rpz rules (${t})" + $DIG -p ${PORT} @$ns3 walled.tld2 > dig.out.$t.before + grep "walled\.tld2\..*IN.*A.*10\.0\.0\.1" dig.out.$t.before > /dev/null || setret "failed" + cp ns3/broken.db.in ns3/manual-update-rpz.db + rndc_reload ns3 $ns3 manual-update-rpz + sleep 1 + # ensure previous RPZ rules still apply. + $DIG -p ${PORT} @$ns3 walled.tld2 > dig.out.$t.after + grep "walled\.tld2\..*IN.*A.*10\.0\.0\.1" dig.out.$t.after > /dev/null || setret "failed" + t=`expr $t + 1` echo_i "checking that ttl values are not zeroed when qtype is '*' (${t})" $DIG +noall +answer -p ${PORT} @$ns3 any a3-2.tld2 > dig.out.$t diff --git a/lib/dns/include/dns/rpz.h b/lib/dns/include/dns/rpz.h index 0c12da6e9d..e8f5170ca7 100644 --- a/lib/dns/include/dns/rpz.h +++ b/lib/dns/include/dns/rpz.h @@ -144,15 +144,14 @@ struct dns_rpz_zone { isc_ht_t *nodes; /* entries in zone */ dns_rpz_zones_t *rpzs; /* owner */ isc_time_t lastupdated; /* last time the zone was processed */ - bool updatepending; /* there is an update pending/waiting */ - bool updaterunning; /* there is an update running */ + bool updatepending; /* there is an update pending/waiting */ + bool updaterunning; /* there is an update running */ dns_db_t *db; /* zones database */ dns_dbversion_t *dbversion; /* version we will be updating to */ dns_db_t *updb; /* zones database we're working on */ dns_dbversion_t *updbversion; /* version we're currently working on */ dns_dbiterator_t *updbit; /* iterator to use when updating */ isc_ht_t *newnodes; /* entries in zone being updated */ - bool db_registered; /* is the notify event registered? */ isc_timer_t *updatetimer; isc_event_t updateevent; }; diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index e3b2f25698..83f8f7d6c5 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -1549,7 +1549,6 @@ dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp) { zone->updbversion = NULL; zone->updbit = NULL; zone->rpzs = rpzs; - zone->db_registered = false; ISC_EVENT_INIT(&zone->updateevent, sizeof(zone->updateevent), 0, NULL, 0, NULL, NULL, NULL, NULL, NULL); @@ -1584,8 +1583,6 @@ dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg) { REQUIRE(zone != NULL); LOCK(&zone->rpzs->maint_lock); - REQUIRE(zone->db_registered); - /* New zone came as AXFR */ if (zone->db != NULL && zone->db != db) { @@ -2097,14 +2094,12 @@ rpz_detach(dns_rpz_zone_t **rpzp, dns_rpz_zones_t *rpzs) { if (dns_name_dynamic(&rpz->cname)) { dns_name_free(&rpz->cname, rpzs->mctx); } - if (rpz->db_registered) { - dns_db_updatenotify_unregister(rpz->db, - dns_rpz_dbupdate_callback, rpz); - } if (rpz->dbversion != NULL) { dns_db_closeversion(rpz->db, &rpz->dbversion, false); } if (rpz->db != NULL) { + dns_db_updatenotify_unregister( + rpz->db, dns_rpz_dbupdate_callback, rpz); dns_db_detach(&rpz->db); } if (rpz->updaterunning) { diff --git a/lib/dns/zone.c b/lib/dns/zone.c index f2087658c8..735928e379 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -1783,16 +1783,27 @@ dns_zone_get_rpz_num(dns_zone_t *zone) { void dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) { isc_result_t result; - if (zone->rpz_num == DNS_RPZ_INVALID_NUM) + if (zone->rpz_num == DNS_RPZ_INVALID_NUM) { return; + } REQUIRE(zone->rpzs != NULL); - zone->rpzs->zones[zone->rpz_num]->db_registered = true; result = dns_db_updatenotify_register(db, dns_rpz_dbupdate_callback, zone->rpzs->zones[zone->rpz_num]); REQUIRE(result == ISC_R_SUCCESS); } +static void +dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) { + if (zone->rpz_num == DNS_RPZ_INVALID_NUM) { + return; + } + REQUIRE(zone->rpzs != NULL); + (void) dns_db_updatenotify_unregister(db, + dns_rpz_dbupdate_callback, + zone->rpzs->zones[zone->rpz_num]); +} + void dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) { REQUIRE(DNS_ZONE_VALID(zone)); @@ -1801,8 +1812,9 @@ dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) { LOCK_ZONE(zone); INSIST(zone->catzs == NULL || zone->catzs == catzs); dns_catz_catzs_set_view(catzs, zone->view); - if (zone->catzs == NULL) + if (zone->catzs == NULL) { dns_catz_catzs_attach(catzs, &zone->catzs); + } UNLOCK_ZONE(zone); } @@ -1820,6 +1832,17 @@ dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) { } } +static void +dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) { + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(db != NULL); + + if (zone->catzs != NULL) { + dns_db_updatenotify_unregister(db, dns_catz_dbupdate_callback, + zone->catzs); + } +} + /* * Set catalog zone ownership of the zone */ @@ -2120,7 +2143,7 @@ zone_load(dns_zone_t *zone, unsigned int flags, bool locked) { } } - if (! dns_db_ispersistent(db)) { + if (!dns_db_ispersistent(db)) { if (zone->masterfile != NULL) { result = zone_startload(db, zone, loadtime); } else { @@ -2487,16 +2510,21 @@ dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) { static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { + const char me[] = "zone_startload"; dns_load_t *load; isc_result_t result; isc_result_t tresult; unsigned int options; + ENTER; + dns_zone_rpz_enable_db(zone, db); dns_zone_catz_enable_db(zone, db); + options = get_master_options(zone); - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) { options |= DNS_MASTER_MANYERRORS; + } if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) { load = isc_mem_get(zone->mctx, sizeof(*load)); @@ -2516,8 +2544,9 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { load->callbacks.rawdata = zone_setrawdata; zone_iattach(zone, &load->callbacks.zone); result = dns_db_beginload(db, &load->callbacks); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { goto cleanup; + } result = zonemgr_getio(zone->zmgr, true, zone->loadtask, zone_gotreadhandle, load, &zone->readio); @@ -2528,8 +2557,9 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { */ (void)dns_db_endload(load->db, &load->callbacks); goto cleanup; - } else + } else { result = DNS_R_CONTINUE; + } } else { dns_rdatacallbacks_t callbacks; @@ -2550,8 +2580,9 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { zone->masterformat, zone->maxttl); tresult = dns_db_endload(db, &callbacks); - if (result == ISC_R_SUCCESS) + if (result == ISC_R_SUCCESS) { result = tresult; + } zone_idetach(&callbacks.zone); } @@ -15801,6 +15832,15 @@ zone_loaddone(void *arg, isc_result_t result) { ENTER; + /* + * If zone loading failed, remove the update db callbacks prior + * to calling the list of callbacks in the zone load structure. + */ + if (result != ISC_R_SUCCESS) { + dns_zone_rpz_disable_db(zone, load->db); + dns_zone_catz_disable_db(zone, load->db); + } + tresult = dns_db_endload(load->db, &load->callbacks); if (tresult != ISC_R_SUCCESS && (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE)) diff --git a/util/copyrights b/util/copyrights index b0b2e2eb22..109c3503e5 100644 --- a/util/copyrights +++ b/util/copyrights @@ -934,6 +934,7 @@ ./bin/tests/system/rootkeysentinel/ns2/sign.sh SH 2018,2019 ./bin/tests/system/rootkeysentinel/setup.sh SH 2018,2019 ./bin/tests/system/rootkeysentinel/tests.sh SH 2018,2019 +./bin/tests/system/rpz/README TXT.BRIEF 2019 ./bin/tests/system/rpz/ckdnsrps.sh SH 2017,2018,2019 ./bin/tests/system/rpz/clean.sh SH 2011,2012,2013,2014,2016,2017,2018,2019 ./bin/tests/system/rpz/dnsrps.c C 2017,2018,2019