diff --git a/CHANGES b/CHANGES index eac40a0800..57cc25ae1d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +3398. [bug] SOA parameters were not being updated with inline + signed zones if the zone was modified while the + server was offline. [RT #29272] + 3397. [bug] dig crashed when using +nssearch with +tcp. [RT #25298] 3396. [bug] OPT records were incorrectly removed from signed, diff --git a/bin/tests/system/inline/ns3/master4.db.in b/bin/tests/system/inline/ns3/master4.db.in new file mode 100644 index 0000000000..217ffbac72 --- /dev/null +++ b/bin/tests/system/inline/ns3/master4.db.in @@ -0,0 +1,136 @@ +; Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") +; +; Permission to use, copy, modify, and/or distribute this software for any +; purpose with or without fee is hereby granted, provided that the above +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +; $Id: master3.db.in,v 1.3 2012/01/31 23:47:32 tbox Exp $ + +$TTL 300 ; 5 minutes +@ IN SOA ns3 hostmaster. ( + 2000042410 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 +d A 10.0.0.4 +e A 10.0.0.5 + +; Used for testing ANY queries +foo TXT "testing" +foo A 10.0.1.0 + +bad-cname CNAME a +bad-dname DNAME @ + +; Used for testing CNAME queries +cname1 CNAME cname1-target +cname1-target TXT "testing cname" + +cname2 CNAME cname2-target +cname2-target TXT "testing cname" + +; Used for testing DNAME queries +dname1 DNAME dname1-target +foo.dname1-target TXT "testing dname" + +dname2 DNAME dname2-target +foo.dname2-target TXT "testing dname" + +; A secure subdomain +secure NS ns.secure +ns.secure A 10.53.0.3 + +; An insecure subdomain +insecure NS ns.insecure +ns.insecure A 10.53.0.3 + +; A secure subdomain we're going to inject bogus data into +bogus NS ns.bogus +ns.bogus A 10.53.0.3 + +; A dynamic secure subdomain +dynamic NS dynamic +dynamic A 10.53.0.3 + +; A insecure subdomain +mustbesecure NS ns.mustbesecure +ns.mustbesecure A 10.53.0.3 + +; A rfc2535 signed zone w/ CNAME +rfc2535 NS ns.rfc2535 +ns.rfc2535 A 10.53.0.3 + +z A 10.0.0.26 + +keyless NS ns.keyless +ns.keyless A 10.53.0.3 + +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 + +optout NS ns.optout +ns.optout A 10.53.0.3 + +nsec3-unknown NS ns.nsec3-unknown +ns.nsec3-unknown A 10.53.0.3 + +optout-unknown NS ns.optout-unknown +ns.optout-unknown A 10.53.0.3 + +multiple NS ns.multiple +ns.multiple A 10.53.0.3 + +*.wild A 10.0.0.27 + +rsasha256 NS ns.rsasha256 +ns.rsasha256 A 10.53.0.3 + +rsasha512 NS ns.rsasha512 +ns.rsasha512 A 10.53.0.3 + +kskonly NS ns.kskonly +ns.kskonly A 10.53.0.3 + +update-nsec3 NS ns.update-nsec3 +ns.update-nsec3 A 10.53.0.3 + +auto-nsec NS ns.auto-nsec +ns.auto-nsec A 10.53.0.3 + +auto-nsec3 NS ns.auto-nsec3 +ns.auto-nsec3 A 10.53.0.3 + + +below-cname CNAME some.where.else. + +insecure.below-cname NS ns.insecure.below-cname +ns.insecure.below-cname A 10.53.0.3 + +secure.below-cname NS ns.secure.below-cname +ns.secure.below-cname A 10.53.0.3 + +ttlpatch NS ns.ttlpatch +ns.ttlpatch A 10.53.0.3 + +split-dnssec NS ns.split-dnssec +ns.split-dnssec A 10.53.0.3 + +split-smart NS ns.split-smart +ns.split-smart A 10.53.0.3 diff --git a/bin/tests/system/inline/tests.sh b/bin/tests/system/inline/tests.sh index 4870097577..16fe1eb268 100644 --- a/bin/tests/system/inline/tests.sh +++ b/bin/tests/system/inline/tests.sh @@ -742,4 +742,37 @@ n=`expr $n + 1` if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +n=`expr $n + 1` +echo "I:stop bump in the wire signer server ($n)" +ret=0 +$PERL ../stop.pl . ns3 || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:update SOA record while stopped" +cp ns3/master4.db.in ns3/master.db +rm ns3/master.db.jnl + +n=`expr $n + 1` +echo "I:restart bump in the wire signer server ($n)" +ret=0 +$PERL ../start.pl --noclean --restart . ns3 || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:updates to SOA parameters other than serial while stopped are reflected in signed zone ($n)" +ret=0 +for i in 1 2 3 4 5 6 7 8 9 +do + ans=0 + $DIG $DIGOPTS @10.53.0.3 -p 5300 master SOA > dig.out.ns3.test$n + grep "hostmaster" dig.out.ns3.test$n > /dev/null || ans=1 + grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ans=1 + [ $ans = 1 ] || break + sleep 1 +done +[ $ans = 0 ] || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + exit $status diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 02a89a0ba8..2a06e63e21 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -12366,15 +12366,19 @@ sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal, static isc_result_t sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb, - dns_dbversion_t *secver, dns_diff_t *diff) + dns_dbversion_t *secver, dns_difftuple_t **soatuple, + dns_diff_t *diff) { isc_result_t result; dns_db_t *rawdb = NULL; dns_dbversion_t *rawver = NULL; dns_difftuple_t *tuple = NULL, *next; + dns_difftuple_t *oldtuple = NULL, *newtuple = NULL; + dns_rdata_soa_t oldsoa, newsoa; REQUIRE(DNS_ZONE_VALID(seczone)); REQUIRE(inline_secure(seczone)); + REQUIRE(soatuple != NULL && *soatuple == NULL); if (!seczone->sourceserialset) return (DNS_R_UNCHANGED); @@ -12397,17 +12401,66 @@ sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb, tuple->rdata.type == dns_rdatatype_rrsig || tuple->rdata.type == dns_rdatatype_dnskey || tuple->rdata.type == dns_rdatatype_nsec3 || - tuple->rdata.type == dns_rdatatype_soa || tuple->rdata.type == dns_rdatatype_nsec3param) { ISC_LIST_UNLINK(diff->tuples, tuple, link); dns_difftuple_free(&tuple); + continue; + } + if (tuple->rdata.type == dns_rdatatype_soa) { + if (tuple->op == DNS_DIFFOP_DEL) { + INSIST(oldtuple == NULL); + oldtuple = tuple; + } + if (tuple->op == DNS_DIFFOP_ADD) { + INSIST(newtuple == NULL); + newtuple = tuple; + } + } + } + + if (oldtuple != NULL && newtuple != NULL) { + + result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + /* + * If the SOA records are the same except for the serial + * remove them from the diff. + */ + if (oldsoa.refresh == newsoa.refresh && + oldsoa.retry == newsoa.retry && + oldsoa.minimum == newsoa.minimum && + oldsoa.expire == newsoa.expire && + dns_name_equal(&oldsoa.origin, &newsoa.origin) && + dns_name_equal(&oldsoa.contact, &newsoa.contact)) { + ISC_LIST_UNLINK(diff->tuples, oldtuple, link); + dns_difftuple_free(&oldtuple); + ISC_LIST_UNLINK(diff->tuples, newtuple, link); + dns_difftuple_free(&newtuple); } } if (ISC_LIST_EMPTY(diff->tuples)) return (DNS_R_UNCHANGED); + /* + * If there are still SOA records in the diff they can now be removed + * saving the new SOA record. + */ + if (oldtuple != NULL) { + ISC_LIST_UNLINK(diff->tuples, oldtuple, link); + dns_difftuple_free(&oldtuple); + } + + if (newtuple != NULL) { + ISC_LIST_UNLINK(diff->tuples, newtuple, link); + *soatuple = newtuple; + } + return (ISC_R_SUCCESS); } @@ -12496,7 +12549,7 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { if (result == DNS_R_UNCHANGED) goto failure; else if (result != ISC_R_SUCCESS) { - CHECK(sync_secure_db(zone, db, oldver, &diff)); + CHECK(sync_secure_db(zone, db, oldver, &soatuple, &diff)); } CHECK(dns_diff_apply(&diff, db, newver));