diff options
Diffstat (limited to 'contrib/bind9/bin/dnssec/dnssectool.c')
-rw-r--r-- | contrib/bind9/bin/dnssec/dnssectool.c | 223 |
1 files changed, 187 insertions, 36 deletions
diff --git a/contrib/bind9/bin/dnssec/dnssectool.c b/contrib/bind9/bin/dnssec/dnssectool.c index 81120e34c49c..da6b0b2a789e 100644 --- a/contrib/bind9/bin/dnssec/dnssectool.c +++ b/contrib/bind9/bin/dnssec/dnssectool.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssectool.c,v 1.45.334.5 2009-06-22 05:05:00 marka Exp $ */ +/* $Id: dnssectool.c,v 1.60 2010-01-19 23:48:56 tbox Exp $ */ /*! \file */ @@ -28,6 +28,7 @@ #include <stdlib.h> #include <isc/buffer.h> +#include <isc/dir.h> #include <isc/entropy.h> #include <isc/list.h> #include <isc/mem.h> @@ -36,6 +37,8 @@ #include <isc/util.h> #include <isc/print.h> +#include <dns/dnssec.h> +#include <dns/keyvalues.h> #include <dns/log.h> #include <dns/name.h> #include <dns/rdatastruct.h> @@ -111,39 +114,16 @@ type_format(const dns_rdatatype_t type, char *cp, unsigned int size) { } void -alg_format(const dns_secalg_t alg, char *cp, unsigned int size) { - isc_buffer_t b; - isc_region_t r; - isc_result_t result; - - isc_buffer_init(&b, cp, size - 1); - result = dns_secalg_totext(alg, &b); - check_result(result, "dns_secalg_totext()"); - isc_buffer_usedregion(&b, &r); - r.base[r.length] = 0; -} - -void sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) { char namestr[DNS_NAME_FORMATSIZE]; char algstr[DNS_NAME_FORMATSIZE]; dns_name_format(&sig->signer, namestr, sizeof(namestr)); - alg_format(sig->algorithm, algstr, sizeof(algstr)); + dns_secalg_format(sig->algorithm, algstr, sizeof(algstr)); snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid); } void -key_format(const dst_key_t *key, char *cp, unsigned int size) { - char namestr[DNS_NAME_FORMATSIZE]; - char algstr[DNS_NAME_FORMATSIZE]; - - dns_name_format(dst_key_name(key), namestr, sizeof(namestr)); - alg_format((dns_secalg_t) dst_key_alg(key), algstr, sizeof(algstr)); - snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key)); -} - -void setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp) { isc_result_t result; isc_logdestination_t destination; @@ -265,32 +245,92 @@ cleanup_entropy(isc_entropy_t **ectx) { isc_entropy_detach(ectx); } +static isc_stdtime_t +time_units(isc_stdtime_t offset, char *suffix, const char *str) { + switch (suffix[0]) { + case 'Y': case 'y': + return (offset * (365 * 24 * 3600)); + case 'M': case 'm': + switch (suffix[1]) { + case 'O': case 'o': + return (offset * (30 * 24 * 3600)); + case 'I': case 'i': + return (offset * 60); + case '\0': + fatal("'%s' ambiguous: use 'mi' for minutes " + "or 'mo' for months", str); + default: + fatal("time value %s is invalid", str); + } + /* NOTREACHED */ + break; + case 'W': case 'w': + return (offset * (7 * 24 * 3600)); + case 'D': case 'd': + return (offset * (24 * 3600)); + case 'H': case 'h': + return (offset * 3600); + case 'S': case 's': case '\0': + return (offset); + default: + fatal("time value %s is invalid", str); + } + /* NOTREACHED */ + return(0); /* silence compiler warning */ +} + +dns_ttl_t +strtottl(const char *str) { + const char *orig = str; + dns_ttl_t ttl; + char *endp; + + ttl = strtol(str, &endp, 0); + if (ttl == 0 && endp == str) + fatal("TTL must be numeric"); + ttl = time_units(ttl, endp, orig); + return (ttl); +} + isc_stdtime_t strtotime(const char *str, isc_int64_t now, isc_int64_t base) { isc_int64_t val, offset; isc_result_t result; + const char *orig = str; char *endp; - if (str[0] == '+') { + if ((str[0] == '0' || str[0] == '-') && str[1] == '\0') + return ((isc_stdtime_t) 0); + + if (strncmp(str, "now", 3) == 0) { + base = now; + str += 3; + } + + if (str[0] == '\0') + return ((isc_stdtime_t) base); + else if (str[0] == '+') { offset = strtol(str + 1, &endp, 0); - if (*endp != '\0') - fatal("time value %s is invalid", str); + offset = time_units((isc_stdtime_t) offset, endp, orig); val = base + offset; - } else if (strncmp(str, "now+", 4) == 0) { - offset = strtol(str + 4, &endp, 0); - if (*endp != '\0') - fatal("time value %s is invalid", str); - val = now + offset; + } else if (str[0] == '-') { + offset = strtol(str + 1, &endp, 0); + offset = time_units((isc_stdtime_t) offset, endp, orig); + val = base - offset; } else if (strlen(str) == 8U) { char timestr[15]; sprintf(timestr, "%s000000", str); result = dns_time64_fromtext(timestr, &val); if (result != ISC_R_SUCCESS) - fatal("time value %s is invalid", str); + fatal("time value %s is invalid: %s", orig, + isc_result_totext(result)); + } else if (strlen(str) > 14U) { + fatal("time value %s is invalid", orig); } else { result = dns_time64_fromtext(str, &val); if (result != ISC_R_SUCCESS) - fatal("time value %s is invalid", str); + fatal("time value %s is invalid: %s", orig, + isc_result_totext(result)); } return ((isc_stdtime_t) val); @@ -311,3 +351,114 @@ strtoclass(const char *str) { fatal("unknown class %s", str); return (rdclass); } + +isc_result_t +try_dir(const char *dirname) { + isc_result_t result; + isc_dir_t d; + + isc_dir_init(&d); + result = isc_dir_open(&d, dirname); + if (result == ISC_R_SUCCESS) { + isc_dir_close(&d); + } + 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); + } +} + +isc_boolean_t +key_collision(isc_uint16_t id, dns_name_t *name, const char *dir, + dns_secalg_t alg, isc_mem_t *mctx, isc_boolean_t *exact) +{ + isc_result_t result; + isc_boolean_t conflict = ISC_FALSE; + dns_dnsseckeylist_t matchkeys; + dns_dnsseckey_t *key = NULL; + isc_uint16_t oldid, diff; + isc_uint16_t bits = DNS_KEYFLAG_REVOKE; /* flag bits to look for */ + + if (exact != NULL) + *exact = ISC_FALSE; + + ISC_LIST_INIT(matchkeys); + result = dns_dnssec_findmatchingkeys(name, dir, mctx, &matchkeys); + if (result == ISC_R_NOTFOUND) + return (ISC_FALSE); + + while (!ISC_LIST_EMPTY(matchkeys) && !conflict) { + key = ISC_LIST_HEAD(matchkeys); + if (dst_key_alg(key->key) != alg) + goto next; + + oldid = dst_key_id(key->key); + diff = (oldid > id) ? (oldid - id) : (id - oldid); + if ((diff & ~bits) == 0) { + conflict = ISC_TRUE; + if (diff != 0) { + if (verbose > 1) + fprintf(stderr, "Key ID %d could " + "collide with %d\n", + id, oldid); + } else { + if (exact != NULL) + *exact = ISC_TRUE; + if (verbose > 1) + fprintf(stderr, "Key ID %d exists\n", + id); + } + } + + next: + ISC_LIST_UNLINK(matchkeys, key, link); + dns_dnsseckey_destroy(mctx, &key); + } + + /* Finish freeing the list */ + while (!ISC_LIST_EMPTY(matchkeys)) { + key = ISC_LIST_HEAD(matchkeys); + ISC_LIST_UNLINK(matchkeys, key, link); + dns_dnsseckey_destroy(mctx, &key); + } + + return (conflict); +} + |