Merge branch '4141-find-zone_keys' into 'main'

Update find_zone_keys for dynamic update

Closes #4141

See merge request isc-projects/bind9!8029
This commit is contained in:
Matthijs Mekking 2023-06-14 08:05:55 +00:00
commit dc71aab358
10 changed files with 195 additions and 17 deletions

View file

@ -1,3 +1,7 @@
6194. [func] Change function 'find_zone_keys()' to look for signing
keys by looking for key files instead of a DNSKEY
RRset lookup. [GL #4141]
6193. [bug] Fix a catz db update notification callback registration
logic error, which could crash named when receiving an
AXFR update for a catalog zone while the previous update

View file

@ -132,10 +132,19 @@ echo server "${SERVER}" "${PORT}"
echo update add $(cat "ns4/${ZONE}.zsk")
echo send
) | $NSUPDATE
# Check the new DNSKEY RRset.
n=$((n+1))
echo_i "check zone ${ZONE} DNSKEY RRset after update ($n)"
retry_quiet 10 zsks_are_published || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Check the logs for find zone keys errors.
n=$((n+1))
ret=0
echo_i "make sure we did not try to sign with the keys added with nsupdate for zone ${ZONE} ($n)"
grep "dns_dnssec_findzonekeys: error reading ./K${ZONE}.*\.private: file not found" "${DIR}/named.run" && ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Verify again.
dnssec_verify
@ -149,10 +158,19 @@ echo server "${SERVER}" "${PORT}"
echo update add $(cat "ns3/${ZONE}.zsk")
echo send
) | $NSUPDATE
# Check the new DNSKEY RRset.
n=$((n+1))
echo_i "check zone ${ZONE} DNSKEY RRset after update ($n)"
retry_quiet 10 zsks_are_published || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Check the logs for find zone keys errors.
n=$((n+1))
ret=0
echo_i "make sure we did not try to sign with the keys added with nsupdate for zone ${ZONE} ($n)"
grep "dns_dnssec_findzonekeys: error reading ./K${ZONE}.*\.private: file not found" "${DIR}/named.run" && ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Verify again.
dnssec_verify
no_dnssec_in_journal
@ -446,6 +464,9 @@ test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
dnssec_verify
no_dnssec_in_journal
grep "dns_dnssec_findzonekeys: error reading ./K${ZONE}.*\.private: file not found" "${DIR}/named.run" && ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# NS4
set_server "ns4" "10.53.0.4"
echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)"
@ -454,6 +475,9 @@ test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
dnssec_verify
no_dnssec_in_journal
grep "dns_dnssec_findzonekeys: error reading ./K${ZONE}.*\.private: file not found" "${DIR}/named.run" && ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
n=$((n+1))
echo_i "remove dnskey record: remove ns3 and ns4 DNSKEY records from primary ns5 ($n)"

View file

@ -21,9 +21,11 @@ rm -f */named.memstats
rm -f */named.run */ans.run
rm -f */named.run.prev
rm -f Kxxx.*
rm -f doubleksk.key prepub.key
rm -f check.out.*
rm -f dig.out.*
rm -f jp.out.ns3.*
rm -f keygen.out.*
rm -f nextpart.out.*
rm -f ns*/managed-keys.bind* ns*/*.mkeys*
rm -f ns*/named.lock
@ -45,12 +47,14 @@ rm -f ns3/*.signed
rm -f ns3/K*
rm -f ns3/delegation.test.db
rm -f ns3/dnskey.test.db
rm -f ns3/doubleksk.test.db
rm -f ns3/dsset-*
rm -f ns3/example.db
rm -f ns3/relaxed.db
rm -f ns3/multisigner.test.db
rm -f ns3/many.test.bk
rm -f ns3/nsec3param.test.db
rm -f ns3/prepub.test.db
rm -f ns3/too-big.test.db
rm -f ns5/local.db
rm -f ns6/in-addr.db

View file

@ -0,0 +1,15 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
doubleksk.test. 10 IN SOA doubleksk.test. hostmaster.doubleksk.test. 1 3600 900 2419200 3600
doubleksk.test. 10 IN NS doubleksk.test.
doubleksk.test. 10 IN A 10.53.0.3
doubleksk.test. 10 IN NSEC3PARAM 1 1 0 -

View file

@ -26,6 +26,16 @@ options {
dnssec-validation yes;
};
key rndc_key {
secret "1234abcd8765";
algorithm @DEFAULT_HMAC@;
};
controls {
inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "example" {
type primary;
allow-update { any; };
@ -71,6 +81,22 @@ zone "too-big.test" {
file "too-big.test.db";
};
zone "prepub.test" {
type primary;
allow-update { any; };
auto-dnssec maintain;
dnssec-dnskey-kskonly yes;
file "prepub.test.db.signed";
};
zone "doubleksk.test" {
type primary;
allow-update { any; };
auto-dnssec maintain;
dnssec-dnskey-kskonly yes;
file "doubleksk.test.db.signed";
};
/* Zone for testing CDS and CDNSKEY updates from other provider */
zone "multisigner.test" {
type primary;

View file

@ -0,0 +1,15 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
prepub.test. 10 IN SOA prepub.test. hostmaster.prepub.test. 1 3600 900 2419200 3600
prepub.test. 10 IN NS prepub.test.
prepub.test. 10 IN A 10.53.0.3
prepub.test. 10 IN NSEC3PARAM 1 1 0 -

View file

@ -46,5 +46,27 @@ cat $infile $keyname1.key $keyname2.key >$zonefile
$SIGNER -A -3 - -P -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
zone=prepub.test.
infile=prepub.test.db.in
zonefile=prepub.test.db
keyname1=$($KEYGEN -q -L 3600 -a ${DEFAULT_ALGORITHM} -f KSK $zone)
keyname2=$($KEYGEN -q -L 3600 -a ${DEFAULT_ALGORITHM} $zone)
cat $infile $keyname1.key $keyname2.key >$zonefile
$SIGNER -A -x -3 - -P -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
zone=doubleksk.test.
infile=doubleksk.test.db.in
zonefile=doubleksk.test.db
keyname1=$($KEYGEN -q -L 3600 -a ${DEFAULT_ALGORITHM} -f KSK $zone)
keyname2=$($KEYGEN -q -L 3600 -a ${DEFAULT_ALGORITHM} $zone)
cat $infile $keyname1.key $keyname2.key >$zonefile
$SIGNER -A -x -3 - -P -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
# Just copy multisigner.db.in because it is signed with dnssec-policy.
cp multisigner.test.db.in multisigner.test.db

View file

@ -1614,6 +1614,48 @@ END
retry_quiet 5 has_positive_response multisigner.test CDNSKEY 10.53.0.3 || ret=1
[ $ret = 0 ] || { echo_i "failed"; status=1; }
n=$((n + 1))
ret=0
echo_i "check that DNSKEY can be prepublished with dynamic update ($n)"
$DIG $DIGOPTS +tcp +norec prepub.test DNSKEY @10.53.0.3 > dig.out.pre.test$n || ret=1
grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1
grep "ANSWER: 2," dig.out.pre.test$n > /dev/null || ret=1
zsk=$($KEYGEN -a $DEFAULT_ALGORITHM -K ns3 -L 3600 -P now -A now+1w prepub.test 2> keygen.out.prepub.test.out$n)
cat "ns3/${zsk}.key" | grep -v ";.*" > prepub.key
$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 || ret=1
server 10.53.0.3 ${PORT}
zone prepub.test
update add $(cat prepub.key)
send
END
$RNDCCMD 10.53.0.3 loadkeys prepub.test. 2>&1 || ret=1
$DIG $DIGOPTS +tcp +norec prepub.test DNSKEY @10.53.0.3 > dig.out.post.test$n || ret=1
grep "status: NOERROR" dig.out.post.test$n > /dev/null || ret=1
grep "ANSWER: 3," dig.out.post.test$n > /dev/null || ret=1
[ $ret = 0 ] || { echo_i "failed"; status=1; }
n=$((n + 1))
ret=0
echo_i "check that DNSKEY can be added as a signing key with dynamic update ($n)"
$DIG $DIGOPTS +dnssec +tcp +norec doubleksk.test DNSKEY @10.53.0.3 > dig.out.pre.test$n || ret=1
grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1
# 2x DNSKEY, 1x RRSIG
grep "ANSWER: 3," dig.out.pre.test$n > /dev/null || ret=1
ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -K ns3 -L 3600 -fk -P now -A now doubleksk.test 2> keygen.out.doubleksk.test.out$n)
cat "ns3/${ksk}.key" | grep -v ";.*" > doubleksk.key
$NSUPDATE -d <<END > nsupdate.out.test$n 2>&1 || ret=1
server 10.53.0.3 ${PORT}
zone doubleksk.test
update add $(cat doubleksk.key)
send
END
$RNDCCMD 10.53.0.3 loadkeys doubleksk.test. 2>&1 || ret=1
$DIG $DIGOPTS +dnssec +tcp +norec doubleksk.test DNSKEY @10.53.0.3 > dig.out.post.test$n || ret=1
grep "status: NOERROR" dig.out.post.test$n > /dev/null || ret=1
# 3x DNSKEY, 2x RRSIG
grep "ANSWER: 5," dig.out.post.test$n > /dev/null || ret=1
[ $ret = 0 ] || { echo_i "failed"; status=1; }
n=$((n + 1))
ret=0
echo_i "check that excessive NSEC3PARAM iterations are rejected by nsupdate ($n)"

View file

@ -858,7 +858,7 @@ dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
"dns_dnssec_findzonekeys2: error "
"dns_dnssec_findzonekeys: error "
"reading %s: %s",
filename, isc_result_totext(result));
}

View file

@ -1055,26 +1055,49 @@ failure:
}
static isc_result_t
find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
isc_mem_t *mctx, unsigned int maxkeys, dst_key_t **keys,
unsigned int *nkeys) {
find_zone_keys(dns_zone_t *zone, isc_mem_t *mctx, unsigned int maxkeys,
dst_key_t **keys, unsigned int *nkeys) {
dns_dnsseckeylist_t keylist;
dns_dnsseckey_t *k = NULL;
unsigned int count = 0;
isc_result_t result;
isc_stdtime_t now = isc_stdtime_now();
dns_dbnode_t *node = NULL;
const char *directory = dns_zone_getkeydirectory(zone);
CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
ISC_LIST_INIT(keylist);
dns_zone_lock_keyfiles(zone);
result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
directory, now, mctx, maxkeys, keys,
nkeys);
result = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone),
dns_zone_getkeydirectory(zone),
now, mctx, &keylist);
dns_zone_unlock_keyfiles(zone);
failure:
if (node != NULL) {
dns_db_detachnode(db, &node);
if (result != ISC_R_SUCCESS) {
*nkeys = 0;
return (result);
}
/* Add new 'dnskeys' to 'keys' */
while ((k = ISC_LIST_HEAD(keylist)) != NULL) {
if (count >= maxkeys) {
result = ISC_R_NOSPACE;
goto next;
}
/* Detect inactive keys */
if (!dns_dnssec_keyactive(k->key, now)) {
dst_key_setinactive(k->key, true);
}
keys[count] = k->key;
k->key = NULL;
count++;
next:
ISC_LIST_UNLINK(keylist, k, link);
dns_dnsseckey_destroy(mctx, &k);
}
*nkeys = count;
return (result);
}
@ -1544,10 +1567,13 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
state->nkeys = 0;
state->build_nsec3 = false;
result = find_zone_keys(zone, db, newver, diff->mctx,
DNS_MAXZONEKEYS, state->zone_keys,
&state->nkeys);
if (result != ISC_R_SUCCESS) {
result = find_zone_keys(zone, diff->mctx, DNS_MAXZONEKEYS,
state->zone_keys, &state->nkeys);
if (result == ISC_R_NOSPACE) {
update_log(log, zone, ISC_LOG_ERROR,
"too many zone keys for secure "
"dynamic update");
} else if (result != ISC_R_SUCCESS) {
update_log(log, zone, ISC_LOG_ERROR,
"could not get zone keys for secure "
"dynamic update");