diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index 9215c594cb..2bf382179b 100644 --- a/bin/dnssec/dnssec-keygen.c +++ b/bin/dnssec/dnssec-keygen.c @@ -1235,6 +1235,8 @@ main(int argc, char **argv) { ctx.ksk = true; ctx.zsk = true; ctx.lifetime = 0; + ctx.tag_min = 0; + ctx.tag_max = 0xffff; keygen(&ctx, mctx, argc, argv); } else { @@ -1283,6 +1285,8 @@ main(int argc, char **argv) { if (ctx.keystore != NULL) { check_keystore_options(&ctx); } + ctx.tag_min = dns_kasp_key_tagmin(kaspkey); + ctx.tag_max = dns_kasp_key_tagmax(kaspkey); if ((ctx.ksk && !ctx.wantksk && ctx.wantzsk) || (ctx.zsk && !ctx.wantzsk && ctx.wantksk)) { diff --git a/bin/dnssec/dnssec-ksr.c b/bin/dnssec/dnssec-ksr.c index 572e2e1207..ea4d3e729e 100644 --- a/bin/dnssec/dnssec-ksr.c +++ b/bin/dnssec/dnssec-ksr.c @@ -436,8 +436,9 @@ create_zsk(ksr_ctx_t *ksr, dns_kasp_key_t *kaspkey, dns_dnsseckeylist_t *keys, } /* Do not overwrite an existing key. */ - if (key_collision(key, name, ksr->keydir, mctx, 0, 0xffff, - NULL)) + if (key_collision(key, name, ksr->keydir, mctx, + dns_kasp_key_tagmin(kaspkey), + dns_kasp_key_tagmax(kaspkey), NULL)) { conflict = true; if (verbose > 0) { diff --git a/doc/misc/options b/doc/misc/options index 0785c4d7bf..dabaad9b68 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -15,7 +15,7 @@ dnssec-policy { cds-digest-types { ; ... }; dnskey-ttl ; inline-signing ; - keys { ( csk | ksk | zsk ) [ key-directory | key-store ] lifetime algorithm [ ]; ... }; + keys { ( csk | ksk | zsk ) [ key-directory | key-store ] lifetime algorithm [ tag-range ] [ ]; ... }; max-zone-ttl ; nsec3param [ iterations ] [ optout ] [ salt-length ]; offline-ksk ; diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c index b6da87a235..f8637958fc 100644 --- a/lib/isccfg/kaspconf.c +++ b/lib/isccfg/kaspconf.c @@ -117,6 +117,7 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp, uint32_t ksk_min_lifetime, uint32_t zsk_min_lifetime) { isc_result_t result; dns_kasp_key_t *key = NULL; + const cfg_obj_t *tagrange = NULL; /* Create a new key reference. */ result = dns_kasp_key_create(kasp, &key); @@ -291,6 +292,38 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp, key->length = size; } + + tagrange = cfg_tuple_get(config, "tag-range"); + if (cfg_obj_istuple(tagrange)) { + uint32_t tag_min = 0, tag_max = 0xffff; + obj = cfg_tuple_get(tagrange, "tag-min"); + tag_min = cfg_obj_asuint32(obj); + if (tag_min > 0xffff) { + cfg_obj_log(obj, ISC_LOG_ERROR, + "dnssec-policy: tag-min " + "too big"); + result = ISC_R_RANGE; + goto cleanup; + } + obj = cfg_tuple_get(tagrange, "tag-max"); + tag_max = cfg_obj_asuint32(obj); + if (tag_max > 0xffff) { + cfg_obj_log(obj, ISC_LOG_ERROR, + "dnssec-policy: tag-max " + "too big"); + result = ISC_R_RANGE; + goto cleanup; + } + if (tag_min >= tag_max) { + cfg_obj_log( + obj, ISC_LOG_ERROR, + "dnssec-policy: tag-min >= tag_max"); + result = ISC_R_RANGE; + goto cleanup; + } + key->tag_min = tag_min; + key->tag_max = tag_max; + } } dns_kasp_addkey(kasp, key); diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index d70e0eb651..83a8a997bb 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -649,12 +649,73 @@ static keyword_type_t lifetime_kw = { "lifetime", static cfg_type_t cfg_type_lifetime = { "lifetime", parse_keyvalue, print_keyvalue, doc_keyvalue, &cfg_rep_duration, &lifetime_kw }; +/* + * + */ +static void +print_tagrange(cfg_printer_t *pctx, const cfg_obj_t *obj) { + REQUIRE(pctx != NULL); + REQUIRE(obj != NULL); + REQUIRE(obj->type->rep == &cfg_rep_tuple); + + if (cfg_obj_istuple(obj)) { + cfg_print_cstr(pctx, "tag-range "); + cfg_print_tuple(pctx, obj); + } +} + +static cfg_tuplefielddef_t tagrange_fields[] = { + { "tag-min", &cfg_type_uint32, 0 }, + { "tag-max", &cfg_type_uint32, 0 }, + { NULL, NULL, 0 } +}; + +static cfg_type_t cfg_type_tagrange = { "tagrange", cfg_parse_tuple, + print_tagrange, cfg_doc_tuple, + &cfg_rep_tuple, tagrange_fields }; + +static keyword_type_t tagrange_kw = { "tag-range", &cfg_type_tagrange }; +static void +doc_optionaltagrange(cfg_printer_t *pctx, const cfg_type_t *type) { + UNUSED(type); + + cfg_print_cstr(pctx, "[ tag-range ]"); +} + +static isc_result_t +parse_optionaltagrange(cfg_parser_t *pctx, const cfg_type_t *type, + cfg_obj_t **ret) { + isc_result_t result; + cfg_obj_t *obj = NULL; + + UNUSED(type); + + CHECK(cfg_peektoken(pctx, 0)); + if (pctx->token.type == isc_tokentype_string && + strcasecmp(TOKEN_STRING(pctx), "tag-range") == 0) + { + CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING)); + CHECK(cfg_parse_obj(pctx, &cfg_type_tagrange, &obj)); + } else { + CHECK(cfg_parse_void(pctx, NULL, &obj)); + } + + *ret = obj; +cleanup: + return (result); +} + +static cfg_type_t cfg_type_optional_tagrange = { + "optionaltagrange", parse_optionaltagrange, NULL, + doc_optionaltagrange, &cfg_rep_tuple, &tagrange_kw +}; static cfg_tuplefielddef_t kaspkey_fields[] = { { "role", &cfg_type_dnsseckeyrole, 0 }, { "keystorage", &cfg_type_optional_keystore, 0 }, { "lifetime", &cfg_type_lifetime, 0 }, { "algorithm", &cfg_type_algorithm, 0 }, + { "tag-range", &cfg_type_optional_tagrange, 0 }, { "length", &cfg_type_optional_uint32, 0 }, { NULL, NULL, 0 } };