diff options
author | Tom Rhodes <trhodes@FreeBSD.org> | 2004-09-19 01:30:24 +0000 |
---|---|---|
committer | Tom Rhodes <trhodes@FreeBSD.org> | 2004-09-19 01:30:24 +0000 |
commit | b1e4bd53e00e9694dd378a884abd3f2dd790190d (patch) | |
tree | 97706b7f62557da0a2539b026e5cf66008ddf8c6 /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')
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 <TBA\>. 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 +> -- 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 <TBA\>. 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 +> -- 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 +> -- 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, ¤tversion); + + 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, ¤tversion, 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, ¤tversion); + + result = dns_db_findnode(db, gorigin, ISC_FALSE, &node); + if (result != ISC_R_SUCCESS) + fatal("failed to find the zone's origin: %s", + isc_result_totext(result)); + + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, currentversion, + dns_rdatatype_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, ¤tversion, ISC_FALSE); +} + +static void +warnifallksk(dns_db_t *db) { + dns_dbversion_t *currentversion = NULL; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + dst_key_t *pubkey; + isc_result_t result; + dns_rdata_key_t key; + isc_boolean_t have_non_ksk = ISC_FALSE; + + dns_db_currentversion(db, ¤tversion); + + result = dns_db_findnode(db, gorigin, ISC_FALSE, &node); + if (result != ISC_R_SUCCESS) + fatal("failed to find the zone's origin: %s", + isc_result_totext(result)); + + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, currentversion, + dns_rdatatype_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, ¤tversion, 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(¤ttime)); +} + +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 +> -- 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 */ |