+ --- 9.7.0a2 released ---
+
+2636. [func] Simplify zone signing and key maintenance with the
+ dnssec-* tools. Major changes:
+ - all dnssec-* tools now take a -K option to
+ specify a directory in which key files will be
+ stored
+ - DNSSEC can now store metadata indicating when
+ they are scheduled to be published, acttivated,
+ revoked or removed; these values can be set by
+ dnssec-keygen or overwritten by the new
+ dnssec-settime command
+ - dnssec-signzone -S (for "smart") option reads key
+ metadata and uses it to determine automatically
+ which keys to publish to the zone, use for
+ signing, revoke, or remove from the zone
+ [RT #19816]
+
2635. [bug] isc_inet_ntop() incorrectly handled 0.0/16 addresses.
[RT #19716]
BIND 9.7.0
- BIND 9.7.0 includes a number of changes from BIND 9.6 and earlier
- releases. Most are intended to simplify DNSSEC configuration.
- New features include:
-
- - Simplified configuration of DNSSEC Lookaside Validation (DLV).
- - Simplified configuration of Dynamic DNS, using the "ddns-confgen"
- command line tool or the "ddns-autoconf" zone option. (As a side
- effect, this also makes it easier to configure automatic zone
- re-signing.)
+ BIND 9.7.0 includes a number of changes from BIND 9.6 and earlier
+ releases. Most are intended to simplify DNSSEC configuration.
+
+ Please note that configuration syntax and APIs for new features
+ are still experimental and are subject to change before the final
+ release.
+
+ New features include:
+
+ - Simplified configuration of DNSSEC Lookaside Validation (DLV).
+ - Simplified configuration of Dynamic DNS, using the "ddns-confgen"
+ command line tool or the "local" update-policy option. (As a side
+ effect, this also makes it easier to configure automatic zone
+ re-signing.)
- New named option "attach-cache" that allows multiple views to
share a single cache.
- - New logging category "query-errors" to provide detailed
- internal information about query failures, especially about
- server failures.
- DNS rebinding attack prevention.
- - New default values for dnssec-keygen parameters.
+ - New default values for dnssec-keygen parameters.
+ - Support for RFC 5011 (automated trust anchor maintenance)
+ - Smart signing: simplified tools for zone signing and key
+ maintenance
+ - The "statistics-channels" option is now available on Windows
- Planned but not complete in alpha:
+ Planned but not complete in this alpha:
- - Support for RFC 5011 (automated trust anchor maintenance)
- - Simplified tools for zone signing and key maintenance
- - Fully automatic signing of zones by "named"
+ - Fully automatic signing of zones by "named"
+ - DNSSEC-aware libdns API
+ - Improved PKCS#11 support, including Keyper support
BIND 9.6.0
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dighost.c,v 1.322 2009/06/24 02:51:29 marka Exp $ */
+/* $Id: dighost.c,v 1.323 2009/07/19 04:18:03 each Exp $ */
/*! \file
* \note
dst_key_t *dstkey = NULL;
debug("setup_file_key()");
- result = dst_key_fromnamedfile(keyfile, DST_TYPE_PRIVATE | DST_TYPE_KEY,
- mctx, &dstkey);
+ result = dst_key_fromnamedfile(keyfile, NULL,
+ DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
+ &dstkey);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "Couldn't read key from %s: %s\n",
keyfile, isc_result_totext(result));
return (ISC_R_FAILURE);
}
fclose(fptemp);
- result = dst_key_fromnamedfile(filetemp, DST_TYPE_PUBLIC,
+ result = dst_key_fromnamedfile(filetemp, NULL, DST_TYPE_PUBLIC,
mctx, &key);
removetmpkey(mctx, filetemp);
isc_mem_free(mctx, filetemp);
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.37 2009/07/01 23:47:36 tbox Exp $
+# $Id: Makefile.in,v 1.38 2009/07/19 04:18:04 each Exp $
srcdir = @srcdir@
VPATH = @srcdir@
# Alphabetically
TARGETS = dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \
dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \
- dnssec-revoke@EXEEXT@
+ dnssec-revoke@EXEEXT@ dnssec-settime@EXEEXT@
OBJS = dnssectool.@O@
SRCS = dnssec-dsfromkey.c dnssec-keyfromlabel.c dnssec-keygen.c \
- dnssec-revoke.c dnssec-signzone.c dnssectool.c
+ dnssec-revoke.c dnssec-settime.c dnssec-signzone.c dnssectool.c
MANPAGES = dnssec-dsfromkey.8 dnssec-keyfromlabel.8 dnssec-keygen.8 \
- dnssec-revoke.8 dnssec-signzone.8
+ dnssec-revoke.8 dnssec-settime.8 dnssec-signzone.8
HTMLPAGES = dnssec-dsfromkey.html dnssec-keyfromlabel.html \
- dnssec-keygen.html dnssec-revoke.html dnssec-signzone.html
+ dnssec-keygen.html dnssec-revoke.html \
+ dnssec-settime.html dnssec-signzone.html
MANOBJS = ${MANPAGES} ${HTMLPAGES}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
dnssec-revoke.@O@ ${OBJS} ${LIBS}
+dnssec-settime@EXEEXT@: dnssec-settime.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-settime.@O@ ${OBJS} ${LIBS}
+
doc man:: ${MANOBJS}
docclean manclean maintainer-clean::
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dnssec-dsfromkey.c,v 1.8 2009/06/17 23:53:04 tbox Exp $ */
+/* $Id: dnssec-dsfromkey.c,v 1.9 2009/07/19 04:18:04 each Exp $ */
/*! \file */
#include <dns/ds.h>
#include <dns/fixedname.h>
#include <dns/log.h>
+#include <dns/keyvalues.h>
+#include <dns/master.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include "dnssectool.h"
+#ifndef PATH_MAX
+#define PATH_MAX 1024 /* AIX and others don't define this. */
+#endif
+
const char *program = "dnssec-dsfromkey";
int verbose;
static dns_rdataclass_t rdclass;
static dns_fixedname_t fixed;
static dns_name_t *name = NULL;
-static dns_db_t *db = NULL;
-static dns_dbnode_t *node = NULL;
-static dns_rdataset_t keyset;
static isc_mem_t *mctx = NULL;
-static void
-loadkeys(char *dirname, char *setname)
-{
- isc_result_t result;
- char filename[1024];
- isc_buffer_t buf;
-
- dns_rdataset_init(&keyset);
- dns_fixedname_init(&fixed);
- name = dns_fixedname_name(&fixed);
+static isc_result_t
+initname(char *setname) {
+ isc_result_t result;
+ isc_buffer_t buf;
- isc_buffer_init(&buf, setname, strlen(setname));
- isc_buffer_add(&buf, strlen(setname));
- result = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL);
- if (result != ISC_R_SUCCESS)
- fatal("can't convert DNS name %s", setname);
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+
+ isc_buffer_init(&buf, setname, strlen(setname));
+ isc_buffer_add(&buf, strlen(setname));
+ result = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL);
+ return (result);
+}
- isc_buffer_init(&buf, filename, sizeof(filename));
- if (dirname != NULL) {
- if (isc_buffer_availablelength(&buf) < strlen(dirname))
- fatal("directory name '%s' too long", dirname);
- isc_buffer_putstr(&buf, dirname);
- if (dirname[strlen(dirname) - 1] != '/') {
- if (isc_buffer_availablelength(&buf) < 1)
- fatal("directory name '%s' too long", dirname);
- isc_buffer_putstr(&buf, "/");
- }
- }
+static isc_result_t
+loadsetfromfile(char *filename, dns_rdataset_t *rdataset) {
+ isc_result_t result;
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ char setname[DNS_NAME_FORMATSIZE];
- if (isc_buffer_availablelength(&buf) < strlen("keyset-"))
- fatal("directory name '%s' too long", dirname);
- isc_buffer_putstr(&buf, "keyset-");
- result = dns_name_tofilenametext(name, ISC_FALSE, &buf);
- check_result(result, "dns_name_tofilenametext()");
- if (isc_buffer_availablelength(&buf) == 0)
- fatal("name %s too long", setname);
- isc_buffer_putuint8(&buf, 0);
+ dns_name_format(name, setname, sizeof(setname));
result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
rdclass, 0, NULL, &db);
fatal("can't find %s node in %s", setname, filename);
result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey,
- 0, 0, &keyset, NULL);
+ 0, 0, rdataset, NULL);
+
if (result == ISC_R_NOTFOUND)
fatal("no DNSKEY RR for %s in %s", setname, filename);
else if (result != ISC_R_SUCCESS)
fatal("dns_db_findrdataset");
+
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ return (result);
+}
+
+static isc_result_t
+loadkeyset(char *dirname, dns_rdataset_t *rdataset) {
+ isc_result_t result;
+ char filename[PATH_MAX + 1];
+ isc_buffer_t buf;
+
+ dns_rdataset_init(rdataset);
+
+ isc_buffer_init(&buf, filename, sizeof(filename));
+ if (dirname != NULL) {
+ /* allow room for a trailing slash */
+ if (strlen(dirname) >= isc_buffer_availablelength(&buf))
+ return (ISC_R_NOSPACE);
+ isc_buffer_putstr(&buf, dirname);
+ if (dirname[strlen(dirname) - 1] != '/')
+ isc_buffer_putstr(&buf, "/");
+ }
+
+ if (isc_buffer_availablelength(&buf) < 7)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putstr(&buf, "keyset-");
+
+ result = dns_name_tofilenametext(name, ISC_FALSE, &buf);
+ check_result(result, "dns_name_tofilenametext()");
+ if (isc_buffer_availablelength(&buf) == 0)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putuint8(&buf, 0);
+
+ return (loadsetfromfile(filename, rdataset));
}
static void
isc_buffer_t keyb;
isc_region_t r;
- dns_rdataset_init(&keyset);
dns_rdata_init(rdata);
isc_buffer_init(&keyb, key_buf, key_buf_size);
- result = dst_key_fromnamedfile(filename, DST_TYPE_PUBLIC, mctx, &key);
+ result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC,
+ mctx, &key);
if (result != ISC_R_SUCCESS)
fatal("invalid keyfile name %s: %s",
filename, isc_result_totext(result));
}
static void
-emit(unsigned int dtype, dns_rdata_t *rdata, char *lookaside)
+emit(unsigned int dtype, isc_boolean_t showall, char *lookaside,
+ dns_rdata_t *rdata)
{
- isc_result_t result;
- unsigned char buf[DNS_DS_BUFFERSIZE];
- char text_buf[DST_KEY_MAXTEXTSIZE];
- char name_buf[DNS_NAME_MAXWIRE];
- char class_buf[10];
- isc_buffer_t textb, nameb, classb;
- isc_region_t r;
- dns_rdata_t ds;
+ isc_result_t result;
+ unsigned char buf[DNS_DS_BUFFERSIZE];
+ char text_buf[DST_KEY_MAXTEXTSIZE];
+ char name_buf[DNS_NAME_MAXWIRE];
+ char class_buf[10];
+ isc_buffer_t textb, nameb, classb;
+ isc_region_t r;
+ dns_rdata_t ds;
+ dns_rdata_dnskey_t dnskey;
isc_buffer_init(&textb, text_buf, sizeof(text_buf));
isc_buffer_init(&nameb, name_buf, sizeof(name_buf));
dns_rdata_init(&ds);
+ result = dns_rdata_tostruct(rdata, &dnskey, NULL);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't convert DNSKEY");
+
+ if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && !showall)
+ return;
+
result = dns_ds_buildrdata(name, rdata, dtype, buf, &ds);
if (result != ISC_R_SUCCESS)
fatal("can't build record");
static void
usage(void) {
fprintf(stderr, "Usage:\n");
- fprintf(stderr, " %s options keyfile\n\n", program);
- fprintf(stderr, " %s options [-c class] [-d dir] [-l lookaside] -s dnsname\n\n",
+ fprintf(stderr, " %s options [-K dir] keyfile\n\n", program);
+ fprintf(stderr, " %s options [-K dir] [-c class] -s dnsname\n\n",
program);
+ fprintf(stderr, " %s options -f zonefile (as zone name)\n\n", program);
+ fprintf(stderr, " %s options -f zonefile zonename\n\n", program);
fprintf(stderr, "Version: %s\n", VERSION);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -v <verbose level>\n");
+ fprintf(stderr, " -K <directory>: directory in which to find "
+ "key file or keyset file\n");
+ fprintf(stderr, " -a algorithm: digest algorithm "
+ "(SHA-1 or SHA-256)\n");
fprintf(stderr, " -1: use SHA-1\n");
fprintf(stderr, " -2: use SHA-256\n");
- fprintf(stderr, " -a algorithm: use algorithm\n");
- fprintf(stderr, "Keyset options:\n");
- fprintf(stderr, " -s: keyset mode\n");
fprintf(stderr, " -l: add lookaside zone and print DLV records\n");
- fprintf(stderr, " -c class\n");
- fprintf(stderr, " -d directory\n");
+ fprintf(stderr, " -s: read keyset from keyset-<dnsname> file\n");
+ fprintf(stderr, " -c class: rdata class for DS set (default: IN)\n");
+ fprintf(stderr, " -f file: read keyset from zone file\n");
+ fprintf(stderr, " -A: when used with -f, "
+ "include all keys in DS set, not just KSKs\n");
fprintf(stderr, "Output: DS or DLV RRs\n");
exit (-1);
int
main(int argc, char **argv) {
- char *algname = NULL, *classname = NULL, *dirname = NULL;
+ char *algname = NULL, *classname = NULL;
+ char *filename = NULL, *dir = NULL, *namestr;
char *lookaside = NULL;
char *endp;
int ch;
unsigned int dtype = DNS_DSDIGEST_SHA1;
isc_boolean_t both = ISC_TRUE;
isc_boolean_t usekeyset = ISC_FALSE;
+ isc_boolean_t showall = ISC_FALSE;
isc_result_t result;
- isc_log_t *log = NULL;
+ isc_log_t *log = NULL;
isc_entropy_t *ectx = NULL;
+ dns_rdataset_t rdataset;
dns_rdata_t rdata;
dns_rdata_init(&rdata);
isc_commandline_errprint = ISC_FALSE;
while ((ch = isc_commandline_parse(argc, argv,
- "12a:c:d:l:sv:Fh")) != -1) {
+ "12Aa:c:d:Ff:K:l:sv:h")) != -1) {
switch (ch) {
case '1':
dtype = DNS_DSDIGEST_SHA1;
dtype = DNS_DSDIGEST_SHA256;
both = ISC_FALSE;
break;
+ case 'A':
+ showall = ISC_TRUE;
+ break;
case 'a':
algname = isc_commandline_argument;
both = ISC_FALSE;
classname = isc_commandline_argument;
break;
case 'd':
- dirname = isc_commandline_argument;
- if (strlen(dirname) == 0)
- fatal("dir must be a non-empty string");
+ fprintf(stderr, "%s: the -d option is deprecated; "
+ "use -K\n", program);
+ /* fall through */
+ case 'K':
+ dir = isc_commandline_argument;
+ if (strlen(dir) == 0)
+ fatal("directory must be non-empty string");
+ break;
+ case 'f':
+ filename = isc_commandline_argument;
break;
case 'l':
lookaside = isc_commandline_argument;
rdclass = strtoclass(classname);
- if (argc < isc_commandline_index + 1)
+ if (usekeyset && filename != NULL)
+ fatal("cannot use both -s and -f");
+
+ /* When not using -f, -A is implicit */
+ if (filename == NULL)
+ showall = ISC_TRUE;
+
+ if (argc < isc_commandline_index + 1 && filename == NULL)
fatal("the key file name was not specified");
if (argc > isc_commandline_index + 1)
fatal("extraneous arguments");
setup_logging(verbose, mctx, &log);
- if (usekeyset) {
- loadkeys(dirname, argv[isc_commandline_index]);
+ dns_rdataset_init(&rdataset);
+
+ if (usekeyset || filename != NULL) {
+ if (argc < isc_commandline_index + 1 && filename != NULL) {
+ /* using zone name as the zone file name */
+ namestr = filename;
+ } else
+ namestr = argv[isc_commandline_index];
- for (result = dns_rdataset_first(&keyset);
+ result = initname(namestr);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize name %s", namestr);
+
+ if (usekeyset)
+ result = loadkeyset(dir, &rdataset);
+ else
+ result = loadsetfromfile(filename, &rdataset);
+
+ if (result != ISC_R_SUCCESS)
+ fatal("could not load DNSKEY set: %s\n",
+ isc_result_totext(result));
+
+ for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
- result = dns_rdataset_next(&keyset)) {
+ result = dns_rdataset_next(&rdataset)) {
dns_rdata_init(&rdata);
- dns_rdataset_current(&keyset, &rdata);
+ dns_rdataset_current(&rdataset, &rdata);
if (verbose > 2)
logkey(&rdata);
if (both) {
- emit(DNS_DSDIGEST_SHA1, &rdata, lookaside);
- emit(DNS_DSDIGEST_SHA256, &rdata, lookaside);
+ emit(DNS_DSDIGEST_SHA1, showall, lookaside,
+ &rdata);
+ emit(DNS_DSDIGEST_SHA256, showall, lookaside,
+ &rdata);
} else
- emit(dtype, &rdata, lookaside);
+ emit(dtype, showall, lookaside, &rdata);
}
} else {
unsigned char key_buf[DST_KEY_MAXSIZE];
DST_KEY_MAXSIZE, &rdata);
if (both) {
- emit(DNS_DSDIGEST_SHA1, &rdata, lookaside);
- emit(DNS_DSDIGEST_SHA256, &rdata, lookaside);
+ emit(DNS_DSDIGEST_SHA1, showall, lookaside, &rdata);
+ emit(DNS_DSDIGEST_SHA256, showall, lookaside, &rdata);
} else
- emit(dtype, &rdata, lookaside);
+ emit(dtype, showall, lookaside, &rdata);
}
- if (dns_rdataset_isassociated(&keyset))
- dns_rdataset_disassociate(&keyset);
- if (node != NULL)
- dns_db_detachnode(db, &node);
- if (db != NULL)
- dns_db_detach(&db);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
cleanup_logging(&log);
dst_lib_destroy();
isc_hash_destroy();
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: dnssec-dsfromkey.docbook,v 1.8 2009/06/17 23:53:04 tbox Exp $ -->
+<!-- $Id: dnssec-dsfromkey.docbook,v 1.9 2009/07/19 04:18:04 each Exp $ -->
<refentry id="man.dnssec-dsfromkey">
<refentryinfo>
<date>November 29, 2008</date>
<cmdsynopsis>
<command>dnssec-dsfromkey</command>
<arg choice="req">-s</arg>
- <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
<arg><option>-1</option></arg>
<arg><option>-2</option></arg>
<arg><option>-a <replaceable class="parameter">alg</replaceable></option></arg>
+ <arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-s</option></arg>
<arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
- <arg><option>-d <replaceable class="parameter">dir</replaceable></option></arg>
+ <arg><option>-f <replaceable class="parameter">file</replaceable></option></arg>
+ <arg><option>-A</option></arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
<arg choice="req">dnsname</arg>
</cmdsynopsis>
</refsynopsisdiv>
</varlistentry>
<varlistentry>
- <term>-v <replaceable class="parameter">level</replaceable></term>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
<listitem>
<para>
- Sets the debugging level.
+ Look for key files (or, in keyset mode,
+ <filename>keyset-</filename> files) in
+ <option>directory</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">file</replaceable></term>
+ <listitem>
+ <para>
+ Zone file mode: in place of the keyfile name, the argument is
+ the DNS domain name of a zone master file, which can be read
+ from <option>file</option>. If the zone name is the same as
+ <option>file</option>, then it may be omitted.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-A</term>
+ <listitem>
+ <para>
+ Include ZSK's when generating DS records. Without this option,
+ only keys which have the KSK flag set will be converted to DS
+ records and printed. Useful only in zone file mode.
</para>
</listitem>
</varlistentry>
<listitem>
<para>
Keyset mode: in place of the keyfile name, the argument is
- the DNS domain name of a keyset file. Following options make sense
- only in this mode.
+ the DNS domain name of a keyset file.
</para>
</listitem>
</varlistentry>
<term>-c <replaceable class="parameter">class</replaceable></term>
<listitem>
<para>
- Specifies the DNS class (default is IN), useful only
- in the keyset mode.
+ Specifies the DNS class (default is IN). Useful only
+ in keyset or zone file mode.
</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-d <replaceable class="parameter">directory</replaceable></term>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
<listitem>
<para>
- Look for <filename>keyset</filename> files in
- <option>directory</option> as the directory, ignored when
- not in the keyset mode.
+ Sets the debugging level.
</para>
</listitem>
</varlistentry>
-
</variablelist>
</refsect1>
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dnssec-keyfromlabel.c,v 1.8 2009/06/30 23:48:00 tbox Exp $ */
+/* $Id: dnssec-keyfromlabel.c,v 1.9 2009/07/19 04:18:04 each Exp $ */
/*! \file */
fprintf(stderr, " (DNSKEY generation defaults to ZONE\n");
fprintf(stderr, " -c <class> (default: IN)\n");
fprintf(stderr, " -f keyflag (KSK or REVOKE)\n");
+ fprintf(stderr, " -K directory: directory in which to place "
+ "key files\n");
fprintf(stderr, " -t <type>: "
"AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
"(default: AUTHCONF)\n");
int
main(int argc, char **argv) {
char *algname = NULL, *nametype = NULL, *type = NULL;
+ char *directory = NULL;
char *classname = NULL;
char *endp;
dst_key_t *key = NULL, *oldkey;
isc_commandline_errprint = ISC_FALSE;
while ((ch = isc_commandline_parse(argc, argv,
- "a:c:f:kl:n:p:t:v:Fh")) != -1)
+ "a:c:f:K:kl:n:p:t:v:Fh")) != -1)
{
switch (ch) {
case 'a':
fatal("unknown flag '%s'",
isc_commandline_argument);
break;
+ case 'K':
+ directory = isc_commandline_argument;
+ break;
case 'k':
options |= DST_TYPE_KEY;
break;
* case we return failure.
*/
ret = dst_key_fromfile(name, dst_key_id(key), alg,
- DST_TYPE_PRIVATE, NULL, mctx, &oldkey);
+ DST_TYPE_PRIVATE, directory, mctx, &oldkey);
/* do not overwrite an existing key */
if (ret == ISC_R_SUCCESS) {
isc_buffer_clear(&buf);
- ret = dst_key_buildfilename(key, 0, NULL, &buf);
+ ret = dst_key_buildfilename(key, 0, directory, &buf);
fprintf(stderr, "%s: %s already exists\n",
program, filename);
dst_key_free(&key);
exit (1);
}
- ret = dst_key_tofile(key, options, NULL);
+ ret = dst_key_tofile(key, options, directory);
if (ret != ISC_R_SUCCESS) {
char keystr[KEY_FORMATSIZE];
key_format(key, keystr, sizeof(keystr));
}
isc_buffer_clear(&buf);
- ret = dst_key_buildfilename(key, 0, NULL, &buf);
+ ret = dst_key_buildfilename(key, 0, directory, &buf);
printf("%s\n", filename);
dst_key_free(&key);
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: dnssec-keyfromlabel.docbook,v 1.6 2008/11/07 13:54:11 jreed Exp $ -->
+<!-- $Id: dnssec-keyfromlabel.docbook,v 1.7 2009/07/19 04:18:04 each Exp $ -->
<refentry id="man.dnssec-keyfromlabel">
<refentryinfo>
<date>February 8, 2008</date>
<arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
<arg><option>-f <replaceable class="parameter">flag</replaceable></option></arg>
<arg><option>-k</option></arg>
+ <arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
<arg><option>-n <replaceable class="parameter">nametype</replaceable></option></arg>
<arg><option>-p <replaceable class="parameter">protocol</replaceable></option></arg>
<arg><option>-t <replaceable class="parameter">type</replaceable></option></arg>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Sets the directory in which the key files are to be written.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term>-k</term>
<listitem>
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dnssec-keygen.c,v 1.87 2009/06/30 23:48:00 tbox Exp $ */
+/* $Id: dnssec-keygen.c,v 1.88 2009/07/19 04:18:04 each Exp $ */
/*! \file */
#include <config.h>
+#include <ctype.h>
#include <stdlib.h>
#include <isc/buffer.h>
const char *program = "dnssec-keygen";
int verbose;
-static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 | NSEC3DSA |"
- " NSEC3RSASHA1 | HMAC-MD5 |"
- " HMAC-SHA1 | HMAC-SHA224 | HMAC-SHA256 |"
- " HMAC-SHA384 | HMAC-SHA512";
+#define DEFAULT_ALGORITHM "RSASHA1"
+#define DEFAULT_NSEC3_ALGORITHM "NSEC3RSASHA1"
#define DEFAULT_ALGORITHM "RSASHA1"
static void
usage(void) {
fprintf(stderr, "Usage:\n");
- fprintf(stderr, " %s [options] name\n\n",
- program);
+ fprintf(stderr, " %s [options] name\n\n", program);
fprintf(stderr, "Version: %s\n", VERSION);
fprintf(stderr, " name: owner of the key\n");
fprintf(stderr, "Options:\n");
- fprintf(stderr, " -a algorithm: %s (default RSASHA1)\n", algs);
- fprintf(stderr, " -b key size, in bits:\n");
- fprintf(stderr, " RSAMD5:\t\t[512..%d]\n", MAX_RSA);
- fprintf(stderr, " RSASHA1:\t\t[512..%d]\n", MAX_RSA);
- fprintf(stderr, " NSEC3RSASHA1:\t\t[512..%d]\n", MAX_RSA);
- fprintf(stderr, " DH:\t\t[128..4096]\n");
- fprintf(stderr, " DSA:\t\t[512..1024] and divisible by 64\n");
- fprintf(stderr, " NSEC3DSA:\t\t[512..1024] and divisible by 64\n");
- fprintf(stderr, " HMAC-MD5:\t[1..512]\n");
- fprintf(stderr, " HMAC-SHA1:\t[1..160]\n");
- fprintf(stderr, " HMAC-SHA224:\t[1..224]\n");
- fprintf(stderr, " HMAC-SHA256:\t[1..256]\n");
- fprintf(stderr, " HMAC-SHA384:\t[1..384]\n");
- fprintf(stderr, " HMAC-SHA512:\t[1..512]\n");
- fprintf(stderr, " (default 1024 for RSASHA1 ZSK, 2048 for KSK\n");
- fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n");
- fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n");
- fprintf(stderr, " -c <class> (default: IN)\n");
+ fprintf(stderr, " -K <directory>: write keys into directory\n");
+ fprintf(stderr, " -a <algorithm>:\n");
+ fprintf(stderr, " RSA | RSAMD5 | DSA | RSASHA1 | "
+ "NSEC3RSASHA1 | NSEC3DSA |\n");
+ fprintf(stderr, " DH | HMAC-MD5 | HMAC-SHA1 | HMAC-SHA224 | "
+ "HMAC-SHA256 | \n");
+ fprintf(stderr, " HMAC-SHA384 | HMAC-SHA512\n");
+ fprintf(stderr, " (default: RSASHA1, or "
+ "NSEC3RSASHA1 if using -3)\n");
+ fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
+ fprintf(stderr, " -b <key size in bits>:\n");
+ fprintf(stderr, " RSAMD5:\t[512..%d]\n", MAX_RSA);
+ fprintf(stderr, " RSASHA1:\t[512..%d]\n", MAX_RSA);
+ fprintf(stderr, " NSEC3RSASHA1:\t[512..%d]\n", MAX_RSA);
+ fprintf(stderr, " DH:\t\t[128..4096]\n");
+ fprintf(stderr, " DSA:\t\t[512..1024] and divisible by 64\n");
+ fprintf(stderr, " NSEC3DSA:\t[512..1024] and divisible "
+ "by 64\n");
+ fprintf(stderr, " HMAC-MD5:\t[1..512]\n");
+ fprintf(stderr, " HMAC-SHA1:\t[1..160]\n");
+ fprintf(stderr, " HMAC-SHA224:\t[1..224]\n");
+ fprintf(stderr, " HMAC-SHA256:\t[1..256]\n");
+ fprintf(stderr, " HMAC-SHA384:\t[1..384]\n");
+ fprintf(stderr, " HMAC-SHA512:\t[1..512]\n");
+ fprintf(stderr, " (if using the default algorithm, key size\n"
+ " defaults to 2048 for KSK, or 1024 for all "
+ "others)\n");
+ fprintf(stderr, " -n <nametype>: ZONE | HOST | ENTITY | "
+ "USER | OTHER\n");
+ fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n");
+ fprintf(stderr, " -c <class>: (default: IN)\n");
fprintf(stderr, " -d <digest bits> (0 => max, default)\n");
- fprintf(stderr, " -e use large exponent (RSAMD5/RSASHA1 only)\n");
- fprintf(stderr, " -f keyflag (KSK or REVOKE)\n");
- fprintf(stderr, " -g <generator> use specified generator "
- "(DH only)\n");
+ fprintf(stderr, " -e: use large exponent (RSAMD5/RSASHA1 only)\n");
+ fprintf(stderr, " -f <keyflag>: KSK | REVOKE\n");
+ fprintf(stderr, " -g <generator>: use specified generator "
+ "(DH only)\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, " -T <rrtype>: DNSKEY | KEY (default: DNSKEY; "
+ "use KEY for SIG(0))\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");
+ "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
+ "(default: AUTHCONF)\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, " -h: print usage and exit\n");
+ fprintf(stderr, " -m <memory debugging mode>:\n");
+ fprintf(stderr, " usage | trace | record | size | mctx\n");
+ fprintf(stderr, " -v <level>: set verbosity level (0 - 10)\n");
+ fprintf(stderr, "Date options:\n");
+ fprintf(stderr, " -P date/[+-]offset: set key publication date\n");
+ fprintf(stderr, " -A date/[+-]offset: set key activation date\n");
+ fprintf(stderr, " -R date/[+-]offset: set key revocation date\n");
+ fprintf(stderr, " -U date/[+-]offset: set key unpublication date\n");
+ fprintf(stderr, " -D date/[+-]offset: set key deletion date\n");
+ fprintf(stderr, " -C: generate a backward-compatible key, omitting "
+ "dates\n");
fprintf(stderr, "Output:\n");
fprintf(stderr, " K<name>+<alg>+<id>.key, "
- "K<name>+<alg>+<id>.private\n");
+ "K<name>+<alg>+<id>.private\n");
exit (-1);
}
dst_key_t *key = NULL, *oldkey;
dns_fixedname_t fname;
dns_name_t *name;
- isc_uint16_t flags = 0, ksk = 0, revoke = 0;
+ isc_uint16_t flags = 0, kskflag = 0, revflag = 0;
dns_secalg_t alg;
isc_boolean_t conflict = ISC_FALSE, null_key = ISC_FALSE;
+ isc_boolean_t oldstyle = 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];
+ const char *directory = NULL;
isc_buffer_t buf;
isc_log_t *log = NULL;
isc_entropy_t *ectx = NULL;
dns_rdataclass_t rdclass;
int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC;
int dbits = 0;
- isc_boolean_t use_default = ISC_FALSE;
+ isc_boolean_t use_default = ISC_FALSE, use_nsec3 = ISC_FALSE;
+ isc_stdtime_t publish = 0, activate = 0, revoke = 0;
+ isc_stdtime_t unpublish = 0, delete = 0;
+ isc_stdtime_t now;
if (argc == 1)
usage();
- RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
-
dns_result_register();
isc_commandline_errprint = ISC_FALSE;
- while ((ch = isc_commandline_parse(argc, argv,
- "a:b:c:d:ef:g:kn:t:p:s:r:v:Fh")) != -1)
- {
+ /*
+ * Process memory debugging argument first.
+ */
+#define CMDLINE_FLAGS "3a:b:Cc:d:eFf:g:K:km:n:p:r:s:T:t:v:hP:A:R:U:D:"
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case 'm':
+ if (strcasecmp(isc_commandline_argument, "record") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ if (strcasecmp(isc_commandline_argument, "trace") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
+ if (strcasecmp(isc_commandline_argument, "usage") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
+ if (strcasecmp(isc_commandline_argument, "size") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
+ if (strcasecmp(isc_commandline_argument, "mctx") == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGCTX;
+ break;
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = ISC_TRUE;
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ isc_stdtime_get(&now);
+
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
switch (ch) {
+ case '3':
+ use_nsec3 = ISC_TRUE;
+ break;
case 'a':
algname = isc_commandline_argument;
break;
if (*endp != '\0' || size < 0)
fatal("-b requires a non-negative number");
break;
+ case 'C':
+ oldstyle = ISC_TRUE;
+ break;
case 'c':
classname = isc_commandline_argument;
break;
rsa_exp = 1;
break;
case 'f':
- if (strcasecmp(isc_commandline_argument, "KSK") == 0)
- ksk = DNS_KEYFLAG_KSK;
- else if (strcasecmp(isc_commandline_argument,
- "REVOKE") == 0)
- revoke = DNS_KEYFLAG_REVOKE;
+ if (toupper(isc_commandline_argument[0]) == 'K')
+ kskflag = DNS_KEYFLAG_KSK;
+ else if (toupper(isc_commandline_argument[0]) == 'R')
+ revflag = DNS_KEYFLAG_REVOKE;
else
fatal("unknown flag '%s'",
isc_commandline_argument);
if (*endp != '\0' || generator <= 0)
fatal("-g requires a positive number");
break;
+ case 'K':
+ directory = isc_commandline_argument;
+ break;
case 'k':
- options |= DST_TYPE_KEY;
+ fatal("The -k option has been deprecated.\n"
+ "To generate a key-signing key, use -f KSK.\n"
+ "To generate a key with TYPE=KEY, use -T KEY.\n");
break;
case 'n':
nametype = isc_commandline_argument;
break;
- case 't':
- type = isc_commandline_argument;
+ case 'm':
break;
case 'p':
protocol = strtol(isc_commandline_argument, &endp, 10);
fatal("-p must be followed by a number "
"[0..255]");
break;
+ case 'r':
+ setup_entropy(mctx, isc_commandline_argument, &ectx);
+ break;
case 's':
signatory = strtol(isc_commandline_argument,
&endp, 10);
fatal("-s must be followed by a number "
"[0..15]");
break;
- case 'r':
- setup_entropy(mctx, isc_commandline_argument, &ectx);
+ case 'T':
+ if (strcasecmp(isc_commandline_argument, "KEY") == 0)
+ options |= DST_TYPE_KEY;
+ else if (strcasecmp(isc_commandline_argument,
+ "DNSKEY") == 0)
+ /* default behavior */
+ ;
+ else
+ fatal("unknown type '%s'",
+ isc_commandline_argument);
+ break;
+ case 't':
+ type = isc_commandline_argument;
break;
case 'v':
endp = NULL;
if (*endp != '\0')
fatal("-v must be followed by a number");
break;
+ case 'z':
+ /* already the default */
+ break;
+ case 'P':
+ publish = strtotime(isc_commandline_argument,
+ now, now);
+ break;
+ case 'A':
+ activate = strtotime(isc_commandline_argument,
+ now, now);
+ break;
+ case 'R':
+ revoke = strtotime(isc_commandline_argument,
+ now, now);
+ break;
+ case 'U':
+ unpublish = strtotime(isc_commandline_argument,
+ now, now);
+ break;
+ case 'D':
+ delete = strtotime(isc_commandline_argument,
+ now, now);
+ break;
case 'F':
/* Reserved for FIPS mode */
/* FALLTHROUGH */
fatal("extraneous arguments");
if (algname == NULL) {
- algname = strdup(DEFAULT_ALGORITHM);
use_default = ISC_TRUE;
+ if (use_nsec3)
+ algname = strdup(DEFAULT_NSEC3_ALGORITHM);
+ else
+ algname = strdup(DEFAULT_ALGORITHM);
if (verbose > 0)
fprintf(stderr, "no algorithm specified; "
"defaulting to %s\n", algname);
options |= DST_TYPE_KEY;
}
+ if (use_nsec3 &&
+ alg != DST_ALG_NSEC3DSA && alg != DST_ALG_NSEC3RSASHA1) {
+ fatal("%s is incompatible with NSEC3; "
+ "do not use the -3 option", algname);
+ }
+
if (type != NULL && (options & DST_TYPE_KEY) != 0) {
if (strcasecmp(type, "NOAUTH") == 0)
flags |= DNS_KEYTYPE_NOAUTH;
if (size < 0) {
if (use_default) {
- size = (ksk != 0) ? 2048 : 1024;
+ size = ((kskflag & DNS_KEYFLAG_KSK) != 0) ? 2048 : 1024;
if (verbose > 0)
fprintf(stderr, "key size not specified; "
"defaulting to %d\n", size);
rdclass = strtoclass(classname);
+ if (directory == NULL)
+ directory = ".";
+
if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */
flags |= signatory;
else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */
- flags |= ksk;
- flags |= revoke;
+ flags |= kskflag;
+ flags |= revflag;
}
if (protocol == -1)
dst_key_setbits(key, dbits);
+ /*
+ * Set key timing metadata
+ */
+ if (!oldstyle) {
+ dst_key_settime(key, DST_TIME_CREATED, now);
+ dst_key_settime(key, DST_TIME_PUBLISH, publish);
+ dst_key_settime(key, DST_TIME_ACTIVATE, activate);
+ dst_key_settime(key, DST_TIME_REVOKE, revoke);
+ dst_key_settime(key, DST_TIME_REMOVE, unpublish);
+ dst_key_settime(key, DST_TIME_DELETE, delete);
+ } else if (publish != 0 || activate != 0 || revoke != 0 ||
+ unpublish != 0 || delete != 0) {
+ fatal("cannot use -C together with "
+ "-P, -A, -R, -U, or -D options");
+ }
+
/*
* 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
fatal("cannot generate a null key when a key with id 0 "
"already exists");
- ret = dst_key_tofile(key, options, NULL);
+ ret = dst_key_tofile(key, options, directory);
if (ret != ISC_R_SUCCESS) {
char keystr[KEY_FORMATSIZE];
key_format(key, keystr, sizeof(keystr));
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: dnssec-keygen.docbook,v 1.24 2009/06/17 23:53:04 tbox Exp $ -->
+<!-- $Id: dnssec-keygen.docbook,v 1.25 2009/07/19 04:18:04 each Exp $ -->
<refentry id="man.dnssec-keygen">
<refentryinfo>
<date>June 30, 2000</date>
<arg><option>-a <replaceable class="parameter">algorithm</replaceable></option></arg>
<arg ><option>-b <replaceable class="parameter">keysize</replaceable></option></arg>
<arg><option>-n <replaceable class="parameter">nametype</replaceable></option></arg>
+ <arg><option>-3</option></arg>
+ <arg><option>-A <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg><option>-C</option></arg>
<arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-D <replaceable class="parameter">date/offset</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 <replaceable class="parameter">directory</replaceable></option></arg>
<arg><option>-k</option></arg>
+ <arg><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
<arg><option>-p <replaceable class="parameter">protocol</replaceable></option></arg>
+ <arg><option>-R <replaceable class="parameter">date/offset</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>-U <replaceable class="parameter">date/offset</replaceable></option></arg>
<arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg><option>-z</option></arg>
<arg choice="req">name</arg>
</cmdsynopsis>
</refsynopsisdiv>
<para><command>dnssec-keygen</command>
generates keys for DNSSEC (Secure DNS), as defined in RFC 2535
and RFC 4034. It can also generate keys for use with
- TSIG (Transaction Signatures), as defined in RFC 2845.
+ TSIG (Transaction Signatures) as defined in RFC 2845, or TKEY
+ (Transaction Key) as defined in RFC 2930.
</para>
</refsect1>
<term>-a <replaceable class="parameter">algorithm</replaceable></term>
<listitem>
<para>
- Selects the cryptographic algorithm. The value of
- <option>algorithm</option> must be one of RSAMD5 (RSA) or RSASHA1,
- DSA, NSEC3RSASHA1, NSEC3DSA, DH (Diffie Hellman), or HMAC-MD5.
- These values are case insensitive. The default is RSASHA1 for
- DNSSEC key generation.
+ Selects the cryptographic algorithm. For DNSSEC keys, the value
+ of <option>algorithm</option> must be one of RSAMD5, RSASHA1,
+ DSA, NSEC3RSASHA1, or NSEC3DSA. For TSIG/TKEY, the value must
+ be DH (Diffie Hellman), HMAC-MD5, HMAC-SHA1, HMAC-SHA224,
+ HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512. These values are
+ case insensitive.
+ </para>
+ <para>
+ If no algorithm is specified, then RSASHA1 will be used by
+ default, unless the <option>-3</option> option is specified,
+ in which case NSEC3RSASHA1 will be used instead.
</para>
<para>
Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
mandatory.
</para>
<para>
- Note 2: HMAC-MD5 and DH automatically set the -k flag.
+ Note 2: DH, HMAC-MD5, and HMAC-SHA1 through HMAC-SHA512
+ automatically set the -T KEY option.
</para>
</listitem>
</varlistentry>
bits and an exact multiple of 64. HMAC-MD5 keys must be
between 1 and 512 bits.
</para>
- When generating a DNSSEC key with the default algorithm, this
- value defaults to 1024, or 2048 if the KSK flag is set.
<para>
+ The key size does not need to be specified if using a default
+ algorithm. The default key size is 1024 bits for zone signing
+ keys (ZSK's) and 2048 bits for key signing keys (KSK's,
+ generated with <option>-f KSK</option>). However, if an
+ algorithm is explicitly specified with the <option>-a</option>,
+ then there is no default key size, and the <option>-b</option>
+ must be used.
</para>
</listitem>
</varlistentry>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>-3</term>
+ <listitem>
+ <para>
+ Use an NSEC3-capable algorithm to generate a DNSSEC key.
+ If this option is used and no algorithm is explicitly
+ set on the command line, NSEC3RSASHA1 will be used by
+ default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-C</term>
+ <listitem>
+ <para>
+ Compatibility mode: generates an old-style key, without
+ any metadata. By default, <command>dnssec-keygen</command>
+ will include the key's creation date in the metadata stored
+ with the private key, and other dates may be set there as well
+ (publication date, activation date, etc). Keys that include
+ this data may be incompatible with older versions of BIND; the
+ <option>-C</option> option suppresses them.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term>-c <replaceable class="parameter">class</replaceable></term>
<listitem>
<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.
+ The only recognized flags are KSK (Key Signing Key) and REVOKE.
</para>
</listitem>
</varlistentry>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Sets the directory in which the key files are to be written.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term>-k</term>
<listitem>
<para>
- Generate KEY records rather than DNSKEY records.
+ Deprecated in favor of -T KEY.
</para>
</listitem>
</varlistentry>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>-T <replaceable class="parameter">rrtype</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the resource record type to use for the key.
+ <option>rrtype</option> must be either DNSKEY or KEY. The
+ default is DNSKEY when using a DNSSEC algorithm, but it can be
+ overridden to KEY for use with SIG(0).
+ <para>
+ </para>
+ Using any TSIG algorithm (HMAC-* or DH) forces this option
+ to KEY.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term>-t <replaceable class="parameter">type</replaceable></term>
<listitem>
</variablelist>
</refsect1>
+ <refsect1>
+ <title>TIMING OPTIONS</title>
+
+ <para>
+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+ If the argument begins with a '+' or '-', it is interpreted as
+ an offset from the present time. If such an offset is followed
+ by one of the characters 'y', 'm', 'w', 'd', or 'h', then the
+ offset is computed in years, months, weeks, days, or hours,
+ respectively; otherwise it is computed in seconds.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>-P <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which a key is to be published to the zone.
+ After that date, the key will be included in the zone but will
+ not be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-A <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be activated. After that
+ date, the key will be included and the zone and used to sign
+ it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-R <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be revoked. After that
+ date, the key will be flagged as revoked. It will be included
+ in the zone and will be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-U <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be unpublished. After that
+ date, the key will no longer be included in the zone, but it
+ may remain in the key repository.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be deleted. After that
+ date, the key can be removed from the key repository.
+ NOTE: Keys are not currently deleted automatically; this field
+ is included for informational purposes and for future
+ development.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+
<refsect1>
<title>GENERATED KEYS</title>
<para>
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dnssec-revoke.c,v 1.4 2009/07/17 23:47:40 tbox Exp $ */
+/* $Id: dnssec-revoke.c,v 1.5 2009/07/19 04:18:04 each Exp $ */
/*! \file */
fprintf(stderr, "Usage:\n");
fprintf(stderr, " %s [options] keyfile\n\n", program);
fprintf(stderr, "Version: %s\n", VERSION);
- fprintf(stderr, " -f: force ovewrite\n");
- fprintf(stderr, " -d directory: use directory for key files\n");
+ fprintf(stderr, " -f: force overwrite\n");
+ fprintf(stderr, " -K directory: use directory for key files\n");
fprintf(stderr, " -h: help\n");
fprintf(stderr, " -r: remove old keyfiles after "
"creating revoked version\n");
isc_commandline_errprint = ISC_FALSE;
- while ((ch = isc_commandline_parse(argc, argv, "d:fhrv:")) != -1) {
+ while ((ch = isc_commandline_parse(argc, argv, "fK:rhv:")) != -1) {
switch (ch) {
- case 'd':
- dir = isc_commandline_argument;
- break;
case 'f':
force = ISC_TRUE;
break;
+ case 'K':
+ dir = isc_commandline_argument;
+ break;
case 'r':
remove = ISC_TRUE;
break;
fatal("Could not initialize dst");
isc_entropy_stopcallbacksources(ectx);
- result = dst_key_fromnamedfile(filename,
+ result = dst_key_fromnamedfile(filename, dir,
DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
mctx, &key);
if (result != ISC_R_SUCCESS)
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: dnssec-revoke.docbook,v 1.3 2009/06/30 03:20:26 each Exp $ -->
+<!-- $Id: dnssec-revoke.docbook,v 1.4 2009/07/19 04:18:04 each Exp $ -->
<refentry id="man.dnssec-revoke">
<refentryinfo>
<date>June 1, 2009</date>
<command>dnssec-revoke</command>
<arg><option>-hr</option></arg>
<arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
- <arg><option>-d <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
<arg><option>-f</option></arg>
<arg choice="req">keyfile</arg>
</cmdsynopsis>
</varlistentry>
<varlistentry>
- <term>-d <replaceable class="parameter">directory</replaceable></term>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
<listitem>
<para>
Sets the directory in which the key files are to reside.
--- /dev/null
+.\" Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $Id: dnssec-settime.8,v 1.2 2009/07/19 04:18:04 each Exp $
+.\"
+.hy 0
+.ad l
+.\"Generated by db2man.xsl. Don't modify this, modify the source.
+.de Sh \" Subsection
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.TH "DNSSEC-REVOKE" 8 "June 29, 2009" "" ""
+.SH NAME
+dnssec-settime \- Set the key timing metadata for a DNSSEC key
+.SH "SYNOPSIS"
+.HP 14
+\fBdnssec\-revoke\fR [\fB\-hr\fR] [\fB\-K\ \fIdirectory\fR\fR] [\fB\-P\ \fIdate/offset\fR\fR] [\fB\-A\ \fIdate/offset\fR\fR] [\fB\-R\ \fIdate/offset\fR\fR] [\fB\-U\ \fIdate/offset\fR\fR] [\fB\-D\ \fIdate/offset\fR\fR] [\fB\-v\ \fIlevel\fR\fR] {keyfile}
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-settime\fR reads a DNSSEC private key file, sets the key timing metadata as specified by the \fB\-P\fR, \fB\-A\fR, \fB\-R\fR, \fB\-U\fR, and \fB\-D\fR options\&.
+.PP
+If none of these options is set on the command line, then \fBdnssec\-settime\fR simply prints the key timing metadata already stored in the key\&.
+.SH "OPTIONS"
+.TP
+\-h
+Emit usage message and exit\&.
+.TP
+\-K \fIdirectory\fR
+Sets the directory in which the key files are to reside\&.
+.TP
+\-P \fIdate/offset\fR
+Sets the date on which a key is to be published to the zone\&. After that date, the key will be included in the zone but will not be used to sign it\&.
+Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS\&. If the argument begins with a '+' or '\-', it is interpreted as an offset from the present time\&. If an offset is followed by one of the characters 'y', 'm', 'w', 'd', or 'h', then the offset is computed in years, months, weeks, days, or hours, respectively; otherwise it is computed in seconds\&.
+.TP
+\-A \fIdate/offset\fR
+Sets the date on which the key is to be activated\&. After that date, the key will be included and the zone and used to sign it\&.
+The date/offset syntax is identical to that in the \fB\-P\fR option\&.
+.TP
+\-R \fIdate/offset\fR
+Sets the date on which the key is to be revoked\&. After that date, the key will be flagged as revoked\&. It will be included in the zone and will be used to sign it\&.
+The date/offset syntax is identical to that in the \fB\-P\fR option\&.
+.TP
+\-U \fIdate/offset\fR
+Sets the date on which the key is to be unpublished\&. After that date, the key will no longer be included in the zone, but it may remain in the key repository\&.
+The date/offset syntax is identical to that in the \fB\-P\fR option\&.
+.TP
+\-D \fIdate/offset\fR
+Sets the date on which the key is to be deleted\&. After that date, the key can be removed from the key repository\&.
+The date/offset syntax is identical to that in the \fB\-P\fR option\&.
+.TP
+\-v \fIlevel\fR
+Sets the debugging level\&.
+.SH "SEE ALSO"
+.PP
+\fBdnssec\-keygen\fR(8), BIND 9 Administrator Reference Manual, RFC 5011\&.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
--- /dev/null
+/*
+ * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dnssec-settime.c,v 1.2 2009/07/19 04:18:04 each Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <libgen.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/errno.h>
+#include <time.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/keyvalues.h>
+#include <dns/result.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-settime";
+int verbose;
+
+static isc_mem_t *mctx = NULL;
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s [options] keyfile\n\n", program);
+ fprintf(stderr, "Version: %s\n", VERSION);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -f: force update of old-style "
+ "keys\n");
+ fprintf(stderr, " -K directory: set key file location\n");
+ fprintf(stderr, " -h: help\n");
+ fprintf(stderr, " -v level: set level of verbosity\n");
+ fprintf(stderr, "Timing options:\n");
+ fprintf(stderr, " -P date/[+-]offset: set key publication date\n");
+ fprintf(stderr, " -A date/[+-]offset: set key activation date\n");
+ fprintf(stderr, " -R date/[+-]offset: set key revocation date\n");
+ fprintf(stderr, " -U date/[+-]offset: set key unpublication date\n");
+ fprintf(stderr, " -D date/[+-]offset: set key deletion date\n");
+ fprintf(stderr, "Output:\n");
+ fprintf(stderr, " K<name>+<alg>+<new id>.key, "
+ "K<name>+<alg>+<new id>.private\n");
+
+ exit (-1);
+}
+
+static void
+printtime(dst_key_t *key, int type, const char *tag, FILE *stream) {
+ isc_result_t result;
+ time_t when;
+ const char *output;
+
+ result = dst_key_gettime(key, type, (isc_stdtime_t *) &when);
+ if (result == ISC_R_NOTFOUND || when == 0) {
+ fprintf(stream, "%s: NOT SET\n", tag);
+ return;
+ }
+
+ output = ctime(&when);
+ fprintf(stream, "%s: %s", tag, output);
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+ char *filename = NULL, *directory = NULL;
+ char newname[1024];
+ char keystr[KEY_FORMATSIZE];
+ char *endp;
+ int ch;
+ isc_entropy_t *ectx = NULL;
+ dst_key_t *key = NULL;
+ isc_buffer_t buf;
+ isc_stdtime_t now, when;
+ isc_stdtime_t pub = 0, act = 0, rev = 0, unpub = 0, del = 0;
+ isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE;
+ isc_boolean_t setrev = ISC_FALSE, setunpub = ISC_FALSE;
+ isc_boolean_t setdel = ISC_FALSE;
+ isc_boolean_t forceupdate = ISC_FALSE;
+ isc_boolean_t print = ISC_TRUE;
+
+ if (argc == 1)
+ usage();
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ fatal("Out of memory");
+
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+
+ isc_stdtime_get(&now);
+
+ while ((ch = isc_commandline_parse(argc, argv,
+ "fK:hv:P:A:R:U:D:")) != -1) {
+ switch (ch) {
+ case 'f':
+ forceupdate = ISC_TRUE;
+ break;
+ case 'K':
+ directory = isc_commandline_argument;
+ break;
+ case 'v':
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0')
+ fatal("-v must be followed by a number");
+ break;
+ case 'P':
+ print = ISC_FALSE;
+ setpub = ISC_TRUE;
+ pub = strtotime(isc_commandline_argument, now, now);
+ break;
+ case 'A':
+ print = ISC_FALSE;
+ setact = ISC_TRUE;
+ act = strtotime(isc_commandline_argument, now, now);
+ break;
+ case 'R':
+ print = ISC_FALSE;
+ setrev = ISC_TRUE;
+ rev = strtotime(isc_commandline_argument, now, now);
+ break;
+ case 'U':
+ print = ISC_FALSE;
+ setunpub = ISC_TRUE;
+ unpub = strtotime(isc_commandline_argument, now, now);
+ break;
+ case 'D':
+ print = ISC_FALSE;
+ setdel = ISC_TRUE;
+ del = strtotime(isc_commandline_argument, now, now);
+ break;
+ case '?':
+ if (isc_commandline_option != '?')
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ /* Falls into */
+ case 'h':
+ usage();
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n",
+ program, isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (argc < isc_commandline_index + 1 ||
+ argv[isc_commandline_index] == NULL)
+ fatal("The key file name was not specified");
+ if (argc > isc_commandline_index + 1)
+ fatal("Extraneous arguments");
+
+ if (directory == NULL)
+ directory = dirname(argv[isc_commandline_index]);
+ filename = basename(argv[isc_commandline_index]);
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS)
+ fatal("Could not initialize hash");
+ result = dst_lib_init(mctx, ectx,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ if (result != ISC_R_SUCCESS)
+ fatal("Could not initialize dst");
+ isc_entropy_stopcallbacksources(ectx);
+
+ result = dst_key_fromnamedfile(filename, directory,
+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
+ mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ fatal("Invalid keyfile %s: %s",
+ filename, isc_result_totext(result));
+
+ if (!dst_key_isprivate(key))
+ fatal("%s is not a private key", filename);
+
+ key_format(key, keystr, sizeof(keystr));
+
+ /* Is this an old-style key? */
+ result = dst_key_gettime(key, DST_TIME_CREATED, &when);
+ if (result == ISC_R_NOTFOUND) {
+ if (forceupdate)
+ dst_key_settime(key, DST_TIME_CREATED, now);
+ else
+ fatal("Incompatible key %s, "
+ "use -f force update.", keystr);
+ }
+
+ if (verbose > 2)
+ fprintf(stderr, "%s: %s\n", program, keystr);
+
+ if (print) {
+ printtime(key, DST_TIME_CREATED, "Created", stdout);
+ printtime(key, DST_TIME_PUBLISH, "Publish", stdout);
+ printtime(key, DST_TIME_ACTIVATE, "Activate", stdout);
+ printtime(key, DST_TIME_REVOKE, "Revoke", stdout);
+ printtime(key, DST_TIME_REMOVE, "Remove", stdout);
+ printtime(key, DST_TIME_DELETE, "Delete", stdout);
+ } else {
+ if (setpub)
+ dst_key_settime(key, DST_TIME_PUBLISH, pub);
+
+ if (setact)
+ dst_key_settime(key, DST_TIME_ACTIVATE, act);
+
+ if (setrev)
+ dst_key_settime(key, DST_TIME_REVOKE, rev);
+
+ if (setunpub)
+ dst_key_settime(key, DST_TIME_REMOVE, unpub);
+
+ if (setdel)
+ dst_key_settime(key, DST_TIME_DELETE, del);
+
+ isc_buffer_init(&buf, newname, sizeof(newname));
+ dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &buf);
+
+ result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
+ directory);
+ if (result != ISC_R_SUCCESS) {
+ key_format(key, keystr, sizeof(keystr));
+ fatal("Failed to write key %s: %s", keystr,
+ isc_result_totext(result));
+ }
+
+ printf("%s\n", newname);
+
+ isc_buffer_clear(&buf);
+ dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &buf);
+ printf("%s\n", newname);
+ }
+
+ dst_key_free(&key);
+ dst_lib_destroy();
+ isc_hash_destroy();
+ cleanup_entropy(&ectx);
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
--- /dev/null
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "—">]>
+<!--
+ - Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<!-- $Id: dnssec-settime.docbook,v 1.2 2009/07/19 04:18:04 each Exp $ -->
+<refentry id="man.dnssec-settime">
+ <refentryinfo>
+ <date>July 15, 2009</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-settime</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-settime</application></refname>
+ <refpurpose>Set the key timing metadata for a DNSSEC key</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2009</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dnssec-settime</command>
+ <arg><option>-fr</option></arg>
+ <arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg><option>-A <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg><option>-R <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg><option>-U <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg><option>-D <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg><option>-h</option></arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="req">keyfile</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>dnssec-settime</command>
+ reads a DNSSEC private key file and sets the key timing metadata
+ as specified by the <option>-P</option>, <option>-A</option>,
+ <option>-R</option>, <option>-U</option>, and <option>-D</option>
+ options. The metadata can then be used by
+ <command>dnssec-signzone</command> or other signing software to
+ determine when a key is to be published, whether it should be
+ used for signing a zone, etc.
+ </para>
+ <para>
+ If none of these options is set on the command line,
+ then <command>dnssec-settime</command> simply prints the key timing
+ metadata already stored in the key.
+ </para>
+ <para>
+ When key metadata fields are changed, both files of a key
+ pair (<filename>Knnnn.+aaa+iiiii.key</filename> and
+ <filename>Knnnn.+aaa+iiiii.private</filename>) are regenerated.
+ Metadata fields are stored in the private file. A human-readable
+ description of the metadata is also placed in comments in the key
+ file.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-f</term>
+ <listitem>
+ <para>
+ Force an update of an old-format key with no metadata fields.
+ Without this option, <command>dnssec-settime</command> will
+ fail when attempting to update a legacy key. With this option,
+ the key will be recreated in the new format, but with the
+ original key data retained. The key's creation date will be
+ set to the present time.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Sets the directory in which the key files are to reside.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Emit usage message and exit.
+ </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>TIMING OPTIONS</title>
+ <para>
+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+ If the argument begins with a '+' or '-', it is interpreted as
+ an offset from the present time. If such an offset is followed
+ by one of the characters 'y', 'm', 'w', 'd', or 'h', then the
+ offset is computed in years, months, weeks, days, or hours,
+ respectively; otherwise it is computed in seconds.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>-P <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which a key is to be published to the zone.
+ After that date, the key will be included in the zone but will
+ not be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-A <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be activated. After that
+ date, the key will be included and the zone and used to sign
+ it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-R <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be revoked. After that
+ date, the key will be flagged as revoked. It will be included
+ in the zone and will be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-U <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be unpublished. After that
+ date, the key will no longer be included in the zone, but it
+ may remain in the key repository.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be deleted. After that
+ date, the key can be removed from the key repository.
+ NOTE: Keys are not currently deleted automatically; this field
+ is included for informational purposes and for future
+ development.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 5011</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
--- /dev/null
+<!--
+ - Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+<!-- $Id: dnssec-settime.html,v 1.2 2009/07/19 04:18:04 each Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-revoke</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.67.2">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.dnssec-settime"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-settime</span> — Set the key timing metadata for a DNSSEC key</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-revoke</code> [<code class="option">-hr</code>] [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-P <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-A <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-R <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-U <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-D <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] {keyfile}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id215085"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-settime</strong></span>
+ reads a DNSSEC private key file, sets the key timing metadata
+ as specified by the <code class="option">-P</code>, <code class="option">-A</code>,
+ <code class="option">-R</code>, <code class="option">-U</code>, and <code class="option">-D</code>
+ options.
+ </p>
+<p>
+ If none of these options is set on the command line,
+ then <span><strong class="command">dnssec-settime</strong></span> simply prints the key timing
+ metadata already stored in the key.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id215121"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Emit usage message and exit.
+ </p></dd>
+<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ Sets the directory in which the key files are to reside.
+ </p></dd>
+<dt><span class="term">-P <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+<p>
+ Sets the date on which a key is to be published to the zone.
+ After that date, the key will be included in the zone but will
+ not be used to sign it.
+ </p>
+<p>
+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+ If the argument begins with a '+' or '-', it is interpreted as
+ an offset from the present time. If an offset is followed by
+ one of the characters 'y', 'm', 'w', 'd', or 'h', then the
+ offset is computed in years, months, weeks, days, or hours,
+ respectively; otherwise it is computed in seconds.
+ </p>
+</dd>
+<dt><span class="term">-A <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+<p>
+ Sets the date on which the key is to be activated. After that
+ date, the key will be included and the zone and used to sign
+ it.
+ </p>
+<p>
+ The date/offset syntax is identical to that in the
+ <code class="option">-P</code> option.
+ </p>
+</dd>
+<dt><span class="term">-R <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+<p>
+ Sets the date on which the key is to be revoked. After that
+ date, the key will be flagged as revoked. It will be included
+ in the zone and will be used to sign it.
+ </p>
+<p>
+ The date/offset syntax is identical to that in the
+ <code class="option">-P</code> option.
+ </p>
+</dd>
+<dt><span class="term">-U <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+<p>
+ Sets the date on which the key is to be unpublished. After that
+ date, the key will no longer be included in the zone, but it
+ may remain in the key repository.
+ </p>
+<p>
+ The date/offset syntax is identical to that in the
+ <code class="option">-P</code> option.
+ </p>
+</dd>
+<dt><span class="term">-D <em class="replaceable"><code>date/offset</code></em></span></dt>
+<dd>
+<p>
+ Sets the date on which the key is to be deleted. After that
+ date, the key can be removed from the key repository.
+ </p>
+<p>
+ The date/offset syntax is identical to that in the
+ <code class="option">-P</code> option.
+ </p>
+</dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id215307"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 5011</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id215330"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dnssec-signzone.c,v 1.220 2009/06/24 01:27:06 marka Exp $ */
+/* $Id: dnssec-signzone.c,v 1.221 2009/07/19 04:18:04 each Exp $ */
/*! \file */
#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;
- isc_boolean_t wasused;
- isc_boolean_t commandline;
- 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)
dns_dbnode_t *node;
};
-static ISC_LIST(signer_key_t) keylist;
+static dns_dnsseckeylist_t keylist;
static unsigned int keycount = 0;
isc_rwlock_t keylist_lock;
static isc_stdtime_t starttime = 0, endtime = 0, now;
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 dns_ttl_t zone_soa_min_ttl;
static FILE *fp;
static char *tempfile = NULL;
static const dns_master_style_t *masterstyle;
static dns_masterformat_t outputformat = dns_masterformat_text;
static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
static unsigned int nverified = 0, nverifyfailed = 0;
-static const char *directory;
+static const char *directory = NULL, *dsdir = NULL;
static isc_mutex_t namelock, statslock;
static isc_taskmgr_t *taskmgr = NULL;
static dns_db_t *gdb; /* The database */
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 isc_boolean_t ignore_kskflag = ISC_FALSE;
static dns_name_t *dlv = NULL;
static dns_fixedname_t dlv_fixed;
static dns_master_style_t *dsstyle = NULL;
static unsigned int hash_length = 0;
static isc_boolean_t unknownalg = ISC_FALSE;
static isc_boolean_t disable_zone_check = ISC_FALSE;
+static int keyttl = 3600;
#define INCSTAT(counter) \
if (printstats) { \
check_result(result, "dns_master_dumpnodetostream");
}
-static signer_key_t *
-newkeystruct(dst_key_t *dstkey, isc_boolean_t signwithkey) {
- signer_key_t *key;
-
- key = isc_mem_get(mctx, sizeof(signer_key_t));
- if (key == NULL)
- fatal("out of memory");
- key->key = dstkey;
- if ((dst_key_flags(dstkey) & DNS_KEYFLAG_KSK) != 0) {
- key->issigningkey = signwithkey;
- key->isksk = ISC_TRUE;
- key->isdsk = ISC_FALSE;
- } else {
- key->issigningkey = signwithkey;
- key->isksk = ISC_FALSE;
- key->isdsk = ISC_TRUE;
- }
- key->wasused = ISC_FALSE;
- key->commandline = ISC_FALSE;
- 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)
+ dst_key_t *key)
{
isc_result_t result;
isc_stdtime_t jendtime;
+ unsigned char array[BUFSIZE];
+ isc_buffer_t b;
jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime;
+ isc_buffer_init(&b, array, sizeof(array));
result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
- mctx, b, rdata);
+ mctx, &b, rdata);
isc_entropy_stopcallbacksources(ectx);
if (result != ISC_R_SUCCESS) {
char keystr[KEY_FORMATSIZE];
}
static inline isc_boolean_t
-issigningkey(signer_key_t *key) {
- return (key->issigningkey);
+issigningkey(dns_dnsseckey_t *key) {
+ return (key->force_sign || key->hint_sign);
}
static inline isc_boolean_t
-iszonekey(signer_key_t *key) {
+iszonekey(dns_dnsseckey_t *key) {
return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
dst_key_iszonekey(key->key)));
}
+static inline isc_boolean_t
+isksk(dns_dnsseckey_t *key) {
+ return (key->ksk);
+}
+
+static inline isc_boolean_t
+iszsk(dns_dnsseckey_t *key) {
+ return (ignore_kskflag || !key->ksk);
+}
+
/*%
- * Find the key if it is in our list. If it is, return it, otherwise null.
+ * Find the key that generated an RRSIG, if it is in the key list. If
+ * so, return a pointer to it, otherwise return NULL.
+ *
* No locking is performed here, this must be done by the caller.
*/
-static signer_key_t *
+static dns_dnsseckey_t *
keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
- signer_key_t *key;
+ dns_dnsseckey_t *key;
key = ISC_LIST_HEAD(keylist);
while (key != NULL) {
* 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 *
+static dns_dnsseckey_t *
keythatsigned(dns_rdata_rrsig_t *rrsig) {
isc_result_t result;
dst_key_t *pubkey = NULL, *privkey = NULL;
- signer_key_t *key;
+ dns_dnsseckey_t *key = NULL;
isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
key = keythatsigned_unlocked(rrsig);
* after all.
*/
isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
-
key = keythatsigned_unlocked(rrsig);
if (key != NULL) {
isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
rrsig->algorithm, DST_TYPE_PUBLIC,
- NULL, mctx, &pubkey);
+ directory, mctx, &pubkey);
if (result != ISC_R_SUCCESS) {
isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
return (NULL);
result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
rrsig->algorithm,
DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
- NULL, mctx, &privkey);
+ directory, mctx, &privkey);
if (result == ISC_R_SUCCESS) {
dst_key_free(&pubkey);
- key = newkeystruct(privkey, ISC_FALSE);
- } else
- key = newkeystruct(pubkey, ISC_FALSE);
+ dns_dnsseckey_create(mctx, &privkey, &key);
+ key->force_publish = ISC_TRUE;
+ key->force_sign = ISC_FALSE;
+ } else {
+ dns_dnsseckey_create(mctx, &pubkey, &key);
+ key->force_publish = ISC_TRUE;
+ key->force_sign = ISC_FALSE;
+ }
ISC_LIST_APPEND(keylist, key, link);
isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
}
static inline isc_boolean_t
-setverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key,
+setverifies(dns_name_t *name, dns_rdataset_t *set, dns_dnsseckey_t *key,
dns_rdata_t *rrsig)
{
isc_result_t result;
dns_rdataset_t sigset;
dns_rdata_t sigrdata = DNS_RDATA_INIT;
dns_rdata_rrsig_t rrsig;
- signer_key_t *key;
+ dns_dnsseckey_t *key;
isc_result_t result;
isc_boolean_t nosigs = ISC_FALSE;
isc_boolean_t *wassignedby, *nowsignedby;
{
vbprintf(2, "\trrsig by %s retained\n", sigstr);
keep = ISC_TRUE;
- wassignedby[key->position] = ISC_TRUE;
- nowsignedby[key->position] = ISC_TRUE;
- key->wasused = ISC_TRUE;
+ wassignedby[key->index] = ISC_TRUE;
+ nowsignedby[key->index] = ISC_TRUE;
} else {
vbprintf(2, "\trrsig by %s dropped - %s\n",
sigstr,
expired ? "expired" :
"failed to verify");
- wassignedby[key->position] = ISC_TRUE;
+ wassignedby[key->index] = ISC_TRUE;
resign = ISC_TRUE;
}
} else if (iszonekey(key)) {
{
vbprintf(2, "\trrsig by %s retained\n", sigstr);
keep = ISC_TRUE;
- wassignedby[key->position] = ISC_TRUE;
- nowsignedby[key->position] = ISC_TRUE;
- key->wasused = ISC_TRUE;
+ wassignedby[key->index] = ISC_TRUE;
+ nowsignedby[key->index] = ISC_TRUE;
} else {
vbprintf(2, "\trrsig by %s dropped - %s\n",
sigstr,
expired ? "expired" :
"failed to verify");
- wassignedby[key->position] = ISC_TRUE;
+ wassignedby[key->index] = ISC_TRUE;
}
} else if (!expired) {
vbprintf(2, "\trrsig by %s retained\n", sigstr);
}
if (keep) {
- nowsignedby[key->position] = ISC_TRUE;
+ nowsignedby[key->index] = ISC_TRUE;
INCSTAT(nretained);
if (sigset.ttl != ttl) {
vbprintf(2, "\tfixing ttl %s\n", sigstr);
}
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;
- key->wasused = ISC_TRUE;
+ signwithkey(name, set, &trdata, key->key);
+ nowsignedby[key->index] = ISC_TRUE;
tuple = NULL;
result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
name, ttl, &trdata,
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])
+ if (nowsignedby[key->index])
continue;
- if (!key->issigningkey)
- continue;
- if (!(ignoreksk || key->isdsk ||
- (key->isksk &&
- set->type == dns_rdatatype_dnskey &&
- dns_name_equal(name, gorigin))))
+ if (!issigningkey(key))
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);
- key->wasused = 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);
+ if (iszsk(key) ||
+ (isksk(key) && set->type == dns_rdatatype_dnskey &&
+ dns_name_equal(name, gorigin))) {
+ key_format(key->key, keystr, sizeof(keystr));
+ vbprintf(1, "\tsigning with dnskey %s\n", keystr);
+ dns_rdata_init(&trdata);
+ signwithkey(name, set, &trdata, key->key);
+ 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));
opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
dns_db_t **dbp)
{
- char filename[256];
+ char filename[PATH_MAX];
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] != '/')
+ if (dsdir != NULL) {
+ /* allow room for a trailing slash */
+ if (strlen(dsdir) >= isc_buffer_availablelength(&b))
+ fatal("path '%s' is too long", dsdir);
+ isc_buffer_putstr(&b, dsdir);
+ if (dsdir[strlen(dsdir) - 1] != '/')
isc_buffer_putstr(&b, "/");
}
+ if (strlen(prefix) > isc_buffer_availablelength(&b))
+ fatal("path '%s' is too long", dsdir);
isc_buffer_putstr(&b, prefix);
result = dns_name_tofilenametext(name, ISC_FALSE, &b);
check_result(result, "dns_name_tofilenametext()");
rdclass, 0, NULL, dbp);
check_result(result, "dns_db_create()");
- result = dns_db_load(*dbp, filename);
+ result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT);
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.
+ * Load the DS set for a child zone, if a dsset-* file can be found.
+ * If not, try to find a keyset-* file from an earlier version of
+ * dnssec-signzone, and build DS records from that.
*/
static isc_result_t
loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
dns_diff_t diff;
dns_difftuple_t *tuple = NULL;
+ opendb("dsset-", name, gclass, &db);
+ if (db != NULL) {
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_init(dsset);
+ result = dns_db_findrdataset(db, node, NULL,
+ dns_rdatatype_ds, 0, 0,
+ dsset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_SUCCESS) {
+ vbprintf(2, "found DS records\n");
+ dsset->ttl = ttl;
+ dns_db_detach(&db);
+ return (result);
+ }
+ }
+ dns_db_detach(&db);
+ }
+
+ /* No DS records found; try again, looking for DNSKEY records */
opendb("keyset-", name, gclass, &db);
- if (db == NULL)
+ 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);
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);
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);
}
/*%
- * Extracts the TTL from the SOA.
+ * Extracts the minimum TTL from the SOA.
*/
static dns_ttl_t
-soattl(void) {
+soa_min_ttl(void) {
dns_rdataset_t soaset;
dns_fixedname_t fname;
dns_name_t *name;
dns_rdatatype_ds, 0);
check_result(result, "dns_db_deleterdataset");
}
+
result = loadds(name, nsttl, &dsset);
if (result == ISC_R_SUCCESS) {
result = dns_db_addrdataset(gdb, node, gversion, 0,
fatal("iterating through the database failed: %s",
isc_result_totext(result));
result = dns_nsec_build(gdb, gversion, node, nextname,
- zonettl);
+ zone_soa_min_ttl);
check_result(result, "dns_nsec_build()");
dns_db_detachnode(gdb, &node);
}
*/
dns_dbiterator_pause(dbiter);
addnsec3(name, node, salt, salt_length, iterations,
- hashlist, zonettl);
+ hashlist, zone_soa_min_ttl);
dns_db_detachnode(gdb, &node);
/*
* Add NSEC3's for empty nodes. Use closest encloser logic.
count--;
dns_name_split(nextname, count, NULL, nextname);
addnsec3(nextname, NULL, salt, salt_length,
- iterations, hashlist, zonettl);
+ iterations, hashlist, zone_soa_min_ttl);
}
}
dns_dbiterator_destroy(&dbiter);
isc_result_t result;
dst_key_t *keys[20];
unsigned int nkeys, i;
+ dns_rdataset_t rdataset;
currentversion = NULL;
dns_db_currentversion(db, ¤tversion);
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)
+ /* Preserve the TTL of the DNSKEY RRset, if any */
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, currentversion,
+ dns_rdatatype_dnskey, 0, 0,
+ &rdataset, NULL);
+
+ if (result == ISC_R_SUCCESS) {
+ keyttl = rdataset.ttl;
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ }
+
+ /* Load keys corresponding to the existing DNSKEY RRset */
+ result = dns_dnssec_findzonekeys2(db, currentversion, node, gorigin,
+ directory, mctx, 20, keys, &nkeys);
+ if (result == ISC_R_NOTFOUND) {
result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
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;
+ dns_dnsseckey_t *key = NULL;
- key = newkeystruct(keys[i], dst_key_isprivate(keys[i]));
+ dns_dnsseckey_create(mctx, &keys[i], &key);
+ key->force_publish = ISC_TRUE;
+ key->force_sign = dst_key_isprivate(key->key);
+ key->source = dns_keysource_zoneapex;
ISC_LIST_APPEND(keylist, key, link);
}
+
+ cleanup:
dns_db_detachnode(db, &node);
dns_db_closeversion(db, ¤tversion, ISC_FALSE);
}
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);
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));
+ dns_rdatatype_dnskey, 0, 0, &rdataset,
+ NULL);
+ if (result != ISC_R_SUCCESS) {
+ vbprintf(2, "failed to find keys at the zone apex: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
result = dns_rdataset_first(&rdataset);
check_result(result, "dns_rdataset_first");
while (result == ISC_R_SUCCESS) {
+ dns_dnsseckey_t *key = NULL;
pubkey = NULL;
dns_rdata_reset(&rdata);
dns_rdataset_current(&rdataset, &rdata);
goto next;
}
- key = newkeystruct(pubkey, ISC_FALSE);
+ dns_dnsseckey_create(mctx, &pubkey, &key);
+ key->force_publish = ISC_TRUE;
+ key->force_sign = 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);
+
+ cleanup:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (currentversion != NULL)
+ dns_db_closeversion(db, ¤tversion, ISC_FALSE);
+}
+
+static isc_result_t
+make_dnskey(dst_key_t *key, dns_rdata_t *target) {
+ isc_result_t result;
+ unsigned char data[DST_KEY_MAXSIZE];
+ isc_buffer_t b;
+ isc_region_t r;
+
+ isc_buffer_init(&b, data, sizeof(data));
+ result = dst_key_todns(key, &b);
+ check_result(result, "dst_key_todns");
+
+ dns_rdata_reset(target);
+ isc_buffer_usedregion(&b, &r);
+ dns_rdata_fromregion(target, dst_key_class(key),
+ dns_rdatatype_dnskey, &r);
+ return (ISC_R_SUCCESS);
+}
+
+static void
+build_final_keylist(dns_db_t *db, const char *directory, isc_mem_t *mctx) {
+ isc_result_t result;
+ dns_dbversion_t *ver = NULL;
+ dns_diff_t del, add;
+ dns_difftuple_t *tuple = NULL;
+ dns_rdata_t dnskey = DNS_RDATA_INIT;
+ dns_dnsseckeylist_t matchkeys;
+ dns_dnsseckey_t *key1, *key2;
+ char name[DNS_NAME_FORMATSIZE];
+ char alg[80];
+
+ dns_name_format(gorigin, name, sizeof(name));
+
+ ISC_LIST_INIT(matchkeys);
+ result = dns_dnssec_findmatchingkeys(gorigin, directory,
+ mctx, &matchkeys);
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_SUCCESS;
+ check_result(result, "dns_dnssec_findmatchingkeys");
+
+ result = dns_db_newversion(db, &ver);
+ check_result(result, "dns_db_newversion");
+
+ dns_diff_init(mctx, &del);
+ dns_diff_init(mctx, &add);
+
+ /*
+ * For each key in matchkeys, see if it has a match in keylist.
+ * - If not, and if the metadata says it should be published:
+ * add it to keylist and to the DNSKEY set
+ * - If so, and if the metadata says it should be removed:
+ * remove it from keylist and from the DNSKEY set
+ * - Otherwise, make sure keylist has up-to-date metadata
+ *
+ * (XXXEACH: logic is needed to make sure revoked keys
+ * can be matched correctly with nonrevoked)
+ */
+
+ key1 = ISC_LIST_HEAD(matchkeys);
+ while (key1 != NULL) {
+ for (key2 = ISC_LIST_HEAD(keylist);
+ key2 != NULL;
+ key2 = ISC_LIST_NEXT(key2, link)) {
+ if (dst_key_compare(key1->key, key2->key))
+ break;
+ }
+
+ /*
+ * No matching key found in keylist, so move the key
+ * we found into keylist
+ */
+ if (key2 == NULL) {
+ dns_dnsseckey_t *next;
+
+ /* move key from matchkeys to keylist */
+ next = ISC_LIST_NEXT(key1, link);
+ ISC_LIST_UNLINK(matchkeys, key1, link);
+ ISC_LIST_APPEND(keylist, key1, link);
+
+ key1 = next;
+ continue;
+ }
+
+ /* Match found: remove it or update it as needed */
+ if (key1->hint_remove) {
+ ISC_LIST_UNLINK(keylist, key2, link);
+ dns_dnsseckey_destroy(mctx, &key2);
+
+ make_dnskey(key1->key, &dnskey);
+ alg_format(dst_key_alg(key1->key), alg, sizeof(alg));
+ fprintf(stderr, "Removing expired key %d/%s from "
+ "DNSKEY RRset.\n",
+ dst_key_id(key1->key), alg);
+
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
+ gorigin, keyttl,
+ &dnskey, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&del, &tuple);
+ } else {
+ key2->hint_publish = key1->hint_publish;
+ key2->hint_sign = key1->hint_sign;
+ }
+
+ key1 = ISC_LIST_NEXT(key1, link);
+ }
+
+ /*
+ * If a key was not in the zone already and needs to be published,
+ * add it now.
+ */
+ for (key1 = ISC_LIST_HEAD(keylist);
+ key1 != NULL;
+ key1 = ISC_LIST_NEXT(key1, link)) {
+ if (key1->source == dns_keysource_zoneapex)
+ continue;
+
+ if (key1->hint_publish || key1->force_publish) {
+ make_dnskey(key1->key, &dnskey);
+
+ alg_format(dst_key_alg(key1->key), alg, sizeof(alg));
+ fprintf(stderr, "Fetching %s %d/%s from key %s.\n",
+ isksk(key1) ?
+ (iszsk(key1) ? "KSK/ZSK" : "KSK") :
+ "ZSK",
+ dst_key_id(key1->key), alg,
+ key1->source == dns_keysource_user ?
+ "file" :
+ "repository");
+
+ /* add key to the zone */
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ gorigin, keyttl,
+ &dnskey, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&add, &tuple);
+ } else {
+ vbprintf(1, "%s %d/%s: not published.\n",
+ isksk(key1) ?
+ (iszsk(key1) ? "KSK/ZSK" : "KSK") :
+ "ZSK",
+ dst_key_id(key1->key), alg);
+ }
+ }
+
+ /* free matchkeys */
+ while (!ISC_LIST_EMPTY(matchkeys)) {
+ key1 = ISC_LIST_HEAD(matchkeys);
+ ISC_LIST_UNLINK(matchkeys, key1, link);
+ dns_dnsseckey_destroy(mctx, &key1);
+ }
+
+ result = dns_diff_applysilently(&del, db, ver);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to delete DNSKEYs at node '%s': %s",
+ name, isc_result_totext(result));
+
+ result = dns_diff_applysilently(&add, db, ver);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to add DNSKEYs at node '%s': %s",
+ name, isc_result_totext(result));
+
+ dns_db_closeversion(db, &ver, ISC_TRUE);
+
+ dns_diff_clear(&del);
+ dns_diff_clear(&add);
}
static void
dns_rdataset_init(&rdataset);
result = dns_db_findrdataset(db, node, currentversion,
- dns_rdatatype_dnskey, 0, 0, &rdataset, NULL);
+ 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));
dns_rdataset_disassociate(&rdataset);
dns_db_detachnode(db, &node);
dns_db_closeversion(db, ¤tversion, ISC_FALSE);
- if (!have_non_ksk && !ignoreksk) {
+ if (!have_non_ksk && !ignore_kskflag) {
if (disable_zone_check)
- fprintf(stderr, "%s: warning: No non-KSK dnskey found. "
- "Supply non-KSK dnskey or use '-z'.\n",
+ fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
+ "supply a ZSK or use '-z'.\n",
program);
else
- fatal("No non-KSK dnskey found. "
- "Supply non-KSK dnskey or use '-z'.");
+ fatal("No non-KSK DNSKEY found; "
+ "supply a ZSK or use '-z'.");
}
}
isc_buffer_t namebuf;
isc_region_t r;
isc_result_t result;
- signer_key_t *key;
+ dns_dnsseckey_t *key;
unsigned char dsbuf[DNS_DS_BUFFERSIZE];
unsigned char keybuf[DST_KEY_MAXSIZE];
unsigned int filenamelen;
check_result(result, "dns_name_tofilenametext");
isc_buffer_putuint8(&namebuf, 0);
filenamelen = strlen(prefix) + strlen(namestr);
- if (directory != NULL)
- filenamelen += strlen(directory) + 1;
+ if (dsdir != NULL)
+ filenamelen += strlen(dsdir) + 1;
filename = isc_mem_get(mctx, filenamelen + 1);
if (filename == NULL)
fatal("out of memory");
- if (directory != NULL)
- sprintf(filename, "%s/", directory);
+ if (dsdir != NULL)
+ sprintf(filename, "%s/", dsdir);
else
filename[0] = 0;
strcat(filename, prefix);
for (key = ISC_LIST_HEAD(keylist);
key != NULL;
key = ISC_LIST_NEXT(key, link))
- if (!key->isksk) {
+ if (!isksk(key)) {
have_non_ksk = ISC_TRUE;
break;
}
for (key = ISC_LIST_HEAD(keylist);
key != NULL;
key = ISC_LIST_NEXT(key, link))
- if (key->isksk) {
+ if (isksk(key)) {
have_ksk = ISC_TRUE;
break;
}
key != NULL;
key = ISC_LIST_NEXT(key, link))
{
- if (have_ksk && have_non_ksk && !key->isksk)
+ if (have_ksk && have_non_ksk && !isksk(key))
continue;
dns_rdata_init(&rdata);
dns_rdata_init(&ds);
} else
result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
- gorigin, zonettl,
+ gorigin, zone_soa_min_ttl,
&rdata, &tuple);
check_result(result, "dns_difftuple_create");
dns_diff_append(&diff, &tuple);
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-S:\tsmart signing: automatically finds key\n"
+ "\t\tfiles for the zone and determines they are to\n"
+ "\t\tbe used\n");
+ fprintf(stderr, "\t-K directory:\n");
+ fprintf(stderr, "\t\tdirectory to find key files (.)\n");
+ fprintf(stderr, "\t-d directory:\n");
+ fprintf(stderr, "\t\tdirectory to find dsset files (.)\n");
fprintf(stderr, "\t-g:\t");
- fprintf(stderr, "generate DS records from keyset files\n");
+ fprintf(stderr, "generate dsset file, and/or include DS records\n"
+ "\t\tfrom child zones' dsset 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\ta file containing random data\n");
fprintf(stderr, "\t-a:\t");
fprintf(stderr, "verify generated signatures\n");
+ fprintf(stderr, "\t-c class (IN)\n");
fprintf(stderr, "\t-p:\t");
fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
fprintf(stderr, "\t-P:\t");
fprintf(stderr, "disable post-sign verification\n");
+ fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs");
fprintf(stderr, "\t-t:\t");
fprintf(stderr, "print statistics\n");
+ fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
+ "\t\twith older versions of dnssec-signzone -g\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");
int ndskeys = 0;
char *endp;
isc_time_t timer_start, timer_finish;
- signer_key_t *key;
+ dns_dnsseckey_t *key;
isc_result_t result;
isc_log_t *log = NULL;
isc_boolean_t pseudorandom = ISC_FALSE;
size_t salt_length = 0;
unsigned char saltbuf[255];
hashlist_t hashlist;
+ isc_boolean_t smartsign = ISC_FALSE;
+ isc_boolean_t make_keyset = ISC_FALSE;
-#define CMDLINE_FLAGS "3:aAc:d:e:f:FghH:i:I:j:k:l:m:n:N:o:O:pPr:s:StUv:z"
+#define CMDLINE_FLAGS "3:AaCc:Dd:e:f:FghH:i:I:j:K:k:l:m:n:N:o:O:pPr:s:ST:tUv:z"
/*
* Process memory debugging argument first.
tryverify = ISC_TRUE;
break;
+ case 'C':
+ make_keyset = ISC_TRUE;
+ break;
+
case 'c':
classname = isc_commandline_argument;
break;
case 'd':
+ dsdir = isc_commandline_argument;
+ if (strlen(dsdir) == 0)
+ fatal("DS directory must be non-empty string");
+ break;
+
+ case 'K':
directory = isc_commandline_argument;
break;
break;
case 'S':
- /* This is intentionally undocumented */
- /* -S: simple output style */
- masterstyle = &dns_master_style_simple;
+ smartsign = ISC_TRUE;
+ generateds = ISC_TRUE;
+ break;
+
+ case 'T':
+ endp = NULL;
+ keyttl = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0')
+ fatal("key TTL must be numeric");
break;
case 't':
break;
case 'z':
- ignoreksk = ISC_TRUE;
+ ignore_kskflag = ISC_TRUE;
break;
case 'F':
isc_stdtime_get(&now);
- if (startstr != NULL)
+ if (startstr != NULL) {
+ if (startstr[0] == '-' || strncmp(startstr, "now-", 4) == 0)
+ fatal("time value %s is invalid", startstr);
starttime = strtotime(startstr, now, now);
- else
+ } else
starttime = now - 3600; /* Allow for some clock skew. */
- if (endstr != NULL)
+ if (endstr != NULL) {
+ if (endstr[0] == '-' || strncmp(endstr, "now-", 4) == 0)
+ fatal("time value %s is invalid", endstr);
endtime = strtotime(endstr, now, starttime);
- else
+ } else
endtime = starttime + (30 * 24 * 60 * 60);
if (cycle == -1)
rdclass = strtoclass(classname);
+ if (directory == NULL)
+ directory = ".";
+
setup_logging(verbose, mctx, &log);
argc -= isc_commandline_index;
loadzone(file, origin, rdclass, &gdb);
gorigin = dns_db_origin(gdb);
gclass = dns_db_class(gdb);
- zonettl = soattl();
+ zone_soa_min_ttl = soa_min_ttl();
if (IS_NSEC3) {
isc_boolean_t answer;
for (i = 0; i < argc; i++) {
dst_key_t *newkey = NULL;
- result = dst_key_fromnamedfile(argv[i],
+ result = dst_key_fromnamedfile(argv[i], directory,
DST_TYPE_PUBLIC |
DST_TYPE_PRIVATE,
mctx, &newkey);
key = ISC_LIST_NEXT(key, link);
}
if (key == NULL) {
- key = newkeystruct(newkey, ISC_TRUE);
- key->commandline = ISC_TRUE;
+ dns_dnsseckey_create(mctx, &newkey, &key);
+ key->force_publish = ISC_TRUE;
+ key->force_sign = ISC_TRUE;
+ key->source = dns_keysource_user;
ISC_LIST_APPEND(keylist, key, link);
} else
dst_key_free(&newkey);
for (i = 0; i < ndskeys; i++) {
dst_key_t *newkey = NULL;
- result = dst_key_fromnamedfile(dskeyfile[i],
+ result = dst_key_fromnamedfile(dskeyfile[i], directory,
DST_TYPE_PUBLIC |
DST_TYPE_PRIVATE,
mctx, &newkey);
dst_key_name(newkey)))
{
/* Override key flags. */
- key->issigningkey = ISC_TRUE;
- key->isksk = ISC_TRUE;
- key->isdsk = ISC_FALSE;
+ key->force_publish = ISC_TRUE;
+ key->force_sign = ISC_TRUE;
+ key->source = dns_keysource_user;
+ key->ksk = ISC_TRUE;
dst_key_free(&dkey);
key->key = newkey;
break;
}
if (key == NULL) {
/* Override dnskey flags. */
- key = newkeystruct(newkey, ISC_TRUE);
- key->isksk = ISC_TRUE;
- key->isdsk = ISC_FALSE;
+ dns_dnsseckey_create(mctx, &newkey, &key);
+ key->force_publish = ISC_TRUE;
+ key->force_sign = ISC_TRUE;
+ key->source = dns_keysource_user;
+ key->ksk = ISC_TRUE;
ISC_LIST_APPEND(keylist, key, link);
}
}
- if (ISC_LIST_EMPTY(keylist)) {
+ /*
+ * If we're doing smart signing, look in the key repository for
+ * key files with metadata, and merge them with the keylist
+ * we have now.
+ */
+ if (smartsign)
+ build_final_keylist(gdb, directory, mctx);
+
+ /* Now enumerate the key list */
+ for (key = ISC_LIST_HEAD(keylist);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
+ key->index = keycount++;
+ }
+
+ if (keycount == 0) {
if (disable_zone_check)
- fprintf(stderr, "%s: warning: No keys specified or found\n",
- program);
+ fprintf(stderr, "%s: warning: No keys specified "
+ "or found\n", program);
else
fatal("No signing keys specified or found.");
nokeys = ISC_TRUE;
nsecify();
if (!nokeys) {
- writeset("keyset-", dns_rdatatype_dnskey);
writeset("dsset-", dns_rdatatype_ds);
+ if (make_keyset)
+ writeset("keyset-", dns_rdatatype_dnskey);
if (dlv != NULL) {
writeset("dlvset-", dns_rdatatype_dlv);
}
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));
+ dns_dnsseckey_destroy(mctx, &key);
}
isc_mem_put(mctx, tempfile, tempfilelen);
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: dnssec-signzone.docbook,v 1.34 2009/06/05 21:59:43 jreed Exp $ -->
+<!-- $Id: dnssec-signzone.docbook,v 1.35 2009/07/19 04:18:04 each Exp $ -->
<refentry id="man.dnssec-signzone">
<refentryinfo>
<date>June 05, 2009</date>
<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">directory</replaceable></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>-p</option></arg>
<arg><option>-P</option></arg>
<arg><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg>
+ <arg><option>-S</option></arg>
<arg><option>-s <replaceable class="parameter">start-time</replaceable></option></arg>
+ <arg><option>-T <replaceable class="parameter">ttl</replaceable></option></arg>
<arg><option>-t</option></arg>
<arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
<arg><option>-z</option></arg>
</varlistentry>
<varlistentry>
- <term>-k <replaceable class="parameter">key</replaceable></term>
+ <term>-d <replaceable class="parameter">directory</replaceable></term>
<listitem>
<para>
- Treat specified key as a key signing key ignoring any
- key flags. This option may be specified multiple times.
+ Look for <filename>dsset-</filename> or
+ <filename>keyset-</filename> files in <option>directory</option>.
</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-l <replaceable class="parameter">domain</replaceable></term>
+ <term>-g</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.
+ Generate DS records for child zones from
+ <filename>dsset-</filename> or <filename>keyset-</filename>
+ file. Existing DS records will be removed.
</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-d <replaceable class="parameter">directory</replaceable></term>
+ <term>-K <replaceable class="parameter">directory</replaceable></term>
<listitem>
<para>
- Look for <filename>keyset</filename> files in
- <option>directory</option> as the directory
+ Key repository: Specify a directory to search for DNSSEC keys.
+ If not specified, defaults to the current directory.
</para>
</listitem>
</varlistentry>
<varlistentry>
- <term>-g</term>
+ <term>-k <replaceable class="parameter">key</replaceable></term>
<listitem>
<para>
- Generate DS records for child zones from keyset files.
- Existing DS records will be removed.
+ 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>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>-S</term>
+ <listitem>
+ <para>
+ Smart signing: Instructs <command>dnssec-signzone</command> to
+ search the key repository for keys that match the zone being
+ signed, and to include them in the zone if appropriate.
+ </para>
+ <para>
+ When a key is found, its timing metadata is examined to
+ determine how it should be used, according to the following
+ rules. Each successive rule takes priority over the prior
+ ones:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <listitem>
+ <para>
+ If no timing metadata has been set for the key, the key is
+ published in the zone and used to sign the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <listitem>
+ <para>
+ If the key's publication date is set and is in the past, the
+ key is published in the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <listitem>
+ <para>
+ If the key's activation date is set and in the past, the
+ key is published (regardless of publication date) and
+ used to sign the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <listitem>
+ <para>
+ If the key's revocation date is set and in the past, and the
+ key is published, then the key is revoked, and the revoked key
+ is used to sign the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <listitem>
+ <para>
+ If either of the key's unpublication or deletion dates are set
+ and in the past, the key is NOT published or used to sign the
+ zone, regardless of any other metadata.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-T <replaceable class="parameter">ttl</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the TTL of new DNSKEY records imported to the zone
+ from the key repository. Only useful with the -S option.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term>-t</term>
<listitem>
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dnssectool.c,v 1.47 2009/06/04 02:56:47 tbox Exp $ */
+/* $Id: dnssectool.c,v 1.48 2009/07/19 04:18:04 each Exp $ */
/*! \file */
isc_entropy_detach(ectx);
}
+static isc_stdtime_t
+time_units(isc_stdtime_t offset, char suffix, const char *str) {
+ switch(suffix) {
+ case 'Y': case 'y':
+ return (offset * (365 * 24 * 3600));
+ case 'M': case 'm':
+ return (offset * (30 * 24 * 3600));
+ case 'W': case 'w':
+ return (offset * (7 * 24 * 3600));
+ case 'D': case 'd':
+ return (offset * (24 * 3600));
+ case 'H': case 'h':
+ return (offset * 3600);
+ case 'S': case 's': case '\0':
+ return (offset);
+ default:
+ fatal("time value %s is invalid", str);
+ }
+ return(0); /* silence compiler warning */
+}
+
isc_stdtime_t
strtotime(const char *str, isc_int64_t now, isc_int64_t base) {
isc_int64_t val, offset;
isc_result_t result;
+ const char *orig = str;
char *endp;
- if (str[0] == '+') {
+ if (strlen(str) == 1 && (str[0] == '0' || str[0] == '-'))
+ return ((isc_stdtime_t) 0);
+
+ if (strncmp(str, "now", 3) == 0) {
+ base = now;
+ str += 3;
+ }
+
+ if (str[0] == '\0')
+ return ((isc_stdtime_t) base);
+ else if (str[0] == '+') {
offset = strtol(str + 1, &endp, 0);
- if (*endp != '\0')
- fatal("time value %s is invalid", str);
+ offset = time_units(offset, *endp, orig);
val = base + offset;
- } else if (strncmp(str, "now+", 4) == 0) {
- offset = strtol(str + 4, &endp, 0);
- if (*endp != '\0')
- fatal("time value %s is invalid", str);
- val = now + offset;
+ } else if (str[0] == '-') {
+ offset = strtol(str + 1, &endp, 0);
+ offset = time_units(offset, *endp, orig);
+ val = base - offset;
} else if (strlen(str) == 8U) {
char timestr[15];
sprintf(timestr, "%s000000", str);
result = dns_time64_fromtext(timestr, &val);
if (result != ISC_R_SUCCESS)
- fatal("time value %s is invalid", str);
+ fatal("time value %s is invalid: %s", orig,
+ isc_result_totext(result));
+ } else if (strlen(str) > 14U) {
+ fatal("time value %s is invalid", orig);
} else {
result = dns_time64_fromtext(str, &val);
if (result != ISC_R_SUCCESS)
- fatal("time value %s is invalid", str);
+ fatal("time value %s is invalid: %s", orig,
+ isc_result_totext(result));
}
return ((isc_stdtime_t) val);
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsupdate.c,v 1.170 2009/07/14 23:47:54 tbox Exp $ */
+/* $Id: nsupdate.c,v 1.171 2009/07/19 04:18:04 each Exp $ */
/*! \file */
debug("Creating key...");
/* Try reading the key from a K* pair */
- result = dst_key_fromnamedfile(keyfile,
+ result = dst_key_fromnamedfile(keyfile, NULL,
DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
&dstkey);
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: sign.sh,v 1.27 2009/06/04 02:56:47 tbox Exp $
+# $Id: sign.sh,v 1.28 2009/07/19 04:18:04 each Exp $
SYSTEMTESTTOP=../..
. $SYSTEMTESTTOP/conf.sh
(cd ../ns2 && sh sign.sh )
-cp ../ns2/keyset-example. .
-cp ../ns2/keyset-dlv. .
+cp ../ns2/dsset-example. .
+cp ../ns2/dsset-dlv. .
keyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
# Configure the resolving server with a trusted key.
-cat $keyname.key | $PERL -n -e '
+cat $keyname.key | grep -v '^; ' | $PERL -n -e '
local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split;
local $key = join("", @rest);
print <<EOF
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: sign.sh,v 1.32 2009/06/04 02:56:47 tbox Exp $
+# $Id: sign.sh,v 1.33 2009/07/19 04:18:04 each Exp $
SYSTEMTESTTOP=../..
. $SYSTEMTESTTOP/conf.sh
for subdomain in secure bogus dynamic keyless nsec3 optout nsec3-unknown optout-unknown multiple
do
- cp ../ns3/keyset-$subdomain.example. .
+ cp ../ns3/dsset-$subdomain.example. .
done
keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: keycreate.c,v 1.15 2007/06/19 23:47:06 tbox Exp $ */
+/* $Id: keycreate.c,v 1.16 2009/07/19 04:18:04 each Exp $ */
#include <config.h>
ourkey = NULL;
type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY;
- result = dst_key_fromnamedfile(ourkeyname, type, mctx, &ourkey);
+ result = dst_key_fromnamedfile(ourkeyname, NULL, type, mctx, &ourkey);
CHECK("dst_key_fromnamedfile", result);
isc_buffer_init(&nonce, noncedata, sizeof(noncedata));
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: keydelete.c,v 1.11 2007/06/19 23:47:06 tbox Exp $ */
+/* $Id: keydelete.c,v 1.12 2009/07/19 04:18:04 each Exp $ */
#include <config.h>
dstkey = NULL;
type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY;
- result = dst_key_fromnamedfile(keyname, type, mctx, &dstkey);
+ result = dst_key_fromnamedfile(keyname, NULL, type, mctx, &dstkey);
CHECK("dst_key_fromnamedfile", result);
result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
DNS_TSIG_HMACMD5_NAME,
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: setup.sh,v 1.8 2007/06/19 23:47:06 tbox Exp $
+# $Id: setup.sh,v 1.9 2009/07/19 04:18:04 each Exp $
RANDFILE=../random.data
-keyname=`$KEYGEN -k -a DH -b 768 -n host -r $RANDFILE server`
+keyname=`$KEYGEN -T KEY -a DH -b 768 -n host -r $RANDFILE server`
keyid=`echo $keyname | $PERL -p -e 's/^.*\+0*//;'`
rm -f named.conf
perl -p -e "s/KEYID/$keyid/;" < named.conf.in > named.conf
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: tests.sh,v 1.7 2007/06/19 23:47:06 tbox Exp $
+# $Id: tests.sh,v 1.8 2009/07/19 04:18:04 each Exp $
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
echo "I:generating new DH key"
ret=0
-dhkeyname=`$KEYGEN -k -a DH -b 768 -n host -r $RANDFILE client` || ret=1
+dhkeyname=`$KEYGEN -T KEY -a DH -b 768 -n host -r $RANDFILE client` || ret=1
if [ $ret != 0 ]; then
echo "I:failed"
echo "I:exit status: $status"
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- File: $Id: Bv9ARM-book.xml,v 1.422 2009/07/14 22:54:57 each Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.423 2009/07/19 04:18:04 each Exp $ -->
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<title>BIND 9 Administrator Reference Manual</title>
<xi:include href="../../bin/dnssec/dnssec-keyfromlabel.docbook"/>
<xi:include href="../../bin/dnssec/dnssec-keygen.docbook"/>
<xi:include href="../../bin/dnssec/dnssec-revoke.docbook"/>
+ <xi:include href="../../bin/dnssec/dnssec-settime.docbook"/>
<xi:include href="../../bin/dnssec/dnssec-signzone.docbook"/>
<xi:include href="../../bin/check/named-checkconf.docbook"/>
<xi:include href="../../bin/check/named-checkzone.docbook"/>
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: db.c,v 1.91 2009/06/30 02:52:32 each Exp $ */
+/* $Id: db.c,v 1.92 2009/07/19 04:18:05 each Exp $ */
/*! \file */
isc_result_t
dns_db_load(dns_db_t *db, const char *filename) {
- return (dns_db_load2(db, filename, dns_masterformat_text));
+ return (dns_db_load3(db, filename, dns_masterformat_text, 0));
}
isc_result_t
dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format) {
+ return (dns_db_load3(db, filename, format, 0));
+}
+
+isc_result_t
+dns_db_load3(dns_db_t *db, const char *filename, dns_masterformat_t format,
+ unsigned int options) {
isc_result_t result, eresult;
dns_rdatacallbacks_t callbacks;
- unsigned int options = 0;
/*
* Load master file 'filename' into 'db'.
*/
/*
- * $Id: dnssec.c,v 1.95 2009/06/04 02:56:47 tbox Exp $
+ * $Id: dnssec.c,v 1.96 2009/07/19 04:18:05 each Exp $
*/
/*! \file */
#include <stdlib.h>
#include <isc/buffer.h>
+#include <isc/dir.h>
#include <isc/mem.h>
#include <isc/serial.h>
#include <isc/string.h>
dst_key_free(&dstkey);
return (ISC_FALSE);
}
+
+isc_result_t
+dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey,
+ dns_dnsseckey_t **dkp)
+{
+ isc_result_t result;
+ isc_stdtime_t when;
+ dns_dnsseckey_t *dk;
+
+ REQUIRE(dkp != NULL && *dkp == NULL);
+ dk = isc_mem_get(mctx, sizeof(dns_dnsseckey_t));
+ if (dk == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dk->key = *dstkey;
+ *dstkey = NULL;
+ dk->force_publish = ISC_FALSE;
+ dk->force_sign = ISC_FALSE;
+ dk->hint_publish = ISC_FALSE;
+ dk->hint_sign = ISC_FALSE;
+ dk->hint_remove = ISC_FALSE;
+ dk->source = dns_keysource_unknown;
+ dk->index = 0;
+
+ /* KSK or ZSK? */
+ dk->ksk = ISC_TF((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) != 0);
+
+ /* Is this an old-style key? */
+ result = dst_key_gettime(dk->key, DST_TIME_CREATED, &when);
+ dk->legacy = ISC_TF(result != ISC_R_SUCCESS);
+
+ ISC_LINK_INIT(dk, link);
+ *dkp = dk;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) {
+ dns_dnsseckey_t *dk;
+
+ REQUIRE(dkp != NULL && *dkp != NULL);
+ dk = *dkp;
+ if (dk->key != NULL)
+ dst_key_free(&dk->key);
+ isc_mem_put(mctx, dk, sizeof(dns_dnsseckey_t));
+ *dkp = NULL;
+}
+
+static void
+get_hints(dns_dnsseckey_t *key) {
+ isc_result_t result;
+ isc_stdtime_t now, publish, active, revoke, remove, delete;
+ isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE;
+ isc_boolean_t revset = ISC_FALSE, remset = ISC_FALSE;
+ isc_boolean_t delset = ISC_FALSE;
+
+ REQUIRE(key != NULL && key->key != NULL);
+
+ isc_stdtime_get(&now);
+
+ result = dst_key_gettime(key->key, DST_TIME_PUBLISH, &publish);
+ if (result == ISC_R_SUCCESS)
+ pubset = ISC_TRUE;
+
+ result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
+ if (result == ISC_R_SUCCESS)
+ actset = ISC_TRUE;
+
+ result = dst_key_gettime(key->key, DST_TIME_REVOKE, &revoke);
+ if (result == ISC_R_SUCCESS)
+ revset = ISC_TRUE;
+
+ result = dst_key_gettime(key->key, DST_TIME_REMOVE, &remove);
+ if (result == ISC_R_SUCCESS)
+ remset = ISC_TRUE;
+
+ result = dst_key_gettime(key->key, DST_TIME_DELETE, &delete);
+ if (result == ISC_R_SUCCESS)
+ delset = ISC_TRUE;
+
+ /* No metadata set: Publish and sign. */
+ if (!pubset && !actset && !revset && !remset && !delset) {
+ key->hint_sign = ISC_TRUE;
+ key->hint_publish = ISC_TRUE;
+ }
+
+ /* Metadata says publish (but possibly not activate) */
+ if (pubset && publish < now)
+ key->hint_publish = ISC_TRUE;
+
+ /* Metadata says activate (so we must also publish) */
+ if (actset && active < now) {
+ key->hint_sign = ISC_TRUE;
+ key->hint_publish = ISC_TRUE;
+ }
+
+ /*
+ * Activation date is set (maybe in the future), but
+ * publication date isn't. Most likely the user wants to
+ * publish now and activate later.
+ */
+ if (actset && !pubset)
+ key->hint_publish = ISC_TRUE;
+
+ /*
+ * Metadata says revoke. If the key is published,
+ * we *have to* sign with it per RFC5011--even if it was
+ * not active before.
+ *
+ * If it hasn't already been done, we should also revoke it now.
+ */
+ if (key->hint_publish && (revset && revoke < now)) {
+ isc_uint32_t flags;
+ key->hint_sign = ISC_TRUE;
+ flags = dst_key_flags(key->key);
+ if ((flags & DNS_KEYFLAG_REVOKE) == 0) {
+ flags |= DNS_KEYFLAG_REVOKE;
+ dst_key_setflags(dstkey, flags);
+ }
+ }
+
+ /*
+ * Metadata says remove or delete, so don't publish
+ * this key or sign with it.
+ */
+ if ((remset && remove < now) ||
+ (delset && delete < now)) {
+ key->hint_publish = ISC_FALSE;
+ key->hint_sign = ISC_FALSE;
+ key->hint_remove = ISC_TRUE;
+ }
+}
+
+/*%
+ * Get a list of DNSSEC keys from the key repository
+ */
+isc_result_t
+dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory,
+ isc_mem_t *mctx, dns_dnsseckeylist_t *keylist)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_dnsseckeylist_t list;
+ isc_dir_t dir;
+ dns_dnsseckey_t *key = NULL;
+ dst_key_t *dstkey = NULL;
+ char namebuf[DNS_NAME_FORMATSIZE], *p;
+ isc_buffer_t b;
+ unsigned int len;
+
+ REQUIRE(keylist != NULL);
+ ISC_LIST_INIT(list);
+
+ isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1);
+ RETERR(dns_name_totext(origin, ISC_FALSE, &b));
+ len = isc_buffer_usedlength(&b);
+ namebuf[len] = '\0';
+
+ isc_dir_init(&dir);
+ RETERR(isc_dir_open(&dir, directory));
+
+ while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
+ if (dir.entry.name[0] == 'K' &&
+ dir.entry.length > len + 1 &&
+ dir.entry.name[len + 1] == '+' &&
+ strncasecmp(dir.entry.name + 1, namebuf, len) == 0) {
+ p = strrchr(dir.entry.name, '.');
+ if (strcmp(p, ".private") != 0)
+ continue;
+
+ dstkey = NULL;
+ RETERR(dst_key_fromnamedfile(dir.entry.name, directory,
+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
+ mctx, &dstkey));
+
+ RETERR(dns_dnsseckey_create(mctx, &dstkey, &key));
+ key->source = dns_keysource_repository;
+ get_hints(key);
+
+ if (key->legacy) {
+ dns_dnsseckey_destroy(mctx, &key);
+ } else {
+ ISC_LIST_APPEND(list, key, link);
+ key = NULL;
+ }
+ }
+ }
+
+ if (!ISC_LIST_EMPTY(list))
+ ISC_LIST_APPENDLIST(*keylist, list, link);
+ else
+ result = ISC_R_NOTFOUND;
+
+ failure:
+ isc_dir_close(&dir);
+ INSIST(key == NULL);
+ while ((key = ISC_LIST_HEAD(list)) != NULL) {
+ ISC_LIST_UNLINK(list, key, link);
+ INSIST(key->key != NULL);
+ dst_key_free(&key->key);
+ dns_dnsseckey_destroy(mctx, &key);
+ }
+ if (dstkey != NULL)
+ dst_key_free(&dstkey);
+ return (result);
+}
/*
* Principal Author: Brian Wellington
- * $Id: dst_api.c,v 1.22 2009/06/30 23:48:01 tbox Exp $
+ * $Id: dst_api.c,v 1.23 2009/07/19 04:18:05 each Exp $
*/
/*! \file */
static isc_result_t algorithm_status(unsigned int alg);
static isc_result_t addsuffix(char *filename, unsigned int len,
- const char *ofilename, const char *suffix);
+ const char *dirname, const char *ofilename,
+ const char *suffix);
#define RETERR(x) \
do { \
return (result);
key = NULL;
- result = dst_key_fromnamedfile(filename, type, mctx, &key);
+ result = dst_key_fromnamedfile(filename, NULL, type, mctx, &key);
if (result != ISC_R_SUCCESS)
return (result);
}
isc_result_t
-dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx,
- dst_key_t **keyp)
+dst_key_fromnamedfile(const char *filename, const char *dirname,
+ int type, isc_mem_t *mctx, dst_key_t **keyp)
{
isc_result_t result;
dst_key_t *pubkey = NULL, *key = NULL;
REQUIRE(mctx != NULL);
REQUIRE(keyp != NULL && *keyp == NULL);
+ /* If an absolute path is specified, don't use the key directory */
+#ifndef WIN32
+ if (filename[0] == '/')
+ dirname = NULL;
+#else /* WIN32 */
+ if (filename[0] == '/' || filename[0] == '\\')
+ dirname = NULL;
+#endif
+
newfilenamelen = strlen(filename) + 5;
+ if (dirname != NULL)
+ newfilenamelen += strlen(dirname) + 1;
newfilename = isc_mem_get(mctx, newfilenamelen);
if (newfilename == NULL)
return (ISC_R_NOMEMORY);
- result = addsuffix(newfilename, newfilenamelen, filename, ".key");
+ result = addsuffix(newfilename, newfilenamelen,
+ dirname, filename, ".key");
INSIST(result == ISC_R_SUCCESS);
result = dst_key_read_public(newfilename, type, mctx, &pubkey);
RETERR(DST_R_UNSUPPORTEDALG);
newfilenamelen = strlen(filename) + 9;
+ if (dirname != NULL)
+ newfilenamelen += strlen(dirname) + 1;
newfilename = isc_mem_get(mctx, newfilenamelen);
if (newfilename == NULL)
RETERR(ISC_R_NOMEMORY);
- result = addsuffix(newfilename, newfilenamelen, filename, ".private");
+ result = addsuffix(newfilename, newfilenamelen,
+ dirname, filename, ".private");
INSIST(result == ISC_R_SUCCESS);
RETERR(isc_lex_create(mctx, 1500, &lex));
return (ISC_R_SUCCESS);
}
+isc_result_t
+dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) {
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(timep != NULL);
+ REQUIRE(type <= DST_MAX_TIMES);
+ if (key->times[type] == 0)
+ return (ISC_R_NOTFOUND);
+ *timep = key->times[type];
+ return (ISC_R_SUCCESS);
+}
+
+void
+dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) {
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(type <= DST_MAX_TIMES);
+ key->times[type] = when;
+}
+
isc_boolean_t
dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
REQUIRE(dst_initialized == ISC_TRUE);
key->key_alg = alg;
key->key_flags = flags;
key->key_proto = protocol;
+ memset(key->times, 0, sizeof(key->times));
key->mctx = mctx;
key->keydata.generic = NULL;
key->key_size = bits;
}
}
+/*%
+ * Write key timing metadata to a file pointer, preceded by 'tag'
+ */
+static void
+printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) {
+ isc_result_t result;
+ isc_stdtime_t when;
+ const char *output;
+
+ result = dst_key_gettime(key, type, &when);
+ if (result == ISC_R_NOTFOUND)
+ return;
+
+ output = ctime((time_t *) &when);
+ fprintf(stream, "%s: %s", tag, output);
+}
+
/*%
* Writes a public key to disk in DNS format.
*/
(void)isc_fsaccess_set(filename, access);
}
- ret = dns_name_print(key->key_name, fp);
- if (ret != ISC_R_SUCCESS) {
- fclose(fp);
- return (ret);
+ /* Write key information in comments */
+ if ((type & DST_TYPE_KEY) == 0) {
+ fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ",
+ (key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ?
+ "revoked " :
+ "",
+ (key->key_flags & DNS_KEYFLAG_KSK) != 0 ?
+ "key" :
+ "zone",
+ key->key_id);
+ ret = dns_name_print(key->key_name, fp);
+ if (ret != ISC_R_SUCCESS) {
+ fclose(fp);
+ return (ret);
+ }
+ fputc('\n', fp);
+
+ printtime(key, DST_TIME_CREATED, "; Created", fp);
+ printtime(key, DST_TIME_PUBLISH, "; Publish", fp);
+ printtime(key, DST_TIME_ACTIVATE, "; Activate", fp);
+ printtime(key, DST_TIME_REVOKE, "; Revoke", fp);
+ printtime(key, DST_TIME_REMOVE, "; Remove", fp);
+ printtime(key, DST_TIME_DELETE, "; Delete", fp);
}
+ /* Now print the actual key */
+ ret = dns_name_print(key->key_name, fp);
+
fprintf(fp, " ");
isc_buffer_usedregion(&classb, &r);
}
static isc_result_t
-addsuffix(char *filename, unsigned int len, const char *ofilename,
- const char *suffix)
+addsuffix(char *filename, unsigned int len, const char *odirname,
+ const char *ofilename, const char *suffix)
{
int olen = strlen(ofilename);
int n;
else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0)
olen -= 4;
- n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix);
+ if (odirname == NULL)
+ n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix);
+ else
+ n = snprintf(filename, len, "%s/%.*s%s",
+ odirname, olen, ofilename, suffix);
if (n < 0)
return (ISC_R_NOSPACE);
return (ISC_R_SUCCESS);
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst_internal.h,v 1.14 2009/06/30 02:52:32 each Exp $ */
+/* $Id: dst_internal.h,v 1.15 2009/07/19 04:18:05 each Exp $ */
#ifndef DST_DST_INTERNAL_H
#define DST_DST_INTERNAL_H 1
#include <isc/types.h>
#include <isc/md5.h>
#include <isc/sha1.h>
+#include <isc/stdtime.h>
#include <isc/hmacmd5.h>
#include <isc/hmacsha.h>
+#include <dns/time.h>
+
#include <dst/dst.h>
#ifdef OPENSSL
dst_hmacsha512_key_t *hmacsha512;
} keydata; /*%< pointer to key in crypto pkg fmt */
- dst_func_t * func; /*%< crypto package specific functions*/
+
+ isc_stdtime_t times[DST_MAX_TIMES + 1]; /*%< key timing metadata */
+ dst_func_t * func; /*%< crypto package specific functions */
};
struct dst_context {
/*%
* Principal Author: Brian Wellington
- * $Id: dst_parse.c,v 1.17 2009/06/17 06:51:44 each Exp $
+ * $Id: dst_parse.c,v 1.18 2009/07/19 04:18:05 each Exp $
*/
#include <config.h>
#include <isc/fsaccess.h>
#include <isc/lex.h>
#include <isc/mem.h>
+#include <isc/stdtime.h>
#include <isc/string.h>
#include <isc/util.h>
+#include <dns/time.h>
+
#include "dst_internal.h"
#include "dst_parse.h"
#include "dst/result.h"
#define PRIVATE_KEY_STR "Private-key-format:"
#define ALGORITHM_STR "Algorithm:"
+#define METADATA_NTAGS 6
+static const char *metatags[METADATA_NTAGS] = {
+ "Created:",
+ "Publish:",
+ "Activate:",
+ "Revoke:",
+ "Remove:",
+ "Delete:"
+};
+
struct parse_map {
const int value;
const char *tag;
find_value(const char *s, const unsigned int alg) {
int i;
- for (i = 0; ; i++) {
- if (map[i].tag == NULL)
- return (-1);
- else if (strcasecmp(s, map[i].tag) == 0 &&
- TAG_ALG(map[i].value) == alg)
+ for (i = 0; map[i].tag != NULL; i++) {
+ if (strcasecmp(s, map[i].tag) == 0 &&
+ (TAG_ALG(map[i].value) == alg))
return (map[i].value);
}
+ return (-1);
}
+static int
+find_metadata(const char *s) {
+ int i;
+
+ for (i = 0; i < METADATA_NTAGS; i++) {
+ if (strcasecmp(s, metatags[i]) == 0)
+ return (i);
+ }
+
+ return (-1);
+}
+
static const char *
find_tag(const int value) {
int i;
isc_token_t token;
unsigned char *data = NULL;
unsigned int opt = ISC_LEXOPT_EOL;
+ isc_stdtime_t when;
isc_result_t ret;
REQUIRE(priv != NULL);
for (n = 0; n < MAXFIELDS; n++) {
int tag;
isc_region_t r;
-
do {
ret = isc_lex_gettoken(lex, opt, &token);
if (ret == ISC_R_EOF)
goto fail;
}
+ /* Key timing metadata */
+ tag = find_metadata(DST_AS_STR(token));
+ if (tag >= 0) {
+ INSIST(tag < METADATA_NTAGS);
+
+ NEXTTOKEN(lex, opt, &token);
+ if (token.type != isc_tokentype_string) {
+ ret = DST_R_INVALIDPRIVATEKEY;
+ goto fail;
+ }
+
+ ret = dns_time32_fromtext(DST_AS_STR(token), &when);
+ if (ret != ISC_R_SUCCESS)
+ goto fail;
+
+ dst_key_settime(key, tag, when);
+
+ goto next;
+ }
+
+ /* Key data */
tag = find_value(DST_AS_STR(token), alg);
- if (tag < 0 || TAG_ALG(tag) != alg) {
+ if (tag < 0) {
ret = DST_R_INVALIDPRIVATEKEY;
goto fail;
}
isc_buffer_usedregion(&b, &r);
priv->elements[n].length = r.length;
priv->elements[n].data = r.base;
+ priv->nelements++;
+ next:
READLINE(lex, opt, &token);
data = NULL;
}
done:
- priv->nelements = n;
-
if (check_data(priv, alg, ISC_TRUE) < 0)
goto fail;
return (ISC_R_SUCCESS);
fail:
- priv->nelements = n;
dst__privstruct_free(priv, mctx);
if (data != NULL)
isc_mem_put(mctx, data, MAXFIELDSIZE);
{
FILE *fp;
int ret, i;
- isc_result_t iret;
+ isc_result_t result;
char filename[ISC_DIR_NAMEMAX];
char buffer[MAXFIELDSIZE * 2];
- isc_buffer_t b;
isc_fsaccess_t access;
+ isc_stdtime_t when;
+ isc_buffer_t b;
+ isc_region_t r;
REQUIRE(priv != NULL);
case DST_ALG_RSASHA1:
fprintf(fp, "(RSASHA1)\n");
break;
+ case DST_ALG_NSEC3RSASHA1:
+ fprintf(fp, "(NSEC3RSASHA1)\n");
+ break;
+ case DST_ALG_NSEC3DSA:
+ fprintf(fp, "(NSEC3DSA)\n");
+ break;
case DST_ALG_HMACMD5:
fprintf(fp, "(HMAC_MD5)\n");
break;
case DST_ALG_HMACSHA512:
fprintf(fp, "(HMAC_SHA512)\n");
break;
- case DST_ALG_NSEC3DSA:
- fprintf(fp, "(NSEC3DSA)\n");
- break;
- case DST_ALG_NSEC3RSASHA1:
- fprintf(fp, "(NSEC3RSASHA1)\n");
- break;
default:
fprintf(fp, "(?)\n");
break;
}
for (i = 0; i < priv->nelements; i++) {
- isc_buffer_t b;
- isc_region_t r;
const char *s;
s = find_tag(priv->elements[i].tag);
r.base = priv->elements[i].data;
r.length = priv->elements[i].length;
isc_buffer_init(&b, buffer, sizeof(buffer));
- iret = isc_base64_totext(&r, sizeof(buffer), "", &b);
- if (iret != ISC_R_SUCCESS) {
+ result = isc_base64_totext(&r, sizeof(buffer), "", &b);
+ if (result != ISC_R_SUCCESS) {
fclose(fp);
return (DST_R_INVALIDPRIVATEKEY);
}
fprintf(fp, "\n");
}
+ /* Add the timing metadata tags */
+ for (i = 0; i < METADATA_NTAGS; i++) {
+ result = dst_key_gettime(key, i, &when);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ isc_buffer_init(&b, buffer, sizeof(buffer));
+ result = dns_time32_totext(when, &b);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ isc_buffer_usedregion(&b, &r);
+
+ fprintf(fp, "%s ", metatags[i]);
+ fwrite(r.base, 1, r.length, fp);
+ fprintf(fp, "\n");
+ }
+
fflush(fp);
- iret = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS;
+ result = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS;
fclose(fp);
- return (iret);
+ return (result);
}
/*! \file */
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst_parse.h,v 1.11 2008/05/15 00:50:26 each Exp $ */
+/* $Id: dst_parse.h,v 1.12 2009/07/19 04:18:05 each Exp $ */
/*! \file */
#ifndef DST_DST_PARSE_H
#include <dst/dst.h>
#define MAJOR_VERSION 1
-#define MINOR_VERSION 2
+#define MINOR_VERSION 3
#define MAXFIELDSIZE 512
-#define MAXFIELDS 12
+
+/*
+ * Maximum number of fields in a private file is 18 (12 algorithm-
+ * specific fields for RSA, plus 6 generic fields).
+ */
+#define MAXFIELDS 12+6
#define TAG_SHIFT 4
#define TAG_ALG(tag) ((unsigned int)(tag) >> TAG_SHIFT)
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: db.h,v 1.98 2009/06/30 02:52:32 each Exp $ */
+/* $Id: db.h,v 1.99 2009/07/19 04:18:05 each Exp $ */
#ifndef DNS_DB_H
#define DNS_DB_H 1
isc_result_t
dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format);
+
+isc_result_t
+dns_db_load3(dns_db_t *db, const char *filename, dns_masterformat_t format,
+ unsigned int options);
/*%<
* Load master file 'filename' into 'db'.
*
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dnssec.h,v 1.34 2009/06/04 02:56:47 tbox Exp $ */
+/* $Id: dnssec.h,v 1.35 2009/07/19 04:18:05 each Exp $ */
#ifndef DNS_DNSSEC_H
#define DNS_DNSSEC_H 1
ISC_LANG_BEGINDECLS
+/*
+ * Indicates how the signer found this key: in the key repository, at the
+ * zone apex, or specified by the user.
+ */
+typedef enum {
+ dns_keysource_unknown,
+ dns_keysource_repository,
+ dns_keysource_zoneapex,
+ dns_keysource_user
+} dns_keysource_t;
+
+/*
+ * A DNSSEC key and hints about its intended use gleaned from metadata
+ */
+struct dns_dnsseckey {
+ dst_key_t *key;
+ isc_boolean_t hint_publish; /*% metadata says to publish */
+ isc_boolean_t force_publish; /*% publish regardless of metadata */
+ isc_boolean_t hint_sign; /*% metadata says to sign with this key */
+ isc_boolean_t force_sign; /*% sign with key regardless of metadata */
+ isc_boolean_t hint_remove; /*% metadata says *don't* publish */
+ dns_keysource_t source; /*% how the key was found */
+ isc_boolean_t ksk; /*% this is a key-signing key */
+ isc_boolean_t legacy; /*% this is old-style key with no
+ metadata (possibly generated by
+ an older version of BIND9) and
+ should be ignored when searching
+ for keys to import into the zone */
+ unsigned int index; /*% position in list */
+ ISC_LINK(dns_dnsseckey_t) link;
+};
+
isc_result_t
dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx,
dst_key_t **key);
isc_boolean_t ignoretime, isc_mem_t *mctx);
+isc_result_t
+dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey,
+ dns_dnsseckey_t **dkp);
+/*%<
+ * Create and initialize a dns_dnsseckey_t structure.
+ *
+ * Requires:
+ *\li 'dkp' is not NULL and '*dkp' is NULL.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+void
+dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp);
+/*%<
+ * Reclaim a dns_dnsseckey_t structure.
+ *
+ * Requires:
+ *\li 'dkp' is not NULL and '*dkp' is not NULL.
+ *
+ * Ensures:
+ *\li '*dkp' is NULL.
+ */
+
+isc_result_t
+dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory,
+ isc_mem_t *mctx, dns_dnsseckeylist_t *keylist);
+/*%<
+ * Search 'directory' for K* key files matching the name in 'origin'.
+ * Append all such keys, along with use hints gleaned from their
+ * metadata, onto 'keylist'.
+ *
+ * Requires:
+ *\li 'keylist' is not NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOTFOUND
+ *\li #ISC_R_NOMEMORY
+ *\li any error returned by dns_name_totext(), isc_dir_open(), or
+ * dst_key_fromnamedfile()
+ *
+ * Ensures:
+ *\li On error, keylist is unchanged
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_DNSSEC_H */
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: types.h,v 1.134 2009/06/30 02:52:32 each Exp $ */
+/* $Id: types.h,v 1.135 2009/07/19 04:18:05 each Exp $ */
#ifndef DNS_TYPES_H
#define DNS_TYPES_H 1
typedef struct dns_dispatchlist dns_dispatchlist_t;
typedef struct dns_dispatchmgr dns_dispatchmgr_t;
typedef struct dns_dispentry dns_dispentry_t;
+typedef struct dns_dnsseckey dns_dnsseckey_t;
+typedef ISC_LIST(dns_dnsseckey_t) dns_dnsseckeylist_t;
typedef struct dns_dumpctx dns_dumpctx_t;
typedef struct dns_fetch dns_fetch_t;
typedef struct dns_fixedname dns_fixedname_t;
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst.h,v 1.15 2009/06/30 02:52:32 each Exp $ */
+/* $Id: dst.h,v 1.16 2009/07/19 04:18:05 each Exp $ */
#ifndef DST_DST_H
#define DST_DST_H 1
/*! \file dst/dst.h */
#include <isc/lang.h>
+#include <isc/stdtime.h>
#include <dns/types.h>
#define DST_TYPE_PRIVATE 0x2000000
#define DST_TYPE_PUBLIC 0x4000000
+/* Key timing metadata definitions */
+#define DST_TIME_CREATED 0
+#define DST_TIME_PUBLISH 1
+#define DST_TIME_ACTIVATE 2
+#define DST_TIME_REVOKE 3
+#define DST_TIME_REMOVE 4
+#define DST_TIME_DELETE 5
+#define DST_MAX_TIMES 5
+
/***
*** Functions
***/
*/
isc_result_t
-dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx,
- dst_key_t **keyp);
+dst_key_fromnamedfile(const char *filename, const char *dirname,
+ int type, isc_mem_t *mctx, dst_key_t **keyp);
/*%<
* Reads a key from permanent storage. The key can either be a public or
* key, and is specified by filename. If a private key is specified, the
* public key must also be present.
*
+ * If 'dirname' is not NULL, and 'filename' is a relative path,
+ * then the file is looked up relative to the given directory.
+ * If 'filename' is an absolute path, 'dirname' is ignored.
+ *
* Requires:
* \li "filename" is not NULL
* \li "type" is DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or the bitwise union
isc_uint16_t
dst_key_getbits(const dst_key_t *key);
-/*
+/*%<
* Get the number of digest bits required (0 == MAX).
*
* Requires:
void
dst_key_setbits(dst_key_t *key, isc_uint16_t bits);
-/*
+/*%<
* Set the number of digest bits required (0 == MAX).
*
* Requires:
* "key" is a valid key.
*/
+isc_result_t
+dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep);
+/*%<
+ * Get a member of the timing metadata array and place it in '*timep'.
+ *
+ * Requires:
+ * "key" is a valid key.
+ * "type" is no larger than DST_MAX_TIMES
+ * "timep" is not null.
+ */
+
+void
+dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when);
+/*%<
+ * Set a member of the timing metadata array.
+ *
+ * Requires:
+ * "key" is a valid key.
+ * "type" is no larger than DST_MAX_TIMES
+ */
+
ISC_LANG_ENDDECLS
#endif /* DST_DST_H */
/*
* Principal Author: Brian Wellington
- * $Id: opensslrsa_link.c,v 1.23 2009/01/17 14:41:43 fdupont Exp $
+ * $Id: opensslrsa_link.c,v 1.24 2009/07/19 04:18:05 each Exp $
*/
#ifdef OPENSSL
#ifndef USE_EVP
i++;
}
+
priv.nelements = i;
- result = dst__privstruct_writefile(key, &priv, directory);
+ result = dst__privstruct_writefile(key, &priv, directory);
fail:
#if USE_EVP
RSA_free(rsa);
-# $Id: version,v 1.45 2009/06/12 02:33:21 each Exp $
+# $Id: version,v 1.46 2009/07/19 04:18:03 each Exp $
#
# This file must follow /bin/sh rules. It is imported directly via
# configure.
MINORVER=7
PATCHVER=0
RELEASETYPE=a
-RELEASEVER=1
+RELEASEVER=2