aboutsummaryrefslogtreecommitdiff
path: root/contrib/bind9/bin/dnssec
diff options
context:
space:
mode:
authorTom Rhodes <trhodes@FreeBSD.org>2004-09-19 01:30:24 +0000
committerTom Rhodes <trhodes@FreeBSD.org>2004-09-19 01:30:24 +0000
commitb1e4bd53e00e9694dd378a884abd3f2dd790190d (patch)
tree97706b7f62557da0a2539b026e5cf66008ddf8c6 /contrib/bind9/bin/dnssec
Vender import of BIND 9.3.0rc4.
Notes
Notes: svn path=/vendor/bind9/dist/; revision=135446
Diffstat (limited to 'contrib/bind9/bin/dnssec')
-rw-r--r--contrib/bind9/bin/dnssec/Makefile.in82
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-keygen.8174
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-keygen.c415
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-keygen.docbook342
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-keygen.html544
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-makekeyset.8113
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-makekeyset.c401
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-makekeyset.docbook233
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-makekeyset.html407
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-signkey.8108
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-signkey.c448
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-signkey.docbook237
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-signkey.html407
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-signzone.8167
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-signzone.c2102
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-signzone.docbook362
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-signzone.html553
-rw-r--r--contrib/bind9/bin/dnssec/dnssectool.c305
-rw-r--r--contrib/bind9/bin/dnssec/dnssectool.h76
19 files changed, 7476 insertions, 0 deletions
diff --git a/contrib/bind9/bin/dnssec/Makefile.in b/contrib/bind9/bin/dnssec/Makefile.in
new file mode 100644
index 000000000000..993c54e4067f
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/Makefile.in
@@ -0,0 +1,82 @@
+# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 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: Makefile.in,v 1.19.12.9 2004/07/20 07:01:48 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@
+
+OBJS = dnssectool.@O@
+
+SRCS = dnssec-keygen.c dnssec-signzone.c dnssectool.c
+
+MANPAGES = dnssec-keygen.8 dnssec-signzone.8
+
+HTMLPAGES = dnssec-keygen.html dnssec-signzone.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+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} ${PURIFY} ${CC} ${ALL_CFLAGS} -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/contrib/bind9/bin/dnssec/dnssec-keygen.8 b/contrib/bind9/bin/dnssec/dnssec-keygen.8
new file mode 100644
index 000000000000..235c26ea32f9
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-keygen.8
@@ -0,0 +1,174 @@
+.\" Copyright (C) 2004 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.19.12.5 2004/06/11 02:32:45 marka Exp $
+.\"
+.TH "DNSSEC-KEYGEN" "8" "June 30, 2000" "BIND9" ""
+.SH NAME
+dnssec-keygen \- DNSSEC key generation tool
+.SH SYNOPSIS
+.sp
+\fBdnssec-keygen\fR \fB-a \fIalgorithm\fB\fR \fB-b \fIkeysize\fB\fR \fB-n \fInametype\fB\fR [ \fB-c \fIclass\fB\fR ] [ \fB-e\fR ] [ \fB-f \fIflag\fB\fR ] [ \fB-g \fIgenerator\fB\fR ] [ \fB-h\fR ] [ \fB-k\fR ] [ \fB-p \fIprotocol\fB\fR ] [ \fB-r \fIrandomdev\fB\fR ] [ \fB-s \fIstrength\fB\fR ] [ \fB-t \fItype\fB\fR ] [ \fB-v \fIlevel\fB\fR ] \fBname\fR
+.SH "DESCRIPTION"
+.PP
+\fBdnssec-keygen\fR generates keys for DNSSEC
+(Secure DNS), as defined in RFC 2535 and RFC <TBA\\>. It can also generate
+keys for use with TSIG (Transaction Signatures), as
+defined in RFC 2845.
+.SH "OPTIONS"
+.TP
+\fB-a \fIalgorithm\fB\fR
+Selects the cryptographic algorithm. The value of
+\fBalgorithm\fR must be one of RSAMD5 (RSA) or RSASHA1,
+DSA, DH (Diffie Hellman), or HMAC-MD5. These values
+are case insensitive.
+
+Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm,
+and DSA is recommended. For TSIG, HMAC-MD5 is mandatory.
+
+Note 2: HMAC-MD5 and DH automatically set the -k flag.
+.TP
+\fB-b \fIkeysize\fB\fR
+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.
+.TP
+\fB-n \fInametype\fB\fR
+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.
+.TP
+\fB-c \fIclass\fB\fR
+Indicates that the DNS record containing the key should have
+the specified class. If not specified, class IN is used.
+.TP
+\fB-e\fR
+If generating an RSAMD5/RSASHA1 key, use a large exponent.
+.TP
+\fB-f \fIflag\fB\fR
+Set the specified flag in the flag field of the KEY/DNSKEY record.
+The only recognized flag is KSK (Key Signing Key) DNSKEY.
+.TP
+\fB-g \fIgenerator\fB\fR
+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.
+.TP
+\fB-h\fR
+Prints a short summary of the options and arguments to
+\fBdnssec-keygen\fR.
+.TP
+\fB-k\fR
+Generate KEY records rather than DNSKEY records.
+.TP
+\fB-p \fIprotocol\fB\fR
+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.
+.TP
+\fB-r \fIrandomdev\fB\fR
+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.
+.TP
+\fB-s \fIstrength\fB\fR
+Specifies the strength value of the key. The strength is
+a number between 0 and 15, and currently has no defined
+purpose in DNSSEC.
+.TP
+\fB-t \fItype\fB\fR
+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.
+.TP
+\fB-v \fIlevel\fB\fR
+Sets the debugging level.
+.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. These strings can be used as arguments
+to \fBdnssec-makekeyset\fR.
+.TP 0.2i
+\(bu
+\fInnnn\fR is the key name.
+.TP 0.2i
+\(bu
+\fIaaa\fR is the numeric representation of the
+algorithm.
+.TP 0.2i
+\(bu
+\fIiiiii\fR is the key identifier (or footprint).
+.PP
+\fBdnssec-keygen\fR creates two file, 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
+.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
+.PP
+The \fI.private\fR file contains algorithm specific
+fields. For obvious security reasons, this file does not have
+general read permission.
+.PP
+.PP
+Both \fI.key\fR and \fI.private\fR
+files are generated for symmetric encryption algorithm such as
+HMAC-MD5, even though the public and private key are equivalent.
+.PP
+.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),
+\fIBIND 9 Administrator Reference Manual\fR,
+\fIRFC 2535\fR,
+\fIRFC 2845\fR,
+\fIRFC 2539\fR.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
diff --git a/contrib/bind9/bin/dnssec/dnssec-keygen.c b/contrib/bind9/bin/dnssec/dnssec-keygen.c
new file mode 100644
index 000000000000..7feaf7c3d977
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-keygen.c
@@ -0,0 +1,415 @@
+/*
+ * Portions Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2000-2003 Internet Software Consortium.
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 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.48.2.1.10.11 2004/06/11 01:17:34 marka Exp $ */
+
+#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 | HMAC-MD5";
+
+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, " DH:\t\t[128..4096]\n");
+ fprintf(stderr, " DSA:\t\t[512..1024] and divisible by 64\n");
+ fprintf(stderr, " HMAC-MD5:\t[1..512]\n");
+ fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n");
+ fprintf(stderr, " name: owner of the key\n");
+ fprintf(stderr, "Other options:\n");
+ fprintf(stderr, " -c <class> (default: IN)\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;
+
+ if (argc == 1)
+ usage();
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ dns_result_register();
+
+ while ((ch = isc_commandline_parse(argc, argv,
+ "a:b:c: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 '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 'h':
+ usage();
+ default:
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, ch);
+ usage();
+ }
+ }
+
+ 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, "HMAC-MD5") == 0) {
+ options |= DST_TYPE_KEY;
+ alg = DST_ALG_HMACMD5;
+ } 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:
+ 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:
+ 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);
+ break;
+ }
+
+ if (!(alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_RSASHA1) &&
+ 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)
+ fatal("no nametype specified");
+ 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 (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))
+ 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:
+ 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);
+ }
+
+ /*
+ * 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();
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/contrib/bind9/bin/dnssec/dnssec-keygen.docbook b/contrib/bind9/bin/dnssec/dnssec-keygen.docbook
new file mode 100644
index 000000000000..a2034d9e8049
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-keygen.docbook
@@ -0,0 +1,342 @@
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<!--
+ - Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2001-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.docbook,v 1.3.12.6 2004/06/11 01:17:34 marka Exp $ -->
+
+<refentry>
+ <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>
+
+ <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 &lt;TBA\&gt;. 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, 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.
+ </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. These strings can be used as arguments
+ to <command>dnssec-makekeyset</command>.
+ </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 file, 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 algorithm 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 2535</citetitle>,
+ <citetitle>RFC 2845</citetitle>,
+ <citetitle>RFC 2539</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para>
+ <corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry>
+
+<!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/contrib/bind9/bin/dnssec/dnssec-keygen.html b/contrib/bind9/bin/dnssec/dnssec-keygen.html
new file mode 100644
index 000000000000..734c914ba617
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-keygen.html
@@ -0,0 +1,544 @@
+<!--
+ - Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2001-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.5.2.1.4.6 2004/08/22 23:38:58 marka Exp $ -->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<HTML
+><HEAD
+><TITLE
+>dnssec-keygen</TITLE
+><META
+NAME="GENERATOR"
+CONTENT="Modular DocBook HTML Stylesheet Version 1.7"></HEAD
+><BODY
+CLASS="REFENTRY"
+BGCOLOR="#FFFFFF"
+TEXT="#000000"
+LINK="#0000FF"
+VLINK="#840084"
+ALINK="#0000FF"
+><H1
+><A
+NAME="AEN1"
+></A
+><SPAN
+CLASS="APPLICATION"
+>dnssec-keygen</SPAN
+></H1
+><DIV
+CLASS="REFNAMEDIV"
+><A
+NAME="AEN9"
+></A
+><H2
+>Name</H2
+><SPAN
+CLASS="APPLICATION"
+>dnssec-keygen</SPAN
+>&nbsp;--&nbsp;DNSSEC key generation tool</DIV
+><DIV
+CLASS="REFSYNOPSISDIV"
+><A
+NAME="AEN13"
+></A
+><H2
+>Synopsis</H2
+><P
+><B
+CLASS="COMMAND"
+>dnssec-keygen</B
+> {-a <VAR
+CLASS="REPLACEABLE"
+>algorithm</VAR
+>} {-b <VAR
+CLASS="REPLACEABLE"
+>keysize</VAR
+>} {-n <VAR
+CLASS="REPLACEABLE"
+>nametype</VAR
+>} [<VAR
+CLASS="OPTION"
+>-c <VAR
+CLASS="REPLACEABLE"
+>class</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-e</VAR
+>] [<VAR
+CLASS="OPTION"
+>-f <VAR
+CLASS="REPLACEABLE"
+>flag</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-g <VAR
+CLASS="REPLACEABLE"
+>generator</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-h</VAR
+>] [<VAR
+CLASS="OPTION"
+>-k</VAR
+>] [<VAR
+CLASS="OPTION"
+>-p <VAR
+CLASS="REPLACEABLE"
+>protocol</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-r <VAR
+CLASS="REPLACEABLE"
+>randomdev</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-s <VAR
+CLASS="REPLACEABLE"
+>strength</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-t <VAR
+CLASS="REPLACEABLE"
+>type</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-v <VAR
+CLASS="REPLACEABLE"
+>level</VAR
+></VAR
+>] {name}</P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN53"
+></A
+><H2
+>DESCRIPTION</H2
+><P
+> <B
+CLASS="COMMAND"
+>dnssec-keygen</B
+> generates keys for DNSSEC
+ (Secure DNS), as defined in RFC 2535 and RFC &lt;TBA\&gt;. It can also generate
+ keys for use with TSIG (Transaction Signatures), as
+ defined in RFC 2845.
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN57"
+></A
+><H2
+>OPTIONS</H2
+><P
+></P
+><DIV
+CLASS="VARIABLELIST"
+><DL
+><DT
+>-a <VAR
+CLASS="REPLACEABLE"
+>algorithm</VAR
+></DT
+><DD
+><P
+> Selects the cryptographic algorithm. The value of
+ <VAR
+CLASS="OPTION"
+>algorithm</VAR
+> must be one of RSAMD5 (RSA) or RSASHA1,
+ DSA, 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
+>-b <VAR
+CLASS="REPLACEABLE"
+>keysize</VAR
+></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
+>-n <VAR
+CLASS="REPLACEABLE"
+>nametype</VAR
+></DT
+><DD
+><P
+> Specifies the owner type of the key. The value of
+ <VAR
+CLASS="OPTION"
+>nametype</VAR
+> 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
+>-c <VAR
+CLASS="REPLACEABLE"
+>class</VAR
+></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
+>-e</DT
+><DD
+><P
+> If generating an RSAMD5/RSASHA1 key, use a large exponent.
+ </P
+></DD
+><DT
+>-f <VAR
+CLASS="REPLACEABLE"
+>flag</VAR
+></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
+>-g <VAR
+CLASS="REPLACEABLE"
+>generator</VAR
+></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
+>-h</DT
+><DD
+><P
+> Prints a short summary of the options and arguments to
+ <B
+CLASS="COMMAND"
+>dnssec-keygen</B
+>.
+ </P
+></DD
+><DT
+>-k</DT
+><DD
+><P
+> Generate KEY records rather than DNSKEY records.
+ </P
+></DD
+><DT
+>-p <VAR
+CLASS="REPLACEABLE"
+>protocol</VAR
+></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
+>-r <VAR
+CLASS="REPLACEABLE"
+>randomdev</VAR
+></DT
+><DD
+><P
+> Specifies the source of randomness. If the operating
+ system does not provide a <TT
+CLASS="FILENAME"
+>/dev/random</TT
+>
+ or equivalent device, the default source of randomness
+ is keyboard input. <TT
+CLASS="FILENAME"
+>randomdev</TT
+> specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <TT
+CLASS="FILENAME"
+>keyboard</TT
+> indicates that keyboard
+ input should be used.
+ </P
+></DD
+><DT
+>-s <VAR
+CLASS="REPLACEABLE"
+>strength</VAR
+></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
+>-t <VAR
+CLASS="REPLACEABLE"
+>type</VAR
+></DT
+><DD
+><P
+> Indicates the use of the key. <VAR
+CLASS="OPTION"
+>type</VAR
+> 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
+>-v <VAR
+CLASS="REPLACEABLE"
+>level</VAR
+></DT
+><DD
+><P
+> Sets the debugging level.
+ </P
+></DD
+></DL
+></DIV
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN136"
+></A
+><H2
+>GENERATED KEYS</H2
+><P
+> When <B
+CLASS="COMMAND"
+>dnssec-keygen</B
+> completes successfully,
+ it prints a string of the form <TT
+CLASS="FILENAME"
+>Knnnn.+aaa+iiiii</TT
+>
+ to the standard output. This is an identification string for
+ the key it has generated. These strings can be used as arguments
+ to <B
+CLASS="COMMAND"
+>dnssec-makekeyset</B
+>.
+ </P
+><P
+></P
+><UL
+><LI
+><P
+> <TT
+CLASS="FILENAME"
+>nnnn</TT
+> is the key name.
+ </P
+></LI
+><LI
+><P
+> <TT
+CLASS="FILENAME"
+>aaa</TT
+> is the numeric representation of the
+ algorithm.
+ </P
+></LI
+><LI
+><P
+> <TT
+CLASS="FILENAME"
+>iiiii</TT
+> is the key identifier (or footprint).
+ </P
+></LI
+></UL
+><P
+> <B
+CLASS="COMMAND"
+>dnssec-keygen</B
+> creates two file, with names based
+ on the printed string. <TT
+CLASS="FILENAME"
+>Knnnn.+aaa+iiiii.key</TT
+>
+ contains the public key, and
+ <TT
+CLASS="FILENAME"
+>Knnnn.+aaa+iiiii.private</TT
+> contains the private
+ key.
+ </P
+><P
+> The <TT
+CLASS="FILENAME"
+>.key</TT
+> file contains a DNS KEY record that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </P
+><P
+> The <TT
+CLASS="FILENAME"
+>.private</TT
+> file contains algorithm specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </P
+><P
+> Both <TT
+CLASS="FILENAME"
+>.key</TT
+> and <TT
+CLASS="FILENAME"
+>.private</TT
+>
+ files are generated for symmetric encryption algorithm such as
+ HMAC-MD5, even though the public and private key are equivalent.
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN163"
+></A
+><H2
+>EXAMPLE</H2
+><P
+> To generate a 768-bit DSA key for the domain
+ <KBD
+CLASS="USERINPUT"
+>example.com</KBD
+>, the following command would be
+ issued:
+ </P
+><P
+> <KBD
+CLASS="USERINPUT"
+>dnssec-keygen -a DSA -b 768 -n ZONE example.com</KBD
+>
+ </P
+><P
+> The command would print a string of the form:
+ </P
+><P
+> <KBD
+CLASS="USERINPUT"
+>Kexample.com.+003+26160</KBD
+>
+ </P
+><P
+> In this example, <B
+CLASS="COMMAND"
+>dnssec-keygen</B
+> creates
+ the files <TT
+CLASS="FILENAME"
+>Kexample.com.+003+26160.key</TT
+> and
+ <TT
+CLASS="FILENAME"
+>Kexample.com.+003+26160.private</TT
+>
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN176"
+></A
+><H2
+>SEE ALSO</H2
+><P
+> <SPAN
+CLASS="CITEREFENTRY"
+><SPAN
+CLASS="REFENTRYTITLE"
+>dnssec-signzone</SPAN
+>(8)</SPAN
+>,
+ <I
+CLASS="CITETITLE"
+>BIND 9 Administrator Reference Manual</I
+>,
+ <I
+CLASS="CITETITLE"
+>RFC 2535</I
+>,
+ <I
+CLASS="CITETITLE"
+>RFC 2845</I
+>,
+ <I
+CLASS="CITETITLE"
+>RFC 2539</I
+>.
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN186"
+></A
+><H2
+>AUTHOR</H2
+><P
+> Internet Systems Consortium
+ </P
+></DIV
+></BODY
+></HTML
+>
diff --git a/contrib/bind9/bin/dnssec/dnssec-makekeyset.8 b/contrib/bind9/bin/dnssec/dnssec-makekeyset.8
new file mode 100644
index 000000000000..0189b31e62e5
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-makekeyset.8
@@ -0,0 +1,113 @@
+.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001, 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-makekeyset.8,v 1.16.2.2.4.1 2004/03/06 07:41:39 marka Exp $
+.\"
+.TH "DNSSEC-MAKEKEYSET" "8" "June 30, 2000" "BIND9" ""
+.SH NAME
+dnssec-makekeyset \- DNSSEC zone signing tool
+.SH SYNOPSIS
+.sp
+\fBdnssec-makekeyset\fR [ \fB-a\fR ] [ \fB-s \fIstart-time\fB\fR ] [ \fB-e \fIend-time\fB\fR ] [ \fB-h\fR ] [ \fB-p\fR ] [ \fB-r \fIrandomdev\fB\fR ] [ \fB-t\fIttl\fB\fR ] [ \fB-v \fIlevel\fB\fR ] \fBkey\fR\fI...\fR
+.SH "DESCRIPTION"
+.PP
+\fBdnssec-makekeyset\fR generates a key set from one
+or more keys created by \fBdnssec-keygen\fR. It creates
+a file containing a KEY record for each key, and self-signs the key
+set with each zone key. The output file is of the form
+\fIkeyset-nnnn.\fR, where \fInnnn\fR
+is the zone name.
+.SH "OPTIONS"
+.TP
+\fB-a\fR
+Verify all generated signatures.
+.TP
+\fB-s \fIstart-time\fB\fR
+Specify the date and time when the generated SIG 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 is used.
+.TP
+\fB-e \fIend-time\fB\fR
+Specify the date and time when the generated SIG 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.
+.TP
+\fB-h\fR
+Prints a short summary of the options and arguments to
+\fBdnssec-makekeyset\fR.
+.TP
+\fB-p\fR
+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.
+.TP
+\fB-r \fIrandomdev\fB\fR
+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.
+.TP
+\fB-t \fIttl\fB\fR
+Specify the TTL (time to live) of the KEY and SIG records.
+The default is 3600 seconds.
+.TP
+\fB-v \fIlevel\fB\fR
+Sets the debugging level.
+.TP
+\fBkey\fR
+The list of keys to be included in the keyset file. These keys
+are expressed in the form \fIKnnnn.+aaa+iiiii\fR
+as generated by \fBdnssec-keygen\fR.
+.SH "EXAMPLE"
+.PP
+The following command generates a keyset containing the DSA key for
+\fBexample.com\fR generated in the
+\fBdnssec-keygen\fR man page.
+.PP
+\fBdnssec-makekeyset -t 86400 -s 20000701120000 -e +2592000 Kexample.com.+003+26160\fR
+.PP
+In this example, \fBdnssec-makekeyset\fR creates
+the file \fIkeyset-example.com.\fR. This file
+contains the specified key and a self-generated signature.
+.PP
+The DNS administrator for \fBexample.com\fR could
+send \fIkeyset-example.com.\fR to the DNS
+administrator for \fB.com\fR for signing, if the
+\&.com zone is DNSSEC-aware and the administrators of the two zones
+have some mechanism for authenticating each other and exchanging
+the keys and signatures securely.
+.SH "SEE ALSO"
+.PP
+\fBdnssec-keygen\fR(8),
+\fBdnssec-signkey\fR(8),
+\fIBIND 9 Administrator Reference Manual\fR,
+\fIRFC 2535\fR.
+.SH "AUTHOR"
+.PP
+Internet Software Consortium
diff --git a/contrib/bind9/bin/dnssec/dnssec-makekeyset.c b/contrib/bind9/bin/dnssec/dnssec-makekeyset.c
new file mode 100644
index 000000000000..c8224ed3888f
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-makekeyset.c
@@ -0,0 +1,401 @@
+/*
+ * Portions Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2000-2003 Internet Software Consortium.
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 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-makekeyset.c,v 1.52.2.1.10.7 2004/08/28 06:25:27 marka Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/diff.h>
+#include <dns/dnssec.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+#include <dns/time.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-makekeyset";
+int verbose;
+
+typedef struct keynode keynode_t;
+struct keynode {
+ dst_key_t *key;
+ ISC_LINK(keynode_t) link;
+};
+typedef ISC_LIST(keynode_t) keylist_t;
+
+static isc_stdtime_t starttime = 0, endtime = 0, now;
+static int ttl = -1;
+
+static isc_mem_t *mctx = NULL;
+static isc_entropy_t *ectx = NULL;
+
+static keylist_t keylist;
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\t%s [options] keys\n", program);
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Version: %s\n", VERSION);
+
+ fprintf(stderr, "Options: (default value in parenthesis) \n");
+ fprintf(stderr, "\t-a\n");
+ fprintf(stderr, "\t\tverify generated signatures\n");
+ fprintf(stderr, "\t-s YYYYMMDDHHMMSS|+offset:\n");
+ fprintf(stderr, "\t\tSIG start time - absolute|offset (now)\n");
+ fprintf(stderr, "\t-e YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
+ fprintf(stderr, "\t\tSIG end time - "
+ "absolute|from start|from now (now + 30 days)\n");
+ fprintf(stderr, "\t-t ttl\n");
+ fprintf(stderr, "\t-p\n");
+ fprintf(stderr, "\t\tuse pseudorandom data (faster but less secure)\n");
+ fprintf(stderr, "\t-r randomdev:\n");
+ fprintf(stderr, "\t\ta file containing random data\n");
+ fprintf(stderr, "\t-v level:\n");
+ fprintf(stderr, "\t\tverbose level (0)\n");
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "keys:\n");
+ fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Output:\n");
+ fprintf(stderr, "\tkeyset (keyset-<name>)\n");
+ exit(0);
+}
+
+static isc_boolean_t
+zonekey_on_list(dst_key_t *key) {
+ keynode_t *keynode;
+ for (keynode = ISC_LIST_HEAD(keylist);
+ keynode != NULL;
+ keynode = ISC_LIST_NEXT(keynode, link))
+ {
+ if (dst_key_compare(keynode->key, key))
+ return (ISC_TRUE);
+ }
+ return (ISC_FALSE);
+}
+
+int
+main(int argc, char *argv[]) {
+ int i, ch;
+ char *startstr = NULL, *endstr = NULL;
+ dns_fixedname_t fdomain;
+ dns_name_t *domain = NULL;
+ char *output = NULL;
+ char *endp;
+ unsigned char data[65536];
+ dns_db_t *db;
+ dns_dbversion_t *version;
+ dns_diff_t diff;
+ dns_difftuple_t *tuple;
+ dns_fixedname_t tname;
+ dst_key_t *key = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ dns_rdataclass_t rdclass;
+ isc_result_t result;
+ isc_buffer_t b;
+ isc_region_t r;
+ isc_log_t *log = NULL;
+ keynode_t *keynode;
+ unsigned int eflags;
+ isc_boolean_t pseudorandom = ISC_FALSE;
+ isc_boolean_t tryverify = ISC_FALSE;
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to create memory context: %s",
+ isc_result_totext(result));
+
+ dns_result_register();
+
+ while ((ch = isc_commandline_parse(argc, argv, "as:e:t:r:v:ph")) != -1)
+ {
+ switch (ch) {
+ case 'a':
+ tryverify = ISC_TRUE;
+ break;
+ case 's':
+ startstr = isc_commandline_argument;
+ break;
+
+ case 'e':
+ endstr = isc_commandline_argument;
+ break;
+
+ case 't':
+ endp = NULL;
+ ttl = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0')
+ fatal("TTL must be numeric");
+ 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("verbose level must be numeric");
+ break;
+
+ case 'p':
+ pseudorandom = ISC_TRUE;
+ break;
+
+ case 'h':
+ default:
+ usage();
+
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc < 1)
+ usage();
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ eflags = ISC_ENTROPY_BLOCKING;
+ if (!pseudorandom)
+ eflags |= ISC_ENTROPY_GOODONLY;
+ result = dst_lib_init(mctx, ectx, eflags);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize dst: %s",
+ isc_result_totext(result));
+
+ isc_stdtime_get(&now);
+
+ if (startstr != NULL)
+ starttime = strtotime(startstr, now, now);
+ else
+ starttime = now;
+
+ if (endstr != NULL)
+ endtime = strtotime(endstr, now, starttime);
+ else
+ endtime = starttime + (30 * 24 * 60 * 60);
+
+ if (ttl == -1) {
+ ttl = 3600;
+ fprintf(stderr, "%s: TTL not specified, assuming 3600\n",
+ program);
+ }
+
+ setup_logging(verbose, mctx, &log);
+
+ dns_diff_init(mctx, &diff);
+ rdclass = 0;
+
+ ISC_LIST_INIT(keylist);
+
+ for (i = 0; i < argc; i++) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ isc_buffer_t namebuf;
+
+ key = NULL;
+ result = dst_key_fromnamedfile(argv[i], DST_TYPE_PUBLIC,
+ mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ fatal("error loading key from %s: %s", argv[i],
+ isc_result_totext(result));
+ if (rdclass == 0)
+ rdclass = dst_key_class(key);
+
+ isc_buffer_init(&namebuf, namestr, sizeof(namestr));
+ result = dns_name_tofilenametext(dst_key_name(key),
+ ISC_FALSE,
+ &namebuf);
+ check_result(result, "dns_name_tofilenametext");
+ isc_buffer_putuint8(&namebuf, 0);
+
+ if (domain == NULL) {
+ dns_fixedname_init(&fdomain);
+ domain = dns_fixedname_name(&fdomain);
+ dns_name_copy(dst_key_name(key), domain, NULL);
+ } else if (!dns_name_equal(domain, dst_key_name(key))) {
+ char str[DNS_NAME_FORMATSIZE];
+ dns_name_format(domain, str, sizeof(str));
+ fatal("all keys must have the same owner - %s "
+ "and %s do not match", str, namestr);
+ }
+
+ if (output == NULL) {
+ output = isc_mem_allocate(mctx,
+ strlen("keyset-") +
+ strlen(namestr) + 1);
+ if (output == NULL)
+ fatal("out of memory");
+ sprintf(output, "keyset-%s", namestr);
+ }
+
+ if (dst_key_iszonekey(key)) {
+ dst_key_t *zonekey = NULL;
+ result = dst_key_fromnamedfile(argv[i],
+ DST_TYPE_PUBLIC |
+ DST_TYPE_PRIVATE,
+ mctx, &zonekey);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to read private key %s: %s",
+ argv[i], isc_result_totext(result));
+ if (!zonekey_on_list(zonekey)) {
+ keynode = isc_mem_get(mctx, sizeof(keynode_t));
+ if (keynode == NULL)
+ fatal("out of memory");
+ keynode->key = zonekey;
+ ISC_LIST_INITANDAPPEND(keylist, keynode, link);
+ } else
+ dst_key_free(&zonekey);
+ }
+ dns_rdata_reset(&rdata);
+ isc_buffer_init(&b, data, sizeof(data));
+ result = dst_key_todns(key, &b);
+ dst_key_free(&key);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to convert key %s to a DNS KEY: %s",
+ argv[i], isc_result_totext(result));
+ isc_buffer_usedregion(&b, &r);
+ dns_rdata_fromregion(&rdata, rdclass, dns_rdatatype_dnskey, &r);
+ tuple = NULL;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ domain, ttl, &rdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+ }
+
+ db = NULL;
+ result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
+ rdclass, 0, NULL, &db);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to create a database");
+
+ version = NULL;
+ dns_db_newversion(db, &version);
+
+ result = dns_diff_apply(&diff, db, version);
+ check_result(result, "dns_diff_apply");
+ dns_diff_clear(&diff);
+
+ dns_fixedname_init(&tname);
+ dns_rdataset_init(&rdataset);
+ result = dns_db_find(db, domain, version, dns_rdatatype_dnskey, 0, 0,
+ NULL, dns_fixedname_name(&tname), &rdataset,
+ NULL);
+ check_result(result, "dns_db_find");
+
+ if (ISC_LIST_EMPTY(keylist))
+ fprintf(stderr,
+ "%s: no private zone key found; not self-signing\n",
+ program);
+ for (keynode = ISC_LIST_HEAD(keylist);
+ keynode != NULL;
+ keynode = ISC_LIST_NEXT(keynode, link))
+ {
+ dns_rdata_reset(&rdata);
+ isc_buffer_init(&b, data, sizeof(data));
+ result = dns_dnssec_sign(domain, &rdataset, keynode->key,
+ &starttime, &endtime, mctx, &b,
+ &rdata);
+ isc_entropy_stopcallbacksources(ectx);
+ if (result != ISC_R_SUCCESS) {
+ char keystr[KEY_FORMATSIZE];
+ key_format(keynode->key, keystr, sizeof(keystr));
+ fatal("failed to sign keyset with key %s: %s",
+ keystr, isc_result_totext(result));
+ }
+ if (tryverify) {
+ result = dns_dnssec_verify(domain, &rdataset,
+ keynode->key, ISC_TRUE,
+ mctx, &rdata);
+ if (result != ISC_R_SUCCESS) {
+ char keystr[KEY_FORMATSIZE];
+ key_format(keynode->key, keystr, sizeof(keystr));
+ fatal("signature from key '%s' failed to "
+ "verify: %s",
+ keystr, isc_result_totext(result));
+ }
+ }
+ tuple = NULL;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ domain, ttl, &rdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+ }
+
+ result = dns_diff_apply(&diff, db, version);
+ check_result(result, "dns_diff_apply");
+ dns_diff_clear(&diff);
+
+ dns_rdataset_disassociate(&rdataset);
+
+ dns_db_closeversion(db, &version, ISC_TRUE);
+ result = dns_db_dump(db, version, output);
+ if (result != ISC_R_SUCCESS) {
+ char domainstr[DNS_NAME_FORMATSIZE];
+ dns_name_format(domain, domainstr, sizeof(domainstr));
+ fatal("failed to write database for %s to %s",
+ domainstr, output);
+ }
+
+ printf("%s\n", output);
+
+ dns_db_detach(&db);
+
+ while (!ISC_LIST_EMPTY(keylist)) {
+ keynode = ISC_LIST_HEAD(keylist);
+ ISC_LIST_UNLINK(keylist, keynode, link);
+ dst_key_free(&keynode->key);
+ isc_mem_put(mctx, keynode, sizeof(keynode_t));
+ }
+
+ cleanup_logging(&log);
+ cleanup_entropy(&ectx);
+
+ isc_mem_free(mctx, output);
+ dst_lib_destroy();
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+ return (0);
+}
diff --git a/contrib/bind9/bin/dnssec/dnssec-makekeyset.docbook b/contrib/bind9/bin/dnssec/dnssec-makekeyset.docbook
new file mode 100644
index 000000000000..07327481550b
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-makekeyset.docbook
@@ -0,0 +1,233 @@
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<!--
+ - Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2001, 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-makekeyset.docbook,v 1.2.2.3.4.2 2004/06/03 02:24:55 marka Exp $ -->
+
+<refentry>
+ <refentryinfo>
+ <date>June 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-makekeyset</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-makekeyset</application></refname>
+ <refpurpose>DNSSEC zone signing tool</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dnssec-makekeyset</command>
+ <arg><option>-a</option></arg>
+ <arg><option>-s <replaceable class="parameter">start-time</replaceable></option></arg>
+ <arg><option>-e <replaceable class="parameter">end-time</replaceable></option></arg>
+ <arg><option>-h</option></arg>
+ <arg><option>-p</option></arg>
+ <arg><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg>
+ <arg><option>-t</option><replaceable class="parameter">ttl</replaceable></arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="req" rep="repeat">key</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>
+ <command>dnssec-makekeyset</command> generates a key set from one
+ or more keys created by <command>dnssec-keygen</command>. It creates
+ a file containing a KEY record for each key, and self-signs the key
+ set with each zone key. The output file is of the form
+ <filename>keyset-nnnn.</filename>, where <filename>nnnn</filename>
+ is the zone name.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-a</term>
+ <listitem>
+ <para>
+ Verify all generated signatures.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">start-time</replaceable></term>
+ <listitem>
+ <para>
+ Specify the date and time when the generated SIG 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 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 SIG 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>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>dnssec-makekeyset</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 <replaceable class="parameter">ttl</replaceable></term>
+ <listitem>
+ <para>
+ Specify the TTL (time to live) of the KEY and SIG records.
+ The default is 3600 seconds.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>key</term>
+ <listitem>
+ <para>
+ The list of keys to be included in the keyset file. These keys
+ are expressed in the form <filename>Knnnn.+aaa+iiiii</filename>
+ as generated by <command>dnssec-keygen</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>EXAMPLE</title>
+ <para>
+ The following command generates a keyset containing the DSA key for
+ <userinput>example.com</userinput> generated in the
+ <command>dnssec-keygen</command> man page.
+ </para>
+ <para>
+ <userinput>dnssec-makekeyset -t 86400 -s 20000701120000 -e +2592000 Kexample.com.+003+26160</userinput>
+ </para>
+ <para>
+ In this example, <command>dnssec-makekeyset</command> creates
+ the file <filename>keyset-example.com.</filename>. This file
+ contains the specified key and a self-generated signature.
+ </para>
+ <para>
+ The DNS administrator for <userinput>example.com</userinput> could
+ send <filename>keyset-example.com.</filename> to the DNS
+ administrator for <userinput>.com</userinput> for signing, if the
+ .com zone is DNSSEC-aware and the administrators of the two zones
+ have some mechanism for authenticating each other and exchanging
+ the keys and signatures securely.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signkey</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 2535</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para>
+ <corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry>
+
+<!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/contrib/bind9/bin/dnssec/dnssec-makekeyset.html b/contrib/bind9/bin/dnssec/dnssec-makekeyset.html
new file mode 100644
index 000000000000..48f1d4a59e11
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-makekeyset.html
@@ -0,0 +1,407 @@
+<!--
+ - Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2001, 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-makekeyset.html,v 1.4.2.2.4.1 2004/03/06 10:21:15 marka Exp $ -->
+
+<HTML
+><HEAD
+><TITLE
+>dnssec-makekeyset</TITLE
+><META
+NAME="GENERATOR"
+CONTENT="Modular DocBook HTML Stylesheet Version 1.73
+"></HEAD
+><BODY
+CLASS="REFENTRY"
+BGCOLOR="#FFFFFF"
+TEXT="#000000"
+LINK="#0000FF"
+VLINK="#840084"
+ALINK="#0000FF"
+><H1
+><A
+NAME="AEN1"
+><SPAN
+CLASS="APPLICATION"
+>dnssec-makekeyset</SPAN
+></A
+></H1
+><DIV
+CLASS="REFNAMEDIV"
+><A
+NAME="AEN9"
+></A
+><H2
+>Name</H2
+><SPAN
+CLASS="APPLICATION"
+>dnssec-makekeyset</SPAN
+>&nbsp;--&nbsp;DNSSEC zone signing tool</DIV
+><DIV
+CLASS="REFSYNOPSISDIV"
+><A
+NAME="AEN13"
+></A
+><H2
+>Synopsis</H2
+><P
+><B
+CLASS="COMMAND"
+>dnssec-makekeyset</B
+> [<TT
+CLASS="OPTION"
+>-a</TT
+>] [<TT
+CLASS="OPTION"
+>-s <TT
+CLASS="REPLACEABLE"
+><I
+>start-time</I
+></TT
+></TT
+>] [<TT
+CLASS="OPTION"
+>-e <TT
+CLASS="REPLACEABLE"
+><I
+>end-time</I
+></TT
+></TT
+>] [<TT
+CLASS="OPTION"
+>-h</TT
+>] [<TT
+CLASS="OPTION"
+>-p</TT
+>] [<TT
+CLASS="OPTION"
+>-r <TT
+CLASS="REPLACEABLE"
+><I
+>randomdev</I
+></TT
+></TT
+>] [<TT
+CLASS="OPTION"
+>-t</TT
+><TT
+CLASS="REPLACEABLE"
+><I
+>ttl</I
+></TT
+>] [<TT
+CLASS="OPTION"
+>-v <TT
+CLASS="REPLACEABLE"
+><I
+>level</I
+></TT
+></TT
+>] {key...}</P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN38"
+></A
+><H2
+>DESCRIPTION</H2
+><P
+> <B
+CLASS="COMMAND"
+>dnssec-makekeyset</B
+> generates a key set from one
+ or more keys created by <B
+CLASS="COMMAND"
+>dnssec-keygen</B
+>. It creates
+ a file containing a KEY record for each key, and self-signs the key
+ set with each zone key. The output file is of the form
+ <TT
+CLASS="FILENAME"
+>keyset-nnnn.</TT
+>, where <TT
+CLASS="FILENAME"
+>nnnn</TT
+>
+ is the zone name.
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN45"
+></A
+><H2
+>OPTIONS</H2
+><P
+></P
+><DIV
+CLASS="VARIABLELIST"
+><DL
+><DT
+>-a</DT
+><DD
+><P
+> Verify all generated signatures.
+ </P
+></DD
+><DT
+>-s <TT
+CLASS="REPLACEABLE"
+><I
+>start-time</I
+></TT
+></DT
+><DD
+><P
+> Specify the date and time when the generated SIG 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 <TT
+CLASS="OPTION"
+>start-time</TT
+> is specified, the current
+ time is used.
+ </P
+></DD
+><DT
+>-e <TT
+CLASS="REPLACEABLE"
+><I
+>end-time</I
+></TT
+></DT
+><DD
+><P
+> Specify the date and time when the generated SIG records
+ expire. As with <TT
+CLASS="OPTION"
+>start-time</TT
+>, 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 <TT
+CLASS="OPTION"
+>end-time</TT
+> is
+ specified, 30 days from the start time is used as a default.
+ </P
+></DD
+><DT
+>-h</DT
+><DD
+><P
+> Prints a short summary of the options and arguments to
+ <B
+CLASS="COMMAND"
+>dnssec-makekeyset</B
+>.
+ </P
+></DD
+><DT
+>-p</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
+>-r <TT
+CLASS="REPLACEABLE"
+><I
+>randomdev</I
+></TT
+></DT
+><DD
+><P
+> Specifies the source of randomness. If the operating
+ system does not provide a <TT
+CLASS="FILENAME"
+>/dev/random</TT
+>
+ or equivalent device, the default source of randomness
+ is keyboard input. <TT
+CLASS="FILENAME"
+>randomdev</TT
+> specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <TT
+CLASS="FILENAME"
+>keyboard</TT
+> indicates that keyboard
+ input should be used.
+ </P
+></DD
+><DT
+>-t <TT
+CLASS="REPLACEABLE"
+><I
+>ttl</I
+></TT
+></DT
+><DD
+><P
+> Specify the TTL (time to live) of the KEY and SIG records.
+ The default is 3600 seconds.
+ </P
+></DD
+><DT
+>-v <TT
+CLASS="REPLACEABLE"
+><I
+>level</I
+></TT
+></DT
+><DD
+><P
+> Sets the debugging level.
+ </P
+></DD
+><DT
+>key</DT
+><DD
+><P
+> The list of keys to be included in the keyset file. These keys
+ are expressed in the form <TT
+CLASS="FILENAME"
+>Knnnn.+aaa+iiiii</TT
+>
+ as generated by <B
+CLASS="COMMAND"
+>dnssec-keygen</B
+>.
+ </P
+></DD
+></DL
+></DIV
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN98"
+></A
+><H2
+>EXAMPLE</H2
+><P
+> The following command generates a keyset containing the DSA key for
+ <TT
+CLASS="USERINPUT"
+><B
+>example.com</B
+></TT
+> generated in the
+ <B
+CLASS="COMMAND"
+>dnssec-keygen</B
+> man page.
+ </P
+><P
+> <TT
+CLASS="USERINPUT"
+><B
+>dnssec-makekeyset -t 86400 -s 20000701120000 -e +2592000 Kexample.com.+003+26160</B
+></TT
+>
+ </P
+><P
+> In this example, <B
+CLASS="COMMAND"
+>dnssec-makekeyset</B
+> creates
+ the file <TT
+CLASS="FILENAME"
+>keyset-example.com.</TT
+>. This file
+ contains the specified key and a self-generated signature.
+ </P
+><P
+> The DNS administrator for <TT
+CLASS="USERINPUT"
+><B
+>example.com</B
+></TT
+> could
+ send <TT
+CLASS="FILENAME"
+>keyset-example.com.</TT
+> to the DNS
+ administrator for <TT
+CLASS="USERINPUT"
+><B
+>.com</B
+></TT
+> for signing, if the
+ .com zone is DNSSEC-aware and the administrators of the two zones
+ have some mechanism for authenticating each other and exchanging
+ the keys and signatures securely.
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN112"
+></A
+><H2
+>SEE ALSO</H2
+><P
+> <SPAN
+CLASS="CITEREFENTRY"
+><SPAN
+CLASS="REFENTRYTITLE"
+>dnssec-keygen</SPAN
+>(8)</SPAN
+>,
+ <SPAN
+CLASS="CITEREFENTRY"
+><SPAN
+CLASS="REFENTRYTITLE"
+>dnssec-signkey</SPAN
+>(8)</SPAN
+>,
+ <I
+CLASS="CITETITLE"
+>BIND 9 Administrator Reference Manual</I
+>,
+ <I
+CLASS="CITETITLE"
+>RFC 2535</I
+>.
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN123"
+></A
+><H2
+>AUTHOR</H2
+><P
+> Internet Software Consortium
+ </P
+></DIV
+></BODY
+></HTML
+>
diff --git a/contrib/bind9/bin/dnssec/dnssec-signkey.8 b/contrib/bind9/bin/dnssec/dnssec-signkey.8
new file mode 100644
index 000000000000..ea2818bdfe21
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-signkey.8
@@ -0,0 +1,108 @@
+.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001, 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-signkey.8,v 1.18.2.1.4.1 2004/03/06 07:41:39 marka Exp $
+.\"
+.TH "DNSSEC-SIGNKEY" "8" "June 30, 2000" "BIND9" ""
+.SH NAME
+dnssec-signkey \- DNSSEC key set signing tool
+.SH SYNOPSIS
+.sp
+\fBdnssec-signkey\fR [ \fB-a\fR ] [ \fB-c \fIclass\fB\fR ] [ \fB-s \fIstart-time\fB\fR ] [ \fB-e \fIend-time\fB\fR ] [ \fB-h\fR ] [ \fB-p\fR ] [ \fB-r \fIrandomdev\fB\fR ] [ \fB-v \fIlevel\fB\fR ] \fBkeyset\fR \fBkey\fR\fI...\fR
+.SH "DESCRIPTION"
+.PP
+\fBdnssec-signkey\fR signs a keyset. Typically
+the keyset will be for a child zone, and will have been generated
+by \fBdnssec-makekeyset\fR. The child zone's keyset
+is signed with the zone keys for its parent zone. The output file
+is of the form \fIsignedkey-nnnn.\fR, where
+\fInnnn\fR is the zone name.
+.SH "OPTIONS"
+.TP
+\fB-a\fR
+Verify all generated signatures.
+.TP
+\fB-c \fIclass\fB\fR
+Specifies the DNS class of the key sets.
+.TP
+\fB-s \fIstart-time\fB\fR
+Specify the date and time when the generated SIG 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 is used.
+.TP
+\fB-e \fIend-time\fB\fR
+Specify the date and time when the generated SIG 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.
+.TP
+\fB-h\fR
+Prints a short summary of the options and arguments to
+\fBdnssec-signkey\fR.
+.TP
+\fB-p\fR
+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.
+.TP
+\fB-r \fIrandomdev\fB\fR
+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.
+.TP
+\fB-v \fIlevel\fB\fR
+Sets the debugging level.
+.TP
+\fBkeyset\fR
+The file containing the child's keyset.
+.TP
+\fBkey\fR
+The keys used to sign the child's keyset.
+.SH "EXAMPLE"
+.PP
+The DNS administrator for a DNSSEC-aware \fB.com\fR
+zone would use the following command to sign the
+\fIkeyset\fR file for \fBexample.com\fR
+created by \fBdnssec-makekeyset\fR with a key generated
+by \fBdnssec-keygen\fR:
+.PP
+\fBdnssec-signkey keyset-example.com. Kcom.+003+51944\fR
+.PP
+In this example, \fBdnssec-signkey\fR creates
+the file \fIsignedkey-example.com.\fR, which
+contains the \fBexample.com\fR keys and the
+signatures by the \fB.com\fR keys.
+.SH "SEE ALSO"
+.PP
+\fBdnssec-keygen\fR(8),
+\fBdnssec-makekeyset\fR(8),
+\fBdnssec-signzone\fR(8).
+.SH "AUTHOR"
+.PP
+Internet Software Consortium
diff --git a/contrib/bind9/bin/dnssec/dnssec-signkey.c b/contrib/bind9/bin/dnssec/dnssec-signkey.c
new file mode 100644
index 000000000000..fd8b0fd322b5
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-signkey.c
@@ -0,0 +1,448 @@
+/*
+ * Portions Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2000-2003 Internet Software Consortium.
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 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-signkey.c,v 1.50.2.2.2.7 2004/08/28 06:25:28 marka Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/string.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/diff.h>
+#include <dns/dnssec.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-signkey";
+int verbose;
+
+typedef struct keynode keynode_t;
+struct keynode {
+ dst_key_t *key;
+ isc_boolean_t verified;
+ ISC_LINK(keynode_t) link;
+};
+typedef ISC_LIST(keynode_t) keylist_t;
+
+static isc_stdtime_t starttime = 0, endtime = 0, now;
+
+static isc_mem_t *mctx = NULL;
+static isc_entropy_t *ectx = NULL;
+static keylist_t keylist;
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\t%s [options] keyset keys\n", program);
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Version: %s\n", VERSION);
+
+ fprintf(stderr, "Options: (default value in parenthesis) \n");
+ fprintf(stderr, "\t-a\n");
+ fprintf(stderr, "\t\tverify generated signatures\n");
+ fprintf(stderr, "\t-c class (IN)\n");
+ fprintf(stderr, "\t-s YYYYMMDDHHMMSS|+offset:\n");
+ fprintf(stderr, "\t\tSIG start time - absolute|offset (from keyset)\n");
+ fprintf(stderr, "\t-e YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
+ fprintf(stderr, "\t\tSIG end time - absolute|from start|from now "
+ "(from keyset)\n");
+ fprintf(stderr, "\t-v level:\n");
+ fprintf(stderr, "\t\tverbose level (0)\n");
+ fprintf(stderr, "\t-p\n");
+ fprintf(stderr, "\t\tuse pseudorandom data (faster but less secure)\n");
+ fprintf(stderr, "\t-r randomdev:\n");
+ fprintf(stderr, "\t\ta file containing random data\n");
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "keyset:\n");
+ fprintf(stderr, "\tfile with keyset to be signed (keyset-<name>)\n");
+ fprintf(stderr, "keys:\n");
+ fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
+
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Output:\n");
+ fprintf(stderr, "\tsigned keyset (signedkey-<name>)\n");
+ exit(0);
+}
+
+static void
+loadkeys(dns_name_t *name, dns_rdataset_t *rdataset) {
+ dst_key_t *key;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ keynode_t *keynode;
+ isc_result_t result;
+
+ ISC_LIST_INIT(keylist);
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "dns_rdataset_first");
+ for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ key = NULL;
+ result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ if (!dst_key_iszonekey(key)) {
+ dst_key_free(&key);
+ continue;
+ }
+ keynode = isc_mem_get(mctx, sizeof(keynode_t));
+ if (keynode == NULL)
+ fatal("out of memory");
+ keynode->key = key;
+ keynode->verified = ISC_FALSE;
+ ISC_LIST_INITANDAPPEND(keylist, keynode, link);
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("failure traversing key list");
+}
+
+static dst_key_t *
+findkey(dns_rdata_rrsig_t *sig) {
+ keynode_t *keynode;
+ for (keynode = ISC_LIST_HEAD(keylist);
+ keynode != NULL;
+ keynode = ISC_LIST_NEXT(keynode, link))
+ {
+ if (dst_key_id(keynode->key) == sig->keyid &&
+ dst_key_alg(keynode->key) == sig->algorithm) {
+ keynode->verified = ISC_TRUE;
+ return (keynode->key);
+ }
+ }
+ fatal("signature generated by non-zone or missing key");
+ return (NULL);
+}
+
+int
+main(int argc, char *argv[]) {
+ int i, ch;
+ char *startstr = NULL, *endstr = NULL, *classname = NULL;
+ char tdomain[1025];
+ dns_fixedname_t fdomain;
+ dns_name_t *domain;
+ char *output = NULL;
+ char *endp;
+ unsigned char data[65536];
+ dns_db_t *db;
+ dns_dbnode_t *node;
+ dns_dbversion_t *version;
+ dns_diff_t diff;
+ dns_difftuple_t *tuple;
+ dns_dbiterator_t *dbiter;
+ dns_rdatasetiter_t *rdsiter;
+ dst_key_t *key = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset, sigrdataset;
+ dns_rdata_rrsig_t sig;
+ isc_result_t result;
+ isc_buffer_t b;
+ isc_log_t *log = NULL;
+ keynode_t *keynode;
+ isc_boolean_t pseudorandom = ISC_FALSE;
+ unsigned int eflags;
+ dns_rdataclass_t rdclass;
+ isc_boolean_t tryverify = ISC_FALSE;
+ isc_boolean_t settime = ISC_FALSE;
+
+ result = isc_mem_create(0, 0, &mctx);
+ check_result(result, "isc_mem_create()");
+
+ dns_result_register();
+
+ while ((ch = isc_commandline_parse(argc, argv, "ac:s:e:pr:v:h")) != -1)
+ {
+ switch (ch) {
+ case 'a':
+ tryverify = ISC_TRUE;
+ break;
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+
+ case 's':
+ startstr = isc_commandline_argument;
+ break;
+
+ case 'e':
+ endstr = isc_commandline_argument;
+ break;
+
+ case 'p':
+ pseudorandom = ISC_TRUE;
+ 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("verbose level must be numeric");
+ break;
+
+ case 'h':
+ default:
+ usage();
+
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc < 2)
+ usage();
+
+ rdclass = strtoclass(classname);
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ eflags = ISC_ENTROPY_BLOCKING;
+ if (!pseudorandom)
+ eflags |= ISC_ENTROPY_GOODONLY;
+ result = dst_lib_init(mctx, ectx, eflags);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize dst: %s",
+ isc_result_totext(result));
+
+ isc_stdtime_get(&now);
+
+ if ((startstr == NULL || endstr == NULL) &&
+ !(startstr == NULL && endstr == NULL))
+ fatal("if -s or -e is specified, both must be");
+
+ if (startstr != NULL) {
+ starttime = strtotime(startstr, now, now);
+ endtime = strtotime(endstr, now, starttime);
+ settime = ISC_TRUE;
+ }
+
+ setup_logging(verbose, mctx, &log);
+
+ if (strlen(argv[0]) < 8U || strncmp(argv[0], "keyset-", 7) != 0)
+ fatal("keyset file '%s' must start with keyset-", argv[0]);
+
+ db = NULL;
+ result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
+ rdclass, 0, NULL, &db);
+ check_result(result, "dns_db_create()");
+
+ result = dns_db_load(db, argv[0]);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
+ fatal("failed to load database from '%s': %s", argv[0],
+ isc_result_totext(result));
+
+ dns_fixedname_init(&fdomain);
+ domain = dns_fixedname_name(&fdomain);
+
+ dbiter = NULL;
+ result = dns_db_createiterator(db, ISC_FALSE, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first()");
+ while (result == ISC_R_SUCCESS) {
+ node = NULL;
+ dns_dbiterator_current(dbiter, &node, domain);
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(db, node, NULL, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ result = dns_rdatasetiter_first(rdsiter);
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (result == ISC_R_SUCCESS)
+ break;
+ dns_db_detachnode(db, &node);
+ result = dns_dbiterator_next(dbiter);
+ }
+ dns_dbiterator_destroy(&dbiter);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to find data in keyset file");
+
+ isc_buffer_init(&b, tdomain, sizeof(tdomain) - 1);
+ result = dns_name_tofilenametext(domain, ISC_FALSE, &b);
+ check_result(result, "dns_name_tofilenametext()");
+ isc_buffer_putuint8(&b, 0);
+
+ output = isc_mem_allocate(mctx,
+ strlen("signedkey-") + strlen(tdomain) + 1);
+ if (output == NULL)
+ fatal("out of memory");
+ sprintf(output, "signedkey-%s", tdomain);
+
+ version = NULL;
+ dns_db_newversion(db, &version);
+
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&sigrdataset);
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey, 0,
+ 0, &rdataset, &sigrdataset);
+ if (result != ISC_R_SUCCESS) {
+ char domainstr[DNS_NAME_FORMATSIZE];
+ dns_name_format(domain, domainstr, sizeof(domainstr));
+ fatal("failed to find rdataset '%s KEY': %s",
+ domainstr, isc_result_totext(result));
+ }
+
+ loadkeys(domain, &rdataset);
+
+ dns_diff_init(mctx, &diff);
+
+ if (!dns_rdataset_isassociated(&sigrdataset))
+ fatal("no SIG KEY set present");
+
+ result = dns_rdataset_first(&sigrdataset);
+ check_result(result, "dns_rdataset_first()");
+ do {
+ dns_rdataset_current(&sigrdataset, &sigrdata);
+ result = dns_rdata_tostruct(&sigrdata, &sig, mctx);
+ check_result(result, "dns_rdata_tostruct()");
+ key = findkey(&sig);
+ result = dns_dnssec_verify(domain, &rdataset, key,
+ ISC_TRUE, mctx, &sigrdata);
+ if (result != ISC_R_SUCCESS) {
+ char keystr[KEY_FORMATSIZE];
+ key_format(key, keystr, sizeof(keystr));
+ fatal("signature by key '%s' did not verify: %s",
+ keystr, isc_result_totext(result));
+ }
+ if (!settime) {
+ starttime = sig.timesigned;
+ endtime = sig.timeexpire;
+ settime = ISC_TRUE;
+ }
+ dns_rdata_freestruct(&sig);
+ dns_rdata_reset(&sigrdata);
+ result = dns_rdataset_next(&sigrdataset);
+ } while (result == ISC_R_SUCCESS);
+
+ for (keynode = ISC_LIST_HEAD(keylist);
+ keynode != NULL;
+ keynode = ISC_LIST_NEXT(keynode, link))
+ if (!keynode->verified)
+ fatal("not all zone keys self signed the key set");
+
+ argc -= 1;
+ argv += 1;
+
+ for (i = 0; i < argc; i++) {
+ key = NULL;
+ result = dst_key_fromnamedfile(argv[i],
+ DST_TYPE_PUBLIC |
+ DST_TYPE_PRIVATE,
+ mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to read key %s from disk: %s",
+ argv[i], isc_result_totext(result));
+
+ dns_rdata_reset(&rdata);
+ isc_buffer_init(&b, data, sizeof(data));
+ result = dns_dnssec_sign(domain, &rdataset, key,
+ &starttime, &endtime,
+ mctx, &b, &rdata);
+ isc_entropy_stopcallbacksources(ectx);
+ if (result != ISC_R_SUCCESS) {
+ char keystr[KEY_FORMATSIZE];
+ key_format(key, keystr, sizeof(keystr));
+ fatal("key '%s' failed to sign data: %s",
+ keystr, isc_result_totext(result));
+ }
+ if (tryverify) {
+ result = dns_dnssec_verify(domain, &rdataset, key,
+ ISC_TRUE, mctx, &rdata);
+ if (result != ISC_R_SUCCESS) {
+ char keystr[KEY_FORMATSIZE];
+ key_format(key, keystr, sizeof(keystr));
+ fatal("signature from key '%s' failed to "
+ "verify: %s",
+ keystr, isc_result_totext(result));
+ }
+ }
+ tuple = NULL;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ domain, rdataset.ttl,
+ &rdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+ dst_key_free(&key);
+ }
+
+ result = dns_db_deleterdataset(db, node, version, dns_rdatatype_rrsig,
+ dns_rdatatype_dnskey);
+ check_result(result, "dns_db_deleterdataset");
+
+ result = dns_diff_apply(&diff, db, version);
+ check_result(result, "dns_diff_apply");
+ dns_diff_clear(&diff);
+
+ dns_db_detachnode(db, &node);
+ dns_db_closeversion(db, &version, ISC_TRUE);
+ result = dns_db_dump(db, version, output);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to write database to '%s': %s",
+ output, isc_result_totext(result));
+
+ printf("%s\n", output);
+
+ dns_rdataset_disassociate(&rdataset);
+ dns_rdataset_disassociate(&sigrdataset);
+
+ dns_db_detach(&db);
+
+ while (!ISC_LIST_EMPTY(keylist)) {
+ keynode = ISC_LIST_HEAD(keylist);
+ ISC_LIST_UNLINK(keylist, keynode, link);
+ dst_key_free(&keynode->key);
+ isc_mem_put(mctx, keynode, sizeof(keynode_t));
+ }
+
+ cleanup_logging(&log);
+
+ isc_mem_free(mctx, output);
+ cleanup_entropy(&ectx);
+ dst_lib_destroy();
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+ return (0);
+}
diff --git a/contrib/bind9/bin/dnssec/dnssec-signkey.docbook b/contrib/bind9/bin/dnssec/dnssec-signkey.docbook
new file mode 100644
index 000000000000..8258a3da7102
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-signkey.docbook
@@ -0,0 +1,237 @@
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<!--
+ - Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2001, 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-signkey.docbook,v 1.2.2.2.4.2 2004/06/03 02:24:55 marka Exp $ -->
+
+<refentry>
+ <refentryinfo>
+ <date>June 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-signkey</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-signkey</application></refname>
+ <refpurpose>DNSSEC key set signing tool</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dnssec-signkey</command>
+ <arg><option>-a</option></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-s <replaceable class="parameter">start-time</replaceable></option></arg>
+ <arg><option>-e <replaceable class="parameter">end-time</replaceable></option></arg>
+ <arg><option>-h</option></arg>
+ <arg><option>-p</option></arg>
+ <arg><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="req">keyset</arg>
+ <arg choice="req" rep="repeat">key</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>
+ <command>dnssec-signkey</command> signs a keyset. Typically
+ the keyset will be for a child zone, and will have been generated
+ by <command>dnssec-makekeyset</command>. The child zone's keyset
+ is signed with the zone keys for its parent zone. The output file
+ is of the form <filename>signedkey-nnnn.</filename>, where
+ <filename>nnnn</filename> is the zone name.
+ </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 key sets.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">start-time</replaceable></term>
+ <listitem>
+ <para>
+ Specify the date and time when the generated SIG 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 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 SIG 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>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>dnssec-signkey</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>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>keyset</term>
+ <listitem>
+ <para>
+ The file containing the child's keyset.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>key</term>
+ <listitem>
+ <para>
+ The keys used to sign the child's keyset.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>EXAMPLE</title>
+ <para>
+ The DNS administrator for a DNSSEC-aware <userinput>.com</userinput>
+ zone would use the following command to sign the
+ <filename>keyset</filename> file for <userinput>example.com</userinput>
+ created by <command>dnssec-makekeyset</command> with a key generated
+ by <command>dnssec-keygen</command>:
+ </para>
+ <para>
+ <userinput>dnssec-signkey keyset-example.com. Kcom.+003+51944</userinput>
+ </para>
+ <para>
+ In this example, <command>dnssec-signkey</command> creates
+ the file <filename>signedkey-example.com.</filename>, which
+ contains the <userinput>example.com</userinput> keys and the
+ signatures by the <userinput>.com</userinput> keys.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-makekeyset</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para>
+ <corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry>
+
+<!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/contrib/bind9/bin/dnssec/dnssec-signkey.html b/contrib/bind9/bin/dnssec/dnssec-signkey.html
new file mode 100644
index 000000000000..8cbf1fc736a3
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-signkey.html
@@ -0,0 +1,407 @@
+<!--
+ - Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2001, 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-signkey.html,v 1.4.2.1.4.1 2004/03/06 10:21:15 marka Exp $ -->
+
+<HTML
+><HEAD
+><TITLE
+>dnssec-signkey</TITLE
+><META
+NAME="GENERATOR"
+CONTENT="Modular DocBook HTML Stylesheet Version 1.73
+"></HEAD
+><BODY
+CLASS="REFENTRY"
+BGCOLOR="#FFFFFF"
+TEXT="#000000"
+LINK="#0000FF"
+VLINK="#840084"
+ALINK="#0000FF"
+><H1
+><A
+NAME="AEN1"
+><SPAN
+CLASS="APPLICATION"
+>dnssec-signkey</SPAN
+></A
+></H1
+><DIV
+CLASS="REFNAMEDIV"
+><A
+NAME="AEN9"
+></A
+><H2
+>Name</H2
+><SPAN
+CLASS="APPLICATION"
+>dnssec-signkey</SPAN
+>&nbsp;--&nbsp;DNSSEC key set signing tool</DIV
+><DIV
+CLASS="REFSYNOPSISDIV"
+><A
+NAME="AEN13"
+></A
+><H2
+>Synopsis</H2
+><P
+><B
+CLASS="COMMAND"
+>dnssec-signkey</B
+> [<TT
+CLASS="OPTION"
+>-a</TT
+>] [<TT
+CLASS="OPTION"
+>-c <TT
+CLASS="REPLACEABLE"
+><I
+>class</I
+></TT
+></TT
+>] [<TT
+CLASS="OPTION"
+>-s <TT
+CLASS="REPLACEABLE"
+><I
+>start-time</I
+></TT
+></TT
+>] [<TT
+CLASS="OPTION"
+>-e <TT
+CLASS="REPLACEABLE"
+><I
+>end-time</I
+></TT
+></TT
+>] [<TT
+CLASS="OPTION"
+>-h</TT
+>] [<TT
+CLASS="OPTION"
+>-p</TT
+>] [<TT
+CLASS="OPTION"
+>-r <TT
+CLASS="REPLACEABLE"
+><I
+>randomdev</I
+></TT
+></TT
+>] [<TT
+CLASS="OPTION"
+>-v <TT
+CLASS="REPLACEABLE"
+><I
+>level</I
+></TT
+></TT
+>] {keyset} {key...}</P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN39"
+></A
+><H2
+>DESCRIPTION</H2
+><P
+> <B
+CLASS="COMMAND"
+>dnssec-signkey</B
+> signs a keyset. Typically
+ the keyset will be for a child zone, and will have been generated
+ by <B
+CLASS="COMMAND"
+>dnssec-makekeyset</B
+>. The child zone's keyset
+ is signed with the zone keys for its parent zone. The output file
+ is of the form <TT
+CLASS="FILENAME"
+>signedkey-nnnn.</TT
+>, where
+ <TT
+CLASS="FILENAME"
+>nnnn</TT
+> is the zone name.
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN46"
+></A
+><H2
+>OPTIONS</H2
+><P
+></P
+><DIV
+CLASS="VARIABLELIST"
+><DL
+><DT
+>-a</DT
+><DD
+><P
+> Verify all generated signatures.
+ </P
+></DD
+><DT
+>-c <TT
+CLASS="REPLACEABLE"
+><I
+>class</I
+></TT
+></DT
+><DD
+><P
+> Specifies the DNS class of the key sets.
+ </P
+></DD
+><DT
+>-s <TT
+CLASS="REPLACEABLE"
+><I
+>start-time</I
+></TT
+></DT
+><DD
+><P
+> Specify the date and time when the generated SIG 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 <TT
+CLASS="OPTION"
+>start-time</TT
+> is specified, the current
+ time is used.
+ </P
+></DD
+><DT
+>-e <TT
+CLASS="REPLACEABLE"
+><I
+>end-time</I
+></TT
+></DT
+><DD
+><P
+> Specify the date and time when the generated SIG records
+ expire. As with <TT
+CLASS="OPTION"
+>start-time</TT
+>, 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 <TT
+CLASS="OPTION"
+>end-time</TT
+> is
+ specified, 30 days from the start time is used as a default.
+ </P
+></DD
+><DT
+>-h</DT
+><DD
+><P
+> Prints a short summary of the options and arguments to
+ <B
+CLASS="COMMAND"
+>dnssec-signkey</B
+>.
+ </P
+></DD
+><DT
+>-p</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
+>-r <TT
+CLASS="REPLACEABLE"
+><I
+>randomdev</I
+></TT
+></DT
+><DD
+><P
+> Specifies the source of randomness. If the operating
+ system does not provide a <TT
+CLASS="FILENAME"
+>/dev/random</TT
+>
+ or equivalent device, the default source of randomness
+ is keyboard input. <TT
+CLASS="FILENAME"
+>randomdev</TT
+> specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <TT
+CLASS="FILENAME"
+>keyboard</TT
+> indicates that keyboard
+ input should be used.
+ </P
+></DD
+><DT
+>-v <TT
+CLASS="REPLACEABLE"
+><I
+>level</I
+></TT
+></DT
+><DD
+><P
+> Sets the debugging level.
+ </P
+></DD
+><DT
+>keyset</DT
+><DD
+><P
+> The file containing the child's keyset.
+ </P
+></DD
+><DT
+>key</DT
+><DD
+><P
+> The keys used to sign the child's keyset.
+ </P
+></DD
+></DL
+></DIV
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN101"
+></A
+><H2
+>EXAMPLE</H2
+><P
+> The DNS administrator for a DNSSEC-aware <TT
+CLASS="USERINPUT"
+><B
+>.com</B
+></TT
+>
+ zone would use the following command to sign the
+ <TT
+CLASS="FILENAME"
+>keyset</TT
+> file for <TT
+CLASS="USERINPUT"
+><B
+>example.com</B
+></TT
+>
+ created by <B
+CLASS="COMMAND"
+>dnssec-makekeyset</B
+> with a key generated
+ by <B
+CLASS="COMMAND"
+>dnssec-keygen</B
+>:
+ </P
+><P
+> <TT
+CLASS="USERINPUT"
+><B
+>dnssec-signkey keyset-example.com. Kcom.+003+51944</B
+></TT
+>
+ </P
+><P
+> In this example, <B
+CLASS="COMMAND"
+>dnssec-signkey</B
+> creates
+ the file <TT
+CLASS="FILENAME"
+>signedkey-example.com.</TT
+>, which
+ contains the <TT
+CLASS="USERINPUT"
+><B
+>example.com</B
+></TT
+> keys and the
+ signatures by the <TT
+CLASS="USERINPUT"
+><B
+>.com</B
+></TT
+> keys.
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN116"
+></A
+><H2
+>SEE ALSO</H2
+><P
+> <SPAN
+CLASS="CITEREFENTRY"
+><SPAN
+CLASS="REFENTRYTITLE"
+>dnssec-keygen</SPAN
+>(8)</SPAN
+>,
+ <SPAN
+CLASS="CITEREFENTRY"
+><SPAN
+CLASS="REFENTRYTITLE"
+>dnssec-makekeyset</SPAN
+>(8)</SPAN
+>,
+ <SPAN
+CLASS="CITEREFENTRY"
+><SPAN
+CLASS="REFENTRYTITLE"
+>dnssec-signzone</SPAN
+>(8)</SPAN
+>.
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN128"
+></A
+><H2
+>AUTHOR</H2
+><P
+> Internet Software Consortium
+ </P
+></DIV
+></BODY
+></HTML
+>
diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.8 b/contrib/bind9/bin/dnssec/dnssec-signzone.8
new file mode 100644
index 000000000000..a1795b8001a2
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-signzone.8
@@ -0,0 +1,167 @@
+.\" Copyright (C) 2004 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.23.2.1.4.6 2004/06/11 02:32:46 marka Exp $
+.\"
+.TH "DNSSEC-SIGNZONE" "8" "June 30, 2000" "BIND9" ""
+.SH NAME
+dnssec-signzone \- DNSSEC zone signing tool
+.SH SYNOPSIS
+.sp
+\fBdnssec-signzone\fR [ \fB-a\fR ] [ \fB-c \fIclass\fB\fR ] [ \fB-d \fIdirectory\fB\fR ] [ \fB-e \fIend-time\fB\fR ] [ \fB-f \fIoutput-file\fB\fR ] [ \fB-g\fR ] [ \fB-h\fR ] [ \fB-k \fIkey\fB\fR ] [ \fB-l \fIdomain\fB\fR ] [ \fB-i \fIinterval\fB\fR ] [ \fB-n \fInthreads\fB\fR ] [ \fB-o \fIorigin\fB\fR ] [ \fB-p\fR ] [ \fB-r \fIrandomdev\fB\fR ] [ \fB-s \fIstart-time\fB\fR ] [ \fB-t\fR ] [ \fB-v \fIlevel\fB\fR ] [ \fB-z\fR ] \fBzonefile\fR [ \fBkey\fR\fI...\fR ]
+.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"
+.TP
+\fB-a\fR
+Verify all generated signatures.
+.TP
+\fB-c \fIclass\fB\fR
+Specifies the DNS class of the zone.
+.TP
+\fB-k \fIkey\fB\fR
+Treat specified key as a key signing key ignoring any
+key flags. This option may be specified multiple times.
+.TP
+\fB-l \fIdomain\fB\fR
+Generate a DLV set in addition to the key (DNSKEY) and DS sets.
+The domain is appended to the name of the records.
+.TP
+\fB-d \fIdirectory\fB\fR
+Look for \fIkeyset\fR files in
+\fBdirectory\fR as the directory
+.TP
+\fB-g\fR
+Generate DS records for child zones from keyset files.
+Existing DS records will be removed.
+.TP
+\fB-s \fIstart-time\fB\fR
+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.
+.TP
+\fB-e \fIend-time\fB\fR
+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.
+.TP
+\fB-f \fIoutput-file\fB\fR
+The name of the output file containing the signed zone. The
+default is to append \fI.signed\fR to the
+input file.
+.TP
+\fB-h\fR
+Prints a short summary of the options and arguments to
+\fBdnssec-signzone\fR.
+.TP
+\fB-i \fIinterval\fB\fR
+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.
+
+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.
+.TP
+\fB-n \fIncpus\fB\fR
+Specifies the number of threads to use. By default, one
+thread is started for each detected CPU.
+.TP
+\fB-o \fIorigin\fB\fR
+The zone origin. If not specified, the name of the zone file
+is assumed to be the origin.
+.TP
+\fB-p\fR
+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.
+.TP
+\fB-r \fIrandomdev\fB\fR
+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.
+.TP
+\fB-t\fR
+Print statistics at completion.
+.TP
+\fB-v \fIlevel\fB\fR
+Sets the debugging level.
+.TP
+\fB-z\fR
+Ignore KSK flag on key when determining what to sign.
+.TP
+\fBzonefile\fR
+The file containing the zone to be signed.
+Sets the debugging level.
+.TP
+\fBkey\fR
+The keys used to sign the zone. If no keys are specified, the
+default all zone keys that have private key files in the
+current directory.
+.SH "EXAMPLE"
+.PP
+The following command signs the \fBexample.com\fR
+zone with the DSA key generated in the \fBdnssec-keygen\fR
+man page. The zone's keys must be in the zone. If there are
+\fIkeyset\fR files associated with child zones,
+they must be in the current directory.
+\fBexample.com\fR, the following command would be
+issued:
+.PP
+\fBdnssec-signzone -o example.com db.example.com Kexample.com.+003+26160\fR
+.PP
+The command would print a string of the form:
+.PP
+In this 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.
+.SH "SEE ALSO"
+.PP
+\fBdnssec-keygen\fR(8),
+\fIBIND 9 Administrator Reference Manual\fR,
+\fIRFC 2535\fR.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.c b/contrib/bind9/bin/dnssec/dnssec-signzone.c
new file mode 100644
index 000000000000..096cd30508ab
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-signzone.c
@@ -0,0 +1,2102 @@
+/*
+ * Portions Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 1999-2003 Internet Software Consortium.
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 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.139.2.2.4.16 2004/08/28 06:25:29 marka Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <time.h>
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/event.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/os.h>
+#include <isc/print.h>
+#include <isc/serial.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+#include <isc/time.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/rdata.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/time.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-signzone";
+int verbose;
+
+#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)
+
+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 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 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 isc_task_t *master = NULL;
+static unsigned int ntasks = 0;
+static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
+static unsigned int assigned = 0, completed = 0;
+static isc_boolean_t nokeys = ISC_FALSE;
+static isc_boolean_t removefile = ISC_FALSE;
+static isc_boolean_t generateds = ISC_FALSE;
+static isc_boolean_t ignoreksk = ISC_FALSE;
+static dns_name_t *dlv = NULL;
+static dns_fixedname_t dlv_fixed;
+static dns_master_style_t *dsstyle = NULL;
+
+#define INCSTAT(counter) \
+ if (printstats) { \
+ LOCK(&statslock); \
+ counter++; \
+ UNLOCK(&statslock); \
+ }
+
+static void
+sign(isc_task_t *task, isc_event_t *event);
+
+
+static inline void
+set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
+ unsigned int shift, mask;
+
+ shift = 7 - (index % 8);
+ mask = 1 << shift;
+
+ if (bit != 0)
+ array[index / 8] |= mask;
+ else
+ array[index / 8] &= (~mask & 0xFF);
+}
+
+static void
+dumpnode(dns_name_t *name, dns_dbnode_t *node) {
+ isc_result_t result;
+
+ result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name,
+ masterstyle, fp);
+ check_result(result, "dns_master_dumpnodetostream");
+}
+
+static void
+dumpdb(dns_db_t *db) {
+ dns_dbiterator_t *dbiter = NULL;
+ dns_dbnode_t *node;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_result_t result;
+
+ dbiter = NULL;
+ result = dns_db_createiterator(db, ISC_FALSE, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ node = NULL;
+
+ for (result = dns_dbiterator_first(dbiter);
+ result == ISC_R_SUCCESS;
+ result = dns_dbiterator_next(dbiter))
+ {
+ result = dns_dbiterator_current(dbiter, &node, name);
+ check_result(result, "dns_dbiterator_current()");
+ dumpnode(name, node);
+ dns_db_detachnode(db, &node);
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("iterating database: %s", isc_result_totext(result));
+
+ dns_dbiterator_destroy(&dbiter);
+}
+
+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;
+
+ result = dns_dnssec_sign(name, rdataset, key, &starttime, &endtime,
+ 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));
+}
+
+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);
+ }
+ 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
+nsec_setbit(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdatatype_t type,
+ unsigned int val)
+{
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec_t nsec;
+ unsigned int newlen;
+ unsigned char bitmap[8192 + 512];
+ unsigned char nsecdata[8192 + 512 + DNS_NAME_MAXWIRE];
+ isc_boolean_t answer = ISC_FALSE;
+ unsigned int i, len, window;
+ int octet;
+
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "dns_rdataset_first()");
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+ INSIST(nsec.len <= sizeof(bitmap));
+
+ newlen = 0;
+
+ memset(bitmap, 0, sizeof(bitmap));
+ for (i = 0; i < nsec.len; i += len) {
+ INSIST(i + 2 <= nsec.len);
+ window = nsec.typebits[i];
+ len = nsec.typebits[i+1];
+ i += 2;
+ INSIST(len > 0 && len <= 32);
+ INSIST(i + len <= nsec.len);
+ memmove(&bitmap[window * 32 + 512], &nsec.typebits[i], len);
+ }
+ set_bit(bitmap + 512, type, val);
+ for (window = 0; window < 256; window++) {
+ for (octet = 31; octet >= 0; octet--)
+ if (bitmap[window * 32 + 512 + octet] != 0)
+ break;
+ if (octet < 0)
+ continue;
+ bitmap[newlen] = window;
+ bitmap[newlen + 1] = octet + 1;
+ newlen += 2;
+ /*
+ * Overlapping move.
+ */
+ memmove(&bitmap[newlen], &bitmap[window * 32 + 512], octet + 1);
+ newlen += octet + 1;
+ }
+ if (newlen != nsec.len ||
+ memcmp(nsec.typebits, bitmap, newlen) != 0) {
+ dns_rdata_t newrdata = DNS_RDATA_INIT;
+ isc_buffer_t b;
+ dns_diff_t diff;
+ dns_difftuple_t *tuple = NULL;
+
+ dns_diff_init(mctx, &diff);
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL, name,
+ rdataset->ttl, &rdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+
+ nsec.typebits = bitmap;
+ nsec.len = newlen;
+ isc_buffer_init(&b, nsecdata, sizeof(nsecdata));
+ result = dns_rdata_fromstruct(&newrdata, rdata.rdclass,
+ dns_rdatatype_nsec, &nsec,
+ &b);
+ check_result(result, "dns_rdata_fromstruct");
+
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ name, rdataset->ttl,
+ &newrdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+ result = dns_diff_apply(&diff, gdb, gversion);
+ check_result(result, "dns_difftuple_apply");
+ dns_diff_clear(&diff);
+ answer = ISC_TRUE;
+ }
+ dns_rdata_freestruct(&nsec);
+ return (answer);
+}
+
+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));
+}
+
+/*
+ * Signs all records at a name. This mostly just signs each set individually,
+ * but also adds the RRSIG bit to any NSECs generated earlier, deals with
+ * parent/child KEY signatures, and handles other exceptional cases.
+ */
+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;
+ isc_boolean_t hasds = ISC_FALSE;
+ isc_boolean_t atorigin;
+ isc_boolean_t changed = ISC_FALSE;
+ dns_diff_t del, add;
+ char namestr[DNS_NAME_FORMATSIZE];
+ isc_uint32_t nsttl = 0;
+
+ dns_name_format(name, namestr, sizeof(namestr));
+
+ atorigin = dns_name_equal(name, gorigin);
+
+ /*
+ * Determine if this is a delegation point.
+ */
+ if (delegation(name, node, &nsttl))
+ isdelegation = ISC_TRUE;
+
+ /*
+ * If this is a delegation point, look for a DS set.
+ */
+ if (isdelegation) {
+ dns_rdataset_t dsset;
+ dns_rdataset_t sigdsset;
+
+ 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);
+ if (generateds) {
+ result = dns_db_deleterdataset(gdb, node,
+ gversion,
+ dns_rdatatype_ds,
+ 0);
+ check_result(result, "dns_db_deleterdataset");
+ } else
+ hasds = ISC_TRUE;
+ }
+ if (generateds) {
+ 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");
+ hasds = ISC_TRUE;
+ 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);
+ }
+ } else if (dns_rdataset_isassociated(&sigdsset))
+ dns_rdataset_disassociate(&sigdsset);
+ }
+
+ /*
+ * Make sure that NSEC bits are appropriately set.
+ */
+ dns_rdataset_init(&rdataset);
+ RUNTIME_CHECK(dns_db_findrdataset(gdb, node, gversion,
+ dns_rdatatype_nsec, 0, 0, &rdataset,
+ NULL) == ISC_R_SUCCESS);
+ if (!nokeys)
+ changed = nsec_setbit(name, &rdataset, dns_rdatatype_rrsig, 1);
+ if (changed) {
+ dns_rdataset_disassociate(&rdataset);
+ RUNTIME_CHECK(dns_db_findrdataset(gdb, node, gversion,
+ dns_rdatatype_nsec, 0, 0,
+ &rdataset,
+ NULL) == ISC_R_SUCCESS);
+ }
+ if (hasds)
+ (void)nsec_setbit(name, &rdataset, dns_rdatatype_ds, 1);
+ else
+ (void)nsec_setbit(name, &rdataset, dns_rdatatype_ds, 0);
+ dns_rdataset_disassociate(&rdataset);
+
+ /*
+ * 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 != dns_rdatatype_nsec &&
+ 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;
+ isc_boolean_t active = ISC_FALSE;
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ 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 (rdataset.type != dns_rdatatype_nsec &&
+ 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) {
+ /*
+ * Make sure there is no NSEC / RRSIG records for
+ * this node.
+ */
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ dns_rdatatype_nsec, 0);
+ if (result == DNS_R_UNCHANGED)
+ result = ISC_R_SUCCESS;
+ check_result(result, "dns_db_deleterdataset(nsec)");
+
+ result = dns_rdatasetiter_first(rdsiter);
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter)) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ if (rdataset.type == dns_rdatatype_rrsig) {
+ dns_rdatatype_t type = rdataset.type;
+ dns_rdatatype_t covers = rdataset.covers;
+ result = dns_db_deleterdataset(gdb, node,
+ gversion, type,
+ covers);
+ if (result == DNS_R_UNCHANGED)
+ result = ISC_R_SUCCESS;
+ check_result(result,
+ "dns_db_deleterdataset(rrsig)");
+ }
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ }
+ 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);
+}
+
+/*
+ * 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;
+
+ 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, ISC_FALSE, &gdbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(gdbiter);
+ check_result(result, "dns_dbiterator_first()");
+}
+
+/*
+ * Clean up the iterator and global state after the tasks complete.
+ */
+static void
+postsign(void) {
+ dns_dbiterator_destroy(&gdbiter);
+}
+
+/*
+ * 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;
+
+ if (shuttingdown)
+ return;
+
+ if (finished) {
+ if (assigned == completed) {
+ isc_task_detach(&task);
+ isc_app_shutdown();
+ }
+ return;
+ }
+
+ 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;
+ LOCK(&namelock);
+ while (!found) {
+ result = dns_dbiterator_current(gdbiter, &node, name);
+ if (result != ISC_R_SUCCESS)
+ fatal("failure iterating database: %s",
+ isc_result_totext(result));
+ dns_rdataset_init(&nsec);
+ result = dns_db_findrdataset(gdb, node, gversion,
+ dns_rdatatype_nsec, 0, 0,
+ &nsec, NULL);
+ if (result == ISC_R_SUCCESS)
+ found = ISC_TRUE;
+ else
+ dumpnode(name, node);
+ if (dns_rdataset_isassociated(&nsec))
+ dns_rdataset_disassociate(&nsec);
+ if (!found)
+ dns_db_detachnode(gdb, &node);
+
+ 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));
+ }
+ UNLOCK(&namelock);
+ if (!found) {
+ if (assigned == completed) {
+ isc_task_detach(&task);
+ isc_app_shutdown();
+ }
+ isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
+ return;
+ }
+ 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));
+ assigned++;
+}
+
+/*
+ * 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;
+
+ completed++;
+ 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));
+}
+
+/*
+ * 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;
+
+ 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, ISC_FALSE, &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, NULL)) {
+ zonecut = dns_fixedname_name(&fzonecut);
+ dns_name_copy(name, zonecut, NULL);
+ }
+ 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 (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(gdb, &nextnode);
+ break;
+ }
+ 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);
+}
+
+/*
+ * 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_load(*db, file);
+ 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], ISC_TRUE);
+ 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;
+ dst_key_t *pubkey;
+ isc_result_t result;
+ dns_rdata_key_t key;
+ isc_boolean_t have_non_ksk = ISC_FALSE;
+
+ dns_db_currentversion(db, &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_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);
+ } 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;
+
+ currenttime = time(NULL);
+ fprintf(fp, "; File written on %s", ctime(&currenttime));
+}
+
+static void
+print_version(FILE *fp) {
+ 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-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-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-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 *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;
+ dns_db_t *udb = NULL;
+ isc_task_t **tasks = NULL;
+ isc_buffer_t b;
+ int len;
+
+ 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();
+
+ while ((ch = isc_commandline_parse(argc, argv,
+ "ac:d:e:f:ghi:k:l:n:o:pr:s:Stv:z"))
+ != -1) {
+ switch (ch) {
+ 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 'h':
+ default:
+ usage();
+ break;
+
+ 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 '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 '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 'o':
+ origin = 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 '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 = 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();
+ 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);
+ }
+
+ 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();
+
+ 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));
+
+ 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));
+
+ 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;
+ }
+
+ warnifallksk(gdb);
+
+ gversion = NULL;
+ result = dns_db_newversion(gdb, &gversion);
+ check_result(result, "dns_db_newversion()");
+
+ 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));
+ result = isc_app_onrun(mctx, master, startworker, tasks[i]);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to start 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();
+ (void)isc_app_run();
+ if (!finished)
+ fatal("process aborted by user");
+ 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 (udb != NULL) {
+ dumpdb(udb);
+ dns_db_detach(&udb);
+ }
+
+ 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();
+ cleanup_entropy(&ectx);
+ 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/contrib/bind9/bin/dnssec/dnssec-signzone.docbook b/contrib/bind9/bin/dnssec/dnssec-signzone.docbook
new file mode 100644
index 000000000000..2b85102a0b54
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-signzone.docbook
@@ -0,0 +1,362 @@
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<!--
+ - Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2001-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.docbook,v 1.2.2.2.4.8 2004/06/11 01:17:35 marka Exp $ -->
+
+<refentry>
+ <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>
+
+ <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>-n <replaceable class="parameter">nthreads</replaceable></option></arg>
+ <arg><option>-o <replaceable class="parameter">origin</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 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 file.
+ </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>-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>-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>-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>zonefile</term>
+ <listitem>
+ <para>
+ The file containing the zone to be signed.
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>key</term>
+ <listitem>
+ <para>
+ The keys used to sign the zone. If no keys are specified, the
+ default all zone keys that have private key files in the
+ current directory.
+ </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 in the <command>dnssec-keygen</command>
+ man page. The zone's keys must be in the zone. If there are
+ <filename>keyset</filename> files associated with child zones,
+ they must be in the current directory.
+ <userinput>example.com</userinput>, the following command would be
+ issued:
+ </para>
+ <para>
+ <userinput>dnssec-signzone -o example.com db.example.com Kexample.com.+003+26160</userinput>
+ </para>
+ <para>
+ The command would print a string of the form:
+ </para>
+ <para>
+ In this 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>
+ </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 2535</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para>
+ <corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry>
+
+<!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.html b/contrib/bind9/bin/dnssec/dnssec-signzone.html
new file mode 100644
index 000000000000..221099fbdbec
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssec-signzone.html
@@ -0,0 +1,553 @@
+<!--
+ - Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2001-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.4.2.1.4.7 2004/08/22 23:38:58 marka Exp $ -->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<HTML
+><HEAD
+><TITLE
+>dnssec-signzone</TITLE
+><META
+NAME="GENERATOR"
+CONTENT="Modular DocBook HTML Stylesheet Version 1.7"></HEAD
+><BODY
+CLASS="REFENTRY"
+BGCOLOR="#FFFFFF"
+TEXT="#000000"
+LINK="#0000FF"
+VLINK="#840084"
+ALINK="#0000FF"
+><H1
+><A
+NAME="AEN1"
+></A
+><SPAN
+CLASS="APPLICATION"
+>dnssec-signzone</SPAN
+></H1
+><DIV
+CLASS="REFNAMEDIV"
+><A
+NAME="AEN9"
+></A
+><H2
+>Name</H2
+><SPAN
+CLASS="APPLICATION"
+>dnssec-signzone</SPAN
+>&nbsp;--&nbsp;DNSSEC zone signing tool</DIV
+><DIV
+CLASS="REFSYNOPSISDIV"
+><A
+NAME="AEN13"
+></A
+><H2
+>Synopsis</H2
+><P
+><B
+CLASS="COMMAND"
+>dnssec-signzone</B
+> [<VAR
+CLASS="OPTION"
+>-a</VAR
+>] [<VAR
+CLASS="OPTION"
+>-c <VAR
+CLASS="REPLACEABLE"
+>class</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-d <VAR
+CLASS="REPLACEABLE"
+>directory</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-e <VAR
+CLASS="REPLACEABLE"
+>end-time</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-f <VAR
+CLASS="REPLACEABLE"
+>output-file</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-g</VAR
+>] [<VAR
+CLASS="OPTION"
+>-h</VAR
+>] [<VAR
+CLASS="OPTION"
+>-k <VAR
+CLASS="REPLACEABLE"
+>key</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-l <VAR
+CLASS="REPLACEABLE"
+>domain</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-i <VAR
+CLASS="REPLACEABLE"
+>interval</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-n <VAR
+CLASS="REPLACEABLE"
+>nthreads</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-o <VAR
+CLASS="REPLACEABLE"
+>origin</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-p</VAR
+>] [<VAR
+CLASS="OPTION"
+>-r <VAR
+CLASS="REPLACEABLE"
+>randomdev</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-s <VAR
+CLASS="REPLACEABLE"
+>start-time</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-t</VAR
+>] [<VAR
+CLASS="OPTION"
+>-v <VAR
+CLASS="REPLACEABLE"
+>level</VAR
+></VAR
+>] [<VAR
+CLASS="OPTION"
+>-z</VAR
+>] {zonefile} [key...]</P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN66"
+></A
+><H2
+>DESCRIPTION</H2
+><P
+> <B
+CLASS="COMMAND"
+>dnssec-signzone</B
+> 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
+ <TT
+CLASS="FILENAME"
+>keyset</TT
+> file for each child zone.
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN71"
+></A
+><H2
+>OPTIONS</H2
+><P
+></P
+><DIV
+CLASS="VARIABLELIST"
+><DL
+><DT
+>-a</DT
+><DD
+><P
+> Verify all generated signatures.
+ </P
+></DD
+><DT
+>-c <VAR
+CLASS="REPLACEABLE"
+>class</VAR
+></DT
+><DD
+><P
+> Specifies the DNS class of the zone.
+ </P
+></DD
+><DT
+>-k <VAR
+CLASS="REPLACEABLE"
+>key</VAR
+></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
+>-l <VAR
+CLASS="REPLACEABLE"
+>domain</VAR
+></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
+>-d <VAR
+CLASS="REPLACEABLE"
+>directory</VAR
+></DT
+><DD
+><P
+> Look for <TT
+CLASS="FILENAME"
+>keyset</TT
+> files in
+ <VAR
+CLASS="OPTION"
+>directory</VAR
+> as the directory
+ </P
+></DD
+><DT
+>-g</DT
+><DD
+><P
+> Generate DS records for child zones from keyset files.
+ Existing DS records will be removed.
+ </P
+></DD
+><DT
+>-s <VAR
+CLASS="REPLACEABLE"
+>start-time</VAR
+></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 <VAR
+CLASS="OPTION"
+>start-time</VAR
+> is specified, the current
+ time minus 1 hour (to allow for clock skew) is used.
+ </P
+></DD
+><DT
+>-e <VAR
+CLASS="REPLACEABLE"
+>end-time</VAR
+></DT
+><DD
+><P
+> Specify the date and time when the generated RRSIG records
+ expire. As with <VAR
+CLASS="OPTION"
+>start-time</VAR
+>, 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 <VAR
+CLASS="OPTION"
+>end-time</VAR
+> is
+ specified, 30 days from the start time is used as a default.
+ </P
+></DD
+><DT
+>-f <VAR
+CLASS="REPLACEABLE"
+>output-file</VAR
+></DT
+><DD
+><P
+> The name of the output file containing the signed zone. The
+ default is to append <TT
+CLASS="FILENAME"
+>.signed</TT
+> to the
+ input file.
+ </P
+></DD
+><DT
+>-h</DT
+><DD
+><P
+> Prints a short summary of the options and arguments to
+ <B
+CLASS="COMMAND"
+>dnssec-signzone</B
+>.
+ </P
+></DD
+><DT
+>-i <VAR
+CLASS="REPLACEABLE"
+>interval</VAR
+></DT
+><DD
+><P
+> When a previously signed zone is passed as input, records
+ may be resigned. The <VAR
+CLASS="OPTION"
+>interval</VAR
+> 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
+ <VAR
+CLASS="OPTION"
+>end-time</VAR
+> or <VAR
+CLASS="OPTION"
+>start-time</VAR
+>
+ are specified, <B
+CLASS="COMMAND"
+>dnssec-signzone</B
+> 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
+>-n <VAR
+CLASS="REPLACEABLE"
+>ncpus</VAR
+></DT
+><DD
+><P
+> Specifies the number of threads to use. By default, one
+ thread is started for each detected CPU.
+ </P
+></DD
+><DT
+>-o <VAR
+CLASS="REPLACEABLE"
+>origin</VAR
+></DT
+><DD
+><P
+> The zone origin. If not specified, the name of the zone file
+ is assumed to be the origin.
+ </P
+></DD
+><DT
+>-p</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
+>-r <VAR
+CLASS="REPLACEABLE"
+>randomdev</VAR
+></DT
+><DD
+><P
+> Specifies the source of randomness. If the operating
+ system does not provide a <TT
+CLASS="FILENAME"
+>/dev/random</TT
+>
+ or equivalent device, the default source of randomness
+ is keyboard input. <TT
+CLASS="FILENAME"
+>randomdev</TT
+> specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <TT
+CLASS="FILENAME"
+>keyboard</TT
+> indicates that keyboard
+ input should be used.
+ </P
+></DD
+><DT
+>-t</DT
+><DD
+><P
+> Print statistics at completion.
+ </P
+></DD
+><DT
+>-v <VAR
+CLASS="REPLACEABLE"
+>level</VAR
+></DT
+><DD
+><P
+> Sets the debugging level.
+ </P
+></DD
+><DT
+>-z</DT
+><DD
+><P
+> Ignore KSK flag on key when determining what to sign.
+ </P
+></DD
+><DT
+>zonefile</DT
+><DD
+><P
+> The file containing the zone to be signed.
+ Sets the debugging level.
+ </P
+></DD
+><DT
+>key</DT
+><DD
+><P
+> The keys used to sign the zone. If no keys are specified, the
+ default all zone keys that have private key files in the
+ current directory.
+ </P
+></DD
+></DL
+></DIV
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN181"
+></A
+><H2
+>EXAMPLE</H2
+><P
+> The following command signs the <KBD
+CLASS="USERINPUT"
+>example.com</KBD
+>
+ zone with the DSA key generated in the <B
+CLASS="COMMAND"
+>dnssec-keygen</B
+>
+ man page. The zone's keys must be in the zone. If there are
+ <TT
+CLASS="FILENAME"
+>keyset</TT
+> files associated with child zones,
+ they must be in the current directory.
+ <KBD
+CLASS="USERINPUT"
+>example.com</KBD
+>, the following command would be
+ issued:
+ </P
+><P
+> <KBD
+CLASS="USERINPUT"
+>dnssec-signzone -o example.com db.example.com Kexample.com.+003+26160</KBD
+>
+ </P
+><P
+> The command would print a string of the form:
+ </P
+><P
+> In this example, <B
+CLASS="COMMAND"
+>dnssec-signzone</B
+> creates
+ the file <TT
+CLASS="FILENAME"
+>db.example.com.signed</TT
+>. This file
+ should be referenced in a zone statement in a
+ <TT
+CLASS="FILENAME"
+>named.conf</TT
+> file.
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN195"
+></A
+><H2
+>SEE ALSO</H2
+><P
+> <SPAN
+CLASS="CITEREFENTRY"
+><SPAN
+CLASS="REFENTRYTITLE"
+>dnssec-keygen</SPAN
+>(8)</SPAN
+>,
+ <I
+CLASS="CITETITLE"
+>BIND 9 Administrator Reference Manual</I
+>,
+ <I
+CLASS="CITETITLE"
+>RFC 2535</I
+>.
+ </P
+></DIV
+><DIV
+CLASS="REFSECT1"
+><A
+NAME="AEN203"
+></A
+><H2
+>AUTHOR</H2
+><P
+> Internet Systems Consortium
+ </P
+></DIV
+></BODY
+></HTML
+>
diff --git a/contrib/bind9/bin/dnssec/dnssectool.c b/contrib/bind9/bin/dnssec/dnssectool.c
new file mode 100644
index 000000000000..1b84de8f48aa
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssectool.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001, 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: dnssectool.c,v 1.31.2.3.2.4 2004/03/08 02:07:38 marka Exp $ */
+
+#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;
+
+ 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/contrib/bind9/bin/dnssec/dnssectool.h b/contrib/bind9/bin/dnssec/dnssectool.h
new file mode 100644
index 000000000000..0d179503b766
--- /dev/null
+++ b/contrib/bind9/bin/dnssec/dnssectool.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001, 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: dnssectool.h,v 1.15.12.3 2004/03/08 04:04:18 marka 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 10
+
+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 */