mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Fix dnssec-keygen key collision checking for KEY rrtype keys
When generating a new key, dnssec-keygen checks for possible
key ID collisions with existing keys. The dnssec.c:findmatchingkeys()
function, which is supposed to get the list of the existing keys,
fails to do that for the existing KEY rrtype keys (i.e. generated
using 'dnssec-keygen -T KEY') because it doesn't pass down to the
dst_key_fromnamedfile() -> dst_key_read_public() functions the type
of the keys it's interested in. Fix the issue by introducing a new
function parameter which tells in which type of keys the caller is
currently interested in.
(cherry picked from commit 49b7ce9a54)
This commit is contained in:
parent
4dcb995aaa
commit
3a1922f464
11 changed files with 81 additions and 35 deletions
|
|
@ -224,7 +224,7 @@ get_dnskeys(ksr_ctx_t *ksr, dns_dnsseckeylist_t *keys) {
|
|||
ISC_LIST_INIT(*keys);
|
||||
ISC_LIST_INIT(keys_read);
|
||||
ret = dns_dnssec_findmatchingkeys(name, NULL, ksr->keydir, NULL,
|
||||
ksr->now, mctx, &keys_read);
|
||||
ksr->now, false, mctx, &keys_read);
|
||||
if (ret != ISC_R_SUCCESS && ret != ISC_R_NOTFOUND) {
|
||||
fatal("failed to load existing keys from %s: %s", ksr->keydir,
|
||||
isc_result_totext(ret));
|
||||
|
|
|
|||
|
|
@ -2852,7 +2852,7 @@ findkeys:
|
|||
* Find keys that match this zone in the key repository.
|
||||
*/
|
||||
result = dns_dnssec_findmatchingkeys(gorigin, NULL, directory, NULL,
|
||||
now, mctx, &matchkeys);
|
||||
now, false, mctx, &matchkeys);
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -511,10 +511,17 @@ key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir,
|
|||
}
|
||||
|
||||
ISC_LIST_INIT(matchkeys);
|
||||
result = dns_dnssec_findmatchingkeys(name, NULL, dir, NULL, now, mctx,
|
||||
&matchkeys);
|
||||
bool keykey = false;
|
||||
|
||||
/*
|
||||
* DNSKEY and KEY both use the same file names patterns so
|
||||
* we have to look for both sets of keys.
|
||||
*/
|
||||
again:
|
||||
result = dns_dnssec_findmatchingkeys(name, NULL, dir, NULL, now, keykey,
|
||||
mctx, &matchkeys);
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
return false;
|
||||
goto try_key;
|
||||
}
|
||||
|
||||
while (!ISC_LIST_EMPTY(matchkeys) && !conflict) {
|
||||
|
|
@ -558,6 +565,11 @@ key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir,
|
|||
dns_dnsseckey_destroy(mctx, &key);
|
||||
}
|
||||
|
||||
try_key:
|
||||
if (!conflict && !keykey) {
|
||||
keykey = true;
|
||||
goto again;
|
||||
}
|
||||
return conflict;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ void
|
|||
set_keyversion(dst_key_t *key);
|
||||
|
||||
bool
|
||||
key_collision(dst_key_t *key, dns_name_t *name, const char *dir,
|
||||
key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir,
|
||||
isc_mem_t *mctx, uint16_t min, uint16_t max, bool *exact);
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -1199,12 +1199,12 @@ dns_dnssec_get_hints(dns_dnsseckey_t *key, isc_stdtime_t now) {
|
|||
}
|
||||
|
||||
static isc_result_t
|
||||
findmatchingkeys(const char *directory, char *namebuf, unsigned int len,
|
||||
isc_mem_t *mctx, isc_stdtime_t now,
|
||||
findmatchingkeys(const char *directory, bool rrtypekey, char *namebuf,
|
||||
unsigned int len, isc_mem_t *mctx, isc_stdtime_t now,
|
||||
dns_dnsseckeylist_t *list) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_result_t result;
|
||||
isc_dir_t dir;
|
||||
bool dir_open = false;
|
||||
bool dir_open = false, match = false;
|
||||
unsigned int i, alg;
|
||||
dns_dnsseckey_t *key = NULL;
|
||||
dst_key_t *dstkey = NULL;
|
||||
|
|
@ -1213,6 +1213,7 @@ findmatchingkeys(const char *directory, char *namebuf, unsigned int len,
|
|||
if (directory == NULL) {
|
||||
directory = ".";
|
||||
}
|
||||
|
||||
RETERR(isc_dir_open(&dir, directory));
|
||||
dir_open = true;
|
||||
|
||||
|
|
@ -1261,11 +1262,13 @@ findmatchingkeys(const char *directory, char *namebuf, unsigned int len,
|
|||
continue;
|
||||
}
|
||||
|
||||
int type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE;
|
||||
if (rrtypekey) {
|
||||
type |= DST_TYPE_KEY;
|
||||
}
|
||||
dstkey = NULL;
|
||||
result = dst_key_fromnamedfile(
|
||||
dir.entry.name, directory,
|
||||
DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE,
|
||||
mctx, &dstkey);
|
||||
result = dst_key_fromnamedfile(dir.entry.name, directory, type,
|
||||
mctx, &dstkey);
|
||||
|
||||
switch (alg) {
|
||||
case DST_ALG_HMACMD5:
|
||||
|
|
@ -1297,9 +1300,11 @@ findmatchingkeys(const char *directory, char *namebuf, unsigned int len,
|
|||
dns_dnsseckey_destroy(mctx, &key);
|
||||
} else {
|
||||
ISC_LIST_APPEND(*list, key, link);
|
||||
match = true;
|
||||
key = NULL;
|
||||
}
|
||||
}
|
||||
result = match ? ISC_R_SUCCESS : ISC_R_NOTFOUND;
|
||||
|
||||
failure:
|
||||
if (dir_open) {
|
||||
|
|
@ -1312,12 +1317,13 @@ failure:
|
|||
}
|
||||
|
||||
/*%
|
||||
* Get a list of DNSSEC keys from the key repository.
|
||||
* Get a list of KEY or DNSKEY keys from the key repository. If rrtypekey
|
||||
* is true KEY keys will be returned otherwise DNSSEC keys.
|
||||
*/
|
||||
isc_result_t
|
||||
dns_dnssec_findmatchingkeys(const dns_name_t *origin, dns_kasp_t *kasp,
|
||||
const char *keydir, dns_keystorelist_t *keystores,
|
||||
isc_stdtime_t now, isc_mem_t *mctx,
|
||||
isc_stdtime_t now, bool rrtypekey, isc_mem_t *mctx,
|
||||
dns_dnsseckeylist_t *keylist) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
dns_dnsseckeylist_t list;
|
||||
|
|
@ -1337,8 +1343,8 @@ dns_dnssec_findmatchingkeys(const dns_name_t *origin, dns_kasp_t *kasp,
|
|||
if (kasp == NULL || (strcmp(dns_kasp_getname(kasp), "none") == 0) ||
|
||||
(strcmp(dns_kasp_getname(kasp), "insecure") == 0))
|
||||
{
|
||||
RETERR(findmatchingkeys(keydir, namebuf, len, mctx, now,
|
||||
&list));
|
||||
RETERR(findmatchingkeys(keydir, rrtypekey, namebuf, len, mctx,
|
||||
now, &list));
|
||||
} else if (keystores != NULL) {
|
||||
for (dns_keystore_t *keystore = ISC_LIST_HEAD(*keystores);
|
||||
keystore != NULL; keystore = ISC_LIST_NEXT(keystore, link))
|
||||
|
|
@ -1352,8 +1358,8 @@ dns_dnssec_findmatchingkeys(const dns_name_t *origin, dns_kasp_t *kasp,
|
|||
dns_keystore_directory(keystore,
|
||||
keydir);
|
||||
RETERR(findmatchingkeys(
|
||||
directory, namebuf, len, mctx,
|
||||
now, &list));
|
||||
directory, rrtypekey, namebuf,
|
||||
len, mctx, now, &list));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -285,13 +285,16 @@ dns_dnssec_get_hints(dns_dnsseckey_t *key, isc_stdtime_t now);
|
|||
isc_result_t
|
||||
dns_dnssec_findmatchingkeys(const dns_name_t *origin, dns_kasp_t *kasp,
|
||||
const char *keydir, dns_keystorelist_t *keystores,
|
||||
isc_stdtime_t now, isc_mem_t *mctx,
|
||||
isc_stdtime_t now, bool rrtypekey, isc_mem_t *mctx,
|
||||
dns_dnsseckeylist_t *keylist);
|
||||
/*%<
|
||||
* Search for K* key files matching the name in 'origin'. If 'kasp' is not
|
||||
* NULL, search in the directories used in 'keystores'. Otherwise search in the
|
||||
* key-directory 'keydir'.
|
||||
*
|
||||
* If 'rrtypekey' is true, then KEY type keys are matched (e.g. for SIG(0)),
|
||||
* otherwise DNSKEY type keys are matched for DNSSEC.
|
||||
*
|
||||
* Append all such keys, along with use hints gleaned from their
|
||||
* metadata, onto 'keylist'. Skip any unsupported algorithms.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -500,7 +500,8 @@ static isc_result_t
|
|||
keymgr_createkey(dns_kasp_key_t *kkey, const dns_name_t *origin,
|
||||
dns_kasp_t *kasp, dns_rdataclass_t rdclass, isc_mem_t *mctx,
|
||||
const char *keydir, dns_dnsseckeylist_t *keylist,
|
||||
dns_dnsseckeylist_t *newkeys, dst_key_t **dst_key) {
|
||||
isc_stdtime_t now, dns_dnsseckeylist_t *newkeys,
|
||||
dst_key_t **dst_key) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
bool conflict = false;
|
||||
int flags = DNS_KEYOWNER_ZONE;
|
||||
|
|
@ -509,11 +510,23 @@ keymgr_createkey(dns_kasp_key_t *kkey, const dns_name_t *origin,
|
|||
dns_keystore_t *keystore = dns_kasp_key_keystore(kkey);
|
||||
const char *dir = NULL;
|
||||
int size = dns_kasp_key_size(kkey);
|
||||
dns_dnsseckeylist_t keykeys;
|
||||
|
||||
ISC_LIST_INIT(keykeys);
|
||||
|
||||
if (dns_kasp_key_ksk(kkey)) {
|
||||
flags |= DNS_KEYFLAG_KSK;
|
||||
}
|
||||
|
||||
/*
|
||||
* We also need to check against K* files for KEYs.
|
||||
*/
|
||||
result = dns_dnssec_findmatchingkeys(origin, NULL, keydir, NULL, now,
|
||||
true, mctx, &keykeys);
|
||||
if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
do {
|
||||
if (keystore == NULL) {
|
||||
RETERR(dst_key_generate(origin, alg, size, 0, flags,
|
||||
|
|
@ -528,6 +541,10 @@ keymgr_createkey(dns_kasp_key_t *kkey, const dns_name_t *origin,
|
|||
/* Key collision? */
|
||||
conflict = keymgr_keyid_conflict(newkey, kkey->tag_min,
|
||||
kkey->tag_max, keylist);
|
||||
if (!conflict) {
|
||||
conflict = keymgr_keyid_conflict(
|
||||
newkey, kkey->tag_min, kkey->tag_max, &keykeys);
|
||||
}
|
||||
if (!conflict) {
|
||||
conflict = keymgr_keyid_conflict(
|
||||
newkey, kkey->tag_min, kkey->tag_max, newkeys);
|
||||
|
|
@ -552,9 +569,14 @@ keymgr_createkey(dns_kasp_key_t *kkey, const dns_name_t *origin,
|
|||
dst_key_setdirectory(newkey, dir);
|
||||
}
|
||||
*dst_key = newkey;
|
||||
return ISC_R_SUCCESS;
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
failure:
|
||||
while (!ISC_LIST_EMPTY(keykeys)) {
|
||||
dns_dnsseckey_t *key = ISC_LIST_HEAD(keykeys);
|
||||
ISC_LIST_UNLINK(keykeys, key, link);
|
||||
dns_dnsseckey_destroy(mctx, &key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1945,9 +1967,9 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
|
|||
bool csk = (dns_kasp_key_ksk(kaspkey) &&
|
||||
dns_kasp_key_zsk(kaspkey));
|
||||
|
||||
isc_result_t result =
|
||||
keymgr_createkey(kaspkey, origin, kasp, rdclass, mctx,
|
||||
keydir, keyring, newkeys, &dst_key);
|
||||
isc_result_t result = keymgr_createkey(
|
||||
kaspkey, origin, kasp, rdclass, mctx, keydir, keyring,
|
||||
now, newkeys, &dst_key);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1068,8 +1068,8 @@ find_zone_keys(dns_zone_t *zone, isc_mem_t *mctx, unsigned int maxkeys,
|
|||
|
||||
dns_zone_lock_keyfiles(zone);
|
||||
result = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone), kasp,
|
||||
keydir, keystores, now, mctx,
|
||||
&keylist);
|
||||
keydir, keystores, now, false,
|
||||
mctx, &keylist);
|
||||
dns_zone_unlock_keyfiles(zone);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
|
|||
|
|
@ -6590,7 +6590,8 @@ dns_zone_getdnsseckeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
|
|||
/* Get keys from private key files. */
|
||||
dns_zone_lock_keyfiles(zone);
|
||||
result = dns_dnssec_findmatchingkeys(origin, kasp, dir, zone->keystores,
|
||||
now, dns_zone_getmctx(zone), keys);
|
||||
now, false, dns_zone_getmctx(zone),
|
||||
keys);
|
||||
dns_zone_unlock_keyfiles(zone);
|
||||
|
||||
if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
|
||||
|
|
@ -16596,8 +16597,8 @@ dns_zone_dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, bool *inuse) {
|
|||
|
||||
dns_zone_lock_keyfiles(zone);
|
||||
result = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone), kasp,
|
||||
keydir, keystores, now, mctx,
|
||||
&keylist);
|
||||
keydir, keystores, now, false,
|
||||
mctx, &keylist);
|
||||
dns_zone_unlock_keyfiles(zone);
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
return ISC_R_SUCCESS;
|
||||
|
|
@ -22622,7 +22623,8 @@ zone_rekey(dns_zone_t *zone) {
|
|||
|
||||
dns_zone_lock_keyfiles(zone);
|
||||
result = dns_dnssec_findmatchingkeys(&zone->origin, kasp, dir,
|
||||
zone->keystores, now, mctx, &keys);
|
||||
zone->keystores, now, false, mctx,
|
||||
&keys);
|
||||
dns_zone_unlock_keyfiles(zone);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
|
|||
|
|
@ -3174,7 +3174,7 @@ check_keydir(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
|||
|
||||
ISC_LIST_INIT(keys);
|
||||
ret = dns_dnssec_findmatchingkeys(origin, kasp, keydir, &kslist,
|
||||
now, mctx, &keys);
|
||||
now, false, mctx, &keys);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
result = ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -453,8 +453,9 @@ ISC_RUN_TEST_IMPL(skr_read) {
|
|||
|
||||
/* Get the KSK */
|
||||
ISC_LIST_INIT(keys);
|
||||
result = dns_dnssec_findmatchingkeys(
|
||||
dname, NULL, TESTS_DIR "/testdata/skr/", NULL, 0, mctx, &keys);
|
||||
result = dns_dnssec_findmatchingkeys(dname, NULL,
|
||||
TESTS_DIR "/testdata/skr/", NULL,
|
||||
0, false, mctx, &keys);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
/* Create/read the SKR file */
|
||||
|
|
|
|||
Loading…
Reference in a new issue