+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]
--- /dev/null
+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.
# 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@
# 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}
${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::
* 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 */
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");
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;
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);
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;
* 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 */
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>: "
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;
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);
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;
--- /dev/null
+.\" Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $Id: dnssec-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
--- /dev/null
+/*
+ * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dnssec-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);
+}
--- /dev/null
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "—">]>
+<!--
+ - Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<!-- $Id: dnssec-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:
+-->
--- /dev/null
+<!--
+ - Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+<!-- $Id: dnssec-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> — 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>
--- /dev/null
+# 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
--- /dev/null
+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>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+# 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
* 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 */
type master;\n\
database \"_builtin authors\";\n\
};\n\
+\n\
zone \"id.server\" chaos {\n\
type master;\n\
database \"_builtin id\";\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\
* 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
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 */
* 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 */
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);
}
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;
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"));
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,
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;
}
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;
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;
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
* 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);
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.
*/
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;
cfg_aclconfctx_init(&aclconfctx);
ISC_LIST_INIT(viewlist);
+ ISC_LIST_INIT(builtin_viewlist);
ISC_LIST_INIT(cachelist);
/* Ensure exclusive access to configuration data. */
/*
* 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",
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,
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");
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 = "";
* 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>
#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) {
}
}
-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) */
typedef struct axfr_rrstream {
rrstream_t common;
- db_rr_iterator_t it;
+ dns_rriterator_t it;
isc_boolean_t it_valid;
} axfr_rrstream_t;
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;
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. */
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;
}
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;
}
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));
}
# 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@
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@
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 \
* 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>
/***
if (db->methods->resigned != NULL)
(db->methods->resigned)(db, rdataset, version);
}
+
/*
* 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 */
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);
* 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
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 {
* 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
*
* 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:
* 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
#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)
--- /dev/null
+/*
+ * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: 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 */
* 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);
/*%<
*/
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:
* 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,
* 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 */
* 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
#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 */
#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 )
* 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
#define DNS_MASTER_CHECKMXFAIL 0x00001000
#define DNS_MASTER_RESIGN 0x00002000
+#define DNS_MASTER_KEY 0x00004000 /*%< Loading a key zone master file. */
ISC_LANG_BEGINDECLS
* 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
*\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);
/*%<
--- /dev/null
+/*
+ * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: 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 */
* 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
* 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
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;
* 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
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;
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')
* 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
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 */
* 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
* "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 */
--- /dev/null
+/*
+ * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: 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);
+}
* 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
return (result);
}
-
void
dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) {
*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,
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;
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)
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;
keytable->active_nodes++;
UNLOCK(&keytable->lock);
result = ISC_R_SUCCESS;
- *nextnodep = knode;
+ dns_keynode_attach(knode, nextnodep);
} else
result = ISC_R_NOTFOUND;
keytable->active_nodes--;
UNLOCK(&keytable->lock);
- *keynodep = NULL;
+ dns_keynode_detach(keytable->mctx, keynodep);
}
isc_result_t
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;
+}
* 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 */
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];
}
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];
--- /dev/null
+/*
+ * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: 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 */
--- /dev/null
+/*
+ * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#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 */
--- /dev/null
+/*
+ * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: 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;
+}
* 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
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);
* 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>
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)
}
/*%
- * 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
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(
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);
}
* 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 */
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) {
"dns_fwdtable_create() failed: %s",
isc_result_totext(result));
result = ISC_R_UNEXPECTED;
- goto cleanup_trustedkeys;
+ goto cleanup_zt;
}
view->acache = NULL;
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);
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);
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;
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
dns_name_free
dns_name_fromregion
dns_name_fromtext
+dns_name_fromstring
dns_name_fromwire
dns_name_fullcompare
dns_name_getlabel
dns_name_split
dns_name_tofilenametext
dns_name_toregion
+dns_name_tostring
dns_name_totext
dns_name_towire
dns_ncache_add
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
dst_key_proto
dst_key_secretsize
dst_key_setbits
+dst_key_setflags
dst_key_sigsize
dst_key_size
dst_key_tobuffer
# 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
# 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
# End Source File
# Begin Source File
+SOURCE=..\keydata.c
+# End Source File
+# Begin Source File
+
SOURCE=..\keytable.c
# End Source File
# Begin Source File
# End Source File
# Begin Source File
+SOURCE=..\rriterator.c
+# End Source File
+# Begin Source File
+
SOURCE=..\sdb.c
# End Source File
# Begin Source File
-@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"
-@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"
"$(INTDIR)\forward.obj" \
"$(INTDIR)\iptable.obj" \
"$(INTDIR)\journal.obj" \
+ "$(INTDIR)\keydata.obj" \
"$(INTDIR)\keytable.obj" \
"$(INTDIR)\lib.obj" \
"$(INTDIR)\log.obj" \
"$(INTDIR)\resolver.obj" \
"$(INTDIR)\result.obj" \
"$(INTDIR)\rootns.obj" \
+ "$(INTDIR)\rriterator.obj" \
"$(INTDIR)\sdb.obj" \
"$(INTDIR)\sdlz.obj" \
"$(INTDIR)\soa.obj" \
-@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"
-@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"
"$(INTDIR)\forward.sbr" \
"$(INTDIR)\iptable.sbr" \
"$(INTDIR)\journal.sbr" \
+ "$(INTDIR)\keydata.sbr" \
"$(INTDIR)\keytable.sbr" \
"$(INTDIR)\lib.sbr" \
"$(INTDIR)\log.sbr" \
"$(INTDIR)\resolver.sbr" \
"$(INTDIR)\result.sbr" \
"$(INTDIR)\rootns.sbr" \
+ "$(INTDIR)\rriterator.sbr" \
"$(INTDIR)\sdb.sbr" \
"$(INTDIR)\sdlz.sbr" \
"$(INTDIR)\soa.sbr" \
"$(INTDIR)\forward.obj" \
"$(INTDIR)\iptable.obj" \
"$(INTDIR)\journal.obj" \
+ "$(INTDIR)\key.obj" \
"$(INTDIR)\keytable.obj" \
"$(INTDIR)\lib.obj" \
"$(INTDIR)\log.obj" \
"$(INTDIR)\resolver.obj" \
"$(INTDIR)\result.obj" \
"$(INTDIR)\rootns.obj" \
+ "$(INTDIR)\rriterator.obj" \
"$(INTDIR)\sdb.obj" \
"$(INTDIR)\sdlz.obj" \
"$(INTDIR)\soa.obj" \
$(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
$(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
* 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 */
#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>
#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>
#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>
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
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;
/*%
* 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;
* 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
#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)
* 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;
};
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;
};
/*%<
* 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
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);
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;
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))));
*/
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) &&
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))
/*
* 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
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);
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)
"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),
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");
}
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);
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);
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)
*/
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.
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;
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;
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;
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:
*/
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;
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);
*/
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;
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.
*/
&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;
}
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
/*
* 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.
*/
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 &&
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:
/*
* 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);
isc_time_t next;
isc_result_t result;
+ ENTER;
REQUIRE(DNS_ZONE_VALID(zone));
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
return;
}
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;
}
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);
"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;
}
* 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.
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;
* 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 */
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
* 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 */
/*%
- * 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 },
{ "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 };
/*% 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 };
/* 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 }
};
*/
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 }
};
&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,
###############################################################################
+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>