summaryrefslogtreecommitdiffstats
path: root/bin/dnssec
diff options
context:
space:
mode:
Diffstat (limited to 'bin/dnssec')
-rw-r--r--bin/dnssec/Makefile.in95
-rw-r--r--bin/dnssec/dnssec-dsfromkey.8124
-rw-r--r--bin/dnssec/dnssec-dsfromkey.c388
-rw-r--r--bin/dnssec/dnssec-dsfromkey.docbook214
-rw-r--r--bin/dnssec/dnssec-dsfromkey.html133
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.8149
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.c327
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.docbook265
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.html171
-rw-r--r--bin/dnssec/dnssec-keygen.8200
-rw-r--r--bin/dnssec/dnssec-keygen.c540
-rw-r--r--bin/dnssec/dnssec-keygen.docbook360
-rw-r--r--bin/dnssec/dnssec-keygen.html232
-rw-r--r--bin/dnssec/dnssec-signzone.8287
-rw-r--r--bin/dnssec/dnssec-signzone.c3031
-rw-r--r--bin/dnssec/dnssec-signzone.docbook512
-rw-r--r--bin/dnssec/dnssec-signzone.html302
-rw-r--r--bin/dnssec/dnssectool.c313
-rw-r--r--bin/dnssec/dnssectool.h76
-rw-r--r--bin/dnssec/win32/dnssectool.dsp113
-rw-r--r--bin/dnssec/win32/dnssectool.dsw29
-rw-r--r--bin/dnssec/win32/dsfromkey.dsp103
-rw-r--r--bin/dnssec/win32/dsfromkey.dsw29
-rw-r--r--bin/dnssec/win32/dsfromkey.mak324
-rw-r--r--bin/dnssec/win32/keyfromlabel.dsp103
-rw-r--r--bin/dnssec/win32/keyfromlabel.dsw29
-rw-r--r--bin/dnssec/win32/keyfromlabel.mak324
-rw-r--r--bin/dnssec/win32/keygen.dsp103
-rw-r--r--bin/dnssec/win32/keygen.dsw29
-rw-r--r--bin/dnssec/win32/keygen.mak324
-rw-r--r--bin/dnssec/win32/nsupdate.dsp103
-rw-r--r--bin/dnssec/win32/nsupdate.dsw29
-rw-r--r--bin/dnssec/win32/signzone.dsp103
-rw-r--r--bin/dnssec/win32/signzone.dsw29
-rw-r--r--bin/dnssec/win32/signzone.mak324
35 files changed, 9817 insertions, 0 deletions
diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in
new file mode 100644
index 0000000..d59a38f
--- /dev/null
+++ b/bin/dnssec/Makefile.in
@@ -0,0 +1,95 @@
+# Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 Internet Software Consortium.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# $Id: Makefile.in,v 1.35 2008/11/07 02:28:49 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES = -DVERSION=\"${VERSION}\"
+CWARNINGS =
+
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../lib/isc/libisc.@A@
+
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+# Alphabetically
+TARGETS = dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \
+ dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@
+
+OBJS = dnssectool.@O@
+
+SRCS = dnssec-dsfromkey.c dnssec-keyfromlabel.c dnssec-keygen.c \
+ dnssec-signzone.c dnssectool.c
+
+MANPAGES = dnssec-dsfromkey.8 dnssec-keyfromlabel.8 dnssec-keygen.8 \
+ dnssec-signzone.8
+
+HTMLPAGES = dnssec-dsfromkey.html dnssec-keyfromlabel.html \
+ dnssec-keygen.html dnssec-signzone.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+dnssec-dsfromkey@EXEEXT@: dnssec-dsfromkey.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-dsfromkey.@O@ ${OBJS} ${LIBS}
+
+dnssec-keyfromlabel@EXEEXT@: dnssec-keyfromlabel.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-keyfromlabel.@O@ ${OBJS} ${LIBS}
+
+dnssec-keygen@EXEEXT@: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-keygen.@O@ ${OBJS} ${LIBS}
+
+dnssec-signzone.@O@: dnssec-signzone.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \
+ -c ${srcdir}/dnssec-signzone.c
+
+dnssec-signzone@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-signzone.@O@ ${OBJS} ${LIBS}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+
+install:: ${TARGETS} installdirs
+ for t in ${TARGETS}; do ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} $$t ${DESTDIR}${sbindir}; done
+ for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man8; done
+
+clean distclean::
+ rm -f ${TARGETS}
+
diff --git a/bin/dnssec/dnssec-dsfromkey.8 b/bin/dnssec/dnssec-dsfromkey.8
new file mode 100644
index 0000000..4d4cbc9
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.8
@@ -0,0 +1,124 @@
+.\" Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" Permission to use, copy, modify, and/or distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $Id: dnssec-dsfromkey.8,v 1.5 2008/11/08 01:11:47 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: dnssec\-dsfromkey
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: November 29, 2008
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "DNSSEC\-DSFROMKEY" "8" "November 29, 2008" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+dnssec\-dsfromkey \- DNSSEC DS RR generation tool
+.SH "SYNOPSIS"
+.HP 17
+\fBdnssec\-dsfromkey\fR [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] {keyfile}
+.HP 17
+\fBdnssec\-dsfromkey\fR {\-s} [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIdir\fR\fR] {dnsname}
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-dsfromkey\fR
+outputs the Delegation Signer (DS) resource record (RR), as defined in RFC 3658 and RFC 4509, for the given key(s).
+.SH "OPTIONS"
+.PP
+\-1
+.RS 4
+Use SHA\-1 as the digest algorithm (the default is to use both SHA\-1 and SHA\-256).
+.RE
+.PP
+\-2
+.RS 4
+Use SHA\-256 as the digest algorithm.
+.RE
+.PP
+\-a \fIalgorithm\fR
+.RS 4
+Select the digest algorithm. The value of
+\fBalgorithm\fR
+must be one of SHA\-1 (SHA1) or SHA\-256 (SHA256). These values are case insensitive.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level.
+.RE
+.PP
+\-s
+.RS 4
+Keyset mode: in place of the keyfile name, the argument is the DNS domain name of a keyset file. Following options make sense only in this mode.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Specifies the DNS class (default is IN), useful only in the keyset mode.
+.RE
+.PP
+\-d \fIdirectory\fR
+.RS 4
+Look for
+\fIkeyset\fR
+files in
+\fBdirectory\fR
+as the directory, ignored when not in the keyset mode.
+.RE
+.SH "EXAMPLE"
+.PP
+To build the SHA\-256 DS RR from the
+\fBKexample.com.+003+26160\fR
+keyfile name, the following command would be issued:
+.PP
+\fBdnssec\-dsfromkey \-2 Kexample.com.+003+26160\fR
+.PP
+The command would print something like:
+.PP
+\fBexample.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94\fR
+.SH "FILES"
+.PP
+The keyfile can be designed by the key identification
+\fIKnnnn.+aaa+iiiii\fR
+or the full file name
+\fIKnnnn.+aaa+iiiii.key\fR
+as generated by
+dnssec\-keygen(8).
+.PP
+The keyset file name is built from the
+\fBdirectory\fR, the string
+\fIkeyset\-\fR
+and the
+\fBdnsname\fR.
+.SH "CAVEAT"
+.PP
+A keyfile error can give a "file not found" even if the file exists.
+.SH "SEE ALSO"
+.PP
+\fBdnssec\-keygen\fR(8),
+\fBdnssec\-signzone\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 3658,
+RFC 4509.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
+.SH "COPYRIGHT"
+Copyright \(co 2008 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dnssec/dnssec-dsfromkey.c b/bin/dnssec/dnssec-dsfromkey.c
new file mode 100644
index 0000000..d3d1d06
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dnssec-dsfromkey.c,v 1.2 2008/11/07 02:28:49 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/ds.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+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 void
+loadkeys(char *dirname, char *setname)
+{
+ isc_result_t result;
+ char filename[1024];
+ 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);
+
+ isc_buffer_init(&buf, filename, sizeof(filename));
+ if (dirname != NULL) {
+ isc_buffer_putstr(&buf, dirname);
+ if (dirname[strlen(dirname) - 1] != '/')
+ isc_buffer_putstr(&buf, "/");
+ }
+ 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);
+
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
+ rdclass, 0, NULL, &db);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't create database");
+
+ result = dns_db_load(db, filename);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
+ fatal("can't load %s: %s", filename, isc_result_totext(result));
+
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't find %s node in %s", setname, filename);
+
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey,
+ 0, 0, &keyset, 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");
+}
+
+static void
+loadkey(char *filename, dns_rdata_t *rdata)
+{
+ isc_result_t result;
+ dst_key_t *key = NULL;
+ unsigned char key_buf[DST_KEY_MAXSIZE];
+ isc_buffer_t keyb;
+ isc_region_t r;
+
+ dns_rdataset_init(&keyset);
+ dns_rdata_init(rdata);
+
+ isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+
+ result = dst_key_fromnamedfile(filename, 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];
+
+ key_format(key, keystr, sizeof(keystr));
+ fprintf(stderr, "%s: %s\n", program, keystr);
+ }
+
+ result = dst_key_todns(key, &keyb);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't decode key");
+
+ isc_buffer_usedregion(&keyb, &r);
+ dns_rdata_fromregion(rdata, dst_key_class(key),
+ dns_rdatatype_dnskey, &r);
+
+ rdclass = dst_key_class(key);
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ result = dns_name_copy(dst_key_name(key), name, NULL);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't copy name");
+
+ dst_key_free(&key);
+}
+
+static void
+logkey(dns_rdata_t *rdata)
+{
+ isc_result_t result;
+ dst_key_t *key = NULL;
+ isc_buffer_t buf;
+ char keystr[KEY_FORMATSIZE];
+
+ isc_buffer_init(&buf, rdata->data, rdata->length);
+ isc_buffer_add(&buf, rdata->length);
+ result = dst_key_fromdns(name, rdclass, &buf, mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ 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)
+{
+ 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_buffer_init(&textb, text_buf, sizeof(text_buf));
+ isc_buffer_init(&classb, class_buf, sizeof(class_buf));
+
+ dns_rdata_init(&ds);
+
+ result = dns_ds_buildrdata(name, rdata, dtype, buf, &ds);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't build DS");
+
+ result = dns_rdata_totext(&ds, (dns_name_t *) NULL, &textb);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't print DS rdata");
+
+ result = dns_rdataclass_totext(rdclass, &classb);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't print DS class");
+
+ result = dns_name_print(name, stdout);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't print DS name");
+
+ putchar(' ');
+
+ isc_buffer_usedregion(&classb, &r);
+ fwrite(r.base, 1, r.length, stdout);
+
+ printf(" DS ");
+
+ isc_buffer_usedregion(&textb, &r);
+ fwrite(r.base, 1, r.length, stdout);
+ putchar('\n');
+}
+
+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",
+ program);
+ fprintf(stderr, "Version: %s\n", VERSION);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -v <verbose level>\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");
+
+ 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;
+
+ dns_rdata_init(&rdata);
+
+ if (argc == 1)
+ usage();
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ fatal("out of memory");
+
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+
+ while ((ch = isc_commandline_parse(argc, argv,
+ "12a:c:d:sv:h")) != -1) {
+ switch (ch) {
+ case '1':
+ dtype = DNS_DSDIGEST_SHA1;
+ both = ISC_FALSE;
+ break;
+ case '2':
+ dtype = DNS_DSDIGEST_SHA256;
+ both = ISC_FALSE;
+ break;
+ case 'a':
+ algname = isc_commandline_argument;
+ both = ISC_FALSE;
+ break;
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+ case 'd':
+ dirname = isc_commandline_argument;
+ break;
+ case 's':
+ usekeyset = ISC_TRUE;
+ break;
+ case 'v':
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0')
+ fatal("-v must be followed by a number");
+ break;
+ case '?':
+ if (isc_commandline_option != '?')
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ /* Falls into */
+ case 'h':
+ usage();
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n",
+ program, isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (algname != NULL) {
+ if (strcasecmp(algname, "SHA1") == 0 ||
+ strcasecmp(algname, "SHA-1") == 0)
+ dtype = DNS_DSDIGEST_SHA1;
+ else if (strcasecmp(algname, "SHA256") == 0 ||
+ strcasecmp(algname, "SHA-256") == 0)
+ dtype = DNS_DSDIGEST_SHA256;
+ else
+ fatal("unknown algorithm %s", algname);
+ }
+
+ rdclass = strtoclass(classname);
+
+ if (argc < isc_commandline_index + 1)
+ fatal("the key file name was not specified");
+ if (argc > isc_commandline_index + 1)
+ fatal("extraneous arguments");
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize hash");
+ result = dst_lib_init(mctx, ectx,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize dst");
+ isc_entropy_stopcallbacksources(ectx);
+
+ setup_logging(verbose, mctx, &log);
+
+ if (usekeyset) {
+ loadkeys(dirname, argv[isc_commandline_index]);
+
+ for (result = dns_rdataset_first(&keyset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&keyset)) {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(&keyset, &rdata);
+
+ if (verbose > 2)
+ logkey(&rdata);
+
+ if (both) {
+ emitds(DNS_DSDIGEST_SHA1, &rdata);
+ emitds(DNS_DSDIGEST_SHA256, &rdata);
+ } else
+ emitds(dtype, &rdata);
+ }
+ } else {
+ loadkey(argv[isc_commandline_index], &rdata);
+
+ if (both) {
+ emitds(DNS_DSDIGEST_SHA1, &rdata);
+ emitds(DNS_DSDIGEST_SHA256, &rdata);
+ } else
+ emitds(dtype, &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);
+ cleanup_logging(&log);
+ dst_lib_destroy();
+ isc_hash_destroy();
+ cleanup_entropy(&ectx);
+ dns_name_destroy();
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-dsfromkey.docbook b/bin/dnssec/dnssec-dsfromkey.docbook
new file mode 100644
index 0000000..c2c6b85
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.docbook
@@ -0,0 +1,214 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<!-- $Id: dnssec-dsfromkey.docbook,v 1.6 2008/11/07 13:54:11 jreed Exp $ -->
+<refentry id="man.dnssec-dsfromkey">
+ <refentryinfo>
+ <date>November 29, 2008</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-dsfromkey</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-dsfromkey</application></refname>
+ <refpurpose>DNSSEC DS RR generation tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dnssec-dsfromkey</command>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg><option>-1</option></arg>
+ <arg><option>-2</option></arg>
+ <arg><option>-a <replaceable class="parameter">alg</replaceable></option></arg>
+ <arg choice="req">keyfile</arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>dnssec-dsfromkey</command>
+ <arg choice="req">-s</arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg><option>-1</option></arg>
+ <arg><option>-2</option></arg>
+ <arg><option>-a <replaceable class="parameter">alg</replaceable></option></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-d <replaceable class="parameter">dir</replaceable></option></arg>
+ <arg choice="req">dnsname</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>dnssec-dsfromkey</command>
+ outputs the Delegation Signer (DS) resource record (RR), as defined in
+ RFC 3658 and RFC 4509, for the given key(s).
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-1</term>
+ <listitem>
+ <para>
+ Use SHA-1 as the digest algorithm (the default is to use
+ both SHA-1 and SHA-256).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-2</term>
+ <listitem>
+ <para>
+ Use SHA-256 as the digest algorithm.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-a <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+ Select the digest algorithm. The value of
+ <option>algorithm</option> must be one of SHA-1 (SHA1) or
+ SHA-256 (SHA256). These values are case insensitive.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s</term>
+ <listitem>
+ <para>
+ Keyset mode: in place of the keyfile name, the argument is
+ the DNS domain name of a keyset file. Following options make sense
+ only in this mode.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the DNS class (default is IN), useful only
+ in the keyset mode.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Look for <filename>keyset</filename> files in
+ <option>directory</option> as the directory, ignored when
+ not in the keyset mode.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>EXAMPLE</title>
+ <para>
+ To build the SHA-256 DS RR from the
+ <userinput>Kexample.com.+003+26160</userinput>
+ keyfile name, the following command would be issued:
+ </para>
+ <para><userinput>dnssec-dsfromkey -2 Kexample.com.+003+26160</userinput>
+ </para>
+ <para>
+ The command would print something like:
+ </para>
+ <para><userinput>example.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94</userinput>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+ <para>
+ The keyfile can be designed by the key identification
+ <filename>Knnnn.+aaa+iiiii</filename> or the full file name
+ <filename>Knnnn.+aaa+iiiii.key</filename> as generated by
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>.
+ </para>
+ <para>
+ The keyset file name is built from the <option>directory</option>,
+ the string <filename>keyset-</filename> and the
+ <option>dnsname</option>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>CAVEAT</title>
+ <para>
+ A keyfile error can give a "file not found" even if the file exists.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 3658</citetitle>,
+ <citetitle>RFC 4509</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dnssec/dnssec-dsfromkey.html b/bin/dnssec/dnssec-dsfromkey.html
new file mode 100644
index 0000000..72dfd3a
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.html
@@ -0,0 +1,133 @@
+<!--
+ - Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<!-- $Id: dnssec-dsfromkey.html,v 1.5 2008/11/08 01:11:47 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-dsfromkey</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.dnssec-dsfromkey"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-dsfromkey</span> &#8212; DNSSEC DS RR generation tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-dsfromkey</code> [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-1</code>] [<code class="option">-2</code>] [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>] {keyfile}</p></div>
+<div class="cmdsynopsis"><p><code class="command">dnssec-dsfromkey</code> {-s} [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-1</code>] [<code class="option">-2</code>] [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-d <em class="replaceable"><code>dir</code></em></code>] {dnsname}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543424"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-dsfromkey</strong></span>
+ outputs the Delegation Signer (DS) resource record (RR), as defined in
+ RFC 3658 and RFC 4509, for the given key(s).
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543435"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-1</span></dt>
+<dd><p>
+ Use SHA-1 as the digest algorithm (the default is to use
+ both SHA-1 and SHA-256).
+ </p></dd>
+<dt><span class="term">-2</span></dt>
+<dd><p>
+ Use SHA-256 as the digest algorithm.
+ </p></dd>
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd><p>
+ Select the digest algorithm. The value of
+ <code class="option">algorithm</code> must be one of SHA-1 (SHA1) or
+ SHA-256 (SHA256). These values are case insensitive.
+ </p></dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+<dt><span class="term">-s</span></dt>
+<dd><p>
+ Keyset mode: in place of the keyfile name, the argument is
+ the DNS domain name of a keyset file. Following options make sense
+ only in this mode.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Specifies the DNS class (default is IN), useful only
+ in the keyset mode.
+ </p></dd>
+<dt><span class="term">-d <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ Look for <code class="filename">keyset</code> files in
+ <code class="option">directory</code> as the directory, ignored when
+ not in the keyset mode.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543563"></a><h2>EXAMPLE</h2>
+<p>
+ To build the SHA-256 DS RR from the
+ <strong class="userinput"><code>Kexample.com.+003+26160</code></strong>
+ keyfile name, the following command would be issued:
+ </p>
+<p><strong class="userinput"><code>dnssec-dsfromkey -2 Kexample.com.+003+26160</code></strong>
+ </p>
+<p>
+ The command would print something like:
+ </p>
+<p><strong class="userinput"><code>example.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94</code></strong>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543593"></a><h2>FILES</h2>
+<p>
+ The keyfile can be designed by the key identification
+ <code class="filename">Knnnn.+aaa+iiiii</code> or the full file name
+ <code class="filename">Knnnn.+aaa+iiiii.key</code> as generated by
+ <span class="refentrytitle">dnssec-keygen</span>(8).
+ </p>
+<p>
+ The keyset file name is built from the <code class="option">directory</code>,
+ the string <code class="filename">keyset-</code> and the
+ <code class="option">dnsname</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543628"></a><h2>CAVEAT</h2>
+<p>
+ A keyfile error can give a "file not found" even if the file exists.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543638"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 3658</em>,
+ <em class="citetitle">RFC 4509</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543674"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-keyfromlabel.8 b/bin/dnssec/dnssec-keyfromlabel.8
new file mode 100644
index 0000000..6222058
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.8
@@ -0,0 +1,149 @@
+.\" Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $Id: dnssec-keyfromlabel.8,v 1.6 2008/11/08 01:11:47 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: dnssec\-keyfromlabel
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: February 8, 2008
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "DNSSEC\-KEYFROMLABEL" "8" "February 8, 2008" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+dnssec\-keyfromlabel \- DNSSEC key generation tool
+.SH "SYNOPSIS"
+.HP 20
+\fBdnssec\-keyfromlabel\fR {\-a\ \fIalgorithm\fR} {\-l\ \fIlabel\fR} [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-k\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] {name}
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-keyfromlabel\fR
+gets keys with the given label from a crypto hardware and builds key files for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034.
+.SH "OPTIONS"
+.PP
+\-a \fIalgorithm\fR
+.RS 4
+Selects the cryptographic algorithm. The value of
+\fBalgorithm\fR
+must be one of RSAMD5 (RSA) or RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA or DH (Diffie Hellman). These values are case insensitive.
+.sp
+Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended.
+.sp
+Note 2: DH automatically sets the \-k flag.
+.RE
+.PP
+\-l \fIlabel\fR
+.RS 4
+Specifies the label of keys in the crypto hardware (PKCS#11 device).
+.RE
+.PP
+\-n \fInametype\fR
+.RS 4
+Specifies the owner type of the key. The value of
+\fBnametype\fR
+must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). These values are case insensitive.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used.
+.RE
+.PP
+\-f \fIflag\fR
+.RS 4
+Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flag is KSK (Key Signing Key) DNSKEY.
+.RE
+.PP
+\-h
+.RS 4
+Prints a short summary of the options and arguments to
+\fBdnssec\-keygen\fR.
+.RE
+.PP
+\-k
+.RS 4
+Generate KEY records rather than DNSKEY records.
+.RE
+.PP
+\-p \fIprotocol\fR
+.RS 4
+Sets the protocol value for the generated key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors.
+.RE
+.PP
+\-t \fItype\fR
+.RS 4
+Indicates the use of the key.
+\fBtype\fR
+must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. AUTH refers to the ability to authenticate data, and CONF the ability to encrypt data.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level.
+.RE
+.SH "GENERATED KEY FILES"
+.PP
+When
+\fBdnssec\-keyfromlabel\fR
+completes successfully, it prints a string of the form
+\fIKnnnn.+aaa+iiiii\fR
+to the standard output. This is an identification string for the key files it has generated.
+.TP 4
+\(bu
+\fInnnn\fR
+is the key name.
+.TP 4
+\(bu
+\fIaaa\fR
+is the numeric representation of the algorithm.
+.TP 4
+\(bu
+\fIiiiii\fR
+is the key identifier (or footprint).
+.PP
+\fBdnssec\-keyfromlabel\fR
+creates two files, with names based on the printed string.
+\fIKnnnn.+aaa+iiiii.key\fR
+contains the public key, and
+\fIKnnnn.+aaa+iiiii.private\fR
+contains the private key.
+.PP
+The
+\fI.key\fR
+file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement).
+.PP
+The
+\fI.private\fR
+file contains algorithm specific fields. For obvious security reasons, this file does not have general read permission.
+.SH "SEE ALSO"
+.PP
+\fBdnssec\-keygen\fR(8),
+\fBdnssec\-signzone\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 2539,
+RFC 2845,
+RFC 4033.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
+.SH "COPYRIGHT"
+Copyright \(co 2008 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c
new file mode 100644
index 0000000..e7587c3
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dnssec-keyfromlabel.c,v 1.4 2008/09/24 02:46:21 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+#define MAX_RSA 4096 /* should be long enough... */
+
+const char *program = "dnssec-keyfromlabel";
+int verbose;
+
+static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 |"
+ " NSEC3DSA | NSEC3RSASHA1";
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s -a alg -l label [options] name\n\n",
+ program);
+ fprintf(stderr, "Version: %s\n", VERSION);
+ fprintf(stderr, "Required options:\n");
+ fprintf(stderr, " -a algorithm: %s\n", algs);
+ fprintf(stderr, " -l label: label of the key\n");
+ fprintf(stderr, " name: owner of the key\n");
+ fprintf(stderr, "Other options:\n");
+ fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n");
+ fprintf(stderr, " (DNSKEY generation defaults to ZONE\n");
+ fprintf(stderr, " -c <class> (default: IN)\n");
+ fprintf(stderr, " -f keyflag: KSK\n");
+ fprintf(stderr, " -t <type>: "
+ "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
+ "(default: AUTHCONF)\n");
+ fprintf(stderr, " -p <protocol>: "
+ "default: 3 [dnssec]\n");
+ fprintf(stderr, " -v <verbose level>\n");
+ fprintf(stderr, " -k : generate a TYPE=KEY key\n");
+ fprintf(stderr, "Output:\n");
+ fprintf(stderr, " K<name>+<alg>+<id>.key, "
+ "K<name>+<alg>+<id>.private\n");
+
+ exit (-1);
+}
+
+int
+main(int argc, char **argv) {
+ char *algname = NULL, *nametype = NULL, *type = NULL;
+ char *classname = NULL;
+ char *endp;
+ dst_key_t *key = NULL, *oldkey;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_uint16_t flags = 0, ksk = 0;
+ dns_secalg_t alg;
+ isc_boolean_t null_key = ISC_FALSE;
+ isc_mem_t *mctx = NULL;
+ int ch;
+ int protocol = -1, signatory = 0;
+ isc_result_t ret;
+ isc_textregion_t r;
+ char filename[255];
+ isc_buffer_t buf;
+ isc_log_t *log = NULL;
+ isc_entropy_t *ectx = NULL;
+ dns_rdataclass_t rdclass;
+ int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC;
+ char *label = NULL;
+
+ if (argc == 1)
+ usage();
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+
+ while ((ch = isc_commandline_parse(argc, argv,
+ "a:c:f:kl:n:p:t:v:h")) != -1)
+ {
+ switch (ch) {
+ case 'a':
+ algname = isc_commandline_argument;
+ break;
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+ case 'f':
+ if (strcasecmp(isc_commandline_argument, "KSK") == 0)
+ ksk = DNS_KEYFLAG_KSK;
+ else
+ fatal("unknown flag '%s'",
+ isc_commandline_argument);
+ break;
+ case 'k':
+ options |= DST_TYPE_KEY;
+ break;
+ case 'l':
+ label = isc_commandline_argument;
+ break;
+ case 'n':
+ nametype = isc_commandline_argument;
+ break;
+ case 'p':
+ protocol = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || protocol < 0 || protocol > 255)
+ fatal("-p must be followed by a number "
+ "[0..255]");
+ break;
+ case 't':
+ type = isc_commandline_argument;
+ break;
+ case 'v':
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0')
+ fatal("-v must be followed by a number");
+ break;
+
+ case '?':
+ if (isc_commandline_option != '?')
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ case 'h':
+ usage();
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n",
+ program, isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ ret = dst_lib_init(mctx, ectx,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ if (ret != ISC_R_SUCCESS)
+ fatal("could not initialize dst");
+
+ setup_logging(verbose, mctx, &log);
+
+ if (label == NULL)
+ fatal("the key label was not specified");
+ if (argc < isc_commandline_index + 1)
+ fatal("the key name was not specified");
+ if (argc > isc_commandline_index + 1)
+ fatal("extraneous arguments");
+
+ if (algname == NULL)
+ fatal("no algorithm was specified");
+ if (strcasecmp(algname, "RSA") == 0) {
+ fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n"
+ "If you still wish to use RSA (RSAMD5) please "
+ "specify \"-a RSAMD5\"\n");
+ return (1);
+ } else {
+ r.base = algname;
+ r.length = strlen(algname);
+ ret = dns_secalg_fromtext(&alg, &r);
+ if (ret != ISC_R_SUCCESS)
+ fatal("unknown algorithm %s", algname);
+ if (alg == DST_ALG_DH)
+ options |= DST_TYPE_KEY;
+ }
+
+ if (type != NULL && (options & DST_TYPE_KEY) != 0) {
+ if (strcasecmp(type, "NOAUTH") == 0)
+ flags |= DNS_KEYTYPE_NOAUTH;
+ else if (strcasecmp(type, "NOCONF") == 0)
+ flags |= DNS_KEYTYPE_NOCONF;
+ else if (strcasecmp(type, "NOAUTHCONF") == 0) {
+ flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF);
+ }
+ else if (strcasecmp(type, "AUTHCONF") == 0)
+ /* nothing */;
+ else
+ fatal("invalid type %s", type);
+ }
+
+ if (nametype == NULL) {
+ if ((options & DST_TYPE_KEY) != 0) /* KEY */
+ fatal("no nametype specified");
+ flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */
+ } else if (strcasecmp(nametype, "zone") == 0)
+ flags |= DNS_KEYOWNER_ZONE;
+ else if ((options & DST_TYPE_KEY) != 0) { /* KEY */
+ if (strcasecmp(nametype, "host") == 0 ||
+ strcasecmp(nametype, "entity") == 0)
+ flags |= DNS_KEYOWNER_ENTITY;
+ else if (strcasecmp(nametype, "user") == 0)
+ flags |= DNS_KEYOWNER_USER;
+ else
+ fatal("invalid KEY nametype %s", nametype);
+ } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */
+ fatal("invalid DNSKEY nametype %s", nametype);
+
+ rdclass = strtoclass(classname);
+
+ if ((options & DST_TYPE_KEY) != 0) /* KEY */
+ flags |= signatory;
+ else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */
+ flags |= ksk;
+
+ if (protocol == -1)
+ protocol = DNS_KEYPROTO_DNSSEC;
+ else if ((options & DST_TYPE_KEY) == 0 &&
+ protocol != DNS_KEYPROTO_DNSSEC)
+ fatal("invalid DNSKEY protocol: %d", protocol);
+
+ if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
+ if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0)
+ fatal("specified null key with signing authority");
+ }
+
+ if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
+ alg == DNS_KEYALG_DH)
+ fatal("a key with algorithm '%s' cannot be a zone key",
+ algname);
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ isc_buffer_init(&buf, argv[isc_commandline_index],
+ strlen(argv[isc_commandline_index]));
+ isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
+ ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL);
+ if (ret != ISC_R_SUCCESS)
+ fatal("invalid key name %s: %s", argv[isc_commandline_index],
+ isc_result_totext(ret));
+
+ if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
+ null_key = ISC_TRUE;
+
+ isc_buffer_init(&buf, filename, sizeof(filename) - 1);
+
+ /* associate the key */
+ ret = dst_key_fromlabel(name, alg, flags, protocol,
+ rdclass, "", label, NULL, mctx, &key);
+ isc_entropy_stopcallbacksources(ectx);
+
+ if (ret != ISC_R_SUCCESS) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char algstr[ALG_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ alg_format(alg, algstr, sizeof(algstr));
+ fatal("failed to generate key %s/%s: %s\n",
+ namestr, algstr, isc_result_totext(ret));
+ exit(-1);
+ }
+
+ /*
+ * Try to read a key with the same name, alg and id from disk.
+ * If there is one we must continue generating a new one
+ * unless we were asked to generate a null key, in which
+ * case we return failure.
+ */
+ ret = dst_key_fromfile(name, dst_key_id(key), alg,
+ DST_TYPE_PRIVATE, NULL, mctx, &oldkey);
+ /* do not overwrite an existing key */
+ if (ret == ISC_R_SUCCESS) {
+ isc_buffer_clear(&buf);
+ ret = dst_key_buildfilename(key, 0, NULL, &buf);
+ fprintf(stderr, "%s: %s already exists\n",
+ program, filename);
+ dst_key_free(&key);
+ exit (1);
+ }
+
+ ret = dst_key_tofile(key, options, NULL);
+ if (ret != ISC_R_SUCCESS) {
+ char keystr[KEY_FORMATSIZE];
+ key_format(key, keystr, sizeof(keystr));
+ fatal("failed to write key %s: %s\n", keystr,
+ isc_result_totext(ret));
+ }
+
+ isc_buffer_clear(&buf);
+ ret = dst_key_buildfilename(key, 0, NULL, &buf);
+ printf("%s\n", filename);
+ dst_key_free(&key);
+
+ cleanup_logging(&log);
+ cleanup_entropy(&ectx);
+ dst_lib_destroy();
+ dns_name_destroy();
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-keyfromlabel.docbook b/bin/dnssec/dnssec-keyfromlabel.docbook
new file mode 100644
index 0000000..2bcf0a4
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.docbook
@@ -0,0 +1,265 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<!-- $Id: dnssec-keyfromlabel.docbook,v 1.6 2008/11/07 13:54:11 jreed Exp $ -->
+<refentry id="man.dnssec-keyfromlabel">
+ <refentryinfo>
+ <date>February 8, 2008</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-keyfromlabel</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-keyfromlabel</application></refname>
+ <refpurpose>DNSSEC key generation tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dnssec-keyfromlabel</command>
+ <arg choice="req">-a <replaceable class="parameter">algorithm</replaceable></arg>
+ <arg choice="req">-l <replaceable class="parameter">label</replaceable></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-f <replaceable class="parameter">flag</replaceable></option></arg>
+ <arg><option>-k</option></arg>
+ <arg><option>-n <replaceable class="parameter">nametype</replaceable></option></arg>
+ <arg><option>-p <replaceable class="parameter">protocol</replaceable></option></arg>
+ <arg><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="req">name</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>dnssec-keyfromlabel</command>
+ gets keys with the given label from a crypto hardware and builds
+ key files for DNSSEC (Secure DNS), as defined in RFC 2535
+ and RFC 4034.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-a <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+ Selects the cryptographic algorithm. The value of
+ <option>algorithm</option> must be one of RSAMD5 (RSA)
+ or RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA or DH (Diffie Hellman).
+ These values are case insensitive.
+ </para>
+ <para>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended.
+ </para>
+ <para>
+ Note 2: DH automatically sets the -k flag.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l <replaceable class="parameter">label</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the label of keys in the crypto hardware
+ (PKCS#11 device).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">nametype</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the owner type of the key. The value of
+ <option>nametype</option> must either be ZONE (for a DNSSEC
+ zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with
+ a host (KEY)),
+ USER (for a key associated with a user(KEY)) or OTHER (DNSKEY).
+ These values are
+ case insensitive.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">flag</replaceable></term>
+ <listitem>
+ <para>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flag is KSK (Key Signing Key) DNSKEY.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>dnssec-keygen</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k</term>
+ <listitem>
+ <para>
+ Generate KEY records rather than DNSKEY records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">protocol</replaceable></term>
+ <listitem>
+ <para>
+ Sets the protocol value for the generated key. The protocol
+ is a number between 0 and 255. The default is 3 (DNSSEC).
+ Other possible values for this argument are listed in
+ RFC 2535 and its successors.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ Indicates the use of the key. <option>type</option> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>GENERATED KEY FILES</title>
+ <para>
+ When <command>dnssec-keyfromlabel</command> completes
+ successfully,
+ it prints a string of the form <filename>Knnnn.+aaa+iiiii</filename>
+ to the standard output. This is an identification string for
+ the key files it has generated.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><filename>nnnn</filename> is the key name.
+ </para>
+ </listitem>
+ <listitem>
+ <para><filename>aaa</filename> is the numeric representation
+ of the
+ algorithm.
+ </para>
+ </listitem>
+ <listitem>
+ <para><filename>iiiii</filename> is the key identifier (or
+ footprint).
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para><command>dnssec-keyfromlabel</command>
+ creates two files, with names based
+ on the printed string. <filename>Knnnn.+aaa+iiiii.key</filename>
+ contains the public key, and
+ <filename>Knnnn.+aaa+iiiii.private</filename> contains the
+ private
+ key.
+ </para>
+ <para>
+ The <filename>.key</filename> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </para>
+ <para>
+ The <filename>.private</filename> file contains algorithm
+ specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 2539</citetitle>,
+ <citetitle>RFC 2845</citetitle>,
+ <citetitle>RFC 4033</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dnssec/dnssec-keyfromlabel.html b/bin/dnssec/dnssec-keyfromlabel.html
new file mode 100644
index 0000000..cbea64b
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.html
@@ -0,0 +1,171 @@
+<!--
+ - Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+<!-- $Id: dnssec-keyfromlabel.html,v 1.5 2008/10/15 01:11:35 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-keyfromlabel</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.dnssec-keyfromlabel"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-keyfromlabel</span> &#8212; DNSSEC key generation tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-keyfromlabel</code> {-a <em class="replaceable"><code>algorithm</code></em>} {-l <em class="replaceable"><code>label</code></em>} [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-f <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-k</code>] [<code class="option">-n <em class="replaceable"><code>nametype</code></em></code>] [<code class="option">-p <em class="replaceable"><code>protocol</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] {name}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543413"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-keyfromlabel</strong></span>
+ gets keys with the given label from a crypto hardware and builds
+ key files for DNSSEC (Secure DNS), as defined in RFC 2535
+ and RFC 4034.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543425"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd>
+<p>
+ Selects the cryptographic algorithm. The value of
+ <code class="option">algorithm</code> must be one of RSAMD5 (RSA)
+ or RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA or DH (Diffie Hellman).
+ These values are case insensitive.
+ </p>
+<p>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended.
+ </p>
+<p>
+ Note 2: DH automatically sets the -k flag.
+ </p>
+</dd>
+<dt><span class="term">-l <em class="replaceable"><code>label</code></em></span></dt>
+<dd><p>
+ Specifies the label of keys in the crypto hardware
+ (PKCS#11 device).
+ </p></dd>
+<dt><span class="term">-n <em class="replaceable"><code>nametype</code></em></span></dt>
+<dd><p>
+ Specifies the owner type of the key. The value of
+ <code class="option">nametype</code> must either be ZONE (for a DNSSEC
+ zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with
+ a host (KEY)),
+ USER (for a key associated with a user(KEY)) or OTHER (DNSKEY).
+ These values are
+ case insensitive.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </p></dd>
+<dt><span class="term">-f <em class="replaceable"><code>flag</code></em></span></dt>
+<dd><p>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flag is KSK (Key Signing Key) DNSKEY.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Prints a short summary of the options and arguments to
+ <span><strong class="command">dnssec-keygen</strong></span>.
+ </p></dd>
+<dt><span class="term">-k</span></dt>
+<dd><p>
+ Generate KEY records rather than DNSKEY records.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>protocol</code></em></span></dt>
+<dd><p>
+ Sets the protocol value for the generated key. The protocol
+ is a number between 0 and 255. The default is 3 (DNSSEC).
+ Other possible values for this argument are listed in
+ RFC 2535 and its successors.
+ </p></dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd><p>
+ Indicates the use of the key. <code class="option">type</code> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </p></dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543619"></a><h2>GENERATED KEY FILES</h2>
+<p>
+ When <span><strong class="command">dnssec-keyfromlabel</strong></span> completes
+ successfully,
+ it prints a string of the form <code class="filename">Knnnn.+aaa+iiiii</code>
+ to the standard output. This is an identification string for
+ the key files it has generated.
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li><p><code class="filename">nnnn</code> is the key name.
+ </p></li>
+<li><p><code class="filename">aaa</code> is the numeric representation
+ of the
+ algorithm.
+ </p></li>
+<li><p><code class="filename">iiiii</code> is the key identifier (or
+ footprint).
+ </p></li>
+</ul></div>
+<p><span><strong class="command">dnssec-keyfromlabel</strong></span>
+ creates two files, with names based
+ on the printed string. <code class="filename">Knnnn.+aaa+iiiii.key</code>
+ contains the public key, and
+ <code class="filename">Knnnn.+aaa+iiiii.private</code> contains the
+ private
+ key.
+ </p>
+<p>
+ The <code class="filename">.key</code> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </p>
+<p>
+ The <code class="filename">.private</code> file contains algorithm
+ specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543691"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 2539</em>,
+ <em class="citetitle">RFC 2845</em>,
+ <em class="citetitle">RFC 4033</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543731"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-keygen.8 b/bin/dnssec/dnssec-keygen.8
new file mode 100644
index 0000000..13db3d9
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.8
@@ -0,0 +1,200 @@
+.\" Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000-2003 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $Id: dnssec-keygen.8,v 1.40 2008/10/15 01:11:35 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: dnssec\-keygen
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: June 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "DNSSEC\-KEYGEN" "8" "June 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+dnssec\-keygen \- DNSSEC key generation tool
+.SH "SYNOPSIS"
+.HP 14
+\fBdnssec\-keygen\fR {\-a\ \fIalgorithm\fR} {\-b\ \fIkeysize\fR} {\-n\ \fInametype\fR} [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-e\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-g\ \fR\fB\fIgenerator\fR\fR] [\fB\-h\fR] [\fB\-k\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-s\ \fR\fB\fIstrength\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] {name}
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-keygen\fR
+generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with TSIG (Transaction Signatures), as defined in RFC 2845.
+.SH "OPTIONS"
+.PP
+\-a \fIalgorithm\fR
+.RS 4
+Selects the cryptographic algorithm. The value of
+\fBalgorithm\fR
+must be one of RSAMD5 (RSA) or RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, DH (Diffie Hellman), or HMAC\-MD5. These values are case insensitive.
+.sp
+Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended. For TSIG, HMAC\-MD5 is mandatory.
+.sp
+Note 2: HMAC\-MD5 and DH automatically set the \-k flag.
+.RE
+.PP
+\-b \fIkeysize\fR
+.RS 4
+Specifies the number of bits in the key. The choice of key size depends on the algorithm used. RSAMD5 / RSASHA1 keys must be between 512 and 2048 bits. Diffie Hellman keys must be between 128 and 4096 bits. DSA keys must be between 512 and 1024 bits and an exact multiple of 64. HMAC\-MD5 keys must be between 1 and 512 bits.
+.RE
+.PP
+\-n \fInametype\fR
+.RS 4
+Specifies the owner type of the key. The value of
+\fBnametype\fR
+must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). These values are case insensitive. Defaults to ZONE for DNSKEY generation.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used.
+.RE
+.PP
+\-e
+.RS 4
+If generating an RSAMD5/RSASHA1 key, use a large exponent.
+.RE
+.PP
+\-f \fIflag\fR
+.RS 4
+Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flag is KSK (Key Signing Key) DNSKEY.
+.RE
+.PP
+\-g \fIgenerator\fR
+.RS 4
+If generating a Diffie Hellman key, use this generator. Allowed values are 2 and 5. If no generator is specified, a known prime from RFC 2539 will be used if possible; otherwise the default is 2.
+.RE
+.PP
+\-h
+.RS 4
+Prints a short summary of the options and arguments to
+\fBdnssec\-keygen\fR.
+.RE
+.PP
+\-k
+.RS 4
+Generate KEY records rather than DNSKEY records.
+.RE
+.PP
+\-p \fIprotocol\fR
+.RS 4
+Sets the protocol value for the generated key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors.
+.RE
+.PP
+\-r \fIrandomdev\fR
+.RS 4
+Specifies the source of randomness. If the operating system does not provide a
+\fI/dev/random\fR
+or equivalent device, the default source of randomness is keyboard input.
+\fIrandomdev\fR
+specifies the name of a character device or file containing random data to be used instead of the default. The special value
+\fIkeyboard\fR
+indicates that keyboard input should be used.
+.RE
+.PP
+\-s \fIstrength\fR
+.RS 4
+Specifies the strength value of the key. The strength is a number between 0 and 15, and currently has no defined purpose in DNSSEC.
+.RE
+.PP
+\-t \fItype\fR
+.RS 4
+Indicates the use of the key.
+\fBtype\fR
+must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. AUTH refers to the ability to authenticate data, and CONF the ability to encrypt data.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level.
+.RE
+.SH "GENERATED KEYS"
+.PP
+When
+\fBdnssec\-keygen\fR
+completes successfully, it prints a string of the form
+\fIKnnnn.+aaa+iiiii\fR
+to the standard output. This is an identification string for the key it has generated.
+.TP 4
+\(bu
+\fInnnn\fR
+is the key name.
+.TP 4
+\(bu
+\fIaaa\fR
+is the numeric representation of the algorithm.
+.TP 4
+\(bu
+\fIiiiii\fR
+is the key identifier (or footprint).
+.PP
+\fBdnssec\-keygen\fR
+creates two files, with names based on the printed string.
+\fIKnnnn.+aaa+iiiii.key\fR
+contains the public key, and
+\fIKnnnn.+aaa+iiiii.private\fR
+contains the private key.
+.PP
+The
+\fI.key\fR
+file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement).
+.PP
+The
+\fI.private\fR
+file contains algorithm\-specific fields. For obvious security reasons, this file does not have general read permission.
+.PP
+Both
+\fI.key\fR
+and
+\fI.private\fR
+files are generated for symmetric encryption algorithms such as HMAC\-MD5, even though the public and private key are equivalent.
+.SH "EXAMPLE"
+.PP
+To generate a 768\-bit DSA key for the domain
+\fBexample.com\fR, the following command would be issued:
+.PP
+\fBdnssec\-keygen \-a DSA \-b 768 \-n ZONE example.com\fR
+.PP
+The command would print a string of the form:
+.PP
+\fBKexample.com.+003+26160\fR
+.PP
+In this example,
+\fBdnssec\-keygen\fR
+creates the files
+\fIKexample.com.+003+26160.key\fR
+and
+\fIKexample.com.+003+26160.private\fR.
+.SH "SEE ALSO"
+.PP
+\fBdnssec\-signzone\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 2539,
+RFC 2845,
+RFC 4033.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000\-2003 Internet Software Consortium.
+.br
diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c
new file mode 100644
index 0000000..614d388
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.c
@@ -0,0 +1,540 @@
+/*
+ * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 1999-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dnssec-keygen.c,v 1.81 2008/09/25 04:02:38 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+#define MAX_RSA 4096 /* should be long enough... */
+
+const char *program = "dnssec-keygen";
+int verbose;
+
+static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 | NSEC3DSA |"
+ " NSEC3RSASHA1 | HMAC-MD5 |"
+ " HMAC-SHA1 | HMAC-SHA224 | HMAC-SHA256 |"
+ " HMAC-SHA384 | HMAC-SHA512";
+
+static isc_boolean_t
+dsa_size_ok(int size) {
+ return (ISC_TF(size >= 512 && size <= 1024 && size % 64 == 0));
+}
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s -a alg -b bits [-n type] [options] name\n\n",
+ program);
+ fprintf(stderr, "Version: %s\n", VERSION);
+ fprintf(stderr, "Required options:\n");
+ fprintf(stderr, " -a algorithm: %s\n", algs);
+ fprintf(stderr, " -b key size, in bits:\n");
+ fprintf(stderr, " RSAMD5:\t\t[512..%d]\n", MAX_RSA);
+ fprintf(stderr, " RSASHA1:\t\t[512..%d]\n", MAX_RSA);
+ fprintf(stderr, " NSEC3RSASHA1:\t\t[512..%d]\n", MAX_RSA);
+ fprintf(stderr, " DH:\t\t[128..4096]\n");
+ fprintf(stderr, " DSA:\t\t[512..1024] and divisible by 64\n");
+ fprintf(stderr, " NSEC3DSA:\t\t[512..1024] and divisible by 64\n");
+ fprintf(stderr, " HMAC-MD5:\t[1..512]\n");
+ fprintf(stderr, " HMAC-SHA1:\t[1..160]\n");
+ fprintf(stderr, " HMAC-SHA224:\t[1..224]\n");
+ fprintf(stderr, " HMAC-SHA256:\t[1..256]\n");
+ fprintf(stderr, " HMAC-SHA384:\t[1..384]\n");
+ fprintf(stderr, " HMAC-SHA512:\t[1..512]\n");
+ fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n");
+ fprintf(stderr, " (DNSKEY generation defaults to ZONE\n");
+ fprintf(stderr, " name: owner of the key\n");
+ fprintf(stderr, "Other options:\n");
+ fprintf(stderr, " -c <class> (default: IN)\n");
+ fprintf(stderr, " -d <digest bits> (0 => max, default)\n");
+ fprintf(stderr, " -e use large exponent (RSAMD5/RSASHA1 only)\n");
+ fprintf(stderr, " -f keyflag: KSK\n");
+ fprintf(stderr, " -g <generator> use specified generator "
+ "(DH only)\n");
+ fprintf(stderr, " -t <type>: "
+ "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
+ "(default: AUTHCONF)\n");
+ fprintf(stderr, " -p <protocol>: "
+ "default: 3 [dnssec]\n");
+ fprintf(stderr, " -s <strength> strength value this key signs DNS "
+ "records with (default: 0)\n");
+ fprintf(stderr, " -r <randomdev>: a file containing random data\n");
+ fprintf(stderr, " -v <verbose level>\n");
+ fprintf(stderr, " -k : generate a TYPE=KEY key\n");
+ fprintf(stderr, "Output:\n");
+ fprintf(stderr, " K<name>+<alg>+<id>.key, "
+ "K<name>+<alg>+<id>.private\n");
+
+ exit (-1);
+}
+
+int
+main(int argc, char **argv) {
+ char *algname = NULL, *nametype = NULL, *type = NULL;
+ char *classname = NULL;
+ char *endp;
+ dst_key_t *key = NULL, *oldkey;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_uint16_t flags = 0, ksk = 0;
+ dns_secalg_t alg;
+ isc_boolean_t conflict = ISC_FALSE, null_key = ISC_FALSE;
+ isc_mem_t *mctx = NULL;
+ int ch, rsa_exp = 0, generator = 0, param = 0;
+ int protocol = -1, size = -1, signatory = 0;
+ isc_result_t ret;
+ isc_textregion_t r;
+ char filename[255];
+ isc_buffer_t buf;
+ isc_log_t *log = NULL;
+ isc_entropy_t *ectx = NULL;
+ dns_rdataclass_t rdclass;
+ int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC;
+ int dbits = 0;
+
+ if (argc == 1)
+ usage();
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+
+ while ((ch = isc_commandline_parse(argc, argv,
+ "a:b:c:d:ef:g:kn:t:p:s:r:v:h")) != -1)
+ {
+ switch (ch) {
+ case 'a':
+ algname = isc_commandline_argument;
+ break;
+ case 'b':
+ size = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || size < 0)
+ fatal("-b requires a non-negative number");
+ break;
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+ case 'd':
+ dbits = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || dbits < 0)
+ fatal("-d requires a non-negative number");
+ break;
+ case 'e':
+ rsa_exp = 1;
+ break;
+ case 'f':
+ if (strcasecmp(isc_commandline_argument, "KSK") == 0)
+ ksk = DNS_KEYFLAG_KSK;
+ else
+ fatal("unknown flag '%s'",
+ isc_commandline_argument);
+ break;
+ case 'g':
+ generator = strtol(isc_commandline_argument,
+ &endp, 10);
+ if (*endp != '\0' || generator <= 0)
+ fatal("-g requires a positive number");
+ break;
+ case 'k':
+ options |= DST_TYPE_KEY;
+ break;
+ case 'n':
+ nametype = isc_commandline_argument;
+ break;
+ case 't':
+ type = isc_commandline_argument;
+ break;
+ case 'p':
+ protocol = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || protocol < 0 || protocol > 255)
+ fatal("-p must be followed by a number "
+ "[0..255]");
+ break;
+ case 's':
+ signatory = strtol(isc_commandline_argument,
+ &endp, 10);
+ if (*endp != '\0' || signatory < 0 || signatory > 15)
+ fatal("-s must be followed by a number "
+ "[0..15]");
+ break;
+ case 'r':
+ setup_entropy(mctx, isc_commandline_argument, &ectx);
+ break;
+ case 'v':
+ endp = NULL;
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0')
+ fatal("-v must be followed by a number");
+ break;
+
+ case '?':
+ if (isc_commandline_option != '?')
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ case 'h':
+ usage();
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n",
+ program, isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ ret = dst_lib_init(mctx, ectx,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ if (ret != ISC_R_SUCCESS)
+ fatal("could not initialize dst");
+
+ setup_logging(verbose, mctx, &log);
+
+ if (argc < isc_commandline_index + 1)
+ fatal("the key name was not specified");
+ if (argc > isc_commandline_index + 1)
+ fatal("extraneous arguments");
+
+ if (algname == NULL)
+ fatal("no algorithm was specified");
+ if (strcasecmp(algname, "RSA") == 0) {
+ fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n"
+ "If you still wish to use RSA (RSAMD5) please "
+ "specify \"-a RSAMD5\"\n");
+ return (1);
+ } else if (strcasecmp(algname, "HMAC-MD5") == 0) {
+ options |= DST_TYPE_KEY;
+ alg = DST_ALG_HMACMD5;
+ } else if (strcasecmp(algname, "HMAC-SHA1") == 0) {
+ options |= DST_TYPE_KEY;
+ alg = DST_ALG_HMACSHA1;
+ } else if (strcasecmp(algname, "HMAC-SHA224") == 0) {
+ options |= DST_TYPE_KEY;
+ alg = DST_ALG_HMACSHA224;
+ } else if (strcasecmp(algname, "HMAC-SHA256") == 0) {
+ options |= DST_TYPE_KEY;
+ alg = DST_ALG_HMACSHA256;
+ } else if (strcasecmp(algname, "HMAC-SHA384") == 0) {
+ options |= DST_TYPE_KEY;
+ alg = DST_ALG_HMACSHA384;
+ } else if (strcasecmp(algname, "HMAC-SHA512") == 0) {
+ options |= DST_TYPE_KEY;
+ alg = DST_ALG_HMACSHA512;
+ } else {
+ r.base = algname;
+ r.length = strlen(algname);
+ ret = dns_secalg_fromtext(&alg, &r);
+ if (ret != ISC_R_SUCCESS)
+ fatal("unknown algorithm %s", algname);
+ if (alg == DST_ALG_DH)
+ options |= DST_TYPE_KEY;
+ }
+
+ if (type != NULL && (options & DST_TYPE_KEY) != 0) {
+ if (strcasecmp(type, "NOAUTH") == 0)
+ flags |= DNS_KEYTYPE_NOAUTH;
+ else if (strcasecmp(type, "NOCONF") == 0)
+ flags |= DNS_KEYTYPE_NOCONF;
+ else if (strcasecmp(type, "NOAUTHCONF") == 0) {
+ flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF);
+ if (size < 0)
+ size = 0;
+ }
+ else if (strcasecmp(type, "AUTHCONF") == 0)
+ /* nothing */;
+ else
+ fatal("invalid type %s", type);
+ }
+
+ if (size < 0)
+ fatal("key size not specified (-b option)");
+
+ switch (alg) {
+ case DNS_KEYALG_RSAMD5:
+ case DNS_KEYALG_RSASHA1:
+ case DNS_KEYALG_NSEC3RSASHA1:
+ if (size != 0 && (size < 512 || size > MAX_RSA))
+ fatal("RSA key size %d out of range", size);
+ break;
+ case DNS_KEYALG_DH:
+ if (size != 0 && (size < 128 || size > 4096))
+ fatal("DH key size %d out of range", size);
+ break;
+ case DNS_KEYALG_DSA:
+ case DNS_KEYALG_NSEC3DSA:
+ if (size != 0 && !dsa_size_ok(size))
+ fatal("invalid DSS key size: %d", size);
+ break;
+ case DST_ALG_HMACMD5:
+ if (size < 1 || size > 512)
+ fatal("HMAC-MD5 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 80 || dbits > 128))
+ fatal("HMAC-MD5 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-MD5 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA1:
+ if (size < 1 || size > 160)
+ fatal("HMAC-SHA1 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 80 || dbits > 160))
+ fatal("HMAC-SHA1 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA1 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA224:
+ if (size < 1 || size > 224)
+ fatal("HMAC-SHA224 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 112 || dbits > 224))
+ fatal("HMAC-SHA224 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA224 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA256:
+ if (size < 1 || size > 256)
+ fatal("HMAC-SHA256 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 128 || dbits > 256))
+ fatal("HMAC-SHA256 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA256 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA384:
+ if (size < 1 || size > 384)
+ fatal("HMAC-384 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 192 || dbits > 384))
+ fatal("HMAC-SHA384 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA384 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA512:
+ if (size < 1 || size > 512)
+ fatal("HMAC-SHA512 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 256 || dbits > 512))
+ fatal("HMAC-SHA512 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA512 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ }
+
+ if (!(alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_RSASHA1 ||
+ alg == DNS_KEYALG_NSEC3RSASHA1) && rsa_exp != 0)
+ fatal("specified RSA exponent for a non-RSA key");
+
+ if (alg != DNS_KEYALG_DH && generator != 0)
+ fatal("specified DH generator for a non-DH key");
+
+ if (nametype == NULL) {
+ if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */
+ fatal("no nametype specified");
+ flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */
+ } else if (strcasecmp(nametype, "zone") == 0)
+ flags |= DNS_KEYOWNER_ZONE;
+ else if ((options & DST_TYPE_KEY) != 0) { /* KEY / HMAC */
+ if (strcasecmp(nametype, "host") == 0 ||
+ strcasecmp(nametype, "entity") == 0)
+ flags |= DNS_KEYOWNER_ENTITY;
+ else if (strcasecmp(nametype, "user") == 0)
+ flags |= DNS_KEYOWNER_USER;
+ else
+ fatal("invalid KEY nametype %s", nametype);
+ } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */
+ fatal("invalid DNSKEY nametype %s", nametype);
+
+ rdclass = strtoclass(classname);
+
+ if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */
+ flags |= signatory;
+ else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */
+ flags |= ksk;
+
+ if (protocol == -1)
+ protocol = DNS_KEYPROTO_DNSSEC;
+ else if ((options & DST_TYPE_KEY) == 0 &&
+ protocol != DNS_KEYPROTO_DNSSEC)
+ fatal("invalid DNSKEY protocol: %d", protocol);
+
+ if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
+ if (size > 0)
+ fatal("specified null key with non-zero size");
+ if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0)
+ fatal("specified null key with signing authority");
+ }
+
+ if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
+ (alg == DNS_KEYALG_DH || alg == DST_ALG_HMACMD5 ||
+ alg == DST_ALG_HMACSHA1 || alg == DST_ALG_HMACSHA224 ||
+ alg == DST_ALG_HMACSHA256 || alg == DST_ALG_HMACSHA384 ||
+ alg == DST_ALG_HMACSHA512))
+ fatal("a key with algorithm '%s' cannot be a zone key",
+ algname);
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ isc_buffer_init(&buf, argv[isc_commandline_index],
+ strlen(argv[isc_commandline_index]));
+ isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
+ ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL);
+ if (ret != ISC_R_SUCCESS)
+ fatal("invalid key name %s: %s", argv[isc_commandline_index],
+ isc_result_totext(ret));
+
+ switch(alg) {
+ case DNS_KEYALG_RSAMD5:
+ case DNS_KEYALG_RSASHA1:
+ param = rsa_exp;
+ break;
+ case DNS_KEYALG_DH:
+ param = generator;
+ break;
+ case DNS_KEYALG_DSA:
+ case DST_ALG_HMACMD5:
+ case DST_ALG_HMACSHA1:
+ case DST_ALG_HMACSHA224:
+ case DST_ALG_HMACSHA256:
+ case DST_ALG_HMACSHA384:
+ case DST_ALG_HMACSHA512:
+ param = 0;
+ break;
+ }
+
+ if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
+ null_key = ISC_TRUE;
+
+ isc_buffer_init(&buf, filename, sizeof(filename) - 1);
+
+ do {
+ conflict = ISC_FALSE;
+ oldkey = NULL;
+
+ /* generate the key */
+ ret = dst_key_generate(name, alg, size, param, flags, protocol,
+ rdclass, mctx, &key);
+ isc_entropy_stopcallbacksources(ectx);
+
+ if (ret != ISC_R_SUCCESS) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char algstr[ALG_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ alg_format(alg, algstr, sizeof(algstr));
+ fatal("failed to generate key %s/%s: %s\n",
+ namestr, algstr, isc_result_totext(ret));
+ exit(-1);
+ }
+
+ dst_key_setbits(key, dbits);
+
+ /*
+ * Try to read a key with the same name, alg and id from disk.
+ * If there is one we must continue generating a new one
+ * unless we were asked to generate a null key, in which
+ * case we return failure.
+ */
+ ret = dst_key_fromfile(name, dst_key_id(key), alg,
+ DST_TYPE_PRIVATE, NULL, mctx, &oldkey);
+ /* do not overwrite an existing key */
+ if (ret == ISC_R_SUCCESS) {
+ dst_key_free(&oldkey);
+ conflict = ISC_TRUE;
+ if (null_key)
+ break;
+ }
+ if (conflict == ISC_TRUE) {
+ if (verbose > 0) {
+ isc_buffer_clear(&buf);
+ ret = dst_key_buildfilename(key, 0, NULL, &buf);
+ fprintf(stderr,
+ "%s: %s already exists, "
+ "generating a new key\n",
+ program, filename);
+ }
+ dst_key_free(&key);
+ }
+
+ } while (conflict == ISC_TRUE);
+
+ if (conflict)
+ fatal("cannot generate a null key when a key with id 0 "
+ "already exists");
+
+ ret = dst_key_tofile(key, options, NULL);
+ if (ret != ISC_R_SUCCESS) {
+ char keystr[KEY_FORMATSIZE];
+ key_format(key, keystr, sizeof(keystr));
+ fatal("failed to write key %s: %s\n", keystr,
+ isc_result_totext(ret));
+ }
+
+ isc_buffer_clear(&buf);
+ ret = dst_key_buildfilename(key, 0, NULL, &buf);
+ printf("%s\n", filename);
+ dst_key_free(&key);
+
+ cleanup_logging(&log);
+ cleanup_entropy(&ectx);
+ dst_lib_destroy();
+ dns_name_destroy();
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-keygen.docbook b/bin/dnssec/dnssec-keygen.docbook
new file mode 100644
index 0000000..c267a1b
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.docbook
@@ -0,0 +1,360 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<!-- $Id: dnssec-keygen.docbook,v 1.22 2008/10/14 14:32:50 jreed Exp $ -->
+<refentry id="man.dnssec-keygen">
+ <refentryinfo>
+ <date>June 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-keygen</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-keygen</application></refname>
+ <refpurpose>DNSSEC key generation tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dnssec-keygen</command>
+ <arg choice="req">-a <replaceable class="parameter">algorithm</replaceable></arg>
+ <arg choice="req">-b <replaceable class="parameter">keysize</replaceable></arg>
+ <arg choice="req">-n <replaceable class="parameter">nametype</replaceable></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-e</option></arg>
+ <arg><option>-f <replaceable class="parameter">flag</replaceable></option></arg>
+ <arg><option>-g <replaceable class="parameter">generator</replaceable></option></arg>
+ <arg><option>-h</option></arg>
+ <arg><option>-k</option></arg>
+ <arg><option>-p <replaceable class="parameter">protocol</replaceable></option></arg>
+ <arg><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg>
+ <arg><option>-s <replaceable class="parameter">strength</replaceable></option></arg>
+ <arg><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="req">name</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>dnssec-keygen</command>
+ generates keys for DNSSEC (Secure DNS), as defined in RFC 2535
+ and RFC 4034. It can also generate keys for use with
+ TSIG (Transaction Signatures), as defined in RFC 2845.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-a <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+ Selects the cryptographic algorithm. The value of
+ <option>algorithm</option> must be one of RSAMD5 (RSA) or RSASHA1,
+ DSA, NSEC3RSASHA1, NSEC3DSA, DH (Diffie Hellman), or HMAC-MD5.
+ These values are case insensitive.
+ </para>
+ <para>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is
+ mandatory.
+ </para>
+ <para>
+ Note 2: HMAC-MD5 and DH automatically set the -k flag.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-b <replaceable class="parameter">keysize</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the number of bits in the key. The choice of key
+ size depends on the algorithm used. RSAMD5 / RSASHA1 keys must be
+ between
+ 512 and 2048 bits. Diffie Hellman keys must be between
+ 128 and 4096 bits. DSA keys must be between 512 and 1024
+ bits and an exact multiple of 64. HMAC-MD5 keys must be
+ between 1 and 512 bits.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">nametype</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the owner type of the key. The value of
+ <option>nametype</option> must either be ZONE (for a DNSSEC
+ zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with
+ a host (KEY)),
+ USER (for a key associated with a user(KEY)) or OTHER (DNSKEY).
+ These values are case insensitive. Defaults to ZONE for DNSKEY
+ generation.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-e</term>
+ <listitem>
+ <para>
+ If generating an RSAMD5/RSASHA1 key, use a large exponent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">flag</replaceable></term>
+ <listitem>
+ <para>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flag is KSK (Key Signing Key) DNSKEY.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-g <replaceable class="parameter">generator</replaceable></term>
+ <listitem>
+ <para>
+ If generating a Diffie Hellman key, use this generator.
+ Allowed values are 2 and 5. If no generator
+ is specified, a known prime from RFC 2539 will be used
+ if possible; otherwise the default is 2.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>dnssec-keygen</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k</term>
+ <listitem>
+ <para>
+ Generate KEY records rather than DNSKEY records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">protocol</replaceable></term>
+ <listitem>
+ <para>
+ Sets the protocol value for the generated key. The protocol
+ is a number between 0 and 255. The default is 3 (DNSSEC).
+ Other possible values for this argument are listed in
+ RFC 2535 and its successors.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r <replaceable class="parameter">randomdev</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the source of randomness. If the operating
+ system does not provide a <filename>/dev/random</filename>
+ or equivalent device, the default source of randomness
+ is keyboard input. <filename>randomdev</filename>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <filename>keyboard</filename> indicates that keyboard
+ input should be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">strength</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the strength value of the key. The strength is
+ a number between 0 and 15, and currently has no defined
+ purpose in DNSSEC.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ Indicates the use of the key. <option>type</option> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>GENERATED KEYS</title>
+ <para>
+ When <command>dnssec-keygen</command> completes
+ successfully,
+ it prints a string of the form <filename>Knnnn.+aaa+iiiii</filename>
+ to the standard output. This is an identification string for
+ the key it has generated.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><filename>nnnn</filename> is the key name.
+ </para>
+ </listitem>
+ <listitem>
+ <para><filename>aaa</filename> is the numeric representation
+ of the
+ algorithm.
+ </para>
+ </listitem>
+ <listitem>
+ <para><filename>iiiii</filename> is the key identifier (or
+ footprint).
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para><command>dnssec-keygen</command>
+ creates two files, with names based
+ on the printed string. <filename>Knnnn.+aaa+iiiii.key</filename>
+ contains the public key, and
+ <filename>Knnnn.+aaa+iiiii.private</filename> contains the
+ private
+ key.
+ </para>
+ <para>
+ The <filename>.key</filename> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </para>
+ <para>
+ The <filename>.private</filename> file contains
+ algorithm-specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </para>
+ <para>
+ Both <filename>.key</filename> and <filename>.private</filename>
+ files are generated for symmetric encryption algorithms such as
+ HMAC-MD5, even though the public and private key are equivalent.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>EXAMPLE</title>
+ <para>
+ To generate a 768-bit DSA key for the domain
+ <userinput>example.com</userinput>, the following command would be
+ issued:
+ </para>
+ <para><userinput>dnssec-keygen -a DSA -b 768 -n ZONE example.com</userinput>
+ </para>
+ <para>
+ The command would print a string of the form:
+ </para>
+ <para><userinput>Kexample.com.+003+26160</userinput>
+ </para>
+ <para>
+ In this example, <command>dnssec-keygen</command> creates
+ the files <filename>Kexample.com.+003+26160.key</filename>
+ and
+ <filename>Kexample.com.+003+26160.private</filename>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 2539</citetitle>,
+ <citetitle>RFC 2845</citetitle>,
+ <citetitle>RFC 4033</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dnssec/dnssec-keygen.html b/bin/dnssec/dnssec-keygen.html
new file mode 100644
index 0000000..696ef88
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.html
@@ -0,0 +1,232 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+<!-- $Id: dnssec-keygen.html,v 1.32 2008/10/15 01:11:35 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-keygen</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.dnssec-keygen"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-keygen</span> &#8212; DNSSEC key generation tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-keygen</code> {-a <em class="replaceable"><code>algorithm</code></em>} {-b <em class="replaceable"><code>keysize</code></em>} {-n <em class="replaceable"><code>nametype</code></em>} [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-e</code>] [<code class="option">-f <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-g <em class="replaceable"><code>generator</code></em></code>] [<code class="option">-h</code>] [<code class="option">-k</code>] [<code class="option">-p <em class="replaceable"><code>protocol</code></em></code>] [<code class="option">-r <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-s <em class="replaceable"><code>strength</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] {name}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543477"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-keygen</strong></span>
+ generates keys for DNSSEC (Secure DNS), as defined in RFC 2535
+ and RFC 4034. It can also generate keys for use with
+ TSIG (Transaction Signatures), as defined in RFC 2845.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543489"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd>
+<p>
+ Selects the cryptographic algorithm. The value of
+ <code class="option">algorithm</code> must be one of RSAMD5 (RSA) or RSASHA1,
+ DSA, NSEC3RSASHA1, NSEC3DSA, DH (Diffie Hellman), or HMAC-MD5.
+ These values are case insensitive.
+ </p>
+<p>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is
+ mandatory.
+ </p>
+<p>
+ Note 2: HMAC-MD5 and DH automatically set the -k flag.
+ </p>
+</dd>
+<dt><span class="term">-b <em class="replaceable"><code>keysize</code></em></span></dt>
+<dd><p>
+ Specifies the number of bits in the key. The choice of key
+ size depends on the algorithm used. RSAMD5 / RSASHA1 keys must be
+ between
+ 512 and 2048 bits. Diffie Hellman keys must be between
+ 128 and 4096 bits. DSA keys must be between 512 and 1024
+ bits and an exact multiple of 64. HMAC-MD5 keys must be
+ between 1 and 512 bits.
+ </p></dd>
+<dt><span class="term">-n <em class="replaceable"><code>nametype</code></em></span></dt>
+<dd><p>
+ Specifies the owner type of the key. The value of
+ <code class="option">nametype</code> must either be ZONE (for a DNSSEC
+ zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with
+ a host (KEY)),
+ USER (for a key associated with a user(KEY)) or OTHER (DNSKEY).
+ These values are case insensitive. Defaults to ZONE for DNSKEY
+ generation.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </p></dd>
+<dt><span class="term">-e</span></dt>
+<dd><p>
+ If generating an RSAMD5/RSASHA1 key, use a large exponent.
+ </p></dd>
+<dt><span class="term">-f <em class="replaceable"><code>flag</code></em></span></dt>
+<dd><p>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flag is KSK (Key Signing Key) DNSKEY.
+ </p></dd>
+<dt><span class="term">-g <em class="replaceable"><code>generator</code></em></span></dt>
+<dd><p>
+ If generating a Diffie Hellman key, use this generator.
+ Allowed values are 2 and 5. If no generator
+ is specified, a known prime from RFC 2539 will be used
+ if possible; otherwise the default is 2.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Prints a short summary of the options and arguments to
+ <span><strong class="command">dnssec-keygen</strong></span>.
+ </p></dd>
+<dt><span class="term">-k</span></dt>
+<dd><p>
+ Generate KEY records rather than DNSKEY records.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>protocol</code></em></span></dt>
+<dd><p>
+ Sets the protocol value for the generated key. The protocol
+ is a number between 0 and 255. The default is 3 (DNSSEC).
+ Other possible values for this argument are listed in
+ RFC 2535 and its successors.
+ </p></dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomdev</code></em></span></dt>
+<dd><p>
+ Specifies the source of randomness. If the operating
+ system does not provide a <code class="filename">/dev/random</code>
+ or equivalent device, the default source of randomness
+ is keyboard input. <code class="filename">randomdev</code>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard
+ input should be used.
+ </p></dd>
+<dt><span class="term">-s <em class="replaceable"><code>strength</code></em></span></dt>
+<dd><p>
+ Specifies the strength value of the key. The strength is
+ a number between 0 and 15, and currently has no defined
+ purpose in DNSSEC.
+ </p></dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd><p>
+ Indicates the use of the key. <code class="option">type</code> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </p></dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543824"></a><h2>GENERATED KEYS</h2>
+<p>
+ When <span><strong class="command">dnssec-keygen</strong></span> completes
+ successfully,
+ it prints a string of the form <code class="filename">Knnnn.+aaa+iiiii</code>
+ to the standard output. This is an identification string for
+ the key it has generated.
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li><p><code class="filename">nnnn</code> is the key name.
+ </p></li>
+<li><p><code class="filename">aaa</code> is the numeric representation
+ of the
+ algorithm.
+ </p></li>
+<li><p><code class="filename">iiiii</code> is the key identifier (or
+ footprint).
+ </p></li>
+</ul></div>
+<p><span><strong class="command">dnssec-keygen</strong></span>
+ creates two files, with names based
+ on the printed string. <code class="filename">Knnnn.+aaa+iiiii.key</code>
+ contains the public key, and
+ <code class="filename">Knnnn.+aaa+iiiii.private</code> contains the
+ private
+ key.
+ </p>
+<p>
+ The <code class="filename">.key</code> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </p>
+<p>
+ The <code class="filename">.private</code> file contains
+ algorithm-specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </p>
+<p>
+ Both <code class="filename">.key</code> and <code class="filename">.private</code>
+ files are generated for symmetric encryption algorithms such as
+ HMAC-MD5, even though the public and private key are equivalent.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543906"></a><h2>EXAMPLE</h2>
+<p>
+ To generate a 768-bit DSA key for the domain
+ <strong class="userinput"><code>example.com</code></strong>, the following command would be
+ issued:
+ </p>
+<p><strong class="userinput"><code>dnssec-keygen -a DSA -b 768 -n ZONE example.com</code></strong>
+ </p>
+<p>
+ The command would print a string of the form:
+ </p>
+<p><strong class="userinput"><code>Kexample.com.+003+26160</code></strong>
+ </p>
+<p>
+ In this example, <span><strong class="command">dnssec-keygen</strong></span> creates
+ the files <code class="filename">Kexample.com.+003+26160.key</code>
+ and
+ <code class="filename">Kexample.com.+003+26160.private</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543949"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 2539</em>,
+ <em class="citetitle">RFC 2845</em>,
+ <em class="citetitle">RFC 4033</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544049"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-signzone.8 b/bin/dnssec/dnssec-signzone.8
new file mode 100644
index 0000000..ca0ed36
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.8
@@ -0,0 +1,287 @@
+.\" Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000-2003 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $Id: dnssec-signzone.8,v 1.47 2008/10/15 01:11:35 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: dnssec\-signzone
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: June 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "DNSSEC\-SIGNZONE" "8" "June 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+dnssec\-signzone \- DNSSEC zone signing tool
+.SH "SYNOPSIS"
+.HP 16
+\fBdnssec\-signzone\fR [\fB\-a\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIdirectory\fR\fR] [\fB\-e\ \fR\fB\fIend\-time\fR\fR] [\fB\-f\ \fR\fB\fIoutput\-file\fR\fR] [\fB\-g\fR] [\fB\-h\fR] [\fB\-k\ \fR\fB\fIkey\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-I\ \fR\fB\fIinput\-format\fR\fR] [\fB\-j\ \fR\fB\fIjitter\fR\fR] [\fB\-N\ \fR\fB\fIsoa\-serial\-format\fR\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-O\ \fR\fB\fIoutput\-format\fR\fR] [\fB\-p\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-s\ \fR\fB\fIstart\-time\fR\fR] [\fB\-t\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-z\fR] [\fB\-3\ \fR\fB\fIsalt\fR\fR] [\fB\-H\ \fR\fB\fIiterations\fR\fR] [\fB\-A\fR] {zonefile} [key...]
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-signzone\fR
+signs a zone. It generates NSEC and RRSIG records and produces a signed version of the zone. The security status of delegations from the signed zone (that is, whether the child zones are secure or not) is determined by the presence or absence of a
+\fIkeyset\fR
+file for each child zone.
+.SH "OPTIONS"
+.PP
+\-a
+.RS 4
+Verify all generated signatures.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Specifies the DNS class of the zone.
+.RE
+.PP
+\-k \fIkey\fR
+.RS 4
+Treat specified key as a key signing key ignoring any key flags. This option may be specified multiple times.
+.RE
+.PP
+\-l \fIdomain\fR
+.RS 4
+Generate a DLV set in addition to the key (DNSKEY) and DS sets. The domain is appended to the name of the records.
+.RE
+.PP
+\-d \fIdirectory\fR
+.RS 4
+Look for
+\fIkeyset\fR
+files in
+\fBdirectory\fR
+as the directory
+.RE
+.PP
+\-g
+.RS 4
+Generate DS records for child zones from keyset files. Existing DS records will be removed.
+.RE
+.PP
+\-s \fIstart\-time\fR
+.RS 4
+Specify the date and time when the generated RRSIG records become valid. This can be either an absolute or relative time. An absolute start time is indicated by a number in YYYYMMDDHHMMSS notation; 20000530144500 denotes 14:45:00 UTC on May 30th, 2000. A relative start time is indicated by +N, which is N seconds from the current time. If no
+\fBstart\-time\fR
+is specified, the current time minus 1 hour (to allow for clock skew) is used.
+.RE
+.PP
+\-e \fIend\-time\fR
+.RS 4
+Specify the date and time when the generated RRSIG records expire. As with
+\fBstart\-time\fR, an absolute time is indicated in YYYYMMDDHHMMSS notation. A time relative to the start time is indicated with +N, which is N seconds from the start time. A time relative to the current time is indicated with now+N. If no
+\fBend\-time\fR
+is specified, 30 days from the start time is used as a default.
+.RE
+.PP
+\-f \fIoutput\-file\fR
+.RS 4
+The name of the output file containing the signed zone. The default is to append
+\fI.signed\fR
+to the input filename.
+.RE
+.PP
+\-h
+.RS 4
+Prints a short summary of the options and arguments to
+\fBdnssec\-signzone\fR.
+.RE
+.PP
+\-i \fIinterval\fR
+.RS 4
+When a previously\-signed zone is passed as input, records may be resigned. The
+\fBinterval\fR
+option specifies the cycle interval as an offset from the current time (in seconds). If a RRSIG record expires after the cycle interval, it is retained. Otherwise, it is considered to be expiring soon, and it will be replaced.
+.sp
+The default cycle interval is one quarter of the difference between the signature end and start times. So if neither
+\fBend\-time\fR
+or
+\fBstart\-time\fR
+are specified,
+\fBdnssec\-signzone\fR
+generates signatures that are valid for 30 days, with a cycle interval of 7.5 days. Therefore, if any existing RRSIG records are due to expire in less than 7.5 days, they would be replaced.
+.RE
+.PP
+\-I \fIinput\-format\fR
+.RS 4
+The format of the input zone file. Possible formats are
+\fB"text"\fR
+(default) and
+\fB"raw"\fR. This option is primarily intended to be used for dynamic signed zones so that the dumped zone file in a non\-text format containing updates can be signed directly. The use of this option does not make much sense for non\-dynamic zones.
+.RE
+.PP
+\-j \fIjitter\fR
+.RS 4
+When signing a zone with a fixed signature lifetime, all RRSIG records issued at the time of signing expires simultaneously. If the zone is incrementally signed, i.e. a previously\-signed zone is passed as input to the signer, all expired signatures have to be regenerated at about the same time. The
+\fBjitter\fR
+option specifies a jitter window that will be used to randomize the signature expire time, thus spreading incremental signature regeneration over time.
+.sp
+Signature lifetime jitter also to some extent benefits validators and servers by spreading out cache expiration, i.e. if large numbers of RRSIGs don't expire at the same time from all caches there will be less congestion than if all validators need to refetch at mostly the same time.
+.RE
+.PP
+\-n \fIncpus\fR
+.RS 4
+Specifies the number of threads to use. By default, one thread is started for each detected CPU.
+.RE
+.PP
+\-N \fIsoa\-serial\-format\fR
+.RS 4
+The SOA serial number format of the signed zone. Possible formats are
+\fB"keep"\fR
+(default),
+\fB"increment"\fR
+and
+\fB"unixtime"\fR.
+.RS 4
+.PP
+\fB"keep"\fR
+.RS 4
+Do not modify the SOA serial number.
+.RE
+.PP
+\fB"increment"\fR
+.RS 4
+Increment the SOA serial number using RFC 1982 arithmetics.
+.RE
+.PP
+\fB"unixtime"\fR
+.RS 4
+Set the SOA serial number to the number of seconds since epoch.
+.RE
+.RE
+.RE
+.PP
+\-o \fIorigin\fR
+.RS 4
+The zone origin. If not specified, the name of the zone file is assumed to be the origin.
+.RE
+.PP
+\-O \fIoutput\-format\fR
+.RS 4
+The format of the output file containing the signed zone. Possible formats are
+\fB"text"\fR
+(default) and
+\fB"raw"\fR.
+.RE
+.PP
+\-p
+.RS 4
+Use pseudo\-random data when signing the zone. This is faster, but less secure, than using real random data. This option may be useful when signing large zones or when the entropy source is limited.
+.RE
+.PP
+\-r \fIrandomdev\fR
+.RS 4
+Specifies the source of randomness. If the operating system does not provide a
+\fI/dev/random\fR
+or equivalent device, the default source of randomness is keyboard input.
+\fIrandomdev\fR
+specifies the name of a character device or file containing random data to be used instead of the default. The special value
+\fIkeyboard\fR
+indicates that keyboard input should be used.
+.RE
+.PP
+\-t
+.RS 4
+Print statistics at completion.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level.
+.RE
+.PP
+\-z
+.RS 4
+Ignore KSK flag on key when determining what to sign.
+.RE
+.PP
+\-3 \fIsalt\fR
+.RS 4
+Generate a NSEC3 chain with the given hex encoded salt. A dash (\fIsalt\fR) can be used to indicate that no salt is to be used when generating the NSEC3 chain.
+.RE
+.PP
+\-H \fIiterations\fR
+.RS 4
+When generating a NSEC3 chain use this many interations. The default is 100.
+.RE
+.PP
+\-A
+.RS 4
+When generating a NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations.
+.RE
+.PP
+zonefile
+.RS 4
+The file containing the zone to be signed.
+.RE
+.PP
+key
+.RS 4
+Specify which keys should be used to sign the zone. If no keys are specified, then the zone will be examined for DNSKEY records at the zone apex. If these are found and there are matching private keys, in the current directory, then these will be used for signing.
+.RE
+.SH "EXAMPLE"
+.PP
+The following command signs the
+\fBexample.com\fR
+zone with the DSA key generated by
+\fBdnssec\-keygen\fR
+(Kexample.com.+003+17247). The zone's keys must be in the master file (\fIdb.example.com\fR). This invocation looks for
+\fIkeyset\fR
+files, in the current directory, so that DS records can be generated from them (\fB\-g\fR).
+.sp
+.RS 4
+.nf
+% dnssec\-signzone \-g \-o example.com db.example.com \\
+Kexample.com.+003+17247
+db.example.com.signed
+%
+.fi
+.RE
+.PP
+In the above example,
+\fBdnssec\-signzone\fR
+creates the file
+\fIdb.example.com.signed\fR. This file should be referenced in a zone statement in a
+\fInamed.conf\fR
+file.
+.PP
+This example re\-signs a previously signed zone with default parameters. The private keys are assumed to be in the current directory.
+.sp
+.RS 4
+.nf
+% cp db.example.com.signed db.example.com
+% dnssec\-signzone \-o example.com db.example.com
+db.example.com.signed
+%
+.fi
+.RE
+.SH "SEE ALSO"
+.PP
+\fBdnssec\-keygen\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 4033.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
+.SH "COPYRIGHT"
+Copyright \(co 2004\-2008 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000\-2003 Internet Software Consortium.
+.br
diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c
new file mode 100644
index 0000000..f446ef3
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.c
@@ -0,0 +1,3031 @@
+/*
+ * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 1999-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dnssec-signzone.c,v 1.209 2008/11/14 22:53:46 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <time.h>
+
+#include <isc/app.h>
+#include <isc/base32.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/event.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/hex.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/os.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/serial.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/diff.h>
+#include <dns/dnssec.h>
+#include <dns/ds.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/masterdump.h>
+#include <dns/nsec.h>
+#include <dns/nsec3.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/soa.h>
+#include <dns/time.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-signzone";
+int verbose;
+
+typedef struct hashlist hashlist_t;
+
+static int nsec_datatype = dns_rdatatype_nsec;
+
+#define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
+#define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
+
+#define BUFSIZE 2048
+#define MAXDSKEYS 8
+
+typedef struct signer_key_struct signer_key_t;
+
+struct signer_key_struct {
+ dst_key_t *key;
+ isc_boolean_t issigningkey;
+ isc_boolean_t isdsk;
+ isc_boolean_t isksk;
+ unsigned int position;
+ ISC_LINK(signer_key_t) link;
+};
+
+#define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
+#define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
+#define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
+
+#define SOA_SERIAL_KEEP 0
+#define SOA_SERIAL_INCREMENT 1
+#define SOA_SERIAL_UNIXTIME 2
+
+typedef struct signer_event sevent_t;
+struct signer_event {
+ ISC_EVENT_COMMON(sevent_t);
+ dns_fixedname_t *fname;
+ dns_dbnode_t *node;
+};
+
+static ISC_LIST(signer_key_t) keylist;
+static unsigned int keycount = 0;
+static isc_stdtime_t starttime = 0, endtime = 0, now;
+static int cycle = -1;
+static int jitter = 0;
+static isc_boolean_t tryverify = ISC_FALSE;
+static isc_boolean_t printstats = ISC_FALSE;
+static isc_mem_t *mctx = NULL;
+static isc_entropy_t *ectx = NULL;
+static dns_ttl_t zonettl;
+static FILE *fp;
+static char *tempfile = NULL;
+static const dns_master_style_t *masterstyle;
+static dns_masterformat_t inputformat = dns_masterformat_text;
+static dns_masterformat_t outputformat = dns_masterformat_text;
+static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
+static unsigned int nverified = 0, nverifyfailed = 0;
+static const char *directory;
+static isc_mutex_t namelock, statslock;
+static isc_taskmgr_t *taskmgr = NULL;
+static dns_db_t *gdb; /* The database */
+static dns_dbversion_t *gversion; /* The database version */
+static dns_dbiterator_t *gdbiter; /* The database iterator */
+static dns_rdataclass_t gclass; /* The class */
+static dns_name_t *gorigin; /* The database origin */
+static int nsec3flags = 0;
+static isc_task_t *master = NULL;
+static unsigned int ntasks = 0;
+static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
+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;
+static dns_name_t *dlv = NULL;
+static dns_fixedname_t dlv_fixed;
+static dns_master_style_t *dsstyle = NULL;
+static unsigned int serialformat = SOA_SERIAL_KEEP;
+static unsigned int hash_length = 0;
+static isc_boolean_t unknownalg = ISC_FALSE;
+
+#define INCSTAT(counter) \
+ if (printstats) { \
+ LOCK(&statslock); \
+ counter++; \
+ UNLOCK(&statslock); \
+ }
+
+static void
+sign(isc_task_t *task, isc_event_t *event);
+
+static isc_boolean_t
+nsec3only(dns_dbnode_t *node);
+
+static void
+dumpnode(dns_name_t *name, dns_dbnode_t *node) {
+ isc_result_t result;
+
+ if (outputformat != dns_masterformat_text)
+ return;
+ result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name,
+ masterstyle, fp);
+ check_result(result, "dns_master_dumpnodetostream");
+}
+
+static signer_key_t *
+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;
+ 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);
+}
+
+static void
+signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdata_t *rdata,
+ dst_key_t *key, isc_buffer_t *b)
+{
+ isc_result_t result;
+ isc_stdtime_t jendtime;
+
+ jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime;
+ result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
+ mctx, b, rdata);
+ isc_entropy_stopcallbacksources(ectx);
+ if (result != ISC_R_SUCCESS) {
+ char keystr[KEY_FORMATSIZE];
+ key_format(key, keystr, sizeof(keystr));
+ fatal("dnskey '%s' failed to sign data: %s",
+ keystr, isc_result_totext(result));
+ }
+ INCSTAT(nsigned);
+
+ if (tryverify) {
+ result = dns_dnssec_verify(name, rdataset, key,
+ ISC_TRUE, mctx, rdata);
+ if (result == ISC_R_SUCCESS) {
+ vbprintf(3, "\tsignature verified\n");
+ INCSTAT(nverified);
+ } else {
+ vbprintf(3, "\tsignature failed to verify\n");
+ INCSTAT(nverifyfailed);
+ }
+ }
+}
+
+static inline isc_boolean_t
+issigningkey(signer_key_t *key) {
+ return (key->issigningkey);
+}
+
+static inline isc_boolean_t
+iszonekey(signer_key_t *key) {
+ return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
+ dst_key_iszonekey(key->key)));
+}
+
+/*%
+ * Finds the key that generated a RRSIG, if possible. First look at the keys
+ * that we've loaded already, and then see if there's a key on disk.
+ */
+static signer_key_t *
+keythatsigned(dns_rdata_rrsig_t *rrsig) {
+ isc_result_t result;
+ dst_key_t *pubkey = NULL, *privkey = NULL;
+ signer_key_t *key;
+
+ key = ISC_LIST_HEAD(keylist);
+ while (key != NULL) {
+ if (rrsig->keyid == dst_key_id(key->key) &&
+ rrsig->algorithm == dst_key_alg(key->key) &&
+ dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
+ return key;
+ key = ISC_LIST_NEXT(key, link);
+ }
+
+ result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
+ rrsig->algorithm, DST_TYPE_PUBLIC,
+ NULL, mctx, &pubkey);
+ if (result != ISC_R_SUCCESS)
+ return (NULL);
+
+ result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
+ rrsig->algorithm,
+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
+ NULL, mctx, &privkey);
+ if (result == ISC_R_SUCCESS) {
+ dst_key_free(&pubkey);
+ key = newkeystruct(privkey, ISC_FALSE);
+ } else
+ key = newkeystruct(pubkey, ISC_FALSE);
+ ISC_LIST_APPEND(keylist, key, link);
+ return (key);
+}
+
+/*%
+ * Check to see if we expect to find a key at this name. If we see a RRSIG
+ * and can't find the signing key that we expect to find, we drop the rrsig.
+ * I'm not sure if this is completely correct, but it seems to work.
+ */
+static isc_boolean_t
+expecttofindkey(dns_name_t *name) {
+ unsigned int options = DNS_DBFIND_NOWILD;
+ dns_fixedname_t fname;
+ isc_result_t result;
+ char namestr[DNS_NAME_FORMATSIZE];
+
+ dns_fixedname_init(&fname);
+ result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
+ 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ case DNS_R_NXDOMAIN:
+ case DNS_R_NXRRSET:
+ return (ISC_TRUE);
+ case DNS_R_DELEGATION:
+ case DNS_R_CNAME:
+ case DNS_R_DNAME:
+ return (ISC_FALSE);
+ }
+ dns_name_format(name, namestr, sizeof(namestr));
+ fatal("failure looking for '%s DNSKEY' in database: %s",
+ namestr, isc_result_totext(result));
+ return (ISC_FALSE); /* removes a warning */
+}
+
+static inline isc_boolean_t
+setverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key,
+ dns_rdata_t *rrsig)
+{
+ isc_result_t result;
+ result = dns_dnssec_verify(name, set, key->key, ISC_FALSE, mctx, rrsig);
+ if (result == ISC_R_SUCCESS) {
+ INCSTAT(nverified);
+ return (ISC_TRUE);
+ } else {
+ INCSTAT(nverifyfailed);
+ return (ISC_FALSE);
+ }
+}
+
+/*%
+ * Signs a set. Goes through contortions to decide if each RRSIG should
+ * be dropped or retained, and then determines if any new SIGs need to
+ * be generated.
+ */
+static void
+signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
+ dns_rdataset_t *set)
+{
+ dns_rdataset_t sigset;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t rrsig;
+ signer_key_t *key;
+ isc_result_t result;
+ isc_boolean_t nosigs = ISC_FALSE;
+ isc_boolean_t *wassignedby, *nowsignedby;
+ int arraysize;
+ dns_difftuple_t *tuple;
+ dns_ttl_t ttl;
+ int i;
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[TYPE_FORMATSIZE];
+ char sigstr[SIG_FORMATSIZE];
+
+ dns_name_format(name, namestr, sizeof(namestr));
+ type_format(set->type, typestr, sizeof(typestr));
+
+ ttl = ISC_MIN(set->ttl, endtime - starttime);
+
+ dns_rdataset_init(&sigset);
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
+ set->type, 0, &sigset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ nosigs = ISC_TRUE;
+ }
+ if (result != ISC_R_SUCCESS)
+ fatal("failed while looking for '%s RRSIG %s': %s",
+ namestr, typestr, isc_result_totext(result));
+
+ vbprintf(1, "%s/%s:\n", namestr, typestr);
+
+ arraysize = keycount;
+ if (!nosigs)
+ arraysize += dns_rdataset_count(&sigset);
+ wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
+ nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
+ if (wassignedby == NULL || nowsignedby == NULL)
+ fatal("out of memory");
+
+ for (i = 0; i < arraysize; i++)
+ wassignedby[i] = nowsignedby[i] = ISC_FALSE;
+
+ if (nosigs)
+ result = ISC_R_NOMORE;
+ else
+ result = dns_rdataset_first(&sigset);
+
+ while (result == ISC_R_SUCCESS) {
+ isc_boolean_t expired, future;
+ isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
+
+ dns_rdataset_current(&sigset, &sigrdata);
+
+ result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+ future = isc_serial_lt(now, rrsig.timesigned);
+
+ key = keythatsigned(&rrsig);
+ sig_format(&rrsig, sigstr, sizeof(sigstr));
+ if (key != NULL && issigningkey(key))
+ expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
+ else
+ expired = isc_serial_gt(now, rrsig.timeexpire);
+
+ if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
+ /* rrsig is dropped and not replaced */
+ vbprintf(2, "\trrsig by %s dropped - "
+ "invalid validity period\n",
+ sigstr);
+ } else if (key == NULL && !future &&
+ expecttofindkey(&rrsig.signer))
+ {
+ /* rrsig is dropped and not replaced */
+ vbprintf(2, "\trrsig by %s dropped - "
+ "private dnskey not found\n",
+ sigstr);
+ } else if (key == NULL || future) {
+ vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
+ expired ? "retained" : "dropped", sigstr);
+ if (!expired)
+ keep = ISC_TRUE;
+ } else if (issigningkey(key)) {
+ if (!expired && setverifies(name, set, key, &sigrdata))
+ {
+ vbprintf(2, "\trrsig by %s retained\n", sigstr);
+ keep = ISC_TRUE;
+ wassignedby[key->position] = ISC_TRUE;
+ nowsignedby[key->position] = ISC_TRUE;
+ } else {
+ vbprintf(2, "\trrsig by %s dropped - %s\n",
+ sigstr,
+ expired ? "expired" :
+ "failed to verify");
+ wassignedby[key->position] = ISC_TRUE;
+ resign = ISC_TRUE;
+ }
+ } else if (iszonekey(key)) {
+ if (!expired && setverifies(name, set, key, &sigrdata))
+ {
+ vbprintf(2, "\trrsig by %s retained\n", sigstr);
+ keep = ISC_TRUE;
+ wassignedby[key->position] = ISC_TRUE;
+ nowsignedby[key->position] = ISC_TRUE;
+ } else {
+ vbprintf(2, "\trrsig by %s dropped - %s\n",
+ sigstr,
+ expired ? "expired" :
+ "failed to verify");
+ wassignedby[key->position] = ISC_TRUE;
+ }
+ } else if (!expired) {
+ vbprintf(2, "\trrsig by %s retained\n", sigstr);
+ keep = ISC_TRUE;
+ } else {
+ vbprintf(2, "\trrsig by %s expired\n", sigstr);
+ }
+
+ if (keep) {
+ nowsignedby[key->position] = ISC_TRUE;
+ INCSTAT(nretained);
+ if (sigset.ttl != ttl) {
+ vbprintf(2, "\tfixing ttl %s\n", sigstr);
+ tuple = NULL;
+ result = dns_difftuple_create(mctx,
+ DNS_DIFFOP_DEL,
+ name, sigset.ttl,
+ &sigrdata,
+ &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(del, &tuple);
+ result = dns_difftuple_create(mctx,
+ DNS_DIFFOP_ADD,
+ name, ttl,
+ &sigrdata,
+ &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(add, &tuple);
+ }
+ } else {
+ tuple = NULL;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
+ name, sigset.ttl,
+ &sigrdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(del, &tuple);
+ INCSTAT(ndropped);
+ }
+
+ if (resign) {
+ isc_buffer_t b;
+ dns_rdata_t trdata = DNS_RDATA_INIT;
+ unsigned char array[BUFSIZE];
+ char keystr[KEY_FORMATSIZE];
+
+ INSIST(!keep);
+
+ key_format(key->key, keystr, sizeof(keystr));
+ vbprintf(1, "\tresigning with dnskey %s\n", keystr);
+ isc_buffer_init(&b, array, sizeof(array));
+ signwithkey(name, set, &trdata, key->key, &b);
+ nowsignedby[key->position] = ISC_TRUE;
+ tuple = NULL;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ name, ttl, &trdata,
+ &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(add, &tuple);
+ }
+
+ dns_rdata_reset(&sigrdata);
+ dns_rdata_freestruct(&rrsig);
+ result = dns_rdataset_next(&sigset);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ check_result(result, "dns_rdataset_first/next");
+ if (dns_rdataset_isassociated(&sigset))
+ dns_rdataset_disassociate(&sigset);
+
+ for (key = ISC_LIST_HEAD(keylist);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link))
+ {
+ isc_buffer_t b;
+ dns_rdata_t trdata;
+ unsigned char array[BUFSIZE];
+ char keystr[KEY_FORMATSIZE];
+
+ if (nowsignedby[key->position])
+ continue;
+
+ if (!key->issigningkey)
+ continue;
+ if (!(ignoreksk || key->isdsk ||
+ (key->isksk &&
+ set->type == dns_rdatatype_dnskey &&
+ dns_name_equal(name, gorigin))))
+ continue;
+
+ key_format(key->key, keystr, sizeof(keystr));
+ vbprintf(1, "\tsigning with dnskey %s\n", keystr);
+ dns_rdata_init(&trdata);
+ isc_buffer_init(&b, array, sizeof(array));
+ signwithkey(name, set, &trdata, key->key, &b);
+ tuple = NULL;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
+ ttl, &trdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(add, &tuple);
+ }
+
+ isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
+ isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
+}
+
+struct hashlist {
+ unsigned char *hashbuf;
+ size_t entries;
+ size_t size;
+ size_t length;
+};
+
+static void
+hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
+
+ l->entries = 0;
+ l->length = length + 1;
+
+ if (nodes != 0) {
+ l->size = nodes;
+ l->hashbuf = malloc(l->size * l->length);
+ if (l->hashbuf == NULL)
+ l->size = 0;
+ } else {
+ l->size = 0;
+ l->hashbuf = NULL;
+ }
+}
+
+static void
+hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
+{
+
+ REQUIRE(len <= l->length);
+
+ if (l->entries == l->size) {
+ l->size = l->size * 2 + 100;
+ l->hashbuf = realloc(l->hashbuf, l->size * l->length);
+ }
+ memset(l->hashbuf + l->entries * l->length, 0, l->length);
+ memcpy(l->hashbuf + l->entries * l->length, hash, len);
+ l->entries++;
+}
+
+static void
+hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
+ unsigned int hashalg, unsigned int iterations,
+ const unsigned char *salt, size_t salt_length,
+ isc_boolean_t speculative)
+{
+ char nametext[DNS_NAME_FORMATSIZE];
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
+ unsigned int len;
+ size_t i;
+
+ len = isc_iterated_hash(hash, hashalg, iterations, salt, salt_length,
+ name->ndata, name->length);
+ if (verbose) {
+ dns_name_format(name, nametext, sizeof nametext);
+ for (i = 0 ; i < len; i++)
+ fprintf(stderr, "%02x", hash[i]);
+ fprintf(stderr, " %s\n", nametext);
+ }
+ hash[len++] = speculative ? 1 : 0;
+ hashlist_add(l, hash, len);
+}
+
+static int
+hashlist_comp(const void *a, const void *b) {
+ return (memcmp(a, b, hash_length + 1));
+}
+
+static void
+hashlist_sort(hashlist_t *l) {
+ qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
+}
+
+static isc_boolean_t
+hashlist_hasdup(hashlist_t *l) {
+ unsigned char *current;
+ unsigned char *next = l->hashbuf;
+ size_t entries = l->entries;
+
+ /*
+ * Skip initial speculative wild card hashs.
+ */
+ while (entries > 0U && next[l->length-1] != 0U) {
+ next += l->length;
+ entries--;
+ }
+
+ current = next;
+ while (entries-- > 1U) {
+ next += l->length;
+ if (next[l->length-1] != 0)
+ continue;
+ if (memcmp(current, next, l->length - 1) == 0)
+ return (ISC_TRUE);
+ current = next;
+ }
+ return (ISC_FALSE);
+}
+
+static const unsigned char *
+hashlist_findnext(const hashlist_t *l,
+ const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
+{
+ unsigned int entries = l->entries;
+ const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
+ l->length, hashlist_comp);
+ INSIST(next != NULL);
+
+ do {
+ if (next < l->hashbuf + (l->entries - 1) * l->length)
+ next += l->length;
+ else
+ next = l->hashbuf;
+ if (next[l->length - 1] == 0)
+ break;
+ } while (entries-- > 1);
+ INSIST(entries != 0);
+ return (next);
+}
+
+static isc_boolean_t
+hashlist_exists(const hashlist_t *l,
+ const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
+{
+ if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+}
+
+static void
+addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
+ unsigned int hashalg, unsigned int iterations,
+ const unsigned char *salt, size_t salt_length)
+{
+ dns_fixedname_t fixed;
+ dns_name_t *wild;
+ dns_dbnode_t *node = NULL;
+ isc_result_t result;
+ char namestr[DNS_NAME_FORMATSIZE];
+
+ dns_fixedname_init(&fixed);
+ wild = dns_fixedname_name(&fixed);
+
+ result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
+ if (result == ISC_R_NOSPACE)
+ return;
+ check_result(result,"addnowildcardhash: dns_name_concatenate()");
+
+ result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
+ if (result == ISC_R_SUCCESS) {
+ dns_db_detachnode(gdb, &node);
+ return;
+ }
+
+ if (verbose) {
+ dns_name_format(wild, namestr, sizeof(namestr));
+ fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
+ }
+
+ hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_length,
+ ISC_TRUE);
+}
+
+static void
+opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
+ dns_db_t **dbp)
+{
+ char filename[256];
+ isc_buffer_t b;
+ isc_result_t result;
+
+ isc_buffer_init(&b, filename, sizeof(filename));
+ if (directory != NULL) {
+ isc_buffer_putstr(&b, directory);
+ if (directory[strlen(directory) - 1] != '/')
+ isc_buffer_putstr(&b, "/");
+ }
+ isc_buffer_putstr(&b, prefix);
+ result = dns_name_tofilenametext(name, ISC_FALSE, &b);
+ check_result(result, "dns_name_tofilenametext()");
+ if (isc_buffer_availablelength(&b) == 0) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ fatal("name '%s' is too long", namestr);
+ }
+ isc_buffer_putuint8(&b, 0);
+
+ result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
+ rdclass, 0, NULL, dbp);
+ check_result(result, "dns_db_create()");
+
+ result = dns_db_load(*dbp, filename);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
+ dns_db_detach(dbp);
+}
+
+/*%
+ * 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, isc_uint32_t ttl, dns_rdataset_t *dsset) {
+ dns_db_t *db = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_dbnode_t *node = NULL;
+ isc_result_t result;
+ dns_rdataset_t keyset;
+ dns_rdata_t key, ds;
+ unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+ dns_diff_t diff;
+ dns_difftuple_t *tuple = NULL;
+
+ opendb("keyset-", name, gclass, &db);
+ if (db == NULL)
+ return (ISC_R_NOTFOUND);
+
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detach(&db);
+ return (DNS_R_BADDB);
+ }
+ dns_rdataset_init(&keyset);
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
+ &keyset, NULL);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ return (result);
+ }
+
+ vbprintf(2, "found DNSKEY records\n");
+
+ result = dns_db_newversion(db, &ver);
+ check_result(result, "dns_db_newversion");
+
+ dns_diff_init(mctx, &diff);
+
+ for (result = dns_rdataset_first(&keyset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&keyset))
+ {
+ dns_rdata_init(&key);
+ dns_rdata_init(&ds);
+ dns_rdataset_current(&keyset, &key);
+ result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
+ dsbuf, &ds);
+ check_result(result, "dns_ds_buildrdata");
+
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
+ ttl, &ds, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+
+ dns_rdata_reset(&ds);
+ result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
+ dsbuf, &ds);
+ check_result(result, "dns_ds_buildrdata");
+
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
+ ttl, &ds, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+ }
+ result = dns_diff_apply(&diff, db, ver);
+ check_result(result, "dns_diff_apply");
+ dns_diff_clear(&diff);
+
+ dns_db_closeversion(db, &ver, ISC_TRUE);
+
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
+ dsset, NULL);
+ check_result(result, "dns_db_findrdataset");
+
+ dns_rdataset_disassociate(&keyset);
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ return (result);
+}
+
+static isc_boolean_t
+delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
+ dns_rdataset_t nsset;
+ isc_result_t result;
+
+ if (dns_name_equal(name, gorigin))
+ return (ISC_FALSE);
+
+ dns_rdataset_init(&nsset);
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns,
+ 0, 0, &nsset, NULL);
+ if (dns_rdataset_isassociated(&nsset)) {
+ if (ttlp != NULL)
+ *ttlp = nsset.ttl;
+ dns_rdataset_disassociate(&nsset);
+ }
+
+ return (ISC_TF(result == ISC_R_SUCCESS));
+}
+
+static isc_boolean_t
+secure(dns_name_t *name, dns_dbnode_t *node) {
+ dns_rdataset_t dsset;
+ isc_result_t result;
+
+ if (dns_name_equal(name, gorigin))
+ return (ISC_FALSE);
+
+ dns_rdataset_init(&dsset);
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
+ 0, 0, &dsset, NULL);
+ if (dns_rdataset_isassociated(&dsset))
+ dns_rdataset_disassociate(&dsset);
+
+ return (ISC_TF(result == ISC_R_SUCCESS));
+}
+
+/*%
+ * Signs all records at a name.
+ */
+static void
+signname(dns_dbnode_t *node, dns_name_t *name) {
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_rdatasetiter_t *rdsiter;
+ isc_boolean_t isdelegation = ISC_FALSE;
+ dns_diff_t del, add;
+ char namestr[DNS_NAME_FORMATSIZE];
+
+ dns_rdataset_init(&rdataset);
+ dns_name_format(name, namestr, sizeof(namestr));
+
+ /*
+ * Determine if this is a delegation point.
+ */
+ if (delegation(name, node, NULL))
+ isdelegation = ISC_TRUE;
+
+ /*
+ * Now iterate through the rdatasets.
+ */
+ dns_diff_init(mctx, &del);
+ dns_diff_init(mctx, &add);
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+
+ /* If this is a RRSIG set, skip it. */
+ if (rdataset.type == dns_rdatatype_rrsig)
+ goto skip;
+
+ /*
+ * If this name is a delegation point, skip all records
+ * except NSEC and DS sets. Otherwise check that there
+ * isn't a DS record.
+ */
+ if (isdelegation) {
+ if (rdataset.type != nsec_datatype &&
+ rdataset.type != dns_rdatatype_ds)
+ goto skip;
+ } else if (rdataset.type == dns_rdatatype_ds) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ fatal("'%s': found DS RRset without NS RRset\n",
+ namebuf);
+ }
+
+ signset(&del, &add, node, name, &rdataset);
+
+ skip:
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_rdatasetiter_next(rdsiter);
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration for name '%s' failed: %s",
+ namestr, isc_result_totext(result));
+
+ dns_rdatasetiter_destroy(&rdsiter);
+
+ result = dns_diff_applysilently(&del, gdb, gversion);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to delete SIGs at node '%s': %s",
+ namestr, isc_result_totext(result));
+
+ result = dns_diff_applysilently(&add, gdb, gversion);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to add SIGs at node '%s': %s",
+ namestr, isc_result_totext(result));
+
+ dns_diff_clear(&del);
+ dns_diff_clear(&add);
+}
+
+static inline isc_boolean_t
+active_node(dns_dbnode_t *node) {
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_rdatasetiter_t *rdsiter2 = NULL;
+ isc_boolean_t active = ISC_FALSE;
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_rdatatype_t type;
+ dns_rdatatype_t covers;
+ isc_boolean_t found;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ if (rdataset.type != dns_rdatatype_nsec &&
+ rdataset.type != dns_rdatatype_nsec3 &&
+ rdataset.type != dns_rdatatype_rrsig)
+ active = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
+ if (!active)
+ result = dns_rdatasetiter_next(rdsiter);
+ else
+ result = ISC_R_NOMORE;
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+
+ if (!active && nsec_datatype == dns_rdatatype_nsec) {
+ /*%
+ * The node is empty of everything but NSEC / RRSIG records.
+ */
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter)) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ rdataset.type,
+ rdataset.covers);
+ check_result(result, "dns_db_deleterdataset()");
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ } else {
+ /*
+ * Delete RRSIGs for types that no longer exist.
+ */
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
+ check_result(result, "dns_db_allrdatasets()");
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter)) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ type = rdataset.type;
+ covers = rdataset.covers;
+ dns_rdataset_disassociate(&rdataset);
+ if (type != dns_rdatatype_rrsig)
+ continue;
+ found = ISC_FALSE;
+ for (result = dns_rdatasetiter_first(rdsiter2);
+ !found && result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter2)) {
+ dns_rdatasetiter_current(rdsiter2, &rdataset);
+ if (rdataset.type == covers)
+ found = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (!found) {
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ result = dns_db_deleterdataset(gdb, node,
+ gversion, type,
+ covers);
+ check_result(result,
+ "dns_db_deleterdataset(rrsig)");
+ } else if (result != ISC_R_NOMORE &&
+ result != ISC_R_SUCCESS)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ dns_rdatasetiter_destroy(&rdsiter2);
+
+#if 0
+ /*
+ * Delete all NSEC records and RRSIG(NSEC) if we are in
+ * NSEC3 mode and vica versa.
+ */
+ for (result = dns_rdatasetiter_first(rdsiter2);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter2)) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ type = rdataset.type;
+ covers = rdataset.covers;
+ if (type == dns_rdatatype_rrsig)
+ type = covers;
+ dns_rdataset_disassociate(&rdataset);
+ if (type == nsec_datatype ||
+ (type != dns_rdatatype_nsec &&
+ type != dns_rdatatype_nsec3))
+ continue;
+ if (covers != 0)
+ type = dns_rdatatype_rrsig;
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ type, covers);
+ check_result(result, "dns_db_deleterdataset()");
+ }
+#endif
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+
+ return (active);
+}
+
+/*%
+ * Extracts the TTL from the SOA.
+ */
+static dns_ttl_t
+soattl(void) {
+ dns_rdataset_t soaset;
+ dns_fixedname_t fname;
+ 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);
+ dns_rdataset_init(&soaset);
+ result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
+ 0, 0, NULL, name, &soaset, NULL);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to find an SOA at the zone apex: %s",
+ isc_result_totext(result));
+
+ 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);
+}
+
+/*%
+ * Increment (or set if nonzero) the SOA serial
+ */
+static isc_result_t
+setsoaserial(isc_uint32_t serial) {
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_uint32_t old_serial, new_serial;
+
+ result = dns_db_getoriginnode(gdb, &node);
+ if (result != ISC_R_SUCCESS)
+ return result;
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_findrdataset(gdb, node, gversion,
+ dns_rdatatype_soa, 0,
+ 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_rdataset_first(&rdataset);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ dns_rdataset_current(&rdataset, &rdata);
+
+ old_serial = dns_soa_getserial(&rdata);
+
+ if (serial) {
+ /* Set SOA serial to the value provided. */
+ new_serial = serial;
+ } else {
+ /* Increment SOA serial using RFC 1982 arithmetics */
+ new_serial = (old_serial + 1) & 0xFFFFFFFF;
+ if (new_serial == 0)
+ new_serial = 1;
+ }
+
+ /* If the new serial is not likely to cause a zone transfer
+ * (a/ixfr) from servers having the old serial, warn the user.
+ *
+ * RFC1982 section 7 defines the maximum increment to be
+ * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
+ * comparison. (5 - 6 == (2^32)-1, not negative-one)
+ */
+ if (new_serial == old_serial ||
+ (new_serial - old_serial) > 0x7fffffffU)
+ fprintf(stderr, "%s: warning: Serial number not advanced, "
+ "zone may not transfer\n", program);
+
+ dns_soa_setserial(new_serial, &rdata);
+
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ dns_rdatatype_soa, 0);
+ check_result(result, "dns_db_deleterdataset");
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_db_addrdataset(gdb, node, gversion,
+ 0, &rdataset, 0, NULL);
+ check_result(result, "dns_db_addrdataset");
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+cleanup:
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(gdb, &node);
+ dns_rdata_reset(&rdata);
+
+ return (result);
+}
+
+/*%
+ * Delete any RRSIG records at a node.
+ */
+static void
+cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_rdataset_t set;
+ isc_result_t result, dresult;
+
+ if (outputformat != dns_masterformat_text)
+ return;
+
+ dns_rdataset_init(&set);
+ result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets");
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ isc_boolean_t destroy = ISC_FALSE;
+ dns_rdatatype_t covers = 0;
+ dns_rdatasetiter_current(rdsiter, &set);
+ if (set.type == dns_rdatatype_rrsig) {
+ covers = set.covers;
+ destroy = ISC_TRUE;
+ }
+ dns_rdataset_disassociate(&set);
+ result = dns_rdatasetiter_next(rdsiter);
+ if (destroy) {
+ dresult = dns_db_deleterdataset(db, node, version,
+ dns_rdatatype_rrsig,
+ covers);
+ check_result(dresult, "dns_db_deleterdataset");
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ dns_rdatasetiter_destroy(&rdsiter);
+}
+
+/*%
+ * Set up the iterator and global state before starting the tasks.
+ */
+static void
+presign(void) {
+ isc_result_t result;
+
+ gdbiter = NULL;
+ result = dns_db_createiterator(gdb, 0, &gdbiter);
+ check_result(result, "dns_db_createiterator()");
+}
+
+/*%
+ * Clean up the iterator and global state after the tasks complete.
+ */
+static void
+postsign(void) {
+ dns_dbiterator_destroy(&gdbiter);
+}
+
+/*%
+ * Sign the apex of the zone.
+ * Note the origin may not be the first node if there are out of zone
+ * records.
+ */
+static void
+signapex(void) {
+ dns_dbnode_t *node = NULL;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_result_t result;
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ result = dns_dbiterator_seek(gdbiter, gorigin);
+ check_result(result, "dns_dbiterator_seek()");
+ result = dns_dbiterator_current(gdbiter, &node, name);
+ check_result(result, "dns_dbiterator_current()");
+ signname(node, name);
+ dumpnode(name, node);
+ cleannode(gdb, gversion, node);
+ dns_db_detachnode(gdb, &node);
+ result = dns_dbiterator_first(gdbiter);
+ if (result == ISC_R_NOMORE)
+ finished = ISC_TRUE;
+ else if (result != ISC_R_SUCCESS)
+ fatal("failure iterating database: %s",
+ isc_result_totext(result));
+}
+
+/*%
+ * Assigns a node to a worker thread. This is protected by the master task's
+ * lock.
+ */
+static void
+assignwork(isc_task_t *task, isc_task_t *worker) {
+ dns_fixedname_t *fname;
+ dns_name_t *name;
+ dns_dbnode_t *node;
+ sevent_t *sevent;
+ dns_rdataset_t nsec;
+ isc_boolean_t found;
+ isc_result_t result;
+ static dns_name_t *zonecut = NULL; /* Protected by namelock. */
+ static dns_fixedname_t fzonecut; /* Protected by namelock. */
+ static unsigned int ended = 0; /* Protected by namelock. */
+
+ if (shuttingdown)
+ return;
+
+ LOCK(&namelock);
+ if (finished) {
+ ended++;
+ if (ended == ntasks) {
+ isc_task_detach(&task);
+ isc_app_shutdown();
+ }
+ goto unlock;
+ }
+
+ fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
+ if (fname == NULL)
+ fatal("out of memory");
+ dns_fixedname_init(fname);
+ name = dns_fixedname_name(fname);
+ node = NULL;
+ found = ISC_FALSE;
+ while (!found) {
+ result = dns_dbiterator_current(gdbiter, &node, name);
+ if (result != ISC_R_SUCCESS)
+ fatal("failure iterating database: %s",
+ isc_result_totext(result));
+ /*
+ * The origin was handled by signapex().
+ */
+ if (dns_name_equal(name, gorigin)) {
+ dns_db_detachnode(gdb, &node);
+ goto next;
+ }
+ /*
+ * Sort the zone data from the glue and out-of-zone data.
+ * For NSEC zones nodes with zone data have NSEC records.
+ * For NSEC3 zones the NSEC3 nodes are zone data but
+ * outside of the zone name space. For the rest we need
+ * to track the bottom of zone cuts.
+ * Nodes which don't need to be signed are dumped here.
+ */
+ dns_rdataset_init(&nsec);
+ result = dns_db_findrdataset(gdb, node, gversion,
+ nsec_datatype, 0, 0,
+ &nsec, NULL);
+ if (dns_rdataset_isassociated(&nsec))
+ dns_rdataset_disassociate(&nsec);
+ if (result == ISC_R_SUCCESS) {
+ found = ISC_TRUE;
+ } else if (nsec_datatype == dns_rdatatype_nsec3) {
+ if (dns_name_issubdomain(name, gorigin) &&
+ (zonecut == NULL ||
+ !dns_name_issubdomain(name, zonecut))) {
+ if (delegation(name, node, NULL)) {
+ dns_fixedname_init(&fzonecut);
+ zonecut = dns_fixedname_name(&fzonecut);
+ dns_name_copy(name, zonecut, NULL);
+ if (!OPTOUT(nsec3flags) ||
+ secure(name, node))
+ found = ISC_TRUE;
+ } else
+ found = ISC_TRUE;
+ }
+ }
+
+ if (!found) {
+ dumpnode(name, node);
+ dns_db_detachnode(gdb, &node);
+ }
+
+ next:
+ result = dns_dbiterator_next(gdbiter);
+ if (result == ISC_R_NOMORE) {
+ finished = ISC_TRUE;
+ break;
+ } else if (result != ISC_R_SUCCESS)
+ fatal("failure iterating database: %s",
+ isc_result_totext(result));
+ }
+ if (!found) {
+ ended++;
+ if (ended == ntasks) {
+ isc_task_detach(&task);
+ isc_app_shutdown();
+ }
+ isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
+ goto unlock;
+ }
+ sevent = (sevent_t *)
+ isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
+ sign, NULL, sizeof(sevent_t));
+ if (sevent == NULL)
+ fatal("failed to allocate event\n");
+
+ sevent->node = node;
+ sevent->fname = fname;
+ isc_task_send(worker, ISC_EVENT_PTR(&sevent));
+ unlock:
+ UNLOCK(&namelock);
+}
+
+/*%
+ * Start a worker task
+ */
+static void
+startworker(isc_task_t *task, isc_event_t *event) {
+ isc_task_t *worker;
+
+ worker = (isc_task_t *)event->ev_arg;
+ assignwork(task, worker);
+ isc_event_free(&event);
+}
+
+/*%
+ * Write a node to the output file, and restart the worker task.
+ */
+static void
+writenode(isc_task_t *task, isc_event_t *event) {
+ isc_task_t *worker;
+ sevent_t *sevent = (sevent_t *)event;
+
+ worker = (isc_task_t *)event->ev_sender;
+ dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
+ cleannode(gdb, gversion, sevent->node);
+ dns_db_detachnode(gdb, &sevent->node);
+ isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
+ assignwork(task, worker);
+ isc_event_free(&event);
+}
+
+/*%
+ * Sign a database node.
+ */
+static void
+sign(isc_task_t *task, isc_event_t *event) {
+ dns_fixedname_t *fname;
+ dns_dbnode_t *node;
+ sevent_t *sevent, *wevent;
+
+ sevent = (sevent_t *)event;
+ node = sevent->node;
+ fname = sevent->fname;
+ isc_event_free(&event);
+
+ signname(node, dns_fixedname_name(fname));
+ wevent = (sevent_t *)
+ isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
+ writenode, NULL, sizeof(sevent_t));
+ if (wevent == NULL)
+ fatal("failed to allocate event\n");
+ wevent->node = node;
+ wevent->fname = fname;
+ isc_task_send(master, ISC_EVENT_PTR(&wevent));
+}
+
+/*%
+ * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
+ */
+static void
+add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
+ dns_rdataset_t dsset;
+ dns_rdataset_t sigdsset;
+ isc_result_t result;
+
+ dns_rdataset_init(&dsset);
+ dns_rdataset_init(&sigdsset);
+ result = dns_db_findrdataset(gdb, node, gversion,
+ dns_rdatatype_ds,
+ 0, 0, &dsset, &sigdsset);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&dsset);
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ dns_rdatatype_ds, 0);
+ check_result(result, "dns_db_deleterdataset");
+ }
+ result = loadds(name, nsttl, &dsset);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_db_addrdataset(gdb, node, gversion, 0,
+ &dsset, 0, NULL);
+ check_result(result, "dns_db_addrdataset");
+ dns_rdataset_disassociate(&dsset);
+ if (dns_rdataset_isassociated(&sigdsset))
+ dns_rdataset_disassociate(&sigdsset);
+ } else if (dns_rdataset_isassociated(&sigdsset)) {
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_ds);
+ check_result(result, "dns_db_deleterdataset");
+ dns_rdataset_disassociate(&sigdsset);
+ }
+}
+
+/*%
+ * Generate NSEC records for the zone.
+ */
+static void
+nsecify(void) {
+ dns_dbiterator_t *dbiter = NULL;
+ dns_dbnode_t *node = NULL, *nextnode = NULL;
+ dns_fixedname_t fname, fnextname, fzonecut;
+ dns_name_t *name, *nextname, *zonecut;
+ isc_boolean_t done = ISC_FALSE;
+ isc_result_t result;
+ isc_uint32_t nsttl = 0;
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_fixedname_init(&fnextname);
+ nextname = dns_fixedname_name(&fnextname);
+ dns_fixedname_init(&fzonecut);
+ zonecut = NULL;
+
+ result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first()");
+
+ while (!done) {
+ dns_dbiterator_current(dbiter, &node, name);
+ if (delegation(name, node, &nsttl)) {
+ zonecut = dns_fixedname_name(&fzonecut);
+ dns_name_copy(name, zonecut, NULL);
+ if (generateds)
+ add_ds(name, node, nsttl);
+ }
+ result = dns_dbiterator_next(dbiter);
+ nextnode = NULL;
+ while (result == ISC_R_SUCCESS) {
+ isc_boolean_t active = ISC_FALSE;
+ result = dns_dbiterator_current(dbiter, &nextnode,
+ nextname);
+ if (result != ISC_R_SUCCESS)
+ break;
+ active = active_node(nextnode);
+ if (!active) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (!dns_name_issubdomain(nextname, gorigin) ||
+ (zonecut != NULL &&
+ dns_name_issubdomain(nextname, zonecut)))
+ {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ dns_db_detachnode(gdb, &nextnode);
+ break;
+ }
+ if (result == ISC_R_NOMORE) {
+ dns_name_clone(gorigin, nextname);
+ done = ISC_TRUE;
+ } else if (result != ISC_R_SUCCESS)
+ fatal("iterating through the database failed: %s",
+ isc_result_totext(result));
+ result = dns_nsec_build(gdb, gversion, node, nextname,
+ zonettl);
+ check_result(result, "dns_nsec_build()");
+ dns_db_detachnode(gdb, &node);
+ }
+
+ dns_dbiterator_destroy(&dbiter);
+}
+
+/*%
+ * Does this node only contain NSEC3 records or RRSIG records or is empty.
+ */
+static isc_boolean_t
+nsec3only(dns_dbnode_t *node) {
+ dns_rdatasetiter_t *rdsiter = NULL;
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ isc_boolean_t answer = ISC_TRUE;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ if (rdataset.type != dns_rdatatype_nsec3 &&
+ rdataset.type != dns_rdatatype_rrsig) {
+ answer = ISC_FALSE;
+ result = ISC_R_NOMORE;
+ } else
+ result = dns_rdatasetiter_next(rdsiter);
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ dns_rdatasetiter_destroy(&rdsiter);
+ return (answer);
+}
+
+static void
+addnsec3param(const unsigned char *salt, size_t salt_length,
+ unsigned int iterations)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdata_nsec3param_t nsec3param;
+ unsigned char nsec3parambuf[5 + 255];
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+
+ nsec3param.common.rdclass = gclass;
+ nsec3param.common.rdtype = dns_rdatatype_nsec3param;
+ ISC_LINK_INIT(&nsec3param.common, link);
+ nsec3param.mctx = NULL;
+ nsec3param.flags = 0;
+ nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
+ nsec3param.iterations = iterations;
+ nsec3param.salt_length = salt_length;
+ DE_CONST(salt, nsec3param.salt);
+
+ isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
+ result = dns_rdata_fromstruct(&rdata, gclass,
+ dns_rdatatype_nsec3param,
+ &nsec3param, &b);
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.type = rdata.type;
+ rdatalist.covers = 0;
+ rdatalist.ttl = 0;
+ ISC_LIST_INIT(rdatalist.rdata);
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+ result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
+ check_result(result, "dns_rdatalist_tordataset()");
+
+ result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node);
+ check_result(result, "dns_db_find(gorigin)");
+ result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
+ DNS_DBADD_MERGE, NULL);
+ if (result == DNS_R_UNCHANGED)
+ result = ISC_R_SUCCESS;
+ check_result(result, "addnsec3param: dns_db_addrdataset()");
+ dns_db_detachnode(gdb, &node);
+}
+
+static void
+addnsec3(dns_name_t *name, dns_dbnode_t *node,
+ const unsigned char *salt, size_t salt_length,
+ unsigned int iterations, hashlist_t *hashlist,
+ dns_ttl_t ttl)
+{
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH];
+ const unsigned char *nexthash;
+ unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
+ dns_fixedname_t hashname;
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+ dns_dbnode_t *nsec3node = NULL;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ size_t hash_length;
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+
+ dns_fixedname_init(&hashname);
+ dns_rdataset_init(&rdataset);
+
+ dns_name_downcase(name, name, NULL);
+ result = dns_nsec3_hashname(&hashname, hash, &hash_length,
+ name, gorigin, dns_hash_sha1, iterations,
+ salt, salt_length);
+ check_result(result, "addnsec3: dns_nsec3_hashname()");
+ nexthash = hashlist_findnext(hashlist, hash);
+ result = dns_nsec3_buildrdata(gdb, gversion, node,
+ unknownalg ?
+ DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
+ nsec3flags, iterations,
+ salt, salt_length,
+ nexthash, ISC_SHA1_DIGESTLENGTH,
+ nsec3buffer, &rdata);
+ check_result(result, "addnsec3: dns_nsec3_buildrdata()");
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.type = rdata.type;
+ rdatalist.covers = 0;
+ rdatalist.ttl = ttl;
+ ISC_LIST_INIT(rdatalist.rdata);
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+ result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
+ check_result(result, "dns_rdatalist_tordataset()");
+ result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
+ ISC_TRUE, &nsec3node);
+ check_result(result, "addnsec3: dns_db_findnode()");
+ result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
+ 0, NULL);
+ if (result == DNS_R_UNCHANGED)
+ result = ISC_R_SUCCESS;
+ check_result(result, "addnsec3: dns_db_addrdataset()");
+ dns_db_detachnode(gdb, &nsec3node);
+}
+
+/*%
+ * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
+ *
+ * Extract the hash from the first label of 'name' then see if it
+ * is in hashlist. If 'name' is not in the hashlist then delete the
+ * any NSEC3 records which have the same parameters as the chain we
+ * are building.
+ *
+ * XXXMPA Should we also check that it of the form <hash>.<origin>?
+ */
+static void
+nsec3clean(dns_name_t *name, dns_dbnode_t *node,
+ unsigned int hashalg, unsigned int iterations,
+ const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
+{
+ dns_label_t label;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_t rdata, delrdata;
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset, delrdataset;
+ isc_boolean_t delete_rrsigs = ISC_FALSE;
+ isc_buffer_t target;
+ isc_result_t result;
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
+
+ /*
+ * Get the first label.
+ */
+ dns_name_getlabel(name, 0, &label);
+
+ /*
+ * We want just the label contents.
+ */
+ isc_region_consume(&label, 1);
+
+ /*
+ * Decode base32hex string.
+ */
+ isc_buffer_init(&target, hash, sizeof(hash) - 1);
+ result = isc_base32hex_decoderegion(&label, &target);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ hash[isc_buffer_usedlength(&target)] = 0;
+
+ if (hashlist_exists(hashlist, hash))
+ return;
+
+ /*
+ * Verify that the NSEC3 parameters match the current ones
+ * otherwise we are dealing with a different NSEC3 chain.
+ */
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&delrdataset);
+
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ /*
+ * Delete any matching NSEC3 records which have parameters that
+ * match the NSEC3 chain we are building.
+ */
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(&rdataset, &rdata);
+ dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ if (nsec3.hash == hashalg &&
+ nsec3.iterations == iterations &&
+ nsec3.salt_length == salt_length &&
+ !memcmp(nsec3.salt, salt, salt_length))
+ break;
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.type = rdata.type;
+ rdatalist.covers = 0;
+ rdatalist.ttl = rdataset.ttl;
+ ISC_LIST_INIT(rdatalist.rdata);
+ dns_rdata_init(&delrdata);
+ dns_rdata_clone(&rdata, &delrdata);
+ ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
+ result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
+ check_result(result, "dns_rdatalist_tordataset()");
+ result = dns_db_subtractrdataset(gdb, node, gversion,
+ &delrdataset, 0, NULL);
+ dns_rdataset_disassociate(&delrdataset);
+ if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
+ check_result(result, "dns_db_subtractrdataset(NSEC3)");
+ delete_rrsigs = ISC_TRUE;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_NOMORE)
+ check_result(result, "dns_rdataset_first/next");
+
+ if (!delete_rrsigs)
+ return;
+ /*
+ * Delete the NSEC3 RRSIGs
+ */
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_nsec3);
+ if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
+ check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
+}
+
+/*
+ * Generate NSEC3 records for the zone.
+ */
+static void
+nsec3ify(unsigned int hashalg, unsigned int iterations,
+ const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
+{
+ dns_dbiterator_t *dbiter = NULL;
+ dns_dbnode_t *node = NULL, *nextnode = NULL;
+ dns_fixedname_t fname, fnextname, fzonecut;
+ dns_name_t *name, *nextname, *zonecut;
+ isc_boolean_t done = ISC_FALSE;
+ isc_result_t result;
+ isc_boolean_t active;
+ isc_uint32_t nsttl = 0;
+ unsigned int count, nlabels;
+ int order;
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_fixedname_init(&fnextname);
+ nextname = dns_fixedname_name(&fnextname);
+ dns_fixedname_init(&fzonecut);
+ zonecut = NULL;
+
+ /*
+ * Walk the zone generating the hash names.
+ */
+ result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first()");
+
+ while (!done) {
+ dns_dbiterator_current(dbiter, &node, name);
+ result = dns_dbiterator_next(dbiter);
+ nextnode = NULL;
+ while (result == ISC_R_SUCCESS) {
+ result = dns_dbiterator_current(dbiter, &nextnode,
+ nextname);
+ if (result != ISC_R_SUCCESS)
+ break;
+ active = active_node(nextnode);
+ if (!active) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (!dns_name_issubdomain(nextname, gorigin) ||
+ (zonecut != NULL &&
+ dns_name_issubdomain(nextname, zonecut))) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (delegation(nextname, nextnode, &nsttl)) {
+ zonecut = dns_fixedname_name(&fzonecut);
+ dns_name_copy(nextname, zonecut, NULL);
+ if (generateds)
+ add_ds(nextname, nextnode, nsttl);
+ if (OPTOUT(nsec3flags) &&
+ !secure(nextname, nextnode)) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ }
+ dns_db_detachnode(gdb, &nextnode);
+ break;
+ }
+ if (result == ISC_R_NOMORE) {
+ dns_name_copy(gorigin, nextname, NULL);
+ done = ISC_TRUE;
+ } else if (result != ISC_R_SUCCESS)
+ fatal("iterating through the database failed: %s",
+ isc_result_totext(result));
+ dns_name_downcase(name, name, NULL);
+ hashlist_add_dns_name(hashlist, name, hashalg, iterations,
+ salt, salt_length, ISC_FALSE);
+ dns_db_detachnode(gdb, &node);
+ /*
+ * Add hashs for empty nodes. Use closest encloser logic.
+ * The closest encloser either has data or is a empty
+ * node for another <name,nextname> span so we don't add
+ * it here. Empty labels on nextname are within the span.
+ */
+ dns_name_downcase(nextname, nextname, NULL);
+ dns_name_fullcompare(name, nextname, &order, &nlabels);
+ addnowildcardhash(hashlist, name, hashalg, iterations,
+ salt, salt_length);
+ count = dns_name_countlabels(nextname);
+ while (count > nlabels + 1) {
+ count--;
+ dns_name_split(nextname, count, NULL, nextname);
+ hashlist_add_dns_name(hashlist, nextname, hashalg,
+ iterations, salt, salt_length,
+ ISC_FALSE);
+ addnowildcardhash(hashlist, nextname, hashalg,
+ iterations, salt, salt_length);
+ }
+ }
+ dns_dbiterator_destroy(&dbiter);
+
+ /*
+ * We have all the hashes now so we can sort them.
+ */
+ hashlist_sort(hashlist);
+
+ /*
+ * Check for duplicate hashes. If found the salt needs to
+ * be changed.
+ */
+ if (hashlist_hasdup(hashlist))
+ fatal("Duplicate hash detected. Pick a different salt.");
+
+ /*
+ * Generate the nsec3 records.
+ */
+ zonecut = NULL;
+ done = ISC_FALSE;
+
+ addnsec3param(salt, salt_length, iterations);
+
+ result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first()");
+
+ while (!done) {
+ dns_dbiterator_current(dbiter, &node, name);
+ result = dns_dbiterator_next(dbiter);
+ nextnode = NULL;
+ while (result == ISC_R_SUCCESS) {
+ result = dns_dbiterator_current(dbiter, &nextnode,
+ nextname);
+ if (result != ISC_R_SUCCESS)
+ break;
+ /*
+ * Cleanout NSEC3 RRsets which don't exist in the
+ * hash table.
+ */
+ nsec3clean(nextname, nextnode, hashalg, iterations,
+ salt, salt_length, hashlist);
+ /*
+ * Skip NSEC3 only nodes when looking for the next
+ * node in the zone. Also skips now empty nodes.
+ */
+ if (nsec3only(nextnode)) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (!dns_name_issubdomain(nextname, gorigin) ||
+ (zonecut != NULL &&
+ dns_name_issubdomain(nextname, zonecut))) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (delegation(nextname, nextnode, NULL)) {
+ zonecut = dns_fixedname_name(&fzonecut);
+ dns_name_copy(nextname, zonecut, NULL);
+ if (OPTOUT(nsec3flags) &&
+ !secure(nextname, nextnode)) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ }
+ dns_db_detachnode(gdb, &nextnode);
+ break;
+ }
+ if (result == ISC_R_NOMORE) {
+ dns_name_copy(gorigin, nextname, NULL);
+ done = ISC_TRUE;
+ } else if (result != ISC_R_SUCCESS)
+ fatal("iterating through the database failed: %s",
+ isc_result_totext(result));
+ /*
+ * We need to pause here to release the lock on the database.
+ */
+ dns_dbiterator_pause(dbiter);
+ addnsec3(name, node, salt, salt_length, iterations,
+ hashlist, zonettl);
+ dns_db_detachnode(gdb, &node);
+ /*
+ * Add NSEC3's for empty nodes. Use closest encloser logic.
+ */
+ dns_name_fullcompare(name, nextname, &order, &nlabels);
+ count = dns_name_countlabels(nextname);
+ while (count > nlabels + 1) {
+ count--;
+ dns_name_split(nextname, count, NULL, nextname);
+ addnsec3(nextname, NULL, salt, salt_length,
+ iterations, hashlist, zonettl);
+ }
+ }
+ dns_dbiterator_destroy(&dbiter);
+}
+
+/*%
+ * Load the zone file from disk
+ */
+static void
+loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
+ isc_buffer_t b;
+ int len;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_result_t result;
+
+ len = strlen(origin);
+ isc_buffer_init(&b, origin, len);
+ isc_buffer_add(&b, len);
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed converting name '%s' to dns format: %s",
+ origin, isc_result_totext(result));
+
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
+ rdclass, 0, NULL, db);
+ check_result(result, "dns_db_create()");
+
+ result = dns_db_load2(*db, file, inputformat);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
+ fatal("failed loading zone from '%s': %s",
+ file, isc_result_totext(result));
+}
+
+/*%
+ * Finds all public zone keys in the zone, and attempts to load the
+ * private keys from disk.
+ */
+static void
+loadzonekeys(dns_db_t *db) {
+ dns_dbnode_t *node;
+ dns_dbversion_t *currentversion;
+ isc_result_t result;
+ dst_key_t *keys[20];
+ unsigned int nkeys, i;
+
+ currentversion = NULL;
+ dns_db_currentversion(db, &currentversion);
+
+ node = NULL;
+ 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));
+
+ result = dns_dnssec_findzonekeys(db, currentversion, node, gorigin,
+ mctx, 20, keys, &nkeys);
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_SUCCESS;
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to find the zone keys: %s",
+ isc_result_totext(result));
+
+ for (i = 0; i < nkeys; i++) {
+ signer_key_t *key;
+
+ key = newkeystruct(keys[i], dst_key_isprivate(keys[i]));
+ ISC_LIST_APPEND(keylist, key, link);
+ }
+ dns_db_detachnode(db, &node);
+ dns_db_closeversion(db, &currentversion, ISC_FALSE);
+}
+
+/*%
+ * Finds all public zone keys in the zone.
+ */
+static void
+loadzonepubkeys(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;
+ signer_key_t *key;
+ isc_result_t result;
+
+ dns_db_currentversion(db, &currentversion);
+
+ 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_dnskey, 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_dnssec_keyfromrdata(gorigin, &rdata, mctx,
+ &pubkey);
+ if (result != ISC_R_SUCCESS)
+ goto next;
+ if (!dst_key_iszonekey(pubkey)) {
+ dst_key_free(&pubkey);
+ goto next;
+ }
+
+ key = newkeystruct(pubkey, ISC_FALSE);
+ ISC_LIST_APPEND(keylist, key, link);
+ next:
+ result = dns_rdataset_next(&rdataset);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &node);
+ dns_db_closeversion(db, &currentversion, 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;
+ isc_result_t result;
+ dns_rdata_key_t key;
+ isc_boolean_t have_non_ksk = ISC_FALSE;
+
+ dns_db_currentversion(db, &currentversion);
+
+ 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_dnskey, 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) {
+ 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, &currentversion, ISC_FALSE);
+ if (!have_non_ksk && !ignoreksk)
+ fprintf(stderr, "%s: warning: No non-KSK dnskey found. "
+ "Supply non-KSK dnskey or use '-z'.\n",
+ program);
+}
+
+static void
+writeset(const char *prefix, dns_rdatatype_t type) {
+ char *filename;
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_db_t *db = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_diff_t diff;
+ dns_difftuple_t *tuple = NULL;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ dns_rdata_t rdata, ds;
+ isc_boolean_t have_ksk = ISC_FALSE;
+ isc_boolean_t have_non_ksk = ISC_FALSE;
+ isc_buffer_t b;
+ isc_buffer_t namebuf;
+ isc_region_t r;
+ isc_result_t result;
+ signer_key_t *key;
+ unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+ unsigned char keybuf[DST_KEY_MAXSIZE];
+ unsigned int filenamelen;
+ const dns_master_style_t *style =
+ (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
+
+ isc_buffer_init(&namebuf, namestr, sizeof(namestr));
+ result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
+ check_result(result, "dns_name_tofilenametext");
+ isc_buffer_putuint8(&namebuf, 0);
+ filenamelen = strlen(prefix) + strlen(namestr);
+ if (directory != NULL)
+ filenamelen += strlen(directory) + 1;
+ filename = isc_mem_get(mctx, filenamelen + 1);
+ if (filename == NULL)
+ fatal("out of memory");
+ if (directory != NULL)
+ sprintf(filename, "%s/", directory);
+ else
+ filename[0] = 0;
+ strcat(filename, prefix);
+ strcat(filename, namestr);
+
+ 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->isksk) {
+ have_ksk = ISC_TRUE;
+ break;
+ }
+
+ if (type == dns_rdatatype_dlv) {
+ dns_name_t tname;
+ unsigned int labels;
+
+ dns_name_init(&tname, NULL);
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ labels = dns_name_countlabels(gorigin);
+ dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
+ result = dns_name_concatenate(&tname, dlv, name, NULL);
+ check_result(result, "dns_name_concatenate");
+ } else
+ name = gorigin;
+
+ for (key = ISC_LIST_HEAD(keylist);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link))
+ {
+ if (have_ksk && have_non_ksk && !key->isksk)
+ continue;
+ dns_rdata_init(&rdata);
+ dns_rdata_init(&ds);
+ isc_buffer_init(&b, keybuf, sizeof(keybuf));
+ result = dst_key_todns(key->key, &b);
+ check_result(result, "dst_key_todns");
+ isc_buffer_usedregion(&b, &r);
+ dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
+ if (type != dns_rdatatype_dnskey) {
+ result = dns_ds_buildrdata(gorigin, &rdata,
+ DNS_DSDIGEST_SHA1,
+ dsbuf, &ds);
+ check_result(result, "dns_ds_buildrdata");
+ if (type == dns_rdatatype_dlv)
+ ds.type = dns_rdatatype_dlv;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ name, 0, &ds, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+
+ dns_rdata_reset(&ds);
+ result = dns_ds_buildrdata(gorigin, &rdata,
+ DNS_DSDIGEST_SHA256,
+ dsbuf, &ds);
+ check_result(result, "dns_ds_buildrdata");
+ if (type == dns_rdatatype_dlv)
+ ds.type = dns_rdatatype_dlv;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ name, 0, &ds, &tuple);
+
+ } else
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ gorigin, zonettl,
+ &rdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+ }
+
+ result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
+ gclass, 0, NULL, &db);
+ check_result(result, "dns_db_create");
+
+ result = dns_db_newversion(db, &version);
+ check_result(result, "dns_db_newversion");
+
+ result = dns_diff_apply(&diff, db, version);
+ check_result(result, "dns_diff_apply");
+ dns_diff_clear(&diff);
+
+ result = dns_master_dump(mctx, db, version, style, filename);
+ check_result(result, "dns_master_dump");
+
+ isc_mem_put(mctx, filename, filenamelen + 1);
+
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ dns_db_detach(&db);
+}
+
+static void
+print_time(FILE *fp) {
+ time_t currenttime;
+
+ if (outputformat != dns_masterformat_text)
+ return;
+
+ currenttime = time(NULL);
+ fprintf(fp, "; File written on %s", ctime(&currenttime));
+}
+
+static void
+print_version(FILE *fp) {
+ if (outputformat != dns_masterformat_text)
+ return;
+
+ fprintf(fp, "; dnssec_signzone version " VERSION "\n");
+}
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Version: %s\n", VERSION);
+
+ fprintf(stderr, "Options: (default value in parenthesis) \n");
+ fprintf(stderr, "\t-c class (IN)\n");
+ fprintf(stderr, "\t-d directory\n");
+ fprintf(stderr, "\t\tdirectory to find keyset files (.)\n");
+ fprintf(stderr, "\t-g:\t");
+ fprintf(stderr, "generate DS records from keyset files\n");
+ fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
+ fprintf(stderr, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n");
+ fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
+ fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now "
+ "(now + 30 days)\n");
+ fprintf(stderr, "\t-i interval:\n");
+ fprintf(stderr, "\t\tcycle interval - resign "
+ "if < interval from end ( (end-start)/4 )\n");
+ fprintf(stderr, "\t-j jitter:\n");
+ fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
+ fprintf(stderr, "\t-v debuglevel (0)\n");
+ fprintf(stderr, "\t-o origin:\n");
+ fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
+ fprintf(stderr, "\t-f outfile:\n");
+ fprintf(stderr, "\t\tfile the signed zone is written in "
+ "(zonefile + .signed)\n");
+ fprintf(stderr, "\t-I format:\n");
+ fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
+ fprintf(stderr, "\t-O format:\n");
+ fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
+ fprintf(stderr, "\t-N format:\n");
+ fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
+ fprintf(stderr, "\t-r randomdev:\n");
+ fprintf(stderr, "\t\ta file containing random data\n");
+ fprintf(stderr, "\t-a:\t");
+ fprintf(stderr, "verify generated signatures\n");
+ fprintf(stderr, "\t-p:\t");
+ fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
+ fprintf(stderr, "\t-t:\t");
+ fprintf(stderr, "print statistics\n");
+ fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
+ fprintf(stderr, "\t-k key_signing_key\n");
+ fprintf(stderr, "\t-l lookasidezone\n");
+ fprintf(stderr, "\t-3 salt (NSEC3 salt)\n");
+ fprintf(stderr, "\t-H interations (NSEC3 interations)\n");
+ fprintf(stderr, "\t-A (NSEC3 optout)\n");
+ fprintf(stderr, "\t-z:\t");
+ fprintf(stderr, "ignore KSK flag in DNSKEYs");
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Signing Keys: ");
+ fprintf(stderr, "(default: all zone keys that have private keys)\n");
+ fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
+ exit(0);
+}
+
+static void
+removetempfile(void) {
+ if (removefile)
+ isc_file_remove(tempfile);
+}
+
+static void
+print_stats(isc_time_t *timer_start, isc_time_t *timer_finish) {
+ isc_uint64_t runtime_us; /* Runtime in microseconds */
+ isc_uint64_t runtime_ms; /* Runtime in milliseconds */
+ isc_uint64_t sig_ms; /* Signatures per millisecond */
+
+ runtime_us = isc_time_microdiff(timer_finish, timer_start);
+
+ printf("Signatures generated: %10d\n", nsigned);
+ printf("Signatures retained: %10d\n", nretained);
+ printf("Signatures dropped: %10d\n", ndropped);
+ printf("Signatures successfully verified: %10d\n", nverified);
+ printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed);
+ runtime_ms = runtime_us / 1000;
+ printf("Runtime in seconds: %7u.%03u\n",
+ (unsigned int) (runtime_ms / 1000),
+ (unsigned int) (runtime_ms % 1000));
+ if (runtime_us > 0) {
+ sig_ms = ((isc_uint64_t)nsigned * 1000000000) / runtime_us;
+ printf("Signatures per second: %7u.%03u\n",
+ (unsigned int) sig_ms / 1000,
+ (unsigned int) sig_ms % 1000);
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ int i, ch;
+ char *startstr = NULL, *endstr = NULL, *classname = NULL;
+ char *origin = NULL, *file = NULL, *output = NULL;
+ char *inputformatstr = NULL, *outputformatstr = NULL;
+ char *serialformatstr = NULL;
+ char *dskeyfile[MAXDSKEYS];
+ int ndskeys = 0;
+ char *endp;
+ isc_time_t timer_start, timer_finish;
+ signer_key_t *key;
+ isc_result_t result;
+ isc_log_t *log = NULL;
+ isc_boolean_t pseudorandom = ISC_FALSE;
+ unsigned int eflags;
+ isc_boolean_t free_output = ISC_FALSE;
+ int tempfilelen;
+ dns_rdataclass_t rdclass;
+ isc_task_t **tasks = NULL;
+ isc_buffer_t b;
+ int len;
+ unsigned int iterations = 100U;
+ const unsigned char *salt = NULL;
+ size_t salt_length = 0;
+ unsigned char saltbuf[255];
+ hashlist_t hashlist;
+
+#define CMDLINE_FLAGS "3:aAc:d:e:f:ghH:i:I:j:k:l:m:n:N:o:O:pr:s:StUv:z"
+
+ /*
+ * Process memory debugging arguement first.
+ */
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case 'm':
+ if (strcasecmp(isc_commandline_argument, "record") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ if (strcasecmp(isc_commandline_argument, "trace") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
+ if (strcasecmp(isc_commandline_argument, "usage") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
+ if (strcasecmp(isc_commandline_argument, "size") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
+ if (strcasecmp(isc_commandline_argument, "mctx") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGCTX;
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = ISC_TRUE;
+
+ masterstyle = &dns_master_style_explicitttl;
+
+ check_result(isc_app_start(), "isc_app_start");
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ fatal("out of memory");
+
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case '3':
+ if (strcmp(isc_commandline_argument, "-")) {
+ isc_buffer_t target;
+ char *sarg;
+
+ sarg = isc_commandline_argument;
+ isc_buffer_init(&target, saltbuf,
+ sizeof(saltbuf));
+ result = isc_hex_decodestring(sarg, &target);
+ check_result(result,
+ "isc_hex_decodestring(salt)");
+ salt = saltbuf;
+ salt_length = isc_buffer_usedlength(&target);
+ } else {
+ salt = saltbuf;
+ salt_length = 0;
+ }
+ nsec_datatype = dns_rdatatype_nsec3;
+ break;
+
+ case 'A':
+ nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
+ break;
+
+ case 'a':
+ tryverify = ISC_TRUE;
+ break;
+
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+
+ 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 '?':
+ if (isc_commandline_option != '?')
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ case 'h':
+ usage();
+ break;
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n",
+ program, isc_commandline_option);
+ exit(1);
+
+ case 'i':
+ endp = NULL;
+ cycle = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0' || cycle < 0)
+ fatal("cycle period must be numeric and "
+ "positive");
+ break;
+
+ case 'I':
+ inputformatstr = isc_commandline_argument;
+ break;
+
+ case 'j':
+ endp = NULL;
+ jitter = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0' || jitter < 0)
+ fatal("jitter must be numeric and positive");
+ break;
+
+ case 'l':
+ dns_fixedname_init(&dlv_fixed);
+ len = strlen(isc_commandline_argument);
+ isc_buffer_init(&b, isc_commandline_argument, len);
+ isc_buffer_add(&b, len);
+
+ dns_fixedname_init(&dlv_fixed);
+ dlv = dns_fixedname_name(&dlv_fixed);
+ result = dns_name_fromtext(dlv, &b, dns_rootname,
+ ISC_FALSE, NULL);
+ check_result(result, "dns_name_fromtext(dlv)");
+ break;
+
+ case 'k':
+ if (ndskeys == MAXDSKEYS)
+ fatal("too many key-signing keys specified");
+ dskeyfile[ndskeys++] = isc_commandline_argument;
+ break;
+
+ case 'm':
+ 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");
+ break;
+
+ case 'N':
+ serialformatstr = isc_commandline_argument;
+ break;
+
+ case 'H':
+ iterations = strtoul(isc_commandline_argument,
+ &endp, 0);
+ if (*endp != '\0')
+ fatal("iterations must be numeric");
+ if (iterations > 0xffffU)
+ fatal("iterations too big");
+ break;
+
+ case 'o':
+ origin = isc_commandline_argument;
+ break;
+
+ case 'O':
+ outputformatstr = isc_commandline_argument;
+ break;
+
+ case 'p':
+ pseudorandom = ISC_TRUE;
+ break;
+
+ case 'r':
+ setup_entropy(mctx, isc_commandline_argument, &ectx);
+ break;
+
+ case 's':
+ startstr = isc_commandline_argument;
+ break;
+
+ case 'S':
+ /* This is intentionally undocumented */
+ /* -S: simple output style */
+ masterstyle = &dns_master_style_simple;
+ break;
+
+ case 't':
+ printstats = ISC_TRUE;
+ break;
+
+ case 'U': /* Undocumented for testing only. */
+ unknownalg = ISC_TRUE;
+ break;
+
+ 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;
+ }
+ }
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ eflags = ISC_ENTROPY_BLOCKING;
+ if (!pseudorandom)
+ eflags |= ISC_ENTROPY_GOODONLY;
+
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not create hash context");
+
+ result = dst_lib_init(mctx, ectx, eflags);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize dst");
+
+ isc_stdtime_get(&now);
+
+ if (startstr != NULL)
+ starttime = strtotime(startstr, now, now);
+ else
+ starttime = now - 3600; /* Allow for some clock skew. */
+
+ if (endstr != NULL)
+ endtime = strtotime(endstr, now, starttime);
+ else
+ endtime = starttime + (30 * 24 * 60 * 60);
+
+ if (cycle == -1)
+ cycle = (endtime - starttime) / 4;
+
+ if (ntasks == 0)
+ ntasks = isc_os_ncpus() * 2;
+ vbprintf(4, "using %d cpus\n", ntasks);
+
+ rdclass = strtoclass(classname);
+
+ setup_logging(verbose, mctx, &log);
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc < 1)
+ usage();
+
+ file = argv[0];
+
+ argc -= 1;
+ argv += 1;
+
+ if (origin == NULL)
+ origin = file;
+
+ if (output == NULL) {
+ free_output = ISC_TRUE;
+ output = isc_mem_allocate(mctx,
+ strlen(file) + strlen(".signed") + 1);
+ if (output == NULL)
+ fatal("out of memory");
+ sprintf(output, "%s.signed", file);
+ }
+
+ if (inputformatstr != NULL) {
+ if (strcasecmp(inputformatstr, "text") == 0)
+ inputformat = dns_masterformat_text;
+ else if (strcasecmp(inputformatstr, "raw") == 0)
+ inputformat = dns_masterformat_raw;
+ else
+ fatal("unknown file format: %s\n", inputformatstr);
+ }
+
+ if (outputformatstr != NULL) {
+ if (strcasecmp(outputformatstr, "text") == 0)
+ outputformat = dns_masterformat_text;
+ else if (strcasecmp(outputformatstr, "raw") == 0)
+ outputformat = dns_masterformat_raw;
+ else
+ fatal("unknown file format: %s\n", outputformatstr);
+ }
+
+ if (serialformatstr != NULL) {
+ if (strcasecmp(serialformatstr, "keep") == 0)
+ serialformat = SOA_SERIAL_KEEP;
+ else if (strcasecmp(serialformatstr, "increment") == 0 ||
+ strcasecmp(serialformatstr, "incr") == 0)
+ serialformat = SOA_SERIAL_INCREMENT;
+ else if (strcasecmp(serialformatstr, "unixtime") == 0)
+ serialformat = SOA_SERIAL_UNIXTIME;
+ else
+ fatal("unknown soa serial format: %s\n", serialformatstr);
+ }
+
+ result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
+ 0, 24, 0, 0, 0, 8, mctx);
+ check_result(result, "dns_master_stylecreate");
+
+ gdb = NULL;
+ TIME_NOW(&timer_start);
+ loadzone(file, origin, rdclass, &gdb);
+ gorigin = dns_db_origin(gdb);
+ gclass = dns_db_class(gdb);
+ zonettl = soattl();
+
+ if (IS_NSEC3) {
+ isc_boolean_t answer;
+ hash_length = dns_nsec3_hashlength(dns_hash_sha1);
+ hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
+ hash_length);
+ result = dns_nsec_nseconly(gdb, gversion, &answer);
+ check_result(result, "dns_nsec_nseconly");
+ if (answer)
+ fatal("NSEC3 generation requested with "
+ "NSEC only DNSKEY");
+ }
+
+ ISC_LIST_INIT(keylist);
+
+ if (argc == 0) {
+ loadzonekeys(gdb);
+ } else {
+ for (i = 0; i < argc; i++) {
+ dst_key_t *newkey = NULL;
+
+ result = dst_key_fromnamedfile(argv[i],
+ DST_TYPE_PUBLIC |
+ DST_TYPE_PRIVATE,
+ mctx, &newkey);
+ if (result != ISC_R_SUCCESS)
+ fatal("cannot load dnskey %s: %s", argv[i],
+ isc_result_totext(result));
+
+ if (!dns_name_equal(gorigin, dst_key_name(newkey)))
+ fatal("key %s not at origin\n", argv[i]);
+
+ key = ISC_LIST_HEAD(keylist);
+ while (key != NULL) {
+ dst_key_t *dkey = key->key;
+ if (dst_key_id(dkey) == dst_key_id(newkey) &&
+ dst_key_alg(dkey) == dst_key_alg(newkey) &&
+ dns_name_equal(dst_key_name(dkey),
+ dst_key_name(newkey)))
+ {
+ if (!dst_key_isprivate(dkey))
+ fatal("cannot sign zone with "
+ "non-private dnskey %s",
+ argv[i]);
+ break;
+ }
+ key = ISC_LIST_NEXT(key, link);
+ }
+ if (key == NULL) {
+ key = newkeystruct(newkey, ISC_TRUE);
+ ISC_LIST_APPEND(keylist, key, link);
+ } else
+ dst_key_free(&newkey);
+ }
+
+ loadzonepubkeys(gdb);
+ }
+
+ for (i = 0; i < ndskeys; i++) {
+ dst_key_t *newkey = NULL;
+
+ result = dst_key_fromnamedfile(dskeyfile[i],
+ DST_TYPE_PUBLIC |
+ DST_TYPE_PRIVATE,
+ mctx, &newkey);
+ if (result != ISC_R_SUCCESS)
+ fatal("cannot load dnskey %s: %s", dskeyfile[i],
+ isc_result_totext(result));
+
+ if (!dns_name_equal(gorigin, dst_key_name(newkey)))
+ fatal("key %s not at origin\n", dskeyfile[i]);
+
+ key = ISC_LIST_HEAD(keylist);
+ while (key != NULL) {
+ dst_key_t *dkey = key->key;
+ if (dst_key_id(dkey) == dst_key_id(newkey) &&
+ dst_key_alg(dkey) == dst_key_alg(newkey) &&
+ dns_name_equal(dst_key_name(dkey),
+ dst_key_name(newkey)))
+ {
+ /* Override key flags. */
+ key->issigningkey = ISC_TRUE;
+ key->isksk = ISC_TRUE;
+ key->isdsk = ISC_FALSE;
+ dst_key_free(&dkey);
+ key->key = newkey;
+ break;
+ }
+ key = ISC_LIST_NEXT(key, link);
+ }
+ if (key == NULL) {
+ /* Override dnskey flags. */
+ key = newkeystruct(newkey, ISC_TRUE);
+ key->isksk = ISC_TRUE;
+ key->isdsk = ISC_FALSE;
+ ISC_LIST_APPEND(keylist, key, link);
+ }
+ }
+
+ if (ISC_LIST_EMPTY(keylist)) {
+ fprintf(stderr, "%s: warning: No keys specified or found\n",
+ program);
+ nokeys = ISC_TRUE;
+ }
+
+ if (IS_NSEC3) {
+ unsigned int max;
+ result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
+ check_result(result, "dns_nsec3_maxiterations()");
+ if (iterations > max)
+ fatal("NSEC3 interations too big for weakest DNSKEY "
+ "strength. Maximum iterations allowed %u.", max);
+ }
+
+ warnifallksk(gdb);
+
+ gversion = NULL;
+ result = dns_db_newversion(gdb, &gversion);
+ check_result(result, "dns_db_newversion()");
+
+ switch (serialformat) {
+ case SOA_SERIAL_INCREMENT:
+ setsoaserial(0);
+ break;
+ case SOA_SERIAL_UNIXTIME:
+ setsoaserial(now);
+ break;
+ case SOA_SERIAL_KEEP:
+ default:
+ /* do nothing */
+ break;
+ }
+
+ if (IS_NSEC3)
+ nsec3ify(dns_hash_sha1, iterations, salt, salt_length,
+ &hashlist);
+ else
+ nsecify();
+
+ if (!nokeys) {
+ writeset("keyset-", dns_rdatatype_dnskey);
+ writeset("dsset-", dns_rdatatype_ds);
+ if (dlv != NULL) {
+ writeset("dlvset-", dns_rdatatype_dlv);
+ }
+ }
+
+ tempfilelen = strlen(output) + 20;
+ tempfile = isc_mem_get(mctx, tempfilelen);
+ if (tempfile == NULL)
+ fatal("out of memory");
+
+ result = isc_file_mktemplate(output, tempfile, tempfilelen);
+ check_result(result, "isc_file_mktemplate");
+
+ fp = NULL;
+ result = isc_file_openunique(tempfile, &fp);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to open temporary output file: %s",
+ isc_result_totext(result));
+ removefile = ISC_TRUE;
+ setfatalcallback(&removetempfile);
+
+ print_time(fp);
+ print_version(fp);
+
+ result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to create task manager: %s",
+ isc_result_totext(result));
+
+ master = NULL;
+ result = isc_task_create(taskmgr, 0, &master);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to create task: %s", isc_result_totext(result));
+
+ tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
+ if (tasks == NULL)
+ fatal("out of memory");
+ for (i = 0; i < (int)ntasks; i++) {
+ tasks[i] = NULL;
+ result = isc_task_create(taskmgr, 0, &tasks[i]);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to create task: %s",
+ isc_result_totext(result));
+ }
+
+ RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
+ if (printstats)
+ RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
+
+ presign();
+ signapex();
+ if (!finished) {
+ /*
+ * There is more work to do. Spread it out over multiple
+ * processors if possible.
+ */
+ for (i = 0; i < (int)ntasks; i++) {
+ result = isc_app_onrun(mctx, master, startworker,
+ tasks[i]);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to start task: %s",
+ isc_result_totext(result));
+ }
+ (void)isc_app_run();
+ if (!finished)
+ fatal("process aborted by user");
+ } else
+ isc_task_detach(&master);
+ shuttingdown = ISC_TRUE;
+ for (i = 0; i < (int)ntasks; i++)
+ isc_task_detach(&tasks[i]);
+ isc_taskmgr_destroy(&taskmgr);
+ isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
+ postsign();
+
+ if (outputformat != dns_masterformat_text) {
+ result = dns_master_dumptostream2(mctx, gdb, gversion,
+ masterstyle, outputformat,
+ fp);
+ check_result(result, "dns_master_dumptostream2");
+ }
+
+ result = isc_stdio_close(fp);
+ check_result(result, "isc_stdio_close");
+ removefile = ISC_FALSE;
+
+ result = isc_file_rename(tempfile, output);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to rename temp file to %s: %s\n",
+ output, isc_result_totext(result));
+
+ DESTROYLOCK(&namelock);
+ if (printstats)
+ DESTROYLOCK(&statslock);
+
+ printf("%s\n", output);
+
+ dns_db_closeversion(gdb, &gversion, ISC_FALSE);
+ dns_db_detach(&gdb);
+
+ while (!ISC_LIST_EMPTY(keylist)) {
+ key = ISC_LIST_HEAD(keylist);
+ ISC_LIST_UNLINK(keylist, key, link);
+ dst_key_free(&key->key);
+ isc_mem_put(mctx, key, sizeof(signer_key_t));
+ }
+
+ isc_mem_put(mctx, tempfile, tempfilelen);
+
+ if (free_output)
+ isc_mem_free(mctx, output);
+
+ dns_master_styledestroy(&dsstyle, mctx);
+
+ cleanup_logging(&log);
+ dst_lib_destroy();
+ isc_hash_destroy();
+ cleanup_entropy(&ectx);
+ dns_name_destroy();
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ (void) isc_app_finish();
+
+ if (printstats) {
+ TIME_NOW(&timer_finish);
+ print_stats(&timer_start, &timer_finish);
+ }
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-signzone.docbook b/bin/dnssec/dnssec-signzone.docbook
new file mode 100644
index 0000000..2f26ba4
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.docbook
@@ -0,0 +1,512 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<!-- $Id: dnssec-signzone.docbook,v 1.31 2008/10/14 14:28:25 jreed Exp $ -->
+<refentry id="man.dnssec-signzone">
+ <refentryinfo>
+ <date>June 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-signzone</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-signzone</application></refname>
+ <refpurpose>DNSSEC zone signing tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dnssec-signzone</command>
+ <arg><option>-a</option></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-d <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-e <replaceable class="parameter">end-time</replaceable></option></arg>
+ <arg><option>-f <replaceable class="parameter">output-file</replaceable></option></arg>
+ <arg><option>-g</option></arg>
+ <arg><option>-h</option></arg>
+ <arg><option>-k <replaceable class="parameter">key</replaceable></option></arg>
+ <arg><option>-l <replaceable class="parameter">domain</replaceable></option></arg>
+ <arg><option>-i <replaceable class="parameter">interval</replaceable></option></arg>
+ <arg><option>-I <replaceable class="parameter">input-format</replaceable></option></arg>
+ <arg><option>-j <replaceable class="parameter">jitter</replaceable></option></arg>
+ <arg><option>-N <replaceable class="parameter">soa-serial-format</replaceable></option></arg>
+ <arg><option>-o <replaceable class="parameter">origin</replaceable></option></arg>
+ <arg><option>-O <replaceable class="parameter">output-format</replaceable></option></arg>
+ <arg><option>-p</option></arg>
+ <arg><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg>
+ <arg><option>-s <replaceable class="parameter">start-time</replaceable></option></arg>
+ <arg><option>-t</option></arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg><option>-z</option></arg>
+ <arg><option>-3 <replaceable class="parameter">salt</replaceable></option></arg>
+ <arg><option>-H <replaceable class="parameter">iterations</replaceable></option></arg>
+ <arg><option>-A</option></arg>
+ <arg choice="req">zonefile</arg>
+ <arg rep="repeat">key</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>dnssec-signzone</command>
+ signs a zone. It generates
+ NSEC and RRSIG records and produces a signed version of the
+ zone. The security status of delegations from the signed zone
+ (that is, whether the child zones are secure or not) is
+ determined by the presence or absence of a
+ <filename>keyset</filename> file for each child zone.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-a</term>
+ <listitem>
+ <para>
+ Verify all generated signatures.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the DNS class of the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">key</replaceable></term>
+ <listitem>
+ <para>
+ Treat specified key as a key signing key ignoring any
+ key flags. This option may be specified multiple times.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l <replaceable class="parameter">domain</replaceable></term>
+ <listitem>
+ <para>
+ Generate a DLV set in addition to the key (DNSKEY) and DS sets.
+ The domain is appended to the name of the records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Look for <filename>keyset</filename> files in
+ <option>directory</option> as the directory
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-g</term>
+ <listitem>
+ <para>
+ Generate DS records for child zones from keyset files.
+ Existing DS records will be removed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">start-time</replaceable></term>
+ <listitem>
+ <para>
+ Specify the date and time when the generated RRSIG records
+ become valid. This can be either an absolute or relative
+ time. An absolute start time is indicated by a number
+ in YYYYMMDDHHMMSS notation; 20000530144500 denotes
+ 14:45:00 UTC on May 30th, 2000. A relative start time is
+ indicated by +N, which is N seconds from the current time.
+ If no <option>start-time</option> is specified, the current
+ time minus 1 hour (to allow for clock skew) is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-e <replaceable class="parameter">end-time</replaceable></term>
+ <listitem>
+ <para>
+ Specify the date and time when the generated RRSIG records
+ expire. As with <option>start-time</option>, an absolute
+ time is indicated in YYYYMMDDHHMMSS notation. A time relative
+ to the start time is indicated with +N, which is N seconds from
+ the start time. A time relative to the current time is
+ indicated with now+N. If no <option>end-time</option> is
+ specified, 30 days from the start time is used as a default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">output-file</replaceable></term>
+ <listitem>
+ <para>
+ The name of the output file containing the signed zone. The
+ default is to append <filename>.signed</filename> to
+ the
+ input filename.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>dnssec-signzone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">interval</replaceable></term>
+ <listitem>
+ <para>
+ When a previously-signed zone is passed as input, records
+ may be resigned. The <option>interval</option> option
+ specifies the cycle interval as an offset from the current
+ time (in seconds). If a RRSIG record expires after the
+ cycle interval, it is retained. Otherwise, it is considered
+ to be expiring soon, and it will be replaced.
+ </para>
+ <para>
+ The default cycle interval is one quarter of the difference
+ between the signature end and start times. So if neither
+ <option>end-time</option> or <option>start-time</option>
+ are specified, <command>dnssec-signzone</command>
+ generates
+ signatures that are valid for 30 days, with a cycle
+ interval of 7.5 days. Therefore, if any existing RRSIG records
+ are due to expire in less than 7.5 days, they would be
+ replaced.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-I <replaceable class="parameter">input-format</replaceable></term>
+ <listitem>
+ <para>
+ The format of the input zone file.
+ Possible formats are <command>"text"</command> (default)
+ and <command>"raw"</command>.
+ This option is primarily intended to be used for dynamic
+ signed zones so that the dumped zone file in a non-text
+ format containing updates can be signed directly.
+ The use of this option does not make much sense for
+ non-dynamic zones.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-j <replaceable class="parameter">jitter</replaceable></term>
+ <listitem>
+ <para>
+ When signing a zone with a fixed signature lifetime, all
+ RRSIG records issued at the time of signing expires
+ simultaneously. If the zone is incrementally signed, i.e.
+ a previously-signed zone is passed as input to the signer,
+ all expired signatures have to be regenerated at about the
+ same time. The <option>jitter</option> option specifies a
+ jitter window that will be used to randomize the signature
+ expire time, thus spreading incremental signature
+ regeneration over time.
+ </para>
+ <para>
+ Signature lifetime jitter also to some extent benefits
+ validators and servers by spreading out cache expiration,
+ i.e. if large numbers of RRSIGs don't expire at the same time
+ from all caches there will be less congestion than if all
+ validators need to refetch at mostly the same time.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">ncpus</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the number of threads to use. By default, one
+ thread is started for each detected CPU.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-N <replaceable class="parameter">soa-serial-format</replaceable></term>
+ <listitem>
+ <para>
+ The SOA serial number format of the signed zone.
+ Possible formats are <command>"keep"</command> (default),
+ <command>"increment"</command> and
+ <command>"unixtime"</command>.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>"keep"</command></term>
+ <listitem>
+ <para>Do not modify the SOA serial number.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>"increment"</command></term>
+ <listitem>
+ <para>Increment the SOA serial number using RFC 1982
+ arithmetics.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>"unixtime"</command></term>
+ <listitem>
+ <para>Set the SOA serial number to the number of seconds
+ since epoch.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-o <replaceable class="parameter">origin</replaceable></term>
+ <listitem>
+ <para>
+ The zone origin. If not specified, the name of the zone file
+ is assumed to be the origin.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-O <replaceable class="parameter">output-format</replaceable></term>
+ <listitem>
+ <para>
+ The format of the output file containing the signed zone.
+ Possible formats are <command>"text"</command> (default)
+ and <command>"raw"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p</term>
+ <listitem>
+ <para>
+ Use pseudo-random data when signing the zone. This is faster,
+ but less secure, than using real random data. This option
+ may be useful when signing large zones or when the entropy
+ source is limited.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r <replaceable class="parameter">randomdev</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the source of randomness. If the operating
+ system does not provide a <filename>/dev/random</filename>
+ or equivalent device, the default source of randomness
+ is keyboard input. <filename>randomdev</filename>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <filename>keyboard</filename> indicates that keyboard
+ input should be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t</term>
+ <listitem>
+ <para>
+ Print statistics at completion.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-z</term>
+ <listitem>
+ <para>
+ Ignore KSK flag on key when determining what to sign.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-3 <replaceable class="parameter">salt</replaceable></term>
+ <listitem>
+ <para>
+ Generate a NSEC3 chain with the given hex encoded salt.
+ A dash (<replaceable class="parameter">salt</replaceable>) can
+ be used to indicate that no salt is to be used when generating the NSEC3 chain.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-H <replaceable class="parameter">iterations</replaceable></term>
+ <listitem>
+ <para>
+ When generating a NSEC3 chain use this many interations. The
+ default is 100.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-A</term>
+ <listitem>
+ <para>
+ When generating a NSEC3 chain set the OPTOUT flag on all
+ NSEC3 records and do not generate NSEC3 records for insecure
+ delegations.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>zonefile</term>
+ <listitem>
+ <para>
+ The file containing the zone to be signed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>key</term>
+ <listitem>
+ <para>
+ Specify which keys should be used to sign the zone. If
+ no keys are specified, then the zone will be examined
+ for DNSKEY records at the zone apex. If these are found and
+ there are matching private keys, in the current directory,
+ then these will be used for signing.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>EXAMPLE</title>
+ <para>
+ The following command signs the <userinput>example.com</userinput>
+ zone with the DSA key generated by <command>dnssec-keygen</command>
+ (Kexample.com.+003+17247). The zone's keys must be in the master
+ file (<filename>db.example.com</filename>). This invocation looks
+ for <filename>keyset</filename> files, in the current directory,
+ so that DS records can be generated from them (<command>-g</command>).
+ </para>
+<programlisting>% dnssec-signzone -g -o example.com db.example.com \
+Kexample.com.+003+17247
+db.example.com.signed
+%</programlisting>
+ <para>
+ In the above example, <command>dnssec-signzone</command> creates
+ the file <filename>db.example.com.signed</filename>. This
+ file should be referenced in a zone statement in a
+ <filename>named.conf</filename> file.
+ </para>
+ <para>
+ This example re-signs a previously signed zone with default parameters.
+ The private keys are assumed to be in the current directory.
+ </para>
+<programlisting>% cp db.example.com.signed db.example.com
+% dnssec-signzone -o example.com db.example.com
+db.example.com.signed
+%</programlisting>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 4033</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dnssec/dnssec-signzone.html b/bin/dnssec/dnssec-signzone.html
new file mode 100644
index 0000000..6548d84
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.html
@@ -0,0 +1,302 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+<!-- $Id: dnssec-signzone.html,v 1.33 2008/10/15 01:11:35 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-signzone</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.dnssec-signzone"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-signzone</span> &#8212; DNSSEC zone signing tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-signzone</code> [<code class="option">-a</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-d <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-e <em class="replaceable"><code>end-time</code></em></code>] [<code class="option">-f <em class="replaceable"><code>output-file</code></em></code>] [<code class="option">-g</code>] [<code class="option">-h</code>] [<code class="option">-k <em class="replaceable"><code>key</code></em></code>] [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>] [<code class="option">-i <em class="replaceable"><code>interval</code></em></code>] [<code class="option">-I <em class="replaceable"><code>input-format</code></em></code>] [<code class="option">-j <em class="replaceable"><code>jitter</code></em></code>] [<code class="option">-N <em class="replaceable"><code>soa-serial-format</code></em></code>] [<code class="option">-o <em class="replaceable"><code>origin</code></em></code>] [<code class="option">-O <em class="replaceable"><code>output-format</code></em></code>] [<code class="option">-p</code>] [<code class="option">-r <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-s <em class="replaceable"><code>start-time</code></em></code>] [<code class="option">-t</code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-z</code>] [<code class="option">-3 <em class="replaceable"><code>salt</code></em></code>] [<code class="option">-H <em class="replaceable"><code>iterations</code></em></code>] [<code class="option">-A</code>] {zonefile} [key...]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543550"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-signzone</strong></span>
+ signs a zone. It generates
+ NSEC and RRSIG records and produces a signed version of the
+ zone. The security status of delegations from the signed zone
+ (that is, whether the child zones are secure or not) is
+ determined by the presence or absence of a
+ <code class="filename">keyset</code> file for each child zone.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543565"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-a</span></dt>
+<dd><p>
+ Verify all generated signatures.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Specifies the DNS class of the zone.
+ </p></dd>
+<dt><span class="term">-k <em class="replaceable"><code>key</code></em></span></dt>
+<dd><p>
+ Treat specified key as a key signing key ignoring any
+ key flags. This option may be specified multiple times.
+ </p></dd>
+<dt><span class="term">-l <em class="replaceable"><code>domain</code></em></span></dt>
+<dd><p>
+ Generate a DLV set in addition to the key (DNSKEY) and DS sets.
+ The domain is appended to the name of the records.
+ </p></dd>
+<dt><span class="term">-d <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ Look for <code class="filename">keyset</code> files in
+ <code class="option">directory</code> as the directory
+ </p></dd>
+<dt><span class="term">-g</span></dt>
+<dd><p>
+ Generate DS records for child zones from keyset files.
+ Existing DS records will be removed.
+ </p></dd>
+<dt><span class="term">-s <em class="replaceable"><code>start-time</code></em></span></dt>
+<dd><p>
+ Specify the date and time when the generated RRSIG records
+ become valid. This can be either an absolute or relative
+ time. An absolute start time is indicated by a number
+ in YYYYMMDDHHMMSS notation; 20000530144500 denotes
+ 14:45:00 UTC on May 30th, 2000. A relative start time is
+ indicated by +N, which is N seconds from the current time.
+ If no <code class="option">start-time</code> is specified, the current
+ time minus 1 hour (to allow for clock skew) is used.
+ </p></dd>
+<dt><span class="term">-e <em class="replaceable"><code>end-time</code></em></span></dt>
+<dd><p>
+ Specify the date and time when the generated RRSIG records
+ expire. As with <code class="option">start-time</code>, an absolute
+ time is indicated in YYYYMMDDHHMMSS notation. A time relative
+ to the start time is indicated with +N, which is N seconds from
+ the start time. A time relative to the current time is
+ indicated with now+N. If no <code class="option">end-time</code> is
+ specified, 30 days from the start time is used as a default.
+ </p></dd>
+<dt><span class="term">-f <em class="replaceable"><code>output-file</code></em></span></dt>
+<dd><p>
+ The name of the output file containing the signed zone. The
+ default is to append <code class="filename">.signed</code> to
+ the
+ input filename.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Prints a short summary of the options and arguments to
+ <span><strong class="command">dnssec-signzone</strong></span>.
+ </p></dd>
+<dt><span class="term">-i <em class="replaceable"><code>interval</code></em></span></dt>
+<dd>
+<p>
+ When a previously-signed zone is passed as input, records
+ may be resigned. The <code class="option">interval</code> option
+ specifies the cycle interval as an offset from the current
+ time (in seconds). If a RRSIG record expires after the
+ cycle interval, it is retained. Otherwise, it is considered
+ to be expiring soon, and it will be replaced.
+ </p>
+<p>
+ The default cycle interval is one quarter of the difference
+ between the signature end and start times. So if neither
+ <code class="option">end-time</code> or <code class="option">start-time</code>
+ are specified, <span><strong class="command">dnssec-signzone</strong></span>
+ generates
+ signatures that are valid for 30 days, with a cycle
+ interval of 7.5 days. Therefore, if any existing RRSIG records
+ are due to expire in less than 7.5 days, they would be
+ replaced.
+ </p>
+</dd>
+<dt><span class="term">-I <em class="replaceable"><code>input-format</code></em></span></dt>
+<dd><p>
+ The format of the input zone file.
+ Possible formats are <span><strong class="command">"text"</strong></span> (default)
+ and <span><strong class="command">"raw"</strong></span>.
+ This option is primarily intended to be used for dynamic
+ signed zones so that the dumped zone file in a non-text
+ format containing updates can be signed directly.
+ The use of this option does not make much sense for
+ non-dynamic zones.
+ </p></dd>
+<dt><span class="term">-j <em class="replaceable"><code>jitter</code></em></span></dt>
+<dd>
+<p>
+ When signing a zone with a fixed signature lifetime, all
+ RRSIG records issued at the time of signing expires
+ simultaneously. If the zone is incrementally signed, i.e.
+ a previously-signed zone is passed as input to the signer,
+ all expired signatures have to be regenerated at about the
+ same time. The <code class="option">jitter</code> option specifies a
+ jitter window that will be used to randomize the signature
+ expire time, thus spreading incremental signature
+ regeneration over time.
+ </p>
+<p>
+ Signature lifetime jitter also to some extent benefits
+ validators and servers by spreading out cache expiration,
+ i.e. if large numbers of RRSIGs don't expire at the same time
+ from all caches there will be less congestion than if all
+ validators need to refetch at mostly the same time.
+ </p>
+</dd>
+<dt><span class="term">-n <em class="replaceable"><code>ncpus</code></em></span></dt>
+<dd><p>
+ Specifies the number of threads to use. By default, one
+ thread is started for each detected CPU.
+ </p></dd>
+<dt><span class="term">-N <em class="replaceable"><code>soa-serial-format</code></em></span></dt>
+<dd>
+<p>
+ The SOA serial number format of the signed zone.
+ Possible formats are <span><strong class="command">"keep"</strong></span> (default),
+ <span><strong class="command">"increment"</strong></span> and
+ <span><strong class="command">"unixtime"</strong></span>.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">"keep"</strong></span></span></dt>
+<dd><p>Do not modify the SOA serial number.</p></dd>
+<dt><span class="term"><span><strong class="command">"increment"</strong></span></span></dt>
+<dd><p>Increment the SOA serial number using RFC 1982
+ arithmetics.</p></dd>
+<dt><span class="term"><span><strong class="command">"unixtime"</strong></span></span></dt>
+<dd><p>Set the SOA serial number to the number of seconds
+ since epoch.</p></dd>
+</dl></div>
+</dd>
+<dt><span class="term">-o <em class="replaceable"><code>origin</code></em></span></dt>
+<dd><p>
+ The zone origin. If not specified, the name of the zone file
+ is assumed to be the origin.
+ </p></dd>
+<dt><span class="term">-O <em class="replaceable"><code>output-format</code></em></span></dt>
+<dd><p>
+ The format of the output file containing the signed zone.
+ Possible formats are <span><strong class="command">"text"</strong></span> (default)
+ and <span><strong class="command">"raw"</strong></span>.
+ </p></dd>
+<dt><span class="term">-p</span></dt>
+<dd><p>
+ Use pseudo-random data when signing the zone. This is faster,
+ but less secure, than using real random data. This option
+ may be useful when signing large zones or when the entropy
+ source is limited.
+ </p></dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomdev</code></em></span></dt>
+<dd><p>
+ Specifies the source of randomness. If the operating
+ system does not provide a <code class="filename">/dev/random</code>
+ or equivalent device, the default source of randomness
+ is keyboard input. <code class="filename">randomdev</code>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard
+ input should be used.
+ </p></dd>
+<dt><span class="term">-t</span></dt>
+<dd><p>
+ Print statistics at completion.
+ </p></dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+<dt><span class="term">-z</span></dt>
+<dd><p>
+ Ignore KSK flag on key when determining what to sign.
+ </p></dd>
+<dt><span class="term">-3 <em class="replaceable"><code>salt</code></em></span></dt>
+<dd><p>
+ Generate a NSEC3 chain with the given hex encoded salt.
+ A dash (<em class="replaceable"><code>salt</code></em>) can
+ be used to indicate that no salt is to be used when generating the NSEC3 chain.
+ </p></dd>
+<dt><span class="term">-H <em class="replaceable"><code>iterations</code></em></span></dt>
+<dd><p>
+ When generating a NSEC3 chain use this many interations. The
+ default is 100.
+ </p></dd>
+<dt><span class="term">-A</span></dt>
+<dd><p>
+ When generating a NSEC3 chain set the OPTOUT flag on all
+ NSEC3 records and do not generate NSEC3 records for insecure
+ delegations.
+ </p></dd>
+<dt><span class="term">zonefile</span></dt>
+<dd><p>
+ The file containing the zone to be signed.
+ </p></dd>
+<dt><span class="term">key</span></dt>
+<dd><p>
+ Specify which keys should be used to sign the zone. If
+ no keys are specified, then the zone will be examined
+ for DNSKEY records at the zone apex. If these are found and
+ there are matching private keys, in the current directory,
+ then these will be used for signing.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544404"></a><h2>EXAMPLE</h2>
+<p>
+ The following command signs the <strong class="userinput"><code>example.com</code></strong>
+ zone with the DSA key generated by <span><strong class="command">dnssec-keygen</strong></span>
+ (Kexample.com.+003+17247). The zone's keys must be in the master
+ file (<code class="filename">db.example.com</code>). This invocation looks
+ for <code class="filename">keyset</code> files, in the current directory,
+ so that DS records can be generated from them (<span><strong class="command">-g</strong></span>).
+ </p>
+<pre class="programlisting">% dnssec-signzone -g -o example.com db.example.com \
+Kexample.com.+003+17247
+db.example.com.signed
+%</pre>
+<p>
+ In the above example, <span><strong class="command">dnssec-signzone</strong></span> creates
+ the file <code class="filename">db.example.com.signed</code>. This
+ file should be referenced in a zone statement in a
+ <code class="filename">named.conf</code> file.
+ </p>
+<p>
+ This example re-signs a previously signed zone with default parameters.
+ The private keys are assumed to be in the current directory.
+ </p>
+<pre class="programlisting">% cp db.example.com.signed db.example.com
+% dnssec-signzone -o example.com db.example.com
+db.example.com.signed
+%</pre>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544523"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 4033</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544548"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c
new file mode 100644
index 0000000..e933a06
--- /dev/null
+++ b/bin/dnssec/dnssectool.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dnssectool.c,v 1.45 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+/*%
+ * DNSSEC Support Routines.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/list.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+#include <isc/print.h>
+
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+#include <dns/time.h>
+
+#include "dnssectool.h"
+
+extern int verbose;
+extern const char *program;
+
+typedef struct entropysource entropysource_t;
+
+struct entropysource {
+ isc_entropysource_t *source;
+ isc_mem_t *mctx;
+ ISC_LINK(entropysource_t) link;
+};
+
+static ISC_LIST(entropysource_t) sources;
+static fatalcallback_t *fatalcallback = NULL;
+
+void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fprintf(stderr, "%s: ", program);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ if (fatalcallback != NULL)
+ (*fatalcallback)();
+ exit(1);
+}
+
+void
+setfatalcallback(fatalcallback_t *callback) {
+ fatalcallback = callback;
+}
+
+void
+check_result(isc_result_t result, const char *message) {
+ if (result != ISC_R_SUCCESS)
+ fatal("%s: %s", message, isc_result_totext(result));
+}
+
+void
+vbprintf(int level, const char *fmt, ...) {
+ va_list ap;
+ if (level > verbose)
+ return;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s: ", program);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+void
+type_format(const dns_rdatatype_t type, 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_rdatatype_totext(type, &b);
+ check_result(result, "dns_rdatatype_totext()");
+ isc_buffer_usedregion(&b, &r);
+ r.base[r.length] = 0;
+}
+
+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));
+ 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;
+ isc_logconfig_t *logconfig = NULL;
+ isc_log_t *log = NULL;
+ int level;
+
+ if (verbose < 0)
+ verbose = 0;
+ switch (verbose) {
+ case 0:
+ /*
+ * We want to see warnings about things like out-of-zone
+ * data in the master file even when not verbose.
+ */
+ level = ISC_LOG_WARNING;
+ break;
+ case 1:
+ level = ISC_LOG_INFO;
+ break;
+ default:
+ level = ISC_LOG_DEBUG(verbose - 2 + 1);
+ break;
+ }
+
+ RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
+ isc_log_setcontext(log);
+ dns_log_init(log);
+ dns_log_setcontext(log);
+
+ RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS);
+
+ /*
+ * Set up a channel similar to default_stderr except:
+ * - the logging level is passed in
+ * - the program name and logging level are printed
+ * - no time stamp is printed
+ */
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ result = isc_log_createchannel(logconfig, "stderr",
+ ISC_LOG_TOFILEDESC,
+ level,
+ &destination,
+ ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL);
+ check_result(result, "isc_log_createchannel()");
+
+ RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
+ NULL, NULL) == ISC_R_SUCCESS);
+
+ *logp = log;
+}
+
+void
+cleanup_logging(isc_log_t **logp) {
+ isc_log_t *log;
+
+ REQUIRE(logp != NULL);
+
+ log = *logp;
+ if (log == NULL)
+ return;
+ isc_log_destroy(&log);
+ isc_log_setcontext(NULL);
+ dns_log_setcontext(NULL);
+ logp = NULL;
+}
+
+void
+setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
+ isc_result_t result;
+ isc_entropysource_t *source = NULL;
+ entropysource_t *elt;
+ int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
+
+ REQUIRE(ectx != NULL);
+
+ if (*ectx == NULL) {
+ result = isc_entropy_create(mctx, ectx);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not create entropy object");
+ ISC_LIST_INIT(sources);
+ }
+
+ if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
+ usekeyboard = ISC_ENTROPY_KEYBOARDYES;
+ randomfile = NULL;
+ }
+
+ result = isc_entropy_usebestsource(*ectx, &source, randomfile,
+ usekeyboard);
+
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize entropy source: %s",
+ isc_result_totext(result));
+
+ if (source != NULL) {
+ elt = isc_mem_get(mctx, sizeof(*elt));
+ if (elt == NULL)
+ fatal("out of memory");
+ elt->source = source;
+ elt->mctx = mctx;
+ ISC_LINK_INIT(elt, link);
+ ISC_LIST_APPEND(sources, elt, link);
+ }
+}
+
+void
+cleanup_entropy(isc_entropy_t **ectx) {
+ entropysource_t *source;
+ while (!ISC_LIST_EMPTY(sources)) {
+ source = ISC_LIST_HEAD(sources);
+ ISC_LIST_UNLINK(sources, source, link);
+ isc_entropy_destroysource(&source->source);
+ isc_mem_put(source->mctx, source, sizeof(*source));
+ }
+ isc_entropy_detach(ectx);
+}
+
+isc_stdtime_t
+strtotime(const char *str, isc_int64_t now, isc_int64_t base) {
+ isc_int64_t val, offset;
+ isc_result_t result;
+ char *endp;
+
+ if (str[0] == '+') {
+ offset = strtol(str + 1, &endp, 0);
+ if (*endp != '\0')
+ fatal("time value %s is invalid", str);
+ 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 (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);
+ } else {
+ result = dns_time64_fromtext(str, &val);
+ if (result != ISC_R_SUCCESS)
+ fatal("time value %s is invalid", str);
+ }
+
+ return ((isc_stdtime_t) val);
+}
+
+dns_rdataclass_t
+strtoclass(const char *str) {
+ isc_textregion_t r;
+ dns_rdataclass_t rdclass;
+ isc_result_t ret;
+
+ if (str == NULL)
+ return dns_rdataclass_in;
+ DE_CONST(str, r.base);
+ r.length = strlen(str);
+ ret = dns_rdataclass_fromtext(&rdclass, &r);
+ if (ret != ISC_R_SUCCESS)
+ fatal("unknown class %s", str);
+ return (rdclass);
+}
diff --git a/bin/dnssec/dnssectool.h b/bin/dnssec/dnssectool.h
new file mode 100644
index 0000000..ee476f4
--- /dev/null
+++ b/bin/dnssec/dnssectool.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 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
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dnssectool.h,v 1.22 2008/09/25 04:02:38 tbox Exp $ */
+
+#ifndef DNSSECTOOL_H
+#define DNSSECTOOL_H 1
+
+#include <isc/log.h>
+#include <isc/stdtime.h>
+#include <dns/rdatastruct.h>
+#include <dst/dst.h>
+
+typedef void (fatalcallback_t)(void);
+
+void
+fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+setfatalcallback(fatalcallback_t *callback);
+
+void
+check_result(isc_result_t result, const char *message);
+
+void
+vbprintf(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
+
+void
+type_format(const dns_rdatatype_t type, char *cp, unsigned int size);
+#define TYPE_FORMATSIZE 20
+
+void
+alg_format(const dns_secalg_t alg, char *cp, unsigned int size);
+#define ALG_FORMATSIZE 10
+
+void
+sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size);
+#define SIG_FORMATSIZE (DNS_NAME_FORMATSIZE + ALG_FORMATSIZE + sizeof("65535"))
+
+void
+key_format(const dst_key_t *key, char *cp, unsigned int size);
+#define KEY_FORMATSIZE (DNS_NAME_FORMATSIZE + ALG_FORMATSIZE + sizeof("65535"))
+
+void
+setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp);
+
+void
+cleanup_logging(isc_log_t **logp);
+
+void
+setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx);
+
+void
+cleanup_entropy(isc_entropy_t **ectx);
+
+isc_stdtime_t
+strtotime(const char *str, isc_int64_t now, isc_int64_t base);
+
+dns_rdataclass_t
+strtoclass(const char *str);
+
+#endif /* DNSSEC_DNSSECTOOL_H */
diff --git a/bin/dnssec/win32/dnssectool.dsp b/bin/dnssec/win32/dnssectool.dsp
new file mode 100644
index 0000000..ebc4b11
--- /dev/null
+++ b/bin/dnssec/win32/dnssectool.dsp
@@ -0,0 +1,113 @@
+# Microsoft Developer Studio Project File - Name="dnssectool" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static-Link Library" 0x0104
+
+CFG=dnssectool - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dnssectool.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dnssectool.mak" CFG="dnssectool - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dnssectool - Win32 Release" (based on "Win32 (x86) Static-Link Library")
+!MESSAGE "dnssectool - Win32 Debug" (based on "Win32 (x86) Static-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dnssectool - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /YX /FD /c /Fddnssectool
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /out:"Release/dnssectool.lib"
+
+!ELSEIF "$(CFG)" == "dnssectool - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR /YX /FD /GZ /c /Fddnssectool
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /debug out:"Debug/dnssectool.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "dnssectool - Win32 Release"
+# Name "dnssectool - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Dns Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\dnssectool.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/dnssectool.dsw b/bin/dnssec/win32/dnssectool.dsw
new file mode 100644
index 0000000..1049441
--- /dev/null
+++ b/bin/dnssec/win32/dnssectool.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "dighost"=".\dnssectool.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/dsfromkey.dsp b/bin/dnssec/win32/dsfromkey.dsp
new file mode 100644
index 0000000..6557bfb
--- /dev/null
+++ b/bin/dnssec/win32/dsfromkey.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="dsfromkey" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=dsfromkey - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dsfromkey.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dsfromkey.mak" CFG="dsfromkey - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dsfromkey - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "dsfromkey - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dsfromkey - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/dnssec-dsfromkey.exe"
+
+!ELSEIF "$(CFG)" == "dsfromkey - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/dnssec-dsfromkey.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "dsfromkey - Win32 Release"
+# Name "dsfromkey - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-dsfromkey.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/dsfromkey.dsw b/bin/dnssec/win32/dsfromkey.dsw
new file mode 100644
index 0000000..62b5c48
--- /dev/null
+++ b/bin/dnssec/win32/dsfromkey.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "dsfromkey"=".\dsfromkey.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/dsfromkey.mak b/bin/dnssec/win32/dsfromkey.mak
new file mode 100644
index 0000000..41612d2
--- /dev/null
+++ b/bin/dnssec/win32/dsfromkey.mak
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on dsfromkey.dsp
+!IF "$(CFG)" == ""
+CFG=dsfromkey - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to dsfromkey - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "dsfromkey - Win32 Release" && "$(CFG)" != "dsfromkey - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dsfromkey.mak" CFG="dsfromkey - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dsfromkey - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "dsfromkey - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "dsfromkey - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "dsfromkey - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-dsfromkey.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-dsfromkey.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-dsfromkey.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\dsfromkey.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\dsfromkey.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-dsfromkey.pdb" /machine:I386 /out:"../../../Build/Release/dnssec-dsfromkey.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-dsfromkey.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-dsfromkey.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "dsfromkey - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-dsfromkey.exe" "$(OUTDIR)\dsfromkey.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-dsfromkey.obj"
+ -@erase "$(INTDIR)\dnssec-dsfromkey.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-dsfromkey.pdb"
+ -@erase "$(OUTDIR)\dsfromkey.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-dsfromkey.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-dsfromkey.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\dsfromkey.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-dsfromkey.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\dsfromkey.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-dsfromkey.pdb" /debug /machine:I386 /out:"../../../Build/Debug/dnssec-dsfromkey.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-dsfromkey.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-dsfromkey.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("dsfromkey.dep")
+!INCLUDE "dsfromkey.dep"
+!ELSE
+!MESSAGE Warning: cannot find "dsfromkey.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "dsfromkey - Win32 Release" || "$(CFG)" == "dsfromkey - Win32 Debug"
+SOURCE="..\dnssec-dsfromkey.c"
+
+!IF "$(CFG)" == "dsfromkey - Win32 Release"
+
+
+"$(INTDIR)\dnssec-dsfromkey.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "dsfromkey - Win32 Debug"
+
+
+"$(INTDIR)\dnssec-dsfromkey.obj" "$(INTDIR)\dnssec-dsfromkey.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "dsfromkey - Win32 Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "dsfromkey - Win32 Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/win32/keyfromlabel.dsp b/bin/dnssec/win32/keyfromlabel.dsp
new file mode 100644
index 0000000..b285b7c
--- /dev/null
+++ b/bin/dnssec/win32/keyfromlabel.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="keyfromlabel" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=keyfromlabel - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "keyfromlabel.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keyfromlabel.mak" CFG="keyfromlabel - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keyfromlabel - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "keyfromlabel - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "keyfromlabel - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/dnssec-keyfromlabel.exe"
+
+!ELSEIF "$(CFG)" == "keyfromlabel - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/dnssec-keyfromlabel.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "keyfromlabel - Win32 Release"
+# Name "keyfromlabel - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-keyfromlabel.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/keyfromlabel.dsw b/bin/dnssec/win32/keyfromlabel.dsw
new file mode 100644
index 0000000..085c24d
--- /dev/null
+++ b/bin/dnssec/win32/keyfromlabel.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "keyfromlabel"=".\keyfromlabel.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/keyfromlabel.mak b/bin/dnssec/win32/keyfromlabel.mak
new file mode 100644
index 0000000..6c5d405
--- /dev/null
+++ b/bin/dnssec/win32/keyfromlabel.mak
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on keyfromlabel.dsp
+!IF "$(CFG)" == ""
+CFG=keyfromlabel - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to keyfromlabel - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "keyfromlabel - Win32 Release" && "$(CFG)" != "keyfromlabel - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keyfromlabel.mak" CFG="keyfromlabel - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keyfromlabel - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "keyfromlabel - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "keyfromlabel - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "keyfromlabel - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-keyfromlabel.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-keyfromlabel.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-keyfromlabel.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\keyfromlabel.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keyfromlabel.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-keyfromlabel.pdb" /machine:I386 /out:"../../../Build/Release/dnssec-keyfromlabel.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-keyfromlabel.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-keyfromlabel.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "keyfromlabel - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-keyfromlabel.exe" "$(OUTDIR)\keyfromlabel.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-keyfromlabel.obj"
+ -@erase "$(INTDIR)\dnssec-keyfromlabel.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-keyfromlabel.pdb"
+ -@erase "$(OUTDIR)\keyfromlabel.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-keyfromlabel.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-keyfromlabel.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keyfromlabel.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-keyfromlabel.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\keyfromlabel.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-keyfromlabel.pdb" /debug /machine:I386 /out:"../../../Build/Debug/dnssec-keyfromlabel.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-keyfromlabel.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-keyfromlabel.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("keyfromlabel.dep")
+!INCLUDE "keyfromlabel.dep"
+!ELSE
+!MESSAGE Warning: cannot find "keyfromlabel.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "keyfromlabel - Win32 Release" || "$(CFG)" == "keyfromlabel - Win32 Debug"
+SOURCE="..\dnssec-keyfromlabel.c"
+
+!IF "$(CFG)" == "keyfromlabel - Win32 Release"
+
+
+"$(INTDIR)\dnssec-keyfromlabel.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "keyfromlabel - Win32 Debug"
+
+
+"$(INTDIR)\dnssec-keyfromlabel.obj" "$(INTDIR)\dnssec-keyfromlabel.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "keyfromlabel - Win32 Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "keyfromlabel - Win32 Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/win32/keygen.dsp b/bin/dnssec/win32/keygen.dsp
new file mode 100644
index 0000000..5eb70f0
--- /dev/null
+++ b/bin/dnssec/win32/keygen.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="keygen" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=keygen - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "keygen.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keygen.mak" CFG="keygen - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keygen - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "keygen - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "keygen - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/dnssec-keygen.exe"
+
+!ELSEIF "$(CFG)" == "keygen - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/dnssec-keygen.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "keygen - Win32 Release"
+# Name "keygen - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-keygen.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/keygen.dsw b/bin/dnssec/win32/keygen.dsw
new file mode 100644
index 0000000..f988651
--- /dev/null
+++ b/bin/dnssec/win32/keygen.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "keygen"=".\keygen.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/keygen.mak b/bin/dnssec/win32/keygen.mak
new file mode 100644
index 0000000..faf134a
--- /dev/null
+++ b/bin/dnssec/win32/keygen.mak
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on keygen.dsp
+!IF "$(CFG)" == ""
+CFG=keygen - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to keygen - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "keygen - Win32 Release" && "$(CFG)" != "keygen - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keygen.mak" CFG="keygen - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keygen - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "keygen - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "keygen - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "keygen - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-keygen.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-keygen.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-keygen.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\keygen.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keygen.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-keygen.pdb" /machine:I386 /out:"../../../Build/Release/dnssec-keygen.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-keygen.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-keygen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "keygen - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-keygen.exe" "$(OUTDIR)\keygen.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-keygen.obj"
+ -@erase "$(INTDIR)\dnssec-keygen.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-keygen.pdb"
+ -@erase "$(OUTDIR)\keygen.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-keygen.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-keygen.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keygen.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-keygen.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\keygen.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-keygen.pdb" /debug /machine:I386 /out:"../../../Build/Debug/dnssec-keygen.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-keygen.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-keygen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("keygen.dep")
+!INCLUDE "keygen.dep"
+!ELSE
+!MESSAGE Warning: cannot find "keygen.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "keygen - Win32 Release" || "$(CFG)" == "keygen - Win32 Debug"
+SOURCE="..\dnssec-keygen.c"
+
+!IF "$(CFG)" == "keygen - Win32 Release"
+
+
+"$(INTDIR)\dnssec-keygen.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "keygen - Win32 Debug"
+
+
+"$(INTDIR)\dnssec-keygen.obj" "$(INTDIR)\dnssec-keygen.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "keygen - Win32 Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "keygen - Win32 Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/win32/nsupdate.dsp b/bin/dnssec/win32/nsupdate.dsp
new file mode 100644
index 0000000..a818f42
--- /dev/null
+++ b/bin/dnssec/win32/nsupdate.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="nsupdate" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=nsupdate - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "nsupdate.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nsupdate.mak" CFG="nsupdate - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nsupdate - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "nsupdate - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nsupdate - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/lwres/win32/Release/liblwres.lib user32.lib advapi32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/nsupdate.exe"
+
+!ELSEIF "$(CFG)" == "nsupdate - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/lwres/win32/Debug/liblwres.lib user32.lib advapi32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/nsupdate.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "nsupdate - Win32 Release"
+# Name "nsupdate - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\nsupdate.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/nsupdate.dsw b/bin/dnssec/win32/nsupdate.dsw
new file mode 100644
index 0000000..5f0ac36
--- /dev/null
+++ b/bin/dnssec/win32/nsupdate.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "nsupdate"=".\nsupdate.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/signzone.dsp b/bin/dnssec/win32/signzone.dsp
new file mode 100644
index 0000000..6fd45d8
--- /dev/null
+++ b/bin/dnssec/win32/signzone.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="signzone" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=signzone - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "signzone.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "signzone.mak" CFG="signzone - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "signzone - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "signzone - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "signzone - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/dnssec-signzone.exe"
+
+!ELSEIF "$(CFG)" == "signzone - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/dnssec-signzone.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "signzone - Win32 Release"
+# Name "signzone - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-signzone.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/signzone.dsw b/bin/dnssec/win32/signzone.dsw
new file mode 100644
index 0000000..f3314b9
--- /dev/null
+++ b/bin/dnssec/win32/signzone.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "signzone"=".\signzone.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/signzone.mak b/bin/dnssec/win32/signzone.mak
new file mode 100644
index 0000000..ff4887c
--- /dev/null
+++ b/bin/dnssec/win32/signzone.mak
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on signzone.dsp
+!IF "$(CFG)" == ""
+CFG=signzone - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to signzone - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "signzone - Win32 Release" && "$(CFG)" != "signzone - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "signzone.mak" CFG="signzone - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "signzone - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "signzone - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "signzone - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "signzone - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-signzone.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-signzone.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-signzone.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\signzone.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\signzone.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-signzone.pdb" /machine:I386 /out:"../../../Build/Release/dnssec-signzone.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-signzone.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-signzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "signzone - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-signzone.exe" "$(OUTDIR)\signzone.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-signzone.obj"
+ -@erase "$(INTDIR)\dnssec-signzone.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-signzone.pdb"
+ -@erase "$(OUTDIR)\signzone.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-signzone.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-signzone.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\signzone.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-signzone.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\signzone.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-signzone.pdb" /debug /machine:I386 /out:"../../../Build/Debug/dnssec-signzone.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-signzone.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-signzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("signzone.dep")
+!INCLUDE "signzone.dep"
+!ELSE
+!MESSAGE Warning: cannot find "signzone.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "signzone - Win32 Release" || "$(CFG)" == "signzone - Win32 Debug"
+SOURCE="..\dnssec-signzone.c"
+
+!IF "$(CFG)" == "signzone - Win32 Release"
+
+
+"$(INTDIR)\dnssec-signzone.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "signzone - Win32 Debug"
+
+
+"$(INTDIR)\dnssec-signzone.obj" "$(INTDIR)\dnssec-signzone.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "signzone - Win32 Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "signzone - Win32 Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP