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.
This commit is contained in:
parent
aabe258774
commit
49b7ce9a54
11 changed files with 81 additions and 36 deletions
|
|
@ -217,7 +217,8 @@ 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, isc_g_mctx, &keys_read);
|
||||
ksr->now, false, isc_g_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));
|
||||
|
|
|
|||
|
|
@ -2738,7 +2738,8 @@ findkeys:
|
|||
* Find keys that match this zone in the key repository.
|
||||
*/
|
||||
result = dns_dnssec_findmatchingkeys(gorigin, NULL, directory, NULL,
|
||||
now, isc_g_mctx, &matchkeys);
|
||||
now, false, isc_g_mctx,
|
||||
&matchkeys);
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -486,10 +486,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) {
|
||||
|
|
@ -531,6 +538,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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,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
|
||||
|
|
|
|||
|
|
@ -1221,12 +1221,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;
|
||||
|
|
@ -1235,6 +1235,7 @@ findmatchingkeys(const char *directory, char *namebuf, unsigned int len,
|
|||
if (directory == NULL) {
|
||||
directory = ".";
|
||||
}
|
||||
|
||||
RETERR(isc_dir_open(&dir, directory));
|
||||
dir_open = true;
|
||||
|
||||
|
|
@ -1283,11 +1284,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:
|
||||
|
|
@ -1319,9 +1322,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) {
|
||||
|
|
@ -1334,12 +1339,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;
|
||||
|
|
@ -1358,8 +1364,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) {
|
||||
ISC_LIST_FOREACH(*keystores, keystore, link) {
|
||||
ISC_LIST_FOREACH(dns_kasp_keys(kasp), kkey, link) {
|
||||
|
|
@ -1368,8 +1374,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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,13 +295,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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -496,7 +496,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;
|
||||
|
|
@ -505,11 +506,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,
|
||||
|
|
@ -524,6 +537,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);
|
||||
|
|
@ -548,9 +565,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;
|
||||
}
|
||||
|
||||
|
|
@ -1920,9 +1942,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1035,8 +1035,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) {
|
||||
|
|
|
|||
|
|
@ -6996,9 +6996,9 @@ 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,
|
||||
dns_zone_getkeystores(zone), now,
|
||||
dns_zone_getmctx(zone), keys);
|
||||
result = dns_dnssec_findmatchingkeys(
|
||||
origin, kasp, dir, dns_zone_getkeystores(zone), now, false,
|
||||
dns_zone_getmctx(zone), keys);
|
||||
dns_zone_unlock_keyfiles(zone);
|
||||
|
||||
if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
|
||||
|
|
@ -16819,8 +16819,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;
|
||||
|
|
@ -22512,7 +22512,7 @@ zone_rekey(dns_zone_t *zone) {
|
|||
dns_zone_lock_keyfiles(zone);
|
||||
result = dns_dnssec_findmatchingkeys(&zone->origin, kasp, dir,
|
||||
dns_zone_getkeystores(zone), now,
|
||||
mctx, &keys);
|
||||
false, mctx, &keys);
|
||||
dns_zone_unlock_keyfiles(zone);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
|
|||
|
|
@ -2962,7 +2962,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ ISC_RUN_TEST_IMPL(skr_read) {
|
|||
ISC_LIST_INIT(keys);
|
||||
result = dns_dnssec_findmatchingkeys(dname, NULL,
|
||||
TESTS_DIR "/testdata/skr/", NULL,
|
||||
0, isc_g_mctx, &keys);
|
||||
0, false, isc_g_mctx, &keys);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
/* Create/read the SKR file */
|
||||
|
|
|
|||
Loading…
Reference in a new issue