diff options
Diffstat (limited to 'contrib/bind9/bin/dnssec/dnssec-dsfromkey.c')
-rw-r--r-- | contrib/bind9/bin/dnssec/dnssec-dsfromkey.c | 314 |
1 files changed, 216 insertions, 98 deletions
diff --git a/contrib/bind9/bin/dnssec/dnssec-dsfromkey.c b/contrib/bind9/bin/dnssec/dnssec-dsfromkey.c index 934d25b..b7f84a0 100644 --- a/contrib/bind9/bin/dnssec/dnssec-dsfromkey.c +++ b/contrib/bind9/bin/dnssec/dnssec-dsfromkey.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-dsfromkey.c,v 1.2.14.6 2010-01-11 23:47:22 tbox Exp $ */ +/* $Id: dnssec-dsfromkey.c,v 1.19 2010-12-23 04:07:59 marka Exp $ */ /*! \file */ @@ -36,6 +36,8 @@ #include <dns/ds.h> #include <dns/fixedname.h> #include <dns/log.h> +#include <dns/keyvalues.h> +#include <dns/master.h> #include <dns/name.h> #include <dns/rdata.h> #include <dns/rdataclass.h> @@ -48,54 +50,40 @@ #include "dnssectool.h" +#ifndef PATH_MAX +#define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */ +#endif + const char *program = "dnssec-dsfromkey"; int verbose; static dns_rdataclass_t rdclass; -static dns_fixedname_t fixed; -static dns_name_t *name = NULL; -static dns_db_t *db = NULL; -static dns_dbnode_t *node = NULL; -static dns_rdataset_t keyset; -static isc_mem_t *mctx = NULL; +static dns_fixedname_t fixed; +static dns_name_t *name = NULL; +static isc_mem_t *mctx = NULL; -static void -loadkeys(char *dirname, char *setname) -{ - isc_result_t result; - char filename[1024]; - isc_buffer_t buf; +static isc_result_t +initname(char *setname) { + isc_result_t result; + isc_buffer_t buf; - dns_rdataset_init(&keyset); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); isc_buffer_init(&buf, setname, strlen(setname)); isc_buffer_add(&buf, strlen(setname)); - result = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); - if (result != ISC_R_SUCCESS) - fatal("can't convert DNS name %s", setname); + result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); + return (result); +} - isc_buffer_init(&buf, filename, sizeof(filename)); - if (dirname != NULL) { - if (isc_buffer_availablelength(&buf) < strlen(dirname)) - fatal("directory name '%s' too long", dirname); - isc_buffer_putstr(&buf, dirname); - if (dirname[strlen(dirname) - 1] != '/') { - if (isc_buffer_availablelength(&buf) < 1) - fatal("directory name '%s' too long", dirname); - isc_buffer_putstr(&buf, "/"); - } - } +static isc_result_t +loadsetfromfile(char *filename, dns_rdataset_t *rdataset) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + char setname[DNS_NAME_FORMATSIZE]; - if (isc_buffer_availablelength(&buf) < strlen("keyset-")) - fatal("directory name '%s' too long", dirname); - isc_buffer_putstr(&buf, "keyset-"); - result = dns_name_tofilenametext(name, ISC_FALSE, &buf); - check_result(result, "dns_name_tofilenametext()"); - if (isc_buffer_availablelength(&buf) == 0) - fatal("name %s too long", setname); - isc_buffer_putuint8(&buf, 0); + dns_name_format(name, setname, sizeof(setname)); result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0, NULL, &db); @@ -111,11 +99,49 @@ loadkeys(char *dirname, char *setname) fatal("can't find %s node in %s", setname, filename); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, - 0, 0, &keyset, NULL); + 0, 0, rdataset, NULL); + if (result == ISC_R_NOTFOUND) fatal("no DNSKEY RR for %s in %s", setname, filename); else if (result != ISC_R_SUCCESS) fatal("dns_db_findrdataset"); + + if (node != NULL) + dns_db_detachnode(db, &node); + if (db != NULL) + dns_db_detach(&db); + return (result); +} + +static isc_result_t +loadkeyset(char *dirname, dns_rdataset_t *rdataset) { + isc_result_t result; + char filename[PATH_MAX + 1]; + isc_buffer_t buf; + + dns_rdataset_init(rdataset); + + isc_buffer_init(&buf, filename, sizeof(filename)); + if (dirname != NULL) { + /* allow room for a trailing slash */ + if (strlen(dirname) >= isc_buffer_availablelength(&buf)) + return (ISC_R_NOSPACE); + isc_buffer_putstr(&buf, dirname); + if (dirname[strlen(dirname) - 1] != '/') + isc_buffer_putstr(&buf, "/"); + } + + if (isc_buffer_availablelength(&buf) < 7) + return (ISC_R_NOSPACE); + isc_buffer_putstr(&buf, "keyset-"); + + result = dns_name_tofilenametext(name, ISC_FALSE, &buf); + check_result(result, "dns_name_tofilenametext()"); + if (isc_buffer_availablelength(&buf) == 0) + return (ISC_R_NOSPACE); + isc_buffer_putuint8(&buf, 0); + + return (loadsetfromfile(filename, rdataset)); } static void @@ -127,20 +153,20 @@ loadkey(char *filename, unsigned char *key_buf, unsigned int key_buf_size, isc_buffer_t keyb; isc_region_t r; - dns_rdataset_init(&keyset); dns_rdata_init(rdata); isc_buffer_init(&keyb, key_buf, key_buf_size); - result = dst_key_fromnamedfile(filename, DST_TYPE_PUBLIC, mctx, &key); + result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC, + mctx, &key); if (result != ISC_R_SUCCESS) fatal("invalid keyfile name %s: %s", filename, isc_result_totext(result)); if (verbose > 2) { - char keystr[KEY_FORMATSIZE]; + char keystr[DST_KEY_FORMATSIZE]; - key_format(key, keystr, sizeof(keystr)); + dst_key_format(key, keystr, sizeof(keystr)); fprintf(stderr, "%s: %s\n", program, keystr); } @@ -169,7 +195,7 @@ logkey(dns_rdata_t *rdata) isc_result_t result; dst_key_t *key = NULL; isc_buffer_t buf; - char keystr[KEY_FORMATSIZE]; + char keystr[DST_KEY_FORMATSIZE]; isc_buffer_init(&buf, rdata->data, rdata->length); isc_buffer_add(&buf, rdata->length); @@ -177,89 +203,132 @@ logkey(dns_rdata_t *rdata) if (result != ISC_R_SUCCESS) return; - key_format(key, keystr, sizeof(keystr)); + dst_key_format(key, keystr, sizeof(keystr)); fprintf(stderr, "%s: %s\n", program, keystr); dst_key_free(&key); } static void -emitds(unsigned int dtype, dns_rdata_t *rdata) +emit(unsigned int dtype, isc_boolean_t showall, char *lookaside, + dns_rdata_t *rdata) { - isc_result_t result; - unsigned char buf[DNS_DS_BUFFERSIZE]; - char text_buf[DST_KEY_MAXTEXTSIZE]; - char class_buf[10]; - isc_buffer_t textb, classb; - isc_region_t r; - dns_rdata_t ds; + isc_result_t result; + unsigned char buf[DNS_DS_BUFFERSIZE]; + char text_buf[DST_KEY_MAXTEXTSIZE]; + char name_buf[DNS_NAME_MAXWIRE]; + char class_buf[10]; + isc_buffer_t textb, nameb, classb; + isc_region_t r; + dns_rdata_t ds; + dns_rdata_dnskey_t dnskey; isc_buffer_init(&textb, text_buf, sizeof(text_buf)); + isc_buffer_init(&nameb, name_buf, sizeof(name_buf)); isc_buffer_init(&classb, class_buf, sizeof(class_buf)); dns_rdata_init(&ds); + result = dns_rdata_tostruct(rdata, &dnskey, NULL); + if (result != ISC_R_SUCCESS) + fatal("can't convert DNSKEY"); + + if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && !showall) + return; + result = dns_ds_buildrdata(name, rdata, dtype, buf, &ds); if (result != ISC_R_SUCCESS) - fatal("can't build DS"); + fatal("can't build record"); + + result = dns_name_totext(name, ISC_FALSE, &nameb); + if (result != ISC_R_SUCCESS) + fatal("can't print name"); + + /* Add lookaside origin, if set */ + if (lookaside != NULL) { + if (isc_buffer_availablelength(&nameb) < strlen(lookaside)) + fatal("DLV origin '%s' is too long", lookaside); + isc_buffer_putstr(&nameb, lookaside); + if (lookaside[strlen(lookaside) - 1] != '.') { + if (isc_buffer_availablelength(&nameb) < 1) + fatal("DLV origin '%s' is too long", lookaside); + isc_buffer_putstr(&nameb, "."); + } + } result = dns_rdata_totext(&ds, (dns_name_t *) NULL, &textb); if (result != ISC_R_SUCCESS) - fatal("can't print DS rdata"); + fatal("can't print rdata"); result = dns_rdataclass_totext(rdclass, &classb); if (result != ISC_R_SUCCESS) - fatal("can't print DS class"); + fatal("can't print class"); - result = dns_name_print(name, stdout); - if (result != ISC_R_SUCCESS) - fatal("can't print DS name"); + isc_buffer_usedregion(&nameb, &r); + isc_util_fwrite(r.base, 1, r.length, stdout); putchar(' '); isc_buffer_usedregion(&classb, &r); isc_util_fwrite(r.base, 1, r.length, stdout); - printf(" DS "); + if (lookaside == NULL) + printf(" DS "); + else + printf(" DLV "); isc_buffer_usedregion(&textb, &r); isc_util_fwrite(r.base, 1, r.length, stdout); putchar('\n'); } +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + static void usage(void) { fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s options keyfile\n\n", program); - fprintf(stderr, " %s options [-c class] [-d dir] -s dnsname\n\n", + fprintf(stderr, " %s options [-K dir] keyfile\n\n", program); + fprintf(stderr, " %s options [-K dir] [-c class] -s dnsname\n\n", program); + fprintf(stderr, " %s options -f zonefile (as zone name)\n\n", program); + fprintf(stderr, " %s options -f zonefile zonename\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "Options:\n"); fprintf(stderr, " -v <verbose level>\n"); + fprintf(stderr, " -K <directory>: directory in which to find " + "key file or keyset file\n"); + fprintf(stderr, " -a algorithm: digest algorithm " + "(SHA-1, SHA-256 or GOST)\n"); fprintf(stderr, " -1: use SHA-1\n"); fprintf(stderr, " -2: use SHA-256\n"); - fprintf(stderr, " -a algorithm: use algorithm\n"); - fprintf(stderr, "Keyset options:\n"); - fprintf(stderr, " -s: keyset mode\n"); - fprintf(stderr, " -c class\n"); - fprintf(stderr, " -d directory\n"); - fprintf(stderr, "Output: DS RRs\n"); + fprintf(stderr, " -l: add lookaside zone and print DLV records\n"); + fprintf(stderr, " -s: read keyset from keyset-<dnsname> file\n"); + fprintf(stderr, " -c class: rdata class for DS set (default: IN)\n"); + fprintf(stderr, " -f file: read keyset from zone file\n"); + fprintf(stderr, " -A: when used with -f, " + "include all keys in DS set, not just KSKs\n"); + fprintf(stderr, "Output: DS or DLV RRs\n"); exit (-1); } int main(int argc, char **argv) { - char *algname = NULL, *classname = NULL, *dirname = NULL; - char *endp; - int ch; - unsigned int dtype = DNS_DSDIGEST_SHA1; - isc_boolean_t both = ISC_TRUE; - isc_boolean_t usekeyset = ISC_FALSE; - isc_result_t result; - isc_log_t *log = NULL; - isc_entropy_t *ectx = NULL; - dns_rdata_t rdata; + char *algname = NULL, *classname = NULL; + char *filename = NULL, *dir = NULL, *namestr; + char *lookaside = NULL; + char *endp; + int ch; + unsigned int dtype = DNS_DSDIGEST_SHA1; + isc_boolean_t both = ISC_TRUE; + isc_boolean_t usekeyset = ISC_FALSE; + isc_boolean_t showall = ISC_FALSE; + isc_result_t result; + isc_log_t *log = NULL; + isc_entropy_t *ectx = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata; dns_rdata_init(&rdata); @@ -275,7 +344,7 @@ main(int argc, char **argv) { isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, - "12a:c:d:sv:h")) != -1) { + "12Aa:c:d:Ff:K:l:sv:h")) != -1) { switch (ch) { case '1': dtype = DNS_DSDIGEST_SHA1; @@ -285,6 +354,9 @@ main(int argc, char **argv) { dtype = DNS_DSDIGEST_SHA256; both = ISC_FALSE; break; + case 'A': + showall = ISC_TRUE; + break; case 'a': algname = isc_commandline_argument; both = ISC_FALSE; @@ -293,7 +365,21 @@ main(int argc, char **argv) { classname = isc_commandline_argument; break; case 'd': - dirname = isc_commandline_argument; + fprintf(stderr, "%s: the -d option is deprecated; " + "use -K\n", program); + /* fall through */ + case 'K': + dir = isc_commandline_argument; + if (strlen(dir) == 0U) + fatal("directory must be non-empty string"); + break; + case 'f': + filename = isc_commandline_argument; + break; + case 'l': + lookaside = isc_commandline_argument; + if (strlen(lookaside) == 0U) + fatal("lookaside must be a non-empty string"); break; case 's': usekeyset = ISC_TRUE; @@ -303,11 +389,14 @@ main(int argc, char **argv) { if (*endp != '\0') fatal("-v must be followed by a number"); break; + case 'F': + /* Reserved for FIPS mode */ + /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); - /* Falls into */ + /* FALLTHROUGH */ case 'h': usage(); @@ -325,13 +414,24 @@ main(int argc, char **argv) { else if (strcasecmp(algname, "SHA256") == 0 || strcasecmp(algname, "SHA-256") == 0) dtype = DNS_DSDIGEST_SHA256; +#ifdef HAVE_OPENSSL_GOST + else if (strcasecmp(algname, "GOST") == 0) + dtype = DNS_DSDIGEST_GOST; +#endif else fatal("unknown algorithm %s", algname); } rdclass = strtoclass(classname); - if (argc < isc_commandline_index + 1) + if (usekeyset && filename != NULL) + fatal("cannot use both -s and -f"); + + /* When not using -f, -A is implicit */ + if (filename == NULL) + showall = ISC_TRUE; + + if (argc < isc_commandline_index + 1 && filename == NULL) fatal("the key file name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); @@ -344,28 +444,50 @@ main(int argc, char **argv) { result = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (result != ISC_R_SUCCESS) - fatal("could not initialize dst"); + fatal("could not initialize dst: %s", + isc_result_totext(result)); isc_entropy_stopcallbacksources(ectx); setup_logging(verbose, mctx, &log); - if (usekeyset) { - loadkeys(dirname, argv[isc_commandline_index]); + dns_rdataset_init(&rdataset); + + if (usekeyset || filename != NULL) { + if (argc < isc_commandline_index + 1 && filename != NULL) { + /* using zone name as the zone file name */ + namestr = filename; + } else + namestr = argv[isc_commandline_index]; - for (result = dns_rdataset_first(&keyset); + result = initname(namestr); + if (result != ISC_R_SUCCESS) + fatal("could not initialize name %s", namestr); + + if (usekeyset) + result = loadkeyset(dir, &rdataset); + else + result = loadsetfromfile(filename, &rdataset); + + if (result != ISC_R_SUCCESS) + fatal("could not load DNSKEY set: %s\n", + isc_result_totext(result)); + + for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; - result = dns_rdataset_next(&keyset)) { + result = dns_rdataset_next(&rdataset)) { dns_rdata_init(&rdata); - dns_rdataset_current(&keyset, &rdata); + dns_rdataset_current(&rdataset, &rdata); if (verbose > 2) logkey(&rdata); if (both) { - emitds(DNS_DSDIGEST_SHA1, &rdata); - emitds(DNS_DSDIGEST_SHA256, &rdata); + emit(DNS_DSDIGEST_SHA1, showall, lookaside, + &rdata); + emit(DNS_DSDIGEST_SHA256, showall, lookaside, + &rdata); } else - emitds(dtype, &rdata); + emit(dtype, showall, lookaside, &rdata); } } else { unsigned char key_buf[DST_KEY_MAXSIZE]; @@ -374,18 +496,14 @@ main(int argc, char **argv) { DST_KEY_MAXSIZE, &rdata); if (both) { - emitds(DNS_DSDIGEST_SHA1, &rdata); - emitds(DNS_DSDIGEST_SHA256, &rdata); + emit(DNS_DSDIGEST_SHA1, showall, lookaside, &rdata); + emit(DNS_DSDIGEST_SHA256, showall, lookaside, &rdata); } else - emitds(dtype, &rdata); + emit(dtype, showall, lookaside, &rdata); } - if (dns_rdataset_isassociated(&keyset)) - dns_rdataset_disassociate(&keyset); - if (node != NULL) - dns_db_detachnode(db, &node); - if (db != NULL) - dns_db_detach(&db); + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); cleanup_logging(&log); dst_lib_destroy(); isc_hash_destroy(); |