Apply SKR bundle on rekey

When a zone has a skr structure, lookup the currently active bundle
that contains the right key and signature material.

(cherry picked from commit 63e058c29e)
This commit is contained in:
Matthijs Mekking 2024-06-19 12:27:58 +02:00
parent f516e461fd
commit 6f6d000103
3 changed files with 132 additions and 6 deletions

View file

@ -21901,6 +21901,71 @@ update_ttl(dns_rdataset_t *rdataset, dns_name_t *name, dns_ttl_t ttl,
return (ISC_R_SUCCESS);
}
static void
remove_rdataset(dns_zone_t *zone, dns_diff_t *diff, dns_rdataset_t *rdataset) {
if (!dns_rdataset_isassociated(rdataset)) {
return;
}
for (isc_result_t result = dns_rdataset_first(rdataset);
result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset))
{
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_difftuple_t *tuple = NULL;
dns_rdataset_current(rdataset, &rdata);
dns_difftuple_create(zone->mctx, DNS_DIFFOP_DEL, &zone->origin,
rdataset->ttl, &rdata, &tuple);
dns_diff_append(diff, &tuple);
}
return;
}
static void
add_tuple(dns_diff_t *diff, dns_difftuple_t *tuple) {
dns_difftuple_t *copy = NULL;
dns_difftuple_copy(tuple, &copy);
dns_diff_appendminimal(diff, &copy);
}
static void
zone_apply_skrbundle(dns_zone_t *zone, dns_skrbundle_t *bundle,
dns_rdataset_t *dnskeyset, dns_rdataset_t *cdsset,
dns_rdataset_t *cdnskeyset, dns_diff_t *diff) {
dns_kasp_t *kasp = zone->kasp;
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(DNS_KASP_VALID(kasp));
REQUIRE(DNS_SKRBUNDLE_VALID(bundle));
/* Remove existing DNSKEY, CDS, and CDNSKEY records. */
remove_rdataset(zone, diff, dnskeyset);
remove_rdataset(zone, diff, cdsset);
remove_rdataset(zone, diff, cdnskeyset);
/* Add the records from the bundle. */
dns_difftuple_t *tuple = ISC_LIST_HEAD(bundle->diff.tuples);
while (tuple != NULL) {
switch (tuple->rdata.type) {
case dns_rdatatype_dnskey:
add_tuple(diff, tuple);
break;
case dns_rdatatype_cdnskey:
case dns_rdatatype_cds:
add_tuple(diff, tuple);
break;
case dns_rdatatype_rrsig:
/* Not interested in right now */
break;
default:
INSIST(0);
}
tuple = ISC_LIST_NEXT(tuple, link);
}
}
static void
zone_rekey(dns_zone_t *zone) {
isc_result_t result;
@ -21912,10 +21977,13 @@ zone_rekey(dns_zone_t *zone) {
dns_dnsseckey_t *key = NULL;
dns_diff_t diff, _sig_diff;
dns_kasp_t *kasp;
dns_skrbundle_t *bundle = NULL;
dns__zonediff_t zonediff;
bool commit = false, newactive = false;
bool newalg = false;
bool fullsign;
bool offlineksk = false;
uint32_t sigval = 0;
dns_ttl_t ttl = 3600;
const char *dir = NULL;
isc_mem_t *mctx = NULL;
@ -21958,14 +22026,13 @@ zone_rekey(dns_zone_t *zone) {
ttl = soaset.ttl;
dns_rdataset_disassociate(&soaset);
/*
* Only update DNSKEY TTL if we have a policy.
*/
if (kasp != NULL) {
ttl = dns_kasp_dnskeyttl(kasp);
offlineksk = dns_kasp_offlineksk(kasp);
sigval = dns_kasp_sigvalidity_dnskey(kasp);
}
/* Get the DNSKEY rdataset */
/* Get the current DNSKEY rdataset */
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
dns_rdatatype_none, 0, &keyset, &keysigs);
if (result == ISC_R_SUCCESS) {
@ -22007,7 +22074,7 @@ zone_rekey(dns_zone_t *zone) {
goto failure;
}
/* Get the CDS rdataset */
/* Get the current CDS rdataset */
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
dns_rdatatype_none, 0, &cdsset, NULL);
if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
@ -22026,7 +22093,7 @@ zone_rekey(dns_zone_t *zone) {
cdsset.ttl = ttl;
}
/* Get the CDNSKEY rdataset */
/* Get the current CDNSKEY rdataset */
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
dns_rdatatype_none, 0, &cdnskeyset, NULL);
if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
@ -22054,6 +22121,59 @@ zone_rekey(dns_zone_t *zone) {
*/
fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
if (offlineksk) {
/* Lookup the correct bundle in the SKR. */
LOCK_ZONE(zone);
if (zone->skr == NULL) {
UNLOCK_ZONE(zone);
dnssec_log(zone, ISC_LOG_DEBUG(1),
"zone_rekey:dns_skr_lookup failed: "
"no SKR available");
result = DNS_R_NOSKRFILE;
goto failure;
}
bundle = dns_skr_lookup(zone->skr, now, sigval);
zone->skrbundle = bundle;
UNLOCK_ZONE(zone);
if (bundle == NULL) {
char nowstr[26]; /* Minimal buf per ctime_r() spec. */
char utc[sizeof("YYYYMMDDHHSSMM")];
isc_buffer_t b;
isc_region_t r;
isc_buffer_init(&b, utc, sizeof(utc));
isc_stdtime_tostring(now, nowstr, sizeof(nowstr));
(void)dns_time32_totext(now, &b);
isc_buffer_usedregion(&b, &r);
dnssec_log(zone, ISC_LOG_DEBUG(1),
"zone_rekey:dns_skr_lookup failed: "
"no available SKR bundle for time "
"%.*s (%s)",
(int)r.length, r.base, nowstr);
result = DNS_R_NOSKRBUNDLE;
goto failure;
}
zone_apply_skrbundle(zone, bundle, &keyset, &cdsset,
&cdnskeyset, &diff);
dns_skrbundle_t *next = ISC_LIST_NEXT(bundle, link);
if (next != NULL) {
if (nexttime == 0) {
nexttime = next->inception;
}
} else {
dnssec_log(zone, ISC_LOG_WARNING,
"zone_rekey: last bundle in skr, please "
"import new skr file");
}
}
/*
* DNSSEC Key and Signing Policy
*/
KASP_LOCK(kasp);
dns_zone_lock_keyfiles(zone);

View file

@ -226,6 +226,8 @@ typedef enum isc_result {
DNS_R_HAVEPARMKEYS,
DNS_R_NOALPN,
DNS_R_NODOHPATH,
DNS_R_NOSKRFILE,
DNS_R_NOSKRBUNDLE,
DST_R_UNSUPPORTEDALG,
DST_R_CRYPTOFAILURE,

View file

@ -225,6 +225,8 @@ static const char *description[ISC_R_NRESULTS] = {
[DNS_R_HAVEPARMKEYS] = "unexpected service parameter keys",
[DNS_R_NOALPN] = "no ALPN",
[DNS_R_NODOHPATH] = "no DOHPATH",
[DNS_R_NOSKRFILE] = "no SKR file",
[DNS_R_NOSKRBUNDLE] = "no available SKR bundle",
[DST_R_UNSUPPORTEDALG] = "algorithm is unsupported",
[DST_R_CRYPTOFAILURE] = "crypto failure",
@ -477,6 +479,8 @@ static const char *identifier[ISC_R_NRESULTS] = {
[DNS_R_HAVEPARMKEYS] = "DNS_R_HAVEPARMKEYS",
[DNS_R_NOALPN] = "DNS_R_NOALPN",
[DNS_R_NODOHPATH] = "DNS_R_NODOHPATH",
[DNS_R_NOSKRFILE] = "DNS_R_NOSKRFILE",
[DNS_R_NOSKRBUNDLE] = "DNS_R_NOSKRBUNDLE",
[DST_R_UNSUPPORTEDALG] = "DST_R_UNSUPPORTEDALG",
[DST_R_CRYPTOFAILURE] = "DST_R_CRYPTOFAILURE",