From: Mark Andrews Date: Sat, 18 Jan 2003 02:40:59 +0000 (+0000) Subject: 1415. [func] DS TTL now derived from NS ttl. NXT TTL now derived X-Git-Tag: v9.2.3rc1~104^2~154 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=b0c15bd9792112fb47f6d956e580e4369e92f4e7;p=thirdparty%2Fbind9.git 1415. [func] DS TTL now derived from NS ttl. NXT TTL now derived from SOA MINIMUM. 1414. [func] Support for KSK flag. --- diff --git a/CHANGES b/CHANGES index ef39c1f1fde..3a4da3d4c0c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +1415. [func] DS TTL now derived from NS ttl. NXT TTL now derived + from SOA MINIMUM. + +1414. [func] Support for KSK flag. + 1413. [func] Explictly request the (re-)generation of DS records from keysets (dnssec-signzone -g). diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index e344db6977c..82f983587dd 100644 --- a/bin/dnssec/dnssec-keygen.c +++ b/bin/dnssec/dnssec-keygen.c @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-keygen.c,v 1.62 2002/12/03 05:01:34 marka Exp $ */ +/* $Id: dnssec-keygen.c,v 1.63 2003/01/18 02:40:58 marka Exp $ */ #include @@ -74,6 +74,7 @@ usage(void) { fprintf(stderr, "Other options:\n"); fprintf(stderr, " -c (default: IN)\n"); fprintf(stderr, " -e use large exponent (RSAMD5/RSASHA1 only)\n"); + fprintf(stderr, " -f keyflag: KSK\n"); fprintf(stderr, " -g use specified generator " "(DH only)\n"); fprintf(stderr, " -t : " @@ -122,7 +123,7 @@ main(int argc, char **argv) { dns_result_register(); while ((ch = isc_commandline_parse(argc, argv, - "a:b:c:eg:n:t:p:s:r:v:h")) != -1) + "a:b:c:ef:g:n:t:p:s:r:v:h")) != -1) { switch (ch) { case 'a': @@ -139,6 +140,13 @@ main(int argc, char **argv) { case 'e': rsa_exp = 1; break; + case 'f': + if (strcasecmp(isc_commandline_argument, "KSK") == 0) + flags |= DNS_KEYFLAG_KSK; + else + fatal("unknown flag '%s'", + isc_commandline_argument); + break; case 'g': generator = strtol(isc_commandline_argument, &endp, 10); diff --git a/bin/dnssec/dnssec-keygen.docbook b/bin/dnssec/dnssec-keygen.docbook index b233ca6ecbc..124e921cfa6 100644 --- a/bin/dnssec/dnssec-keygen.docbook +++ b/bin/dnssec/dnssec-keygen.docbook @@ -16,7 +16,7 @@ - WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. --> - + @@ -42,6 +42,7 @@ -n nametype + @@ -129,6 +130,16 @@ + + -f flag + + + Set the specified flag in the flag field of the key record. + The only recognized flag is KSK (Key Signing Key). + + + + -g generator diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index e07e76236cf..17f24146a49 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-signzone.c,v 1.166 2003/01/18 00:24:09 marka Exp $ */ +/* $Id: dnssec-signzone.c,v 1.167 2003/01/18 02:40:58 marka Exp $ */ #include @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -72,8 +73,9 @@ typedef struct signer_key_struct signer_key_t; struct signer_key_struct { dst_key_t *key; - isc_boolean_t isdefault; - isc_boolean_t keysigning; + isc_boolean_t issigningkey; + isc_boolean_t isdsk; + isc_boolean_t isksk; unsigned int position; ISC_LINK(signer_key_t) link; }; @@ -118,6 +120,7 @@ static unsigned int assigned = 0, completed = 0; static isc_boolean_t nokeys = ISC_FALSE; static isc_boolean_t removefile = ISC_FALSE; static isc_boolean_t generateds = ISC_FALSE; +static isc_boolean_t ignoreksk = ISC_FALSE; #define INCSTAT(counter) \ if (printstats) { \ @@ -184,17 +187,22 @@ dumpdb(dns_db_t *db) { } static signer_key_t * -newkeystruct(dst_key_t *dstkey, isc_boolean_t isdefault, - isc_boolean_t iskeysigning) -{ +newkeystruct(dst_key_t *dstkey, isc_boolean_t signwithkey) { signer_key_t *key; key = isc_mem_get(mctx, sizeof(signer_key_t)); if (key == NULL) fatal("out of memory"); key->key = dstkey; - key->isdefault = isdefault; - key->keysigning = iskeysigning; + if ((dst_key_flags(dstkey) & DNS_KEYFLAG_KSK) != 0) { + key->issigningkey = signwithkey; + key->isksk = ISC_TRUE; + key->isdsk = ISC_FALSE; + } else { + key->issigningkey = signwithkey; + key->isksk = ISC_FALSE; + key->isdsk = ISC_TRUE; + } key->position = keycount++; ISC_LINK_INIT(key, link); return (key); @@ -232,7 +240,7 @@ signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdata_t *rdata, static inline isc_boolean_t issigningkey(signer_key_t *key) { - return (key->isdefault); + return (key->issigningkey); } static inline isc_boolean_t @@ -270,9 +278,9 @@ keythatsigned(dns_rdata_sig_t *sig) { NULL, mctx, &privkey); if (result == ISC_R_SUCCESS) { dst_key_free(&pubkey); - key = newkeystruct(privkey, ISC_FALSE, ISC_FALSE); + key = newkeystruct(privkey, ISC_FALSE); } else - key = newkeystruct(pubkey, ISC_FALSE, ISC_FALSE); + key = newkeystruct(pubkey, ISC_FALSE); ISC_LIST_APPEND(keylist, key, link); return (key); } @@ -390,13 +398,16 @@ signset(dns_diff_t *diff, dns_dbnode_t *node, dns_name_t *name, result = dns_rdata_tostruct(&sigrdata, &sig, NULL); check_result(result, "dns_rdata_tostruct"); - expired = ISC_TF(now + cycle > sig.timeexpire); - future = ISC_TF(now < sig.timesigned); + future = isc_serial_lt(now, sig.timesigned); key = keythatsigned(&sig); sig_format(&sig, sigstr, sizeof(sigstr)); + if (key != NULL && issigningkey(key)) + expired = isc_serial_gt(now + cycle, sig.timeexpire); + else + expired = isc_serial_gt(now, sig.timeexpire); - if (sig.timesigned > sig.timeexpire) { + if (isc_serial_gt(sig.timesigned, sig.timeexpire)) { /* sig is dropped and not replaced */ vbprintf(2, "\tsig by %s dropped - " "invalid validity period\n", @@ -504,8 +515,10 @@ signset(dns_diff_t *diff, dns_dbnode_t *node, dns_name_t *name, if (nowsignedby[key->position]) continue; - if (!(key->isdefault || - (key->keysigning && + if (!key->issigningkey) + continue; + if (!(ignoreksk || key->isdsk || + (key->isksk && set->type == dns_rdatatype_key && dns_name_equal(name, gorigin)))) continue; @@ -563,7 +576,7 @@ opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass, * Loads the key set for a child zone, if there is one, and builds DS records. */ static isc_result_t -loadds(dns_name_t *name, dns_rdataset_t *dsset) { +loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) { dns_db_t *db = NULL; dns_dbversion_t *ver = NULL; dns_dbnode_t *node = NULL; @@ -611,7 +624,7 @@ loadds(dns_name_t *name, dns_rdataset_t *dsset) { check_result(result, "dns_ds_buildrdata"); result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name, - zonettl, &ds, &tuple); + ttl, &ds, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(&diff, &tuple); } @@ -707,7 +720,7 @@ warnwild(const char *name) { } static isc_boolean_t -delegation(dns_name_t *name, dns_dbnode_t *node) { +delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) { dns_rdataset_t nsset; isc_result_t result; @@ -717,8 +730,11 @@ delegation(dns_name_t *name, dns_dbnode_t *node) { dns_rdataset_init(&nsset); result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns, 0, 0, &nsset, NULL); - if (dns_rdataset_isassociated(&nsset)) + if (dns_rdataset_isassociated(&nsset)) { + if (ttlp != NULL) + *ttlp = nsset.ttl; dns_rdataset_disassociate(&nsset); + } return (ISC_TF(result == ISC_R_SUCCESS)); } @@ -738,6 +754,7 @@ signname(dns_dbnode_t *node, dns_name_t *name) { isc_boolean_t atorigin; dns_diff_t diff; char namestr[DNS_NAME_FORMATSIZE]; + isc_uint32_t nsttl = 0; dns_name_format(name, namestr, sizeof(namestr)); @@ -749,7 +766,7 @@ signname(dns_dbnode_t *node, dns_name_t *name) { /* * Determine if this is a delegation point. */ - if (delegation(name, node)) + if (delegation(name, node, &nsttl)) isdelegation = ISC_TRUE; /* @@ -776,7 +793,7 @@ signname(dns_dbnode_t *node, dns_name_t *name) { hasds = ISC_TRUE; } if (generateds) { - result = loadds(name, &dsset); + result = loadds(name, nsttl, &dsset); if (result == ISC_R_SUCCESS) { result = dns_db_addrdataset(gdb, node, gversion, 0, @@ -911,6 +928,8 @@ soattl(void) { dns_name_t *name; isc_result_t result; dns_ttl_t ttl; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_soa_t soa; dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); @@ -921,7 +940,12 @@ soattl(void) { fatal("failed to find an SOA at the zone apex: %s", isc_result_totext(result)); - ttl = soaset.ttl; + result = dns_rdataset_first(&soaset); + check_result(result, "dns_rdataset_first"); + dns_rdataset_current(&soaset, &rdata); + result = dns_rdata_tostruct(&rdata, &soa, NULL); + check_result(result, "dns_rdata_tostruct"); + ttl = soa.minimum; dns_rdataset_disassociate(&soaset); return (ttl); } @@ -1147,7 +1171,7 @@ nxtify(void) { while (!done) { dns_dbiterator_current(dbiter, &node, name); - if (delegation(name, node)) { + if (delegation(name, node, NULL)) { zonecut = dns_fixedname_name(&fzonecut); dns_name_copy(name, zonecut, NULL); } @@ -1258,7 +1282,7 @@ loadzonekeys(dns_db_t *db) { for (i = 0; i < nkeys; i++) { signer_key_t *key; - key = newkeystruct(keys[i], ISC_FALSE, ISC_FALSE); + key = newkeystruct(keys[i], ISC_TRUE); ISC_LIST_APPEND(keylist, key, link); } dns_db_detachnode(db, &node); @@ -1306,7 +1330,7 @@ loadzonepubkeys(dns_db_t *db) { goto next; } - key = newkeystruct(pubkey, ISC_FALSE, ISC_FALSE); + key = newkeystruct(pubkey, ISC_FALSE); ISC_LIST_APPEND(keylist, key, link); next: result = dns_rdataset_next(&rdataset); @@ -1316,6 +1340,53 @@ loadzonepubkeys(dns_db_t *db) { dns_db_closeversion(db, ¤tversion, ISC_FALSE); } +static void +warnifallksk(dns_db_t *db) { + dns_dbversion_t *currentversion = NULL; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + dst_key_t *pubkey; + isc_result_t result; + dns_rdata_key_t key; + isc_boolean_t have_non_ksk = ISC_FALSE; + + dns_db_currentversion(db, ¤tversion); + + result = dns_db_findnode(db, gorigin, ISC_FALSE, &node); + if (result != ISC_R_SUCCESS) + fatal("failed to find the zone's origin: %s", + isc_result_totext(result)); + + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, currentversion, + dns_rdatatype_key, 0, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) + fatal("failed to find keys at the zone apex: %s", + isc_result_totext(result)); + result = dns_rdataset_first(&rdataset); + check_result(result, "dns_rdataset_first"); + while (result == ISC_R_SUCCESS) { + pubkey = NULL; + dns_rdata_reset(&rdata); + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &key, NULL); + check_result(result, "dns_rdata_tostruct"); + if ((key.flags & DNS_KEYFLAG_KSK) == 0) { + have_non_ksk = ISC_TRUE; + result = ISC_R_NOMORE; + } else + result = dns_rdataset_next(&rdataset); + } + dns_rdataset_disassociate(&rdataset); + dns_db_detachnode(db, &node); + dns_db_closeversion(db, ¤tversion, ISC_FALSE); + if (!have_non_ksk && !ignoreksk) + fprintf(stderr, + "%s: warning: No non-KSK key found. Supply non-KSK key or use '-z'.\n", + program); +} + static void writekeyset(void) { char namestr[DNS_NAME_FORMATSIZE]; @@ -1332,6 +1403,7 @@ writekeyset(void) { isc_buffer_t b; isc_region_t r; isc_result_t result; + isc_boolean_t have_non_ksk = ISC_FALSE; isc_buffer_init(&namebuf, namestr, sizeof(namestr)); result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf); @@ -1352,11 +1424,19 @@ writekeyset(void) { dns_diff_init(mctx, &diff); + for (key = ISC_LIST_HEAD(keylist); + key != NULL; + key = ISC_LIST_NEXT(key, link)) + if (!key->isksk) { + have_non_ksk = ISC_TRUE; + break; + } + for (key = ISC_LIST_HEAD(keylist); key != NULL; key = ISC_LIST_NEXT(key, link)) { - if (!key->keysigning) + if (have_non_ksk && !key->isksk) continue; dns_rdata_init(&rdata); isc_buffer_init(&b, keybuf, sizeof(keybuf)); @@ -1512,25 +1592,38 @@ main(int argc, char *argv[]) { dns_result_register(); while ((ch = isc_commandline_parse(argc, argv, - "ac:de:f:ghi:k:n:v:o:pr:s:St:")) + "ac:de:f:ghi:k:n:o:pr:s:St:v:z")) != -1) { switch (ch) { + case 'a': + tryverify = ISC_TRUE; + break; + case 'c': classname = isc_commandline_argument; break; - case 's': - startstr = isc_commandline_argument; + case 'd': + directory = isc_commandline_argument; break; case 'e': endstr = isc_commandline_argument; break; + case 'f': + output = isc_commandline_argument; + break; + case 'g': generateds = ISC_TRUE; break; + case 'h': + default: + usage(); + break; + case 'i': endp = NULL; cycle = strtol(isc_commandline_argument, &endp, 0); @@ -1539,46 +1632,33 @@ main(int argc, char *argv[]) { "positive"); break; - case 'p': - pseudorandom = ISC_TRUE; - break; - - case 'r': - setup_entropy(mctx, isc_commandline_argument, &ectx); + case 'k': + if (ndskeys == MAXDSKEYS) + fatal("too many key-signing keys specified"); + dskeyfile[ndskeys++] = isc_commandline_argument; break; - case 'v': + case 'n': endp = NULL; - verbose = strtol(isc_commandline_argument, &endp, 0); - if (*endp != '\0') - fatal("verbose level must be numeric"); + ntasks = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0' || ntasks > ISC_INT32_MAX) + fatal("number of cpus must be numeric"); break; case 'o': origin = isc_commandline_argument; break; - case 'f': - output = isc_commandline_argument; - break; - - case 'a': - tryverify = ISC_TRUE; - break; - - case 't': - printstats = ISC_TRUE; + case 'p': + pseudorandom = ISC_TRUE; break; - case 'd': - directory = isc_commandline_argument; + case 'r': + setup_entropy(mctx, isc_commandline_argument, &ectx); break; - case 'n': - endp = NULL; - ntasks = strtol(isc_commandline_argument, &endp, 0); - if (*endp != '\0' || ntasks > ISC_INT32_MAX) - fatal("number of cpus must be numeric"); + case 's': + startstr = isc_commandline_argument; break; case 'S': @@ -1587,16 +1667,20 @@ main(int argc, char *argv[]) { masterstyle = &dns_master_style_simple; break; - case 'k': - if (ndskeys == MAXDSKEYS) - fatal("too many key-signing keys specified"); - dskeyfile[ndskeys++] = isc_commandline_argument; + case 't': + printstats = ISC_TRUE; break; - case 'h': - default: - usage(); + case 'v': + endp = NULL; + verbose = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') + fatal("verbose level must be numeric"); + break; + case 'z': + ignoreksk = ISC_TRUE; + break; } } @@ -1666,14 +1750,6 @@ main(int argc, char *argv[]) { if (argc == 0) { loadzonekeys(gdb); - - key = ISC_LIST_HEAD(keylist); - while (key != NULL) { - key->isdefault = ISC_TRUE; - if (ndskeys == 0) - key->keysigning = ISC_TRUE; - key = ISC_LIST_NEXT(key, link); - } } else { for (i = 0; i < argc; i++) { dst_key_t *newkey = NULL; @@ -1694,7 +1770,6 @@ main(int argc, char *argv[]) { dns_name_equal(dst_key_name(dkey), dst_key_name(newkey))) { - key->isdefault = ISC_TRUE; if (!dst_key_isprivate(dkey)) fatal("cannot sign zone with " "non-private key %s", @@ -1704,11 +1779,7 @@ main(int argc, char *argv[]) { key = ISC_LIST_NEXT(key, link); } if (key == NULL) { - isc_boolean_t iskeysigning = ISC_FALSE; - if (ndskeys == 0) - iskeysigning = ISC_TRUE; - key = newkeystruct(newkey, ISC_TRUE, - iskeysigning); + key = newkeystruct(newkey, ISC_TRUE); ISC_LIST_APPEND(keylist, key, link); } else dst_key_free(&newkey); @@ -1736,7 +1807,9 @@ main(int argc, char *argv[]) { dns_name_equal(dst_key_name(dkey), dst_key_name(newkey))) { - key->keysigning = ISC_TRUE; + /* Override key flags. */ + key->isksk = ISC_TRUE; + key->isdsk = ISC_FALSE; dst_key_free(&dkey); key->key = newkey; break; @@ -1744,7 +1817,10 @@ main(int argc, char *argv[]) { key = ISC_LIST_NEXT(key, link); } if (key == NULL) { - key = newkeystruct(newkey, ISC_FALSE, ISC_TRUE); + /* Override key flags. */ + key = newkeystruct(newkey, ISC_TRUE); + key->isksk = ISC_TRUE; + key->isdsk = ISC_FALSE; ISC_LIST_APPEND(keylist, key, link); } } @@ -1755,6 +1831,8 @@ main(int argc, char *argv[]) { nokeys = ISC_TRUE; } + warnifallksk(gdb); + gversion = NULL; result = dns_db_newversion(gdb, &gversion); check_result(result, "dns_db_newversion()"); diff --git a/bin/dnssec/dnssec-signzone.docbook b/bin/dnssec/dnssec-signzone.docbook index 93d1be91985..f8f31440195 100644 --- a/bin/dnssec/dnssec-signzone.docbook +++ b/bin/dnssec/dnssec-signzone.docbook @@ -16,7 +16,7 @@ - WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. --> - + @@ -40,18 +40,20 @@ - - + + + + zonefile key @@ -93,6 +95,16 @@ + + -k key + + + Treat specified key as a key signing key ignoring any + key flags. This option may be specified multiple times. + + + + -d directory @@ -255,6 +267,15 @@ + + -z + + + Ignore KSK flag on key when determining what to sign. + + + + zonefile diff --git a/lib/dns/include/dns/keyvalues.h b/lib/dns/include/dns/keyvalues.h index 57e9a41ed9d..9af738e5585 100644 --- a/lib/dns/include/dns/keyvalues.h +++ b/lib/dns/include/dns/keyvalues.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: keyvalues.h,v 1.13 2001/09/25 22:45:02 bwelling Exp $ */ +/* $Id: keyvalues.h,v 1.14 2003/01/18 02:40:59 marka Exp $ */ #ifndef DNS_KEYVALUES_H #define DNS_KEYVALUES_H 1 @@ -53,6 +53,7 @@ DNS_KEYFLAG_RESERVED9 | \ DNS_KEYFLAG_RESERVED10 | \ DNS_KEYFLAG_RESERVED11 ) +#define DNS_KEYFLAG_KSK 0x0001 /* key signing key */ #define DNS_KEYFLAG_RESERVEDMASK2 0xFFFF /* no bits defined here */ diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index 6984b0c49a4..e3108d8cd2f 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdata.c,v 1.172 2002/06/17 04:01:21 marka Exp $ */ +/* $Id: rdata.c,v 1.173 2003/01/18 02:40:59 marka Exp $ */ #include #include @@ -345,6 +345,7 @@ static struct keyflag { { "SIG13", 0x000D, 0x000F }, { "SIG14", 0x000E, 0x000F }, { "SIG15", 0x000F, 0x000F }, + { "KSK", DNS_KEYFLAG_KSK, DNS_KEYFLAG_KSK }, { NULL, 0, 0 } };