From 7ed089576f295b8330d4527ff0fefda0b228be03 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 8 Apr 2021 11:35:03 +0200 Subject: [PATCH] Try to read state when reading keylist from rdata The function 'dns_dnssec_keylistfromrdataset()' creates a keylist from the DNSKEY RRset. If we attempt to read the private key, we also store the key state. However, if the private key is offline, the key state will not be stored. To fix this, first attempt to read the public key file. If then reading the private key file fails, and we do have a public key, add that to the keylist, with appropriate state. If we also failed to read the public key file, add the DNSKEY to the keylist, as we did before. --- lib/dns/dnssec.c | 67 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index 97316b7d33..f2a107b5fd 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -1657,7 +1657,7 @@ dns_dnssec_keylistfromrdataset(const dns_name_t *origin, const char *directory, dns_dnsseckeylist_t *keylist) { dns_rdataset_t keys; dns_rdata_t rdata = DNS_RDATA_INIT; - dst_key_t *pubkey = NULL, *privkey = NULL; + dst_key_t *dnskey = NULL, *pubkey = NULL, *privkey = NULL; isc_result_t result; REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset)); @@ -1680,27 +1680,38 @@ dns_dnssec_keylistfromrdataset(const dns_name_t *origin, const char *directory, goto skip; } - RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &pubkey)); - dst_key_setttl(pubkey, keys.ttl); + RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &dnskey)); + dst_key_setttl(dnskey, keys.ttl); - if (!is_zone_key(pubkey) || - (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) { + if (!is_zone_key(dnskey) || + (dst_key_flags(dnskey) & DNS_KEYTYPE_NOAUTH) != 0) { goto skip; } /* Corrupted .key file? */ - if (!dns_name_equal(origin, dst_key_name(pubkey))) { + if (!dns_name_equal(origin, dst_key_name(dnskey))) { goto skip; } if (publickey) { - RETERR(addkey(keylist, &pubkey, savekeys, mctx)); + RETERR(addkey(keylist, &dnskey, savekeys, mctx)); goto skip; } + /* Try to read the public key. */ result = dst_key_fromfile( - dst_key_name(pubkey), dst_key_id(pubkey), - dst_key_alg(pubkey), + dst_key_name(dnskey), dst_key_id(dnskey), + dst_key_alg(dnskey), (DST_TYPE_PUBLIC | DST_TYPE_STATE), + directory, mctx, &pubkey); + if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { + result = ISC_R_SUCCESS; + } + RETERR(result); + + /* Now read the private key. */ + result = dst_key_fromfile( + dst_key_name(dnskey), dst_key_id(dnskey), + dst_key_alg(dnskey), (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE), directory, mctx, &privkey); @@ -1711,22 +1722,22 @@ dns_dnssec_keylistfromrdataset(const dns_name_t *origin, const char *directory, */ if (result == ISC_R_FILENOTFOUND) { uint32_t flags; - flags = dst_key_flags(pubkey); + flags = dst_key_flags(dnskey); if ((flags & DNS_KEYFLAG_REVOKE) != 0) { - dst_key_setflags(pubkey, + dst_key_setflags(dnskey, flags & ~DNS_KEYFLAG_REVOKE); result = dst_key_fromfile( - dst_key_name(pubkey), - dst_key_id(pubkey), dst_key_alg(pubkey), + dst_key_name(dnskey), + dst_key_id(dnskey), dst_key_alg(dnskey), (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE), directory, mctx, &privkey); if (result == ISC_R_SUCCESS && - dst_key_pubcompare(pubkey, privkey, false)) + dst_key_pubcompare(dnskey, privkey, false)) { dst_key_setflags(privkey, flags); } - dst_key_setflags(pubkey, flags); + dst_key_setflags(dnskey, flags); } } @@ -1739,8 +1750,8 @@ dns_dnssec_keylistfromrdataset(const dns_name_t *origin, const char *directory, isc_buffer_init(&buf, filename, NAME_MAX); result2 = dst_key_getfilename( - dst_key_name(pubkey), dst_key_id(pubkey), - dst_key_alg(pubkey), + dst_key_name(dnskey), dst_key_id(dnskey), + dst_key_alg(dnskey), (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE), directory, mctx, &buf); @@ -1748,13 +1759,13 @@ dns_dnssec_keylistfromrdataset(const dns_name_t *origin, const char *directory, char namebuf[DNS_NAME_FORMATSIZE]; char algbuf[DNS_SECALG_FORMATSIZE]; - dns_name_format(dst_key_name(pubkey), namebuf, + dns_name_format(dst_key_name(dnskey), namebuf, sizeof(namebuf)); - dns_secalg_format(dst_key_alg(pubkey), algbuf, + dns_secalg_format(dst_key_alg(dnskey), algbuf, sizeof(algbuf)); snprintf(filename, sizeof(filename) - 1, "key file for %s/%s/%d", namebuf, - algbuf, dst_key_id(pubkey)); + algbuf, dst_key_id(dnskey)); } isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, @@ -1765,7 +1776,13 @@ dns_dnssec_keylistfromrdataset(const dns_name_t *origin, const char *directory, } if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { - RETERR(addkey(keylist, &pubkey, savekeys, mctx)); + if (pubkey != NULL) { + RETERR(addkey(keylist, &pubkey, savekeys, + mctx)); + } else { + RETERR(addkey(keylist, &dnskey, savekeys, + mctx)); + } goto skip; } RETERR(result); @@ -1779,10 +1796,13 @@ dns_dnssec_keylistfromrdataset(const dns_name_t *origin, const char *directory, * Whatever the key's default TTL may have * been, the rdataset TTL takes priority. */ - dst_key_setttl(privkey, dst_key_getttl(pubkey)); + dst_key_setttl(privkey, dst_key_getttl(dnskey)); RETERR(addkey(keylist, &privkey, savekeys, mctx)); skip: + if (dnskey != NULL) { + dst_key_free(&dnskey); + } if (pubkey != NULL) { dst_key_free(&pubkey); } @@ -1809,6 +1829,9 @@ failure: if (dns_rdataset_isassociated(&keys)) { dns_rdataset_disassociate(&keys); } + if (dnskey != NULL) { + dst_key_free(&dnskey); + } if (pubkey != NULL) { dst_key_free(&pubkey); }