Commit a111c8d7 authored by Matthijs Mekking's avatar Matthijs Mekking 🏡
Browse files

Merge branch '813-matthijs-failure-loading-rpz' into 'master'

Resolve "Problems after failure of loading rpz [ISC-support #14002]"

Closes #813

See merge request isc-projects/bind9!1507
parents f9b50a40 e5565808
Pipeline #10529 passed with stages
in 13 minutes and 9 seconds
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]
 
......
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.
......@@ -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
......
; 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
; 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
; 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
......@@ -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;
};
......@@ -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 <<EOF >ns5/rpz-switch
response-policy {
......
......@@ -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
......@@ -151,7 +153,9 @@ 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
# $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 [ "$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
......@@ -542,11 +560,13 @@ EOF
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
# 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
......@@ -575,14 +595,14 @@ EOF
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
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
......@@ -624,7 +644,7 @@ EOF
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-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
......@@ -633,7 +653,7 @@ EOF
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'
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"
......@@ -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
......
......@@ -152,7 +152,6 @@ struct dns_rpz_zone {
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;
};
......
......@@ -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) {
......
......@@ -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))
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment