]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2636. [func] Simplify zone signing and key maintenance with the
authorEvan Hunt <each@isc.org>
Sun, 19 Jul 2009 04:18:05 +0000 (04:18 +0000)
committerEvan Hunt <each@isc.org>
Sun, 19 Jul 2009 04:18:05 +0000 (04:18 +0000)
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]

39 files changed:
CHANGES
README
bin/dig/dighost.c
bin/dnssec/Makefile.in
bin/dnssec/dnssec-dsfromkey.c
bin/dnssec/dnssec-dsfromkey.docbook
bin/dnssec/dnssec-keyfromlabel.c
bin/dnssec/dnssec-keyfromlabel.docbook
bin/dnssec/dnssec-keygen.c
bin/dnssec/dnssec-keygen.docbook
bin/dnssec/dnssec-revoke.c
bin/dnssec/dnssec-revoke.docbook
bin/dnssec/dnssec-settime.8 [new file with mode: 0644]
bin/dnssec/dnssec-settime.c [new file with mode: 0644]
bin/dnssec/dnssec-settime.docbook [new file with mode: 0644]
bin/dnssec/dnssec-settime.html [new file with mode: 0644]
bin/dnssec/dnssec-signzone.c
bin/dnssec/dnssec-signzone.docbook
bin/dnssec/dnssectool.c
bin/nsupdate/nsupdate.c
bin/tests/system/dnssec/ns1/sign.sh
bin/tests/system/dnssec/ns2/sign.sh
bin/tests/system/tkey/keycreate.c
bin/tests/system/tkey/keydelete.c
bin/tests/system/tkey/ns1/setup.sh
bin/tests/system/tkey/tests.sh
doc/arm/Bv9ARM-book.xml
lib/dns/db.c
lib/dns/dnssec.c
lib/dns/dst_api.c
lib/dns/dst_internal.h
lib/dns/dst_parse.c
lib/dns/dst_parse.h
lib/dns/include/dns/db.h
lib/dns/include/dns/dnssec.h
lib/dns/include/dns/types.h
lib/dns/include/dst/dst.h
lib/dns/opensslrsa_link.c
version

diff --git a/CHANGES b/CHANGES
index e4f611b7403f266390d8d1a854d9680fe668d1e6..a1f785ff960db4aa4c7602993f70f8904d00dfa2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,21 @@
+       --- 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]
 
diff --git a/README b/README
index a613a31bbd1d24148a041d82b3c780dcadfed4d5..51dd578120f192cc7eff8e43e4f8e909888b9305 100644 (file)
--- a/README
+++ b/README
@@ -44,28 +44,34 @@ BIND 9
 
 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
 
index 295a0f3b63637982f59ecfcbcc1111476f82fc89..271f806e4979651818677286101f880e7e452c70 100644 (file)
@@ -15,7 +15,7 @@
  * 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
@@ -948,8 +948,9 @@ setup_file_key(void) {
        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));
@@ -4051,7 +4052,7 @@ get_trusted_key(isc_mem_t *mctx)
                        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);
index 92072811064d29d2a64aa532f3795a8ad47c11ac..af6f3a556f8497b28daf44a79b28d880c9e503fa 100644 (file)
@@ -13,7 +13,7 @@
 # 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@
@@ -41,18 +41,19 @@ LIBS =              ${DNSLIBS} ${ISCLIBS} @LIBS@
 # 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}
 
@@ -82,6 +83,10 @@ dnssec-revoke@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS}
        ${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::
index a92b742443a92743127e4748c03a61f4ad0eaafa..c00f9860d9937a346eabb17ae8447e56d7ed16ff 100644 (file)
@@ -14,7 +14,7 @@
  * 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 */
 
@@ -36,6 +36,8 @@
 #include <dns/ds.h>
 #include <dns/fixedname.h>
 #include <dns/log.h>
+#include <dns/keyvalues.h>
+#include <dns/master.h>
 #include <dns/name.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
 
 #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);
@@ -111,11 +99,49 @@ loadkeys(char *dirname, char *setname)
                fatal("can't find %s node in %s", setname, filename);
 
        result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey,
-                                    0, 0, &keyset, NULL);
+                                    0, 0, rdataset, NULL);
+
        if (result == ISC_R_NOTFOUND)
                fatal("no DNSKEY RR for %s in %s", setname, filename);
        else if (result != ISC_R_SUCCESS)
                fatal("dns_db_findrdataset");
+
+       if (node != NULL)
+               dns_db_detachnode(db, &node);
+       if (db != NULL)
+               dns_db_detach(&db);
+       return (result);
+}
+
+static isc_result_t
+loadkeyset(char *dirname, dns_rdataset_t *rdataset) {
+       isc_result_t     result;
+       char             filename[PATH_MAX + 1];
+       isc_buffer_t     buf;
+
+       dns_rdataset_init(rdataset);
+
+       isc_buffer_init(&buf, filename, sizeof(filename));
+       if (dirname != NULL) {
+               /* allow room for a trailing slash */
+               if (strlen(dirname) >= isc_buffer_availablelength(&buf))
+                       return (ISC_R_NOSPACE);
+               isc_buffer_putstr(&buf, dirname);
+               if (dirname[strlen(dirname) - 1] != '/')
+                       isc_buffer_putstr(&buf, "/");
+       }
+
+       if (isc_buffer_availablelength(&buf) < 7)
+               return (ISC_R_NOSPACE);
+       isc_buffer_putstr(&buf, "keyset-");
+
+       result = dns_name_tofilenametext(name, ISC_FALSE, &buf);
+       check_result(result, "dns_name_tofilenametext()");
+       if (isc_buffer_availablelength(&buf) == 0)
+               return (ISC_R_NOSPACE);
+       isc_buffer_putuint8(&buf, 0);
+
+       return (loadsetfromfile(filename, rdataset));
 }
 
 static void
@@ -127,12 +153,12 @@ loadkey(char *filename, unsigned char *key_buf, unsigned int key_buf_size,
        isc_buffer_t  keyb;
        isc_region_t  r;
 
-       dns_rdataset_init(&keyset);
        dns_rdata_init(rdata);
 
        isc_buffer_init(&keyb, key_buf, key_buf_size);
 
-       result = dst_key_fromnamedfile(filename, DST_TYPE_PUBLIC, mctx, &key);
+       result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC,
+                                      mctx, &key);
        if (result != ISC_R_SUCCESS)
                fatal("invalid keyfile name %s: %s",
                      filename, isc_result_totext(result));
@@ -184,16 +210,18 @@ logkey(dns_rdata_t *rdata)
 }
 
 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));
@@ -201,6 +229,13 @@ emit(unsigned int dtype, dns_rdata_t *rdata, char *lookaside)
 
        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");
@@ -250,20 +285,26 @@ emit(unsigned int dtype, dns_rdata_t *rdata, char *lookaside)
 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);
@@ -271,16 +312,19 @@ usage(void) {
 
 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);
@@ -297,7 +341,7 @@ main(int argc, char **argv) {
        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;
@@ -307,6 +351,9 @@ main(int argc, char **argv) {
                        dtype = DNS_DSDIGEST_SHA256;
                        both = ISC_FALSE;
                        break;
+               case 'A':
+                       showall = ISC_TRUE;
+                       break;
                case 'a':
                        algname = isc_commandline_argument;
                        both = ISC_FALSE;
@@ -315,9 +362,16 @@ main(int argc, char **argv) {
                        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;
@@ -363,7 +417,14 @@ main(int argc, char **argv) {
 
        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");
@@ -381,23 +442,44 @@ main(int argc, char **argv) {
 
        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];
@@ -406,18 +488,14 @@ main(int argc, char **argv) {
                        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();
index bd8f468b4df472d9d1fd06c983feb951183a1a20..7f777b76451b4d96cf435a82d1fcbb68ff51cab9 100644 (file)
@@ -17,7 +17,7 @@
  - 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>
 
index 130bc1f3f0e3218b0db886d089e3526fd31c1d15..02bba62a115735c52edd79ee5716d16b1a965566 100644 (file)
@@ -14,7 +14,7 @@
  * 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 */
 
@@ -65,6 +65,8 @@ usage(void) {
        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");
@@ -82,6 +84,7 @@ usage(void) {
 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;
@@ -113,7 +116,7 @@ main(int argc, char **argv) {
        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':
@@ -132,6 +135,9 @@ main(int argc, char **argv) {
                                fatal("unknown flag '%s'",
                                      isc_commandline_argument);
                        break;
+               case 'K':
+                       directory = isc_commandline_argument;
+                       break;
                case 'k':
                        options |= DST_TYPE_KEY;
                        break;
@@ -299,18 +305,18 @@ main(int argc, char **argv) {
         * 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));
@@ -319,7 +325,7 @@ main(int argc, char **argv) {
        }
 
        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);
 
index 2bcf0a48da4aa6f9dc23bd7afd328eb21062bb54..f7af284dff51223c1847e8aaaae07eeb2330de10 100644 (file)
@@ -17,7 +17,7 @@
  - 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>
@@ -49,6 +49,7 @@
       <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>
index 546b2c502022abbaa080fc216adf0e8667828c1f..454bce9f8171fa5551b9cd9378bd2b03222cc491 100644 (file)
  * 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"
 
@@ -77,47 +76,71 @@ dsa_size_ok(int size) {
 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);
 }
@@ -130,36 +153,68 @@ main(int argc, char **argv) {
        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;
@@ -168,6 +223,9 @@ main(int argc, char **argv) {
                        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;
@@ -180,11 +238,10 @@ main(int argc, char **argv) {
                        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);
@@ -195,14 +252,18 @@ main(int argc, char **argv) {
                        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);
@@ -210,6 +271,9 @@ main(int argc, char **argv) {
                                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);
@@ -217,8 +281,19 @@ main(int argc, char **argv) {
                                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;
@@ -226,6 +301,29 @@ main(int argc, char **argv) {
                        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 */
@@ -259,8 +357,11 @@ main(int argc, char **argv) {
                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);
@@ -299,6 +400,12 @@ main(int argc, char **argv) {
                        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;
@@ -317,7 +424,7 @@ main(int argc, char **argv) {
 
        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);
@@ -424,11 +531,14 @@ main(int argc, char **argv) {
 
        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)
@@ -507,6 +617,22 @@ main(int argc, char **argv) {
 
                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
@@ -540,7 +666,7 @@ main(int argc, char **argv) {
                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));
index 903da941a760e2691d50c6ab6fc9ee925f04affb..5ba3862ea17d674a65198b0af492fcf16c2116cd 100644 (file)
@@ -18,7 +18,7 @@
  - 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>
@@ -79,7 +88,8 @@
     <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>
index 7da15b037c5570809032b8d14567ae2aceccb719..a1bef44cd7f5e6953427c3259ada0ba017e2523f 100644 (file)
@@ -14,7 +14,7 @@
  * 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 */
 
@@ -50,8 +50,8 @@ usage(void) {
        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");
@@ -89,14 +89,14 @@ main(int argc, char **argv) {
 
        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;
@@ -163,7 +163,7 @@ main(int argc, char **argv) {
                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)
index c8c58c725ebf810707aa7cf3fee32e6fd792238d..2d01c561be2ed6abe1ee2a21ed0f888d50ece824 100644 (file)
@@ -17,7 +17,7 @@
  - 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>
@@ -46,7 +46,7 @@
       <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>
@@ -75,7 +75,7 @@
       </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.
diff --git a/bin/dnssec/dnssec-settime.8 b/bin/dnssec/dnssec-settime.8
new file mode 100644 (file)
index 0000000..70383ee
--- /dev/null
@@ -0,0 +1,84 @@
+.\" 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 
diff --git a/bin/dnssec/dnssec-settime.c b/bin/dnssec/dnssec-settime.c
new file mode 100644 (file)
index 0000000..1a3b441
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * 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);
+}
diff --git a/bin/dnssec/dnssec-settime.docbook b/bin/dnssec/dnssec-settime.docbook
new file mode 100644 (file)
index 0000000..7e0142e
--- /dev/null
@@ -0,0 +1,228 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+               [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 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:
+-->
diff --git a/bin/dnssec/dnssec-settime.html b/bin/dnssec/dnssec-settime.html
new file mode 100644 (file)
index 0000000..19ccf41
--- /dev/null
@@ -0,0 +1,140 @@
+<!--
+ - 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> &#8212; 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>
index 1dc2891b402d87db04d33a7f98c7da5a983fee12..17975dd5982e1ed79f9abd71d9ccbde8aa527f91 100644 (file)
@@ -29,7 +29,7 @@
  * 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 */
 
@@ -100,19 +100,6 @@ static int nsec_datatype = dns_rdatatype_nsec;
 #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)
@@ -128,7 +115,7 @@ struct signer_event {
        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;
@@ -138,7 +125,7 @@ static isc_boolean_t tryverify = ISC_FALSE;
 static isc_boolean_t printstats = ISC_FALSE;
 static isc_mem_t *mctx = NULL;
 static isc_entropy_t *ectx = NULL;
-static dns_ttl_t zonettl;
+static dns_ttl_t zone_soa_min_ttl;
 static FILE *fp;
 static char *tempfile = NULL;
 static const dns_master_style_t *masterstyle;
@@ -146,7 +133,7 @@ static dns_masterformat_t inputformat = dns_masterformat_text;
 static dns_masterformat_t outputformat = dns_masterformat_text;
 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
 static unsigned int nverified = 0, nverifyfailed = 0;
-static const char *directory;
+static 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 */
@@ -161,7 +148,7 @@ static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
 static isc_boolean_t nokeys = ISC_FALSE;
 static isc_boolean_t removefile = ISC_FALSE;
 static isc_boolean_t generateds = ISC_FALSE;
-static isc_boolean_t ignoreksk = ISC_FALSE;
+static 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;
@@ -169,6 +156,7 @@ static unsigned int serialformat = SOA_SERIAL_KEEP;
 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) {               \
@@ -194,40 +182,19 @@ dumpnode(dns_name_t *name, dns_dbnode_t *node) {
        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];
@@ -251,23 +218,35 @@ signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdata_t *rdata,
 }
 
 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) {
@@ -284,11 +263,11 @@ keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
  * 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);
@@ -304,7 +283,6 @@ keythatsigned(dns_rdata_rrsig_t *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);
@@ -313,7 +291,7 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) {
 
        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);
@@ -322,12 +300,17 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) {
        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);
@@ -366,7 +349,7 @@ expecttofindkey(dns_name_t *name) {
 }
 
 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;
@@ -392,7 +375,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
        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;
@@ -478,15 +461,14 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
                        {
                                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)) {
@@ -494,15 +476,14 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
                        {
                                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);
@@ -512,7 +493,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
                }
 
                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);
@@ -543,19 +524,15 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
                }
 
                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,
@@ -579,33 +556,29 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
             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));
@@ -779,16 +752,21 @@ static void
 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()");
@@ -803,13 +781,15 @@ opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
                               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) {
@@ -823,15 +803,31 @@ 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);
@@ -840,12 +836,10 @@ loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
                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);
@@ -874,6 +868,7 @@ loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
                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);
@@ -1129,10 +1124,10 @@ active_node(dns_dbnode_t *node) {
 }
 
 /*%
- * 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;
@@ -1932,6 +1927,7 @@ add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
                                               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,
@@ -2015,7 +2011,7 @@ nsecify(void) {
                        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);
        }
@@ -2452,7 +2448,7 @@ nsec3ify(unsigned int hashalg, unsigned int iterations,
                 */
                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.
@@ -2463,7 +2459,7 @@ nsec3ify(unsigned int hashalg, unsigned int iterations,
                        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);
@@ -2512,6 +2508,7 @@ loadzonekeys(dns_db_t *db) {
        isc_result_t result;
        dst_key_t *keys[20];
        unsigned int nkeys, i;
+       dns_rdataset_t rdataset;
 
        currentversion = NULL;
        dns_db_currentversion(db, &currentversion);
@@ -2522,20 +2519,41 @@ loadzonekeys(dns_db_t *db) {
                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, &currentversion, ISC_FALSE);
 }
@@ -2550,7 +2568,6 @@ loadzonepubkeys(dns_db_t *db) {
        dns_rdataset_t rdataset;
        dns_rdata_t rdata = DNS_RDATA_INIT;
        dst_key_t *pubkey;
-       signer_key_t *key;
        isc_result_t result;
 
        dns_db_currentversion(db, &currentversion);
@@ -2562,13 +2579,18 @@ loadzonepubkeys(dns_db_t *db) {
 
        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);
@@ -2581,14 +2603,188 @@ loadzonepubkeys(dns_db_t *db) {
                        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, &currentversion, 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, &currentversion, 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
@@ -2610,7 +2806,8 @@ warnifallksk(dns_db_t *db) {
 
        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));
@@ -2631,14 +2828,14 @@ warnifallksk(dns_db_t *db) {
        dns_rdataset_disassociate(&rdataset);
        dns_db_detachnode(db, &node);
        dns_db_closeversion(db, &currentversion, 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'.");
        }
 }
 
@@ -2659,7 +2856,7 @@ writeset(const char *prefix, dns_rdatatype_t type) {
        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;
@@ -2671,13 +2868,13 @@ writeset(const char *prefix, dns_rdatatype_t type) {
        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);
@@ -2688,7 +2885,7 @@ writeset(const char *prefix, dns_rdatatype_t type) {
        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;
                }
@@ -2696,7 +2893,7 @@ writeset(const char *prefix, dns_rdatatype_t type) {
        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;
                }
@@ -2719,7 +2916,7 @@ writeset(const char *prefix, dns_rdatatype_t type) {
             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);
@@ -2752,7 +2949,7 @@ writeset(const char *prefix, dns_rdatatype_t type) {
 
                } 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);
@@ -2807,11 +3004,16 @@ usage(void) {
        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");
@@ -2838,12 +3040,16 @@ usage(void) {
        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");
@@ -2903,7 +3109,7 @@ main(int argc, char *argv[]) {
        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;
@@ -2919,8 +3125,10 @@ main(int argc, char *argv[]) {
        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.
@@ -2987,11 +3195,21 @@ main(int argc, char *argv[]) {
                        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;
 
@@ -3096,9 +3314,15 @@ main(int argc, char *argv[]) {
                        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':
@@ -3117,7 +3341,7 @@ main(int argc, char *argv[]) {
                        break;
 
                case 'z':
-                       ignoreksk = ISC_TRUE;
+                       ignore_kskflag = ISC_TRUE;
                        break;
 
                case 'F':
@@ -3153,14 +3377,18 @@ main(int argc, char *argv[]) {
 
        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)
@@ -3172,6 +3400,9 @@ main(int argc, char *argv[]) {
 
        rdclass = strtoclass(classname);
 
+       if (directory == NULL)
+               directory = ".";
+
        setup_logging(verbose, mctx, &log);
 
        argc -= isc_commandline_index;
@@ -3236,7 +3467,7 @@ main(int argc, char *argv[]) {
        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;
@@ -3263,7 +3494,7 @@ main(int argc, char *argv[]) {
                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);
@@ -3291,8 +3522,10 @@ main(int argc, char *argv[]) {
                                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);
@@ -3304,7 +3537,7 @@ main(int argc, char *argv[]) {
        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);
@@ -3324,9 +3557,10 @@ main(int argc, char *argv[]) {
                                           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;
@@ -3335,17 +3569,34 @@ main(int argc, char *argv[]) {
                }
                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;
@@ -3386,8 +3637,9 @@ main(int argc, char *argv[]) {
                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);
                }
@@ -3492,8 +3744,7 @@ main(int argc, char *argv[]) {
        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);
index 1d6ba01cb91921baef14b0431e09b07d5478cf34..d22fd6c0f9fc59300c3115d67b6d5143df8dd0ed 100644 (file)
@@ -18,7 +18,7 @@
  - 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>
@@ -64,6 +64,7 @@
       <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>
@@ -75,7 +76,9 @@
       <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>
index bd1467a72e1e7c7e2961bbc856ff04fc62337319..14d888f25f199948f9de51e2c16d6d8392d79506 100644 (file)
@@ -15,7 +15,7 @@
  * 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 */
 
@@ -265,32 +265,66 @@ cleanup_entropy(isc_entropy_t **ectx) {
        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);
index a7990c30e6fb67623333a28e0957fe5bf3593430..27c61742e07887039c7b8ef79be82d8dd29ea32a 100644 (file)
@@ -15,7 +15,7 @@
  * 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 */
 
@@ -626,7 +626,7 @@ setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) {
        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);
 
index a467db9e6e6ac9c41a247e1cf032eb436031c985..410450aecadd46868955b45f3618647bae498514 100644 (file)
@@ -15,7 +15,7 @@
 # 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
@@ -28,8 +28,8 @@ zonefile=root.db
 
 (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`
 
@@ -39,7 +39,7 @@ $SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
 
 # 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
index 4be15df7edad29954864e67b05a82d77a7c2dae6..e9ce8f2e9f95cd51cd7bd78e250fee16cdd5d2ec 100644 (file)
@@ -15,7 +15,7 @@
 # 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
@@ -32,7 +32,7 @@ zonefile=example.db
 
 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`
index 5540866a0e2e05b4f2bb996796255e2dccbb7017..cf4f6ce81c4529380aa7ad6d80e5a5a9039065f5 100644 (file)
@@ -15,7 +15,7 @@
  * 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>
 
@@ -285,7 +285,7 @@ main(int argc, char *argv[]) {
 
        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));
index cb028adc8caa68efb2da5736eec54eb238e3e683..66ac7dd290f7894bc7aebb2dd95b664b38affb9c 100644 (file)
@@ -15,7 +15,7 @@
  * 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>
 
@@ -226,7 +226,7 @@ main(int argc, char **argv) {
 
        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,
index c54e17f1ecf8e5eaaa47ec9ac0f69bbd66d51909..269710a8c2012d7208a25bc72e706c5bab235521 100644 (file)
 # 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
index 199a3b9dae29ba238bbef3317c9a09c26540cfc0..f53b2d2df92c78100074803e02955469454784eb 100644 (file)
@@ -15,7 +15,7 @@
 # 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
@@ -28,7 +28,7 @@ RANDFILE=random.data
 
 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"
index 716914140b1e0b2079a417d416e181e692494c50..6d0cac62b732380c1dcb54f41fe895c09044e624 100644 (file)
@@ -18,7 +18,7 @@
  - 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>
 
@@ -15264,6 +15264,7 @@ zone "example.com" {
       <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"/>
index 58726b8eed0fd6607df33c3838ffeaa3f22f98f2..ed2a06c14b963e6c26c61394521bb9aae5053396 100644 (file)
@@ -15,7 +15,7 @@
  * 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 */
 
@@ -320,14 +320,19 @@ dns_db_endload(dns_db_t *db, dns_dbload_t **dbloadp) {
 
 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'.
index 1bfee7c6d7b0c6a26642157814479cf4314b4d24..e34eb394cde247dddf2c6054877937786b452895 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 /*
- * $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 */
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 
 #include <isc/buffer.h>
+#include <isc/dir.h>
 #include <isc/mem.h>
 #include <isc/serial.h>
 #include <isc/string.h>
@@ -951,3 +952,208 @@ dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name,
        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);
+}
index 96ad88ec2c4f9168c403edfa553150409be4175a..66915338e93acc907229c08375b376c95de42547 100644 (file)
@@ -31,7 +31,7 @@
 
 /*
  * 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 */
@@ -108,7 +108,8 @@ static isc_result_t frombuffer(dns_name_t *name,
 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 {                                    \
@@ -394,7 +395,7 @@ dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
                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);
 
@@ -416,8 +417,8 @@ dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
 }
 
 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;
@@ -432,11 +433,23 @@ dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx,
        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);
@@ -476,10 +489,13 @@ dst_key_fromnamedfile(const char *filename, int type, isc_mem_t *mctx,
                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));
@@ -755,6 +771,24 @@ dst_key_generate(dns_name_t *name, unsigned int alg,
        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);
@@ -933,6 +967,7 @@ get_key_struct(dns_name_t *name, unsigned int alg,
        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;
@@ -1094,6 +1129,23 @@ issymmetric(const dst_key_t *key) {
        }
 }
 
+/*%
+ * 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.
  */
@@ -1153,12 +1205,34 @@ write_public_key(const dst_key_t *key, int type, const char *directory) {
                (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);
@@ -1292,8 +1366,8 @@ algorithm_status(unsigned int alg) {
 }
 
 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;
@@ -1305,7 +1379,11 @@ addsuffix(char *filename, unsigned int len, const char *ofilename,
        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);
index 7ff8d0d98488d4ee340b0f1a2574148836f5f855..6bdd5ed2e66ede985b71f71fa8d3a10c1bd612e0 100644 (file)
@@ -29,7 +29,7 @@
  * 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
@@ -112,7 +115,9 @@ struct dst_key {
                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 {
index 2fe626c561cb3d374f1595d0156e9b1c325c27bb..6fa3eb9f4ddfec7005f69980aa25ff9ca3863a08 100644 (file)
@@ -31,7 +31,7 @@
 
 /*%
  * 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;
@@ -107,15 +120,26 @@ static int
 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;
@@ -294,6 +318,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
        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);
@@ -377,7 +402,6 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
        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)
@@ -391,8 +415,29 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
                        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;
                }
@@ -409,20 +454,19 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
                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);
@@ -436,11 +480,13 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
 {
        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);
 
@@ -480,6 +526,12 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
        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;
@@ -498,20 +550,12 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
        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);
@@ -519,8 +563,8 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
                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);
                }
@@ -531,10 +575,28 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
                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 */
index 27c7580e54beab21809c865b80780ec40432d2d8..effc4c6af499133020996fde94110c33613de771 100644 (file)
@@ -29,7 +29,7 @@
  * 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)
index db396bed7b11f44906c146936a21bc467c4adf81..5e3c214d1e7eb5dd88dc8afef0ddb36fda1db8d5 100644 (file)
@@ -15,7 +15,7 @@
  * 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
@@ -493,6 +493,10 @@ dns_db_load(dns_db_t *db, const char *filename);
 
 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'.
  *
index 09ada3cd2cfb26385d048aa35bf10d8f97dd2161..ea1c916761d843729fc9a2f0b25dafecb92d3903 100644 (file)
@@ -15,7 +15,7 @@
  * 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);
@@ -184,6 +216,54 @@ dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name,
                     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 */
index d6d97b05af44ff9a4b2388be16abc7634369b33b..2e100d317ef8af0beec0703c93b8dc946979f74d 100644 (file)
@@ -15,7 +15,7 @@
  * 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
@@ -63,6 +63,8 @@ typedef struct dns_dispatchevent              dns_dispatchevent_t;
 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;
index b122a6addb35bb8a42eaf8033e65f8627fe320a5..0236248f60d04441de25be20460794229f09f13f 100644 (file)
@@ -15,7 +15,7 @@
  * 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
@@ -23,6 +23,7 @@
 /*! \file dst/dst.h */
 
 #include <isc/lang.h>
+#include <isc/stdtime.h>
 
 #include <dns/types.h>
 
@@ -78,6 +79,15 @@ typedef struct dst_context   dst_context_t;
 #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
  ***/
@@ -242,13 +252,17 @@ dst_key_fromfile(dns_name_t *name, dns_keytag_t id, unsigned int alg, int type,
  */
 
 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
@@ -623,7 +637,7 @@ dst_region_computeid(const isc_region_t *source, unsigned int alg);
 
 isc_uint16_t
 dst_key_getbits(const dst_key_t *key);
-/*
+/*%<
  * Get the number of digest bits required (0 == MAX).
  *
  * Requires:
@@ -632,7 +646,7 @@ dst_key_getbits(const dst_key_t *key);
 
 void
 dst_key_setbits(dst_key_t *key, isc_uint16_t bits);
-/*
+/*%<
  * Set the number of digest bits required (0 == MAX).
  *
  * Requires:
@@ -648,6 +662,27 @@ dst_key_setflags(dst_key_t *key, isc_uint32_t flags);
  *     "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 */
index 8f0733d2a84359ce9894ab3020199fbb97881a88..131b4cb5208ec99a928273a688cd68767bd65e59 100644 (file)
@@ -17,7 +17,7 @@
 
 /*
  * 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
@@ -751,8 +751,9 @@ opensslrsa_tofile(const dst_key_t *key, const char *directory) {
                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);
diff --git a/version b/version
index 8ff4c904dd14c70e99e93627f8dc69124cf3fbf5..80321bfc0fa8cfa9e15cca6a6e74cc2958605c25 100644 (file)
--- a/version
+++ b/version
@@ -1,4 +1,4 @@
-# $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.
@@ -7,4 +7,4 @@ MAJORVER=9
 MINORVER=7
 PATCHVER=0
 RELEASETYPE=a
-RELEASEVER=1
+RELEASEVER=2