Update ZONEMD records as part of UPDATE processing
dns_update_zonemd() has been added to update ZONEMD records. dns_update_signaturesinc() has been extended to update (via dns_update_zonemd) and sign ZONEMD records.
This commit is contained in:
@@ -105,3 +105,15 @@ zone "multisigner.test" {
|
||||
dnssec-policy "default-dynamic";
|
||||
file "multisigner.test.db";
|
||||
};
|
||||
|
||||
zone "zonemd.test" {
|
||||
type primary;
|
||||
allow-update { any; };
|
||||
file "zonemd.test.db.signed";
|
||||
};
|
||||
|
||||
zone "zonemd-nsec3.test" {
|
||||
type primary;
|
||||
allow-update { any; };
|
||||
file "zonemd-nsec3.test.db.signed";
|
||||
};
|
||||
|
||||
@@ -48,3 +48,28 @@ $SIGNER -A -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
|
||||
|
||||
# test a NSEC signed zone with ZONEMD being added.
|
||||
|
||||
zone=zonemd.test.
|
||||
infile=zonemd.test.db.in
|
||||
zonefile=zonemd.test.db
|
||||
|
||||
keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b 1024 -n zone -f KSK $zone)
|
||||
keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b 1024 -n zone $zone)
|
||||
|
||||
cat $infile $keyname1.key $keyname2.key >$zonefile
|
||||
|
||||
$SIGNER -z -o $zone -k $keyname1 $zonefile $keyname2 >/dev/null
|
||||
|
||||
# test a NSEC3 signed zone with ZONEMD being added.
|
||||
zone=zonemd-nsec3.test.
|
||||
infile=zonemd-nsec3.test.db.in
|
||||
zonefile=zonemd-nsec3.test.db
|
||||
|
||||
keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b 1024 -n zone -f KSK $zone)
|
||||
keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b 1024 -n zone $zone)
|
||||
|
||||
cat $infile $keyname1.key $keyname2.key >$zonefile
|
||||
|
||||
$SIGNER -3 - -z -o $zone -k $keyname1 $zonefile $keyname2 >/dev/null
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
; 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.
|
||||
|
||||
$TTL 10
|
||||
zonemd-nsec3.test. IN SOA ns3.zonemd-nsec3.test. hostmaster.zonemd-nsec3.test. 1 3600 900 2419200 3600
|
||||
zonemd-nsec3.test. IN NS ns3.zonemd-nsec3.test.
|
||||
zonemd-nsec3.test. IN NS ns5.zonemd-nsec3.test.
|
||||
ns3.zonemd-nsec3.test. IN A 10.53.0.3
|
||||
ns5.zonemd-nsec3.test. IN A 10.53.0.5
|
||||
@@ -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.
|
||||
|
||||
$TTL 10
|
||||
zonemd.test. IN SOA zonemd.test. hostmaster.zonemd.test. 1 3600 900 2419200 3600
|
||||
zonemd.test. IN NS zonemd.test.
|
||||
zonemd.test. IN A 10.53.0.3
|
||||
@@ -2443,6 +2443,44 @@ wait_for_log 10 "too many DNS UPDATEs queued" ns1/named.run || ret=1
|
||||
status=1
|
||||
}
|
||||
|
||||
n=$(expr $n + 1)
|
||||
ret=0
|
||||
echo_i "check that adding a dummy ZONEMD record result updated ZONEMD record (nsec) ($n)"
|
||||
$NSUPDATE -D -C resolv.conf -p ${PORT} <<EOF >nsupdate.out-$n 2>&1 || ret=1
|
||||
server 10.53.0.3 ${PORT}
|
||||
zone zonemd.test
|
||||
update add zonemd.test 0 zonemd 0 1 1 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
send
|
||||
EOF
|
||||
$DIG $DIGOPTS +tcp +norec zonemd.test ZONEMD +dnssec @10.53.0.3 >dig.out.test$n || ret=1
|
||||
grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1
|
||||
grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1
|
||||
grep "^zonemd\.test\..*IN.ZONEMD.2 1 1" dig.out.test$n >/dev/null || ret=1
|
||||
grep "^zonemd\.test\..*IN.RRSIG.ZONEMD" dig.out.test$n >/dev/null || ret=1
|
||||
[ $ret = 0 ] || {
|
||||
echo_i "failed"
|
||||
status=1
|
||||
}
|
||||
|
||||
n=$(expr $n + 1)
|
||||
ret=0
|
||||
echo_i "check that adding a dummy ZONEMD record result updated ZONEMD record (nsec3) ($n)"
|
||||
$NSUPDATE -D -C resolv.conf -p ${PORT} <<EOF >nsupdate.out-$n 2>&1 || ret=1
|
||||
server 10.53.0.3 ${PORT}
|
||||
zone zonemd-nsec3.test
|
||||
update add zonemd-nsec3.test 0 zonemd 0 1 1 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
send
|
||||
EOF
|
||||
$DIG $DIGOPTS +tcp +norec zonemd-nsec3.test ZONEMD +dnssec @10.53.0.3 >dig.out.test$n || ret=1
|
||||
grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1
|
||||
grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1
|
||||
grep "^zonemd-nsec3\.test\..*IN.ZONEMD.2 1 1" dig.out.test$n >/dev/null || ret=1
|
||||
grep "^zonemd-nsec3\.test\..*IN.RRSIG.ZONEMD" dig.out.test$n >/dev/null || ret=1
|
||||
[ $ret = 0 ] || {
|
||||
echo_i "failed"
|
||||
status=1
|
||||
}
|
||||
|
||||
if ! $FEATURETEST --gssapi; then
|
||||
echo_i "SKIPPED: GSSAPI tests"
|
||||
else
|
||||
|
||||
@@ -59,6 +59,8 @@ pytestmark = pytest.mark.extra_artifacts(
|
||||
"ns3/nsec3param.test.db",
|
||||
"ns3/relaxed.db",
|
||||
"ns3/too-big.test.db",
|
||||
"ns3/zonemd-nsec3.test.db",
|
||||
"ns3/zonemd.test.db",
|
||||
"ns5/local.db",
|
||||
"ns6/2.0.0.2.ip6.addr.db",
|
||||
"ns6/in-addr.db",
|
||||
|
||||
@@ -54,6 +54,13 @@ dns_update_soaserial(uint32_t serial, dns_updatemethod_t method,
|
||||
* Sets *used to the method that was used.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_update_zonemd(dns_db_t *db, dns_dbversion_t *version, dns_diff_t *diff);
|
||||
/*%<
|
||||
* Update the apex ZONEMD RRset's simple records to reflect changes in
|
||||
* zone content.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
||||
dns_dbversion_t *oldver, dns_dbversion_t *newver,
|
||||
|
||||
+113
-3
@@ -53,6 +53,7 @@
|
||||
#include <dns/update.h>
|
||||
#include <dns/view.h>
|
||||
#include <dns/zone.h>
|
||||
#include <dns/zonemd.h>
|
||||
#include <dns/zt.h>
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -1484,7 +1485,8 @@ struct dns_update_state {
|
||||
sign_nsec,
|
||||
update_nsec3,
|
||||
process_nsec3,
|
||||
sign_nsec3
|
||||
sign_nsec3,
|
||||
update_zonemd
|
||||
} state;
|
||||
};
|
||||
|
||||
@@ -1515,6 +1517,73 @@ dns__jitter_expire(dns_zone_t *zone) {
|
||||
return sigvalidity;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_update_zonemd(dns_db_t *db, dns_dbversion_t *version, dns_diff_t *diff) {
|
||||
bool found[256] = { 0 };
|
||||
dns_dbnode_t *node = NULL;
|
||||
dns_rdataset_t rdataset;
|
||||
isc_result_t result;
|
||||
|
||||
dns_rdataset_init(&rdataset);
|
||||
CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
|
||||
result = dns_db_findrdataset(db, node, version, dns_rdatatype_zonemd, 0,
|
||||
(isc_stdtime_t)0, &rdataset, NULL);
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
result = ISC_R_SUCCESS;
|
||||
goto failure;
|
||||
}
|
||||
CHECK(result);
|
||||
result = dns_rdataset_first(&rdataset);
|
||||
while (result == ISC_R_SUCCESS) {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdata_zonemd_t zonemd;
|
||||
unsigned char buf[DNS_ZONEMD_BUFFERSIZE];
|
||||
|
||||
dns_rdataset_current(&rdataset, &rdata);
|
||||
CHECK(dns_rdata_tostruct(&rdata, &zonemd, NULL));
|
||||
if (zonemd.scheme == DNS_ZONEMD_SCHEME_SIMPLE) {
|
||||
/*
|
||||
* Delete all ZONEMD simple records. We will
|
||||
* regenerate those with digest types we support.
|
||||
*/
|
||||
CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_DEL,
|
||||
dns_db_origin(db), rdataset.ttl,
|
||||
&rdata));
|
||||
/*
|
||||
* Only add a single record for a given digest type
|
||||
* regardless of how many records of that type exist.
|
||||
*/
|
||||
if (dns_zonemd_supported(&rdata) &&
|
||||
!found[zonemd.digest_type])
|
||||
{
|
||||
dns_rdata_reset(&rdata);
|
||||
CHECK(dns_zonemd_buildrdata(
|
||||
&rdata, db, version, zonemd.scheme,
|
||||
zonemd.digest_type, diff->mctx, buf,
|
||||
sizeof(buf)));
|
||||
CHECK(update_one_rr(db, version, diff,
|
||||
DNS_DIFFOP_ADD,
|
||||
dns_db_origin(db),
|
||||
rdataset.ttl, &rdata));
|
||||
found[zonemd.digest_type] = true;
|
||||
}
|
||||
}
|
||||
result = dns_rdataset_next(&rdataset);
|
||||
}
|
||||
if (result == ISC_R_NOMORE) {
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
failure:
|
||||
if (dns_rdataset_isassociated(&rdataset)) {
|
||||
dns_rdataset_disassociate(&rdataset);
|
||||
}
|
||||
if (node != NULL) {
|
||||
dns_db_detachnode(db, &node);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
||||
dns_dbversion_t *oldver, dns_dbversion_t *newver,
|
||||
@@ -1536,6 +1605,8 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
||||
unsigned int sigs = 0;
|
||||
unsigned int maxsigs = dns_zone_getsignatures(zone);
|
||||
|
||||
dns_rdataset_init(&rdataset);
|
||||
|
||||
if (statep == NULL || *statep == NULL) {
|
||||
if (statep == NULL) {
|
||||
state = &mystate;
|
||||
@@ -1582,7 +1653,6 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
||||
* MINIMUM field.
|
||||
*/
|
||||
CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
|
||||
dns_rdataset_init(&rdataset);
|
||||
CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa,
|
||||
0, (isc_stdtime_t)0, &rdataset,
|
||||
NULL));
|
||||
@@ -1590,6 +1660,7 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
||||
dns_rdataset_current(&rdataset, &rdata);
|
||||
CHECK(dns_rdata_tostruct(&rdata, &soa, NULL));
|
||||
state->nsecttl = ISC_MIN(rdataset.ttl, soa.minimum);
|
||||
dns_rdata_reset(&rdata);
|
||||
dns_rdataset_disassociate(&rdataset);
|
||||
dns_db_detachnode(db, &node);
|
||||
|
||||
@@ -1992,7 +2063,8 @@ next_state:
|
||||
if (!state->build_nsec3) {
|
||||
update_log(log, zone, ISC_LOG_DEBUG(3),
|
||||
"no NSEC3 chains to rebuild");
|
||||
goto failure;
|
||||
state->state = update_zonemd;
|
||||
goto next_state;
|
||||
}
|
||||
|
||||
update_log(log, zone, ISC_LOG_DEBUG(3),
|
||||
@@ -2156,6 +2228,41 @@ next_state:
|
||||
dns_diff_appendminimal(diff, &t);
|
||||
}
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case update_zonemd:
|
||||
state->state = update_zonemd;
|
||||
/*
|
||||
* Update apex ZONEMD RRset if present.
|
||||
*/
|
||||
update_log(log, zone, ISC_LOG_DEBUG(3), "Update apex ZONEMD?");
|
||||
|
||||
CHECK(dns_update_zonemd(db, newver, &state->work));
|
||||
if (ISC_LIST_EMPTY(state->work.tuples)) {
|
||||
update_log(log, zone, ISC_LOG_DEBUG(3),
|
||||
"No apex ZONEMD changes");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
update_log(log, zone, ISC_LOG_DEBUG(3),
|
||||
"Update apex ZONEMD RRset signatures");
|
||||
|
||||
CHECK(delete_if(true_p, db, newver, dns_db_origin(db),
|
||||
dns_rdatatype_rrsig, dns_rdatatype_zonemd, NULL,
|
||||
&state->sig_diff));
|
||||
CHECK(add_sigs(log, zone, db, newver, dns_db_origin(db),
|
||||
dns_rdatatype_zonemd, &state->sig_diff,
|
||||
state->zone_keys, state->nkeys, state->now,
|
||||
state->inception, state->expire));
|
||||
|
||||
/* Record our changes for the journal. */
|
||||
while ((t = ISC_LIST_HEAD(state->work.tuples)) != NULL) {
|
||||
ISC_LIST_UNLINK(state->work.tuples, t, link);
|
||||
dns_diff_appendminimal(diff, &t);
|
||||
}
|
||||
while ((t = ISC_LIST_HEAD(state->sig_diff.tuples)) != NULL) {
|
||||
ISC_LIST_UNLINK(state->sig_diff.tuples, t, link);
|
||||
dns_diff_appendminimal(diff, &t);
|
||||
}
|
||||
INSIST(ISC_LIST_EMPTY(state->sig_diff.tuples));
|
||||
INSIST(ISC_LIST_EMPTY(state->nsec_diff.tuples));
|
||||
INSIST(ISC_LIST_EMPTY(state->nsec_mindiff.tuples));
|
||||
@@ -2165,6 +2272,9 @@ next_state:
|
||||
}
|
||||
|
||||
failure:
|
||||
if (dns_rdataset_isassociated(&rdataset)) {
|
||||
dns_rdataset_disassociate(&rdataset);
|
||||
}
|
||||
if (node != NULL) {
|
||||
dns_db_detachnode(db, &node);
|
||||
}
|
||||
|
||||
@@ -3338,6 +3338,7 @@ update_action(void *arg) {
|
||||
*/
|
||||
CHECK(dns_nsec3param_deletechains(db, ver, zone, true,
|
||||
&diff));
|
||||
CHECK(dns_update_zonemd(db, ver, &diff));
|
||||
} else if (has_dnskey && isdnssec(db, ver, privatetype)) {
|
||||
dns_update_log_t log;
|
||||
uint32_t interval =
|
||||
@@ -3354,6 +3355,8 @@ update_action(void *arg) {
|
||||
isc_result_totext(result));
|
||||
goto failure;
|
||||
}
|
||||
} else {
|
||||
CHECK(dns_update_zonemd(db, ver, &diff));
|
||||
}
|
||||
|
||||
maxrecords = dns_zone_getmaxrecords(zone);
|
||||
|
||||
Reference in New Issue
Block a user