]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2619. [func] Add support for RFC 5011, automatic trust anchor
authorEvan Hunt <each@isc.org>
Tue, 30 Jun 2009 02:53:46 +0000 (02:53 +0000)
committerEvan Hunt <each@isc.org>
Tue, 30 Jun 2009 02:53:46 +0000 (02:53 +0000)
maintenance.  The new "managed-keys" statement can
be used in place of "trusted-keys" for zones which
support this protocol.  (Note: this syntax is
expected to change prior to 9.7.0 final.) [RT #19248]

49 files changed:
CHANGES
README.rfc5011 [new file with mode: 0644]
bin/dnssec/Makefile.in
bin/dnssec/dnssec-keyfromlabel.c
bin/dnssec/dnssec-keygen.c
bin/dnssec/dnssec-revoke.8 [new file with mode: 0644]
bin/dnssec/dnssec-revoke.c [new file with mode: 0644]
bin/dnssec/dnssec-revoke.docbook [new file with mode: 0644]
bin/dnssec/dnssec-revoke.html [new file with mode: 0644]
bin/dnssec/win32/revoke.dsp [new file with mode: 0644]
bin/dnssec/win32/revoke.dsw [new file with mode: 0644]
bin/dnssec/win32/revoke.mak [new file with mode: 0644]
bin/named/config.c
bin/named/include/named/server.h
bin/named/server.c
bin/named/xfrout.c
lib/dns/Makefile.in
lib/dns/db.c
lib/dns/dst_api.c
lib/dns/dst_internal.h
lib/dns/include/dns/db.h
lib/dns/include/dns/events.h
lib/dns/include/dns/keydata.h [new file with mode: 0644]
lib/dns/include/dns/keytable.h
lib/dns/include/dns/keyvalues.h
lib/dns/include/dns/master.h
lib/dns/include/dns/name.h
lib/dns/include/dns/rriterator.h [new file with mode: 0644]
lib/dns/include/dns/soa.h
lib/dns/include/dns/types.h
lib/dns/include/dns/view.h
lib/dns/include/dns/zone.h
lib/dns/include/dst/dst.h
lib/dns/keydata.c [new file with mode: 0644]
lib/dns/keytable.c
lib/dns/master.c
lib/dns/rdata/generic/keydata_65533.c [new file with mode: 0644]
lib/dns/rdata/generic/keydata_65533.h [new file with mode: 0644]
lib/dns/rriterator.c [new file with mode: 0644]
lib/dns/soa.c
lib/dns/validator.c
lib/dns/view.c
lib/dns/win32/libdns.def
lib/dns/win32/libdns.dsp
lib/dns/win32/libdns.mak
lib/dns/zone.c
lib/isc/random.c
lib/isccfg/namedconf.c
win32utils/BINDBuild.dsw

diff --git a/CHANGES b/CHANGES
index b3c7cf6e998d479410e68c61fb332d6741219965..d1b23919940beb7ec37574c420f5745505677653 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+2619.  [func]          Add support for RFC 5011, automatic trust anchor
+                       maintenance.  The new "managed-keys" statement can
+                       be used in place of "trusted-keys" for zones which
+                       support this protocol.  (Note: this syntax is
+                       expected to change prior to 9.7.0 final.) [RT #19248]
+
 2618.  [bug]           The sdb and sdlz db_interator_seek() methods could
                        loop infinitely. [RT #19847]
 
diff --git a/README.rfc5011 b/README.rfc5011
new file mode 100644 (file)
index 0000000..e8f07d0
--- /dev/null
@@ -0,0 +1,67 @@
+BIND 9.7.0 introduces support for RFC 5011, dynamic trust anchor
+management.  Using this feature allows named to keep track of changes to
+critical DNSSEC keys without any need for the operator to make changes to
+configuration files.
+
+As of 9.7.0a1, the syntax for using RFC5011 is expected to change, so
+proper documentation has yet to be written.  This file is intended to
+provide enough information to get started.
+
+AUTHORITATIVE SERVER
+--------------------
+
+To set up an authoritative zone for RFC5011 trust anchor maintenance,
+generate two (or more) key signing keys (KSKs) for the zone.  Sign the zone
+with one of them; this is the "active" KSK.  All KSK's which do not sign
+the zone are "stand-by" keys.
+
+Any validating resolver which is configured to use the active KSK as an
+RFC5011-managed trust anchor will take note of the stand-by KSKs in the
+zone's DNSKEY RRset, and store them for future reference.  The resolver
+will recheck the zone periodically, and after 30 days, if the new key is
+still there, then the key will be accepted by the resolver as a valid
+trust anchor for the zone.
+
+At any time after this 30-day acceptance timer has expired, the active
+KSK can be revoked and the zone can be "rolled over" to one of the
+standby KSKs.
+
+To revoke a key, the new command "dnssec-revoke" has been added.  This adds
+the REVOKED bit to the key flags and re-generates the K*.key and K*.private
+files.
+
+After revoking the active key, the zone must be signed with both the
+revoked KSK and the new active KSK.  Once a key has been revoked and
+used to sign the DNSKEY RRset in which it appears, that key will never
+again be accepted as a valid trust anchor by the resolver.  However,
+validation can proceed using the new active key (which had been accepted
+by the resolver when it was a stand-by key).
+
+See RFC 5011 for more details on key rollover scenarios.
+
+VALIDATING RESOLVER
+-------------------
+
+NOTE: This is expected to change before 9.7.0 is final!
+
+To configure a validating resolver to use RFC5011 to maintain a trust
+anchor, configure the trust anchor using a "managed-keys" statement
+instead of a "trusted-keys" statement.
+
+The syntax for "managed-keys" is identical to that for "trusted-keys".
+However, whereas a trusted key is trusted permanently until it is removed
+from named.conf, a managed key is only trusted for as long as it takes to
+initialize RFC5011 key maintenance.
+
+When named loads for the first time with a managed key configured, it
+will fetch the DNSKEY RRset directly from the zone apex and check its
+signature against the key specified in the "managed-keys" statement.
+If it is validly signed, then the DNSKEY RRset is used as the basis for a
+new managed keys database.
+
+From that point on, when named loads, it will see the "managed-keys"
+statement, check to make sure RFC5011 key maintenance has already been
+initialized for the specified zone, and if so, it will simply move on.
+No action will be taken unless a key is *removed* from the "managed-keys"
+statement--in which case that zone is removed from the managed keys
+database as well, and RFC5011 key maintenance will no longer be used.
index d59a38fb114ef5d303f0c4cb883a877095ab1c69..81c4725f98cb8d4dbcac1b863ef81502a923dc98 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.35 2008/11/07 02:28:49 marka Exp $
+# $Id: Makefile.in,v 1.36 2009/06/30 02:52:32 each Exp $
 
 srcdir =       @srcdir@
 VPATH =                @srcdir@
@@ -40,18 +40,19 @@ LIBS =              ${DNSLIBS} ${ISCLIBS} @LIBS@
 
 # Alphabetically
 TARGETS =      dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \
-               dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@
+               dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \
+               dnssec-revoke@EXEEXT@
 
 OBJS =         dnssectool.@O@
 
 SRCS =         dnssec-dsfromkey.c dnssec-keyfromlabel.c dnssec-keygen.c \
-               dnssec-signzone.c dnssectool.c
+               dnssec-revoke.c dnssec-signzone.c dnssectool.c
 
 MANPAGES =     dnssec-dsfromkey.8 dnssec-keyfromlabel.8 dnssec-keygen.8 \
-               dnssec-signzone.8
+               dnssec-revoke.8 dnssec-signzone.8
 
 HTMLPAGES =    dnssec-dsfromkey.html dnssec-keyfromlabel.html \
-               dnssec-keygen.html dnssec-signzone.html 
+               dnssec-keygen.html dnssec-revoke.html dnssec-signzone.html 
 
 MANOBJS =      ${MANPAGES} ${HTMLPAGES}
 
@@ -77,6 +78,10 @@ dnssec-signzone@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS}
        ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
        dnssec-signzone.@O@ ${OBJS} ${LIBS}
 
+dnssec-revoke@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+       dnssec-revoke.@O@ ${OBJS} ${LIBS}
+
 doc man:: ${MANOBJS}
 
 docclean manclean maintainer-clean::
index 1ad66d70be279bec55d5f75712e18d56865878f8..98edcbc880dd1d7ee10e59ea977060e0625e0014 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dnssec-keyfromlabel.c,v 1.6 2009/05/07 23:47:44 tbox Exp $ */
+/* $Id: dnssec-keyfromlabel.c,v 1.7 2009/06/30 02:52:32 each Exp $ */
 
 /*! \file */
 
@@ -64,7 +64,7 @@ usage(void) {
        fprintf(stderr, "    -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n");
        fprintf(stderr, "        (DNSKEY generation defaults to ZONE\n");
        fprintf(stderr, "    -c <class> (default: IN)\n");
-       fprintf(stderr, "    -f keyflag: KSK\n");
+       fprintf(stderr, "    -f keyflag (KSK or REVOKE)\n");
        fprintf(stderr, "    -t <type>: "
                "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
                "(default: AUTHCONF)\n");
@@ -87,7 +87,7 @@ 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;
+       isc_uint16_t    flags = 0, ksk = 0, revoke = 0;
        dns_secalg_t    alg;
        isc_boolean_t   null_key = ISC_FALSE;
        isc_mem_t       *mctx = NULL;
@@ -125,6 +125,9 @@ main(int argc, char **argv) {
                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;
                        else
                                fatal("unknown flag '%s'",
                                      isc_commandline_argument);
@@ -238,8 +241,10 @@ main(int argc, char **argv) {
 
        if ((options & DST_TYPE_KEY) != 0)  /* KEY */
                flags |= signatory;
-       else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */
+       else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */
                flags |= ksk;
+               flags |= revoke;
+        }
 
        if (protocol == -1)
                protocol = DNS_KEYPROTO_DNSSEC;
index 3f521b2d6d9e57cab0825f844b8e05dad838faf2..72108e998b2860e600fb02eec8c30bcf1b254e02 100644 (file)
@@ -29,7 +29,7 @@
  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dnssec-keygen.c,v 1.85 2009/06/17 23:53:04 tbox Exp $ */
+/* $Id: dnssec-keygen.c,v 1.86 2009/06/30 02:52:32 each Exp $ */
 
 /*! \file */
 
@@ -102,7 +102,7 @@ usage(void) {
        fprintf(stderr, "    -c <class> (default: IN)\n");
        fprintf(stderr, "    -d <digest bits> (0 => max, default)\n");
        fprintf(stderr, "    -e use large exponent (RSAMD5/RSASHA1 only)\n");
-       fprintf(stderr, "    -f keyflag: KSK\n");
+       fprintf(stderr, "    -f keyflag (KSK or REVOKE)\n");
        fprintf(stderr, "    -g <generator> use specified generator "
                "(DH only)\n");
        fprintf(stderr, "    -t <type>: "
@@ -130,7 +130,7 @@ 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;
+       isc_uint16_t    flags = 0, ksk = 0, revoke = 0;
        dns_secalg_t    alg;
        isc_boolean_t   conflict = ISC_FALSE, null_key = ISC_FALSE;
        isc_mem_t       *mctx = NULL;
@@ -182,6 +182,9 @@ main(int argc, char **argv) {
                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;
                        else
                                fatal("unknown flag '%s'",
                                      isc_commandline_argument);
@@ -423,8 +426,10 @@ main(int argc, char **argv) {
 
        if ((options & DST_TYPE_KEY) != 0)  /* KEY / HMAC */
                flags |= signatory;
-       else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */
+       else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */
                flags |= ksk;
+               flags |= revoke;
+        }
 
        if (protocol == -1)
                protocol = DNS_KEYPROTO_DNSSEC;
diff --git a/bin/dnssec/dnssec-revoke.8 b/bin/dnssec/dnssec-revoke.8
new file mode 100644 (file)
index 0000000..728309f
--- /dev/null
@@ -0,0 +1,62 @@
+.\" 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-revoke.8,v 1.2 2009/06/30 02:52:32 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 1, 2009" "" ""
+.SH NAME
+dnssec-revoke \- Set the REVOKED bit on a DNSSEC key
+.SH "SYNOPSIS"
+.HP 14
+\fBdnssec\-revoke\fR [\fB\-v\ \fIlevel\fR\fR] [\fB\-d\ \fIdirectory\fR\fR] [\fB\-F\fR] {keyfile}
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-revoke\fR reads a DNSSEC key file, sets the REVOKED bit on the key as defined in RFC 5011, and creates a new pair of key files containing the now\- revoked key\&.
+.SH "OPTIONS"
+.TP
+\-d \fIdirectory\fR
+Sets the directory in which the key files are to reside\&.
+.TP
+\-v \fIlevel\fR
+Sets the debugging level\&.
+.TP
+\-F
+Force overwrite: Causes \fBdnssec\-revoke\fR to write the new key pair even if a file already exists matching the algorithm and key ID of the revoked key\&.
+.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-revoke.c b/bin/dnssec/dnssec-revoke.c
new file mode 100644 (file)
index 0000000..57473b3
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * 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-revoke.c,v 1.2 2009/06/30 02:52:32 each Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <libgen.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/errno.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-revoke";
+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, "    -f:           force ovewrite\n");
+       fprintf(stderr, "    -d directory: use directory for key files\n");
+       fprintf(stderr, "    -h:           help\n");
+       fprintf(stderr, "    -r:           remove old keyfiles after "
+                                          "creating revoked version\n");
+       fprintf(stderr, "    -v level:     set level of verbosity\n");
+       fprintf(stderr, "Output:\n");
+       fprintf(stderr, "     K<name>+<alg>+<new id>.key, "
+                            "K<name>+<alg>+<new id>.private\n");
+
+       exit (-1);
+}
+
+int
+main(int argc, char **argv) {
+       isc_result_t result;
+       char *filename = NULL, *dir= NULL;
+       char newname[1024], oldname[1024];
+       char keystr[KEY_FORMATSIZE];
+       char *endp;
+       int ch;
+       isc_entropy_t *ectx = NULL;
+       dst_key_t *key = NULL;
+       isc_uint32_t flags;
+       isc_buffer_t buf;
+       isc_boolean_t force = ISC_FALSE;
+       isc_boolean_t remove = ISC_FALSE;
+
+       if (argc == 1)
+               usage();
+
+       result = isc_mem_create(0, 0, &mctx);
+       if (result != ISC_R_SUCCESS)
+               fatal("Out of memory");
+
+       dns_result_register();
+
+       isc_commandline_errprint = ISC_FALSE;
+
+       while ((ch = isc_commandline_parse(argc, argv, "d:fhrv:")) != -1) {
+               switch (ch) {
+                   case 'd':
+                       dir = isc_commandline_argument;
+                       break;
+                   case 'f':
+                       force = ISC_TRUE;
+                       break;
+                   case 'r':
+                       remove = ISC_TRUE;
+                       break;
+                   case 'v':
+                       verbose = strtol(isc_commandline_argument, &endp, 0);
+                       if (*endp != '\0')
+                               fatal("-v must be followed by a number");
+                       break;
+                   case '?':
+                       if (isc_commandline_option != '?')
+                               fprintf(stderr, "%s: invalid argument -%c\n",
+                                       program, isc_commandline_option);
+                       /* Falls into */
+                   case 'h':
+                       usage();
+
+                   default:
+                       fprintf(stderr, "%s: unhandled option -%c\n",
+                               program, isc_commandline_option);
+                       exit(1);
+               }
+       }
+
+       if (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 (dir == NULL)
+               dir = dirname(argv[isc_commandline_index]);
+       filename = 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,
+                                      DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
+                                      mctx, &key);
+       if (result != ISC_R_SUCCESS)
+               fatal("Invalid keyfile name %s: %s",
+                     filename, isc_result_totext(result));
+
+       if (verbose > 2) {
+               char keystr[KEY_FORMATSIZE];
+
+               key_format(key, keystr, sizeof(keystr));
+               fprintf(stderr, "%s: %s\n", program, keystr);
+       }
+
+       flags = dst_key_flags(key);
+       if ((flags & DNS_KEYFLAG_REVOKE) == 0) {
+               dst_key_setflags(key, flags | DNS_KEYFLAG_REVOKE);
+
+               isc_buffer_init(&buf, newname, sizeof(newname));
+               dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf);
+
+               if (access(newname, F_OK) == 0 && !force) {
+                       fatal("Key file %s already exists; "
+                             "use -f to force overwrite", newname);
+               }
+
+               result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
+                                       dir);
+               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, dir, &buf);
+               printf("%s\n", newname);
+
+               /*
+                * Remove old key file, if told to (and if
+                * it isn't the same as the new file)
+                */
+               if (remove && dst_key_alg(key) != DST_ALG_RSAMD5) {
+                       isc_buffer_init(&buf, oldname, sizeof(oldname));
+                       dst_key_setflags(key, flags & ~DNS_KEYFLAG_REVOKE);
+                       dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf);
+                       if (strcmp(oldname, newname) == 0)
+                               goto cleanup;
+                       if (access(oldname, F_OK) == 0)
+                               unlink(oldname);
+                       isc_buffer_clear(&buf);
+                       dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf);
+                       if (access(oldname, F_OK) == 0)
+                               unlink(oldname);
+               }
+       } else {
+               key_format(key, keystr, sizeof(keystr));
+               fatal("Key %s is already revoked", keystr);
+       }
+
+cleanup:
+       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-revoke.docbook b/bin/dnssec/dnssec-revoke.docbook
new file mode 100644 (file)
index 0000000..c78ce6b
--- /dev/null
@@ -0,0 +1,138 @@
+<!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-revoke.docbook,v 1.2 2009/06/30 02:52:32 each Exp $ -->
+<refentry id="man.dnssec-revoke">
+  <refentryinfo>
+    <date>June 1, 2009</date>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle><application>dnssec-revoke</application></refentrytitle>
+    <manvolnum>8</manvolnum>
+    <refmiscinfo>BIND9</refmiscinfo>
+  </refmeta>
+
+  <refnamediv>
+    <refname><application>dnssec-revoke</application></refname>
+    <refpurpose>Set the REVOKED bit on a DNSSEC key</refpurpose>
+  </refnamediv>
+
+  <docinfo>
+    <copyright>
+      <year>2009</year>
+      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+    </copyright>
+  </docinfo>
+
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <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>-f</option></arg>
+      <arg choice="req">keyfile</arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>DESCRIPTION</title>
+    <para><command>dnssec-revoke</command>
+      reads a DNSSEC key file, sets the REVOKED bit on the key as defined
+      in RFC 5011, and creates a new pair of key files containing the now-
+      revoked key.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>OPTIONS</title>
+
+    <variablelist>
+      <varlistentry>
+       <term>-h</term>
+        <listitem>
+         <para>
+           Emit usage message and exit.
+         </para>
+        </listitem>
+      </varlistentry>
+  
+      <varlistentry>
+        <term>-d <replaceable class="parameter">directory</replaceable></term>
+        <listitem>
+          <para>
+            Sets the directory in which the key files are to reside.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term>-r</term>
+        <listitem>
+         <para>
+           After writing the new keyset files remove the original keyset
+           files.
+         </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>-v <replaceable class="parameter">level</replaceable></term>
+        <listitem>
+          <para>
+            Sets the debugging level.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>-f</term>
+        <listitem>
+          <para>
+            Force overwrite: Causes <command>dnssec-revoke</command> to
+            write the new key pair even if a file already exists matching
+            the algorithm and key ID of the revoked key.
+          </para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>SEE ALSO</title>
+    <para><citerefentry>
+        <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>,
+      <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+      <citetitle>RFC 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-revoke.html b/bin/dnssec/dnssec-revoke.html
new file mode 100644 (file)
index 0000000..4352ebb
--- /dev/null
@@ -0,0 +1,73 @@
+<!--
+ - 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-revoke.html,v 1.2 2009/06/30 02:52:32 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-revoke"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-revoke</span> &#8212; Set the REVOKED bit on a DNSSEC key</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-revoke</code>  [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-d <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-F</code>] {keyfile}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id215043"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-revoke</strong></span>
+      reads a DNSSEC key file, sets the REVOKED bit on the key as defined
+      in RFC 5011, and creates a new pair of key files containing the now-
+      revoked key.
+    </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id215056"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-d <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">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+            Sets the debugging level.
+          </p></dd>
+<dt><span class="term">-F</span></dt>
+<dd><p>
+            Force overwrite: Causes <span><strong class="command">dnssec-revoke</strong></span> to
+            write the new key pair even if a file already exists matching
+            the algorithm and key ID of the revoked key.
+          </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id215118"></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="id215141"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+    </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dnssec/win32/revoke.dsp b/bin/dnssec/win32/revoke.dsp
new file mode 100644 (file)
index 0000000..ce3b00c
--- /dev/null
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="revoke" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=revoke - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "revoke.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "revoke.mak" CFG="revoke - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "revoke - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "revoke - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "revoke - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/dnssec-revoke.exe"
+
+!ELSEIF  "$(CFG)" == "revoke - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/dnssec-revoke.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "revoke - Win32 Release"
+# Name "revoke - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-revoke.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/revoke.dsw b/bin/dnssec/win32/revoke.dsw
new file mode 100644 (file)
index 0000000..f588e21
--- /dev/null
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "revoke"=".\revoke.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/revoke.mak b/bin/dnssec/win32/revoke.mak
new file mode 100644 (file)
index 0000000..f8bcae0
--- /dev/null
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on revoke.dsp
+!IF "$(CFG)" == ""
+CFG=revoke - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to revoke - Win32 Debug.
+!ENDIF 
+
+!IF "$(CFG)" != "revoke - Win32 Release" && "$(CFG)" != "revoke - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "revoke.mak" CFG="revoke - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "revoke - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "revoke - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+!ERROR An invalid configuration is specified.
+!ENDIF 
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE 
+NULL=nul
+!ENDIF 
+
+!IF  "$(CFG)" == "revoke - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+    $(_VC_MANIFEST_BASENAME).auto.rc \
+    $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF  "$(CFG)" == "revoke - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-revoke.exe"
+
+
+CLEAN :
+       -@erase "$(INTDIR)\dnssec-revoke.obj"
+       -@erase "$(INTDIR)\dnssectool.obj"
+       -@erase "$(INTDIR)\vc60.idb"
+       -@erase "..\..\..\Build\Release\dnssec-revoke.exe"
+       -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\revoke.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+
+.c{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.c{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\revoke.bsc" 
+BSC32_SBRS= \
+       
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-revoke.pdb" /machine:I386 /out:"../../../Build/Release/dnssec-revoke.exe" 
+LINK32_OBJS= \
+       "$(INTDIR)\dnssec-revoke.obj" \
+       "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-revoke.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+    $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF  "$(CFG)" == "revoke - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-revoke.exe" "$(OUTDIR)\revoke.bsc"
+
+
+CLEAN :
+       -@erase "$(INTDIR)\dnssec-revoke.obj"
+       -@erase "$(INTDIR)\dnssec-revoke.sbr"
+       -@erase "$(INTDIR)\dnssectool.obj"
+       -@erase "$(INTDIR)\dnssectool.sbr"
+       -@erase "$(INTDIR)\vc60.idb"
+       -@erase "$(INTDIR)\vc60.pdb"
+       -@erase "$(OUTDIR)\dnssec-revoke.pdb"
+       -@erase "$(OUTDIR)\revoke.bsc"
+       -@erase "..\..\..\Build\Debug\dnssec-revoke.exe"
+       -@erase "..\..\..\Build\Debug\dnssec-revoke.ilk"
+       -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
+
+.c{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.obj::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.c{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cpp{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+.cxx{$(INTDIR)}.sbr::
+   $(CPP) @<<
+   $(CPP_PROJ) $< 
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\revoke.bsc" 
+BSC32_SBRS= \
+       "$(INTDIR)\dnssec-revoke.sbr" \
+       "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\revoke.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+    $(BSC32) @<<
+  $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-revoke.pdb" /debug /machine:I386 /out:"../../../Build/Debug/dnssec-revoke.exe" /pdbtype:sept 
+LINK32_OBJS= \
+       "$(INTDIR)\dnssec-revoke.obj" \
+       "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-revoke.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+    $(LINK32) @<<
+  $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+    $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF 
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("revoke.dep")
+!INCLUDE "revoke.dep"
+!ELSE 
+!MESSAGE Warning: cannot find "revoke.dep"
+!ENDIF 
+!ENDIF 
+
+
+!IF "$(CFG)" == "revoke - Win32 Release" || "$(CFG)" == "revoke - Win32 Debug"
+SOURCE="..\dnssec-revoke.c"
+
+!IF  "$(CFG)" == "revoke - Win32 Release"
+
+
+"$(INTDIR)\dnssec-revoke.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "revoke - Win32 Debug"
+
+
+"$(INTDIR)\dnssec-revoke.obj"  "$(INTDIR)\dnssec-revoke.sbr" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF 
+
+SOURCE=..\dnssectool.c
+
+!IF  "$(CFG)" == "revoke - Win32 Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "revoke - Win32 Debug"
+
+
+"$(INTDIR)\dnssectool.obj"     "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF 
+
+
+!ENDIF 
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+    type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+    type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
index db650a85bd9c8a5363a6f1ee7732a359797c05fb..9834c1993566b716deaf98b35c2038a0496c19f2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: config.c,v 1.97 2009/06/10 00:27:21 each Exp $ */
+/* $Id: config.c,v 1.98 2009/06/30 02:52:32 each Exp $ */
 
 /*! \file */
 
@@ -225,6 +225,7 @@ view \"_bind\" chaos {\n\
                type master;\n\
                database \"_builtin authors\";\n\
        };\n\
+\n\
        zone \"id.server\" chaos {\n\
                type master;\n\
                database \"_builtin id\";\n\
@@ -232,6 +233,17 @@ view \"_bind\" chaos {\n\
 };\n\
 "
 
+"#\n\
+#  The \"_meta\" view is for zones that are used to store internal\n\
+#  information for named, such as managed keys.  The zones are defined\n\
+#  elsewhere.\n\
+#\n\
+view \"_meta\" in {\n\
+       recursion no;\n\
+       notify no;\n\
+};\n\
+"
+
 "#\n\
 #  Default trusted key(s) for builtin DLV support\n\
 #  (used if \"dnssec-lookaside auto;\" is set and\n\
index 9a25a15f83871be5811c3023936508fdce7eefd1..b076cbaa3f1f48d0719fa9e5bb764db97d9c449c 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.h,v 1.98 2009/06/10 00:27:21 each Exp $ */
+/* $Id: server.h,v 1.99 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef NAMED_SERVER_H
 #define NAMED_SERVER_H 1
@@ -55,6 +55,8 @@ struct ns_server {
        char *                  statsfile;      /*%< Statistics file name */
        char *                  dumpfile;       /*%< Dump file name */
        char *                  bindkeysfile;   /*%< bind.keys file name */
+       isc_boolean_t           managedkeys;    /*%< A managed-keys
+                                                    statement exists */
        char *                  recfile;        /*%< Recursive file name */
        isc_boolean_t           version_set;    /*%< User has set version */
        char *                  version;        /*%< User-specified version */
index 4c92d7d2c17ac6c914149a0a4caad4336a21e336..01419d4d879602f7c19c9c1e50bded950c3b3446 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.c,v 1.534 2009/06/10 23:47:47 tbox Exp $ */
+/* $Id: server.c,v 1.535 2009/06/30 02:52:32 each Exp $ */
 
 /*! \file */
 
@@ -270,6 +270,9 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
               const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
               cfg_aclconfctx_t *aclconf);
 
+static isc_result_t
+add_keydata_zone(dns_view_t *view, isc_mem_t *mctx);
+
 static void
 end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
 
@@ -439,8 +442,8 @@ configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config,
 }
 
 static isc_result_t
-configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
-                        dns_keytable_t *keytable, isc_mem_t *mctx)
+dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key,
+                 isc_boolean_t managed, dst_key_t **target, isc_mem_t *mctx)
 {
        dns_rdataclass_t viewclass;
        dns_rdata_dnskey_t keystruct;
@@ -457,6 +460,8 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
        isc_result_t result;
        dst_key_t *dstkey = NULL;
 
+       INSIST(target != NULL && *target == NULL);
+
        flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
        proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
        alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
@@ -502,7 +507,8 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
             keystruct.algorithm == DST_ALG_RSAMD5) &&
            r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
                cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
-                           "trusted key '%s' has a weak exponent",
+                           "%s key '%s' has a weak exponent",
+                           managed ? "managed" : "trusted",
                            keynamestr);
 
        CHECK(dns_rdata_fromstruct(NULL,
@@ -518,19 +524,20 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
        CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf,
                              mctx, &dstkey));
 
-       CHECK(dns_keytable_add(keytable, &dstkey));
-       INSIST(dstkey == NULL);
+       *target = dstkey;
        return (ISC_R_SUCCESS);
 
  cleanup:
        if (result == DST_R_NOCRYPTO) {
                cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
-                           "ignoring trusted key for '%s': no crypto support",
+                           "ignoring %s key for '%s': no crypto support",
+                           managed ? "managed" : "trusted",
                            keynamestr);
                result = ISC_R_SUCCESS;
        } else {
                cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
-                           "configuring trusted key for '%s': %s",
+                           "configuring %s key for '%s': %s",
+                           managed ? "managed" : "trusted",
                            keynamestr, isc_result_totext(result));
                result = ISC_R_FAILURE;
        }
@@ -541,15 +548,14 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
        return (result);
 }
 
-
-static void
-configure_view_dnsseckeylist(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
-                            dns_keytable_t *keytable, isc_mem_t *mctx)
+static isc_result_t
+load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
+              dns_view_t *view, isc_boolean_t managed, isc_mem_t *mctx)
 {
        const cfg_listelt_t *elt, *elt2;
-       const cfg_obj_t *key;
-       const cfg_obj_t *keylist;
-       isc_result_t result;
+       const cfg_obj_t *key, *keylist;
+       dst_key_t *dstkey = NULL;
+       isc_result_t result = ISC_R_SUCCESS;
 
        for (elt = cfg_list_first(keys);
             elt != NULL;
@@ -560,49 +566,57 @@ configure_view_dnsseckeylist(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
                     elt2 != NULL;
                     elt2 = cfg_list_next(elt2)) {
                        key = cfg_listelt_value(elt2);
-                       CHECK(configure_view_dnsseckey(vconfig, key,
-                                                      keytable, mctx));
+                       CHECK(dstkey_fromconfig(vconfig, key, managed,
+                                               &dstkey, mctx));
+                       CHECK(dns_keytable_add(view->secroots, managed,
+                                              &dstkey));
                }
        }
 
  cleanup:
-       return;
+       return (result);
 }
 
 /*%
- * Configure DNSSEC keys for a view.  Currently used only for the security
- * roots.
+ * Configure DNSSEC keys for a view.
  *
  * The per-view configuration values and the server-global defaults are read
- * from 'vconfig' and 'config'.         The variable to be configured is '*target'.
+ * from 'vconfig' and 'config'.
  */
 static isc_result_t
-configure_view_dnsseckeys(const cfg_obj_t *vconfig, const cfg_obj_t *config,
-                         const cfg_obj_t *bindkeys, isc_boolean_t auto_dlv,
-                         isc_mem_t *mctx, dns_keytable_t **target)
+configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
+                         const cfg_obj_t *config, const cfg_obj_t *bindkeys,
+                         isc_boolean_t auto_dlv, isc_mem_t *mctx)
 {
+       isc_result_t result = ISC_R_SUCCESS;
        const cfg_obj_t *view_keys = NULL;
        const cfg_obj_t *global_keys = NULL;
+       const cfg_obj_t *global_managed_keys = NULL;
        const cfg_obj_t *builtin_keys = NULL;
+       const cfg_obj_t *builtin_managed_keys = NULL;
        const cfg_obj_t *maps[4];
        const cfg_obj_t *voptions = NULL;
        const cfg_obj_t *options = NULL;
-       dns_keytable_t *keytable = NULL;
-       isc_result_t result;
        int i = 0;
 
-       CHECK(dns_keytable_create(mctx, &keytable));
+       /* We don't need trust anchors for the _bind view */
+       if (strcmp(view->name, "_bind") == 0) {
+               view->secroots = NULL;
+               return (ISC_R_SUCCESS);
+       }
 
        if (vconfig != NULL) {
                voptions = cfg_tuple_get(vconfig, "options");
                if (voptions != NULL) {
-                       (void)cfg_map_get(voptions, "trusted-keys", &view_keys);
+                       (void) cfg_map_get(voptions, "trusted-keys",
+                                          &view_keys);
                        maps[i++] = voptions;
                }
        }
 
        if (config != NULL) {
                (void)cfg_map_get(config, "trusted-keys", &global_keys);
+               (void)cfg_map_get(config, "managed-keys", &global_managed_keys);
                (void)cfg_map_get(config, "options", &options);
                if (options != NULL) {
                        maps[i++] = options;
@@ -612,35 +626,60 @@ configure_view_dnsseckeys(const cfg_obj_t *vconfig, const cfg_obj_t *config,
        maps[i++] = ns_g_defaults;
        maps[i] = NULL;
 
+       if (view->secroots != NULL)
+               dns_keytable_detach(&view->secroots);
+       result = dns_keytable_create(mctx, &view->secroots);
+       if (result != ISC_R_SUCCESS) {
+               isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+                             NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+                             "couldn't create keytable");
+               return (ISC_R_UNEXPECTED);
+       }
+
+       if (global_managed_keys != NULL)
+               ns_g_server->managedkeys = ISC_TRUE;
+
        if (auto_dlv) {
                isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
                              NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
-                             "using built-in trusted-keys");
+                             "using built-in trusted-keys for view %s",
+                             view->name);
 
                /*
-                * If bind.keys exists, it overrides the trusted-keys
+                * If bind.keys exists, it overrides the managed-keys
                 * clause hard-coded in ns_g_config.
                 */
-               if (bindkeys != NULL)
+               if (bindkeys != NULL) {
                        (void)cfg_map_get(bindkeys, "trusted-keys",
                                          &builtin_keys);
-               else
+                       (void)cfg_map_get(bindkeys, "managed-keys",
+                                         &builtin_managed_keys);
+               } else {
                        (void)cfg_map_get(ns_g_config, "trusted-keys",
                                          &builtin_keys);
+                       (void)cfg_map_get(ns_g_config, "managed-keys",
+                                         &builtin_managed_keys);
+               }
+
+               if (builtin_managed_keys != NULL)
+                       ns_g_server->managedkeys = ISC_TRUE;
+               CHECK(load_view_keys(builtin_keys, vconfig, view,
+                                     ISC_FALSE, mctx));
 
-               configure_view_dnsseckeylist(builtin_keys, vconfig,
-                                            keytable, mctx);
+               if (strcmp(view->name, "_meta") == 0)
+                       CHECK(load_view_keys(builtin_managed_keys, vconfig,
+                                             view, ISC_TRUE, mctx));
        }
 
-       configure_view_dnsseckeylist(global_keys, vconfig, keytable, mctx);
-       configure_view_dnsseckeylist(view_keys, vconfig, keytable, mctx);
+       CHECK(load_view_keys(view_keys, vconfig, view, ISC_FALSE, mctx));
+       CHECK(load_view_keys(global_keys, vconfig, view, ISC_FALSE, mctx));
 
-       dns_keytable_detach(target);
-       *target = keytable; /* Transfer ownership. */
-       keytable = NULL;
+       if (strcmp(view->name, "_meta") == 0)
+               CHECK(load_view_keys(global_managed_keys, vconfig, view,
+                              ISC_TRUE, mctx));
 
- cleanup:
-       return (ISC_R_SUCCESS);
 cleanup:
+       return (result);
 }
 
 static isc_result_t
@@ -2082,8 +2121,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
         * For now, there is only one kind of trusted keys, the
         * "security roots".
         */
-       CHECK(configure_view_dnsseckeys(vconfig, config, bindkeys, auto_dlv,
-                                       mctx, &view->secroots));
+       CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys,
+                                       auto_dlv, mctx));
        dns_resolver_resetmustbesecure(view->resolver);
        obj = NULL;
        result = ns_config_get(maps, "dnssec-must-be-secure", &obj);
@@ -2823,6 +2862,73 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
        return (result);
 }
 
+/*
+ * Configure built-in zone for storing managed-key data.
+ */
+
+#define KEYZONE "managed-keys.bind"
+
+static isc_result_t
+add_keydata_zone(dns_view_t *view, isc_mem_t *mctx) {
+       isc_result_t result;
+       dns_zone_t *zone = NULL;
+       dns_acl_t *none = NULL;
+       dns_name_t zname;
+
+       if (!ns_g_server->managedkeys)
+               return (ISC_R_SUCCESS);
+
+       REQUIRE(view != NULL);
+
+       CHECK(dns_zone_create(&zone, mctx));
+
+        dns_name_init(&zname, NULL);
+       CHECK(dns_name_fromstring(&zname, KEYZONE, mctx));
+       CHECK(dns_zone_setorigin(zone, &zname));
+       dns_name_free(&zname, mctx);
+
+       CHECK(dns_zone_setfile(zone, KEYZONE));
+
+       if (view->hints == NULL)
+               dns_view_sethints(view, ns_g_server->in_roothints);
+
+       dns_zone_setview(zone, view);
+       dns_zone_settype(zone, dns_zone_key);
+       dns_zone_setclass(zone, view->rdclass);
+
+       CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
+
+       if (view->acache != NULL)
+               dns_zone_setacache(zone, view->acache);
+
+       CHECK(dns_acl_none(mctx, &none));
+       dns_zone_setqueryacl(zone, none);
+       dns_zone_setqueryonacl(zone, none);
+       dns_acl_detach(&none);
+
+       dns_zone_setdialup(zone, dns_dialuptype_no);
+       dns_zone_setnotifytype(zone, dns_notifytype_no);
+       dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE);
+       dns_zone_setjournalsize(zone, 0);
+
+       dns_zone_setstats(zone, ns_g_server->zonestats);
+       CHECK(setquerystats(zone, mctx, ISC_FALSE));
+
+       CHECK(dns_view_addzone(view, zone));
+
+       isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+                     NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+                     "set up %s meta-zone", KEYZONE);
+
+cleanup:
+       if (zone != NULL)
+               dns_zone_detach(&zone);
+       if (none != NULL)
+               dns_acl_detach(&none);
+
+       return (result);
+}
+
 /*
  * Configure a single server quota.
  */
@@ -3442,7 +3548,7 @@ load_configuration(const char *filename, ns_server_t *server,
        dns_view_t *view = NULL;
        dns_view_t *view_next;
        dns_viewlist_t tmpviewlist;
-       dns_viewlist_t viewlist;
+       dns_viewlist_t viewlist, builtin_viewlist;
        in_port_t listen_port, udpport_low, udpport_high;
        int i;
        isc_interval_t interval;
@@ -3460,6 +3566,7 @@ load_configuration(const char *filename, ns_server_t *server,
 
        cfg_aclconfctx_init(&aclconfctx);
        ISC_LIST_INIT(viewlist);
+       ISC_LIST_INIT(builtin_viewlist);
        ISC_LIST_INIT(cachelist);
 
        /* Ensure exclusive access to configuration data. */
@@ -3908,7 +4015,7 @@ load_configuration(const char *filename, ns_server_t *server,
 
        /*
         * Create (or recreate) the built-in views.  Currently
-        * there is only one, the _bind view.
+        * there is only one, the _bind view, but allow for others.
         */
        builtin_views = NULL;
        RUNTIME_CHECK(cfg_map_get(ns_g_config, "view",
@@ -3918,32 +4025,43 @@ load_configuration(const char *filename, ns_server_t *server,
             element = cfg_list_next(element))
        {
                const cfg_obj_t *vconfig = cfg_listelt_value(element);
-               CHECK(create_view(vconfig, &viewlist, &view));
+
+               CHECK(create_view(vconfig, &builtin_viewlist, &view));
                CHECK(configure_view(view, config, vconfig,
                                     &cachelist, bindkeys,
                                     ns_g_mctx, &aclconfctx, ISC_FALSE));
+
+               if (!strcmp(view->name, "_meta")) {
+                       result = add_keydata_zone(view, ns_g_mctx);
+                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+               }
+
                dns_view_freeze(view);
                dns_view_detach(&view);
                view = NULL;
        }
 
-       /*
-        * Swap our new view list with the production one.
-        */
+       /* Now combine the two viewlists into one */
+       ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link);
+
+       /* Swap our new view list with the production one. */
        tmpviewlist = server->viewlist;
        server->viewlist = viewlist;
        viewlist = tmpviewlist;
 
-       /*
-        * Swap our new cache list with the production one.
-        */
+       /* Make the view list available to each of the views */
+       view = ISC_LIST_HEAD(server->viewlist);
+       while (view != NULL) {
+               view->viewlist = &server->viewlist;
+               view = ISC_LIST_NEXT(view, link);
+       }
+
+       /* Swap our new cache list with the production one. */
        tmpcachelist = server->cachelist;
        server->cachelist = cachelist;
        cachelist = tmpcachelist;
 
-       /*
-        * Load the TKEY information from the configuration.
-        */
+       /* Load the TKEY information from the configuration. */
        if (options != NULL) {
                dns_tkeyctx_t *t = NULL;
                CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy,
@@ -4552,6 +4670,8 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
                                                  ISC_R_SUCCESS,
                   "isc_mem_strdup");
 
+       server->managedkeys = ISC_FALSE;
+
        server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");
        CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
                   "isc_mem_strdup");
@@ -6161,8 +6281,9 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) {
                dns_zone_setupdatedisabled(zone, freeze);
 
        view = dns_zone_getview(zone);
-       if (strcmp(view->name, "_bind") == 0 ||
-           strcmp(view->name, "_default") == 0)
+       if (strcmp(view->name, "_default") == 0 ||
+           strcmp(view->name, "_bind") == 0 ||
+           strcmp(view->name, "_meta"))
        {
                vname = "";
                sep = "";
index 6236dfa4cc864667f8ae45921a0f6a5c6b2f85b6..4cd88ab82cd274607623b8fcc29b88df63ec6e58 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: xfrout.c,v 1.135 2009/01/27 22:29:58 jinmei Exp $ */
+/* $Id: xfrout.c,v 1.136 2009/06/30 02:52:32 each Exp $ */
 
 #include <config.h>
 
@@ -40,6 +40,7 @@
 #include <dns/rdataset.h>
 #include <dns/rdatasetiter.h>
 #include <dns/result.h>
+#include <dns/rriterator.h>
 #include <dns/soa.h>
 #include <dns/stats.h>
 #include <dns/timer.h>
        } while (0)
 
 /**************************************************************************/
-/*%
- * A db_rr_iterator_t is an iterator that iterates over an entire database,
- * returning one RR at a time, in some arbitrary order.
- */
-
-typedef struct db_rr_iterator db_rr_iterator_t;
-
-/*% db_rr_iterator structure */
-struct db_rr_iterator {
-       isc_result_t            result;
-       dns_db_t                *db;
-       dns_dbiterator_t        *dbit;
-       dns_dbversion_t         *ver;
-       isc_stdtime_t           now;
-       dns_dbnode_t            *node;
-       dns_fixedname_t         fixedname;
-       dns_rdatasetiter_t      *rdatasetit;
-       dns_rdataset_t          rdataset;
-       dns_rdata_t             rdata;
-};
-
-static isc_result_t
-db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
-                   isc_stdtime_t now);
-
-static isc_result_t
-db_rr_iterator_first(db_rr_iterator_t *it);
-
-static isc_result_t
-db_rr_iterator_next(db_rr_iterator_t *it);
-
-static void
-db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
-                      isc_uint32_t *ttl, dns_rdata_t **rdata);
-
-static void
-db_rr_iterator_destroy(db_rr_iterator_t *it);
 
 static inline void
 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
@@ -160,145 +124,6 @@ inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
        }
 }
 
-static isc_result_t
-db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
-                   isc_stdtime_t now)
-{
-       isc_result_t result;
-       it->db = db;
-       it->dbit = NULL;
-       it->ver = ver;
-       it->now = now;
-       it->node = NULL;
-       result = dns_db_createiterator(it->db, 0, &it->dbit);
-       if (result != ISC_R_SUCCESS)
-               return (result);
-       it->rdatasetit = NULL;
-       dns_rdata_init(&it->rdata);
-       dns_rdataset_init(&it->rdataset);
-       dns_fixedname_init(&it->fixedname);
-       INSIST(! dns_rdataset_isassociated(&it->rdataset));
-       it->result = ISC_R_SUCCESS;
-       return (it->result);
-}
-
-static isc_result_t
-db_rr_iterator_first(db_rr_iterator_t *it) {
-       it->result = dns_dbiterator_first(it->dbit);
-       /*
-        * The top node may be empty when out of zone glue exists.
-        * Walk the tree to find the first node with data.
-        */
-       while (it->result == ISC_R_SUCCESS) {
-               it->result = dns_dbiterator_current(it->dbit, &it->node,
-                                   dns_fixedname_name(&it->fixedname));
-               if (it->result != ISC_R_SUCCESS)
-                       return (it->result);
-
-               it->result = dns_db_allrdatasets(it->db, it->node,
-                                                it->ver, it->now,
-                                                &it->rdatasetit);
-               if (it->result != ISC_R_SUCCESS)
-                       return (it->result);
-
-               it->result = dns_rdatasetiter_first(it->rdatasetit);
-               if (it->result != ISC_R_SUCCESS) {
-                       /*
-                        * This node is empty. Try next node.
-                        */
-                       dns_rdatasetiter_destroy(&it->rdatasetit);
-                       dns_db_detachnode(it->db, &it->node);
-                       it->result = dns_dbiterator_next(it->dbit);
-                       continue;
-               }
-               dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
-               it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
-               it->result = dns_rdataset_first(&it->rdataset);
-               return (it->result);
-       }
-       return (it->result);
-}
-
-
-static isc_result_t
-db_rr_iterator_next(db_rr_iterator_t *it) {
-       if (it->result != ISC_R_SUCCESS)
-               return (it->result);
-
-       INSIST(it->dbit != NULL);
-       INSIST(it->node != NULL);
-       INSIST(it->rdatasetit != NULL);
-
-       it->result = dns_rdataset_next(&it->rdataset);
-       if (it->result == ISC_R_NOMORE) {
-               dns_rdataset_disassociate(&it->rdataset);
-               it->result = dns_rdatasetiter_next(it->rdatasetit);
-               /*
-                * The while loop body is executed more than once
-                * only when an empty dbnode needs to be skipped.
-                */
-               while (it->result == ISC_R_NOMORE) {
-                       dns_rdatasetiter_destroy(&it->rdatasetit);
-                       dns_db_detachnode(it->db, &it->node);
-                       it->result = dns_dbiterator_next(it->dbit);
-                       if (it->result == ISC_R_NOMORE) {
-                               /* We are at the end of the entire database. */
-                               return (it->result);
-                       }
-                       if (it->result != ISC_R_SUCCESS)
-                               return (it->result);
-                       it->result = dns_dbiterator_current(it->dbit,
-                                   &it->node,
-                                   dns_fixedname_name(&it->fixedname));
-                       if (it->result != ISC_R_SUCCESS)
-                               return (it->result);
-                       it->result = dns_db_allrdatasets(it->db, it->node,
-                                        it->ver, it->now,
-                                        &it->rdatasetit);
-                       if (it->result != ISC_R_SUCCESS)
-                               return (it->result);
-                       it->result = dns_rdatasetiter_first(it->rdatasetit);
-               }
-               if (it->result != ISC_R_SUCCESS)
-                       return (it->result);
-               dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
-               it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
-               it->result = dns_rdataset_first(&it->rdataset);
-               if (it->result != ISC_R_SUCCESS)
-                       return (it->result);
-       }
-       return (it->result);
-}
-
-static void
-db_rr_iterator_pause(db_rr_iterator_t *it) {
-       RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS);
-}
-
-static void
-db_rr_iterator_destroy(db_rr_iterator_t *it) {
-       if (dns_rdataset_isassociated(&it->rdataset))
-               dns_rdataset_disassociate(&it->rdataset);
-       if (it->rdatasetit != NULL)
-               dns_rdatasetiter_destroy(&it->rdatasetit);
-       if (it->node != NULL)
-               dns_db_detachnode(it->db, &it->node);
-       dns_dbiterator_destroy(&it->dbit);
-}
-
-static void
-db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
-                     isc_uint32_t *ttl, dns_rdata_t **rdata)
-{
-       REQUIRE(name != NULL && *name == NULL);
-       REQUIRE(it->result == ISC_R_SUCCESS);
-       *name = dns_fixedname_name(&it->fixedname);
-       *ttl = it->rdataset.ttl;
-       dns_rdata_reset(&it->rdata);
-       dns_rdataset_current(&it->rdataset, &it->rdata);
-       *rdata = &it->rdata;
-}
-
 /**************************************************************************/
 
 /*% Log an RR (for debugging) */
@@ -488,7 +313,7 @@ static rrstream_methods_t ixfr_rrstream_methods = {
 
 typedef struct axfr_rrstream {
        rrstream_t              common;
-       db_rr_iterator_t        it;
+       dns_rriterator_t        it;
        isc_boolean_t           it_valid;
 } axfr_rrstream_t;
 
@@ -516,7 +341,7 @@ axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
        s->common.methods = &axfr_rrstream_methods;
        s->it_valid = ISC_FALSE;
 
-       CHECK(db_rr_iterator_init(&s->it, db, ver, 0));
+       CHECK(dns_rriterator_init(&s->it, db, ver, 0));
        s->it_valid = ISC_TRUE;
 
        *sp = (rrstream_t *) s;
@@ -531,7 +356,7 @@ static isc_result_t
 axfr_rrstream_first(rrstream_t *rs) {
        axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
        isc_result_t result;
-       result = db_rr_iterator_first(&s->it);
+       result = dns_rriterator_first(&s->it);
        if (result != ISC_R_SUCCESS)
                return (result);
        /* Skip SOA records. */
@@ -539,11 +364,11 @@ axfr_rrstream_first(rrstream_t *rs) {
                dns_name_t *name_dummy = NULL;
                isc_uint32_t ttl_dummy;
                dns_rdata_t *rdata = NULL;
-               db_rr_iterator_current(&s->it, &name_dummy,
-                                     &ttl_dummy, &rdata);
+               dns_rriterator_current(&s->it, &name_dummy,
+                                      &ttl_dummy, NULL, &rdata);
                if (rdata->type != dns_rdatatype_soa)
                        break;
-               result = db_rr_iterator_next(&s->it);
+               result = dns_rriterator_next(&s->it);
                if (result != ISC_R_SUCCESS)
                        break;
        }
@@ -560,11 +385,11 @@ axfr_rrstream_next(rrstream_t *rs) {
                dns_name_t *name_dummy = NULL;
                isc_uint32_t ttl_dummy;
                dns_rdata_t *rdata = NULL;
-               result = db_rr_iterator_next(&s->it);
+               result = dns_rriterator_next(&s->it);
                if (result != ISC_R_SUCCESS)
                        break;
-               db_rr_iterator_current(&s->it, &name_dummy,
-                                     &ttl_dummy, &rdata);
+               dns_rriterator_current(&s->it, &name_dummy,
+                                      &ttl_dummy, NULL, &rdata);
                if (rdata->type != dns_rdatatype_soa)
                        break;
        }
@@ -576,20 +401,20 @@ axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
                      dns_rdata_t **rdata)
 {
        axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
-       db_rr_iterator_current(&s->it, name, ttl, rdata);
+       dns_rriterator_current(&s->it, name, ttl, NULL, rdata);
 }
 
 static void
 axfr_rrstream_pause(rrstream_t *rs) {
        axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
-       db_rr_iterator_pause(&s->it);
+       dns_rriterator_pause(&s->it);
 }
 
 static void
 axfr_rrstream_destroy(rrstream_t **rsp) {
        axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp;
        if (s->it_valid)
-               db_rr_iterator_destroy(&s->it);
+               dns_rriterator_destroy(&s->it);
        isc_mem_put(s->common.mctx, s, sizeof(*s));
 }
 
index ef5c12a5d0d76fcd1849f57571dca1cae47b6dc5..b8164657ed3cfa95067f0909d4294323dc080ff6 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.163 2008/09/24 02:46:22 marka Exp $
+# $Id: Makefile.in,v 1.164 2009/06/30 02:52:32 each Exp $
 
 srcdir =       @srcdir@
 VPATH =                @srcdir@
@@ -58,14 +58,15 @@ DNSOBJS =   acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \
                cache.@O@ callbacks.@O@ compress.@O@ \
                db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
                dlz.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ journal.@O@ \
-               keytable.@O@ lib.@O@ log.@O@ lookup.@O@ \
+               keydata.@O@ keytable.@O@ lib.@O@ log.@O@ lookup.@O@ \
                master.@O@ masterdump.@O@ message.@O@ \
-               name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ portlist.@O@ \
+               name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ \
+               portlist.@O@ \
                rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rcode.@O@ rdata.@O@ \
                rdatalist.@O@ \
                rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ request.@O@ \
-               resolver.@O@ result.@O@ rootns.@O@ sdb.@O@ sdlz.@O@ \
-               soa.@O@ ssu.@O@ \
+               resolver.@O@ result.@O@ rootns.@O@ rriterator.@O@ sdb.@O@ \
+               sdlz.@O@ soa.@O@ ssu.@O@ \
                stats.@O@ tcpmsg.@O@ time.@O@ timer.@O@ tkey.@O@ \
                tsig.@O@ ttl.@O@ validator.@O@ \
                version.@O@ view.@O@ xfrin.@O@ zone.@O@ zonekey.@O@ zt.@O@
@@ -84,13 +85,13 @@ DNSSRCS =   acache.c acl.c adb.c byaddr.c \
                cache.c callbacks.c compress.c \
                db.c dbiterator.c dbtable.c diff.c dispatch.c \
                dlz.c dnssec.c ds.c forward.c iptable.c journal.c \
-               keytable.c lib.c log.c lookup.c \
+               keydata.c keytable.c lib.c log.c lookup.c \
                master.c masterdump.c message.c \
                name.c ncache.c nsec.c nsec3.c order.c peer.c portlist.c \
                rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c \
                rdatalist.c \
                rdataset.c rdatasetiter.c rdataslab.c request.c \
-               resolver.c result.c rootns.c sdb.c sdlz.c \
+               resolver.c result.c rootns.c rriterator.c sdb.c sdlz.c \
                soa.c ssu.c \
                stats.c tcpmsg.c time.c timer.c tkey.c \
                tsig.c ttl.c validator.c \
index 83430c0bf765ab8b014821e943b7f36ef6faafe6..58726b8eed0fd6607df33c3838ffeaa3f22f98f2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: db.c,v 1.90 2009/04/29 23:48:02 tbox Exp $ */
+/* $Id: db.c,v 1.91 2009/06/30 02:52:32 each Exp $ */
 
 /*! \file */
 
 
 #include <dns/callbacks.h>
 #include <dns/db.h>
+#include <dns/dbiterator.h>
 #include <dns/log.h>
 #include <dns/master.h>
 #include <dns/rdata.h>
 #include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
 #include <dns/result.h>
 
 /***
@@ -926,3 +928,4 @@ dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version
        if (db->methods->resigned != NULL)
                (db->methods->resigned)(db, rdataset, version);
 }
+
index 4fccc216058c32f7a235c640cb36725ae0c60686..aef47515332e38af31efa5b900ea847574dbee58 100644 (file)
@@ -31,7 +31,7 @@
 
 /*
  * Principal Author: Brian Wellington
- * $Id: dst_api.c,v 1.20 2009/06/10 00:27:22 each Exp $
+ * $Id: dst_api.c,v 1.21 2009/06/30 02:52:32 each Exp $
  */
 
 /*! \file */
@@ -1062,6 +1062,16 @@ dst_key_read_public(const char *filename, int type,
        return (ret);
 }
 
+/*%
+ * Set the flags on a key, then recompute the key ID
+ */
+isc_result_t
+dst_key_setflags(dst_key_t *key, isc_uint32_t flags) {
+        REQUIRE(VALID_KEY(key));
+        key->key_flags = flags;
+        return (computeid(key));
+}
+
 static isc_boolean_t
 issymmetric(const dst_key_t *key) {
        REQUIRE(dst_initialized == ISC_TRUE);
index f531ad06500d036937143aeca06e7b1c2a89be7d..7ff8d0d98488d4ee340b0f1a2574148836f5f855 100644 (file)
@@ -29,7 +29,7 @@
  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dst_internal.h,v 1.13 2009/06/11 23:47:55 tbox Exp $ */
+/* $Id: dst_internal.h,v 1.14 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef DST_DST_INTERNAL_H
 #define DST_DST_INTERNAL_H 1
@@ -112,7 +112,7 @@ struct dst_key {
                dst_hmacsha512_key_t *hmacsha512;
 
        } keydata;                      /*%< pointer to key in crypto pkg fmt */
-       dst_func_t *    func;          /*%< crypto package specific functions */
+       dst_func_t *    func;           /*%< crypto package specific functions*/
 };
 
 struct dst_context {
index e4e89efe1c078818f02c4cb4801b2f9c1fd66f9b..db396bed7b11f44906c146936a21bc467c4adf81 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: db.h,v 1.97 2009/05/07 09:41:23 fdupont Exp $ */
+/* $Id: db.h,v 1.98 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef DNS_DB_H
 #define DNS_DB_H 1
 #include <isc/ondestroy.h>
 #include <isc/stdtime.h>
 
+#include <dns/fixedname.h>
 #include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
 #include <dns/types.h>
 
 ISC_LANG_BEGINDECLS
@@ -613,7 +616,7 @@ dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
  *
  * Note: if '*versionp' is a read-write version and 'commit' is ISC_TRUE,
  * then all changes made in the version will take effect, otherwise they
- * will be rolled back.  The value if 'commit' is ignored for read-only
+ * will be rolled back.  The value of 'commit' is ignored for read-only
  * versions.
  *
  * Requires:
index 18659e27f9b7cf2aa5ffeada8728120fdaf7bc2b..ec4aee0185f399b5fb2c6d7b04e675a9882fe8da 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: events.h,v 1.51 2009/05/06 23:47:50 tbox Exp $ */
+/* $Id: events.h,v 1.52 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef DNS_EVENTS_H
 #define DNS_EVENTS_H 1
@@ -69,6 +69,7 @@
 #define DNS_EVENT_ACACHECLEAN                  (ISC_EVENTCLASS_DNS + 39)
 #define DNS_EVENT_ACACHEOVERMEM                        (ISC_EVENTCLASS_DNS + 40)
 #define DNS_EVENT_RBTPRUNE                     (ISC_EVENTCLASS_DNS + 41)
+#define DNS_EVENT_MANAGEKEYS                   (ISC_EVENTCLASS_DNS + 42)
 
 #define DNS_EVENT_FIRSTEVENT                   (ISC_EVENTCLASS_DNS + 0)
 #define DNS_EVENT_LASTEVENT                    (ISC_EVENTCLASS_DNS + 65535)
diff --git a/lib/dns/include/dns/keydata.h b/lib/dns/include/dns/keydata.h
new file mode 100644 (file)
index 0000000..f24ca06
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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: keydata.h,v 1.2 2009/06/30 02:52:32 each Exp $ */
+
+#ifndef DNS_KEYDATA_H
+#define DNS_KEYDATA_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/keydata.h
+ * \brief
+ * KEYDATA utilities.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <dns/types.h>
+#include <dns/rdatastruct.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_keydata_todnskey(dns_rdata_keydata_t *keydata,
+                    dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx);
+
+isc_result_t
+dns_keydata_fromdnskey(dns_rdata_keydata_t *keydata,
+                      dns_rdata_dnskey_t *dnskey,
+                      isc_uint32_t refresh, isc_uint32_t addhd,
+                      isc_uint32_t removehd, isc_mem_t *mctx);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_KEYDATA_H */
index 553aa990b6d7f19543dd5cdd35f1b38cc39bb6c9..2212fd08a3c8c18279f93f0fab6e6999f6e9b68b 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: keytable.h,v 1.16 2007/06/19 23:47:16 tbox Exp $ */
+/* $Id: keytable.h,v 1.17 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef DNS_KEYTABLE_H
 #define DNS_KEYTABLE_H 1
  */
 
 #include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/refcount.h>
+#include <isc/rwlock.h>
+#include <isc/stdtime.h>
 
 #include <dns/types.h>
 
 
 ISC_LANG_BEGINDECLS
 
+struct dns_keytable {
+       /* Unlocked. */
+       unsigned int            magic;
+       isc_mem_t               *mctx;
+       isc_mutex_t             lock;
+       isc_rwlock_t            rwlock;
+       /* Locked by lock. */
+       isc_uint32_t            active_nodes;
+       /* Locked by rwlock. */
+       isc_uint32_t            references;
+       dns_rbt_t               *table;
+};
+
+#define KEYTABLE_MAGIC                 ISC_MAGIC('K', 'T', 'b', 'l')
+#define VALID_KEYTABLE(kt)             ISC_MAGIC_VALID(kt, KEYTABLE_MAGIC)
+
+struct dns_keynode {
+       unsigned int            magic;
+       isc_refcount_t          refcount;
+       dst_key_t *             key;
+       isc_boolean_t           managed;
+       struct dns_keynode *    next;
+};
+
+#define KEYNODE_MAGIC                  ISC_MAGIC('K', 'N', 'o', 'd')
+#define VALID_KEYNODE(kn)              ISC_MAGIC_VALID(kn, KEYNODE_MAGIC)
+
 isc_result_t
 dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep);
 /*%<
@@ -106,16 +137,22 @@ dns_keytable_detach(dns_keytable_t **keytablep);
  */
 
 isc_result_t
-dns_keytable_add(dns_keytable_t *keytable, dst_key_t **keyp);
+dns_keytable_add(dns_keytable_t *keytable, isc_boolean_t managed,
+                dst_key_t **keyp);
 /*%<
- * Add '*keyp' to 'keytable'.
+ * Add '*keyp' to 'keytable' (using the name in '*keyp').
+ * The value of keynode->managed is set to 'managed'
  *
  * Notes:
  *
  *\li  Ownership of *keyp is transferred to the keytable.
+ *\li   If the key already exists in the table, ISC_R_EXISTS is
+ *      returned and the new key is freed.
  *
  * Requires:
  *
+ *\li  'keytable' points to a valid keytable.
+ *
  *\li  keyp != NULL && *keyp is a valid dst_key_t *.
  *
  * Ensures:
@@ -125,10 +162,123 @@ dns_keytable_add(dns_keytable_t *keytable, dst_key_t **keyp);
  * Returns:
  *
  *\li  ISC_R_SUCCESS
+ *\li  ISC_R_EXISTS
+ *
+ *\li  Any other result indicates failure.
+ */
+
+isc_result_t
+dns_keytable_marksecure(dns_keytable_t *keytable, dns_name_t *name);
+/*%<
+ * Add a null key to 'keytable' for name 'name'.  This marks the 
+ * name as a secure domain, but doesn't supply any key data to allow the
+ * domain to be validated.  (Used when automated trust anchor management
+ * has gotten broken by a zone misconfiguration; for exmaple, when the
+ * active key has been revoked but the stand-by key was still in its 30-day
+ * waiting period for validity.)
+ *
+ * Notes:
+ *
+ *\li   If a key already exists in the table, ISC_R_EXISTS is
+ *      returned and nothing is done.
+ *
+ * Requires:
+ *
+ *\li  'keytable' points to a valid keytable.
+ *
+ *\li  keyp != NULL && *keyp is a valid dst_key_t *.
+ *
+ * Returns:
+ *
+ *\li  ISC_R_SUCCESS
+ *\li  ISC_R_EXISTS
  *
  *\li  Any other result indicates failure.
  */
 
+isc_result_t
+dns_keytable_delete(dns_keytable_t *keytable, dns_name_t *keyname);
+/*%<
+ * Delete node(s) from 'keytable' matching name 'keyname'
+ * 
+ * Requires:
+ *
+ *\li  'keytable' points to a valid keytable.
+ *
+ *\li  'name' is not NULL
+ *
+ * Returns:
+ *
+ *\li  ISC_R_SUCCESS
+ *
+ *\li  Any other result indicates failure.
+ */
+
+isc_result_t
+dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey);
+/*%<
+ * Delete node(s) from 'keytable' containing copies of the key pointed
+ * to by 'dstkey'
+ * 
+ * Requires:
+ *
+ *\li  'keytable' points to a valid keytable.
+ *\li  'dstkey' is not NULL 
+ *
+ * Returns:
+ *
+ *\li  ISC_R_SUCCESS
+ *
+ *\li  Any other result indicates failure.
+ */
+
+isc_result_t
+dns_keytable_find(dns_keytable_t *keytable, dns_name_t *keyname,
+                 dns_keynode_t **keynodep);
+/*%<
+ * Search for the first instance of a key named 'name' in 'keytable',
+ * without regard to keyid and algorithm.  Use dns_keytable_nextkeynode()
+ * to find subsequent instances.
+ *
+ * Requires:
+ *
+ *\li  'keytable' is a valid keytable.
+ *
+ *\li  'name' is a valid absolute name.
+ *
+ *\li  keynodep != NULL && *keynodep == NULL
+ *
+ * Returns:
+ *
+ *\li  ISC_R_SUCCESS
+ *\li  ISC_R_NOTFOUND
+ *
+ *\li  Any other result indicates an error.
+ */
+
+isc_result_t
+dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
+                        dns_keynode_t **nextnodep);
+/*%<
+ * Return for the next key after 'keynode' in 'keytable', without regard to
+ * keyid and algorithm.
+ *
+ * Requires:
+ *
+ *\li  'keytable' is a valid keytable.
+ *
+ *\li  'keynode' is a valid keynode.
+ *
+ *\li  nextnodep != NULL && *nextnodep == NULL
+ *
+ * Returns:
+ *
+ *\li  ISC_R_SUCCESS
+ *\li  ISC_R_NOTFOUND
+ *
+ *\li  Any other result indicates an error.
+ */
+
 isc_result_t
 dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
                         dns_secalg_t algorithm, dns_keytag_t tag,
@@ -250,6 +400,30 @@ dns_keynode_key(dns_keynode_t *keynode);
  * Get the DST key associated with keynode.
  */
 
+isc_boolean_t
+dns_keynode_managed(dns_keynode_t *keynode);
+/*%<
+ * Is this flagged as a managed key?
+ */
+
+isc_result_t
+dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target);
+/*%<
+ * Allocate space for a keynode
+ */
+
+void
+dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target);
+/*%<
+ * Attach keynode 'source' to '*target'
+ */
+
+void
+dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **target);
+/*%<
+ * Detach keynode.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_KEYTABLE_H */
index eef496c9af785883460bda479951e0a55b7994ce..38d78fabc97ea80201afbd7fd76bef00c50cfbf3 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: keyvalues.h,v 1.25 2009/06/04 02:56:47 tbox Exp $ */
+/* $Id: keyvalues.h,v 1.26 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef DNS_KEYVALUES_H
 #define DNS_KEYVALUES_H 1
@@ -42,7 +42,7 @@
 #define DNS_KEYOWNER_ENTITY    0x0200  /*%< key is assoc. with entity eg host */
 #define DNS_KEYOWNER_ZONE      0x0100  /*%< key is zone key */
 #define DNS_KEYOWNER_RESERVED  0x0300  /*%< reserved meaning */
-#define DNS_KEYFLAG_REVOKE     0x0080  /*%< key revoked (per rfc5001) */
+#define DNS_KEYFLAG_REVOKE     0x0080  /*%< key revoked (per rfc5011) */
 #define DNS_KEYFLAG_RESERVED9  0x0040  /*%< reserved - must be zero */
 #define DNS_KEYFLAG_RESERVED10 0x0020  /*%< reserved - must be zero */
 #define DNS_KEYFLAG_RESERVED11 0x0010  /*%< reserved - must be zero */
@@ -51,7 +51,6 @@
 #define DNS_KEYFLAG_RESERVEDMASK (DNS_KEYFLAG_RESERVED2 | \
                                  DNS_KEYFLAG_RESERVED4 | \
                                  DNS_KEYFLAG_RESERVED5 | \
-                                 DNS_KEYFLAG_RESERVED8 | \
                                  DNS_KEYFLAG_RESERVED9 | \
                                  DNS_KEYFLAG_RESERVED10 | \
                                  DNS_KEYFLAG_RESERVED11 )
index 93a782d82c1ae6736a060a4a62fa528fc7fb14e0..74888a7f427e9ade10321f498af33d5717289c10 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: master.h,v 1.51 2008/04/02 02:37:42 marka Exp $ */
+/* $Id: master.h,v 1.52 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef DNS_MASTER_H
 #define DNS_MASTER_H 1
@@ -56,6 +56,7 @@
 #define DNS_MASTER_CHECKMXFAIL 0x00001000
 
 #define DNS_MASTER_RESIGN      0x00002000
+#define DNS_MASTER_KEY         0x00004000      /*%< Loading a key zone master file. */
 
 ISC_LANG_BEGINDECLS
 
index f42fcbb23c0a5a79492df047ead5b6baf31a06d3..4c6c5231126daa58e80914478e63f589ab8b24ed 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: name.h,v 1.129 2009/03/11 07:02:34 each Exp $ */
+/* $Id: name.h,v 1.130 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef DNS_NAME_H
 #define DNS_NAME_H 1
@@ -1165,6 +1165,46 @@ dns_name_fromstring(dns_name_t *target, const char *src, isc_mem_t *mctx);
  *\li  Any error that dns_name_dup() can return.
  */
 
+isc_result_t
+dns_name_tostring(dns_name_t *source, char **target, isc_mem_t *mctx);
+/*%<
+ * Convert 'name' to string format, allocating sufficient memory to
+ * hold it (free with isc_mem_free()).
+ *
+ * Differs from dns_name_format in that it allocates its own memory.
+ *
+ * Requires:
+ *
+ *\li  'name' is a valid name.
+ *\li  'target' is not NULL.
+ *\li  '*target' is NULL.
+ *
+ * Returns:
+ *
+ *\li  ISC_R_SUCCESS
+ *
+ *\li  Any error that dns_name_totext() can return.
+ */
+
+isc_result_t
+dns_name_fromstring(dns_name_t *target, const char *src, isc_mem_t *mctx);
+/*%<
+ * Convert a string to a name and place it in target, allocating memory
+ * as necessary.
+ *
+ * Requires:
+ *
+ * \li 'target' is a valid name that is not read-only.
+ *
+ * Returns:
+ *
+ *\li  #ISC_R_SUCCESS
+ *
+ *\li  Any error that dns_name_fromtext() can return.
+ *
+ *\li  Any error that dns_name_dup() can return.
+ */
+
 isc_result_t
 dns_name_settotextfilter(dns_name_totextfilter_t proc);
 /*%<
diff --git a/lib/dns/include/dns/rriterator.h b/lib/dns/include/dns/rriterator.h
new file mode 100644 (file)
index 0000000..0e4b0a4
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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: rriterator.h,v 1.2 2009/06/30 02:52:32 each Exp $ */
+
+#ifndef DNS_RRITERATOR_H
+#define DNS_RRITERATOR_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/rriterator.h
+ * \brief
+ * Functions for "walking" a zone database, visiting each RR or RRset in turn.
+ */
+
+/*****
+ ***** Imports
+ *****/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/ondestroy.h>
+#include <isc/stdtime.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Types
+ *****/
+
+/*%
+ * A dns_rriterator_t is an iterator that iterates over an entire database,
+ * returning one RR at a time, in some arbitrary order.
+ */
+
+typedef struct dns_rriterator {
+       unsigned int            magic;
+       isc_result_t            result;
+       dns_db_t                *db;
+       dns_dbiterator_t        *dbit;
+       dns_dbversion_t         *ver;
+       isc_stdtime_t           now;
+       dns_dbnode_t            *node;
+       dns_fixedname_t         fixedname;
+       dns_rdatasetiter_t      *rdatasetit;
+       dns_rdataset_t          rdataset;
+       dns_rdata_t             rdata;
+} dns_rriterator_t;
+
+#define RRITERATOR_MAGIC               ISC_MAGIC('R', 'R', 'I', 't')
+#define VALID_RRITERATOR(m)            ISC_MAGIC_VALID(m, RRITERATOR_MAGIC)
+
+isc_result_t
+dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db,
+                      dns_dbversion_t *ver, isc_stdtime_t now);
+
+isc_result_t
+dns_rriterator_first(dns_rriterator_t *it);
+
+isc_result_t
+dns_rriterator_nextrrset(dns_rriterator_t *it);
+
+isc_result_t
+dns_rriterator_next(dns_rriterator_t *it);
+
+void
+dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name,
+                         isc_uint32_t *ttl, dns_rdataset_t **rdataset,
+                         dns_rdata_t **rdata);
+
+void
+dns_rriterator_pause(dns_rriterator_t *it);
+
+void
+dns_rriterator_destroy(dns_rriterator_t *it);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RRITERATOR_H */
index bb563655cea7b01e656bb67162717840184f07ad..a57939a24f03dff0b93eedacca9e8afe82198e29 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: soa.h,v 1.9 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id: soa.h,v 1.10 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef DNS_SOA_H
 #define DNS_SOA_H 1
 
 ISC_LANG_BEGINDECLS
 
+isc_result_t
+dns_soa_buildrdata(dns_name_t *origin, dns_name_t *contact,
+                  dns_rdataclass_t rdclass,
+                  isc_uint32_t serial, isc_uint32_t refresh, 
+                  isc_uint32_t retry, isc_uint32_t expire, 
+                  isc_uint32_t minimum, dns_rdata_t *rdata);
 isc_uint32_t
 dns_soa_getserial(dns_rdata_t *rdata);
 isc_uint32_t
index 292ec600429b3a9b2f7e5c5c4405ffe5d2ca1a05..d6d97b05af44ff9a4b2388be16abc7634369b33b 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: types.h,v 1.133 2009/01/27 22:29:59 jinmei Exp $ */
+/* $Id: types.h,v 1.134 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef DNS_TYPES_H
 #define DNS_TYPES_H 1
@@ -72,6 +72,7 @@ typedef struct dns_iptable                    dns_iptable_t;
 typedef isc_uint32_t                           dns_iterations_t;
 typedef isc_uint16_t                           dns_keyflags_t;
 typedef struct dns_keynode                     dns_keynode_t;
+typedef ISC_LIST(dns_keynode_t)                        dns_keynodelist_t;
 typedef struct dns_keytable                    dns_keytable_t;
 typedef isc_uint16_t                           dns_keytag_t;
 typedef struct dns_loadctx                     dns_loadctx_t;
index d275b10fb69a6c4af36d314b18a23605496a28f7..0f511384d15a3a6b60384c3ec3bb98eb5a96ca41 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.h,v 1.117 2009/05/29 22:22:37 jinmei Exp $ */
+/* $Id: view.h,v 1.118 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef DNS_VIEW_H
 #define DNS_VIEW_H 1
@@ -92,8 +92,7 @@ struct dns_view {
        dns_cache_t *                   cache;
        dns_db_t *                      cachedb;
        dns_db_t *                      hints;
-       dns_keytable_t *                secroots;
-       dns_keytable_t *                trustedkeys;
+       dns_keytable_t *                secroots;   /* security roots */
        isc_mutex_t                     lock;
        isc_boolean_t                   frozen;
        isc_task_t *                    task;
@@ -165,6 +164,7 @@ struct dns_view {
        unsigned int                    attributes;
        /* Under owner's locking control. */
        ISC_LINK(struct dns_view)       link;
+       dns_viewlist_t *                viewlist;
 };
 
 #define DNS_VIEW_MAGIC                 ISC_MAGIC('V','i','e','w')
index b917b4d651ed89bde9bf3aed20ffc26319091c79..0f5c0023007fa93182f6a83fff25c9e9138a96b9 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: zone.h,v 1.164 2009/01/27 22:29:59 jinmei Exp $ */
+/* $Id: zone.h,v 1.165 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef DNS_ZONE_H
 #define DNS_ZONE_H 1
@@ -40,7 +40,8 @@ typedef enum {
        dns_zone_none,
        dns_zone_master,
        dns_zone_slave,
-       dns_zone_stub
+       dns_zone_stub,
+       dns_zone_key
 } dns_zonetype_t;
 
 #define DNS_ZONEOPT_SERVERS      0x00000001U   /*%< perform server checks */
index 0708e5fb04979aff5eb9d8d8912c372d77b214a1..b122a6addb35bb8a42eaf8033e65f8627fe320a5 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dst.h,v 1.14 2009/06/11 23:47:55 tbox Exp $ */
+/* $Id: dst.h,v 1.15 2009/06/30 02:52:32 each Exp $ */
 
 #ifndef DST_DST_H
 #define DST_DST_H 1
@@ -639,6 +639,15 @@ dst_key_setbits(dst_key_t *key, isc_uint16_t bits);
  *     "key" is a valid key.
  */
 
+isc_result_t
+dst_key_setflags(dst_key_t *key, isc_uint32_t flags);
+/*
+ * Set the key flags, and recompute the key ID.
+ *
+ * Requires:
+ *     "key" is a valid key.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* DST_DST_H */
diff --git a/lib/dns/keydata.c b/lib/dns/keydata.c
new file mode 100644 (file)
index 0000000..588e31e
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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: keydata.c,v 1.2 2009/06/30 02:52:32 each Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/rdata.h>
+#include <dns/rdatastruct.h>
+#include <dns/keydata.h>
+
+isc_result_t
+dns_keydata_todnskey(dns_rdata_keydata_t *keydata,
+                    dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx)
+{
+       REQUIRE(keydata != NULL && dnskey != NULL);
+
+       dnskey->common.rdtype = dns_rdatatype_dnskey;
+       dnskey->common.rdclass = keydata->common.rdclass;
+       dnskey->mctx = mctx;
+       dnskey->flags = keydata->flags;
+       dnskey->protocol = keydata->protocol;
+       dnskey->algorithm = keydata->algorithm;
+
+       dnskey->datalen = keydata->datalen;
+
+       if (mctx == NULL)
+               dnskey->data = keydata->data;
+       else {
+               dnskey->data = isc_mem_allocate(mctx, dnskey->datalen);
+               if (dnskey->data == NULL)
+                       return (ISC_R_NOMEMORY);
+               memcpy(dnskey->data, keydata->data, dnskey->datalen);
+       }
+
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_keydata_fromdnskey(dns_rdata_keydata_t *keydata,
+                      dns_rdata_dnskey_t *dnskey,
+                      isc_uint32_t refresh, isc_uint32_t addhd,
+                      isc_uint32_t removehd, isc_mem_t *mctx)
+{
+       REQUIRE(keydata != NULL && dnskey != NULL);
+
+       keydata->common.rdtype = dns_rdatatype_keydata;
+       keydata->common.rdclass = dnskey->common.rdclass;
+       keydata->mctx = mctx;
+       keydata->refresh = refresh;
+       keydata->addhd = addhd;
+       keydata->removehd = removehd;
+       keydata->flags = dnskey->flags;
+       keydata->protocol = dnskey->protocol;
+       keydata->algorithm = dnskey->algorithm;
+
+       keydata->datalen = dnskey->datalen;
+       if (mctx == NULL) 
+               keydata->data = dnskey->data;
+       else {
+               keydata->data = isc_mem_allocate(mctx, keydata->datalen);
+               if (keydata->data == NULL)
+                       return (ISC_R_NOMEMORY);
+               memcpy(keydata->data, dnskey->data, keydata->datalen);
+       }
+
+       return (ISC_R_SUCCESS);
+}
index bffd2d3ac741364148d14fb0a597b7a6e366116e..32cc494dacb5e5e69e86f64b34d5578571e0b3a1 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: keytable.c,v 1.34 2007/06/19 23:47:16 tbox Exp $ */
+/* $Id: keytable.c,v 1.35 2009/06/30 02:52:32 each Exp $ */
 
 /*! \file */
 
 #include <dns/rbt.h>
 #include <dns/result.h>
 
-struct dns_keytable {
-       /* Unlocked. */
-       unsigned int            magic;
-       isc_mem_t               *mctx;
-       isc_mutex_t             lock;
-       isc_rwlock_t            rwlock;
-       /* Locked by lock. */
-       isc_uint32_t            active_nodes;
-       /* Locked by rwlock. */
-       isc_uint32_t            references;
-       dns_rbt_t               *table;
-};
-
-#define KEYTABLE_MAGIC                 ISC_MAGIC('K', 'T', 'b', 'l')
-#define VALID_KEYTABLE(kt)             ISC_MAGIC_VALID(kt, KEYTABLE_MAGIC)
-
-struct dns_keynode {
-       unsigned int            magic;
-       dst_key_t *             key;
-       struct dns_keynode *    next;
-};
-
-#define KEYNODE_MAGIC                  ISC_MAGIC('K', 'N', 'o', 'd')
-#define VALID_KEYNODE(kn)              ISC_MAGIC_VALID(kn, KEYNODE_MAGIC)
-
 static void
 free_keynode(void *node, void *arg) {
        dns_keynode_t *keynode = node;
        isc_mem_t *mctx = arg;
 
-       REQUIRE(VALID_KEYNODE(keynode));
-       dst_key_free(&keynode->key);
-       if (keynode->next != NULL)
-               free_keynode(keynode->next, mctx);
-       isc_mem_put(mctx, keynode, sizeof(dns_keynode_t));
+       dns_keynode_detach(mctx, &keynode);
 }
 
 isc_result_t
@@ -116,7 +87,6 @@ dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
        return (result);
 }
 
-
 void
 dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) {
 
@@ -173,49 +143,218 @@ dns_keytable_detach(dns_keytable_t **keytablep) {
        *keytablep = NULL;
 }
 
-isc_result_t
-dns_keytable_add(dns_keytable_t *keytable, dst_key_t **keyp) {
+static isc_result_t
+insert(dns_keytable_t *keytable, isc_boolean_t managed,
+       dns_name_t *keyname, dst_key_t **keyp)
+{
        isc_result_t result;
-       dns_keynode_t *knode;
+       dns_keynode_t *knode = NULL;
        dns_rbtnode_t *node;
-       dns_name_t *keyname;
-
-       /*
-        * Add '*keyp' to 'keytable'.
-        */
 
+       REQUIRE(keyp == NULL || *keyp != NULL);
        REQUIRE(VALID_KEYTABLE(keytable));
-       REQUIRE(keyp != NULL);
 
-       keyname = dst_key_name(*keyp);
+       result = dns_keynode_create(keytable->mctx, &knode);
+       if (result != ISC_R_SUCCESS)
+               return (result);
 
-       knode = isc_mem_get(keytable->mctx, sizeof(*knode));
-       if (knode == NULL)
-               return (ISC_R_NOMEMORY);
+       knode->managed = managed;
 
        RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
 
        node = NULL;
        result = dns_rbt_addnode(keytable->table, keyname, &node);
 
-       if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
-               knode->magic = KEYNODE_MAGIC;
-               knode->key = *keyp;
-               knode->next = node->data;
+       if (keyp != NULL) {
+               if (result == ISC_R_EXISTS) {
+                       /* Key already in table? */
+                       dns_keynode_t *k;
+                       for (k = node->data; k != NULL; k = k->next) {
+                               if (k->key == NULL) {
+                                       k->key = *keyp;
+                                       break;
+                               }
+                               if (dst_key_compare(k->key, *keyp) == ISC_TRUE)
+                                       break;
+                       }
+                       if (k == NULL)
+                               result = ISC_R_SUCCESS;
+                       else
+                               dst_key_free(keyp);
+               }
+
+               if (result == ISC_R_SUCCESS) {
+                       knode->key = *keyp;
+                       knode->next = node->data;
+                       *keyp = NULL;
+               }
+       }
+
+       if (result == ISC_R_SUCCESS) {
                node->data = knode;
-               *keyp = NULL;
                knode = NULL;
-               result = ISC_R_SUCCESS;
        }
 
        RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
 
        if (knode != NULL)
-               isc_mem_put(keytable->mctx, knode, sizeof(*knode));
+               dns_keynode_detach(keytable->mctx, &knode);
+
+       return (result);
+}
+
+isc_result_t
+dns_keytable_add(dns_keytable_t *keytable, isc_boolean_t managed,
+                dst_key_t **keyp)
+{ 
+       REQUIRE(keyp != NULL && *keyp != NULL);
+       return (insert(keytable, managed, dst_key_name(*keyp), keyp));
+}
+
+isc_result_t
+dns_keytable_marksecure(dns_keytable_t *keytable, dns_name_t *name) {
+       return (insert(keytable, ISC_TRUE, name, NULL));
+}
+
+isc_result_t
+dns_keytable_delete(dns_keytable_t *keytable, dns_name_t *keyname) {
+       isc_result_t result;
+       dns_rbtnode_t *node = NULL;
+
+       REQUIRE(VALID_KEYTABLE(keytable));
+       REQUIRE(keyname != NULL);
+       
+       RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
+       result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
+                                 DNS_RBTFIND_NOOPTIONS, NULL, NULL);
+       if (result == ISC_R_SUCCESS) {
+               if (node->data != NULL)
+                       result = dns_rbt_deletenode(keytable->table,
+                                                   node, ISC_FALSE);
+               else
+                       result = ISC_R_NOTFOUND;
+       } else if (result == DNS_R_PARTIALMATCH)
+               result = ISC_R_NOTFOUND;
+       RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
+
+       return (result);
+}
+
+isc_result_t
+dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey) {
+       isc_result_t result;
+       dns_name_t *keyname;
+       dns_rbtnode_t *node = NULL;
+       dns_keynode_t *knode = NULL, **kprev = NULL;
+
+       REQUIRE(VALID_KEYTABLE(keytable));
+       REQUIRE(dstkey != NULL);
+
+       keyname = dst_key_name(dstkey);
+
+       RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
+       result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
+                                 DNS_RBTFIND_NOOPTIONS, NULL, NULL);
+
+       if (result == DNS_R_PARTIALMATCH)
+               result = ISC_R_NOTFOUND;
+       if (result != ISC_R_SUCCESS)
+               goto finish;
+
+       if (node->data == NULL) {
+               result = ISC_R_NOTFOUND;
+               goto finish;
+       }
+
+       knode = node->data;
+       if (knode->next == NULL && 
+           (knode->key == NULL ||
+            dst_key_compare(knode->key, dstkey) == ISC_TRUE)) {
+               result = dns_rbt_deletenode(keytable->table, node, ISC_FALSE);
+               goto finish;
+       }
+               
+       kprev = (dns_keynode_t **) &node->data;
+       while (knode != NULL) {
+               if (dst_key_compare(knode->key, dstkey) == ISC_TRUE) 
+                       break;
+               kprev = &knode;
+               knode = knode->next;
+       }
+
+       if (knode != NULL) {
+               if (knode->key != NULL)
+                       dst_key_free(&knode->key);
+               /*
+                * This is equivalent to:
+                * dns_keynode_attach(knode->next, &tmp);
+                * dns_keynode_detach(kprev);
+                * dns_keynode_attach(tmp, &kprev);
+                * dns_keynode_detach(&tmp);
+                */
+               *kprev = knode->next;
+               knode->next = NULL;
+               dns_keynode_detach(keytable->mctx, &knode);
+       } else
+               result = DNS_R_PARTIALMATCH;
+  finish:
+       RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
+       return (result);
+}
+
+isc_result_t
+dns_keytable_find(dns_keytable_t *keytable, dns_name_t *keyname,
+                 dns_keynode_t **keynodep)
+{
+       isc_result_t result;
+       dns_rbtnode_t *node = NULL;
+
+       REQUIRE(VALID_KEYTABLE(keytable));
+       REQUIRE(keyname != NULL);
+       REQUIRE(keynodep != NULL && *keynodep == NULL);
+       
+       RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
+       result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
+                                 DNS_RBTFIND_NOOPTIONS, NULL, NULL);
+       if (result == ISC_R_SUCCESS) {
+               if (node->data != NULL) {
+                       LOCK(&keytable->lock);
+                       keytable->active_nodes++;
+                       UNLOCK(&keytable->lock);
+                       dns_keynode_attach(node->data, keynodep);
+               } else
+                       result = ISC_R_NOTFOUND;
+       } else if (result == DNS_R_PARTIALMATCH)
+               result = ISC_R_NOTFOUND;
+       RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
 
        return (result);
 }
 
+isc_result_t
+dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
+                        dns_keynode_t **nextnodep)
+{
+       /*
+        * Return the next key after 'keynode', regardless of
+        * properties.
+        */
+
+       REQUIRE(VALID_KEYTABLE(keytable));
+       REQUIRE(VALID_KEYNODE(keynode));
+       REQUIRE(nextnodep != NULL && *nextnodep == NULL);
+
+       if (keynode->next == NULL)
+               return (ISC_R_NOTFOUND);
+
+       dns_keynode_attach(keynode->next, nextnodep);
+       LOCK(&keytable->lock);
+       keytable->active_nodes++;
+       UNLOCK(&keytable->lock);
+
+       return (ISC_R_SUCCESS);
+}
+
 isc_result_t
 dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
                         dns_secalg_t algorithm, dns_keytag_t tag,
@@ -250,6 +389,10 @@ dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
        if (result == ISC_R_SUCCESS) {
                INSIST(data != NULL);
                for (knode = data; knode != NULL; knode = knode->next) {
+                       if (knode->key == NULL) {
+                               knode = NULL;
+                               break;
+                       }
                        if (algorithm == dst_key_alg(knode->key)
                            && tag == dst_key_id(knode->key))
                                break;
@@ -258,7 +401,7 @@ dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
                        LOCK(&keytable->lock);
                        keytable->active_nodes++;
                        UNLOCK(&keytable->lock);
-                       *keynodep = knode;
+                       dns_keynode_attach(knode, keynodep);
                } else
                        result = DNS_R_PARTIALMATCH;
        } else if (result == DNS_R_PARTIALMATCH)
@@ -286,6 +429,10 @@ dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
        REQUIRE(nextnodep != NULL && *nextnodep == NULL);
 
        for (knode = keynode->next; knode != NULL; knode = knode->next) {
+               if (knode->key == NULL) {
+                       knode = NULL;
+                       break;
+               }
                if (dst_key_alg(keynode->key) == dst_key_alg(knode->key) &&
                    dst_key_id(keynode->key) == dst_key_id(knode->key))
                        break;
@@ -295,7 +442,7 @@ dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
                keytable->active_nodes++;
                UNLOCK(&keytable->lock);
                result = ISC_R_SUCCESS;
-               *nextnodep = knode;
+               dns_keynode_attach(knode, nextnodep);
        } else
                result = ISC_R_NOTFOUND;
 
@@ -345,7 +492,7 @@ dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
        keytable->active_nodes--;
        UNLOCK(&keytable->lock);
 
-       *keynodep = NULL;
+       dns_keynode_detach(keytable->mctx, keynodep);
 }
 
 isc_result_t
@@ -393,3 +540,61 @@ dns_keynode_key(dns_keynode_t *keynode) {
 
        return (keynode->key);
 }
+
+isc_boolean_t
+dns_keynode_managed(dns_keynode_t *keynode) {
+       /*
+        * Is this a managed key?
+        */
+       REQUIRE(VALID_KEYNODE(keynode));
+
+       return (keynode->managed);
+}
+
+isc_result_t
+dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
+       isc_result_t result;
+       dns_keynode_t *knode = NULL;
+
+       REQUIRE(target != NULL && *target == NULL);
+
+       knode = isc_mem_get(mctx, sizeof(dns_keynode_t));
+       if (knode == NULL)
+               return (ISC_R_NOMEMORY);
+
+       knode->magic = KEYNODE_MAGIC;
+       knode->managed = ISC_FALSE;
+       knode->key = NULL;
+       knode->next = NULL;
+
+       result = isc_refcount_init(&knode->refcount, 1);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+
+       *target = knode;
+       return (ISC_R_SUCCESS);
+}
+
+void
+dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
+       REQUIRE(VALID_KEYNODE(source));
+       isc_refcount_increment(&source->refcount, NULL);
+       *target = source;
+}
+
+void
+dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) {
+       unsigned int refs;
+       dns_keynode_t *node = *keynode;
+       REQUIRE(VALID_KEYNODE(node));
+       isc_refcount_decrement(&node->refcount, &refs);
+       if (refs == 0) {
+               if (node->key != NULL)
+                       dst_key_free(&node->key);
+               if (node->next != NULL)
+                       dns_keynode_detach(mctx, &node->next);
+               isc_refcount_destroy(&node->refcount);
+               isc_mem_put(mctx, node, sizeof(dns_keynode_t));
+       }
+       *keynode = NULL;
+}
index ec45a720002c8fbada22a2c4c87eba5c3bd86f89..35543520ba7f4c3a80f312f3b6563e6da74f1eb3 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: master.c,v 1.176 2009/02/16 03:19:40 marka Exp $ */
+/* $Id: master.c,v 1.177 2009/06/30 02:52:32 each Exp $ */
 
 /*! \file */
 
@@ -862,6 +862,7 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
 
                if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
                    (lctx->options & DNS_MASTER_SLAVE) == 0 &&
+                   (lctx->options & DNS_MASTER_KEY) == 0 &&
                    !dns_name_issubdomain(owner, lctx->top))
                {
                        char namebuf[DNS_NAME_FORMATSIZE];
@@ -1502,6 +1503,7 @@ load_text(dns_loadctx_t *lctx) {
                        }
                        if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
                            (lctx->options & DNS_MASTER_SLAVE) == 0 &&
+                           (lctx->options & DNS_MASTER_KEY) == 0 &&
                            !dns_name_issubdomain(new_name, lctx->top))
                        {
                                char namebuf[DNS_NAME_FORMATSIZE];
diff --git a/lib/dns/rdata/generic/keydata_65533.c b/lib/dns/rdata/generic/keydata_65533.c
new file mode 100644 (file)
index 0000000..0d374a0
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * 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: keydata_65533.c,v 1.2 2009/06/30 02:52:32 each Exp $ */
+
+#ifndef GENERIC_KEYDATA_65533_C
+#define GENERIC_KEYDATA_65533_C 1
+
+#include <dst/dst.h>
+
+#define RRTYPE_KEYDATA_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+
+static inline isc_result_t
+fromtext_keydata(ARGS_FROMTEXT) {
+       isc_token_t token;
+       dns_secalg_t alg;
+       dns_secproto_t proto;
+       dns_keyflags_t flags;
+       isc_uint32_t refresh, addhd, removehd;
+
+       REQUIRE(type == 65533);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(origin);
+       UNUSED(options);
+       UNUSED(callbacks);
+
+       /* refresh timer */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &refresh));
+       RETERR(uint32_tobuffer(refresh, target));
+
+       /* add hold-down */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &addhd));
+       RETERR(uint32_tobuffer(addhd, target));
+
+       /* remove hold-down */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &removehd));
+       RETERR(uint32_tobuffer(removehd, target));
+
+       /* flags */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion));
+       RETERR(uint16_tobuffer(flags, target));
+
+       /* protocol */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion));
+       RETERR(mem_tobuffer(target, &proto, 1));
+
+       /* algorithm */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
+       RETERR(mem_tobuffer(target, &alg, 1));
+
+       /* No Key? */
+       if ((flags & 0xc000) == 0xc000)
+               return (ISC_R_SUCCESS);
+
+       return (isc_base64_tobuffer(lexer, target, -1));
+}
+
+static inline isc_result_t
+totext_keydata(ARGS_TOTEXT) {
+       isc_region_t sr;
+       char buf[sizeof("64000")];
+       unsigned int flags;
+       unsigned char algorithm;
+       unsigned long when;
+
+       REQUIRE(rdata->type == 65533);
+       REQUIRE(rdata->length != 0);
+
+       dns_rdata_toregion(rdata, &sr);
+
+       /* refresh timer */
+       when = uint32_fromregion(&sr);
+       isc_region_consume(&sr, 4);
+       RETERR(dns_time32_totext(when, target));
+       RETERR(str_totext(" ", target));
+
+       /* add hold-down */
+       when = uint32_fromregion(&sr);
+       isc_region_consume(&sr, 4);
+       RETERR(dns_time32_totext(when, target));
+       RETERR(str_totext(" ", target));
+
+       /* remove hold-down */
+       when = uint32_fromregion(&sr);
+       isc_region_consume(&sr, 4);
+       RETERR(dns_time32_totext(when, target));
+       RETERR(str_totext(" ", target));
+
+       /* flags */
+       flags = uint16_fromregion(&sr);
+       isc_region_consume(&sr, 2);
+       sprintf(buf, "%u", flags);
+       RETERR(str_totext(buf, target));
+       RETERR(str_totext(" ", target));
+
+       /* protocol */
+       sprintf(buf, "%u", sr.base[0]);
+       isc_region_consume(&sr, 1);
+       RETERR(str_totext(buf, target));
+       RETERR(str_totext(" ", target));
+
+       /* algorithm */
+       algorithm = sr.base[0];
+       sprintf(buf, "%u", algorithm);
+       isc_region_consume(&sr, 1);
+       RETERR(str_totext(buf, target));
+
+       /* No Key? */
+       if ((flags & 0xc000) == 0xc000)
+               return (ISC_R_SUCCESS);
+
+       /* key */
+       if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(" (", target));
+       RETERR(str_totext(tctx->linebreak, target));
+       RETERR(isc_base64_totext(&sr, tctx->width - 2,
+                                tctx->linebreak, target));
+
+       if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0)
+               RETERR(str_totext(tctx->linebreak, target));
+       else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(" ", target));
+
+       if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(")", target));
+
+       if ((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0) {
+               isc_region_t tmpr;
+
+               RETERR(str_totext(" ; key id = ", target));
+               dns_rdata_toregion(rdata, &tmpr);
+               /* Skip over refresh, addhd, and removehd */
+               isc_region_consume(&tmpr, 12);
+               sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm));
+               RETERR(str_totext(buf, target));
+       }
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_keydata(ARGS_FROMWIRE) {
+       isc_region_t sr;
+
+       REQUIRE(type == 65533);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(dctx);
+       UNUSED(options);
+
+       isc_buffer_activeregion(source, &sr);
+       if (sr.length < 4)
+               return (ISC_R_UNEXPECTEDEND);
+
+       isc_buffer_forward(source, sr.length);
+       return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_keydata(ARGS_TOWIRE) {
+       isc_region_t sr;
+
+       REQUIRE(rdata->type == 65533);
+       REQUIRE(rdata->length != 0);
+
+       UNUSED(cctx);
+
+       dns_rdata_toregion(rdata, &sr);
+       return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_keydata(ARGS_COMPARE) {
+       isc_region_t r1;
+       isc_region_t r2;
+
+       REQUIRE(rdata1->type == rdata2->type);
+       REQUIRE(rdata1->rdclass == rdata2->rdclass);
+       REQUIRE(rdata1->type == 65533);
+       REQUIRE(rdata1->length != 0);
+       REQUIRE(rdata2->length != 0);
+
+       dns_rdata_toregion(rdata1, &r1);
+       dns_rdata_toregion(rdata2, &r2);
+       return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_keydata(ARGS_FROMSTRUCT) {
+       dns_rdata_keydata_t *keydata = source;
+
+       REQUIRE(type == 65533);
+       REQUIRE(source != NULL);
+       REQUIRE(keydata->common.rdtype == type);
+       REQUIRE(keydata->common.rdclass == rdclass);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+
+       /* Refresh timer */
+       RETERR(uint32_tobuffer(keydata->refresh, target));
+
+       /* Add hold-down */
+       RETERR(uint32_tobuffer(keydata->addhd, target));
+
+       /* Remove hold-down */
+       RETERR(uint32_tobuffer(keydata->removehd, target));
+
+       /* Flags */
+       RETERR(uint16_tobuffer(keydata->flags, target));
+
+       /* Protocol */
+       RETERR(uint8_tobuffer(keydata->protocol, target));
+
+       /* Algorithm */
+       RETERR(uint8_tobuffer(keydata->algorithm, target));
+
+       /* Data */
+       return (mem_tobuffer(target, keydata->data, keydata->datalen));
+}
+
+static inline isc_result_t
+tostruct_keydata(ARGS_TOSTRUCT) {
+       dns_rdata_keydata_t *keydata = target;
+       isc_region_t sr;
+
+       REQUIRE(rdata->type == 65533);
+       REQUIRE(target != NULL);
+       REQUIRE(rdata->length != 0);
+
+       keydata->common.rdclass = rdata->rdclass;
+       keydata->common.rdtype = rdata->type;
+       ISC_LINK_INIT(&keydata->common, link);
+
+       dns_rdata_toregion(rdata, &sr);
+
+       /* Refresh timer */
+       if (sr.length < 4)
+               return (ISC_R_UNEXPECTEDEND);
+       keydata->refresh = uint32_fromregion(&sr);
+       isc_region_consume(&sr, 4);
+
+       /* Add hold-down */
+       if (sr.length < 4)
+               return (ISC_R_UNEXPECTEDEND);
+       keydata->addhd = uint32_fromregion(&sr);
+       isc_region_consume(&sr, 4);
+
+       /* Remove hold-down */
+       if (sr.length < 4)
+               return (ISC_R_UNEXPECTEDEND);
+       keydata->removehd = uint32_fromregion(&sr);
+       isc_region_consume(&sr, 4);
+
+       /* Flags */
+       if (sr.length < 2)
+               return (ISC_R_UNEXPECTEDEND);
+       keydata->flags = uint16_fromregion(&sr);
+       isc_region_consume(&sr, 2);
+
+       /* Protocol */
+       if (sr.length < 1)
+               return (ISC_R_UNEXPECTEDEND);
+       keydata->protocol = uint8_fromregion(&sr);
+       isc_region_consume(&sr, 1);
+
+       /* Algorithm */
+       if (sr.length < 1)
+               return (ISC_R_UNEXPECTEDEND);
+       keydata->algorithm = uint8_fromregion(&sr);
+       isc_region_consume(&sr, 1);
+
+       /* Data */
+       keydata->datalen = sr.length;
+       keydata->data = mem_maybedup(mctx, sr.base, keydata->datalen);
+       if (keydata->data == NULL)
+               return (ISC_R_NOMEMORY);
+
+       keydata->mctx = mctx;
+       return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_keydata(ARGS_FREESTRUCT) {
+       dns_rdata_keydata_t *keydata = (dns_rdata_keydata_t *) source;
+
+       REQUIRE(source != NULL);
+       REQUIRE(keydata->common.rdtype == 65533);
+
+       if (keydata->mctx == NULL)
+               return;
+
+       if (keydata->data != NULL)
+               isc_mem_free(keydata->mctx, keydata->data);
+       keydata->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_keydata(ARGS_ADDLDATA) {
+       REQUIRE(rdata->type == 65533);
+
+       UNUSED(rdata);
+       UNUSED(add);
+       UNUSED(arg);
+
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_keydata(ARGS_DIGEST) {
+       isc_region_t r;
+
+       REQUIRE(rdata->type == 65533);
+
+       dns_rdata_toregion(rdata, &r);
+
+       return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_keydata(ARGS_CHECKOWNER) {
+
+       REQUIRE(type == 65533);
+
+       UNUSED(name);
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(wildcard);
+
+       return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_keydata(ARGS_CHECKNAMES) {
+
+       REQUIRE(rdata->type == 65533);
+
+       UNUSED(rdata);
+       UNUSED(owner);
+       UNUSED(bad);
+
+       return (ISC_TRUE);
+}
+
+#endif /* GENERIC_KEYDATA_65533_C */
diff --git a/lib/dns/rdata/generic/keydata_65533.h b/lib/dns/rdata/generic/keydata_65533.h
new file mode 100644 (file)
index 0000000..8db827e
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#ifndef GENERIC_KEYDATA_65533_H
+#define GENERIC_KEYDATA_65533_H 1
+
+/* $Id: keydata_65533.h,v 1.2 2009/06/30 02:52:32 each Exp $ */
+
+typedef struct dns_rdata_keydata {
+       dns_rdatacommon_t       common;
+       isc_mem_t *             mctx;
+       isc_uint32_t            refresh;      /* Timer for refreshing data */
+       isc_uint32_t            addhd;        /* Hold-down timer for adding */
+       isc_uint32_t            removehd;     /* Hold-down timer for removing */
+       isc_uint16_t            flags;        /* Copy of DNSKEY_48 */
+       isc_uint8_t             protocol;
+       isc_uint8_t             algorithm;
+       isc_uint16_t            datalen;
+       unsigned char *         data;
+} dns_rdata_keydata_t;
+
+#endif /* GENERIC_KEYDATA_65533_H */
diff --git a/lib/dns/rriterator.c b/lib/dns/rriterator.c
new file mode 100644 (file)
index 0000000..c98caf3
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * 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: rriterator.c,v 1.2 2009/06/30 02:52:32 each Exp $ */
+
+/*! \file */
+
+/***
+ *** Imports
+ ***/
+
+#include <config.h>
+
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+#include <dns/rriterator.h>
+
+/***
+ *** RRiterator methods
+ ***/
+
+isc_result_t
+dns_rriterator_init(dns_rriterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
+                   isc_stdtime_t now)
+{
+       isc_result_t result;
+       it->magic = RRITERATOR_MAGIC;
+       it->db = db;
+       it->dbit = NULL;
+       it->ver = ver;
+       it->now = now;
+       it->node = NULL;
+       result = dns_db_createiterator(it->db, 0, &it->dbit);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+       it->rdatasetit = NULL;
+       dns_rdata_init(&it->rdata);
+       dns_rdataset_init(&it->rdataset);
+       dns_fixedname_init(&it->fixedname);
+       INSIST(! dns_rdataset_isassociated(&it->rdataset));
+       it->result = ISC_R_SUCCESS;
+       return (it->result);
+}
+
+isc_result_t
+dns_rriterator_first(dns_rriterator_t *it) {
+       REQUIRE(VALID_RRITERATOR(it));
+       /* Reset state */
+       if (dns_rdataset_isassociated(&it->rdataset))
+               dns_rdataset_disassociate(&it->rdataset);
+       if (it->rdatasetit != NULL)
+               dns_rdatasetiter_destroy(&it->rdatasetit);
+       if (it->node != NULL)
+               dns_db_detachnode(it->db, &it->node);
+       it->result = dns_dbiterator_first(it->dbit);
+
+       /*
+        * The top node may be empty when out of zone glue exists.
+        * Walk the tree to find the first node with data.
+        */
+       while (it->result == ISC_R_SUCCESS) {
+               it->result = dns_dbiterator_current(it->dbit, &it->node,
+                                          dns_fixedname_name(&it->fixedname));
+               if (it->result != ISC_R_SUCCESS)
+                       return (it->result);
+
+               it->result = dns_db_allrdatasets(it->db, it->node, it->ver,
+                                                it->now, &it->rdatasetit);
+               if (it->result != ISC_R_SUCCESS)
+                       return (it->result);
+
+               it->result = dns_rdatasetiter_first(it->rdatasetit);
+               if (it->result != ISC_R_SUCCESS) {
+                       /*
+                        * This node is empty. Try next node.
+                        */
+                       dns_rdatasetiter_destroy(&it->rdatasetit);
+                       dns_db_detachnode(it->db, &it->node);
+                       it->result = dns_dbiterator_next(it->dbit);
+                       continue;
+               }
+               dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
+               it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
+               it->result = dns_rdataset_first(&it->rdataset);
+               return (it->result);
+       }
+       return (it->result);
+}
+
+isc_result_t
+dns_rriterator_nextrrset(dns_rriterator_t *it) {
+       REQUIRE(VALID_RRITERATOR(it));
+       if (dns_rdataset_isassociated(&it->rdataset))
+               dns_rdataset_disassociate(&it->rdataset);
+       it->result = dns_rdatasetiter_next(it->rdatasetit);
+       /*
+        * The while loop body is executed more than once
+        * only when an empty dbnode needs to be skipped.
+        */
+       while (it->result == ISC_R_NOMORE) {
+               dns_rdatasetiter_destroy(&it->rdatasetit);
+               dns_db_detachnode(it->db, &it->node);
+               it->result = dns_dbiterator_next(it->dbit);
+               if (it->result == ISC_R_NOMORE) {
+                       /* We are at the end of the entire database. */
+                       return (it->result);
+               }
+               if (it->result != ISC_R_SUCCESS)
+                       return (it->result);
+               it->result = dns_dbiterator_current(it->dbit, &it->node,
+                                          dns_fixedname_name(&it->fixedname));
+               if (it->result != ISC_R_SUCCESS)
+                       return (it->result);
+               it->result = dns_db_allrdatasets(it->db, it->node, it->ver,
+                                                it->now, &it->rdatasetit);
+               if (it->result != ISC_R_SUCCESS)
+                       return (it->result);
+               it->result = dns_rdatasetiter_first(it->rdatasetit);
+       }
+       if (it->result != ISC_R_SUCCESS)
+               return (it->result);
+       dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
+       it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
+       it->result = dns_rdataset_first(&it->rdataset);
+       return (it->result);
+}
+
+isc_result_t
+dns_rriterator_next(dns_rriterator_t *it) {
+       REQUIRE(VALID_RRITERATOR(it));
+       if (it->result != ISC_R_SUCCESS)
+               return (it->result);
+
+       INSIST(it->dbit != NULL);
+       INSIST(it->node != NULL);
+       INSIST(it->rdatasetit != NULL);
+
+       it->result = dns_rdataset_next(&it->rdataset);
+       if (it->result == ISC_R_NOMORE)
+               return (dns_rriterator_nextrrset(it));
+       return (it->result);
+}
+
+void
+dns_rriterator_pause(dns_rriterator_t *it) {
+       REQUIRE(VALID_RRITERATOR(it));
+       RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS);
+}
+
+void
+dns_rriterator_destroy(dns_rriterator_t *it) {
+       REQUIRE(VALID_RRITERATOR(it));
+       if (dns_rdataset_isassociated(&it->rdataset))
+               dns_rdataset_disassociate(&it->rdataset);
+       if (it->rdatasetit != NULL)
+               dns_rdatasetiter_destroy(&it->rdatasetit);
+       if (it->node != NULL)
+               dns_db_detachnode(it->db, &it->node);
+       dns_dbiterator_destroy(&it->dbit);
+}
+
+void
+dns_rriterator_current(dns_rriterator_t *it, dns_name_t **name,
+                      isc_uint32_t *ttl, dns_rdataset_t **rdataset,
+                      dns_rdata_t **rdata)
+{
+       REQUIRE(name != NULL && *name == NULL);
+       REQUIRE(VALID_RRITERATOR(it));
+       REQUIRE(it->result == ISC_R_SUCCESS);
+
+       *name = dns_fixedname_name(&it->fixedname);
+       *ttl = it->rdataset.ttl;
+
+       dns_rdata_reset(&it->rdata);
+       dns_rdataset_current(&it->rdataset, &it->rdata);
+
+       if (rdataset)
+               *rdataset = &it->rdataset;
+
+       if (rdata)
+               *rdata = &it->rdata;
+}
index 83a1c1790e3c18c5946312bdf69f2d2dd1ec2edb..c974d15d35ecb00fd273a587296cb6765bd056a9 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: soa.c,v 1.8 2007/06/19 23:47:16 tbox Exp $ */
+/* $Id: soa.c,v 1.9 2009/06/30 02:52:32 each Exp $ */
 
 /*! \file */
 
 #include <config.h>
 
+#include <isc/buffer.h>
 #include <isc/util.h>
 
 #include <dns/rdata.h>
+#include <dns/rdatastruct.h>
 #include <dns/soa.h>
 
 static inline isc_uint32_t
@@ -60,6 +62,37 @@ soa_get(dns_rdata_t *rdata, int offset) {
        return (decode_uint32(rdata->data + rdata->length - 20 + offset));
 }
 
+isc_result_t
+dns_soa_buildrdata(dns_name_t *origin, dns_name_t *contact,
+                  dns_rdataclass_t rdclass,
+                  isc_uint32_t serial, isc_uint32_t refresh, 
+                  isc_uint32_t retry, isc_uint32_t expire, 
+                  isc_uint32_t minimum, dns_rdata_t *rdata) {
+       dns_rdata_soa_t soa;
+       char soadata[DNS_NAME_FORMATSIZE];
+       isc_buffer_t rdatabuf;
+
+       REQUIRE(origin != NULL);
+       REQUIRE(contact != NULL);
+
+       soa.common.rdtype = dns_rdatatype_soa;
+       soa.common.rdclass = rdclass;
+       soa.mctx = NULL;
+       soa.serial = serial;
+       soa.refresh = refresh;
+       soa.retry = retry;
+       soa.expire = expire;
+       soa.minimum = minimum;
+       dns_name_init(&soa.origin, NULL);
+       dns_name_clone(origin, &soa.origin);
+       dns_name_init(&soa.contact, NULL);
+       dns_name_clone(contact, &soa.contact);
+
+       isc_buffer_init(&rdatabuf, soadata, sizeof(soadata));
+       return (dns_rdata_fromstruct(rdata, rdclass, dns_rdatatype_soa,
+                                     &soa, &rdatabuf));
+}
+
 isc_uint32_t
 dns_soa_getserial(dns_rdata_t *rdata) {
        return soa_get(rdata, 0);
index 88f661a76a2bce467b2427d0b4ed021ee2193148..8f8f331296833b8aabc64af52ba98baa07d36155 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: validator.c,v 1.177 2009/06/09 22:57:09 marka Exp $ */
+/* $Id: validator.c,v 1.178 2009/06/30 02:52:32 each Exp $ */
 
 #include <config.h>
 
@@ -1875,6 +1875,8 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
                                        break;
                                }
                                val->key = dns_keynode_key(val->keynode);
+                               if (val->key == NULL)
+                                       break;
                        } else {
                                if (get_dst_key(val, val->siginfo, val->keyset)
                                    != ISC_R_SUCCESS)
@@ -2115,7 +2117,8 @@ dlv_validatezonekey(dns_validator_t *val) {
 }
 
 /*%
- * Attempts positive response validation of an RRset containing zone keys.
+ * Attempts positive response validation of an RRset containing zone keys
+ * (i.e. a DNSKEY rrset).
  *
  * Returns:
  * \li ISC_R_SUCCESS   Validation completed successfully
@@ -2182,11 +2185,18 @@ validatezonekey(dns_validator_t *val) {
                                atsep = ISC_TRUE;
                        while (result == ISC_R_SUCCESS) {
                                dstkey = dns_keynode_key(keynode);
+                               if (dstkey == NULL) {
+                                       dns_keytable_detachkeynode(
+                                                               val->keytable,
+                                                               &keynode);
+                                       break;
+                               }
                                result = verify(val, dstkey, &sigrdata,
                                                sig.keyid);
                                if (result == ISC_R_SUCCESS) {
-                                       dns_keytable_detachkeynode(val->keytable,
-                                                                  &keynode);
+                                       dns_keytable_detachkeynode(
+                                                               val->keytable,
+                                                               &keynode);
                                        break;
                                }
                                result = dns_keytable_findnextkeynode(
@@ -2228,8 +2238,8 @@ validatezonekey(dns_validator_t *val) {
                                        sizeof(namebuf));
                        validator_log(val, ISC_LOG_DEBUG(2),
                                      "unable to find a DNSKEY which verifies "
-                                     "the DNSKEY RRset and also matches one "
-                                     "of specified trusted-keys for '%s'",
+                                     "the DNSKEY RRset and also matches a "
+                                     "trusted key for '%s'",
                                      namebuf);
                        return (DNS_R_NOVALIDKEY);
                }
index b5414d4cd3ca0e0e87ac033452ca77bf4b477525..57dc6174721d9553b96d043db252987b7c24c36e 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.c,v 1.154 2009/05/29 22:22:37 jinmei Exp $ */
+/* $Id: view.c,v 1.155 2009/06/30 02:52:32 each Exp $ */
 
 /*! \file */
 
@@ -96,23 +96,6 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
                goto cleanup_mutex;
        }
        view->secroots = NULL;
-       result = dns_keytable_create(mctx, &view->secroots);
-       if (result != ISC_R_SUCCESS) {
-               UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                "dns_keytable_create() failed: %s",
-                                isc_result_totext(result));
-               result = ISC_R_UNEXPECTED;
-               goto cleanup_zt;
-       }
-       view->trustedkeys = NULL;
-       result = dns_keytable_create(mctx, &view->trustedkeys);
-       if (result != ISC_R_SUCCESS) {
-               UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                "dns_keytable_create() failed: %s",
-                                isc_result_totext(result));
-               result = ISC_R_UNEXPECTED;
-               goto cleanup_secroots;
-       }
        view->fwdtable = NULL;
        result = dns_fwdtable_create(mctx, &view->fwdtable);
        if (result != ISC_R_SUCCESS) {
@@ -120,7 +103,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
                                 "dns_fwdtable_create() failed: %s",
                                 isc_result_totext(result));
                result = ISC_R_UNEXPECTED;
-               goto cleanup_trustedkeys;
+               goto cleanup_zt;
        }
 
        view->acache = NULL;
@@ -237,12 +220,6 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
  cleanup_fwdtable:
        dns_fwdtable_destroy(&view->fwdtable);
 
- cleanup_trustedkeys:
-       dns_keytable_detach(&view->trustedkeys);
-
- cleanup_secroots:
-       dns_keytable_detach(&view->secroots);
-
  cleanup_zt:
        dns_zt_detach(&view->zonetable);
 
@@ -365,8 +342,8 @@ destroy(dns_view_t *view) {
                isc_stats_detach(&view->resstats);
        if (view->resquerystats != NULL)
                dns_stats_detach(&view->resquerystats);
-       dns_keytable_detach(&view->trustedkeys);
-       dns_keytable_detach(&view->secroots);
+       if (view->secroots != NULL)
+               dns_keytable_detach(&view->secroots);
        dns_fwdtable_destroy(&view->fwdtable);
        dns_aclenv_destroy(&view->aclenv);
        DESTROYLOCK(&view->lock);
@@ -990,7 +967,7 @@ dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
 isc_result_t
 dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
                      isc_stdtime_t now, unsigned int options,
-                     isc_boolean_t use_hints,  isc_boolean_t use_cache,
+                     isc_boolean_t use_hints,  isc_boolean_t use_cache,
                      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
 {
        isc_result_t result;
index 4a568588fb05d71f76881f172798a4850ff28a11..ff1575b4a395013e116fafd2ea4e011d4ea406d7 100644 (file)
@@ -226,17 +226,25 @@ dns_journal_print
 dns_journal_rollforward
 dns_journal_write_transaction
 dns_journal_writediff
+dns_keydata_fromdnskey
+dns_keydata_todnskey
 dns_keyflags_fromtext
 dns_keynode_key
+dns_keynode_managed
 dns_keytable_add
 dns_keytable_attach
 dns_keytable_create
+dns_keytable_delete
+dns_keytable_deletekeynode
 dns_keytable_detach
 dns_keytable_detachkeynode
+dns_keytable_find
 dns_keytable_finddeepestmatch
 dns_keytable_findkeynode
 dns_keytable_findnextkeynode
 dns_keytable_issecuredomain
+dns_keytable_marksecure
+dns_keytable_nextkeynode
 dns_lib_initmsgcat
 dns_loadctx_attach
 dns_loadctx_cancel
@@ -332,6 +340,7 @@ dns_name_format
 dns_name_free
 dns_name_fromregion
 dns_name_fromtext
+dns_name_fromstring
 dns_name_fromwire
 dns_name_fullcompare
 dns_name_getlabel
@@ -353,6 +362,7 @@ dns_name_settotextfilter
 dns_name_split
 dns_name_tofilenametext
 dns_name_toregion
+dns_name_tostring
 dns_name_totext
 dns_name_towire
 dns_ncache_add
@@ -559,6 +569,13 @@ dns_result_register
 dns_result_torcode
 dns_result_totext
 dns_rootns_create
+dns_rriterator_current
+dns_rriterator_first
+dns_rriterator_destroy
+dns_rriterator_init
+dns_rriterator_next
+dns_rriterator_nextrrset
+dns_rriterator_pause
 dns_sdb_putnamedrr
 dns_sdb_putrdata
 dns_sdb_putrr
@@ -852,6 +869,7 @@ dst_key_paramcompare
 dst_key_proto
 dst_key_secretsize
 dst_key_setbits
+dst_key_setflags
 dst_key_sigsize
 dst_key_size
 dst_key_tobuffer
index ce283b2fe90d28f79d4f08ccc6a36454f3b35915..64e21b4ace8b7b51d8f337d6b98204152797e419 100644 (file)
@@ -198,6 +198,10 @@ SOURCE=..\include\dns\journal.h
 # End Source File
 # Begin Source File
 
+SOURCE=..\include\dns\keydata.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\include\dns\keyflags.h
 # End Source File
 # Begin Source File
@@ -326,6 +330,10 @@ SOURCE=..\include\dns\rootns.h
 # End Source File
 # Begin Source File
 
+SOURCE=..\include\dns\rriterator.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\include\dns\sdb.h
 # End Source File
 # Begin Source File
@@ -494,6 +502,10 @@ SOURCE=..\journal.c
 # End Source File
 # Begin Source File
 
+SOURCE=..\keydata.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\keytable.c
 # End Source File
 # Begin Source File
@@ -602,6 +614,10 @@ SOURCE=..\rootns.c
 # End Source File
 # Begin Source File
 
+SOURCE=..\rriterator.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\sdb.c
 # End Source File
 # Begin Source File
index d4d3ef65fd39e68f55a11826e44c6c2cc9f893a5..1dde5713df4239fd05e362be212c08cb608b84b0 100644 (file)
@@ -148,6 +148,7 @@ CLEAN :
        -@erase "$(INTDIR)\iptable.obj"
        -@erase "$(INTDIR)\journal.obj"
        -@erase "$(INTDIR)\key.obj"
+       -@erase "$(INTDIR)\keydata.obj"
        -@erase "$(INTDIR)\keytable.obj"
        -@erase "$(INTDIR)\lib.obj"
        -@erase "$(INTDIR)\log.obj"
@@ -179,6 +180,7 @@ CLEAN :
        -@erase "$(INTDIR)\resolver.obj"
        -@erase "$(INTDIR)\result.obj"
        -@erase "$(INTDIR)\rootns.obj"
+       -@erase "$(INTDIR)\rriterator.obj"
        -@erase "$(INTDIR)\sdb.obj"
        -@erase "$(INTDIR)\sdlz.obj"
        -@erase "$(INTDIR)\soa.obj"
@@ -270,6 +272,7 @@ LINK32_OBJS= \
        "$(INTDIR)\forward.obj" \
        "$(INTDIR)\iptable.obj" \
        "$(INTDIR)\journal.obj" \
+       "$(INTDIR)\keydata.obj" \
        "$(INTDIR)\keytable.obj" \
        "$(INTDIR)\lib.obj" \
        "$(INTDIR)\log.obj" \
@@ -297,6 +300,7 @@ LINK32_OBJS= \
        "$(INTDIR)\resolver.obj" \
        "$(INTDIR)\result.obj" \
        "$(INTDIR)\rootns.obj" \
+       "$(INTDIR)\rriterator.obj" \
        "$(INTDIR)\sdb.obj" \
        "$(INTDIR)\sdlz.obj" \
        "$(INTDIR)\soa.obj" \
@@ -415,6 +419,8 @@ CLEAN :
        -@erase "$(INTDIR)\journal.sbr"
        -@erase "$(INTDIR)\key.obj"
        -@erase "$(INTDIR)\key.sbr"
+       -@erase "$(INTDIR)\keydata.obj"
+       -@erase "$(INTDIR)\keydata.sbr"
        -@erase "$(INTDIR)\keytable.obj"
        -@erase "$(INTDIR)\keytable.sbr"
        -@erase "$(INTDIR)\lib.obj"
@@ -477,6 +483,8 @@ CLEAN :
        -@erase "$(INTDIR)\result.sbr"
        -@erase "$(INTDIR)\rootns.obj"
        -@erase "$(INTDIR)\rootns.sbr"
+       -@erase "$(INTDIR)\rriterator.obj"
+       -@erase "$(INTDIR)\rriterator.sbr"
        -@erase "$(INTDIR)\sdb.obj"
        -@erase "$(INTDIR)\sdb.sbr"
        -@erase "$(INTDIR)\sdlz.obj"
@@ -585,6 +593,7 @@ BSC32_SBRS= \
        "$(INTDIR)\forward.sbr" \
        "$(INTDIR)\iptable.sbr" \
        "$(INTDIR)\journal.sbr" \
+       "$(INTDIR)\keydata.sbr" \
        "$(INTDIR)\keytable.sbr" \
        "$(INTDIR)\lib.sbr" \
        "$(INTDIR)\log.sbr" \
@@ -612,6 +621,7 @@ BSC32_SBRS= \
        "$(INTDIR)\resolver.sbr" \
        "$(INTDIR)\result.sbr" \
        "$(INTDIR)\rootns.sbr" \
+       "$(INTDIR)\rriterator.sbr" \
        "$(INTDIR)\sdb.sbr" \
        "$(INTDIR)\sdlz.sbr" \
        "$(INTDIR)\soa.sbr" \
@@ -673,6 +683,7 @@ LINK32_OBJS= \
        "$(INTDIR)\forward.obj" \
        "$(INTDIR)\iptable.obj" \
        "$(INTDIR)\journal.obj" \
+       "$(INTDIR)\key.obj" \
        "$(INTDIR)\keytable.obj" \
        "$(INTDIR)\lib.obj" \
        "$(INTDIR)\log.obj" \
@@ -700,6 +711,7 @@ LINK32_OBJS= \
        "$(INTDIR)\resolver.obj" \
        "$(INTDIR)\result.obj" \
        "$(INTDIR)\rootns.obj" \
+       "$(INTDIR)\rriterator.obj" \
        "$(INTDIR)\sdb.obj" \
        "$(INTDIR)\sdlz.obj" \
        "$(INTDIR)\soa.obj" \
@@ -1094,6 +1106,24 @@ SOURCE=..\journal.c
        $(CPP) $(CPP_PROJ) $(SOURCE)
 
 
+!ENDIF 
+
+SOURCE=..\keydata.c
+
+!IF  "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\keydata.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\keydata.obj"        "$(INTDIR)\keydata.sbr" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
 !ENDIF 
 
 SOURCE=..\keytable.c
@@ -1581,6 +1611,24 @@ SOURCE=..\rootns.c
        $(CPP) $(CPP_PROJ) $(SOURCE)
 
 
+!ENDIF 
+
+SOURCE=..\rriterator.c
+
+!IF  "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\rriterator.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\rriterator.obj"     "$(INTDIR)\rriterator.sbr" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
 !ENDIF 
 
 SOURCE=..\sdb.c
index ea8d1a1f707d37c7484961f108676f957f759b43..b9cb07f012f84c52e931051a53c7b8e8401e7291 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: zone.c,v 1.493 2009/06/17 04:29:43 marka Exp $ */
+/* $Id: zone.c,v 1.494 2009/06/30 02:52:32 each Exp $ */
 
 /*! \file */
 
@@ -47,6 +47,8 @@
 #include <dns/dnssec.h>
 #include <dns/events.h>
 #include <dns/journal.h>
+#include <dns/keydata.h>
+#include <dns/keytable.h>
 #include <dns/keyvalues.h>
 #include <dns/log.h>
 #include <dns/master.h>
@@ -56,6 +58,7 @@
 #include <dns/nsec.h>
 #include <dns/nsec3.h>
 #include <dns/peer.h>
+#include <dns/rbt.h>
 #include <dns/rcode.h>
 #include <dns/rdataclass.h>
 #include <dns/rdatalist.h>
@@ -66,6 +69,7 @@
 #include <dns/request.h>
 #include <dns/resolver.h>
 #include <dns/result.h>
+#include <dns/rriterator.h>
 #include <dns/soa.h>
 #include <dns/ssu.h>
 #include <dns/stats.h>
@@ -129,6 +133,7 @@ typedef struct dns_signing dns_signing_t;
 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
 typedef struct dns_nsec3chain dns_nsec3chain_t;
 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
+typedef struct dns_keyfetch dns_keyfetch_t;
 
 #define DNS_ZONE_CHECKLOCK
 #ifdef DNS_ZONE_CHECKLOCK
@@ -200,6 +205,8 @@ struct dns_zone {
        isc_time_t              keywarntime;
        isc_time_t              signingtime;
        isc_time_t              nsec3chaintime;
+       isc_time_t              refreshkeytime;         /* Used by key zones */
+       isc_uint32_t            refreshkeycount;
        isc_uint32_t            serial;
        isc_uint32_t            refresh;
        isc_uint32_t            retry;
@@ -274,13 +281,13 @@ struct dns_zone {
        /*%
         * Statistics counters about zone management.
         */
-       isc_stats_t             *stats;
+       isc_stats_t             *stats;
        /*%
         * Optional per-zone statistics counters.  Counted outside of this
         * module.
         */
-       isc_boolean_t           requeststats_on;
-       isc_stats_t             *requeststats;
+       isc_boolean_t           requeststats_on;
+       isc_stats_t             *requeststats;
        isc_uint32_t            notifydelay;
        dns_isselffunc_t        isself;
        void                    *isselfarg;
@@ -340,7 +347,7 @@ struct dns_zone {
                                                 * from SOA (if not set, we
                                                 * are still using
                                                 * default timer values) */
-#define DNS_ZONEFLG_FORCEXFER   0x00008000U     /*%< Force a zone xfer */
+#define DNS_ZONEFLG_FORCEXFER  0x00008000U     /*%< Force a zone xfer */
 #define DNS_ZONEFLG_NOREFRESH  0x00010000U
 #define DNS_ZONEFLG_DIALNOTIFY 0x00020000U
 #define DNS_ZONEFLG_DIALREFRESH        0x00040000U
@@ -351,6 +358,7 @@ struct dns_zone {
 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
+#define DNS_ZONEFLG_REFRESHING 0x04000000U     /*%< Refreshing keydata */
 
 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
 
@@ -481,7 +489,7 @@ struct dns_io {
  *     DNSKEY as result of an update.
  */
 struct dns_signing {
-       unsigned int            magic;
+       unsigned int            magic;
        dns_db_t                *db;
        dns_dbiterator_t        *dbiterator;
        dns_secalg_t            algorithm;
@@ -492,15 +500,15 @@ struct dns_signing {
 };
 
 struct dns_nsec3chain {
-       unsigned int                    magic;
+       unsigned int                    magic;
        dns_db_t                        *db;
        dns_dbiterator_t                *dbiterator;
        dns_rdata_nsec3param_t          nsec3param;
        unsigned char                   salt[255];
        isc_boolean_t                   done;
-       isc_boolean_t                   seen_nsec;
-       isc_boolean_t                   delete_nsec;
-       isc_boolean_t                   save_delete_nsec;
+       isc_boolean_t                   seen_nsec;
+       isc_boolean_t                   delete_nsec;
+       isc_boolean_t                   save_delete_nsec;
        ISC_LINK(dns_nsec3chain_t)      link;
 };
 /*%<
@@ -525,6 +533,19 @@ struct dns_nsec3chain {
  * so it can be recovered in the event of a error.
  */
 
+struct dns_keyfetch {
+       dns_fixedname_t name;
+       dns_rdataset_t keydataset;
+       dns_rdataset_t dnskeyset;
+       dns_rdataset_t dnskeysigset;
+       dns_zone_t *zone;
+       dns_db_t *db;
+       dns_fetch_t *fetch;
+};
+
+#define HOUR 3600
+#define DAY (24*HOUR)
+#define MONTH (30*DAY)
 
 #define SEND_BUFFER_SIZE 2048
 
@@ -535,6 +556,10 @@ static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
      ISC_FORMAT_PRINTF(3, 4);
 static void queue_xfrin(dns_zone_t *zone);
+static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
+                                 dns_diff_t *diff, dns_diffop_t op,
+                                 dns_name_t *name, dns_ttl_t ttl,
+                                 dns_rdata_t *rdata);
 static void zone_unload(dns_zone_t *zone);
 static void zone_expire(dns_zone_t *zone);
 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
@@ -718,6 +743,8 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
        isc_time_settoepoch(&zone->keywarntime);
        isc_time_settoepoch(&zone->signingtime);
        isc_time_settoepoch(&zone->nsec3chaintime);
+       isc_time_settoepoch(&zone->refreshkeytime);
+       zone->refreshkeycount = 0;
        zone->serial = 0;
        zone->refresh = DNS_ZONE_DEFAULTREFRESH;
        zone->retry = DNS_ZONE_DEFAULTRETRY;
@@ -1293,6 +1320,7 @@ zone_isdynamic(dns_zone_t *zone) {
 
        return (ISC_TF(zone->type == dns_zone_slave ||
                       zone->type == dns_zone_stub ||
+                      zone->type == dns_zone_key ||
                       (!zone->update_disabled && zone->ssutable != NULL) ||
                       (!zone->update_disabled && zone->update_acl != NULL &&
                        !dns_acl_isnone(zone->update_acl))));
@@ -1360,7 +1388,7 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
         */
        if (zone->masterfile != NULL) {
                /*
-                * The file is already loaded.  If we are just doing a
+                * The file is already loaded.  If we are just doing a
                 * "rndc reconfig", we are done.
                 */
                if (!isc_time_isepoch(&zone->loadtime) &&
@@ -1477,6 +1505,8 @@ get_master_options(dns_zone_t *zone) {
        options = DNS_MASTER_ZONE;
        if (zone->type == dns_zone_slave)
                options |= DNS_MASTER_SLAVE;
+       if (zone->type == dns_zone_key)
+               options |= DNS_MASTER_KEY;
        if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
                options |= DNS_MASTER_CHECKNS;
        if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
@@ -2049,7 +2079,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
 
 /*
  * OpenSSL verification of RSA keys with exponent 3 is known to be
- * broken prior OpenSSL 0.9.8c/0.9.7k.  Look for such keys and warn
+ * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
  * if they are in use.
  */
 static void
@@ -2299,7 +2329,7 @@ set_resigntime(dns_zone_t *zone) {
 
        dns_rdataset_init(&rdataset);
        dns_fixedname_init(&fixed);
-       result  = dns_db_getsigningtime(zone->db, &rdataset,
+       result  = dns_db_getsigningtime(zone->db, &rdataset,
                                        dns_fixedname_name(&fixed));
        if (result != ISC_R_SUCCESS) {
                isc_time_settoepoch(&zone->resigntime);
@@ -2403,6 +2433,588 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
        return (result);
 }
 
+/*
+ * Set the timer for refreshing the key zone to the soonest future time
+ * of the set (current timer, keydata->refresh, keydata->addhd,
+ * keydata->removehd).
+ */
+static void
+set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
+                   isc_stdtime_t now) {
+       const char me[] = "set_refreshkeytimer";
+       isc_stdtime_t then;
+       isc_time_t timenow, timethen;
+
+       ENTER;
+       then = key->refresh;
+       if (key->addhd > now && key->addhd < then)
+               then = key->addhd;
+       if (key->removehd > now && key->removehd < then)
+               then = key->removehd;
+
+       isc_time_set(&timenow, now, 0);
+       isc_time_set(&timethen, ISC_MAX(then, now), 0);
+       if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
+           isc_time_compare(&timethen, &zone->refreshkeytime) < 0) {
+               zone->refreshkeytime = timethen;
+       }
+       zone_settimer(zone, &timenow);
+}
+
+/*
+ * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
+ * If the key zone is changed, set '*changed' to ISC_TRUE.
+ */
+static isc_result_t
+create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
+              dns_diff_t *diff, dns_name_t *name, dns_keytable_t *keytable,
+              dns_keynode_t *keynode, isc_boolean_t *changed)
+{
+       const char me[] = "create_keydata";
+       isc_result_t result = ISC_R_SUCCESS;
+       isc_buffer_t keyb, dstb;
+       unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
+       dns_rdata_keydata_t keydata;
+       dns_rdata_dnskey_t dnskey;
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       dns_keynode_t *nextnode = NULL;
+       isc_stdtime_t now;
+       isc_region_t r;
+       dst_key_t *key;
+
+       ENTER;
+       isc_stdtime_get(&now);
+
+       /* Loop in case there's more than one key. */
+       while (result == ISC_R_SUCCESS) {
+               key = dns_keynode_key(keynode);
+               if (key == NULL)
+                       goto skip;
+
+               isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
+               CHECK(dst_key_todns(key, &dstb));
+
+               /* Convert DST key to DNSKEY. */
+               dns_rdata_reset(&rdata);
+               isc_buffer_usedregion(&dstb, &r);
+               dns_rdata_fromregion(&rdata, dst_key_class(key),
+                                    dns_rdatatype_dnskey, &r);
+
+               /* DSTKEY to KEYDATA. */
+               dns_rdata_tostruct(&rdata, &dnskey, NULL);
+               dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0, NULL);
+
+               /* KEYDATA to rdata. */
+               dns_rdata_reset(&rdata);
+               isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+               dns_rdata_fromstruct(&rdata,
+                                    zone->rdclass, dns_rdatatype_keydata,
+                                    &keydata, &keyb);
+
+               /* Add rdata to zone. */
+               CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
+                                   name, 0, &rdata));
+               *changed = ISC_TRUE;
+
+ skip:
+               result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
+               if(result != ISC_R_NOTFOUND) {
+                       dns_keytable_detachkeynode(keytable, &keynode);
+                       keynode = nextnode;
+               }
+       }
+
+       /* Refresh new keys from the zone apex as soon as possible. */
+       if (*changed)
+               set_refreshkeytimer(zone, &keydata, now);
+
+       return (ISC_R_SUCCESS);
+
+  failure:
+       return (result);
+}
+
+/*
+ * Remove from the key zone all the KEYDATA records found in rdataset.
+ */
+static isc_result_t
+delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
+              dns_name_t *name, dns_rdataset_t *rdataset)
+{
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       isc_result_t result, uresult;
+
+       for (result = dns_rdataset_first(rdataset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(rdataset)) {
+               dns_rdata_reset(&rdata);
+               dns_rdataset_current(rdataset, &rdata);
+               uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
+                                       name, 0, &rdata);
+               if (uresult != ISC_R_SUCCESS)
+                       return (uresult);
+       }
+       if (result == ISC_R_NOMORE)
+               result = ISC_R_SUCCESS;
+       return (result);
+}
+
+/*
+ * Compute the DNSSEC key ID for a DNSKEY record.
+ */
+static isc_result_t
+compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
+           dns_keytag_t *tag)
+{
+       isc_result_t result;
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       unsigned char data[4096];
+       isc_buffer_t buffer;
+       dst_key_t *dstkey = NULL;
+
+       isc_buffer_init(&buffer, data, sizeof(data));
+       dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
+                            dns_rdatatype_dnskey, dnskey, &buffer);
+
+       result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
+       if (result == ISC_R_SUCCESS)
+               *tag = dst_key_id(dstkey);
+       dst_key_free(&dstkey);
+
+       return (result);
+}
+
+/*
+ * Add key to the security roots for all views.
+ */
+static void
+trust_key(dns_viewlist_t *viewlist, dns_name_t *keyname,
+         dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
+       isc_result_t result;
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       unsigned char data[4096];
+       isc_buffer_t buffer;
+       dns_view_t *view;
+
+       /* Convert dnskey to DST key. */
+       isc_buffer_init(&buffer, data, sizeof(data));
+       dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
+                            dns_rdatatype_dnskey, dnskey, &buffer);
+
+       for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
+            view = ISC_LIST_NEXT(view, link)) {
+               if (view->secroots != NULL) {
+                       dst_key_t *key = NULL;
+                       CHECK(dns_dnssec_keyfromrdata(keyname, &rdata,
+                                                     mctx, &key));
+                       CHECK(dns_keytable_add(view->secroots, ISC_TRUE, &key));
+               }
+       }
+
+  failure:
+       return;
+}
+
+/*
+ * Remove key from the security roots for all views.
+ */
+static void
+untrust_key(dns_viewlist_t *viewlist, dns_name_t *keyname, isc_mem_t *mctx,
+           dns_rdata_dnskey_t *dnskey)
+{
+       isc_result_t result;
+       unsigned char data[4096];
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       isc_buffer_t buffer;
+       dns_view_t *view;
+       dst_key_t *key = NULL;
+
+       /*
+        * Clear the revoke bit, if set, so that the key will match what's
+        * in secroots now.
+        */
+       dnskey->flags &= ~DNS_KEYFLAG_REVOKE;
+
+       /* Convert dnskey to DST key. */
+       isc_buffer_init(&buffer, data, sizeof(data));
+       dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
+                            dns_rdatatype_dnskey, dnskey, &buffer);
+       result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key);
+       if (result != ISC_R_SUCCESS)
+               return;
+
+       for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
+            view = ISC_LIST_NEXT(view, link)) {
+               if (view->secroots == NULL)
+                       continue;
+               dns_keytable_deletekeynode(view->secroots, key);
+       }
+
+       dst_key_free(&key);
+}
+
+/*
+ * Add a null key to the security roots for all views, so that all queries
+ * to the zone will fail.
+ */
+static void
+fail_secure(dns_viewlist_t *viewlist, dns_name_t *keyname) {
+       dns_view_t *view;
+
+       for (view = ISC_LIST_HEAD(*viewlist);
+            view != NULL;
+            view = ISC_LIST_NEXT(view, link)) {
+               if (view->secroots != NULL)
+                       dns_keytable_marksecure(view->secroots, keyname);
+       }
+}
+
+/*
+ * Scan a set of KEYDATA records from the key zone.  The ones that are
+ * valid (i.e., the add holddown timer has expired) become trusted keys for
+ * all views.
+ */
+static void
+load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
+       isc_result_t result;
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       dns_rdata_keydata_t keydata;
+       dns_rdata_dnskey_t dnskey;
+       isc_mem_t *mctx = zone->mctx;
+       dns_view_t *view = zone->view;
+       dns_viewlist_t *viewlist = view->viewlist;
+       int trusted = 0, revoked = 0, pending = 0;
+       isc_stdtime_t now;
+
+       isc_stdtime_get(&now);
+
+       /* For each view, delete references to this key from secroots. */
+       for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
+            view = ISC_LIST_NEXT(view, link)) {
+               if (view->secroots != NULL)
+                       dns_keytable_delete(view->secroots, name);
+       }
+
+       /* Now insert all the accepted trust anchors from this keydata set. */
+       for (result = dns_rdataset_first(rdataset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(rdataset)) {
+               dns_rdata_reset(&rdata);
+               dns_rdataset_current(rdataset, &rdata);
+
+               /* Convert rdata to keydata. */
+               dns_rdata_tostruct(&rdata, &keydata, NULL);
+
+               /* Set the key refresh timer. */
+               set_refreshkeytimer(zone, &keydata, now);
+
+               /* If the removal timer is nonzero, this key was revoked. */
+               if (keydata.removehd != 0) {
+                       revoked++;
+                       continue;
+               }
+
+               /*
+                * If the add timer is still pending, this key is not
+                * trusted yet.
+                */
+               if (now < keydata.addhd) {
+                       pending++;
+                       continue;
+               }
+
+               /* Convert keydata to dnskey. */
+               dns_keydata_todnskey(&keydata, &dnskey, NULL);
+
+               /* Add to keytables. */
+               trusted++;
+               trust_key(viewlist, name, &dnskey, mctx);
+       }
+
+       if (trusted == 0 && pending != 0) {
+               char namebuf[DNS_NAME_FORMATSIZE];
+               dns_name_format(name, namebuf, sizeof namebuf);
+               dns_zone_log(zone, ISC_LOG_ERROR,
+                            "No valid trust anchors for '%s'!", namebuf);
+               dns_zone_log(zone, ISC_LOG_ERROR,
+                            "%d key(s) revoked, %d still pending",
+                            revoked, pending);
+               dns_zone_log(zone, ISC_LOG_ERROR,
+                            "All queries to '%s' will fail", namebuf);
+               fail_secure(viewlist, name);
+       }
+}
+
+static isc_result_t
+do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
+            dns_diff_t *diff)
+{
+       dns_diff_t temp_diff;
+       isc_result_t result;
+
+       /*
+        * Create a singleton diff.
+        */
+       dns_diff_init(diff->mctx, &temp_diff);
+       temp_diff.resign = diff->resign;
+       ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
+
+       /*
+        * Apply it to the database.
+        */
+       result = dns_diff_apply(&temp_diff, db, ver);
+       ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
+       if (result != ISC_R_SUCCESS) {
+               dns_difftuple_free(tuple);
+               return (result);
+       }
+
+       /*
+        * Merge it into the current pending journal entry.
+        */
+       dns_diff_appendminimal(diff, tuple);
+
+       /*
+        * Do not clear temp_diff.
+        */
+       return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
+             dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
+             dns_rdata_t *rdata)
+{
+       dns_difftuple_t *tuple = NULL;
+       isc_result_t result;
+       result = dns_difftuple_create(diff->mctx, op,
+                                     name, ttl, rdata, &tuple);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+       return (do_one_tuple(&tuple, db, ver, diff));
+}
+
+static isc_result_t
+increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver,
+                    dns_diff_t *diff, isc_mem_t *mctx) {
+       dns_difftuple_t *deltuple = NULL;
+       dns_difftuple_t *addtuple = NULL;
+       isc_uint32_t serial;
+       isc_result_t result;
+
+       CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
+       CHECK(dns_difftuple_copy(deltuple, &addtuple));
+       addtuple->op = DNS_DIFFOP_ADD;
+
+       serial = dns_soa_getserial(&addtuple->rdata);
+
+       /* RFC1982 */
+       serial = (serial + 1) & 0xFFFFFFFF;
+       if (serial == 0)
+               serial = 1;
+
+       dns_soa_setserial(serial, &addtuple->rdata);
+       CHECK(do_one_tuple(&deltuple, db, ver, diff));
+       CHECK(do_one_tuple(&addtuple, db, ver, diff));
+       result = ISC_R_SUCCESS;
+
+       failure:
+       if (addtuple != NULL)
+               dns_difftuple_free(&addtuple);
+       if (deltuple != NULL)
+               dns_difftuple_free(&deltuple);
+       return (result);
+}
+
+/*
+ * Write all transactions in 'diff' to the zone journal file.
+ */
+static void
+zone_journal(dns_zone_t *zone, dns_diff_t *diff, const char *caller) {
+       const char me[] = "zone_journal";
+       const char *journalfile;
+       isc_result_t result;
+       dns_journal_t *journal = NULL;
+
+       ENTER;
+       journalfile = dns_zone_getjournal(zone);
+       if (journalfile != NULL) {
+               result = dns_journal_open(zone->mctx, journalfile,
+                                         ISC_TRUE, &journal);
+               if (result != ISC_R_SUCCESS) {
+                       dns_zone_log(zone, ISC_LOG_ERROR,
+                                    "%s:dns_journal_open -> %s\n",
+                                    caller, dns_result_totext(result));
+                       return;
+               }
+
+               result = dns_journal_write_transaction(journal, diff);
+               dns_journal_destroy(&journal);
+               if (result != ISC_R_SUCCESS) {
+                       dns_zone_log(zone, ISC_LOG_ERROR,
+                                    "%s:dns_journal_write_transaction -> %s\n",
+                                    caller, dns_result_totext(result));
+                       return;
+               }
+       }
+}
+
+/*
+ * Synchronize the set of initializing keys found in managed-keys {} 
+ * statements with the set of trust anchors found in the managed-keys.bind
+ * zone.  If a domain is no longer named in managed-keys, delete all keys
+ * from that domain from the key zone. If a domain is mentioned in in
+ * managed-keys but there are no references to it in the key zone, load
+ * the key zone with the initializing key(s) for that domain.
+ */
+static isc_result_t
+sync_keyzone(dns_zone_t *zone, dns_db_t *db, isc_boolean_t addsoa) {
+       isc_result_t result = ISC_R_SUCCESS;
+       isc_boolean_t changed = ISC_FALSE;
+       dns_rbtnodechain_t chain;
+       dns_fixedname_t fn;
+       dns_name_t foundname, *origin;
+       dns_keynode_t *keynode = NULL;
+       dns_view_t *view = zone->view;
+       dns_keytable_t *sr = view->secroots;
+       dns_dbversion_t *ver = NULL;
+       dns_diff_t diff;
+       dns_rriterator_t rrit;
+
+       dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
+
+       dns_name_init(&foundname, NULL);
+       dns_fixedname_init(&fn);
+       origin = dns_fixedname_name(&fn);
+
+       dns_diff_init(zone->mctx, &diff);
+       result = dns_db_newversion(db, &ver);
+       if (result != ISC_R_SUCCESS) {
+               dns_zone_log(zone, ISC_LOG_ERROR,
+                            "sync_keyzone:dns_db_newversion -> %s\n",
+                            dns_result_totext(result));
+               goto failure;
+       }
+
+       if (addsoa) {
+               /* If this zone is being newly created, make an SOA record. */
+               dns_rdata_t rdata = DNS_RDATA_INIT;
+
+               dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating key zone");
+
+               result = dns_soa_buildrdata(&zone->origin, dns_rootname,
+                                           zone->rdclass,
+                                           0, 0, 0, 0, 0, &rdata);
+               if (result != ISC_R_SUCCESS) {
+                       dns_zone_log(zone, ISC_LOG_ERROR,
+                                    "sync_keyzone:dns_soa_buildrdata -> %s\n",
+                                    dns_result_totext(result));
+                       goto failure;
+               }
+
+               CHECK(update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
+                                   &zone->origin, 0, &rdata));
+       } else {
+               /*
+                * Zone is not new, so walk the zone DB; if we find any keys
+                * whose names are no longer in managed-keys (or *are*
+                * in trusted-keys, meaning they are permanent and not
+                * RFC5011-maintained), delete them from the zone.  Otherwise
+                * call load_secroots(), which loads keys into secroots as
+                * appropriate.
+                */
+               dns_rriterator_init(&rrit, db, ver, 0);
+               for (result = dns_rriterator_first(&rrit);
+                    result == ISC_R_SUCCESS;
+                    result = dns_rriterator_nextrrset(&rrit)) {
+                       dns_rdataset_t *rdataset;
+                       dns_name_t *rrname = NULL;
+                       isc_uint32_t ttl;
+
+                       dns_rriterator_current(&rrit, &rrname, &ttl,
+                                              &rdataset, NULL);
+                       if (!dns_rdataset_isassociated(rdataset)) {
+                               dns_rriterator_destroy(&rrit);
+                               goto failure;
+                       } 
+
+                       if (rdataset->type != dns_rdatatype_keydata)
+                               continue;
+
+                       result = dns_keytable_find(sr, rrname, &keynode);
+
+                       if ((result != ISC_R_SUCCESS &&
+                            result != DNS_R_PARTIALMATCH) ||
+                           dns_keynode_managed(keynode) == ISC_FALSE) {
+                               CHECK(delete_keydata(db, ver, &diff,
+                                                    rrname, rdataset));
+                       } else {
+                               load_secroots(zone, rrname, rdataset);
+                       }
+
+                       if (keynode != NULL)
+                               dns_keytable_detachkeynode(sr, &keynode);
+               }
+
+               dns_rriterator_destroy(&rrit);
+       }
+
+       /*
+        * Now walk secroots to find any managed keys that aren't
+        * in the zone.  If we find any, we add them to the zone.
+        */
+       RWLOCK(&sr->rwlock, isc_rwlocktype_write);
+       dns_rbtnodechain_init(&chain, zone->mctx);
+       result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
+       if (result == ISC_R_NOTFOUND)
+               result = ISC_R_NOMORE;
+       while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
+               dns_rbtnode_t *rbtnode = NULL;
+               dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
+               keynode = rbtnode->data;
+               if (dns_keynode_managed(keynode)) {
+                       dns_fixedname_t fname;
+                       dns_fixedname_init(&fname);
+                       dst_key_t *key = dns_keynode_key(keynode);
+                       dns_name_t *keyname;
+                       if (key == NULL)   /* fail_secure() was called. */
+                               goto skip;
+                       keyname = dst_key_name(key);
+                       result = dns_db_find(db, keyname, ver,
+                                            dns_rdatatype_keydata,
+                                            DNS_DBFIND_NOWILD, 0, NULL,
+                                            dns_fixedname_name(&fname),
+                                            NULL, NULL);
+                       if (result != ISC_R_SUCCESS)
+                               result = create_keydata(zone, db, ver, &diff,
+                                                       keyname, sr, keynode,
+                                                       &changed);
+                       if (result != ISC_R_SUCCESS)
+                               break;
+               }
+  skip:
+               result = dns_rbtnodechain_next(&chain, &foundname, origin);
+       }
+       RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
+
+       if (changed) {
+               /* Write changes to journal file. */
+               result = increment_soa_serial(db, ver, &diff, zone->mctx);
+               if (result == ISC_R_SUCCESS)
+                       zone_journal(zone, &diff, "sync_keyzone");
+
+               DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
+               zone_needdump(zone, 30);
+       }
+
+ failure:
+       if (ver != NULL)
+               dns_db_closeversion(db, &ver, changed);
+       dns_diff_clear(&diff);
+
+       return (result);
+}
+
 static isc_result_t
 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
              isc_result_t result)
@@ -2435,12 +3047,15 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
                                             "failed: %s",
                                             zone->masterfile,
                                             dns_result_totext(result));
-               } else
+               } else {
                        dns_zone_log(zone, ISC_LOG_ERROR,
                                     "loading from master file %s failed: %s",
                                     zone->masterfile,
                                     dns_result_totext(result));
-               goto cleanup;
+               }
+
+               if (zone->type != dns_zone_key)
+                       goto cleanup;
        }
 
        dns_zone_log(zone, ISC_LOG_DEBUG(2),
@@ -2498,7 +3113,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
        result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
                                  &refresh, &retry, &expire, &minimum,
                                  &errors);
-       if (result != ISC_R_SUCCESS) {
+       if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
                dns_zone_log(zone, ISC_LOG_ERROR,
                             "could not find NS and/or SOA records");
        }
@@ -2616,6 +3231,13 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
                                zone->refreshtime = now;
                }
                break;
+
+       case dns_zone_key:
+               result = sync_keyzone(zone, db, ISC_TF(soacount == 0));
+               if (result != ISC_R_SUCCESS)
+                       goto cleanup;
+               break;
+
        default:
                UNEXPECTED_ERROR(__FILE__, __LINE__,
                                 "unexpected zone type %d", zone->type);
@@ -2653,9 +3275,12 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
                DNS_ZONE_SETFLAG(zone,
                                 DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
        }
+
        result = ISC_R_SUCCESS;
+
        if (needdump)
                zone_needdump(zone, DNS_DUMP_DELAY);
+
        if (zone->task != NULL) {
                if (zone->type == dns_zone_master) {
                        set_resigntime(zone);
@@ -2674,7 +3299,8 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
 
  cleanup:
        if (zone->type == dns_zone_slave ||
-           zone->type == dns_zone_stub) {
+           zone->type == dns_zone_stub ||
+           zone->type == dns_zone_key) {
                if (zone->journal != NULL)
                        zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
                if (zone->masterfile != NULL)
@@ -2972,7 +3598,7 @@ dns_zone_detach(dns_zone_t **zonep) {
                 */
                if (zone->task != NULL) {
                        /*
-                        * This zone is being managed.  Post
+                        * This zone is being managed.  Post
                         * its control event and let it clean
                         * up synchronously in the context of
                         * its task.
@@ -3461,105 +4087,23 @@ dns_zone_maintenance(dns_zone_t *zone) {
        UNLOCK_ZONE(zone);
 }
 
-static inline isc_boolean_t
-was_dumping(dns_zone_t *zone) {
-       isc_boolean_t dumping;
-
-       REQUIRE(LOCKED_ZONE(zone));
-
-       dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
-       DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
-       if (!dumping) {
-               DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
-               isc_time_settoepoch(&zone->dumptime);
-       }
-       return (dumping);
-}
-
-#define MAXZONEKEYS 10
-
-static isc_result_t
-do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
-            dns_diff_t *diff)
-{
-       dns_diff_t temp_diff;
-       isc_result_t result;
-
-       /*
-        * Create a singleton diff.
-        */
-       dns_diff_init(diff->mctx, &temp_diff);
-       temp_diff.resign = diff->resign;
-       ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
-
-       /*
-        * Apply it to the database.
-        */
-       result = dns_diff_apply(&temp_diff, db, ver);
-       ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
-       if (result != ISC_R_SUCCESS) {
-               dns_difftuple_free(tuple);
-               return (result);
-       }
-
-       /*
-        * Merge it into the current pending journal entry.
-        */
-       dns_diff_appendminimal(diff, tuple);
-
-       /*
-        * Do not clear temp_diff.
-        */
-       return (ISC_R_SUCCESS);
-}
-
-static isc_result_t
-increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver,
-                    dns_diff_t *diff, isc_mem_t *mctx)
-{
-       dns_difftuple_t *deltuple = NULL;
-       dns_difftuple_t *addtuple = NULL;
-       isc_uint32_t serial;
-       isc_result_t result;
-
-       CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
-       CHECK(dns_difftuple_copy(deltuple, &addtuple));
-       addtuple->op = DNS_DIFFOP_ADD;
-
-       serial = dns_soa_getserial(&addtuple->rdata);
-
-       /* RFC1982 */
-       serial = (serial + 1) & 0xFFFFFFFF;
-       if (serial == 0)
-               serial = 1;
-
-       dns_soa_setserial(serial, &addtuple->rdata);
-       CHECK(do_one_tuple(&deltuple, db, ver, diff));
-       CHECK(do_one_tuple(&addtuple, db, ver, diff));
-       result = ISC_R_SUCCESS;
-
-       failure:
-       if (addtuple != NULL)
-               dns_difftuple_free(&addtuple);
-       if (deltuple != NULL)
-               dns_difftuple_free(&deltuple);
-       return (result);
-}
-
-static isc_result_t
-update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
-             dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
-             dns_rdata_t *rdata)
-{
-       dns_difftuple_t *tuple = NULL;
-       isc_result_t result;
-       result = dns_difftuple_create(diff->mctx, op,
-                                     name, ttl, rdata, &tuple);
-       if (result != ISC_R_SUCCESS)
-               return (result);
-       return (do_one_tuple(&tuple, db, ver, diff));
+static inline isc_boolean_t
+was_dumping(dns_zone_t *zone) {
+       isc_boolean_t dumping;
+
+       REQUIRE(LOCKED_ZONE(zone));
+
+       dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
+       DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
+       if (!dumping) {
+               DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
+               isc_time_settoepoch(&zone->dumptime);
+       }
+       return (dumping);
 }
 
+#define MAXZONEKEYS 10
+
 static isc_boolean_t
 ksk_sanity(dns_db_t *db, dns_dbversion_t *ver) {
        isc_boolean_t ret = ISC_FALSE;
@@ -3839,7 +4383,6 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
 
 static void
 zone_resigninc(dns_zone_t *zone) {
-       const char *journalfile;
        dns_db_t *db = NULL;
        dns_dbversion_t *version = NULL;
        dns_diff_t sig_diff;
@@ -3955,7 +4498,7 @@ zone_resigninc(dns_zone_t *zone) {
                                     dns_result_totext(result));
                        break;
                }
-               result  = dns_db_getsigningtime(db, &rdataset,
+               result  = dns_db_getsigningtime(db, &rdataset,
                                                dns_fixedname_name(&fixed));
                if (nkeys == 0 && result == ISC_R_NOTFOUND) {
                        result = ISC_R_SUCCESS;
@@ -4001,31 +4544,10 @@ zone_resigninc(dns_zone_t *zone) {
                goto failure;
        }
 
-       journalfile = dns_zone_getjournal(zone);
-       if (journalfile != NULL) {
-               dns_journal_t *journal = NULL;
-               result = dns_journal_open(zone->mctx, journalfile,
-                                         ISC_TRUE, &journal);
-               if (result != ISC_R_SUCCESS) {
-                       dns_zone_log(zone, ISC_LOG_ERROR,
-                                    "zone_resigninc:dns_journal_open -> %s\n",
-                                    dns_result_totext(result));
-                       goto failure;
-               }
-
-               result = dns_journal_write_transaction(journal, &sig_diff);
-               dns_journal_destroy(&journal);
-               if (result != ISC_R_SUCCESS) {
-                       dns_zone_log(zone, ISC_LOG_ERROR,
-                        "zone_resigninc:dns_journal_write_transaction -> %s\n",
-                                    dns_result_totext(result));
-                       goto failure;
-               }
-       }
+       /* Write changes to journal file. */
+       zone_journal(zone, &sig_diff, "zone_resigninc");
 
-       /*
-        * Everything has succeeded. Commit the changes.
-        */
+       /* Everything has succeeded. Commit the changes. */
        dns_db_closeversion(db, &version, ISC_TRUE);
 
  failure:
@@ -4652,7 +5174,6 @@ need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
  */
 static void
 zone_nsec3chain(dns_zone_t *zone) {
-       const char *journalfile;
        dns_db_t *db = NULL;
        dns_dbnode_t *node = NULL;
        dns_dbversion_t *version = NULL;
@@ -5242,27 +5763,8 @@ zone_nsec3chain(dns_zone_t *zone) {
                goto failure;
        }
 
-       journalfile = dns_zone_getjournal(zone);
-       if (journalfile != NULL) {
-               dns_journal_t *journal = NULL;
-               result = dns_journal_open(zone->mctx, journalfile,
-                                         ISC_TRUE, &journal);
-               if (result != ISC_R_SUCCESS) {
-                       dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
-                                    "dns_journal_open -> %s\n",
-                                    dns_result_totext(result));
-                       goto failure;
-               }
-
-               result = dns_journal_write_transaction(journal, &sig_diff);
-               dns_journal_destroy(&journal);
-               if (result != ISC_R_SUCCESS) {
-                       dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
-                                    "dns_journal_write_transaction -> %s\n",
-                                    dns_result_totext(result));
-                       goto failure;
-               }
-       }
+       /* Write changes to journal file. */
+       zone_journal(zone, &sig_diff, "zone_nsec3chain");
 
        LOCK_ZONE(zone);
        zone_needdump(zone, DNS_DUMP_DELAY);
@@ -5447,7 +5949,6 @@ del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
  */
 static void
 zone_sign(dns_zone_t *zone) {
-       const char *journalfile;
        dns_db_t *db = NULL;
        dns_dbnode_t *node = NULL;
        dns_dbversion_t *version = NULL;
@@ -5577,7 +6078,7 @@ zone_sign(dns_zone_t *zone) {
                ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
                if (signing->done || signing->db != zone->db) {
                        /*
-                        * The zone has been reloaded.  We will have
+                        * The zone has been reloaded.  We will have
                         * created new signings as part of the reload
                         * process so we can destroy this one.
                         */
@@ -5696,7 +6197,8 @@ zone_sign(dns_zone_t *zone) {
                                                           &sig_diff);
                                if (result != ISC_R_SUCCESS) {
                                        dns_zone_log(zone, ISC_LOG_ERROR,
-                                                    "updatesignwithkey -> %s\n",
+                                                    "updatesignwithkey "
+                                                    "-> %s\n",
                                                     dns_result_totext(result));
                                        goto failure;
                                }
@@ -5773,134 +6275,896 @@ zone_sign(dns_zone_t *zone) {
                        goto failure;
                }
        }
-       result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
-                         &sig_diff, zone_keys, nkeys, now);
-       if (result != ISC_R_SUCCESS) {
-               dns_zone_log(zone, ISC_LOG_ERROR,
-                            "zone_sign:del_sigs -> %s\n",
-                            dns_result_totext(result));
-               goto failure;
-       }
+       result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
+                         &sig_diff, zone_keys, nkeys, now);
+       if (result != ISC_R_SUCCESS) {
+               dns_zone_log(zone, ISC_LOG_ERROR,
+                            "zone_sign:del_sigs -> %s\n",
+                            dns_result_totext(result));
+               goto failure;
+       }
+
+       result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
+       if (result != ISC_R_SUCCESS) {
+               dns_zone_log(zone, ISC_LOG_ERROR,
+                            "zone_sign:increment_soa_serial -> %s\n",
+                            dns_result_totext(result));
+               goto failure;
+       }
+
+       /*
+        * Generate maximum life time signatures so that the above loop
+        * termination is sensible.
+        */
+       result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
+                         &sig_diff, zone_keys, nkeys, zone->mctx, inception,
+                         soaexpire, check_ksk);
+       if (result != ISC_R_SUCCESS) {
+               dns_zone_log(zone, ISC_LOG_ERROR,
+                            "zone_sign:add_sigs -> %s\n",
+                            dns_result_totext(result));
+               goto failure;
+       }
+
+       /* Write changes to journal file. */
+       zone_journal(zone, &sig_diff, "zone_sign");
+
+       /*
+        * Pause all iterators so that dns_db_closeversion() can succeed.
+        */
+       for (signing = ISC_LIST_HEAD(zone->signing);
+            signing != NULL;
+            signing = ISC_LIST_NEXT(signing, link))
+               dns_dbiterator_pause(signing->dbiterator);
+
+       for (signing = ISC_LIST_HEAD(cleanup);
+            signing != NULL;
+            signing = ISC_LIST_NEXT(signing, link))
+               dns_dbiterator_pause(signing->dbiterator);
+
+       /*
+        * Everything has succeeded. Commit the changes.
+        */
+       dns_db_closeversion(db, &version, ISC_TRUE);
+
+       /*
+        * Everything succeeded so we can clean these up now.
+        */
+       signing = ISC_LIST_HEAD(cleanup);
+       while (signing != NULL) {
+               ISC_LIST_UNLINK(cleanup, signing, link);
+               dns_db_detach(&signing->db);
+               dns_dbiterator_destroy(&signing->dbiterator);
+               isc_mem_put(zone->mctx, signing, sizeof *signing);
+               signing = ISC_LIST_HEAD(cleanup);
+       }
+
+       set_resigntime(zone);
+
+       LOCK_ZONE(zone);
+       zone_needdump(zone, DNS_DUMP_DELAY);
+       UNLOCK_ZONE(zone);
+
+ failure:
+       /*
+        * Rollback the cleanup list.
+        */
+       signing = ISC_LIST_HEAD(cleanup);
+       while (signing != NULL) {
+               ISC_LIST_UNLINK(cleanup, signing, link);
+               ISC_LIST_APPEND(zone->signing, signing, link);
+               dns_dbiterator_first(signing->dbiterator);
+               dns_dbiterator_pause(signing->dbiterator);
+               signing = ISC_LIST_HEAD(cleanup);
+       }
+
+       for (signing = ISC_LIST_HEAD(zone->signing);
+            signing != NULL;
+            signing = ISC_LIST_NEXT(signing, link))
+               dns_dbiterator_pause(signing->dbiterator);
+
+       dns_diff_clear(&sig_diff);
+
+       for (i = 0; i < nkeys; i++)
+               dst_key_free(&zone_keys[i]);
+
+       if (version != NULL) {
+               dns_db_closeversion(db, &version, ISC_FALSE);
+               dns_db_detach(&db);
+       } else if (db != NULL)
+               dns_db_detach(&db);
+
+       if (ISC_LIST_HEAD(zone->signing) != NULL) {
+               isc_interval_t i;
+               if (zone->update_disabled || result != ISC_R_SUCCESS)
+                       isc_interval_set(&i, 60, 0);            /* 1 minute */
+               else
+                       isc_interval_set(&i, 0, 10000000);      /* 10 ms */
+               isc_time_nowplusinterval(&zone->signingtime, &i);
+       } else
+               isc_time_settoepoch(&zone->signingtime);
+}
+
+static void
+normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
+             unsigned char *data, int size) {
+       dns_rdata_dnskey_t dnskey;
+       dns_rdata_keydata_t keydata;
+       isc_buffer_t buf;
+
+       dns_rdata_reset(target);
+       isc_buffer_init(&buf, data, size);
+
+       switch (rr->type) {
+           case dns_rdatatype_dnskey:
+               dns_rdata_tostruct(rr, &dnskey, NULL);
+               dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
+               dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
+                                    &dnskey, &buf);
+               break;
+           case dns_rdatatype_keydata:
+               dns_rdata_tostruct(rr, &keydata, NULL);
+               dns_keydata_todnskey(&keydata, &dnskey, NULL);
+               dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
+                                    &dnskey, &buf);
+               break;
+           default:
+               INSIST(0);
+       }
+}
+
+/*
+ * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
+ * a KEYDATA rdataset from the key zone.
+ *
+ * 'rr' contains either a DNSKEY record, or a KEYDATA record
+ *
+ * After normalizing keys to the same format (DNSKEY, with revoke bit
+ * cleared), return ISC_TRUE if a key that matches 'rr' is found in
+ * 'rdset', or ISC_FALSE if not.
+ */
+
+static isc_boolean_t
+matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
+       unsigned char data1[4096], data2[4096];
+       dns_rdata_t rdata, rdata1, rdata2;
+       isc_result_t result;
+
+       dns_rdata_init(&rdata);
+       dns_rdata_init(&rdata1);
+       dns_rdata_init(&rdata2);
+
+       normalize_key(rr, &rdata1, data1, sizeof(data1));
+
+       for (result = dns_rdataset_first(rdset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(rdset)) {
+               dns_rdata_reset(&rdata);
+               dns_rdataset_current(rdset, &rdata);
+               normalize_key(&rdata, &rdata2, data2, sizeof(data2));
+               if (dns_rdata_compare(&rdata1, &rdata2) == 0)
+                       return (ISC_TRUE);
+       }
+
+       return (ISC_FALSE);
+}
+
+/*
+ * Calculate the refresh interval for a keydata zone, per
+ * RFC5011: MAX(1 hr,
+ *             MIN(15 days,
+ *                 1/2 * OrigTTL,
+ *                 1/2 * RRSigExpirationInterval))
+ */
+static inline isc_stdtime_t
+refresh_time(dns_keyfetch_t *kfetch) {
+       isc_result_t result;
+       isc_uint32_t t;
+       dns_rdataset_t *rdset;
+       dns_rdata_t sigrr = DNS_RDATA_INIT;
+       dns_rdata_sig_t sig;
+       isc_stdtime_t now;
+
+       isc_stdtime_get(&now);
+
+       if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
+               rdset = &kfetch->dnskeysigset;
+       else
+               return (now + HOUR);
+
+       result = dns_rdataset_first(rdset);
+       if (result != ISC_R_SUCCESS)
+               return (now + HOUR);
+
+       dns_rdataset_current(rdset, &sigrr);
+       result = dns_rdata_tostruct(&sigrr, &sig, NULL);
+
+       t = sig.originalttl / 2;
+
+       if (isc_serial_gt(sig.timeexpire, now)) {
+               isc_uint32_t exp = (sig.timeexpire - now) / 2;
+               if (t > exp)
+                       t = exp;
+       }
+
+       if (t > (15*DAY))
+               t = (15*DAY);
+
+       if (t < HOUR)
+               t = HOUR;
+
+       return (now + t);
+}
+
+/*
+ * This routine is called when no changes are needed in a KEYDATA
+ * record except to simply update the refresh timer.  Caller should
+ * hold zone lock.
+ */
+static isc_result_t
+minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) {
+       isc_result_t result;
+       isc_buffer_t keyb;
+       unsigned char key_buf[4096];
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       dns_rdata_keydata_t keydata;
+       dns_name_t *name;
+       dns_zone_t *zone = kfetch->zone;
+       isc_stdtime_t now;
+
+       name = dns_fixedname_name(&kfetch->name);
+       isc_stdtime_get(&now);
+
+       for (result = dns_rdataset_first(&kfetch->keydataset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(&kfetch->keydataset)) {
+               dns_rdata_reset(&rdata);
+               dns_rdataset_current(&kfetch->keydataset, &rdata);
+
+               /* Delete old version */
+               CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
+                                   name, 0, &rdata));
+
+               /* Update refresh timer */
+               dns_rdata_tostruct(&rdata, &keydata, NULL);
+               keydata.refresh = refresh_time(kfetch);
+               set_refreshkeytimer(zone, &keydata, now);
+
+               dns_rdata_reset(&rdata);
+               isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+               dns_rdata_fromstruct(&rdata,
+                                    zone->rdclass, dns_rdatatype_keydata,
+                                    &keydata, &keyb);
+
+               /* Insert updated version */
+               CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
+                                   name, 0, &rdata));
+       }
+       result = ISC_R_SUCCESS;
+  failure:
+       return (result);
+}
+
+/*
+ * Verify that DNSKEY set is signed by the key specified in 'keydata'.
+ */
+static isc_boolean_t
+revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
+       isc_result_t result;
+       dns_name_t *keyname;
+       isc_mem_t *mctx;
+       dns_rdata_t sigrr = DNS_RDATA_INIT;
+       dns_rdata_t rr = DNS_RDATA_INIT;
+       dns_rdata_rrsig_t sig;
+       dns_rdata_dnskey_t dnskey;
+       dst_key_t *dstkey = NULL;
+       unsigned char key_buf[4096];
+       isc_buffer_t keyb;
+       isc_boolean_t answer = ISC_FALSE;
+
+       REQUIRE(kfetch != NULL && keydata != NULL);
+       REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
+
+       keyname = dns_fixedname_name(&kfetch->name);
+       mctx = kfetch->zone->view->mctx;
+
+       /* Generate a key from keydata */
+       isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+       dns_keydata_todnskey(keydata, &dnskey, NULL);
+       dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
+                                    &dnskey, &keyb);
+       result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
+       if (result != ISC_R_SUCCESS)
+               return (ISC_FALSE);
+
+       /* See if that key generated any of the signatures */
+       for (result = dns_rdataset_first(&kfetch->dnskeysigset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(&kfetch->dnskeysigset)) {
+               dns_fixedname_t fixed;
+               dns_fixedname_init(&fixed);
+
+               dns_rdata_reset(&sigrr);
+               dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
+               result = dns_rdata_tostruct(&sigrr, &sig, NULL);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+               if (dst_key_alg(dstkey) == sig.algorithm &&
+                   (dst_key_id(dstkey) == sig.keyid ||
+                    (sig.algorithm != 1 && sig.keyid ==
+                      ((dst_key_id(dstkey) + 128) & 0xffff)))) {
+                       result = dns_dnssec_verify2(keyname,
+                                           &kfetch->dnskeyset,
+                                           dstkey, ISC_FALSE, mctx, &sigrr,
+                                           dns_fixedname_name(&fixed));
+
+                       dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
+                                    "Confirm revoked DNSKEY is self-signed: "
+                                    "%s", dns_result_totext(result));
+
+                       if (result == ISC_R_SUCCESS) {
+                               answer = ISC_TRUE;
+                               break;
+                       }
+               }
+       }
 
-       result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
-       if (result != ISC_R_SUCCESS) {
-               dns_zone_log(zone, ISC_LOG_ERROR,
-                            "zone_sign:increment_soa_serial -> %s\n",
-                            dns_result_totext(result));
+       dst_key_free(&dstkey);
+       return (answer);
+}
+
+/*
+ * A DNSKEY set has been fetched from the zone apex of a zone whose trust
+ * anchors are being managed; scan the keyset, and update the key zone and the
+ * local trust anchors according to RFC5011.
+ */
+static void
+keyfetch_done(isc_task_t *task, isc_event_t *event) {
+       isc_result_t result, eresult;
+       dns_fetchevent_t *devent;
+       dns_keyfetch_t *kfetch;
+       dns_zone_t *zone;
+       dns_keytable_t *secroots;
+       dns_dbversion_t *ver = NULL;
+       dns_diff_t diff;
+       isc_boolean_t changed = ISC_FALSE;
+       isc_boolean_t alldone = ISC_FALSE;
+       dns_name_t *keyname;
+       dns_rdata_t sigrr = DNS_RDATA_INIT;
+       dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
+       dns_rdata_t keydatarr = DNS_RDATA_INIT;
+       dns_rdata_rrsig_t sig;
+       dns_rdata_dnskey_t dnskey;
+       dns_rdata_keydata_t keydata;
+       isc_boolean_t initializing;
+       char namebuf[DNS_NAME_FORMATSIZE];
+       unsigned char key_buf[4096];
+       isc_buffer_t keyb;
+       dst_key_t *dstkey;
+       isc_stdtime_t now;
+       int pending = 0;
+
+       UNUSED(task);
+       INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
+       INSIST(event->ev_arg != NULL);
+
+       kfetch = event->ev_arg;
+       zone = kfetch->zone;
+       secroots = zone->view->secroots;
+       keyname = dns_fixedname_name(&kfetch->name);
+
+       devent = (dns_fetchevent_t *) event;
+       eresult = devent->result;
+
+       /* Free resources which are not of interest */
+       if (devent->node != NULL)
+               dns_db_detachnode(devent->db, &devent->node);
+       if (devent->db != NULL)
+               dns_db_detach(&devent->db);
+       isc_event_free(&event);
+       dns_resolver_destroyfetch(&kfetch->fetch);
+
+       isc_stdtime_get(&now);
+       dns_name_format(keyname, namebuf, sizeof(namebuf));
+
+       LOCK_ZONE(zone);
+       dns_db_newversion(kfetch->db, &ver);
+       dns_diff_init(zone->mctx, &diff);
+
+       /* Fetch failed */
+       if (eresult != ISC_R_SUCCESS) {
+               dns_zone_log(zone, ISC_LOG_WARNING,
+                            "Unable to fetch DNSKEY set "
+                            "'%s': %s", namebuf, dns_result_totext(eresult));
+               CHECK(minimal_update(kfetch, ver, &diff));
                goto failure;
        }
 
        /*
-        * Generate maximum life time signatures so that the above loop
-        * termination is sensible.
+        * Validate the dnskeyset against the current trusted keys.
+        * (Note, if a key has been revoked and isn't RSAMD5, then
+        * its key ID will have changed.)
         */
-       result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
-                         &sig_diff, zone_keys, nkeys, zone->mctx, inception,
-                         soaexpire, check_ksk);
-       if (result != ISC_R_SUCCESS) {
-               dns_zone_log(zone, ISC_LOG_ERROR,
-                            "zone_sign:add_sigs -> %s\n",
-                            dns_result_totext(result));
-               goto failure;
-       }
+       for (result = dns_rdataset_first(&kfetch->dnskeysigset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(&kfetch->dnskeysigset)) {
+               dns_keynode_t *keynode = NULL;
 
-       journalfile = dns_zone_getjournal(zone);
-       if (journalfile != NULL) {
-               dns_journal_t *journal = NULL;
-               result = dns_journal_open(zone->mctx, journalfile,
-                                         ISC_TRUE, &journal);
-               if (result != ISC_R_SUCCESS) {
-                       dns_zone_log(zone, ISC_LOG_ERROR,
-                                    "zone_sign:dns_journal_open -> %s\n",
-                                    dns_result_totext(result));
-                       goto failure;
-               }
+               dns_rdata_reset(&sigrr);
+               dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
+               result = dns_rdata_tostruct(&sigrr, &sig, NULL);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
-               result = dns_journal_write_transaction(journal, &sig_diff);
-               dns_journal_destroy(&journal);
-               if (result != ISC_R_SUCCESS) {
-                       dns_zone_log(zone, ISC_LOG_ERROR,
-                        "zone_sign:dns_journal_write_transaction -> %s\n",
-                                    dns_result_totext(result));
-                       goto failure;
+               result = dns_keytable_find(secroots, keyname, &keynode);
+               while (result == ISC_R_SUCCESS) {
+                       dns_keynode_t *nextnode = NULL;
+                       dns_fixedname_t fixed;
+                       dns_fixedname_init(&fixed);
+
+                       dstkey = dns_keynode_key(keynode);
+                       if (dstkey == NULL) /* fail_secure() was called */
+                               break;
+
+                       if (dst_key_alg(dstkey) == sig.algorithm &&
+                           (dst_key_id(dstkey) == sig.keyid ||
+                            (sig.algorithm != 1 && sig.keyid ==
+                              ((dst_key_id(dstkey) + 128) & 0xffff)))) {
+                               result = dns_dnssec_verify2(keyname,
+                                                   &kfetch->dnskeyset,
+                                                   dstkey, ISC_FALSE,
+                                                   zone->view->mctx, &sigrr,
+                                                   dns_fixedname_name(&fixed));
+
+                               dns_zone_log(zone, ISC_LOG_DEBUG(3),
+                                            "Verifying DNSKEY set for zone "
+                                            "'%s': %s", namebuf,
+                                            dns_result_totext(result));
+
+                               if (result == ISC_R_SUCCESS) {
+                                       kfetch->dnskeyset.trust =
+                                               dns_trust_secure;
+                                       kfetch->dnskeysigset.trust =
+                                               dns_trust_secure;
+                                       dns_keytable_detachkeynode(secroots,
+                                                                  &keynode);
+                                       break;
+                               }
+                       }
+
+                       result = dns_keytable_nextkeynode(secroots,
+                                                         keynode, &nextnode);
+                       dns_keytable_detachkeynode(secroots, &keynode);
+                       keynode = nextnode;
                }
+
+               if (kfetch->dnskeyset.trust == dns_trust_secure)
+                       break;
        }
 
+       /* Failed to validate?  Let's go home. */
+       if (kfetch->dnskeyset.trust != dns_trust_secure) {
+               dns_zone_log(zone, ISC_LOG_WARNING,
+                            "DNSKEY set for zone '%s' failed to validate",
+                            namebuf);
+               CHECK(minimal_update(kfetch, ver, &diff));
+               changed = ISC_TRUE;
+               goto failure;
+       }
 
        /*
-        * Pause all iterators so that dns_db_closeversion() can succeed.
-        */
-       for (signing = ISC_LIST_HEAD(zone->signing);
-            signing != NULL;
-            signing = ISC_LIST_NEXT(signing, link))
-               dns_dbiterator_pause(signing->dbiterator);
+        * First scan keydataset to find keys that are not in dnskeyset
+        *   - Missing keys which are not scheduled for removal,
+        *     log a warning
+        *   - Missing keys which are scheduled for removal and
+        *     the remove hold-down timer has completed should
+        *     be removed from the key zone
+        *   - Missing keys whose acceptance timers have not yet
+        *     completed, log a warning and reset the acceptance
+        *     timer to 30 days in the future
+        *   - All keys not being removed have their refresh timers
+        *     updated
+        */ 
+       initializing = ISC_TRUE;
+       for (result = dns_rdataset_first(&kfetch->keydataset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(&kfetch->keydataset)) {
+               dns_rdata_reset(&keydatarr);
+               dns_rdataset_current(&kfetch->keydataset, &keydatarr);
+               dns_rdata_tostruct(&keydatarr, &keydata, NULL);
 
-       for (signing = ISC_LIST_HEAD(cleanup);
-            signing != NULL;
-            signing = ISC_LIST_NEXT(signing, link))
-               dns_dbiterator_pause(signing->dbiterator);
+               /*
+                * If any keydata record has a nonzero add holddown, then
+                * there was a pre-existing trust anchor for this domain;
+                * that means we are *not* initializing it and shouldn't
+                * automatically trust all the keys we find at the zone apex.
+                */
+               initializing = initializing && ISC_TF(keydata.addhd == 0);
 
-       /*
-        * Everything has succeeded. Commit the changes.
-        */
-       dns_db_closeversion(db, &version, ISC_TRUE);
+               if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
+                       isc_boolean_t deletekey = ISC_FALSE;
+
+                       if (now < keydata.addhd) {
+                               dns_zone_log(zone, ISC_LOG_WARNING,
+                                            "Pending key unexpectedly missing "
+                                            "from %s; restarting acceptance "
+                                            "timer", namebuf);
+                               keydata.addhd = now + MONTH;
+                               keydata.refresh = refresh_time(kfetch);
+                       } else if (keydata.addhd == 0) {
+                               keydata.addhd = now;
+                       } else if (keydata.removehd == 0) {
+                               dns_zone_log(zone, ISC_LOG_WARNING,
+                                            "Active key unexpectedly missing "
+                                            "from %s", namebuf);
+                               keydata.refresh = now + HOUR;
+                       } else if (now > keydata.removehd) {
+                               deletekey = ISC_TRUE;
+                       } else {
+                               keydata.refresh = refresh_time(kfetch);
+                       }
+
+                       /* Delete old version */
+                       CHECK(update_one_rr(kfetch->db, ver, &diff,
+                                           DNS_DIFFOP_DEL, keyname, 0,
+                                           &keydatarr));
+                       changed = ISC_TRUE;
+
+                       if (deletekey)
+                               continue;
+
+                       dns_rdata_reset(&keydatarr);
+                       isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+                       dns_rdata_fromstruct(&keydatarr, zone->rdclass,
+                                            dns_rdatatype_keydata,
+                                            &keydata, &keyb);
+
+                       /* Insert updated version */
+                       CHECK(update_one_rr(kfetch->db, ver, &diff, 
+                                           DNS_DIFFOP_ADD, keyname, 0,
+                                           &keydatarr));
+                       changed = ISC_TRUE;
+
+                       set_refreshkeytimer(zone, &keydata, now);
+               }
+       }
 
        /*
-        * Everything succeeded so we can clean these up now.
+        * Next scan dnskeyset:
+        *   - If new keys are found (i.e., lacking a match in keydataset)
+        *     add them to the key zone and set the acceptance timer
+        *     to 30 days in the future (or to immediately if we've
+        *     determined that we're initializing the zone for the
+        *     first time)
+        *   - Previously-known keys that have been revoked
+        *     must be scheduled for removal from the key zone (or,
+        *     if they hadn't been accepted as trust anchors yet
+        *     anyway, removed at once)
+        *   - Previously-known unrevoked keys whose acceptance timers
+        *     have completed are promoted to trust anchors
+        *   - All keys not being removed have their refresh
+        *     timers updated
         */
-       signing = ISC_LIST_HEAD(cleanup);
-       while (signing != NULL) {
-               ISC_LIST_UNLINK(cleanup, signing, link);
-               dns_db_detach(&signing->db);
-               dns_dbiterator_destroy(&signing->dbiterator);
-               isc_mem_put(zone->mctx, signing, sizeof *signing);
-               signing = ISC_LIST_HEAD(cleanup);
-       }
+       for (result = dns_rdataset_first(&kfetch->dnskeyset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(&kfetch->dnskeyset)) {
+               isc_boolean_t revoked = ISC_FALSE;
+               isc_boolean_t newkey = ISC_FALSE;
+               isc_boolean_t updatekey = ISC_FALSE;
+               isc_boolean_t deletekey = ISC_FALSE;
+               isc_boolean_t trustkey = ISC_FALSE;
+
+               dns_rdata_reset(&dnskeyrr);
+               dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
+               dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
+
+               /* Skip ZSK's */
+               if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
+                       continue;
 
-       set_resigntime(zone);
+               revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
+
+               if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
+                       dns_rdata_reset(&keydatarr);
+                       dns_rdataset_current(&kfetch->keydataset, &keydatarr);
+                       dns_rdata_tostruct(&keydatarr, &keydata, NULL);
+
+                       if (revoked) {
+                               if (keydata.addhd > now) {
+                                       /*
+                                        * Key wasn't trusted yet, and now
+                                        * it's been revoked?  Just remove it
+                                        */
+                                       deletekey = ISC_TRUE;
+                               } else if (keydata.removehd == 0) {
+                                       /*
+                                        * Newly revoked key?  Make sure
+                                        * it signed itself
+                                        */
+                                       if(! revocable(kfetch, &keydata)) {
+                                               dns_zone_log(zone,
+                                                            ISC_LOG_WARNING,
+                                                        "Active key for zone "
+                                                        "'%s' is revoked but "
+                                                        "did not self-sign; "
+                                                        "ignoring.", namebuf);
+                                               continue;
+                                       }
+
+                                       /* Remove from secroots */
+                                       untrust_key(zone->view->viewlist,
+                                                   keyname, zone->mctx,
+                                                   &dnskey);
+
+                                       /* If initializing, delete now */
+                                       if (keydata.addhd == 0)
+                                               deletekey = ISC_TRUE;
+                                       else
+                                               keydata.removehd = now + MONTH;
+                               } else if (keydata.removehd < now) {
+                                       /* Scheduled for removal */
+                                       deletekey = ISC_TRUE;
+                               }
+                       } else {
+                               if (keydata.removehd != 0) {
+                                       /*
+                                        * Key isn't revoked--but it 
+                                        * seems it used to be. 
+                                        * Remove it now and add it
+                                        * back as if it were a fresh key.
+                                        */
+                                       deletekey = ISC_TRUE;
+                                       newkey = ISC_TRUE;
+                               } else if (keydata.addhd > now)
+                                       pending++;
+                               else if (keydata.addhd == 0)
+                                       keydata.addhd = now;
+
+                               if (keydata.addhd <= now)
+                                       trustkey = ISC_TRUE;
+                       }
+
+                       if (!deletekey && !newkey)
+                               updatekey = ISC_TRUE;
+               } else {
+                       /*
+                        * Key wasn't in the key zone but it's 
+                        * revoked now anyway, so just skip it
+                        */
+                       if (revoked)
+                               continue;
+
+                       /* Key wasn't in the key zone: add it */
+                       newkey = ISC_TRUE;
+
+                       if (initializing) {
+                               dns_keytag_t tag = 0;
+                               CHECK(compute_tag(keyname, &dnskey,
+                                                 zone->mctx, &tag));
+                               dns_zone_log(zone, ISC_LOG_WARNING,
+                                            "Initializing automatic trust "
+                                            "anchor management for zone '%s'; "
+                                            "DNSKEY ID %d is now trusted, "
+                                            "waiving the normal 30-day "
+                                            "waiting period.",
+                                            namebuf, tag);
+                               trustkey = ISC_TRUE;
+                       }
+               }
+
+               /* Delete old version */
+               if (deletekey || !newkey) {
+                       CHECK(update_one_rr(kfetch->db, ver, &diff, 
+                                           DNS_DIFFOP_DEL, keyname, 0,
+                                           &keydatarr));
+                       changed = ISC_TRUE;
+               }
+
+               if (updatekey) {
+                       /* Set refresh timer */
+                       keydata.refresh = refresh_time(kfetch);
+                       dns_rdata_reset(&keydatarr);
+                       isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+                       dns_rdata_fromstruct(&keydatarr, zone->rdclass,
+                                            dns_rdatatype_keydata,
+                                            &keydata, &keyb);
+
+                       /* Insert updated version */
+                       CHECK(update_one_rr(kfetch->db, ver, &diff,
+                                           DNS_DIFFOP_ADD, keyname, 0,
+                                           &keydatarr));
+                       changed = ISC_TRUE;
+               } else if (newkey) {
+                       /* Convert DNSKEY to KEYDATA */
+                       dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
+                       dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
+                                              NULL);
+                       keydata.addhd = initializing ? now : now + MONTH;
+                       keydata.refresh = refresh_time(kfetch);
+                       dns_rdata_reset(&keydatarr);
+                       isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+                       dns_rdata_fromstruct(&keydatarr, zone->rdclass,
+                                            dns_rdatatype_keydata,
+                                            &keydata, &keyb);
+
+                       /* Insert into key zone */
+                       CHECK(update_one_rr(kfetch->db, ver, &diff,
+                                           DNS_DIFFOP_ADD, keyname, 0,
+                                           &keydatarr));
+                       changed = ISC_TRUE;
+               }
+
+               if (trustkey) {
+                       /* Trust this key in all views */
+                       dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
+                       trust_key(zone->view->viewlist, keyname, &dnskey,
+                                 zone->mctx);
+               }
+
+               if (!deletekey)
+                       set_refreshkeytimer(zone, &keydata, now);
+       }
+
+       /*
+        * RFC5011 says, "A trust point that has all of its trust anchors
+        * revoked is considered deleted and is treated as if the trust
+        * point was never configured."  But if someone revoked their
+        * active key before the standby was trusted, that would mean the
+        * zone would suddenly be nonsecured.  We avoid this by checking to
+        * see if there's pending keydata.  If so, we put a null key in
+        * the security roots; then all queries to the zone will fail.
+        */
+       if (pending != 0)
+               fail_secure(zone->view->viewlist, keyname);
+
+  failure:
+       zone->refreshkeycount--;
+       alldone = ISC_TF(zone->refreshkeycount == 0);
+
+       if (changed) {
+               DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
+               zone_needdump(zone, 30);
+       }
+       
+       if (alldone)
+               DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
 
-       LOCK_ZONE(zone);
-       zone_needdump(zone, DNS_DUMP_DELAY);
        UNLOCK_ZONE(zone);
 
- failure:
-       /*
-        * Rollback the cleanup list.
-        */
-       signing = ISC_LIST_HEAD(cleanup);
-       while (signing != NULL) {
-               ISC_LIST_UNLINK(cleanup, signing, link);
-               ISC_LIST_APPEND(zone->signing, signing, link);
-               dns_dbiterator_first(signing->dbiterator);
-               dns_dbiterator_pause(signing->dbiterator);
-               signing = ISC_LIST_HEAD(cleanup);
+       /* Write changes to journal file. */
+       if (alldone) {
+               result = increment_soa_serial(kfetch->db, ver, &diff,
+                                             zone->mctx);
+               if (result == ISC_R_SUCCESS)
+                       zone_journal(zone, &diff, "keyfetch_done");
        }
 
-       for (signing = ISC_LIST_HEAD(zone->signing);
-            signing != NULL;
-            signing = ISC_LIST_NEXT(signing, link))
-               dns_dbiterator_pause(signing->dbiterator);
+       dns_diff_clear(&diff);
+       dns_db_closeversion(kfetch->db, &ver, alldone);
+       dns_db_detach(&kfetch->db);
 
-       dns_diff_clear(&sig_diff);
+       if (dns_rdataset_isassociated(&kfetch->keydataset))
+               dns_rdataset_disassociate(&kfetch->keydataset);
+       if (dns_rdataset_isassociated(&kfetch->dnskeyset))
+               dns_rdataset_disassociate(&kfetch->dnskeyset);
+       if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
+               dns_rdataset_disassociate(&kfetch->dnskeysigset);
 
-       for (i = 0; i < nkeys; i++)
-               dst_key_free(&zone_keys[i]);
+       dns_name_free(keyname, zone->mctx);
+       isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
+}
 
-       if (version != NULL) {
-               dns_db_closeversion(db, &version, ISC_FALSE);
-               dns_db_detach(&db);
-       } else if (db != NULL)
-               dns_db_detach(&db);
+/*
+ * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
+ * records from the zone apex.
+ */
+static void
+zone_refreshkeys(dns_zone_t *zone) {
+       const char me[] = "zone_refreshkeys";
+       isc_result_t result;
+       dns_rriterator_t rrit;
+       dns_db_t *db = NULL;
+       dns_dbversion_t *ver = NULL;
+       dns_diff_t diff;
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       dns_rdata_keydata_t kd;
+       isc_stdtime_t now;
 
-       if (ISC_LIST_HEAD(zone->signing) != NULL) {
-               isc_interval_t i;
-               if (zone->update_disabled || result != ISC_R_SUCCESS)
-                       isc_interval_set(&i, 60, 0);            /* 1 minute */
-               else
-                       isc_interval_set(&i, 0, 10000000);      /* 10 ms */
-               isc_time_nowplusinterval(&zone->signingtime, &i);
-       } else
-               isc_time_settoepoch(&zone->signingtime);
+       ENTER;
+       REQUIRE(zone->db != NULL);
+
+       isc_stdtime_get(&now);
+
+       ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+       dns_db_attach(zone->db, &db);
+       ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+       LOCK_ZONE(zone);
+       dns_db_newversion(db, &ver);
+       dns_diff_init(zone->mctx, &diff);
+
+       DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
+
+       dns_rriterator_init(&rrit, db, ver, 0);
+       for (result = dns_rriterator_first(&rrit);
+            result == ISC_R_SUCCESS;
+            result = dns_rriterator_nextrrset(&rrit)) {
+               isc_stdtime_t timer = 0xffffffff;
+               dns_keyfetch_t *kfetch;
+               dns_rdataset_t *kdset;
+               dns_name_t *name = NULL;
+               isc_uint32_t ttl;
+
+               dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
+               if (!dns_rdataset_isassociated(kdset))
+                       continue;
+
+               if (kdset->type != dns_rdatatype_keydata)
+                       continue;
+
+               /*
+                * Scan the stored keys looking for ones that need
+                * removal or refreshing
+                */
+               for (result = dns_rdataset_first(kdset);
+                    result == ISC_R_SUCCESS;
+                    result = dns_rdataset_next(kdset)) {
+                       dns_rdata_reset(&rdata);
+                       dns_rdataset_current(kdset, &rdata);
+                       result = dns_rdata_tostruct(&rdata, &kd, NULL);
+                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+                       /* Removal timer expired? */
+                       if (kd.removehd != 0 && kd.removehd < now) {
+                               CHECK(update_one_rr(db, ver, &diff,
+                                                   DNS_DIFFOP_DEL, name, ttl,
+                                                   &rdata));
+                               continue;
+                       }
+
+                       /* Acceptance timer expired? */
+                       if (kd.addhd != 0 && kd.addhd < now)
+                               timer = kd.addhd;
+
+                       /* Or do we just need to refresh the keyset? */
+                       if (timer > kd.refresh)
+                               timer = kd.refresh;
+               }
+
+               if (timer > now)
+                       continue;
+
+               zone->refreshkeycount++;
+
+               kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
+               kfetch->zone = zone;
+               dns_fixedname_init(&kfetch->name);
+               dns_name_dup(name, zone->mctx,
+                            dns_fixedname_name(&kfetch->name));
+               dns_rdataset_init(&kfetch->dnskeyset);
+               dns_rdataset_init(&kfetch->dnskeysigset);
+               dns_rdataset_init(&kfetch->keydataset);
+               dns_rdataset_clone(kdset, &kfetch->keydataset);
+               kfetch->db = NULL;
+               dns_db_attach(db, &kfetch->db);
+               kfetch->fetch = NULL;
+
+               dns_resolver_createfetch(zone->view->resolver,
+                                        dns_fixedname_name(&kfetch->name),
+                                        dns_rdatatype_dnskey, 
+                                        NULL, NULL, NULL,
+                                        DNS_FETCHOPT_NOVALIDATE,
+                                        zone->task, keyfetch_done, kfetch,
+                                        &kfetch->dnskeyset,
+                                        &kfetch->dnskeysigset,
+                                        &kfetch->fetch);
+       }
+  failure:
+       UNLOCK_ZONE(zone);
+
+       dns_rriterator_destroy(&rrit);
+       dns_diff_clear(&diff);
+       dns_db_closeversion(db, &ver, ISC_FALSE);
+       dns_db_detach(&db);
 }
 
 static void
@@ -5916,7 +7180,7 @@ zone_maintenance(dns_zone_t *zone) {
        /*
         * Configuring the view of this zone may have
         * failed, for example because the config file
-        * had a syntax error.  In that case, the view
+        * had a syntax error.  In that case, the view
         * adb or resolver, and we had better not try
         * to do maintenance on it.
         */
@@ -5963,6 +7227,7 @@ zone_maintenance(dns_zone_t *zone) {
        switch (zone->type) {
        case dns_zone_master:
        case dns_zone_slave:
+       case dns_zone_key:
                LOCK_ZONE(zone);
                if (zone->masterfile != NULL &&
                    isc_time_compare(&now, &zone->dumptime) >= 0 &&
@@ -5984,6 +7249,20 @@ zone_maintenance(dns_zone_t *zone) {
                break;
        }
 
+       /*
+        * Do we need to refresh keys?
+        */
+       switch (zone->type) {
+       case dns_zone_key:
+               if (isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
+                   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
+                   !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
+                       zone_refreshkeys(zone);
+               break;
+       default:
+               break;
+       }
+
        switch (zone->type) {
        case dns_zone_master:
        case dns_zone_slave:
@@ -8376,7 +9655,7 @@ zone_shutdown(isc_task_t *task, isc_event_t *event) {
 
        /*
         * We have now canceled everything set the flag to allow exit_check()
-        * to succeed.  We must not unlock between setting this flag and
+        * to succeed.  We must not unlock between setting this flag and
         * calling exit_check().
         */
        DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
@@ -8407,6 +9686,7 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) {
        isc_time_t next;
        isc_result_t result;
 
+       ENTER;
        REQUIRE(DNS_ZONE_VALID(zone));
        if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
                return;
@@ -8476,6 +9756,22 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) {
                }
                break;
 
+       case dns_zone_key:
+               if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
+                   !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
+                       INSIST(!isc_time_isepoch(&zone->dumptime));
+                       if (isc_time_isepoch(&next) ||
+                           isc_time_compare(&zone->dumptime, &next) < 0)
+                               next = zone->dumptime;
+               }
+               if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
+                       if (isc_time_isepoch(&next) ||
+                           (!isc_time_isepoch(&zone->refreshkeytime) &&
+                           isc_time_compare(&zone->refreshkeytime, &next) < 0))
+                               next = zone->refreshkeytime;
+               }
+               break;
+
        default:
                break;
        }
@@ -9393,7 +10689,7 @@ notify_done(isc_task_t *task, isc_event_t *event) {
                           dns_result_totext(result));
 
        /*
-        * Old bind's return formerr if they see a soa record.  Retry w/o
+        * Old bind's return formerr if they see a soa record.  Retry w/o
         * the soa if we see a formerr and had sent a SOA.
         */
        isc_event_free(&event);
@@ -9448,7 +10744,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
                                     "has %d SOA records", soacount);
                        result = DNS_R_BADZONE;
                }
-               if (nscount == 0) {
+               if (nscount == 0 && zone->type != dns_zone_key) {
                        dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
                        result = DNS_R_BADZONE;
                }
@@ -9555,7 +10851,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
                         * being loaded from disk.  Also, we have not
                         * journaled diffs for this change.
                         * Therefore, the on-disk journal is missing
-                        * the deltas for this change.  Since it can
+                        * the deltas for this change.  Since it can
                         * no longer be used to bring the zone
                         * up-to-date, it is useless and should be
                         * removed.
@@ -11190,7 +12486,7 @@ dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
        case dns_dialuptype_no:
                break;
        case dns_dialuptype_yes:
-               DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
+               DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
                                 DNS_ZONEFLG_DIALREFRESH |
                                 DNS_ZONEFLG_NOREFRESH));
                break;
index 0329abde72b29bc4674b8eaa5a03c22ebdd061fe..905697cc9fd46f0a018846cf295eb54906d1903c 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: random.c,v 1.25 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id: random.c,v 1.26 2009/06/30 02:52:32 each Exp $ */
 
 /*! \file */
 
@@ -92,7 +92,7 @@ isc_random_get(isc_uint32_t *val)
 
 isc_uint32_t
 isc_random_jitter(isc_uint32_t max, isc_uint32_t jitter) {
-       REQUIRE(jitter < max);
+       REQUIRE(jitter < max || (jitter == 0 && max == 0));
        if (jitter == 0)
                return (max);
        else
index 48f7913e3686f93082056ecb3afdf02d3dcc46cb..f359b6398ef7dd88b63ef3978190eda96127a48d 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: namedconf.c,v 1.98 2009/06/10 23:47:47 tbox Exp $ */
+/* $Id: namedconf.c,v 1.99 2009/06/30 02:52:33 each Exp $ */
 
 /*! \file */
 
@@ -361,9 +361,9 @@ static cfg_type_t cfg_type_category = {
 
 
 /*%
- * A trusted key, as used in the "trusted-keys" statement.
+ * A dnssec key, as used in the "trusted-keys" or "managed-keys" statement.
  */
-static cfg_tuplefielddef_t trustedkey_fields[] = {
+static cfg_tuplefielddef_t dnsseckey_fields[] = {
        { "name", &cfg_type_astring, 0 },
        { "flags", &cfg_type_uint32, 0 },
        { "protocol", &cfg_type_uint32, 0 },
@@ -371,9 +371,9 @@ static cfg_tuplefielddef_t trustedkey_fields[] = {
        { "key", &cfg_type_qstring, 0 },
        { NULL, NULL, 0 }
 };
-static cfg_type_t cfg_type_trustedkey = {
-       "trustedkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
-       trustedkey_fields
+static cfg_type_t cfg_type_dnsseckey = {
+       "dnsseckey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+       &cfg_rep_tuple, dnsseckey_fields
 };
 
 static keyword_type_t wild_class_kw = { "class", &cfg_type_ustring };
@@ -459,13 +459,14 @@ static cfg_type_t cfg_type_optional_port = {
 
 /*% A list of keys, as in the "key" clause of the controls statement. */
 static cfg_type_t cfg_type_keylist = {
-       "keylist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list,
-       &cfg_type_astring
+       "keylist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
+       cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring
 };
 
-static cfg_type_t cfg_type_trustedkeys = {
-       "trusted-keys", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list,
-       &cfg_type_trustedkey
+/*% A list of dnssec keys, as in "trusted-keys" and "managed-keys" stanzas */
+static cfg_type_t cfg_type_dnsseckeys = {
+       "dnsseckeys", cfg_parse_bracketed_list, cfg_print_bracketed_list,
+       cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_dnsseckey
 };
 
 static const char *forwardtype_enums[] = { "first", "only", NULL };
@@ -690,7 +691,8 @@ namedconf_or_view_clauses[] = {
        /* only 1 DLZ per view allowed */
        { "dlz", &cfg_type_dynamically_loadable_zones, 0 },
        { "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI },
-       { "trusted-keys", &cfg_type_trustedkeys, CFG_CLAUSEFLAG_MULTI },
+       { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
+       { "managed-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
        { NULL, NULL, 0 }
 };
 
@@ -699,7 +701,8 @@ namedconf_or_view_clauses[] = {
  */
 static cfg_clausedef_t
 bindkeys_clauses[] = {
-       { "trusted-keys", &cfg_type_trustedkeys, CFG_CLAUSEFLAG_MULTI },
+       { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
+       { "managed-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
        { NULL, NULL, 0 }
 };
 
@@ -1086,7 +1089,7 @@ LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_namedconf = {
        &cfg_rep_map, namedconf_clausesets
 };
 
-/*% The bind.keys syntax (trusted-keys only). */
+/*% The bind.keys syntax (trusted-keys/managed-keys only). */
 static cfg_clausedef_t *
 bindkeys_clausesets[] = {
        bindkeys_clauses,
index 03b7e0c5d1c4a0bc83024d3531fdfa49c45533d5..bd6a3d92126ecc628b666d17e5637b730934e821 100644 (file)
@@ -114,6 +114,27 @@ Package=<4>
 
 ###############################################################################
 
+Project: "revoke"="..\bin\dnssec\win32\revoke.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name libdns
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libisc
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name dnssectool
+    End Project Dependency
+}}}
+
+###############################################################################
+
 Project: "keygen"="..\bin\dnssec\win32\keygen.dsp" - Package Owner=<4>
 
 Package=<5>