Merge branch '468-queue-rndc-signing-nsec3param-requests-if-needed' into 'master'

Queue "rndc signing -nsec3param ..." requests if needed

Closes #468

See merge request isc-projects/bind9!610
This commit is contained in:
Michał Kępień 2018-08-14 03:44:53 -04:00
commit dc5b8ec97a
4 changed files with 83 additions and 18 deletions

View file

@ -1,3 +1,7 @@
5008. [bug] "rndc signing -nsec3param ..." requests were silently
ignored for zones which were not yet loaded or
transferred. [GL #468]
5007. [cleanup] Replace custom ISC boolean and integer data types
with C99 stdint.h and stdbool.h types. [GL #9]

View file

@ -48,6 +48,7 @@ zone "retransfer3" {
type master;
file "retransfer3.db";
allow-update { any; };
allow-transfer { none; }; // changed dynamically by tests.sh
notify no;
};

View file

@ -27,22 +27,6 @@ do
sleep 1
done
# Loop until retransfer3 has been transferred.
for i in 1 2 3 4 5 6 7 8 9 0
do
ans=0
$RNDCCMD 10.53.0.3 signing -nsec3param 1 0 0 - retransfer3 > /dev/null 2>&1 || ans=1
[ $ans = 0 ] && break
sleep 1
done
for i in 1 2 3 4 5 6 7 8 9 0
do
nsec3param=`$DIG $DIGOPTS +nodnssec +short @10.53.0.3 nsec3param retransfer3.`
test "$nsec3param" = "1 0 0 -" && break
sleep 1
done
n=`expr $n + 1`
echo_i "checking that rrsigs are replaced with ksk only ($n)"
ret=0
@ -770,9 +754,45 @@ done
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check 'rndc signing -nsec3param' requests are queued for zones which are not loaded ($n)"
ret=0
# The "retransfer3" zone is configured with "allow-transfer { none; };" on ns2,
# which means it should not yet be available on ns3.
$DIG $DIGOPTS @10.53.0.3 retransfer3 SOA > dig.out.ns3.pre.test$n
grep "status: SERVFAIL" dig.out.ns3.pre.test$n > /dev/null || ret=1
# Switch the zone to NSEC3. An "NSEC3 -> NSEC -> NSEC3" sequence is used purely
# to test that multiple queued "rndc signing -nsec3param" requests are handled
# properly.
$RNDCCMD 10.53.0.3 signing -nsec3param 1 0 0 - retransfer3 > /dev/null 2>&1 || ret=1
$RNDCCMD 10.53.0.3 signing -nsec3param none retransfer3 > /dev/null 2>&1 || ret=1
$RNDCCMD 10.53.0.3 signing -nsec3param 1 0 0 - retransfer3 > /dev/null 2>&1 || ret=1
# Reconfigure ns2 to allow outgoing transfers for the "retransfer3" zone.
sed "s|\(allow-transfer { none; };.*\)|// \1|;" ns2/named.conf > ns2/named.conf.new
mv ns2/named.conf.new ns2/named.conf
$RNDCCMD 10.53.0.2 reconfig || ret=1
# Request ns3 to retransfer the "retransfer3" zone.
$RNDCCMD 10.53.0.3 retransfer retransfer3 || ret=1
# Wait until ns3 finishes building the NSEC3 chain for "retransfer3". There is
# no need to immediately set ret=1 if the expected message does not appear in
# the log within the time limit because the query we will send shortly will
# detect problems anyway.
for i in 0 1 2 3 4 5 6 7 8 9
do
grep "add.*retransfer3.*NSEC3PARAM 1 0 0 -" ns3/named.run > /dev/null && break
sleep 1
done
# Check whether "retransfer3" uses NSEC3 as requested.
$DIG $DIGOPTS @10.53.0.3 nonexist.retransfer3 A > dig.out.ns3.post.test$n
grep "status: NXDOMAIN" dig.out.ns3.post.test$n > /dev/null || ret=1
grep "NSEC3" dig.out.ns3.post.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check rndc retransfer of a inline nsec3 slave retains nsec3 ($n)"
ret=0
$RNDCCMD 10.53.0.3 signing -nsec3param 1 0 0 - retransfer3 > /dev/null 2>&1 || ret=1
for i in 0 1 2 3 4 5 6 7 8 9
do
ans=0

View file

@ -357,6 +357,10 @@ struct dns_zone {
*/
dns_signinglist_t signing;
dns_nsec3chainlist_t nsec3chain;
/*%
* List of outstanding NSEC3PARAM change requests.
*/
isc_eventlist_t setnsec3param_queue;
/*%
* Signing / re-signing quantum stopping parameters.
*/
@ -1039,6 +1043,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
zone->isselfarg = NULL;
ISC_LIST_INIT(zone->signing);
ISC_LIST_INIT(zone->nsec3chain);
ISC_LIST_INIT(zone->setnsec3param_queue);
zone->signatures = 10;
zone->nodes = 100;
zone->privatetype = (dns_rdatatype_t)0xffffU;
@ -1116,6 +1121,7 @@ zone_free(dns_zone_t *zone) {
isc_mem_t *mctx = NULL;
dns_signing_t *signing;
dns_nsec3chain_t *nsec3chain;
isc_event_t *setnsec3param_event;
dns_include_t *include;
REQUIRE(DNS_ZONE_VALID(zone));
@ -1149,6 +1155,12 @@ zone_free(dns_zone_t *zone) {
}
/* Unmanaged objects */
while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
ev_link);
isc_event_free(&setnsec3param_event);
}
for (signing = ISC_LIST_HEAD(zone->signing);
signing != NULL;
signing = ISC_LIST_HEAD(zone->signing)) {
@ -14750,6 +14762,8 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) {
unsigned int oldserial = 0;
bool have_oldserial = false;
nsec3paramlist_t nsec3list;
isc_event_t *setnsec3param_event;
dns_zone_t *dummy;
UNUSED(task);
@ -14874,6 +14888,18 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) {
zone_needdump(zone, 0); /* XXXMPA */
UNLOCK_ZONE(zone->raw);
/*
* Process any queued NSEC3PARAM change requests.
*/
while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
ev_link);
dummy = NULL;
zone_iattach(zone, &dummy);
isc_task_send(zone->task, &setnsec3param_event);
}
failure:
UNLOCK_ZONE(zone);
if (result != ISC_R_SUCCESS)
@ -19093,8 +19119,22 @@ dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
np->nsec = false;
}
zone_iattach(zone, &dummy);
isc_task_send(zone->task, &e);
/*
* setnsec3param() will silently return early if the zone does not yet
* have a database. Prevent that by queueing the event up if zone->db
* is NULL. All events queued here are subsequently processed by
* receive_secure_db() if it ever gets called or simply freed by
* zone_free() otherwise.
*/
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
if (zone->db != NULL) {
zone_iattach(zone, &dummy);
isc_task_send(zone->task, &e);
} else {
ISC_LIST_APPEND(zone->setnsec3param_queue, e, ev_link);
e = NULL;
}
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
failure:
if (e != NULL)