2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

2735. [bug] dnssec-signzone could fail to read keys

that were specified on the command line with
			full paths, but weren't in the current
			directory. [RT #20421]
This commit is contained in:
Evan Hunt
2009-10-27 03:59:45 +00:00
parent af30180834
commit e8831e51c1
5 changed files with 219 additions and 186 deletions

View File

@@ -16,7 +16,7 @@
*/
/*
* $Id: dnssec.c,v 1.107 2009/10/26 21:18:24 each Exp $
* $Id: dnssec.c,v 1.108 2009/10/27 03:59:45 each Exp $
*/
/*! \file */
@@ -1202,7 +1202,8 @@ addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey,
/*
* Found a match. If the old key was only public and the
* new key is private, replace the old one; otherwise
* we're done.
* leave it. But either way, mark the key as having
* been found in the zone.
*/
if (dst_key_isprivate(key->key)) {
dst_key_free(newkey);
@@ -1211,6 +1212,7 @@ addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey,
key->key = *newkey;
}
key->source = dns_keysource_zoneapex;
return;
}
@@ -1224,49 +1226,95 @@ addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey,
*newkey = NULL;
}
/*%
* Mark all keys which signed the DNSKEY/SOA RRsets as "active",
* for future reference.
*/
static isc_result_t
mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) {
isc_result_t result = ISC_R_SUCCESS;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_t sigs;
dns_dnsseckey_t *key;
REQUIRE(rrsigs != NULL && dns_rdataset_isassociated(rrsigs));
dns_rdataset_init(&sigs);
dns_rdataset_clone(rrsigs, &sigs);
for (key = ISC_LIST_HEAD(*keylist);
key != NULL;
key = ISC_LIST_NEXT(key, link)) {
isc_uint16_t keyid, sigid;
dns_secalg_t keyalg, sigalg;
keyid = dst_key_id(key->key);
keyalg = dst_key_alg(key->key);
for (result = dns_rdataset_first(&sigs);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&sigs)) {
dns_rdata_rrsig_t sig;
dns_rdata_reset(&rdata);
dns_rdataset_current(&sigs, &rdata);
result = dns_rdata_tostruct(&rdata, &sig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
sigalg = sig.algorithm;
sigid = sig.keyid;
if (keyid == sigid && keyalg == sigalg) {
key->is_active = ISC_TRUE;
break;
}
}
}
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
if (dns_rdataset_isassociated(&sigs))
dns_rdataset_disassociate(&sigs);
return (result);
}
/*%
* Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'.
*/
isc_result_t
dns_dnssec_keylistfromrdataset(dns_name_t *origin,
const char *directory, isc_mem_t *mctx,
dns_rdataset_t *keyset, dns_rdataset_t *sigset,
isc_boolean_t savekeys, isc_boolean_t public,
dns_rdataset_t *keyset, dns_rdataset_t *keysigs,
dns_rdataset_t *soasigs, isc_boolean_t savekeys,
isc_boolean_t public,
dns_dnsseckeylist_t *keylist)
{
dns_rdataset_t keys, sigs;
dns_rdataset_t keys;
dns_rdata_t rdata = DNS_RDATA_INIT;
dst_key_t *pubkey, *privkey;
dns_dnsseckey_t *key;
dst_key_t *pubkey = NULL, *privkey = NULL;
isc_result_t result;
dns_rdataset_init(&keys);
dns_rdataset_init(&sigs);
REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset));
dns_rdataset_clone(keyset, &keys);
dns_rdataset_init(&keys);
dns_rdataset_clone(keyset, &keys);
for (result = dns_rdataset_first(&keys);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&keys)) {
pubkey = NULL;
privkey = NULL;
dns_rdata_reset(&rdata);
dns_rdataset_current(&keys, &rdata);
RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &pubkey));
if (!is_zone_key(pubkey) ||
(dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0)
goto again;
goto skip;
/* Corrupted .key file? */
if (!dns_name_equal(origin, dst_key_name(pubkey)))
goto again;
goto skip;
if (public) {
addkey(keylist, &pubkey, savekeys, mctx);
goto again;
goto skip;
}
result = dst_key_fromfile(dst_key_name(pubkey),
@@ -1276,65 +1324,36 @@ dns_dnssec_keylistfromrdataset(dns_name_t *origin,
directory, mctx, &privkey);
if (result == ISC_R_FILENOTFOUND) {
addkey(keylist, &pubkey, savekeys, mctx);
goto again;
goto skip;
}
RETERR(result);
/* This should never happen. */
if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0)
goto again;
goto skip;
addkey(keylist, &privkey, savekeys, mctx);
again:
skip:
if (pubkey != NULL)
dst_key_free(&pubkey);
if (privkey != NULL)
dst_key_free(&privkey);
}
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
else if (result != ISC_R_SUCCESS)
goto failure;
if (sigset == NULL || !dns_rdataset_isassociated(sigset))
goto success;
if (result != ISC_R_NOMORE)
RETERR(result);
dns_rdataset_clone(sigset, &sigs);
if (keysigs != NULL && dns_rdataset_isassociated(keysigs))
RETERR(mark_active_keys(keylist, keysigs));
/*
* Mark all keys which signed the DNSKEY set, for future reference.
*/
for (key = ISC_LIST_HEAD(*keylist);
key != NULL;
key = ISC_LIST_NEXT(key, link)) {
isc_uint16_t keyid, sigid;
isc_uint8_t keyalg, sigalg;
keyid = dst_key_id(key->key);
keyalg = dst_key_alg(key->key);
if (soasigs != NULL && dns_rdataset_isassociated(soasigs))
RETERR(mark_active_keys(keylist, soasigs));
for (result = dns_rdataset_first(&sigs);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&sigs)) {
dns_rdata_reset(&rdata);
dns_rdataset_current(&sigs, &rdata);
sigalg = rdata.data[2];
sigid = (rdata.data[16] << 8) | rdata.data[17];
if (keyid == sigid && keyalg == sigalg) {
key->is_active = ISC_TRUE;
break;
}
}
}
if (result == ISC_R_NOMORE)
success:
result = ISC_R_SUCCESS;
result = ISC_R_SUCCESS;
failure:
if (dns_rdataset_isassociated(&keys))
dns_rdataset_disassociate(&keys);
if (dns_rdataset_isassociated(&sigs))
dns_rdataset_disassociate(&sigs);
if (pubkey != NULL)
dst_key_free(&pubkey);
if (privkey != NULL)
@@ -1342,7 +1361,6 @@ dns_dnssec_keylistfromrdataset(dns_name_t *origin,
return (result);
}
static isc_result_t
make_dnskey(dst_key_t *key, dns_rdata_t *target) {
isc_result_t result;
@@ -1441,11 +1459,32 @@ dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
void (*report)(const char *, ...))
{
isc_result_t result;
dns_dnsseckey_t *key1, *key2;
dns_dnsseckey_t *key, *key1, *key2, *next;
key1 = ISC_LIST_HEAD(*newkeys);
while (key1 != NULL) {
/*
* First, look through the existing key list to find keys
* supplied from the command line which are not in the zone.
* Update the zone to include them.
*/
for (key = ISC_LIST_HEAD(*keys);
key != NULL;
key = ISC_LIST_NEXT(key, link)) {
if (key->source == dns_keysource_user &&
(key->hint_publish || key->force_publish)) {
RETERR(publish_key(add, key, origin, ttl,
mctx, allzsk, report));
}
}
/*
* Second, scan the list of newly found keys looking for matches
* with known keys, and update accordingly.
*/
for (key1 = ISC_LIST_HEAD(*newkeys); key1 != NULL; key1 = next) {
isc_boolean_t key_revoked = ISC_FALSE;
next = ISC_LIST_NEXT(key1, link);
for (key2 = ISC_LIST_HEAD(*keys);
key2 != NULL;
key2 = ISC_LIST_NEXT(key2, link)) {
@@ -1477,7 +1516,6 @@ dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
key1->first_sign = ISC_TRUE;
}
key1 = next;
continue;
}
@@ -1492,7 +1530,6 @@ dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
dns_dnsseckey_destroy(mctx, &key2);
} else if (key_revoked &&
(dst_key_flags(key1->key) & DNS_KEYFLAG_REVOKE) != 0) {
dns_dnsseckey_t *next;
/*
* A previously valid key has been revoked.
@@ -1509,7 +1546,6 @@ dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
RETERR(publish_key(add, key1, origin, ttl,
mctx, allzsk, report));
next = ISC_LIST_NEXT(key1, link);
ISC_LIST_UNLINK(*newkeys, key1, link);
ISC_LIST_APPEND(*keys, key1, link);
@@ -1522,27 +1558,14 @@ dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
* sign other records with it.
*/
key1->ksk = ISC_TRUE;
key1 = next;
continue;
} else {
if (!key2->is_active &&
(key1->hint_sign || key1->force_sign))
key2->first_sign = ISC_TRUE;
key2->hint_sign = key1->hint_sign;
/*
* If a key was specified on the command line,
* not in the zone, it can be imported into the
* zone now.
*/
key2->hint_publish = key1->hint_publish;
if (key2->source == dns_keysource_user &&
(key2->hint_publish || key2->force_publish))
RETERR(publish_key(add, key2, origin, ttl,
mctx, allzsk, report));
}
key1 = ISC_LIST_NEXT(key1, link);
}
/* Free any leftover keys in newkeys */