diff --git a/CHANGES b/CHANGES index 159108b04d648650e707c7d80288a5c9ece7be45..2b9eb3e9fc12908a1e78ccde26691675baa1a0e5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +2731. [func] Additional work on change 2709. The key parser + will now ignore unrecognized fields when the + minor version number of the private key format + has been increased. It will reject any key with + the major version number increased. [RT #20310] + 2730. [func] Have dnssec-keygen display a progress indication a la 'openssl genrsa' on standard error. Note when the first '.' is followed by a long stop diff --git a/bin/dnssec/dnssec-revoke.c b/bin/dnssec/dnssec-revoke.c index 34798f8b9887c5fd264f31d736ed1258dd0381d4..a04cabeecb15cd6ebb51dfb0fde5a4a3a7e391ae 100644 --- a/bin/dnssec/dnssec-revoke.c +++ b/bin/dnssec/dnssec-revoke.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-revoke.c,v 1.16 2009/10/12 20:48:10 each Exp $ */ +/* $Id: dnssec-revoke.c,v 1.17 2009/10/26 21:18:24 each Exp $ */ /*! \file */ @@ -179,18 +179,21 @@ main(int argc, char **argv) { fatal("Invalid keyfile name %s: %s", filename, isc_result_totext(result)); - if (verbose > 2) { - char keystr[DST_KEY_FORMATSIZE]; + dst_key_format(key, keystr, sizeof(keystr)); - dst_key_format(key, keystr, sizeof(keystr)); + if (verbose > 2) fprintf(stderr, "%s: %s\n", program, keystr); - } + + if (force) + set_keyversion(key); + else + check_keyversion(key, keystr); + flags = dst_key_flags(key); if ((flags & DNS_KEYFLAG_REVOKE) == 0) { isc_stdtime_t now; - if ((flags & DNS_KEYFLAG_KSK) == 0) fprintf(stderr, "%s: warning: Key is not flagged " "as a KSK. Revoking a ZSK is " diff --git a/bin/dnssec/dnssec-settime.c b/bin/dnssec/dnssec-settime.c index 7371955a25593eae5fac9c455d1e3fb9c896276d..4a7f04811c85b4cc632a64c5c0ce59a37d3c5cd9 100644 --- a/bin/dnssec/dnssec-settime.c +++ b/bin/dnssec/dnssec-settime.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-settime.c,v 1.17 2009/10/12 20:48:10 each Exp $ */ +/* $Id: dnssec-settime.c,v 1.18 2009/10/26 21:18:24 each Exp $ */ /*! \file */ @@ -131,7 +131,6 @@ main(int argc, char **argv) { isc_entropy_t *ectx = NULL; dst_key_t *key = NULL; isc_buffer_t buf; - int major, minor; isc_stdtime_t now; isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0; isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; @@ -143,7 +142,7 @@ main(int argc, char **argv) { isc_boolean_t printcreate = ISC_FALSE, printpub = ISC_FALSE; isc_boolean_t printact = ISC_FALSE, printrev = ISC_FALSE; isc_boolean_t printinact = ISC_FALSE, printdel = ISC_FALSE; - isc_boolean_t forceupdate = ISC_FALSE; + isc_boolean_t force = ISC_FALSE; isc_boolean_t epoch = ISC_FALSE; isc_boolean_t changed = ISC_FALSE; @@ -167,7 +166,7 @@ main(int argc, char **argv) { engine = isc_commandline_argument; break; case 'f': - forceupdate = ISC_TRUE; + force = ISC_TRUE; break; case 'p': p = isc_commandline_argument; @@ -346,20 +345,10 @@ main(int argc, char **argv) { dst_key_format(key, keystr, sizeof(keystr)); - /* Is this an old-style key? */ - dst_key_getprivateformat(key, &major, &minor); - if (major <= 1 && minor <= 2) { - if (forceupdate) { - /* - * Updating to new-style key: set - * Private-key-format to 1.3 - */ - dst_key_setprivateformat(key, 1, 3); - dst_key_settime(key, DST_TIME_CREATED, now); - } else - fatal("Incompatible key %s, " - "use -f to force update.", keystr); - } + if (force) + set_keyversion(key); + else + check_keyversion(key, keystr); if (verbose > 2) fprintf(stderr, "%s: %s\n", program, keystr); diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c index 541dda0b12de414df5916d636216c1baa7fe8583..d8c4ea48659bd9146ba30aeef3014e599ecc1ac0 100644 --- a/bin/dnssec/dnssectool.c +++ b/bin/dnssec/dnssectool.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssectool.c,v 1.56 2009/10/24 00:00:06 each Exp $ */ +/* $Id: dnssectool.c,v 1.57 2009/10/26 21:18:24 each Exp $ */ /*! \file */ @@ -362,3 +362,43 @@ try_dir(const char *dirname) { } return (result); } + +/* + * Check private key version compatibility. + */ +void +check_keyversion(dst_key_t *key, char *keystr) { + int major, minor; + dst_key_getprivateformat(key, &major, &minor); + INSIST(major <= DST_MAJOR_VERSION); /* invalid private key */ + + if (major < DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) + fatal("Key %s has incompatible format version %d.%d, " + "use -f to force upgrade to new version.", + keystr, major, minor); + if (minor > DST_MINOR_VERSION) + fatal("Key %s has incompatible format version %d.%d, " + "use -f to force downgrade to current version.", + keystr, major, minor); +} + +void +set_keyversion(dst_key_t *key) { + int major, minor; + dst_key_getprivateformat(key, &major, &minor); + INSIST(major <= DST_MAJOR_VERSION); + + if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION) + dst_key_setprivateformat(key, DST_MAJOR_VERSION, + DST_MINOR_VERSION); + + /* + * If the key is from a version older than 1.3, set + * set the creation date + */ + if (major < 1 || (major == 1 && minor <= 2)) { + isc_stdtime_t now; + isc_stdtime_get(&now); + dst_key_settime(key, DST_TIME_CREATED, now); + } +} diff --git a/bin/dnssec/dnssectool.h b/bin/dnssec/dnssectool.h index c1a0ee1767ea6051ad294fff6a3ee547d3fe11b8..249d7054e6161cdee1f9dc61e931edf209af5b3f 100644 --- a/bin/dnssec/dnssectool.h +++ b/bin/dnssec/dnssectool.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssectool.h,v 1.28 2009/10/24 00:00:06 each Exp $ */ +/* $Id: dnssectool.h,v 1.29 2009/10/26 21:18:24 each Exp $ */ #ifndef DNSSECTOOL_H #define DNSSECTOOL_H 1 @@ -70,4 +70,10 @@ strtoclass(const char *str); isc_result_t try_dir(const char *dirname); + +void +check_keyversion(dst_key_t *key, char *keystr); + +void +set_keyversion(dst_key_t *key); #endif /* DNSSEC_DNSSECTOOL_H */ diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index 9c90215bed3dc1b73049f107ee8022d50c77ed56..5a40d2e80ae15182dae3f048e3acabe3e5062092 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -16,7 +16,7 @@ */ /* - * $Id: dnssec.c,v 1.106 2009/10/16 23:47:54 tbox Exp $ + * $Id: dnssec.c,v 1.107 2009/10/26 21:18:24 each Exp $ */ /*! \file */ @@ -985,6 +985,8 @@ dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey, /* Is this an old-style key? */ result = dst_key_getprivateformat(dk->key, &major, &minor); + + /* Smart signing started with key format 1.3 */ dk->legacy = ISC_TF(major == 1 && minor <= 2); ISC_LINK_INIT(dk, link); diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c index c5dc612f416c4d1242ab207d5cdde2c058b661e3..5fc5638193901d0978e2920226a2cf0e91f2147b 100644 --- a/lib/dns/dst_parse.c +++ b/lib/dns/dst_parse.c @@ -31,7 +31,7 @@ /*% * Principal Author: Brian Wellington - * $Id: dst_parse.c,v 1.22 2009/10/22 02:21:30 each Exp $ + * $Id: dst_parse.c,v 1.23 2009/10/26 21:18:24 each Exp $ */ #include @@ -385,9 +385,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, goto fail; } - if (major > MAJOR_VERSION || - (major == MAJOR_VERSION && minor > MINOR_VERSION)) - { + if (major > DST_MAJOR_VERSION) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } @@ -476,10 +474,13 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, /* Key data */ tag = find_value(DST_AS_STR(token), alg); - if (tag < 0) { + if (tag < 0 && minor > DST_MINOR_VERSION) + goto next; + else if (tag < 0) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } + priv->elements[n].tag = tag; data = (unsigned char *) isc_mem_get(mctx, MAXFIELDSIZE); @@ -490,6 +491,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, ret = isc_base64_tobuffer(lex, &b, -1); if (ret != ISC_R_SUCCESS) goto fail; + isc_buffer_usedregion(&b, &r); priv->elements[n].length = r.length; priv->elements[n].data = r.base; @@ -550,8 +552,8 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, dst_key_getprivateformat(key, &major, &minor); if (major == 0 && minor == 0) { - major = MAJOR_VERSION; - minor = MINOR_VERSION; + major = DST_MAJOR_VERSION; + minor = DST_MINOR_VERSION; } /* XXXDCL return value should be checked for full filesystem */ diff --git a/lib/dns/dst_parse.h b/lib/dns/dst_parse.h index d893c2dc2afedf975edd5515645d4ae95e3cadfe..ceb8b188bd863fc0d39bb406ad5f14c7c698ad8f 100644 --- a/lib/dns/dst_parse.h +++ b/lib/dns/dst_parse.h @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dst_parse.h,v 1.14 2009/09/02 06:29:01 each Exp $ */ +/* $Id: dst_parse.h,v 1.15 2009/10/26 21:18:24 each Exp $ */ /*! \file */ #ifndef DST_DST_PARSE_H @@ -39,9 +39,6 @@ #include -#define MAJOR_VERSION 1 -#define MINOR_VERSION 3 - #define MAXFIELDSIZE 512 /* diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h index 2217139e3d2b12b2ba682e2e1c82243506b9403b..1f6020a3bff313ea077ebe389face43ef0c394cd 100644 --- a/lib/dns/include/dst/dst.h +++ b/lib/dns/include/dst/dst.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dst.h,v 1.24 2009/10/24 09:46:19 fdupont Exp $ */ +/* $Id: dst.h,v 1.25 2009/10/26 21:18:24 each Exp $ */ #ifndef DST_DST_H #define DST_DST_H 1 @@ -100,6 +100,28 @@ typedef struct dst_context dst_context_t; #define DST_NUM_ROLLPERIOD 3 #define DST_MAX_NUMERIC 3 +/* + * Current format version number of the private key parser. + * + * When parsing a key file with the same major number but a higher minor + * number, the key parser will ignore any fields it does not recognize. + * Thus, DST_MINOR_VERSION should be incremented whenever new + * fields are added to the private key file (such as new metadata). + * + * When rewriting these keys, those fields will be dropped, and the + * format version set back to the current one.. + * + * When a key is seen with a higher major number, the key parser will + * reject it as invalid. Thus, DST_MAJOR_VERSION should be incremented + * and DST_MINOR_VERSION set to zero whenever there is a format change + * which is not backward compatible to previous versions of the dst_key + * parser, such as change in the syntax of an existing field, the removal + * of a currently mandatory field, or a new field added which would + * alter the functioning of the key if it were absent. + */ +#define DST_MAJOR_VERSION 1 +#define DST_MINOR_VERSION 3 + /*** *** Functions ***/