From 79f9a10eb6d98f06c21ea3196aabe2d8d96cb016 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 6 Aug 2024 14:28:08 +1000 Subject: [PATCH] Add restrict key tag range support to dnssec-keygen and dnssec-keyfromlabel. (cherry picked from commit 329e5eee9b5f10b6d3b4f78a298f38d762682bfc) --- bin/dnssec/dnssec-keyfromlabel.c | 22 ++++++++++++++++++++-- bin/dnssec/dnssec-keygen.c | 26 +++++++++++++++++++++++--- bin/dnssec/dnssec-ksr.c | 4 +++- bin/dnssec/dnssectool.c | 17 ++++++++++++++++- bin/dnssec/dnssectool.h | 2 +- 5 files changed, 63 insertions(+), 8 deletions(-) diff --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c index 8b052aba9b..01d1a9315d 100644 --- a/bin/dnssec/dnssec-keyfromlabel.c +++ b/bin/dnssec/dnssec-keyfromlabel.c @@ -43,6 +43,8 @@ const char *program = "dnssec-keyfromlabel"; +static uint16_t tag_min = 0, tag_max = 0xffff; + noreturn static void usage(void); @@ -70,6 +72,7 @@ usage(void) { "key files\n"); fprintf(stderr, " -k: generate a TYPE=KEY key\n"); fprintf(stderr, " -L ttl: default key TTL\n"); + fprintf(stderr, " -M :: allowed Key ID range\n"); fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | " "OTHER\n"); fprintf(stderr, " (DNSKEY generation defaults to ZONE\n"); @@ -160,7 +163,7 @@ main(int argc, char **argv) { isc_commandline_errprint = false; -#define CMDLINE_FLAGS "3A:a:Cc:D:E:Ff:GhI:i:kK:L:l:n:P:p:R:S:t:v:Vy" +#define CMDLINE_FLAGS "3A:a:Cc:D:E:Ff:GhI:i:kK:L:l:M:n:P:p:R:S:t:v:Vy" while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case '3': @@ -207,6 +210,20 @@ main(int argc, char **argv) { case 'l': label = isc_mem_strdup(mctx, isc_commandline_argument); break; + case 'M': { + unsigned long ul; + tag_min = ul = strtoul(isc_commandline_argument, &endp, + 10); + if (*endp != ':' || ul > 0xffff) { + fatal("-M range invalid"); + } + tag_max = ul = strtoul(endp + 1, &endp, 10); + if (*endp != '\0' || ul > 0xffff || tag_max <= tag_min) + { + fatal("-M range invalid"); + } + break; + } case 'n': nametype = isc_commandline_argument; break; @@ -686,7 +703,8 @@ main(int argc, char **argv) { * is a risk of ID collision due to this key or another key * being revoked. */ - if (key_collision(key, name, directory, mctx, &exact)) { + if (key_collision(key, name, directory, mctx, tag_min, tag_max, &exact)) + { isc_buffer_clear(&buf); ret = dst_key_buildfilename(key, 0, directory, &buf); if (ret != ISC_R_SUCCESS) { diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index 4742a06feb..7e9486a591 100644 --- a/bin/dnssec/dnssec-keygen.c +++ b/bin/dnssec/dnssec-keygen.c @@ -91,6 +91,8 @@ struct keygen_ctx { char *type; int protocol; int size; + uint16_t tag_min; + uint16_t tag_max; int signatory; dns_rdataclass_t rdclass; int options; @@ -181,6 +183,7 @@ usage(void) { fprintf(stderr, " -f : ZSK | KSK | REVOKE\n"); fprintf(stderr, " -F: FIPS mode\n"); fprintf(stderr, " -L : default key TTL\n"); + fprintf(stderr, " -M :: allowed Key ID range\n"); fprintf(stderr, " -p : (default: 3 [dnssec])\n"); fprintf(stderr, " -s : strength value this key signs DNS " "records with (default: 0)\n"); @@ -758,7 +761,9 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) { * if there is a risk of ID collision due to this key * or another key being revoked. */ - if (key_collision(key, name, ctx->directory, mctx, NULL)) { + if (key_collision(key, name, ctx->directory, mctx, ctx->tag_min, + ctx->tag_max, NULL)) + { conflict = true; if (null_key) { dst_key_free(&key); @@ -868,8 +873,8 @@ main(int argc, char **argv) { /* * Process memory debugging argument first. */ -#define CMDLINE_FLAGS \ - "3A:a:b:Cc:D:d:E:Ff:GhI:i:K:k:L:l:m:n:P:p:qR:r:S:s:" \ +#define CMDLINE_FLAGS \ + "3A:a:b:Cc:D:d:E:Ff:GhI:i:K:k:L:l:M:m:n:P:p:qR:r:S:s:" \ "T:t:v:V" while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { @@ -958,6 +963,21 @@ main(int argc, char **argv) { case 'n': ctx.nametype = isc_commandline_argument; break; + case 'M': { + unsigned long ul; + ctx.tag_min = ul = strtoul(isc_commandline_argument, + &endp, 10); + if (*endp != ':' || ul > 0xffff) { + fatal("-M range invalid"); + } + ctx.tag_max = ul = strtoul(endp + 1, &endp, 10); + if (*endp != '\0' || ul > 0xffff || + ctx.tag_max <= ctx.tag_min) + { + fatal("-M range invalid"); + } + break; + } case 'm': break; case 'p': diff --git a/bin/dnssec/dnssec-ksr.c b/bin/dnssec/dnssec-ksr.c index 493c483d6e..a02da6d1a0 100644 --- a/bin/dnssec/dnssec-ksr.c +++ b/bin/dnssec/dnssec-ksr.c @@ -440,7 +440,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, NULL)) { + if (key_collision(key, name, ksr->keydir, mctx, 0, 0xffff, + NULL)) + { conflict = true; if (verbose > 0) { isc_buffer_clear(&buf); diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c index 69f93c0852..7c38fc923e 100644 --- a/bin/dnssec/dnssectool.c +++ b/bin/dnssec/dnssectool.c @@ -479,7 +479,7 @@ set_keyversion(dst_key_t *key) { bool key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir, - isc_mem_t *mctx, bool *exact) { + isc_mem_t *mctx, uint16_t min, uint16_t max, bool *exact) { isc_result_t result; bool conflict = false; dns_dnsseckeylist_t matchkeys; @@ -497,6 +497,21 @@ key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir, rid = dst_key_rid(dstkey); alg = dst_key_alg(dstkey); + if (min != max) { + if (id < min || id > max) { + fprintf(stderr, "Key ID %d outside of [%u..%u]\n", id, + min, max); + return (true); + } + if (rid < min || rid > max) { + fprintf(stderr, + "Revoked Key ID %d (for tag %d) outside of " + "[%u..%u]\n", + rid, id, min, max); + return (true); + } + } + ISC_LIST_INIT(matchkeys); result = dns_dnssec_findmatchingkeys(name, NULL, dir, NULL, now, mctx, &matchkeys); diff --git a/bin/dnssec/dnssectool.h b/bin/dnssec/dnssectool.h index c9a1a5f757..8b0f0386e0 100644 --- a/bin/dnssec/dnssectool.h +++ b/bin/dnssec/dnssectool.h @@ -109,7 +109,7 @@ set_keyversion(dst_key_t *key); bool key_collision(dst_key_t *key, dns_name_t *name, const char *dir, - isc_mem_t *mctx, bool *exact); + isc_mem_t *mctx, uint16_t min, uint16_t max, bool *exact); bool isoptarg(const char *arg, char **argv, void (*usage)(void));