diff options
author | Doug Barton <dougb@FreeBSD.org> | 2011-07-16 11:12:09 +0000 |
---|---|---|
committer | Doug Barton <dougb@FreeBSD.org> | 2011-07-16 11:12:09 +0000 |
commit | 7afecc12f4d7b56f03438d5f41b837b9696f0a94 (patch) | |
tree | 7873e6a2dac5f9ddbfefa3b07f3cf0570f682321 /contrib/bind9/bin | |
parent | a9285ae5c428d2017b1b907b8403ebe30f369bec (diff) | |
parent | 473038528ab5bd55332138ebf791ab91a25f747b (diff) |
Upgrade to version 9.8.0-P4
This version has many new features, see /usr/share/doc/bind9/README
for details.
Notes
Notes:
svn path=/head/; revision=224092
Diffstat (limited to 'contrib/bind9/bin')
151 files changed, 16243 insertions, 3043 deletions
diff --git a/contrib/bind9/bin/Makefile.in b/contrib/bind9/bin/Makefile.in index 1694268fb79e..d263d795eb02 100644 --- a/contrib/bind9/bin/Makefile.in +++ b/contrib/bind9/bin/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2001 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,13 +13,14 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.25 2007-06-19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.29 2009-10-05 12:07:08 fdupont Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -SUBDIRS = named rndc dig dnssec tests nsupdate check +SUBDIRS = named rndc dig dnssec tests tools nsupdate \ + check confgen @PKCS11_TOOLS@ TARGETS = @BIND9_MAKE_RULES@ diff --git a/contrib/bind9/bin/check/Makefile.in b/contrib/bind9/bin/check/Makefile.in index 46271c77de7f..d5827dcce11e 100644 --- a/contrib/bind9/bin/check/Makefile.in +++ b/contrib/bind9/bin/check/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2000-2003 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.32 2007-06-19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.36 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -32,6 +32,7 @@ CWARNINGS = DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ @@ -39,7 +40,8 @@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ -LIBS = @LIBS@ +LIBS = ${ISCLIBS} @LIBS@ +NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@ SUBDIRS = @@ -69,14 +71,14 @@ named-checkzone.@O@: named-checkzone.c named-checkconf@EXEEXT@: named-checkconf.@O@ check-tool.@O@ ${ISCDEPLIBS} \ ${ISCCFGDEPLIBS} ${BIND9DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - named-checkconf.@O@ check-tool.@O@ ${BIND9LIBS} ${ISCCFGLIBS} \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} + export BASEOBJS="named-checkconf.@O@ check-tool.@O@"; \ + export LIBS0="${BIND9LIBS} ${ISCCFGLIBS} ${DNSLIBS}"; \ + ${FINALBUILDCMD} named-checkzone@EXEEXT@: named-checkzone.@O@ check-tool.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - named-checkzone.@O@ check-tool.@O@ ${ISCCFGLIBS} ${DNSLIBS} \ - ${ISCLIBS} ${LIBS} + export BASEOBJS="named-checkzone.@O@ check-tool.@O@"; \ + export LIBS0="${ISCCFGLIBS} ${DNSLIBS}"; \ + ${FINALBUILDCMD} doc man:: ${MANOBJS} diff --git a/contrib/bind9/bin/check/check-tool.c b/contrib/bind9/bin/check/check-tool.c index ed9224bb9aa2..4d2ca5c45ab5 100644 --- a/contrib/bind9/bin/check/check-tool.c +++ b/contrib/bind9/bin/check/check-tool.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check-tool.c,v 1.35.36.5 2010-09-07 23:46:05 tbox Exp $ */ +/* $Id: check-tool.c,v 1.41 2010-09-07 23:46:59 tbox Exp $ */ /*! \file */ @@ -601,8 +601,7 @@ load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, isc_buffer_add(&buffer, strlen(zonename)); dns_fixedname_init(&fixorigin); origin = dns_fixedname_name(&fixorigin); - CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL)); CHECK(dns_zone_setorigin(zone, origin)); CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype)); CHECK(dns_zone_setfile2(zone, filename, fileformat)); diff --git a/contrib/bind9/bin/check/check-tool.h b/contrib/bind9/bin/check/check-tool.h index f9273ff152e8..4371ae29ec20 100644 --- a/contrib/bind9/bin/check/check-tool.h +++ b/contrib/bind9/bin/check/check-tool.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check-tool.h,v 1.14.334.2 2010-09-07 23:46:05 tbox Exp $ */ +/* $Id: check-tool.h,v 1.16 2010-09-07 23:46:59 tbox Exp $ */ #ifndef CHECK_TOOL_H #define CHECK_TOOL_H diff --git a/contrib/bind9/bin/check/named-checkconf.8 b/contrib/bind9/bin/check/named-checkconf.8 index 71310073e8d0..fabcfa916eb7 100644 --- a/contrib/bind9/bin/check/named-checkconf.8 +++ b/contrib/bind9/bin/check/named-checkconf.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000-2002 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: named-checkconf.8,v 1.30.334.1 2009-07-11 01:55:20 tbox Exp $ +.\" $Id: named-checkconf.8,v 1.33 2009-12-29 01:14:03 tbox Exp $ .\" .hy 0 .ad l @@ -33,11 +33,29 @@ named\-checkconf \- named configuration file syntax checking tool .SH "SYNOPSIS" .HP 16 -\fBnamed\-checkconf\fR [\fB\-h\fR] [\fB\-v\fR] [\fB\-j\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] {filename} [\fB\-z\fR] +\fBnamed\-checkconf\fR [\fB\-h\fR] [\fB\-v\fR] [\fB\-j\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] {filename} [\fB\-p\fR] [\fB\-z\fR] .SH "DESCRIPTION" .PP \fBnamed\-checkconf\fR -checks the syntax, but not the semantics, of a named configuration file. +checks the syntax, but not the semantics, of a +\fBnamed\fR +configuration file. The file is parsed and checked for syntax errors, along with all files included by it. If no file is specified, +\fI/etc/named.conf\fR +is read by default. +.PP +Note: files that +\fBnamed\fR +reads in separate parser contexts, such as +\fIrndc.key\fR +and +\fIbind.keys\fR, are not automatically read by +\fBnamed\-checkconf\fR. Configuration errors in these files may cause +\fBnamed\fR +to fail to run, even if +\fBnamed\-checkconf\fR +was successful. +\fBnamed\-checkconf\fR +can be run on these files explicitly, however. .SH "OPTIONS" .PP \-h @@ -59,6 +77,13 @@ Print the version of the program and exit. .RE .PP +\-p +.RS 4 +Print out the +\fInamed.conf\fR +and included files in canonical form if no errors were detected. +.RE +.PP \-z .RS 4 Perform a test load of all master zones found in @@ -88,7 +113,7 @@ BIND 9 Administrator Reference Manual. .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2000\-2002 Internet Software Consortium. .br diff --git a/contrib/bind9/bin/check/named-checkconf.c b/contrib/bind9/bin/check/named-checkconf.c index 20983b5b9392..521ed31916c5 100644 --- a/contrib/bind9/bin/check/named-checkconf.c +++ b/contrib/bind9/bin/check/named-checkconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named-checkconf.c,v 1.46.222.4 2010-09-07 23:46:05 tbox Exp $ */ +/* $Id: named-checkconf.c,v 1.54 2010-09-07 01:49:08 marka Exp $ */ /*! \file */ @@ -59,9 +59,12 @@ isc_log_t *logc = NULL; } while (0) /*% usage */ +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + static void usage(void) { - fprintf(stderr, "usage: %s [-h] [-j] [-v] [-z] [-t directory] " + fprintf(stderr, "usage: %s [-h] [-j] [-p] [-v] [-z] [-t directory] " "[named.conf]\n", program); exit(1); } @@ -203,6 +206,24 @@ configure_zone(const char *vclass, const char *view, zfile = cfg_obj_asstring(fileobj); obj = NULL; + if (get_maps(maps, "check-dup-records", &obj)) { + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + zone_options |= DNS_ZONEOPT_CHECKDUPRR; + zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + zone_options |= DNS_ZONEOPT_CHECKDUPRR; + zone_options |= DNS_ZONEOPT_CHECKDUPRRFAIL; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + zone_options &= ~DNS_ZONEOPT_CHECKDUPRR; + zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; + } else + INSIST(0); + } else { + zone_options |= DNS_ZONEOPT_CHECKDUPRR; + zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; + } + + obj = NULL; if (get_maps(maps, "check-mx", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKMX; @@ -387,6 +408,15 @@ load_zones_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx) { return (result); } +static void +output(void *closure, const char *text, int textlen) { + UNUSED(closure); + if (fwrite(text, 1, textlen, stdout) != (size_t)textlen) { + perror("fwrite"); + exit(1); + } +} + /*% The main processing routine */ int main(int argc, char **argv) { @@ -399,10 +429,11 @@ main(int argc, char **argv) { int exit_status = 0; isc_entropy_t *ectx = NULL; isc_boolean_t load_zones = ISC_FALSE; + isc_boolean_t print = ISC_FALSE; isc_commandline_errprint = ISC_FALSE; - while ((c = isc_commandline_parse(argc, argv, "dhjt:vz")) != EOF) { + while ((c = isc_commandline_parse(argc, argv, "dhjt:pvz")) != EOF) { switch (c) { case 'd': debug++; @@ -421,6 +452,10 @@ main(int argc, char **argv) { } break; + case 'p': + print = ISC_TRUE; + break; + case 'v': printf(VERSION "\n"); exit(0); @@ -485,6 +520,8 @@ main(int argc, char **argv) { exit_status = 1; } + if (print && exit_status == 0) + cfg_print(config, output, NULL); cfg_obj_destroy(parser, &config); cfg_parser_destroy(&parser); diff --git a/contrib/bind9/bin/check/named-checkconf.docbook b/contrib/bind9/bin/check/named-checkconf.docbook index e0c43d17118b..fe12cb3ea278 100644 --- a/contrib/bind9/bin/check/named-checkconf.docbook +++ b/contrib/bind9/bin/check/named-checkconf.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [<!ENTITY mdash "—">]> <!-- - - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") - Copyright (C) 2000-2002 Internet Software Consortium. - - Permission to use, copy, modify, and/or distribute this software for any @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: named-checkconf.docbook,v 1.19 2007-06-19 06:58:03 marka Exp $ --> +<!-- $Id: named-checkconf.docbook,v 1.22 2009-12-28 23:21:16 each Exp $ --> <refentry id="man.named-checkconf"> <refentryinfo> <date>June 14, 2000</date> @@ -35,6 +35,7 @@ <year>2004</year> <year>2005</year> <year>2007</year> + <year>2009</year> <holder>Internet Systems Consortium, Inc. ("ISC")</holder> </copyright> <copyright> @@ -58,6 +59,7 @@ <arg><option>-j</option></arg> <arg><option>-t <replaceable class="parameter">directory</replaceable></option></arg> <arg choice="req">filename</arg> + <arg><option>-p</option></arg> <arg><option>-z</option></arg> </cmdsynopsis> </refsynopsisdiv> @@ -65,8 +67,21 @@ <refsect1> <title>DESCRIPTION</title> <para><command>named-checkconf</command> - checks the syntax, but not the semantics, of a named - configuration file. + checks the syntax, but not the semantics, of a + <command>named</command> configuration file. The file is parsed + and checked for syntax errors, along with all files included by it. + If no file is specified, <filename>/etc/named.conf</filename> is read + by default. + </para> + <para> + Note: files that <command>named</command> reads in separate + parser contexts, such as <filename>rndc.key</filename> and + <filename>bind.keys</filename>, are not automatically read + by <command>named-checkconf</command>. Configuration + errors in these files may cause <command>named</command> to + fail to run, even if <command>named-checkconf</command> was + successful. <command>named-checkconf</command> can be run + on these files explicitly, however. </para> </refsect1> @@ -87,8 +102,7 @@ <term>-t <replaceable class="parameter">directory</replaceable></term> <listitem> <para> - Chroot to <filename>directory</filename> so that - include + Chroot to <filename>directory</filename> so that include directives in the configuration file are processed as if run by a similarly chrooted named. </para> @@ -106,6 +120,16 @@ </varlistentry> <varlistentry> + <term>-p</term> + <listitem> + <para> + Print out the <filename>named.conf</filename> and included files + in canonical form if no errors were detected. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-z</term> <listitem> <para> diff --git a/contrib/bind9/bin/check/named-checkconf.html b/contrib/bind9/bin/check/named-checkconf.html index 458b486e90fd..f5e4cd385114 100644 --- a/contrib/bind9/bin/check/named-checkconf.html +++ b/contrib/bind9/bin/check/named-checkconf.html @@ -1,5 +1,5 @@ <!-- - - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") - Copyright (C) 2000-2002 Internet Software Consortium. - - Permission to use, copy, modify, and/or distribute this software for any @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: named-checkconf.html,v 1.30.334.1 2009-07-11 01:55:20 tbox Exp $ --> +<!-- $Id: named-checkconf.html,v 1.33 2009-12-29 01:14:03 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> @@ -29,17 +29,30 @@ </div> <div class="refsynopsisdiv"> <h2>Synopsis</h2> -<div class="cmdsynopsis"><p><code class="command">named-checkconf</code> [<code class="option">-h</code>] [<code class="option">-v</code>] [<code class="option">-j</code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] {filename} [<code class="option">-z</code>]</p></div> +<div class="cmdsynopsis"><p><code class="command">named-checkconf</code> [<code class="option">-h</code>] [<code class="option">-v</code>] [<code class="option">-j</code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] {filename} [<code class="option">-p</code>] [<code class="option">-z</code>]</p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543387"></a><h2>DESCRIPTION</h2> +<a name="id2543395"></a><h2>DESCRIPTION</h2> <p><span><strong class="command">named-checkconf</strong></span> - checks the syntax, but not the semantics, of a named - configuration file. + checks the syntax, but not the semantics, of a + <span><strong class="command">named</strong></span> configuration file. The file is parsed + and checked for syntax errors, along with all files included by it. + If no file is specified, <code class="filename">/etc/named.conf</code> is read + by default. + </p> +<p> + Note: files that <span><strong class="command">named</strong></span> reads in separate + parser contexts, such as <code class="filename">rndc.key</code> and + <code class="filename">bind.keys</code>, are not automatically read + by <span><strong class="command">named-checkconf</strong></span>. Configuration + errors in these files may cause <span><strong class="command">named</strong></span> to + fail to run, even if <span><strong class="command">named-checkconf</strong></span> was + successful. <span><strong class="command">named-checkconf</strong></span> can be run + on these files explicitly, however. </p> </div> <div class="refsect1" lang="en"> -<a name="id2543399"></a><h2>OPTIONS</h2> +<a name="id2543444"></a><h2>OPTIONS</h2> <div class="variablelist"><dl> <dt><span class="term">-h</span></dt> <dd><p> @@ -47,8 +60,7 @@ </p></dd> <dt><span class="term">-t <em class="replaceable"><code>directory</code></em></span></dt> <dd><p> - Chroot to <code class="filename">directory</code> so that - include + Chroot to <code class="filename">directory</code> so that include directives in the configuration file are processed as if run by a similarly chrooted named. </p></dd> @@ -57,6 +69,11 @@ Print the version of the <span><strong class="command">named-checkconf</strong></span> program and exit. </p></dd> +<dt><span class="term">-p</span></dt> +<dd><p> + Print out the <code class="filename">named.conf</code> and included files + in canonical form if no errors were detected. + </p></dd> <dt><span class="term">-z</span></dt> <dd><p> Perform a test load of all master zones found in @@ -74,21 +91,21 @@ </dl></div> </div> <div class="refsect1" lang="en"> -<a name="id2543507"></a><h2>RETURN VALUES</h2> +<a name="id2543568"></a><h2>RETURN VALUES</h2> <p><span><strong class="command">named-checkconf</strong></span> returns an exit status of 1 if errors were detected and 0 otherwise. </p> </div> <div class="refsect1" lang="en"> -<a name="id2543518"></a><h2>SEE ALSO</h2> +<a name="id2543579"></a><h2>SEE ALSO</h2> <p><span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>, <span class="citerefentry"><span class="refentrytitle">named-checkzone</span>(8)</span>, <em class="citetitle">BIND 9 Administrator Reference Manual</em>. </p> </div> <div class="refsect1" lang="en"> -<a name="id2543548"></a><h2>AUTHOR</h2> +<a name="id2543609"></a><h2>AUTHOR</h2> <p><span class="corpauthor">Internet Systems Consortium</span> </p> </div> diff --git a/contrib/bind9/bin/check/named-checkzone.8 b/contrib/bind9/bin/check/named-checkzone.8 index e5f07906a457..1bb784606d8d 100644 --- a/contrib/bind9/bin/check/named-checkzone.8 +++ b/contrib/bind9/bin/check/named-checkzone.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000-2002 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: named-checkzone.8,v 1.42.334.3 2009-11-11 01:56:22 tbox Exp $ +.\" $Id: named-checkzone.8,v 1.47 2010-01-17 01:14:02 tbox Exp $ .\" .hy 0 .ad l @@ -33,9 +33,9 @@ named\-checkzone, named\-compilezone \- zone file validity checking or converting tool .SH "SYNOPSIS" .HP 16 -\fBnamed\-checkzone\fR [\fB\-d\fR] [\fB\-h\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-M\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-S\ \fR\fB\fImode\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {zonename} {filename} +\fBnamed\-checkzone\fR [\fB\-d\fR] [\fB\-h\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-M\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-o\ \fR\fB\fIfilename\fR\fR] [\fB\-r\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-S\ \fR\fB\fImode\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {zonename} {filename} .HP 18 -\fBnamed\-compilezone\fR [\fB\-d\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-C\ \fR\fB\fImode\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-o\ \fR\fB\fIfilename\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {\fB\-o\ \fR\fB\fIfilename\fR\fR} {zonename} {filename} +\fBnamed\-compilezone\fR [\fB\-d\fR] [\fB\-j\fR] [\fB\-q\fR] [\fB\-v\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-C\ \fR\fB\fImode\fR\fR] [\fB\-f\ \fR\fB\fIformat\fR\fR] [\fB\-F\ \fR\fB\fIformat\fR\fR] [\fB\-i\ \fR\fB\fImode\fR\fR] [\fB\-k\ \fR\fB\fImode\fR\fR] [\fB\-m\ \fR\fB\fImode\fR\fR] [\fB\-n\ \fR\fB\fImode\fR\fR] [\fB\-r\ \fR\fB\fImode\fR\fR] [\fB\-s\ \fR\fB\fIstyle\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-w\ \fR\fB\fIdirectory\fR\fR] [\fB\-D\fR] [\fB\-W\ \fR\fB\fImode\fR\fR] {\fB\-o\ \fR\fB\fIfilename\fR\fR} {zonename} {filename} .SH "DESCRIPTION" .PP \fBnamed\-checkzone\fR @@ -201,6 +201,15 @@ then write to standard out. This is mandatory for \fBnamed\-compilezone\fR. .RE .PP +\-r \fImode\fR +.RS 4 +Check for records that are treated as different by DNSSEC but are semantically equal in plain DNS. Possible modes are +\fB"fail"\fR, +\fB"warn"\fR +(default) and +\fB"ignore"\fR. +.RE +.PP \-s \fIstyle\fR .RS 4 Specify the style of the dumped zone file. Possible styles are @@ -272,7 +281,7 @@ BIND 9 Administrator Reference Manual. .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2004\-2007, 2009 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004\-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2000\-2002 Internet Software Consortium. .br diff --git a/contrib/bind9/bin/check/named-checkzone.c b/contrib/bind9/bin/check/named-checkzone.c index 3b86e576df5a..100e809867d1 100644 --- a/contrib/bind9/bin/check/named-checkzone.c +++ b/contrib/bind9/bin/check/named-checkzone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named-checkzone.c,v 1.51.34.6 2010-09-07 23:46:06 tbox Exp $ */ +/* $Id: named-checkzone.c,v 1.61 2010-09-07 23:46:59 tbox Exp $ */ /*! \file */ @@ -70,6 +70,9 @@ static enum { progmode_check, progmode_compile } progmode; } \ } while (0) +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + static void usage(void) { fprintf(stderr, @@ -77,12 +80,13 @@ usage(void) { "[-f inputformat] [-F outputformat] " "[-t directory] [-w directory] [-k (ignore|warn|fail)] " "[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] " + "[-r (ignore|warn|fail)] " "[-i (full|full-sibling|local|local-sibling|none)] " "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] " "[-W (ignore|warn)] " "%s zonename filename\n", prog_name, - progmode == progmode_check ? "[-o filename]" : "{-o filename}"); + progmode == progmode_check ? "[-o filename]" : "-o filename"); exit(1); } @@ -140,17 +144,19 @@ main(int argc, char **argv) { if (progmode == progmode_compile) { zone_options |= (DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_FATALNS | + DNS_ZONEOPT_CHECKDUPRR | DNS_ZONEOPT_CHECKNAMES | DNS_ZONEOPT_CHECKNAMESFAIL | DNS_ZONEOPT_CHECKWILDCARD); - } + } else + zone_options |= DNS_ZONEOPT_CHECKDUPRR; #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0) isc_commandline_errprint = ISC_FALSE; while ((c = isc_commandline_parse(argc, argv, - "c:df:hi:jk:m:n:qs:t:o:vw:DF:M:S:W:")) + "c:df:hi:jk:m:n:qr:s:t:o:vw:DF:M:S:W:")) != EOF) { switch (c) { case 'c': @@ -262,16 +268,27 @@ main(int argc, char **argv) { } break; + case 'o': + output_filename = isc_commandline_argument; + break; + case 'q': quiet++; break; - case 't': - result = isc_dir_chroot(isc_commandline_argument); - if (result != ISC_R_SUCCESS) { - fprintf(stderr, "isc_dir_chroot: %s: %s\n", - isc_commandline_argument, - isc_result_totext(result)); + case 'r': + if (ARGCMP("warn")) { + zone_options |= DNS_ZONEOPT_CHECKDUPRR; + zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; + } else if (ARGCMP("fail")) { + zone_options |= DNS_ZONEOPT_CHECKDUPRR | + DNS_ZONEOPT_CHECKDUPRRFAIL; + } else if (ARGCMP("ignore")) { + zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR | + DNS_ZONEOPT_CHECKDUPRRFAIL); + } else { + fprintf(stderr, "invalid argument to -r: %s\n", + isc_commandline_argument); exit(1); } break; @@ -289,8 +306,14 @@ main(int argc, char **argv) { } break; - case 'o': - output_filename = isc_commandline_argument; + case 't': + result = isc_dir_chroot(isc_commandline_argument); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "isc_dir_chroot: %s: %s\n", + isc_commandline_argument, + isc_result_totext(result)); + exit(1); + } break; case 'v': diff --git a/contrib/bind9/bin/check/named-checkzone.docbook b/contrib/bind9/bin/check/named-checkzone.docbook index 0e04c033f38b..415ee1c34499 100644 --- a/contrib/bind9/bin/check/named-checkzone.docbook +++ b/contrib/bind9/bin/check/named-checkzone.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [<!ENTITY mdash "—">]> <!-- - - Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") - Copyright (C) 2000-2002 Internet Software Consortium. - - Permission to use, copy, modify, and/or distribute this software for any @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: named-checkzone.docbook,v 1.34.334.3 2009-11-10 20:01:41 each Exp $ --> +<!-- $Id: named-checkzone.docbook,v 1.40 2010-01-16 23:48:15 tbox Exp $ --> <refentry id="man.named-checkzone"> <refentryinfo> <date>June 13, 2000</date> @@ -37,6 +37,7 @@ <year>2006</year> <year>2007</year> <year>2009</year> + <year>2010</year> <holder>Internet Systems Consortium, Inc. ("ISC")</holder> </copyright> <copyright> @@ -69,6 +70,8 @@ <arg><option>-m <replaceable class="parameter">mode</replaceable></option></arg> <arg><option>-M <replaceable class="parameter">mode</replaceable></option></arg> <arg><option>-n <replaceable class="parameter">mode</replaceable></option></arg> + <arg><option>-o <replaceable class="parameter">filename</replaceable></option></arg> + <arg><option>-r <replaceable class="parameter">mode</replaceable></option></arg> <arg><option>-s <replaceable class="parameter">style</replaceable></option></arg> <arg><option>-S <replaceable class="parameter">mode</replaceable></option></arg> <arg><option>-t <replaceable class="parameter">directory</replaceable></option></arg> @@ -92,7 +95,7 @@ <arg><option>-k <replaceable class="parameter">mode</replaceable></option></arg> <arg><option>-m <replaceable class="parameter">mode</replaceable></option></arg> <arg><option>-n <replaceable class="parameter">mode</replaceable></option></arg> - <arg><option>-o <replaceable class="parameter">filename</replaceable></option></arg> + <arg><option>-r <replaceable class="parameter">mode</replaceable></option></arg> <arg><option>-s <replaceable class="parameter">style</replaceable></option></arg> <arg><option>-t <replaceable class="parameter">directory</replaceable></option></arg> <arg><option>-w <replaceable class="parameter">directory</replaceable></option></arg> @@ -320,6 +323,19 @@ </varlistentry> <varlistentry> + <term>-r <replaceable class="parameter">mode</replaceable></term> + <listitem> + <para> + Check for records that are treated as different by DNSSEC but + are semantically equal in plain DNS. + Possible modes are <command>"fail"</command>, + <command>"warn"</command> (default) and + <command>"ignore"</command>. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-s <replaceable class="parameter">style</replaceable></term> <listitem> <para> diff --git a/contrib/bind9/bin/check/named-checkzone.html b/contrib/bind9/bin/check/named-checkzone.html index 24f5c0586dde..e0532af0f590 100644 --- a/contrib/bind9/bin/check/named-checkzone.html +++ b/contrib/bind9/bin/check/named-checkzone.html @@ -1,5 +1,5 @@ <!-- - - Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") - Copyright (C) 2000-2002 Internet Software Consortium. - - Permission to use, copy, modify, and/or distribute this software for any @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: named-checkzone.html,v 1.42.334.3 2009-11-11 01:56:22 tbox Exp $ --> +<!-- $Id: named-checkzone.html,v 1.47 2010-01-17 01:14:02 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> @@ -29,11 +29,11 @@ </div> <div class="refsynopsisdiv"> <h2>Synopsis</h2> -<div class="cmdsynopsis"><p><code class="command">named-checkzone</code> [<code class="option">-d</code>] [<code class="option">-h</code>] [<code class="option">-j</code>] [<code class="option">-q</code>] [<code class="option">-v</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-f <em class="replaceable"><code>format</code></em></code>] [<code class="option">-F <em class="replaceable"><code>format</code></em></code>] [<code class="option">-i <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-k <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-m <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-M <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-n <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-s <em class="replaceable"><code>style</code></em></code>] [<code class="option">-S <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-w <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-D</code>] [<code class="option">-W <em class="replaceable"><code>mode</code></em></code>] {zonename} {filename}</p></div> -<div class="cmdsynopsis"><p><code class="command">named-compilezone</code> [<code class="option">-d</code>] [<code class="option">-j</code>] [<code class="option">-q</code>] [<code class="option">-v</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-C <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-f <em class="replaceable"><code>format</code></em></code>] [<code class="option">-F <em class="replaceable"><code>format</code></em></code>] [<code class="option">-i <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-k <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-m <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-n <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-o <em class="replaceable"><code>filename</code></em></code>] [<code class="option">-s <em class="replaceable"><code>style</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-w <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-D</code>] [<code class="option">-W <em class="replaceable"><code>mode</code></em></code>] {<code class="option">-o <em class="replaceable"><code>filename</code></em></code>} {zonename} {filename}</p></div> +<div class="cmdsynopsis"><p><code class="command">named-checkzone</code> [<code class="option">-d</code>] [<code class="option">-h</code>] [<code class="option">-j</code>] [<code class="option">-q</code>] [<code class="option">-v</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-f <em class="replaceable"><code>format</code></em></code>] [<code class="option">-F <em class="replaceable"><code>format</code></em></code>] [<code class="option">-i <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-k <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-m <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-M <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-n <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-o <em class="replaceable"><code>filename</code></em></code>] [<code class="option">-r <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-s <em class="replaceable"><code>style</code></em></code>] [<code class="option">-S <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-w <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-D</code>] [<code class="option">-W <em class="replaceable"><code>mode</code></em></code>] {zonename} {filename}</p></div> +<div class="cmdsynopsis"><p><code class="command">named-compilezone</code> [<code class="option">-d</code>] [<code class="option">-j</code>] [<code class="option">-q</code>] [<code class="option">-v</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-C <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-f <em class="replaceable"><code>format</code></em></code>] [<code class="option">-F <em class="replaceable"><code>format</code></em></code>] [<code class="option">-i <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-k <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-m <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-n <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-r <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-s <em class="replaceable"><code>style</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-w <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-D</code>] [<code class="option">-W <em class="replaceable"><code>mode</code></em></code>] {<code class="option">-o <em class="replaceable"><code>filename</code></em></code>} {zonename} {filename}</p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543674"></a><h2>DESCRIPTION</h2> +<a name="id2543694"></a><h2>DESCRIPTION</h2> <p><span><strong class="command">named-checkzone</strong></span> checks the syntax and integrity of a zone file. It performs the same checks as <span><strong class="command">named</strong></span> does when loading a @@ -53,7 +53,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543709"></a><h2>OPTIONS</h2> +<a name="id2543730"></a><h2>OPTIONS</h2> <div class="variablelist"><dl> <dt><span class="term">-d</span></dt> <dd><p> @@ -177,6 +177,14 @@ write to standard out. This is mandatory for <span><strong class="command">named-compilezone</strong></span>. </p></dd> +<dt><span class="term">-r <em class="replaceable"><code>mode</code></em></span></dt> +<dd><p> + Check for records that are treated as different by DNSSEC but + are semantically equal in plain DNS. + Possible modes are <span><strong class="command">"fail"</strong></span>, + <span><strong class="command">"warn"</strong></span> (default) and + <span><strong class="command">"ignore"</strong></span>. + </p></dd> <dt><span class="term">-s <em class="replaceable"><code>style</code></em></span></dt> <dd><p> Specify the style of the dumped zone file. @@ -239,14 +247,14 @@ </dl></div> </div> <div class="refsect1" lang="en"> -<a name="id2544330"></a><h2>RETURN VALUES</h2> +<a name="id2544377"></a><h2>RETURN VALUES</h2> <p><span><strong class="command">named-checkzone</strong></span> returns an exit status of 1 if errors were detected and 0 otherwise. </p> </div> <div class="refsect1" lang="en"> -<a name="id2544342"></a><h2>SEE ALSO</h2> +<a name="id2544389"></a><h2>SEE ALSO</h2> <p><span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>, <span class="citerefentry"><span class="refentrytitle">named-checkconf</span>(8)</span>, <em class="citetitle">RFC 1035</em>, @@ -254,7 +262,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2544375"></a><h2>AUTHOR</h2> +<a name="id2544422"></a><h2>AUTHOR</h2> <p><span class="corpauthor">Internet Systems Consortium</span> </p> </div> diff --git a/contrib/bind9/bin/confgen/Makefile.in b/contrib/bind9/bin/confgen/Makefile.in new file mode 100644 index 000000000000..da3587982cd3 --- /dev/null +++ b/contrib/bind9/bin/confgen/Makefile.in @@ -0,0 +1,101 @@ +# 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: Makefile.in,v 1.8 2009-12-05 23:31:40 each Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/include ${ISC_INCLUDES} ${ISCCC_INCLUDES} \ + ${ISCCFG_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} + +CDEFINES = +CWARNINGS = + +ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ +ISCCCLIBS = ../../lib/isccc/libisccc.@A@ +ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ +DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ +BIND9LIBS = ../../lib/bind9/libbind9.@A@ + +ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ +ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@ +ISCDEPLIBS = ../../lib/isc/libisc.@A@ +DNSDEPLIBS = ../../lib/dns/libdns.@A@ +BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ + +RNDCLIBS = ${ISCCFGLIBS} ${ISCCCLIBS} ${BIND9LIBS} ${DNSLIBS} ${ISCLIBS} @LIBS@ +RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS} + +LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ + +NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@ + +CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} + +SRCS= rndc-confgen.c ddns-confgen.c + +SUBDIRS = unix + +TARGETS = rndc-confgen@EXEEXT@ ddns-confgen@EXEEXT@ + +MANPAGES = rndc-confgen.8 ddns-confgen.8 + +HTMLPAGES = rndc-confgen.html ddns-confgen.html + +MANOBJS = ${MANPAGES} ${HTMLPAGES} + +UOBJS = unix/os.@O@ + +@BIND9_MAKE_RULES@ + +rndc-confgen.@O@: rndc-confgen.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \ + -c ${srcdir}/rndc-confgen.c + +ddns-confgen.@O@: ddns-confgen.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${srcdir}/ddns-confgen.c + +rndc-confgen@EXEEXT@: rndc-confgen.@O@ util.@O@ keygen.@O@ ${UOBJS} ${CONFDEPLIBS} + export BASEOBJS="rndc-confgen.@O@ util.@O@ keygen.@O@ ${UOBJS}"; \ + ${FINALBUILDCMD} + +ddns-confgen@EXEEXT@: ddns-confgen.@O@ util.@O@ keygen.@O@ ${UOBJS} ${CONFDEPLIBS} + export BASEOBJS="ddns-confgen.@O@ util.@O@ keygen.@O@ ${UOBJS}"; \ + ${FINALBUILDCMD} + +doc man:: ${MANOBJS} + +docclean manclean maintainer-clean:: + rm -f ${MANOBJS} + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + +install:: rndc-confgen@EXEEXT@ ddns-confgen@EXEEXT@ installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} rndc-confgen@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} ddns-confgen@EXEEXT@ ${DESTDIR}${sbindir} + ${INSTALL_DATA} ${srcdir}/rndc-confgen.8 ${DESTDIR}${mandir}/man8 + ${INSTALL_DATA} ${srcdir}/ddns-confgen.8 ${DESTDIR}${mandir}/man8 + +clean distclean maintainer-clean:: + rm -f ${TARGETS} diff --git a/contrib/bind9/bin/confgen/ddns-confgen.8 b/contrib/bind9/bin/confgen/ddns-confgen.8 new file mode 100644 index 000000000000..d69af398e614 --- /dev/null +++ b/contrib/bind9/bin/confgen/ddns-confgen.8 @@ -0,0 +1,143 @@ +.\" 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: ddns-confgen.8,v 1.10 2009-09-19 01:14:52 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: ddns\-confgen +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/> +.\" Date: Jan 29, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "DDNS\-CONFGEN" "8" "Jan 29, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +ddns\-confgen \- ddns key generation tool +.SH "SYNOPSIS" +.HP 13 +\fBddns\-confgen\fR [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-h\fR] [\fB\-k\ \fR\fB\fIkeyname\fR\fR] [\fB\-r\ \fR\fB\fIrandomfile\fR\fR] [\-s\ \fIname\fR | \-z\ \fIzone\fR] [\fB\-q\fR] [name] +.SH "DESCRIPTION" +.PP +\fBddns\-confgen\fR +generates a key for use by +\fBnsupdate\fR +and +\fBnamed\fR. It simplifies configuration of dynamic zones by generating a key and providing the +\fBnsupdate\fR +and +\fBnamed.conf\fR +syntax that will be needed to use it, including an example +\fBupdate\-policy\fR +statement. +.PP +If a domain name is specified on the command line, it will be used in the name of the generated key and in the sample +\fBnamed.conf\fR +syntax. For example, +\fBddns\-confgen example.com\fR +would generate a key called "ddns\-key.example.com", and sample +\fBnamed.conf\fR +command that could be used in the zone definition for "example.com". +.PP +Note that +\fBnamed\fR +itself can configure a local DDNS key for use with +\fBnsupdate \-l\fR. +\fBddns\-confgen\fR +is only needed when a more elaborate configuration is required: for instance, if +\fBnsupdate\fR +is to be used from a remote system. +.SH "OPTIONS" +.PP +\-a \fIalgorithm\fR +.RS 4 +Specifies the algorithm to use for the TSIG key. Available choices are: hmac\-md5, hmac\-sha1, hmac\-sha224, hmac\-sha256, hmac\-sha384 and hmac\-sha512. The default is hmac\-sha256. +.RE +.PP +\-h +.RS 4 +Prints a short summary of the options and arguments to +\fBddns\-confgen\fR. +.RE +.PP +\-k \fIkeyname\fR +.RS 4 +Specifies the key name of the DDNS authentication key. The default is +\fBddns\-key\fR +when neither the +\fB\-s\fR +nor +\fB\-z\fR +option is specified; otherwise, the default is +\fBddns\-key\fR +as a separate label followed by the argument of the option, e.g., +\fBddns\-key.example.com.\fR +The key name must have the format of a valid domain name, consisting of letters, digits, hyphens and periods. +.RE +.PP +\-q +.RS 4 +Quiet mode: Print only the key, with no explanatory text or usage examples. +.RE +.PP +\-r \fIrandomfile\fR +.RS 4 +Specifies a source of random data for generating the authorization. If the operating system does not provide a +\fI/dev/random\fR +or equivalent device, the default source of randomness is keyboard input. +\fIrandomdev\fR +specifies the name of a character device or file containing random data to be used instead of the default. The special value +\fIkeyboard\fR +indicates that keyboard input should be used. +.RE +.PP +\-s \fIname\fR +.RS 4 +Single host mode: The example +\fBnamed.conf\fR +text shows how to set an update policy for the specified +\fIname\fR +using the "name" nametype. The default key name is ddns\-key.\fIname\fR. Note that the "self" nametype cannot be used, since the name to be updated may differ from the key name. This option cannot be used with the +\fB\-z\fR +option. +.RE +.PP +\-z \fIzone\fR +.RS 4 +zone mode: The example +\fBnamed.conf\fR +text shows how to set an update policy for the specified +\fIzone\fR +using the "zonesub" nametype, allowing updates to all subdomain names within that +\fIzone\fR. This option cannot be used with the +\fB\-s\fR +option. +.RE +.SH "SEE ALSO" +.PP +\fBnsupdate\fR(1), +\fBnamed.conf\fR(5), +\fBnamed\fR(8), +BIND 9 Administrator Reference Manual. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/contrib/bind9/bin/confgen/ddns-confgen.c b/contrib/bind9/bin/confgen/ddns-confgen.c new file mode 100644 index 000000000000..814a5657bb4d --- /dev/null +++ b/contrib/bind9/bin/confgen/ddns-confgen.c @@ -0,0 +1,257 @@ +/* + * 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: ddns-confgen.c,v 1.9 2009-09-29 15:06:05 fdupont Exp $ */ + +/*! \file */ + +/** + * ddns-confgen generates configuration files for dynamic DNS. It can + * be used as a convenient alternative to writing the ddns.key file + * and the corresponding key and update-policy statements in named.conf. + */ + +#include <config.h> + +#include <stdlib.h> +#include <stdarg.h> + +#include <isc/assertions.h> +#include <isc/base64.h> +#include <isc/buffer.h> +#include <isc/commandline.h> +#include <isc/entropy.h> +#include <isc/file.h> +#include <isc/keyboard.h> +#include <isc/mem.h> +#include <isc/net.h> +#include <isc/print.h> +#include <isc/result.h> +#include <isc/string.h> +#include <isc/time.h> +#include <isc/util.h> + +#include <dns/keyvalues.h> +#include <dns/name.h> + +#include <dst/dst.h> +#include <confgen/os.h> + +#include "util.h" +#include "keygen.h" + +#define DEFAULT_KEYNAME "ddns-key" + +static char program[256]; +const char *progname; + +isc_boolean_t verbose = ISC_FALSE; + +ISC_PLATFORM_NORETURN_PRE static void +usage(int status) ISC_PLATFORM_NORETURN_POST; + +static void +usage(int status) { + + fprintf(stderr, "\ +Usage:\n\ + %s [-a alg] [-k keyname] [-r randomfile] [-q] [-s name | -z zone]\n\ + -a alg: algorithm (default hmac-sha256)\n\ + -k keyname: name of the key as it will be used in named.conf\n\ + -r randomfile: source of random data (use \"keyboard\" for key timing)\n\ + -s name: domain name to be updated using the created key\n\ + -z zone: name of the zone as it will be used in named.conf\n\ + -q: quiet mode: print the key, with no explanatory text\n", + progname); + + exit (status); +} + +int +main(int argc, char **argv) { + isc_boolean_t show_final_mem = ISC_FALSE; + isc_boolean_t quiet = ISC_FALSE; + isc_buffer_t key_txtbuffer; + char key_txtsecret[256]; + isc_mem_t *mctx = NULL; + isc_result_t result = ISC_R_SUCCESS; + const char *randomfile = NULL; + const char *keyname = NULL; + const char *zone = NULL; + const char *self_domain = NULL; + char *keybuf = NULL; + dns_secalg_t alg = DST_ALG_HMACSHA256; + const char *algname = alg_totext(alg); + int keysize = 256; + int len = 0; + int ch; + + result = isc_file_progname(*argv, program, sizeof(program)); + if (result != ISC_R_SUCCESS) + memcpy(program, "ddns-confgen", 13); + progname = program; + + isc_commandline_errprint = ISC_FALSE; + + while ((ch = isc_commandline_parse(argc, argv, + "a:hk:Mmr:qs:Vy:z:")) != -1) { + switch (ch) { + case 'a': + algname = isc_commandline_argument; + alg = alg_fromtext(algname); + if (alg == DST_ALG_UNKNOWN) + fatal("Unsupported algorithm '%s'", algname); + keysize = alg_bits(alg); + break; + case 'h': + usage(0); + case 'k': + case 'y': + keyname = isc_commandline_argument; + break; + case 'M': + isc_mem_debugging = ISC_MEM_DEBUGTRACE; + break; + case 'm': + show_final_mem = ISC_TRUE; + break; + case 'q': + quiet = ISC_TRUE; + break; + case 'r': + randomfile = isc_commandline_argument; + break; + case 's': + self_domain = isc_commandline_argument; + break; + case 'V': + verbose = ISC_TRUE; + break; + case 'z': + zone = isc_commandline_argument; + break; + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + usage(1); + } else + usage(0); + break; + default: + fprintf(stderr, "%s: unhandled option -%c\n", + program, isc_commandline_option); + exit(1); + } + } + + argc -= isc_commandline_index; + argv += isc_commandline_index; + + if (self_domain != NULL && zone != NULL) + usage(1); /* -s and -z cannot coexist */ + + if (argc > 0) + usage(1); + + DO("create memory context", isc_mem_create(0, 0, &mctx)); + + if (keyname == NULL) { + const char *suffix = NULL; + + keyname = DEFAULT_KEYNAME; + if (self_domain != NULL) + suffix = self_domain; + else if (zone != NULL) + suffix = zone; + if (suffix != NULL) { + len = strlen(keyname) + strlen(suffix) + 2; + keybuf = isc_mem_get(mctx, len); + if (keybuf == NULL) + fatal("failed to allocate memory for keyname"); + snprintf(keybuf, len, "%s.%s", keyname, suffix); + keyname = (const char *) keybuf; + } + } + + isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); + + generate_key(mctx, randomfile, alg, keysize, &key_txtbuffer); + + + if (!quiet) + printf("\ +# To activate this key, place the following in named.conf, and\n\ +# in a separate keyfile on the system or systems from which nsupdate\n\ +# will be run:\n"); + + printf("\ +key \"%s\" {\n\ + algorithm %s;\n\ + secret \"%.*s\";\n\ +};\n", + keyname, algname, + (int)isc_buffer_usedlength(&key_txtbuffer), + (char *)isc_buffer_base(&key_txtbuffer)); + + if (!quiet) { + if (self_domain != NULL) { + printf("\n\ +# Then, in the \"zone\" statement for the zone containing the\n\ +# name \"%s\", place an \"update-policy\" statement\n\ +# like this one, adjusted as needed for your preferred permissions:\n\ +update-policy {\n\ + grant %s name %s ANY;\n\ +};\n", + self_domain, keyname, self_domain); + } else if (zone != NULL) { + printf("\n\ +# Then, in the \"zone\" definition statement for \"%s\",\n\ +# place an \"update-policy\" statement like this one, adjusted as \n\ +# needed for your preferred permissions:\n\ +update-policy {\n\ + grant %s zonesub ANY;\n\ +};\n", + zone, keyname); + } else { + printf("\n\ +# Then, in the \"zone\" statement for each zone you wish to dynamically\n\ +# update, place an \"update-policy\" statement granting update permission\n\ +# to this key. For example, the following statement grants this key\n\ +# permission to update any name within the zone:\n\ +update-policy {\n\ + grant %s zonesub ANY;\n\ +};\n", + keyname); + } + + printf("\n\ +# After the keyfile has been placed, the following command will\n\ +# execute nsupdate using this key:\n\ +nsupdate -k <keyfile>\n"); + + } + + if (keybuf != NULL) + isc_mem_put(mctx, keybuf, len); + + if (show_final_mem) + isc_mem_stats(mctx, stderr); + + isc_mem_destroy(&mctx); + + return (0); +} diff --git a/contrib/bind9/bin/confgen/ddns-confgen.docbook b/contrib/bind9/bin/confgen/ddns-confgen.docbook new file mode 100644 index 000000000000..2b3e1c0556a5 --- /dev/null +++ b/contrib/bind9/bin/confgen/ddns-confgen.docbook @@ -0,0 +1,218 @@ +<!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: ddns-confgen.docbook,v 1.6 2009-09-18 22:08:55 fdupont Exp $ --> +<refentry id="man.ddns-confgen"> + <refentryinfo> + <date>Jan 29, 2009</date> + </refentryinfo> + + <refmeta> + <refentrytitle><application>ddns-confgen</application></refentrytitle> + <manvolnum>8</manvolnum> + <refmiscinfo>BIND9</refmiscinfo> + </refmeta> + + <refnamediv> + <refname><application>ddns-confgen</application></refname> + <refpurpose>ddns key generation tool</refpurpose> + </refnamediv> + + <docinfo> + <copyright> + <year>2009</year> + <holder>Internet Systems Consortium, Inc. ("ISC")</holder> + </copyright> + </docinfo> + + <refsynopsisdiv> + <cmdsynopsis> + <command>ddns-confgen</command> + <arg><option>-a <replaceable class="parameter">algorithm</replaceable></option></arg> + <arg><option>-h</option></arg> + <arg><option>-k <replaceable class="parameter">keyname</replaceable></option></arg> + <arg><option>-r <replaceable class="parameter">randomfile</replaceable></option></arg> + <group> + <arg choice="plain">-s <replaceable class="parameter">name</replaceable></arg> + <arg choice="plain">-z <replaceable class="parameter">zone</replaceable></arg> + </group> + <arg><option>-q</option></arg> + <arg choice="opt">name</arg> + </cmdsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>DESCRIPTION</title> + <para><command>ddns-confgen</command> + generates a key for use by <command>nsupdate</command> + and <command>named</command>. It simplifies configuration + of dynamic zones by generating a key and providing the + <command>nsupdate</command> and <command>named.conf</command> + syntax that will be needed to use it, including an example + <command>update-policy</command> statement. + </para> + + <para> + If a domain name is specified on the command line, it will + be used in the name of the generated key and in the sample + <command>named.conf</command> syntax. For example, + <command>ddns-confgen example.com</command> would + generate a key called "ddns-key.example.com", and sample + <command>named.conf</command> command that could be used + in the zone definition for "example.com". + </para> + + <para> + Note that <command>named</command> itself can configure a + local DDNS key for use with <command>nsupdate -l</command>. + <command>ddns-confgen</command> is only needed when a + more elaborate configuration is required: for instance, if + <command>nsupdate</command> is to be used from a remote system. + </para> + </refsect1> + + <refsect1> + <title>OPTIONS</title> + + <variablelist> + <varlistentry> + <term>-a <replaceable class="parameter">algorithm</replaceable></term> + <listitem> + <para> + Specifies the algorithm to use for the TSIG key. Available + choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, + hmac-sha384 and hmac-sha512. The default is hmac-sha256. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-h</term> + <listitem> + <para> + Prints a short summary of the options and arguments to + <command>ddns-confgen</command>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-k <replaceable class="parameter">keyname</replaceable></term> + <listitem> + <para> + Specifies the key name of the DDNS authentication key. + The default is <constant>ddns-key</constant> when neither + the <option>-s</option> nor <option>-z</option> option is + specified; otherwise, the default + is <constant>ddns-key</constant> as a separate label + followed by the argument of the option, e.g., + <constant>ddns-key.example.com.</constant> + The key name must have the format of a valid domain name, + consisting of letters, digits, hyphens and periods. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-q</term> + <listitem> + <para> + Quiet mode: Print only the key, with no explanatory text or + usage examples. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-r <replaceable class="parameter">randomfile</replaceable></term> + <listitem> + <para> + Specifies a source of random data for generating the + authorization. If the operating system does not provide a + <filename>/dev/random</filename> or equivalent device, the + default source of randomness is keyboard input. + <filename>randomdev</filename> specifies the name of a + character device or file containing random data to be used + instead of the default. The special value + <filename>keyboard</filename> indicates that keyboard input + should be used. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-s <replaceable class="parameter">name</replaceable></term> + <listitem> + <para> + Single host mode: The example <command>named.conf</command> text + shows how to set an update policy for the specified + <replaceable class="parameter">name</replaceable> + using the "name" nametype. + The default key name is + ddns-key.<replaceable class="parameter">name</replaceable>. + Note that the "self" nametype cannot be used, since + the name to be updated may differ from the key name. + This option cannot be used with the <option>-z</option> option. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-z <replaceable class="parameter">zone</replaceable></term> + <listitem> + <para> + zone mode: The example <command>named.conf</command> text + shows how to set an update policy for the specified + <replaceable class="parameter">zone</replaceable> + using the "zonesub" nametype, allowing updates to all subdomain + names within + that <replaceable class="parameter">zone</replaceable>. + This option cannot be used with the <option>-s</option> option. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>SEE ALSO</title> + <para><citerefentry> + <refentrytitle>nsupdate</refentrytitle><manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>named.conf</refentrytitle><manvolnum>5</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum> + </citerefentry>, + <citetitle>BIND 9 Administrator Reference Manual</citetitle>. + </para> + </refsect1> + + <refsect1> + <title>AUTHOR</title> + <para><corpauthor>Internet Systems Consortium</corpauthor> + </para> + </refsect1> + +</refentry><!-- + - Local variables: + - mode: sgml + - End: +--> diff --git a/contrib/bind9/bin/confgen/ddns-confgen.html b/contrib/bind9/bin/confgen/ddns-confgen.html new file mode 100644 index 000000000000..17c3f26dccae --- /dev/null +++ b/contrib/bind9/bin/confgen/ddns-confgen.html @@ -0,0 +1,141 @@ +<!-- + - 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: ddns-confgen.html,v 1.10 2009-09-19 01:14:52 tbox Exp $ --> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<title>ddns-confgen</title> +<meta name="generator" content="DocBook XSL Stylesheets V1.71.1"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en"> +<a name="man.ddns-confgen"></a><div class="titlepage"></div> +<div class="refnamediv"> +<h2>Name</h2> +<p><span class="application">ddns-confgen</span> — ddns key generation tool</p> +</div> +<div class="refsynopsisdiv"> +<h2>Synopsis</h2> +<div class="cmdsynopsis"><p><code class="command">ddns-confgen</code> [<code class="option">-a <em class="replaceable"><code>algorithm</code></em></code>] [<code class="option">-h</code>] [<code class="option">-k <em class="replaceable"><code>keyname</code></em></code>] [<code class="option">-r <em class="replaceable"><code>randomfile</code></em></code>] [ -s <em class="replaceable"><code>name</code></em> | -z <em class="replaceable"><code>zone</code></em> ] [<code class="option">-q</code>] [name]</p></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543395"></a><h2>DESCRIPTION</h2> +<p><span><strong class="command">ddns-confgen</strong></span> + generates a key for use by <span><strong class="command">nsupdate</strong></span> + and <span><strong class="command">named</strong></span>. It simplifies configuration + of dynamic zones by generating a key and providing the + <span><strong class="command">nsupdate</strong></span> and <span><strong class="command">named.conf</strong></span> + syntax that will be needed to use it, including an example + <span><strong class="command">update-policy</strong></span> statement. + </p> +<p> + If a domain name is specified on the command line, it will + be used in the name of the generated key and in the sample + <span><strong class="command">named.conf</strong></span> syntax. For example, + <span><strong class="command">ddns-confgen example.com</strong></span> would + generate a key called "ddns-key.example.com", and sample + <span><strong class="command">named.conf</strong></span> command that could be used + in the zone definition for "example.com". + </p> +<p> + Note that <span><strong class="command">named</strong></span> itself can configure a + local DDNS key for use with <span><strong class="command">nsupdate -l</strong></span>. + <span><strong class="command">ddns-confgen</strong></span> is only needed when a + more elaborate configuration is required: for instance, if + <span><strong class="command">nsupdate</strong></span> is to be used from a remote system. + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543454"></a><h2>OPTIONS</h2> +<div class="variablelist"><dl> +<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt> +<dd><p> + Specifies the algorithm to use for the TSIG key. Available + choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, + hmac-sha384 and hmac-sha512. The default is hmac-sha256. + </p></dd> +<dt><span class="term">-h</span></dt> +<dd><p> + Prints a short summary of the options and arguments to + <span><strong class="command">ddns-confgen</strong></span>. + </p></dd> +<dt><span class="term">-k <em class="replaceable"><code>keyname</code></em></span></dt> +<dd><p> + Specifies the key name of the DDNS authentication key. + The default is <code class="constant">ddns-key</code> when neither + the <code class="option">-s</code> nor <code class="option">-z</code> option is + specified; otherwise, the default + is <code class="constant">ddns-key</code> as a separate label + followed by the argument of the option, e.g., + <code class="constant">ddns-key.example.com.</code> + The key name must have the format of a valid domain name, + consisting of letters, digits, hyphens and periods. + </p></dd> +<dt><span class="term">-q</span></dt> +<dd><p> + Quiet mode: Print only the key, with no explanatory text or + usage examples. + </p></dd> +<dt><span class="term">-r <em class="replaceable"><code>randomfile</code></em></span></dt> +<dd><p> + Specifies a source of random data for generating the + authorization. If the operating system does not provide a + <code class="filename">/dev/random</code> or equivalent device, the + default source of randomness is keyboard input. + <code class="filename">randomdev</code> specifies the name of a + character device or file containing random data to be used + instead of the default. The special value + <code class="filename">keyboard</code> indicates that keyboard input + should be used. + </p></dd> +<dt><span class="term">-s <em class="replaceable"><code>name</code></em></span></dt> +<dd><p> + Single host mode: The example <span><strong class="command">named.conf</strong></span> text + shows how to set an update policy for the specified + <em class="replaceable"><code>name</code></em> + using the "name" nametype. + The default key name is + ddns-key.<em class="replaceable"><code>name</code></em>. + Note that the "self" nametype cannot be used, since + the name to be updated may differ from the key name. + This option cannot be used with the <code class="option">-z</code> option. + </p></dd> +<dt><span class="term">-z <em class="replaceable"><code>zone</code></em></span></dt> +<dd><p> + zone mode: The example <span><strong class="command">named.conf</strong></span> text + shows how to set an update policy for the specified + <em class="replaceable"><code>zone</code></em> + using the "zonesub" nametype, allowing updates to all subdomain + names within + that <em class="replaceable"><code>zone</code></em>. + This option cannot be used with the <code class="option">-s</code> option. + </p></dd> +</dl></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543642"></a><h2>SEE ALSO</h2> +<p><span class="citerefentry"><span class="refentrytitle">nsupdate</span>(1)</span>, + <span class="citerefentry"><span class="refentrytitle">named.conf</span>(5)</span>, + <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>, + <em class="citetitle">BIND 9 Administrator Reference Manual</em>. + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543681"></a><h2>AUTHOR</h2> +<p><span class="corpauthor">Internet Systems Consortium</span> + </p> +</div> +</div></body> +</html> diff --git a/contrib/bind9/bin/confgen/include/confgen/os.h b/contrib/bind9/bin/confgen/include/confgen/os.h new file mode 100644 index 000000000000..bf80f00ef417 --- /dev/null +++ b/contrib/bind9/bin/confgen/include/confgen/os.h @@ -0,0 +1,39 @@ +/* + * 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: os.h,v 1.3 2009-06-11 23:47:55 tbox Exp $ */ + +/*! \file */ + +#ifndef RNDC_OS_H +#define RNDC_OS_H 1 + +#include <isc/lang.h> +#include <stdio.h> + +ISC_LANG_BEGINDECLS + +int set_user(FILE *fd, const char *user); +/*%< + * Set the owner of the file referenced by 'fd' to 'user'. + * Returns: + * 0 success + * -1 insufficient permissions, or 'user' does not exist. + */ + +ISC_LANG_ENDDECLS + +#endif diff --git a/contrib/bind9/bin/confgen/keygen.c b/contrib/bind9/bin/confgen/keygen.c new file mode 100644 index 000000000000..c259e7e6a721 --- /dev/null +++ b/contrib/bind9/bin/confgen/keygen.c @@ -0,0 +1,218 @@ +/* + * 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: keygen.c,v 1.4 2009-11-12 14:02:38 marka Exp $ */ + +/*! \file */ + +#include <config.h> + +#include <stdlib.h> +#include <stdarg.h> + +#include <isc/base64.h> +#include <isc/buffer.h> +#include <isc/entropy.h> +#include <isc/file.h> +#include <isc/keyboard.h> +#include <isc/mem.h> +#include <isc/result.h> +#include <isc/string.h> + +#include <dns/keyvalues.h> +#include <dns/name.h> + +#include <dst/dst.h> +#include <confgen/os.h> + +#include "util.h" +#include "keygen.h" + +/*% + * Convert algorithm type to string. + */ +const char * +alg_totext(dns_secalg_t alg) { + switch (alg) { + case DST_ALG_HMACMD5: + return "hmac-md5"; + case DST_ALG_HMACSHA1: + return "hmac-sha1"; + case DST_ALG_HMACSHA224: + return "hmac-sha224"; + case DST_ALG_HMACSHA256: + return "hmac-sha256"; + case DST_ALG_HMACSHA384: + return "hmac-sha384"; + case DST_ALG_HMACSHA512: + return "hmac-sha512"; + default: + return "(unknown)"; + } +} + +/*% + * Convert string to algorithm type. + */ +dns_secalg_t +alg_fromtext(const char *name) { + if (strcmp(name, "hmac-md5") == 0) + return DST_ALG_HMACMD5; + if (strcmp(name, "hmac-sha1") == 0) + return DST_ALG_HMACSHA1; + if (strcmp(name, "hmac-sha224") == 0) + return DST_ALG_HMACSHA224; + if (strcmp(name, "hmac-sha256") == 0) + return DST_ALG_HMACSHA256; + if (strcmp(name, "hmac-sha384") == 0) + return DST_ALG_HMACSHA384; + if (strcmp(name, "hmac-sha512") == 0) + return DST_ALG_HMACSHA512; + return DST_ALG_UNKNOWN; +} + +/*% + * Return default keysize for a given algorithm type. + */ +int +alg_bits(dns_secalg_t alg) { + switch (alg) { + case DST_ALG_HMACMD5: + return 128; + case DST_ALG_HMACSHA1: + return 160; + case DST_ALG_HMACSHA224: + return 224; + case DST_ALG_HMACSHA256: + return 256; + case DST_ALG_HMACSHA384: + return 384; + case DST_ALG_HMACSHA512: + return 512; + default: + return 0; + } +} + +/*% + * Generate a key of size 'keysize' using entropy source 'randomfile', + * and place it in 'key_txtbuffer' + */ +void +generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg, + int keysize, isc_buffer_t *key_txtbuffer) { + isc_result_t result = ISC_R_SUCCESS; + isc_entropysource_t *entropy_source = NULL; + int open_keyboard = ISC_ENTROPY_KEYBOARDMAYBE; + int entropy_flags = 0; + isc_entropy_t *ectx = NULL; + isc_buffer_t key_rawbuffer; + isc_region_t key_rawregion; + char key_rawsecret[64]; + dst_key_t *key = NULL; + + switch (alg) { + case DST_ALG_HMACMD5: + if (keysize < 1 || keysize > 512) + fatal("keysize %d out of range (must be 1-512)\n", + keysize); + break; + case DST_ALG_HMACSHA256: + if (keysize < 1 || keysize > 256) + fatal("keysize %d out of range (must be 1-256)\n", + keysize); + break; + default: + fatal("unsupported algorithm %d\n", alg); + } + + + DO("create entropy context", isc_entropy_create(mctx, &ectx)); + + if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) { + randomfile = NULL; + open_keyboard = ISC_ENTROPY_KEYBOARDYES; + } + DO("start entropy source", isc_entropy_usebestsource(ectx, + &entropy_source, + randomfile, + open_keyboard)); + + entropy_flags = ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY; + + DO("initialize dst library", dst_lib_init(mctx, ectx, entropy_flags)); + + DO("generate key", dst_key_generate(dns_rootname, alg, + keysize, 0, 0, + DNS_KEYPROTO_ANY, + dns_rdataclass_in, mctx, &key)); + + isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); + + DO("dump key to buffer", dst_key_tobuffer(key, &key_rawbuffer)); + + isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); + + DO("bsse64 encode secret", isc_base64_totext(&key_rawregion, -1, "", + key_txtbuffer)); + + /* + * Shut down the entropy source now so the "stop typing" message + * does not muck with the output. + */ + if (entropy_source != NULL) + isc_entropy_destroysource(&entropy_source); + + if (key != NULL) + dst_key_free(&key); + + isc_entropy_detach(&ectx); + dst_lib_destroy(); +} + +/*% + * Write a key file to 'keyfile'. If 'user' is non-NULL, + * make that user the owner of the file. The key will have + * the name 'keyname' and the secret in the buffer 'secret'. + */ +void +write_key_file(const char *keyfile, const char *user, + const char *keyname, isc_buffer_t *secret, + dns_secalg_t alg) { + isc_result_t result; + const char *algname = alg_totext(alg); + FILE *fd = NULL; + + DO("create keyfile", isc_file_safecreate(keyfile, &fd)); + + if (user != NULL) { + if (set_user(fd, user) == -1) + fatal("unable to set file owner\n"); + } + + fprintf(fd, "key \"%s\" {\n\talgorithm %s;\n" + "\tsecret \"%.*s\";\n};\n", + keyname, algname, + (int)isc_buffer_usedlength(secret), + (char *)isc_buffer_base(secret)); + fflush(fd); + if (ferror(fd)) + fatal("write to %s failed\n", keyfile); + if (fclose(fd)) + fatal("fclose(%s) failed\n", keyfile); + fprintf(stderr, "wrote key file \"%s\"\n", keyfile); +} + diff --git a/contrib/bind9/bin/confgen/keygen.h b/contrib/bind9/bin/confgen/keygen.h new file mode 100644 index 000000000000..cea25dd4f92a --- /dev/null +++ b/contrib/bind9/bin/confgen/keygen.h @@ -0,0 +1,41 @@ +/* + * 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: keygen.h,v 1.3 2009-06-11 23:47:55 tbox Exp $ */ + +#ifndef RNDC_KEYGEN_H +#define RNDC_KEYGEN_H 1 + +/*! \file */ + +#include <isc/lang.h> + +ISC_LANG_BEGINDECLS + +void generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg, + int keysize, isc_buffer_t *key_txtbuffer); + +void write_key_file(const char *keyfile, const char *user, + const char *keyname, isc_buffer_t *secret, + dns_secalg_t alg); + +const char *alg_totext(dns_secalg_t alg); +dns_secalg_t alg_fromtext(const char *name); +int alg_bits(dns_secalg_t alg); + +ISC_LANG_ENDDECLS + +#endif /* RNDC_KEYGEN_H */ diff --git a/contrib/bind9/bin/rndc/rndc-confgen.8 b/contrib/bind9/bin/confgen/rndc-confgen.8 index db45df4dd7c3..a1b3ae86b735 100644 --- a/contrib/bind9/bin/rndc/rndc-confgen.8 +++ b/contrib/bind9/bin/confgen/rndc-confgen.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2001, 2003 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: rndc-confgen.8,v 1.20.418.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: rndc-confgen.8,v 1.7 2009-07-11 01:12:45 tbox Exp $ .\" .hy 0 .ad l @@ -205,7 +205,7 @@ BIND 9 Administrator Reference Manual. .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2001, 2003 Internet Software Consortium. .br diff --git a/contrib/bind9/bin/rndc/rndc-confgen.c b/contrib/bind9/bin/confgen/rndc-confgen.c index 1cb0a0a7c9b9..766e3b49444e 100644 --- a/contrib/bind9/bin/rndc/rndc-confgen.c +++ b/contrib/bind9/bin/confgen/rndc-confgen.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rndc-confgen.c,v 1.26 2008-10-15 23:47:31 tbox Exp $ */ +/* $Id: rndc-confgen.c,v 1.5 2009-09-29 15:06:05 fdupont Exp $ */ /*! \file */ @@ -52,9 +52,10 @@ #include <dns/name.h> #include <dst/dst.h> -#include <rndc/os.h> +#include <confgen/os.h> #include "util.h" +#include "keygen.h" #define DEFAULT_KEYLENGTH 128 /*% Bits. */ #define DEFAULT_KEYNAME "rndc-key" @@ -68,6 +69,9 @@ isc_boolean_t verbose = ISC_FALSE; const char *keyfile, *keydef; +ISC_PLATFORM_NORETURN_PRE static void +usage(int status) ISC_PLATFORM_NORETURN_POST; + static void usage(int status) { @@ -75,72 +79,36 @@ usage(int status) { Usage:\n\ %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \ [-s addr] [-t chrootdir] [-u user]\n\ - -a: generate just the key clause and write it to keyfile (%s)\n\ - -b bits: from 1 through 512, default %d; total length of the secret\n\ - -c keyfile: specify an alternate key file (requires -a)\n\ - -k keyname: the name as it will be used in named.conf and rndc.conf\n\ - -p port: the port named will listen on and rndc will connect to\n\ - -r randomfile: a file containing random data\n\ - -s addr: the address to which rndc should connect\n\ - -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ - -u user: set the keyfile owner to \"user\" (requires -a)\n", - progname, keydef, DEFAULT_KEYLENGTH); + -a: generate just the key clause and write it to keyfile (%s)\n\ + -b bits: from 1 through 512, default %d; total length of the secret\n\ + -c keyfile: specify an alternate key file (requires -a)\n\ + -k keyname: the name as it will be used in named.conf and rndc.conf\n\ + -p port: the port named will listen on and rndc will connect to\n\ + -r randomfile: source of random data (use \"keyboard\" for key timing)\n\ + -s addr: the address to which rndc should connect\n\ + -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ + -u user: set the keyfile owner to \"user\" (requires -a)\n", + progname, keydef, DEFAULT_KEYLENGTH); exit (status); } -/*% - * Write an rndc.key file to 'keyfile'. If 'user' is non-NULL, - * make that user the owner of the file. The key will have - * the name 'keyname' and the secret in the buffer 'secret'. - */ -static void -write_key_file(const char *keyfile, const char *user, - const char *keyname, isc_buffer_t *secret ) -{ - FILE *fd; - - fd = safe_create(keyfile); - if (fd == NULL) - fatal( "unable to create \"%s\"\n", keyfile); - if (user != NULL) { - if (set_user(fd, user) == -1) - fatal("unable to set file owner\n"); - } - fprintf(fd, "key \"%s\" {\n\talgorithm hmac-md5;\n" - "\tsecret \"%.*s\";\n};\n", keyname, - (int)isc_buffer_usedlength(secret), - (char *)isc_buffer_base(secret)); - fflush(fd); - if (ferror(fd)) - fatal("write to %s failed\n", keyfile); - if (fclose(fd)) - fatal("fclose(%s) failed\n", keyfile); - fprintf(stderr, "wrote key file \"%s\"\n", keyfile); -} - int main(int argc, char **argv) { isc_boolean_t show_final_mem = ISC_FALSE; - isc_buffer_t key_rawbuffer; isc_buffer_t key_txtbuffer; - isc_region_t key_rawregion; + char key_txtsecret[256]; isc_mem_t *mctx = NULL; - isc_entropy_t *ectx = NULL; - isc_entropysource_t *entropy_source = NULL; isc_result_t result = ISC_R_SUCCESS; - dst_key_t *key = NULL; const char *keyname = NULL; const char *randomfile = NULL; const char *serveraddr = NULL; - char key_rawsecret[64]; - char key_txtsecret[256]; + dns_secalg_t alg = DST_ALG_HMACMD5; + const char *algname = alg_totext(alg); char *p; int ch; int port; int keysize; - int entropy_flags = 0; - int open_keyboard = ISC_ENTROPY_KEYBOARDMAYBE; struct in_addr addr4_dummy; struct in6_addr addr6_dummy; char *chrootdir = NULL; @@ -237,53 +205,13 @@ main(int argc, char **argv) { usage(1); DO("create memory context", isc_mem_create(0, 0, &mctx)); - - DO("create entropy context", isc_entropy_create(mctx, &ectx)); - - if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) { - randomfile = NULL; - open_keyboard = ISC_ENTROPY_KEYBOARDYES; - } - DO("start entropy source", isc_entropy_usebestsource(ectx, - &entropy_source, - randomfile, - open_keyboard)); - - entropy_flags = ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY; - - DO("initialize dst library", dst_lib_init(mctx, ectx, entropy_flags)); - - DO("generate key", dst_key_generate(dns_rootname, DST_ALG_HMACMD5, - keysize, 0, 0, - DNS_KEYPROTO_ANY, - dns_rdataclass_in, mctx, &key)); - - isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); - - DO("dump key to buffer", dst_key_tobuffer(key, &key_rawbuffer)); - isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); - isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); - - DO("bsse64 encode secret", isc_base64_totext(&key_rawregion, -1, "", - &key_txtbuffer)); - - /* - * Shut down the entropy source now so the "stop typing" message - * does not muck with the output. - */ - if (entropy_source != NULL) - isc_entropy_destroysource(&entropy_source); - - if (key != NULL) - dst_key_free(&key); - isc_entropy_detach(&ectx); - dst_lib_destroy(); + generate_key(mctx, randomfile, alg, keysize, &key_txtbuffer); if (keyonly) { write_key_file(keyfile, chrootdir == NULL ? user : NULL, - keyname, &key_txtbuffer); + keyname, &key_txtbuffer, alg); if (chrootdir != NULL) { char *buf; @@ -294,14 +222,14 @@ main(int argc, char **argv) { snprintf(buf, len, "%s%s%s", chrootdir, (*keyfile != '/') ? "/" : "", keyfile); - write_key_file(buf, user, keyname, &key_txtbuffer); + write_key_file(buf, user, keyname, &key_txtbuffer, alg); isc_mem_put(mctx, buf, len); } } else { printf("\ # Start of rndc.conf\n\ key \"%s\" {\n\ - algorithm hmac-md5;\n\ + algorithm %s;\n\ secret \"%.*s\";\n\ };\n\ \n\ @@ -314,7 +242,7 @@ options {\n\ \n\ # Use with the following in named.conf, adjusting the allow list as needed:\n\ # key \"%s\" {\n\ -# algorithm hmac-md5;\n\ +# algorithm %s;\n\ # secret \"%.*s\";\n\ # };\n\ # \n\ @@ -323,11 +251,11 @@ options {\n\ # allow { %s; } keys { \"%s\"; };\n\ # };\n\ # End of named.conf\n", - keyname, + keyname, algname, (int)isc_buffer_usedlength(&key_txtbuffer), (char *)isc_buffer_base(&key_txtbuffer), keyname, serveraddr, port, - keyname, + keyname, algname, (int)isc_buffer_usedlength(&key_txtbuffer), (char *)isc_buffer_base(&key_txtbuffer), serveraddr, port, serveraddr, keyname); diff --git a/contrib/bind9/bin/rndc/rndc-confgen.docbook b/contrib/bind9/bin/confgen/rndc-confgen.docbook index f71dd9f94c7b..d43fcfbe8aa4 100644 --- a/contrib/bind9/bin/rndc/rndc-confgen.docbook +++ b/contrib/bind9/bin/confgen/rndc-confgen.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [<!ENTITY mdash "—">]> <!-- - - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") - Copyright (C) 2001, 2003 Internet Software Consortium. - - Permission to use, copy, modify, and/or distribute this software for any @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: rndc-confgen.docbook,v 1.13 2007-06-18 23:47:25 tbox Exp $ --> +<!-- $Id: rndc-confgen.docbook,v 1.4 2009-06-15 23:47:59 tbox Exp $ --> <refentry id="man.rndc-confgen"> <refentryinfo> <date>Aug 27, 2001</date> @@ -40,6 +40,7 @@ <year>2004</year> <year>2005</year> <year>2007</year> + <year>2009</year> <holder>Internet Systems Consortium, Inc. ("ISC")</holder> </copyright> <copyright> diff --git a/contrib/bind9/bin/rndc/rndc-confgen.html b/contrib/bind9/bin/confgen/rndc-confgen.html index 6ef10737ae43..82a712091614 100644 --- a/contrib/bind9/bin/rndc/rndc-confgen.html +++ b/contrib/bind9/bin/confgen/rndc-confgen.html @@ -1,5 +1,5 @@ <!-- - - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") - Copyright (C) 2001, 2003 Internet Software Consortium. - - Permission to use, copy, modify, and/or distribute this software for any @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: rndc-confgen.html,v 1.25.418.1 2009-07-11 01:55:21 tbox Exp $ --> +<!-- $Id: rndc-confgen.html,v 1.7 2009-07-11 01:12:45 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> @@ -32,7 +32,7 @@ <div class="cmdsynopsis"><p><code class="command">rndc-confgen</code> [<code class="option">-a</code>] [<code class="option">-b <em class="replaceable"><code>keysize</code></em></code>] [<code class="option">-c <em class="replaceable"><code>keyfile</code></em></code>] [<code class="option">-h</code>] [<code class="option">-k <em class="replaceable"><code>keyname</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-r <em class="replaceable"><code>randomfile</code></em></code>] [<code class="option">-s <em class="replaceable"><code>address</code></em></code>] [<code class="option">-t <em class="replaceable"><code>chrootdir</code></em></code>] [<code class="option">-u <em class="replaceable"><code>user</code></em></code>]</p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543429"></a><h2>DESCRIPTION</h2> +<a name="id2543432"></a><h2>DESCRIPTION</h2> <p><span><strong class="command">rndc-confgen</strong></span> generates configuration files for <span><strong class="command">rndc</strong></span>. It can be used as a @@ -48,7 +48,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543474"></a><h2>OPTIONS</h2> +<a name="id2543477"></a><h2>OPTIONS</h2> <div class="variablelist"><dl> <dt><span class="term">-a</span></dt> <dd> @@ -155,7 +155,7 @@ </dl></div> </div> <div class="refsect1" lang="en"> -<a name="id2543787"></a><h2>EXAMPLES</h2> +<a name="id2543790"></a><h2>EXAMPLES</h2> <p> To allow <span><strong class="command">rndc</strong></span> to be used with no manual configuration, run @@ -172,7 +172,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543829"></a><h2>SEE ALSO</h2> +<a name="id2543832"></a><h2>SEE ALSO</h2> <p><span class="citerefentry"><span class="refentrytitle">rndc</span>(8)</span>, <span class="citerefentry"><span class="refentrytitle">rndc.conf</span>(5)</span>, <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>, @@ -180,7 +180,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543867"></a><h2>AUTHOR</h2> +<a name="id2543870"></a><h2>AUTHOR</h2> <p><span class="corpauthor">Internet Systems Consortium</span> </p> </div> diff --git a/contrib/bind9/bin/rndc/unix/Makefile.in b/contrib/bind9/bin/confgen/unix/Makefile.in index e503db3b0b27..1785e0d0f4de 100644 --- a/contrib/bind9/bin/rndc/unix/Makefile.in +++ b/contrib/bind9/bin/confgen/unix/Makefile.in @@ -1,5 +1,4 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") -# Copyright (C) 2001 Internet Software Consortium. +# 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 @@ -13,7 +12,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.5 2007-06-19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.3 2009-06-11 23:47:55 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/contrib/bind9/bin/rndc/unix/os.c b/contrib/bind9/bin/confgen/unix/os.c index e9ece1ba776c..e439a5182648 100644 --- a/contrib/bind9/bin/rndc/unix/os.c +++ b/contrib/bind9/bin/confgen/unix/os.c @@ -1,6 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2001 Internet Software Consortium. + * 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 @@ -15,13 +14,13 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: os.c,v 1.10 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: os.c,v 1.3 2009-06-11 23:47:55 tbox Exp $ */ /*! \file */ #include <config.h> -#include <rndc/os.h> +#include <confgen/os.h> #include <fcntl.h> #include <unistd.h> @@ -42,29 +41,3 @@ set_user(FILE *fd, const char *user) { } return (fchown(fileno(fd), pw->pw_uid, -1)); } - -FILE * -safe_create(const char *filename) { - int fd; - FILE *f; - struct stat sb; - int flags = O_WRONLY; - - if (stat(filename, &sb) == -1) { - if (errno != ENOENT) - return (NULL); - flags = O_WRONLY | O_CREAT | O_EXCL; - } else if ((sb.st_mode & S_IFREG) == 0) { - errno = EOPNOTSUPP; - return (NULL); - } else - flags = O_WRONLY | O_TRUNC; - - fd = open(filename, flags, S_IRUSR | S_IWUSR); - if (fd == -1) - return (NULL); - f = fdopen(fd, "w"); - if (f == NULL) - close(fd); - return (f); -} diff --git a/contrib/bind9/bin/confgen/util.c b/contrib/bind9/bin/confgen/util.c new file mode 100644 index 000000000000..158a8d355818 --- /dev/null +++ b/contrib/bind9/bin/confgen/util.c @@ -0,0 +1,56 @@ +/* + * 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: util.c,v 1.3 2009-06-11 23:47:55 tbox Exp $ */ + +/*! \file */ + +#include <config.h> + +#include <stdarg.h> +#include <stdlib.h> +#include <stdio.h> + +#include <isc/boolean.h> + +#include "util.h" + +extern isc_boolean_t verbose; +extern const char *progname; + +void +notify(const char *fmt, ...) { + va_list ap; + + if (verbose) { + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fputs("\n", stderr); + } +} + +void +fatal(const char *format, ...) { + va_list args; + + fprintf(stderr, "%s: ", progname); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + exit(1); +} diff --git a/contrib/bind9/bin/confgen/util.h b/contrib/bind9/bin/confgen/util.h new file mode 100644 index 000000000000..651b6e558cf2 --- /dev/null +++ b/contrib/bind9/bin/confgen/util.h @@ -0,0 +1,52 @@ +/* + * 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: util.h,v 1.4 2009-09-29 15:06:05 fdupont Exp $ */ + +#ifndef RNDC_UTIL_H +#define RNDC_UTIL_H 1 + +/*! \file */ + +#include <isc/lang.h> +#include <isc/platform.h> + +#include <isc/formatcheck.h> + +#define NS_CONTROL_PORT 953 + +#undef DO +#define DO(name, function) \ + do { \ + result = function; \ + if (result != ISC_R_SUCCESS) \ + fatal("%s: %s", name, isc_result_totext(result)); \ + else \ + notify("%s", name); \ + } while (0) + +ISC_LANG_BEGINDECLS + +void +notify(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2); + +ISC_PLATFORM_NORETURN_PRE void +fatal(const char *format, ...) +ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; + +ISC_LANG_ENDDECLS + +#endif /* RNDC_UTIL_H */ diff --git a/contrib/bind9/bin/dig/Makefile.in b/contrib/bind9/bin/dig/Makefile.in index ad20553d532b..bebef6f45d34 100644 --- a/contrib/bind9/bin/dig/Makefile.in +++ b/contrib/bind9/bin/dig/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2000-2002 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.41 2007-06-19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.47 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -24,7 +24,7 @@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} ${BIND9_INCLUDES} \ - ${ISC_INCLUDES} ${LWRES_INCLUDES} + ${ISC_INCLUDES} ${LWRES_INCLUDES} ${ISCCFG_INCLUDES} CDEFINES = -DVERSION=\"${VERSION}\" CWARNINGS = @@ -33,6 +33,7 @@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ LWRESLIBS = ../../lib/lwres/liblwres.@A@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ @@ -44,8 +45,11 @@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} ${ISCCFGDEPLIBS} \ ${LWRESDEPLIBS} -LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCLIBS} \ - ${ISCCFGLIBS} @IDNLIBS@ @LIBS@ +LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ + ${ISCLIBS} @IDNLIBS@ @LIBS@ + +NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ + ${ISCNOSYMLIBS} @IDNLIBS@ @LIBS@ SUBDIRS = @@ -66,16 +70,16 @@ MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ dig@EXEEXT@: dig.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dig.@O@ dighost.@O@ ${UOBJS} ${LIBS} + export BASEOBJS="dig.@O@ dighost.@O@ ${UOBJS}"; \ + ${FINALBUILDCMD} host@EXEEXT@: host.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - host.@O@ dighost.@O@ ${UOBJS} ${LIBS} + export BASEOBJS="host.@O@ dighost.@O@ ${UOBJS}"; \ + ${FINALBUILDCMD} nslookup@EXEEXT@: nslookup.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - nslookup.@O@ dighost.@O@ ${UOBJS} ${LIBS} + export BASEOBJS="nslookup.@O@ dighost.@O@ ${UOBJS}"; \ + ${FINALBUILDCMD} doc man:: ${MANOBJS} diff --git a/contrib/bind9/bin/dig/dig.1 b/contrib/bind9/bin/dig/dig.1 index 93f90b2ea84c..87d5045701ce 100644 --- a/contrib/bind9/bin/dig/dig.1 +++ b/contrib/bind9/bin/dig/dig.1 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000-2003 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: dig.1,v 1.50.44.3 2009-07-11 01:55:20 tbox Exp $ +.\" $Id: dig.1,v 1.54 2010-03-05 01:14:15 tbox Exp $ .\" .hy 0 .ad l @@ -455,6 +455,11 @@ Print records like the SOA records in a verbose multi\-line format with human\-r output. .RE .PP +\fB+[no]onesoa\fR +.RS 4 +Print only one (starting) SOA record when performing an AXFR. The default is to print both the starting and ending SOA records. +.RE +.PP \fB+[no]fail\fR .RS 4 Do not try the next server if you receive a SERVFAIL. The default is to not try the next server which is the reverse of normal stub resolver behavior. @@ -562,7 +567,7 @@ RFC1035. .PP There are probably too many query options. .SH "COPYRIGHT" -Copyright \(co 2004\-2009 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004\-2010 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2000\-2003 Internet Software Consortium. .br diff --git a/contrib/bind9/bin/dig/dig.c b/contrib/bind9/bin/dig/dig.c index 7de934bb50d2..a3143c93d273 100644 --- a/contrib/bind9/bin/dig/dig.c +++ b/contrib/bind9/bin/dig/dig.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dig.c,v 1.225.26.7 2010-05-13 00:43:37 marka Exp $ */ +/* $Id: dig.c,v 1.237 2010-05-13 00:40:46 marka Exp $ */ /*! \file */ @@ -68,7 +68,8 @@ static char domainopt[DNS_NAME_MAXTEXT]; static isc_boolean_t short_form = ISC_FALSE, printcmd = ISC_TRUE, ip6_int = ISC_FALSE, plusquest = ISC_FALSE, pluscomm = ISC_FALSE, - multiline = ISC_FALSE, nottl = ISC_FALSE, noclass = ISC_FALSE; + multiline = ISC_FALSE, nottl = ISC_FALSE, noclass = ISC_FALSE, + onesoa = ISC_FALSE; /*% opcode text */ static const char * const opcodetext[] = { @@ -138,6 +139,9 @@ print_usage(FILE *fp) { " [ host [@local-server] {local-d-opt} [...]]\n", fp); } +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + static void usage(void) { print_usage(stderr); @@ -222,6 +226,7 @@ help(void) { #endif #endif " +[no]multiline (Print records in an expanded format)\n" +" +[no]onesoa (AXFR prints only one soa record)\n" " global d-opts and servers (before host name) affect all queries.\n" " local d-opts and servers (after host name) affect only that lookup.\n" " -h (print help and exit)\n" @@ -468,6 +473,9 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { flags |= DNS_MESSAGETEXTFLAG_NOHEADERS; flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; } + if (onesoa && query->lookup->rdtype == dns_rdatatype_axfr) + flags |= (query->msg_count == 0) ? DNS_MESSAGETEXTFLAG_ONESOA : + DNS_MESSAGETEXTFLAG_OMITSOA; if (!query->lookup->comments) flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; @@ -673,19 +681,6 @@ printgreeting(int argc, char **argv, dig_lookup_t *lookup) { } } -static isc_uint32_t -parse_uint(char *arg, const char *desc, isc_uint32_t max) { - isc_result_t result; - isc_uint32_t tmp; - - result = isc_parse_uint32(&tmp, arg, 10); - if (result == ISC_R_SUCCESS && tmp > max) - result = ISC_R_RANGE; - if (result != ISC_R_SUCCESS) - fatal("%s '%s': %s", desc, arg, isc_result_totext(result)); - return (tmp); -} - /*% * We're not using isc_commandline_parse() here since the command line * syntax of dig is quite a bit different from that which can be described @@ -697,8 +692,10 @@ static void plus_option(char *option, isc_boolean_t is_batchfile, dig_lookup_t *lookup) { + isc_result_t result; char option_store[256]; char *cmd, *value, *ptr; + isc_uint32_t num; isc_boolean_t state = ISC_TRUE; #ifdef DIG_SIGCHASE size_t n; @@ -746,6 +743,7 @@ plus_option(char *option, isc_boolean_t is_batchfile, lookup->section_additional = state; break; case 'f': /* adflag */ + case '\0': /* +ad is a synonym for +adflag */ FULLCHECK("adflag"); lookup->adflag = state; break; @@ -787,8 +785,11 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto need_value; if (!state) goto invalid_option; - lookup->udpsize = (isc_uint16_t) parse_uint(value, - "buffer size", COMMSIZE); + result = parse_uint(&num, value, COMMSIZE, + "buffer size"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse buffer size"); + lookup->udpsize = num; break; default: goto invalid_option; @@ -797,8 +798,15 @@ plus_option(char *option, isc_boolean_t is_batchfile, case 'c': switch (cmd[1]) { case 'd':/* cdflag */ - FULLCHECK("cdflag"); - lookup->cdflag = state; + switch (cmd[2]) { + case 'f': /* cdflag */ + case '\0': /* +cd is a synonym for +cdflag */ + FULLCHECK("cdflag"); + lookup->cdflag = state; + break; + default: + goto invalid_option; + } break; case 'l': /* cl */ FULLCHECK("cl"); @@ -853,7 +861,10 @@ plus_option(char *option, isc_boolean_t is_batchfile, } if (value == NULL) goto need_value; - lookup->edns = (isc_int16_t) parse_uint(value, "edns", 255); + result = parse_uint(&num, value, 255, "edns"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse edns"); + lookup->edns = num; break; case 'f': /* fail */ FULLCHECK("fail"); @@ -883,7 +894,10 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto need_value; if (!state) goto invalid_option; - ndots = parse_uint(value, "ndots", MAXNDOTS); + result = parse_uint(&num, value, MAXNDOTS, "ndots"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse ndots"); + ndots = num; break; case 's': switch (cmd[2]) { @@ -918,6 +932,10 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto invalid_option; } break; + case 'o': + FULLCHECK("onesoa"); + onesoa = state; + break; case 'q': switch (cmd[1]) { case 'r': /* qr */ @@ -948,8 +966,10 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto need_value; if (!state) goto invalid_option; - lookup->retries = parse_uint(value, "retries", - MAXTRIES - 1); + result = parse_uint(&lookup->retries, value, + MAXTRIES - 1, "retries"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse retries"); lookup->retries++; break; default: @@ -1025,7 +1045,10 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto need_value; if (!state) goto invalid_option; - timeout = parse_uint(value, "timeout", MAXTIMEOUT); + result = parse_uint(&timeout, value, MAXTIMEOUT, + "timeout"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse timeout"); if (timeout == 0) timeout = 1; break; @@ -1058,8 +1081,10 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto need_value; if (!state) goto invalid_option; - lookup->retries = parse_uint(value, "tries", - MAXTRIES); + result = parse_uint(&lookup->retries, value, + MAXTRIES, "tries"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse tries"); if (lookup->retries == 0) lookup->retries = 1; break; @@ -1125,6 +1150,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, struct in6_addr in6; in_port_t srcport; char *hash, *cmd; + isc_uint32_t num; while (strpbrk(option, single_dash_opts) == &option[0]) { /* @@ -1140,6 +1166,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, have_ipv6 = ISC_FALSE; } else { fatal("can't find IPv4 networking"); + /* NOTREACHED */ return (ISC_FALSE); } break; @@ -1149,6 +1176,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, have_ipv4 = ISC_FALSE; } else { fatal("can't find IPv6 networking"); + /* NOTREACHED */ return (ISC_FALSE); } break; @@ -1199,9 +1227,11 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, case 'b': hash = strchr(value, '#'); if (hash != NULL) { - srcport = (in_port_t) - parse_uint(hash + 1, - "port number", MAXPORT); + result = parse_uint(&num, hash + 1, MAXPORT, + "port number"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse port number"); + srcport = num; *hash = '\0'; } else srcport = 0; @@ -1245,7 +1275,10 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, keyfile[sizeof(keyfile)-1]=0; return (value_from_next); case 'p': - port = (in_port_t) parse_uint(value, "port number", MAXPORT); + result = parse_uint(&num, value, MAXPORT, "port number"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse port number"); + port = num; return (value_from_next); case 'q': if (!config_only) { @@ -1288,11 +1321,14 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, "extra type option\n"); } if (rdtype == dns_rdatatype_ixfr) { + isc_uint32_t serial; (*lookup)->rdtype = dns_rdatatype_ixfr; (*lookup)->rdtypeset = ISC_TRUE; - (*lookup)->ixfr_serial = - parse_uint(&value[5], "serial number", - MAXSERIAL); + result = parse_uint(&serial, &value[5], + MAXSERIAL, "serial number"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse serial number"); + (*lookup)->ixfr_serial = serial; (*lookup)->section_question = plusquest; (*lookup)->comments = pluscomm; (*lookup)->tcp_mode = ISC_TRUE; @@ -1320,65 +1356,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, usage(); ptr3 = next_token(&value,":"); /* secret or NULL */ if (ptr3 != NULL) { - if (strcasecmp(ptr, "hmac-md5") == 0) { - hmacname = DNS_TSIG_HMACMD5_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-md5-", 9) == 0) { - hmacname = DNS_TSIG_HMACMD5_NAME; - digestbits = parse_uint(&ptr[9], - "digest-bits [0..128]", - 128); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha1") == 0) { - hmacname = DNS_TSIG_HMACSHA1_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha1-", 10) == 0) { - hmacname = DNS_TSIG_HMACSHA1_NAME; - digestbits = parse_uint(&ptr[10], - "digest-bits [0..160]", - 160); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha224") == 0) { - hmacname = DNS_TSIG_HMACSHA224_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha224-", 12) == 0) { - hmacname = DNS_TSIG_HMACSHA224_NAME; - digestbits = parse_uint(&ptr[12], - "digest-bits [0..224]", - 224); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha256") == 0) { - hmacname = DNS_TSIG_HMACSHA256_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha256-", 12) == 0) { - hmacname = DNS_TSIG_HMACSHA256_NAME; - digestbits = parse_uint(&ptr[12], - "digest-bits [0..256]", - 256); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha384") == 0) { - hmacname = DNS_TSIG_HMACSHA384_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha384-", 12) == 0) { - hmacname = DNS_TSIG_HMACSHA384_NAME; - digestbits = parse_uint(&ptr[12], - "digest-bits [0..384]", - 384); - digestbits = (digestbits + 7) & ~0x7U; - } else if (strcasecmp(ptr, "hmac-sha512") == 0) { - hmacname = DNS_TSIG_HMACSHA512_NAME; - digestbits = 0; - } else if (strncasecmp(ptr, "hmac-sha512-", 12) == 0) { - hmacname = DNS_TSIG_HMACSHA512_NAME; - digestbits = parse_uint(&ptr[12], - "digest-bits [0..512]", - 512); - digestbits = (digestbits + 7) & ~0x7U; - } else { - fprintf(stderr, ";; Warning, ignoring " - "invalid TSIG algorithm %s\n", ptr); - return (value_from_next); - } + parse_hmac(ptr); ptr = ptr2; ptr2 = ptr3; } else { @@ -1422,6 +1400,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, fprintf(stderr, "Invalid option: -%s\n", option); usage(); } + /* NOTREACHED */ return (ISC_FALSE); } @@ -1626,13 +1605,18 @@ parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only, "extra type option\n"); } if (rdtype == dns_rdatatype_ixfr) { + isc_uint32_t serial; lookup->rdtype = dns_rdatatype_ixfr; lookup->rdtypeset = ISC_TRUE; - lookup->ixfr_serial = - parse_uint(&rv[0][5], - "serial number", - MAXSERIAL); + result = parse_uint(&serial, + &rv[0][5], + MAXSERIAL, + "serial number"); + if (result != ISC_R_SUCCESS) + fatal("Couldn't parse " + "serial number"); + lookup->ixfr_serial = serial; lookup->section_question = plusquest; lookup->comments = pluscomm; diff --git a/contrib/bind9/bin/dig/dig.docbook b/contrib/bind9/bin/dig/dig.docbook index d8e358644c9c..19e2ca2afbf3 100644 --- a/contrib/bind9/bin/dig/dig.docbook +++ b/contrib/bind9/bin/dig/dig.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [<!ENTITY mdash "—">]> <!-- - - Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") - Copyright (C) 2000-2003 Internet Software Consortium. - - Permission to use, copy, modify, and/or distribute this software for any @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: dig.docbook,v 1.42.44.3 2009-02-02 04:42:48 marka Exp $ --> +<!-- $Id: dig.docbook,v 1.47 2010-03-04 23:50:34 tbox Exp $ --> <refentry id="man.dig"> <refentryinfo> @@ -44,6 +44,7 @@ <year>2007</year> <year>2008</year> <year>2009</year> + <year>2010</year> <holder>Internet Systems Consortium, Inc. ("ISC")</holder> </copyright> <copyright> @@ -766,6 +767,17 @@ </listitem> </varlistentry> + <varlistentry> + <term><option>+[no]onesoa</option></term> + <listitem> + <para> + Print only one (starting) SOA record when performing + an AXFR. The default is to print both the starting and + ending SOA records. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><option>+[no]fail</option></term> <listitem> diff --git a/contrib/bind9/bin/dig/dig.html b/contrib/bind9/bin/dig/dig.html index 17fd5bb3bc75..c9ce8f0e254c 100644 --- a/contrib/bind9/bin/dig/dig.html +++ b/contrib/bind9/bin/dig/dig.html @@ -1,5 +1,5 @@ <!-- - - Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") - Copyright (C) 2000-2003 Internet Software Consortium. - - Permission to use, copy, modify, and/or distribute this software for any @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: dig.html,v 1.45.44.3 2009-07-11 01:55:20 tbox Exp $ --> +<!-- $Id: dig.html,v 1.49 2010-03-05 01:14:15 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> @@ -34,7 +34,7 @@ <div class="cmdsynopsis"><p><code class="command">dig</code> [global-queryopt...] [query...]</p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543518"></a><h2>DESCRIPTION</h2> +<a name="id2543522"></a><h2>DESCRIPTION</h2> <p><span><strong class="command">dig</strong></span> (domain information groper) is a flexible tool for interrogating DNS name servers. It performs DNS lookups and @@ -80,7 +80,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543592"></a><h2>SIMPLE USAGE</h2> +<a name="id2543595"></a><h2>SIMPLE USAGE</h2> <p> A typical invocation of <span><strong class="command">dig</strong></span> looks like: </p> @@ -126,7 +126,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543683"></a><h2>OPTIONS</h2> +<a name="id2543686"></a><h2>OPTIONS</h2> <p> The <code class="option">-b</code> option sets the source IP address of the query to <em class="parameter"><code>address</code></em>. This must be a valid @@ -230,7 +230,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2544032"></a><h2>QUERY OPTIONS</h2> +<a name="id2544035"></a><h2>QUERY OPTIONS</h2> <p><span><strong class="command">dig</strong></span> provides a number of query options which affect the way in which lookups are made and the results displayed. Some of @@ -499,6 +499,12 @@ each record on a single line, to facilitate machine parsing of the <span><strong class="command">dig</strong></span> output. </p></dd> +<dt><span class="term"><code class="option">+[no]onesoa</code></span></dt> +<dd><p> + Print only one (starting) SOA record when performing + an AXFR. The default is to print both the starting and + ending SOA records. + </p></dd> <dt><span class="term"><code class="option">+[no]fail</code></span></dt> <dd><p> Do not try the next server if you receive a SERVFAIL. The @@ -555,7 +561,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2545166"></a><h2>MULTIPLE QUERIES</h2> +<a name="id2545184"></a><h2>MULTIPLE QUERIES</h2> <p> The BIND 9 implementation of <span><strong class="command">dig </strong></span> supports @@ -601,7 +607,7 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr </p> </div> <div class="refsect1" lang="en"> -<a name="id2545228"></a><h2>IDN SUPPORT</h2> +<a name="id2545245"></a><h2>IDN SUPPORT</h2> <p> If <span><strong class="command">dig</strong></span> has been built with IDN (internationalized domain name) support, it can accept and display non-ASCII domain names. @@ -615,14 +621,14 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr </p> </div> <div class="refsect1" lang="en"> -<a name="id2545251"></a><h2>FILES</h2> +<a name="id2545336"></a><h2>FILES</h2> <p><code class="filename">/etc/resolv.conf</code> </p> <p><code class="filename">${HOME}/.digrc</code> </p> </div> <div class="refsect1" lang="en"> -<a name="id2545336"></a><h2>SEE ALSO</h2> +<a name="id2545353"></a><h2>SEE ALSO</h2> <p><span class="citerefentry"><span class="refentrytitle">host</span>(1)</span>, <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>, <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>, @@ -630,7 +636,7 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr </p> </div> <div class="refsect1" lang="en"> -<a name="id2545373"></a><h2>BUGS</h2> +<a name="id2545390"></a><h2>BUGS</h2> <p> There are probably too many query options. </p> diff --git a/contrib/bind9/bin/dig/dighost.c b/contrib/bind9/bin/dig/dighost.c index df5a0c09f5fc..e92bc6edceec 100644 --- a/contrib/bind9/bin/dig/dighost.c +++ b/contrib/bind9/bin/dig/dighost.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dighost.c,v 1.311.70.17 2010-12-09 01:12:54 marka Exp $ */ +/* $Id: dighost.c,v 1.336 2010-12-09 00:54:33 marka Exp $ */ /*! \file * \note @@ -53,6 +53,7 @@ #include <ctype.h> #endif #include <dns/fixedname.h> +#include <dns/log.h> #include <dns/message.h> #include <dns/name.h> #include <dns/rdata.h> @@ -71,10 +72,12 @@ #include <isc/entropy.h> #include <isc/file.h> #include <isc/lang.h> +#include <isc/log.h> #include <isc/netaddr.h> #ifdef DIG_SIGCHASE #include <isc/netdb.h> #endif +#include <isc/parseint.h> #include <isc/print.h> #include <isc/random.h> #include <isc/result.h> @@ -84,6 +87,8 @@ #include <isc/types.h> #include <isc/util.h> +#include <isccfg/namedconf.h> + #include <lwres/lwres.h> #include <lwres/net.h> @@ -121,6 +126,7 @@ in_port_t port = 53; unsigned int timeout = 0; unsigned int extrabytes; isc_mem_t *mctx = NULL; +isc_log_t *lctx = NULL; isc_taskmgr_t *taskmgr = NULL; isc_task_t *global_task = NULL; isc_timermgr_t *timermgr = NULL; @@ -393,7 +399,7 @@ count_dots(char *string) { static void hex_dump(isc_buffer_t *b) { - unsigned int len; + unsigned int len, i; isc_region_t r; isc_buffer_usedregion(b, &r); @@ -401,11 +407,29 @@ hex_dump(isc_buffer_t *b) { printf("%d bytes\n", r.length); for (len = 0; len < r.length; len++) { printf("%02x ", r.base[len]); - if (len % 16 == 15) + if (len % 16 == 15) { + fputs(" ", stdout); + for (i = len - 15; i <= len; i++) { + if (r.base[i] >= '!' && r.base[i] <= '}') + putchar(r.base[i]); + else + putchar('.'); + } printf("\n"); + } } - if (len % 16 != 0) + if (len % 16 != 0) { + for (i = len; (i % 16) != 0; i++) + fputs(" ", stdout); + fputs(" ", stdout); + for (i = ((len>>4)<<4); i < len; i++) { + if (r.base[i] >= '!' && r.base[i] <= '}') + putchar(r.base[i]); + else + putchar('.'); + } printf("\n"); + } } /*% @@ -903,9 +927,7 @@ setup_text_key(void) { secretsize = isc_buffer_usedlength(&secretbuf); - result = dns_name_fromtext(&keyname, namebuf, - dns_rootname, ISC_FALSE, - namebuf); + result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf); if (result != ISC_R_SUCCESS) goto failure; @@ -924,14 +946,164 @@ setup_text_key(void) { isc_buffer_free(&namebuf); } +isc_result_t +parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, + const char *desc) { + isc_uint32_t n; + isc_result_t result = isc_parse_uint32(&n, value, 10); + if (result == ISC_R_SUCCESS && n > max) + result = ISC_R_RANGE; + if (result != ISC_R_SUCCESS) { + printf("invalid %s '%s': %s\n", desc, + value, isc_result_totext(result)); + return (result); + } + *uip = n; + return (ISC_R_SUCCESS); +} + +static isc_uint32_t +parse_bits(char *arg, const char *desc, isc_uint32_t max) { + isc_result_t result; + isc_uint32_t tmp; + + result = parse_uint(&tmp, arg, max, desc); + if (result != ISC_R_SUCCESS) + fatal("couldn't parse digest bits"); + tmp = (tmp + 7) & ~0x7U; + return (tmp); +} + + +/* + * Parse HMAC algorithm specification + */ +void +parse_hmac(const char *hmac) { + char buf[20]; + int len; + + REQUIRE(hmac != NULL); + + len = strlen(hmac); + if (len >= (int) sizeof(buf)) + fatal("unknown key type '%.*s'", len, hmac); + strncpy(buf, hmac, sizeof(buf)); + + digestbits = 0; + + if (strcasecmp(buf, "hmac-md5") == 0) { + hmacname = DNS_TSIG_HMACMD5_NAME; + } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { + hmacname = DNS_TSIG_HMACMD5_NAME; + digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128); + } else if (strcasecmp(buf, "hmac-sha1") == 0) { + hmacname = DNS_TSIG_HMACSHA1_NAME; + digestbits = 0; + } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) { + hmacname = DNS_TSIG_HMACSHA1_NAME; + digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160); + } else if (strcasecmp(buf, "hmac-sha224") == 0) { + hmacname = DNS_TSIG_HMACSHA224_NAME; + } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) { + hmacname = DNS_TSIG_HMACSHA224_NAME; + digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224); + } else if (strcasecmp(buf, "hmac-sha256") == 0) { + hmacname = DNS_TSIG_HMACSHA256_NAME; + } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) { + hmacname = DNS_TSIG_HMACSHA256_NAME; + digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256); + } else if (strcasecmp(buf, "hmac-sha384") == 0) { + hmacname = DNS_TSIG_HMACSHA384_NAME; + } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) { + hmacname = DNS_TSIG_HMACSHA384_NAME; + digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384); + } else if (strcasecmp(buf, "hmac-sha512") == 0) { + hmacname = DNS_TSIG_HMACSHA512_NAME; + } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) { + hmacname = DNS_TSIG_HMACSHA512_NAME; + digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512); + } else { + fprintf(stderr, ";; Warning, ignoring " + "invalid TSIG algorithm %s\n", buf); + } +} + +/* + * Get a key from a named.conf format keyfile + */ +static isc_result_t +read_confkey(void) { + isc_log_t *lctx = NULL; + cfg_parser_t *pctx = NULL; + cfg_obj_t *file = NULL; + const cfg_obj_t *key = NULL; + const cfg_obj_t *secretobj = NULL; + const cfg_obj_t *algorithmobj = NULL; + const char *keyname; + const char *secretstr; + const char *algorithm; + isc_result_t result; + + if (! isc_file_exists(keyfile)) + return (ISC_R_FILENOTFOUND); + + result = cfg_parser_create(mctx, lctx, &pctx); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, + &file); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = cfg_map_get(file, "key", &key); + if (result != ISC_R_SUCCESS) + goto cleanup; + + (void) cfg_map_get(key, "secret", &secretobj); + (void) cfg_map_get(key, "algorithm", &algorithmobj); + if (secretobj == NULL || algorithmobj == NULL) + fatal("key must have algorithm and secret"); + + keyname = cfg_obj_asstring(cfg_map_getname(key)); + secretstr = cfg_obj_asstring(secretobj); + algorithm = cfg_obj_asstring(algorithmobj); + + strncpy(keynametext, keyname, sizeof(keynametext)); + strncpy(keysecret, secretstr, sizeof(keysecret)); + parse_hmac(algorithm); + setup_text_key(); + + cleanup: + if (pctx != NULL) { + if (file != NULL) + cfg_obj_destroy(pctx, &file); + cfg_parser_destroy(&pctx); + } + + return (result); +} + static void setup_file_key(void) { isc_result_t result; dst_key_t *dstkey = NULL; debug("setup_file_key()"); - result = dst_key_fromnamedfile(keyfile, DST_TYPE_PRIVATE | DST_TYPE_KEY, - mctx, &dstkey); + + /* Try reading the key from a K* pair */ + result = dst_key_fromnamedfile(keyfile, NULL, + DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, + &dstkey); + + /* If that didn't work, try reading it as a session.key keyfile */ + if (result != ISC_R_SUCCESS) { + result = read_confkey(); + if (result == ISC_R_SUCCESS) + return; + } + if (result != ISC_R_SUCCESS) { fprintf(stderr, "Couldn't read key from %s: %s\n", keyfile, isc_result_totext(result)); @@ -1119,6 +1291,7 @@ set_search_domain(char *domain) { void setup_libs(void) { isc_result_t result; + isc_logconfig_t *logconfig = NULL; debug("setup_libs()"); @@ -1135,6 +1308,18 @@ setup_libs(void) { result = isc_mem_create(0, 0, &mctx); check_result(result, "isc_mem_create"); + result = isc_log_create(mctx, &lctx, &logconfig); + check_result(result, "isc_log_create"); + + isc_log_setcontext(lctx); + dns_log_init(lctx); + dns_log_setcontext(lctx); + + result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL); + check_result(result, "isc_log_usechannel"); + + isc_log_setdebuglevel(lctx, 0); + result = isc_taskmgr_create(mctx, 1, 0, &taskmgr); check_result(result, "isc_taskmgr_create"); @@ -1871,7 +2056,7 @@ setup_lookup(dig_lookup_t *lookup) { isc_buffer_init(&b, lookup->origin->origin, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->oname, &b, dns_rootname, - ISC_FALSE, &lookup->onamebuf); + 0, &lookup->onamebuf); if (result != ISC_R_SUCCESS) { dns_message_puttempname(lookup->sendmsg, &lookup->name); @@ -1888,7 +2073,7 @@ setup_lookup(dig_lookup_t *lookup) { isc_buffer_init(&b, lookup->textname, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->name, &b, - lookup->oname, ISC_FALSE, + lookup->oname, 0, &lookup->namebuf); } if (result != ISC_R_SUCCESS) { @@ -1912,16 +2097,14 @@ setup_lookup(dig_lookup_t *lookup) { isc_buffer_init(&b, idn_textname, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->name, &b, - dns_rootname, - ISC_FALSE, + dns_rootname, 0, &lookup->namebuf); #else len = strlen(lookup->textname); isc_buffer_init(&b, lookup->textname, len); isc_buffer_add(&b, len); result = dns_name_fromtext(lookup->name, &b, - dns_rootname, - ISC_FALSE, + dns_rootname, 0, &lookup->namebuf); #endif } @@ -3549,9 +3732,11 @@ destroy_libs(void) { free_name(&chase_signame, mctx); #endif - debug("Destroy memory"); - #endif + debug("Removing log context"); + isc_log_destroy(&lctx); + + debug("Destroy memory"); if (memdebugging != 0) isc_mem_stats(mctx, stderr); if (mctx != NULL) @@ -4041,7 +4226,7 @@ get_trusted_key(isc_mem_t *mctx) return (ISC_R_FAILURE); } fclose(fptemp); - result = dst_key_fromnamedfile(filetemp, DST_TYPE_PUBLIC, + result = dst_key_fromnamedfile(filetemp, NULL, DST_TYPE_PUBLIC, mctx, &key); removetmpkey(mctx, filetemp); isc_mem_free(mctx, filetemp); @@ -4075,7 +4260,7 @@ nameFromString(const char *str, dns_name_t *p_ret) { dns_fixedname_init(&fixedname); result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer, - dns_rootname, ISC_TRUE, NULL); + dns_rootname, DNS_NAME_DOWNCASE, NULL); check_result(result, "nameFromString"); if (dns_name_dynamic(p_ret)) diff --git a/contrib/bind9/bin/dig/host.1 b/contrib/bind9/bin/dig/host.1 index 1573effc8f2a..464d517a0b3d 100644 --- a/contrib/bind9/bin/dig/host.1 +++ b/contrib/bind9/bin/dig/host.1 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: host.1,v 1.29.114.2 2009-07-11 01:55:20 tbox Exp $ +.\" $Id: host.1,v 1.31 2009-07-11 01:12:45 tbox Exp $ .\" .hy 0 .ad l diff --git a/contrib/bind9/bin/dig/host.c b/contrib/bind9/bin/dig/host.c index ab0be99cd4bd..13569f63ac98 100644 --- a/contrib/bind9/bin/dig/host.c +++ b/contrib/bind9/bin/dig/host.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: host.c,v 1.116.216.5 2010-10-19 23:45:58 tbox Exp $ */ +/* $Id: host.c,v 1.124 2010-11-16 05:38:30 marka Exp $ */ /*! \file */ @@ -141,6 +141,9 @@ rcode_totext(dns_rcode_t rcode) return totext.deconsttext; } +ISC_PLATFORM_NORETURN_PRE static void +show_usage(void) ISC_PLATFORM_NORETURN_POST; + static void show_usage(void) { fputs( diff --git a/contrib/bind9/bin/dig/host.docbook b/contrib/bind9/bin/dig/host.docbook index 41175aaffb2c..9ffd8e6ffb11 100644 --- a/contrib/bind9/bin/dig/host.docbook +++ b/contrib/bind9/bin/dig/host.docbook @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: host.docbook,v 1.18.114.2 2009-01-22 23:47:05 tbox Exp $ --> +<!-- $Id: host.docbook,v 1.20 2009-01-20 23:47:56 tbox Exp $ --> <refentry id="man.host"> <refentryinfo> diff --git a/contrib/bind9/bin/dig/host.html b/contrib/bind9/bin/dig/host.html index de4b5797de99..531fc1d78968 100644 --- a/contrib/bind9/bin/dig/host.html +++ b/contrib/bind9/bin/dig/host.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: host.html,v 1.28.114.2 2009-07-11 01:55:20 tbox Exp $ --> +<!-- $Id: host.html,v 1.30 2009-07-11 01:12:45 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> diff --git a/contrib/bind9/bin/dig/include/dig/dig.h b/contrib/bind9/bin/dig/include/dig/dig.h index 3d696c70bb8f..c0f778b5f142 100644 --- a/contrib/bind9/bin/dig/include/dig/dig.h +++ b/contrib/bind9/bin/dig/include/dig/dig.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dig.h,v 1.107.120.2 2009-01-06 23:47:26 tbox Exp $ */ +/* $Id: dig.h,v 1.111 2009-09-29 15:06:06 fdupont Exp $ */ #ifndef DIG_H #define DIG_H @@ -292,8 +292,9 @@ isc_result_t get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int, isc_boolean_t strict); -void -fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); +ISC_PLATFORM_NORETURN_PRE void +fatal(const char *format, ...) +ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; void debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); @@ -325,6 +326,13 @@ setup_libs(void); void setup_system(void); +isc_result_t +parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, + const char *desc); + +void +parse_hmac(const char *hmacstr); + dig_lookup_t * requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers); diff --git a/contrib/bind9/bin/dig/nslookup.1 b/contrib/bind9/bin/dig/nslookup.1 index a8331f9b4c64..e97ee1f9ba39 100644 --- a/contrib/bind9/bin/dig/nslookup.1 +++ b/contrib/bind9/bin/dig/nslookup.1 @@ -12,7 +12,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: nslookup.1,v 1.14.354.2 2010-02-23 01:56:02 tbox Exp $ +.\" $Id: nslookup.1,v 1.16 2010-02-23 01:14:31 tbox Exp $ .\" .hy 0 .ad l diff --git a/contrib/bind9/bin/dig/nslookup.c b/contrib/bind9/bin/dig/nslookup.c index 8a166fd05535..0d368b15c800 100644 --- a/contrib/bind9/bin/dig/nslookup.c +++ b/contrib/bind9/bin/dig/nslookup.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nslookup.c,v 1.117.334.5 2009-10-20 01:11:22 marka Exp $ */ +/* $Id: nslookup.c,v 1.127 2010-11-17 23:47:08 tbox Exp $ */ #include <config.h> @@ -541,22 +541,6 @@ safecpy(char *dest, char *src, int size) { dest[size-1] = 0; } -static isc_result_t -parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, - const char *desc) { - isc_uint32_t n; - isc_result_t result = isc_parse_uint32(&n, value, 10); - if (result == ISC_R_SUCCESS && n > max) - result = ISC_R_RANGE; - if (result != ISC_R_SUCCESS) { - printf("invalid %s '%s': %s\n", desc, - value, isc_result_totext(result)); - return result; - } - *uip = n; - return (ISC_R_SUCCESS); -} - static void set_port(const char *value) { isc_uint32_t n; diff --git a/contrib/bind9/bin/dig/nslookup.docbook b/contrib/bind9/bin/dig/nslookup.docbook index fb6e70652c50..9c4789d4cb18 100644 --- a/contrib/bind9/bin/dig/nslookup.docbook +++ b/contrib/bind9/bin/dig/nslookup.docbook @@ -17,7 +17,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: nslookup.docbook,v 1.16.334.2 2010-02-22 23:47:53 tbox Exp $ --> +<!-- $Id: nslookup.docbook,v 1.18 2010-02-22 23:49:11 tbox Exp $ --> <!-- - Copyright (c) 1985, 1989 - The Regents of the University of California. All rights reserved. diff --git a/contrib/bind9/bin/dig/nslookup.html b/contrib/bind9/bin/dig/nslookup.html index bff35282a79e..bae63bd0fd3d 100644 --- a/contrib/bind9/bin/dig/nslookup.html +++ b/contrib/bind9/bin/dig/nslookup.html @@ -13,7 +13,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: nslookup.html,v 1.21.354.2 2010-02-23 01:56:02 tbox Exp $ --> +<!-- $Id: nslookup.html,v 1.23 2010-02-23 01:14:31 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> diff --git a/contrib/bind9/bin/dnssec/Makefile.in b/contrib/bind9/bin/dnssec/Makefile.in index 50429be61337..0f5e4e842c20 100644 --- a/contrib/bind9/bin/dnssec/Makefile.in +++ b/contrib/bind9/bin/dnssec/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2000-2002 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.35 2008-11-07 02:28:49 marka Exp $ +# $Id: Makefile.in,v 1.42 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -25,11 +25,12 @@ top_srcdir = @top_srcdir@ CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} -CDEFINES = -DVERSION=\"${VERSION}\" +CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ CWARNINGS = DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ @@ -38,44 +39,56 @@ DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ +NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@ + # Alphabetically TARGETS = dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \ - dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ + dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \ + dnssec-revoke@EXEEXT@ dnssec-settime@EXEEXT@ OBJS = dnssectool.@O@ SRCS = dnssec-dsfromkey.c dnssec-keyfromlabel.c dnssec-keygen.c \ - dnssec-signzone.c dnssectool.c + dnssec-revoke.c dnssec-settime.c dnssec-signzone.c dnssectool.c MANPAGES = dnssec-dsfromkey.8 dnssec-keyfromlabel.8 dnssec-keygen.8 \ - dnssec-signzone.8 + dnssec-revoke.8 dnssec-settime.8 dnssec-signzone.8 HTMLPAGES = dnssec-dsfromkey.html dnssec-keyfromlabel.html \ - dnssec-keygen.html dnssec-signzone.html + dnssec-keygen.html dnssec-revoke.html \ + dnssec-settime.html dnssec-signzone.html MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ dnssec-dsfromkey@EXEEXT@: dnssec-dsfromkey.@O@ ${OBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dnssec-dsfromkey.@O@ ${OBJS} ${LIBS} + export BASEOBJS="dnssec-dsfromkey.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} dnssec-keyfromlabel@EXEEXT@: dnssec-keyfromlabel.@O@ ${OBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dnssec-keyfromlabel.@O@ ${OBJS} ${LIBS} + export BASEOBJS="dnssec-keyfromlabel.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} dnssec-keygen@EXEEXT@: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dnssec-keygen.@O@ ${OBJS} ${LIBS} + export BASEOBJS="dnssec-keygen.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} dnssec-signzone.@O@: dnssec-signzone.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \ -c ${srcdir}/dnssec-signzone.c dnssec-signzone@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS} + export BASEOBJS="dnssec-signzone.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} + +dnssec-revoke@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dnssec-revoke.@O@ ${OBJS} ${LIBS} + +dnssec-settime@EXEEXT@: dnssec-settime.@O@ ${OBJS} ${DEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dnssec-signzone.@O@ ${OBJS} ${LIBS} + dnssec-settime.@O@ ${OBJS} ${LIBS} doc man:: ${MANOBJS} diff --git a/contrib/bind9/bin/dnssec/dnssec-dsfromkey.8 b/contrib/bind9/bin/dnssec/dnssec-dsfromkey.8 index c49ccdc82377..25aa2bf831fc 100644 --- a/contrib/bind9/bin/dnssec/dnssec-dsfromkey.8 +++ b/contrib/bind9/bin/dnssec/dnssec-dsfromkey.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2008-2010 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 @@ -12,18 +12,18 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: dnssec-dsfromkey.8,v 1.5.14.1 2010-05-19 02:06:11 tbox Exp $ +.\" $Id: dnssec-dsfromkey.8,v 1.13 2010-12-24 01:14:20 tbox Exp $ .\" .hy 0 .ad l .\" Title: dnssec\-dsfromkey .\" Author: .\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/> -.\" Date: November 29, 2008 +.\" Date: August 26, 2009 .\" Manual: BIND9 .\" Source: BIND9 .\" -.TH "DNSSEC\-DSFROMKEY" "8" "November 29, 2008" "BIND9" "BIND9" +.TH "DNSSEC\-DSFROMKEY" "8" "August 26, 2009" "BIND9" "BIND9" .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) @@ -32,9 +32,9 @@ dnssec\-dsfromkey \- DNSSEC DS RR generation tool .SH "SYNOPSIS" .HP 17 -\fBdnssec\-dsfromkey\fR [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] {keyfile} +\fBdnssec\-dsfromkey\fR [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] {keyfile} .HP 17 -\fBdnssec\-dsfromkey\fR {\-s} [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIdir\fR\fR] {dnsname} +\fBdnssec\-dsfromkey\fR {\-s} [\fB\-1\fR] [\fB\-2\fR] [\fB\-a\ \fR\fB\fIalg\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-s\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIfile\fR\fR] [\fB\-A\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] {dnsname} .SH "DESCRIPTION" .PP \fBdnssec\-dsfromkey\fR @@ -55,31 +55,49 @@ Use SHA\-256 as the digest algorithm. .RS 4 Select the digest algorithm. The value of \fBalgorithm\fR -must be one of SHA\-1 (SHA1) or SHA\-256 (SHA256). These values are case insensitive. +must be one of SHA\-1 (SHA1), SHA\-256 (SHA256) or GOST. These values are case insensitive. .RE .PP -\-v \fIlevel\fR +\-K \fIdirectory\fR .RS 4 -Sets the debugging level. +Look for key files (or, in keyset mode, +\fIkeyset\-\fR +files) in +\fBdirectory\fR. +.RE +.PP +\-f \fIfile\fR +.RS 4 +Zone file mode: in place of the keyfile name, the argument is the DNS domain name of a zone master file, which can be read from +\fBfile\fR. If the zone name is the same as +\fBfile\fR, then it may be omitted. +.RE +.PP +\-A +.RS 4 +Include ZSK's when generating DS records. Without this option, only keys which have the KSK flag set will be converted to DS records and printed. Useful only in zone file mode. +.RE +.PP +\-l \fIdomain\fR +.RS 4 +Generate a DLV set instead of a DS set. The specified +\fBdomain\fR +is appended to the name for each record in the set. The DNSSEC Lookaside Validation (DLV) RR is described in RFC 4431. .RE .PP \-s .RS 4 -Keyset mode: in place of the keyfile name, the argument is the DNS domain name of a keyset file. Following options make sense only in this mode. +Keyset mode: in place of the keyfile name, the argument is the DNS domain name of a keyset file. .RE .PP \-c \fIclass\fR .RS 4 -Specifies the DNS class (default is IN), useful only in the keyset mode. +Specifies the DNS class (default is IN). Useful only in keyset or zone file mode. .RE .PP -\-d \fIdirectory\fR +\-v \fIlevel\fR .RS 4 -Look for -\fIkeyset\fR -files in -\fBdirectory\fR -as the directory, ignored when not in the keyset mode. +Sets the debugging level. .RE .SH "EXAMPLE" .PP @@ -115,10 +133,11 @@ A keyfile error can give a "file not found" even if the file exists. \fBdnssec\-signzone\fR(8), BIND 9 Administrator Reference Manual, RFC 3658, +RFC 4431. RFC 4509. .SH "AUTHOR" .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2008 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2008\-2010 Internet Systems Consortium, Inc. ("ISC") .br diff --git a/contrib/bind9/bin/dnssec/dnssec-dsfromkey.c b/contrib/bind9/bin/dnssec/dnssec-dsfromkey.c index 934d25bd35ab..b7f84a041110 100644 --- a/contrib/bind9/bin/dnssec/dnssec-dsfromkey.c +++ b/contrib/bind9/bin/dnssec/dnssec-dsfromkey.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-dsfromkey.c,v 1.2.14.6 2010-01-11 23:47:22 tbox Exp $ */ +/* $Id: dnssec-dsfromkey.c,v 1.19 2010-12-23 04:07:59 marka Exp $ */ /*! \file */ @@ -36,6 +36,8 @@ #include <dns/ds.h> #include <dns/fixedname.h> #include <dns/log.h> +#include <dns/keyvalues.h> +#include <dns/master.h> #include <dns/name.h> #include <dns/rdata.h> #include <dns/rdataclass.h> @@ -48,54 +50,40 @@ #include "dnssectool.h" +#ifndef PATH_MAX +#define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */ +#endif + const char *program = "dnssec-dsfromkey"; int verbose; static dns_rdataclass_t rdclass; -static dns_fixedname_t fixed; -static dns_name_t *name = NULL; -static dns_db_t *db = NULL; -static dns_dbnode_t *node = NULL; -static dns_rdataset_t keyset; -static isc_mem_t *mctx = NULL; +static dns_fixedname_t fixed; +static dns_name_t *name = NULL; +static isc_mem_t *mctx = NULL; -static void -loadkeys(char *dirname, char *setname) -{ - isc_result_t result; - char filename[1024]; - isc_buffer_t buf; +static isc_result_t +initname(char *setname) { + isc_result_t result; + isc_buffer_t buf; - dns_rdataset_init(&keyset); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); isc_buffer_init(&buf, setname, strlen(setname)); isc_buffer_add(&buf, strlen(setname)); - result = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); - if (result != ISC_R_SUCCESS) - fatal("can't convert DNS name %s", setname); + result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); + return (result); +} - isc_buffer_init(&buf, filename, sizeof(filename)); - if (dirname != NULL) { - if (isc_buffer_availablelength(&buf) < strlen(dirname)) - fatal("directory name '%s' too long", dirname); - isc_buffer_putstr(&buf, dirname); - if (dirname[strlen(dirname) - 1] != '/') { - if (isc_buffer_availablelength(&buf) < 1) - fatal("directory name '%s' too long", dirname); - isc_buffer_putstr(&buf, "/"); - } - } +static isc_result_t +loadsetfromfile(char *filename, dns_rdataset_t *rdataset) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + char setname[DNS_NAME_FORMATSIZE]; - if (isc_buffer_availablelength(&buf) < strlen("keyset-")) - fatal("directory name '%s' too long", dirname); - isc_buffer_putstr(&buf, "keyset-"); - result = dns_name_tofilenametext(name, ISC_FALSE, &buf); - check_result(result, "dns_name_tofilenametext()"); - if (isc_buffer_availablelength(&buf) == 0) - fatal("name %s too long", setname); - isc_buffer_putuint8(&buf, 0); + dns_name_format(name, setname, sizeof(setname)); result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, rdclass, 0, NULL, &db); @@ -111,11 +99,49 @@ loadkeys(char *dirname, char *setname) fatal("can't find %s node in %s", setname, filename); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, - 0, 0, &keyset, NULL); + 0, 0, rdataset, NULL); + if (result == ISC_R_NOTFOUND) fatal("no DNSKEY RR for %s in %s", setname, filename); else if (result != ISC_R_SUCCESS) fatal("dns_db_findrdataset"); + + if (node != NULL) + dns_db_detachnode(db, &node); + if (db != NULL) + dns_db_detach(&db); + return (result); +} + +static isc_result_t +loadkeyset(char *dirname, dns_rdataset_t *rdataset) { + isc_result_t result; + char filename[PATH_MAX + 1]; + isc_buffer_t buf; + + dns_rdataset_init(rdataset); + + isc_buffer_init(&buf, filename, sizeof(filename)); + if (dirname != NULL) { + /* allow room for a trailing slash */ + if (strlen(dirname) >= isc_buffer_availablelength(&buf)) + return (ISC_R_NOSPACE); + isc_buffer_putstr(&buf, dirname); + if (dirname[strlen(dirname) - 1] != '/') + isc_buffer_putstr(&buf, "/"); + } + + if (isc_buffer_availablelength(&buf) < 7) + return (ISC_R_NOSPACE); + isc_buffer_putstr(&buf, "keyset-"); + + result = dns_name_tofilenametext(name, ISC_FALSE, &buf); + check_result(result, "dns_name_tofilenametext()"); + if (isc_buffer_availablelength(&buf) == 0) + return (ISC_R_NOSPACE); + isc_buffer_putuint8(&buf, 0); + + return (loadsetfromfile(filename, rdataset)); } static void @@ -127,20 +153,20 @@ loadkey(char *filename, unsigned char *key_buf, unsigned int key_buf_size, isc_buffer_t keyb; isc_region_t r; - dns_rdataset_init(&keyset); dns_rdata_init(rdata); isc_buffer_init(&keyb, key_buf, key_buf_size); - result = dst_key_fromnamedfile(filename, DST_TYPE_PUBLIC, mctx, &key); + result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC, + mctx, &key); if (result != ISC_R_SUCCESS) fatal("invalid keyfile name %s: %s", filename, isc_result_totext(result)); if (verbose > 2) { - char keystr[KEY_FORMATSIZE]; + char keystr[DST_KEY_FORMATSIZE]; - key_format(key, keystr, sizeof(keystr)); + dst_key_format(key, keystr, sizeof(keystr)); fprintf(stderr, "%s: %s\n", program, keystr); } @@ -169,7 +195,7 @@ logkey(dns_rdata_t *rdata) isc_result_t result; dst_key_t *key = NULL; isc_buffer_t buf; - char keystr[KEY_FORMATSIZE]; + char keystr[DST_KEY_FORMATSIZE]; isc_buffer_init(&buf, rdata->data, rdata->length); isc_buffer_add(&buf, rdata->length); @@ -177,89 +203,132 @@ logkey(dns_rdata_t *rdata) if (result != ISC_R_SUCCESS) return; - key_format(key, keystr, sizeof(keystr)); + dst_key_format(key, keystr, sizeof(keystr)); fprintf(stderr, "%s: %s\n", program, keystr); dst_key_free(&key); } static void -emitds(unsigned int dtype, dns_rdata_t *rdata) +emit(unsigned int dtype, isc_boolean_t showall, char *lookaside, + dns_rdata_t *rdata) { - isc_result_t result; - unsigned char buf[DNS_DS_BUFFERSIZE]; - char text_buf[DST_KEY_MAXTEXTSIZE]; - char class_buf[10]; - isc_buffer_t textb, classb; - isc_region_t r; - dns_rdata_t ds; + isc_result_t result; + unsigned char buf[DNS_DS_BUFFERSIZE]; + char text_buf[DST_KEY_MAXTEXTSIZE]; + char name_buf[DNS_NAME_MAXWIRE]; + char class_buf[10]; + isc_buffer_t textb, nameb, classb; + isc_region_t r; + dns_rdata_t ds; + dns_rdata_dnskey_t dnskey; isc_buffer_init(&textb, text_buf, sizeof(text_buf)); + isc_buffer_init(&nameb, name_buf, sizeof(name_buf)); isc_buffer_init(&classb, class_buf, sizeof(class_buf)); dns_rdata_init(&ds); + result = dns_rdata_tostruct(rdata, &dnskey, NULL); + if (result != ISC_R_SUCCESS) + fatal("can't convert DNSKEY"); + + if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && !showall) + return; + result = dns_ds_buildrdata(name, rdata, dtype, buf, &ds); if (result != ISC_R_SUCCESS) - fatal("can't build DS"); + fatal("can't build record"); + + result = dns_name_totext(name, ISC_FALSE, &nameb); + if (result != ISC_R_SUCCESS) + fatal("can't print name"); + + /* Add lookaside origin, if set */ + if (lookaside != NULL) { + if (isc_buffer_availablelength(&nameb) < strlen(lookaside)) + fatal("DLV origin '%s' is too long", lookaside); + isc_buffer_putstr(&nameb, lookaside); + if (lookaside[strlen(lookaside) - 1] != '.') { + if (isc_buffer_availablelength(&nameb) < 1) + fatal("DLV origin '%s' is too long", lookaside); + isc_buffer_putstr(&nameb, "."); + } + } result = dns_rdata_totext(&ds, (dns_name_t *) NULL, &textb); if (result != ISC_R_SUCCESS) - fatal("can't print DS rdata"); + fatal("can't print rdata"); result = dns_rdataclass_totext(rdclass, &classb); if (result != ISC_R_SUCCESS) - fatal("can't print DS class"); + fatal("can't print class"); - result = dns_name_print(name, stdout); - if (result != ISC_R_SUCCESS) - fatal("can't print DS name"); + isc_buffer_usedregion(&nameb, &r); + isc_util_fwrite(r.base, 1, r.length, stdout); putchar(' '); isc_buffer_usedregion(&classb, &r); isc_util_fwrite(r.base, 1, r.length, stdout); - printf(" DS "); + if (lookaside == NULL) + printf(" DS "); + else + printf(" DLV "); isc_buffer_usedregion(&textb, &r); isc_util_fwrite(r.base, 1, r.length, stdout); putchar('\n'); } +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + static void usage(void) { fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s options keyfile\n\n", program); - fprintf(stderr, " %s options [-c class] [-d dir] -s dnsname\n\n", + fprintf(stderr, " %s options [-K dir] keyfile\n\n", program); + fprintf(stderr, " %s options [-K dir] [-c class] -s dnsname\n\n", program); + fprintf(stderr, " %s options -f zonefile (as zone name)\n\n", program); + fprintf(stderr, " %s options -f zonefile zonename\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "Options:\n"); fprintf(stderr, " -v <verbose level>\n"); + fprintf(stderr, " -K <directory>: directory in which to find " + "key file or keyset file\n"); + fprintf(stderr, " -a algorithm: digest algorithm " + "(SHA-1, SHA-256 or GOST)\n"); fprintf(stderr, " -1: use SHA-1\n"); fprintf(stderr, " -2: use SHA-256\n"); - fprintf(stderr, " -a algorithm: use algorithm\n"); - fprintf(stderr, "Keyset options:\n"); - fprintf(stderr, " -s: keyset mode\n"); - fprintf(stderr, " -c class\n"); - fprintf(stderr, " -d directory\n"); - fprintf(stderr, "Output: DS RRs\n"); + fprintf(stderr, " -l: add lookaside zone and print DLV records\n"); + fprintf(stderr, " -s: read keyset from keyset-<dnsname> file\n"); + fprintf(stderr, " -c class: rdata class for DS set (default: IN)\n"); + fprintf(stderr, " -f file: read keyset from zone file\n"); + fprintf(stderr, " -A: when used with -f, " + "include all keys in DS set, not just KSKs\n"); + fprintf(stderr, "Output: DS or DLV RRs\n"); exit (-1); } int main(int argc, char **argv) { - char *algname = NULL, *classname = NULL, *dirname = NULL; - char *endp; - int ch; - unsigned int dtype = DNS_DSDIGEST_SHA1; - isc_boolean_t both = ISC_TRUE; - isc_boolean_t usekeyset = ISC_FALSE; - isc_result_t result; - isc_log_t *log = NULL; - isc_entropy_t *ectx = NULL; - dns_rdata_t rdata; + char *algname = NULL, *classname = NULL; + char *filename = NULL, *dir = NULL, *namestr; + char *lookaside = NULL; + char *endp; + int ch; + unsigned int dtype = DNS_DSDIGEST_SHA1; + isc_boolean_t both = ISC_TRUE; + isc_boolean_t usekeyset = ISC_FALSE; + isc_boolean_t showall = ISC_FALSE; + isc_result_t result; + isc_log_t *log = NULL; + isc_entropy_t *ectx = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata; dns_rdata_init(&rdata); @@ -275,7 +344,7 @@ main(int argc, char **argv) { isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, - "12a:c:d:sv:h")) != -1) { + "12Aa:c:d:Ff:K:l:sv:h")) != -1) { switch (ch) { case '1': dtype = DNS_DSDIGEST_SHA1; @@ -285,6 +354,9 @@ main(int argc, char **argv) { dtype = DNS_DSDIGEST_SHA256; both = ISC_FALSE; break; + case 'A': + showall = ISC_TRUE; + break; case 'a': algname = isc_commandline_argument; both = ISC_FALSE; @@ -293,7 +365,21 @@ main(int argc, char **argv) { classname = isc_commandline_argument; break; case 'd': - dirname = isc_commandline_argument; + fprintf(stderr, "%s: the -d option is deprecated; " + "use -K\n", program); + /* fall through */ + case 'K': + dir = isc_commandline_argument; + if (strlen(dir) == 0U) + fatal("directory must be non-empty string"); + break; + case 'f': + filename = isc_commandline_argument; + break; + case 'l': + lookaside = isc_commandline_argument; + if (strlen(lookaside) == 0U) + fatal("lookaside must be a non-empty string"); break; case 's': usekeyset = ISC_TRUE; @@ -303,11 +389,14 @@ main(int argc, char **argv) { if (*endp != '\0') fatal("-v must be followed by a number"); break; + case 'F': + /* Reserved for FIPS mode */ + /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); - /* Falls into */ + /* FALLTHROUGH */ case 'h': usage(); @@ -325,13 +414,24 @@ main(int argc, char **argv) { else if (strcasecmp(algname, "SHA256") == 0 || strcasecmp(algname, "SHA-256") == 0) dtype = DNS_DSDIGEST_SHA256; +#ifdef HAVE_OPENSSL_GOST + else if (strcasecmp(algname, "GOST") == 0) + dtype = DNS_DSDIGEST_GOST; +#endif else fatal("unknown algorithm %s", algname); } rdclass = strtoclass(classname); - if (argc < isc_commandline_index + 1) + if (usekeyset && filename != NULL) + fatal("cannot use both -s and -f"); + + /* When not using -f, -A is implicit */ + if (filename == NULL) + showall = ISC_TRUE; + + if (argc < isc_commandline_index + 1 && filename == NULL) fatal("the key file name was not specified"); if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); @@ -344,28 +444,50 @@ main(int argc, char **argv) { result = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (result != ISC_R_SUCCESS) - fatal("could not initialize dst"); + fatal("could not initialize dst: %s", + isc_result_totext(result)); isc_entropy_stopcallbacksources(ectx); setup_logging(verbose, mctx, &log); - if (usekeyset) { - loadkeys(dirname, argv[isc_commandline_index]); + dns_rdataset_init(&rdataset); + + if (usekeyset || filename != NULL) { + if (argc < isc_commandline_index + 1 && filename != NULL) { + /* using zone name as the zone file name */ + namestr = filename; + } else + namestr = argv[isc_commandline_index]; - for (result = dns_rdataset_first(&keyset); + result = initname(namestr); + if (result != ISC_R_SUCCESS) + fatal("could not initialize name %s", namestr); + + if (usekeyset) + result = loadkeyset(dir, &rdataset); + else + result = loadsetfromfile(filename, &rdataset); + + if (result != ISC_R_SUCCESS) + fatal("could not load DNSKEY set: %s\n", + isc_result_totext(result)); + + for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; - result = dns_rdataset_next(&keyset)) { + result = dns_rdataset_next(&rdataset)) { dns_rdata_init(&rdata); - dns_rdataset_current(&keyset, &rdata); + dns_rdataset_current(&rdataset, &rdata); if (verbose > 2) logkey(&rdata); if (both) { - emitds(DNS_DSDIGEST_SHA1, &rdata); - emitds(DNS_DSDIGEST_SHA256, &rdata); + emit(DNS_DSDIGEST_SHA1, showall, lookaside, + &rdata); + emit(DNS_DSDIGEST_SHA256, showall, lookaside, + &rdata); } else - emitds(dtype, &rdata); + emit(dtype, showall, lookaside, &rdata); } } else { unsigned char key_buf[DST_KEY_MAXSIZE]; @@ -374,18 +496,14 @@ main(int argc, char **argv) { DST_KEY_MAXSIZE, &rdata); if (both) { - emitds(DNS_DSDIGEST_SHA1, &rdata); - emitds(DNS_DSDIGEST_SHA256, &rdata); + emit(DNS_DSDIGEST_SHA1, showall, lookaside, &rdata); + emit(DNS_DSDIGEST_SHA256, showall, lookaside, &rdata); } else - emitds(dtype, &rdata); + emit(dtype, showall, lookaside, &rdata); } - if (dns_rdataset_isassociated(&keyset)) - dns_rdataset_disassociate(&keyset); - if (node != NULL) - dns_db_detachnode(db, &node); - if (db != NULL) - dns_db_detach(&db); + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); cleanup_logging(&log); dst_lib_destroy(); isc_hash_destroy(); diff --git a/contrib/bind9/bin/dnssec/dnssec-dsfromkey.docbook b/contrib/bind9/bin/dnssec/dnssec-dsfromkey.docbook index c4ea38d68d94..36410d5f35c1 100644 --- a/contrib/bind9/bin/dnssec/dnssec-dsfromkey.docbook +++ b/contrib/bind9/bin/dnssec/dnssec-dsfromkey.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [<!ENTITY mdash "—">]> <!-- - - Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2008-2010 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 @@ -17,10 +17,10 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: dnssec-dsfromkey.docbook,v 1.6 2008-11-07 13:54:11 jreed Exp $ --> +<!-- $Id: dnssec-dsfromkey.docbook,v 1.12 2010-12-23 23:47:08 tbox Exp $ --> <refentry id="man.dnssec-dsfromkey"> <refentryinfo> - <date>November 29, 2008</date> + <date>August 26, 2009</date> </refentryinfo> <refmeta> @@ -37,6 +37,8 @@ <docinfo> <copyright> <year>2008</year> + <year>2009</year> + <year>2010</year> <holder>Internet Systems Consortium, Inc. ("ISC")</holder> </copyright> </docinfo> @@ -48,17 +50,22 @@ <arg><option>-1</option></arg> <arg><option>-2</option></arg> <arg><option>-a <replaceable class="parameter">alg</replaceable></option></arg> + <arg><option>-l <replaceable class="parameter">domain</replaceable></option></arg> <arg choice="req">keyfile</arg> </cmdsynopsis> <cmdsynopsis> <command>dnssec-dsfromkey</command> <arg choice="req">-s</arg> - <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg> <arg><option>-1</option></arg> <arg><option>-2</option></arg> <arg><option>-a <replaceable class="parameter">alg</replaceable></option></arg> + <arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg> + <arg><option>-l <replaceable class="parameter">domain</replaceable></option></arg> + <arg><option>-s</option></arg> <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg> - <arg><option>-d <replaceable class="parameter">dir</replaceable></option></arg> + <arg><option>-f <replaceable class="parameter">file</replaceable></option></arg> + <arg><option>-A</option></arg> + <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg> <arg choice="req">dnsname</arg> </cmdsynopsis> </refsynopsisdiv> @@ -99,17 +106,55 @@ <listitem> <para> Select the digest algorithm. The value of - <option>algorithm</option> must be one of SHA-1 (SHA1) or - SHA-256 (SHA256). These values are case insensitive. + <option>algorithm</option> must be one of SHA-1 (SHA1), + SHA-256 (SHA256) or GOST. These values are case insensitive. </para> </listitem> </varlistentry> <varlistentry> - <term>-v <replaceable class="parameter">level</replaceable></term> + <term>-K <replaceable class="parameter">directory</replaceable></term> <listitem> <para> - Sets the debugging level. + Look for key files (or, in keyset mode, + <filename>keyset-</filename> files) in + <option>directory</option>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-f <replaceable class="parameter">file</replaceable></term> + <listitem> + <para> + Zone file mode: in place of the keyfile name, the argument is + the DNS domain name of a zone master file, which can be read + from <option>file</option>. If the zone name is the same as + <option>file</option>, then it may be omitted. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-A</term> + <listitem> + <para> + Include ZSK's when generating DS records. Without this option, + only keys which have the KSK flag set will be converted to DS + records and printed. Useful only in zone file mode. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-l <replaceable class="parameter">domain</replaceable></term> + <listitem> + <para> + Generate a DLV set instead of a DS set. The specified + <option>domain</option> is appended to the name for each + record in the set. + The DNSSEC Lookaside Validation (DLV) RR is described + in RFC 4431. </para> </listitem> </varlistentry> @@ -119,8 +164,7 @@ <listitem> <para> Keyset mode: in place of the keyfile name, the argument is - the DNS domain name of a keyset file. Following options make sense - only in this mode. + the DNS domain name of a keyset file. </para> </listitem> </varlistentry> @@ -129,23 +173,20 @@ <term>-c <replaceable class="parameter">class</replaceable></term> <listitem> <para> - Specifies the DNS class (default is IN), useful only - in the keyset mode. + Specifies the DNS class (default is IN). Useful only + in keyset or zone file mode. </para> </listitem> </varlistentry> <varlistentry> - <term>-d <replaceable class="parameter">directory</replaceable></term> + <term>-v <replaceable class="parameter">level</replaceable></term> <listitem> <para> - Look for <filename>keyset</filename> files in - <option>directory</option> as the directory, ignored when - not in the keyset mode. + Sets the debugging level. </para> </listitem> </varlistentry> - </variablelist> </refsect1> @@ -197,6 +238,7 @@ </citerefentry>, <citetitle>BIND 9 Administrator Reference Manual</citetitle>, <citetitle>RFC 3658</citetitle>, + <citetitle>RFC 4431</citetitle>. <citetitle>RFC 4509</citetitle>. </para> </refsect1> diff --git a/contrib/bind9/bin/dnssec/dnssec-dsfromkey.html b/contrib/bind9/bin/dnssec/dnssec-dsfromkey.html index 618648118dd6..54cc1ab61ca2 100644 --- a/contrib/bind9/bin/dnssec/dnssec-dsfromkey.html +++ b/contrib/bind9/bin/dnssec/dnssec-dsfromkey.html @@ -1,5 +1,5 @@ <!-- - - Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2008-2010 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 @@ -13,7 +13,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: dnssec-dsfromkey.html,v 1.5.14.1 2010-05-19 02:06:11 tbox Exp $ --> +<!-- $Id: dnssec-dsfromkey.html,v 1.13 2010-12-24 01:14:19 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> @@ -28,18 +28,18 @@ </div> <div class="refsynopsisdiv"> <h2>Synopsis</h2> -<div class="cmdsynopsis"><p><code class="command">dnssec-dsfromkey</code> [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-1</code>] [<code class="option">-2</code>] [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>] {keyfile}</p></div> -<div class="cmdsynopsis"><p><code class="command">dnssec-dsfromkey</code> {-s} [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-1</code>] [<code class="option">-2</code>] [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-d <em class="replaceable"><code>dir</code></em></code>] {dnsname}</p></div> +<div class="cmdsynopsis"><p><code class="command">dnssec-dsfromkey</code> [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-1</code>] [<code class="option">-2</code>] [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>] [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>] {keyfile}</p></div> +<div class="cmdsynopsis"><p><code class="command">dnssec-dsfromkey</code> {-s} [<code class="option">-1</code>] [<code class="option">-2</code>] [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>] [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>] [<code class="option">-s</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-f <em class="replaceable"><code>file</code></em></code>] [<code class="option">-A</code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] {dnsname}</p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543424"></a><h2>DESCRIPTION</h2> +<a name="id2543464"></a><h2>DESCRIPTION</h2> <p><span><strong class="command">dnssec-dsfromkey</strong></span> outputs the Delegation Signer (DS) resource record (RR), as defined in RFC 3658 and RFC 4509, for the given key(s). </p> </div> <div class="refsect1" lang="en"> -<a name="id2543435"></a><h2>OPTIONS</h2> +<a name="id2543476"></a><h2>OPTIONS</h2> <div class="variablelist"><dl> <dt><span class="term">-1</span></dt> <dd><p> @@ -53,34 +53,54 @@ <dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt> <dd><p> Select the digest algorithm. The value of - <code class="option">algorithm</code> must be one of SHA-1 (SHA1) or - SHA-256 (SHA256). These values are case insensitive. + <code class="option">algorithm</code> must be one of SHA-1 (SHA1), + SHA-256 (SHA256) or GOST. These values are case insensitive. </p></dd> -<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt> +<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt> <dd><p> - Sets the debugging level. + Look for key files (or, in keyset mode, + <code class="filename">keyset-</code> files) in + <code class="option">directory</code>. + </p></dd> +<dt><span class="term">-f <em class="replaceable"><code>file</code></em></span></dt> +<dd><p> + Zone file mode: in place of the keyfile name, the argument is + the DNS domain name of a zone master file, which can be read + from <code class="option">file</code>. If the zone name is the same as + <code class="option">file</code>, then it may be omitted. + </p></dd> +<dt><span class="term">-A</span></dt> +<dd><p> + Include ZSK's when generating DS records. Without this option, + only keys which have the KSK flag set will be converted to DS + records and printed. Useful only in zone file mode. + </p></dd> +<dt><span class="term">-l <em class="replaceable"><code>domain</code></em></span></dt> +<dd><p> + Generate a DLV set instead of a DS set. The specified + <code class="option">domain</code> is appended to the name for each + record in the set. + The DNSSEC Lookaside Validation (DLV) RR is described + in RFC 4431. </p></dd> <dt><span class="term">-s</span></dt> <dd><p> Keyset mode: in place of the keyfile name, the argument is - the DNS domain name of a keyset file. Following options make sense - only in this mode. + the DNS domain name of a keyset file. </p></dd> <dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt> <dd><p> - Specifies the DNS class (default is IN), useful only - in the keyset mode. + Specifies the DNS class (default is IN). Useful only + in keyset or zone file mode. </p></dd> -<dt><span class="term">-d <em class="replaceable"><code>directory</code></em></span></dt> +<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt> <dd><p> - Look for <code class="filename">keyset</code> files in - <code class="option">directory</code> as the directory, ignored when - not in the keyset mode. + Sets the debugging level. </p></dd> </dl></div> </div> <div class="refsect1" lang="en"> -<a name="id2543563"></a><h2>EXAMPLE</h2> +<a name="id2543662"></a><h2>EXAMPLE</h2> <p> To build the SHA-256 DS RR from the <strong class="userinput"><code>Kexample.com.+003+26160</code></strong> @@ -95,7 +115,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543593"></a><h2>FILES</h2> +<a name="id2543692"></a><h2>FILES</h2> <p> The keyfile can be designed by the key identification <code class="filename">Knnnn.+aaa+iiiii</code> or the full file name @@ -109,22 +129,23 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543628"></a><h2>CAVEAT</h2> +<a name="id2543728"></a><h2>CAVEAT</h2> <p> A keyfile error can give a "file not found" even if the file exists. </p> </div> <div class="refsect1" lang="en"> -<a name="id2543638"></a><h2>SEE ALSO</h2> +<a name="id2543737"></a><h2>SEE ALSO</h2> <p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>, <span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>, <em class="citetitle">BIND 9 Administrator Reference Manual</em>, <em class="citetitle">RFC 3658</em>, + <em class="citetitle">RFC 4431</em>. <em class="citetitle">RFC 4509</em>. </p> </div> <div class="refsect1" lang="en"> -<a name="id2543674"></a><h2>AUTHOR</h2> +<a name="id2543777"></a><h2>AUTHOR</h2> <p><span class="corpauthor">Internet Systems Consortium</span> </p> </div> diff --git a/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.8 b/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.8 index 45fc0877b725..d8c19f2e527a 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.8 +++ b/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2008, 2010 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2008-2011 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 @@ -12,7 +12,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: dnssec-keyfromlabel.8,v 1.6.14.3 2010-01-16 01:55:32 tbox Exp $ +.\" $Id: dnssec-keyfromlabel.8,v 1.18.14.1.2.1 2011-06-09 03:41:05 tbox Exp $ .\" .hy 0 .ad l @@ -32,18 +32,22 @@ dnssec\-keyfromlabel \- DNSSEC key generation tool .SH "SYNOPSIS" .HP 20 -\fBdnssec\-keyfromlabel\fR {\-a\ \fIalgorithm\fR} {\-l\ \fIlabel\fR} [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-k\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] {name} +\fBdnssec\-keyfromlabel\fR {\-l\ \fIlabel\fR} [\fB\-3\fR] [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-G\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-k\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-y\fR] {name} .SH "DESCRIPTION" .PP \fBdnssec\-keyfromlabel\fR gets keys with the given label from a crypto hardware and builds key files for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. +.PP +The +\fBname\fR +of the key is specified on the command line. This must match the name of the zone for which the key is being generated. .SH "OPTIONS" .PP \-a \fIalgorithm\fR .RS 4 Selects the cryptographic algorithm. The value of \fBalgorithm\fR -must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or DH (Diffie Hellman). These values are case insensitive. +must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. These values are case insensitive. .sp If no algorithm is specified, then RSASHA1 will be used by default, unless the \fB\-3\fR @@ -56,9 +60,19 @@ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA Note 2: DH automatically sets the \-k flag. .RE .PP +\-3 +.RS 4 +Use an NSEC3\-capable algorithm to generate a DNSSEC key. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default. +.RE +.PP +\-E \fIengine\fR +.RS 4 +Specifies the name of the crypto hardware (OpenSSL engine). When compiled with PKCS#11 support it defaults to "pkcs11". +.RE +.PP \-l \fIlabel\fR .RS 4 -Specifies the label of keys in the crypto hardware (PKCS#11 device). +Specifies the label of the key pair in the crypto hardware. The label may be preceded by an optional OpenSSL engine name, separated by a colon, as in "pkcs11:keylabel". .RE .PP \-n \fInametype\fR @@ -68,6 +82,15 @@ Specifies the owner type of the key. The value of must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). These values are case insensitive. .RE .PP +\-C +.RS 4 +Compatibility mode: generates an old\-style key, without any metadata. By default, +\fBdnssec\-keyfromlabel\fR +will include the key's creation date in the metadata stored with the private key, and other dates may be set there as well (publication date, activation date, etc). Keys that include this data may be incompatible with older versions of BIND; the +\fB\-C\fR +option suppresses them. +.RE +.PP \-c \fIclass\fR .RS 4 Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used. @@ -75,13 +98,23 @@ Indicates that the DNS record containing the key should have the specified class .PP \-f \fIflag\fR .RS 4 -Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flag is KSK (Key Signing Key) DNSKEY. +Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flags are KSK (Key Signing Key) and REVOKE. +.RE +.PP +\-G +.RS 4 +Generate a key, but do not publish it or sign with it. This option is incompatible with \-P and \-A. .RE .PP \-h .RS 4 Prints a short summary of the options and arguments to -\fBdnssec\-keygen\fR. +\fBdnssec\-keyfromlabel\fR. +.RE +.PP +\-K \fIdirectory\fR +.RS 4 +Sets the directory in which the key files are to be written. .RE .PP \-k @@ -91,7 +124,7 @@ Generate KEY records rather than DNSKEY records. .PP \-p \fIprotocol\fR .RS 4 -Sets the protocol value for the generated key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. +Sets the protocol value for the key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. .RE .PP \-t \fItype\fR @@ -105,6 +138,39 @@ must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. .RS 4 Sets the debugging level. .RE +.PP +\-y +.RS 4 +Allows DNSSEC key files to be generated even if the key ID would collide with that of an existing key, in the event of either key being revoked. (This is only safe to use if you are sure you won't be using RFC 5011 trust anchor maintenance with either of the keys involved.) +.RE +.SH "TIMING OPTIONS" +.PP +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '\-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24\-hour days, ignoring leap years), months (defined as 30 24\-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. +.PP +\-P \fIdate/offset\fR +.RS 4 +Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it. If not set, and if the \-G option has not been used, the default is "now". +.RE +.PP +\-A \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it. If not set, and if the \-G option has not been used, the default is "now". +.RE +.PP +\-R \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it. +.RE +.PP +\-I \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it. +.RE +.PP +\-D \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.) +.RE .SH "GENERATED KEY FILES" .PP When @@ -138,7 +204,7 @@ file contains a DNS KEY record that can be inserted into a zone file (directly o .PP The \fI.private\fR -file contains algorithm specific fields. For obvious security reasons, this file does not have general read permission. +file contains algorithm\-specific fields. For obvious security reasons, this file does not have general read permission. .SH "SEE ALSO" .PP \fBdnssec\-keygen\fR(8), @@ -149,5 +215,5 @@ RFC 4034. .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2008, 2010 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2008\-2011 Internet Systems Consortium, Inc. ("ISC") .br diff --git a/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.c b/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.c index 8e9a53bb798e..323f9187c64a 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.c +++ b/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2007-2010 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 @@ -14,12 +14,13 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-keyfromlabel.c,v 1.4.50.2 2010-01-15 23:47:31 tbox Exp $ */ +/* $Id: dnssec-keyfromlabel.c,v 1.32 2010-12-23 04:07:59 marka Exp $ */ /*! \file */ #include <config.h> +#include <ctype.h> #include <stdlib.h> #include <isc/buffer.h> @@ -27,9 +28,11 @@ #include <isc/entropy.h> #include <isc/mem.h> #include <isc/region.h> +#include <isc/print.h> #include <isc/string.h> #include <isc/util.h> +#include <dns/dnssec.h> #include <dns/fixedname.h> #include <dns/keyvalues.h> #include <dns/log.h> @@ -47,35 +50,60 @@ const char *program = "dnssec-keyfromlabel"; int verbose; +#define DEFAULT_ALGORITHM "RSASHA1" +#define DEFAULT_NSEC3_ALGORITHM "NSEC3RSASHA1" + static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 |" " NSEC3DSA | NSEC3RSASHA1 |" - " RSASHA256 | RSASHA512"; + " RSASHA256 | RSASHA512 | ECCGOST"; + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s -a alg -l label [options] name\n\n", + fprintf(stderr, " %s -l label [options] name\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "Required options:\n"); - fprintf(stderr, " -a algorithm: %s\n", algs); - fprintf(stderr, " -l label: label of the key\n"); + fprintf(stderr, " -l label: label of the key pair\n"); fprintf(stderr, " name: owner of the key\n"); fprintf(stderr, "Other options:\n"); + fprintf(stderr, " -a algorithm: %s\n", algs); + fprintf(stderr, " (default: RSASHA1, or " + "NSEC3RSASHA1 if using -3)\n"); + fprintf(stderr, " -3: use NSEC3-capable algorithm\n"); + fprintf(stderr, " -c class (default: IN)\n"); +#ifdef USE_PKCS11 + fprintf(stderr, " -E enginename (default: pkcs11)\n"); +#else + fprintf(stderr, " -E enginename\n"); +#endif + fprintf(stderr, " -f keyflag: KSK | REVOKE\n"); + fprintf(stderr, " -K directory: directory in which to place " + "key files\n"); + fprintf(stderr, " -k: generate a TYPE=KEY key\n"); fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n"); fprintf(stderr, " (DNSKEY generation defaults to ZONE\n"); - fprintf(stderr, " -c <class> (default: IN)\n"); - fprintf(stderr, " -f keyflag: KSK\n"); - fprintf(stderr, " -t <type>: " + fprintf(stderr, " -p protocol: default: 3 [dnssec]\n"); + fprintf(stderr, " -t type: " "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " "(default: AUTHCONF)\n"); - fprintf(stderr, " -p <protocol>: " - "default: 3 [dnssec]\n"); - fprintf(stderr, " -v <verbose level>\n"); - fprintf(stderr, " -k : generate a TYPE=KEY key\n"); + fprintf(stderr, " -y: permit keys that might collide\n"); + fprintf(stderr, " -v verbose level\n"); + fprintf(stderr, "Date options:\n"); + fprintf(stderr, " -P date/[+-]offset: set key publication date\n"); + fprintf(stderr, " -A date/[+-]offset: set key activation date\n"); + fprintf(stderr, " -R date/[+-]offset: set key revocation date\n"); + fprintf(stderr, " -I date/[+-]offset: set key inactivation date\n"); + fprintf(stderr, " -D date/[+-]offset: set key deletion date\n"); + fprintf(stderr, " -G: generate key only; do not set -P or -A\n"); + fprintf(stderr, " -C: generate a backward-compatible key, omitting" + " all dates\n"); fprintf(stderr, "Output:\n"); fprintf(stderr, " K<name>+<alg>+<id>.key, " - "K<name>+<alg>+<id>.private\n"); + "K<name>+<alg>+<id>.private\n"); exit (-1); } @@ -83,14 +111,20 @@ usage(void) { int main(int argc, char **argv) { char *algname = NULL, *nametype = NULL, *type = NULL; + const char *directory = NULL; +#ifdef USE_PKCS11 + const char *engine = "pkcs11"; +#else + const char *engine = NULL; +#endif char *classname = NULL; char *endp; - dst_key_t *key = NULL, *oldkey; + dst_key_t *key = NULL; dns_fixedname_t fname; dns_name_t *name; - isc_uint16_t flags = 0, ksk = 0; + isc_uint16_t flags = 0, kskflag = 0, revflag = 0; dns_secalg_t alg; - isc_boolean_t null_key = ISC_FALSE; + isc_boolean_t oldstyle = ISC_FALSE; isc_mem_t *mctx = NULL; int ch; int protocol = -1, signatory = 0; @@ -103,6 +137,20 @@ main(int argc, char **argv) { dns_rdataclass_t rdclass; int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; char *label = NULL; + isc_stdtime_t publish = 0, activate = 0, revoke = 0; + isc_stdtime_t inactive = 0, delete = 0; + isc_stdtime_t now; + isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; + isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE; + isc_boolean_t setdel = ISC_FALSE; + isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE; + isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE; + isc_boolean_t unsetdel = ISC_FALSE; + isc_boolean_t genonly = ISC_FALSE; + isc_boolean_t use_nsec3 = ISC_FALSE; + isc_boolean_t avoid_collisions = ISC_TRUE; + isc_boolean_t exact; + unsigned char c; if (argc == 1) usage(); @@ -113,28 +161,49 @@ main(int argc, char **argv) { isc_commandline_errprint = ISC_FALSE; + isc_stdtime_get(&now); + while ((ch = isc_commandline_parse(argc, argv, - "a:c:f:kl:n:p:t:v:h")) != -1) + "3a:Cc:E:f:K:kl:n:p:t:v:yFhGP:A:R:I:D:")) != -1) { switch (ch) { + case '3': + use_nsec3 = ISC_TRUE; + break; case 'a': algname = isc_commandline_argument; break; + case 'C': + oldstyle = ISC_TRUE; + break; case 'c': classname = isc_commandline_argument; break; + case 'E': + engine = isc_commandline_argument; + break; case 'f': - if (strcasecmp(isc_commandline_argument, "KSK") == 0) - ksk = DNS_KEYFLAG_KSK; + c = (unsigned char)(isc_commandline_argument[0]); + if (toupper(c) == 'K') + kskflag = DNS_KEYFLAG_KSK; + else if (toupper(c) == 'R') + revflag = DNS_KEYFLAG_REVOKE; else fatal("unknown flag '%s'", isc_commandline_argument); break; + case 'K': + directory = isc_commandline_argument; + ret = try_dir(directory); + if (ret != ISC_R_SUCCESS) + fatal("cannot open directory %s: %s", + directory, isc_result_totext(ret)); + break; case 'k': options |= DST_TYPE_KEY; break; case 'l': - label = isc_commandline_argument; + label = isc_mem_strdup(mctx, isc_commandline_argument); break; case 'n': nametype = isc_commandline_argument; @@ -153,11 +222,80 @@ main(int argc, char **argv) { if (*endp != '\0') fatal("-v must be followed by a number"); break; - + case 'y': + avoid_collisions = ISC_FALSE; + break; + case 'G': + genonly = ISC_TRUE; + break; + case 'P': + if (setpub || unsetpub) + fatal("-P specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setpub = ISC_TRUE; + publish = strtotime(isc_commandline_argument, + now, now); + } else { + unsetpub = ISC_TRUE; + } + break; + case 'A': + if (setact || unsetact) + fatal("-A specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setact = ISC_TRUE; + activate = strtotime(isc_commandline_argument, + now, now); + } else { + unsetact = ISC_TRUE; + } + break; + case 'R': + if (setrev || unsetrev) + fatal("-R specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setrev = ISC_TRUE; + revoke = strtotime(isc_commandline_argument, + now, now); + } else { + unsetrev = ISC_TRUE; + } + break; + case 'I': + if (setinact || unsetinact) + fatal("-I specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setinact = ISC_TRUE; + inactive = strtotime(isc_commandline_argument, + now, now); + } else { + unsetinact = ISC_TRUE; + } + break; + case 'D': + if (setdel || unsetdel) + fatal("-D specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setdel = ISC_TRUE; + delete = strtotime(isc_commandline_argument, + now, now); + } else { + unsetdel = ISC_TRUE; + } + break; + case 'F': + /* Reserved for FIPS mode */ + /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); + /* FALLTHROUGH */ case 'h': usage(); @@ -170,10 +308,11 @@ main(int argc, char **argv) { if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); - ret = dst_lib_init(mctx, ectx, - ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); + ret = dst_lib_init2(mctx, ectx, engine, + ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (ret != ISC_R_SUCCESS) - fatal("could not initialize dst"); + fatal("could not initialize dst: %s", + isc_result_totext(ret)); setup_logging(verbose, mctx, &log); @@ -184,8 +323,30 @@ main(int argc, char **argv) { if (argc > isc_commandline_index + 1) fatal("extraneous arguments"); - if (algname == NULL) - fatal("no algorithm was specified"); + if (strchr(label, ':') == NULL && + engine != NULL && strlen(engine) != 0U) { + char *l; + int len; + + len = strlen(label) + strlen(engine) + 2; + l = isc_mem_allocate(mctx, len); + if (l == NULL) + fatal("cannot allocate memory"); + snprintf(l, len, "%s:%s", engine, label); + isc_mem_free(mctx, label); + label = l; + } + + if (algname == NULL) { + if (use_nsec3) + algname = strdup(DEFAULT_NSEC3_ALGORITHM); + else + algname = strdup(DEFAULT_ALGORITHM); + if (verbose > 0) + fprintf(stderr, "no algorithm specified; " + "defaulting to %s\n", algname); + } + if (strcasecmp(algname, "RSA") == 0) { fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n" "If you still wish to use RSA (RSAMD5) please " @@ -201,6 +362,14 @@ main(int argc, char **argv) { options |= DST_TYPE_KEY; } + if (use_nsec3 && + alg != DST_ALG_NSEC3DSA && alg != DST_ALG_NSEC3RSASHA1 && + alg != DST_ALG_RSASHA256 && alg != DST_ALG_RSASHA512 && + alg != DST_ALG_ECCGOST) { + fatal("%s is incompatible with NSEC3; " + "do not use the -3 option", algname); + } + if (type != NULL && (options & DST_TYPE_KEY) != 0) { if (strcasecmp(type, "NOAUTH") == 0) flags |= DNS_KEYTYPE_NOAUTH; @@ -234,10 +403,15 @@ main(int argc, char **argv) { rdclass = strtoclass(classname); + if (directory == NULL) + directory = "."; + if ((options & DST_TYPE_KEY) != 0) /* KEY */ flags |= signatory; - else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */ - flags |= ksk; + else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */ + flags |= kskflag; + flags |= revflag; + } if (protocol == -1) protocol = DNS_KEYPROTO_DNSSEC; @@ -260,53 +434,108 @@ main(int argc, char **argv) { isc_buffer_init(&buf, argv[isc_commandline_index], strlen(argv[isc_commandline_index])); isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); - ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); + ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); if (ret != ISC_R_SUCCESS) fatal("invalid key name %s: %s", argv[isc_commandline_index], isc_result_totext(ret)); - if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) - null_key = ISC_TRUE; - isc_buffer_init(&buf, filename, sizeof(filename) - 1); /* associate the key */ ret = dst_key_fromlabel(name, alg, flags, protocol, - rdclass, "", label, NULL, mctx, &key); + rdclass, engine, label, NULL, mctx, &key); isc_entropy_stopcallbacksources(ectx); if (ret != ISC_R_SUCCESS) { char namestr[DNS_NAME_FORMATSIZE]; - char algstr[ALG_FORMATSIZE]; + char algstr[DNS_SECALG_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); - alg_format(alg, algstr, sizeof(algstr)); - fatal("failed to generate key %s/%s: %s\n", + dns_secalg_format(alg, algstr, sizeof(algstr)); + fatal("failed to get key %s/%s: %s\n", namestr, algstr, isc_result_totext(ret)); + /* NOTREACHED */ exit(-1); } /* - * Try to read a key with the same name, alg and id from disk. - * If there is one we must continue generating a new one - * unless we were asked to generate a null key, in which - * case we return failure. + * Set key timing metadata (unless using -C) + * + * Publish and activation dates are set to "now" by default, but + * can be overridden. Creation date is always set to "now". */ - ret = dst_key_fromfile(name, dst_key_id(key), alg, - DST_TYPE_PRIVATE, NULL, mctx, &oldkey); - /* do not overwrite an existing key */ - if (ret == ISC_R_SUCCESS) { + if (!oldstyle) { + dst_key_settime(key, DST_TIME_CREATED, now); + + if (genonly && (setpub || setact)) + fatal("cannot use -G together with -P or -A options"); + + if (setpub) + dst_key_settime(key, DST_TIME_PUBLISH, publish); + else if (setact) + dst_key_settime(key, DST_TIME_PUBLISH, activate); + else if (!genonly && !unsetpub) + dst_key_settime(key, DST_TIME_PUBLISH, now); + + if (setact) + dst_key_settime(key, DST_TIME_ACTIVATE, activate); + else if (!genonly && !unsetact) + dst_key_settime(key, DST_TIME_ACTIVATE, now); + + if (setrev) { + if (kskflag == 0) + fprintf(stderr, "%s: warning: Key is " + "not flagged as a KSK, but -R " + "was used. Revoking a ZSK is " + "legal, but undefined.\n", + program); + dst_key_settime(key, DST_TIME_REVOKE, revoke); + } + + if (setinact) + dst_key_settime(key, DST_TIME_INACTIVE, inactive); + + if (setdel) + dst_key_settime(key, DST_TIME_DELETE, delete); + } else { + if (setpub || setact || setrev || setinact || + setdel || unsetpub || unsetact || + unsetrev || unsetinact || unsetdel || genonly) + fatal("cannot use -C together with " + "-P, -A, -R, -I, -D, or -G options"); + /* + * Compatibility mode: Private-key-format + * should be set to 1.2. + */ + dst_key_setprivateformat(key, 1, 2); + } + + /* + * Do not overwrite an existing key. Warn LOUDLY if there + * is a risk of ID collision due to this key or another key + * being revoked. + */ + if (key_collision(dst_key_id(key), name, directory, alg, mctx, &exact)) + { isc_buffer_clear(&buf); - ret = dst_key_buildfilename(key, 0, NULL, &buf); - fprintf(stderr, "%s: %s already exists\n", - program, filename); - dst_key_free(&key); - exit (1); + ret = dst_key_buildfilename(key, 0, directory, &buf); + if (exact) + fatal("%s: %s already exists\n", program, filename); + + if (avoid_collisions) + fatal("%s: %s could collide with another key upon " + "revokation\n", program, filename); + + fprintf(stderr, "%s: WARNING: Key %s could collide with " + "another key upon revokation. If you plan " + "to revoke keys, destroy this key and " + "generate a different one.\n", + program, filename); } - ret = dst_key_tofile(key, options, NULL); + ret = dst_key_tofile(key, options, directory); if (ret != ISC_R_SUCCESS) { - char keystr[KEY_FORMATSIZE]; - key_format(key, keystr, sizeof(keystr)); + char keystr[DST_KEY_FORMATSIZE]; + dst_key_format(key, keystr, sizeof(keystr)); fatal("failed to write key %s: %s\n", keystr, isc_result_totext(ret)); } @@ -322,6 +551,7 @@ main(int argc, char **argv) { dns_name_destroy(); if (verbose > 10) isc_mem_stats(mctx, stdout); + isc_mem_free(mctx, label); isc_mem_destroy(&mctx); return (0); diff --git a/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.docbook b/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.docbook index a2fff5a0d4b5..be38a2465785 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.docbook +++ b/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [<!ENTITY mdash "—">]> <!-- - - Copyright (C) 2008, 2010 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2008-2011 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 @@ -17,7 +17,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: dnssec-keyfromlabel.docbook,v 1.6.14.2 2010-01-15 23:47:31 tbox Exp $ --> +<!-- $Id: dnssec-keyfromlabel.docbook,v 1.18.14.1.2.1 2011-06-02 23:47:27 tbox Exp $ --> <refentry id="man.dnssec-keyfromlabel"> <refentryinfo> <date>February 8, 2008</date> @@ -37,7 +37,9 @@ <docinfo> <copyright> <year>2008</year> + <year>2009</year> <year>2010</year> + <year>2011</year> <holder>Internet Systems Consortium, Inc. ("ISC")</holder> </copyright> </docinfo> @@ -45,15 +47,25 @@ <refsynopsisdiv> <cmdsynopsis> <command>dnssec-keyfromlabel</command> - <arg choice="req">-a <replaceable class="parameter">algorithm</replaceable></arg> <arg choice="req">-l <replaceable class="parameter">label</replaceable></arg> + <arg><option>-3</option></arg> + <arg><option>-a <replaceable class="parameter">algorithm</replaceable></option></arg> + <arg><option>-A <replaceable class="parameter">date/offset</replaceable></option></arg> <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg> + <arg><option>-D <replaceable class="parameter">date/offset</replaceable></option></arg> + <arg><option>-E <replaceable class="parameter">engine</replaceable></option></arg> <arg><option>-f <replaceable class="parameter">flag</replaceable></option></arg> + <arg><option>-G</option></arg> + <arg><option>-I <replaceable class="parameter">date/offset</replaceable></option></arg> <arg><option>-k</option></arg> + <arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg> <arg><option>-n <replaceable class="parameter">nametype</replaceable></option></arg> + <arg><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg> <arg><option>-p <replaceable class="parameter">protocol</replaceable></option></arg> + <arg><option>-R <replaceable class="parameter">date/offset</replaceable></option></arg> <arg><option>-t <replaceable class="parameter">type</replaceable></option></arg> <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg> + <arg><option>-y</option></arg> <arg choice="req">name</arg> </cmdsynopsis> </refsynopsisdiv> @@ -65,6 +77,11 @@ key files for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. </para> + <para> + The <option>name</option> of the key is specified on the command + line. This must match the name of the zone for which the key is + being generated. + </para> </refsect1> <refsect1> @@ -76,9 +93,8 @@ <listitem> <para> Selects the cryptographic algorithm. The value of - <option>algorithm</option> must be one of RSAMD5, - RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, - RSASHA512 or DH (Diffie Hellman). + <option>algorithm</option> must be one of RSAMD5, RSASHA1, + DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. These values are case insensitive. </para> <para> @@ -99,11 +115,34 @@ </varlistentry> <varlistentry> + <term>-3</term> + <listitem> + <para> + Use an NSEC3-capable algorithm to generate a DNSSEC key. + If this option is used and no algorithm is explicitly + set on the command line, NSEC3RSASHA1 will be used by + default. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-E <replaceable class="parameter">engine</replaceable></term> + <listitem> + <para> + Specifies the name of the crypto hardware (OpenSSL engine). + When compiled with PKCS#11 support it defaults to "pkcs11". + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-l <replaceable class="parameter">label</replaceable></term> <listitem> <para> - Specifies the label of keys in the crypto hardware - (PKCS#11 device). + Specifies the label of the key pair in the crypto hardware. + The label may be preceded by an optional OpenSSL engine name, + separated by a colon, as in "pkcs11:keylabel". </para> </listitem> </varlistentry> @@ -117,8 +156,22 @@ zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). - These values are - case insensitive. + These values are case insensitive. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-C</term> + <listitem> + <para> + Compatibility mode: generates an old-style key, without + any metadata. By default, <command>dnssec-keyfromlabel</command> + will include the key's creation date in the metadata stored + with the private key, and other dates may be set there as well + (publication date, activation date, etc). Keys that include + this data may be incompatible with older versions of BIND; the + <option>-C</option> option suppresses them. </para> </listitem> </varlistentry> @@ -138,7 +191,17 @@ <listitem> <para> Set the specified flag in the flag field of the KEY/DNSKEY record. - The only recognized flag is KSK (Key Signing Key) DNSKEY. + The only recognized flags are KSK (Key Signing Key) and REVOKE. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-G</term> + <listitem> + <para> + Generate a key, but do not publish it or sign with it. This + option is incompatible with -P and -A. </para> </listitem> </varlistentry> @@ -148,7 +211,16 @@ <listitem> <para> Prints a short summary of the options and arguments to - <command>dnssec-keygen</command>. + <command>dnssec-keyfromlabel</command>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-K <replaceable class="parameter">directory</replaceable></term> + <listitem> + <para> + Sets the directory in which the key files are to be written. </para> </listitem> </varlistentry> @@ -166,7 +238,7 @@ <term>-p <replaceable class="parameter">protocol</replaceable></term> <listitem> <para> - Sets the protocol value for the generated key. The protocol + Sets the protocol value for the key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. @@ -195,6 +267,93 @@ </listitem> </varlistentry> + <varlistentry> + <term>-y</term> + <listitem> + <para> + Allows DNSSEC key files to be generated even if the key ID + would collide with that of an existing key, in the event of + either key being revoked. (This is only safe to use if you + are sure you won't be using RFC 5011 trust anchor maintenance + with either of the keys involved.) + </para> + </listitem> + </varlistentry> + + </variablelist> + </refsect1> + + <refsect1> + <title>TIMING OPTIONS</title> + + <para> + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. + </para> + + <variablelist> + <varlistentry> + <term>-P <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. If not set, and if the -G option has + not been used, the default is "now". + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-A <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. If not set, and if the -G option has not been used, the + default is "now". + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-R <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-I <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-D <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) + </para> + </listitem> + </varlistentry> </variablelist> </refsect1> @@ -214,8 +373,7 @@ </listitem> <listitem> <para><filename>aaa</filename> is the numeric representation - of the - algorithm. + of the algorithm. </para> </listitem> <listitem> @@ -229,8 +387,7 @@ on the printed string. <filename>Knnnn.+aaa+iiiii.key</filename> contains the public key, and <filename>Knnnn.+aaa+iiiii.private</filename> contains the - private - key. + private key. </para> <para> The <filename>.key</filename> file contains a DNS KEY record @@ -239,8 +396,8 @@ statement). </para> <para> - The <filename>.private</filename> file contains algorithm - specific + The <filename>.private</filename> file contains + algorithm-specific fields. For obvious security reasons, this file does not have general read permission. </para> diff --git a/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.html b/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.html index ad2a5621ba99..2b1b23690bb1 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.html +++ b/contrib/bind9/bin/dnssec/dnssec-keyfromlabel.html @@ -1,5 +1,5 @@ <!-- - - Copyright (C) 2008, 2010 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2008-2011 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 @@ -13,7 +13,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: dnssec-keyfromlabel.html,v 1.5.44.3 2010-01-16 01:55:32 tbox Exp $ --> +<!-- $Id: dnssec-keyfromlabel.html,v 1.17.14.1.2.1 2011-06-09 03:41:05 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> @@ -28,26 +28,30 @@ </div> <div class="refsynopsisdiv"> <h2>Synopsis</h2> -<div class="cmdsynopsis"><p><code class="command">dnssec-keyfromlabel</code> {-a <em class="replaceable"><code>algorithm</code></em>} {-l <em class="replaceable"><code>label</code></em>} [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-f <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-k</code>] [<code class="option">-n <em class="replaceable"><code>nametype</code></em></code>] [<code class="option">-p <em class="replaceable"><code>protocol</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] {name}</p></div> +<div class="cmdsynopsis"><p><code class="command">dnssec-keyfromlabel</code> {-l <em class="replaceable"><code>label</code></em>} [<code class="option">-3</code>] [<code class="option">-a <em class="replaceable"><code>algorithm</code></em></code>] [<code class="option">-A <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-D <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-E <em class="replaceable"><code>engine</code></em></code>] [<code class="option">-f <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-G</code>] [<code class="option">-I <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-k</code>] [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-n <em class="replaceable"><code>nametype</code></em></code>] [<code class="option">-P <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-p <em class="replaceable"><code>protocol</code></em></code>] [<code class="option">-R <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-y</code>] {name}</p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543416"></a><h2>DESCRIPTION</h2> +<a name="id2543494"></a><h2>DESCRIPTION</h2> <p><span><strong class="command">dnssec-keyfromlabel</strong></span> gets keys with the given label from a crypto hardware and builds key files for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. </p> +<p> + The <code class="option">name</code> of the key is specified on the command + line. This must match the name of the zone for which the key is + being generated. + </p> </div> <div class="refsect1" lang="en"> -<a name="id2543428"></a><h2>OPTIONS</h2> +<a name="id2543512"></a><h2>OPTIONS</h2> <div class="variablelist"><dl> <dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt> <dd> <p> Selects the cryptographic algorithm. The value of - <code class="option">algorithm</code> must be one of RSAMD5, - RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, - RSASHA512 or DH (Diffie Hellman). + <code class="option">algorithm</code> must be one of RSAMD5, RSASHA1, + DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. These values are case insensitive. </p> <p> @@ -65,10 +69,23 @@ Note 2: DH automatically sets the -k flag. </p> </dd> +<dt><span class="term">-3</span></dt> +<dd><p> + Use an NSEC3-capable algorithm to generate a DNSSEC key. + If this option is used and no algorithm is explicitly + set on the command line, NSEC3RSASHA1 will be used by + default. + </p></dd> +<dt><span class="term">-E <em class="replaceable"><code>engine</code></em></span></dt> +<dd><p> + Specifies the name of the crypto hardware (OpenSSL engine). + When compiled with PKCS#11 support it defaults to "pkcs11". + </p></dd> <dt><span class="term">-l <em class="replaceable"><code>label</code></em></span></dt> <dd><p> - Specifies the label of keys in the crypto hardware - (PKCS#11 device). + Specifies the label of the key pair in the crypto hardware. + The label may be preceded by an optional OpenSSL engine name, + separated by a colon, as in "pkcs11:keylabel". </p></dd> <dt><span class="term">-n <em class="replaceable"><code>nametype</code></em></span></dt> <dd><p> @@ -77,8 +94,17 @@ zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). - These values are - case insensitive. + These values are case insensitive. + </p></dd> +<dt><span class="term">-C</span></dt> +<dd><p> + Compatibility mode: generates an old-style key, without + any metadata. By default, <span><strong class="command">dnssec-keyfromlabel</strong></span> + will include the key's creation date in the metadata stored + with the private key, and other dates may be set there as well + (publication date, activation date, etc). Keys that include + this data may be incompatible with older versions of BIND; the + <code class="option">-C</code> option suppresses them. </p></dd> <dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt> <dd><p> @@ -88,12 +114,21 @@ <dt><span class="term">-f <em class="replaceable"><code>flag</code></em></span></dt> <dd><p> Set the specified flag in the flag field of the KEY/DNSKEY record. - The only recognized flag is KSK (Key Signing Key) DNSKEY. + The only recognized flags are KSK (Key Signing Key) and REVOKE. + </p></dd> +<dt><span class="term">-G</span></dt> +<dd><p> + Generate a key, but do not publish it or sign with it. This + option is incompatible with -P and -A. </p></dd> <dt><span class="term">-h</span></dt> <dd><p> Prints a short summary of the options and arguments to - <span><strong class="command">dnssec-keygen</strong></span>. + <span><strong class="command">dnssec-keyfromlabel</strong></span>. + </p></dd> +<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt> +<dd><p> + Sets the directory in which the key files are to be written. </p></dd> <dt><span class="term">-k</span></dt> <dd><p> @@ -101,7 +136,7 @@ </p></dd> <dt><span class="term">-p <em class="replaceable"><code>protocol</code></em></span></dt> <dd><p> - Sets the protocol value for the generated key. The protocol + Sets the protocol value for the key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. @@ -117,10 +152,65 @@ <dd><p> Sets the debugging level. </p></dd> +<dt><span class="term">-y</span></dt> +<dd><p> + Allows DNSSEC key files to be generated even if the key ID + would collide with that of an existing key, in the event of + either key being revoked. (This is only safe to use if you + are sure you won't be using RFC 5011 trust anchor maintenance + with either of the keys involved.) + </p></dd> +</dl></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543876"></a><h2>TIMING OPTIONS</h2> +<p> + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. + </p> +<div class="variablelist"><dl> +<dt><span class="term">-P <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. If not set, and if the -G option has + not been used, the default is "now". + </p></dd> +<dt><span class="term">-A <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. If not set, and if the -G option has not been used, the + default is "now". + </p></dd> +<dt><span class="term">-R <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. + </p></dd> +<dt><span class="term">-I <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. + </p></dd> +<dt><span class="term">-D <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) + </p></dd> </dl></div> </div> <div class="refsect1" lang="en"> -<a name="id2543632"></a><h2>GENERATED KEY FILES</h2> +<a name="id2544042"></a><h2>GENERATED KEY FILES</h2> <p> When <span><strong class="command">dnssec-keyfromlabel</strong></span> completes successfully, @@ -132,8 +222,7 @@ <li><p><code class="filename">nnnn</code> is the key name. </p></li> <li><p><code class="filename">aaa</code> is the numeric representation - of the - algorithm. + of the algorithm. </p></li> <li><p><code class="filename">iiiii</code> is the key identifier (or footprint). @@ -144,8 +233,7 @@ on the printed string. <code class="filename">Knnnn.+aaa+iiiii.key</code> contains the public key, and <code class="filename">Knnnn.+aaa+iiiii.private</code> contains the - private - key. + private key. </p> <p> The <code class="filename">.key</code> file contains a DNS KEY record @@ -154,14 +242,14 @@ statement). </p> <p> - The <code class="filename">.private</code> file contains algorithm - specific + The <code class="filename">.private</code> file contains + algorithm-specific fields. For obvious security reasons, this file does not have general read permission. </p> </div> <div class="refsect1" lang="en"> -<a name="id2543704"></a><h2>SEE ALSO</h2> +<a name="id2544115"></a><h2>SEE ALSO</h2> <p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>, <span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>, <em class="citetitle">BIND 9 Administrator Reference Manual</em>, @@ -169,7 +257,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543737"></a><h2>AUTHOR</h2> +<a name="id2544148"></a><h2>AUTHOR</h2> <p><span class="corpauthor">Internet Systems Consortium</span> </p> </div> diff --git a/contrib/bind9/bin/dnssec/dnssec-keygen.8 b/contrib/bind9/bin/dnssec/dnssec-keygen.8 index c4be24eba0cf..ea4690eb71a1 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keygen.8 +++ b/contrib/bind9/bin/dnssec/dnssec-keygen.8 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: dnssec-keygen.8,v 1.40.44.4 2010-01-16 01:55:32 tbox Exp $ +.\" $Id: dnssec-keygen.8,v 1.55 2010-12-24 01:14:19 tbox Exp $ .\" .hy 0 .ad l @@ -33,11 +33,11 @@ dnssec\-keygen \- DNSSEC key generation tool .SH "SYNOPSIS" .HP 14 -\fBdnssec\-keygen\fR {\-a\ \fIalgorithm\fR} {\-b\ \fIkeysize\fR} {\-n\ \fInametype\fR} [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-e\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-g\ \fR\fB\fIgenerator\fR\fR] [\fB\-h\fR] [\fB\-k\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-s\ \fR\fB\fIstrength\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] {name} +\fBdnssec\-keygen\fR [\fB\-a\ \fR\fB\fIalgorithm\fR\fR] [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-n\ \fR\fB\fInametype\fR\fR] [\fB\-3\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-C\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-e\fR] [\fB\-f\ \fR\fB\fIflag\fR\fR] [\fB\-G\fR] [\fB\-g\ \fR\fB\fIgenerator\fR\fR] [\fB\-h\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-k\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-p\ \fR\fB\fIprotocol\fR\fR] [\fB\-q\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-S\ \fR\fB\fIkey\fR\fR] [\fB\-s\ \fR\fB\fIstrength\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-z\fR] {name} .SH "DESCRIPTION" .PP \fBdnssec\-keygen\fR -generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with TSIG (Transaction Signatures), as defined in RFC 2845. +generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with TSIG (Transaction Signatures) as defined in RFC 2845, or TKEY (Transaction Key) as defined in RFC 2930. .PP The \fBname\fR @@ -48,16 +48,28 @@ of the key is specified on the command line. For DNSSEC keys, this must match th .RS 4 Selects the cryptographic algorithm. For DNSSEC keys, the value of \fBalgorithm\fR -must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256 or RSASHA512. For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC\-MD5, HMAC\-SHA1, HMAC\-SHA224, HMAC\-SHA256, HMAC\-SHA384, or HMAC\-SHA512. These values are case insensitive. +must be one of RSAMD5, RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC\-MD5, HMAC\-SHA1, HMAC\-SHA224, HMAC\-SHA256, HMAC\-SHA384, or HMAC\-SHA512. These values are case insensitive. +.sp +If no algorithm is specified, then RSASHA1 will be used by default, unless the +\fB\-3\fR +option is specified, in which case NSEC3RSASHA1 will be used instead. (If +\fB\-3\fR +is used and an algorithm is specified, that algorithm will be checked for compatibility with NSEC3.) .sp Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended. For TSIG, HMAC\-MD5 is mandatory. .sp -Note 2: HMAC\-MD5 and DH automatically set the \-k flag. +Note 2: DH, HMAC\-MD5, and HMAC\-SHA1 through HMAC\-SHA512 automatically set the \-T KEY option. .RE .PP \-b \fIkeysize\fR .RS 4 Specifies the number of bits in the key. The choice of key size depends on the algorithm used. RSA keys must be between 512 and 2048 bits. Diffie Hellman keys must be between 128 and 4096 bits. DSA keys must be between 512 and 1024 bits and an exact multiple of 64. HMAC keys must be between 1 and 512 bits. +.sp +The key size does not need to be specified if using a default algorithm. The default key size is 1024 bits for zone signing keys (ZSK's) and 2048 bits for key signing keys (KSK's, generated with +\fB\-f KSK\fR). However, if an algorithm is explicitly specified with the +\fB\-a\fR, then there is no default key size, and the +\fB\-b\fR +must be used. .RE .PP \-n \fInametype\fR @@ -67,11 +79,30 @@ Specifies the owner type of the key. The value of must either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with a host (KEY)), USER (for a key associated with a user(KEY)) or OTHER (DNSKEY). These values are case insensitive. Defaults to ZONE for DNSKEY generation. .RE .PP +\-3 +.RS 4 +Use an NSEC3\-capable algorithm to generate a DNSSEC key. If this option is used and no algorithm is explicitly set on the command line, NSEC3RSASHA1 will be used by default. Note that RSASHA256, RSASHA512 and ECCGOST algorithms are NSEC3\-capable. +.RE +.PP +\-C +.RS 4 +Compatibility mode: generates an old\-style key, without any metadata. By default, +\fBdnssec\-keygen\fR +will include the key's creation date in the metadata stored with the private key, and other dates may be set there as well (publication date, activation date, etc). Keys that include this data may be incompatible with older versions of BIND; the +\fB\-C\fR +option suppresses them. +.RE +.PP \-c \fIclass\fR .RS 4 Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used. .RE .PP +\-E \fIengine\fR +.RS 4 +Uses a crypto hardware (OpenSSL engine) for random number and, when supported, key generation. When compiled with PKCS#11 support it defaults to pkcs11; the empty name resets it to no engine. +.RE +.PP \-e .RS 4 If generating an RSAMD5/RSASHA1 key, use a large exponent. @@ -79,7 +110,12 @@ If generating an RSAMD5/RSASHA1 key, use a large exponent. .PP \-f \fIflag\fR .RS 4 -Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flag is KSK (Key Signing Key) DNSKEY. +Set the specified flag in the flag field of the KEY/DNSKEY record. The only recognized flags are KSK (Key Signing Key) and REVOKE. +.RE +.PP +\-G +.RS 4 +Generate a key, but do not publish it or sign with it. This option is incompatible with \-P and \-A. .RE .PP \-g \fIgenerator\fR @@ -93,9 +129,14 @@ Prints a short summary of the options and arguments to \fBdnssec\-keygen\fR. .RE .PP +\-K \fIdirectory\fR +.RS 4 +Sets the directory in which the key files are to be written. +.RE +.PP \-k .RS 4 -Generate KEY records rather than DNSKEY records. +Deprecated in favor of \-T KEY. .RE .PP \-p \fIprotocol\fR @@ -103,6 +144,15 @@ Generate KEY records rather than DNSKEY records. Sets the protocol value for the generated key. The protocol is a number between 0 and 255. The default is 3 (DNSSEC). Other possible values for this argument are listed in RFC 2535 and its successors. .RE .PP +\-q +.RS 4 +Quiet mode: Suppresses unnecessary output, including progress indication. Without this option, when +\fBdnssec\-keygen\fR +is run interactively to generate an RSA or DSA key pair, it will print a string of symbols to +\fIstderr\fR +indicating the progress of the key generation. A '.' indicates that a random number has been found which passed an initial sieve test; '+' means a number has passed a single round of the Miller\-Rabin primality test; a space means that the number has passed all the tests and is a satisfactory key. +.RE +.PP \-r \fIrandomdev\fR .RS 4 Specifies the source of randomness. If the operating system does not provide a @@ -114,11 +164,24 @@ specifies the name of a character device or file containing random data to be us indicates that keyboard input should be used. .RE .PP +\-S \fIkey\fR +.RS 4 +Create a new key which is an explicit successor to an existing key. The name, algorithm, size, and type of the key will be set to match the existing key. The activation date of the new key will be set to the inactivation date of the existing one. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days. +.RE +.PP \-s \fIstrength\fR .RS 4 Specifies the strength value of the key. The strength is a number between 0 and 15, and currently has no defined purpose in DNSSEC. .RE .PP +\-T \fIrrtype\fR +.RS 4 +Specifies the resource record type to use for the key. +\fBrrtype\fR +must be either DNSKEY or KEY. The default is DNSKEY when using a DNSSEC algorithm, but it can be overridden to KEY for use with SIG(0). +Using any TSIG algorithm (HMAC\-* or DH) forces this option to KEY. +.RE +.PP \-t \fItype\fR .RS 4 Indicates the use of the key. @@ -130,6 +193,43 @@ must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. .RS 4 Sets the debugging level. .RE +.SH "TIMING OPTIONS" +.PP +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '\-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24\-hour days, ignoring leap years), months (defined as 30 24\-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. +.PP +\-P \fIdate/offset\fR +.RS 4 +Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it. If not set, and if the \-G option has not been used, the default is "now". +.RE +.PP +\-A \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it. If not set, and if the \-G option has not been used, the default is "now". +.RE +.PP +\-R \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it. +.RE +.PP +\-I \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it. +.RE +.PP +\-D \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.) +.RE +.PP +\-i \fIinterval\fR +.RS 4 +Sets the prepublication interval for a key. If set, then the publication and activation dates must be separated by at least this much time. If the activation date is specified but the publication date isn't, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn't, then activation will be set to this much time after publication. +.sp +If the key is being created as an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero. +.sp +As with date offsets, if the argument is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the interval is measured in years, months, weeks, days, hours, or minutes, respectively. Without a suffix, the interval is measured in seconds. +.RE .SH "GENERATED KEYS" .PP When diff --git a/contrib/bind9/bin/dnssec/dnssec-keygen.c b/contrib/bind9/bin/dnssec/dnssec-keygen.c index 21841227d439..f369326aaf82 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keygen.c +++ b/contrib/bind9/bin/dnssec/dnssec-keygen.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -29,13 +29,15 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-keygen.c,v 1.81.48.2 2010-01-15 23:47:31 tbox Exp $ */ +/* $Id: dnssec-keygen.c,v 1.115 2010-12-23 04:07:59 marka Exp $ */ /*! \file */ #include <config.h> +#include <ctype.h> #include <stdlib.h> +#include <unistd.h> #include <isc/buffer.h> #include <isc/commandline.h> @@ -45,6 +47,7 @@ #include <isc/string.h> #include <isc/util.h> +#include <dns/dnssec.h> #include <dns/fixedname.h> #include <dns/keyvalues.h> #include <dns/log.h> @@ -62,103 +65,224 @@ const char *program = "dnssec-keygen"; int verbose; -static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 | RSASHA256 |" - " RSASHA512 | NSEC3DSA | NSEC3RSASHA1 | HMAC-MD5 |" - " HMAC-SHA1 | HMAC-SHA224 | HMAC-SHA256 |" - " HMAC-SHA384 | HMAC-SHA512"; +#define DEFAULT_ALGORITHM "RSASHA1" +#define DEFAULT_NSEC3_ALGORITHM "NSEC3RSASHA1" -static isc_boolean_t -dsa_size_ok(int size) { - return (ISC_TF(size >= 512 && size <= 1024 && size % 64 == 0)); -} +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void progress(int p); static void usage(void) { fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s -a alg -b bits [-n type] [options] name\n\n", - program); + fprintf(stderr, " %s [options] name\n\n", program); fprintf(stderr, "Version: %s\n", VERSION); - fprintf(stderr, "Required options:\n"); - fprintf(stderr, " -a algorithm: %s\n", algs); - fprintf(stderr, " -b key size, in bits:\n"); - fprintf(stderr, " RSAMD5:\t\t[512..%d]\n", MAX_RSA); - fprintf(stderr, " RSASHA1:\t\t[512..%d]\n", MAX_RSA); - fprintf(stderr, " NSEC3RSASHA1:\t\t[512..%d]\n", MAX_RSA); - fprintf(stderr, " RSASHA256:\t[512..%d]\n", MAX_RSA); - fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA); + fprintf(stderr, " name: owner of the key\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -K <directory>: write keys into directory\n"); + fprintf(stderr, " -a <algorithm>:\n"); + fprintf(stderr, " RSA | RSAMD5 | DSA | RSASHA1 | NSEC3RSASHA1" + " | NSEC3DSA |\n"); + fprintf(stderr, " RSASHA256 | RSASHA512 | ECCGOST |\n"); + fprintf(stderr, " DH | HMAC-MD5 | HMAC-SHA1 | HMAC-SHA224 | " + "HMAC-SHA256 | \n"); + fprintf(stderr, " HMAC-SHA384 | HMAC-SHA512\n"); + fprintf(stderr, " (default: RSASHA1, or " + "NSEC3RSASHA1 if using -3)\n"); + fprintf(stderr, " -3: use NSEC3-capable algorithm\n"); + fprintf(stderr, " -b <key size in bits>:\n"); + fprintf(stderr, " RSAMD5:\t[512..%d]\n", MAX_RSA); + fprintf(stderr, " RSASHA1:\t[512..%d]\n", MAX_RSA); + fprintf(stderr, " NSEC3RSASHA1:\t[512..%d]\n", MAX_RSA); + fprintf(stderr, " RSASHA256:\t[512..%d]\n", MAX_RSA); + fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA); fprintf(stderr, " DH:\t\t[128..4096]\n"); fprintf(stderr, " DSA:\t\t[512..1024] and divisible by 64\n"); - fprintf(stderr, " NSEC3DSA:\t\t[512..1024] and divisible by 64\n"); + fprintf(stderr, " NSEC3DSA:\t[512..1024] and divisible " + "by 64\n"); + fprintf(stderr, " ECCGOST:\tignored\n"); fprintf(stderr, " HMAC-MD5:\t[1..512]\n"); fprintf(stderr, " HMAC-SHA1:\t[1..160]\n"); fprintf(stderr, " HMAC-SHA224:\t[1..224]\n"); fprintf(stderr, " HMAC-SHA256:\t[1..256]\n"); fprintf(stderr, " HMAC-SHA384:\t[1..384]\n"); fprintf(stderr, " HMAC-SHA512:\t[1..512]\n"); - fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n"); - fprintf(stderr, " (DNSKEY generation defaults to ZONE\n"); - fprintf(stderr, " name: owner of the key\n"); - fprintf(stderr, "Other options:\n"); - fprintf(stderr, " -c <class> (default: IN)\n"); + fprintf(stderr, " (if using the default algorithm, key size\n" + " defaults to 2048 for KSK, or 1024 for all " + "others)\n"); + fprintf(stderr, " -n <nametype>: ZONE | HOST | ENTITY | " + "USER | OTHER\n"); + fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n"); + fprintf(stderr, " -c <class>: (default: IN)\n"); fprintf(stderr, " -d <digest bits> (0 => max, default)\n"); - fprintf(stderr, " -e use large exponent (RSAMD5/RSASHA1 only)\n"); - fprintf(stderr, " -f keyflag: KSK\n"); - fprintf(stderr, " -g <generator> use specified generator " - "(DH only)\n"); +#ifdef USE_PKCS11 + fprintf(stderr, " -E <engine name> (default \"pkcs11\")\n"); +#else + fprintf(stderr, " -E <engine name>\n"); +#endif + fprintf(stderr, " -e: use large exponent (RSAMD5/RSASHA1 only)\n"); + fprintf(stderr, " -f <keyflag>: KSK | REVOKE\n"); + fprintf(stderr, " -g <generator>: use specified generator " + "(DH only)\n"); + fprintf(stderr, " -p <protocol>: (default: 3 [dnssec])\n"); + fprintf(stderr, " -s <strength>: strength value this key signs DNS " + "records with (default: 0)\n"); + fprintf(stderr, " -T <rrtype>: DNSKEY | KEY (default: DNSKEY; " + "use KEY for SIG(0))\n"); + fprintf(stderr, " ECCGOST:\tignored\n"); fprintf(stderr, " -t <type>: " - "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " - "(default: AUTHCONF)\n"); - fprintf(stderr, " -p <protocol>: " - "default: 3 [dnssec]\n"); - fprintf(stderr, " -s <strength> strength value this key signs DNS " - "records with (default: 0)\n"); + "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " + "(default: AUTHCONF)\n"); fprintf(stderr, " -r <randomdev>: a file containing random data\n"); - fprintf(stderr, " -v <verbose level>\n"); - fprintf(stderr, " -k : generate a TYPE=KEY key\n"); + + fprintf(stderr, " -h: print usage and exit\n"); + fprintf(stderr, " -m <memory debugging mode>:\n"); + fprintf(stderr, " usage | trace | record | size | mctx\n"); + fprintf(stderr, " -v <level>: set verbosity level (0 - 10)\n"); + fprintf(stderr, "Timing options:\n"); + fprintf(stderr, " -P date/[+-]offset/none: set key publication date " + "(default: now)\n"); + fprintf(stderr, " -A date/[+-]offset/none: set key activation date " + "(default: now)\n"); + fprintf(stderr, " -R date/[+-]offset/none: set key " + "revocation date\n"); + fprintf(stderr, " -I date/[+-]offset/none: set key " + "inactivation date\n"); + fprintf(stderr, " -D date/[+-]offset/none: set key deletion date\n"); + fprintf(stderr, " -G: generate key only; do not set -P or -A\n"); + fprintf(stderr, " -C: generate a backward-compatible key, omitting " + "all dates\n"); + fprintf(stderr, " -S <key>: generate a successor to an existing " + "key\n"); + fprintf(stderr, " -i <interval>: prepublication interval for " + "successor key " + "(default: 30 days)\n"); fprintf(stderr, "Output:\n"); fprintf(stderr, " K<name>+<alg>+<id>.key, " - "K<name>+<alg>+<id>.private\n"); + "K<name>+<alg>+<id>.private\n"); exit (-1); } +static isc_boolean_t +dsa_size_ok(int size) { + return (ISC_TF(size >= 512 && size <= 1024 && size % 64 == 0)); +} + +static void +progress(int p) +{ + char c = '*'; + + switch (p) { + case 0: + c = '.'; + break; + case 1: + c = '+'; + break; + case 2: + c = '*'; + break; + case 3: + c = ' '; + break; + default: + break; + } + (void) putc(c, stderr); + (void) fflush(stderr); +} + int main(int argc, char **argv) { char *algname = NULL, *nametype = NULL, *type = NULL; char *classname = NULL; char *endp; - dst_key_t *key = NULL, *oldkey; + dst_key_t *key = NULL; dns_fixedname_t fname; dns_name_t *name; - isc_uint16_t flags = 0, ksk = 0; + isc_uint16_t flags = 0, kskflag = 0, revflag = 0; dns_secalg_t alg; isc_boolean_t conflict = ISC_FALSE, null_key = ISC_FALSE; + isc_boolean_t oldstyle = ISC_FALSE; isc_mem_t *mctx = NULL; int ch, rsa_exp = 0, generator = 0, param = 0; int protocol = -1, size = -1, signatory = 0; isc_result_t ret; isc_textregion_t r; char filename[255]; + const char *directory = NULL; + const char *predecessor = NULL; + dst_key_t *prevkey = NULL; isc_buffer_t buf; isc_log_t *log = NULL; isc_entropy_t *ectx = NULL; +#ifdef USE_PKCS11 + const char *engine = "pkcs11"; +#else + const char *engine = NULL; +#endif dns_rdataclass_t rdclass; int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; int dbits = 0; + isc_boolean_t use_default = ISC_FALSE, use_nsec3 = ISC_FALSE; + isc_stdtime_t publish = 0, activate = 0, revoke = 0; + isc_stdtime_t inactive = 0, delete = 0; + isc_stdtime_t now; + int prepub = -1; + isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; + isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE; + isc_boolean_t setdel = ISC_FALSE; + isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE; + isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE; + isc_boolean_t unsetdel = ISC_FALSE; + isc_boolean_t genonly = ISC_FALSE; + isc_boolean_t quiet = ISC_FALSE; + isc_boolean_t show_progress = ISC_FALSE; + unsigned char c; if (argc == 1) usage(); - RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); - dns_result_register(); isc_commandline_errprint = ISC_FALSE; - while ((ch = isc_commandline_parse(argc, argv, - "a:b:c:d:ef:g:kn:t:p:s:r:v:h")) != -1) - { + /* + * Process memory debugging argument first. + */ +#define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:km:n:P:p:qR:r:S:s:T:t:v:" + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case 'm': + if (strcasecmp(isc_commandline_argument, "record") == 0) + isc_mem_debugging |= ISC_MEM_DEBUGRECORD; + if (strcasecmp(isc_commandline_argument, "trace") == 0) + isc_mem_debugging |= ISC_MEM_DEBUGTRACE; + if (strcasecmp(isc_commandline_argument, "usage") == 0) + isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; + if (strcasecmp(isc_commandline_argument, "size") == 0) + isc_mem_debugging |= ISC_MEM_DEBUGSIZE; + if (strcasecmp(isc_commandline_argument, "mctx") == 0) + isc_mem_debugging |= ISC_MEM_DEBUGCTX; + break; + default: + break; + } + } + isc_commandline_reset = ISC_TRUE; + + RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); + + isc_stdtime_get(&now); + + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { + case '3': + use_nsec3 = ISC_TRUE; + break; case 'a': algname = isc_commandline_argument; break; @@ -167,6 +291,9 @@ main(int argc, char **argv) { if (*endp != '\0' || size < 0) fatal("-b requires a non-negative number"); break; + case 'C': + oldstyle = ISC_TRUE; + break; case 'c': classname = isc_commandline_argument; break; @@ -175,12 +302,18 @@ main(int argc, char **argv) { if (*endp != '\0' || dbits < 0) fatal("-d requires a non-negative number"); break; + case 'E': + engine = isc_commandline_argument; + break; case 'e': rsa_exp = 1; break; case 'f': - if (strcasecmp(isc_commandline_argument, "KSK") == 0) - ksk = DNS_KEYFLAG_KSK; + c = (unsigned char)(isc_commandline_argument[0]); + if (toupper(c) == 'K') + kskflag = DNS_KEYFLAG_KSK; + else if (toupper(c) == 'R') + revflag = DNS_KEYFLAG_REVOKE; else fatal("unknown flag '%s'", isc_commandline_argument); @@ -191,14 +324,22 @@ main(int argc, char **argv) { if (*endp != '\0' || generator <= 0) fatal("-g requires a positive number"); break; + case 'K': + directory = isc_commandline_argument; + ret = try_dir(directory); + if (ret != ISC_R_SUCCESS) + fatal("cannot open directory %s: %s", + directory, isc_result_totext(ret)); + break; case 'k': - options |= DST_TYPE_KEY; + fatal("The -k option has been deprecated.\n" + "To generate a key-signing key, use -f KSK.\n" + "To generate a key with TYPE=KEY, use -T KEY.\n"); break; case 'n': nametype = isc_commandline_argument; break; - case 't': - type = isc_commandline_argument; + case 'm': break; case 'p': protocol = strtol(isc_commandline_argument, &endp, 10); @@ -206,6 +347,12 @@ main(int argc, char **argv) { fatal("-p must be followed by a number " "[0..255]"); break; + case 'q': + quiet = ISC_TRUE; + break; + case 'r': + setup_entropy(mctx, isc_commandline_argument, &ectx); + break; case 's': signatory = strtol(isc_commandline_argument, &endp, 10); @@ -213,8 +360,19 @@ main(int argc, char **argv) { fatal("-s must be followed by a number " "[0..15]"); break; - case 'r': - setup_entropy(mctx, isc_commandline_argument, &ectx); + case 'T': + if (strcasecmp(isc_commandline_argument, "KEY") == 0) + options |= DST_TYPE_KEY; + else if (strcasecmp(isc_commandline_argument, + "DNSKEY") == 0) + /* default behavior */ + ; + else + fatal("unknown type '%s'", + isc_commandline_argument); + break; + case 't': + type = isc_commandline_argument; break; case 'v': endp = NULL; @@ -222,11 +380,86 @@ main(int argc, char **argv) { if (*endp != '\0') fatal("-v must be followed by a number"); break; - + case 'z': + /* already the default */ + break; + case 'G': + genonly = ISC_TRUE; + break; + case 'P': + if (setpub || unsetpub) + fatal("-P specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setpub = ISC_TRUE; + publish = strtotime(isc_commandline_argument, + now, now); + } else { + unsetpub = ISC_TRUE; + } + break; + case 'A': + if (setact || unsetact) + fatal("-A specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setact = ISC_TRUE; + activate = strtotime(isc_commandline_argument, + now, now); + } else { + unsetact = ISC_TRUE; + } + break; + case 'R': + if (setrev || unsetrev) + fatal("-R specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setrev = ISC_TRUE; + revoke = strtotime(isc_commandline_argument, + now, now); + } else { + unsetrev = ISC_TRUE; + } + break; + case 'I': + if (setinact || unsetinact) + fatal("-I specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setinact = ISC_TRUE; + inactive = strtotime(isc_commandline_argument, + now, now); + } else { + unsetinact = ISC_TRUE; + } + break; + case 'D': + if (setdel || unsetdel) + fatal("-D specified more than once"); + + if (strcasecmp(isc_commandline_argument, "none")) { + setdel = ISC_TRUE; + delete = strtotime(isc_commandline_argument, + now, now); + } else { + unsetdel = ISC_TRUE; + } + break; + case 'S': + predecessor = isc_commandline_argument; + break; + case 'i': + prepub = strtottl(isc_commandline_argument); + break; + case 'F': + /* Reserved for FIPS mode */ + /* FALLTHROUGH */ case '?': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); + /* FALLTHROUGH */ case 'h': usage(); @@ -237,73 +470,219 @@ main(int argc, char **argv) { } } + if (!isatty(0)) + quiet = ISC_TRUE; + if (ectx == NULL) setup_entropy(mctx, NULL, &ectx); - ret = dst_lib_init(mctx, ectx, - ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); + ret = dst_lib_init2(mctx, ectx, engine, + ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); if (ret != ISC_R_SUCCESS) - fatal("could not initialize dst"); + fatal("could not initialize dst: %s", + isc_result_totext(ret)); setup_logging(verbose, mctx, &log); - if (argc < isc_commandline_index + 1) - fatal("the key name was not specified"); - if (argc > isc_commandline_index + 1) - fatal("extraneous arguments"); - - if (algname == NULL) - fatal("no algorithm was specified"); - if (strcasecmp(algname, "RSA") == 0) { - fprintf(stderr, "The use of RSA (RSAMD5) is not recommended.\n" - "If you still wish to use RSA (RSAMD5) please " - "specify \"-a RSAMD5\"\n"); - return (1); - } else if (strcasecmp(algname, "HMAC-MD5") == 0) { - options |= DST_TYPE_KEY; - alg = DST_ALG_HMACMD5; - } else if (strcasecmp(algname, "HMAC-SHA1") == 0) { - options |= DST_TYPE_KEY; - alg = DST_ALG_HMACSHA1; - } else if (strcasecmp(algname, "HMAC-SHA224") == 0) { - options |= DST_TYPE_KEY; - alg = DST_ALG_HMACSHA224; - } else if (strcasecmp(algname, "HMAC-SHA256") == 0) { - options |= DST_TYPE_KEY; - alg = DST_ALG_HMACSHA256; - } else if (strcasecmp(algname, "HMAC-SHA384") == 0) { - options |= DST_TYPE_KEY; - alg = DST_ALG_HMACSHA384; - } else if (strcasecmp(algname, "HMAC-SHA512") == 0) { - options |= DST_TYPE_KEY; - alg = DST_ALG_HMACSHA512; - } else { - r.base = algname; - r.length = strlen(algname); - ret = dns_secalg_fromtext(&alg, &r); + if (predecessor == NULL) { + if (prepub == -1) + prepub = 0; + + if (argc < isc_commandline_index + 1) + fatal("the key name was not specified"); + if (argc > isc_commandline_index + 1) + fatal("extraneous arguments"); + + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + isc_buffer_init(&buf, argv[isc_commandline_index], + strlen(argv[isc_commandline_index])); + isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); + ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); if (ret != ISC_R_SUCCESS) - fatal("unknown algorithm %s", algname); - if (alg == DST_ALG_DH) - options |= DST_TYPE_KEY; - } + fatal("invalid key name %s: %s", + argv[isc_commandline_index], + isc_result_totext(ret)); + + if (algname == NULL) { + use_default = ISC_TRUE; + if (use_nsec3) + algname = strdup(DEFAULT_NSEC3_ALGORITHM); + else + algname = strdup(DEFAULT_ALGORITHM); + if (verbose > 0) + fprintf(stderr, "no algorithm specified; " + "defaulting to %s\n", algname); + } - if (type != NULL && (options & DST_TYPE_KEY) != 0) { - if (strcasecmp(type, "NOAUTH") == 0) - flags |= DNS_KEYTYPE_NOAUTH; - else if (strcasecmp(type, "NOCONF") == 0) - flags |= DNS_KEYTYPE_NOCONF; - else if (strcasecmp(type, "NOAUTHCONF") == 0) { - flags |= (DNS_KEYTYPE_NOAUTH | DNS_KEYTYPE_NOCONF); - if (size < 0) - size = 0; + if (strcasecmp(algname, "RSA") == 0) { + fprintf(stderr, "The use of RSA (RSAMD5) is not " + "recommended.\nIf you still wish to " + "use RSA (RSAMD5) please specify " + "\"-a RSAMD5\"\n"); + return (1); + } else if (strcasecmp(algname, "HMAC-MD5") == 0) + alg = DST_ALG_HMACMD5; + else if (strcasecmp(algname, "HMAC-SHA1") == 0) + alg = DST_ALG_HMACSHA1; + else if (strcasecmp(algname, "HMAC-SHA224") == 0) + alg = DST_ALG_HMACSHA224; + else if (strcasecmp(algname, "HMAC-SHA256") == 0) + alg = DST_ALG_HMACSHA256; + else if (strcasecmp(algname, "HMAC-SHA384") == 0) + alg = DST_ALG_HMACSHA384; + else if (strcasecmp(algname, "HMAC-SHA512") == 0) + alg = DST_ALG_HMACSHA512; + else { + r.base = algname; + r.length = strlen(algname); + ret = dns_secalg_fromtext(&alg, &r); + if (ret != ISC_R_SUCCESS) + fatal("unknown algorithm %s", algname); + if (alg == DST_ALG_DH) + options |= DST_TYPE_KEY; } - else if (strcasecmp(type, "AUTHCONF") == 0) - /* nothing */; - else - fatal("invalid type %s", type); - } - if (size < 0) - fatal("key size not specified (-b option)"); + if (use_nsec3 && + alg != DST_ALG_NSEC3DSA && alg != DST_ALG_NSEC3RSASHA1 && + alg != DST_ALG_RSASHA256 && alg!= DST_ALG_RSASHA512 && + alg != DST_ALG_ECCGOST) { + fatal("%s is incompatible with NSEC3; " + "do not use the -3 option", algname); + } + + if (type != NULL && (options & DST_TYPE_KEY) != 0) { + if (strcasecmp(type, "NOAUTH") == 0) + flags |= DNS_KEYTYPE_NOAUTH; + else if (strcasecmp(type, "NOCONF") == 0) + flags |= DNS_KEYTYPE_NOCONF; + else if (strcasecmp(type, "NOAUTHCONF") == 0) { + flags |= (DNS_KEYTYPE_NOAUTH | + DNS_KEYTYPE_NOCONF); + if (size < 0) + size = 0; + } + else if (strcasecmp(type, "AUTHCONF") == 0) + /* nothing */; + else + fatal("invalid type %s", type); + } + + if (size < 0) { + if (use_default) { + if ((kskflag & DNS_KEYFLAG_KSK) != 0) + size = 2048; + else + size = 1024; + if (verbose > 0) + fprintf(stderr, "key size not " + "specified; defaulting " + "to %d\n", size); + } else if (alg != DST_ALG_ECCGOST) + fatal("key size not specified (-b option)"); + } + + if (!oldstyle && prepub > 0) { + if (setpub && setact && (activate - prepub) < publish) + fatal("Activation and publication dates " + "are closer together than the\n\t" + "prepublication interval."); + + if (!setpub && !setact) { + setpub = setact = ISC_TRUE; + publish = now; + activate = now + prepub; + } else if (setpub && !setact) { + setact = ISC_TRUE; + activate = publish + prepub; + } else if (setact && !setpub) { + setpub = ISC_TRUE; + publish = activate - prepub; + } + + if ((activate - prepub) < now) + fatal("Time until activation is shorter " + "than the\n\tprepublication interval."); + } + } else { + char keystr[DST_KEY_FORMATSIZE]; + isc_stdtime_t when; + int major, minor; + + if (prepub == -1) + prepub = (30 * 86400); + + if (algname != NULL) + fatal("-S and -a cannot be used together"); + if (size >= 0) + fatal("-S and -b cannot be used together"); + if (nametype != NULL) + fatal("-S and -n cannot be used together"); + if (type != NULL) + fatal("-S and -t cannot be used together"); + if (setpub || unsetpub) + fatal("-S and -P cannot be used together"); + if (setact || unsetact) + fatal("-S and -A cannot be used together"); + if (use_nsec3) + fatal("-S and -3 cannot be used together"); + if (oldstyle) + fatal("-S and -C cannot be used together"); + if (genonly) + fatal("-S and -G cannot be used together"); + + ret = dst_key_fromnamedfile(predecessor, directory, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, + mctx, &prevkey); + if (ret != ISC_R_SUCCESS) + fatal("Invalid keyfile %s: %s", + filename, isc_result_totext(ret)); + if (!dst_key_isprivate(prevkey)) + fatal("%s is not a private key", filename); + + name = dst_key_name(prevkey); + alg = dst_key_alg(prevkey); + size = dst_key_size(prevkey); + flags = dst_key_flags(prevkey); + + dst_key_format(prevkey, keystr, sizeof(keystr)); + dst_key_getprivateformat(prevkey, &major, &minor); + if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) + fatal("Key %s has incompatible format version %d.%d\n\t" + "It is not possible to generate a successor key.", + keystr, major, minor); + + ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when); + if (ret != ISC_R_SUCCESS) + fatal("Key %s has no activation date.\n\t" + "You must use dnssec-settime -A to set one " + "before generating a successor.", keystr); + + ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &activate); + if (ret != ISC_R_SUCCESS) + fatal("Key %s has no inactivation date.\n\t" + "You must use dnssec-settime -I to set one " + "before generating a successor.", keystr); + + publish = activate - prepub; + if (publish < now) + fatal("Key %s becomes inactive\n\t" + "sooner than the prepublication period " + "for the new key ends.\n\t" + "Either change the inactivation date with " + "dnssec-settime -I,\n\t" + "or use the -i option to set a shorter " + "prepublication interval.", keystr); + + ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when); + if (ret != ISC_R_SUCCESS) + fprintf(stderr, "%s: WARNING: Key %s has no removal " + "date;\n\t it will remain in the zone " + "indefinitely after rollover.\n\t " + "You can use dnssec-settime -D to " + "change this.\n", program, keystr); + + setpub = setact = ISC_TRUE; + } switch (alg) { case DNS_KEYALG_RSAMD5: @@ -326,7 +705,10 @@ main(int argc, char **argv) { if (size != 0 && !dsa_size_ok(size)) fatal("invalid DSS key size: %d", size); break; + case DST_ALG_ECCGOST: + break; case DST_ALG_HMACMD5: + options |= DST_TYPE_KEY; if (size < 1 || size > 512) fatal("HMAC-MD5 key size %d out of range", size); if (dbits != 0 && (dbits < 80 || dbits > 128)) @@ -336,6 +718,7 @@ main(int argc, char **argv) { dbits); break; case DST_ALG_HMACSHA1: + options |= DST_TYPE_KEY; if (size < 1 || size > 160) fatal("HMAC-SHA1 key size %d out of range", size); if (dbits != 0 && (dbits < 80 || dbits > 160)) @@ -345,6 +728,7 @@ main(int argc, char **argv) { dbits); break; case DST_ALG_HMACSHA224: + options |= DST_TYPE_KEY; if (size < 1 || size > 224) fatal("HMAC-SHA224 key size %d out of range", size); if (dbits != 0 && (dbits < 112 || dbits > 224)) @@ -354,6 +738,7 @@ main(int argc, char **argv) { dbits); break; case DST_ALG_HMACSHA256: + options |= DST_TYPE_KEY; if (size < 1 || size > 256) fatal("HMAC-SHA256 key size %d out of range", size); if (dbits != 0 && (dbits < 128 || dbits > 256)) @@ -363,6 +748,7 @@ main(int argc, char **argv) { dbits); break; case DST_ALG_HMACSHA384: + options |= DST_TYPE_KEY; if (size < 1 || size > 384) fatal("HMAC-384 key size %d out of range", size); if (dbits != 0 && (dbits < 192 || dbits > 384)) @@ -372,6 +758,7 @@ main(int argc, char **argv) { dbits); break; case DST_ALG_HMACSHA512: + options |= DST_TYPE_KEY; if (size < 1 || size > 512) fatal("HMAC-SHA512 key size %d out of range", size); if (dbits != 0 && (dbits < 256 || dbits > 512)) @@ -384,7 +771,8 @@ main(int argc, char **argv) { if (!(alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_RSASHA1 || alg == DNS_KEYALG_NSEC3RSASHA1 || alg == DNS_KEYALG_RSASHA256 || - alg == DNS_KEYALG_RSASHA512) && rsa_exp != 0) + alg == DNS_KEYALG_RSASHA512 || alg == DST_ALG_ECCGOST) && + rsa_exp != 0) fatal("specified RSA exponent for a non-RSA key"); if (alg != DNS_KEYALG_DH && generator != 0) @@ -409,10 +797,15 @@ main(int argc, char **argv) { rdclass = strtoclass(classname); + if (directory == NULL) + directory = "."; + if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */ flags |= signatory; - else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */ - flags |= ksk; + else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */ + flags |= kskflag; + flags |= revflag; + } if (protocol == -1) protocol = DNS_KEYPROTO_DNSSEC; @@ -435,16 +828,6 @@ main(int argc, char **argv) { fatal("a key with algorithm '%s' cannot be a zone key", algname); - dns_fixedname_init(&fname); - name = dns_fixedname_name(&fname); - isc_buffer_init(&buf, argv[isc_commandline_index], - strlen(argv[isc_commandline_index])); - isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); - ret = dns_name_fromtext(name, &buf, dns_rootname, ISC_FALSE, NULL); - if (ret != ISC_R_SUCCESS) - fatal("invalid key name %s: %s", argv[isc_commandline_index], - isc_result_totext(ret)); - switch(alg) { case DNS_KEYALG_RSAMD5: case DNS_KEYALG_RSASHA1: @@ -452,12 +835,19 @@ main(int argc, char **argv) { case DNS_KEYALG_RSASHA256: case DNS_KEYALG_RSASHA512: param = rsa_exp; + show_progress = ISC_TRUE; break; + case DNS_KEYALG_DH: param = generator; break; + case DNS_KEYALG_DSA: case DNS_KEYALG_NSEC3DSA: + case DST_ALG_ECCGOST: + show_progress = ISC_TRUE; + /* fall through */ + case DST_ALG_HMACMD5: case DST_ALG_HMACSHA1: case DST_ALG_HMACSHA224: @@ -475,62 +865,136 @@ main(int argc, char **argv) { do { conflict = ISC_FALSE; - oldkey = NULL; - /* generate the key */ - ret = dst_key_generate(name, alg, size, param, flags, protocol, - rdclass, mctx, &key); + if (!quiet && show_progress) { + fprintf(stderr, "Generating key pair."); + ret = dst_key_generate2(name, alg, size, param, flags, + protocol, rdclass, mctx, &key, + &progress); + putc('\n', stderr); + fflush(stderr); + } else { + ret = dst_key_generate2(name, alg, size, param, flags, + protocol, rdclass, mctx, &key, + NULL); + } + isc_entropy_stopcallbacksources(ectx); if (ret != ISC_R_SUCCESS) { char namestr[DNS_NAME_FORMATSIZE]; - char algstr[ALG_FORMATSIZE]; + char algstr[DNS_SECALG_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); - alg_format(alg, algstr, sizeof(algstr)); + dns_secalg_format(alg, algstr, sizeof(algstr)); fatal("failed to generate key %s/%s: %s\n", namestr, algstr, isc_result_totext(ret)); + /* NOTREACHED */ exit(-1); } dst_key_setbits(key, dbits); /* - * Try to read a key with the same name, alg and id from disk. - * If there is one we must continue generating a new one - * unless we were asked to generate a null key, in which - * case we return failure. + * Set key timing metadata (unless using -C) + * + * Creation date is always set to "now". + * + * For a new key without an explicit predecessor, publish + * and activation dates are set to "now" by default, but + * can both be overridden. + * + * For a successor key, activation is set to match the + * predecessor's inactivation date. Publish is set to 30 + * days earlier than that (XXX: this should be configurable). + * If either of the resulting dates are in the past, that's + * an error; the inactivation date of the predecessor key + * must be updated before a successor key can be created. */ - ret = dst_key_fromfile(name, dst_key_id(key), alg, - DST_TYPE_PRIVATE, NULL, mctx, &oldkey); - /* do not overwrite an existing key */ - if (ret == ISC_R_SUCCESS) { - dst_key_free(&oldkey); + if (!oldstyle) { + dst_key_settime(key, DST_TIME_CREATED, now); + + if (genonly && (setpub || setact)) + fatal("cannot use -G together with " + "-P or -A options"); + + if (setpub) + dst_key_settime(key, DST_TIME_PUBLISH, publish); + else if (setact) + dst_key_settime(key, DST_TIME_PUBLISH, + activate); + else if (!genonly && !unsetpub) + dst_key_settime(key, DST_TIME_PUBLISH, now); + + if (setact) + dst_key_settime(key, DST_TIME_ACTIVATE, + activate); + else if (!genonly && !unsetact) + dst_key_settime(key, DST_TIME_ACTIVATE, now); + + if (setrev) { + if (kskflag == 0) + fprintf(stderr, "%s: warning: Key is " + "not flagged as a KSK, but -R " + "was used. Revoking a ZSK is " + "legal, but undefined.\n", + program); + dst_key_settime(key, DST_TIME_REVOKE, revoke); + } + + if (setinact) + dst_key_settime(key, DST_TIME_INACTIVE, + inactive); + + if (setdel) + dst_key_settime(key, DST_TIME_DELETE, delete); + } else { + if (setpub || setact || setrev || setinact || + setdel || unsetpub || unsetact || + unsetrev || unsetinact || unsetdel || genonly) + fatal("cannot use -C together with " + "-P, -A, -R, -I, -D, or -G options"); + /* + * Compatibility mode: Private-key-format + * should be set to 1.2. + */ + dst_key_setprivateformat(key, 1, 2); + } + + /* + * Do not overwrite an existing key, or create a key + * if there is a risk of ID collision due to this key + * or another key being revoked. + */ + if (key_collision(dst_key_id(key), name, directory, + alg, mctx, NULL)) { conflict = ISC_TRUE; - if (null_key) + if (null_key) { + dst_key_free(&key); break; - } - if (conflict == ISC_TRUE) { + } + if (verbose > 0) { isc_buffer_clear(&buf); - ret = dst_key_buildfilename(key, 0, NULL, &buf); + dst_key_buildfilename(key, 0, directory, &buf); fprintf(stderr, - "%s: %s already exists, " - "generating a new key\n", + "%s: %s already exists, or might " + "collide with another key upon " + "revokation. Generating a new key\n", program, filename); } + dst_key_free(&key); } - } while (conflict == ISC_TRUE); if (conflict) - fatal("cannot generate a null key when a key with id 0 " - "already exists"); + fatal("cannot generate a null key due to possible key ID " + "collision"); - ret = dst_key_tofile(key, options, NULL); + ret = dst_key_tofile(key, options, directory); if (ret != ISC_R_SUCCESS) { - char keystr[KEY_FORMATSIZE]; - key_format(key, keystr, sizeof(keystr)); + char keystr[DST_KEY_FORMATSIZE]; + dst_key_format(key, keystr, sizeof(keystr)); fatal("failed to write key %s: %s\n", keystr, isc_result_totext(ret)); } @@ -539,6 +1003,8 @@ main(int argc, char **argv) { ret = dst_key_buildfilename(key, 0, NULL, &buf); printf("%s\n", filename); dst_key_free(&key); + if (prevkey != NULL) + dst_key_free(&prevkey); cleanup_logging(&log); cleanup_entropy(&ectx); diff --git a/contrib/bind9/bin/dnssec/dnssec-keygen.docbook b/contrib/bind9/bin/dnssec/dnssec-keygen.docbook index 5c7d1649fe67..dc140ebfe386 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keygen.docbook +++ b/contrib/bind9/bin/dnssec/dnssec-keygen.docbook @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: dnssec-keygen.docbook,v 1.22.44.4 2010-01-15 23:47:33 tbox Exp $ --> +<!-- $Id: dnssec-keygen.docbook,v 1.36 2010-12-23 04:07:59 marka Exp $ --> <refentry id="man.dnssec-keygen"> <refentryinfo> <date>June 30, 2000</date> @@ -57,20 +57,34 @@ <refsynopsisdiv> <cmdsynopsis> <command>dnssec-keygen</command> - <arg choice="req">-a <replaceable class="parameter">algorithm</replaceable></arg> - <arg choice="req">-b <replaceable class="parameter">keysize</replaceable></arg> - <arg choice="req">-n <replaceable class="parameter">nametype</replaceable></arg> + <arg><option>-a <replaceable class="parameter">algorithm</replaceable></option></arg> + <arg ><option>-b <replaceable class="parameter">keysize</replaceable></option></arg> + <arg><option>-n <replaceable class="parameter">nametype</replaceable></option></arg> + <arg><option>-3</option></arg> + <arg><option>-A <replaceable class="parameter">date/offset</replaceable></option></arg> + <arg><option>-C</option></arg> <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg> + <arg><option>-D <replaceable class="parameter">date/offset</replaceable></option></arg> + <arg><option>-E <replaceable class="parameter">engine</replaceable></option></arg> <arg><option>-e</option></arg> <arg><option>-f <replaceable class="parameter">flag</replaceable></option></arg> + <arg><option>-G</option></arg> <arg><option>-g <replaceable class="parameter">generator</replaceable></option></arg> <arg><option>-h</option></arg> + <arg><option>-I <replaceable class="parameter">date/offset</replaceable></option></arg> + <arg><option>-i <replaceable class="parameter">interval</replaceable></option></arg> + <arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg> <arg><option>-k</option></arg> + <arg><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg> <arg><option>-p <replaceable class="parameter">protocol</replaceable></option></arg> + <arg><option>-q</option></arg> + <arg><option>-R <replaceable class="parameter">date/offset</replaceable></option></arg> <arg><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg> + <arg><option>-S <replaceable class="parameter">key</replaceable></option></arg> <arg><option>-s <replaceable class="parameter">strength</replaceable></option></arg> <arg><option>-t <replaceable class="parameter">type</replaceable></option></arg> <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg> + <arg><option>-z</option></arg> <arg choice="req">name</arg> </cmdsynopsis> </refsynopsisdiv> @@ -80,7 +94,8 @@ <para><command>dnssec-keygen</command> generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with - TSIG (Transaction Signatures), as defined in RFC 2845. + TSIG (Transaction Signatures) as defined in RFC 2845, or TKEY + (Transaction Key) as defined in RFC 2930. </para> <para> The <option>name</option> of the key is specified on the command @@ -99,19 +114,27 @@ <para> Selects the cryptographic algorithm. For DNSSEC keys, the value of <option>algorithm</option> must be one of RSAMD5, RSASHA1, - DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256 or RSASHA512. - For TSIG/TKEY, the value must + DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. + For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC-MD5, HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512. These values are case insensitive. </para> <para> + If no algorithm is specified, then RSASHA1 will be used by + default, unless the <option>-3</option> option is specified, + in which case NSEC3RSASHA1 will be used instead. (If + <option>-3</option> is used and an algorithm is specified, + that algorithm will be checked for compatibility with NSEC3.) + </para> + <para> Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is mandatory. </para> <para> - Note 2: HMAC-MD5 and DH automatically set the -k flag. + Note 2: DH, HMAC-MD5, and HMAC-SHA1 through HMAC-SHA512 + automatically set the -T KEY option. </para> </listitem> </varlistentry> @@ -127,6 +150,15 @@ bits and an exact multiple of 64. HMAC keys must be between 1 and 512 bits. </para> + <para> + The key size does not need to be specified if using a default + algorithm. The default key size is 1024 bits for zone signing + keys (ZSK's) and 2048 bits for key signing keys (KSK's, + generated with <option>-f KSK</option>). However, if an + algorithm is explicitly specified with the <option>-a</option>, + then there is no default key size, and the <option>-b</option> + must be used. + </para> </listitem> </varlistentry> @@ -146,6 +178,34 @@ </varlistentry> <varlistentry> + <term>-3</term> + <listitem> + <para> + Use an NSEC3-capable algorithm to generate a DNSSEC key. + If this option is used and no algorithm is explicitly + set on the command line, NSEC3RSASHA1 will be used by + default. Note that RSASHA256, RSASHA512 and ECCGOST algorithms + are NSEC3-capable. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-C</term> + <listitem> + <para> + Compatibility mode: generates an old-style key, without + any metadata. By default, <command>dnssec-keygen</command> + will include the key's creation date in the metadata stored + with the private key, and other dates may be set there as well + (publication date, activation date, etc). Keys that include + this data may be incompatible with older versions of BIND; the + <option>-C</option> option suppresses them. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-c <replaceable class="parameter">class</replaceable></term> <listitem> <para> @@ -156,6 +216,18 @@ </varlistentry> <varlistentry> + <term>-E <replaceable class="parameter">engine</replaceable></term> + <listitem> + <para> + Uses a crypto hardware (OpenSSL engine) for random number + and, when supported, key generation. When compiled with PKCS#11 + support it defaults to pkcs11; the empty name resets it to + no engine. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-e</term> <listitem> <para> @@ -169,7 +241,17 @@ <listitem> <para> Set the specified flag in the flag field of the KEY/DNSKEY record. - The only recognized flag is KSK (Key Signing Key) DNSKEY. + The only recognized flags are KSK (Key Signing Key) and REVOKE. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-G</term> + <listitem> + <para> + Generate a key, but do not publish it or sign with it. This + option is incompatible with -P and -A. </para> </listitem> </varlistentry> @@ -197,10 +279,19 @@ </varlistentry> <varlistentry> + <term>-K <replaceable class="parameter">directory</replaceable></term> + <listitem> + <para> + Sets the directory in which the key files are to be written. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-k</term> <listitem> <para> - Generate KEY records rather than DNSKEY records. + Deprecated in favor of -T KEY. </para> </listitem> </varlistentry> @@ -218,6 +309,25 @@ </varlistentry> <varlistentry> + <term>-q</term> + <listitem> + <para> + Quiet mode: Suppresses unnecessary output, including + progress indication. Without this option, when + <command>dnssec-keygen</command> is run interactively + to generate an RSA or DSA key pair, it will print a string + of symbols to <filename>stderr</filename> indicating the + progress of the key generation. A '.' indicates that a + random number has been found which passed an initial + sieve test; '+' means a number has passed a single + round of the Miller-Rabin primality test; a space + means that the number has passed all the tests and is + a satisfactory key. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-r <replaceable class="parameter">randomdev</replaceable></term> <listitem> <para> @@ -235,6 +345,21 @@ </varlistentry> <varlistentry> + <term>-S <replaceable class="parameter">key</replaceable></term> + <listitem> + <para> + Create a new key which is an explicit successor to an + existing key. The name, algorithm, size, and type of the + key will be set to match the existing key. The activation + date of the new key will be set to the inactivation date of + the existing one. The publication date will be set to the + activation date minus the prepublication interval, which + defaults to 30 days. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-s <replaceable class="parameter">strength</replaceable></term> <listitem> <para> @@ -246,6 +371,22 @@ </varlistentry> <varlistentry> + <term>-T <replaceable class="parameter">rrtype</replaceable></term> + <listitem> + <para> + Specifies the resource record type to use for the key. + <option>rrtype</option> must be either DNSKEY or KEY. The + default is DNSKEY when using a DNSSEC algorithm, but it can be + overridden to KEY for use with SIG(0). + <para> + </para> + Using any TSIG algorithm (HMAC-* or DH) forces this option + to KEY. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-t <replaceable class="parameter">type</replaceable></term> <listitem> <para> @@ -270,6 +411,109 @@ </refsect1> <refsect1> + <title>TIMING OPTIONS</title> + + <para> + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. + </para> + + <variablelist> + <varlistentry> + <term>-P <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. If not set, and if the -G option has + not been used, the default is "now". + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-A <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. If not set, and if the -G option has not been used, the + default is "now". + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-R <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-I <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-D <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-i <replaceable class="parameter">interval</replaceable></term> + <listitem> + <para> + Sets the prepublication interval for a key. If set, then + the publication and activation dates must be separated by at least + this much time. If the activation date is specified but the + publication date isn't, then the publication date will default + to this much time before the activation date; conversely, if + the publication date is specified but activation date isn't, + then activation will be set to this much time after publication. + </para> + <para> + If the key is being created as an explicit successor to another + key, then the default prepublication interval is 30 days; + otherwise it is zero. + </para> + <para> + As with date offsets, if the argument is followed by one of + the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the + interval is measured in years, months, weeks, days, hours, + or minutes, respectively. Without a suffix, the interval is + measured in seconds. + </para> + </listitem> + </varlistentry> + + </variablelist> + </refsect1> + + + <refsect1> <title>GENERATED KEYS</title> <para> When <command>dnssec-keygen</command> completes diff --git a/contrib/bind9/bin/dnssec/dnssec-keygen.html b/contrib/bind9/bin/dnssec/dnssec-keygen.html index 7ca7d577e8fb..2f3a69b9a2fd 100644 --- a/contrib/bind9/bin/dnssec/dnssec-keygen.html +++ b/contrib/bind9/bin/dnssec/dnssec-keygen.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: dnssec-keygen.html,v 1.32.44.4 2010-01-16 01:55:32 tbox Exp $ --> +<!-- $Id: dnssec-keygen.html,v 1.47 2010-12-24 01:14:20 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> @@ -29,14 +29,15 @@ </div> <div class="refsynopsisdiv"> <h2>Synopsis</h2> -<div class="cmdsynopsis"><p><code class="command">dnssec-keygen</code> {-a <em class="replaceable"><code>algorithm</code></em>} {-b <em class="replaceable"><code>keysize</code></em>} {-n <em class="replaceable"><code>nametype</code></em>} [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-e</code>] [<code class="option">-f <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-g <em class="replaceable"><code>generator</code></em></code>] [<code class="option">-h</code>] [<code class="option">-k</code>] [<code class="option">-p <em class="replaceable"><code>protocol</code></em></code>] [<code class="option">-r <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-s <em class="replaceable"><code>strength</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] {name}</p></div> +<div class="cmdsynopsis"><p><code class="command">dnssec-keygen</code> [<code class="option">-a <em class="replaceable"><code>algorithm</code></em></code>] [<code class="option">-b <em class="replaceable"><code>keysize</code></em></code>] [<code class="option">-n <em class="replaceable"><code>nametype</code></em></code>] [<code class="option">-3</code>] [<code class="option">-A <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-C</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-D <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-E <em class="replaceable"><code>engine</code></em></code>] [<code class="option">-e</code>] [<code class="option">-f <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-G</code>] [<code class="option">-g <em class="replaceable"><code>generator</code></em></code>] [<code class="option">-h</code>] [<code class="option">-I <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-i <em class="replaceable"><code>interval</code></em></code>] [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-k</code>] [<code class="option">-P <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-p <em class="replaceable"><code>protocol</code></em></code>] [<code class="option">-q</code>] [<code class="option">-R <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-r <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-S <em class="replaceable"><code>key</code></em></code>] [<code class="option">-s <em class="replaceable"><code>strength</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-z</code>] {name}</p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543483"></a><h2>DESCRIPTION</h2> +<a name="id2543578"></a><h2>DESCRIPTION</h2> <p><span><strong class="command">dnssec-keygen</strong></span> generates keys for DNSSEC (Secure DNS), as defined in RFC 2535 and RFC 4034. It can also generate keys for use with - TSIG (Transaction Signatures), as defined in RFC 2845. + TSIG (Transaction Signatures) as defined in RFC 2845, or TKEY + (Transaction Key) as defined in RFC 2930. </p> <p> The <code class="option">name</code> of the key is specified on the command @@ -45,37 +46,56 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543501"></a><h2>OPTIONS</h2> +<a name="id2543596"></a><h2>OPTIONS</h2> <div class="variablelist"><dl> <dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt> <dd> <p> Selects the cryptographic algorithm. For DNSSEC keys, the value of <code class="option">algorithm</code> must be one of RSAMD5, RSASHA1, - DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256 or RSASHA512. - For TSIG/TKEY, the value must + DSA, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512 or ECCGOST. + For TSIG/TKEY, the value must be DH (Diffie Hellman), HMAC-MD5, HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512. These values are case insensitive. </p> <p> + If no algorithm is specified, then RSASHA1 will be used by + default, unless the <code class="option">-3</code> option is specified, + in which case NSEC3RSASHA1 will be used instead. (If + <code class="option">-3</code> is used and an algorithm is specified, + that algorithm will be checked for compatibility with NSEC3.) + </p> +<p> Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is mandatory. </p> <p> - Note 2: HMAC-MD5 and DH automatically set the -k flag. + Note 2: DH, HMAC-MD5, and HMAC-SHA1 through HMAC-SHA512 + automatically set the -T KEY option. </p> </dd> <dt><span class="term">-b <em class="replaceable"><code>keysize</code></em></span></dt> -<dd><p> +<dd> +<p> Specifies the number of bits in the key. The choice of key size depends on the algorithm used. RSA keys must be between 512 and 2048 bits. Diffie Hellman keys must be between 128 and 4096 bits. DSA keys must be between 512 and 1024 bits and an exact multiple of 64. HMAC keys must be between 1 and 512 bits. - </p></dd> + </p> +<p> + The key size does not need to be specified if using a default + algorithm. The default key size is 1024 bits for zone signing + keys (ZSK's) and 2048 bits for key signing keys (KSK's, + generated with <code class="option">-f KSK</code>). However, if an + algorithm is explicitly specified with the <code class="option">-a</code>, + then there is no default key size, and the <code class="option">-b</code> + must be used. + </p> +</dd> <dt><span class="term">-n <em class="replaceable"><code>nametype</code></em></span></dt> <dd><p> Specifies the owner type of the key. The value of @@ -86,11 +106,36 @@ These values are case insensitive. Defaults to ZONE for DNSKEY generation. </p></dd> +<dt><span class="term">-3</span></dt> +<dd><p> + Use an NSEC3-capable algorithm to generate a DNSSEC key. + If this option is used and no algorithm is explicitly + set on the command line, NSEC3RSASHA1 will be used by + default. Note that RSASHA256, RSASHA512 and ECCGOST algorithms + are NSEC3-capable. + </p></dd> +<dt><span class="term">-C</span></dt> +<dd><p> + Compatibility mode: generates an old-style key, without + any metadata. By default, <span><strong class="command">dnssec-keygen</strong></span> + will include the key's creation date in the metadata stored + with the private key, and other dates may be set there as well + (publication date, activation date, etc). Keys that include + this data may be incompatible with older versions of BIND; the + <code class="option">-C</code> option suppresses them. + </p></dd> <dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt> <dd><p> Indicates that the DNS record containing the key should have the specified class. If not specified, class IN is used. </p></dd> +<dt><span class="term">-E <em class="replaceable"><code>engine</code></em></span></dt> +<dd><p> + Uses a crypto hardware (OpenSSL engine) for random number + and, when supported, key generation. When compiled with PKCS#11 + support it defaults to pkcs11; the empty name resets it to + no engine. + </p></dd> <dt><span class="term">-e</span></dt> <dd><p> If generating an RSAMD5/RSASHA1 key, use a large exponent. @@ -98,7 +143,12 @@ <dt><span class="term">-f <em class="replaceable"><code>flag</code></em></span></dt> <dd><p> Set the specified flag in the flag field of the KEY/DNSKEY record. - The only recognized flag is KSK (Key Signing Key) DNSKEY. + The only recognized flags are KSK (Key Signing Key) and REVOKE. + </p></dd> +<dt><span class="term">-G</span></dt> +<dd><p> + Generate a key, but do not publish it or sign with it. This + option is incompatible with -P and -A. </p></dd> <dt><span class="term">-g <em class="replaceable"><code>generator</code></em></span></dt> <dd><p> @@ -112,9 +162,13 @@ Prints a short summary of the options and arguments to <span><strong class="command">dnssec-keygen</strong></span>. </p></dd> +<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt> +<dd><p> + Sets the directory in which the key files are to be written. + </p></dd> <dt><span class="term">-k</span></dt> <dd><p> - Generate KEY records rather than DNSKEY records. + Deprecated in favor of -T KEY. </p></dd> <dt><span class="term">-p <em class="replaceable"><code>protocol</code></em></span></dt> <dd><p> @@ -123,6 +177,20 @@ Other possible values for this argument are listed in RFC 2535 and its successors. </p></dd> +<dt><span class="term">-q</span></dt> +<dd><p> + Quiet mode: Suppresses unnecessary output, including + progress indication. Without this option, when + <span><strong class="command">dnssec-keygen</strong></span> is run interactively + to generate an RSA or DSA key pair, it will print a string + of symbols to <code class="filename">stderr</code> indicating the + progress of the key generation. A '.' indicates that a + random number has been found which passed an initial + sieve test; '+' means a number has passed a single + round of the Miller-Rabin primality test; a space + means that the number has passed all the tests and is + a satisfactory key. + </p></dd> <dt><span class="term">-r <em class="replaceable"><code>randomdev</code></em></span></dt> <dd><p> Specifies the source of randomness. If the operating @@ -135,12 +203,37 @@ <code class="filename">keyboard</code> indicates that keyboard input should be used. </p></dd> +<dt><span class="term">-S <em class="replaceable"><code>key</code></em></span></dt> +<dd><p> + Create a new key which is an explicit successor to an + existing key. The name, algorithm, size, and type of the + key will be set to match the existing key. The activation + date of the new key will be set to the inactivation date of + the existing one. The publication date will be set to the + activation date minus the prepublication interval, which + defaults to 30 days. + </p></dd> <dt><span class="term">-s <em class="replaceable"><code>strength</code></em></span></dt> <dd><p> Specifies the strength value of the key. The strength is a number between 0 and 15, and currently has no defined purpose in DNSSEC. </p></dd> +<dt><span class="term">-T <em class="replaceable"><code>rrtype</code></em></span></dt> +<dd> +<p> + Specifies the resource record type to use for the key. + <code class="option">rrtype</code> must be either DNSKEY or KEY. The + default is DNSKEY when using a DNSSEC algorithm, but it can be + overridden to KEY for use with SIG(0). + </p> +<p> + </p> +<p> + Using any TSIG algorithm (HMAC-* or DH) forces this option + to KEY. + </p> +</dd> <dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt> <dd><p> Indicates the use of the key. <code class="option">type</code> must be @@ -155,7 +248,78 @@ </dl></div> </div> <div class="refsect1" lang="en"> -<a name="id2543836"></a><h2>GENERATED KEYS</h2> +<a name="id2544301"></a><h2>TIMING OPTIONS</h2> +<p> + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. + </p> +<div class="variablelist"><dl> +<dt><span class="term">-P <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. If not set, and if the -G option has + not been used, the default is "now". + </p></dd> +<dt><span class="term">-A <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. If not set, and if the -G option has not been used, the + default is "now". + </p></dd> +<dt><span class="term">-R <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. + </p></dd> +<dt><span class="term">-I <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. + </p></dd> +<dt><span class="term">-D <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) + </p></dd> +<dt><span class="term">-i <em class="replaceable"><code>interval</code></em></span></dt> +<dd> +<p> + Sets the prepublication interval for a key. If set, then + the publication and activation dates must be separated by at least + this much time. If the activation date is specified but the + publication date isn't, then the publication date will default + to this much time before the activation date; conversely, if + the publication date is specified but activation date isn't, + then activation will be set to this much time after publication. + </p> +<p> + If the key is being created as an explicit successor to another + key, then the default prepublication interval is 30 days; + otherwise it is zero. + </p> +<p> + As with date offsets, if the argument is followed by one of + the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the + interval is measured in years, months, weeks, days, hours, + or minutes, respectively. Without a suffix, the interval is + measured in seconds. + </p> +</dd> +</dl></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2544491"></a><h2>GENERATED KEYS</h2> <p> When <span><strong class="command">dnssec-keygen</strong></span> completes successfully, @@ -201,7 +365,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543918"></a><h2>EXAMPLE</h2> +<a name="id2544642"></a><h2>EXAMPLE</h2> <p> To generate a 768-bit DSA key for the domain <strong class="userinput"><code>example.com</code></strong>, the following command would be @@ -222,7 +386,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2544030"></a><h2>SEE ALSO</h2> +<a name="id2544685"></a><h2>SEE ALSO</h2> <p><span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>, <em class="citetitle">BIND 9 Administrator Reference Manual</em>, <em class="citetitle">RFC 2539</em>, @@ -231,7 +395,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2544061"></a><h2>AUTHOR</h2> +<a name="id2544716"></a><h2>AUTHOR</h2> <p><span class="corpauthor">Internet Systems Consortium</span> </p> </div> diff --git a/contrib/bind9/bin/dnssec/dnssec-revoke.8 b/contrib/bind9/bin/dnssec/dnssec-revoke.8 new file mode 100644 index 000000000000..d57b6aa09de2 --- /dev/null +++ b/contrib/bind9/bin/dnssec/dnssec-revoke.8 @@ -0,0 +1,83 @@ +.\" 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.8,v 1.9 2010-05-19 01:14:14 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: dnssec\-revoke +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/> +.\" Date: June 1, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "DNSSEC\-REVOKE" "8" "June 1, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +dnssec\-revoke \- Set the REVOKED bit on a DNSSEC key +.SH "SYNOPSIS" +.HP 14 +\fBdnssec\-revoke\fR [\fB\-hr\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-E\ \fR\fB\fIengine\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" +.PP +\-h +.RS 4 +Emit usage message and exit. +.RE +.PP +\-K \fIdirectory\fR +.RS 4 +Sets the directory in which the key files are to reside. +.RE +.PP +\-r +.RS 4 +After writing the new keyset files remove the original keyset files. +.RE +.PP +\-v \fIlevel\fR +.RS 4 +Sets the debugging level. +.RE +.PP +\-E \fIengine\fR +.RS 4 +Use the given OpenSSL engine. When compiled with PKCS#11 support it defaults to pkcs11; the empty name resets it to no engine. +.RE +.PP +\-f +.RS 4 +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. +.RE +.SH "SEE ALSO" +.PP +\fBdnssec\-keygen\fR(8), +BIND 9 Administrator Reference Manual, +RFC 5011. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/contrib/bind9/bin/dnssec/dnssec-revoke.c b/contrib/bind9/bin/dnssec/dnssec-revoke.c new file mode 100644 index 000000000000..90e905c4d0b0 --- /dev/null +++ b/contrib/bind9/bin/dnssec/dnssec-revoke.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2009, 2010 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.22 2010-05-06 23:50:56 tbox Exp $ */ + +/*! \file */ + +#include <config.h> + +#include <libgen.h> +#include <stdlib.h> +#include <unistd.h> + +#include <isc/buffer.h> +#include <isc/commandline.h> +#include <isc/entropy.h> +#include <isc/file.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; + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s [options] keyfile\n\n", program); + fprintf(stderr, "Version: %s\n", VERSION); +#ifdef USE_PKCS11 + fprintf(stderr, " -E engine: specify OpenSSL engine " + "(default \"pkcs11\")\n"); +#else + fprintf(stderr, " -E engine: specify OpenSSL engine\n"); +#endif + fprintf(stderr, " -f: force overwrite\n"); + fprintf(stderr, " -K directory: use directory for key files\n"); + fprintf(stderr, " -h: help\n"); + fprintf(stderr, " -r: remove old keyfiles after " + "creating revoked version\n"); + 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; +#ifdef USE_PKCS11 + const char *engine = "pkcs11"; +#else + const char *engine = NULL; +#endif + char *filename = NULL, *dir = NULL; + char newname[1024], oldname[1024]; + char keystr[DST_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, "E:fK:rhv:")) != -1) { + switch (ch) { + case 'E': + engine = isc_commandline_argument; + break; + case 'f': + force = ISC_TRUE; + break; + case 'K': + /* + * We don't have to copy it here, but do it to + * simplify cleanup later + */ + dir = isc_mem_strdup(mctx, isc_commandline_argument); + if (dir == NULL) { + fatal("Failed to allocate memory for " + "directory"); + } + 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) { + filename = argv[isc_commandline_index]; + } else { + result = isc_file_splitpath(mctx, argv[isc_commandline_index], + &dir, &filename); + if (result != ISC_R_SUCCESS) + fatal("cannot process filename %s: %s", + argv[isc_commandline_index], + isc_result_totext(result)); + if (strcmp(dir, ".") == 0) { + isc_mem_free(mctx, dir); + dir = NULL; + } + } + + 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_init2(mctx, ectx, engine, + ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); + if (result != ISC_R_SUCCESS) + fatal("Could not initialize dst: %s", + isc_result_totext(result)); + isc_entropy_stopcallbacksources(ectx); + + result = dst_key_fromnamedfile(filename, dir, + DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, + mctx, &key); + if (result != ISC_R_SUCCESS) + fatal("Invalid keyfile name %s: %s", + filename, isc_result_totext(result)); + + dst_key_format(key, keystr, sizeof(keystr)); + + if (verbose > 2) + fprintf(stderr, "%s: %s\n", program, keystr); + + if (force) + set_keyversion(key); + else + check_keyversion(key, keystr); + + + flags = dst_key_flags(key); + if ((flags & DNS_KEYFLAG_REVOKE) == 0) { + isc_stdtime_t now; + + if ((flags & DNS_KEYFLAG_KSK) == 0) + fprintf(stderr, "%s: warning: Key is not flagged " + "as a KSK. Revoking a ZSK is " + "legal, but undefined.\n", + program); + + isc_stdtime_get(&now); + dst_key_settime(key, DST_TIME_REVOKE, now); + + 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) { + dst_key_format(key, keystr, sizeof(keystr)); + fatal("Failed to write key %s: %s", keystr, + isc_result_totext(result)); + } + + isc_buffer_clear(&buf); + dst_key_buildfilename(key, 0, 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 { + dst_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); + if (dir != NULL) + isc_mem_free(mctx, dir); + isc_mem_destroy(&mctx); + + return (0); +} diff --git a/contrib/bind9/bin/dnssec/dnssec-revoke.docbook b/contrib/bind9/bin/dnssec/dnssec-revoke.docbook new file mode 100644 index 000000000000..b7b562021308 --- /dev/null +++ b/contrib/bind9/bin/dnssec/dnssec-revoke.docbook @@ -0,0 +1,149 @@ +<!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.7 2009-11-03 21:44:46 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>-K <replaceable class="parameter">directory</replaceable></option></arg> + <arg><option>-E <replaceable class="parameter">engine</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>-K <replaceable class="parameter">directory</replaceable></term> + <listitem> + <para> + Sets the directory in which the key files are to reside. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-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>-E <replaceable class="parameter">engine</replaceable></term> + <listitem> + <para> + Use the given OpenSSL engine. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-f</term> + <listitem> + <para> + Force overwrite: Causes <command>dnssec-revoke</command> to + write the new key pair even if a file already exists matching + the algorithm and key ID of the revoked key. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>SEE ALSO</title> + <para><citerefentry> + <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum> + </citerefentry>, + <citetitle>BIND 9 Administrator Reference Manual</citetitle>, + <citetitle>RFC 5011</citetitle>. + </para> + </refsect1> + + <refsect1> + <title>AUTHOR</title> + <para><corpauthor>Internet Systems Consortium</corpauthor> + </para> + </refsect1> + +</refentry><!-- + - Local variables: + - mode: sgml + - End: +--> diff --git a/contrib/bind9/bin/dnssec/dnssec-revoke.html b/contrib/bind9/bin/dnssec/dnssec-revoke.html new file mode 100644 index 000000000000..fad9ac520196 --- /dev/null +++ b/contrib/bind9/bin/dnssec/dnssec-revoke.html @@ -0,0 +1,87 @@ +<!-- + - 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.html,v 1.9 2010-05-19 01:14:14 tbox 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.71.1"> +</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">-hr</code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-E <em class="replaceable"><code>engine</code></em></code>] [<code class="option">-f</code>] {keyfile}</p></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543373"></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="id2543385"></a><h2>OPTIONS</h2> +<div class="variablelist"><dl> +<dt><span class="term">-h</span></dt> +<dd><p> + Emit usage message and exit. + </p></dd> +<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt> +<dd><p> + Sets the directory in which the key files are to reside. + </p></dd> +<dt><span class="term">-r</span></dt> +<dd><p> + After writing the new keyset files remove the original keyset + files. + </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">-E <em class="replaceable"><code>engine</code></em></span></dt> +<dd><p> + Use the given OpenSSL engine. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. + </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="id2543491"></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="id2543515"></a><h2>AUTHOR</h2> +<p><span class="corpauthor">Internet Systems Consortium</span> + </p> +</div> +</div></body> +</html> diff --git a/contrib/bind9/bin/dnssec/dnssec-settime.8 b/contrib/bind9/bin/dnssec/dnssec-settime.8 new file mode 100644 index 000000000000..4390494474ce --- /dev/null +++ b/contrib/bind9/bin/dnssec/dnssec-settime.8 @@ -0,0 +1,166 @@ +.\" Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") +.\" +.\" Permission to use, copy, modify, and/or distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +.\" PERFORMANCE OF THIS SOFTWARE. +.\" +.\" $Id: dnssec-settime.8,v 1.14 2010-08-17 01:15:26 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: dnssec\-settime +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/> +.\" Date: July 15, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "DNSSEC\-SETTIME" "8" "July 15, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +dnssec\-settime \- Set the key timing metadata for a DNSSEC key +.SH "SYNOPSIS" +.HP 15 +\fBdnssec\-settime\fR [\fB\-f\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-A\ \fR\fB\fIdate/offset\fR\fR] [\fB\-R\ \fR\fB\fIdate/offset\fR\fR] [\fB\-I\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-h\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] {keyfile} +.SH "DESCRIPTION" +.PP +\fBdnssec\-settime\fR +reads a DNSSEC private key file and sets the key timing metadata as specified by the +\fB\-P\fR, +\fB\-A\fR, +\fB\-R\fR, +\fB\-I\fR, and +\fB\-D\fR +options. The metadata can then be used by +\fBdnssec\-signzone\fR +or other signing software to determine when a key is to be published, whether it should be used for signing a zone, etc. +.PP +If none of these options is set on the command line, then +\fBdnssec\-settime\fR +simply prints the key timing metadata already stored in the key. +.PP +When key metadata fields are changed, both files of a key pair (\fIKnnnn.+aaa+iiiii.key\fR +and +\fIKnnnn.+aaa+iiiii.private\fR) are regenerated. Metadata fields are stored in the private file. A human\-readable description of the metadata is also placed in comments in the key file. +.SH "OPTIONS" +.PP +\-f +.RS 4 +Force an update of an old\-format key with no metadata fields. Without this option, +\fBdnssec\-settime\fR +will fail when attempting to update a legacy key. With this option, the key will be recreated in the new format, but with the original key data retained. The key's creation date will be set to the present time. +.RE +.PP +\-K \fIdirectory\fR +.RS 4 +Sets the directory in which the key files are to reside. +.RE +.PP +\-h +.RS 4 +Emit usage message and exit. +.RE +.PP +\-v \fIlevel\fR +.RS 4 +Sets the debugging level. +.RE +.PP +\-E \fIengine\fR +.RS 4 +Use the given OpenSSL engine. When compiled with PKCS#11 support it defaults to pkcs11; the empty name resets it to no engine. +.RE +.SH "TIMING OPTIONS" +.PP +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. If the argument begins with a '+' or '\-', it is interpreted as an offset from the present time. For convenience, if such an offset is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the offset is computed in years (defined as 365 24\-hour days, ignoring leap years), months (defined as 30 24\-hour days), weeks, days, hours, or minutes, respectively. Without a suffix, the offset is computed in seconds. To unset a date, use 'none'. +.PP +\-P \fIdate/offset\fR +.RS 4 +Sets the date on which a key is to be published to the zone. After that date, the key will be included in the zone but will not be used to sign it. +.RE +.PP +\-A \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be activated. After that date, the key will be included in the zone and used to sign it. +.RE +.PP +\-R \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be revoked. After that date, the key will be flagged as revoked. It will be included in the zone and will be used to sign it. +.RE +.PP +\-I \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be retired. After that date, the key will still be included in the zone, but it will not be used to sign it. +.RE +.PP +\-D \fIdate/offset\fR +.RS 4 +Sets the date on which the key is to be deleted. After that date, the key will no longer be included in the zone. (It may remain in the key repository, however.) +.RE +.PP +\-S \fIpredecessor key\fR +.RS 4 +Select a key for which the key being modified will be an explicit successor. The name, algorithm, size, and type of the predecessor key must exactly match those of the key being modified. The activation date of the successor key will be set to the inactivation date of the predecessor. The publication date will be set to the activation date minus the prepublication interval, which defaults to 30 days. +.RE +.PP +\-i \fIinterval\fR +.RS 4 +Sets the prepublication interval for a key. If set, then the publication and activation dates must be separated by at least this much time. If the activation date is specified but the publication date isn't, then the publication date will default to this much time before the activation date; conversely, if the publication date is specified but activation date isn't, then activation will be set to this much time after publication. +.sp +If the key is being set to be an explicit successor to another key, then the default prepublication interval is 30 days; otherwise it is zero. +.sp +As with date offsets, if the argument is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the interval is measured in years, months, weeks, days, hours, or minutes, respectively. Without a suffix, the interval is measured in seconds. +.RE +.SH "PRINTING OPTIONS" +.PP +\fBdnssec\-settime\fR +can also be used to print the timing metadata associated with a key. +.PP +\-u +.RS 4 +Print times in UNIX epoch format. +.RE +.PP +\-p \fIC/P/A/R/I/D/all\fR +.RS 4 +Print a specific metadata value or set of metadata values. The +\fB\-p\fR +option may be followed by one or more of the following letters to indicate which value or values to print: +\fBC\fR +for the creation date, +\fBP\fR +for the publication date, +\fBA\fR +for the activation date, +\fBR\fR +for the revocation date, +\fBI\fR +for the inactivation date, or +\fBD\fR +for the deletion date. To print all of the metadata, use +\fB\-p all\fR. +.RE +.SH "SEE ALSO" +.PP +\fBdnssec\-keygen\fR(8), +\fBdnssec\-signzone\fR(8), +BIND 9 Administrator Reference Manual, +RFC 5011. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009, 2010 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/contrib/bind9/bin/dnssec/dnssec-settime.c b/contrib/bind9/bin/dnssec/dnssec-settime.c new file mode 100644 index 000000000000..364e2ab59268 --- /dev/null +++ b/contrib/bind9/bin/dnssec/dnssec-settime.c @@ -0,0 +1,576 @@ +/* + * Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: dnssec-settime.c,v 1.28 2010-12-19 07:29:36 each Exp $ */ + +/*! \file */ + +#include <config.h> + +#include <libgen.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <time.h> + +#include <isc/buffer.h> +#include <isc/commandline.h> +#include <isc/entropy.h> +#include <isc/file.h> +#include <isc/hash.h> +#include <isc/mem.h> +#include <isc/print.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <dns/keyvalues.h> +#include <dns/result.h> + +#include <dst/dst.h> + +#include "dnssectool.h" + +const char *program = "dnssec-settime"; +int verbose; + +static isc_mem_t *mctx = NULL; + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s [options] keyfile\n\n", program); + fprintf(stderr, "Version: %s\n", VERSION); + fprintf(stderr, "General options:\n"); +#ifdef USE_PKCS11 + fprintf(stderr, " -E engine: specify OpenSSL engine " + "(default \"pkcs11\")\n"); +#else + fprintf(stderr, " -E engine: specify OpenSSL engine\n"); +#endif + fprintf(stderr, " -f: force update of old-style " + "keys\n"); + fprintf(stderr, " -K directory: set key file location\n"); + fprintf(stderr, " -v level: set level of verbosity\n"); + fprintf(stderr, " -h: help\n"); + fprintf(stderr, "Timing options:\n"); + fprintf(stderr, " -P date/[+-]offset/none: set/unset key " + "publication date\n"); + fprintf(stderr, " -A date/[+-]offset/none: set/unset key " + "activation date\n"); + fprintf(stderr, " -R date/[+-]offset/none: set/unset key " + "revocation date\n"); + fprintf(stderr, " -I date/[+-]offset/none: set/unset key " + "inactivation date\n"); + fprintf(stderr, " -D date/[+-]offset/none: set/unset key " + "deletion date\n"); + fprintf(stderr, "Printing options:\n"); + fprintf(stderr, " -p C/P/A/R/I/D/all: print a particular time " + "value or values " + "[default: all]\n"); + fprintf(stderr, " -u: print times in unix epoch " + "format\n"); + fprintf(stderr, "Output:\n"); + fprintf(stderr, " K<name>+<alg>+<new id>.key, " + "K<name>+<alg>+<new id>.private\n"); + + exit (-1); +} + +static void +printtime(dst_key_t *key, int type, const char *tag, isc_boolean_t epoch, + FILE *stream) +{ + isc_result_t result; + const char *output = NULL; + isc_stdtime_t when; + + if (tag != NULL) + fprintf(stream, "%s: ", tag); + + result = dst_key_gettime(key, type, &when); + if (result == ISC_R_NOTFOUND) { + fprintf(stream, "UNSET\n"); + } else if (epoch) { + fprintf(stream, "%d\n", (int) when); + } else { + time_t time = when; + output = ctime(&time); + fprintf(stream, "%s", output); + } +} + +int +main(int argc, char **argv) { + isc_result_t result; +#ifdef USE_PKCS11 + const char *engine = "pkcs11"; +#else + const char *engine = NULL; +#endif + char *filename = NULL, *directory = NULL; + char newname[1024]; + char keystr[DST_KEY_FORMATSIZE]; + char *endp, *p; + int ch; + isc_entropy_t *ectx = NULL; + const char *predecessor = NULL; + dst_key_t *prevkey = NULL; + dst_key_t *key = NULL; + isc_buffer_t buf; + dns_name_t *name = NULL; + dns_secalg_t alg = 0; + unsigned int size = 0; + isc_uint16_t flags = 0; + int prepub = -1; + isc_stdtime_t now; + isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0; + isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE; + isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE; + isc_boolean_t setdel = ISC_FALSE; + isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE; + isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE; + isc_boolean_t unsetdel = ISC_FALSE; + isc_boolean_t printcreate = ISC_FALSE, printpub = ISC_FALSE; + isc_boolean_t printact = ISC_FALSE, printrev = ISC_FALSE; + isc_boolean_t printinact = ISC_FALSE, printdel = ISC_FALSE; + isc_boolean_t force = ISC_FALSE; + isc_boolean_t epoch = ISC_FALSE; + isc_boolean_t changed = 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; + + isc_stdtime_get(&now); + +#define CMDLINE_FLAGS "A:D:E:fhI:i:K:P:p:R:S:uv:" + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case 'E': + engine = isc_commandline_argument; + break; + case 'f': + force = ISC_TRUE; + break; + case 'p': + p = isc_commandline_argument; + if (!strcasecmp(p, "all")) { + printcreate = ISC_TRUE; + printpub = ISC_TRUE; + printact = ISC_TRUE; + printrev = ISC_TRUE; + printinact = ISC_TRUE; + printdel = ISC_TRUE; + break; + } + + do { + switch (*p++) { + case 'C': + printcreate = ISC_TRUE; + break; + case 'P': + printpub = ISC_TRUE; + break; + case 'A': + printact = ISC_TRUE; + break; + case 'R': + printrev = ISC_TRUE; + break; + case 'I': + printinact = ISC_TRUE; + break; + case 'D': + printdel = ISC_TRUE; + break; + case ' ': + break; + default: + usage(); + break; + } + } while (*p != '\0'); + break; + case 'u': + epoch = ISC_TRUE; + break; + case 'K': + /* + * We don't have to copy it here, but do it to + * simplify cleanup later + */ + directory = isc_mem_strdup(mctx, + isc_commandline_argument); + if (directory == NULL) { + fatal("Failed to allocate memory for " + "directory"); + } + break; + case 'v': + verbose = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') + fatal("-v must be followed by a number"); + break; + case 'P': + if (setpub || unsetpub) + fatal("-P specified more than once"); + + changed = ISC_TRUE; + if (!strcasecmp(isc_commandline_argument, "none")) { + unsetpub = ISC_TRUE; + } else { + setpub = ISC_TRUE; + pub = strtotime(isc_commandline_argument, + now, now); + } + break; + case 'A': + if (setact || unsetact) + fatal("-A specified more than once"); + + changed = ISC_TRUE; + if (!strcasecmp(isc_commandline_argument, "none")) { + unsetact = ISC_TRUE; + } else { + setact = ISC_TRUE; + act = strtotime(isc_commandline_argument, + now, now); + } + break; + case 'R': + if (setrev || unsetrev) + fatal("-R specified more than once"); + + changed = ISC_TRUE; + if (!strcasecmp(isc_commandline_argument, "none")) { + unsetrev = ISC_TRUE; + } else { + setrev = ISC_TRUE; + rev = strtotime(isc_commandline_argument, + now, now); + } + break; + case 'I': + if (setinact || unsetinact) + fatal("-I specified more than once"); + + changed = ISC_TRUE; + if (!strcasecmp(isc_commandline_argument, "none")) { + unsetinact = ISC_TRUE; + } else { + setinact = ISC_TRUE; + inact = strtotime(isc_commandline_argument, + now, now); + } + break; + case 'D': + if (setdel || unsetdel) + fatal("-D specified more than once"); + + changed = ISC_TRUE; + if (!strcasecmp(isc_commandline_argument, "none")) { + unsetdel = ISC_TRUE; + } else { + setdel = ISC_TRUE; + del = strtotime(isc_commandline_argument, + now, now); + } + break; + case 'S': + predecessor = isc_commandline_argument; + break; + case 'i': + prepub = strtottl(isc_commandline_argument); + 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 (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_init2(mctx, ectx, engine, + ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); + if (result != ISC_R_SUCCESS) + fatal("Could not initialize dst: %s", + isc_result_totext(result)); + isc_entropy_stopcallbacksources(ectx); + + if (predecessor != NULL) { + char keystr[DST_KEY_FORMATSIZE]; + isc_stdtime_t when; + int major, minor; + + if (prepub == -1) + prepub = (30 * 86400); + + if (setpub || unsetpub) + fatal("-S and -P cannot be used together"); + if (setact || unsetact) + fatal("-S and -A cannot be used together"); + + result = dst_key_fromnamedfile(predecessor, directory, + DST_TYPE_PUBLIC | + DST_TYPE_PRIVATE, + mctx, &prevkey); + if (result != ISC_R_SUCCESS) + fatal("Invalid keyfile %s: %s", + filename, isc_result_totext(result)); + if (!dst_key_isprivate(prevkey)) + fatal("%s is not a private key", filename); + + name = dst_key_name(prevkey); + alg = dst_key_alg(prevkey); + size = dst_key_size(prevkey); + flags = dst_key_flags(prevkey); + + dst_key_format(prevkey, keystr, sizeof(keystr)); + dst_key_getprivateformat(prevkey, &major, &minor); + if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) + fatal("Predecessor has incompatible format " + "version %d.%d\n\t", major, minor); + + result = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when); + if (result != ISC_R_SUCCESS) + fatal("Predecessor has no activation date. " + "You must set one before\n\t" + "generating a successor."); + + result = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &act); + if (result != ISC_R_SUCCESS) + fatal("Predecessor has no inactivation date. " + "You must set one before\n\t" + "generating a successor."); + + pub = act - prepub; + if (pub < now && prepub != 0) + fatal("Predecessor will become inactive before the\n\t" + "prepublication period ends. Either change " + "its inactivation date,\n\t" + "or use the -i option to set a shorter " + "prepublication interval."); + + result = dst_key_gettime(prevkey, DST_TIME_DELETE, &when); + if (result != ISC_R_SUCCESS) + fprintf(stderr, "%s: WARNING: Predecessor has no " + "removal date;\n\t" + "it will remain in the zone " + "indefinitely after rollover.\n", + program); + + changed = setpub = setact = ISC_TRUE; + dst_key_free(&prevkey); + } else { + if (prepub < 0) + prepub = 0; + + if (prepub > 0) { + if (setpub && setact && (act - prepub) < pub) + fatal("Activation and publication dates " + "are closer together than the\n\t" + "prepublication interval."); + + if (setpub && !setact) { + setact = ISC_TRUE; + act = pub + prepub; + } else if (setact && !setpub) { + setpub = ISC_TRUE; + pub = act - prepub; + } + + if ((act - prepub) < now) + fatal("Time until activation is shorter " + "than the\n\tprepublication interval."); + } + } + + if (directory != NULL) { + filename = argv[isc_commandline_index]; + } else { + result = isc_file_splitpath(mctx, argv[isc_commandline_index], + &directory, &filename); + if (result != ISC_R_SUCCESS) + fatal("cannot process filename %s: %s", + argv[isc_commandline_index], + isc_result_totext(result)); + } + + result = dst_key_fromnamedfile(filename, directory, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, + mctx, &key); + if (result != ISC_R_SUCCESS) + fatal("Invalid keyfile %s: %s", + filename, isc_result_totext(result)); + + if (!dst_key_isprivate(key)) + fatal("%s is not a private key", filename); + + dst_key_format(key, keystr, sizeof(keystr)); + + if (predecessor != NULL) { + if (!dns_name_equal(name, dst_key_name(key))) + fatal("Key name mismatch"); + if (alg != dst_key_alg(key)) + fatal("Key algorithm mismatch"); + if (size != dst_key_size(key)) + fatal("Key size mismatch"); + if (flags != dst_key_flags(key)) + fatal("Key flags mismatch"); + } + + if (force) + set_keyversion(key); + else + check_keyversion(key, keystr); + + if (verbose > 2) + fprintf(stderr, "%s: %s\n", program, keystr); + + /* + * Set time values. + */ + if (setpub) + dst_key_settime(key, DST_TIME_PUBLISH, pub); + else if (unsetpub) + dst_key_unsettime(key, DST_TIME_PUBLISH); + + if (setact) + dst_key_settime(key, DST_TIME_ACTIVATE, act); + else if (unsetact) + dst_key_unsettime(key, DST_TIME_ACTIVATE); + + if (setrev) { + if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) + fprintf(stderr, "%s: warning: Key %s is already " + "revoked; changing the revocation date " + "will not affect this.\n", + program, keystr); + if ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0) + fprintf(stderr, "%s: warning: Key %s is not flagged as " + "a KSK, but -R was used. Revoking a " + "ZSK is legal, but undefined.\n", + program, keystr); + dst_key_settime(key, DST_TIME_REVOKE, rev); + } else if (unsetrev) { + if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) + fprintf(stderr, "%s: warning: Key %s is already " + "revoked; removing the revocation date " + "will not affect this.\n", + program, keystr); + dst_key_unsettime(key, DST_TIME_REVOKE); + } + + if (setinact) + dst_key_settime(key, DST_TIME_INACTIVE, inact); + else if (unsetinact) + dst_key_unsettime(key, DST_TIME_INACTIVE); + + if (setdel) + dst_key_settime(key, DST_TIME_DELETE, del); + else if (unsetdel) + dst_key_unsettime(key, DST_TIME_DELETE); + + /* + * Print out time values, if -p was used. + */ + if (printcreate) + printtime(key, DST_TIME_CREATED, "Created", epoch, stdout); + + if (printpub) + printtime(key, DST_TIME_PUBLISH, "Publish", epoch, stdout); + + if (printact) + printtime(key, DST_TIME_ACTIVATE, "Activate", epoch, stdout); + + if (printrev) + printtime(key, DST_TIME_REVOKE, "Revoke", epoch, stdout); + + if (printinact) + printtime(key, DST_TIME_INACTIVE, "Inactive", epoch, stdout); + + if (printdel) + printtime(key, DST_TIME_DELETE, "Delete", epoch, stdout); + + if (changed) { + isc_buffer_init(&buf, newname, sizeof(newname)); + result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, + &buf); + if (result != ISC_R_SUCCESS) { + fatal("Failed to build public key filename: %s", + isc_result_totext(result)); + } + + result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, + directory); + if (result != ISC_R_SUCCESS) { + dst_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); + result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, + &buf); + if (result != ISC_R_SUCCESS) { + fatal("Failed to build private key filename: %s", + isc_result_totext(result)); + } + printf("%s\n", newname); + } + + dst_key_free(&key); + dst_lib_destroy(); + isc_hash_destroy(); + cleanup_entropy(&ectx); + if (verbose > 10) + isc_mem_stats(mctx, stdout); + isc_mem_free(mctx, directory); + isc_mem_destroy(&mctx); + + return (0); +} diff --git a/contrib/bind9/bin/dnssec/dnssec-settime.docbook b/contrib/bind9/bin/dnssec/dnssec-settime.docbook new file mode 100644 index 000000000000..1096cb7ec5ae --- /dev/null +++ b/contrib/bind9/bin/dnssec/dnssec-settime.docbook @@ -0,0 +1,319 @@ +<!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, 2010 Internet Systems Consortium, Inc. ("ISC") + - + - Permission to use, copy, modify, and/or distribute this software for any + - purpose with or without fee is hereby granted, provided that the above + - copyright notice and this permission notice appear in all copies. + - + - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + - PERFORMANCE OF THIS SOFTWARE. +--> + +<!-- $Id: dnssec-settime.docbook,v 1.11 2010-08-16 22:21:06 marka Exp $ --> +<refentry id="man.dnssec-settime"> + <refentryinfo> + <date>July 15, 2009</date> + </refentryinfo> + + <refmeta> + <refentrytitle><application>dnssec-settime</application></refentrytitle> + <manvolnum>8</manvolnum> + <refmiscinfo>BIND9</refmiscinfo> + </refmeta> + + <refnamediv> + <refname><application>dnssec-settime</application></refname> + <refpurpose>Set the key timing metadata for a DNSSEC key</refpurpose> + </refnamediv> + + <docinfo> + <copyright> + <year>2009</year> + <year>2010</year> + <holder>Internet Systems Consortium, Inc. ("ISC")</holder> + </copyright> + </docinfo> + + <refsynopsisdiv> + <cmdsynopsis> + <command>dnssec-settime</command> + <arg><option>-f</option></arg> + <arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg> + <arg><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg> + <arg><option>-A <replaceable class="parameter">date/offset</replaceable></option></arg> + <arg><option>-R <replaceable class="parameter">date/offset</replaceable></option></arg> + <arg><option>-I <replaceable class="parameter">date/offset</replaceable></option></arg> + <arg><option>-D <replaceable class="parameter">date/offset</replaceable></option></arg> + <arg><option>-h</option></arg> + <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg> + <arg><option>-E <replaceable class="parameter">engine</replaceable></option></arg> + <arg choice="req">keyfile</arg> + </cmdsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>DESCRIPTION</title> + <para><command>dnssec-settime</command> + reads a DNSSEC private key file and sets the key timing metadata + as specified by the <option>-P</option>, <option>-A</option>, + <option>-R</option>, <option>-I</option>, and <option>-D</option> + options. The metadata can then be used by + <command>dnssec-signzone</command> or other signing software to + determine when a key is to be published, whether it should be + used for signing a zone, etc. + </para> + <para> + If none of these options is set on the command line, + then <command>dnssec-settime</command> simply prints the key timing + metadata already stored in the key. + </para> + <para> + When key metadata fields are changed, both files of a key + pair (<filename>Knnnn.+aaa+iiiii.key</filename> and + <filename>Knnnn.+aaa+iiiii.private</filename>) are regenerated. + Metadata fields are stored in the private file. A human-readable + description of the metadata is also placed in comments in the key + file. + </para> + </refsect1> + + <refsect1> + <title>OPTIONS</title> + + <variablelist> + <varlistentry> + <term>-f</term> + <listitem> + <para> + Force an update of an old-format key with no metadata fields. + Without this option, <command>dnssec-settime</command> will + fail when attempting to update a legacy key. With this option, + the key will be recreated in the new format, but with the + original key data retained. The key's creation date will be + set to the present time. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-K <replaceable class="parameter">directory</replaceable></term> + <listitem> + <para> + Sets the directory in which the key files are to reside. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-h</term> + <listitem> + <para> + Emit usage message and exit. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-v <replaceable class="parameter">level</replaceable></term> + <listitem> + <para> + Sets the debugging level. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-E <replaceable class="parameter">engine</replaceable></term> + <listitem> + <para> + Use the given OpenSSL engine. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>TIMING OPTIONS</title> + <para> + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. To unset a date, use 'none'. + </para> + + <variablelist> + <varlistentry> + <term>-P <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-A <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-R <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-I <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-D <replaceable class="parameter">date/offset</replaceable></term> + <listitem> + <para> + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-S <replaceable class="parameter">predecessor key</replaceable></term> + <listitem> + <para> + Select a key for which the key being modified will be an + explicit successor. The name, algorithm, size, and type of the + predecessor key must exactly match those of the key being + modified. The activation date of the successor key will be set + to the inactivation date of the predecessor. The publication + date will be set to the activation date minus the prepublication + interval, which defaults to 30 days. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-i <replaceable class="parameter">interval</replaceable></term> + <listitem> + <para> + Sets the prepublication interval for a key. If set, then + the publication and activation dates must be separated by at least + this much time. If the activation date is specified but the + publication date isn't, then the publication date will default + to this much time before the activation date; conversely, if + the publication date is specified but activation date isn't, + then activation will be set to this much time after publication. + </para> + <para> + If the key is being set to be an explicit successor to another + key, then the default prepublication interval is 30 days; + otherwise it is zero. + </para> + <para> + As with date offsets, if the argument is followed by one of + the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the + interval is measured in years, months, weeks, days, hours, + or minutes, respectively. Without a suffix, the interval is + measured in seconds. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>PRINTING OPTIONS</title> + <para> + <command>dnssec-settime</command> can also be used to print the + timing metadata associated with a key. + </para> + + <variablelist> + <varlistentry> + <term>-u</term> + <listitem> + <para> + Print times in UNIX epoch format. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-p <replaceable class="parameter">C/P/A/R/I/D/all</replaceable></term> + <listitem> + <para> + Print a specific metadata value or set of metadata values. + The <option>-p</option> option may be followed by one or more + of the following letters to indicate which value or values to print: + <option>C</option> for the creation date, + <option>P</option> for the publication date, + <option>A</option> for the activation date, + <option>R</option> for the revocation date, + <option>I</option> for the inactivation date, or + <option>D</option> for the deletion date. + To print all of the metadata, use <option>-p all</option>. + </para> + </listitem> + </varlistentry> + + </variablelist> + </refsect1> + + <refsect1> + <title>SEE ALSO</title> + <para><citerefentry> + <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum> + </citerefentry>, + <citetitle>BIND 9 Administrator Reference Manual</citetitle>, + <citetitle>RFC 5011</citetitle>. + </para> + </refsect1> + + <refsect1> + <title>AUTHOR</title> + <para><corpauthor>Internet Systems Consortium</corpauthor> + </para> + </refsect1> + +</refentry><!-- + - Local variables: + - mode: sgml + - End: +--> diff --git a/contrib/bind9/bin/dnssec/dnssec-settime.html b/contrib/bind9/bin/dnssec/dnssec-settime.html new file mode 100644 index 000000000000..84c8dde49a1d --- /dev/null +++ b/contrib/bind9/bin/dnssec/dnssec-settime.html @@ -0,0 +1,208 @@ +<!-- + - Copyright (C) 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + - + - Permission to use, copy, modify, and/or distribute this software for any + - purpose with or without fee is hereby granted, provided that the above + - copyright notice and this permission notice appear in all copies. + - + - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + - PERFORMANCE OF THIS SOFTWARE. +--> +<!-- $Id: dnssec-settime.html,v 1.14 2010-08-17 01:15:26 tbox Exp $ --> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<title>dnssec-settime</title> +<meta name="generator" content="DocBook XSL Stylesheets V1.71.1"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en"> +<a name="man.dnssec-settime"></a><div class="titlepage"></div> +<div class="refnamediv"> +<h2>Name</h2> +<p><span class="application">dnssec-settime</span> — Set the key timing metadata for a DNSSEC key</p> +</div> +<div class="refsynopsisdiv"> +<h2>Synopsis</h2> +<div class="cmdsynopsis"><p><code class="command">dnssec-settime</code> [<code class="option">-f</code>] [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-P <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-A <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-R <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-I <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-D <em class="replaceable"><code>date/offset</code></em></code>] [<code class="option">-h</code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-E <em class="replaceable"><code>engine</code></em></code>] {keyfile}</p></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543419"></a><h2>DESCRIPTION</h2> +<p><span><strong class="command">dnssec-settime</strong></span> + reads a DNSSEC private key file and sets the key timing metadata + as specified by the <code class="option">-P</code>, <code class="option">-A</code>, + <code class="option">-R</code>, <code class="option">-I</code>, and <code class="option">-D</code> + options. The metadata can then be used by + <span><strong class="command">dnssec-signzone</strong></span> or other signing software to + determine when a key is to be published, whether it should be + used for signing a zone, etc. + </p> +<p> + If none of these options is set on the command line, + then <span><strong class="command">dnssec-settime</strong></span> simply prints the key timing + metadata already stored in the key. + </p> +<p> + When key metadata fields are changed, both files of a key + pair (<code class="filename">Knnnn.+aaa+iiiii.key</code> and + <code class="filename">Knnnn.+aaa+iiiii.private</code>) are regenerated. + Metadata fields are stored in the private file. A human-readable + description of the metadata is also placed in comments in the key + file. + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543467"></a><h2>OPTIONS</h2> +<div class="variablelist"><dl> +<dt><span class="term">-f</span></dt> +<dd><p> + Force an update of an old-format key with no metadata fields. + Without this option, <span><strong class="command">dnssec-settime</strong></span> will + fail when attempting to update a legacy key. With this option, + the key will be recreated in the new format, but with the + original key data retained. The key's creation date will be + set to the present time. + </p></dd> +<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt> +<dd><p> + Sets the directory in which the key files are to reside. + </p></dd> +<dt><span class="term">-h</span></dt> +<dd><p> + Emit usage message and exit. + </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">-E <em class="replaceable"><code>engine</code></em></span></dt> +<dd><p> + Use the given OpenSSL engine. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. + </p></dd> +</dl></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543559"></a><h2>TIMING OPTIONS</h2> +<p> + Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. + If the argument begins with a '+' or '-', it is interpreted as + an offset from the present time. For convenience, if such an offset + is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', + then the offset is computed in years (defined as 365 24-hour days, + ignoring leap years), months (defined as 30 24-hour days), weeks, + days, hours, or minutes, respectively. Without a suffix, the offset + is computed in seconds. To unset a date, use 'none'. + </p> +<div class="variablelist"><dl> +<dt><span class="term">-P <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which a key is to be published to the zone. + After that date, the key will be included in the zone but will + not be used to sign it. + </p></dd> +<dt><span class="term">-A <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which the key is to be activated. After that + date, the key will be included in the zone and used to sign + it. + </p></dd> +<dt><span class="term">-R <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which the key is to be revoked. After that + date, the key will be flagged as revoked. It will be included + in the zone and will be used to sign it. + </p></dd> +<dt><span class="term">-I <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which the key is to be retired. After that + date, the key will still be included in the zone, but it + will not be used to sign it. + </p></dd> +<dt><span class="term">-D <em class="replaceable"><code>date/offset</code></em></span></dt> +<dd><p> + Sets the date on which the key is to be deleted. After that + date, the key will no longer be included in the zone. (It + may remain in the key repository, however.) + </p></dd> +<dt><span class="term">-S <em class="replaceable"><code>predecessor key</code></em></span></dt> +<dd><p> + Select a key for which the key being modified will be an + explicit successor. The name, algorithm, size, and type of the + predecessor key must exactly match those of the key being + modified. The activation date of the successor key will be set + to the inactivation date of the predecessor. The publication + date will be set to the activation date minus the prepublication + interval, which defaults to 30 days. + </p></dd> +<dt><span class="term">-i <em class="replaceable"><code>interval</code></em></span></dt> +<dd> +<p> + Sets the prepublication interval for a key. If set, then + the publication and activation dates must be separated by at least + this much time. If the activation date is specified but the + publication date isn't, then the publication date will default + to this much time before the activation date; conversely, if + the publication date is specified but activation date isn't, + then activation will be set to this much time after publication. + </p> +<p> + If the key is being set to be an explicit successor to another + key, then the default prepublication interval is 30 days; + otherwise it is zero. + </p> +<p> + As with date offsets, if the argument is followed by one of + the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', then the + interval is measured in years, months, weeks, days, hours, + or minutes, respectively. Without a suffix, the interval is + measured in seconds. + </p> +</dd> +</dl></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543698"></a><h2>PRINTING OPTIONS</h2> +<p> + <span><strong class="command">dnssec-settime</strong></span> can also be used to print the + timing metadata associated with a key. + </p> +<div class="variablelist"><dl> +<dt><span class="term">-u</span></dt> +<dd><p> + Print times in UNIX epoch format. + </p></dd> +<dt><span class="term">-p <em class="replaceable"><code>C/P/A/R/I/D/all</code></em></span></dt> +<dd><p> + Print a specific metadata value or set of metadata values. + The <code class="option">-p</code> option may be followed by one or more + of the following letters to indicate which value or values to print: + <code class="option">C</code> for the creation date, + <code class="option">P</code> for the publication date, + <code class="option">A</code> for the activation date, + <code class="option">R</code> for the revocation date, + <code class="option">I</code> for the inactivation date, or + <code class="option">D</code> for the deletion date. + To print all of the metadata, use <code class="option">-p all</code>. + </p></dd> +</dl></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543912"></a><h2>SEE ALSO</h2> +<p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>, + <span class="citerefentry"><span class="refentrytitle">dnssec-signzone</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="id2543945"></a><h2>AUTHOR</h2> +<p><span class="corpauthor">Internet Systems Consortium</span> + </p> +</div> +</div></body> +</html> diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.8 b/contrib/bind9/bin/dnssec/dnssec-signzone.8 index bfe7a2013b18..9822883747b8 100644 --- a/contrib/bind9/bin/dnssec/dnssec-signzone.8 +++ b/contrib/bind9/bin/dnssec/dnssec-signzone.8 @@ -13,18 +13,18 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: dnssec-signzone.8,v 1.47.44.8 2009-11-07 01:56:11 tbox Exp $ +.\" $Id: dnssec-signzone.8,v 1.59 2009-12-04 01:13:44 tbox Exp $ .\" .hy 0 .ad l .\" Title: dnssec\-signzone .\" Author: .\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/> -.\" Date: June 08, 2009 +.\" Date: June 05, 2009 .\" Manual: BIND9 .\" Source: BIND9 .\" -.TH "DNSSEC\-SIGNZONE" "8" "June 08, 2009" "BIND9" "BIND9" +.TH "DNSSEC\-SIGNZONE" "8" "June 05, 2009" "BIND9" "BIND9" .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) @@ -33,15 +33,13 @@ dnssec\-signzone \- DNSSEC zone signing tool .SH "SYNOPSIS" .HP 16 -\fBdnssec\-signzone\fR [\fB\-a\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIdirectory\fR\fR] [\fB\-e\ \fR\fB\fIend\-time\fR\fR] [\fB\-f\ \fR\fB\fIoutput\-file\fR\fR] [\fB\-g\fR] [\fB\-h\fR] [\fB\-k\ \fR\fB\fIkey\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-I\ \fR\fB\fIinput\-format\fR\fR] [\fB\-j\ \fR\fB\fIjitter\fR\fR] [\fB\-N\ \fR\fB\fIsoa\-serial\-format\fR\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-O\ \fR\fB\fIoutput\-format\fR\fR] [\fB\-p\fR] [\fB\-P\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-s\ \fR\fB\fIstart\-time\fR\fR] [\fB\-t\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-z\fR] [\fB\-3\ \fR\fB\fIsalt\fR\fR] [\fB\-H\ \fR\fB\fIiterations\fR\fR] [\fB\-A\fR] {zonefile} [key...] +\fBdnssec\-signzone\fR [\fB\-a\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIdirectory\fR\fR] [\fB\-E\ \fR\fB\fIengine\fR\fR] [\fB\-e\ \fR\fB\fIend\-time\fR\fR] [\fB\-f\ \fR\fB\fIoutput\-file\fR\fR] [\fB\-g\fR] [\fB\-h\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-k\ \fR\fB\fIkey\fR\fR] [\fB\-l\ \fR\fB\fIdomain\fR\fR] [\fB\-i\ \fR\fB\fIinterval\fR\fR] [\fB\-I\ \fR\fB\fIinput\-format\fR\fR] [\fB\-j\ \fR\fB\fIjitter\fR\fR] [\fB\-N\ \fR\fB\fIsoa\-serial\-format\fR\fR] [\fB\-o\ \fR\fB\fIorigin\fR\fR] [\fB\-O\ \fR\fB\fIoutput\-format\fR\fR] [\fB\-p\fR] [\fB\-P\fR] [\fB\-r\ \fR\fB\fIrandomdev\fR\fR] [\fB\-S\fR] [\fB\-s\ \fR\fB\fIstart\-time\fR\fR] [\fB\-T\ \fR\fB\fIttl\fR\fR] [\fB\-t\fR] [\fB\-u\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fB\-x\fR] [\fB\-z\fR] [\fB\-3\ \fR\fB\fIsalt\fR\fR] [\fB\-H\ \fR\fB\fIiterations\fR\fR] [\fB\-A\fR] {zonefile} [key...] .SH "DESCRIPTION" .PP \fBdnssec\-signzone\fR -signs a zone. It generates NSEC and RRSIG records and produces a signed version of the zone. It also generates a -\fIkeyset\-\fR -file containing the key\-signing keys for the zone, and if signing a zone which contains delegations, it can optionally generate DS records for the child zones from their -\fIkeyset\-\fR -files. +signs a zone. It generates NSEC and RRSIG records and produces a signed version of the zone. The security status of delegations from the signed zone (that is, whether the child zones are secure or not) is determined by the presence or absence of a +\fIkeyset\fR +file for each child zone. .SH "OPTIONS" .PP \-a @@ -54,30 +52,53 @@ Verify all generated signatures. Specifies the DNS class of the zone. .RE .PP -\-k \fIkey\fR -.RS 4 -Treat specified key as a key signing key ignoring any key flags. This option may be specified multiple times. -.RE -.PP -\-l \fIdomain\fR +\-C .RS 4 -Generate a DLV set in addition to the key (DNSKEY) and DS sets. The domain is appended to the name of the records. +Compatibility mode: Generate a +\fIkeyset\-\fR\fI\fIzonename\fR\fR +file in addition to +\fIdsset\-\fR\fI\fIzonename\fR\fR +when signing a zone, for use by older versions of +\fBdnssec\-signzone\fR. .RE .PP \-d \fIdirectory\fR .RS 4 Look for -\fIkeyset\fR +\fIdsset\-\fR +or +\fIkeyset\-\fR files in -\fBdirectory\fR -as the directory +\fBdirectory\fR. +.RE +.PP +\-E \fIengine\fR +.RS 4 +Uses a crypto hardware (OpenSSL engine) for the crypto operations it supports, for instance signing with private keys from a secure key store. When compiled with PKCS#11 support it defaults to pkcs11; the empty name resets it to no engine. .RE .PP \-g .RS 4 -If the zone contains any delegations, and there are +Generate DS records for child zones from +\fIdsset\-\fR +or \fIkeyset\-\fR -files for any of the child zones, then DS records for the child zones will be generated from the keys in those files. Existing DS records will be removed. +file. Existing DS records will be removed. +.RE +.PP +\-K \fIdirectory\fR +.RS 4 +Key repository: Specify a directory to search for DNSSEC keys. If not specified, defaults to the current directory. +.RE +.PP +\-k \fIkey\fR +.RS 4 +Treat specified key as a key signing key ignoring any key flags. This option may be specified multiple times. +.RE +.PP +\-l \fIdomain\fR +.RS 4 +Generate a DLV set in addition to the key (DNSKEY) and DS sets. The domain is appended to the name of the records. .RE .PP \-s \fIstart\-time\fR @@ -93,6 +114,9 @@ Specify the date and time when the generated RRSIG records expire. As with \fBstart\-time\fR, an absolute time is indicated in YYYYMMDDHHMMSS notation. A time relative to the start time is indicated with +N, which is N seconds from the start time. A time relative to the current time is indicated with now+N. If no \fBend\-time\fR is specified, 30 days from the start time is used as a default. +\fBend\-time\fR +must be later than +\fBstart\-time\fR. .RE .PP \-f \fIoutput\-file\fR @@ -208,34 +232,94 @@ specifies the name of a character device or file containing random data to be us indicates that keyboard input should be used. .RE .PP +\-S +.RS 4 +Smart signing: Instructs +\fBdnssec\-signzone\fR +to search the key repository for keys that match the zone being signed, and to include them in the zone if appropriate. +.sp +When a key is found, its timing metadata is examined to determine how it should be used, according to the following rules. Each successive rule takes priority over the prior ones: +.RS 4 +.PP +.RS 4 +If no timing metadata has been set for the key, the key is published in the zone and used to sign the zone. +.RE +.PP +.RS 4 +If the key's publication date is set and is in the past, the key is published in the zone. +.RE +.PP +.RS 4 +If the key's activation date is set and in the past, the key is published (regardless of publication date) and used to sign the zone. +.RE +.PP +.RS 4 +If the key's revocation date is set and in the past, and the key is published, then the key is revoked, and the revoked key is used to sign the zone. +.RE +.PP +.RS 4 +If either of the key's unpublication or deletion dates are set and in the past, the key is NOT published or used to sign the zone, regardless of any other metadata. +.RE +.RE +.RE +.PP +\-T \fIttl\fR +.RS 4 +Specifies the TTL to be used for new DNSKEY records imported into the zone from the key repository. If not specified, the default is the minimum TTL value from the zone's SOA record. This option is ignored when signing without +\fB\-S\fR, since DNSKEY records are not imported from the key repository in that case. It is also ignored if there are any pre\-existing DNSKEY records at the zone apex, in which case new records' TTL values will be set to match them. +.RE +.PP \-t .RS 4 Print statistics at completion. .RE .PP +\-u +.RS 4 +Update NSEC/NSEC3 chain when re\-signing a previously signed zone. With this option, a zone signed with NSEC can be switched to NSEC3, or a zone signed with NSEC3 can be switch to NSEC or to NSEC3 with different parameters. Without this option, +\fBdnssec\-signzone\fR +will retain the existing chain when re\-signing. +.RE +.PP \-v \fIlevel\fR .RS 4 Sets the debugging level. .RE .PP +\-x +.RS 4 +Only sign the DNSKEY RRset with key\-signing keys, and omit signatures from zone\-signing keys. (This is similar to the +\fBdnssec\-dnskey\-kskonly yes;\fR +zone option in +\fBnamed\fR.) +.RE +.PP \-z .RS 4 -Ignore KSK flag on key when determining what to sign. +Ignore KSK flag on key when determining what to sign. This causes KSK\-flagged keys to sign all records, not just the DNSKEY RRset. (This is similar to the +\fBupdate\-check\-ksk no;\fR +zone option in +\fBnamed\fR.) .RE .PP \-3 \fIsalt\fR .RS 4 -Generate a NSEC3 chain with the given hex encoded salt. A dash (\fIsalt\fR) can be used to indicate that no salt is to be used when generating the NSEC3 chain. +Generate an NSEC3 chain with the given hex encoded salt. A dash (\fIsalt\fR) can be used to indicate that no salt is to be used when generating the NSEC3 chain. .RE .PP \-H \fIiterations\fR .RS 4 -When generating a NSEC3 chain use this many interations. The default is 100. +When generating an NSEC3 chain, use this many interations. The default is 10. .RE .PP \-A .RS 4 -When generating a NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations. +When generating an NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations. +.sp +Using this option twice (i.e., +\fB\-AA\fR) turns the OPTOUT flag off for all records. This is useful when using the +\fB\-u\fR +option to modify an NSEC3 chain which previously had OPTOUT set. .RE .PP zonefile @@ -253,9 +337,11 @@ The following command signs the \fBexample.com\fR zone with the DSA key generated by \fBdnssec\-keygen\fR -(Kexample.com.+003+17247). The zone's keys must be in the master file (\fIdb.example.com\fR). This invocation looks for -\fIkeyset\fR -files, in the current directory, so that DS records can be generated from them (\fB\-g\fR). +(Kexample.com.+003+17247). Because the +\fB\-S\fR +option is not being used, the zone's keys must be in the master file (\fIdb.example.com\fR). This invocation looks for +\fIdsset\fR +files, in the current directory, so that DS records can be imported from them (\fB\-g\fR). .sp .RS 4 .nf @@ -283,18 +369,6 @@ db.example.com.signed % .fi .RE -.SH "KNOWN BUGS" -.PP -\fBdnssec\-signzone\fR -was designed so that it could sign a zone partially, using only a subset of the DNSSEC keys needed to produce a fully\-signed zone. This permits a zone administrator, for example, to sign a zone with one key on one machine, move the resulting partially\-signed zone to a second machine, and sign it again with a second key. -.PP -An unfortunate side\-effect of this flexibility is that -\fBdnssec\-signzone\fR -does not check to make sure it's signing a zone with any valid keys at all. An attempt to sign a zone without any keys will appear to succeed, producing a "signed" zone with no signatures. There is no warning issued when a zone is not fully signed. -.PP -This will be corrected in a future release. In the meantime, ISC recommends examining the output of -\fBdnssec\-signzone\fR -to confirm that the zone is properly signed by all keys before using it. .SH "SEE ALSO" .PP \fBdnssec\-keygen\fR(8), diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.c b/contrib/bind9/bin/dnssec/dnssec-signzone.c index b8f4d664b6da..3997a135b465 100644 --- a/contrib/bind9/bin/dnssec/dnssec-signzone.c +++ b/contrib/bind9/bin/dnssec/dnssec-signzone.c @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-signzone.c,v 1.209.12.20 2010-06-03 23:47:48 tbox Exp $ */ +/* $Id: dnssec-signzone.c,v 1.262 2010-06-03 23:51:04 tbox Exp $ */ /*! \file */ @@ -87,6 +87,10 @@ #include "dnssectool.h" +#ifndef PATH_MAX +#define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */ +#endif + const char *program = "dnssec-signzone"; int verbose; @@ -97,22 +101,11 @@ static int nsec_datatype = dns_rdatatype_nsec; #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3) #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0) +#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0) + #define BUFSIZE 2048 #define MAXDSKEYS 8 -typedef struct signer_key_struct signer_key_t; - -struct signer_key_struct { - dst_key_t *key; - isc_boolean_t issigningkey; - isc_boolean_t isdsk; - isc_boolean_t isksk; - isc_boolean_t wasused; - isc_boolean_t commandline; - unsigned int position; - ISC_LINK(signer_key_t) link; -}; - #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453) #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0) #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1) @@ -128,7 +121,7 @@ struct signer_event { dns_dbnode_t *node; }; -static ISC_LIST(signer_key_t) keylist; +static dns_dnsseckeylist_t keylist; static unsigned int keycount = 0; isc_rwlock_t keylist_lock; static isc_stdtime_t starttime = 0, endtime = 0, now; @@ -138,7 +131,8 @@ static isc_boolean_t tryverify = ISC_FALSE; static isc_boolean_t printstats = ISC_FALSE; static isc_mem_t *mctx = NULL; static isc_entropy_t *ectx = NULL; -static dns_ttl_t zonettl; +static dns_ttl_t zone_soa_min_ttl; +static dns_ttl_t soa_ttl; static FILE *fp; static char *tempfile = NULL; static const dns_master_style_t *masterstyle; @@ -146,7 +140,7 @@ static dns_masterformat_t inputformat = dns_masterformat_text; static dns_masterformat_t outputformat = dns_masterformat_text; static unsigned int nsigned = 0, nretained = 0, ndropped = 0; static unsigned int nverified = 0, nverifyfailed = 0; -static const char *directory; +static const char *directory = NULL, *dsdir = NULL; static isc_mutex_t namelock, statslock; static isc_taskmgr_t *taskmgr = NULL; static dns_db_t *gdb; /* The database */ @@ -155,13 +149,18 @@ static dns_dbiterator_t *gdbiter; /* The database iterator */ static dns_rdataclass_t gclass; /* The class */ static dns_name_t *gorigin; /* The database origin */ static int nsec3flags = 0; +static dns_iterations_t nsec3iter = 10U; +static unsigned char saltbuf[255]; +static unsigned char *salt = saltbuf; +static size_t salt_length = 0; static isc_task_t *master = NULL; static unsigned int ntasks = 0; static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE; static isc_boolean_t nokeys = ISC_FALSE; static isc_boolean_t removefile = ISC_FALSE; static isc_boolean_t generateds = ISC_FALSE; -static isc_boolean_t ignoreksk = ISC_FALSE; +static isc_boolean_t ignore_kskflag = ISC_FALSE; +static isc_boolean_t keyset_kskonly = ISC_FALSE; static dns_name_t *dlv = NULL; static dns_fixedname_t dlv_fixed; static dns_master_style_t *dsstyle = NULL; @@ -169,6 +168,9 @@ static unsigned int serialformat = SOA_SERIAL_KEEP; static unsigned int hash_length = 0; static isc_boolean_t unknownalg = ISC_FALSE; static isc_boolean_t disable_zone_check = ISC_FALSE; +static isc_boolean_t update_chain = ISC_FALSE; +static isc_boolean_t set_keyttl = ISC_FALSE; +static dns_ttl_t keyttl; #define INCSTAT(counter) \ if (printstats) { \ @@ -195,48 +197,23 @@ dumpnode(dns_name_t *name, dns_dbnode_t *node) { check_result(result, "dns_master_dumpnodetostream"); } -static signer_key_t * -newkeystruct(dst_key_t *dstkey, isc_boolean_t signwithkey) { - signer_key_t *key; - - key = isc_mem_get(mctx, sizeof(signer_key_t)); - if (key == NULL) - fatal("out of memory"); - key->key = dstkey; - if ((dst_key_flags(dstkey) & DNS_KEYFLAG_KSK) != 0) { - key->issigningkey = signwithkey; - key->isksk = ISC_TRUE; - key->isdsk = ISC_FALSE; - } else { - key->issigningkey = signwithkey; - key->isksk = ISC_FALSE; - key->isdsk = ISC_TRUE; - } - key->wasused = ISC_FALSE; - key->commandline = ISC_FALSE; - key->position = keycount++; - ISC_LINK_INIT(key, link); - return (key); -} - /*% * Sign the given RRset with given key, and add the signature record to the * given tuple. */ - static void signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key, dns_ttl_t ttl, dns_diff_t *add, const char *logmsg) { isc_result_t result; isc_stdtime_t jendtime; - char keystr[KEY_FORMATSIZE]; + char keystr[DST_KEY_FORMATSIZE]; dns_rdata_t trdata = DNS_RDATA_INIT; unsigned char array[BUFSIZE]; isc_buffer_t b; dns_difftuple_t *tuple; - key_format(key, keystr, sizeof(keystr)); + dst_key_format(key, keystr, sizeof(keystr)); vbprintf(1, "\t%s %s\n", logmsg, keystr); jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime; @@ -245,8 +222,8 @@ signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key, mctx, &b, &trdata); isc_entropy_stopcallbacksources(ectx); if (result != ISC_R_SUCCESS) { - char keystr[KEY_FORMATSIZE]; - key_format(key, keystr, sizeof(keystr)); + char keystr[DST_KEY_FORMATSIZE]; + dst_key_format(key, keystr, sizeof(keystr)); fatal("dnskey '%s' failed to sign data: %s", keystr, isc_result_totext(result)); } @@ -272,31 +249,43 @@ signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key, } static inline isc_boolean_t -issigningkey(signer_key_t *key) { - return (key->issigningkey); +issigningkey(dns_dnsseckey_t *key) { + return (key->force_sign || key->hint_sign); } static inline isc_boolean_t -iszonekey(signer_key_t *key) { +iszonekey(dns_dnsseckey_t *key) { return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) && dst_key_iszonekey(key->key))); } +static inline isc_boolean_t +isksk(dns_dnsseckey_t *key) { + return (key->ksk); +} + +static inline isc_boolean_t +iszsk(dns_dnsseckey_t *key) { + return (ignore_kskflag || !key->ksk); +} + /*% - * Find the key if it is in our list. If it is, return it, otherwise null. + * Find the key that generated an RRSIG, if it is in the key list. If + * so, return a pointer to it, otherwise return NULL. + * * No locking is performed here, this must be done by the caller. */ -static signer_key_t * +static dns_dnsseckey_t * keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) { - signer_key_t *key; + dns_dnsseckey_t *key; - key = ISC_LIST_HEAD(keylist); - while (key != NULL) { + for (key = ISC_LIST_HEAD(keylist); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { if (rrsig->keyid == dst_key_id(key->key) && rrsig->algorithm == dst_key_alg(key->key) && dns_name_equal(&rrsig->signer, dst_key_name(key->key))) return (key); - key = ISC_LIST_NEXT(key, link); } return (NULL); } @@ -305,11 +294,11 @@ keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) { * Finds the key that generated a RRSIG, if possible. First look at the keys * that we've loaded already, and then see if there's a key on disk. */ -static signer_key_t * +static dns_dnsseckey_t * keythatsigned(dns_rdata_rrsig_t *rrsig) { isc_result_t result; dst_key_t *pubkey = NULL, *privkey = NULL; - signer_key_t *key; + dns_dnsseckey_t *key = NULL; isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read); key = keythatsigned_unlocked(rrsig); @@ -325,7 +314,6 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) { * after all. */ isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write); - key = keythatsigned_unlocked(rrsig); if (key != NULL) { isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); @@ -334,7 +322,7 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) { result = dst_key_fromfile(&rrsig->signer, rrsig->keyid, rrsig->algorithm, DST_TYPE_PUBLIC, - NULL, mctx, &pubkey); + directory, mctx, &pubkey); if (result != ISC_R_SUCCESS) { isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); return (NULL); @@ -343,12 +331,15 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) { result = dst_key_fromfile(&rrsig->signer, rrsig->keyid, rrsig->algorithm, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, - NULL, mctx, &privkey); + directory, mctx, &privkey); if (result == ISC_R_SUCCESS) { dst_key_free(&pubkey); - key = newkeystruct(privkey, ISC_FALSE); - } else - key = newkeystruct(pubkey, ISC_FALSE); + dns_dnsseckey_create(mctx, &privkey, &key); + } else { + dns_dnsseckey_create(mctx, &pubkey, &key); + } + key->force_publish = ISC_TRUE; + key->force_sign = ISC_FALSE; ISC_LIST_APPEND(keylist, key, link); isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); @@ -383,15 +374,16 @@ expecttofindkey(dns_name_t *name) { dns_name_format(name, namestr, sizeof(namestr)); fatal("failure looking for '%s DNSKEY' in database: %s", namestr, isc_result_totext(result)); + /* NOTREACHED */ return (ISC_FALSE); /* removes a warning */ } static inline isc_boolean_t -setverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key, +setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, dns_rdata_t *rrsig) { isc_result_t result; - result = dns_dnssec_verify(name, set, key->key, ISC_FALSE, mctx, rrsig); + result = dns_dnssec_verify(name, set, key, ISC_FALSE, mctx, rrsig); if (result == ISC_R_SUCCESS) { INCSTAT(nverified); return (ISC_TRUE); @@ -413,7 +405,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, dns_rdataset_t sigset; dns_rdata_t sigrdata = DNS_RDATA_INIT; dns_rdata_rrsig_t rrsig; - signer_key_t *key; + dns_dnsseckey_t *key; isc_result_t result; isc_boolean_t nosigs = ISC_FALSE; isc_boolean_t *wassignedby, *nowsignedby; @@ -483,8 +475,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, "invalid validity period\n", sigstr); } else if (key == NULL && !future && - expecttofindkey(&rrsig.signer)) - { + expecttofindkey(&rrsig.signer)) { /* rrsig is dropped and not replaced */ vbprintf(2, "\trrsig by %s dropped - " "private dnskey not found\n", @@ -495,35 +486,33 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, if (!expired) keep = ISC_TRUE; } else if (issigningkey(key)) { - if (!expired && setverifies(name, set, key, &sigrdata)) - { + if (!expired && setverifies(name, set, key->key, + &sigrdata)) { vbprintf(2, "\trrsig by %s retained\n", sigstr); keep = ISC_TRUE; - wassignedby[key->position] = ISC_TRUE; - nowsignedby[key->position] = ISC_TRUE; - key->wasused = ISC_TRUE; + wassignedby[key->index] = ISC_TRUE; + nowsignedby[key->index] = ISC_TRUE; } else { vbprintf(2, "\trrsig by %s dropped - %s\n", sigstr, expired ? "expired" : "failed to verify"); - wassignedby[key->position] = ISC_TRUE; + wassignedby[key->index] = ISC_TRUE; resign = ISC_TRUE; } } else if (iszonekey(key)) { - if (!expired && setverifies(name, set, key, &sigrdata)) - { + if (!expired && setverifies(name, set, key->key, + &sigrdata)) { vbprintf(2, "\trrsig by %s retained\n", sigstr); keep = ISC_TRUE; - wassignedby[key->position] = ISC_TRUE; - nowsignedby[key->position] = ISC_TRUE; - key->wasused = ISC_TRUE; + wassignedby[key->index] = ISC_TRUE; + nowsignedby[key->index] = ISC_TRUE; } else { vbprintf(2, "\trrsig by %s dropped - %s\n", sigstr, expired ? "expired" : "failed to verify"); - wassignedby[key->position] = ISC_TRUE; + wassignedby[key->index] = ISC_TRUE; } } else if (!expired) { vbprintf(2, "\trrsig by %s retained\n", sigstr); @@ -533,7 +522,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, } if (keep) { - nowsignedby[key->position] = ISC_TRUE; + nowsignedby[key->index] = ISC_TRUE; INCSTAT(nretained); if (sigset.ttl != ttl) { vbprintf(2, "\tfixing ttl %s\n", sigstr); @@ -568,8 +557,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, signwithkey(name, set, key->key, ttl, add, "resigning with dnskey"); - nowsignedby[key->position] = ISC_TRUE; - key->wasused = ISC_TRUE; + nowsignedby[key->index] = ISC_TRUE; } dns_rdata_reset(&sigrdata); @@ -587,20 +575,37 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, key != NULL; key = ISC_LIST_NEXT(key, link)) { - if (nowsignedby[key->position]) + if (nowsignedby[key->index]) continue; - if (!key->issigningkey) - continue; - if (!(ignoreksk || key->isdsk || - (key->isksk && - set->type == dns_rdatatype_dnskey && - dns_name_equal(name, gorigin)))) + if (!issigningkey(key)) continue; - signwithkey(name, set, key->key, ttl, add, - "signing with dnskey"); - key->wasused = ISC_TRUE; + if (set->type == dns_rdatatype_dnskey && + dns_name_equal(name, gorigin)) { + isc_boolean_t have_ksk; + dns_dnsseckey_t *tmpkey; + + have_ksk = isksk(key); + for (tmpkey = ISC_LIST_HEAD(keylist); + tmpkey != NULL; + tmpkey = ISC_LIST_NEXT(tmpkey, link)) { + if (dst_key_alg(key->key) != + dst_key_alg(tmpkey->key)) + continue; + if (REVOKE(tmpkey->key)) + continue; + if (isksk(tmpkey)) + have_ksk = ISC_TRUE; + } + if (isksk(key) || !have_ksk || + (iszsk(key) && !keyset_kskonly)) + signwithkey(name, set, key->key, ttl, add, + "signing with dnskey"); + } else if (iszsk(key)) { + signwithkey(name, set, key->key, ttl, add, + "signing with dnskey"); + } } isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t)); @@ -774,16 +779,21 @@ static void opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp) { - char filename[256]; + char filename[PATH_MAX]; isc_buffer_t b; isc_result_t result; isc_buffer_init(&b, filename, sizeof(filename)); - if (directory != NULL) { - isc_buffer_putstr(&b, directory); - if (directory[strlen(directory) - 1] != '/') + if (dsdir != NULL) { + /* allow room for a trailing slash */ + if (strlen(dsdir) >= isc_buffer_availablelength(&b)) + fatal("path '%s' is too long", dsdir); + isc_buffer_putstr(&b, dsdir); + if (dsdir[strlen(dsdir) - 1] != '/') isc_buffer_putstr(&b, "/"); } + if (strlen(prefix) > isc_buffer_availablelength(&b)) + fatal("path '%s' is too long", dsdir); isc_buffer_putstr(&b, prefix); result = dns_name_tofilenametext(name, ISC_FALSE, &b); check_result(result, "dns_name_tofilenametext()"); @@ -798,13 +808,15 @@ opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass, rdclass, 0, NULL, dbp); check_result(result, "dns_db_create()"); - result = dns_db_load(*dbp, filename); + result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT); if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) dns_db_detach(dbp); } /*% - * Loads the key set for a child zone, if there is one, and builds DS records. + * Load the DS set for a child zone, if a dsset-* file can be found. + * If not, try to find a keyset-* file from an earlier version of + * dnssec-signzone, and build DS records from that. */ static isc_result_t loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) { @@ -818,29 +830,49 @@ loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) { dns_diff_t diff; dns_difftuple_t *tuple = NULL; + opendb("dsset-", name, gclass, &db); + if (db != NULL) { + result = dns_db_findnode(db, name, ISC_FALSE, &node); + if (result == ISC_R_SUCCESS) { + dns_rdataset_init(dsset); + result = dns_db_findrdataset(db, node, NULL, + dns_rdatatype_ds, 0, 0, + dsset, NULL); + dns_db_detachnode(db, &node); + if (result == ISC_R_SUCCESS) { + vbprintf(2, "found DS records\n"); + dsset->ttl = ttl; + dns_db_detach(&db); + return (result); + } + } + dns_db_detach(&db); + } + + /* No DS records found; try again, looking for DNSKEY records */ opendb("keyset-", name, gclass, &db); - if (db == NULL) + if (db == NULL) { return (ISC_R_NOTFOUND); + } result = dns_db_findnode(db, name, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) { dns_db_detach(&db); - return (DNS_R_BADDB); + return (result); } + dns_rdataset_init(&keyset); - result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, - 0, &keyset, NULL); + result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0, + &keyset, NULL); if (result != ISC_R_SUCCESS) { dns_db_detachnode(db, &node); dns_db_detach(&db); return (result); } - vbprintf(2, "found DNSKEY records\n"); result = dns_db_newversion(db, &ver); check_result(result, "dns_db_newversion"); - dns_diff_init(mctx, &diff); for (result = dns_rdataset_first(&keyset); @@ -869,6 +901,7 @@ loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) { check_result(result, "dns_difftuple_create"); dns_diff_append(&diff, &tuple); } + result = dns_diff_apply(&diff, db, ver); check_result(result, "dns_diff_apply"); dns_diff_clear(&diff); @@ -1112,17 +1145,15 @@ active_node(dns_dbnode_t *node) { } /*% - * Extracts the TTL from the SOA. + * Extracts the minimum TTL from the SOA record, and the SOA record's TTL. */ -static dns_ttl_t -soattl(void) { +static void +get_soa_ttls(void) { dns_rdataset_t soaset; dns_fixedname_t fname; dns_name_t *name; isc_result_t result; - dns_ttl_t ttl; dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdata_soa_t soa; dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); @@ -1136,11 +1167,9 @@ soattl(void) { result = dns_rdataset_first(&soaset); check_result(result, "dns_rdataset_first"); dns_rdataset_current(&soaset, &rdata); - result = dns_rdata_tostruct(&rdata, &soa, NULL); - check_result(result, "dns_rdata_tostruct"); - ttl = soa.minimum; + zone_soa_min_ttl = dns_soa_getminimum(&rdata); + soa_ttl = soaset.ttl; dns_rdataset_disassociate(&soaset); - return (ttl); } /*% @@ -1371,7 +1400,7 @@ verifyset(dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node, for (i = 0; i < 256; i++) if ((ksk_algorithms[i] != 0) && (set_algorithms[i] == 0)) { - alg_format(i, algbuf, sizeof(algbuf)); + dns_secalg_format(i, algbuf, sizeof(algbuf)); fprintf(stderr, "Missing %s signature for " "%s %s\n", algbuf, namebuf, typebuf); bad_algorithms[i] = 1; @@ -1414,8 +1443,8 @@ verifynode(dns_name_t *name, dns_dbnode_t *node, isc_boolean_t delegation, /*% * Verify that certain things are sane: * - * The apex has a DNSKEY record with at least one KSK and at least - * one ZSK. + * The apex has a DNSKEY record with at least one KSK, and at least + * one ZSK if the -x flag was not used. * * The DNSKEY record was signed with at least one of the KSKs in this * set. @@ -1440,8 +1469,10 @@ verifyzone(void) { isc_boolean_t goodksk = ISC_FALSE; isc_boolean_t goodzsk = ISC_FALSE; isc_result_t result; - unsigned char revoked[256]; - unsigned char standby[256]; + unsigned char revoked_ksk[256]; + unsigned char revoked_zsk[256]; + unsigned char standby_ksk[256]; + unsigned char standby_zsk[256]; unsigned char ksk_algorithms[256]; unsigned char zsk_algorithms[256]; unsigned char bad_algorithms[256]; @@ -1470,8 +1501,10 @@ verifyzone(void) { if (!dns_rdataset_isassociated(&sigrdataset)) fatal("cannot find DNSKEY RRSIGs\n"); - memset(revoked, 0, sizeof(revoked)); - memset(standby, 0, sizeof(revoked)); + memset(revoked_ksk, 0, sizeof(revoked_ksk)); + memset(revoked_zsk, 0, sizeof(revoked_zsk)); + memset(standby_ksk, 0, sizeof(standby_ksk)); + memset(standby_zsk, 0, sizeof(standby_zsk)); memset(ksk_algorithms, 0, sizeof(ksk_algorithms)); memset(zsk_algorithms, 0, sizeof(zsk_algorithms)); memset(bad_algorithms, 0, sizeof(bad_algorithms)); @@ -1480,8 +1513,9 @@ verifyzone(void) { #endif /* - * Check that the DNSKEY RR has at least one self signing KSK and - * one ZSK per algorithm in it. + * Check that the DNSKEY RR has at least one self signing KSK + * and one ZSK per algorithm in it (or, if -x was used, one + * self-signing KSK). */ for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; @@ -1511,8 +1545,11 @@ verifyzone(void) { (int)isc_buffer_usedlength(&buf), buffer); } if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && - revoked[dnskey.algorithm] != 255) - revoked[dnskey.algorithm]++; + revoked_ksk[dnskey.algorithm] != 255) + revoked_ksk[dnskey.algorithm]++; + else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && + revoked_zsk[dnskey.algorithm] != 255) + revoked_zsk[dnskey.algorithm]++; } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) { if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset, &sigrdataset, ISC_FALSE, mctx)) { @@ -1520,8 +1557,8 @@ verifyzone(void) { ksk_algorithms[dnskey.algorithm]++; goodksk = ISC_TRUE; } else { - if (standby[dnskey.algorithm] != 255) - standby[dnskey.algorithm]++; + if (standby_ksk[dnskey.algorithm] != 255) + standby_ksk[dnskey.algorithm]++; } } else if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset, &sigrdataset, ISC_FALSE, @@ -1534,8 +1571,8 @@ verifyzone(void) { zsk_algorithms[dnskey.algorithm]++; goodzsk = ISC_TRUE; } else { - if (zsk_algorithms[dnskey.algorithm] != 255) - zsk_algorithms[dnskey.algorithm]++; + if (standby_zsk[dnskey.algorithm] != 255) + standby_zsk[dnskey.algorithm]++; #ifdef ALLOW_KSKLESS_ZONES allzsksigned = ISC_FALSE; #endif @@ -1545,42 +1582,54 @@ verifyzone(void) { } dns_rdataset_disassociate(&sigrdataset); - if (!goodksk) { #ifdef ALLOW_KSKLESS_ZONES - if (!goodzsk) - fatal("no self signing keys found"); - fprintf(stderr, "No self signing KSK found. Using self signed " - "ZSK's for active algorithm list.\n"); + if (!goodksk) { + if (!ignore_kskflag) + fprintf(stderr, "No self signing KSK found. Using " + "self signed ZSK's for active " + "algorithm list.\n"); memcpy(ksk_algorithms, self_algorithms, sizeof(ksk_algorithms)); if (!allzsksigned) fprintf(stderr, "warning: not all ZSK's are self " "signed.\n"); + } #else + if (!goodksk) { fatal("no self signed KSK's found"); -#endif } +#endif fprintf(stderr, "Verifying the zone using the following algorithms:"); for (i = 0; i < 256; i++) { - if (ksk_algorithms[i] != 0) { - alg_format(i, algbuf, sizeof(algbuf)); +#ifdef ALLOW_KSKLESS_ZONES + if (ksk_algorithms[i] != 0 || zsk_algorithms[i] != 0) +#else + if (ksk_algorithms[i] != 0) +#endif + { + dns_secalg_format(i, algbuf, sizeof(algbuf)); fprintf(stderr, " %s", algbuf); } } fprintf(stderr, ".\n"); - for (i = 0; i < 256; i++) { - /* - * The counts should both be zero or both be non-zero. - * Mark the algorithm as bad if this is not met. - */ - if ((ksk_algorithms[i] != 0) == (zsk_algorithms[i] != 0)) - continue; - alg_format(i, algbuf, sizeof(algbuf)); - fprintf(stderr, "Missing %s for algorithm %s\n", - (ksk_algorithms[i] != 0) ? "ZSK" : "self signing KSK", - algbuf); - bad_algorithms[i] = 1; + if (!ignore_kskflag && !keyset_kskonly) { + for (i = 0; i < 256; i++) { + /* + * The counts should both be zero or both be non-zero. + * Mark the algorithm as bad if this is not met. + */ + if ((ksk_algorithms[i] != 0) == + (zsk_algorithms[i] != 0)) + continue; + dns_secalg_format(i, algbuf, sizeof(algbuf)); + fprintf(stderr, "Missing %s for algorithm %s\n", + (ksk_algorithms[i] != 0) + ? "ZSK" + : "self signing KSK", + algbuf); + bad_algorithms[i] = 1; + } } /* @@ -1674,7 +1723,7 @@ verifyzone(void) { if (first) fprintf(stderr, "The zone is not fully signed " "for the following algorithms:"); - alg_format(i, algbuf, sizeof(algbuf)); + dns_secalg_format(i, algbuf, sizeof(algbuf)); fprintf(stderr, " %s", algbuf); first = ISC_FALSE; } @@ -1684,21 +1733,30 @@ verifyzone(void) { fatal("DNSSEC completeness test failed."); } - if (goodksk) { + if (goodksk || ignore_kskflag) { /* * Print the success summary. */ fprintf(stderr, "Zone signing complete:\n"); for (i = 0; i < 256; i++) { - if ((zsk_algorithms[i] != 0) || - (ksk_algorithms[i] != 0) || - (revoked[i] != 0) || (standby[i] != 0)) { - alg_format(i, algbuf, sizeof(algbuf)); - fprintf(stderr, "Algorithm: %s: ZSKs: %u, " - "KSKs: %u active, %u revoked, %u " - "stand-by\n", algbuf, - zsk_algorithms[i], ksk_algorithms[i], - revoked[i], standby[i]); + if ((ksk_algorithms[i] != 0) || + (standby_ksk[i] != 0) || + (revoked_zsk[i] != 0) || + (zsk_algorithms[i] != 0) || + (standby_zsk[i] != 0) || + (revoked_zsk[i] != 0)) { + dns_secalg_format(i, algbuf, sizeof(algbuf)); + fprintf(stderr, "Algorithm: %s: KSKs: " + "%u active, %u stand-by, %u revoked\n", + algbuf, ksk_algorithms[i], + standby_ksk[i], revoked_ksk[i]); + fprintf(stderr, "%*sZSKs: " + "%u active, %u %s, %u revoked\n", + (int) strlen(algbuf) + 13, "", + zsk_algorithms[i], + standby_zsk[i], + keyset_kskonly ? "present" : "stand-by", + revoked_zsk[i]); } } } @@ -1923,6 +1981,7 @@ add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) { dns_rdatatype_ds, 0); check_result(result, "dns_db_deleterdataset"); } + result = loadds(name, nsttl, &dsset); if (result == ISC_R_SUCCESS) { result = dns_db_addrdataset(gdb, node, gversion, 0, @@ -1953,7 +2012,7 @@ remove_records(dns_dbnode_t *node, dns_rdatatype_t which) { dns_rdataset_init(&rdataset); /* - * Delete any NSEC records at the apex. + * Delete any records of the given type at the apex. */ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); check_result(result, "dns_db_allrdatasets()"); @@ -1965,6 +2024,12 @@ remove_records(dns_dbnode_t *node, dns_rdatatype_t which) { covers = rdataset.covers; dns_rdataset_disassociate(&rdataset); if (type == which || covers == which) { + if (which == dns_rdatatype_nsec && !update_chain) + fatal("Zone contains NSEC records. Use -u " + "to update to NSEC3."); + if (which == dns_rdatatype_nsec3param && !update_chain) + fatal("Zone contains NSEC3 chains. Use -u " + "to update to NSEC."); result = dns_db_deleterdataset(gdb, node, gversion, type, covers); check_result(result, "dns_db_deleterdataset()"); @@ -2088,8 +2153,9 @@ nsecify(void) { } else if (result != ISC_R_SUCCESS) fatal("iterating through the database failed: %s", isc_result_totext(result)); + dns_dbiterator_pause(dbiter); result = dns_nsec_build(gdb, gversion, node, nextname, - zonettl); + zone_soa_min_ttl); check_result(result, "dns_nsec_build()"); dns_db_detachnode(gdb, &node); } @@ -2320,6 +2386,97 @@ nsec3clean(dns_name_t *name, dns_dbnode_t *node, check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))"); } +static void +rrset_remove_duplicates(dns_name_t *name, dns_rdataset_t *rdataset, + dns_diff_t *diff) +{ + dns_difftuple_t *tuple = NULL; + isc_result_t result; + unsigned int count1 = 0; + dns_rdataset_t tmprdataset; + + dns_rdataset_init(&tmprdataset); + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_rdata_t rdata1 = DNS_RDATA_INIT; + unsigned int count2 = 0; + + count1++; + dns_rdataset_current(rdataset, &rdata1); + dns_rdataset_clone(rdataset, &tmprdataset); + for (result = dns_rdataset_first(&tmprdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&tmprdataset)) { + dns_rdata_t rdata2 = DNS_RDATA_INIT; + count2++; + if (count1 >= count2) + continue; + dns_rdataset_current(&tmprdataset, &rdata2); + if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) { + result = dns_difftuple_create(mctx, + DNS_DIFFOP_DEL, + name, + rdataset->ttl, + &rdata2, &tuple); + check_result(result, "dns_difftuple_create"); + dns_diff_append(diff, &tuple); + } + } + dns_rdataset_disassociate(&tmprdataset); + } +} + +static void +remove_duplicates(void) { + isc_result_t result; + dns_dbiterator_t *dbiter = NULL; + dns_rdatasetiter_t *rdsiter = NULL; + dns_diff_t diff; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_fixedname_t fname; + dns_name_t *name; + + dns_diff_init(mctx, &diff); + dns_fixedname_init(&fname); + name = dns_fixedname_name(&fname); + dns_rdataset_init(&rdataset); + + result = dns_db_createiterator(gdb, 0, &dbiter); + check_result(result, "dns_db_createiterator()"); + + for (result = dns_dbiterator_first(dbiter); + result == ISC_R_SUCCESS; + result = dns_dbiterator_next(dbiter)) { + + result = dns_dbiterator_current(dbiter, &node, name); + check_dns_dbiterator_current(result); + result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) { + dns_rdatasetiter_current(rdsiter, &rdataset); + rrset_remove_duplicates(name, &rdataset, &diff); + dns_rdataset_disassociate(&rdataset); + } + if (result != ISC_R_NOMORE) + fatal("rdatasets iteration failed."); + dns_rdatasetiter_destroy(&rdsiter); + dns_db_detachnode(gdb, &node); + } + if (result != ISC_R_NOMORE) + fatal("zone iteration failed."); + + if (!ISC_LIST_EMPTY(diff.tuples)) { + result = dns_diff_applysilently(&diff, gdb, gversion); + check_result(result, "dns_diff_applysilently"); + } + dns_diff_clear(&diff); + dns_dbiterator_destroy(&dbiter); +} + /* * Generate NSEC3 records for the zone. */ @@ -2546,7 +2703,7 @@ nsec3ify(unsigned int hashalg, unsigned int iterations, */ dns_dbiterator_pause(dbiter); addnsec3(name, node, salt, salt_length, iterations, - hashlist, zonettl); + hashlist, zone_soa_min_ttl); dns_db_detachnode(gdb, &node); /* * Add NSEC3's for empty nodes. Use closest encloser logic. @@ -2557,7 +2714,7 @@ nsec3ify(unsigned int hashalg, unsigned int iterations, count--; dns_name_split(nextname, count, NULL, nextname); addnsec3(nextname, NULL, salt, salt_length, - iterations, hashlist, zonettl); + iterations, hashlist, zone_soa_min_ttl); } } dns_dbiterator_destroy(&dbiter); @@ -2580,7 +2737,7 @@ loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("failed converting name '%s' to dns format: %s", origin, isc_result_totext(result)); @@ -2600,90 +2757,169 @@ loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { * private keys from disk. */ static void -loadzonekeys(dns_db_t *db) { +loadzonekeys(isc_boolean_t preserve_keys, isc_boolean_t load_public) { dns_dbnode_t *node; - dns_dbversion_t *currentversion; + dns_dbversion_t *currentversion = NULL; isc_result_t result; - dst_key_t *keys[20]; - unsigned int nkeys, i; - - currentversion = NULL; - dns_db_currentversion(db, ¤tversion); + dns_rdataset_t rdataset, keysigs, soasigs; node = NULL; - result = dns_db_findnode(db, gorigin, ISC_FALSE, &node); + result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) fatal("failed to find the zone's origin: %s", isc_result_totext(result)); - result = dns_dnssec_findzonekeys(db, currentversion, node, gorigin, - mctx, 20, keys, &nkeys); - if (result == ISC_R_NOTFOUND) - result = ISC_R_SUCCESS; + dns_db_currentversion(gdb, ¤tversion); + + dns_rdataset_init(&rdataset); + dns_rdataset_init(&soasigs); + dns_rdataset_init(&keysigs); + + /* Make note of the keys which signed the SOA, if any */ + result = dns_db_findrdataset(gdb, node, currentversion, + dns_rdatatype_soa, 0, 0, + &rdataset, &soasigs); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Preserve the TTL of the DNSKEY RRset, if any */ + dns_rdataset_disassociate(&rdataset); + result = dns_db_findrdataset(gdb, node, currentversion, + dns_rdatatype_dnskey, 0, 0, + &rdataset, &keysigs); + if (result != ISC_R_SUCCESS) - fatal("failed to find the zone keys: %s", + goto cleanup; + + if (set_keyttl && keyttl != rdataset.ttl) { + fprintf(stderr, "User-specified TTL (%d) conflicts " + "with existing DNSKEY RRset TTL.\n", + keyttl); + fprintf(stderr, "Imported keys will use the RRSet " + "TTL (%d) instead.\n", + rdataset.ttl); + } + keyttl = rdataset.ttl; + + /* Load keys corresponding to the existing DNSKEY RRset */ + result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx, + &rdataset, &keysigs, &soasigs, + preserve_keys, load_public, + &keylist); + if (result != ISC_R_SUCCESS) + fatal("failed to load the zone keys: %s", isc_result_totext(result)); - for (i = 0; i < nkeys; i++) { - signer_key_t *key; + cleanup: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (dns_rdataset_isassociated(&keysigs)) + dns_rdataset_disassociate(&keysigs); + if (dns_rdataset_isassociated(&soasigs)) + dns_rdataset_disassociate(&soasigs); + dns_db_detachnode(gdb, &node); + dns_db_closeversion(gdb, ¤tversion, ISC_FALSE); +} + +static void +loadexplicitkeys(char *keyfiles[], int n, isc_boolean_t setksk) { + isc_result_t result; + int i; + + for (i = 0; i < n; i++) { + dns_dnsseckey_t *key = NULL; + dst_key_t *newkey = NULL; + + result = dst_key_fromnamedfile(keyfiles[i], directory, + DST_TYPE_PUBLIC | + DST_TYPE_PRIVATE, + mctx, &newkey); + if (result != ISC_R_SUCCESS) + fatal("cannot load dnskey %s: %s", keyfiles[i], + isc_result_totext(result)); + + if (!dns_name_equal(gorigin, dst_key_name(newkey))) + fatal("key %s not at origin\n", keyfiles[i]); + + if (!dst_key_isprivate(newkey)) + fatal("cannot sign zone with non-private dnskey %s", + keyfiles[i]); + + /* Skip any duplicates */ + for (key = ISC_LIST_HEAD(keylist); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + if (dst_key_id(key->key) == dst_key_id(newkey) && + dst_key_alg(key->key) == dst_key_alg(newkey)) + break; + } + + if (key == NULL) { + /* We haven't seen this key before */ + dns_dnsseckey_create(mctx, &newkey, &key); + ISC_LIST_APPEND(keylist, key, link); + key->source = dns_keysource_user; + } else { + dst_key_free(&key->key); + key->key = newkey; + } + + key->force_publish = ISC_TRUE; + key->force_sign = ISC_TRUE; - key = newkeystruct(keys[i], dst_key_isprivate(keys[i])); - ISC_LIST_APPEND(keylist, key, link); + if (setksk) + key->ksk = ISC_TRUE; } - dns_db_detachnode(db, &node); - dns_db_closeversion(db, ¤tversion, ISC_FALSE); } -/*% - * Finds all public zone keys in the zone. - */ static void -loadzonepubkeys(dns_db_t *db) { - dns_dbversion_t *currentversion = NULL; - dns_dbnode_t *node = NULL; - dns_rdataset_t rdataset; - dns_rdata_t rdata = DNS_RDATA_INIT; - dst_key_t *pubkey; - signer_key_t *key; +report(const char *format, ...) { + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + putc('\n', stderr); +} + +static void +build_final_keylist() { isc_result_t result; + dns_dbversion_t *ver = NULL; + dns_diff_t diff; + dns_dnsseckeylist_t matchkeys; + char name[DNS_NAME_FORMATSIZE]; - dns_db_currentversion(db, ¤tversion); + /* + * Find keys that match this zone in the key repository. + */ + ISC_LIST_INIT(matchkeys); + result = dns_dnssec_findmatchingkeys(gorigin, directory, + mctx, &matchkeys); + if (result == ISC_R_NOTFOUND) + result = ISC_R_SUCCESS; + check_result(result, "dns_dnssec_findmatchingkeys"); - result = dns_db_findnode(db, gorigin, ISC_FALSE, &node); - if (result != ISC_R_SUCCESS) - fatal("failed to find the zone's origin: %s", - isc_result_totext(result)); + result = dns_db_newversion(gdb, &ver); + check_result(result, "dns_db_newversion"); - dns_rdataset_init(&rdataset); - result = dns_db_findrdataset(db, node, currentversion, - dns_rdatatype_dnskey, 0, 0, &rdataset, - NULL); + dns_diff_init(mctx, &diff); + + /* + * Update keylist with information from from the key repository. + */ + dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl, + &diff, ignore_kskflag, mctx, report); + + dns_name_format(gorigin, name, sizeof(name)); + + result = dns_diff_applysilently(&diff, gdb, ver); if (result != ISC_R_SUCCESS) - fatal("failed to find keys at the zone apex: %s", - isc_result_totext(result)); - result = dns_rdataset_first(&rdataset); - check_result(result, "dns_rdataset_first"); - while (result == ISC_R_SUCCESS) { - pubkey = NULL; - dns_rdata_reset(&rdata); - dns_rdataset_current(&rdataset, &rdata); - result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx, - &pubkey); - if (result != ISC_R_SUCCESS) - goto next; - if (!dst_key_iszonekey(pubkey)) { - dst_key_free(&pubkey); - goto next; - } + fatal("failed to update DNSKEY RRset at node '%s': %s", + name, isc_result_totext(result)); - key = newkeystruct(pubkey, ISC_FALSE); - ISC_LIST_APPEND(keylist, key, link); - next: - result = dns_rdataset_next(&rdataset); - } - dns_rdataset_disassociate(&rdataset); - dns_db_detachnode(db, &node); - dns_db_closeversion(db, ¤tversion, ISC_FALSE); + dns_db_closeversion(gdb, &ver, ISC_TRUE); + + dns_diff_clear(&diff); } static void @@ -2727,18 +2963,112 @@ warnifallksk(dns_db_t *db) { dns_rdataset_disassociate(&rdataset); dns_db_detachnode(db, &node); dns_db_closeversion(db, ¤tversion, ISC_FALSE); - if (!have_non_ksk && !ignoreksk) { + if (!have_non_ksk && !ignore_kskflag) { if (disable_zone_check) - fprintf(stderr, "%s: warning: No non-KSK dnskey found. " - "Supply non-KSK dnskey or use '-z'.\n", + fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; " + "supply a ZSK or use '-z'.\n", program); else - fatal("No non-KSK dnskey found. " - "Supply non-KSK dnskey or use '-z'."); + fatal("No non-KSK DNSKEY found; " + "supply a ZSK or use '-z'."); } } static void +set_nsec3params(isc_boolean_t update_chain, isc_boolean_t set_salt, + isc_boolean_t set_optout, isc_boolean_t set_iter) +{ + isc_result_t result; + dns_dbversion_t *ver = NULL; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_nsec3_t nsec3; + dns_fixedname_t fname; + dns_name_t *hashname; + unsigned char orig_salt[256]; + size_t orig_saltlen; + dns_hash_t orig_hash; + isc_uint16_t orig_iter; + + dns_db_currentversion(gdb, &ver); + dns_rdataset_init(&rdataset); + + orig_saltlen = sizeof(orig_salt); + result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL, + &orig_iter, orig_salt, + &orig_saltlen); + if (result != ISC_R_SUCCESS) + goto cleanup; + + nsec_datatype = dns_rdatatype_nsec3; + + if (!update_chain && set_salt) { + if (salt_length != orig_saltlen || + memcmp(saltbuf, orig_salt, salt_length) != 0) + fatal("An NSEC3 chain exists with a different salt. " + "Use -u to update it."); + } else if (!set_salt) { + salt_length = orig_saltlen; + memcpy(saltbuf, orig_salt, orig_saltlen); + salt = saltbuf; + } + + if (!update_chain && set_iter) { + if (nsec3iter != orig_iter) + fatal("An NSEC3 chain exists with different " + "iterations. Use -u to update it."); + } else if (!set_iter) + nsec3iter = orig_iter; + + /* + * Find an NSEC3 record to get the current OPTOUT value. + * (This assumes all NSEC3 records agree.) + */ + + dns_fixedname_init(&fname); + hashname = dns_fixedname_name(&fname); + result = dns_nsec3_hashname(&fname, NULL, NULL, + gorigin, gorigin, dns_hash_sha1, + orig_iter, orig_salt, orig_saltlen); + check_result(result, "dns_nsec3_hashname"); + + result = dns_db_findnsec3node(gdb, hashname, ISC_FALSE, &node); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3, + 0, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_rdataset_first(&rdataset); + check_result(result, "dns_rdataset_first"); + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &nsec3, NULL); + check_result(result, "dns_rdata_tostruct"); + + if (!update_chain && set_optout) { + if (nsec3flags != nsec3.flags) + fatal("An NSEC3 chain exists with%s OPTOUT. " + "Use -u -%s to %s it.", + OPTOUT(nsec3.flags) ? "" : "out", + OPTOUT(nsec3.flags) ? "AA" : "A", + OPTOUT(nsec3.flags) ? "clear" : "set"); + } else if (!set_optout) + nsec3flags = nsec3.flags; + + dns_rdata_freestruct(&nsec3); + + cleanup: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (node != NULL) + dns_db_detachnode(gdb, &node); + dns_db_closeversion(gdb, &ver, ISC_FALSE); +} + +static void writeset(const char *prefix, dns_rdatatype_t type) { char *filename; char namestr[DNS_NAME_FORMATSIZE]; @@ -2755,7 +3085,7 @@ writeset(const char *prefix, dns_rdatatype_t type) { isc_buffer_t namebuf; isc_region_t r; isc_result_t result; - signer_key_t *key; + dns_dnsseckey_t *key, *tmpkey; unsigned char dsbuf[DNS_DS_BUFFERSIZE]; unsigned char keybuf[DST_KEY_MAXSIZE]; unsigned int filenamelen; @@ -2767,13 +3097,13 @@ writeset(const char *prefix, dns_rdatatype_t type) { check_result(result, "dns_name_tofilenametext"); isc_buffer_putuint8(&namebuf, 0); filenamelen = strlen(prefix) + strlen(namestr); - if (directory != NULL) - filenamelen += strlen(directory) + 1; + if (dsdir != NULL) + filenamelen += strlen(dsdir) + 1; filename = isc_mem_get(mctx, filenamelen + 1); if (filename == NULL) fatal("out of memory"); - if (directory != NULL) - sprintf(filename, "%s/", directory); + if (dsdir != NULL) + sprintf(filename, "%s/", dsdir); else filename[0] = 0; strcat(filename, prefix); @@ -2781,22 +3111,6 @@ writeset(const char *prefix, dns_rdatatype_t type) { dns_diff_init(mctx, &diff); - for (key = ISC_LIST_HEAD(keylist); - key != NULL; - key = ISC_LIST_NEXT(key, link)) - if (!key->isksk) { - have_non_ksk = ISC_TRUE; - break; - } - - for (key = ISC_LIST_HEAD(keylist); - key != NULL; - key = ISC_LIST_NEXT(key, link)) - if (key->isksk) { - have_ksk = ISC_TRUE; - break; - } - if (type == dns_rdatatype_dlv) { dns_name_t tname; unsigned int labels; @@ -2815,7 +3129,28 @@ writeset(const char *prefix, dns_rdatatype_t type) { key != NULL; key = ISC_LIST_NEXT(key, link)) { - if (have_ksk && have_non_ksk && !key->isksk) + if (REVOKE(key->key)) + continue; + if (isksk(key)) { + have_ksk = ISC_TRUE; + have_non_ksk = ISC_FALSE; + } else { + have_ksk = ISC_FALSE; + have_non_ksk = ISC_TRUE; + } + for (tmpkey = ISC_LIST_HEAD(keylist); + tmpkey != NULL; + tmpkey = ISC_LIST_NEXT(tmpkey, link)) { + if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key)) + continue; + if (REVOKE(tmpkey->key)) + continue; + if (isksk(tmpkey)) + have_ksk = ISC_TRUE; + else + have_non_ksk = ISC_TRUE; + } + if (have_ksk && have_non_ksk && !isksk(key)) continue; dns_rdata_init(&rdata); dns_rdata_init(&ds); @@ -2848,7 +3183,7 @@ writeset(const char *prefix, dns_rdatatype_t type) { } else result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, - gorigin, zonettl, + gorigin, zone_soa_min_ttl, &rdata, &tuple); check_result(result, "dns_difftuple_create"); dns_diff_append(&diff, &tuple); @@ -2893,6 +3228,9 @@ print_version(FILE *fp) { fprintf(fp, "; dnssec_signzone version " VERSION "\n"); } +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + static void usage(void) { fprintf(stderr, "Usage:\n"); @@ -2903,14 +3241,18 @@ usage(void) { fprintf(stderr, "Version: %s\n", VERSION); fprintf(stderr, "Options: (default value in parenthesis) \n"); - fprintf(stderr, "\t-c class (IN)\n"); - fprintf(stderr, "\t-d directory\n"); - fprintf(stderr, "\t\tdirectory to find keyset files (.)\n"); + fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n" + "\t\tfor the zone and determines how they are to " + "be used\n"); + fprintf(stderr, "\t-K directory:\n"); + fprintf(stderr, "\t\tdirectory to find key files (.)\n"); + fprintf(stderr, "\t-d directory:\n"); + fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n"); fprintf(stderr, "\t-g:\t"); - fprintf(stderr, "generate DS records from keyset files\n"); + fprintf(stderr, "update DS records based on child zones' " + "dsset-* files\n"); fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n"); - fprintf(stderr, "\t\tRRSIG start time - absolute|offset " - "(now - 1 hour)\n"); + fprintf(stderr, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n"); fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n"); fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now " "(now + 30 days)\n"); @@ -2918,8 +3260,7 @@ usage(void) { fprintf(stderr, "\t\tcycle interval - resign " "if < interval from end ( (end-start)/4 )\n"); fprintf(stderr, "\t-j jitter:\n"); - fprintf(stderr, "\t\trandomize signature end time up to jitter " - "seconds\n"); + fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n"); fprintf(stderr, "\t-v debuglevel (0)\n"); fprintf(stderr, "\t-o origin:\n"); fprintf(stderr, "\t\tzone origin (name of zonefile)\n"); @@ -2936,20 +3277,33 @@ usage(void) { fprintf(stderr, "\t\ta file containing random data\n"); fprintf(stderr, "\t-a:\t"); fprintf(stderr, "verify generated signatures\n"); + fprintf(stderr, "\t-c class (IN)\n"); + fprintf(stderr, "\t-E engine:\n"); +#ifdef USE_PKCS11 + fprintf(stderr, "\t\tname of an OpenSSL engine to use " + "(default is \"pkcs11\")\n"); +#else + fprintf(stderr, "\t\tname of an OpenSSL engine to use\n"); +#endif fprintf(stderr, "\t-p:\t"); fprintf(stderr, "use pseudorandom data (faster but less secure)\n"); fprintf(stderr, "\t-P:\t"); fprintf(stderr, "disable post-sign verification\n"); + fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n"); fprintf(stderr, "\t-t:\t"); fprintf(stderr, "print statistics\n"); + fprintf(stderr, "\t-u:\t"); + fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n"); + fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n"); + fprintf(stderr, "\t-z:\tsign all records with KSKs\n"); + fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n" + "\t\twith older versions of dnssec-signzone -g\n"); fprintf(stderr, "\t-n ncpus (number of cpus present)\n"); fprintf(stderr, "\t-k key_signing_key\n"); fprintf(stderr, "\t-l lookasidezone\n"); - fprintf(stderr, "\t-3 salt (NSEC3 salt)\n"); - fprintf(stderr, "\t-H iterations (NSEC3 iterations)\n"); - fprintf(stderr, "\t-A (NSEC3 optout)\n"); - fprintf(stderr, "\t-z:\t"); - fprintf(stderr, "ignore KSK flag in DNSKEYs"); + fprintf(stderr, "\t-3 NSEC3 salt\n"); + fprintf(stderr, "\t-H NSEC3 iterations (10)\n"); + fprintf(stderr, "\t-A NSEC3 optout\n"); fprintf(stderr, "\n"); @@ -3001,10 +3355,15 @@ main(int argc, char *argv[]) { int ndskeys = 0; char *endp; isc_time_t timer_start, timer_finish; - signer_key_t *key; + dns_dnsseckey_t *key; isc_result_t result; isc_log_t *log = NULL; isc_boolean_t pseudorandom = ISC_FALSE; +#ifdef USE_PKCS11 + const char *engine = "pkcs11"; +#else + const char *engine = NULL; +#endif unsigned int eflags; isc_boolean_t free_output = ISC_FALSE; int tempfilelen; @@ -3012,13 +3371,15 @@ main(int argc, char *argv[]) { isc_task_t **tasks = NULL; isc_buffer_t b; int len; - unsigned int iterations = 100U; - const unsigned char *salt = NULL; - size_t salt_length = 0; - unsigned char saltbuf[255]; hashlist_t hashlist; + isc_boolean_t smartsign = ISC_FALSE; + isc_boolean_t make_keyset = ISC_FALSE; + isc_boolean_t set_salt = ISC_FALSE; + isc_boolean_t set_optout = ISC_FALSE; + isc_boolean_t set_iter = ISC_FALSE; -#define CMDLINE_FLAGS "3:aAc:d:e:f:FghH:i:I:j:k:l:m:n:N:o:O:pPr:s:StUv:z" +#define CMDLINE_FLAGS \ + "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:l:m:n:N:o:O:pPr:s:ST:tuUv:xz" /* * Process memory debugging argument first. @@ -3058,7 +3419,9 @@ main(int argc, char *argv[]) { while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { switch (ch) { case '3': - if (strcmp(isc_commandline_argument, "-")) { + set_salt = ISC_TRUE; + nsec_datatype = dns_rdatatype_nsec3; + if (strcmp(isc_commandline_argument, "-") != 0) { isc_buffer_t target; char *sarg; @@ -3068,29 +3431,42 @@ main(int argc, char *argv[]) { result = isc_hex_decodestring(sarg, &target); check_result(result, "isc_hex_decodestring(salt)"); - salt = saltbuf; salt_length = isc_buffer_usedlength(&target); - } else { - salt = saltbuf; - salt_length = 0; } - nsec_datatype = dns_rdatatype_nsec3; break; case 'A': - nsec3flags |= DNS_NSEC3FLAG_OPTOUT; + set_optout = ISC_TRUE; + if (OPTOUT(nsec3flags)) + nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT; + else + nsec3flags |= DNS_NSEC3FLAG_OPTOUT; break; case 'a': tryverify = ISC_TRUE; break; + case 'C': + make_keyset = ISC_TRUE; + break; + case 'c': classname = isc_commandline_argument; break; case 'd': - directory = isc_commandline_argument; + dsdir = isc_commandline_argument; + if (strlen(dsdir) == 0U) + fatal("DS directory must be non-empty string"); + result = try_dir(dsdir); + if (result != ISC_R_SUCCESS) + fatal("cannot open directory %s: %s", + dsdir, isc_result_totext(result)); + break; + + case 'E': + engine = isc_commandline_argument; break; case 'e': @@ -3106,11 +3482,11 @@ main(int argc, char *argv[]) { break; case 'H': - iterations = strtoul(isc_commandline_argument, - &endp, 0); + set_iter = ISC_TRUE; + nsec3iter = strtoul(isc_commandline_argument, &endp, 0); if (*endp != '\0') fatal("iterations must be numeric"); - if (iterations > 0xffffU) + if (nsec3iter > 0xffffU) fatal("iterations too big"); break; @@ -3118,6 +3494,10 @@ main(int argc, char *argv[]) { usage(); break; + case 'I': + inputformatstr = isc_commandline_argument; + break; + case 'i': endp = NULL; cycle = strtol(isc_commandline_argument, &endp, 0); @@ -3126,10 +3506,6 @@ main(int argc, char *argv[]) { "positive"); break; - case 'I': - inputformatstr = isc_commandline_argument; - break; - case 'j': endp = NULL; jitter = strtol(isc_commandline_argument, &endp, 0); @@ -3137,6 +3513,10 @@ main(int argc, char *argv[]) { fatal("jitter must be numeric and positive"); break; + case 'K': + directory = isc_commandline_argument; + break; + case 'k': if (ndskeys == MAXDSKEYS) fatal("too many key-signing keys specified"); @@ -3150,14 +3530,18 @@ main(int argc, char *argv[]) { dns_fixedname_init(&dlv_fixed); dlv = dns_fixedname_name(&dlv_fixed); - result = dns_name_fromtext(dlv, &b, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(dlv, &b, dns_rootname, 0, + NULL); check_result(result, "dns_name_fromtext(dlv)"); break; case 'm': break; + case 'N': + serialformatstr = isc_commandline_argument; + break; + case 'n': endp = NULL; ntasks = strtol(isc_commandline_argument, &endp, 0); @@ -3165,38 +3549,38 @@ main(int argc, char *argv[]) { fatal("number of cpus must be numeric"); break; - case 'N': - serialformatstr = isc_commandline_argument; + case 'O': + outputformatstr = isc_commandline_argument; break; case 'o': origin = isc_commandline_argument; break; - case 'O': - outputformatstr = isc_commandline_argument; + case 'P': + disable_zone_check = ISC_TRUE; break; case 'p': pseudorandom = ISC_TRUE; break; - case 'P': - disable_zone_check = ISC_TRUE; - break; - case 'r': setup_entropy(mctx, isc_commandline_argument, &ectx); break; + case 'S': + smartsign = ISC_TRUE; + break; + case 's': startstr = isc_commandline_argument; break; - case 'S': - /* This is intentionally undocumented */ - /* -S: simple output style */ - masterstyle = &dns_master_style_simple; + case 'T': + endp = NULL; + set_keyttl = ISC_TRUE; + keyttl = strtottl(isc_commandline_argument); break; case 't': @@ -3207,6 +3591,10 @@ main(int argc, char *argv[]) { unknownalg = ISC_TRUE; break; + case 'u': + update_chain = ISC_TRUE; + break; + case 'v': endp = NULL; verbose = strtol(isc_commandline_argument, &endp, 0); @@ -3214,8 +3602,12 @@ main(int argc, char *argv[]) { fatal("verbose level must be numeric"); break; + case 'x': + keyset_kskonly = ISC_TRUE; + break; + case 'z': - ignoreksk = ISC_TRUE; + ignore_kskflag = ISC_TRUE; break; case 'F': @@ -3245,20 +3637,21 @@ main(int argc, char *argv[]) { if (result != ISC_R_SUCCESS) fatal("could not create hash context"); - result = dst_lib_init(mctx, ectx, eflags); + result = dst_lib_init2(mctx, ectx, engine, eflags); if (result != ISC_R_SUCCESS) - fatal("could not initialize dst"); + fatal("could not initialize dst: %s", + isc_result_totext(result)); isc_stdtime_get(&now); - if (startstr != NULL) + if (startstr != NULL) { starttime = strtotime(startstr, now, now); - else + } else starttime = now - 3600; /* Allow for some clock skew. */ - if (endstr != NULL) + if (endstr != NULL) { endtime = strtotime(endstr, now, starttime); - else + } else endtime = starttime + (30 * 24 * 60 * 60); if (cycle == -1) @@ -3270,6 +3663,9 @@ main(int argc, char *argv[]) { rdclass = strtoclass(classname); + if (directory == NULL) + directory = "."; + setup_logging(verbose, mctx, &log); argc -= isc_commandline_index; @@ -3335,7 +3731,19 @@ main(int argc, char *argv[]) { loadzone(file, origin, rdclass, &gdb); gorigin = dns_db_origin(gdb); gclass = dns_db_class(gdb); - zonettl = soattl(); + get_soa_ttls(); + + if (!set_keyttl) + keyttl = soa_ttl; + + /* + * Check for any existing NSEC3 parameters in the zone, + * and use them as defaults if -u was not specified. + */ + if (update_chain && !set_optout && !set_iter && !set_salt) + nsec_datatype = dns_rdatatype_nsec; + else + set_nsec3params(update_chain, set_salt, set_optout, set_iter); if (IS_NSEC3) { isc_boolean_t answer; @@ -3356,95 +3764,42 @@ main(int argc, char *argv[]) { ISC_LIST_INIT(keylist); isc_rwlock_init(&keylist_lock, 0, 0); - if (argc == 0) { - loadzonekeys(gdb); - } else { - for (i = 0; i < argc; i++) { - dst_key_t *newkey = NULL; - - result = dst_key_fromnamedfile(argv[i], - DST_TYPE_PUBLIC | - DST_TYPE_PRIVATE, - mctx, &newkey); - if (result != ISC_R_SUCCESS) - fatal("cannot load dnskey %s: %s", argv[i], - isc_result_totext(result)); - - if (!dns_name_equal(gorigin, dst_key_name(newkey))) - fatal("key %s not at origin\n", argv[i]); - - key = ISC_LIST_HEAD(keylist); - while (key != NULL) { - dst_key_t *dkey = key->key; - if (dst_key_id(dkey) == dst_key_id(newkey) && - dst_key_alg(dkey) == dst_key_alg(newkey) && - dns_name_equal(dst_key_name(dkey), - dst_key_name(newkey))) - { - if (!dst_key_isprivate(dkey)) - fatal("cannot sign zone with " - "non-private dnskey %s", - argv[i]); - break; - } - key = ISC_LIST_NEXT(key, link); - } - if (key == NULL) { - key = newkeystruct(newkey, ISC_TRUE); - key->commandline = ISC_TRUE; - ISC_LIST_APPEND(keylist, key, link); - } else - dst_key_free(&newkey); - } - - loadzonepubkeys(gdb); - } - - for (i = 0; i < ndskeys; i++) { - dst_key_t *newkey = NULL; - - result = dst_key_fromnamedfile(dskeyfile[i], - DST_TYPE_PUBLIC | - DST_TYPE_PRIVATE, - mctx, &newkey); - if (result != ISC_R_SUCCESS) - fatal("cannot load dnskey %s: %s", dskeyfile[i], - isc_result_totext(result)); + /* + * Fill keylist with: + * 1) Keys listed in the DNSKEY set that have + * private keys associated, *if* no keys were + * set on the command line. + * 2) ZSKs set on the command line + * 3) KSKs set on the command line + * 4) Any keys remaining in the DNSKEY set which + * do not have private keys associated and were + * not specified on the command line. + */ + if (argc == 0 || smartsign) + loadzonekeys(!smartsign, ISC_FALSE); + loadexplicitkeys(argv, argc, ISC_FALSE); + loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE); + loadzonekeys(!smartsign, ISC_TRUE); - if (!dns_name_equal(gorigin, dst_key_name(newkey))) - fatal("key %s not at origin\n", dskeyfile[i]); + /* + * If we're doing smart signing, look in the key repository for + * key files with metadata, and merge them with the keylist + * we have now. + */ + if (smartsign) + build_final_keylist(); - key = ISC_LIST_HEAD(keylist); - while (key != NULL) { - dst_key_t *dkey = key->key; - if (dst_key_id(dkey) == dst_key_id(newkey) && - dst_key_alg(dkey) == dst_key_alg(newkey) && - dns_name_equal(dst_key_name(dkey), - dst_key_name(newkey))) - { - /* Override key flags. */ - key->issigningkey = ISC_TRUE; - key->isksk = ISC_TRUE; - key->isdsk = ISC_FALSE; - dst_key_free(&dkey); - key->key = newkey; - break; - } - key = ISC_LIST_NEXT(key, link); - } - if (key == NULL) { - /* Override dnskey flags. */ - key = newkeystruct(newkey, ISC_TRUE); - key->isksk = ISC_TRUE; - key->isdsk = ISC_FALSE; - ISC_LIST_APPEND(keylist, key, link); - } + /* Now enumerate the key list */ + for (key = ISC_LIST_HEAD(keylist); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + key->index = keycount++; } - if (ISC_LIST_EMPTY(keylist)) { + if (keycount == 0) { if (disable_zone_check) fprintf(stderr, "%s: warning: No keys specified " - "or found\n", program); + "or found\n", program); else fatal("No signing keys specified or found."); nokeys = ISC_TRUE; @@ -3454,7 +3809,7 @@ main(int argc, char *argv[]) { unsigned int max; result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max); check_result(result, "dns_nsec3_maxiterations()"); - if (iterations > max) + if (nsec3iter > max) fatal("NSEC3 iterations too big for weakest DNSKEY " "strength. Maximum iterations allowed %u.", max); } @@ -3478,15 +3833,18 @@ main(int argc, char *argv[]) { break; } + remove_duplicates(); + if (IS_NSEC3) - nsec3ify(dns_hash_sha1, iterations, salt, salt_length, + nsec3ify(dns_hash_sha1, nsec3iter, salt, salt_length, &hashlist); else nsecify(); if (!nokeys) { - writeset("keyset-", dns_rdatatype_dnskey); writeset("dsset-", dns_rdatatype_ds); + if (make_keyset) + writeset("keyset-", dns_rdatatype_dnskey); if (dlv != NULL) { writeset("dlvset-", dns_rdatatype_dlv); } @@ -3591,8 +3949,7 @@ main(int argc, char *argv[]) { while (!ISC_LIST_EMPTY(keylist)) { key = ISC_LIST_HEAD(keylist); ISC_LIST_UNLINK(keylist, key, link); - dst_key_free(&key->key); - isc_mem_put(mctx, key, sizeof(signer_key_t)); + dns_dnsseckey_destroy(mctx, &key); } isc_mem_put(mctx, tempfile, tempfilelen); diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.docbook b/contrib/bind9/bin/dnssec/dnssec-signzone.docbook index 87a801e7442f..51a14968a9c3 100644 --- a/contrib/bind9/bin/dnssec/dnssec-signzone.docbook +++ b/contrib/bind9/bin/dnssec/dnssec-signzone.docbook @@ -18,10 +18,10 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: dnssec-signzone.docbook,v 1.31.44.8 2009-11-06 21:36:22 each Exp $ --> +<!-- $Id: dnssec-signzone.docbook,v 1.44 2009-12-03 23:18:16 each Exp $ --> <refentry id="man.dnssec-signzone"> <refentryinfo> - <date>June 08, 2009</date> + <date>June 05, 2009</date> </refentryinfo> <refmeta> @@ -60,10 +60,12 @@ <arg><option>-a</option></arg> <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg> <arg><option>-d <replaceable class="parameter">directory</replaceable></option></arg> + <arg><option>-E <replaceable class="parameter">engine</replaceable></option></arg> <arg><option>-e <replaceable class="parameter">end-time</replaceable></option></arg> <arg><option>-f <replaceable class="parameter">output-file</replaceable></option></arg> <arg><option>-g</option></arg> <arg><option>-h</option></arg> + <arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg> <arg><option>-k <replaceable class="parameter">key</replaceable></option></arg> <arg><option>-l <replaceable class="parameter">domain</replaceable></option></arg> <arg><option>-i <replaceable class="parameter">interval</replaceable></option></arg> @@ -75,9 +77,13 @@ <arg><option>-p</option></arg> <arg><option>-P</option></arg> <arg><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg> + <arg><option>-S</option></arg> <arg><option>-s <replaceable class="parameter">start-time</replaceable></option></arg> + <arg><option>-T <replaceable class="parameter">ttl</replaceable></option></arg> <arg><option>-t</option></arg> + <arg><option>-u</option></arg> <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg> + <arg><option>-x</option></arg> <arg><option>-z</option></arg> <arg><option>-3 <replaceable class="parameter">salt</replaceable></option></arg> <arg><option>-H <replaceable class="parameter">iterations</replaceable></option></arg> @@ -92,10 +98,10 @@ <para><command>dnssec-signzone</command> signs a zone. It generates NSEC and RRSIG records and produces a signed version of the - zone. It also generates a <filename>keyset-</filename> file containing - the key-signing keys for the zone, and if signing a zone which - contains delegations, it can optionally generate DS records for - the child zones from their <filename>keyset-</filename> files. + zone. The security status of delegations from the signed zone + (that is, whether the child zones are secure or not) is + determined by the presence or absence of a + <filename>keyset</filename> file for each child zone. </para> </refsect1> @@ -122,31 +128,37 @@ </varlistentry> <varlistentry> - <term>-k <replaceable class="parameter">key</replaceable></term> + <term>-C</term> <listitem> <para> - Treat specified key as a key signing key ignoring any - key flags. This option may be specified multiple times. + Compatibility mode: Generate a + <filename>keyset-<replaceable>zonename</replaceable></filename> + file in addition to + <filename>dsset-<replaceable>zonename</replaceable></filename> + when signing a zone, for use by older versions of + <command>dnssec-signzone</command>. </para> </listitem> </varlistentry> <varlistentry> - <term>-l <replaceable class="parameter">domain</replaceable></term> + <term>-d <replaceable class="parameter">directory</replaceable></term> <listitem> <para> - Generate a DLV set in addition to the key (DNSKEY) and DS sets. - The domain is appended to the name of the records. + Look for <filename>dsset-</filename> or + <filename>keyset-</filename> files in <option>directory</option>. </para> </listitem> </varlistentry> <varlistentry> - <term>-d <replaceable class="parameter">directory</replaceable></term> + <term>-E <replaceable class="parameter">engine</replaceable></term> <listitem> <para> - Look for <filename>keyset</filename> files in - <option>directory</option> as the directory + Uses a crypto hardware (OpenSSL engine) for the crypto operations + it supports, for instance signing with private keys from + a secure key store. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. </para> </listitem> </varlistentry> @@ -155,10 +167,39 @@ <term>-g</term> <listitem> <para> - If the zone contains any delegations, and there are - <filename>keyset-</filename> files for any of the child zones, - then DS records for the child zones will be generated from the - keys in those files. Existing DS records will be removed. + Generate DS records for child zones from + <filename>dsset-</filename> or <filename>keyset-</filename> + file. Existing DS records will be removed. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-K <replaceable class="parameter">directory</replaceable></term> + <listitem> + <para> + Key repository: Specify a directory to search for DNSSEC keys. + If not specified, defaults to the current directory. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-k <replaceable class="parameter">key</replaceable></term> + <listitem> + <para> + Treat specified key as a key signing key ignoring any + key flags. This option may be specified multiple times. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-l <replaceable class="parameter">domain</replaceable></term> + <listitem> + <para> + Generate a DLV set in addition to the key (DNSKEY) and DS sets. + The domain is appended to the name of the records. </para> </listitem> </varlistentry> @@ -190,6 +231,8 @@ the start time. A time relative to the current time is indicated with now+N. If no <option>end-time</option> is specified, 30 days from the start time is used as a default. + <option>end-time</option> must be later than + <option>start-time</option>. </para> </listitem> </varlistentry> @@ -396,6 +439,89 @@ </varlistentry> <varlistentry> + <term>-S</term> + <listitem> + <para> + Smart signing: Instructs <command>dnssec-signzone</command> to + search the key repository for keys that match the zone being + signed, and to include them in the zone if appropriate. + </para> + <para> + When a key is found, its timing metadata is examined to + determine how it should be used, according to the following + rules. Each successive rule takes priority over the prior + ones: + </para> + <variablelist> + <varlistentry> + <listitem> + <para> + If no timing metadata has been set for the key, the key is + published in the zone and used to sign the zone. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <listitem> + <para> + If the key's publication date is set and is in the past, the + key is published in the zone. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <listitem> + <para> + If the key's activation date is set and in the past, the + key is published (regardless of publication date) and + used to sign the zone. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <listitem> + <para> + If the key's revocation date is set and in the past, and the + key is published, then the key is revoked, and the revoked key + is used to sign the zone. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <listitem> + <para> + If either of the key's unpublication or deletion dates are set + and in the past, the key is NOT published or used to sign the + zone, regardless of any other metadata. + </para> + </listitem> + </varlistentry> + </variablelist> + </listitem> + </varlistentry> + + <varlistentry> + <term>-T <replaceable class="parameter">ttl</replaceable></term> + <listitem> + <para> + Specifies the TTL to be used for new DNSKEY records imported + into the zone from the key repository. If not specified, + the default is the minimum TTL value from the zone's SOA + record. This option is ignored when signing without + <option>-S</option>, since DNSKEY records are not imported + from the key repository in that case. It is also ignored if + there are any pre-existing DNSKEY records at the zone apex, + in which case new records' TTL values will be set to match + them. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-t</term> <listitem> <para> @@ -405,6 +531,20 @@ </varlistentry> <varlistentry> + <term>-u</term> + <listitem> + <para> + Update NSEC/NSEC3 chain when re-signing a previously signed + zone. With this option, a zone signed with NSEC can be + switched to NSEC3, or a zone signed with NSEC3 can + be switch to NSEC or to NSEC3 with different parameters. + Without this option, <command>dnssec-signzone</command> will + retain the existing chain when re-signing. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-v <replaceable class="parameter">level</replaceable></term> <listitem> <para> @@ -414,10 +554,26 @@ </varlistentry> <varlistentry> + <term>-x</term> + <listitem> + <para> + Only sign the DNSKEY RRset with key-signing keys, and omit + signatures from zone-signing keys. (This is similar to the + <command>dnssec-dnskey-kskonly yes;</command> zone option in + <command>named</command>.) + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-z</term> <listitem> <para> - Ignore KSK flag on key when determining what to sign. + Ignore KSK flag on key when determining what to sign. This + causes KSK-flagged keys to sign all records, not just the + DNSKEY RRset. (This is similar to the + <command>update-check-ksk no;</command> zone option in + <command>named</command>.) </para> </listitem> </varlistentry> @@ -426,7 +582,7 @@ <term>-3 <replaceable class="parameter">salt</replaceable></term> <listitem> <para> - Generate a NSEC3 chain with the given hex encoded salt. + Generate an NSEC3 chain with the given hex encoded salt. A dash (<replaceable class="parameter">salt</replaceable>) can be used to indicate that no salt is to be used when generating the NSEC3 chain. </para> @@ -437,8 +593,8 @@ <term>-H <replaceable class="parameter">iterations</replaceable></term> <listitem> <para> - When generating a NSEC3 chain use this many interations. The - default is 100. + When generating an NSEC3 chain, use this many interations. The + default is 10. </para> </listitem> </varlistentry> @@ -447,10 +603,16 @@ <term>-A</term> <listitem> <para> - When generating a NSEC3 chain set the OPTOUT flag on all + When generating an NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations. </para> + <para> + Using this option twice (i.e., <option>-AA</option>) + turns the OPTOUT flag off for all records. This is useful + when using the <option>-u</option> option to modify an NSEC3 + chain which previously had OPTOUT set. + </para> </listitem> </varlistentry> @@ -484,10 +646,11 @@ <para> The following command signs the <userinput>example.com</userinput> zone with the DSA key generated by <command>dnssec-keygen</command> - (Kexample.com.+003+17247). The zone's keys must be in the master - file (<filename>db.example.com</filename>). This invocation looks - for <filename>keyset</filename> files, in the current directory, - so that DS records can be generated from them (<command>-g</command>). + (Kexample.com.+003+17247). Because the <command>-S</command> option + is not being used, the zone's keys must be in the master file + (<filename>db.example.com</filename>). This invocation looks + for <filename>dsset</filename> files, in the current directory, + so that DS records can be imported from them (<command>-g</command>). </para> <programlisting>% dnssec-signzone -g -o example.com db.example.com \ Kexample.com.+003+17247 @@ -510,33 +673,6 @@ db.example.com.signed </refsect1> <refsect1> - <title>KNOWN BUGS</title> - <para> - <command>dnssec-signzone</command> was designed so that it could - sign a zone partially, using only a subset of the DNSSEC keys - needed to produce a fully-signed zone. This permits a zone - administrator, for example, to sign a zone with one key on one - machine, move the resulting partially-signed zone to a second - machine, and sign it again with a second key. - </para> - <para> - An unfortunate side-effect of this flexibility is that - <command>dnssec-signzone</command> does not check to make sure - it's signing a zone with any valid keys at all. An attempt to - sign a zone without any keys will appear to succeed, producing - a "signed" zone with no signatures. There is no warning issued - when a zone is not fully signed. - </para> - - <para> - This will be corrected in a future release. In the meantime, ISC - recommends examining the output of <command>dnssec-signzone</command> - to confirm that the zone is properly signed by all keys before - using it. - </para> - </refsect1> - - <refsect1> <title>SEE ALSO</title> <para><citerefentry> <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum> diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.html b/contrib/bind9/bin/dnssec/dnssec-signzone.html index 1d4ecffc85b4..28e7158e6e7c 100644 --- a/contrib/bind9/bin/dnssec/dnssec-signzone.html +++ b/contrib/bind9/bin/dnssec/dnssec-signzone.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: dnssec-signzone.html,v 1.33.44.8 2009-11-07 01:56:11 tbox Exp $ --> +<!-- $Id: dnssec-signzone.html,v 1.45 2009-12-04 01:13:44 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> @@ -29,21 +29,21 @@ </div> <div class="refsynopsisdiv"> <h2>Synopsis</h2> -<div class="cmdsynopsis"><p><code class="command">dnssec-signzone</code> [<code class="option">-a</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-d <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-e <em class="replaceable"><code>end-time</code></em></code>] [<code class="option">-f <em class="replaceable"><code>output-file</code></em></code>] [<code class="option">-g</code>] [<code class="option">-h</code>] [<code class="option">-k <em class="replaceable"><code>key</code></em></code>] [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>] [<code class="option">-i <em class="replaceable"><code>interval</code></em></code>] [<code class="option">-I <em class="replaceable"><code>input-format</code></em></code>] [<code class="option">-j <em class="replaceable"><code>jitter</code></em></code>] [<code class="option">-N <em class="replaceable"><code>soa-serial-format</code></em></code>] [<code class="option">-o <em class="replaceable"><code>origin</code></em></code>] [<code class="option">-O <em class="replaceable"><code>output-format</code></em></code>] [<code class="option">-p</code>] [<code class="option">-P</code>] [<code class="option">-r <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-s <em class="replaceable"><code>start-time</code></em></code>] [<code class="option">-t</code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-z</code>] [<code class="option">-3 <em class="replaceable"><code>salt</code></em></code>] [<code class="option">-H <em class="replaceable"><code>iterations</code></em></code>] [<code class="option">-A</code>] {zonefile} [key...]</p></div> +<div class="cmdsynopsis"><p><code class="command">dnssec-signzone</code> [<code class="option">-a</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-d <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-E <em class="replaceable"><code>engine</code></em></code>] [<code class="option">-e <em class="replaceable"><code>end-time</code></em></code>] [<code class="option">-f <em class="replaceable"><code>output-file</code></em></code>] [<code class="option">-g</code>] [<code class="option">-h</code>] [<code class="option">-K <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-k <em class="replaceable"><code>key</code></em></code>] [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>] [<code class="option">-i <em class="replaceable"><code>interval</code></em></code>] [<code class="option">-I <em class="replaceable"><code>input-format</code></em></code>] [<code class="option">-j <em class="replaceable"><code>jitter</code></em></code>] [<code class="option">-N <em class="replaceable"><code>soa-serial-format</code></em></code>] [<code class="option">-o <em class="replaceable"><code>origin</code></em></code>] [<code class="option">-O <em class="replaceable"><code>output-format</code></em></code>] [<code class="option">-p</code>] [<code class="option">-P</code>] [<code class="option">-r <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-S</code>] [<code class="option">-s <em class="replaceable"><code>start-time</code></em></code>] [<code class="option">-T <em class="replaceable"><code>ttl</code></em></code>] [<code class="option">-t</code>] [<code class="option">-u</code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-x</code>] [<code class="option">-z</code>] [<code class="option">-3 <em class="replaceable"><code>salt</code></em></code>] [<code class="option">-H <em class="replaceable"><code>iterations</code></em></code>] [<code class="option">-A</code>] {zonefile} [key...]</p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543558"></a><h2>DESCRIPTION</h2> +<a name="id2543596"></a><h2>DESCRIPTION</h2> <p><span><strong class="command">dnssec-signzone</strong></span> signs a zone. It generates NSEC and RRSIG records and produces a signed version of the - zone. It also generates a <code class="filename">keyset-</code> file containing - the key-signing keys for the zone, and if signing a zone which - contains delegations, it can optionally generate DS records for - the child zones from their <code class="filename">keyset-</code> files. + zone. The security status of delegations from the signed zone + (that is, whether the child zones are secure or not) is + determined by the presence or absence of a + <code class="filename">keyset</code> file for each child zone. </p> </div> <div class="refsect1" lang="en"> -<a name="id2543576"></a><h2>OPTIONS</h2> +<a name="id2543611"></a><h2>OPTIONS</h2> <div class="variablelist"><dl> <dt><span class="term">-a</span></dt> <dd><p> @@ -53,6 +53,38 @@ <dd><p> Specifies the DNS class of the zone. </p></dd> +<dt><span class="term">-C</span></dt> +<dd><p> + Compatibility mode: Generate a + <code class="filename">keyset-<em class="replaceable"><code>zonename</code></em></code> + file in addition to + <code class="filename">dsset-<em class="replaceable"><code>zonename</code></em></code> + when signing a zone, for use by older versions of + <span><strong class="command">dnssec-signzone</strong></span>. + </p></dd> +<dt><span class="term">-d <em class="replaceable"><code>directory</code></em></span></dt> +<dd><p> + Look for <code class="filename">dsset-</code> or + <code class="filename">keyset-</code> files in <code class="option">directory</code>. + </p></dd> +<dt><span class="term">-E <em class="replaceable"><code>engine</code></em></span></dt> +<dd><p> + Uses a crypto hardware (OpenSSL engine) for the crypto operations + it supports, for instance signing with private keys from + a secure key store. When compiled with PKCS#11 support + it defaults to pkcs11; the empty name resets it to no engine. + </p></dd> +<dt><span class="term">-g</span></dt> +<dd><p> + Generate DS records for child zones from + <code class="filename">dsset-</code> or <code class="filename">keyset-</code> + file. Existing DS records will be removed. + </p></dd> +<dt><span class="term">-K <em class="replaceable"><code>directory</code></em></span></dt> +<dd><p> + Key repository: Specify a directory to search for DNSSEC keys. + If not specified, defaults to the current directory. + </p></dd> <dt><span class="term">-k <em class="replaceable"><code>key</code></em></span></dt> <dd><p> Treat specified key as a key signing key ignoring any @@ -63,18 +95,6 @@ Generate a DLV set in addition to the key (DNSKEY) and DS sets. The domain is appended to the name of the records. </p></dd> -<dt><span class="term">-d <em class="replaceable"><code>directory</code></em></span></dt> -<dd><p> - Look for <code class="filename">keyset</code> files in - <code class="option">directory</code> as the directory - </p></dd> -<dt><span class="term">-g</span></dt> -<dd><p> - If the zone contains any delegations, and there are - <code class="filename">keyset-</code> files for any of the child zones, - then DS records for the child zones will be generated from the - keys in those files. Existing DS records will be removed. - </p></dd> <dt><span class="term">-s <em class="replaceable"><code>start-time</code></em></span></dt> <dd><p> Specify the date and time when the generated RRSIG records @@ -95,6 +115,8 @@ the start time. A time relative to the current time is indicated with now+N. If no <code class="option">end-time</code> is specified, 30 days from the start time is used as a default. + <code class="option">end-time</code> must be later than + <code class="option">start-time</code>. </p></dd> <dt><span class="term">-f <em class="replaceable"><code>output-file</code></em></span></dt> <dd><p> @@ -229,35 +251,119 @@ <code class="filename">keyboard</code> indicates that keyboard input should be used. </p></dd> +<dt><span class="term">-S</span></dt> +<dd> +<p> + Smart signing: Instructs <span><strong class="command">dnssec-signzone</strong></span> to + search the key repository for keys that match the zone being + signed, and to include them in the zone if appropriate. + </p> +<p> + When a key is found, its timing metadata is examined to + determine how it should be used, according to the following + rules. Each successive rule takes priority over the prior + ones: + </p> +<div class="variablelist"><dl> +<dt></dt> +<dd><p> + If no timing metadata has been set for the key, the key is + published in the zone and used to sign the zone. + </p></dd> +<dt></dt> +<dd><p> + If the key's publication date is set and is in the past, the + key is published in the zone. + </p></dd> +<dt></dt> +<dd><p> + If the key's activation date is set and in the past, the + key is published (regardless of publication date) and + used to sign the zone. + </p></dd> +<dt></dt> +<dd><p> + If the key's revocation date is set and in the past, and the + key is published, then the key is revoked, and the revoked key + is used to sign the zone. + </p></dd> +<dt></dt> +<dd><p> + If either of the key's unpublication or deletion dates are set + and in the past, the key is NOT published or used to sign the + zone, regardless of any other metadata. + </p></dd> +</dl></div> +</dd> +<dt><span class="term">-T <em class="replaceable"><code>ttl</code></em></span></dt> +<dd><p> + Specifies the TTL to be used for new DNSKEY records imported + into the zone from the key repository. If not specified, + the default is the minimum TTL value from the zone's SOA + record. This option is ignored when signing without + <code class="option">-S</code>, since DNSKEY records are not imported + from the key repository in that case. It is also ignored if + there are any pre-existing DNSKEY records at the zone apex, + in which case new records' TTL values will be set to match + them. + </p></dd> <dt><span class="term">-t</span></dt> <dd><p> Print statistics at completion. </p></dd> +<dt><span class="term">-u</span></dt> +<dd><p> + Update NSEC/NSEC3 chain when re-signing a previously signed + zone. With this option, a zone signed with NSEC can be + switched to NSEC3, or a zone signed with NSEC3 can + be switch to NSEC or to NSEC3 with different parameters. + Without this option, <span><strong class="command">dnssec-signzone</strong></span> will + retain the existing chain when re-signing. + </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">-x</span></dt> +<dd><p> + Only sign the DNSKEY RRset with key-signing keys, and omit + signatures from zone-signing keys. (This is similar to the + <span><strong class="command">dnssec-dnskey-kskonly yes;</strong></span> zone option in + <span><strong class="command">named</strong></span>.) + </p></dd> <dt><span class="term">-z</span></dt> <dd><p> - Ignore KSK flag on key when determining what to sign. + Ignore KSK flag on key when determining what to sign. This + causes KSK-flagged keys to sign all records, not just the + DNSKEY RRset. (This is similar to the + <span><strong class="command">update-check-ksk no;</strong></span> zone option in + <span><strong class="command">named</strong></span>.) </p></dd> <dt><span class="term">-3 <em class="replaceable"><code>salt</code></em></span></dt> <dd><p> - Generate a NSEC3 chain with the given hex encoded salt. + Generate an NSEC3 chain with the given hex encoded salt. A dash (<em class="replaceable"><code>salt</code></em>) can be used to indicate that no salt is to be used when generating the NSEC3 chain. </p></dd> <dt><span class="term">-H <em class="replaceable"><code>iterations</code></em></span></dt> <dd><p> - When generating a NSEC3 chain use this many interations. The - default is 100. + When generating an NSEC3 chain, use this many interations. The + default is 10. </p></dd> <dt><span class="term">-A</span></dt> -<dd><p> - When generating a NSEC3 chain set the OPTOUT flag on all +<dd> +<p> + When generating an NSEC3 chain set the OPTOUT flag on all NSEC3 records and do not generate NSEC3 records for insecure delegations. - </p></dd> + </p> +<p> + Using this option twice (i.e., <code class="option">-AA</code>) + turns the OPTOUT flag off for all records. This is useful + when using the <code class="option">-u</code> option to modify an NSEC3 + chain which previously had OPTOUT set. + </p> +</dd> <dt><span class="term">zonefile</span></dt> <dd><p> The file containing the zone to be signed. @@ -273,14 +379,15 @@ </dl></div> </div> <div class="refsect1" lang="en"> -<a name="id2544503"></a><h2>EXAMPLE</h2> +<a name="id2544896"></a><h2>EXAMPLE</h2> <p> The following command signs the <strong class="userinput"><code>example.com</code></strong> zone with the DSA key generated by <span><strong class="command">dnssec-keygen</strong></span> - (Kexample.com.+003+17247). The zone's keys must be in the master - file (<code class="filename">db.example.com</code>). This invocation looks - for <code class="filename">keyset</code> files, in the current directory, - so that DS records can be generated from them (<span><strong class="command">-g</strong></span>). + (Kexample.com.+003+17247). Because the <span><strong class="command">-S</strong></span> option + is not being used, the zone's keys must be in the master file + (<code class="filename">db.example.com</code>). This invocation looks + for <code class="filename">dsset</code> files, in the current directory, + so that DS records can be imported from them (<span><strong class="command">-g</strong></span>). </p> <pre class="programlisting">% dnssec-signzone -g -o example.com db.example.com \ Kexample.com.+003+17247 @@ -302,39 +409,14 @@ db.example.com.signed %</pre> </div> <div class="refsect1" lang="en"> -<a name="id2544554"></a><h2>KNOWN BUGS</h2> -<p> - <span><strong class="command">dnssec-signzone</strong></span> was designed so that it could - sign a zone partially, using only a subset of the DNSSEC keys - needed to produce a fully-signed zone. This permits a zone - administrator, for example, to sign a zone with one key on one - machine, move the resulting partially-signed zone to a second - machine, and sign it again with a second key. - </p> -<p> - An unfortunate side-effect of this flexibility is that - <span><strong class="command">dnssec-signzone</strong></span> does not check to make sure - it's signing a zone with any valid keys at all. An attempt to - sign a zone without any keys will appear to succeed, producing - a "signed" zone with no signatures. There is no warning issued - when a zone is not fully signed. - </p> -<p> - This will be corrected in a future release. In the meantime, ISC - recommends examining the output of <span><strong class="command">dnssec-signzone</strong></span> - to confirm that the zone is properly signed by all keys before - using it. - </p> -</div> -<div class="refsect1" lang="en"> -<a name="id2544716"></a><h2>SEE ALSO</h2> +<a name="id2545019"></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 4033</em>. </p> </div> <div class="refsect1" lang="en"> -<a name="id2544741"></a><h2>AUTHOR</h2> +<a name="id2545044"></a><h2>AUTHOR</h2> <p><span class="corpauthor">Internet Systems Consortium</span> </p> </div> diff --git a/contrib/bind9/bin/dnssec/dnssectool.c b/contrib/bind9/bin/dnssec/dnssectool.c index 81120e34c49c..da6b0b2a789e 100644 --- a/contrib/bind9/bin/dnssec/dnssectool.c +++ b/contrib/bind9/bin/dnssec/dnssectool.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssectool.c,v 1.45.334.5 2009-06-22 05:05:00 marka Exp $ */ +/* $Id: dnssectool.c,v 1.60 2010-01-19 23:48:56 tbox Exp $ */ /*! \file */ @@ -28,6 +28,7 @@ #include <stdlib.h> #include <isc/buffer.h> +#include <isc/dir.h> #include <isc/entropy.h> #include <isc/list.h> #include <isc/mem.h> @@ -36,6 +37,8 @@ #include <isc/util.h> #include <isc/print.h> +#include <dns/dnssec.h> +#include <dns/keyvalues.h> #include <dns/log.h> #include <dns/name.h> #include <dns/rdatastruct.h> @@ -111,39 +114,16 @@ type_format(const dns_rdatatype_t type, char *cp, unsigned int size) { } void -alg_format(const dns_secalg_t alg, char *cp, unsigned int size) { - isc_buffer_t b; - isc_region_t r; - isc_result_t result; - - isc_buffer_init(&b, cp, size - 1); - result = dns_secalg_totext(alg, &b); - check_result(result, "dns_secalg_totext()"); - isc_buffer_usedregion(&b, &r); - r.base[r.length] = 0; -} - -void sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) { char namestr[DNS_NAME_FORMATSIZE]; char algstr[DNS_NAME_FORMATSIZE]; dns_name_format(&sig->signer, namestr, sizeof(namestr)); - alg_format(sig->algorithm, algstr, sizeof(algstr)); + dns_secalg_format(sig->algorithm, algstr, sizeof(algstr)); snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid); } void -key_format(const dst_key_t *key, char *cp, unsigned int size) { - char namestr[DNS_NAME_FORMATSIZE]; - char algstr[DNS_NAME_FORMATSIZE]; - - dns_name_format(dst_key_name(key), namestr, sizeof(namestr)); - alg_format((dns_secalg_t) dst_key_alg(key), algstr, sizeof(algstr)); - snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key)); -} - -void setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp) { isc_result_t result; isc_logdestination_t destination; @@ -265,32 +245,92 @@ cleanup_entropy(isc_entropy_t **ectx) { isc_entropy_detach(ectx); } +static isc_stdtime_t +time_units(isc_stdtime_t offset, char *suffix, const char *str) { + switch (suffix[0]) { + case 'Y': case 'y': + return (offset * (365 * 24 * 3600)); + case 'M': case 'm': + switch (suffix[1]) { + case 'O': case 'o': + return (offset * (30 * 24 * 3600)); + case 'I': case 'i': + return (offset * 60); + case '\0': + fatal("'%s' ambiguous: use 'mi' for minutes " + "or 'mo' for months", str); + default: + fatal("time value %s is invalid", str); + } + /* NOTREACHED */ + break; + case 'W': case 'w': + return (offset * (7 * 24 * 3600)); + case 'D': case 'd': + return (offset * (24 * 3600)); + case 'H': case 'h': + return (offset * 3600); + case 'S': case 's': case '\0': + return (offset); + default: + fatal("time value %s is invalid", str); + } + /* NOTREACHED */ + return(0); /* silence compiler warning */ +} + +dns_ttl_t +strtottl(const char *str) { + const char *orig = str; + dns_ttl_t ttl; + char *endp; + + ttl = strtol(str, &endp, 0); + if (ttl == 0 && endp == str) + fatal("TTL must be numeric"); + ttl = time_units(ttl, endp, orig); + return (ttl); +} + isc_stdtime_t strtotime(const char *str, isc_int64_t now, isc_int64_t base) { isc_int64_t val, offset; isc_result_t result; + const char *orig = str; char *endp; - if (str[0] == '+') { + if ((str[0] == '0' || str[0] == '-') && str[1] == '\0') + return ((isc_stdtime_t) 0); + + if (strncmp(str, "now", 3) == 0) { + base = now; + str += 3; + } + + if (str[0] == '\0') + return ((isc_stdtime_t) base); + else if (str[0] == '+') { offset = strtol(str + 1, &endp, 0); - if (*endp != '\0') - fatal("time value %s is invalid", str); + offset = time_units((isc_stdtime_t) offset, endp, orig); val = base + offset; - } else if (strncmp(str, "now+", 4) == 0) { - offset = strtol(str + 4, &endp, 0); - if (*endp != '\0') - fatal("time value %s is invalid", str); - val = now + offset; + } else if (str[0] == '-') { + offset = strtol(str + 1, &endp, 0); + offset = time_units((isc_stdtime_t) offset, endp, orig); + val = base - offset; } else if (strlen(str) == 8U) { char timestr[15]; sprintf(timestr, "%s000000", str); result = dns_time64_fromtext(timestr, &val); if (result != ISC_R_SUCCESS) - fatal("time value %s is invalid", str); + fatal("time value %s is invalid: %s", orig, + isc_result_totext(result)); + } else if (strlen(str) > 14U) { + fatal("time value %s is invalid", orig); } else { result = dns_time64_fromtext(str, &val); if (result != ISC_R_SUCCESS) - fatal("time value %s is invalid", str); + fatal("time value %s is invalid: %s", orig, + isc_result_totext(result)); } return ((isc_stdtime_t) val); @@ -311,3 +351,114 @@ strtoclass(const char *str) { fatal("unknown class %s", str); return (rdclass); } + +isc_result_t +try_dir(const char *dirname) { + isc_result_t result; + isc_dir_t d; + + isc_dir_init(&d); + result = isc_dir_open(&d, dirname); + if (result == ISC_R_SUCCESS) { + isc_dir_close(&d); + } + return (result); +} + +/* + * Check private key version compatibility. + */ +void +check_keyversion(dst_key_t *key, char *keystr) { + int major, minor; + dst_key_getprivateformat(key, &major, &minor); + INSIST(major <= DST_MAJOR_VERSION); /* invalid private key */ + + if (major < DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) + fatal("Key %s has incompatible format version %d.%d, " + "use -f to force upgrade to new version.", + keystr, major, minor); + if (minor > DST_MINOR_VERSION) + fatal("Key %s has incompatible format version %d.%d, " + "use -f to force downgrade to current version.", + keystr, major, minor); +} + +void +set_keyversion(dst_key_t *key) { + int major, minor; + dst_key_getprivateformat(key, &major, &minor); + INSIST(major <= DST_MAJOR_VERSION); + + if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION) + dst_key_setprivateformat(key, DST_MAJOR_VERSION, + DST_MINOR_VERSION); + + /* + * If the key is from a version older than 1.3, set + * set the creation date + */ + if (major < 1 || (major == 1 && minor <= 2)) { + isc_stdtime_t now; + isc_stdtime_get(&now); + dst_key_settime(key, DST_TIME_CREATED, now); + } +} + +isc_boolean_t +key_collision(isc_uint16_t id, dns_name_t *name, const char *dir, + dns_secalg_t alg, isc_mem_t *mctx, isc_boolean_t *exact) +{ + isc_result_t result; + isc_boolean_t conflict = ISC_FALSE; + dns_dnsseckeylist_t matchkeys; + dns_dnsseckey_t *key = NULL; + isc_uint16_t oldid, diff; + isc_uint16_t bits = DNS_KEYFLAG_REVOKE; /* flag bits to look for */ + + if (exact != NULL) + *exact = ISC_FALSE; + + ISC_LIST_INIT(matchkeys); + result = dns_dnssec_findmatchingkeys(name, dir, mctx, &matchkeys); + if (result == ISC_R_NOTFOUND) + return (ISC_FALSE); + + while (!ISC_LIST_EMPTY(matchkeys) && !conflict) { + key = ISC_LIST_HEAD(matchkeys); + if (dst_key_alg(key->key) != alg) + goto next; + + oldid = dst_key_id(key->key); + diff = (oldid > id) ? (oldid - id) : (id - oldid); + if ((diff & ~bits) == 0) { + conflict = ISC_TRUE; + if (diff != 0) { + if (verbose > 1) + fprintf(stderr, "Key ID %d could " + "collide with %d\n", + id, oldid); + } else { + if (exact != NULL) + *exact = ISC_TRUE; + if (verbose > 1) + fprintf(stderr, "Key ID %d exists\n", + id); + } + } + + next: + ISC_LIST_UNLINK(matchkeys, key, link); + dns_dnsseckey_destroy(mctx, &key); + } + + /* Finish freeing the list */ + while (!ISC_LIST_EMPTY(matchkeys)) { + key = ISC_LIST_HEAD(matchkeys); + ISC_LIST_UNLINK(matchkeys, key, link); + dns_dnsseckey_destroy(mctx, &key); + } + + return (conflict); +} + diff --git a/contrib/bind9/bin/dnssec/dnssectool.h b/contrib/bind9/bin/dnssec/dnssectool.h index 8cc133df42f4..b52bc135ea0e 100644 --- a/contrib/bind9/bin/dnssec/dnssectool.h +++ b/contrib/bind9/bin/dnssec/dnssectool.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssectool.h,v 1.22.48.2 2009-09-04 23:46:58 tbox Exp $ */ +/* $Id: dnssectool.h,v 1.31 2010-01-19 23:48:56 tbox Exp $ */ #ifndef DNSSECTOOL_H #define DNSSECTOOL_H 1 @@ -27,8 +27,9 @@ typedef void (fatalcallback_t)(void); -void -fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); +ISC_PLATFORM_NORETURN_PRE void +fatal(const char *format, ...) +ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; void setfatalcallback(fatalcallback_t *callback); @@ -44,16 +45,8 @@ type_format(const dns_rdatatype_t type, char *cp, unsigned int size); #define TYPE_FORMATSIZE 20 void -alg_format(const dns_secalg_t alg, char *cp, unsigned int size); -#define ALG_FORMATSIZE 20 - -void sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size); -#define SIG_FORMATSIZE (DNS_NAME_FORMATSIZE + ALG_FORMATSIZE + sizeof("65535")) - -void -key_format(const dst_key_t *key, char *cp, unsigned int size); -#define KEY_FORMATSIZE (DNS_NAME_FORMATSIZE + ALG_FORMATSIZE + sizeof("65535")) +#define SIG_FORMATSIZE (DNS_NAME_FORMATSIZE + DNS_SECALG_FORMATSIZE + sizeof("65535")) void setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp); @@ -67,10 +60,24 @@ setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx); void cleanup_entropy(isc_entropy_t **ectx); +dns_ttl_t strtottl(const char *str); + isc_stdtime_t strtotime(const char *str, isc_int64_t now, isc_int64_t base); dns_rdataclass_t strtoclass(const char *str); +isc_result_t +try_dir(const char *dirname); + +void +check_keyversion(dst_key_t *key, char *keystr); + +void +set_keyversion(dst_key_t *key); + +isc_boolean_t +key_collision(isc_uint16_t id, dns_name_t *name, const char *dir, + dns_secalg_t alg, isc_mem_t *mctx, isc_boolean_t *exact); #endif /* DNSSEC_DNSSECTOOL_H */ diff --git a/contrib/bind9/bin/named/Makefile.in b/contrib/bind9/bin/named/Makefile.in index ee7613435759..a3dbb3802dc9 100644 --- a/contrib/bind9/bin/named/Makefile.in +++ b/contrib/bind9/bin/named/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2002 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.101 2008-09-23 17:25:47 jinmei Exp $ +# $Id: Makefile.in,v 1.114 2010-12-22 09:00:40 marka Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -43,9 +43,9 @@ DLZDRIVER_LIBS = @DLZ_DRIVER_LIBS@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ - ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} + ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@ -CDEFINES = @USE_DLZ@ +CDEFINES = @USE_DLZ@ @USE_PKCS11@ @USE_OPENSSL@ CWARNINGS = @@ -53,6 +53,7 @@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ ISCCCLIBS = ../../lib/isccc/libisccc.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ LWRESLIBS = ../../lib/lwres/liblwres.@A@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ @@ -70,6 +71,10 @@ LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \ ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ +NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ + ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCNOSYMLIBS} \ + ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ + SUBDIRS = unix TARGETS = named@EXEEXT@ lwresd@EXEEXT@ @@ -86,10 +91,12 @@ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \ UOBJS = unix/os.@O@ +SYMOBJS = symtbl.@O@ + SRCS = builtin.c client.c config.c control.c \ controlconf.c interfacemgr.c \ listenlist.c log.c logconf.c main.c notify.c \ - query.c server.c sortlist.c statschannel.c \ + query.c server.c sortlist.c statschannel.c symtbl.c symtbl-empty.c \ tkeyconf.c tsigconf.c update.c xfrout.c \ zoneconf.c \ lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \ @@ -111,15 +118,20 @@ main.@O@: main.c -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ -DNS_SYSCONFDIR=\"${sysconfdir}\" -c ${srcdir}/main.c -config.@O@: config.c +bind.keys.h: ${top_srcdir}/bind.keys ${srcdir}/bindkeys.pl + ${PERL} ${srcdir}/bindkeys.pl < ${top_srcdir}/bind.keys > $@ + +config.@O@: config.c bind.keys.h ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -DVERSION=\"${VERSION}\" \ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ + -DNS_SYSCONFDIR=\"${sysconfdir}\" \ -c ${srcdir}/config.c named@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - ${OBJS} ${UOBJS} ${LIBS} + export MAKE_SYMTABLE="yes"; \ + export BASEOBJS="${OBJS} ${UOBJS}"; \ + ${FINALBUILDCMD} lwresd@EXEEXT@: named@EXEEXT@ rm -f lwresd@EXEEXT@ @@ -133,7 +145,10 @@ docclean manclean maintainer-clean:: clean distclean maintainer-clean:: rm -f ${TARGETS} ${OBJS} -bind9.xsl.h: bind9.xsl convertxsl.pl +maintainer-clean:: + rm -f bind.keys.h + +bind9.xsl.h: bind9.xsl ${srcdir}/convertxsl.pl ${PERL} ${srcdir}/convertxsl.pl < ${srcdir}/bind9.xsl > bind9.xsl.h depend: bind9.xsl.h diff --git a/contrib/bind9/bin/named/bind.keys.h b/contrib/bind9/bin/named/bind.keys.h new file mode 100644 index 000000000000..0177214159e7 --- /dev/null +++ b/contrib/bind9/bin/named/bind.keys.h @@ -0,0 +1,99 @@ +/* + * Generated by bindkeys.pl 1.7 2011-01-04 23:47:13 tbox Exp + * From bind.keys 1.7 2011-01-03 23:45:07 each Exp + */ +#define TRUSTED_KEYS "\ +# The bind.keys file is used to override the built-in DNSSEC trust anchors\n\ +# which are included as part of BIND 9. As of the current release, the only\n\ +# trust anchors it contains are those for the DNS root zone (\".\"), and for\n\ +# the ISC DNSSEC Lookaside Validation zone (\"dlv.isc.org\"). Trust anchors\n\ +# for any other zones MUST be configured elsewhere; if they are configured\n\ +# here, they will not be recognized or used by named.\n\ +#\n\ +# The built-in trust anchors are provided for convenience of configuration.\n\ +# They are not activated within named.conf unless specifically switched on.\n\ +# To use the built-in root key, set \"dnssec-validation auto;\" in\n\ +# named.conf options. To use the built-in DLV key, set\n\ +# \"dnssec-lookaside auto;\". Without these options being set,\n\ +# the keys in this file are ignored.\n\ +#\n\ +# This file is NOT expected to be user-configured.\n\ +#\n\ +# These keys are current as of January 2011. If any key fails to\n\ +# initialize correctly, it may have expired. In that event you should\n\ +# replace this file with a current version. The latest version of\n\ +# bind.keys can always be obtained from ISC at https://www.isc.org/bind-keys.\n\ +\n\ +trusted-keys {\n\ + # ISC DLV: See https://www.isc.org/solutions/dlv for details.\n\ + # NOTE: This key is activated by setting \"dnssec-lookaside auto;\"\n\ + # in named.conf.\n\ + dlv.isc.org. 257 3 5 \"BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWEn4MxDCE1+lLy2\n\ + brhQv5rN32RKtMzX6Mj70jdzeND4XknW58dnJNPCxn8+jAGl2FZLK8t+\n\ + 1uq4W+nnA3qO2+DL+k6BD4mewMLbIYFwe0PG73Te9fZ2kJb56dhgMde5\n\ + ymX4BI/oQ+cAK50/xvJv00Frf8kw6ucMTwFlgPe+jnGxPPEmHAte/URk\n\ + Y62ZfkLoBAADLHQ9IrS2tryAe7mbBZVcOwIeU/Rw/mRx/vwwMCTgNboM\n\ + QKtUdvNXDrYJDSHZws3xiRXF1Rf+al9UmZfSav/4NWLKjHzpT59k/VSt\n\ + TDN0YUuWrBNh\";\n\ +\n\ + # ROOT KEY: See https://data.iana.org/root-anchors/root-anchors.xml\n\ + # for current trust anchor information.\n\ + # NOTE: This key is activated by setting \"dnssec-validation auto;\"\n\ + # in named.conf.\n\ + . 257 3 8 \"AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF\n\ + FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX\n\ + bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD\n\ + X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz\n\ + W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS\n\ + Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq\n\ + QxA+Uk1ihz0=\";\n\ +};\n\ +" + +#define MANAGED_KEYS "\ +# The bind.keys file is used to override the built-in DNSSEC trust anchors\n\ +# which are included as part of BIND 9. As of the current release, the only\n\ +# trust anchors it contains are those for the DNS root zone (\".\"), and for\n\ +# the ISC DNSSEC Lookaside Validation zone (\"dlv.isc.org\"). Trust anchors\n\ +# for any other zones MUST be configured elsewhere; if they are configured\n\ +# here, they will not be recognized or used by named.\n\ +#\n\ +# The built-in trust anchors are provided for convenience of configuration.\n\ +# They are not activated within named.conf unless specifically switched on.\n\ +# To use the built-in root key, set \"dnssec-validation auto;\" in\n\ +# named.conf options. To use the built-in DLV key, set\n\ +# \"dnssec-lookaside auto;\". Without these options being set,\n\ +# the keys in this file are ignored.\n\ +#\n\ +# This file is NOT expected to be user-configured.\n\ +#\n\ +# These keys are current as of January 2011. If any key fails to\n\ +# initialize correctly, it may have expired. In that event you should\n\ +# replace this file with a current version. The latest version of\n\ +# bind.keys can always be obtained from ISC at https://www.isc.org/bind-keys.\n\ +\n\ +managed-keys {\n\ + # ISC DLV: See https://www.isc.org/solutions/dlv for details.\n\ + # NOTE: This key is activated by setting \"dnssec-lookaside auto;\"\n\ + # in named.conf.\n\ + dlv.isc.org. initial-key 257 3 5 \"BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWEn4MxDCE1+lLy2\n\ + brhQv5rN32RKtMzX6Mj70jdzeND4XknW58dnJNPCxn8+jAGl2FZLK8t+\n\ + 1uq4W+nnA3qO2+DL+k6BD4mewMLbIYFwe0PG73Te9fZ2kJb56dhgMde5\n\ + ymX4BI/oQ+cAK50/xvJv00Frf8kw6ucMTwFlgPe+jnGxPPEmHAte/URk\n\ + Y62ZfkLoBAADLHQ9IrS2tryAe7mbBZVcOwIeU/Rw/mRx/vwwMCTgNboM\n\ + QKtUdvNXDrYJDSHZws3xiRXF1Rf+al9UmZfSav/4NWLKjHzpT59k/VSt\n\ + TDN0YUuWrBNh\";\n\ +\n\ + # ROOT KEY: See https://data.iana.org/root-anchors/root-anchors.xml\n\ + # for current trust anchor information.\n\ + # NOTE: This key is activated by setting \"dnssec-validation auto;\"\n\ + # in named.conf.\n\ + . initial-key 257 3 8 \"AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF\n\ + FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX\n\ + bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD\n\ + X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz\n\ + W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS\n\ + Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq\n\ + QxA+Uk1ihz0=\";\n\ +};\n\ +" diff --git a/contrib/bind9/bin/named/bind9.xsl b/contrib/bind9/bin/named/bind9.xsl index 71d2eba108d2..5913c1cc2000 100644 --- a/contrib/bind9/bin/named/bind9.xsl +++ b/contrib/bind9/bin/named/bind9.xsl @@ -15,7 +15,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: bind9.xsl,v 1.19.82.2 2009-01-29 23:47:43 tbox Exp $ --> +<!-- $Id: bind9.xsl,v 1.21 2009-01-27 23:47:54 tbox Exp $ --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" diff --git a/contrib/bind9/bin/named/bind9.xsl.h b/contrib/bind9/bin/named/bind9.xsl.h index d68675131eb9..b6f1f5491b95 100644 --- a/contrib/bind9/bin/named/bind9.xsl.h +++ b/contrib/bind9/bin/named/bind9.xsl.h @@ -1,6 +1,6 @@ /* * Generated by convertxsl.pl 1.14 2008-07-17 23:43:26 jinmei Exp - * From bind9.xsl 1.19.82.2 2009-01-29 23:47:43 tbox Exp + * From bind9.xsl 1.21 2009-01-27 23:47:54 tbox Exp */ static char xslmsg[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" @@ -20,7 +20,7 @@ static char xslmsg[] = " - PERFORMANCE OF THIS SOFTWARE.\n" "-->\n" "\n" - "<!-- \045Id: bind9.xsl,v 1.19.82.2 2009-01-29 23:47:43 tbox Exp \045 -->\n" + "<!-- \045Id: bind9.xsl,v 1.21 2009-01-27 23:47:54 tbox Exp \045 -->\n" "\n" "<xsl:stylesheet version=\"1.0\"\n" " xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n" diff --git a/contrib/bind9/bin/named/builtin.c b/contrib/bind9/bin/named/builtin.c index 60cb634fabd3..d7730e7afed0 100644 --- a/contrib/bind9/bin/named/builtin.c +++ b/contrib/bind9/bin/named/builtin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: builtin.c,v 1.12.334.3 2010-08-03 23:45:47 tbox Exp $ */ +/* $Id: builtin.c,v 1.20 2011-01-07 23:47:07 tbox Exp $ */ /*! \file * \brief @@ -47,6 +47,7 @@ static isc_result_t do_hostname_lookup(dns_sdblookup_t *lookup); static isc_result_t do_authors_lookup(dns_sdblookup_t *lookup); static isc_result_t do_id_lookup(dns_sdblookup_t *lookup); static isc_result_t do_empty_lookup(dns_sdblookup_t *lookup); +static isc_result_t do_dns64_lookup(dns_sdblookup_t *lookup); /* * We can't use function pointers as the db_data directly @@ -65,9 +66,179 @@ static builtin_t hostname_builtin = { do_hostname_lookup, NULL, NULL }; static builtin_t authors_builtin = { do_authors_lookup, NULL, NULL }; static builtin_t id_builtin = { do_id_lookup, NULL, NULL }; static builtin_t empty_builtin = { do_empty_lookup, NULL, NULL }; +static builtin_t dns64_builtin = { do_dns64_lookup, NULL, NULL }; static dns_sdbimplementation_t *builtin_impl; +static const char hex[] = "0123456789abcdef"; +static const char HEX[] = "0123456789ABCDEF"; + +static isc_result_t +dns64_cname(const char *zone, const char *name, dns_sdblookup_t *lookup) { + size_t zlen, nlen, j; + const char *s; + unsigned char v[16]; + unsigned int i; + char reverse[sizeof("123.123.123.123.in-addr.arpa.")]; + + /* + * The sum the length of the relative name and the length of the zone + * name for a IPv6 reverse lookup comes to 71. + * + * The reverse of 2001::10.0.0.1 (dns64 2001::/96) has a zone of + * "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.2.ip6.arpa" + * and a name of "1.0.0.0.0.0.a.0". The sum of the lengths of these + * two strings is 71. + * + * The minimum length for a ip6.arpa zone name is 8. + * + * The length of name should always be odd as we are expecting + * a series of nibbles. + */ + zlen = strlen(zone); + nlen = strlen(name); + if ((zlen + nlen) > 71U || zlen < 8U || (nlen % 2) != 1U) + return (ISC_R_NOTFOUND); + + /* + * We assume the zone name is well formed. + */ + + /* + * XXXMPA We could check the dns64 suffix here if we need to. + */ + /* + * Check that name is a series of nibbles. + * Compute the byte values that correspond to the nibbles as we go. + * + * Shift the final result 4 bits, by setting 'i' to 1, if we if we + * have a odd number of nibbles so that "must be zero" tests below + * are byte aligned and we correctly return ISC_R_NOTFOUND or + * ISC_R_SUCCESS. We will not generate a CNAME in this case. + */ + i = (nlen % 4) == 1U ? 1 : 0; + j = nlen; + memset(v, 0, sizeof(v)); + while (j >= 1U) { + INSIST((i/2) < sizeof(v)); + if (j > 1U && name[1] != '.') + return (ISC_R_NOTFOUND); + v[i/2] >>= 4; + if ((s = strchr(hex, name[0])) != NULL) + v[i/2] |= (s - hex) << 4; + else if ((s = strchr(HEX, name[0])) != NULL) + v[i/2] |= (s - HEX) << 4; + else + return (ISC_R_NOTFOUND); + if (j > 1U) + j -= 2; + else + j -= 1; + name += 2; + i++; + } + + /* + * If we get here then we know name only consisted of nibbles. + * Now we need to determine if the name exists or not and whether + * it corresponds to a empty node in the zone or there should be + * a CNAME. + */ + switch (zlen) { + case 24: /* prefix len 32 */ + /* + * If the total length is not 71 then this is a empty node + * so return success. + */ + if (nlen + zlen != 71U) + return (ISC_R_SUCCESS); + snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.", + v[8], v[9], v[10], v[11]); + break; + case 28: /* prefix len 40 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (nlen > 11U && v[nlen/4 - 3] != 0) + return (ISC_R_NOTFOUND); + /* + * If the total length is not 71 then this is a empty node + * so return success. + */ + if (nlen + zlen != 71U) + return (ISC_R_SUCCESS); + snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.", + v[6], v[8], v[9], v[10]); + break; + case 32: /* prefix len 48 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (nlen > 7U && v[nlen/4 - 2] != 0) + return (ISC_R_NOTFOUND); + /* + * If the total length is not 71 then this is a empty node + * so return success. + */ + if (nlen + zlen != 71U) + return (ISC_R_SUCCESS); + snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.", + v[5], v[6], v[8], v[9]); + break; + case 36: /* prefix len 56 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (nlen > 3U && v[nlen/4 - 1] != 0) + return (ISC_R_NOTFOUND); + /* + * If the total length is not 71 then this is a empty node + * so return success. + */ + if (nlen + zlen != 71U) + return (ISC_R_SUCCESS); + snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.", + v[4], v[5], v[6], v[8]); + break; + case 40: /* prefix len 64 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (v[nlen/4] != 0) + return (ISC_R_NOTFOUND); + /* + * If the total length is not 71 then this is a empty node + * so return success. + */ + if (nlen + zlen != 71U) + return (ISC_R_SUCCESS); + snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.", + v[3], v[4], v[5], v[6]); + break; + case 56: /* prefix len 96 */ + /* + * If the total length is not 71 then this is a empty node + * so return success. + */ + if (nlen + zlen != 71U) + return (ISC_R_SUCCESS); + snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.", + v[0], v[1], v[2], v[3]); + break; + default: + /* + * This should never be reached unless someone adds a + * zone declaration with this internal type to named.conf. + */ + return (ISC_R_NOTFOUND); + } + return (dns_sdb_putrr(lookup, "CNAME", 600, reverse)); +} + static isc_result_t builtin_lookup(const char *zone, const char *name, void *dbdata, dns_sdblookup_t *lookup) @@ -78,6 +249,8 @@ builtin_lookup(const char *zone, const char *name, void *dbdata, if (strcmp(name, "@") == 0) return (b->do_lookup(lookup)); + else if (b->do_lookup == do_dns64_lookup) + return (dns64_cname(zone, name, lookup)); else return (ISC_R_NOTFOUND); } @@ -132,11 +305,13 @@ do_authors_lookup(dns_sdblookup_t *lookup) { "Michael Graff", "Andreas Gustafsson", "Bob Halley", + "Evan Hunt", "JINMEI Tatuya", "David Lawrence", "Danny Mayer", "Damien Neil", "Matt Nelson", + "Jeremy C. Reed", "Michael Sawyer", "Brian Wellington", NULL @@ -174,6 +349,12 @@ do_id_lookup(dns_sdblookup_t *lookup) { } static isc_result_t +do_dns64_lookup(dns_sdblookup_t *lookup) { + UNUSED(lookup); + return (ISC_R_SUCCESS); +} + +static isc_result_t do_empty_lookup(dns_sdblookup_t *lookup) { UNUSED(lookup); @@ -220,7 +401,7 @@ builtin_create(const char *zone, int argc, char **argv, UNUSED(zone); UNUSED(driverdata); - if (strcmp(argv[0], "empty") == 0) { + if (strcmp(argv[0], "empty") == 0 || strcmp(argv[0], "dns64") == 0) { if (argc != 3) return (DNS_R_SYNTAX); } else if (argc != 1) @@ -234,7 +415,8 @@ builtin_create(const char *zone, int argc, char **argv, *dbdata = &authors_builtin; else if (strcmp(argv[0], "id") == 0) *dbdata = &id_builtin; - else if (strcmp(argv[0], "empty") == 0) { + else if (strcmp(argv[0], "empty") == 0 || + strcmp(argv[0], "dns64") == 0) { builtin_t *empty; char *server; char *contact; @@ -246,7 +428,10 @@ builtin_create(const char *zone, int argc, char **argv, server = isc_mem_strdup(ns_g_mctx, argv[1]); contact = isc_mem_strdup(ns_g_mctx, argv[2]); if (empty == NULL || server == NULL || contact == NULL) { - *dbdata = &empty_builtin; + if (strcmp(argv[0], "empty") == 0) + *dbdata = &empty_builtin; + else + *dbdata = &dns64_builtin; if (server != NULL) isc_mem_free(ns_g_mctx, server); if (contact != NULL) @@ -254,7 +439,12 @@ builtin_create(const char *zone, int argc, char **argv, if (empty != NULL) isc_mem_put(ns_g_mctx, empty, sizeof (*empty)); } else { - memcpy(empty, &empty_builtin, sizeof (empty_builtin)); + if (strcmp(argv[0], "empty") == 0) + memcpy(empty, &empty_builtin, + sizeof (empty_builtin)); + else + memcpy(empty, &dns64_builtin, + sizeof (empty_builtin)); empty->server = server; empty->contact = contact; *dbdata = empty; @@ -276,7 +466,7 @@ builtin_destroy(const char *zone, void *driverdata, void **dbdata) { */ if (*dbdata == &version_builtin || *dbdata == &hostname_builtin || *dbdata == &authors_builtin || *dbdata == &id_builtin || - *dbdata == &empty_builtin) + *dbdata == &empty_builtin || *dbdata == &dns64_builtin) return; isc_mem_free(ns_g_mctx, b->server); @@ -306,3 +496,4 @@ void ns_builtin_deinit(void) { dns_sdb_unregister(&builtin_impl); } + diff --git a/contrib/bind9/bin/named/client.c b/contrib/bind9/bin/named/client.c index 6236d27f28a0..bc9cc878adbc 100644 --- a/contrib/bind9/bin/named/client.c +++ b/contrib/bind9/bin/named/client.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.c,v 1.259.12.5 2010-09-24 08:30:27 tbox Exp $ */ +/* $Id: client.c,v 1.271 2011-01-11 23:47:12 tbox Exp $ */ #include <config.h> @@ -918,7 +918,7 @@ ns_client_send(ns_client_t *client) { dns_compress_t cctx; isc_boolean_t cleanup_cctx = ISC_FALSE; unsigned char sendbuf[SEND_BUFFER_SIZE]; - unsigned int dnssec_opts; + unsigned int render_opts; unsigned int preferred_glue; isc_boolean_t opt_included = ISC_FALSE; @@ -930,10 +930,21 @@ ns_client_send(ns_client_t *client) { client->message->flags |= DNS_MESSAGEFLAG_RA; if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0) - dnssec_opts = 0; + render_opts = 0; else - dnssec_opts = DNS_MESSAGERENDER_OMITDNSSEC; - + render_opts = DNS_MESSAGERENDER_OMITDNSSEC; +#ifdef ALLOW_FILTER_AAAA_ON_V4 + /* + * filter-aaaa-on-v4 yes or break-dnssec option to suppress + * AAAA records + * We already know that request came via IPv4, + * that we have both AAAA and A records, + * and that we either have no signatures that the client wants + * or we are supposed to break DNSSEC. + */ + if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0) + render_opts |= DNS_MESSAGERENDER_FILTER_AAAA; +#endif preferred_glue = 0; if (client->view != NULL) { if (client->view->preferred_glue == dns_rdatatype_a) @@ -977,7 +988,7 @@ ns_client_send(ns_client_t *client) { result = dns_message_rendersection(client->message, DNS_SECTION_ANSWER, DNS_MESSAGERENDER_PARTIAL | - dnssec_opts); + render_opts); if (result == ISC_R_NOSPACE) { client->message->flags |= DNS_MESSAGEFLAG_TC; goto renderend; @@ -987,7 +998,7 @@ ns_client_send(ns_client_t *client) { result = dns_message_rendersection(client->message, DNS_SECTION_AUTHORITY, DNS_MESSAGERENDER_PARTIAL | - dnssec_opts); + render_opts); if (result == ISC_R_NOSPACE) { client->message->flags |= DNS_MESSAGEFLAG_TC; goto renderend; @@ -996,7 +1007,7 @@ ns_client_send(ns_client_t *client) { goto done; result = dns_message_rendersection(client->message, DNS_SECTION_ADDITIONAL, - preferred_glue | dnssec_opts); + preferred_glue | render_opts); if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) goto done; renderend: @@ -1355,7 +1366,6 @@ client_request(isc_task_t *task, isc_event_t *event) { dns_name_t *signame; isc_boolean_t ra; /* Recursion available. */ isc_netaddr_t netaddr; - isc_netaddr_t destaddr; int match; dns_messageid_t id; unsigned int flags; @@ -1473,7 +1483,7 @@ client_request(isc_task_t *task, isc_event_t *event) { /* * Silently drop multicast requests for the present. - * XXXMPA look at when/if mDNS spec stabilizes. + * XXXMPA revisit this as mDNS spec was published. */ if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) { ns_client_log(client, NS_LOGCATEGORY_CLIENT, @@ -1647,24 +1657,20 @@ client_request(isc_task_t *task, isc_event_t *event) { * etc), we regard this as an error for safety. */ if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0) - isc_netaddr_fromsockaddr(&destaddr, &client->interface->addr); + isc_netaddr_fromsockaddr(&client->destaddr, + &client->interface->addr); else { + isc_sockaddr_t sockaddr; result = ISC_R_FAILURE; - if (TCP_CLIENT(client)) { - isc_sockaddr_t destsockaddr; - + if (TCP_CLIENT(client)) result = isc_socket_getsockname(client->tcpsocket, - &destsockaddr); - if (result == ISC_R_SUCCESS) - isc_netaddr_fromsockaddr(&destaddr, - &destsockaddr); - } + &sockaddr); + if (result == ISC_R_SUCCESS) + isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr); if (result != ISC_R_SUCCESS && client->interface->addr.type.sa.sa_family == AF_INET6 && (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) { - isc_uint32_t zone = 0; - /* * XXXJT technically, we should convert the receiving * interface ID to a proper scope zone ID. However, @@ -1673,12 +1679,11 @@ client_request(isc_task_t *task, isc_event_t *event) { * interface index as link ID. Despite the assumption, * it should cover most typical cases. */ - if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr)) - zone = (isc_uint32_t)client->pktinfo.ipi6_ifindex; - - isc_netaddr_fromin6(&destaddr, + isc_netaddr_fromin6(&client->destaddr, &client->pktinfo.ipi6_addr); - isc_netaddr_setzone(&destaddr, zone); + if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr)) + isc_netaddr_setzone(&client->destaddr, + client->pktinfo.ipi6_ifindex); result = ISC_R_SUCCESS; } if (result != ISC_R_SUCCESS) { @@ -1708,7 +1713,8 @@ client_request(isc_task_t *task, isc_event_t *event) { tsig = dns_tsigkey_identity(client->message->tsigkey); if (allowed(&netaddr, tsig, view->matchclients) && - allowed(&destaddr, tsig, view->matchdestinations) && + allowed(&client->destaddr, tsig, + view->matchdestinations) && !((client->message->flags & DNS_MESSAGEFLAG_RD) == 0 && view->matchrecursiveonly)) { @@ -1771,9 +1777,11 @@ client_request(isc_task_t *task, isc_event_t *event) { } if (result == ISC_R_SUCCESS) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(&client->signername, namebuf, sizeof(namebuf)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), - "request has valid signature"); + "request has valid signature: %s", namebuf); client->signer = &client->signername; } else if (result == ISC_R_NOTFOUND) { ns_client_log(client, DNS_LOGCATEGORY_SECURITY, @@ -1861,10 +1869,10 @@ client_request(isc_task_t *task, isc_event_t *event) { ns_client_checkaclsilent(client, NULL, client->view->cacheacl, ISC_TRUE) == ISC_R_SUCCESS && - ns_client_checkaclsilent(client, &client->interface->addr, + ns_client_checkaclsilent(client, &client->destaddr, client->view->recursiononacl, ISC_TRUE) == ISC_R_SUCCESS && - ns_client_checkaclsilent(client, &client->interface->addr, + ns_client_checkaclsilent(client, &client->destaddr, client->view->cacheonacl, ISC_TRUE) == ISC_R_SUCCESS) ra = ISC_TRUE; @@ -2600,12 +2608,12 @@ ns_client_getsockaddr(ns_client_t *client) { } isc_result_t -ns_client_checkaclsilent(ns_client_t *client, isc_sockaddr_t *sockaddr, +ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr, dns_acl_t *acl, isc_boolean_t default_allow) { isc_result_t result; + isc_netaddr_t tmpnetaddr; int match; - isc_netaddr_t netaddr; if (acl == NULL) { if (default_allow) @@ -2614,15 +2622,13 @@ ns_client_checkaclsilent(ns_client_t *client, isc_sockaddr_t *sockaddr, goto deny; } + if (netaddr == NULL) { + isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr); + netaddr = &tmpnetaddr; + } - if (sockaddr == NULL) - isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); - else - isc_netaddr_fromsockaddr(&netaddr, sockaddr); - - result = dns_acl_match(&netaddr, client->signer, acl, - &ns_g_server->aclenv, - &match, NULL); + result = dns_acl_match(netaddr, client->signer, acl, + &ns_g_server->aclenv, &match, NULL); if (result != ISC_R_SUCCESS) goto deny; /* Internal error, already logged. */ @@ -2642,8 +2648,14 @@ ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr, const char *opname, dns_acl_t *acl, isc_boolean_t default_allow, int log_level) { - isc_result_t result = - ns_client_checkaclsilent(client, sockaddr, acl, default_allow); + isc_result_t result; + isc_netaddr_t netaddr; + + if (sockaddr != NULL) + isc_netaddr_fromsockaddr(&netaddr, sockaddr); + + result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL, + acl, default_allow); if (result == ISC_R_SUCCESS) ns_client_log(client, DNS_LOGCATEGORY_SECURITY, @@ -2753,9 +2765,14 @@ void ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { ns_client_t *client; char namebuf[DNS_NAME_FORMATSIZE]; + char original[DNS_NAME_FORMATSIZE]; char peerbuf[ISC_SOCKADDR_FORMATSIZE]; + char typebuf[DNS_RDATATYPE_FORMATSIZE]; + char classbuf[DNS_RDATACLASS_FORMATSIZE]; const char *name; const char *sep; + const char *origfor; + dns_rdataset_t *rdataset; REQUIRE(VALID_MANAGER(manager)); @@ -2773,8 +2790,31 @@ ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { sep = ""; } dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); - fprintf(f, "; client %s%s%s: '%s' requesttime %d\n", - peerbuf, sep, name, namebuf, client->requesttime); + if (client->query.qname != client->query.origqname && + client->query.origqname != NULL) { + origfor = " for "; + dns_name_format(client->query.origqname, original, + sizeof(original)); + } else { + origfor = ""; + original[0] = '\0'; + } + rdataset = ISC_LIST_HEAD(client->query.qname->list); + if (rdataset == NULL && client->query.origqname != NULL) + rdataset = ISC_LIST_HEAD(client->query.origqname->list); + if (rdataset != NULL) { + dns_rdatatype_format(rdataset->type, typebuf, + sizeof(typebuf)); + dns_rdataclass_format(rdataset->rdclass, classbuf, + sizeof(classbuf)); + } else { + strcpy(typebuf, "-"); + strcpy(classbuf, "-"); + } + fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s " + "requesttime %d\n", peerbuf, sep, name, + client->message->id, namebuf, typebuf, classbuf, + origfor, original, client->requesttime); client = ISC_LIST_NEXT(client, link); } UNLOCK(&manager->lock); diff --git a/contrib/bind9/bin/named/config.c b/contrib/bind9/bin/named/config.c index 43d0e5287d04..704d7ecc55ef 100644 --- a/contrib/bind9/bin/named/config.c +++ b/contrib/bind9/bin/named/config.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.c,v 1.93.14.2 2009-03-17 23:47:28 tbox Exp $ */ +/* $Id: config.c,v 1.113.16.1.2.1 2011-06-02 23:47:28 tbox Exp $ */ /*! \file */ @@ -42,9 +42,13 @@ #include <dns/tsig.h> #include <dns/zone.h> +#include <dst/dst.h> + #include <named/config.h> #include <named/globals.h> +#include "bind.keys.h" + /*% default configuration */ static char defaultconf[] = "\ options {\n\ @@ -55,7 +59,10 @@ options {\n\ files unlimited;\n\ stacksize default;\n" #endif -" deallocate-on-exit true;\n\ +"# session-keyfile \"" NS_LOCALSTATEDIR "/run/named/session.key\";\n\ + session-keyname local-ddns;\n\ + session-keyalg hmac-sha256;\n\ + deallocate-on-exit true;\n\ # directory <none>\n\ dump-file \"named_dump.db\";\n\ fake-iquery no;\n\ @@ -70,8 +77,10 @@ options {\n\ multiple-cnames no;\n\ # named-xfer <obsolete>;\n\ # pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\ + bindkeys-file \"" NS_SYSCONFDIR "/bind.keys\";\n\ port 53;\n\ recursing-file \"named.recursing\";\n\ + secroots-file \"named.secroots\";\n\ " #ifdef PATH_RANDOMDEV "\ @@ -80,6 +89,7 @@ options {\n\ #endif "\ recursive-clients 1000;\n\ + resolver-query-timeout 30;\n\ rrset-order {type NS order random; order cyclic; };\n\ serial-queries 20;\n\ serial-query-rate 20;\n\ @@ -102,6 +112,9 @@ options {\n\ request-nsid false;\n\ reserved-sockets 512;\n\ \n\ + /* DLV */\n\ + dnssec-lookaside . trust-anchor dlv.isc.org;\n\ +\n\ /* view */\n\ allow-notify {none;};\n\ allow-update-forwarding {none;};\n\ @@ -135,6 +148,7 @@ options {\n\ check-names master fail;\n\ check-names slave warn;\n\ check-names response ignore;\n\ + check-dup-records warn;\n\ check-mx warn;\n\ acache-enable no;\n\ acache-cleaning-interval 60;\n\ @@ -146,7 +160,13 @@ options {\n\ max-clients-per-query 100;\n\ zero-no-soa-ttl-cache no;\n\ nsec3-test-zone no;\n\ + allow-new-zones no;\n\ +" +#ifdef ALLOW_FILTER_AAAA_ON_V4 +" filter-aaaa-on-v4 no;\n\ + filter-aaaa { any; };\n\ " +#endif " /* zone */\n\ allow-query {any;};\n\ @@ -174,6 +194,7 @@ options {\n\ max-refresh-time 2419200; /* 4 weeks */\n\ min-refresh-time 300;\n\ multi-master no;\n\ + dnssec-secure-to-insecure no;\n\ sig-validity-interval 30; /* days */\n\ sig-signing-nodes 100;\n\ sig-signing-signatures 10;\n\ @@ -188,6 +209,7 @@ options {\n\ check-srv-cname warn;\n\ zero-no-soa-ttl yes;\n\ update-check-ksk yes;\n\ + dnssec-dnskey-kskonly no;\n\ try-tcp-refresh yes; /* BIND 8 compat */\n\ };\n\ " @@ -198,6 +220,7 @@ options {\n\ view \"_bind\" chaos {\n\ recursion no;\n\ notify no;\n\ + allow-new-zones no;\n\ \n\ zone \"version.bind\" chaos {\n\ type master;\n\ @@ -213,11 +236,24 @@ view \"_bind\" chaos {\n\ type master;\n\ database \"_builtin authors\";\n\ };\n\ +\n\ zone \"id.server\" chaos {\n\ type master;\n\ database \"_builtin id\";\n\ };\n\ };\n\ +" +"#\n\ +# Default trusted key(s) for builtin DLV support\n\ +# (used if \"dnssec-lookaside auto;\" is set and\n\ +# sysconfdir/bind.keys doesn't exist).\n\ +#\n\ +# BEGIN MANAGED KEYS\n" + +/* Imported from bind.keys.h: */ +MANAGED_KEYS + +"# END MANAGED KEYS\n\ "; isc_result_t @@ -339,6 +375,8 @@ ns_config_getzonetype(const cfg_obj_t *zonetypeobj) { ztype = dns_zone_slave; else if (strcasecmp(str, "stub") == 0) ztype = dns_zone_stub; + else if (strcasecmp(str, "static-stub") == 0) + ztype = dns_zone_staticstub; else INSIST(0); return (ztype); @@ -615,7 +653,7 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, isc_buffer_add(&b, strlen(keystr)); dns_fixedname_init(&fname); result = dns_name_fromtext(dns_fixedname_name(&fname), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_name_dup(dns_fixedname_name(&fname), mctx, @@ -747,23 +785,31 @@ struct keyalgorithms { const char *str; enum { hmacnone, hmacmd5, hmacsha1, hmacsha224, hmacsha256, hmacsha384, hmacsha512 } hmac; + unsigned int type; isc_uint16_t size; } algorithms[] = { - { "hmac-md5", hmacmd5, 128 }, - { "hmac-md5.sig-alg.reg.int", hmacmd5, 0 }, - { "hmac-md5.sig-alg.reg.int.", hmacmd5, 0 }, - { "hmac-sha1", hmacsha1, 160 }, - { "hmac-sha224", hmacsha224, 224 }, - { "hmac-sha256", hmacsha256, 256 }, - { "hmac-sha384", hmacsha384, 384 }, - { "hmac-sha512", hmacsha512, 512 }, - { NULL, hmacnone, 0 } + { "hmac-md5", hmacmd5, DST_ALG_HMACMD5, 128 }, + { "hmac-md5.sig-alg.reg.int", hmacmd5, DST_ALG_HMACMD5, 0 }, + { "hmac-md5.sig-alg.reg.int.", hmacmd5, DST_ALG_HMACMD5, 0 }, + { "hmac-sha1", hmacsha1, DST_ALG_HMACSHA1, 160 }, + { "hmac-sha224", hmacsha224, DST_ALG_HMACSHA224, 224 }, + { "hmac-sha256", hmacsha256, DST_ALG_HMACSHA256, 256 }, + { "hmac-sha384", hmacsha384, DST_ALG_HMACSHA384, 384 }, + { "hmac-sha512", hmacsha512, DST_ALG_HMACSHA512, 512 }, + { NULL, hmacnone, DST_ALG_UNKNOWN, 0 } }; isc_result_t ns_config_getkeyalgorithm(const char *str, dns_name_t **name, isc_uint16_t *digestbits) { + return (ns_config_getkeyalgorithm2(str, name, NULL, digestbits)); +} + +isc_result_t +ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, + unsigned int *typep, isc_uint16_t *digestbits) +{ int i; size_t len = 0; isc_uint16_t bits; @@ -801,6 +847,8 @@ ns_config_getkeyalgorithm(const char *str, dns_name_t **name, INSIST(0); } } + if (typep != NULL) + *typep = algorithms[i].type; if (digestbits != NULL) *digestbits = bits; return (ISC_R_SUCCESS); diff --git a/contrib/bind9/bin/named/control.c b/contrib/bind9/bin/named/control.c index 38115d607bbb..3fc7bd3916f5 100644 --- a/contrib/bind9/bin/named/control.c +++ b/contrib/bind9/bin/named/control.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: control.c,v 1.33.266.4 2010-12-03 23:45:46 tbox Exp $ */ +/* $Id: control.c,v 1.41 2010-12-03 22:05:19 each Exp $ */ /*! \file */ @@ -158,6 +158,8 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { } else if (command_compare(command, NS_COMMAND_DUMPDB)) { ns_server_dumpdb(ns_g_server, command); result = ISC_R_SUCCESS; + } else if (command_compare(command, NS_COMMAND_SECROOTS)) { + result = ns_server_dumpsecroots(ns_g_server, command); } else if (command_compare(command, NS_COMMAND_TRACE)) { result = ns_server_setdebuglevel(ns_g_server, command); } else if (command_compare(command, NS_COMMAND_NOTRACE)) { @@ -192,6 +194,13 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { result = ns_server_notifycommand(ns_g_server, command, text); } else if (command_compare(command, NS_COMMAND_VALIDATION)) { result = ns_server_validation(ns_g_server, command); + } else if (command_compare(command, NS_COMMAND_SIGN) || + command_compare(command, NS_COMMAND_LOADKEYS)) { + result = ns_server_rekey(ns_g_server, command); + } else if (command_compare(command, NS_COMMAND_ADDZONE)) { + result = ns_server_add_zone(ns_g_server, command); + } else if (command_compare(command, NS_COMMAND_DELZONE)) { + result = ns_server_del_zone(ns_g_server, command); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, diff --git a/contrib/bind9/bin/named/include/named/client.h b/contrib/bind9/bin/named/include/named/client.h index 5ad9c6bf5ff0..33f124d94c14 100644 --- a/contrib/bind9/bin/named/include/named/client.h +++ b/contrib/bind9/bin/named/include/named/client.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.h,v 1.86.120.2 2009-01-18 23:47:34 tbox Exp $ */ +/* $Id: client.h,v 1.91 2009-10-26 23:14:53 each Exp $ */ #ifndef NAMED_CLIENT_H #define NAMED_CLIENT_H 1 @@ -138,6 +138,7 @@ struct ns_client { ns_interface_t *interface; isc_sockaddr_t peeraddr; isc_boolean_t peeraddr_valid; + isc_netaddr_t destaddr; struct in6_pktinfo pktinfo; isc_event_t ctlevent; /*% @@ -167,6 +168,10 @@ struct ns_client { #define NS_CLIENTATTR_MULTICAST 0x08 /*%< recv'd from multicast */ #define NS_CLIENTATTR_WANTDNSSEC 0x10 /*%< include dnssec records */ #define NS_CLIENTATTR_WANTNSID 0x20 /*%< include nameserver ID */ +#ifdef ALLOW_FILTER_AAAA_ON_V4 +#define NS_CLIENTATTR_FILTER_AAAA 0x40 /*%< suppress AAAAs */ +#define NS_CLIENTATTR_FILTER_AAAA_RC 0x80 /*%< recursing for A against AAAA */ +#endif extern unsigned int ns_client_requests; @@ -274,10 +279,8 @@ ns_client_getsockaddr(ns_client_t *client); */ isc_result_t -ns_client_checkaclsilent(ns_client_t *client, - isc_sockaddr_t *sockaddr, - dns_acl_t *acl, - isc_boolean_t default_allow); +ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr, + dns_acl_t *acl, isc_boolean_t default_allow); /*% * Convenience function for client request ACL checking. @@ -296,12 +299,12 @@ ns_client_checkaclsilent(ns_client_t *client, * * Requires: *\li 'client' points to a valid client. - *\li 'sockaddr' points to a valid address, or is NULL. + *\li 'netaddr' points to a valid address, or is NULL. *\li 'acl' points to a valid ACL, or is NULL. * * Returns: *\li ISC_R_SUCCESS if the request should be allowed - * \li ISC_R_REFUSED if the request should be denied + * \li DNS_R_REFUSED if the request should be denied *\li No other return values are possible. */ diff --git a/contrib/bind9/bin/named/include/named/config.h b/contrib/bind9/bin/named/include/named/config.h index fa96d32947e3..d1570b0e5704 100644 --- a/contrib/bind9/bin/named/include/named/config.h +++ b/contrib/bind9/bin/named/include/named/config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001, 2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.h,v 1.14 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: config.h,v 1.16 2009-06-11 23:47:55 tbox Exp $ */ #ifndef NAMED_CONFIG_H #define NAMED_CONFIG_H 1 @@ -75,5 +75,8 @@ ns_config_getport(const cfg_obj_t *config, in_port_t *portp); isc_result_t ns_config_getkeyalgorithm(const char *str, dns_name_t **name, isc_uint16_t *digestbits); +isc_result_t +ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, + unsigned int *typep, isc_uint16_t *digestbits); #endif /* NAMED_CONFIG_H */ diff --git a/contrib/bind9/bin/named/include/named/control.h b/contrib/bind9/bin/named/include/named/control.h index 436fb19c7bf6..e699892ca4ce 100644 --- a/contrib/bind9/bin/named/include/named/control.h +++ b/contrib/bind9/bin/named/include/named/control.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: control.h,v 1.25 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: control.h,v 1.31 2010-08-16 22:21:06 marka Exp $ */ #ifndef NAMED_CONTROL_H #define NAMED_CONTROL_H 1 @@ -42,6 +42,7 @@ #define NS_COMMAND_DUMPSTATS "stats" #define NS_COMMAND_QUERYLOG "querylog" #define NS_COMMAND_DUMPDB "dumpdb" +#define NS_COMMAND_SECROOTS "secroots" #define NS_COMMAND_TRACE "trace" #define NS_COMMAND_NOTRACE "notrace" #define NS_COMMAND_FLUSH "flush" @@ -57,6 +58,10 @@ #define NS_COMMAND_NULL "null" #define NS_COMMAND_NOTIFY "notify" #define NS_COMMAND_VALIDATION "validation" +#define NS_COMMAND_SIGN "sign" +#define NS_COMMAND_LOADKEYS "loadkeys" +#define NS_COMMAND_ADDZONE "addzone" +#define NS_COMMAND_DELZONE "delzone" isc_result_t ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp); diff --git a/contrib/bind9/bin/named/include/named/globals.h b/contrib/bind9/bin/named/include/named/globals.h index 1d57a18f2008..f155c7f05ed5 100644 --- a/contrib/bind9/bin/named/include/named/globals.h +++ b/contrib/bind9/bin/named/include/named/globals.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: globals.h,v 1.80.12.3 2010-09-15 12:16:50 marka Exp $ */ +/* $Id: globals.h,v 1.89 2010-09-15 12:07:55 marka Exp $ */ #ifndef NAMED_GLOBALS_H #define NAMED_GLOBALS_H 1 @@ -30,6 +30,8 @@ #include <dns/zone.h> +#include <dst/dst.h> + #include <named/types.h> #undef EXTERN @@ -86,8 +88,13 @@ EXTERN cfg_obj_t * ns_g_config INIT(NULL); EXTERN const cfg_obj_t * ns_g_defaults INIT(NULL); EXTERN const char * ns_g_conffile INIT(NS_SYSCONFDIR "/named.conf"); +EXTERN cfg_obj_t * ns_g_bindkeys INIT(NULL); EXTERN const char * ns_g_keyfile INIT(NS_SYSCONFDIR "/rndc.key"); + +EXTERN dns_tsigkey_t * ns_g_sessionkey INIT(NULL); +EXTERN dns_name_t ns_g_sessionkeyname; + EXTERN const char * lwresd_g_conffile INIT(NS_SYSCONFDIR "/lwresd.conf"); EXTERN const char * lwresd_g_resolvconffile INIT("/etc" @@ -112,6 +119,10 @@ EXTERN const char * ns_g_chrootdir INIT(NULL); EXTERN isc_boolean_t ns_g_foreground INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_logstderr INIT(ISC_FALSE); +EXTERN const char * ns_g_defaultsessionkeyfile + INIT(NS_LOCALSTATEDIR "/run/named/" + "session.key"); + #if NS_RUN_PID_DIR EXTERN const char * ns_g_defaultpidfile INIT(NS_LOCALSTATEDIR "/run/named/" @@ -128,6 +139,12 @@ EXTERN const char * lwresd_g_defaultpidfile INIT(NS_LOCALSTATEDIR EXTERN const char * ns_g_username INIT(NULL); +#ifdef USE_PKCS11 +EXTERN const char * ns_g_engine INIT("pkcs11"); +#else +EXTERN const char * ns_g_engine INIT(NULL); +#endif + EXTERN int ns_g_listen INIT(3); EXTERN isc_time_t ns_g_boottime; EXTERN isc_boolean_t ns_g_memstatistics INIT(ISC_FALSE); diff --git a/contrib/bind9/bin/named/include/named/log.h b/contrib/bind9/bin/named/include/named/log.h index 0cfbee9ad396..1ce680f31e02 100644 --- a/contrib/bind9/bin/named/include/named/log.h +++ b/contrib/bind9/bin/named/include/named/log.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.h,v 1.25.332.2 2009-01-07 23:47:16 tbox Exp $ */ +/* $Id: log.h,v 1.27 2009-01-07 23:47:46 tbox Exp $ */ #ifndef NAMED_LOG_H #define NAMED_LOG_H 1 diff --git a/contrib/bind9/bin/named/include/named/lwdclient.h b/contrib/bind9/bin/named/include/named/lwdclient.h index 44e1fa6e0878..5451b73675ab 100644 --- a/contrib/bind9/bin/named/include/named/lwdclient.h +++ b/contrib/bind9/bin/named/include/named/lwdclient.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwdclient.h,v 1.18.332.2 2009-01-18 23:47:34 tbox Exp $ */ +/* $Id: lwdclient.h,v 1.20 2009-01-17 23:47:42 tbox Exp $ */ #ifndef NAMED_LWDCLIENT_H #define NAMED_LWDCLIENT_H 1 diff --git a/contrib/bind9/bin/named/include/named/main.h b/contrib/bind9/bin/named/include/named/main.h index 96fb23edd80a..6116add55b85 100644 --- a/contrib/bind9/bin/named/include/named/main.h +++ b/contrib/bind9/bin/named/include/named/main.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,15 +15,16 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: main.h,v 1.15 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: main.h,v 1.17 2009-09-29 23:48:03 tbox Exp $ */ #ifndef NAMED_MAIN_H #define NAMED_MAIN_H 1 /*! \file */ -void -ns_main_earlyfatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); +ISC_PLATFORM_NORETURN_PRE void +ns_main_earlyfatal(const char *format, ...) +ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; void ns_main_earlywarning(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); diff --git a/contrib/bind9/bin/named/include/named/notify.h b/contrib/bind9/bin/named/include/named/notify.h index ac7fe2d3a9a6..34fabcd0620c 100644 --- a/contrib/bind9/bin/named/include/named/notify.h +++ b/contrib/bind9/bin/named/include/named/notify.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: notify.h,v 1.14.332.2 2009-01-18 23:47:34 tbox Exp $ */ +/* $Id: notify.h,v 1.16 2009-01-17 23:47:42 tbox Exp $ */ #ifndef NAMED_NOTIFY_H #define NAMED_NOTIFY_H 1 diff --git a/contrib/bind9/bin/named/include/named/query.h b/contrib/bind9/bin/named/include/named/query.h index 2f00f1ea3843..37f771bd5960 100644 --- a/contrib/bind9/bin/named/include/named/query.h +++ b/contrib/bind9/bin/named/include/named/query.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2010, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.h,v 1.40.332.2 2010-09-24 08:30:28 tbox Exp $ */ +/* $Id: query.h,v 1.45 2011-01-13 04:59:24 tbox Exp $ */ #ifndef NAMED_QUERY_H #define NAMED_QUERY_H 1 @@ -26,6 +26,8 @@ #include <isc/buffer.h> #include <isc/netaddr.h> +#include <dns/rdataset.h> +#include <dns/rpz.h> #include <dns/types.h> #include <named/types.h> @@ -34,6 +36,7 @@ typedef struct ns_dbversion { dns_db_t *db; dns_dbversion_t *version; + isc_boolean_t acl_checked; isc_boolean_t queryok; ISC_LINK(struct ns_dbversion) link; } ns_dbversion_t; @@ -54,9 +57,16 @@ struct ns_query { isc_boolean_t isreferral; isc_mutex_t fetchlock; dns_fetch_t * fetch; + dns_rpz_st_t * rpz_st; isc_bufferlist_t namebufs; ISC_LIST(ns_dbversion_t) activeversions; ISC_LIST(ns_dbversion_t) freeversions; + dns_rdataset_t * dns64_aaaa; + dns_rdataset_t * dns64_sigaaaa; + isc_boolean_t * dns64_aaaaok; + unsigned int dns64_aaaaoklen; + unsigned int dns64_options; + unsigned int dns64_ttl; }; #define NS_QUERYATTR_RECURSIONOK 0x0001 @@ -73,6 +83,9 @@ struct ns_query { #define NS_QUERYATTR_NOADDITIONAL 0x0800 #define NS_QUERYATTR_CACHEACLOKVALID 0x1000 #define NS_QUERYATTR_CACHEACLOK 0x2000 +#define NS_QUERYATTR_DNS64 0x4000 +#define NS_QUERYATTR_DNS64EXCLUDE 0x8000 + isc_result_t ns_query_init(ns_client_t *client); diff --git a/contrib/bind9/bin/named/include/named/server.h b/contrib/bind9/bin/named/include/named/server.h index 3a4c5f7248e2..3c6426eecf61 100644 --- a/contrib/bind9/bin/named/include/named/server.h +++ b/contrib/bind9/bin/named/include/named/server.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.h,v 1.93.120.3 2009-07-11 04:23:53 marka Exp $ */ +/* $Id: server.h,v 1.110 2010-08-16 23:46:52 tbox Exp $ */ #ifndef NAMED_SERVER_H #define NAMED_SERVER_H 1 @@ -54,6 +54,8 @@ struct ns_server { dns_acl_t *blackholeacl; char * statsfile; /*%< Statistics file name */ char * dumpfile; /*%< Dump file name */ + char * secrootsfile; /*%< Secroots file name */ + char * bindkeysfile; /*%< bind.keys file name */ char * recfile; /*%< Recursive file name */ isc_boolean_t version_set; /*%< User has set version */ char * version; /*%< User-specified version */ @@ -91,13 +93,14 @@ struct ns_server { isc_boolean_t flushonshutdown; isc_boolean_t log_queries; /*%< For BIND 8 compatibility */ - isc_stats_t * nsstats; /*%< Server statistics */ - dns_stats_t * rcvquerystats; /*% Incoming query statistics */ - dns_stats_t * opcodestats; /*%< Incoming message statistics */ - isc_stats_t * zonestats; /*% Zone management statistics */ - isc_stats_t * resolverstats; /*% Resolver statistics */ + ns_cachelist_t cachelist; /*%< Possibly shared caches */ + isc_stats_t * nsstats; /*%< Server stats */ + dns_stats_t * rcvquerystats; /*% Incoming query stats */ + dns_stats_t * opcodestats; /*%< Incoming message stats */ + isc_stats_t * zonestats; /*% Zone management stats */ + isc_stats_t * resolverstats; /*% Resolver stats */ + isc_stats_t * sockstats; /*%< Socket stats */ - isc_stats_t * sockstats; /*%< Socket statistics */ ns_controls_t * controls; /*%< Control channels */ unsigned int dispatchgen; ns_dispatchlist_t dispatches; @@ -105,6 +108,12 @@ struct ns_server { dns_acache_t *acache; ns_statschannellist_t statschannels; + + dns_tsigkey_t *sessionkey; + char *session_keyfile; + dns_name_t *session_keyname; + unsigned int session_keyalg; + isc_uint16_t session_keybits; }; #define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R') @@ -237,6 +246,12 @@ isc_result_t ns_server_dumpdb(ns_server_t *server, char *args); /*% + * Dump the current security roots to the secroots file. + */ +isc_result_t +ns_server_dumpsecroots(ns_server_t *server, char *args); + +/*% * Change or increment the server debug level. */ isc_result_t @@ -280,6 +295,16 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, isc_buffer_t *text); /*% + * Update a zone's DNSKEY set from the key repository. If + * the command that triggered the call to this function was "sign", + * then force a full signing of the zone. If it was "loadkeys", + * then don't sign the zone; any needed changes to signatures can + * take place incrementally. + */ +isc_result_t +ns_server_rekey(ns_server_t *server, char *args); + +/*% * Dump the current recursive queries. */ isc_result_t @@ -297,4 +322,16 @@ ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr); isc_result_t ns_server_validation(ns_server_t *server, char *args); +/*% + * Add a zone to a running process + */ +isc_result_t +ns_server_add_zone(ns_server_t *server, char *args); + +/*% + * Deletes a zone from a running process + */ +isc_result_t +ns_server_del_zone(ns_server_t *server, char *args); + #endif /* NAMED_SERVER_H */ diff --git a/contrib/bind9/bin/named/include/named/tsigconf.h b/contrib/bind9/bin/named/include/named/tsigconf.h index a4841bad9df9..4a59ec2c0ff7 100644 --- a/contrib/bind9/bin/named/include/named/tsigconf.h +++ b/contrib/bind9/bin/named/include/named/tsigconf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tsigconf.h,v 1.16 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: tsigconf.h,v 1.18 2009-06-11 23:47:55 tbox Exp $ */ #ifndef NS_TSIGCONF_H #define NS_TSIGCONF_H 1 @@ -36,8 +36,9 @@ ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, * * Requires: * \li 'config' is not NULL. + * \li 'vconfig' is not NULL. * \li 'mctx' is not NULL - * \li 'ring' is not NULL, and '*ring' is NULL + * \li 'ringp' is not NULL, and '*ringp' is NULL * * Returns: * \li ISC_R_SUCCESS diff --git a/contrib/bind9/bin/named/include/named/types.h b/contrib/bind9/bin/named/include/named/types.h index b0729a787ba7..96c4c012b71f 100644 --- a/contrib/bind9/bin/named/include/named/types.h +++ b/contrib/bind9/bin/named/include/named/types.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: types.h,v 1.29 2008-01-17 23:46:59 tbox Exp $ */ +/* $Id: types.h,v 1.31 2009-01-09 23:47:45 tbox Exp $ */ #ifndef NAMED_TYPES_H #define NAMED_TYPES_H 1 @@ -24,6 +24,8 @@ #include <dns/types.h> +typedef struct ns_cache ns_cache_t; +typedef ISC_LIST(ns_cache_t) ns_cachelist_t; typedef struct ns_client ns_client_t; typedef struct ns_clientmgr ns_clientmgr_t; typedef struct ns_query ns_query_t; diff --git a/contrib/bind9/bin/named/include/named/zoneconf.h b/contrib/bind9/bin/named/include/named/zoneconf.h index ab84c84515bf..65cf72f9f3ac 100644 --- a/contrib/bind9/bin/named/include/named/zoneconf.h +++ b/contrib/bind9/bin/named/include/named/zoneconf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.h,v 1.26 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: zoneconf.h,v 1.28 2010-12-20 23:47:20 tbox Exp $ */ #ifndef NS_ZONECONF_H #define NS_ZONECONF_H 1 @@ -58,6 +58,21 @@ ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig); * and recreated, return ISC_FALSE. */ + +isc_result_t +ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, + dns_rdataclass_t rdclass, dns_name_t *name); +/*%> + * configure a DLZ zone, setting up the database methods and calling + * postload to load the origin values + * + * Require: + * \li 'dlzdatabase' to be a valid dlz database + * \li 'zone' to be initialized. + * \li 'rdclass' to be a valid rdataclass + * \li 'name' to be a valid zone origin name + */ + ISC_LANG_ENDDECLS #endif /* NS_ZONECONF_H */ diff --git a/contrib/bind9/bin/named/interfacemgr.c b/contrib/bind9/bin/named/interfacemgr.c index fad32137f6df..e99d3b9cfe38 100644 --- a/contrib/bind9/bin/named/interfacemgr.c +++ b/contrib/bind9/bin/named/interfacemgr.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfacemgr.c,v 1.93.70.2 2009-01-18 23:47:34 tbox Exp $ */ +/* $Id: interfacemgr.c,v 1.95 2009-01-17 23:47:42 tbox Exp $ */ /*! \file */ diff --git a/contrib/bind9/bin/named/log.c b/contrib/bind9/bin/named/log.c index 867ad56b8c51..5d1c942074ca 100644 --- a/contrib/bind9/bin/named/log.c +++ b/contrib/bind9/bin/named/log.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.c,v 1.46.334.3 2009-01-07 01:50:14 jinmei Exp $ */ +/* $Id: log.c,v 1.49 2009-01-07 01:46:40 jinmei Exp $ */ /*! \file */ diff --git a/contrib/bind9/bin/named/lwdgabn.c b/contrib/bind9/bin/named/lwdgabn.c index 66d724624a5c..6a609c9acc4f 100644 --- a/contrib/bind9/bin/named/lwdgabn.c +++ b/contrib/bind9/bin/named/lwdgabn.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwdgabn.c,v 1.22 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: lwdgabn.c,v 1.24 2009-09-02 23:48:01 tbox Exp $ */ /*! \file */ @@ -619,7 +619,7 @@ ns_lwdclient_processgabn(ns_lwdclient_t *client, lwres_buffer_t *b) { dns_fixedname_init(&client->target_name); dns_fixedname_init(&client->query_name); result = dns_name_fromtext(dns_fixedname_name(&client->query_name), - &namebuf, NULL, ISC_FALSE, NULL); + &namebuf, NULL, 0, NULL); if (result != ISC_R_SUCCESS) goto out; ns_lwsearchctx_init(&client->searchctx, diff --git a/contrib/bind9/bin/named/lwdgrbn.c b/contrib/bind9/bin/named/lwdgrbn.c index bf29a481c488..22b62c625c12 100644 --- a/contrib/bind9/bin/named/lwdgrbn.c +++ b/contrib/bind9/bin/named/lwdgrbn.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwdgrbn.c,v 1.20 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: lwdgrbn.c,v 1.22 2009-09-02 23:48:01 tbox Exp $ */ /*! \file */ @@ -472,7 +472,7 @@ ns_lwdclient_processgrbn(ns_lwdclient_t *client, lwres_buffer_t *b) { dns_fixedname_init(&client->query_name); result = dns_name_fromtext(dns_fixedname_name(&client->query_name), - &namebuf, NULL, ISC_FALSE, NULL); + &namebuf, NULL, 0, NULL); if (result != ISC_R_SUCCESS) goto out; ns_lwsearchctx_init(&client->searchctx, diff --git a/contrib/bind9/bin/named/lwresd.8 b/contrib/bind9/bin/named/lwresd.8 index d1e760d10887..30dfbd55e783 100644 --- a/contrib/bind9/bin/named/lwresd.8 +++ b/contrib/bind9/bin/named/lwresd.8 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: lwresd.8,v 1.29.14.2 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: lwresd.8,v 1.31 2009-07-11 01:12:45 tbox Exp $ .\" .hy 0 .ad l diff --git a/contrib/bind9/bin/named/lwresd.c b/contrib/bind9/bin/named/lwresd.c index b7dc0af1038f..ad3670960cb1 100644 --- a/contrib/bind9/bin/named/lwresd.c +++ b/contrib/bind9/bin/named/lwresd.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lwresd.c,v 1.58 2008-07-23 23:27:54 marka Exp $ */ +/* $Id: lwresd.c,v 1.60 2009-09-02 23:48:01 tbox Exp $ */ /*! \file * \brief @@ -372,8 +372,7 @@ ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres, strlen(searchstr)); isc_buffer_add(&namebuf, strlen(searchstr)); result = dns_name_fromtext(name, &namebuf, - dns_rootname, ISC_FALSE, - NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, diff --git a/contrib/bind9/bin/named/lwresd.docbook b/contrib/bind9/bin/named/lwresd.docbook index f8e1500d0479..934b5da21dcc 100644 --- a/contrib/bind9/bin/named/lwresd.docbook +++ b/contrib/bind9/bin/named/lwresd.docbook @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: lwresd.docbook,v 1.18.14.2 2009-01-22 23:47:05 tbox Exp $ --> +<!-- $Id: lwresd.docbook,v 1.20 2009-01-20 23:47:56 tbox Exp $ --> <refentry> <refentryinfo> <date>June 30, 2000</date> diff --git a/contrib/bind9/bin/named/lwresd.html b/contrib/bind9/bin/named/lwresd.html index dec47caa2b86..223b1c2c5250 100644 --- a/contrib/bind9/bin/named/lwresd.html +++ b/contrib/bind9/bin/named/lwresd.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: lwresd.html,v 1.25.14.2 2009-07-11 01:55:21 tbox Exp $ --> +<!-- $Id: lwresd.html,v 1.27 2009-07-11 01:12:45 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> diff --git a/contrib/bind9/bin/named/main.c b/contrib/bind9/bin/named/main.c index a1d94fff80d5..84d86b146f4c 100644 --- a/contrib/bind9/bin/named/main.c +++ b/contrib/bind9/bin/named/main.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: main.c,v 1.166.34.7 2010-09-15 12:16:49 marka Exp $ */ +/* $Id: main.c,v 1.180 2010-12-22 03:59:02 marka Exp $ */ /*! \file */ @@ -26,6 +26,7 @@ #include <string.h> #include <isc/app.h> +#include <isc/backtrace.h> #include <isc/commandline.h> #include <isc/dir.h> #include <isc/entropy.h> @@ -69,6 +70,12 @@ #include <named/ns_smf_globals.h> #endif +#ifdef OPENSSL +#include <openssl/opensslv.h> +#endif +#ifdef HAVE_LIBXML2 +#include <libxml/xmlversion.h> +#endif /* * Include header files for database drivers here. */ @@ -81,12 +88,20 @@ #include <dlz/dlz_drivers.h> #endif +/* + * The maximum number of stack frames to dump on assertion failure. + */ +#ifndef BACKTRACE_MAXFRAME +#define BACKTRACE_MAXFRAME 128 +#endif + static isc_boolean_t want_stats = ISC_FALSE; static char program_name[ISC_DIR_NAMEMAX] = "named"; static char absolute_conffile[ISC_DIR_PATHMAX]; static char saved_command_line[512]; static char version[512]; static unsigned int maxsocks = 0; +static int maxudp = 0; void ns_main_earlywarning(const char *format, ...) { @@ -129,10 +144,20 @@ ns_main_earlyfatal(const char *format, ...) { exit(1); } +ISC_PLATFORM_NORETURN_PRE static void +assertion_failed(const char *file, int line, isc_assertiontype_t type, + const char *cond) ISC_PLATFORM_NORETURN_POST; + static void assertion_failed(const char *file, int line, isc_assertiontype_t type, const char *cond) { + void *tracebuf[BACKTRACE_MAXFRAME]; + int i, nframes; + isc_result_t result; + const char *logsuffix = ""; + const char *fname; + /* * Handle assertion failures. */ @@ -144,10 +169,40 @@ assertion_failed(const char *file, int line, isc_assertiontype_t type, */ isc_assertion_setcallback(NULL); + result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, + &nframes); + if (result == ISC_R_SUCCESS && nframes > 0) + logsuffix = ", back trace"; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, - "%s:%d: %s(%s) failed", file, line, - isc_assertion_typetotext(type), cond); + "%s:%d: %s(%s) failed%s", file, line, + isc_assertion_typetotext(type), cond, logsuffix); + if (result == ISC_R_SUCCESS) { + for (i = 0; i < nframes; i++) { + unsigned long offset; + + fname = NULL; + result = isc_backtrace_getsymbol(tracebuf[i], + &fname, + &offset); + if (result == ISC_R_SUCCESS) { + isc_log_write(ns_g_lctx, + NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_MAIN, + ISC_LOG_CRITICAL, + "#%d %p in %s()+0x%lx", i, + tracebuf[i], fname, + offset); + } else { + isc_log_write(ns_g_lctx, + NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_MAIN, + ISC_LOG_CRITICAL, + "#%d %p in ??", i, + tracebuf[i]); + } + } + } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL, "exiting (due to assertion failure)"); @@ -162,9 +217,10 @@ assertion_failed(const char *file, int line, isc_assertiontype_t type, exit(1); } -static void +ISC_PLATFORM_NORETURN_PRE static void library_fatal_error(const char *file, int line, const char *format, - va_list args) ISC_FORMAT_PRINTF(3, 0); + va_list args) +ISC_FORMAT_PRINTF(3, 0) ISC_PLATFORM_NORETURN_POST; static void library_fatal_error(const char *file, int line, const char *format, @@ -248,8 +304,9 @@ usage(void) { } fprintf(stderr, "usage: named [-4|-6] [-c conffile] [-d debuglevel] " - "[-f|-g] [-n number_of_cpus]\n" - " [-p port] [-s] [-t chrootdir] [-u username]\n" + "[-E engine] [-f|-g]\n" + " [-n number_of_cpus] [-p port] [-s] " + "[-t chrootdir] [-u username]\n" " [-m {usage|trace|record|size|mctx}]\n"); } @@ -358,7 +415,7 @@ parse_command_line(int argc, char *argv[]) { isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, - "46c:C:d:fgi:lm:n:N:p:P:" + "46c:C:d:E:fFgi:lm:n:N:p:P:" "sS:t:T:u:vVx:")) != -1) { switch (ch) { case '4': @@ -394,6 +451,9 @@ parse_command_line(int argc, char *argv[]) { ns_g_debuglevel = parse_int(isc_commandline_argument, "debug level"); break; + case 'E': + ns_g_engine = isc_commandline_argument; + break; case 'f': ns_g_foreground = ISC_TRUE; break; @@ -451,12 +511,16 @@ parse_command_line(int argc, char *argv[]) { * clienttest: make clients single shot with their * own memory context. */ - if (strcmp(isc_commandline_argument, "clienttest") == 0) + if (!strcmp(isc_commandline_argument, "clienttest")) ns_g_clienttest = ISC_TRUE; else if (!strcmp(isc_commandline_argument, "nosoa")) ns_g_nosoa = ISC_TRUE; else if (!strcmp(isc_commandline_argument, "noaa")) ns_g_noaa = ISC_TRUE; + else if (!strcmp(isc_commandline_argument, "maxudp512")) + maxudp = 512; + else if (!strcmp(isc_commandline_argument, "maxudp1460")) + maxudp = 1460; else fprintf(stderr, "unknown -T flag '%s\n", isc_commandline_argument); @@ -470,13 +534,25 @@ parse_command_line(int argc, char *argv[]) { case 'V': printf("BIND %s built with %s\n", ns_g_version, ns_g_configargs); +#ifdef OPENSSL + printf("using OpenSSL version: %s\n", + OPENSSL_VERSION_TEXT); +#endif +#ifdef HAVE_LIBXML2 + printf("using libxml2 version: %s\n", + LIBXML_DOTTED_VERSION); +#endif exit(0); + case 'F': + /* Reserved for FIPS mode */ + /* FALLTHROUGH */ case '?': usage(); if (isc_commandline_option == '?') exit(0); ns_main_earlyfatal("unknown option '-%c'", isc_commandline_option); + /* FALLTHROUGH */ default: ns_main_earlyfatal("parsing options returned %d", ch); } @@ -529,6 +605,7 @@ create_managers(void) { isc_result_totext(result)); return (ISC_R_UNEXPECTED); } + isc__socketmgr_maxudp(ns_g_socketmgr, maxudp); result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &socks); if (result == ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, @@ -579,6 +656,34 @@ destroy_managers(void) { } static void +dump_symboltable() { + int i; + isc_result_t result; + const char *fname; + const void *addr; + + if (isc__backtrace_nsymbols == 0) + return; + + if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(99))) + return; + + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, + ISC_LOG_DEBUG(99), "Symbol table:"); + + for (i = 0, result = ISC_R_SUCCESS; result == ISC_R_SUCCESS; i++) { + addr = NULL; + fname = NULL; + result = isc_backtrace_getsymbolfromindex(i, &addr, &fname); + if (result == ISC_R_SUCCESS) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(99), + "[%d] %p %s", i, addr, fname); + } + } +} + +static void setup(void) { isc_result_t result; isc_resourcevalue_t old_openfiles; @@ -685,6 +790,8 @@ setup(void) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "built with %s", ns_g_configargs); + dump_symboltable(); + /* * Get the initial resource limits. */ @@ -723,8 +830,8 @@ setup(void) { absolute_conffile, sizeof(absolute_conffile)); if (result != ISC_R_SUCCESS) - ns_main_earlyfatal("could not construct absolute path of " - "configuration file: %s", + ns_main_earlyfatal("could not construct absolute path " + "of configuration file: %s", isc_result_totext(result)); ns_g_conffile = absolute_conffile; } @@ -896,6 +1003,9 @@ main(int argc, char *argv[]) { if (strcmp(program_name, "lwresd") == 0) ns_g_lwresdonly = ISC_TRUE; + if (result != ISC_R_SUCCESS) + ns_main_earlyfatal("failed to build internal symbol table"); + isc_assertion_setcallback(assertion_failed); isc_error_setfatal(library_fatal_error); isc_error_setunexpected(library_unexpected_error); diff --git a/contrib/bind9/bin/named/named.8 b/contrib/bind9/bin/named/named.8 index 90782ed8171e..23805b04a935 100644 --- a/contrib/bind9/bin/named/named.8 +++ b/contrib/bind9/bin/named/named.8 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: named.8,v 1.38.14.2 2009-12-03 05:06:38 tbox Exp $ +.\" $Id: named.8,v 1.41 2009-10-06 01:14:41 tbox Exp $ .\" .hy 0 .ad l @@ -33,7 +33,7 @@ named \- Internet domain name server .SH "SYNOPSIS" .HP 6 -\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR] +\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-E\ \fR\fB\fIengine\-name\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR] .SH "DESCRIPTION" .PP \fBnamed\fR @@ -83,6 +83,13 @@ Set the daemon's debug level to become more verbose as the debug level increases. .RE .PP +\-E \fIengine\-name\fR +.RS 4 +Use a crypto hardware (OpenSSL engine) for the crypto operations it supports, for instance re\-signing with private keys from a secure key store. When compiled with PKCS#11 support +\fIengine\-name\fR +defaults to pkcs11, the empty name resets it to no engine. +.RE +.PP \-f .RS 4 Run the server in the foreground (i.e. do not daemonize). diff --git a/contrib/bind9/bin/named/named.conf.5 b/contrib/bind9/bin/named/named.conf.5 index cd0d4ad75543..9dc7002b09c9 100644 --- a/contrib/bind9/bin/named/named.conf.5 +++ b/contrib/bind9/bin/named/named.conf.5 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004-2011 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 @@ -12,7 +12,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: named.conf.5,v 1.36.48.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: named.conf.5,v 1.44.12.1 2011-02-03 12:29:12 tbox Exp $ .\" .hy 0 .ad l @@ -102,6 +102,15 @@ trusted\-keys { }; .fi .RE +.SH "MANAGED\-KEYS" +.sp +.RS 4 +.nf +managed\-keys { + \fIdomain_name\fR \fBinitial\-key\fR \fIflags\fR \fIprotocol\fR \fIalgorithm\fR \fIkey\fR; ... +}; +.fi +.RE .SH "CONTROLS" .sp .RS 4 @@ -186,6 +195,7 @@ options { tcp\-listen\-queue \fIinteger\fR; tkey\-dhkey \fIquoted_string\fR \fIinteger\fR; tkey\-gssapi\-credential \fIquoted_string\fR; + tkey\-gssapi\-keytab \fIquoted_string\fR; tkey\-domain \fIquoted_string\fR; transfers\-per\-ns \fIinteger\fR; transfers\-in \fIinteger\fR; @@ -214,6 +224,7 @@ options { queryport\-pool\-ports \fIinteger\fR; queryport\-pool\-updateinterval \fIinteger\fR; cleaning\-interval \fIinteger\fR; + resolver\-query\-timeout \fIinteger\fR; min\-roots \fIinteger\fR; // not implemented lame\-ttl \fIinteger\fR; max\-ncache\-ttl \fIinteger\fR; @@ -244,8 +255,19 @@ options { dnssec\-enable \fIboolean\fR; dnssec\-validation \fIboolean\fR; dnssec\-lookaside \fIstring\fR trust\-anchor \fIstring\fR; + dnssec\-lookaside ( \fIauto\fR | \fIdomain\fR trust\-anchor \fIdomain\fR ); dnssec\-must\-be\-secure \fIstring\fR \fIboolean\fR; dnssec\-accept\-expired \fIboolean\fR; + dns64\-server \fIstring\fR; + dns64\-contact \fIstring\fR; + dns64 \fIprefix\fR { + clients { <replacable>acl</replacable>; }; + exclude { <replacable>acl</replacable>; }; + mapped { <replacable>acl</replacable>; }; + break\-dnssec \fIboolean\fR; + recursive\-only \fIboolean\fR; + suffix \fIipv6_address\fR; + }; empty\-server \fIstring\fR; empty\-contact \fIstring\fR; empty\-zones\-enable \fIboolean\fR; @@ -260,6 +282,7 @@ options { allow\-update { \fIaddress_match_element\fR; ... }; allow\-update\-forwarding { \fIaddress_match_element\fR; ... }; update\-check\-ksk \fIboolean\fR; + dnssec\-dnskey\-kskonly \fIboolean\fR; masterfile\-format ( text | raw ); notify \fInotifytype\fR; notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ]; @@ -299,9 +322,18 @@ options { use\-alt\-transfer\-source \fIboolean\fR; zone\-statistics \fIboolean\fR; key\-directory \fIquoted_string\fR; + managed\-keys\-directory \fIquoted_string\fR; + auto\-dnssec \fBallow\fR|\fBmaintain\fR|\fBcreate\fR|\fBoff\fR; try\-tcp\-refresh \fIboolean\fR; zero\-no\-soa\-ttl \fIboolean\fR; zero\-no\-soa\-ttl\-cache \fIboolean\fR; + dnssec\-secure\-to\-insecure \fIboolean\fR; + deny\-answer\-addresses { + \fIaddress_match_list\fR + } [ except\-from { \fInamelist\fR } ]; + deny\-answer\-aliases { + \fInamelist\fR + } [ except\-from { \fInamelist\fR } ]; nsec3\-test\-zone \fIboolean\fR; // testing only allow\-v6\-synthesis { \fIaddress_match_element\fR; ... }; // obsolete deallocate\-on\-exit \fIboolean\fR; // obsolete @@ -337,7 +369,8 @@ view \fIstring\fR \fIoptional_class\fR { ... }; trusted\-keys { - \fIstring\fR \fIinteger\fR \fIinteger\fR \fIinteger\fR \fIquoted_string\fR; ... + \fIstring\fR \fIinteger\fR \fIinteger\fR \fIinteger\fR \fIquoted_string\fR; + [...] }; allow\-recursion { \fIaddress_match_element\fR; ... }; allow\-recursion\-on { \fIaddress_match_element\fR; ... }; @@ -361,6 +394,7 @@ view \fIstring\fR \fIoptional_class\fR { queryport\-pool\-ports \fIinteger\fR; queryport\-pool\-updateinterval \fIinteger\fR; cleaning\-interval \fIinteger\fR; + resolver\-query\-timeout \fIinteger\fR; min\-roots \fIinteger\fR; // not implemented lame\-ttl \fIinteger\fR; max\-ncache\-ttl \fIinteger\fR; @@ -393,6 +427,16 @@ view \fIstring\fR \fIoptional_class\fR { dnssec\-lookaside \fIstring\fR trust\-anchor \fIstring\fR; dnssec\-must\-be\-secure \fIstring\fR \fIboolean\fR; dnssec\-accept\-expired \fIboolean\fR; + dns64\-server \fIstring\fR; + dns64\-contact \fIstring\fR; + dns64 \fIprefix\fR { + clients { <replacable>acl</replacable>; }; + exclude { <replacable>acl</replacable>; }; + mapped { <replacable>acl</replacable>; }; + break\-dnssec \fIboolean\fR; + recursive\-only \fIboolean\fR; + suffix \fIipv6_address\fR; + }; empty\-server \fIstring\fR; empty\-contact \fIstring\fR; empty\-zones\-enable \fIboolean\fR; @@ -407,6 +451,7 @@ view \fIstring\fR \fIoptional_class\fR { allow\-update { \fIaddress_match_element\fR; ... }; allow\-update\-forwarding { \fIaddress_match_element\fR; ... }; update\-check\-ksk \fIboolean\fR; + dnssec\-dnskey\-kskonly \fIboolean\fR; masterfile\-format ( text | raw ); notify \fInotifytype\fR; notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ]; @@ -445,6 +490,7 @@ view \fIstring\fR \fIoptional_class\fR { key\-directory \fIquoted_string\fR; zero\-no\-soa\-ttl \fIboolean\fR; zero\-no\-soa\-ttl\-cache \fIboolean\fR; + dnssec\-secure\-to\-insecure \fIboolean\fR; allow\-v6\-synthesis { \fIaddress_match_element\fR; ... }; // obsolete fetch\-glue \fIboolean\fR; // obsolete maintain\-ixfr\-base \fIboolean\fR; // obsolete @@ -476,19 +522,22 @@ zone \fIstring\fR \fIoptional_class\fR { ixfr\-from\-differences \fIboolean\fR; journal \fIquoted_string\fR; zero\-no\-soa\-ttl \fIboolean\fR; + dnssec\-secure\-to\-insecure \fIboolean\fR; allow\-query { \fIaddress_match_element\fR; ... }; allow\-query\-on { \fIaddress_match_element\fR; ... }; allow\-transfer { \fIaddress_match_element\fR; ... }; allow\-update { \fIaddress_match_element\fR; ... }; allow\-update\-forwarding { \fIaddress_match_element\fR; ... }; - update\-policy { - ( grant | deny ) \fIstring\fR + update\-policy \fIlocal\fR | \fI { + ( grant | deny ) \fR\fI\fIstring\fR\fR\fI ( name | subdomain | wildcard | self | selfsub | selfwild | krb5\-self | ms\-self | krb5\-subdomain | ms\-subdomain | - tcp\-self | 6to4\-self ) \fIstring\fR - \fIrrtypelist\fR; ... - }; + tcp\-self | zonesub | 6to4\-self ) \fR\fI\fIstring\fR\fR\fI + \fR\fI\fIrrtypelist\fR\fR\fI; + \fR\fI[...]\fR\fI + }\fR; update\-check\-ksk \fIboolean\fR; + dnssec\-dnskey\-kskonly \fIboolean\fR; masterfile\-format ( text | raw ); notify \fInotifytype\fR; notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ]; @@ -544,5 +593,5 @@ zone \fIstring\fR \fIoptional_class\fR { \fBrndc\fR(8), BIND 9 Administrator Reference Manual. .SH "COPYRIGHT" -Copyright \(co 2004\-2008 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004\-2011 Internet Systems Consortium, Inc. ("ISC") .br diff --git a/contrib/bind9/bin/named/named.conf.docbook b/contrib/bind9/bin/named/named.conf.docbook index d98e2899295a..962eaaa0e2bd 100644 --- a/contrib/bind9/bin/named/named.conf.docbook +++ b/contrib/bind9/bin/named/named.conf.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [<!ENTITY mdash "—">]> <!-- - - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004-2011 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 @@ -17,7 +17,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: named.conf.docbook,v 1.39 2008-09-24 02:46:21 marka Exp $ --> +<!-- $Id: named.conf.docbook,v 1.49.14.1 2011-02-03 05:50:05 marka Exp $ --> <refentry> <refentryinfo> <date>Aug 13, 2004</date> @@ -41,6 +41,9 @@ <year>2006</year> <year>2007</year> <year>2008</year> + <year>2009</year> + <year>2010</year> + <year>2011</year> <holder>Internet Systems Consortium, Inc. ("ISC")</holder> </copyright> </docinfo> @@ -132,6 +135,15 @@ trusted-keys { </refsect1> <refsect1> + <title>MANAGED-KEYS</title> + <literallayout> +managed-keys { + <replaceable>domain_name</replaceable> <constant>initial-key</constant> <replaceable>flags</replaceable> <replaceable>protocol</replaceable> <replaceable>algorithm</replaceable> <replaceable>key</replaceable>; ... +}; +</literallayout> + </refsect1> + + <refsect1> <title>CONTROLS</title> <literallayout> controls { @@ -214,6 +226,7 @@ options { tcp-listen-queue <replaceable>integer</replaceable>; tkey-dhkey <replaceable>quoted_string</replaceable> <replaceable>integer</replaceable>; tkey-gssapi-credential <replaceable>quoted_string</replaceable>; + tkey-gssapi-keytab <replaceable>quoted_string</replaceable>; tkey-domain <replaceable>quoted_string</replaceable>; transfers-per-ns <replaceable>integer</replaceable>; transfers-in <replaceable>integer</replaceable>; @@ -242,6 +255,7 @@ options { queryport-pool-ports <replaceable>integer</replaceable>; queryport-pool-updateinterval <replaceable>integer</replaceable>; cleaning-interval <replaceable>integer</replaceable>; + resolver-query-timeout <replaceable>integer</replaceable>; min-roots <replaceable>integer</replaceable>; // not implemented lame-ttl <replaceable>integer</replaceable>; max-ncache-ttl <replaceable>integer</replaceable>; @@ -272,9 +286,21 @@ options { dnssec-enable <replaceable>boolean</replaceable>; dnssec-validation <replaceable>boolean</replaceable>; dnssec-lookaside <replaceable>string</replaceable> trust-anchor <replaceable>string</replaceable>; + dnssec-lookaside ( <replaceable>auto</replaceable> | <replaceable>domain</replaceable> trust-anchor <replaceable>domain</replaceable> ); dnssec-must-be-secure <replaceable>string</replaceable> <replaceable>boolean</replaceable>; dnssec-accept-expired <replaceable>boolean</replaceable>; + dns64-server <replaceable>string</replaceable>; + dns64-contact <replaceable>string</replaceable>; + dns64 <replaceable>prefix</replaceable> { + clients { <replacable>acl</replacable>; }; + exclude { <replacable>acl</replacable>; }; + mapped { <replacable>acl</replacable>; }; + break-dnssec <replaceable>boolean</replaceable>; + recursive-only <replaceable>boolean</replaceable>; + suffix <replaceable>ipv6_address</replaceable>; + }; + empty-server <replaceable>string</replaceable>; empty-contact <replaceable>string</replaceable>; empty-zones-enable <replaceable>boolean</replaceable>; @@ -291,6 +317,7 @@ options { allow-update { <replaceable>address_match_element</replaceable>; ... }; allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... }; update-check-ksk <replaceable>boolean</replaceable>; + dnssec-dnskey-kskonly <replaceable>boolean</replaceable>; masterfile-format ( text | raw ); notify <replaceable>notifytype</replaceable>; @@ -337,9 +364,18 @@ options { zone-statistics <replaceable>boolean</replaceable>; key-directory <replaceable>quoted_string</replaceable>; + managed-keys-directory <replaceable>quoted_string</replaceable>; + auto-dnssec <constant>allow</constant>|<constant>maintain</constant>|<constant>create</constant>|<constant>off</constant>; try-tcp-refresh <replaceable>boolean</replaceable>; zero-no-soa-ttl <replaceable>boolean</replaceable>; zero-no-soa-ttl-cache <replaceable>boolean</replaceable>; + dnssec-secure-to-insecure <replaceable>boolean</replaceable>; + deny-answer-addresses { + <replaceable>address_match_list</replaceable> + } <optional> except-from { <replaceable>namelist</replaceable> } </optional>; + deny-answer-aliases { + <replaceable>namelist</replaceable> + } <optional> except-from { <replaceable>namelist</replaceable> } </optional>; nsec3-test-zone <replaceable>boolean</replaceable>; // testing only @@ -381,7 +417,8 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable> }; trusted-keys { - <replaceable>string</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>quoted_string</replaceable>; ... + <replaceable>string</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>quoted_string</replaceable>; + <optional>...</optional> }; allow-recursion { <replaceable>address_match_element</replaceable>; ... }; @@ -406,6 +443,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable> queryport-pool-ports <replaceable>integer</replaceable>; queryport-pool-updateinterval <replaceable>integer</replaceable>; cleaning-interval <replaceable>integer</replaceable>; + resolver-query-timeout <replaceable>integer</replaceable>; min-roots <replaceable>integer</replaceable>; // not implemented lame-ttl <replaceable>integer</replaceable>; max-ncache-ttl <replaceable>integer</replaceable>; @@ -439,6 +477,17 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable> dnssec-must-be-secure <replaceable>string</replaceable> <replaceable>boolean</replaceable>; dnssec-accept-expired <replaceable>boolean</replaceable>; + dns64-server <replaceable>string</replaceable>; + dns64-contact <replaceable>string</replaceable>; + dns64 <replaceable>prefix</replaceable> { + clients { <replacable>acl</replacable>; }; + exclude { <replacable>acl</replacable>; }; + mapped { <replacable>acl</replacable>; }; + break-dnssec <replaceable>boolean</replaceable>; + recursive-only <replaceable>boolean</replaceable>; + suffix <replaceable>ipv6_address</replaceable>; + }; + empty-server <replaceable>string</replaceable>; empty-contact <replaceable>string</replaceable>; empty-zones-enable <replaceable>boolean</replaceable>; @@ -455,6 +504,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable> allow-update { <replaceable>address_match_element</replaceable>; ... }; allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... }; update-check-ksk <replaceable>boolean</replaceable>; + dnssec-dnskey-kskonly <replaceable>boolean</replaceable>; masterfile-format ( text | raw ); notify <replaceable>notifytype</replaceable>; @@ -499,6 +549,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable> key-directory <replaceable>quoted_string</replaceable>; zero-no-soa-ttl <replaceable>boolean</replaceable>; zero-no-soa-ttl-cache <replaceable>boolean</replaceable>; + dnssec-secure-to-insecure <replaceable>boolean</replaceable>; allow-v6-synthesis { <replaceable>address_match_element</replaceable>; ... }; // obsolete fetch-glue <replaceable>boolean</replaceable>; // obsolete @@ -533,20 +584,23 @@ zone <replaceable>string</replaceable> <replaceable>optional_class</replaceable> ixfr-from-differences <replaceable>boolean</replaceable>; journal <replaceable>quoted_string</replaceable>; zero-no-soa-ttl <replaceable>boolean</replaceable>; + dnssec-secure-to-insecure <replaceable>boolean</replaceable>; allow-query { <replaceable>address_match_element</replaceable>; ... }; allow-query-on { <replaceable>address_match_element</replaceable>; ... }; allow-transfer { <replaceable>address_match_element</replaceable>; ... }; allow-update { <replaceable>address_match_element</replaceable>; ... }; allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... }; - update-policy { + update-policy <replaceable>local</replaceable> | <replaceable> { ( grant | deny ) <replaceable>string</replaceable> ( name | subdomain | wildcard | self | selfsub | selfwild | krb5-self | ms-self | krb5-subdomain | ms-subdomain | - tcp-self | 6to4-self ) <replaceable>string</replaceable> - <replaceable>rrtypelist</replaceable>; ... - }; + tcp-self | zonesub | 6to4-self ) <replaceable>string</replaceable> + <replaceable>rrtypelist</replaceable>; + <optional>...</optional> + }</replaceable>; update-check-ksk <replaceable>boolean</replaceable>; + dnssec-dnskey-kskonly <replaceable>boolean</replaceable>; masterfile-format ( text | raw ); notify <replaceable>notifytype</replaceable>; diff --git a/contrib/bind9/bin/named/named.conf.html b/contrib/bind9/bin/named/named.conf.html index fccad183f9e6..f20e411f45b0 100644 --- a/contrib/bind9/bin/named/named.conf.html +++ b/contrib/bind9/bin/named/named.conf.html @@ -1,5 +1,5 @@ <!-- - - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004-2011 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 @@ -13,7 +13,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: named.conf.html,v 1.45.48.1 2009-07-11 01:55:21 tbox Exp $ --> +<!-- $Id: named.conf.html,v 1.53.12.1 2011-02-03 12:29:12 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> @@ -31,7 +31,7 @@ <div class="cmdsynopsis"><p><code class="command">named.conf</code> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543342"></a><h2>DESCRIPTION</h2> +<a name="id2543352"></a><h2>DESCRIPTION</h2> <p><code class="filename">named.conf</code> is the configuration file for <span><strong class="command">named</strong></span>. Statements are enclosed @@ -50,14 +50,14 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543370"></a><h2>ACL</h2> +<a name="id2543380"></a><h2>ACL</h2> <div class="literallayout"><p><br> acl <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> <br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543386"></a><h2>KEY</h2> +<a name="id2543396"></a><h2>KEY</h2> <div class="literallayout"><p><br> key <em class="replaceable"><code>domain_name</code></em> {<br> algorithm <em class="replaceable"><code>string</code></em>;<br> @@ -66,7 +66,7 @@ key <em class="replaceable"><code>domain_name</code></em> {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543405"></a><h2>MASTERS</h2> +<a name="id2543415"></a><h2>MASTERS</h2> <div class="literallayout"><p><br> masters <em class="replaceable"><code>string</code></em> [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br> ( <em class="replaceable"><code>masters</code></em> | <em class="replaceable"><code>ipv4_address</code></em> [<span class="optional">port <em class="replaceable"><code>integer</code></em></span>] |<br> @@ -75,7 +75,7 @@ masters <em class="replaceable"><code>string</code></em> [<span class="optional" </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543451"></a><h2>SERVER</h2> +<a name="id2543461"></a><h2>SERVER</h2> <div class="literallayout"><p><br> server ( <em class="replaceable"><code>ipv4_address[<span class="optional">/prefixlen</span>]</code></em> | <em class="replaceable"><code>ipv6_address[<span class="optional">/prefixlen</span>]</code></em> ) {<br> bogus <em class="replaceable"><code>boolean</code></em>;<br> @@ -97,7 +97,7 @@ server ( <em class="replaceable"><code>ipv4_address[<span class="optional">/pref </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543520"></a><h2>TRUSTED-KEYS</h2> +<a name="id2543529"></a><h2>TRUSTED-KEYS</h2> <div class="literallayout"><p><br> trusted-keys {<br> <em class="replaceable"><code>domain_name</code></em> <em class="replaceable"><code>flags</code></em> <em class="replaceable"><code>protocol</code></em> <em class="replaceable"><code>algorithm</code></em> <em class="replaceable"><code>key</code></em>; ... <br> @@ -105,7 +105,15 @@ trusted-keys {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543545"></a><h2>CONTROLS</h2> +<a name="id2543555"></a><h2>MANAGED-KEYS</h2> +<div class="literallayout"><p><br> +managed-keys {<br> + <em class="replaceable"><code>domain_name</code></em> <code class="constant">initial-key</code> <em class="replaceable"><code>flags</code></em> <em class="replaceable"><code>protocol</code></em> <em class="replaceable"><code>algorithm</code></em> <em class="replaceable"><code>key</code></em>; ... <br> +};<br> +</p></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543584"></a><h2>CONTROLS</h2> <div class="literallayout"><p><br> controls {<br> inet ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> | * )<br> @@ -117,7 +125,7 @@ controls {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543580"></a><h2>LOGGING</h2> +<a name="id2543619"></a><h2>LOGGING</h2> <div class="literallayout"><p><br> logging {<br> channel <em class="replaceable"><code>string</code></em> {<br> @@ -135,7 +143,7 @@ logging {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543619"></a><h2>LWRES</h2> +<a name="id2543657"></a><h2>LWRES</h2> <div class="literallayout"><p><br> lwres {<br> listen-on [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br> @@ -148,7 +156,7 @@ lwres {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543660"></a><h2>OPTIONS</h2> +<a name="id2543699"></a><h2>OPTIONS</h2> <div class="literallayout"><p><br> options {<br> avoid-v4-udp-ports { <em class="replaceable"><code>port</code></em>; ... };<br> @@ -184,6 +192,7 @@ options {<br> tcp-listen-queue <em class="replaceable"><code>integer</code></em>;<br> tkey-dhkey <em class="replaceable"><code>quoted_string</code></em> <em class="replaceable"><code>integer</code></em>;<br> tkey-gssapi-credential <em class="replaceable"><code>quoted_string</code></em>;<br> + tkey-gssapi-keytab <em class="replaceable"><code>quoted_string</code></em>;<br> tkey-domain <em class="replaceable"><code>quoted_string</code></em>;<br> transfers-per-ns <em class="replaceable"><code>integer</code></em>;<br> transfers-in <em class="replaceable"><code>integer</code></em>;<br> @@ -212,6 +221,7 @@ options {<br> queryport-pool-ports <em class="replaceable"><code>integer</code></em>;<br> queryport-pool-updateinterval <em class="replaceable"><code>integer</code></em>;<br> cleaning-interval <em class="replaceable"><code>integer</code></em>;<br> + resolver-query-timeout <em class="replaceable"><code>integer</code></em>;<br> min-roots <em class="replaceable"><code>integer</code></em>; // not implemented<br> lame-ttl <em class="replaceable"><code>integer</code></em>;<br> max-ncache-ttl <em class="replaceable"><code>integer</code></em>;<br> @@ -242,9 +252,21 @@ options {<br> dnssec-enable <em class="replaceable"><code>boolean</code></em>;<br> dnssec-validation <em class="replaceable"><code>boolean</code></em>;<br> dnssec-lookaside <em class="replaceable"><code>string</code></em> trust-anchor <em class="replaceable"><code>string</code></em>;<br> + dnssec-lookaside ( <em class="replaceable"><code>auto</code></em> | <em class="replaceable"><code>domain</code></em> trust-anchor <em class="replaceable"><code>domain</code></em> );<br> dnssec-must-be-secure <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>boolean</code></em>;<br> dnssec-accept-expired <em class="replaceable"><code>boolean</code></em>;<br> <br> + dns64-server <em class="replaceable"><code>string</code></em>;<br> + dns64-contact <em class="replaceable"><code>string</code></em>;<br> + dns64 <em class="replaceable"><code>prefix</code></em> {<br> + clients { <font color="red"><replacable>acl</replacable></font>; };<br> + exclude { <font color="red"><replacable>acl</replacable></font>; };<br> + mapped { <font color="red"><replacable>acl</replacable></font>; };<br> + break-dnssec <em class="replaceable"><code>boolean</code></em>;<br> + recursive-only <em class="replaceable"><code>boolean</code></em>;<br> + suffix <em class="replaceable"><code>ipv6_address</code></em>;<br> + };<br> +<br> empty-server <em class="replaceable"><code>string</code></em>;<br> empty-contact <em class="replaceable"><code>string</code></em>;<br> empty-zones-enable <em class="replaceable"><code>boolean</code></em>;<br> @@ -261,6 +283,7 @@ options {<br> allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br> + dnssec-dnskey-kskonly <em class="replaceable"><code>boolean</code></em>;<br> <br> masterfile-format ( text | raw );<br> notify <em class="replaceable"><code>notifytype</code></em>;<br> @@ -307,9 +330,18 @@ options {<br> <br> zone-statistics <em class="replaceable"><code>boolean</code></em>;<br> key-directory <em class="replaceable"><code>quoted_string</code></em>;<br> + managed-keys-directory <em class="replaceable"><code>quoted_string</code></em>;<br> + auto-dnssec <code class="constant">allow</code>|<code class="constant">maintain</code>|<code class="constant">create</code>|<code class="constant">off</code>;<br> try-tcp-refresh <em class="replaceable"><code>boolean</code></em>;<br> zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br> zero-no-soa-ttl-cache <em class="replaceable"><code>boolean</code></em>;<br> + dnssec-secure-to-insecure <em class="replaceable"><code>boolean</code></em>;<br> + deny-answer-addresses {<br> + <em class="replaceable"><code>address_match_list</code></em><br> + } [<span class="optional"> except-from { <em class="replaceable"><code>namelist</code></em> } </span>];<br> + deny-answer-aliases {<br> + <em class="replaceable"><code>namelist</code></em><br> + } [<span class="optional"> except-from { <em class="replaceable"><code>namelist</code></em> } </span>];<br> <br> nsec3-test-zone <em class="replaceable"><code>boolean</code></em>; // testing only<br> <br> @@ -329,7 +361,7 @@ options {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2544452"></a><h2>VIEW</h2> +<a name="id2544577"></a><h2>VIEW</h2> <div class="literallayout"><p><br> view <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>optional_class</code></em> {<br> match-clients { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> @@ -350,7 +382,8 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c };<br> <br> trusted-keys {<br> - <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>quoted_string</code></em>; ...<br> + <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>quoted_string</code></em>;<br> + [<span class="optional">...</span>]<br> };<br> <br> allow-recursion { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> @@ -375,6 +408,7 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c queryport-pool-ports <em class="replaceable"><code>integer</code></em>;<br> queryport-pool-updateinterval <em class="replaceable"><code>integer</code></em>;<br> cleaning-interval <em class="replaceable"><code>integer</code></em>;<br> + resolver-query-timeout <em class="replaceable"><code>integer</code></em>;<br> min-roots <em class="replaceable"><code>integer</code></em>; // not implemented<br> lame-ttl <em class="replaceable"><code>integer</code></em>;<br> max-ncache-ttl <em class="replaceable"><code>integer</code></em>;<br> @@ -408,6 +442,17 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c dnssec-must-be-secure <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>boolean</code></em>;<br> dnssec-accept-expired <em class="replaceable"><code>boolean</code></em>;<br> <br> + dns64-server <em class="replaceable"><code>string</code></em>;<br> + dns64-contact <em class="replaceable"><code>string</code></em>;<br> + dns64 <em class="replaceable"><code>prefix</code></em> {<br> + clients { <font color="red"><replacable>acl</replacable></font>; };<br> + exclude { <font color="red"><replacable>acl</replacable></font>; };<br> + mapped { <font color="red"><replacable>acl</replacable></font>; };<br> + break-dnssec <em class="replaceable"><code>boolean</code></em>;<br> + recursive-only <em class="replaceable"><code>boolean</code></em>;<br> + suffix <em class="replaceable"><code>ipv6_address</code></em>;<br> + };<br> +<br> empty-server <em class="replaceable"><code>string</code></em>;<br> empty-contact <em class="replaceable"><code>string</code></em>;<br> empty-zones-enable <em class="replaceable"><code>boolean</code></em>;<br> @@ -424,6 +469,7 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br> + dnssec-dnskey-kskonly <em class="replaceable"><code>boolean</code></em>;<br> <br> masterfile-format ( text | raw );<br> notify <em class="replaceable"><code>notifytype</code></em>;<br> @@ -468,6 +514,7 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c key-directory <em class="replaceable"><code>quoted_string</code></em>;<br> zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br> zero-no-soa-ttl-cache <em class="replaceable"><code>boolean</code></em>;<br> + dnssec-secure-to-insecure <em class="replaceable"><code>boolean</code></em>;<br> <br> allow-v6-synthesis { <em class="replaceable"><code>address_match_element</code></em>; ... }; // obsolete<br> fetch-glue <em class="replaceable"><code>boolean</code></em>; // obsolete<br> @@ -477,7 +524,7 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2545113"></a><h2>ZONE</h2> +<a name="id2545280"></a><h2>ZONE</h2> <div class="literallayout"><p><br> zone <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>optional_class</code></em> {<br> type ( master | slave | stub | hint |<br> @@ -501,20 +548,23 @@ zone <em class="replaceable"><code>string</code></em> <em class="replaceable"><c ixfr-from-differences <em class="replaceable"><code>boolean</code></em>;<br> journal <em class="replaceable"><code>quoted_string</code></em>;<br> zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br> + dnssec-secure-to-insecure <em class="replaceable"><code>boolean</code></em>;<br> <br> allow-query { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> allow-query-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> allow-transfer { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> - update-policy {<br> + update-policy <em class="replaceable"><code>local</code></em> | <em class="replaceable"><code> {<br> ( grant | deny ) <em class="replaceable"><code>string</code></em><br> ( name | subdomain | wildcard | self | selfsub | selfwild |<br> krb5-self | ms-self | krb5-subdomain | ms-subdomain |<br> - tcp-self | 6to4-self ) <em class="replaceable"><code>string</code></em><br> - <em class="replaceable"><code>rrtypelist</code></em>; ...<br> - };<br> + tcp-self | zonesub | 6to4-self ) <em class="replaceable"><code>string</code></em><br> + <em class="replaceable"><code>rrtypelist</code></em>;<br> + [<span class="optional">...</span>]<br> + }</code></em>;<br> update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br> + dnssec-dnskey-kskonly <em class="replaceable"><code>boolean</code></em>;<br> <br> masterfile-format ( text | raw );<br> notify <em class="replaceable"><code>notifytype</code></em>;<br> @@ -569,12 +619,12 @@ zone <em class="replaceable"><code>string</code></em> <em class="replaceable"><c </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2545410"></a><h2>FILES</h2> +<a name="id2545659"></a><h2>FILES</h2> <p><code class="filename">/etc/named.conf</code> </p> </div> <div class="refsect1" lang="en"> -<a name="id2545421"></a><h2>SEE ALSO</h2> +<a name="id2545671"></a><h2>SEE ALSO</h2> <p><span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>, <span class="citerefentry"><span class="refentrytitle">named-checkconf</span>(8)</span>, <span class="citerefentry"><span class="refentrytitle">rndc</span>(8)</span>, diff --git a/contrib/bind9/bin/named/named.docbook b/contrib/bind9/bin/named/named.docbook index 808e998eb8a5..214f8ac6e9d7 100644 --- a/contrib/bind9/bin/named/named.docbook +++ b/contrib/bind9/bin/named/named.docbook @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: named.docbook,v 1.23.14.2 2009-12-03 04:49:32 tbox Exp $ --> +<!-- $Id: named.docbook,v 1.26 2009-10-05 17:30:49 fdupont Exp $ --> <refentry id="man.named"> <refentryinfo> <date>May 21, 2009</date> @@ -60,6 +60,7 @@ <arg><option>-6</option></arg> <arg><option>-c <replaceable class="parameter">config-file</replaceable></option></arg> <arg><option>-d <replaceable class="parameter">debug-level</replaceable></option></arg> + <arg><option>-E <replaceable class="parameter">engine-name</replaceable></option></arg> <arg><option>-f</option></arg> <arg><option>-g</option></arg> <arg><option>-m <replaceable class="parameter">flag</replaceable></option></arg> @@ -116,6 +117,7 @@ </para> </listitem> </varlistentry> + <varlistentry> <term>-c <replaceable class="parameter">config-file</replaceable></term> <listitem> @@ -145,6 +147,19 @@ </varlistentry> <varlistentry> + <term>-E <replaceable class="parameter">engine-name</replaceable></term> + <listitem> + <para> + Use a crypto hardware (OpenSSL engine) for the crypto operations + it supports, for instance re-signing with private keys from + a secure key store. When compiled with PKCS#11 support + <replaceable class="parameter">engine-name</replaceable> + defaults to pkcs11, the empty name resets it to no engine. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-f</term> <listitem> <para> diff --git a/contrib/bind9/bin/named/named.html b/contrib/bind9/bin/named/named.html index 031b4921ff4e..fa869c4c6d10 100644 --- a/contrib/bind9/bin/named/named.html +++ b/contrib/bind9/bin/named/named.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: named.html,v 1.30.14.2 2009-12-03 05:06:38 tbox Exp $ --> +<!-- $Id: named.html,v 1.33 2009-10-06 01:14:41 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> @@ -29,10 +29,10 @@ </div> <div class="refsynopsisdiv"> <h2>Synopsis</h2> -<div class="cmdsynopsis"><p><code class="command">named</code> [<code class="option">-4</code>] [<code class="option">-6</code>] [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>] [<code class="option">-d <em class="replaceable"><code>debug-level</code></em></code>] [<code class="option">-f</code>] [<code class="option">-g</code>] [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-n <em class="replaceable"><code>#cpus</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-s</code>] [<code class="option">-S <em class="replaceable"><code>#max-socks</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-u <em class="replaceable"><code>user</code></em></code>] [<code class="option">-v</code>] [<code class="option">-V</code>] [<code class="option">-x <em class="replaceable"><code>cache-file</code></em></code>]</p></div> +<div class="cmdsynopsis"><p><code class="command">named</code> [<code class="option">-4</code>] [<code class="option">-6</code>] [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>] [<code class="option">-d <em class="replaceable"><code>debug-level</code></em></code>] [<code class="option">-E <em class="replaceable"><code>engine-name</code></em></code>] [<code class="option">-f</code>] [<code class="option">-g</code>] [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-n <em class="replaceable"><code>#cpus</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-s</code>] [<code class="option">-S <em class="replaceable"><code>#max-socks</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-u <em class="replaceable"><code>user</code></em></code>] [<code class="option">-v</code>] [<code class="option">-V</code>] [<code class="option">-x <em class="replaceable"><code>cache-file</code></em></code>]</p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543472"></a><h2>DESCRIPTION</h2> +<a name="id2543480"></a><h2>DESCRIPTION</h2> <p><span><strong class="command">named</strong></span> is a Domain Name System (DNS) server, part of the BIND 9 distribution from ISC. For more @@ -47,7 +47,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543496"></a><h2>OPTIONS</h2> +<a name="id2543505"></a><h2>OPTIONS</h2> <div class="variablelist"><dl> <dt><span class="term">-4</span></dt> <dd><p> @@ -79,6 +79,14 @@ Debugging traces from <span><strong class="command">named</strong></span> become more verbose as the debug level increases. </p></dd> +<dt><span class="term">-E <em class="replaceable"><code>engine-name</code></em></span></dt> +<dd><p> + Use a crypto hardware (OpenSSL engine) for the crypto operations + it supports, for instance re-signing with private keys from + a secure key store. When compiled with PKCS#11 support + <em class="replaceable"><code>engine-name</code></em> + defaults to pkcs11, the empty name resets it to no engine. + </p></dd> <dt><span class="term">-f</span></dt> <dd><p> Run the server in the foreground (i.e. do not daemonize). @@ -220,7 +228,7 @@ </dl></div> </div> <div class="refsect1" lang="en"> -<a name="id2543931"></a><h2>SIGNALS</h2> +<a name="id2543962"></a><h2>SIGNALS</h2> <p> In routine operation, signals should not be used to control the nameserver; <span><strong class="command">rndc</strong></span> should be used @@ -241,7 +249,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543979"></a><h2>CONFIGURATION</h2> +<a name="id2544010"></a><h2>CONFIGURATION</h2> <p> The <span><strong class="command">named</strong></span> configuration file is too complex to describe in detail here. A complete description is provided @@ -258,7 +266,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2544016"></a><h2>FILES</h2> +<a name="id2544046"></a><h2>FILES</h2> <div class="variablelist"><dl> <dt><span class="term"><code class="filename">/etc/named.conf</code></span></dt> <dd><p> @@ -271,7 +279,7 @@ </dl></div> </div> <div class="refsect1" lang="en"> -<a name="id2544123"></a><h2>SEE ALSO</h2> +<a name="id2544086"></a><h2>SEE ALSO</h2> <p><em class="citetitle">RFC 1033</em>, <em class="citetitle">RFC 1034</em>, <em class="citetitle">RFC 1035</em>, @@ -284,7 +292,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2544194"></a><h2>AUTHOR</h2> +<a name="id2544293"></a><h2>AUTHOR</h2> <p><span class="corpauthor">Internet Systems Consortium</span> </p> </div> diff --git a/contrib/bind9/bin/named/query.c b/contrib/bind9/bin/named/query.c index fa34da6e28c0..1950257dca2c 100644 --- a/contrib/bind9/bin/named/query.c +++ b/contrib/bind9/bin/named/query.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.c,v 1.313.20.24 2010-09-24 08:09:07 marka Exp $ */ +/* $Id: query.c,v 1.353.8.2.2.5 2011-06-09 03:17:10 marka Exp $ */ /*! \file */ @@ -34,6 +34,7 @@ #ifdef DLZ #include <dns/dlz.h> #endif +#include <dns/dns64.h> #include <dns/dnssec.h> #include <dns/events.h> #include <dns/message.h> @@ -62,6 +63,17 @@ #include <named/sortlist.h> #include <named/xfrout.h> +#if 0 +/* + * It has been recommended that DNS64 be changed to return excluded + * AAAA addresses if DNS64 synthesis does not occur. This minimises + * the impact on the lookup results. While most DNS AAAA lookups are + * done to send IP packets to a host, not all of them are and filtering + * excluded addresses has a negative impact on those uses. + */ +#define dns64_bis_return_excluded_addresses 1 +#endif + /*% Partial answer? */ #define PARTIALANSWER(c) (((c)->query.attributes & \ NS_QUERYATTR_PARTIALANSWER) != 0) @@ -92,6 +104,12 @@ /*% Secure? */ #define SECURE(c) (((c)->query.attributes & \ NS_QUERYATTR_SECURE) != 0) +/*% DNS64 A lookup? */ +#define DNS64(c) (((c)->query.attributes & \ + NS_QUERYATTR_DNS64) != 0) + +#define DNS64EXCLUDE(c) (((c)->query.attributes & \ + NS_QUERYATTR_DNS64EXCLUDE) != 0) /*% No QNAME Proof? */ #define NOQNAME(r) (((r)->attributes & \ @@ -116,6 +134,7 @@ #define DNS_GETDB_NOEXACT 0x01U #define DNS_GETDB_NOLOG 0x02U #define DNS_GETDB_PARTIAL 0x04U +#define DNS_GETDB_IGNOREACL 0x08U #define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0) @@ -141,6 +160,9 @@ query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, static inline void log_queryerror(ns_client_t *client, isc_result_t result, int line, int level); +static void +rpz_st_clear(ns_client_t *client); + /*% * Increment query statistics counters. */ @@ -252,6 +274,19 @@ ns_query_cancel(ns_client_t *client) { } static inline void +query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) { + dns_rdataset_t *rdataset = *rdatasetp; + + CTRACE("query_putrdataset"); + if (rdataset != NULL) { + if (dns_rdataset_isassociated(rdataset)) + dns_rdataset_disassociate(rdataset); + dns_message_puttemprdataset(client->message, rdatasetp); + } + CTRACE("query_putrdataset: done"); +} + +static inline void query_reset(ns_client_t *client, isc_boolean_t everything) { isc_buffer_t *dbuf, *dbuf_next; ns_dbversion_t *dbversion, *dbversion_next; @@ -285,6 +320,18 @@ query_reset(ns_client_t *client, isc_boolean_t everything) { if (client->query.authzone != NULL) dns_zone_detach(&client->query.authzone); + if (client->query.dns64_aaaa != NULL) + query_putrdataset(client, &client->query.dns64_aaaa); + if (client->query.dns64_sigaaaa != NULL) + query_putrdataset(client, &client->query.dns64_sigaaaa); + if (client->query.dns64_aaaaok != NULL) { + isc_mem_put(client->mctx, client->query.dns64_aaaaok, + client->query.dns64_aaaaoklen * + sizeof(isc_boolean_t)); + client->query.dns64_aaaaok = NULL; + client->query.dns64_aaaaoklen = 0; + } + query_freefreeversions(client, everything); for (dbuf = ISC_LIST_HEAD(client->query.namebufs); @@ -310,13 +357,22 @@ query_reset(ns_client_t *client, isc_boolean_t everything) { NS_QUERYATTR_SECURE); client->query.restarts = 0; client->query.timerset = ISC_FALSE; + if (client->query.rpz_st != NULL) { + rpz_st_clear(client); + if (everything) { + isc_mem_put(client->mctx, client->query.rpz_st, + sizeof(*client->query.rpz_st)); + client->query.rpz_st = NULL; + } + } client->query.origqname = NULL; - client->query.qname = NULL; client->query.dboptions = 0; client->query.fetchoptions = 0; client->query.gluedb = NULL; client->query.authdbset = ISC_FALSE; client->query.isreferral = ISC_FALSE; + client->query.dns64_options = 0; + client->query.dns64_ttl = ISC_UINT32_MAX; } static void @@ -473,20 +529,6 @@ query_newrdataset(ns_client_t *client) { return (rdataset); } -static inline void -query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) { - dns_rdataset_t *rdataset = *rdatasetp; - - CTRACE("query_putrdataset"); - if (rdataset != NULL) { - if (dns_rdataset_isassociated(rdataset)) - dns_rdataset_disassociate(rdataset); - dns_message_puttemprdataset(client->message, rdatasetp); - } - CTRACE("query_putrdataset: done"); -} - - static inline isc_result_t query_newdbversion(ns_client_t *client, unsigned int n) { unsigned int i; @@ -540,6 +582,7 @@ ns_query_init(ns_client_t *client) { ISC_LIST_INIT(client->query.freeversions); client->query.restarts = 0; client->query.timerset = ISC_FALSE; + client->query.rpz_st = NULL; client->query.qname = NULL; result = isc_mutex_init(&client->query.fetchlock); if (result != ISC_R_SUCCESS) @@ -549,6 +592,10 @@ ns_query_init(ns_client_t *client) { client->query.authzone = NULL; client->query.authdbset = ISC_FALSE; client->query.isreferral = ISC_FALSE; + client->query.dns64_aaaa = NULL; + client->query.dns64_sigaaaa = NULL; + client->query.dns64_aaaaok = NULL; + client->query.dns64_aaaaoklen = 0; query_reset(client, ISC_FALSE); result = query_newdbversion(client, 3); if (result != ISC_R_SUCCESS) { @@ -563,8 +610,7 @@ ns_query_init(ns_client_t *client) { } static inline ns_dbversion_t * -query_findversion(ns_client_t *client, dns_db_t *db, - isc_boolean_t *newzonep) +query_findversion(ns_client_t *client, dns_db_t *db) { ns_dbversion_t *dbversion; @@ -590,12 +636,11 @@ query_findversion(ns_client_t *client, dns_db_t *db, return (NULL); dns_db_attach(db, &dbversion->db); dns_db_currentversion(db, &dbversion->version); + dbversion->acl_checked = ISC_FALSE; dbversion->queryok = ISC_FALSE; ISC_LIST_APPEND(client->query.activeversions, dbversion, link); - *newzonep = ISC_TRUE; - } else - *newzonep = ISC_FALSE; + } return (dbversion); } @@ -607,7 +652,6 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name, dns_dbversion_t **versionp) { isc_result_t result; - isc_boolean_t check_acl, new_zone; dns_acl_t *queryacl; ns_dbversion_t *dbversion; @@ -623,7 +667,17 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name, if (!client->view->additionalfromauth && client->query.authdbset && db != client->query.authdb) - goto refuse; + return (DNS_R_REFUSED); + + /* + * Non recursive query to a static-stub zone is prohibited; its + * zone content is not public data, but a part of local configuration + * and should not be disclosed. + */ + if (dns_zone_gettype(zone) == dns_zone_staticstub && + !RECURSIONOK(client)) { + return (DNS_R_REFUSED); + } /* * If the zone has an ACL, we'll check it, otherwise @@ -633,23 +687,19 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name, * Also, get the database version to use. */ - check_acl = ISC_TRUE; /* Keep compiler happy. */ - queryacl = NULL; - /* * Get the current version of this database. */ - dbversion = query_findversion(client, db, &new_zone); - if (dbversion == NULL) { - result = DNS_R_SERVFAIL; - goto fail; - } - if (new_zone) { - check_acl = ISC_TRUE; - } else if (!dbversion->queryok) { - goto refuse; - } else { - check_acl = ISC_FALSE; + dbversion = query_findversion(client, db); + if (dbversion == NULL) + return (DNS_R_SERVFAIL); + + if ((options & DNS_GETDB_IGNOREACL) != 0) + goto approved; + if (dbversion->acl_checked) { + if (!dbversion->queryok) + return (DNS_R_REFUSED); + goto approved; } queryacl = dns_zone_getqueryacl(zone); @@ -663,88 +713,69 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name, * allowed to make queries, otherwise the query should * be refused. */ - check_acl = ISC_FALSE; + dbversion->acl_checked = ISC_TRUE; if ((client->query.attributes & - NS_QUERYATTR_QUERYOK) == 0) - goto refuse; - } else { - /* - * We haven't evaluated the view's queryacl yet. - */ - check_acl = ISC_TRUE; + NS_QUERYATTR_QUERYOK) == 0) { + dbversion->queryok = ISC_FALSE; + return (DNS_R_REFUSED); + } + dbversion->queryok = ISC_TRUE; + goto approved; } } - if (check_acl) { - isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0); - - result = ns_client_checkaclsilent(client, NULL, queryacl, - ISC_TRUE); - if (log) { - char msg[NS_CLIENT_ACLMSGSIZE("query")]; - if (result == ISC_R_SUCCESS) { - if (isc_log_wouldlog(ns_g_lctx, - ISC_LOG_DEBUG(3))) - { - ns_client_aclmsg("query", name, qtype, - client->view->rdclass, - msg, sizeof(msg)); - ns_client_log(client, - DNS_LOGCATEGORY_SECURITY, - NS_LOGMODULE_QUERY, - ISC_LOG_DEBUG(3), - "%s approved", msg); - } - } else { + result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE); + if ((options & DNS_GETDB_NOLOG) == 0) { + char msg[NS_CLIENT_ACLMSGSIZE("query")]; + if (result == ISC_R_SUCCESS) { + if (isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(3))) { ns_client_aclmsg("query", name, qtype, client->view->rdclass, msg, sizeof(msg)); - ns_client_log(client, DNS_LOGCATEGORY_SECURITY, - NS_LOGMODULE_QUERY, ISC_LOG_INFO, - "%s denied", msg); + ns_client_log(client, + DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_QUERY, + ISC_LOG_DEBUG(3), + "%s approved", msg); } + } else { + ns_client_aclmsg("query", name, qtype, + client->view->rdclass, + msg, sizeof(msg)); + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_QUERY, ISC_LOG_INFO, + "%s denied", msg); } + } - if (queryacl == client->view->queryacl) { - if (result == ISC_R_SUCCESS) { - /* - * We were allowed by the default - * "allow-query" ACL. Remember this so we - * don't have to check again. - */ - client->query.attributes |= - NS_QUERYATTR_QUERYOK; - } + if (queryacl == client->view->queryacl) { + if (result == ISC_R_SUCCESS) { /* - * We've now evaluated the view's query ACL, and - * the NS_QUERYATTR_QUERYOK attribute is now valid. + * We were allowed by the default + * "allow-query" ACL. Remember this so we + * don't have to check again. */ - client->query.attributes |= NS_QUERYATTR_QUERYOKVALID; + client->query.attributes |= NS_QUERYATTR_QUERYOK; } - - if (result != ISC_R_SUCCESS) - goto refuse; + /* + * We've now evaluated the view's query ACL, and + * the NS_QUERYATTR_QUERYOK attribute is now valid. + */ + client->query.attributes |= NS_QUERYATTR_QUERYOKVALID; } - /* Approved. */ - - /* - * Remember the result of the ACL check so we - * don't have to check again. - */ + dbversion->acl_checked = ISC_TRUE; + if (result != ISC_R_SUCCESS) { + dbversion->queryok = ISC_FALSE; + return (DNS_R_REFUSED); + } dbversion->queryok = ISC_TRUE; + approved: /* Transfer ownership, if necessary. */ if (versionp != NULL) *versionp = dbversion->version; - return (ISC_R_SUCCESS); - - refuse: - return (DNS_R_REFUSED); - - fail: - return (result); } static inline isc_result_t @@ -800,6 +831,97 @@ query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, return (result); } +static void +rpz_log(ns_client_t *client) { + char namebuf1[DNS_NAME_FORMATSIZE]; + char namebuf2[DNS_NAME_FORMATSIZE]; + dns_rpz_st_t *st; + const char *pat; + + if (!ns_g_server->log_queries || + !isc_log_wouldlog(ns_g_lctx, DNS_RPZ_INFO_LEVEL)) + return; + + st = client->query.rpz_st; + dns_name_format(client->query.qname, namebuf1, sizeof(namebuf1)); + dns_name_format(st->qname, namebuf2, sizeof(namebuf2)); + + switch (st->m.policy) { + case DNS_RPZ_POLICY_NO_OP: + pat ="response policy %s rewrite %s NO-OP using %s"; + break; + case DNS_RPZ_POLICY_NXDOMAIN: + pat = "response policy %s rewrite %s to NXDOMAIN using %s"; + break; + case DNS_RPZ_POLICY_NODATA: + pat = "response policy %s rewrite %s to NODATA using %s"; + break; + case DNS_RPZ_POLICY_RECORD: + case DNS_RPZ_POLICY_CNAME: + pat = "response policy %s rewrite %s using %s"; + break; + default: + INSIST(0); + } + ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY, + DNS_RPZ_INFO_LEVEL, pat, dns_rpz_type2str(st->m.type), + namebuf1, namebuf2); +} + +static void +rpz_fail_log(ns_client_t *client, int level, dns_rpz_type_t rpz_type, + dns_name_t *name, const char *str, isc_result_t result) +{ + char namebuf1[DNS_NAME_FORMATSIZE]; + char namebuf2[DNS_NAME_FORMATSIZE]; + + if (!ns_g_server->log_queries || !isc_log_wouldlog(ns_g_lctx, level)) + return; + + dns_name_format(client->query.qname, namebuf1, sizeof(namebuf1)); + dns_name_format(name, namebuf2, sizeof(namebuf2)); + ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS, + NS_LOGMODULE_QUERY, level, + "response policy %s rewrite %s via %s %sfailed: %s", + dns_rpz_type2str(rpz_type), + namebuf1, namebuf2, str, isc_result_totext(result)); +} + +/* + * Get a policy rewrite zone database. + */ +static isc_result_t +rpz_getdb(ns_client_t *client, dns_rpz_type_t rpz_type, + dns_name_t *rpz_qname, dns_zone_t **zonep, + dns_db_t **dbp, dns_dbversion_t **versionp) +{ + char namebuf1[DNS_NAME_FORMATSIZE]; + char namebuf2[DNS_NAME_FORMATSIZE]; + dns_dbversion_t *rpz_version = NULL; + isc_result_t result; + + result = query_getzonedb(client, rpz_qname, dns_rdatatype_any, + DNS_GETDB_IGNOREACL, zonep, dbp, &rpz_version); + if (result == ISC_R_SUCCESS) { + if (ns_g_server->log_queries && + isc_log_wouldlog(ns_g_lctx, DNS_RPZ_DEBUG_LEVEL2)) { + dns_name_format(client->query.qname, namebuf1, + sizeof(namebuf1)); + dns_name_format(rpz_qname, namebuf2, sizeof(namebuf2)); + ns_client_log(client, NS_LOGCATEGORY_QUERIES, + NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2, + "try rpz %s rewrite %s via %s", + dns_rpz_type2str(rpz_type), + namebuf1, namebuf2); + } + *versionp = rpz_version; + return (ISC_R_SUCCESS); + } + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, rpz_type, rpz_qname, + "query_getzonedb() ", result); + return (result); +} + static inline isc_result_t query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, dns_db_t **dbp, unsigned int options) @@ -1958,6 +2080,323 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname, CTRACE("query_addrdataset: done"); } +static isc_result_t +query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset, isc_buffer_t *dbuf, + dns_section_t section) +{ + dns_name_t *name, *mname; + dns_rdata_t *dns64_rdata; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdatalist_t *dns64_rdatalist; + dns_rdataset_t *dns64_rdataset; + dns_rdataset_t *mrdataset; + isc_buffer_t *buffer; + isc_region_t r; + isc_result_t result; + dns_view_t *view = client->view; + isc_netaddr_t netaddr; + dns_dns64_t *dns64; + unsigned int flags = 0; + + /*% + * To the current response for 'client', add the answer RRset + * '*rdatasetp' and an optional signature set '*sigrdatasetp', with + * owner name '*namep', to section 'section', unless they are + * already there. Also add any pertinent additional data. + * + * If 'dbuf' is not NULL, then '*namep' is the name whose data is + * stored in 'dbuf'. In this case, query_addrrset() guarantees that + * when it returns the name will either have been kept or released. + */ + CTRACE("query_dns64"); + name = *namep; + mname = NULL; + mrdataset = NULL; + buffer = NULL; + dns64_rdata = NULL; + dns64_rdataset = NULL; + dns64_rdatalist = NULL; + result = dns_message_findname(client->message, section, + name, dns_rdatatype_aaaa, + rdataset->covers, + &mname, &mrdataset); + if (result == ISC_R_SUCCESS) { + /* + * We've already got an RRset of the given name and type. + * There's nothing else to do; + */ + CTRACE("query_dns64: dns_message_findname succeeded: done"); + if (dbuf != NULL) + query_releasename(client, namep); + return (ISC_R_SUCCESS); + } else if (result == DNS_R_NXDOMAIN) { + /* + * The name doesn't exist. + */ + if (dbuf != NULL) + query_keepname(client, name, dbuf); + dns_message_addname(client->message, name, section); + *namep = NULL; + mname = name; + } else { + RUNTIME_CHECK(result == DNS_R_NXRRSET); + if (dbuf != NULL) + query_releasename(client, namep); + } + + if (rdataset->trust != dns_trust_secure && + (section == DNS_SECTION_ANSWER || + section == DNS_SECTION_AUTHORITY)) + client->query.attributes &= ~NS_QUERYATTR_SECURE; + + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); + + result = isc_buffer_allocate(client->mctx, &buffer, view->dns64cnt * + 16 * dns_rdataset_count(rdataset)); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_message_gettemprdataset(client->message, &dns64_rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_message_gettemprdatalist(client->message, + &dns64_rdatalist); + if (result != ISC_R_SUCCESS) + goto cleanup; + + dns_rdataset_init(dns64_rdataset); + dns_rdatalist_init(dns64_rdatalist); + dns64_rdatalist->rdclass = dns_rdataclass_in; + dns64_rdatalist->type = dns_rdatatype_aaaa; + if (client->query.dns64_ttl != ISC_UINT32_MAX) + dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl, + client->query.dns64_ttl); + else + dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl, 600); + + if (RECURSIONOK(client)) + flags |= DNS_DNS64_RECURSIVE; + + /* + * We use the signatures from the A lookup to set DNS_DNS64_DNSSEC + * as this provides a easy way to see if the answer was signed. + */ + if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) + flags |= DNS_DNS64_DNSSEC; + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + for (dns64 = ISC_LIST_HEAD(client->view->dns64); + dns64 != NULL; dns64 = dns_dns64_next(dns64)) { + + dns_rdataset_current(rdataset, &rdata); + isc__buffer_availableregion(buffer, &r); + INSIST(r.length >= 16); + result = dns_dns64_aaaafroma(dns64, &netaddr, + client->signer, + &ns_g_server->aclenv, + flags, rdata.data, r.base); + if (result != ISC_R_SUCCESS) { + dns_rdata_reset(&rdata); + continue; + } + isc_buffer_add(buffer, 16); + isc_buffer_remainingregion(buffer, &r); + isc_buffer_forward(buffer, 16); + result = dns_message_gettemprdata(client->message, + &dns64_rdata); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_rdata_init(dns64_rdata); + dns_rdata_fromregion(dns64_rdata, dns_rdataclass_in, + dns_rdatatype_aaaa, &r); + ISC_LIST_APPEND(dns64_rdatalist->rdata, dns64_rdata, + link); + dns64_rdata = NULL; + dns_rdata_reset(&rdata); + } + } + if (result != ISC_R_NOMORE) + goto cleanup; + + if (ISC_LIST_EMPTY(dns64_rdatalist->rdata)) + goto cleanup; + + result = dns_rdatalist_tordataset(dns64_rdatalist, dns64_rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + client->query.attributes |= NS_QUERYATTR_NOADDITIONAL; + dns64_rdataset->trust = rdataset->trust; + query_addrdataset(client, mname, dns64_rdataset); + dns64_rdataset = NULL; + dns64_rdatalist = NULL; + dns_message_takebuffer(client->message, &buffer); + result = ISC_R_SUCCESS; + + cleanup: + if (buffer != NULL) + isc_buffer_free(&buffer); + + if (dns64_rdata != NULL) + dns_message_puttemprdata(client->message, &dns64_rdata); + + if (dns64_rdataset != NULL) + dns_message_puttemprdataset(client->message, &dns64_rdataset); + + if (dns64_rdatalist != NULL) { + for (dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata); + dns64_rdata != NULL; + dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata)) + { + ISC_LIST_UNLINK(dns64_rdatalist->rdata, + dns64_rdata, link); + dns_message_puttemprdata(client->message, &dns64_rdata); + } + dns_message_puttemprdatalist(client->message, &dns64_rdatalist); + } + + CTRACE("query_dns64: done"); + return (result); +} + +static void +query_filter64(ns_client_t *client, dns_name_t **namep, + dns_rdataset_t *rdataset, isc_buffer_t *dbuf, + dns_section_t section) +{ + dns_name_t *name, *mname; + dns_rdata_t *myrdata; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdatalist_t *myrdatalist; + dns_rdataset_t *myrdataset; + isc_buffer_t *buffer; + isc_region_t r; + isc_result_t result; + unsigned int i; + + CTRACE("query_filter64"); + + INSIST(client->query.dns64_aaaaok != NULL); + INSIST(client->query.dns64_aaaaoklen == dns_rdataset_count(rdataset)); + + name = *namep; + mname = NULL; + buffer = NULL; + myrdata = NULL; + myrdataset = NULL; + myrdatalist = NULL; + result = dns_message_findname(client->message, section, + name, dns_rdatatype_aaaa, + rdataset->covers, + &mname, &myrdataset); + if (result == ISC_R_SUCCESS) { + /* + * We've already got an RRset of the given name and type. + * There's nothing else to do; + */ + CTRACE("query_filter64: dns_message_findname succeeded: done"); + if (dbuf != NULL) + query_releasename(client, namep); + return; + } else if (result == DNS_R_NXDOMAIN) { + mname = name; + *namep = NULL; + } else { + RUNTIME_CHECK(result == DNS_R_NXRRSET); + if (dbuf != NULL) + query_releasename(client, namep); + dbuf = NULL; + } + + if (rdataset->trust != dns_trust_secure && + (section == DNS_SECTION_ANSWER || + section == DNS_SECTION_AUTHORITY)) + client->query.attributes &= ~NS_QUERYATTR_SECURE; + + result = isc_buffer_allocate(client->mctx, &buffer, + 16 * dns_rdataset_count(rdataset)); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_message_gettemprdataset(client->message, &myrdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_message_gettemprdatalist(client->message, &myrdatalist); + if (result != ISC_R_SUCCESS) + goto cleanup; + + dns_rdataset_init(myrdataset); + dns_rdatalist_init(myrdatalist); + myrdatalist->rdclass = dns_rdataclass_in; + myrdatalist->type = dns_rdatatype_aaaa; + myrdatalist->ttl = rdataset->ttl; + + i = 0; + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + if (!client->query.dns64_aaaaok[i++]) + continue; + dns_rdataset_current(rdataset, &rdata); + INSIST(rdata.length == 16); + isc_buffer_putmem(buffer, rdata.data, rdata.length); + isc_buffer_remainingregion(buffer, &r); + isc_buffer_forward(buffer, rdata.length); + result = dns_message_gettemprdata(client->message, &myrdata); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_rdata_init(myrdata); + dns_rdata_fromregion(myrdata, dns_rdataclass_in, + dns_rdatatype_aaaa, &r); + ISC_LIST_APPEND(myrdatalist->rdata, myrdata, link); + myrdata = NULL; + dns_rdata_reset(&rdata); + } + if (result != ISC_R_NOMORE) + goto cleanup; + + result = dns_rdatalist_tordataset(myrdatalist, myrdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + client->query.attributes |= NS_QUERYATTR_NOADDITIONAL; + if (mname == name) { + if (dbuf != NULL) + query_keepname(client, name, dbuf); + dns_message_addname(client->message, name, section); + dbuf = NULL; + } + myrdataset->trust = rdataset->trust; + query_addrdataset(client, mname, myrdataset); + myrdataset = NULL; + myrdatalist = NULL; + dns_message_takebuffer(client->message, &buffer); + + cleanup: + if (buffer != NULL) + isc_buffer_free(&buffer); + + if (myrdata != NULL) + dns_message_puttemprdata(client->message, &myrdata); + + if (myrdataset != NULL) + dns_message_puttemprdataset(client->message, &myrdataset); + + if (myrdatalist != NULL) { + for (myrdata = ISC_LIST_HEAD(myrdatalist->rdata); + myrdata != NULL; + myrdata = ISC_LIST_HEAD(myrdatalist->rdata)) + { + ISC_LIST_UNLINK(myrdatalist->rdata, myrdata, link); + dns_message_puttemprdata(client->message, &myrdata); + } + dns_message_puttemprdatalist(client->message, &myrdatalist); + } + if (dbuf != NULL) + query_releasename(client, &name); + + CTRACE("query_filter64: done"); +} + static void query_addrrset(ns_client_t *client, dns_name_t **namep, dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp, @@ -2036,7 +2475,7 @@ query_addrrset(ns_client_t *client, dns_name_t **namep, static inline isc_result_t query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, - isc_boolean_t zero_ttl, isc_boolean_t isassociated) + unsigned int override_ttl, isc_boolean_t isassociated) { dns_name_t *name; dns_dbnode_t *node; @@ -2119,10 +2558,11 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, if (result != ISC_R_SUCCESS) goto cleanup; - if (zero_ttl) { - rdataset->ttl = 0; + if (override_ttl != ISC_UINT32_MAX && + override_ttl < rdataset->ttl) { + rdataset->ttl = override_ttl; if (sigrdataset != NULL) - sigrdataset->ttl = 0; + sigrdataset->ttl = override_ttl; } /* @@ -2246,67 +2686,79 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) { return (eresult); } -static inline isc_result_t -query_addcnamelike(ns_client_t *client, dns_name_t *qname, dns_name_t *tname, - dns_rdataset_t *dname, dns_name_t **anamep, - dns_rdatatype_t type) +static isc_result_t +query_add_cname(ns_client_t *client, dns_name_t *qname, dns_name_t *tname, + dns_trust_t trust, dns_ttl_t ttl) { dns_rdataset_t *rdataset; dns_rdatalist_t *rdatalist; dns_rdata_t *rdata; - isc_result_t result; isc_region_t r; + dns_name_t *aname; + isc_result_t result; /* * We assume the name data referred to by tname won't go away. */ - REQUIRE(anamep != NULL); + aname = NULL; + result = dns_message_gettempname(client->message, &aname); + if (result != ISC_R_SUCCESS) + return (result); + result = dns_name_dup(qname, client->mctx, aname); + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(client->message, &aname); + return (result); + } rdatalist = NULL; result = dns_message_gettemprdatalist(client->message, &rdatalist); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(client->message, &aname); return (result); + } rdata = NULL; result = dns_message_gettemprdata(client->message, &rdata); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(client->message, &aname); + dns_message_puttemprdatalist(client->message, &rdatalist); return (result); + } rdataset = NULL; result = dns_message_gettemprdataset(client->message, &rdataset); - if (result != ISC_R_SUCCESS) - return (result); - dns_rdataset_init(rdataset); - result = dns_name_dup(qname, client->mctx, *anamep); if (result != ISC_R_SUCCESS) { - dns_message_puttemprdataset(client->message, &rdataset); + dns_message_puttempname(client->message, &aname); + dns_message_puttemprdatalist(client->message, &rdatalist); + dns_message_puttemprdata(client->message, &rdata); return (result); } - - rdatalist->type = type; + dns_rdataset_init(rdataset); + rdatalist->type = dns_rdatatype_cname; rdatalist->covers = 0; rdatalist->rdclass = client->message->rdclass; - rdatalist->ttl = dname->ttl; + rdatalist->ttl = ttl; dns_name_toregion(tname, &r); rdata->data = r.base; rdata->length = r.length; rdata->rdclass = client->message->rdclass; - rdata->type = type; + rdata->type = dns_rdatatype_cname; ISC_LIST_INIT(rdatalist->rdata); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS); - rdataset->trust = dname->trust; + rdataset->trust = trust; - query_addrrset(client, anamep, &rdataset, NULL, NULL, + query_addrrset(client, &aname, &rdataset, NULL, NULL, DNS_SECTION_ANSWER); - if (rdataset != NULL) { if (dns_rdataset_isassociated(rdataset)) dns_rdataset_disassociate(rdataset); dns_message_puttemprdataset(client->message, &rdataset); } + if (aname != NULL) + dns_message_puttempname(client->message, &aname); return (ISC_R_SUCCESS); } @@ -2860,7 +3312,7 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db, * j.example -> z.i.example NSEC example * owner common example * next common example - * wild *.f.example + * wild *.example */ options = client->query.dboptions | DNS_DBFIND_NOWILD; dns_fixedname_init(&wfixed); @@ -3196,8 +3648,9 @@ query_resume(isc_task_t *task, isc_event_t *event) { } static isc_result_t -query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, - dns_rdataset_t *nameservers, isc_boolean_t resuming) +query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, + dns_name_t *qdomain, dns_rdataset_t *nameservers, + isc_boolean_t resuming) { isc_result_t result; dns_rdataset_t *rdataset, *sigrdataset; @@ -3229,7 +3682,11 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, "recursive-clients soft limit " - "exceeded, aborting oldest query"); + "exceeded (%d/%d/%d), " + "aborting oldest query", + client->recursionquota->used, + client->recursionquota->soft, + client->recursionquota->max); } ns_client_killoldestquery(client); result = ISC_R_SUCCESS; @@ -3242,7 +3699,11 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, ISC_LOG_WARNING, - "no more recursive clients: %s", + "no more recursive clients " + "(%d/%d/%d): %s", + ns_g_server->recursionquota.used, + ns_g_server->recursionquota.soft, + ns_g_server->recursionquota.max, isc_result_totext(result)); } ns_client_killoldestquery(client); @@ -3289,8 +3750,7 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, else peeraddr = NULL; result = dns_resolver_createfetch2(client->view->resolver, - client->query.qname, - qtype, qdomain, nameservers, + qname, qtype, qdomain, nameservers, NULL, peeraddr, client->message->id, client->query.fetchoptions, client->task, @@ -3313,6 +3773,696 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain, return (result); } +static inline void +rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep, + dns_rdataset_t **rdatasetp) +{ + if (nodep != NULL && *nodep != NULL) { + REQUIRE(dbp != NULL && *dbp != NULL); + dns_db_detachnode(*dbp, nodep); + } + if (dbp != NULL && *dbp != NULL) + dns_db_detach(dbp); + if (zonep != NULL && *zonep != NULL) + dns_zone_detach(zonep); + if (rdatasetp != NULL && *rdatasetp != NULL && + dns_rdataset_isassociated(*rdatasetp)) + dns_rdataset_disassociate(*rdatasetp); +} + +static inline isc_result_t +rpz_ready(ns_client_t *client, dns_zone_t **zonep, dns_db_t **dbp, + dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp) +{ + REQUIRE(rdatasetp != NULL); + + rpz_clean(zonep, dbp, nodep, rdatasetp); + if (*rdatasetp == NULL) { + *rdatasetp = query_newrdataset(client); + if (*rdatasetp == NULL) + return (DNS_R_SERVFAIL); + } + return (ISC_R_SUCCESS); +} + +static void +rpz_st_clear(ns_client_t *client) { + dns_rpz_st_t *st = client->query.rpz_st; + + rpz_clean(&st->m.zone, &st->m.db, &st->m.node, NULL); + if (st->m.rdataset != NULL) + query_putrdataset(client, &st->m.rdataset); + + rpz_clean(NULL, &st->ns.db, NULL, NULL); + if (st->ns.ns_rdataset != NULL) + query_putrdataset(client, &st->ns.ns_rdataset); + if (st->ns.r_rdataset != NULL) + query_putrdataset(client, &st->ns.r_rdataset); + + rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL); + if (st->q.rdataset != NULL) + query_putrdataset(client, &st->q.rdataset); + if (st->q.sigrdataset != NULL) + query_putrdataset(client, &st->q.sigrdataset); + st->state = 0; +} + +/* + * Get NS, A, or AAAA rrset for rpz nsdname or nsip checking. + */ +static isc_result_t +rpz_ns_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type, + dns_db_t **dbp, dns_dbversion_t *version, + dns_rdataset_t **rdatasetp, isc_boolean_t resuming) +{ + dns_rpz_st_t *st; + isc_boolean_t is_zone; + dns_dbnode_t *node; + dns_fixedname_t fixed; + dns_name_t *found; + isc_result_t result; + + st = client->query.rpz_st; + if ((st->state & DNS_RPZ_RECURSING) != 0) { + INSIST(st->ns.r_type == type); + INSIST(dns_name_equal(name, st->r_name)); + INSIST(*rdatasetp == NULL || + !dns_rdataset_isassociated(*rdatasetp)); + st->state &= ~DNS_RPZ_RECURSING; + *dbp = st->ns.db; + st->ns.db = NULL; + if (*rdatasetp != NULL) + query_putrdataset(client, rdatasetp); + *rdatasetp = st->ns.r_rdataset; + st->ns.r_rdataset = NULL; + result = st->ns.r_result; + if (result == DNS_R_DELEGATION) { + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, + DNS_RPZ_TYPE_NSIP, name, + "rpz_ns_find() ", result); + st->m.policy = DNS_RPZ_POLICY_ERROR; + result = DNS_R_SERVFAIL; + } + return (result); + } + + result = rpz_ready(client, NULL, NULL, NULL, rdatasetp); + if (result != ISC_R_SUCCESS) { + st->m.policy = DNS_RPZ_POLICY_ERROR; + return (result); + } + if (*dbp != NULL) { + is_zone = ISC_FALSE; + } else { + dns_zone_t *zone; + + version = NULL; + zone = NULL; + result = query_getdb(client, name, type, 0, &zone, dbp, + &version, &is_zone); + if (result != ISC_R_SUCCESS) { + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, + DNS_RPZ_TYPE_NSIP, name, "NS getdb() ", + result); + st->m.policy = DNS_RPZ_POLICY_ERROR; + if (zone != NULL) + dns_zone_detach(&zone); + return (result); + } + if (zone != NULL) + dns_zone_detach(&zone); + } + + node = NULL; + dns_fixedname_init(&fixed); + found = dns_fixedname_name(&fixed); + result = dns_db_find(*dbp, name, version, type, 0, client->now, &node, + found, *rdatasetp, NULL); + if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) { + /* + * Try the cache if we're authoritative for an + * ancestor but not the domain itself. + */ + rpz_clean(NULL, dbp, &node, rdatasetp); + version = NULL; + dns_db_attach(client->view->cachedb, dbp); + result = dns_db_find(*dbp, name, version, dns_rdatatype_ns, + 0, client->now, &node, found, + *rdatasetp, NULL); + } + rpz_clean(NULL, dbp, &node, NULL); + if (result == DNS_R_DELEGATION) { + /* + * Recurse to get NS rrset or A or AAAA rrset for an NS name. + */ + rpz_clean(NULL, NULL, NULL, rdatasetp); + dns_name_copy(name, st->r_name, NULL); + result = query_recurse(client, type, st->r_name, NULL, NULL, + resuming); + if (result == ISC_R_SUCCESS) { + st->state |= DNS_RPZ_RECURSING; + result = DNS_R_DELEGATION; + } + } + return (result); +} + +/* + * Check the IP address in an A or AAAA rdataset against + * the IP or NSIP response policy rules of a view. + */ +static isc_result_t +rpz_rewrite_ip(ns_client_t *client, dns_rdataset_t *rdataset, + dns_rpz_type_t rpz_type) +{ + dns_rpz_st_t *st; + dns_dbversion_t *version; + dns_zone_t *zone; + dns_db_t *db; + dns_rpz_zone_t *new_rpz; + isc_result_t result; + + st = client->query.rpz_st; + if (st->m.rdataset == NULL) { + st->m.rdataset = query_newrdataset(client); + if (st->m.rdataset == NULL) + return (DNS_R_SERVFAIL); + } + zone = NULL; + db = NULL; + for (new_rpz = ISC_LIST_HEAD(client->view->rpz_zones); + new_rpz != NULL; + new_rpz = ISC_LIST_NEXT(new_rpz, link)) { + version = NULL; + + /* + * Find the database for this policy zone to get its + * radix tree. + */ + result = rpz_getdb(client, rpz_type, &new_rpz->origin, + &zone, &db, &version); + if (result != ISC_R_SUCCESS) { + rpz_clean(&zone, &db, NULL, NULL); + continue; + } + /* + * Look for a better (e.g. longer prefix) hit for an IP address + * in this rdataset in this radix tree than than the previous + * hit, if any. Note the domain name and quality of the + * best hit. + */ + result = dns_db_rpz_findips(new_rpz, rpz_type, zone, db, + version, rdataset, st); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + rpz_clean(&zone, &db, NULL, NULL); + } + return (ISC_R_SUCCESS); +} + +static isc_result_t +rpz_rewrite_nsip(ns_client_t *client, dns_rdatatype_t type, dns_name_t *name, + dns_db_t **dbp, dns_dbversion_t *version, + dns_rdataset_t **rdatasetp, isc_boolean_t resuming) +{ + isc_result_t result; + + result = rpz_ns_find(client, name, type, dbp, version, rdatasetp, + resuming); + switch (result) { + case ISC_R_SUCCESS: + result = rpz_rewrite_ip(client, *rdatasetp, DNS_RPZ_TYPE_NSIP); + break; + case DNS_R_EMPTYNAME: + case DNS_R_EMPTYWILD: + case DNS_R_NXDOMAIN: + case DNS_R_NCACHENXDOMAIN: + case DNS_R_NXRRSET: + case DNS_R_NCACHENXRRSET: + result = ISC_R_SUCCESS; + break; + case DNS_R_DELEGATION: + case DNS_R_DUPLICATE: + case DNS_R_DROP: + break; + default: + if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) { + client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR; + rpz_fail_log(client, ISC_LOG_WARNING, DNS_RPZ_TYPE_NSIP, + name, "NS address rewrite nsip ", result); + } + break; + } + return (result); +} + +/* + * Get the rrset from a response policy zone. + */ +static isc_result_t +rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef, + dns_name_t *sname, dns_rpz_type_t rpz_type, dns_zone_t **zonep, + dns_db_t **dbp, dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp, + dns_rpz_policy_t *policyp) +{ + dns_dbversion_t *version; + dns_rpz_policy_t policy; + dns_fixedname_t fixed; + dns_name_t *found; + isc_result_t result; + + result = rpz_ready(client, zonep, dbp, nodep, rdatasetp); + if (result != ISC_R_SUCCESS) { + *policyp = DNS_RPZ_POLICY_ERROR; + return (result); + } + + /* + * Try to get either a CNAME or the type of record demanded by the + * request from the policy zone. + */ + version = NULL; + result = rpz_getdb(client, rpz_type, qnamef, zonep, dbp, &version); + if (result != ISC_R_SUCCESS) { + *policyp = DNS_RPZ_POLICY_MISS; + return (DNS_R_NXDOMAIN); + } + + dns_fixedname_init(&fixed); + found = dns_fixedname_name(&fixed); + result = dns_db_find(*dbp, qnamef, version, dns_rdatatype_any, 0, + client->now, nodep, found, *rdatasetp, NULL); + if (result == ISC_R_SUCCESS) { + dns_rdatasetiter_t *rdsiter; + + rdsiter = NULL; + result = dns_db_allrdatasets(*dbp, *nodep, version, 0, + &rdsiter); + if (result != ISC_R_SUCCESS) { + dns_db_detachnode(*dbp, nodep); + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, rpz_type, + qnamef, "allrdatasets()", result); + *policyp = DNS_RPZ_POLICY_ERROR; + return (DNS_R_SERVFAIL); + } + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) { + dns_rdatasetiter_current(rdsiter, *rdatasetp); + if ((*rdatasetp)->type == dns_rdatatype_cname || + (*rdatasetp)->type == qtype) + break; + dns_rdataset_disassociate(*rdatasetp); + } + dns_rdatasetiter_destroy(&rdsiter); + if (result != ISC_R_SUCCESS) { + if (result != ISC_R_NOMORE) { + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, + rpz_type, qnamef, "rdatasetiter", + result); + *policyp = DNS_RPZ_POLICY_ERROR; + return (DNS_R_SERVFAIL); + } + /* + * Ask again to get the right DNS_R_DNAME/NXRRSET/... + * result if there is neither a CNAME nor target type. + */ + if (dns_rdataset_isassociated(*rdatasetp)) + dns_rdataset_disassociate(*rdatasetp); + dns_db_detachnode(*dbp, nodep); + + if (qtype == dns_rdatatype_rrsig || + qtype == dns_rdatatype_sig) + result = DNS_R_NXRRSET; + else + result = dns_db_find(*dbp, qnamef, version, + qtype, 0, client->now, + nodep, found, *rdatasetp, + NULL); + } + } + switch (result) { + case ISC_R_SUCCESS: + if ((*rdatasetp)->type != dns_rdatatype_cname) { + policy = DNS_RPZ_POLICY_RECORD; + } else { + policy = dns_rpz_decode_cname(*rdatasetp, sname); + if (policy == DNS_RPZ_POLICY_RECORD && + qtype != dns_rdatatype_cname && + qtype != dns_rdatatype_any) + result = DNS_R_CNAME; + } + break; + case DNS_R_DNAME: + /* + * DNAME policy RRs have very few if any uses that are not + * better served with simple wildcards. Making the work would + * require complications to get the number of labels matched + * in the name or the found name itself to the main DNS_R_DNAME + * case in query_find(). So fall through to treat them as NODATA. + */ + case DNS_R_NXRRSET: + policy = DNS_RPZ_POLICY_NODATA; + break; + case DNS_R_NXDOMAIN: + case DNS_R_EMPTYNAME: + /* + * If we don't get a qname hit, + * see if it is worth looking for other types. + */ + dns_db_rpz_enabled(*dbp, client->query.rpz_st); + dns_db_detach(dbp); + dns_zone_detach(zonep); + policy = DNS_RPZ_POLICY_MISS; + break; + default: + dns_db_detach(dbp); + dns_zone_detach(zonep); + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, rpz_type, qnamef, + "", result); + policy = DNS_RPZ_POLICY_ERROR; + result = DNS_R_SERVFAIL; + break; + } + + *policyp = policy; + return (result); +} + +/* + * Build and look for a QNAME or NSDNAME owner name in a response policy zone. + */ +static isc_result_t +rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, + dns_rpz_type_t rpz_type, dns_rdataset_t **rdatasetp) +{ + dns_rpz_st_t *st; + dns_rpz_zone_t *rpz; + dns_fixedname_t prefixf, rpz_qnamef; + dns_name_t *prefix, *suffix, *rpz_qname; + dns_zone_t *zone; + dns_db_t *db; + dns_dbnode_t *node; + dns_rpz_policy_t policy; + unsigned int labels; + isc_result_t result; + + st = client->query.rpz_st; + zone = NULL; + db = NULL; + node = NULL; + + for (rpz = ISC_LIST_HEAD(client->view->rpz_zones); + rpz != NULL; + rpz = ISC_LIST_NEXT(rpz, link)) { + /* + * Construct the rule's owner name. + */ + dns_fixedname_init(&prefixf); + prefix = dns_fixedname_name(&prefixf); + dns_name_split(qname, 1, prefix, NULL); + if (rpz_type == DNS_RPZ_TYPE_NSDNAME) + suffix = &rpz->nsdname; + else + suffix = &rpz->origin; + dns_fixedname_init(&rpz_qnamef); + rpz_qname = dns_fixedname_name(&rpz_qnamef); + for (;;) { + result = dns_name_concatenate(prefix, suffix, + rpz_qname, NULL); + if (result == ISC_R_SUCCESS) + break; + INSIST(result == DNS_R_NAMETOOLONG); + labels = dns_name_countlabels(prefix); + if (labels < 2) { + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, + rpz_type, suffix, + "concatentate() ", result); + return (ISC_R_SUCCESS); + } + if (labels+1 == dns_name_countlabels(qname)) { + rpz_fail_log(client, DNS_RPZ_DEBUG_LEVEL1, + rpz_type, suffix, + "concatentate() ", result); + } + dns_name_split(prefix, labels - 1, NULL, prefix); + } + + /* + * See if the qname rule (or RR) exists. + */ + result = rpz_find(client, qtype, rpz_qname, qname, rpz_type, + &zone, &db, &node, rdatasetp, &policy); + switch (result) { + case DNS_R_NXDOMAIN: + case DNS_R_EMPTYNAME: + break; + case DNS_R_SERVFAIL: + rpz_clean(&zone, &db, &node, rdatasetp); + st->m.policy = DNS_RPZ_POLICY_ERROR; + return (DNS_R_SERVFAIL); + default: + /* + * when more than one name or address hits a rule, + * prefer the first set of names (qname or NS), + * the first policy zone, and the smallest name + */ + if (st->m.type == rpz_type && + rpz->num > st->m.rpz->num && + 0 <= dns_name_compare(rpz_qname, st->qname)) + continue; + rpz_clean(&st->m.zone, &st->m.db, &st->m.node, + &st->m.rdataset); + st->m.rpz = rpz; + st->m.type = rpz_type; + st->m.prefix = 0; + st->m.policy = policy; + st->m.result = result; + dns_name_copy(rpz_qname, st->qname, NULL); + if (dns_rdataset_isassociated(*rdatasetp)) { + dns_rdataset_t *trdataset; + + trdataset = st->m.rdataset; + st->m.rdataset = *rdatasetp; + *rdatasetp = trdataset; + st->m.ttl = st->m.rdataset->ttl; + } else { + st->m.ttl = DNS_RPZ_TTL_DEFAULT; + } + st->m.node = node; + node = NULL; + st->m.db = db; + db = NULL; + st->m.zone = zone; + zone = NULL; + } + } + + rpz_clean(&zone, &db, &node, rdatasetp); + return (ISC_R_SUCCESS); +} + +/* + * Look for response policy zone NSIP and NSDNAME rewriting. + */ +static isc_result_t +rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, + isc_boolean_t resuming) +{ + dns_rpz_st_t *st; + dns_db_t *ipdb; + dns_rdataset_t *rdataset; + dns_fixedname_t nsnamef; + dns_name_t *nsname; + dns_dbversion_t *version; + isc_result_t result; + + ipdb = NULL; + rdataset = NULL; + + st = client->query.rpz_st; + if (st == NULL) { + st = isc_mem_get(client->mctx, sizeof(*st)); + if (st == NULL) + return (ISC_R_NOMEMORY); + st->state = 0; + memset(&st->m, 0, sizeof(st->m)); + memset(&st->ns, 0, sizeof(st->ns)); + memset(&st->q, 0, sizeof(st->q)); + dns_fixedname_init(&st->_qnamef); + dns_fixedname_init(&st->_r_namef); + dns_fixedname_init(&st->_fnamef); + st->qname = dns_fixedname_name(&st->_qnamef); + st->r_name = dns_fixedname_name(&st->_r_namef); + st->fname = dns_fixedname_name(&st->_fnamef); + client->query.rpz_st = st; + } + if ((st->state & DNS_RPZ_DONE_QNAME) == 0) { + st->state = DNS_RPZ_DONE_QNAME; + st->m.type = DNS_RPZ_TYPE_BAD; + st->m.policy = DNS_RPZ_POLICY_MISS; + + /* + * Check rules for the name if this it the first time, + * i.e. we've not been recursing. + */ + result = DNS_R_SERVFAIL; + st->state &= ~(DNS_RPZ_HAVE_IP | DNS_RPZ_HAVE_NSIPv4 | + DNS_RPZ_HAVE_NSIPv6 | DNS_RPZ_HAD_NSDNAME); + result = rpz_rewrite_name(client, qtype, client->query.qname, + DNS_RPZ_TYPE_QNAME, &rdataset); + if (st->m.policy != DNS_RPZ_POLICY_MISS) + goto cleanup; + if ((st->state & (DNS_RPZ_HAVE_NSIPv4 | DNS_RPZ_HAVE_NSIPv6 | + DNS_RPZ_HAD_NSDNAME)) == 0) + goto cleanup; + st->ns.label = dns_name_countlabels(client->query.qname); + } + + dns_fixedname_init(&nsnamef); + dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef)); + while (st->ns.label > 1 && st->m.policy == DNS_RPZ_POLICY_MISS) { + if (st->ns.label == dns_name_countlabels(client->query.qname)) { + nsname = client->query.qname; + } else { + nsname = dns_fixedname_name(&nsnamef); + dns_name_split(client->query.qname, st->ns.label, + NULL, nsname); + } + if (st->ns.ns_rdataset == NULL || + !dns_rdataset_isassociated(st->ns.ns_rdataset)) { + dns_db_t *db = NULL; + result = rpz_ns_find(client, nsname, dns_rdatatype_ns, + &db, NULL, &st->ns.ns_rdataset, + resuming); + if (db != NULL) + dns_db_detach(&db); + if (result != ISC_R_SUCCESS) { + if (result == DNS_R_DELEGATION) + goto cleanup; + if (result == DNS_R_EMPTYNAME || + result == DNS_R_NXRRSET || + result == DNS_R_EMPTYWILD || + result == DNS_R_NXDOMAIN || + result == DNS_R_NCACHENXDOMAIN || + result == DNS_R_NCACHENXRRSET || + result == DNS_R_CNAME || + result == DNS_R_DNAME) { + rpz_fail_log(client, + DNS_RPZ_DEBUG_LEVEL2, + DNS_RPZ_TYPE_NSIP, nsname, + "NS db_find() ", result); + dns_rdataset_disassociate(st->ns. + ns_rdataset); + st->ns.label--; + continue; + } + if (st->m.policy != DNS_RPZ_POLICY_ERROR) { + rpz_fail_log(client, DNS_RPZ_INFO_LEVEL, + DNS_RPZ_TYPE_NSIP, nsname, + "NS db_find() ", result); + st->m.policy = DNS_RPZ_POLICY_ERROR; + } + goto cleanup; + } + result = dns_rdataset_first(st->ns.ns_rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + /* + * Check all NS names. + */ + do { + dns_rdata_ns_t ns; + dns_rdata_t nsrdata = DNS_RDATA_INIT; + + dns_rdataset_current(st->ns.ns_rdataset, &nsrdata); + result = dns_rdata_tostruct(&nsrdata, &ns, NULL); + dns_rdata_reset(&nsrdata); + if (result != ISC_R_SUCCESS) { + rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, + DNS_RPZ_TYPE_NSIP, nsname, + "rdata_tostruct() ", result); + st->m.policy = DNS_RPZ_POLICY_ERROR; + goto cleanup; + } + if ((st->state & DNS_RPZ_HAD_NSDNAME) != 0) { + result = rpz_rewrite_name(client, qtype, + &ns.name, + DNS_RPZ_TYPE_NSDNAME, + &rdataset); + if (result != ISC_R_SUCCESS) { + dns_rdata_freestruct(&ns); + goto cleanup; + } + } + /* + * Check all IP addresses for this NS name, but don't + * bother without NSIP rules or with a NSDNAME hit. + */ + version = NULL; + if ((st->state & DNS_RPZ_HAVE_NSIPv4) != 0 && + st->m.type != DNS_RPZ_TYPE_NSDNAME && + (st->state & DNS_RPZ_DONE_A) == 0) { + result = rpz_rewrite_nsip(client, + dns_rdatatype_a, + &ns.name, &ipdb, + version, &rdataset, + resuming); + if (result == ISC_R_SUCCESS) + st->state |= DNS_RPZ_DONE_A; + } + if (result == ISC_R_SUCCESS && + (st->state & DNS_RPZ_HAVE_NSIPv6) != 0 && + st->m.type != DNS_RPZ_TYPE_NSDNAME) { + result = rpz_rewrite_nsip(client, + dns_rdatatype_aaaa, + &ns.name, &ipdb, version, + &rdataset, resuming); + } + dns_rdata_freestruct(&ns); + if (ipdb != NULL) + dns_db_detach(&ipdb); + if (result != ISC_R_SUCCESS) + goto cleanup; + st->state &= ~DNS_RPZ_DONE_A; + result = dns_rdataset_next(st->ns.ns_rdataset); + } while (result == ISC_R_SUCCESS); + dns_rdataset_disassociate(st->ns.ns_rdataset); + st->ns.label--; + } + + /* + * Use the best, if any, hit. + */ + result = ISC_R_SUCCESS; + +cleanup: + if (st->m.policy != DNS_RPZ_POLICY_MISS && + st->m.policy != DNS_RPZ_POLICY_NO_OP && + st->m.policy != DNS_RPZ_POLICY_ERROR && + st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN) + st->m.policy = st->m.rpz->policy; + if (st->m.policy == DNS_RPZ_POLICY_NO_OP) + rpz_log(client); + if (st->m.policy == DNS_RPZ_POLICY_MISS || + st->m.policy == DNS_RPZ_POLICY_NO_OP || + st->m.policy == DNS_RPZ_POLICY_ERROR) + rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset); + if (st->m.policy != DNS_RPZ_POLICY_MISS) + st->state |= DNS_RPZ_REWRITTEN; + if (st->m.policy == DNS_RPZ_POLICY_ERROR) { + st->m.type = DNS_RPZ_TYPE_BAD; + result = DNS_R_SERVFAIL; + } + if (rdataset != NULL) + query_putrdataset(client, &rdataset); + if ((st->state & DNS_RPZ_RECURSING) == 0) { + rpz_clean(NULL, &st->ns.db, NULL, &st->ns.ns_rdataset); + } + + return (result); +} + #define MAX_RESTARTS 16 #define QUERY_ERROR(r) \ @@ -3698,6 +4848,99 @@ query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, return; } +#ifdef ALLOW_FILTER_AAAA_ON_V4 +static isc_boolean_t +is_v4_client(ns_client_t *client) { + if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) + return (ISC_TRUE); + if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr)) + return (ISC_TRUE); + return (ISC_FALSE); +} +#endif + +static isc_uint32_t +dns64_ttl(dns_db_t *db, dns_dbversion_t *version) { + dns_dbnode_t *node = NULL; + dns_rdata_soa_t soa; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_t rdataset; + isc_result_t result; + isc_uint32_t ttl = ISC_UINT32_MAX; + + result = dns_db_getoriginnode(db, &node); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, + 0, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) + goto cleanup; + result = dns_rdataset_first(&rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &soa, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + ttl = ISC_MIN(rdataset.ttl, soa.minimum); + +cleanup: + if (dns_rdataset_isassociated(&rdataset)) + dns_rdataset_disassociate(&rdataset); + if (node != NULL) + dns_db_detachnode(db, &node); + return (ttl); +} + +static isc_boolean_t +dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset) +{ + isc_netaddr_t netaddr; + dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64); + unsigned int flags = 0; + unsigned int i, count; + isc_boolean_t *aaaaok; + + INSIST(client->query.dns64_aaaaok == NULL); + INSIST(client->query.dns64_aaaaoklen == 0); + INSIST(client->query.dns64_aaaa == NULL); + INSIST(client->query.dns64_sigaaaa == NULL); + + if (dns64 == NULL) + return (ISC_TRUE); + + if (RECURSIONOK(client)) + flags |= DNS_DNS64_RECURSIVE; + + if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) + flags |= DNS_DNS64_DNSSEC; + + count = dns_rdataset_count(rdataset); + aaaaok = isc_mem_get(client->mctx, sizeof(isc_boolean_t) * count); + + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); + if (dns_dns64_aaaaok(dns64, &netaddr, client->signer, + &ns_g_server->aclenv, flags, rdataset, + aaaaok, count)) { + for (i = 0; i < count; i++) { + if (aaaaok != NULL && !aaaaok[i]) { + client->query.dns64_aaaaok = aaaaok; + client->query.dns64_aaaaoklen = count; + break; + } + } + if (i == count) + isc_mem_put(client->mctx, aaaaok, + sizeof(isc_boolean_t) * count); + return (ISC_TRUE); + } + isc_mem_put(client->mctx, aaaaok, sizeof(isc_boolean_t) * count); + return (ISC_FALSE); +} + /* * Do the bulk of query processing for the current query of 'client'. * If 'event' is non-NULL, we are returning from recursion and 'qtype' @@ -3716,6 +4959,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdatasetiter_t *rdsiter; isc_boolean_t want_restart, authoritative, is_zone, need_wildcardproof; + isc_boolean_t is_staticstub_zone; unsigned int n, nlabels; dns_namereln_t namereln; int order; @@ -3731,8 +4975,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) unsigned int options; isc_boolean_t empty_wild; dns_rdataset_t *noqname; + dns_rpz_st_t *rpz_st; isc_boolean_t resuming; int line = -1; + isc_boolean_t dns64_exclude, dns64; CTRACE("query_find"); @@ -3758,28 +5004,67 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) zone = NULL; need_wildcardproof = ISC_FALSE; empty_wild = ISC_FALSE; + dns64_exclude = dns64 = ISC_FALSE; options = 0; resuming = ISC_FALSE; is_zone = ISC_FALSE; + is_staticstub_zone = ISC_FALSE; if (event != NULL) { /* * We're returning from recursion. Restore the query context * and resume. */ - want_restart = ISC_FALSE; - authoritative = ISC_FALSE; - qtype = event->qtype; + rpz_st = client->query.rpz_st; + if (rpz_st != NULL && + (rpz_st->state & DNS_RPZ_RECURSING) != 0) { + is_zone = rpz_st->q.is_zone; + authoritative = rpz_st->q.authoritative; + zone = rpz_st->q.zone; + rpz_st->q.zone = NULL; + node = rpz_st->q.node; + rpz_st->q.node = NULL; + db = rpz_st->q.db; + rpz_st->q.db = NULL; + rdataset = rpz_st->q.rdataset; + rpz_st->q.rdataset = NULL; + sigrdataset = rpz_st->q.sigrdataset; + rpz_st->q.sigrdataset = NULL; + qtype = rpz_st->q.qtype; + + if (event->node != NULL) + dns_db_detachnode(db, &event->node); + rpz_st->ns.db = event->db; + rpz_st->ns.r_type = event->qtype; + rpz_st->ns.r_rdataset = event->rdataset; + if (event->sigrdataset != NULL && + dns_rdataset_isassociated(event->sigrdataset)) + dns_rdataset_disassociate(event->sigrdataset); + } else { + authoritative = ISC_FALSE; + + qtype = event->qtype; + db = event->db; + node = event->node; + rdataset = event->rdataset; + sigrdataset = event->sigrdataset; + } + if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig) type = dns_rdatatype_any; else type = qtype; - db = event->db; - node = event->node; - rdataset = event->rdataset; - sigrdataset = event->sigrdataset; + + if (DNS64(client)) { + client->query.attributes &= ~NS_QUERYATTR_DNS64; + dns64 = ISC_TRUE; + } + if (DNS64EXCLUDE(client)) { + client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE; + dns64_exclude = ISC_TRUE; + } /* * We'll need some resources... @@ -3794,16 +5079,26 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } - tname = dns_fixedname_name(&event->foundname); + if (rpz_st != NULL && + (rpz_st->state & DNS_RPZ_RECURSING) != 0) { + tname = rpz_st->fname; + } else { + tname = dns_fixedname_name(&event->foundname); + } result = dns_name_copy(tname, fname, NULL); if (result != ISC_R_SUCCESS) { QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } - - result = event->result; + if (rpz_st != NULL && + (rpz_st->state & DNS_RPZ_RECURSING) != 0) { + rpz_st->ns.r_result = event->result; + result = rpz_st->q.result; + isc_event_free(ISC_EVENT_PTR(&event)); + } else { + result = event->result; + } resuming = ISC_TRUE; - goto resume; } @@ -3902,8 +5197,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) goto cleanup; } - if (is_zone) + is_staticstub_zone = ISC_FALSE; + if (is_zone && zone != NULL) { authoritative = ISC_TRUE; + if (dns_zone_gettype(zone) == dns_zone_staticstub) + is_staticstub_zone = ISC_TRUE; + } if (event == NULL && client->query.restarts == 0) { if (is_zone) { @@ -3956,6 +5255,119 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) resume: CTRACE("query_find: resume"); + + if (!ISC_LIST_EMPTY(client->view->rpz_zones) && + RECURSIONOK(client) && !RECURSING(client) && + result != DNS_R_DELEGATION && result != ISC_R_NOTFOUND && + (client->query.rpz_st == NULL || + (client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) && + !dns_name_equal(client->query.qname, dns_rootname)) { + isc_result_t rresult; + + rresult = rpz_rewrite(client, qtype, resuming); + rpz_st = client->query.rpz_st; + switch (rresult) { + case ISC_R_SUCCESS: + break; + case DNS_R_DELEGATION: + /* + * recursing for NS names or addresses, + * so save the main query state + */ + rpz_st->q.qtype = qtype; + rpz_st->q.is_zone = is_zone; + rpz_st->q.authoritative = authoritative; + rpz_st->q.zone = zone; + zone = NULL; + rpz_st->q.db = db; + db = NULL; + rpz_st->q.node = node; + node = NULL; + rpz_st->q.rdataset = rdataset; + rdataset = NULL; + rpz_st->q.sigrdataset = sigrdataset; + sigrdataset = NULL; + dns_name_copy(fname, rpz_st->fname, NULL); + rpz_st->q.result = result; + client->query.attributes |= NS_QUERYATTR_RECURSING; + result = ISC_R_SUCCESS; + goto cleanup; + default: + RECURSE_ERROR(rresult); + goto cleanup; + } + if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS && + rpz_st->m.policy != DNS_RPZ_POLICY_NO_OP) { + result = dns_name_copy(client->query.qname, fname, + NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + finish_rewrite: + rpz_clean(&zone, &db, &node, NULL); + if (rpz_st->m.rdataset != NULL) { + if (rdataset != NULL) + query_putrdataset(client, &rdataset); + rdataset = rpz_st->m.rdataset; + rpz_st->m.rdataset = NULL; + } else if (rdataset != NULL && + dns_rdataset_isassociated(rdataset)) { + dns_rdataset_disassociate(rdataset); + } + node = rpz_st->m.node; + rpz_st->m.node = NULL; + db = rpz_st->m.db; + rpz_st->m.db = NULL; + zone = rpz_st->m.zone; + rpz_st->m.zone = NULL; + + result = rpz_st->m.result; + switch (rpz_st->m.policy) { + case DNS_RPZ_POLICY_NXDOMAIN: + result = DNS_R_NXDOMAIN; + break; + case DNS_RPZ_POLICY_NODATA: + result = DNS_R_NXRRSET; + break; + case DNS_RPZ_POLICY_RECORD: + if (type == dns_rdatatype_any && + result != DNS_R_CNAME && + dns_rdataset_isassociated(rdataset)) + dns_rdataset_disassociate(rdataset); + break; + case DNS_RPZ_POLICY_CNAME: + result = dns_name_copy(&rpz_st->m.rpz->cname, + fname, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + query_keepname(client, fname, dbuf); + result = query_add_cname(client, + client->query.qname, + fname, + dns_trust_authanswer, + rpz_st->m.ttl); + if (result != ISC_R_SUCCESS) + goto cleanup; + ns_client_qnamereplace(client, fname); + fname = NULL; + client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC; + rpz_log(client); + want_restart = ISC_TRUE; + goto cleanup; + default: + INSIST(0); + } + + /* + * Turn off DNSSEC because the results of a + * response policy zone cannot verify. + */ + client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC; + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) + dns_rdataset_disassociate(sigrdataset); + is_zone = ISC_TRUE; + rpz_log(client); + } + } + switch (result) { case ISC_R_SUCCESS: /* @@ -4008,11 +5420,18 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) */ if (RECURSIONOK(client)) { result = query_recurse(client, qtype, + client->query.qname, NULL, NULL, resuming); - if (result == ISC_R_SUCCESS) + if (result == ISC_R_SUCCESS) { client->query.attributes |= NS_QUERYATTR_RECURSING; - else + if (dns64) + client->query.attributes |= + NS_QUERYATTR_DNS64; + if (dns64_exclude) + client->query.attributes |= + NS_QUERYATTR_DNS64EXCLUDE; + } else RECURSE_ERROR(result); goto cleanup; } else { @@ -4143,12 +5562,22 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) } } else { if (zfname != NULL && - !dns_name_issubdomain(fname, zfname)) { + (!dns_name_issubdomain(fname, zfname) || + (is_staticstub_zone && + dns_name_equal(fname, zfname)))) { /* - * We've already got a delegation from - * authoritative data, and it is better - * than what we found in the cache. Use - * it instead of the cache delegation. + * In the following cases use "authoritative" + * data instead of the cache delegation: + * 1. We've already got a delegation from + * authoritative data, and it is better + * than what we found in the cache. + * 2. The query name matches the origin name + * of a static-stub zone. This needs to be + * considered for the case where the NS of + * the static-stub zone and the cached NS + * are different. We still need to contact + * the nameservers configured in the + * static-stub zone. */ query_releasename(client, &fname); fname = zfname; @@ -4183,15 +5612,31 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) */ if (dns_rdatatype_atparent(type)) result = query_recurse(client, qtype, - NULL, NULL, - resuming); + client->query.qname, + NULL, NULL, resuming); + else if (dns64) + result = query_recurse(client, + dns_rdatatype_a, + client->query.qname, + NULL, NULL, resuming); else result = query_recurse(client, qtype, - fname, rdataset, - resuming); - if (result == ISC_R_SUCCESS) + client->query.qname, + fname, rdataset, + resuming); + + if (result == ISC_R_SUCCESS) { client->query.attributes |= NS_QUERYATTR_RECURSING; + if (dns64) + client->query.attributes |= + NS_QUERYATTR_DNS64; + if (dns64_exclude) + client->query.attributes |= + NS_QUERYATTR_DNS64EXCLUDE; + } else if (result == DNS_R_DUPLICATE || + result == DNS_R_DROP) + QUERY_ERROR(result); else RECURSE_ERROR(result); } else { @@ -4231,11 +5676,75 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) } } goto cleanup; + case DNS_R_EMPTYNAME: - result = DNS_R_NXRRSET; - /* FALLTHROUGH */ case DNS_R_NXRRSET: + nxrrset: INSIST(is_zone); + +#ifdef dns64_bis_return_excluded_addresses + if (dns64) +#else + if (dns64 && !dns64_exclude) +#endif + { + /* + * Restore the answers from the previous AAAA lookup. + */ + if (rdataset != NULL) + query_putrdataset(client, &rdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); + rdataset = client->query.dns64_aaaa; + sigrdataset = client->query.dns64_sigaaaa; + if (fname == NULL) { + dbuf = query_getnamebuf(client); + if (dbuf == NULL) { + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + fname = query_newname(client, dbuf, &b); + if (fname == NULL) { + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + } + dns_name_copy(client->query.qname, fname, NULL); + client->query.dns64_aaaa = NULL; + client->query.dns64_sigaaaa = NULL; + dns64 = ISC_FALSE; +#ifdef dns64_bis_return_excluded_addresses + /* + * Resume the diverted processing of the AAAA response? + */ + if (dns64_excluded) + break; +#endif + } else if (result == DNS_R_NXRRSET && + !ISC_LIST_EMPTY(client->view->dns64) && + client->message->rdclass == dns_rdataclass_in && + qtype == dns_rdatatype_aaaa) + { + /* + * Look to see if there are A records for this + * name. + */ + INSIST(client->query.dns64_aaaa == NULL); + INSIST(client->query.dns64_sigaaaa == NULL); + client->query.dns64_aaaa = rdataset; + client->query.dns64_sigaaaa = sigrdataset; + client->query.dns64_ttl = dns64_ttl(db, version); + query_releasename(client, &fname); + dns_db_detachnode(db, &node); + rdataset = NULL; + sigrdataset = NULL; + type = qtype = dns_rdatatype_a; + dns64 = ISC_TRUE; + goto db_find; + } + + result = DNS_R_NXRRSET; + /* * Look for a NSEC3 record if we don't have a NSEC record. */ @@ -4258,10 +5767,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) * instead? If so add the nearest to the * closest provable encloser. */ - if (found && - dns_rdataset_isassociated(rdataset) && - !dns_name_equal(qname, found)) - { + if (dns_rdataset_isassociated(rdataset) && + !dns_name_equal(qname, found)) { unsigned int count; unsigned int skip; @@ -4328,7 +5835,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) /* * Add SOA. */ - result = query_addsoa(client, db, version, ISC_FALSE, + result = query_addsoa(client, db, version, ISC_UINT32_MAX, dns_rdataset_isassociated(rdataset)); if (result != ISC_R_SUCCESS) { QUERY_ERROR(result); @@ -4377,10 +5884,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) zone != NULL && #endif dns_zone_getzeronosoattl(zone)) - result = query_addsoa(client, db, version, ISC_TRUE, + result = query_addsoa(client, db, version, 0, dns_rdataset_isassociated(rdataset)); else - result = query_addsoa(client, db, version, ISC_FALSE, + result = query_addsoa(client, db, version, + ISC_UINT32_MAX, dns_rdataset_isassociated(rdataset)); if (result != ISC_R_SUCCESS) { QUERY_ERROR(result); @@ -4411,6 +5919,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) case DNS_R_NCACHENXDOMAIN: case DNS_R_NCACHENXRRSET: + ncache_nxrrset: INSIST(!is_zone); authoritative = ISC_FALSE; /* @@ -4426,6 +5935,74 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) client->message->rdclass == dns_rdataclass_in && dns_name_countlabels(fname) == 7) warn_rfc1918(client, fname, rdataset); + +#ifdef dns64_bis_return_excluded_addresses + if (dns64) +#else + if (dns64 && !dns64_exclude) +#endif + { + /* + * Restore the answers from the previous AAAA lookup. + */ + if (rdataset != NULL) + query_putrdataset(client, &rdataset); + if (sigrdataset != NULL) + query_putrdataset(client, &sigrdataset); + rdataset = client->query.dns64_aaaa; + sigrdataset = client->query.dns64_sigaaaa; + if (fname == NULL) { + dbuf = query_getnamebuf(client); + if (dbuf == NULL) { + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + fname = query_newname(client, dbuf, &b); + if (fname == NULL) { + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + } + dns_name_copy(client->query.qname, fname, NULL); + client->query.dns64_aaaa = NULL; + client->query.dns64_sigaaaa = NULL; + dns64 = ISC_FALSE; +#ifdef dns64_bis_return_excluded_addresses + if (dns64_excluded) + break; +#endif + } else if (result == DNS_R_NCACHENXRRSET && + !ISC_LIST_EMPTY(client->view->dns64) && + client->message->rdclass == dns_rdataclass_in && + qtype == dns_rdatatype_aaaa) + { + /* + * Look to see if there are A records for this + * name. + */ + INSIST(client->query.dns64_aaaa == NULL); + INSIST(client->query.dns64_sigaaaa == NULL); + client->query.dns64_aaaa = rdataset; + client->query.dns64_sigaaaa = sigrdataset; + /* + * If the ttl is zero we need to workout if we have just + * decremented to zero or if there was no negative cache + * ttl in the answer. + */ + if (rdataset->ttl != 0) + client->query.dns64_ttl = rdataset->ttl; + else if (dns_rdataset_first(rdataset) == ISC_R_SUCCESS) + client->query.dns64_ttl = 0; + query_releasename(client, &fname); + dns_db_detachnode(db, &node); + rdataset = NULL; + sigrdataset = NULL; + fname = NULL; + type = qtype = dns_rdatatype_a; + dns64 = ISC_TRUE; + goto db_find; + } + /* * We don't call query_addrrset() because we don't need any * of its extra features (and things would probably break!). @@ -4562,11 +6139,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_message_puttempname(client->message, &tname); goto cleanup; } - dns_name_init(tname, NULL); dns_name_clone(&dname.dname, tname); dns_rdata_freestruct(&dname); /* - * Construct the new qname. + * Construct the new qname consisting of + * <found name prefix>.<dname target> */ dns_fixedname_init(&fixed); prefix = dns_fixedname_name(&fixed); @@ -4583,8 +6160,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) goto cleanup; } result = dns_name_concatenate(prefix, tname, fname, NULL); + dns_message_puttempname(client->message, &tname); if (result != ISC_R_SUCCESS) { - dns_message_puttempname(client->message, &tname); if (result == ISC_R_NOSPACE) { /* * RFC2672, section 4.1, subsection 3c says @@ -4597,11 +6174,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) } query_keepname(client, fname, dbuf); /* - * Synthesize a CNAME for this DNAME. + * Synthesize a CNAME consisting of + * <old qname> <dname ttl> CNAME <new qname> + * with <dname trust value> * - * We want to synthesize a CNAME since if we don't - * then older software that doesn't understand DNAME - * will not chain like it should. + * Synthesize a CNAME so old old clients that don't understand + * DNAME can chain. * * We do not try to synthesize a signature because we hope * that security aware servers will understand DNAME. Also, @@ -4609,12 +6187,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) * on-the-fly is costly, and not really legitimate anyway * since the synthesized CNAME is NOT in the zone. */ - dns_name_init(tname, NULL); - (void)query_addcnamelike(client, client->query.qname, fname, - trdataset, &tname, - dns_rdatatype_cname); - if (tname != NULL) - dns_message_puttempname(client->message, &tname); + result = query_add_cname(client, client->query.qname, fname, + trdataset->trust, trdataset->ttl); + if (result != ISC_R_SUCCESS) + goto cleanup; /* * Switch to the new qname and restart. */ @@ -4641,6 +6217,28 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) } if (type == dns_rdatatype_any) { +#ifdef ALLOW_FILTER_AAAA_ON_V4 + isc_boolean_t have_aaaa, have_a, have_sig, filter_aaaa; + + /* + * The filter-aaaa-on-v4 option should + * suppress AAAAs for IPv4 clients if there is an A. + * If we are not authoritative, assume there is a A + * even in if it is not in our cache. This assumption could + * be wrong but it is a good bet. + */ + have_aaaa = ISC_FALSE; + have_a = !authoritative; + have_sig = ISC_FALSE; + if (client->view->v4_aaaa != dns_v4_aaaa_ok && + is_v4_client(client) && + ns_client_checkaclsilent(client, NULL, + client->view->v4_aaaa_acl, + ISC_TRUE) == ISC_R_SUCCESS) + filter_aaaa = ISC_TRUE; + else + filter_aaaa = ISC_FALSE; +#endif /* * XXXRTH Need to handle zonecuts with special case * code. @@ -4652,6 +6250,54 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } + + /* + * Check all A and AAAA records in all response policy + * IP address zones + */ + rpz_st = client->query.rpz_st; + if (rpz_st != NULL && + (rpz_st->state & DNS_RPZ_DONE_QNAME) != 0 && + (rpz_st->state & DNS_RPZ_REWRITTEN) == 0 && + RECURSIONOK(client) && !RECURSING(client) && + (rpz_st->state & DNS_RPZ_HAVE_IP) != 0) { + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) { + dns_rdatasetiter_current(rdsiter, rdataset); + if (rdataset->type == dns_rdatatype_a || + rdataset->type == dns_rdatatype_aaaa) + result = rpz_rewrite_ip(client, + rdataset, + DNS_RPZ_TYPE_IP); + dns_rdataset_disassociate(rdataset); + if (result != ISC_R_SUCCESS) + break; + } + if (result != ISC_R_NOMORE) { + dns_rdatasetiter_destroy(&rdsiter); + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + switch (rpz_st->m.policy) { + case DNS_RPZ_POLICY_MISS: + break; + case DNS_RPZ_POLICY_NO_OP: + rpz_log(client); + rpz_st->state |= DNS_RPZ_REWRITTEN; + break; + case DNS_RPZ_POLICY_NXDOMAIN: + case DNS_RPZ_POLICY_NODATA: + case DNS_RPZ_POLICY_RECORD: + case DNS_RPZ_POLICY_CNAME: + dns_rdatasetiter_destroy(&rdsiter); + rpz_st->state |= DNS_RPZ_REWRITTEN; + goto finish_rewrite; + default: + INSIST(0); + } + } + /* * Calling query_addrrset() with a non-NULL dbuf is going * to either keep or release the name. We don't want it to @@ -4668,6 +6314,18 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) result = dns_rdatasetiter_first(rdsiter); while (result == ISC_R_SUCCESS) { dns_rdatasetiter_current(rdsiter, rdataset); +#ifdef ALLOW_FILTER_AAAA_ON_V4 + /* + * Notice the presence of A and AAAAs so + * that AAAAs can be hidden from IPv4 clients. + */ + if (filter_aaaa) { + if (rdataset->type == dns_rdatatype_aaaa) + have_aaaa = ISC_TRUE; + else if (rdataset->type == dns_rdatatype_a) + have_a = ISC_TRUE; + } +#endif if (is_zone && qtype == dns_rdatatype_any && !dns_db_issecure(db) && dns_rdatatype_isdnssec(rdataset->type)) { @@ -4679,6 +6337,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_rdataset_disassociate(rdataset); } else if ((qtype == dns_rdatatype_any || rdataset->type == qtype) && rdataset->type != 0) { +#ifdef ALLOW_FILTER_AAAA_ON_V4 + if (dns_rdatatype_isdnssec(rdataset->type)) + have_sig = ISC_TRUE; +#endif if (NOQNAME(rdataset) && WANTDNSSEC(client)) noqname = rdataset; else @@ -4709,6 +6371,16 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) result = dns_rdatasetiter_next(rdsiter); } +#ifdef ALLOW_FILTER_AAAA_ON_V4 + /* + * Filter AAAAs if there is an A and there is no signature + * or we are supposed to break DNSSEC. + */ + if (filter_aaaa && have_aaaa && have_a && + (!have_sig || !WANTDNSSEC(client) || + client->view->v4_aaaa == dns_v4_aaaa_break_dnssec)) + client->attributes |= NS_CLIENTATTR_FILTER_AAAA; +#endif if (fname != NULL) dns_message_puttempname(client->message, &fname); @@ -4742,10 +6414,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_rdatasetiter_destroy(&rdsiter); if (RECURSIONOK(client)) { result = query_recurse(client, - qtype, - NULL, - NULL, - resuming); + qtype, + client->query.qname, + NULL, NULL, + resuming); if (result == ISC_R_SUCCESS) client->query.attributes |= NS_QUERYATTR_RECURSING; @@ -4763,7 +6435,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) * Add SOA. */ result = query_addsoa(client, db, version, - ISC_FALSE, ISC_FALSE); + ISC_UINT32_MAX, + ISC_FALSE); if (result == ISC_R_SUCCESS) result = ISC_R_NOMORE; } else { @@ -4783,6 +6456,162 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) * This is the "normal" case -- an ordinary question to which * we know the answer. */ + + /* + * Check all A and AAAA records in all response policy + * IP address zones + */ + rpz_st = client->query.rpz_st; + if (rpz_st != NULL && + (rpz_st->state & DNS_RPZ_DONE_QNAME) != 0 && + (rpz_st->state & DNS_RPZ_REWRITTEN) == 0 && + RECURSIONOK(client) && !RECURSING(client) && + (rpz_st->state & DNS_RPZ_HAVE_IP) != 0 && + (qtype == dns_rdatatype_aaaa || qtype == dns_rdatatype_a)) { + result = rpz_rewrite_ip(client, rdataset, + DNS_RPZ_TYPE_IP); + if (result != ISC_R_SUCCESS) { + QUERY_ERROR(DNS_R_SERVFAIL); + goto cleanup; + } + /* + * After a hit in the radix tree for the policy domain, + * either stop trying to rewrite (DNS_RPZ_POLICY_NO_OP) + * or restart to ask the ordinary database of the + * policy zone for the DNS record corresponding to the + * record in the radix tree. + */ + switch (rpz_st->m.policy) { + case DNS_RPZ_POLICY_MISS: + break; + case DNS_RPZ_POLICY_NO_OP: + rpz_log(client); + rpz_st->state |= DNS_RPZ_REWRITTEN; + break; + case DNS_RPZ_POLICY_NXDOMAIN: + case DNS_RPZ_POLICY_NODATA: + case DNS_RPZ_POLICY_RECORD: + case DNS_RPZ_POLICY_CNAME: + rpz_st->state |= DNS_RPZ_REWRITTEN; + goto finish_rewrite; + default: + INSIST(0); + } + } + +#ifdef ALLOW_FILTER_AAAA_ON_V4 + /* + * Optionally hide AAAAs from IPv4 clients if there is an A. + * We add the AAAAs now, but might refuse to render them later + * after DNSSEC is figured out. + * This could be more efficient, but the whole idea is + * so fundamentally wrong, unavoidably inaccurate, and + * unneeded that it is best to keep it as short as possible. + */ + if (client->view->v4_aaaa != dns_v4_aaaa_ok && + is_v4_client(client) && + ns_client_checkaclsilent(client, NULL, + client->view->v4_aaaa_acl, + ISC_TRUE) == ISC_R_SUCCESS && + (!WANTDNSSEC(client) || + sigrdataset == NULL || + !dns_rdataset_isassociated(sigrdataset) || + client->view->v4_aaaa == dns_v4_aaaa_break_dnssec)) { + if (qtype == dns_rdatatype_aaaa) { + trdataset = query_newrdataset(client); + result = dns_db_findrdataset(db, node, version, + dns_rdatatype_a, 0, + client->now, + trdataset, NULL); + if (dns_rdataset_isassociated(trdataset)) + dns_rdataset_disassociate(trdataset); + query_putrdataset(client, &trdataset); + + /* + * We have an AAAA but the A is not in our cache. + * Assume any result other than DNS_R_DELEGATION + * or ISC_R_NOTFOUND means there is no A and + * so AAAAs are ok. + * Assume there is no A if we can't recurse + * for this client, although that could be + * the wrong answer. What else can we do? + * Besides, that we have the AAAA and are using + * this mechanism suggests that we care more + * about As than AAAAs and would have cached + * the A if it existed. + */ + if (result == ISC_R_SUCCESS) { + client->attributes |= + NS_CLIENTATTR_FILTER_AAAA; + + } else if (authoritative || + !RECURSIONOK(client) || + (result != DNS_R_DELEGATION && + result != ISC_R_NOTFOUND)) { + client->attributes &= + ~NS_CLIENTATTR_FILTER_AAAA; + } else { + /* + * This is an ugly kludge to recurse + * for the A and discard the result. + * + * Continue to add the AAAA now. + * We'll make a note to not render it + * if the recursion for the A succeeds. + */ + result = query_recurse(client, + dns_rdatatype_a, + client->query.qname, + NULL, NULL, resuming); + if (result == ISC_R_SUCCESS) { + client->attributes |= + NS_CLIENTATTR_FILTER_AAAA_RC; + client->query.attributes |= + NS_QUERYATTR_RECURSING; + } + } + + } else if (qtype == dns_rdatatype_a && + (client->attributes & + NS_CLIENTATTR_FILTER_AAAA_RC) != 0) { + client->attributes &= + ~NS_CLIENTATTR_FILTER_AAAA_RC; + client->attributes |= + NS_CLIENTATTR_FILTER_AAAA; + dns_rdataset_disassociate(rdataset); + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) + dns_rdataset_disassociate(sigrdataset); + goto cleanup; + } + } +#endif + /* + * Check to see if the AAAA RRset has non-excluded addresses + * in it. If not look for a A RRset. + */ + INSIST(client->query.dns64_aaaaok == NULL); + + if (qtype == dns_rdatatype_aaaa && !dns64_exclude && + !ISC_LIST_EMPTY(client->view->dns64) && + client->message->rdclass == dns_rdataclass_in && + !dns64_aaaaok(client, rdataset, sigrdataset)) { + /* + * Look to see if there are A records for this + * name. + */ + client->query.dns64_aaaa = rdataset; + client->query.dns64_sigaaaa = sigrdataset; + client->query.dns64_ttl = rdataset->ttl; + query_releasename(client, &fname); + dns_db_detachnode(db, &node); + rdataset = NULL; + sigrdataset = NULL; + type = qtype = dns_rdatatype_a; + dns64_exclude = dns64 = ISC_TRUE; + goto db_find; + } + if (sigrdataset != NULL) sigrdatasetp = &sigrdataset; else @@ -4798,8 +6627,43 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) dns_name_equal(client->query.qname, dns_rootname)) client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL; - query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf, - DNS_SECTION_ANSWER); + if (dns64) { + qtype = type = dns_rdatatype_aaaa; + result = query_dns64(client, &fname, rdataset, + sigrdataset, dbuf, + DNS_SECTION_ANSWER); + dns_rdataset_disassociate(rdataset); + dns_message_puttemprdataset(client->message, &rdataset); + if (result == ISC_R_NOMORE) { +#ifndef dns64_bis_return_excluded_addresses + if (dns64_exclude) { + if (!is_zone) + goto cleanup; + /* + * Add a fake SOA record. + */ + result = query_addsoa(client, db, + version, 600, + ISC_FALSE); + goto cleanup; + } +#endif + if (is_zone) + goto nxrrset; + else + goto ncache_nxrrset; + } else if (result != ISC_R_SUCCESS) { + eresult = result; + goto cleanup; + } + } else if (client->query.dns64_aaaaok != NULL) { + query_filter64(client, &fname, rdataset, dbuf, + DNS_SECTION_ANSWER); + query_putrdataset(client, &rdataset); + } else + query_addrrset(client, &fname, &rdataset, + sigrdatasetp, dbuf, DNS_SECTION_ANSWER); + if (noqname != NULL) query_addnoqnameproof(client, noqname); /* @@ -4842,6 +6706,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) /* * General cleanup. */ + rpz_st = client->query.rpz_st; + if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) == 0) + rpz_clean(&rpz_st->m.zone, &rpz_st->m.db, &rpz_st->m.node, + &rpz_st->m.rdataset); if (rdataset != NULL) query_putrdataset(client, &rdataset); if (sigrdataset != NULL) @@ -4949,6 +6817,7 @@ log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) { char namebuf[DNS_NAME_FORMATSIZE]; char typename[DNS_RDATATYPE_FORMATSIZE]; char classname[DNS_RDATACLASS_FORMATSIZE]; + char onbuf[ISC_NETADDR_FORMATSIZE]; dns_rdataset_t *rdataset; int level = ISC_LOG_INFO; @@ -4960,14 +6829,18 @@ log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) { dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname)); dns_rdatatype_format(rdataset->type, typename, sizeof(typename)); + isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf)); ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY, - level, "query: %s %s %s %s%s%s%s%s", namebuf, classname, - typename, WANTRECURSION(client) ? "+" : "-", + level, "query: %s %s %s %s%s%s%s%s%s (%s)", namebuf, + classname, typename, WANTRECURSION(client) ? "+" : "-", (client->signer != NULL) ? "S": "", (client->opt != NULL) ? "E" : "", + ((client->attributes & NS_CLIENTATTR_TCP) != 0) ? + "T" : "", ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "", - ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : ""); + ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "", + onbuf); } static inline void diff --git a/contrib/bind9/bin/named/server.c b/contrib/bind9/bin/named/server.c index bc7fc17c3296..5bbf94b9b604 100644 --- a/contrib/bind9/bin/named/server.c +++ b/contrib/bind9/bin/named/server.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.520.12.21 2011-01-14 23:45:49 tbox Exp $ */ +/* $Id: server.c,v 1.599.8.4 2011-02-16 19:46:12 each Exp $ */ /*! \file */ @@ -23,6 +23,10 @@ #include <stdlib.h> #include <unistd.h> +#include <limits.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> #include <isc/app.h> #include <isc/base64.h> @@ -36,7 +40,9 @@ #include <isc/portset.h> #include <isc/print.h> #include <isc/resource.h> +#include <isc/sha2.h> #include <isc/socket.h> +#include <isc/stat.h> #include <isc/stats.h> #include <isc/stdio.h> #include <isc/string.h> @@ -57,9 +63,11 @@ #ifdef DLZ #include <dns/dlz.h> #endif +#include <dns/dns64.h> #include <dns/forward.h> #include <dns/journal.h> #include <dns/keytable.h> +#include <dns/keyvalues.h> #include <dns/lib.h> #include <dns/master.h> #include <dns/masterdump.h> @@ -102,6 +110,10 @@ #include <stdlib.h> #endif +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + /*% * Check an operation for failure. Assumes that the function * using it has a 'result' variable and a 'cleanup' label. @@ -143,6 +155,14 @@ fatal(msg, result); \ } while (0) \ +/*% + * Maximum ADB size for views that share a cache. Use this limit to suppress + * the total of memory footprint, which should be the main reason for sharing + * a cache. Only effective when a finite max-cache-size is specified. + * This is currently defined to be 8MB. + */ +#define MAX_ADB_SIZE_FOR_CACHESHARE 8388608 + struct ns_dispatch { isc_sockaddr_t addr; unsigned int dispatchgen; @@ -150,6 +170,14 @@ struct ns_dispatch { ISC_LINK(struct ns_dispatch) link; }; +struct ns_cache { + dns_cache_t *cache; + dns_view_t *primaryview; + isc_boolean_t needflush; + isc_boolean_t adbsizeadjusted; + ISC_LINK(ns_cache_t) link; +}; + struct dumpcontext { isc_mem_t *mctx; isc_boolean_t dumpcache; @@ -176,6 +204,17 @@ struct zonelistentry { ISC_LINK(struct zonelistentry) link; }; +/*% + * Configuration context to retain for each view that allows + * new zones to be added at runtime + */ +struct cfg_context { + isc_mem_t * mctx; + cfg_obj_t * config; + cfg_parser_t * parser; + cfg_aclconfctx_t actx; +}; + /* * These zones should not leak onto the Internet. */ @@ -230,8 +269,8 @@ static const struct { { NULL, ISC_FALSE } }; -static void -fatal(const char *msg, isc_result_t result); +ISC_PLATFORM_NORETURN_PRE static void +fatal(const char *msg, isc_result_t result) ISC_PLATFORM_NORETURN_POST; static void ns_server_reload(isc_task_t *task, isc_event_t *event); @@ -256,19 +295,25 @@ configure_alternates(const cfg_obj_t *config, dns_view_t *view, static isc_result_t configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, - cfg_aclconfctx_t *aclconf); + cfg_aclconfctx_t *aclconf, isc_boolean_t added); + +static isc_result_t +add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); static void end_reserved_dispatches(ns_server_t *server, isc_boolean_t all); +static void +cfgctx_destroy(void **cfgp); + /*% * Configure a single view ACL at '*aclp'. Get its configuration from * 'vconfig' (for per-view configuration) and maybe from 'config' */ static isc_result_t configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, - const char *aclname, cfg_aclconfctx_t *actx, - isc_mem_t *mctx, dns_acl_t **aclp) + const char *aclname, const char *acltuplename, + cfg_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp) { isc_result_t result; const cfg_obj_t *maps[3]; @@ -294,13 +339,21 @@ configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, */ return (ISC_R_SUCCESS); + if (acltuplename != NULL) { + /* + * If the ACL is given in an optional tuple, retrieve it. + * The parser should have ensured that a valid object be + * returned. + */ + aclobj = cfg_tuple_get(aclobj, acltuplename); + } + result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx, mctx, 0, aclp); return (result); } - /*% * Configure a sortlist at '*aclp'. Essentially the same as * configure_view_acl() except it calls cfg_acl_fromconfig with a @@ -345,8 +398,88 @@ configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config, } static isc_result_t -configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, - dns_keytable_t *keytable, isc_mem_t *mctx) +configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, + const char *confname, const char *conftuplename, + isc_mem_t *mctx, dns_rbt_t **rbtp) +{ + isc_result_t result; + const cfg_obj_t *maps[3]; + const cfg_obj_t *obj = NULL; + const cfg_listelt_t *element; + int i = 0; + dns_fixedname_t fixed; + dns_name_t *name; + isc_buffer_t b; + const char *str; + const cfg_obj_t *nameobj; + + if (*rbtp != NULL) + dns_rbt_destroy(rbtp); + if (vconfig != NULL) + maps[i++] = cfg_tuple_get(vconfig, "options"); + if (config != NULL) { + const cfg_obj_t *options = NULL; + (void)cfg_map_get(config, "options", &options); + if (options != NULL) + maps[i++] = options; + } + maps[i] = NULL; + + (void)ns_config_get(maps, confname, &obj); + if (obj == NULL) + /* + * No value available. *rbtp == NULL. + */ + return (ISC_R_SUCCESS); + + if (conftuplename != NULL) { + obj = cfg_tuple_get(obj, conftuplename); + if (cfg_obj_isvoid(obj)) + return (ISC_R_SUCCESS); + } + + result = dns_rbt_create(mctx, NULL, NULL, rbtp); + if (result != ISC_R_SUCCESS) + return (result); + + dns_fixedname_init(&fixed); + name = dns_fixedname_name(&fixed); + for (element = cfg_list_first(obj); + element != NULL; + element = cfg_list_next(element)) { + nameobj = cfg_listelt_value(element); + str = cfg_obj_asstring(nameobj); + isc_buffer_init(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + /* + * We don't need the node data, but need to set dummy data to + * avoid a partial match with an empty node. For example, if + * we have foo.example.com and bar.example.com, we'd get a match + * for baz.example.com, which is not the expected result. + * We simply use (void *)1 as the dummy data. + */ + result = dns_rbt_addname(*rbtp, name, (void *)1); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(nameobj, ns_g_lctx, ISC_LOG_ERROR, + "failed to add %s for %s: %s", + str, confname, isc_result_totext(result)); + goto cleanup; + } + + } + + return (result); + + cleanup: + dns_rbt_destroy(rbtp); + return (result); + +} + +static isc_result_t +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; @@ -363,12 +496,28 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, isc_result_t result; dst_key_t *dstkey = NULL; + INSIST(target != NULL && *target == NULL); + flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); keyname = dns_fixedname_name(&fkeyname); keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); + if (managed) { + const char *initmethod; + initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init")); + + if (strcasecmp(initmethod, "initial-key") != 0) { + cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, + "managed key '%s': " + "invalid initialization method '%s'", + keynamestr, initmethod); + result = ISC_R_FAILURE; + goto cleanup; + } + } + if (vconfig == NULL) viewclass = dns_rdataclass_in; else { @@ -408,7 +557,8 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, keystruct.algorithm == DST_ALG_RSAMD5) && r.length > 1 && r.base[0] == 1 && r.base[1] == 3) cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, - "trusted key '%s' has a weak exponent", + "%s key '%s' has a weak exponent", + managed ? "managed" : "trusted", keynamestr); CHECK(dns_rdata_fromstruct(NULL, @@ -418,25 +568,28 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, dns_fixedname_init(&fkeyname); isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr)); isc_buffer_add(&namebuf, strlen(keynamestr)); - CHECK(dns_name_fromtext(keyname, &namebuf, - dns_rootname, ISC_FALSE, - NULL)); + CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, 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 if (result == DST_R_UNSUPPORTEDALG) { + cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, + "skipping %s key for '%s': %s", + managed ? "managed" : "trusted", + keynamestr, isc_result_totext(result)); } 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; } @@ -447,63 +600,215 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, return (result); } +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, + dns_name_t *keyname, isc_mem_t *mctx) +{ + const cfg_listelt_t *elt, *elt2; + const cfg_obj_t *key, *keylist; + dst_key_t *dstkey = NULL; + isc_result_t result; + dns_keytable_t *secroots = NULL; + + CHECK(dns_view_getsecroots(view, &secroots)); + + for (elt = cfg_list_first(keys); + elt != NULL; + elt = cfg_list_next(elt)) { + keylist = cfg_listelt_value(elt); + + for (elt2 = cfg_list_first(keylist); + elt2 != NULL; + elt2 = cfg_list_next(elt2)) { + key = cfg_listelt_value(elt2); + result = dstkey_fromconfig(vconfig, key, managed, + &dstkey, mctx); + if (result == DST_R_UNSUPPORTEDALG) { + result = ISC_R_SUCCESS; + continue; + } + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* + * If keyname was specified, we only add that key. + */ + if (keyname != NULL && + !dns_name_equal(keyname, dst_key_name(dstkey))) + { + dst_key_free(&dstkey); + continue; + } + + CHECK(dns_keytable_add(secroots, managed, &dstkey)); + } + } + + cleanup: + if (dstkey != NULL) + dst_key_free(&dstkey); + if (secroots != NULL) + dns_keytable_detach(&secroots); + if (result == DST_R_NOCRYPTO) + result = ISC_R_SUCCESS; + 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, - 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_boolean_t auto_root, + isc_mem_t *mctx) { - isc_result_t result; - const cfg_obj_t *keys = NULL; + 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 *view_managed_keys = NULL; + const cfg_obj_t *global_managed_keys = NULL; + const cfg_obj_t *maps[4]; const cfg_obj_t *voptions = NULL; - const cfg_listelt_t *element, *element2; - const cfg_obj_t *keylist; - const cfg_obj_t *key; - dns_keytable_t *keytable = NULL; + const cfg_obj_t *options = NULL; + const cfg_obj_t *obj = NULL; + const char *directory; + 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->rdclass == dns_rdataclass_chaos) { + return (ISC_R_SUCCESS); + } - if (vconfig != NULL) + 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, "managed-keys", + &view_managed_keys); + maps[i++] = voptions; + } + } - keys = NULL; - if (voptions != NULL) - (void)cfg_map_get(voptions, "trusted-keys", &keys); - if (keys == NULL) - (void)cfg_map_get(config, "trusted-keys", &keys); + 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; + } + } - for (element = cfg_list_first(keys); - element != NULL; - element = cfg_list_next(element)) - { - keylist = cfg_listelt_value(element); - for (element2 = cfg_list_first(keylist); - element2 != NULL; - element2 = cfg_list_next(element2)) - { - key = cfg_listelt_value(element2); - CHECK(configure_view_dnsseckey(vconfig, key, - keytable, mctx)); + maps[i++] = ns_g_defaults; + maps[i] = NULL; + + result = dns_view_initsecroots(view, mctx); + 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 (auto_dlv && view->rdclass == dns_rdataclass_in) { + const cfg_obj_t *builtin_keys = NULL; + const cfg_obj_t *builtin_managed_keys = NULL; + + isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_SERVER, ISC_LOG_WARNING, + "using built-in DLV key for view %s", + view->name); + + /* + * If bind.keys exists, it overrides the managed-keys + * clause hard-coded in ns_g_config. + */ + if (bindkeys != NULL) { + (void)cfg_map_get(bindkeys, "trusted-keys", + &builtin_keys); + (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_keys != NULL) + CHECK(load_view_keys(builtin_keys, vconfig, view, + ISC_FALSE, view->dlv, mctx)); + if (builtin_managed_keys != NULL) + CHECK(load_view_keys(builtin_managed_keys, vconfig, + view, ISC_TRUE, view->dlv, mctx)); } - dns_keytable_detach(target); - *target = keytable; /* Transfer ownership. */ - keytable = NULL; - result = ISC_R_SUCCESS; + if (auto_root && view->rdclass == dns_rdataclass_in) { + const cfg_obj_t *builtin_keys = NULL; + const cfg_obj_t *builtin_managed_keys = NULL; - cleanup: + isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_SERVER, ISC_LOG_WARNING, + "using built-in root key for view %s", + view->name); + + /* + * If bind.keys exists, it overrides the managed-keys + * clause hard-coded in ns_g_config. + */ + if (bindkeys != NULL) { + (void)cfg_map_get(bindkeys, "trusted-keys", + &builtin_keys); + (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_keys != NULL) + CHECK(load_view_keys(builtin_keys, vconfig, view, + ISC_FALSE, dns_rootname, mctx)); + if (builtin_managed_keys != NULL) + CHECK(load_view_keys(builtin_managed_keys, vconfig, + view, ISC_TRUE, dns_rootname, + mctx)); + } + + CHECK(load_view_keys(view_keys, vconfig, view, ISC_FALSE, + NULL, mctx)); + CHECK(load_view_keys(view_managed_keys, vconfig, view, ISC_TRUE, + NULL, mctx)); + + if (view->rdclass == dns_rdataclass_in) { + CHECK(load_view_keys(global_keys, vconfig, view, ISC_FALSE, + NULL, mctx)); + CHECK(load_view_keys(global_managed_keys, vconfig, view, + ISC_TRUE, NULL, mctx)); + } + + /* + * Add key zone for managed-keys. + */ + obj = NULL; + (void)ns_config_get(maps, "managed-keys-directory", &obj); + directory = obj != NULL ? cfg_obj_asstring(obj) : NULL; + CHECK(add_keydata_zone(view, directory, ns_g_mctx)); + + cleanup: return (result); } static isc_result_t -mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) -{ +mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) { const cfg_listelt_t *element; const cfg_obj_t *obj; const char *str; @@ -523,8 +828,7 @@ mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - CHECK(dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); CHECK(dns_resolver_setmustbesecure(resolver, name, value)); } @@ -684,7 +988,7 @@ configure_order(dns_order_t *order, const cfg_obj_t *ent) { isc_buffer_add(&b, strlen(str)); dns_fixedname_init(&fixed); result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); @@ -868,7 +1172,7 @@ disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); algorithms = cfg_tuple_get(disabled, "algorithms"); for (element = cfg_list_first(algorithms); @@ -921,7 +1225,7 @@ on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(name, &b, dns_rootname, - ISC_TRUE, NULL); + 0, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); if (dns_name_equal(name, zonename)) return (ISC_TRUE); @@ -979,6 +1283,20 @@ setquerystats(dns_zone_t *zone, isc_mem_t *mctx, isc_boolean_t on) { return (ISC_R_SUCCESS); } +static ns_cache_t * +cachelist_find(ns_cachelist_t *cachelist, const char *cachename) { + ns_cache_t *nsc; + + for (nsc = ISC_LIST_HEAD(*cachelist); + nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) { + if (strcmp(dns_cache_getname(nsc->cache), cachename) == 0) + return (nsc); + } + + return (NULL); +} + static isc_boolean_t cache_reusable(dns_view_t *originview, dns_view_t *view, isc_boolean_t new_zero_no_soattl) @@ -996,6 +1314,238 @@ cache_reusable(dns_view_t *originview, dns_view_t *view, return (ISC_TRUE); } +static isc_boolean_t +cache_sharable(dns_view_t *originview, dns_view_t *view, + isc_boolean_t new_zero_no_soattl, + unsigned int new_cleaning_interval, + isc_uint32_t new_max_cache_size) +{ + /* + * If the cache cannot even reused for the same view, it cannot be + * shared with other views. + */ + if (!cache_reusable(originview, view, new_zero_no_soattl)) + return (ISC_FALSE); + + /* + * Check other cache related parameters that must be consistent among + * the sharing views. + */ + if (dns_cache_getcleaninginterval(originview->cache) != + new_cleaning_interval || + dns_cache_getcachesize(originview->cache) != new_max_cache_size) { + return (ISC_FALSE); + } + + return (ISC_TRUE); +} + +#ifdef DLZ +/* + * Callback from DLZ configure when the driver sets up a writeable zone + */ +static isc_result_t +dlzconfigure_callback(dns_view_t *view, dns_zone_t *zone) { + dns_name_t *origin = dns_zone_getorigin(zone); + dns_rdataclass_t zclass = view->rdclass; + isc_result_t result; + + result = dns_zonemgr_managezone(ns_g_server->zonemgr, zone); + if (result != ISC_R_SUCCESS) + return result; + dns_zone_setstats(zone, ns_g_server->zonestats); + + return ns_zone_configure_writeable_dlz(view->dlzdatabase, + zone, zclass, origin); +} +#endif + +static isc_result_t +dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na, + unsigned int prefixlen, const char *server, + const char *contact) +{ + char *cp; + char reverse[48+sizeof("ip6.arpa.")]; + const char *dns64_dbtype[4] = { "_builtin", "dns64", ".", "." }; + const char *sep = ": view "; + const char *viewname = view->name; + const unsigned char *s6; + dns_fixedname_t fixed; + dns_name_t *name; + dns_zone_t *zone = NULL; + int dns64_dbtypec = 4; + isc_buffer_t b; + isc_result_t result; + + REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 || + prefixlen == 56 || prefixlen == 64 || prefixlen == 96); + + if (!strcmp(viewname, "_default")) { + sep = ""; + viewname = ""; + } + + /* + * Construct the reverse name of the zone. + */ + cp = reverse; + s6 = na->type.in6.s6_addr; + while (prefixlen > 0) { + prefixlen -= 8; + sprintf(cp, "%x.%x.", s6[prefixlen/8] & 0xf, + (s6[prefixlen/8] >> 4) & 0xf); + cp += 4; + } + strcat(cp, "ip6.arpa."); + + /* + * Create the actual zone. + */ + if (server != NULL) + dns64_dbtype[2] = server; + if (contact != NULL) + dns64_dbtype[3] = contact; + dns_fixedname_init(&fixed); + name = dns_fixedname_name(&fixed); + isc_buffer_init(&b, reverse, strlen(reverse)); + isc_buffer_add(&b, strlen(reverse)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + CHECK(dns_zone_create(&zone, mctx)); + CHECK(dns_zone_setorigin(zone, name)); + dns_zone_setview(zone, view); + CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); + dns_zone_setclass(zone, view->rdclass); + dns_zone_settype(zone, dns_zone_master); + dns_zone_setstats(zone, ns_g_server->zonestats); + CHECK(dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype)); + if (view->queryacl != NULL) + dns_zone_setqueryacl(zone, view->queryacl); + if (view->queryonacl != NULL) + dns_zone_setqueryonacl(zone, view->queryonacl); + dns_zone_setdialup(zone, dns_dialuptype_no); + dns_zone_setnotifytype(zone, dns_notifytype_no); + dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE); + CHECK(setquerystats(zone, mctx, ISC_FALSE)); /* XXXMPA */ + CHECK(dns_view_addzone(view, zone)); + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_INFO, "dns64 reverse zone%s%s: %s", sep, + viewname, reverse); + +cleanup: + if (zone != NULL) + dns_zone_detach(&zone); + return (result); +} + +static isc_result_t +configure_rpz(dns_view_t *view, const cfg_listelt_t *element) { + const cfg_obj_t *rpz_obj, *policy_obj; + const char *str; + dns_fixedname_t fixed; + dns_name_t *origin; + dns_rpz_zone_t *old, *new; + dns_zone_t *zone = NULL; + isc_result_t result; + unsigned int l1, l2; + + new = isc_mem_get(view->mctx, sizeof(*new)); + if (new == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + + memset(new, 0, sizeof(*new)); + dns_name_init(&new->nsdname, NULL); + dns_name_init(&new->origin, NULL); + dns_name_init(&new->cname, NULL); + ISC_LIST_INITANDAPPEND(view->rpz_zones, new, link); + + rpz_obj = cfg_listelt_value(element); + policy_obj = cfg_tuple_get(rpz_obj, "policy"); + if (cfg_obj_isvoid(policy_obj)) { + new->policy = DNS_RPZ_POLICY_GIVEN; + } else { + str = cfg_obj_asstring(policy_obj); + new->policy = dns_rpz_str2policy(str); + INSIST(new->policy != DNS_RPZ_POLICY_ERROR); + } + + dns_fixedname_init(&fixed); + origin = dns_fixedname_name(&fixed); + str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "name")); + result = dns_name_fromstring(origin, str, DNS_NAME_DOWNCASE, NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "invalid zone '%s'", str); + goto cleanup; + } + + result = dns_name_fromstring2(&new->nsdname, DNS_RPZ_NSDNAME_ZONE, + origin, DNS_NAME_DOWNCASE, view->mctx); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "invalid zone '%s'", str); + goto cleanup; + } + + /* + * The origin is part of 'nsdname' so we don't need to keep it + * seperately. + */ + l1 = dns_name_countlabels(&new->nsdname); + l2 = dns_name_countlabels(origin); + dns_name_getlabelsequence(&new->nsdname, l1 - l2, l2, &new->origin); + + /* + * Are we configured to with the reponse policy zone? + */ + result = dns_view_findzone(view, &new->origin, &zone); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "unknown zone '%s'", str); + goto cleanup; + } + + if (dns_zone_gettype(zone) != dns_zone_master && + dns_zone_gettype(zone) != dns_zone_slave) { + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "zone '%s' is neither master nor slave", str); + dns_zone_detach(&zone); + result = DNS_R_NOTMASTER; + goto cleanup; + } + dns_zone_detach(&zone); + + for (old = ISC_LIST_HEAD(view->rpz_zones); + old != new; + old = ISC_LIST_NEXT(old, link)) { + ++new->num; + if (dns_name_equal(&old->origin, &new->origin)) { + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "duplicate '%s'", str); + result = DNS_R_DUPLICATE; + goto cleanup; + } + } + + if (new->policy == DNS_RPZ_POLICY_CNAME) { + str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "cname")); + result = dns_name_fromstring(&new->cname, str, 0, view->mctx); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "invalid cname '%s'", str); + goto cleanup; + } + } + + return (ISC_R_SUCCESS); + + cleanup: + dns_rpz_view_destroy(view); + return (result); +} + /* * Configure 'view' according to 'vconfig', taking defaults from 'config' * where values are missing in 'vconfig'. @@ -1004,12 +1554,15 @@ cache_reusable(dns_view_t *originview, dns_view_t *view, * global defaults in 'config' used exclusively. */ static isc_result_t -configure_view(dns_view_t *view, const cfg_obj_t *config, - const cfg_obj_t *vconfig, isc_mem_t *mctx, - cfg_aclconfctx_t *actx, isc_boolean_t need_hints) +configure_view(dns_view_t *view, cfg_parser_t* parser, + cfg_obj_t *config, cfg_obj_t *vconfig, + ns_cachelist_t *cachelist, const cfg_obj_t *bindkeys, + isc_mem_t *mctx, cfg_aclconfctx_t *actx, + isc_boolean_t need_hints) { const cfg_obj_t *maps[4]; const cfg_obj_t *cfgmaps[3]; + const cfg_obj_t *optionmaps[3]; const cfg_obj_t *options = NULL; const cfg_obj_t *voptions = NULL; const cfg_obj_t *forwardtype; @@ -1028,17 +1581,20 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, dns_cache_t *cache = NULL; isc_result_t result; isc_uint32_t max_adb_size; + unsigned int cleaning_interval; isc_uint32_t max_cache_size; isc_uint32_t max_acache_size; isc_uint32_t lame_ttl; - dns_tsig_keyring_t *ring; + dns_tsig_keyring_t *ring = NULL; dns_view_t *pview = NULL; /* Production view */ isc_mem_t *cmctx; dns_dispatch_t *dispatch4 = NULL; dns_dispatch_t *dispatch6 = NULL; isc_boolean_t reused_cache = ISC_FALSE; - int i; + isc_boolean_t shared_cache = ISC_FALSE; + int i = 0, j = 0, k = 0; const char *str; + const char *cachename = NULL; dns_order_t *order = NULL; isc_uint32_t udpsize; unsigned int resopts = 0; @@ -1052,7 +1608,14 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, const cfg_obj_t *disablelist = NULL; isc_stats_t *resstats = NULL; dns_stats_t *resquerystats = NULL; + isc_boolean_t auto_dlv = ISC_FALSE; + isc_boolean_t auto_root = ISC_FALSE; + ns_cache_t *nsc; isc_boolean_t zero_no_soattl; + cfg_parser_t *newzones_parser = NULL; + cfg_obj_t *nzfconf = NULL; + dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; + unsigned int query_timeout; REQUIRE(DNS_VIEW_VALID(view)); @@ -1061,22 +1624,28 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, if (config != NULL) (void)cfg_map_get(config, "options", &options); - i = 0; + /* + * maps: view options, options, defaults + * cfgmaps: view options, config + * optionmaps: view options, options + */ if (vconfig != NULL) { voptions = cfg_tuple_get(vconfig, "options"); maps[i++] = voptions; + optionmaps[j++] = voptions; + cfgmaps[k++] = voptions; } - if (options != NULL) + if (options != NULL) { maps[i++] = options; + optionmaps[j++] = options; + } + maps[i++] = ns_g_defaults; maps[i] = NULL; - - i = 0; - if (voptions != NULL) - cfgmaps[i++] = voptions; + optionmaps[j] = NULL; if (config != NULL) - cfgmaps[i++] = config; - cfgmaps[i] = NULL; + cfgmaps[k++] = config; + cfgmaps[k] = NULL; if (!strcmp(viewname, "_default")) { sep = ""; @@ -1137,12 +1706,12 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, dns_acache_setcachesize(view->acache, max_acache_size); } - CHECK(configure_view_acl(vconfig, config, "allow-query", actx, + CHECK(configure_view_acl(vconfig, config, "allow-query", NULL, actx, ns_g_mctx, &view->queryacl)); - if (view->queryacl == NULL) { - CHECK(configure_view_acl(NULL, ns_g_config, "allow-query", actx, - ns_g_mctx, &view->queryacl)); + CHECK(configure_view_acl(NULL, ns_g_config, "allow-query", + NULL, actx, ns_g_mctx, + &view->queryacl)); } /* @@ -1159,7 +1728,62 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, { const cfg_obj_t *zconfig = cfg_listelt_value(element); CHECK(configure_zone(config, zconfig, vconfig, mctx, view, - actx)); + actx, ISC_FALSE)); + } + + /* + * Are we allowing zones to be added and deleted dynamically? + */ + obj = NULL; + result = ns_config_get(maps, "allow-new-zones", &obj); + if (result == ISC_R_SUCCESS) { + isc_boolean_t allow = cfg_obj_asboolean(obj); + struct cfg_context *cfg = NULL; + if (allow) { + cfg = isc_mem_get(view->mctx, sizeof(*cfg)); + if (cfg == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + memset(cfg, 0, sizeof(*cfg)); + isc_mem_attach(view->mctx, &cfg->mctx); + if (config != NULL) + cfg_obj_attach(config, &cfg->config); + cfg_parser_attach(parser, &cfg->parser); + cfg_aclconfctx_clone(actx, &cfg->actx); + } + dns_view_setnewzones(view, allow, cfg, cfgctx_destroy); + } + + /* + * If we're allowing added zones, then load zone configuration + * from the newzone file for zones that were added during previous + * runs. + */ + if (view->new_zone_file != NULL) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "loading additional zones for view '%s'", + view->name); + + CHECK(cfg_parser_create(view->mctx, ns_g_lctx, + &newzones_parser)); + result = cfg_parse_file(newzones_parser, view->new_zone_file, + &cfg_type_newzones, &nzfconf); + if (result == ISC_R_SUCCESS) { + zonelist = NULL; + cfg_map_get(nzfconf, "zone", &zonelist); + for (element = cfg_list_first(zonelist); + element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *zconfig = + cfg_listelt_value(element); + CHECK(configure_zone(config, zconfig, vconfig, + mctx, view, actx, + ISC_TRUE)); + } + } } #ifdef DLZ @@ -1197,6 +1821,14 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv)); if (result != ISC_R_SUCCESS) goto cleanup; + + /* + * If the dlz backend supports configuration, + * then call its configure method now. + */ + result = dns_dlzconfigure(view, dlzconfigure_callback); + if (result != ISC_R_SUCCESS) + goto cleanup; } } #endif @@ -1205,6 +1837,32 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, * Obtain configuration parameters that affect the decision of whether * we can reuse/share an existing cache. */ + obj = NULL; + result = ns_config_get(maps, "cleaning-interval", &obj); + INSIST(result == ISC_R_SUCCESS); + cleaning_interval = cfg_obj_asuint32(obj) * 60; + + obj = NULL; + result = ns_config_get(maps, "max-cache-size", &obj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_isstring(obj)) { + str = cfg_obj_asstring(obj); + INSIST(strcasecmp(str, "unlimited") == 0); + max_cache_size = ISC_UINT32_MAX; + } else { + isc_resourcevalue_t value; + value = cfg_obj_asuint64(obj); + if (value > ISC_UINT32_MAX) { + cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, + "'max-cache-size " + "%" ISC_PRINT_QUADFORMAT "d' is too large", + value); + result = ISC_R_RANGE; + goto cleanup; + } + max_cache_size = (isc_uint32_t)value; + } + /* Check-names. */ obj = NULL; result = ns_checknames_get(maps, "response", &obj); @@ -1229,6 +1887,109 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, zero_no_soattl = cfg_obj_asboolean(obj); obj = NULL; + result = ns_config_get(maps, "dns64", &obj); + if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") && + strcmp(view->name, "_meta")) { + const cfg_listelt_t *element; + isc_netaddr_t na, suffix, *sp; + unsigned int prefixlen; + const char *server, *contact; + const cfg_obj_t *myobj; + + myobj = NULL; + result = ns_config_get(maps, "dns64-server", &myobj); + if (result == ISC_R_SUCCESS) + server = cfg_obj_asstring(myobj); + else + server = NULL; + + myobj = NULL; + result = ns_config_get(maps, "dns64-contact", &myobj); + if (result == ISC_R_SUCCESS) + contact = cfg_obj_asstring(myobj); + else + contact = NULL; + + for (element = cfg_list_first(obj); + element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *map = cfg_listelt_value(element); + dns_dns64_t *dns64 = NULL; + unsigned int dns64options = 0; + + cfg_obj_asnetprefix(cfg_map_getname(map), &na, + &prefixlen); + + obj = NULL; + (void)cfg_map_get(map, "suffix", &obj); + if (obj != NULL) { + sp = &suffix; + isc_netaddr_fromsockaddr(sp, + cfg_obj_assockaddr(obj)); + } else + sp = NULL; + + clients = mapped = excluded = NULL; + obj = NULL; + (void)cfg_map_get(map, "clients", &obj); + if (obj != NULL) { + result = cfg_acl_fromconfig(obj, config, + ns_g_lctx, actx, + mctx, 0, &clients); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + obj = NULL; + (void)cfg_map_get(map, "mapped", &obj); + if (obj != NULL) { + result = cfg_acl_fromconfig(obj, config, + ns_g_lctx, actx, + mctx, 0, &mapped); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + obj = NULL; + (void)cfg_map_get(map, "exclude", &obj); + if (obj != NULL) { + result = cfg_acl_fromconfig(obj, config, + ns_g_lctx, actx, + mctx, 0, &excluded); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + + obj = NULL; + (void)cfg_map_get(map, "recursive-only", &obj); + if (obj != NULL && cfg_obj_asboolean(obj)) + dns64options |= DNS_DNS64_RECURSIVE_ONLY; + + obj = NULL; + (void)cfg_map_get(map, "break-dnssec", &obj); + if (obj != NULL && cfg_obj_asboolean(obj)) + dns64options |= DNS_DNS64_BREAK_DNSSEC; + + result = dns_dns64_create(mctx, &na, prefixlen, sp, + clients, mapped, excluded, + dns64options, &dns64); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_dns64_append(&view->dns64, dns64); + view->dns64cnt++; + result = dns64_reverse(view, mctx, &na, prefixlen, + server, contact); + if (result != ISC_R_SUCCESS) + goto cleanup; + if (clients != NULL) + dns_acl_detach(&clients); + if (mapped != NULL) + dns_acl_detach(&mapped); + if (excluded != NULL) + dns_acl_detach(&excluded); + } + } + + obj = NULL; result = ns_config_get(maps, "dnssec-accept-expired", &obj); INSIST(result == ISC_R_SUCCESS); view->acceptexpired = cfg_obj_asboolean(obj); @@ -1236,7 +1997,13 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, obj = NULL; result = ns_config_get(maps, "dnssec-validation", &obj); INSIST(result == ISC_R_SUCCESS); - view->enablevalidation = cfg_obj_asboolean(obj); + if (cfg_obj_isboolean(obj)) { + view->enablevalidation = cfg_obj_asboolean(obj); + } else { + /* If dnssec-validation is not boolean, it must be "auto" */ + view->enablevalidation = ISC_TRUE; + auto_root = ISC_TRUE; + } obj = NULL; result = ns_config_get(maps, "max-cache-ttl", &obj); @@ -1251,53 +2018,113 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, view->maxncachettl = 7 * 24 * 3600; /* - * Configure the view's cache. Try to reuse an existing - * cache if possible, otherwise create a new cache. - * Note that the ADB is not preserved in either case. - * When a matching view is found, the associated statistics are - * also retrieved and reused. + * Configure the view's cache. + * + * First, check to see if there are any attach-cache options. If yes, + * attempt to lookup an existing cache at attach it to the view. If + * there is not one, then try to reuse an existing cache if possible; + * otherwise create a new cache. * - * XXX Determining when it is safe to reuse a cache is tricky. + * Note that the ADB is not preserved or shared in either case. + * + * When a matching view is found, the associated statistics are also + * retrieved and reused. + * + * XXX Determining when it is safe to reuse or share a cache is tricky. * When the view's configuration changes, the cached data may become * invalid because it reflects our old view of the world. We check - * some of the configuration parameters that could invalidate the cache, - * but there are other configuration options that should be checked. - * For example, if a view uses a forwarder, changes in the forwarder - * configuration may invalidate the cache. At the moment, it's the - * administrator's responsibility to ensure these configuration options - * don't invalidate reusing. + * some of the configuration parameters that could invalidate the cache + * or otherwise make it unsharable, but there are other configuration + * options that should be checked. For example, if a view uses a + * forwarder, changes in the forwarder configuration may invalidate + * the cache. At the moment, it's the administrator's responsibility to + * ensure these configuration options don't invalidate reusing/sharing. */ - result = dns_viewlist_find(&ns_g_server->viewlist, - view->name, view->rdclass, - &pview); - if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) - goto cleanup; - if (pview != NULL) { - if (cache_reusable(pview, view, zero_no_soattl)) { - INSIST(pview->cache != NULL); - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3), - "reusing existing cache"); - reused_cache = ISC_TRUE; - dns_cache_attach(pview->cache, &cache); - } else { + obj = NULL; + result = ns_config_get(maps, "attach-cache", &obj); + if (result == ISC_R_SUCCESS) + cachename = cfg_obj_asstring(obj); + else + cachename = view->name; + cache = NULL; + nsc = cachelist_find(cachelist, cachename); + if (nsc != NULL) { + if (!cache_sharable(nsc->primaryview, view, zero_no_soattl, + cleaning_interval, max_cache_size)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), - "cache cannot be reused for view %s " + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "views %s and %s can't share the cache " "due to configuration parameter mismatch", - view->name); + nsc->primaryview->name, view->name); + result = ISC_R_FAILURE; + goto cleanup; } - dns_view_getresstats(pview, &resstats); - dns_view_getresquerystats(pview, &resquerystats); - dns_view_detach(&pview); - } - if (cache == NULL) { - CHECK(isc_mem_create(0, 0, &cmctx)); - CHECK(dns_cache_create(cmctx, ns_g_taskmgr, ns_g_timermgr, - view->rdclass, "rbt", 0, NULL, &cache)); - isc_mem_setname(cmctx, "cache", NULL); + dns_cache_attach(nsc->cache, &cache); + shared_cache = ISC_TRUE; + } else { + if (strcmp(cachename, view->name) == 0) { + result = dns_viewlist_find(&ns_g_server->viewlist, + cachename, view->rdclass, + &pview); + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) + goto cleanup; + if (pview != NULL) { + if (!cache_reusable(pview, view, + zero_no_soattl)) { + isc_log_write(ns_g_lctx, + NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, + ISC_LOG_DEBUG(1), + "cache cannot be reused " + "for view %s due to " + "configuration parameter " + "mismatch", view->name); + } else { + INSIST(pview->cache != NULL); + isc_log_write(ns_g_lctx, + NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, + ISC_LOG_DEBUG(3), + "reusing existing cache"); + reused_cache = ISC_TRUE; + dns_cache_attach(pview->cache, &cache); + } + dns_view_getresstats(pview, &resstats); + dns_view_getresquerystats(pview, + &resquerystats); + dns_view_detach(&pview); + } + } + if (cache == NULL) { + /* + * Create a cache with the desired name. This normally + * equals the view name, but may also be a forward + * reference to a view that share the cache with this + * view but is not yet configured. If it is not the + * view name but not a forward reference either, then it + * is simply a named cache that is not shared. + */ + CHECK(isc_mem_create(0, 0, &cmctx)); + isc_mem_setname(cmctx, "cache", NULL); + CHECK(dns_cache_create2(cmctx, ns_g_taskmgr, + ns_g_timermgr, view->rdclass, + cachename, "rbt", 0, NULL, + &cache)); + } + nsc = isc_mem_get(mctx, sizeof(*nsc)); + if (nsc == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + nsc->cache = NULL; + dns_cache_attach(cache, &nsc->cache); + nsc->primaryview = view; + nsc->needflush = ISC_FALSE; + nsc->adbsizeadjusted = ISC_FALSE; + ISC_LINK_INIT(nsc, link); + ISC_LIST_APPEND(*cachelist, nsc, link); } - dns_view_setcache(view, cache); + dns_view_setcache2(view, cache, shared_cache); /* * cache-file cannot be inherited if views are present, but this @@ -1307,35 +2134,11 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, result = ns_config_get(maps, "cache-file", &obj); if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) { CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj))); - if (!reused_cache) + if (!reused_cache && !shared_cache) CHECK(dns_cache_load(cache)); } - obj = NULL; - result = ns_config_get(maps, "cleaning-interval", &obj); - INSIST(result == ISC_R_SUCCESS); - dns_cache_setcleaninginterval(cache, cfg_obj_asuint32(obj) * 60); - - obj = NULL; - result = ns_config_get(maps, "max-cache-size", &obj); - INSIST(result == ISC_R_SUCCESS); - if (cfg_obj_isstring(obj)) { - str = cfg_obj_asstring(obj); - INSIST(strcasecmp(str, "unlimited") == 0); - max_cache_size = ISC_UINT32_MAX; - } else { - isc_resourcevalue_t value; - value = cfg_obj_asuint64(obj); - if (value > ISC_UINT32_MAX) { - cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, - "'max-cache-size " - "%" ISC_PRINT_QUADFORMAT "d' is too large", - value); - result = ISC_R_RANGE; - goto cleanup; - } - max_cache_size = (isc_uint32_t)value; - } + dns_cache_setcleaninginterval(cache, cleaning_interval); dns_cache_setcachesize(cache, max_cache_size); dns_cache_detach(&cache); @@ -1373,13 +2176,23 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, dns_view_setresquerystats(view, resquerystats); /* - * Set the ADB cache size to 1/8th of the max-cache-size. + * Set the ADB cache size to 1/8th of the max-cache-size or + * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared. */ max_adb_size = 0; if (max_cache_size != 0) { max_adb_size = max_cache_size / 8; if (max_adb_size == 0) max_adb_size = 1; /* Force minimum. */ + if (view != nsc->primaryview && + max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) { + max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE; + if (!nsc->adbsizeadjusted) { + dns_adb_setadbsize(nsc->primaryview->adb, + MAX_ADB_SIZE_FOR_CACHESHARE); + nsc->adbsizeadjusted = ISC_TRUE; + } + } } dns_adb_setadbsize(view->adb, max_adb_size); @@ -1395,6 +2208,18 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, dns_resolver_setlamettl(view->resolver, lame_ttl); /* + * Set the resolver's query timeout. + */ + obj = NULL; + result = ns_config_get(maps, "resolver-query-timeout", &obj); + INSIST(result == ISC_R_SUCCESS); + query_timeout = cfg_obj_asuint32(obj); + dns_resolver_settimeout(view->resolver, query_timeout); + + /* Specify whether to use 0-TTL for negative response for SOA query */ + dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl); + + /* * Set the resolver's EDNS UDP size. */ obj = NULL; @@ -1484,9 +2309,29 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, /* * Configure the view's TSIG keys. */ - ring = NULL; CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); + if (ns_g_server->sessionkey != NULL) { + CHECK(dns_tsigkeyring_add(ring, ns_g_server->session_keyname, + ns_g_server->sessionkey)); + } dns_view_setkeyring(view, ring); + dns_tsigkeyring_detach(&ring); + + /* + * See if we can re-use a dynamic key ring. + */ + result = dns_viewlist_find(&ns_g_server->viewlist, view->name, + view->rdclass, &pview); + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) + goto cleanup; + if (pview != NULL) { + dns_view_getdynamickeyring(pview, &ring); + if (ring != NULL) + dns_view_setdynamickeyring(view, ring); + dns_tsigkeyring_detach(&ring); + dns_view_detach(&pview); + } else + dns_view_restorekeyring(view); /* * Configure the view's peer list. @@ -1543,10 +2388,10 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, /* * Configure the "match-clients" and "match-destinations" ACL. */ - CHECK(configure_view_acl(vconfig, config, "match-clients", actx, + CHECK(configure_view_acl(vconfig, config, "match-clients", NULL, actx, ns_g_mctx, &view->matchclients)); - CHECK(configure_view_acl(vconfig, config, "match-destinations", actx, - ns_g_mctx, &view->matchdestinations)); + CHECK(configure_view_acl(vconfig, config, "match-destinations", NULL, + actx, ns_g_mctx, &view->matchdestinations)); /* * Configure the "match-recursive-only" option. @@ -1618,20 +2463,20 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, * "allow-recursion", and "allow-recursion-on" acls if * configured in named.conf. */ - CHECK(configure_view_acl(vconfig, config, "allow-query-cache", + CHECK(configure_view_acl(vconfig, config, "allow-query-cache", NULL, actx, ns_g_mctx, &view->cacheacl)); - CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", + CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", NULL, actx, ns_g_mctx, &view->cacheonacl)); if (view->cacheonacl == NULL) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-query-cache-on", actx, + "allow-query-cache-on", NULL, actx, ns_g_mctx, &view->cacheonacl)); if (strcmp(view->name, "_bind") != 0) { CHECK(configure_view_acl(vconfig, config, "allow-recursion", - actx, ns_g_mctx, + NULL, actx, ns_g_mctx, &view->recursionacl)); CHECK(configure_view_acl(vconfig, config, "allow-recursion-on", - actx, ns_g_mctx, + NULL, actx, ns_g_mctx, &view->recursiononacl)); } @@ -1643,8 +2488,14 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, */ if (view->cacheacl == NULL && view->recursionacl != NULL) dns_acl_attach(view->recursionacl, &view->cacheacl); + /* + * XXXEACH: This call to configure_view_acl() is redundant. We + * are leaving it as it is because we are making a minimal change + * for a patch release. In the future this should be changed to + * dns_acl_attach(view->queryacl, &view->cacheacl). + */ if (view->cacheacl == NULL && view->recursion) - CHECK(configure_view_acl(vconfig, config, "allow-query", + CHECK(configure_view_acl(vconfig, config, "allow-query", NULL, actx, ns_g_mctx, &view->cacheacl)); if (view->recursion && view->recursionacl == NULL && view->cacheacl != NULL) @@ -1656,24 +2507,44 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, */ if (view->recursionacl == NULL && view->recursion) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-recursion", + "allow-recursion", NULL, actx, ns_g_mctx, &view->recursionacl)); if (view->recursiononacl == NULL && view->recursion) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-recursion-on", + "allow-recursion-on", NULL, actx, ns_g_mctx, &view->recursiononacl)); if (view->cacheacl == NULL) { if (view->recursion) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-query-cache", actx, - ns_g_mctx, &view->cacheacl)); + "allow-query-cache", NULL, + actx, ns_g_mctx, + &view->cacheacl)); else - CHECK(dns_acl_none(ns_g_mctx, &view->cacheacl)); + CHECK(dns_acl_none(mctx, &view->cacheacl)); } /* + * Filter setting on addresses in the answer section. + */ + CHECK(configure_view_acl(vconfig, config, "deny-answer-addresses", + "acl", actx, ns_g_mctx, &view->denyansweracl)); + CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses", + "except-from", ns_g_mctx, + &view->answeracl_exclude)); + + /* + * Filter setting on names (CNAME/DNAME targets) in the answer section. + */ + CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", + "name", ns_g_mctx, + &view->denyanswernames)); + CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", + "except-from", ns_g_mctx, + &view->answernames_exclude)); + + /* * Configure sortlist, if set */ CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx, @@ -1686,19 +2557,19 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, */ if (view->notifyacl == NULL) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-notify", actx, + "allow-notify", NULL, actx, ns_g_mctx, &view->notifyacl)); if (view->transferacl == NULL) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-transfer", actx, + "allow-transfer", NULL, actx, ns_g_mctx, &view->transferacl)); if (view->updateacl == NULL) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-update", actx, + "allow-update", NULL, actx, ns_g_mctx, &view->updateacl)); if (view->upfwdacl == NULL) CHECK(configure_view_acl(NULL, ns_g_config, - "allow-update-forwarding", actx, + "allow-update-forwarding", NULL, actx, ns_g_mctx, &view->upfwdacl)); obj = NULL; @@ -1728,13 +2599,47 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, cfg_obj_asuint32(obj), max_clients_per_query); +#ifdef ALLOW_FILTER_AAAA_ON_V4 + obj = NULL; + result = ns_config_get(maps, "filter-aaaa-on-v4", &obj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) + view->v4_aaaa = dns_v4_aaaa_filter; + else + view->v4_aaaa = dns_v4_aaaa_ok; + } else { + const char *v4_aaaastr = cfg_obj_asstring(obj); + if (strcasecmp(v4_aaaastr, "break-dnssec") == 0) + view->v4_aaaa = dns_v4_aaaa_break_dnssec; + else + INSIST(0); + } + CHECK(configure_view_acl(vconfig, config, "filter-aaaa", NULL, + actx, ns_g_mctx, &view->v4_aaaa_acl)); +#endif + obj = NULL; result = ns_config_get(maps, "dnssec-enable", &obj); INSIST(result == ISC_R_SUCCESS); view->enablednssec = cfg_obj_asboolean(obj); obj = NULL; - result = ns_config_get(maps, "dnssec-lookaside", &obj); + result = ns_config_get(optionmaps, "dnssec-lookaside", &obj); + if (result == ISC_R_SUCCESS) { + /* If set to "auto", use the version from the defaults */ + const cfg_obj_t *dlvobj; + dlvobj = cfg_listelt_value(cfg_list_first(obj)); + if (!strcmp(cfg_obj_asstring(cfg_tuple_get(dlvobj, "domain")), + "auto") && + cfg_obj_isvoid(cfg_tuple_get(dlvobj, "trust-anchor"))) { + auto_dlv = ISC_TRUE; + obj = NULL; + result = cfg_map_get(ns_g_defaults, + "dnssec-lookaside", &obj); + } + } + if (result == ISC_R_SUCCESS) { for (element = cfg_list_first(obj); element != NULL; @@ -1745,31 +2650,13 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, dns_name_t *dlv; obj = cfg_listelt_value(element); -#if 0 - dns_fixedname_t fixed; - dns_name_t *name; - - /* - * When we support multiple dnssec-lookaside - * entries this is how to find the domain to be - * checked. XXXMPA - */ - dns_fixedname_init(&fixed); - name = dns_fixedname_name(&fixed); - str = cfg_obj_asstring(cfg_tuple_get(obj, - "domain")); - isc_buffer_init(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - CHECK(dns_name_fromtext(name, &b, dns_rootname, - ISC_TRUE, NULL)); -#endif str = cfg_obj_asstring(cfg_tuple_get(obj, "trust-anchor")); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); dlv = dns_fixedname_name(&view->dlv_fixed); CHECK(dns_name_fromtext(dlv, &b, dns_rootname, - ISC_TRUE, NULL)); + DNS_NAME_DOWNCASE, NULL)); view->dlv = dns_fixedname_name(&view->dlv_fixed); } } else @@ -1779,8 +2666,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, * For now, there is only one kind of trusted keys, the * "security roots". */ - CHECK(configure_view_dnsseckeys(vconfig, config, mctx, - &view->secroots)); + CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys, + auto_dlv, auto_root, mctx)); dns_resolver_resetmustbesecure(view->resolver); obj = NULL; result = ns_config_get(maps, "dnssec-must-be-secure", &obj); @@ -1821,7 +2708,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL)); + 0, NULL)); CHECK(dns_view_excludedelegationonly(view, name)); } @@ -1874,8 +2761,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, str = cfg_obj_asstring(obj); isc_buffer_init(&buffer, str, strlen(str)); isc_buffer_add(&buffer, strlen(str)); - CHECK(dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); isc_buffer_init(&buffer, server, sizeof(server) - 1); CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); server[isc_buffer_usedlength(&buffer)] = 0; @@ -1889,8 +2776,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, str = cfg_obj_asstring(obj); isc_buffer_init(&buffer, str, strlen(str)); isc_buffer_add(&buffer, strlen(str)); - CHECK(dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); isc_buffer_init(&buffer, contact, sizeof(contact) - 1); CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); contact[isc_buffer_usedlength(&buffer)] = 0; @@ -1916,8 +2803,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, /* * Look for zone on drop list. */ - CHECK(dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); if (disablelist != NULL && on_disable_list(disablelist, name)) continue; @@ -2012,9 +2899,40 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, } } + /* + * Make the list of response policy zone names for views that + * are used for real lookups and so care about hints. + */ + zonelist = NULL; + if (view->rdclass == dns_rdataclass_in && need_hints) { + obj = NULL; + result = ns_config_get(maps, "response-policy", &obj); + if (result == ISC_R_SUCCESS) + cfg_map_get(obj, "zone", &zonelist); + } + if (zonelist != NULL) { + + for (element = cfg_list_first(zonelist); + element != NULL; + element = cfg_list_next(element)) { + result = configure_rpz(view, element); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_rpz_set_need(ISC_TRUE); + } + } + result = ISC_R_SUCCESS; cleanup: + if (clients != NULL) + dns_acl_detach(&clients); + if (mapped != NULL) + dns_acl_detach(&mapped); + if (excluded != NULL) + dns_acl_detach(&excluded); + if (ring != NULL) + dns_tsigkeyring_detach(&ring); if (zone != NULL) dns_zone_detach(&zone); if (dispatch4 != NULL) @@ -2033,6 +2951,12 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, if (cache != NULL) dns_cache_detach(&cache); + if (newzones_parser != NULL) { + if (nzfconf != NULL) + cfg_obj_destroy(newzones_parser, &nzfconf); + cfg_parser_destroy(&newzones_parser); + } + return (result); } @@ -2105,8 +3029,8 @@ configure_alternates(const cfg_obj_t *config, dns_view_t *view, isc_buffer_add(&buffer, strlen(str)); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); - CHECK(dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL)); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); portobj = cfg_tuple_get(alternate, "port"); if (cfg_obj_isuint32(portobj)) { @@ -2286,7 +3210,7 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, static isc_result_t configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, - cfg_aclconfctx_t *aclconf) + cfg_aclconfctx_t *aclconf, isc_boolean_t added) { dns_view_t *pview = NULL; /* Production view */ dns_zone_t *zone = NULL; /* New or reused zone */ @@ -2319,7 +3243,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, isc_buffer_add(&buffer, strlen(zname)); dns_fixedname_init(&fixorigin); CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), - &buffer, dns_rootname, ISC_FALSE, NULL)); + &buffer, dns_rootname, 0, NULL)); origin = dns_fixedname_name(&fixorigin); CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"), @@ -2349,7 +3273,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, ztypestr = cfg_obj_asstring(typeobj); /* - * "hints zones" aren't zones. If we've got one, + * "hints zones" aren't zones. If we've got one, * configure it and return. */ if (strcasecmp(ztypestr, "hint") == 0) { @@ -2500,6 +3424,11 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, } /* + * Mark whether the zone was originally added at runtime or not + */ + dns_zone_setadded(zone, added); + + /* * Configure the zone. */ CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone)); @@ -2519,6 +3448,95 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, } /* + * Configure built-in zone for storing managed-key data. + */ + +#define KEYZONE "managed-keys.bind" +#define MKEYS ".mkeys" + +static isc_result_t +add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { + isc_result_t result; + dns_view_t *pview = NULL; + dns_zone_t *zone = NULL; + dns_acl_t *none = NULL; + char filename[PATH_MAX]; + char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(MKEYS)]; + int n; + + REQUIRE(view != NULL); + + /* See if we can re-use an existing keydata zone. */ + result = dns_viewlist_find(&ns_g_server->viewlist, + view->name, view->rdclass, + &pview); + if (result != ISC_R_NOTFOUND && + result != ISC_R_SUCCESS) + return (result); + + if (pview != NULL && pview->managed_keys != NULL) { + dns_zone_attach(pview->managed_keys, &view->managed_keys); + dns_zone_setview(pview->managed_keys, view); + dns_view_detach(&pview); + return (ISC_R_SUCCESS); + } + + /* No existing keydata zone was found; create one */ + CHECK(dns_zone_create(&zone, mctx)); + CHECK(dns_zone_setorigin(zone, dns_rootname)); + + isc_sha256_data((void *)view->name, strlen(view->name), buffer); + strcat(buffer, MKEYS); + n = snprintf(filename, sizeof(filename), "%s%s%s", + directory ? directory : "", directory ? "/" : "", + strcmp(view->name, "_default") == 0 ? KEYZONE : buffer); + if (n < 0 || (size_t)n >= sizeof(filename)) { + result = (n < 0) ? ISC_R_FAILURE : ISC_R_NOSPACE; + goto cleanup; + } + CHECK(dns_zone_setfile(zone, filename)); + + 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)); + + if (view->managed_keys != NULL) + dns_zone_detach(&view->managed_keys); + dns_zone_attach(zone, &view->managed_keys); + + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "set up managed keys zone for view %s, file '%s'", + view->name, filename); + +cleanup: + if (zone != NULL) + dns_zone_detach(&zone); + if (none != NULL) + dns_acl_detach(&none); + + return (result); +} + +/* * Configure a single server quota. */ static void @@ -2914,13 +3932,226 @@ removed(dns_zone_t *zone, void *uap) { return (ISC_R_SUCCESS); } +static void +cleanup_session_key(ns_server_t *server, isc_mem_t *mctx) { + if (server->session_keyfile != NULL) { + isc_file_remove(server->session_keyfile); + isc_mem_free(mctx, server->session_keyfile); + server->session_keyfile = NULL; + } + + if (server->session_keyname != NULL) { + if (dns_name_dynamic(server->session_keyname)) + dns_name_free(server->session_keyname, mctx); + isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t)); + server->session_keyname = NULL; + } + + if (server->sessionkey != NULL) + dns_tsigkey_detach(&server->sessionkey); + + server->session_keyalg = DST_ALG_UNKNOWN; + server->session_keybits = 0; +} + +static isc_result_t +generate_session_key(const char *filename, const char *keynamestr, + dns_name_t *keyname, const char *algstr, + dns_name_t *algname, unsigned int algtype, + isc_uint16_t bits, isc_mem_t *mctx, + dns_tsigkey_t **tsigkeyp) +{ + isc_result_t result = ISC_R_SUCCESS; + dst_key_t *key = NULL; + isc_buffer_t key_txtbuffer; + isc_buffer_t key_rawbuffer; + char key_txtsecret[256]; + char key_rawsecret[64]; + isc_region_t key_rawregion; + isc_stdtime_t now; + dns_tsigkey_t *tsigkey = NULL; + FILE *fp = NULL; + + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "generating session key for dynamic DNS"); + + /* generate key */ + result = dst_key_generate(keyname, algtype, bits, 1, 0, + DNS_KEYPROTO_ANY, dns_rdataclass_in, + mctx, &key); + if (result != ISC_R_SUCCESS) + return (result); + + /* + * Dump the key to the buffer for later use. Should be done before + * we transfer the ownership of key to tsigkey. + */ + isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); + CHECK(dst_key_tobuffer(key, &key_rawbuffer)); + + isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); + isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); + CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer)); + + /* Store the key in tsigkey. */ + isc_stdtime_get(&now); + CHECK(dns_tsigkey_createfromkey(dst_key_name(key), algname, key, + ISC_FALSE, NULL, now, now, mctx, NULL, + &tsigkey)); + + /* Dump the key to the key file. */ + fp = ns_os_openfile(filename, S_IRUSR|S_IWUSR, ISC_TRUE); + if (fp == NULL) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "could not create %s", filename); + result = ISC_R_NOPERM; + goto cleanup; + } + + fprintf(fp, "key \"%s\" {\n" + "\talgorithm %s;\n" + "\tsecret \"%.*s\";\n};\n", keynamestr, algstr, + (int) isc_buffer_usedlength(&key_txtbuffer), + (char*) isc_buffer_base(&key_txtbuffer)); + + RUNTIME_CHECK(isc_stdio_flush(fp) == ISC_R_SUCCESS); + RUNTIME_CHECK(isc_stdio_close(fp) == ISC_R_SUCCESS); + + dst_key_free(&key); + + *tsigkeyp = tsigkey; + + return (ISC_R_SUCCESS); + + cleanup: + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed to generate session key " + "for dynamic DNS: %s", isc_result_totext(result)); + if (tsigkey != NULL) + dns_tsigkey_detach(&tsigkey); + if (key != NULL) + dst_key_free(&key); + + return (result); +} + +static isc_result_t +configure_session_key(const cfg_obj_t **maps, ns_server_t *server, + isc_mem_t *mctx) +{ + const char *keyfile, *keynamestr, *algstr; + unsigned int algtype; + dns_fixedname_t fname; + dns_name_t *keyname, *algname; + isc_buffer_t buffer; + isc_uint16_t bits; + const cfg_obj_t *obj; + isc_boolean_t need_deleteold = ISC_FALSE; + isc_boolean_t need_createnew = ISC_FALSE; + isc_result_t result; + + obj = NULL; + result = ns_config_get(maps, "session-keyfile", &obj); + if (result == ISC_R_SUCCESS) { + if (cfg_obj_isvoid(obj)) + keyfile = NULL; /* disable it */ + else + keyfile = cfg_obj_asstring(obj); + } else + keyfile = ns_g_defaultsessionkeyfile; + + obj = NULL; + result = ns_config_get(maps, "session-keyname", &obj); + INSIST(result == ISC_R_SUCCESS); + keynamestr = cfg_obj_asstring(obj); + dns_fixedname_init(&fname); + isc_buffer_init(&buffer, keynamestr, strlen(keynamestr)); + isc_buffer_add(&buffer, strlen(keynamestr)); + keyname = dns_fixedname_name(&fname); + result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + return (result); + + obj = NULL; + result = ns_config_get(maps, "session-keyalg", &obj); + INSIST(result == ISC_R_SUCCESS); + algstr = cfg_obj_asstring(obj); + algname = NULL; + result = ns_config_getkeyalgorithm2(algstr, &algname, &algtype, &bits); + if (result != ISC_R_SUCCESS) { + const char *s = " (keeping current key)"; + + cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "session-keyalg: " + "unsupported or unknown algorithm '%s'%s", + algstr, + server->session_keyfile != NULL ? s : ""); + return (result); + } + + /* See if we need to (re)generate a new key. */ + if (keyfile == NULL) { + if (server->session_keyfile != NULL) + need_deleteold = ISC_TRUE; + } else if (server->session_keyfile == NULL) + need_createnew = ISC_TRUE; + else if (strcmp(keyfile, server->session_keyfile) != 0 || + !dns_name_equal(server->session_keyname, keyname) || + server->session_keyalg != algtype || + server->session_keybits != bits) { + need_deleteold = ISC_TRUE; + need_createnew = ISC_TRUE; + } + + if (need_deleteold) { + INSIST(server->session_keyfile != NULL); + INSIST(server->session_keyname != NULL); + INSIST(server->sessionkey != NULL); + + cleanup_session_key(server, mctx); + } + + if (need_createnew) { + INSIST(server->sessionkey == NULL); + INSIST(server->session_keyfile == NULL); + INSIST(server->session_keyname == NULL); + INSIST(server->session_keyalg == DST_ALG_UNKNOWN); + INSIST(server->session_keybits == 0); + + server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t)); + if (server->session_keyname == NULL) + goto cleanup; + dns_name_init(server->session_keyname, NULL); + CHECK(dns_name_dup(keyname, mctx, server->session_keyname)); + + server->session_keyfile = isc_mem_strdup(mctx, keyfile); + if (server->session_keyfile == NULL) + goto cleanup; + + server->session_keyalg = algtype; + server->session_keybits = bits; + + CHECK(generate_session_key(keyfile, keynamestr, keyname, algstr, + algname, algtype, bits, mctx, + &server->sessionkey)); + } + + return (result); + + cleanup: + cleanup_session_key(server, mctx); + return (result); +} + static isc_result_t load_configuration(const char *filename, ns_server_t *server, isc_boolean_t first_time) { cfg_aclconfctx_t aclconfctx; - cfg_obj_t *config; - cfg_parser_t *parser = NULL; + cfg_obj_t *config = NULL, *bindkeys = NULL; + cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL; const cfg_listelt_t *element; const cfg_obj_t *builtin_views; const cfg_obj_t *maps[3]; @@ -2931,7 +4162,7 @@ load_configuration(const char *filename, ns_server_t *server, dns_view_t *view = NULL; dns_view_t *view_next; dns_viewlist_t tmpviewlist; - dns_viewlist_t viewlist; + dns_viewlist_t viewlist, builtin_viewlist; in_port_t listen_port, udpport_low, udpport_high; int i; isc_interval_t interval; @@ -2943,10 +4174,14 @@ load_configuration(const char *filename, ns_server_t *server, isc_uint32_t interface_interval; isc_uint32_t reserved; isc_uint32_t udpsize; + ns_cachelist_t cachelist, tmpcachelist; unsigned int maxsocks; + ns_cache_t *nsc; cfg_aclconfctx_init(&aclconfctx); ISC_LIST_INIT(viewlist); + ISC_LIST_INIT(builtin_viewlist); + ISC_LIST_INIT(cachelist); /* Ensure exclusive access to configuration data. */ result = isc_task_beginexclusive(server->task); @@ -2958,8 +4193,7 @@ load_configuration(const char *filename, ns_server_t *server, if (first_time) { CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config)); RUNTIME_CHECK(cfg_map_get(ns_g_config, "options", - &ns_g_defaults) == - ISC_R_SUCCESS); + &ns_g_defaults) == ISC_R_SUCCESS); } /* @@ -2976,10 +4210,10 @@ load_configuration(const char *filename, ns_server_t *server, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading configuration from '%s'", filename); - CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); - cfg_parser_setcallback(parser, directory_callback, NULL); - result = cfg_parse_file(parser, filename, &cfg_type_namedconf, - &config); + CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser)); + cfg_parser_setcallback(conf_parser, directory_callback, NULL); + result = cfg_parse_file(conf_parser, filename, + &cfg_type_namedconf, &config); } /* @@ -2994,10 +4228,10 @@ load_configuration(const char *filename, ns_server_t *server, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "loading configuration from '%s'", lwresd_g_resolvconffile); - if (parser != NULL) - cfg_parser_destroy(&parser); - CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); - result = ns_lwresd_parseeresolvconf(ns_g_mctx, parser, + if (conf_parser != NULL) + cfg_parser_destroy(&conf_parser); + CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser)); + result = ns_lwresd_parseeresolvconf(ns_g_mctx, conf_parser, &config); } CHECK(result); @@ -3019,13 +4253,38 @@ load_configuration(const char *filename, ns_server_t *server, maps[i++] = NULL; /* + * If bind.keys exists, load it. If "dnssec-lookaside auto" + * is turned on, the keys found there will be used as default + * trust anchors. + */ + obj = NULL; + result = ns_config_get(maps, "bindkeys-file", &obj); + INSIST(result == ISC_R_SUCCESS); + CHECKM(setstring(server, &server->bindkeysfile, + cfg_obj_asstring(obj)), "strdup"); + + if (access(server->bindkeysfile, R_OK) == 0) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "reading built-in trusted " + "keys from file '%s'", server->bindkeysfile); + + CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, + &bindkeys_parser)); + + result = cfg_parse_file(bindkeys_parser, server->bindkeysfile, + &cfg_type_bindkeys, &bindkeys); + CHECK(result); + } + + /* * Set process limits, which (usually) needs to be done as root. */ set_limits(maps); /* * Check if max number of open sockets that the system allows is - * sufficiently large. Failing this condition is not necessarily fatal, + * sufficiently large. Failing this condition is not necessarily fatal, * but may cause subsequent runtime failures for a busy recursive * server. */ @@ -3078,7 +4337,7 @@ load_configuration(const char *filename, ns_server_t *server, else isc_quota_soft(&server->recursionquota, 0); - CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx, + CHECK(configure_view_acl(NULL, config, "blackhole", NULL, &aclconfctx, ns_g_mctx, &server->blackholeacl)); if (server->blackholeacl != NULL) dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, @@ -3318,6 +4577,31 @@ load_configuration(const char *filename, ns_server_t *server, &interval, ISC_FALSE)); /* + * Write the PID file. + */ + obj = NULL; + if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) + if (cfg_obj_isvoid(obj)) + ns_os_writepidfile(NULL, first_time); + else + ns_os_writepidfile(cfg_obj_asstring(obj), first_time); + else if (ns_g_lwresdonly) + ns_os_writepidfile(lwresd_g_defaultpidfile, first_time); + else + ns_os_writepidfile(ns_g_defaultpidfile, first_time); + + /* + * Configure the server-wide session key. This must be done before + * configure views because zone configuration may need to know + * session-keyname. + * + * Failure of session key generation isn't fatal at this time; if it + * turns out that a session key is really needed but doesn't exist, + * we'll treat it as a fatal error then. + */ + (void)configure_session_key(maps, server, ns_g_mctx); + + /* * Configure and freeze all explicit views. Explicit * views that have zones were already created at parsing * time, but views with no zones must be created here. @@ -3328,12 +4612,13 @@ load_configuration(const char *filename, ns_server_t *server, element != NULL; element = cfg_list_next(element)) { - const cfg_obj_t *vconfig = cfg_listelt_value(element); + cfg_obj_t *vconfig = cfg_listelt_value(element); view = NULL; CHECK(create_view(vconfig, &viewlist, &view)); INSIST(view != NULL); - CHECK(configure_view(view, config, vconfig, + CHECK(configure_view(view, conf_parser, config, vconfig, + &cachelist, bindkeys, ns_g_mctx, &aclconfctx, ISC_TRUE)); dns_view_freeze(view); dns_view_detach(&view); @@ -3351,15 +4636,15 @@ load_configuration(const char *filename, ns_server_t *server, * In either case, we need to configure and freeze it. */ CHECK(create_view(NULL, &viewlist, &view)); - CHECK(configure_view(view, config, NULL, ns_g_mctx, - &aclconfctx, ISC_TRUE)); + CHECK(configure_view(view, conf_parser, config, NULL, + &cachelist, bindkeys, + ns_g_mctx, &aclconfctx, ISC_TRUE)); dns_view_freeze(view); dns_view_detach(&view); } /* - * Create (or recreate) the built-in views. Currently - * there is only one, the _bind view. + * Create (or recreate) the built-in views. */ builtin_views = NULL; RUNTIME_CHECK(cfg_map_get(ns_g_config, "view", @@ -3368,25 +4653,38 @@ load_configuration(const char *filename, ns_server_t *server, element != NULL; element = cfg_list_next(element)) { - const cfg_obj_t *vconfig = cfg_listelt_value(element); - CHECK(create_view(vconfig, &viewlist, &view)); - CHECK(configure_view(view, config, vconfig, ns_g_mctx, - &aclconfctx, ISC_FALSE)); + cfg_obj_t *vconfig = cfg_listelt_value(element); + + CHECK(create_view(vconfig, &builtin_viewlist, &view)); + CHECK(configure_view(view, conf_parser, config, vconfig, + &cachelist, bindkeys, + ns_g_mctx, &aclconfctx, ISC_FALSE)); 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; - /* - * Load the TKEY information from the configuration. - */ + /* 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. */ if (options != NULL) { dns_tkeyctx_t *t = NULL; CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy, @@ -3551,16 +4849,6 @@ load_configuration(const char *filename, ns_server_t *server, } } - obj = NULL; - if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) - if (cfg_obj_isvoid(obj)) - ns_os_writepidfile(NULL, first_time); - else - ns_os_writepidfile(cfg_obj_asstring(obj), first_time); - else if (ns_g_lwresdonly) - ns_os_writepidfile(lwresd_g_defaultpidfile, first_time); - else - ns_os_writepidfile(ns_g_defaultpidfile, first_time); obj = NULL; if (options != NULL && @@ -3591,6 +4879,12 @@ load_configuration(const char *filename, ns_server_t *server, "strdup"); obj = NULL; + result = ns_config_get(maps, "secroots-file", &obj); + INSIST(result == ISC_R_SUCCESS); + CHECKM(setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)), + "strdup"); + + obj = NULL; result = ns_config_get(maps, "recursing-file", &obj); INSIST(result == ISC_R_SUCCESS); CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)), @@ -3647,12 +4941,18 @@ load_configuration(const char *filename, ns_server_t *server, if (v6portset != NULL) isc_portset_destroy(ns_g_mctx, &v6portset); - cfg_aclconfctx_destroy(&aclconfctx); + cfg_aclconfctx_clear(&aclconfctx); - if (parser != NULL) { + if (conf_parser != NULL) { if (config != NULL) - cfg_obj_destroy(parser, &config); - cfg_parser_destroy(&parser); + cfg_obj_destroy(conf_parser, &config); + cfg_parser_destroy(&conf_parser); + } + + if (bindkeys_parser != NULL) { + if (bindkeys != NULL) + cfg_obj_destroy(bindkeys_parser, &bindkeys); + cfg_parser_destroy(&bindkeys_parser); } if (view != NULL) @@ -3675,6 +4975,13 @@ load_configuration(const char *filename, ns_server_t *server, dns_view_detach(&view); } + /* Same cleanup for cache list. */ + while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) { + ISC_LIST_UNLINK(cachelist, nsc, link); + dns_cache_detach(&nsc->cache); + isc_mem_put(server->mctx, nsc, sizeof(*nsc)); + } + /* * Adjust the listening interfaces in accordance with the source * addresses specified in views and zones. @@ -3708,6 +5015,8 @@ load_zones(ns_server_t *server, isc_boolean_t stop) { view = ISC_LIST_NEXT(view, link)) { CHECK(dns_view_load(view, stop)); + if (view->managed_keys != NULL) + CHECK(dns_zone_load(view->managed_keys)); } /* @@ -3737,11 +5046,14 @@ load_new_zones(ns_server_t *server, isc_boolean_t stop) { view = ISC_LIST_NEXT(view, link)) { CHECK(dns_view_loadnew(view, stop)); + + /* Load managed-keys data */ + if (view->managed_keys != NULL) + CHECK(dns_zone_loadnew(view->managed_keys)); } + /* - * Force zone maintenance. Do this after loading - * so that we know when we need to force AXFR of - * slave zones whose master files are missing. + * Resume zone XFRs. */ dns_zonemgr_resumexfrs(server->zonemgr); cleanup: @@ -3820,6 +5132,7 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { dns_view_t *view, *view_next; ns_server_t *server = (ns_server_t *)event->ev_arg; isc_boolean_t flush = server->flushonshutdown; + ns_cache_t *nsc; UNUSED(task); INSIST(task == server->task); @@ -3834,6 +5147,7 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { ns_statschannels_shutdown(server); ns_controls_shutdown(server->controls); end_reserved_dispatches(server, ISC_TRUE); + cleanup_session_key(server, server->mctx); cfg_obj_destroy(ns_g_parser, &ns_g_config); cfg_parser_destroy(&ns_g_parser); @@ -3849,6 +5163,12 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { dns_view_detach(&view); } + while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) { + ISC_LIST_UNLINK(server->cachelist, nsc, link); + dns_cache_detach(&nsc->cache); + isc_mem_put(server->mctx, nsc, sizeof(*nsc)); + } + isc_timer_detach(&server->interface_timer); isc_timer_detach(&server->heartbeat_timer); isc_timer_detach(&server->pps_timer); @@ -3860,6 +5180,11 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { dns_zonemgr_shutdown(server->zonemgr); + if (ns_g_sessionkey != NULL) { + dns_tsigkey_detach(&ns_g_sessionkey); + dns_name_free(&ns_g_sessionkeyname, server->mctx); + } + if (server->blackholeacl != NULL) dns_acl_detach(&server->blackholeacl); @@ -3918,7 +5243,8 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { ISC_R_NOMEMORY : ISC_R_SUCCESS, "allocating reload event"); - CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY), + CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy, + ns_g_engine, ISC_ENTROPY_GOODONLY), "initializing DST"); server->tkeyctx = NULL; @@ -3963,10 +5289,20 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { "isc_stats_create"); isc_socketmgr_setstats(ns_g_socketmgr, server->sockstats); + server->bindkeysfile = isc_mem_strdup(server->mctx, "bind.keys"); + CHECKFATAL(server->bindkeysfile == NULL ? ISC_R_NOMEMORY : + ISC_R_SUCCESS, + "isc_mem_strdup"); + server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db"); CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, "isc_mem_strdup"); + server->secrootsfile = isc_mem_strdup(server->mctx, "named.secroots"); + CHECKFATAL(server->secrootsfile == NULL ? ISC_R_NOMEMORY : + ISC_R_SUCCESS, + "isc_mem_strdup"); + server->recfile = isc_mem_strdup(server->mctx, "named.recursing"); CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, "isc_mem_strdup"); @@ -4008,6 +5344,14 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { ISC_LIST_INIT(server->statschannels); + ISC_LIST_INIT(server->cachelist); + + server->sessionkey = NULL; + server->session_keyfile = NULL; + server->session_keyname = NULL; + server->session_keyalg = DST_ALG_UNKNOWN; + server->session_keybits = 0; + server->magic = NS_SERVER_MAGIC; *serverp = server; } @@ -4027,7 +5371,9 @@ ns_server_destroy(ns_server_t **serverp) { isc_stats_detach(&server->sockstats); isc_mem_free(server->mctx, server->statsfile); + isc_mem_free(server->mctx, server->bindkeysfile); isc_mem_free(server->mctx, server->dumpfile); + isc_mem_free(server->mctx, server->secrootsfile); isc_mem_free(server->mctx, server->recfile); if (server->version != NULL) @@ -4047,6 +5393,7 @@ ns_server_destroy(ns_server_t **serverp) { isc_event_free(&server->reload_event); INSIST(ISC_LIST_EMPTY(server->viewlist)); + INSIST(ISC_LIST_EMPTY(server->cachelist)); dns_aclenv_destroy(&server->aclenv); @@ -4278,7 +5625,9 @@ next_token(char **stringp, const char *delim) { * set '*zonep' to NULL. */ static isc_result_t -zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) { +zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep, + const char **zonename) +{ char *input, *ptr; const char *zonetxt; char *classtxt; @@ -4302,6 +5651,8 @@ zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) { zonetxt = next_token(&input, " \t"); if (zonetxt == NULL) return (ISC_R_SUCCESS); + if (zonename) + *zonename = zonetxt; /* Look for the optional class name. */ classtxt = next_token(&input, " \t"); @@ -4314,7 +5665,7 @@ zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) { isc_buffer_add(&buf, strlen(zonetxt)); dns_fixedname_init(&name); result = dns_name_fromtext(dns_fixedname_name(&name), - &buf, dns_rootname, ISC_FALSE, NULL); + &buf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) goto fail1; @@ -4362,7 +5713,7 @@ ns_server_retransfercommand(ns_server_t *server, char *args) { dns_zone_t *zone = NULL; dns_zonetype_t type; - result = zone_from_args(server, args, &zone); + result = zone_from_args(server, args, &zone, NULL); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) @@ -4386,7 +5737,7 @@ ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) { dns_zonetype_t type; const char *msg = NULL; - result = zone_from_args(server, args, &zone); + result = zone_from_args(server, args, &zone, NULL); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) { @@ -4446,7 +5797,7 @@ ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) { dns_zone_t *zone = NULL; const unsigned char msg[] = "zone notify queued"; - result = zone_from_args(server, args, &zone); + result = zone_from_args(server, args, &zone, NULL); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) @@ -4471,7 +5822,7 @@ ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) { const unsigned char msg2[] = "not a slave or stub zone"; dns_zonetype_t type; - result = zone_from_args(server, args, &zone); + result = zone_from_args(server, args, &zone, NULL); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) @@ -4710,15 +6061,23 @@ dumpdone(void *arg, isc_result_t result) { nextview: fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name); resume: - if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) { + if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) { + fprintf(dctx->fp, + ";\n; Cache of view '%s' is shared as '%s'\n", + dctx->view->view->name, + dns_cache_getname(dctx->view->view->cache)); + } else if (dctx->zone == NULL && dctx->cache == NULL && + dctx->dumpcache) + { style = &dns_master_style_cache; /* start cache dump */ if (dctx->view->view->cachedb != NULL) dns_db_attach(dctx->view->view->cachedb, &dctx->cache); if (dctx->cache != NULL) { - - fprintf(dctx->fp, ";\n; Cache dump of view '%s'\n;\n", - dctx->view->view->name); + fprintf(dctx->fp, + ";\n; Cache dump of view '%s' (cache %s)\n;\n", + dctx->view->view->name, + dns_cache_getname(dctx->view->view->cache)); result = dns_master_dumptostreaminc(dctx->mctx, dctx->cache, NULL, style, dctx->fp, @@ -4880,6 +6239,68 @@ ns_server_dumpdb(ns_server_t *server, char *args) { } isc_result_t +ns_server_dumpsecroots(ns_server_t *server, char *args) { + dns_view_t *view; + dns_keytable_t *secroots = NULL; + isc_result_t result; + char *ptr; + FILE *fp = NULL; + isc_time_t now; + char tbuf[64]; + + /* Skip the command name. */ + ptr = next_token(&args, " \t"); + if (ptr == NULL) + return (ISC_R_UNEXPECTEDEND); + ptr = next_token(&args, " \t"); + + CHECKMF(isc_stdio_open(server->secrootsfile, "w", &fp), + "could not open secroots dump file", server->secrootsfile); + TIME_NOW(&now); + isc_time_formattimestamp(&now, tbuf, sizeof(tbuf)); + fprintf(fp, "%s\n", tbuf); + + nextview: + for (view = ISC_LIST_HEAD(server->viewlist); + view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (ptr != NULL && strcmp(view->name, ptr) != 0) + continue; + if (secroots != NULL) + dns_keytable_detach(&secroots); + result = dns_view_getsecroots(view, &secroots); + if (result == ISC_R_NOTFOUND) { + result = ISC_R_SUCCESS; + continue; + } + fprintf(fp, "\n Start view %s\n\n", view->name); + CHECK(dns_keytable_dump(secroots, fp)); + } + if (ptr != NULL) { + ptr = next_token(&args, " \t"); + if (ptr != NULL) + goto nextview; + } + + cleanup: + if (secroots != NULL) + dns_keytable_detach(&secroots); + if (fp != NULL) + (void)isc_stdio_close(fp); + if (result == ISC_R_SUCCESS) + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "dumpsecroots complete"); + else + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "dumpsecroots failed: %s", + dns_result_totext(result)); + return (result); +} + +isc_result_t ns_server_dumprecursing(ns_server_t *server) { FILE *fp = NULL; isc_result_t result; @@ -4997,6 +6418,7 @@ ns_server_flushcache(ns_server_t *server, char *args) { isc_boolean_t flushed; isc_boolean_t found; isc_result_t result; + ns_cache_t *nsc; /* Skip the command name. */ ptr = next_token(&args, " \t"); @@ -5010,22 +6432,96 @@ ns_server_flushcache(ns_server_t *server, char *args) { RUNTIME_CHECK(result == ISC_R_SUCCESS); flushed = ISC_TRUE; found = ISC_FALSE; - for (view = ISC_LIST_HEAD(server->viewlist); - view != NULL; - view = ISC_LIST_NEXT(view, link)) - { - if (viewname != NULL && strcasecmp(viewname, view->name) != 0) - continue; + + /* + * Flushing a cache is tricky when caches are shared by multiple views. + * We first identify which caches should be flushed in the local cache + * list, flush these caches, and then update other views that refer to + * the flushed cache DB. + */ + if (viewname != NULL) { + /* + * Mark caches that need to be flushed. This is an O(#view^2) + * operation in the very worst case, but should be normally + * much more lightweight because only a few (most typically just + * one) views will match. + */ + for (view = ISC_LIST_HEAD(server->viewlist); + view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (strcasecmp(viewname, view->name) != 0) + continue; + found = ISC_TRUE; + for (nsc = ISC_LIST_HEAD(server->cachelist); + nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) { + if (nsc->cache == view->cache) + break; + } + INSIST(nsc != NULL); + nsc->needflush = ISC_TRUE; + } + } else found = ISC_TRUE; - result = dns_view_flushcache(view); + + /* Perform flush */ + for (nsc = ISC_LIST_HEAD(server->cachelist); + nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) { + if (viewname != NULL && !nsc->needflush) + continue; + nsc->needflush = ISC_TRUE; + result = dns_view_flushcache2(nsc->primaryview, ISC_FALSE); if (result != ISC_R_SUCCESS) { flushed = ISC_FALSE; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "flushing cache in view '%s' failed: %s", - view->name, isc_result_totext(result)); + nsc->primaryview->name, + isc_result_totext(result)); + } + } + + /* + * Fix up views that share a flushed cache: let the views update the + * cache DB they're referring to. This could also be an expensive + * operation, but should typically be marginal: the inner loop is only + * necessary for views that share a cache, and if there are many such + * views the number of shared cache should normally be small. + * A worst case is that we have n views and n/2 caches, each shared by + * two views. Then this will be a O(n^2/4) operation. + */ + for (view = ISC_LIST_HEAD(server->viewlist); + view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (!dns_view_iscacheshared(view)) + continue; + for (nsc = ISC_LIST_HEAD(server->cachelist); + nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) { + if (!nsc->needflush || nsc->cache != view->cache) + continue; + result = dns_view_flushcache2(view, ISC_TRUE); + if (result != ISC_R_SUCCESS) { + flushed = ISC_FALSE; + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "fixing cache in view '%s' " + "failed: %s", view->name, + isc_result_totext(result)); + } } } + + /* Cleanup the cache list. */ + for (nsc = ISC_LIST_HEAD(server->cachelist); + nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) { + nsc->needflush = ISC_FALSE; + } + if (flushed && found) { if (viewname != NULL) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, @@ -5076,7 +6572,7 @@ ns_server_flushname(ns_server_t *server, char *args) { isc_buffer_add(&b, strlen(target)); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); - result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); @@ -5094,6 +6590,11 @@ ns_server_flushname(ns_server_t *server, char *args) { if (viewname != NULL && strcasecmp(viewname, view->name) != 0) continue; found = ISC_TRUE; + /* + * It's a little inefficient to try flushing name for all views + * if some of the views share a single cache. But since the + * operation is lightweight we prefer simplicity here. + */ result = dns_view_flushname(view, name); if (result != ISC_R_SUCCESS) { flushed = ISC_FALSE; @@ -5408,6 +6909,46 @@ ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) { } /* + * Act on a "sign" or "loadkeys" command from the command channel. + */ +isc_result_t +ns_server_rekey(ns_server_t *server, char *args) { + isc_result_t result; + dns_zone_t *zone = NULL; + dns_zonetype_t type; + isc_uint16_t keyopts; + isc_boolean_t fullsign = ISC_FALSE; + + if (strncasecmp(args, NS_COMMAND_SIGN, strlen(NS_COMMAND_SIGN)) == 0) + fullsign = ISC_TRUE; + + result = zone_from_args(server, args, &zone, NULL); + if (result != ISC_R_SUCCESS) + return (result); + if (zone == NULL) + return (ISC_R_UNEXPECTEDEND); /* XXX: or do all zones? */ + + type = dns_zone_gettype(zone); + if (type != dns_zone_master) { + dns_zone_detach(&zone); + return (DNS_R_NOTMASTER); + } + + keyopts = dns_zone_getkeyopts(zone); + + /* "rndc loadkeys" requires "auto-dnssec maintain". */ + if ((keyopts & DNS_ZONEKEY_ALLOW) == 0) + result = ISC_R_NOPERM; + else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign) + result = ISC_R_NOPERM; + else + dns_zone_rekey(zone, fullsign); + + dns_zone_detach(&zone); + return (result); +} + +/* * Act on a "freeze" or "thaw" command from the command channel. */ isc_result_t @@ -5425,7 +6966,7 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, isc_boolean_t frozen; const char *msg = NULL; - result = zone_from_args(server, args, &zone); + result = zone_from_args(server, args, &zone, NULL); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) { @@ -5451,7 +6992,7 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, type = dns_zone_gettype(zone); if (type != dns_zone_master) { dns_zone_detach(&zone); - return (ISC_R_NOTFOUND); + return (DNS_R_NOTMASTER); } result = isc_task_beginexclusive(server->task); @@ -5502,8 +7043,8 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, strlen(msg) + 1); 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) { vname = ""; sep = ""; @@ -5543,3 +7084,376 @@ ns_smf_add_message(isc_buffer_t *text) { return (ISC_R_SUCCESS); } #endif /* HAVE_LIBSCF */ + +/* + * Act on an "addzone" command from the command channel. + */ +isc_result_t +ns_server_add_zone(ns_server_t *server, char *args) { + isc_result_t result; + isc_buffer_t argbuf; + size_t arglen; + cfg_parser_t *parser = NULL; + cfg_obj_t *config = NULL; + const cfg_obj_t *vconfig = NULL; + const cfg_obj_t *views = NULL; + const cfg_obj_t *parms = NULL; + const cfg_obj_t *obj = NULL; + const cfg_listelt_t *element; + const char *zonename; + const char *classname = NULL; + const char *argp; + const char *viewname = NULL; + dns_rdataclass_t rdclass; + dns_view_t *view = 0; + isc_buffer_t buf, *nbuf = NULL; + dns_name_t dnsname; + dns_zone_t *zone = NULL; + FILE *fp = NULL; + struct cfg_context *cfg = NULL; + + /* Try to parse the argument string */ + arglen = strlen(args); + isc_buffer_init(&argbuf, args, arglen); + isc_buffer_add(&argbuf, strlen(args)); + CHECK(cfg_parser_create(server->mctx, ns_g_lctx, &parser)); + CHECK(cfg_parse_buffer(parser, &argbuf, &cfg_type_addzoneconf, + &config)); + CHECK(cfg_map_get(config, "addzone", &parms)); + + zonename = cfg_obj_asstring(cfg_tuple_get(parms, "name")); + isc_buffer_init(&buf, zonename, strlen(zonename)); + isc_buffer_add(&buf, strlen(zonename)); + dns_name_init(&dnsname, NULL); + isc_buffer_allocate(server->mctx, &nbuf, 256); + dns_name_setbuffer(&dnsname, nbuf); + CHECK(dns_name_fromtext(&dnsname, &buf, dns_rootname, ISC_FALSE, NULL)); + + /* Make sense of optional class argument */ + obj = cfg_tuple_get(parms, "class"); + CHECK(ns_config_getclass(obj, dns_rdataclass_in, &rdclass)); + if (rdclass != dns_rdataclass_in && obj) + classname = cfg_obj_asstring(obj); + + /* Make sense of optional view argument */ + obj = cfg_tuple_get(parms, "view"); + if (obj && cfg_obj_isstring(obj)) + viewname = cfg_obj_asstring(obj); + if (viewname == NULL || *viewname == '\0') + viewname = "_default"; + CHECK(dns_viewlist_find(&server->viewlist, viewname, rdclass, &view)); + + /* Are we accepting new zones? */ + if (view->new_zone_file == NULL) { + result = ISC_R_NOPERM; + goto cleanup; + } + + cfg = (struct cfg_context *) view->new_zone_config; + if (cfg == NULL) { + result = ISC_R_FAILURE; + goto cleanup; + } + + /* Zone shouldn't already exist */ + result = dns_zt_find(view->zonetable, &dnsname, 0, NULL, &zone); + if (result == ISC_R_SUCCESS) { + result = ISC_R_EXISTS; + goto cleanup; + } else if (result == DNS_R_PARTIALMATCH) { + /* Create our sub-zone anyway */ + dns_zone_detach(&zone); + zone = NULL; + } + else if (result != ISC_R_NOTFOUND) + goto cleanup; + + /* Find the view statement */ + cfg_map_get(cfg->config, "view", &views); + for (element = cfg_list_first(views); + element != NULL; + element = cfg_list_next(element)) + { + const char *vname; + vconfig = cfg_listelt_value(element); + vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); + if (vname && !strcasecmp(vname, viewname)) + break; + vconfig = NULL; + } + + /* Open save file for write configuration */ + CHECK(isc_stdio_open(view->new_zone_file, "a", &fp)); + + /* Mark view unfrozen so that zone can be added */ + dns_view_thaw(view); + result = configure_zone(cfg->config, parms, vconfig, + server->mctx, view, &cfg->actx, ISC_FALSE); + dns_view_freeze(view); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + /* Is it there yet? */ + CHECK(dns_zt_find(view->zonetable, &dnsname, 0, NULL, &zone)); + + /* + * Load the zone from the master file. If this fails, we'll + * need to undo the configuration we've done already. + */ + result = dns_zone_loadnew(zone); + if (result != ISC_R_SUCCESS) { + dns_db_t *dbp = NULL; + + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "addzone failed; reverting."); + + /* If the zone loaded partially, unload it */ + if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { + dns_db_detach(&dbp); + dns_zone_unload(zone); + } + + /* Remove the zone from the zone table */ + dns_zt_unmount(view->zonetable, zone); + goto cleanup; + } + + /* Flag the zone as having been added at runtime */ + dns_zone_setadded(zone, ISC_TRUE); + + /* Emit just the zone name from args */ + CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); + CHECK(isc_stdio_write(zonename, strlen(zonename), 1, fp, NULL)); + CHECK(isc_stdio_write(" ", 1, 1, fp, NULL)); + + /* Classname, if not default */ + if (classname != NULL && *classname != '\0') { + CHECK(isc_stdio_write(classname, strlen(classname), 1, fp, + NULL)); + CHECK(isc_stdio_write(" ", 1, 1, fp, NULL)); + } + + /* Find beginning of option block from args */ + for (argp = args; *argp; argp++, arglen--) { + if (*argp == '{') { /* Assume matching '}' */ + /* Add that to our file */ + CHECK(isc_stdio_write(argp, arglen, 1, fp, NULL)); + + /* Make sure we end with a LF */ + if (argp[arglen-1] != '\n') { + CHECK(isc_stdio_write("\n", 1, 1, fp, NULL)); + } + break; + } + } + + CHECK(isc_stdio_close(fp)); + fp = NULL; + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "zone %s added to view %s via addzone", + zonename, viewname); + + result = ISC_R_SUCCESS; + + cleanup: + if (fp != NULL) + isc_stdio_close(fp); + if (parser != NULL) { + if (config != NULL) + cfg_obj_destroy(parser, &config); + cfg_parser_destroy(&parser); + } + if (zone != NULL) + dns_zone_detach(&zone); + if (view != NULL) + dns_view_detach(&view); + if (nbuf != NULL) + isc_buffer_free(&nbuf); + + return (result); +} + +/* + * Act on a "delzone" command from the command channel. + */ +isc_result_t +ns_server_del_zone(ns_server_t *server, char *args) { + isc_result_t result; + dns_zone_t *zone = NULL; + dns_view_t *view = NULL; + dns_db_t *dbp = NULL; + const char *filename = NULL; + char *tmpname = NULL; + char buf[1024]; + const char *zonename = NULL; + size_t znamelen = 0; + FILE *ifp = NULL, *ofp = NULL; + + /* Parse parameters */ + CHECK(zone_from_args(server, args, &zone, &zonename)); + if (result != ISC_R_SUCCESS) + return (result); + if (zone == NULL) { + result = ISC_R_UNEXPECTEDEND; + goto cleanup; + } + + /* + * Was this zone originally added at runtime? + * If not, we can't delete it now. + */ + if (!dns_zone_getadded(zone)) { + result = ISC_R_NOPERM; + goto cleanup; + } + + if (zonename != NULL) + znamelen = strlen(zonename); + + /* Dig out configuration for this zone */ + view = dns_zone_getview(zone); + filename = view->new_zone_file; + if (filename == NULL) { + /* No adding zones in this view */ + result = ISC_R_FAILURE; + goto cleanup; + } + + /* Rewrite zone list */ + result = isc_stdio_open(filename, "r", &ifp); + if (ifp != NULL && result == ISC_R_SUCCESS) { + char *found = NULL, *p = NULL; + size_t n; + + /* Create a temporary file */ + CHECK(isc_string_printf(buf, 1023, "%s.%ld", filename, + (long)getpid())); + if (!(tmpname = isc_mem_strdup(server->mctx, buf))) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + CHECK(isc_stdio_open(tmpname, "w", &ofp)); + + /* Look for the entry for that zone */ + while (fgets(buf, 1024, ifp)) { + /* A 'zone' line */ + if (strncasecmp(buf, "zone", 4)) { + fputs(buf, ofp); + continue; + } + p = buf+4; + + /* Locate a name */ + while (*p && + ((*p == '"') || isspace((unsigned char)*p))) + p++; + + /* Is that the zone we're looking for */ + if (strncasecmp(p, zonename, znamelen)) { + fputs(buf, ofp); + continue; + } + + /* And nothing else? */ + p += znamelen; + if (isspace((unsigned char)*p) || + *p == '"' || *p == '{') { + /* This must be the entry */ + found = p; + break; + } + + /* Spit it out, keep looking */ + fputs(buf, ofp); + } + + /* Skip over an option block (matching # of braces) */ + if (found) { + int obrace = 0, cbrace = 0; + for (;;) { + while (*p) { + if (*p == '{') obrace++; + if (*p == '}') cbrace++; + p++; + } + if (obrace && (obrace == cbrace)) + break; + if (!fgets(buf, 1024, ifp)) + break; + p = buf; + } + + /* Just spool the remainder of the file out */ + result = isc_stdio_read(buf, 1, 1024, ifp, &n); + while (n > 0U) { + if (result == ISC_R_EOF) + result = ISC_R_SUCCESS; + CHECK(result); + isc_stdio_write(buf, 1, n, ofp, NULL); + result = isc_stdio_read(buf, 1, 1024, ifp, &n); + } + + /* Move temporary into place */ + CHECK(isc_file_rename(tmpname, view->new_zone_file)); + } else { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_WARNING, + "deleted zone %s was missing from " + "new zone file", zonename); + goto cleanup; + } + } + + /* Stop answering for this zone */ + if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { + dns_db_detach(&dbp); + dns_zone_unload(zone); + } + + CHECK(dns_zt_unmount(view->zonetable, zone)); + + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "zone %s removed via delzone", zonename); + + result = ISC_R_SUCCESS; + + cleanup: + if (ifp != NULL) + isc_stdio_close(ifp); + if (ofp != NULL) { + isc_stdio_close(ofp); + isc_file_remove(tmpname); + } + if (tmpname != NULL) + isc_mem_free(server->mctx, tmpname); + if (zone != NULL) + dns_zone_detach(&zone); + + return (result); +} + +static void +cfgctx_destroy(void **cfgp) { + struct cfg_context *cfg; + isc_mem_t *mctx; + + REQUIRE(cfgp != NULL && *cfgp != NULL); + cfg = *cfgp; + mctx = cfg->mctx; + cfg->mctx = NULL; + + if (cfg->parser != NULL) { + if (cfg->config != NULL) + cfg_obj_destroy(cfg->parser, &cfg->config); + cfg_parser_destroy(&cfg->parser); + } + cfg_aclconfctx_clear(&cfg->actx); + + isc_mem_put(mctx, cfg, sizeof(*cfg)); + isc_mem_detach(&mctx); + *cfgp = NULL; +} diff --git a/contrib/bind9/bin/named/statschannel.c b/contrib/bind9/bin/named/statschannel.c index c77d3ca1bfeb..6dce8e0a77c5 100644 --- a/contrib/bind9/bin/named/statschannel.c +++ b/contrib/bind9/bin/named/statschannel.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: statschannel.c,v 1.14.64.11 2010-02-04 23:47:46 tbox Exp $ */ +/* $Id: statschannel.c,v 1.26 2010-02-04 23:49:13 tbox Exp $ */ /*! \file */ @@ -29,6 +29,7 @@ #include <isc/stats.h> #include <isc/task.h> +#include <dns/cache.h> #include <dns/db.h> #include <dns/opcode.h> #include <dns/resolver.h> @@ -823,9 +824,9 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) { TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "cache")); TRY0(xmlTextWriterWriteAttribute(writer, - ISC_XMLCHAR "name", - ISC_XMLCHAR - view->name)); + ISC_XMLCHAR "name", + ISC_XMLCHAR + dns_cache_getname(view->cache))); dumparg.result = ISC_R_SUCCESS; dns_rdatasetstats_dump(cachestats, rdatasetstats_dump, &dumparg, 0); @@ -1405,7 +1406,15 @@ ns_stats_dump(ns_server_t *server, FILE *fp) { if (strcmp(view->name, "_default") == 0) fprintf(fp, "[View: default]\n"); else - fprintf(fp, "[View: %s]\n", view->name); + fprintf(fp, "[View: %s (Cache: %s)]\n", view->name, + dns_cache_getname(view->cache)); + if (dns_view_iscacheshared(view)) { + /* + * Avoid dumping redundant statistics when the cache is + * shared. + */ + continue; + } dns_rdatasetstats_dump(cachestats, rdatasetstats_dump, &dumparg, 0); } diff --git a/contrib/bind9/bin/named/tkeyconf.c b/contrib/bind9/bin/named/tkeyconf.c index 734497803191..66c2d7f47cc9 100644 --- a/contrib/bind9/bin/named/tkeyconf.c +++ b/contrib/bind9/bin/named/tkeyconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tkeyconf.c,v 1.29 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: tkeyconf.c,v 1.33 2010-12-20 23:47:20 tbox Exp $ */ /*! \file */ @@ -77,8 +77,7 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - RETERR(dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL)); + RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY; RETERR(dst_key_fromfile(name, (dns_keytag_t) n, DNS_KEYALG_DH, type, NULL, mctx, &tctx->dhkey)); @@ -92,8 +91,7 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - RETERR(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, - NULL)); + RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); tctx->domain = isc_mem_get(mctx, sizeof(dns_name_t)); if (tctx->domain == NULL) { result = ISC_R_NOMEMORY; @@ -112,12 +110,22 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - RETERR(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, - NULL)); - RETERR(dst_gssapi_acquirecred(name, ISC_FALSE, - &tctx->gsscred)); + RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + RETERR(dst_gssapi_acquirecred(name, ISC_FALSE, &tctx->gsscred)); } + obj = NULL; + result = cfg_map_get(options, "tkey-gssapi-keytab", &obj); + if (result == ISC_R_SUCCESS) { + s = cfg_obj_asstring(obj); + tctx->gssapi_keytab = isc_mem_strdup(mctx, s); + if (tctx->gssapi_keytab == NULL) { + result = ISC_R_NOMEMORY; + goto failure; + } + } + + *tctxp = tctx; return (ISC_R_SUCCESS); diff --git a/contrib/bind9/bin/named/tsigconf.c b/contrib/bind9/bin/named/tsigconf.c index e90a86b5a783..19e8d385e05b 100644 --- a/contrib/bind9/bin/named/tsigconf.c +++ b/contrib/bind9/bin/named/tsigconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tsigconf.c,v 1.30 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: tsigconf.c,v 1.35 2011-01-11 23:47:12 tbox Exp $ */ /*! \file */ @@ -82,7 +82,7 @@ add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring, isc_buffer_add(&keynamesrc, strlen(keyid)); isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata)); ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname, - ISC_TRUE, &keynamebuf); + DNS_NAME_DOWNCASE, &keynamebuf); if (ret != ISC_R_SUCCESS) goto failure; @@ -149,6 +149,8 @@ ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, isc_result_t result; int i; + REQUIRE(ringp != NULL && *ringp == NULL); + i = 0; if (config != NULL) maps[i++] = config; @@ -176,6 +178,6 @@ ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, return (ISC_R_SUCCESS); failure: - dns_tsigkeyring_destroy(&ring); + dns_tsigkeyring_detach(&ring); return (result); } diff --git a/contrib/bind9/bin/named/unix/Makefile.in b/contrib/bind9/bin/named/unix/Makefile.in index 502db2508c98..ca92c49b5c78 100644 --- a/contrib/bind9/bin/named/unix/Makefile.in +++ b/contrib/bind9/bin/named/unix/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1999-2001 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.10 2007-06-19 23:46:59 tbox Exp $ +# $Id: Makefile.in,v 1.13 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/contrib/bind9/bin/named/unix/include/named/os.h b/contrib/bind9/bin/named/unix/include/named/os.h index 0a846080a66f..c2768f426647 100644 --- a/contrib/bind9/bin/named/unix/include/named/os.h +++ b/contrib/bind9/bin/named/unix/include/named/os.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: os.h,v 1.29 2008-10-24 01:44:48 tbox Exp $ */ +/* $Id: os.h,v 1.31 2009-08-05 23:47:43 tbox Exp $ */ #ifndef NS_OS_H #define NS_OS_H 1 @@ -51,8 +51,12 @@ ns_os_adjustnofile(void); void ns_os_minprivs(void); +FILE * +ns_os_openfile(const char *filename, mode_t mode, isc_boolean_t switch_user); + void ns_os_writepidfile(const char *filename, isc_boolean_t first_time); + void ns_os_shutdown(void); diff --git a/contrib/bind9/bin/named/unix/os.c b/contrib/bind9/bin/named/unix/os.c index 3f07784fcb82..53e9e4501249 100644 --- a/contrib/bind9/bin/named/unix/os.c +++ b/contrib/bind9/bin/named/unix/os.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: os.c,v 1.89.12.5 2009-03-02 03:03:54 marka Exp $ */ +/* $Id: os.c,v 1.104 2010-11-17 23:47:08 tbox Exp $ */ /*! \file */ @@ -291,6 +291,12 @@ linux_initialprivs(void) { */ SET_CAP(CAP_SYS_RESOURCE); + /* + * We need to be able to set the ownership of the containing + * directory of the pid file when we create it. + */ + SET_CAP(CAP_CHOWN); + linux_setcaps(caps); #ifdef HAVE_LIBCAP @@ -631,7 +637,7 @@ ns_os_minprivs(void) { } static int -safe_open(const char *filename, isc_boolean_t append) { +safe_open(const char *filename, mode_t mode, isc_boolean_t append) { int fd; struct stat sb; @@ -644,13 +650,11 @@ safe_open(const char *filename, isc_boolean_t append) { } if (append) - fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, - S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, mode); else { if (unlink(filename) < 0 && errno != ENOENT) return (-1); - fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, - S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode); } return (fd); } @@ -686,6 +690,15 @@ mkdirpath(char *filename, void (*report)(const char *, ...)) { } if (mkdirpath(filename, report) == -1) goto error; + /* + * Handle "//", "/./" and "/../" in path. + */ + if (!strcmp(slash + 1, "") || + !strcmp(slash + 1, ".") || + !strcmp(slash + 1, "..")) { + *slash = '/'; + return (0); + } mode = S_IRUSR | S_IWUSR | S_IXUSR; /* u=rwx */ mode |= S_IRGRP | S_IXGRP; /* g=rx */ mode |= S_IROTH | S_IXOTH; /* o=rx */ @@ -695,6 +708,13 @@ mkdirpath(char *filename, void (*report)(const char *, ...)) { strbuf); goto error; } + if (runas_pw != NULL && + chown(filename, runas_pw->pw_uid, + runas_pw->pw_gid) == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + (*report)("couldn't chown '%s': %s", filename, + strbuf); + } } *slash = '/'; } @@ -705,11 +725,127 @@ mkdirpath(char *filename, void (*report)(const char *, ...)) { return (-1); } +static void +setperms(uid_t uid, gid_t gid) { + char strbuf[ISC_STRERRORSIZE]; +#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) + gid_t oldgid, tmpg; +#endif +#if !defined(HAVE_SETEUID) && defined(HAVE_SETRESUID) + uid_t olduid, tmpu; +#endif +#if defined(HAVE_SETEGID) + if (getegid() != gid && setegid(gid) == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("unable to set effective gid to %ld: %s", + (long)gid, strbuf); + } +#elif defined(HAVE_SETRESGID) + if (getresgid(&tmpg, &oldgid, &tmpg) == -1 || oldgid != gid) { + if (setresgid(-1, gid, -1) == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("unable to set effective " + "gid to %d: %s", gid, strbuf); + } + } +#endif + +#if defined(HAVE_SETEUID) + if (geteuid() != uid && seteuid(uid) == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("unable to set effective uid to %ld: %s", + (long)uid, strbuf); + } +#elif defined(HAVE_SETRESUID) + if (getresuid(&tmpu, &olduid, &tmpu) == -1 || olduid != uid) { + if (setresuid(-1, uid, -1) == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("unable to set effective " + "uid to %d: %s", uid, strbuf); + } + } +#endif +} + +FILE * +ns_os_openfile(const char *filename, mode_t mode, isc_boolean_t switch_user) { + char strbuf[ISC_STRERRORSIZE], *f; + FILE *fp; + int fd; + + /* + * Make the containing directory if it doesn't exist. + */ + f = strdup(filename); + if (f == NULL) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("couldn't strdup() '%s': %s", + filename, strbuf); + return (NULL); + } + if (mkdirpath(f, ns_main_earlywarning) == -1) { + free(f); + return (NULL); + } + free(f); + + if (switch_user && runas_pw != NULL) { + /* Set UID/GID to the one we'll be running with eventually */ + setperms(runas_pw->pw_uid, runas_pw->pw_gid); + + fd = safe_open(filename, mode, ISC_FALSE); + +#ifndef HAVE_LINUXTHREADS + /* Restore UID/GID to root */ + setperms(0, 0); +#endif /* HAVE_LINUXTHREADS */ + + if (fd == -1) { +#ifndef HAVE_LINUXTHREADS + fd = safe_open(filename, mode, ISC_FALSE); + if (fd != -1) { + ns_main_earlywarning("Required root " + "permissions to open " + "'%s'.", filename); + } else { + ns_main_earlywarning("Could not open " + "'%s'.", filename); + } + ns_main_earlywarning("Please check file and " + "directory permissions " + "or reconfigure the filename."); +#else /* HAVE_LINUXTHREADS */ + ns_main_earlywarning("Could not open " + "'%s'.", filename); + ns_main_earlywarning("Please check file and " + "directory permissions " + "or reconfigure the filename."); +#endif /* HAVE_LINUXTHREADS */ + } + } else { + fd = safe_open(filename, mode, ISC_FALSE); + } + + if (fd < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("could not open file '%s': %s", + filename, strbuf); + return (NULL); + } + + fp = fdopen(fd, "w"); + if (fp == NULL) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + ns_main_earlywarning("could not fdopen() file '%s': %s", + filename, strbuf); + } + + return (fp); +} + void ns_os_writepidfile(const char *filename, isc_boolean_t first_time) { - int fd; FILE *lockfile; - size_t len; pid_t pid; char strbuf[ISC_STRERRORSIZE]; void (*report)(const char *, ...); @@ -725,40 +861,16 @@ ns_os_writepidfile(const char *filename, isc_boolean_t first_time) { if (filename == NULL) return; - len = strlen(filename); - pidfile = malloc(len + 1); + pidfile = strdup(filename); if (pidfile == NULL) { isc__strerror(errno, strbuf, sizeof(strbuf)); - (*report)("couldn't malloc '%s': %s", filename, strbuf); + (*report)("couldn't strdup() '%s': %s", filename, strbuf); return; } - /* This is safe. */ - strcpy(pidfile, filename); - - /* - * Make the containing directory if it doesn't exist. - */ - if (mkdirpath(pidfile, report) == -1) { - free(pidfile); - pidfile = NULL; - return; - } - - fd = safe_open(filename, ISC_FALSE); - if (fd < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - (*report)("couldn't open pid file '%s': %s", filename, strbuf); - free(pidfile); - pidfile = NULL; - return; - } - lockfile = fdopen(fd, "w"); + lockfile = ns_os_openfile(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, + first_time); if (lockfile == NULL) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - (*report)("could not fdopen() pid file '%s': %s", - filename, strbuf); - (void)close(fd); cleanup_pidfile(); return; } diff --git a/contrib/bind9/bin/named/update.c b/contrib/bind9/bin/named/update.c index 1504a44b5ad0..eb1ed1d64ef9 100644 --- a/contrib/bind9/bin/named/update.c +++ b/contrib/bind9/bin/named/update.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: update.c,v 1.151.12.11 2010-02-26 23:48:43 tbox Exp $ */ +/* $Id: update.c,v 1.186.16.1.2.1 2011-06-02 23:47:28 tbox Exp $ */ #include <config.h> @@ -38,6 +38,7 @@ #include <dns/message.h> #include <dns/nsec.h> #include <dns/nsec3.h> +#include <dns/private.h> #include <dns/rdataclass.h> #include <dns/rdataset.h> #include <dns/rdatasetiter.h> @@ -45,6 +46,7 @@ #include <dns/rdatatype.h> #include <dns/soa.h> #include <dns/ssu.h> +#include <dns/tsig.h> #include <dns/view.h> #include <dns/zone.h> #include <dns/zt.h> @@ -281,6 +283,47 @@ inc_stats(dns_zone_t *zone, isc_statscounter_t counter) { } /*% + * Check if we could have queried for the contents of this zone or + * if the zone is potentially updateable. + * If the zone can potentially be updated and the check failed then + * log a error otherwise we log a informational message. + */ +static isc_result_t +checkqueryacl(ns_client_t *client, dns_acl_t *queryacl, dns_name_t *zonename, + dns_acl_t *updateacl, dns_ssutable_t *ssutable) +{ + char namebuf[DNS_NAME_FORMATSIZE]; + char classbuf[DNS_RDATACLASS_FORMATSIZE]; + int level; + isc_result_t result; + + result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE); + if (result != ISC_R_SUCCESS) { + dns_name_format(zonename, namebuf, sizeof(namebuf)); + dns_rdataclass_format(client->view->rdclass, classbuf, + sizeof(classbuf)); + + level = (updateacl == NULL && ssutable == NULL) ? + ISC_LOG_INFO : ISC_LOG_ERROR; + + ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, + NS_LOGMODULE_UPDATE, level, + "update '%s/%s' denied due to allow-query", + namebuf, classbuf); + } else if (updateacl == NULL && ssutable == NULL) { + dns_name_format(zonename, namebuf, sizeof(namebuf)); + dns_rdataclass_format(client->view->rdclass, classbuf, + sizeof(classbuf)); + + result = DNS_R_REFUSED; + ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, + NS_LOGMODULE_UPDATE, ISC_LOG_INFO, + "update '%s/%s' denied", namebuf, classbuf); + } + return (result); +} + +/*% * Override the default acl logging when checking whether a client * can update the zone or whether we can forward the request to the * master based on IP address. @@ -809,6 +852,9 @@ typedef struct { /* The ssu table to check against. */ dns_ssutable_t *table; + + /* the key used for TKEY requests */ + dst_key_t *key; } ssu_check_t; static isc_result_t @@ -825,14 +871,14 @@ ssu_checkrule(void *data, dns_rdataset_t *rrset) { return (ISC_R_SUCCESS); result = dns_ssutable_checkrules(ssuinfo->table, ssuinfo->signer, ssuinfo->name, ssuinfo->tcpaddr, - rrset->type); + rrset->type, ssuinfo->key); return (result == ISC_TRUE ? ISC_R_SUCCESS : ISC_R_FAILURE); } static isc_boolean_t ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_ssutable_t *ssutable, dns_name_t *signer, - isc_netaddr_t *tcpaddr) + isc_netaddr_t *tcpaddr, dst_key_t *key) { isc_result_t result; ssu_check_t ssuinfo; @@ -841,6 +887,7 @@ ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, ssuinfo.table = ssutable; ssuinfo.signer = signer; ssuinfo.tcpaddr = tcpaddr; + ssuinfo.key = key; result = foreach_rrset(db, ver, name, ssu_checkrule, &ssuinfo); return (ISC_TF(result == ISC_R_SUCCESS)); } @@ -889,7 +936,7 @@ temp_check_rrset(dns_difftuple_t *a, dns_difftuple_t *b) { b->op == DNS_DIFFOP_EXISTS); INSIST(a->rdata.type == b->rdata.type); INSIST(dns_name_equal(&a->name, &b->name)); - if (dns_rdata_compare(&a->rdata, &b->rdata) != 0) + if (dns_rdata_casecompare(&a->rdata, &b->rdata) != 0) return (DNS_R_NXRRSET); a = ISC_LIST_NEXT(a, link); b = ISC_LIST_NEXT(b, link); @@ -917,7 +964,7 @@ temp_order(const void *av, const void *bv) { r = (b->rdata.type - a->rdata.type); if (r != 0) return (r); - r = dns_rdata_compare(&a->rdata, &b->rdata); + r = dns_rdata_casecompare(&a->rdata, &b->rdata); return (r); } @@ -1146,7 +1193,7 @@ rr_equal_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { * dns_rdata_equal() (that used dns_name_equal()), since it * would be faster. Not a priority. */ - return (dns_rdata_compare(update_rr, db_rr) == 0 ? + return (dns_rdata_casecompare(update_rr, db_rr) == 0 ? ISC_TRUE : ISC_FALSE); } @@ -1208,11 +1255,10 @@ replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { return (ISC_FALSE); INSIST(db_rr->length >= 4 && update_rr->length >= 4); /* - * Replace records added in this UPDATE request. + * Replace NSEC3PARAM records that only differ by the + * flags field. */ if (db_rr->data[0] == update_rr->data[0] && - db_rr->data[1] & DNS_NSEC3FLAG_UPDATE && - update_rr->data[1] & DNS_NSEC3FLAG_UPDATE && memcmp(db_rr->data+2, update_rr->data+2, update_rr->length - 2) == 0) return (ISC_TRUE); @@ -1293,7 +1339,7 @@ add_rr_prepare_action(void *data, rr_t *rr) { * If the update RR is a "duplicate" of the update RR, * the update should be silently ignored. */ - equal = ISC_TF(dns_rdata_compare(&rr->rdata, ctx->update_rr) == 0); + equal = ISC_TF(dns_rdata_casecompare(&rr->rdata, ctx->update_rr) == 0); if (equal && rr->ttl == ctx->update_rr_ttl) { ctx->ignore_add = ISC_TRUE; return (ISC_R_SUCCESS); @@ -1717,35 +1763,6 @@ next_active(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, return (result); } -static isc_boolean_t -has_opt_bit(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) { - isc_result_t result; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdataset_t rdataset; - isc_boolean_t has_bit = ISC_FALSE; - - dns_rdataset_init(&rdataset); - CHECK(dns_db_findrdataset(db, node, version, dns_rdatatype_nsec, - dns_rdatatype_none, 0, &rdataset, NULL)); - CHECK(dns_rdataset_first(&rdataset)); - dns_rdataset_current(&rdataset, &rdata); - has_bit = dns_nsec_typepresent(&rdata, dns_rdatatype_opt); - failure: - if (dns_rdataset_isassociated(&rdataset)) - dns_rdataset_disassociate(&rdataset); - return (has_bit); -} - -static void -set_bit(unsigned char *array, unsigned int index) { - unsigned int shift, bit; - - shift = 7 - (index % 8); - bit = 1 << shift; - - array[index / 8] |= bit; -} - /*% * Add a NSEC record for "name", recording the change in "diff". * The existing NSEC is removed. @@ -1777,24 +1794,6 @@ add_nsec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); dns_rdata_init(&rdata); CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata)); - /* - * Preserve the status of the OPT bit in the origin's NSEC record. - */ - if (dns_name_equal(dns_db_origin(db), name) && - has_opt_bit(db, ver, node)) - { - isc_region_t region; - dns_name_t next; - - dns_name_init(&next, NULL); - dns_rdata_toregion(&rdata, ®ion); - dns_name_fromregion(&next, ®ion); - isc_region_consume(®ion, next.length); - INSIST(region.length > (2 + dns_rdatatype_opt / 8) && - region.base[0] == 0 && - region.base[1] > dns_rdatatype_opt / 8); - set_bit(region.base + 2, dns_rdatatype_opt); - } dns_db_detachnode(db, &node); /* @@ -1856,44 +1855,6 @@ find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, return (result); } -static isc_boolean_t -ksk_sanity(dns_db_t *db, dns_dbversion_t *ver) { - isc_boolean_t ret = ISC_FALSE; - isc_boolean_t have_ksk = ISC_FALSE, have_nonksk = ISC_FALSE; - isc_result_t result; - dns_dbnode_t *node = NULL; - dns_rdataset_t rdataset; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdata_dnskey_t dnskey; - - dns_rdataset_init(&rdataset); - CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); - CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0, - &rdataset, NULL)); - CHECK(dns_rdataset_first(&rdataset)); - while (result == ISC_R_SUCCESS && (!have_ksk || !have_nonksk)) { - dns_rdataset_current(&rdataset, &rdata); - CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL)); - if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) - == DNS_KEYOWNER_ZONE) { - if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) - have_ksk = ISC_TRUE; - else - have_nonksk = ISC_TRUE; - } - dns_rdata_reset(&rdata); - result = dns_rdataset_next(&rdataset); - } - if (have_ksk && have_nonksk) - ret = ISC_TRUE; - failure: - if (dns_rdataset_isassociated(&rdataset)) - dns_rdataset_disassociate(&rdataset); - if (node != NULL) - dns_db_detachnode(db, &node); - return (ret); -} - /*% * Add RRSIG records for an RRset, recording the change in "diff". */ @@ -1902,7 +1863,7 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, isc_stdtime_t inception, isc_stdtime_t expire, - isc_boolean_t check_ksk) + isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly) { isc_result_t result; dns_dbnode_t *node = NULL; @@ -1910,7 +1871,7 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_rdata_t sig_rdata = DNS_RDATA_INIT; isc_buffer_t buffer; unsigned char data[1024]; /* XXX */ - unsigned int i; + unsigned int i, j; isc_boolean_t added_sig = ISC_FALSE; isc_mem_t *mctx = client->mctx; @@ -1926,13 +1887,52 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, (isc_stdtime_t) 0, &rdataset, NULL)); dns_db_detachnode(db, &node); +#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0) +#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0) +#define ALG(x) dst_key_alg(x) + + /* + * If we are honoring KSK flags then we need to check that we + * have both KSK and non-KSK keys that are not revoked per + * algorithm. + */ for (i = 0; i < nkeys; i++) { + isc_boolean_t both = ISC_FALSE; - if (check_ksk && type != dns_rdatatype_dnskey && - (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0) + if (!dst_key_isprivate(keys[i])) continue; - if (!dst_key_isprivate(keys[i])) + if (check_ksk && !REVOKE(keys[i])) { + isc_boolean_t have_ksk, have_nonksk; + if (KSK(keys[i])) { + have_ksk = ISC_TRUE; + have_nonksk = ISC_FALSE; + } else { + have_ksk = ISC_FALSE; + have_nonksk = ISC_TRUE; + } + for (j = 0; j < nkeys; j++) { + if (j == i || ALG(keys[i]) != ALG(keys[j])) + continue; + if (REVOKE(keys[j])) + continue; + if (KSK(keys[j])) + have_ksk = ISC_TRUE; + else + have_nonksk = ISC_TRUE; + both = have_ksk && have_nonksk; + if (both) + break; + } + } + + if (both) { + if (type == dns_rdatatype_dnskey) { + if (!KSK(keys[i]) && keyset_kskonly) + continue; + } else if (KSK(keys[i])) + continue; + } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) continue; /* Calculate the signature, creating a RRSIG RDATA. */ @@ -1950,7 +1950,7 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, } if (!added_sig) { update_log(client, zone, ISC_LOG_ERROR, - "found no private keys, " + "found no active private keys, " "unable to generate any signatures"); result = ISC_R_NOTFOUND; } @@ -2044,7 +2044,7 @@ add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t cut, dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, isc_stdtime_t inception, isc_stdtime_t expire, - isc_boolean_t check_ksk) + isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly) { isc_result_t result; dns_dbnode_t *node; @@ -2090,7 +2090,8 @@ add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, if (flag) continue;; result = add_sigs(client, zone, db, ver, name, type, diff, - keys, nkeys, inception, expire, check_ksk); + keys, nkeys, inception, expire, + check_ksk, keyset_kskonly); if (result != ISC_R_SUCCESS) goto cleanup_iterator; } @@ -2120,8 +2121,7 @@ add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, static isc_result_t update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *oldver, dns_dbversion_t *newver, - dns_diff_t *diff, isc_uint32_t sigvalidityinterval, - isc_boolean_t *deleted_zsk) + dns_diff_t *diff, isc_uint32_t sigvalidityinterval) { isc_result_t result; dns_difftuple_t *t; @@ -2130,7 +2130,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_diff_t sig_diff; dns_diff_t nsec_diff; dns_diff_t nsec_mindiff; - isc_boolean_t flag; + isc_boolean_t flag, build_nsec, build_nsec3; dst_key_t *zone_keys[MAXZONEKEYS]; unsigned int nkeys = 0; unsigned int i; @@ -2140,9 +2140,10 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_t rdataset; dns_dbnode_t *node = NULL; - isc_boolean_t check_ksk; + isc_boolean_t check_ksk, keyset_kskonly; isc_boolean_t unsecure; isc_boolean_t cut; + dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); dns_diff_init(client->mctx, &diffnames); dns_diff_init(client->mctx, &affected); @@ -2172,27 +2173,8 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, */ check_ksk = ISC_TF((dns_zone_getoptions(zone) & DNS_ZONEOPT_UPDATECHECKKSK) != 0); - /* - * If we are not checking the ZSK flag then all DNSKEY's are - * already signing all RRsets so we don't need to trigger special - * changes. - */ - if (*deleted_zsk && (!check_ksk || !ksk_sanity(db, oldver))) - *deleted_zsk = ISC_FALSE; - - if (check_ksk) { - check_ksk = ksk_sanity(db, newver); - if (!check_ksk && ksk_sanity(db, oldver)) - update_log(client, zone, ISC_LOG_WARNING, - "disabling update-check-ksk"); - } - - /* - * If we have deleted a ZSK and we we still have some ZSK's - * we don't need to convert the KSK's to a ZSK's. - */ - if (*deleted_zsk && check_ksk) - *deleted_zsk = ISC_FALSE; + keyset_kskonly = ISC_TF((dns_zone_getoptions(zone) & + DNS_ZONEOPT_DNSKEYKSKONLY) != 0); /* * Get the NSEC/NSEC3 TTL from the SOA MINIMUM field. @@ -2259,7 +2241,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, CHECK(add_sigs(client, zone, db, newver, name, type, &sig_diff, zone_keys, nkeys, inception, expire, - check_ksk)); + check_ksk, keyset_kskonly)); } skip: /* Skip any other updates to the same RRset. */ @@ -2289,12 +2271,11 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, "removed any orphaned NSEC records"); /* - * If we don't have a NSEC record at the origin then we need to - * update the NSEC3 records. + * See if we need to build NSEC or NSEC3 chains. */ - CHECK(rrset_exists(db, newver, dns_db_origin(db), dns_rdatatype_nsec, - 0, &flag)); - if (!flag) + CHECK(dns_private_chains(db, newver, privatetype, &build_nsec, + &build_nsec3)); + if (!build_nsec) goto update_nsec3; update_log(client, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC chain"); @@ -2398,16 +2379,25 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_rdatatype_any, 0, NULL, diff)); } else { /* - * This name is not obscured. It should have a NSEC. + * This name is not obscured. It needs to have a + * NSEC unless it is the at the origin, in which + * case it should already exist if there is a complete + * NSEC chain and if there isn't a complete NSEC chain + * we don't want to add one as that would signal that + * there is a complete NSEC chain. */ - CHECK(rrset_exists(db, newver, name, - dns_rdatatype_nsec, 0, &flag)); - if (! flag) - CHECK(add_placeholder_nsec(db, newver, name, - diff)); + if (!dns_name_equal(name, dns_db_origin(db))) { + CHECK(rrset_exists(db, newver, name, + dns_rdatatype_nsec, 0, + &flag)); + if (!flag) + CHECK(add_placeholder_nsec(db, newver, + name, diff)); + } CHECK(add_exposed_sigs(client, zone, db, newver, name, cut, diff, zone_keys, nkeys, - inception, expire, check_ksk)); + inception, expire, check_ksk, + keyset_kskonly)); } } @@ -2469,7 +2459,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, CHECK(add_sigs(client, zone, db, newver, &t->name, dns_rdatatype_nsec, &sig_diff, zone_keys, nkeys, inception, expire, - check_ksk)); + check_ksk, keyset_kskonly)); } else { INSIST(0); } @@ -2491,13 +2481,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, INSIST(ISC_LIST_EMPTY(nsec_diff.tuples)); INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples)); - /* - * Check if we have any active NSEC3 chains by looking for a - * NSEC3PARAM RRset. - */ - CHECK(rrset_exists(db, newver, dns_db_origin(db), - dns_rdatatype_nsec3param, 0, &flag)); - if (!flag) { + if (!build_nsec3) { update_log(client, zone, ISC_LOG_DEBUG(3), "no NSEC3 chains to rebuild"); goto failure; @@ -2521,6 +2505,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, isc_boolean_t ns_existed, dname_existed; isc_boolean_t ns_exists, dname_exists; + isc_boolean_t exists, existed; if (t->rdata.type == dns_rdatatype_nsec || t->rdata.type == dns_rdatatype_rrsig) { @@ -2539,7 +2524,9 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, CHECK(rrset_exists(db, newver, name, dns_rdatatype_dname, 0, &dname_exists)); - if ((ns_exists || dname_exists) == (ns_existed || dname_existed)) + exists = ns_exists || dname_exists; + existed = ns_existed || dname_existed; + if (exists == existed) goto nextname; /* * There was a delegation change. Mark all subdomains @@ -2563,14 +2550,16 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, if (!flag) { CHECK(delete_if(rrsig_p, db, newver, name, dns_rdatatype_any, 0, NULL, diff)); - CHECK(dns_nsec3_delnsec3s(db, newver, name, - &nsec_diff)); + CHECK(dns_nsec3_delnsec3sx(db, newver, name, + privatetype, &nsec_diff)); } else { CHECK(add_exposed_sigs(client, zone, db, newver, name, cut, diff, zone_keys, nkeys, - inception, expire, check_ksk)); - CHECK(dns_nsec3_addnsec3s(db, newver, name, nsecttl, - unsecure, &nsec_diff)); + inception, expire, check_ksk, + keyset_kskonly)); + CHECK(dns_nsec3_addnsec3sx(db, newver, name, nsecttl, + unsecure, privatetype, + &nsec_diff)); } } @@ -2601,7 +2590,8 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, CHECK(add_sigs(client, zone, db, newver, &t->name, dns_rdatatype_nsec3, &sig_diff, zone_keys, nkeys, - inception, expire, check_ksk)); + inception, expire, check_ksk, + keyset_kskonly)); } else { INSIST(0); } @@ -2734,6 +2724,7 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) { switch(dns_zone_gettype(zone)) { case dns_zone_master: + case dns_zone_dlz: /* * We can now fail due to a bad signature as we now know * that we are the master. @@ -2943,7 +2934,7 @@ rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, result = dns_rdataset_next(&rdataset)) { dns_rdata_t myrdata = DNS_RDATA_INIT; dns_rdataset_current(&rdataset, &myrdata); - if (!dns_rdata_compare(&myrdata, rdata)) + if (!dns_rdata_casecompare(&myrdata, rdata)) break; } dns_rdataset_disassociate(&rdataset); @@ -2961,7 +2952,9 @@ rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, } static isc_result_t -get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) { +get_iterations(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype, + unsigned int *iterationsp) +{ dns_dbnode_t *node = NULL; dns_rdata_nsec3param_t nsec3param; dns_rdataset_t rdataset; @@ -2975,7 +2968,33 @@ get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) { return (result); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0, (isc_stdtime_t) 0, &rdataset, NULL); - dns_db_detachnode(db, &node); + if (result == ISC_R_NOTFOUND) + goto try_private; + if (result != ISC_R_SUCCESS) + goto failure; + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(&rdataset, &rdata); + CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); + if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) + continue; + if (nsec3param.iterations > iterations) + iterations = nsec3param.iterations; + } + if (result != ISC_R_NOMORE) + goto failure; + + dns_rdataset_disassociate(&rdataset); + + try_private: + if (privatetype == 0) + goto success; + + result = dns_db_findrdataset(db, node, ver, privatetype, + 0, (isc_stdtime_t) 0, &rdataset, NULL); if (result == ISC_R_NOTFOUND) goto success; if (result != ISC_R_SUCCESS) @@ -2984,8 +3003,14 @@ get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) { for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + dns_rdata_t private = DNS_RDATA_INIT; dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(&rdataset, &rdata); + if (!dns_nsec3param_fromprivate(&private, &rdata, + buf, sizeof(buf))) + continue; CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) continue; @@ -3000,6 +3025,8 @@ get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) { result = ISC_R_SUCCESS; failure: + if (node != NULL) + dns_db_detachnode(db, &node); if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); return (result); @@ -3013,77 +3040,83 @@ static isc_result_t check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff) { - dns_diff_t temp_diff; - dns_diffop_t op; - dns_difftuple_t *tuple, *newtuple = NULL, *next; - isc_boolean_t flag; + dns_difftuple_t *tuple; + isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE; isc_result_t result; unsigned int iterations = 0, max; + dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); - dns_diff_init(diff->mctx, &temp_diff); - - CHECK(dns_nsec_nseconly(db, ver, &flag)); + /* Scan the tuples for an NSEC-only DNSKEY or an NSEC3PARAM */ + for (tuple = ISC_LIST_HEAD(diff->tuples); + tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) { + if (tuple->op != DNS_DIFFOP_ADD) + continue; - if (flag) - CHECK(dns_nsec3_active(db, ver, ISC_FALSE, &flag)); - if (flag) { - update_log(client, zone, ISC_LOG_WARNING, - "NSEC only DNSKEYs and NSEC3 chains not allowed"); - } else { - CHECK(get_iterations(db, ver, &iterations)); - CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max)); - if (max != 0 && iterations > max) { - flag = ISC_TRUE; - update_log(client, zone, ISC_LOG_WARNING, - "too many NSEC3 iterations (%u) for " - "weakest DNSKEY (%u)", iterations, max); + if (tuple->rdata.type == dns_rdatatype_dnskey) { + isc_uint8_t alg; + alg = tuple->rdata.data[3]; + if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 || + alg == DST_ALG_DSA || alg == DST_ALG_ECC) { + nseconly = ISC_TRUE; + break; + } + } else if (tuple->rdata.type == dns_rdatatype_nsec3param) { + nsec3 = ISC_TRUE; + break; } } - if (flag) { - for (tuple = ISC_LIST_HEAD(diff->tuples); - tuple != NULL; - tuple = next) { - next = ISC_LIST_NEXT(tuple, link); - if (tuple->rdata.type != dns_rdatatype_dnskey && - tuple->rdata.type != dns_rdatatype_nsec3param) - continue; - op = (tuple->op == DNS_DIFFOP_DEL) ? - DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; - CHECK(dns_difftuple_create(temp_diff.mctx, op, - &tuple->name, tuple->ttl, - &tuple->rdata, &newtuple)); - CHECK(do_one_tuple(&newtuple, db, ver, &temp_diff)); - INSIST(newtuple == NULL); - } - for (tuple = ISC_LIST_HEAD(temp_diff.tuples); - tuple != NULL; - tuple = ISC_LIST_HEAD(temp_diff.tuples)) { - ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); - dns_diff_appendminimal(diff, &tuple); - } + + /* Check existing DB for NSEC-only DNSKEY */ + if (!nseconly) + CHECK(dns_nsec_nseconly(db, ver, &nseconly)); + + /* Check existing DB for NSEC3 */ + if (!nsec3) + CHECK(dns_nsec3_activex(db, ver, ISC_FALSE, + privatetype, &nsec3)); + + /* Refuse to allow NSEC3 with NSEC-only keys */ + if (nseconly && nsec3) { + update_log(client, zone, ISC_LOG_ERROR, + "NSEC only DNSKEYs and NSEC3 chains not allowed"); + result = DNS_R_REFUSED; + goto failure; } + /* Verify NSEC3 params */ + CHECK(get_iterations(db, ver, privatetype, &iterations)); + CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max)); + if (max != 0 && iterations > max) { + update_log(client, zone, ISC_LOG_ERROR, + "too many NSEC3 iterations (%u) for " + "weakest DNSKEY (%u)", iterations, max); + result = DNS_R_REFUSED; + goto failure; + } failure: - dns_diff_clear(&temp_diff); return (result); } -#ifdef ALLOW_NSEC3PARAM_UPDATE /* * Delay NSEC3PARAM changes as they need to be applied to the whole zone. */ static isc_result_t add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, - dns_name_t *name, dns_dbversion_t *ver, dns_diff_t *diff) + dns_dbversion_t *ver, dns_diff_t *diff) { isc_result_t result = ISC_R_SUCCESS; dns_difftuple_t *tuple, *newtuple = NULL, *next; dns_rdata_t rdata = DNS_RDATA_INIT; - unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE + 1]; dns_diff_t temp_diff; dns_diffop_t op; isc_boolean_t flag; + dns_name_t *name = dns_zone_getorigin(zone); + dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); + isc_uint32_t ttl = 0; + isc_boolean_t ttl_good = ISC_FALSE; update_log(client, zone, ISC_LOG_DEBUG(3), "checking for NSEC3PARAM changes"); @@ -3106,55 +3139,143 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, ISC_LIST_APPEND(temp_diff.tuples, tuple, link); } + /* + * Extract TTL changes pairs, we don't need to convert these to + * delayed changes. + */ for (tuple = ISC_LIST_HEAD(temp_diff.tuples); tuple != NULL; tuple = next) { - if (tuple->op == DNS_DIFFOP_ADD) { + if (!ttl_good) { + /* + * Any adds here will contain the final + * NSEC3PARAM RRset TTL. + */ + ttl = tuple->ttl; + ttl_good = ISC_TRUE; + } + /* + * Walk the temp_diff list looking for the + * corresponding delete. + */ + next = ISC_LIST_HEAD(temp_diff.tuples); + while (next != NULL) { + unsigned char *next_data = next->rdata.data; + unsigned char *tuple_data = tuple->rdata.data; + if (next->op == DNS_DIFFOP_DEL && + next->rdata.length == tuple->rdata.length && + !memcmp(next_data, tuple_data, + next->rdata.length)) { + ISC_LIST_UNLINK(temp_diff.tuples, next, + link); + ISC_LIST_APPEND(diff->tuples, next, + link); + break; + } + next = ISC_LIST_NEXT(next, link); + } + /* + * If we have not found a pair move onto the next + * tuple. + */ + if (next == NULL) { + next = ISC_LIST_NEXT(tuple, link); + continue; + } + /* + * Find the next tuple to be processed before + * unlinking then complete moving the pair to 'diff'. + */ + next = ISC_LIST_NEXT(tuple, link); + ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); + ISC_LIST_APPEND(diff->tuples, tuple, link); + } else next = ISC_LIST_NEXT(tuple, link); + } + + /* + * Preserve any ongoing changes from a BIND 9.6.x upgrade. + * + * Any NSEC3PARAM records with flags other than OPTOUT named + * in managing and should not be touched so revert such changes + * taking into account any TTL change of the NSEC3PARAM RRset. + */ + for (tuple = ISC_LIST_HEAD(temp_diff.tuples); + tuple != NULL; tuple = next) { + next = ISC_LIST_NEXT(tuple, link); + if ((tuple->rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) { + /* + * If we havn't had any adds then the tuple->ttl must + * be the original ttl and should be used for any + * future changes. + */ + if (!ttl_good) { + ttl = tuple->ttl; + ttl_good = ISC_TRUE; + } + op = (tuple->op == DNS_DIFFOP_DEL) ? + DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; + CHECK(dns_difftuple_create(diff->mctx, op, name, + ttl, &tuple->rdata, + &newtuple)); + CHECK(do_one_tuple(&newtuple, db, ver, diff)); + ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); + dns_diff_appendminimal(diff, &tuple); + } + } + + /* + * We now have just the actual changes to the NSEC3PARAM RRset. + * Convert the adds to delayed adds and the deletions into delayed + * deletions. + */ + for (tuple = ISC_LIST_HEAD(temp_diff.tuples); + tuple != NULL; tuple = next) { + /* + * If we havn't had any adds then the tuple->ttl must be the + * original ttl and should be used for any future changes. + */ + if (!ttl_good) { + ttl = tuple->ttl; + ttl_good = ISC_TRUE; + } + if (tuple->op == DNS_DIFFOP_ADD) { + /* + * Look for any deletes which match this ADD ignoring + * OPTOUT. We don't need to explictly remove them as + * they will be removed a side effect of processing + * the add. + */ + next = ISC_LIST_HEAD(temp_diff.tuples); while (next != NULL) { unsigned char *next_data = next->rdata.data; unsigned char *tuple_data = tuple->rdata.data; - if (next_data[0] != tuple_data[0] || - /* Ignore flags. */ + if (next->op != DNS_DIFFOP_DEL || + next->rdata.length != tuple->rdata.length || + next_data[0] != tuple_data[0] || next_data[2] != tuple_data[2] || next_data[3] != tuple_data[3] || - next_data[4] != tuple_data[4] || - !memcmp(&next_data[5], &tuple_data[5], - tuple_data[4])) { + memcmp(next_data + 4, tuple_data + 4, + tuple->rdata.length - 4)) { next = ISC_LIST_NEXT(next, link); continue; } - op = (next->op == DNS_DIFFOP_DEL) ? - DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; - CHECK(dns_difftuple_create(diff->mctx, op, - name, next->ttl, - &next->rdata, - &newtuple)); - CHECK(do_one_tuple(&newtuple, db, ver, diff)); ISC_LIST_UNLINK(temp_diff.tuples, next, link); - dns_diff_appendminimal(diff, &next); - next = ISC_LIST_NEXT(tuple, link); + ISC_LIST_APPEND(diff->tuples, next, link); + next = ISC_LIST_HEAD(temp_diff.tuples); } - - INSIST(tuple->rdata.data[1] & DNS_NSEC3FLAG_UPDATE); - /* * See if we already have a CREATE request in progress. */ - dns_rdata_clone(&tuple->rdata, &rdata); - INSIST(rdata.length <= sizeof(buf)); - memcpy(buf, rdata.data, rdata.length); - buf[1] |= DNS_NSEC3FLAG_CREATE; - buf[1] &= ~DNS_NSEC3FLAG_UPDATE; - rdata.data = buf; - + dns_nsec3param_toprivate(&tuple->rdata, &rdata, + privatetype, buf, sizeof(buf)); + buf[2] |= DNS_NSEC3FLAG_CREATE; CHECK(rr_exists(db, ver, name, &rdata, &flag)); if (!flag) { CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, - name, tuple->ttl, - &rdata, + name, 0, &rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); } @@ -3164,26 +3285,26 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, * otherwise indentical chain with a reversed * OPTOUT state. */ - buf[1] ^= DNS_NSEC3FLAG_OPTOUT; + buf[2] ^= DNS_NSEC3FLAG_OPTOUT; CHECK(rr_exists(db, ver, name, &rdata, &flag)); if (flag) { CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, - name, tuple->ttl, - &rdata, + name, 0, &rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); } /* - * Remove the temporary add record. + * Find the next tuple to be processed and remove the + * temporary add record. */ + next = ISC_LIST_NEXT(tuple, link); CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, - name, tuple->ttl, - &tuple->rdata, &newtuple)); + name, ttl, &tuple->rdata, + &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); - next = ISC_LIST_NEXT(tuple, link); ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); dns_diff_appendminimal(diff, &tuple); dns_rdata_reset(&rdata); @@ -3191,50 +3312,33 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, next = ISC_LIST_NEXT(tuple, link); } - /* - * Reverse any pending changes. - */ for (tuple = ISC_LIST_HEAD(temp_diff.tuples); tuple != NULL; tuple = next) { - next = ISC_LIST_NEXT(tuple, link); - if ((tuple->rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) { - op = (tuple->op == DNS_DIFFOP_DEL) ? - DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; - CHECK(dns_difftuple_create(diff->mctx, op, name, - tuple->ttl, &tuple->rdata, - &newtuple)); - CHECK(do_one_tuple(&newtuple, db, ver, diff)); - ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); - dns_diff_appendminimal(diff, &tuple); - } - } - /* - * Convert deletions into delayed deletions. - */ - for (tuple = ISC_LIST_HEAD(temp_diff.tuples); - tuple != NULL; tuple = next) { + INSIST(ttl_good); + next = ISC_LIST_NEXT(tuple, link); /* * See if we already have a REMOVE request in progress. */ - dns_rdata_clone(&tuple->rdata, &rdata); - INSIST(rdata.length <= sizeof(buf)); - memcpy(buf, rdata.data, rdata.length); - buf[1] |= DNS_NSEC3FLAG_REMOVE; - rdata.data = buf; + dns_nsec3param_toprivate(&tuple->rdata, &rdata, privatetype, + buf, sizeof(buf)); + + buf[2] |= DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC; CHECK(rr_exists(db, ver, name, &rdata, &flag)); + if (!flag) { + buf[2] &= ~DNS_NSEC3FLAG_NONSEC; + CHECK(rr_exists(db, ver, name, &rdata, &flag)); + } if (!flag) { CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, - name, tuple->ttl, &rdata, - &newtuple)); + name, 0, &rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); } CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, - tuple->ttl, &tuple->rdata, - &newtuple)); + ttl, &tuple->rdata, &newtuple)); CHECK(do_one_tuple(&newtuple, db, ver, diff)); ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); dns_diff_appendminimal(diff, &tuple); @@ -3246,17 +3350,75 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_diff_clear(&temp_diff); return (result); } -#endif + +static isc_result_t +rollback_private(dns_db_t *db, dns_rdatatype_t privatetype, + dns_dbversion_t *ver, dns_diff_t *diff) +{ + dns_diff_t temp_diff; + dns_diffop_t op; + dns_difftuple_t *tuple, *newtuple = NULL, *next; + dns_name_t *name = dns_db_origin(db); + isc_mem_t *mctx = diff->mctx; + isc_result_t result; + + if (privatetype == 0) + return (ISC_R_SUCCESS); + + dns_diff_init(mctx, &temp_diff); + + /* + * Extract the changes to be rolled back. + */ + for (tuple = ISC_LIST_HEAD(diff->tuples); + tuple != NULL; tuple = next) { + + next = ISC_LIST_NEXT(tuple, link); + + if (tuple->rdata.type != privatetype || + !dns_name_equal(name, &tuple->name)) + continue; + + /* + * Allow records which indicate that a zone has been + * signed with a DNSKEY to be be removed. + */ + if (tuple->op == DNS_DIFFOP_DEL && + tuple->rdata.length == 5 && + tuple->rdata.data[0] != 0 && + tuple->rdata.data[4] != 0) + continue; + + ISC_LIST_UNLINK(diff->tuples, tuple, link); + ISC_LIST_PREPEND(temp_diff.tuples, tuple, link); + } + + /* + * Rollback the changes. + */ + while ((tuple = ISC_LIST_HEAD(temp_diff.tuples)) != NULL) { + op = (tuple->op == DNS_DIFFOP_DEL) ? + DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; + CHECK(dns_difftuple_create(mctx, op, name, tuple->ttl, + &tuple->rdata, &newtuple)); + CHECK(do_one_tuple(&newtuple, db, ver, &temp_diff)); + } + result = ISC_R_SUCCESS; + + failure: + dns_diff_clear(&temp_diff); + return (result); +} /* * Add records to cause the delayed signing of the zone by added DNSKEY * to remove the RRSIG records generated by a deleted DNSKEY. */ static isc_result_t -add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver, - dns_rdatatype_t privatetype, dns_diff_t *diff) +add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype, + dns_dbversion_t *ver, dns_diff_t *diff) { - dns_difftuple_t *tuple, *newtuple = NULL; + dns_difftuple_t *tuple, *newtuple = NULL, *next; dns_rdata_dnskey_t dnskey; dns_rdata_t rdata = DNS_RDATA_INIT; isc_boolean_t flag; @@ -3264,13 +3426,82 @@ add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver, isc_result_t result = ISC_R_SUCCESS; isc_uint16_t keyid; unsigned char buf[5]; + dns_name_t *name = dns_db_origin(db); + dns_diff_t temp_diff; + + dns_diff_init(diff->mctx, &temp_diff); + /* + * Extract the DNSKEY tuples from the list. + */ for (tuple = ISC_LIST_HEAD(diff->tuples); - tuple != NULL; - tuple = ISC_LIST_NEXT(tuple, link)) { + tuple != NULL; tuple = next) { + + next = ISC_LIST_NEXT(tuple, link); + if (tuple->rdata.type != dns_rdatatype_dnskey) continue; + ISC_LIST_UNLINK(diff->tuples, tuple, link); + ISC_LIST_APPEND(temp_diff.tuples, tuple, link); + } + + /* + * Extract TTL changes pairs, we don't need signing records for these. + */ + for (tuple = ISC_LIST_HEAD(temp_diff.tuples); + tuple != NULL; tuple = next) { + if (tuple->op == DNS_DIFFOP_ADD) { + /* + * Walk the temp_diff list looking for the + * corresponding delete. + */ + next = ISC_LIST_HEAD(temp_diff.tuples); + while (next != NULL) { + unsigned char *next_data = next->rdata.data; + unsigned char *tuple_data = tuple->rdata.data; + if (next->op == DNS_DIFFOP_DEL && + dns_name_equal(&tuple->name, &next->name) && + next->rdata.length == tuple->rdata.length && + !memcmp(next_data, tuple_data, + next->rdata.length)) { + ISC_LIST_UNLINK(temp_diff.tuples, next, + link); + ISC_LIST_APPEND(diff->tuples, next, + link); + break; + } + next = ISC_LIST_NEXT(next, link); + } + /* + * If we have not found a pair move onto the next + * tuple. + */ + if (next == NULL) { + next = ISC_LIST_NEXT(tuple, link); + continue; + } + /* + * Find the next tuple to be processed before + * unlinking then complete moving the pair to 'diff'. + */ + next = ISC_LIST_NEXT(tuple, link); + ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); + ISC_LIST_APPEND(diff->tuples, tuple, link); + } else + next = ISC_LIST_NEXT(tuple, link); + } + + /* + * Process the remaining DNSKEY entries. + */ + for (tuple = ISC_LIST_HEAD(temp_diff.tuples); + tuple != NULL; + tuple = ISC_LIST_HEAD(temp_diff.tuples)) { + + ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); + ISC_LIST_APPEND(diff->tuples, tuple, link); + dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) @@ -3278,6 +3509,7 @@ add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver, continue; dns_rdata_toregion(&tuple->rdata, &r); + keyid = dst_region_computeid(&r, dnskey.algorithm); buf[0] = dnskey.algorithm; @@ -3310,87 +3542,25 @@ add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver, INSIST(newtuple == NULL); } } + failure: + dns_diff_clear(&temp_diff); return (result); } -#ifdef ALLOW_NSEC3PARAM_UPDATE -/* - * Mark all NSEC3 chains for deletion without creating a NSEC chain as - * a side effect of deleting the last chain. - */ -static isc_result_t -delete_chains(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, - dns_diff_t *diff) -{ - dns_dbnode_t *node = NULL; - dns_difftuple_t *tuple = NULL; - dns_name_t next; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdataset_t rdataset; - isc_boolean_t flag; - isc_result_t result = ISC_R_SUCCESS; - unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; - - dns_name_init(&next, NULL); - dns_rdataset_init(&rdataset); - - result = dns_db_getoriginnode(db, &node); - if (result != ISC_R_SUCCESS) - return (result); - - /* - * Cause all NSEC3 chains to be deleted. - */ - result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, - 0, (isc_stdtime_t) 0, &rdataset, NULL); - if (result == ISC_R_NOTFOUND) - goto success; - if (result != ISC_R_SUCCESS) - goto failure; - - for (result = dns_rdataset_first(&rdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(&rdataset)) { - dns_rdataset_current(&rdataset, &rdata); - INSIST(rdata.length <= sizeof(buf)); - memcpy(buf, rdata.data, rdata.length); - - if (buf[1] == (DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC)) { - dns_rdata_reset(&rdata); - continue; - } - - CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, - origin, 0, &rdata, &tuple)); - CHECK(do_one_tuple(&tuple, db, ver, diff)); - INSIST(tuple == NULL); - - buf[1] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC; - rdata.data = buf; - - CHECK(rr_exists(db, ver, origin, &rdata, &flag)); +static isc_boolean_t +isdnssec(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype) { + isc_result_t result; + isc_boolean_t build_nsec, build_nsec3; - if (!flag) { - CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, - origin, 0, &rdata, &tuple)); - CHECK(do_one_tuple(&tuple, db, ver, diff)); - INSIST(tuple == NULL); - } - dns_rdata_reset(&rdata); - } - if (result != ISC_R_NOMORE) - goto failure; - success: - result = ISC_R_SUCCESS; + if (dns_db_issecure(db)) + return (ISC_TRUE); - failure: - if (dns_rdataset_isassociated(&rdataset)) - dns_rdataset_disassociate(&rdataset); - dns_db_detachnode(db, &node); - return (result); + result = dns_private_chains(db, ver, privatetype, + &build_nsec, &build_nsec3); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + return (build_nsec || build_nsec3); } -#endif static void update_action(isc_task_t *task, isc_event_t *event) { @@ -3414,15 +3584,10 @@ update_action(isc_task_t *task, isc_event_t *event) { dns_fixedname_t tmpnamefixed; dns_name_t *tmpname = NULL; unsigned int options; - isc_boolean_t deleted_zsk; dns_difftuple_t *tuple; dns_rdata_dnskey_t dnskey; -#ifdef ALLOW_NSEC3PARAM_UPDATE - unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; -#endif -#if !defined(ALLOW_SECURE_TO_INSECURE) || !defined(ALLOW_INSECURE_TO_SECURE) isc_boolean_t had_dnskey; -#endif + dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); INSIST(event->ev_type == DNS_EVENT_UPDATE); @@ -3433,6 +3598,18 @@ update_action(isc_task_t *task, isc_event_t *event) { zonename = dns_db_origin(db); zoneclass = dns_db_class(db); dns_zone_getssutable(zone, &ssutable); + + /* + * Update message processing can leak record existance information + * so check that we are allowed to query this zone. Additionally + * if we would refuse all updates for this zone we bail out here. + */ + CHECK(checkqueryacl(client, dns_zone_getqueryacl(zone), zonename, + dns_zone_getupdateacl(zone), ssutable)); + + /* + * Get old and new versions now that queryacl has been checked. + */ dns_db_currentversion(db, &oldver); CHECK(dns_db_newversion(db, &ver)); @@ -3525,7 +3702,6 @@ update_action(isc_task_t *task, isc_event_t *event) { if (result != ISC_R_NOMORE) FAIL(result); - /* * Perform the final check of the "rrset exists (value dependent)" * prerequisites. @@ -3619,31 +3795,31 @@ update_action(isc_task_t *task, isc_event_t *event) { update_class); FAIL(DNS_R_FORMERR); } + /* * draft-ietf-dnsind-simple-secure-update-01 says * "Unlike traditional dynamic update, the client * is forbidden from updating NSEC records." */ - if (dns_db_issecure(db)) { - if (rdata.type == dns_rdatatype_nsec3) { - FAILC(DNS_R_REFUSED, - "explicit NSEC3 updates are not allowed " - "in secure zones"); - } else if (rdata.type == dns_rdatatype_nsec) { - FAILC(DNS_R_REFUSED, - "explicit NSEC updates are not allowed " - "in secure zones"); - } else if (rdata.type == dns_rdatatype_rrsig && - !dns_name_equal(name, zonename)) { - FAILC(DNS_R_REFUSED, - "explicit RRSIG updates are currently " - "not supported in secure zones except " - "at the apex"); - } + if (rdata.type == dns_rdatatype_nsec3) { + FAILC(DNS_R_REFUSED, + "explicit NSEC3 updates are not allowed " + "in secure zones"); + } else if (rdata.type == dns_rdatatype_nsec) { + FAILC(DNS_R_REFUSED, + "explicit NSEC updates are not allowed " + "in secure zones"); + } else if (rdata.type == dns_rdatatype_rrsig && + !dns_name_equal(name, zonename)) { + FAILC(DNS_R_REFUSED, + "explicit RRSIG updates are currently " + "not supported in secure zones except " + "at the apex"); } if (ssutable != NULL) { isc_netaddr_t *tcpaddr, netaddr; + dst_key_t *tsigkey = NULL; /* * If this is a TCP connection then pass the * address of the client through for tcp-self @@ -3656,16 +3832,22 @@ update_action(isc_task_t *task, isc_event_t *event) { tcpaddr = &netaddr; } else tcpaddr = NULL; + + if (client->message->tsigkey != NULL) + tsigkey = client->message->tsigkey->key; + if (rdata.type != dns_rdatatype_any) { if (!dns_ssutable_checkrules(ssutable, client->signer, name, tcpaddr, - rdata.type)) + rdata.type, + tsigkey)) FAILC(DNS_R_REFUSED, "rejected by secure update"); } else { if (!ssu_checkall(db, ver, name, ssutable, - client->signer, tcpaddr)) + client->signer, tcpaddr, + tsigkey)) FAILC(DNS_R_REFUSED, "rejected by secure update"); } @@ -3774,7 +3956,14 @@ update_action(isc_task_t *task, isc_event_t *event) { soa_serial_changed = ISC_TRUE; } -#ifdef ALLOW_NSEC3PARAM_UPDATE + if (rdata.type == privatetype) { + update_log(client, zone, LOGLEVEL_PROTOCOL, + "attempt to add a private type " + "(%u) record rejected internal " + "use only", privatetype); + continue; + } + if (rdata.type == dns_rdatatype_nsec3param) { /* * Ignore attempts to add NSEC3PARAM records @@ -3788,27 +3977,7 @@ update_action(isc_task_t *task, isc_event_t *event) { "flag"); continue; } - - /* - * Set the NSEC3CHAIN creation flag. - */ - INSIST(rdata.length <= sizeof(buf)); - memcpy(buf, rdata.data, rdata.length); - buf[1] |= DNS_NSEC3FLAG_UPDATE; - rdata.data = buf; - /* - * Force the TTL to zero for NSEC3PARAM records. - */ - ttl = 0; } -#else - if (rdata.type == dns_rdatatype_nsec3param) { - update_log(client, zone, LOGLEVEL_PROTOCOL, - "attempt to add NSEC3PARAM " - "record ignored"); - continue; - }; -#endif if ((options & DNS_ZONEOPT_CHECKWILDCARD) != 0 && dns_name_internalwildcard(name)) { @@ -3885,13 +4054,6 @@ update_action(isc_task_t *task, isc_event_t *event) { dns_rdatatype_any, 0, &rdata, &diff)); } -#ifndef ALLOW_NSEC3PARAM_UPDATE - } else if (rdata.type == dns_rdatatype_nsec3param) { - update_log(client, zone, LOGLEVEL_PROTOCOL, - "attempt to delete a NSEC3PARAM " - "records ignored"); - continue; -#endif } else if (dns_name_equal(name, zonename) && (rdata.type == dns_rdatatype_soa || rdata.type == dns_rdatatype_ns)) { @@ -3920,6 +4082,9 @@ update_action(isc_task_t *task, isc_event_t *event) { &diff)); } } else if (update_class == dns_rdataclass_none) { + char namestr[DNS_NAME_FORMATSIZE]; + char typestr[DNS_RDATATYPE_FORMATSIZE]; + /* * The (name == zonename) condition appears in * RFC2136 3.4.2.4 but is missing from the pseudocode. @@ -3947,11 +4112,13 @@ update_action(isc_task_t *task, isc_event_t *event) { } } } - update_log(client, zone, - LOGLEVEL_PROTOCOL, - "deleting an RR"); - CHECK(delete_if(rr_equal_p, db, ver, name, - rdata.type, covers, &rdata, &diff)); + dns_name_format(name, namestr, sizeof(namestr)); + dns_rdatatype_format(rdata.type, typestr, + sizeof(typestr)); + update_log(client, zone, LOGLEVEL_PROTOCOL, + "deleting an RR at %s %s", namestr, typestr); + CHECK(delete_if(rr_equal_p, db, ver, name, rdata.type, + covers, &rdata, &diff)); } } if (result != ISC_R_NOMORE) @@ -3965,6 +4132,18 @@ update_action(isc_task_t *task, isc_event_t *event) { if (! ISC_LIST_EMPTY(diff.tuples)) CHECK(check_dnssec(client, zone, db, ver, &diff)); + if (! ISC_LIST_EMPTY(diff.tuples)) { + unsigned int errors = 0; + CHECK(dns_zone_nscheck(zone, db, ver, &errors)); + if (errors != 0) { + update_log(client, zone, LOGLEVEL_PROTOCOL, + "update rejected: post update name server " + "sanity check failed"); + result = DNS_R_REFUSED; + goto failure; + } + } + /* * If any changes were made, increment the SOA serial number, * update RRSIGs and NSECs (if zone is secure), and write the update @@ -3990,37 +4169,29 @@ update_action(isc_task_t *task, isc_event_t *event) { CHECK(rrset_exists(db, ver, zonename, dns_rdatatype_dnskey, 0, &has_dnskey)); -#if !defined(ALLOW_SECURE_TO_INSECURE) || !defined(ALLOW_INSECURE_TO_SECURE) - CHECK(rrset_exists(db, oldver, zonename, dns_rdatatype_dnskey, - 0, &had_dnskey)); +#define ALLOW_SECURE_TO_INSECURE(zone) \ + ((dns_zone_getoptions(zone) & DNS_ZONEOPT_SECURETOINSECURE) != 0) -#ifndef ALLOW_SECURE_TO_INSECURE - if (had_dnskey && !has_dnskey) { - update_log(client, zone, LOGLEVEL_PROTOCOL, - "update rejected: all DNSKEY records " - "removed"); - result = DNS_R_REFUSED; - goto failure; - } -#endif -#ifndef ALLOW_INSECURE_TO_SECURE - if (!had_dnskey && has_dnskey) { - update_log(client, zone, LOGLEVEL_PROTOCOL, - "update rejected: DNSKEY record added"); - result = DNS_R_REFUSED; - goto failure; + if (!ALLOW_SECURE_TO_INSECURE(zone)) { + CHECK(rrset_exists(db, oldver, zonename, + dns_rdatatype_dnskey, 0, + &had_dnskey)); + if (had_dnskey && !has_dnskey) { + update_log(client, zone, LOGLEVEL_PROTOCOL, + "update rejected: all DNSKEY " + "records removed and " + "'dnssec-secure-to-insecure' " + "not set"); + result = DNS_R_REFUSED; + goto failure; + } } -#endif -#endif - CHECK(add_signing_records(db, zonename, ver, - dns_zone_getprivatetype(zone), - &diff)); + CHECK(rollback_private(db, privatetype, ver, &diff)); + + CHECK(add_signing_records(db, privatetype, ver, &diff)); -#ifdef ALLOW_NSEC3PARAM_UPDATE - CHECK(add_nsec3param_records(client, zone, db, zonename, - ver, &diff)); -#endif + CHECK(add_nsec3param_records(client, zone, db, ver, &diff)); if (!has_dnskey) { /* @@ -4029,15 +4200,13 @@ update_action(isc_task_t *task, isc_event_t *event) { * the last signature for the DNSKEY records are * remove any NSEC chain present will also be removed. */ -#ifdef ALLOW_NSEC3PARAM_UPDATE - CHECK(delete_chains(db, ver, zonename, &diff)); -#endif - } else if (has_dnskey && dns_db_isdnssec(db)) { + CHECK(dns_nsec3param_deletechains(db, ver, zone, + &diff)); + } else if (has_dnskey && isdnssec(db, ver, privatetype)) { isc_uint32_t interval; interval = dns_zone_getsigvalidityinterval(zone); result = update_signatures(client, zone, db, oldver, - ver, &diff, interval, - &deleted_zsk); + ver, &diff, interval); if (result != ISC_R_SUCCESS) { update_log(client, zone, ISC_LOG_ERROR, @@ -4123,7 +4292,6 @@ update_action(isc_task_t *task, isc_event_t *event) { } } -#ifdef ALLOW_NSEC3PARAM_UPDATE /* * Cause the zone to add/delete NSEC3 chains for the * deferred NSEC3PARAM changes. @@ -4133,13 +4301,18 @@ update_action(isc_task_t *task, isc_event_t *event) { for (tuple = ISC_LIST_HEAD(diff.tuples); tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link)) { + unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; + dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_nsec3param_t nsec3param; - if (tuple->rdata.type != dns_rdatatype_nsec3param || + if (tuple->rdata.type != privatetype || tuple->op != DNS_DIFFOP_ADD) continue; - dns_rdata_tostruct(&tuple->rdata, &nsec3param, NULL); + if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata, + buf, sizeof(buf))) + continue; + dns_rdata_tostruct(&rdata, &nsec3param, NULL); if (nsec3param.flags == 0) continue; @@ -4150,7 +4323,6 @@ update_action(isc_task_t *task, isc_event_t *event) { dns_result_totext(result)); } } -#endif } else { update_log(client, zone, LOGLEVEL_DEBUG, "redundant request"); dns_db_closeversion(db, &ver, ISC_TRUE); diff --git a/contrib/bind9/bin/named/xfrout.c b/contrib/bind9/bin/named/xfrout.c index e61dc72efda2..b036ed14d57f 100644 --- a/contrib/bind9/bin/named/xfrout.c +++ b/contrib/bind9/bin/named/xfrout.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: xfrout.c,v 1.131.26.6 2010-05-27 23:48:18 tbox Exp $ */ +/* $Id: xfrout.c,v 1.139 2010-12-18 01:56:19 each Exp $ */ #include <config.h> @@ -40,6 +40,7 @@ #include <dns/rdataset.h> #include <dns/rdatasetiter.h> #include <dns/result.h> +#include <dns/rriterator.h> #include <dns/soa.h> #include <dns/stats.h> #include <dns/timer.h> @@ -112,43 +113,6 @@ } while (0) /**************************************************************************/ -/*% - * A db_rr_iterator_t is an iterator that iterates over an entire database, - * returning one RR at a time, in some arbitrary order. - */ - -typedef struct db_rr_iterator db_rr_iterator_t; - -/*% db_rr_iterator structure */ -struct db_rr_iterator { - isc_result_t result; - dns_db_t *db; - dns_dbiterator_t *dbit; - dns_dbversion_t *ver; - isc_stdtime_t now; - dns_dbnode_t *node; - dns_fixedname_t fixedname; - dns_rdatasetiter_t *rdatasetit; - dns_rdataset_t rdataset; - dns_rdata_t rdata; -}; - -static isc_result_t -db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver, - isc_stdtime_t now); - -static isc_result_t -db_rr_iterator_first(db_rr_iterator_t *it); - -static isc_result_t -db_rr_iterator_next(db_rr_iterator_t *it); - -static void -db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name, - isc_uint32_t *ttl, dns_rdata_t **rdata); - -static void -db_rr_iterator_destroy(db_rr_iterator_t *it); static inline void inc_stats(dns_zone_t *zone, isc_statscounter_t counter) { @@ -160,145 +124,6 @@ inc_stats(dns_zone_t *zone, isc_statscounter_t counter) { } } -static isc_result_t -db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver, - isc_stdtime_t now) -{ - isc_result_t result; - it->db = db; - it->dbit = NULL; - it->ver = ver; - it->now = now; - it->node = NULL; - result = dns_db_createiterator(it->db, 0, &it->dbit); - if (result != ISC_R_SUCCESS) - return (result); - it->rdatasetit = NULL; - dns_rdata_init(&it->rdata); - dns_rdataset_init(&it->rdataset); - dns_fixedname_init(&it->fixedname); - INSIST(! dns_rdataset_isassociated(&it->rdataset)); - it->result = ISC_R_SUCCESS; - return (it->result); -} - -static isc_result_t -db_rr_iterator_first(db_rr_iterator_t *it) { - it->result = dns_dbiterator_first(it->dbit); - /* - * The top node may be empty when out of zone glue exists. - * Walk the tree to find the first node with data. - */ - while (it->result == ISC_R_SUCCESS) { - it->result = dns_dbiterator_current(it->dbit, &it->node, - dns_fixedname_name(&it->fixedname)); - if (it->result != ISC_R_SUCCESS) - return (it->result); - - it->result = dns_db_allrdatasets(it->db, it->node, - it->ver, it->now, - &it->rdatasetit); - if (it->result != ISC_R_SUCCESS) - return (it->result); - - it->result = dns_rdatasetiter_first(it->rdatasetit); - if (it->result != ISC_R_SUCCESS) { - /* - * This node is empty. Try next node. - */ - dns_rdatasetiter_destroy(&it->rdatasetit); - dns_db_detachnode(it->db, &it->node); - it->result = dns_dbiterator_next(it->dbit); - continue; - } - dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); - it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; - it->result = dns_rdataset_first(&it->rdataset); - return (it->result); - } - return (it->result); -} - - -static isc_result_t -db_rr_iterator_next(db_rr_iterator_t *it) { - if (it->result != ISC_R_SUCCESS) - return (it->result); - - INSIST(it->dbit != NULL); - INSIST(it->node != NULL); - INSIST(it->rdatasetit != NULL); - - it->result = dns_rdataset_next(&it->rdataset); - if (it->result == ISC_R_NOMORE) { - dns_rdataset_disassociate(&it->rdataset); - it->result = dns_rdatasetiter_next(it->rdatasetit); - /* - * The while loop body is executed more than once - * only when an empty dbnode needs to be skipped. - */ - while (it->result == ISC_R_NOMORE) { - dns_rdatasetiter_destroy(&it->rdatasetit); - dns_db_detachnode(it->db, &it->node); - it->result = dns_dbiterator_next(it->dbit); - if (it->result == ISC_R_NOMORE) { - /* We are at the end of the entire database. */ - return (it->result); - } - if (it->result != ISC_R_SUCCESS) - return (it->result); - it->result = dns_dbiterator_current(it->dbit, - &it->node, - dns_fixedname_name(&it->fixedname)); - if (it->result != ISC_R_SUCCESS) - return (it->result); - it->result = dns_db_allrdatasets(it->db, it->node, - it->ver, it->now, - &it->rdatasetit); - if (it->result != ISC_R_SUCCESS) - return (it->result); - it->result = dns_rdatasetiter_first(it->rdatasetit); - } - if (it->result != ISC_R_SUCCESS) - return (it->result); - dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); - it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER; - it->result = dns_rdataset_first(&it->rdataset); - if (it->result != ISC_R_SUCCESS) - return (it->result); - } - return (it->result); -} - -static void -db_rr_iterator_pause(db_rr_iterator_t *it) { - RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS); -} - -static void -db_rr_iterator_destroy(db_rr_iterator_t *it) { - if (dns_rdataset_isassociated(&it->rdataset)) - dns_rdataset_disassociate(&it->rdataset); - if (it->rdatasetit != NULL) - dns_rdatasetiter_destroy(&it->rdatasetit); - if (it->node != NULL) - dns_db_detachnode(it->db, &it->node); - dns_dbiterator_destroy(&it->dbit); -} - -static void -db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name, - isc_uint32_t *ttl, dns_rdata_t **rdata) -{ - REQUIRE(name != NULL && *name == NULL); - REQUIRE(it->result == ISC_R_SUCCESS); - *name = dns_fixedname_name(&it->fixedname); - *ttl = it->rdataset.ttl; - dns_rdata_reset(&it->rdata); - dns_rdataset_current(&it->rdataset, &it->rdata); - *rdata = &it->rdata; -} - /**************************************************************************/ /*% Log an RR (for debugging) */ @@ -488,7 +313,7 @@ static rrstream_methods_t ixfr_rrstream_methods = { typedef struct axfr_rrstream { rrstream_t common; - db_rr_iterator_t it; + dns_rriterator_t it; isc_boolean_t it_valid; } axfr_rrstream_t; @@ -516,7 +341,7 @@ axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver, s->common.methods = &axfr_rrstream_methods; s->it_valid = ISC_FALSE; - CHECK(db_rr_iterator_init(&s->it, db, ver, 0)); + CHECK(dns_rriterator_init(&s->it, db, ver, 0)); s->it_valid = ISC_TRUE; *sp = (rrstream_t *) s; @@ -531,7 +356,7 @@ static isc_result_t axfr_rrstream_first(rrstream_t *rs) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; isc_result_t result; - result = db_rr_iterator_first(&s->it); + result = dns_rriterator_first(&s->it); if (result != ISC_R_SUCCESS) return (result); /* Skip SOA records. */ @@ -539,11 +364,11 @@ axfr_rrstream_first(rrstream_t *rs) { dns_name_t *name_dummy = NULL; isc_uint32_t ttl_dummy; dns_rdata_t *rdata = NULL; - db_rr_iterator_current(&s->it, &name_dummy, - &ttl_dummy, &rdata); + dns_rriterator_current(&s->it, &name_dummy, + &ttl_dummy, NULL, &rdata); if (rdata->type != dns_rdatatype_soa) break; - result = db_rr_iterator_next(&s->it); + result = dns_rriterator_next(&s->it); if (result != ISC_R_SUCCESS) break; } @@ -560,11 +385,11 @@ axfr_rrstream_next(rrstream_t *rs) { dns_name_t *name_dummy = NULL; isc_uint32_t ttl_dummy; dns_rdata_t *rdata = NULL; - result = db_rr_iterator_next(&s->it); + result = dns_rriterator_next(&s->it); if (result != ISC_R_SUCCESS) break; - db_rr_iterator_current(&s->it, &name_dummy, - &ttl_dummy, &rdata); + dns_rriterator_current(&s->it, &name_dummy, + &ttl_dummy, NULL, &rdata); if (rdata->type != dns_rdatatype_soa) break; } @@ -576,20 +401,20 @@ axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, dns_rdata_t **rdata) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; - db_rr_iterator_current(&s->it, name, ttl, rdata); + dns_rriterator_current(&s->it, name, ttl, NULL, rdata); } static void axfr_rrstream_pause(rrstream_t *rs) { axfr_rrstream_t *s = (axfr_rrstream_t *) rs; - db_rr_iterator_pause(&s->it); + dns_rriterator_pause(&s->it); } static void axfr_rrstream_destroy(rrstream_t **rsp) { axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp; if (s->it_valid) - db_rr_iterator_destroy(&s->it); + dns_rriterator_destroy(&s->it); isc_mem_put(s->common.mctx, s, sizeof(*s)); } @@ -1038,6 +863,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { switch(dns_zone_gettype(zone)) { case dns_zone_master: case dns_zone_slave: + case dns_zone_dlz: break; /* Master and slave zones are OK for transfer. */ default: FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); diff --git a/contrib/bind9/bin/named/zoneconf.c b/contrib/bind9/bin/named/zoneconf.c index 367ddd320d2c..eb93f1bbe45b 100644 --- a/contrib/bind9/bin/named/zoneconf.c +++ b/contrib/bind9/bin/named/zoneconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.c,v 1.147.50.2 2009-01-29 23:47:44 tbox Exp $ */ +/* $Id: zoneconf.c,v 1.170 2011-01-06 23:47:00 tbox Exp $ */ /*% */ @@ -30,10 +30,16 @@ #include <isc/util.h> #include <dns/acl.h> +#include <dns/db.h> #include <dns/fixedname.h> #include <dns/log.h> #include <dns/name.h> +#include <dns/rdata.h> #include <dns/rdatatype.h> +#include <dns/rdataset.h> +#include <dns/rdatalist.h> +#include <dns/result.h> +#include <dns/sdlz.h> #include <dns/ssu.h> #include <dns/stats.h> #include <dns/view.h> @@ -55,16 +61,18 @@ typedef enum { allow_update_forwarding } acl_type_t; -/*% - * These are BIND9 server defaults, not necessarily identical to the - * library defaults defined in zone.c. - */ #define RETERR(x) do { \ isc_result_t _r = (x); \ if (_r != ISC_R_SUCCESS) \ return (_r); \ } while (0) +#define CHECK(x) do { \ + result = (x); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + /*% * Convenience function for configuring a single zone ACL. */ @@ -133,8 +141,11 @@ configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, } /* Check for default ACLs that haven't been parsed yet */ - if (vconfig != NULL) - maps[i++] = cfg_tuple_get(vconfig, "options"); + if (vconfig != NULL) { + const cfg_obj_t *options = cfg_tuple_get(vconfig, "options"); + if (options != NULL) + maps[i++] = options; + } if (config != NULL) { const cfg_obj_t *options = NULL; (void)cfg_map_get(config, "options", &options); @@ -169,19 +180,29 @@ parse_acl: * Parse the zone update-policy statement. */ static isc_result_t -configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { +configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, + const char *zname) +{ const cfg_obj_t *updatepolicy = NULL; const cfg_listelt_t *element, *element2; dns_ssutable_t *table = NULL; isc_mem_t *mctx = dns_zone_getmctx(zone); + isc_boolean_t autoddns = ISC_FALSE; isc_result_t result; (void)cfg_map_get(zconfig, "update-policy", &updatepolicy); + if (updatepolicy == NULL) { dns_zone_setssutable(zone, NULL); return (ISC_R_SUCCESS); } + if (cfg_obj_isstring(updatepolicy) && + strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) { + autoddns = ISC_TRUE; + updatepolicy = NULL; + } + result = dns_ssutable_create(mctx, &table); if (result != ISC_R_SUCCESS) return (result); @@ -198,6 +219,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types"); const char *str; isc_boolean_t grant = ISC_FALSE; + isc_boolean_t usezone = ISC_FALSE; unsigned int mtype = DNS_SSUMATCHTYPE_NAME; dns_fixedname_t fname, fident; isc_buffer_t b; @@ -237,6 +259,11 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { mtype = DNS_SSUMATCHTYPE_TCPSELF; else if (strcasecmp(str, "6to4-self") == 0) mtype = DNS_SSUMATCHTYPE_6TO4SELF; + else if (strcasecmp(str, "zonesub") == 0) { + mtype = DNS_SSUMATCHTYPE_SUBDOMAIN; + usezone = ISC_TRUE; + } else if (strcasecmp(str, "external") == 0) + mtype = DNS_SSUMATCHTYPE_EXTERNAL; else INSIST(0); @@ -245,7 +272,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(dns_fixedname_name(&fident), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); @@ -253,15 +280,27 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { } dns_fixedname_init(&fname); - str = cfg_obj_asstring(dname); - isc_buffer_init(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - result = dns_name_fromtext(dns_fixedname_name(&fname), &b, - dns_rootname, ISC_FALSE, NULL); - if (result != ISC_R_SUCCESS) { - cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, - "'%s' is not a valid name", str); - goto cleanup; + if (usezone) { + result = dns_name_copy(dns_zone_getorigin(zone), + dns_fixedname_name(&fname), + NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, + "error copying origin: %s", + isc_result_totext(result)); + goto cleanup; + } + } else { + str = cfg_obj_asstring(dname); + isc_buffer_init(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + result = dns_name_fromtext(dns_fixedname_name(&fname), + &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, + "'%s' is not a valid name", str); + goto cleanup; + } } n = ns_config_listcount(typelist); @@ -311,7 +350,34 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { if (result != ISC_R_SUCCESS) { goto cleanup; } + } + + /* + * If "update-policy local;" and a session key exists, + * then use the default policy, which is equivalent to: + * update-policy { grant <session-keyname> zonesub any; }; + */ + if (autoddns) { + dns_rdatatype_t any = dns_rdatatype_any; + + if (ns_g_server->session_keyname == NULL) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed to enable auto DDNS policy " + "for zone %s: session key not found", + zname); + result = ISC_R_NOTFOUND; + goto cleanup; + } + result = dns_ssutable_addrule(table, ISC_TRUE, + ns_g_server->session_keyname, + DNS_SSUMATCHTYPE_SUBDOMAIN, + dns_zone_getorigin(zone), + 1, &any); + + if (result != ISC_R_SUCCESS) + goto cleanup; } result = ISC_R_SUCCESS; @@ -322,6 +388,323 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) { return (result); } +/* + * This is the TTL used for internally generated RRsets for static-stub zones. + * The value doesn't matter because the mapping is static, but needs to be + * defined for the sake of implementation. + */ +#define STATICSTUB_SERVER_TTL 86400 + +/*% + * Configure an apex NS with glues for a static-stub zone. + * For example, for the zone named "example.com", the following RRs will be + * added to the zone DB: + * example.com. NS example.com. + * example.com. A 192.0.2.1 + * example.com. AAAA 2001:db8::1 + */ +static isc_result_t +configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone, + dns_rdatalist_t *rdatalist_ns, + dns_rdatalist_t *rdatalist_a, + dns_rdatalist_t *rdatalist_aaaa) +{ + const cfg_listelt_t *element; + isc_mem_t *mctx = dns_zone_getmctx(zone); + isc_region_t region, sregion; + dns_rdata_t *rdata; + isc_result_t result = ISC_R_SUCCESS; + + for (element = cfg_list_first(zconfig); + element != NULL; + element = cfg_list_next(element)) + { + const isc_sockaddr_t* sa; + isc_netaddr_t na; + const cfg_obj_t *address = cfg_listelt_value(element); + dns_rdatalist_t *rdatalist; + + sa = cfg_obj_assockaddr(address); + if (isc_sockaddr_getport(sa) != 0) { + cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, + "port is not configurable for " + "static stub server-addresses"); + return (ISC_R_FAILURE); + } + isc_netaddr_fromsockaddr(&na, sa); + if (isc_netaddr_getzone(&na) != 0) { + cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, + "scoped address is not allowed " + "for static stub " + "server-addresses"); + return (ISC_R_FAILURE); + } + + switch (na.family) { + case AF_INET: + region.length = sizeof(na.type.in); + rdatalist = rdatalist_a; + break; + default: + INSIST(na.family == AF_INET6); + region.length = sizeof(na.type.in6); + rdatalist = rdatalist_aaaa; + break; + } + + rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length); + if (rdata == NULL) + return (ISC_R_NOMEMORY); + region.base = (unsigned char *)(rdata + 1); + memcpy(region.base, &na.type, region.length); + dns_rdata_init(rdata); + dns_rdata_fromregion(rdata, dns_zone_getclass(zone), + rdatalist->type, ®ion); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + } + + /* + * If no address is specified (unlikely in this context, but possible), + * there's nothing to do anymore. + */ + if (ISC_LIST_EMPTY(rdatalist_a->rdata) && + ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) { + return (ISC_R_SUCCESS); + } + + /* Add to the list an apex NS with the ns name being the origin name */ + dns_name_toregion(dns_zone_getorigin(zone), &sregion); + rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); + if (rdata == NULL) { + /* + * Already allocated data will be freed in the caller, so + * we can simply return here. + */ + return (ISC_R_NOMEMORY); + } + region.length = sregion.length; + region.base = (unsigned char *)(rdata + 1); + memcpy(region.base, sregion.base, region.length); + dns_rdata_init(rdata); + dns_rdata_fromregion(rdata, dns_zone_getclass(zone), + dns_rdatatype_ns, ®ion); + ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link); + + return (result); +} + +/*% + * Configure an apex NS with an out-of-zone NS names for a static-stub zone. + * For example, for the zone named "example.com", something like the following + * RRs will be added to the zone DB: + * example.com. NS ns.example.net. + */ +static isc_result_t +configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone, + dns_rdatalist_t *rdatalist, const char *zname) +{ + const cfg_listelt_t *element; + isc_mem_t *mctx = dns_zone_getmctx(zone); + dns_rdata_t *rdata; + isc_region_t sregion, region; + isc_result_t result = ISC_R_SUCCESS; + + for (element = cfg_list_first(zconfig); + element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *obj; + const char *str; + dns_fixedname_t fixed_name; + dns_name_t *nsname; + isc_buffer_t b; + + obj = cfg_listelt_value(element); + str = cfg_obj_asstring(obj); + + dns_fixedname_init(&fixed_name); + nsname = dns_fixedname_name(&fixed_name); + + isc_buffer_init(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, + "server-name '%s' is not a valid " + "name", str); + return (result); + } + if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) { + cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, + "server-name '%s' must not be a " + "subdomain of zone name '%s'", + str, zname); + return (ISC_R_FAILURE); + } + + dns_name_toregion(nsname, &sregion); + rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); + if (rdata == NULL) + return (ISC_R_NOMEMORY); + region.length = sregion.length; + region.base = (unsigned char *)(rdata + 1); + memcpy(region.base, sregion.base, region.length); + dns_rdata_init(rdata); + dns_rdata_fromregion(rdata, dns_zone_getclass(zone), + dns_rdatatype_ns, ®ion); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + } + + return (result); +} + +/*% + * Configure static-stub zone. + */ +static isc_result_t +configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone, + const char *zname, const char *dbtype) +{ + int i = 0; + const cfg_obj_t *obj; + isc_mem_t *mctx = dns_zone_getmctx(zone); + dns_db_t *db = NULL; + dns_dbversion_t *dbversion = NULL; + dns_dbnode_t *apexnode = NULL; + dns_name_t apexname; + isc_result_t result; + dns_rdataset_t rdataset; + dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa; + dns_rdatalist_t* rdatalists[] = { + &rdatalist_ns, &rdatalist_a, &rdatalist_aaaa, NULL + }; + dns_rdata_t *rdata; + isc_region_t region; + + /* Create the DB beforehand */ + RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone), + dns_dbtype_stub, dns_zone_getclass(zone), + 0, NULL, &db)); + dns_zone_setdb(zone, db); + + dns_rdatalist_init(&rdatalist_ns); + rdatalist_ns.rdclass = dns_zone_getclass(zone); + rdatalist_ns.type = dns_rdatatype_ns; + rdatalist_ns.ttl = STATICSTUB_SERVER_TTL; + + dns_rdatalist_init(&rdatalist_a); + rdatalist_a.rdclass = dns_zone_getclass(zone); + rdatalist_a.type = dns_rdatatype_a; + rdatalist_a.ttl = STATICSTUB_SERVER_TTL; + + dns_rdatalist_init(&rdatalist_aaaa); + rdatalist_aaaa.rdclass = dns_zone_getclass(zone); + rdatalist_aaaa.type = dns_rdatatype_aaaa; + rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL; + + /* Prepare zone RRs from the configuration */ + obj = NULL; + result = cfg_map_get(zconfig, "server-addresses", &obj); + if (obj != NULL) { + result = configure_staticstub_serveraddrs(obj, zone, + &rdatalist_ns, + &rdatalist_a, + &rdatalist_aaaa); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + + obj = NULL; + result = cfg_map_get(zconfig, "server-names", &obj); + if (obj != NULL) { + result = configure_staticstub_servernames(obj, zone, + &rdatalist_ns, + zname); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + + /* + * Sanity check: there should be at least one NS RR at the zone apex + * to trigger delegation. + */ + if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "No NS record is configured for a " + "static-stub zone '%s'", zname); + result = ISC_R_FAILURE; + goto cleanup; + } + + /* + * Now add NS and glue A/AAAA RRsets to the zone DB. + * First open a new version for the add operation and get a pointer + * to the apex node (all RRs are of the apex name). + */ + result = dns_db_newversion(db, &dbversion); + if (result != ISC_R_SUCCESS) + goto cleanup; + dns_name_init(&apexname, NULL); + dns_name_clone(dns_zone_getorigin(zone), &apexname); + result = dns_db_findnode(db, &apexname, ISC_FALSE, &apexnode); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Add NS RRset */ + dns_rdataset_init(&rdataset); + RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset) + == ISC_R_SUCCESS); + result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, + 0, NULL); + dns_rdataset_disassociate(&rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Add glue A RRset, if any */ + if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) { + RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_a, &rdataset) + == ISC_R_SUCCESS); + result = dns_db_addrdataset(db, apexnode, dbversion, 0, + &rdataset, 0, NULL); + dns_rdataset_disassociate(&rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + + /* Add glue AAAA RRset, if any */ + if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) { + RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_aaaa, + &rdataset) + == ISC_R_SUCCESS); + result = dns_db_addrdataset(db, apexnode, dbversion, 0, + &rdataset, 0, NULL); + dns_rdataset_disassociate(&rdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + } + + result = ISC_R_SUCCESS; + + cleanup: + if (apexnode != NULL) + dns_db_detachnode(db, &apexnode); + if (dbversion != NULL) + dns_db_closeversion(db, &dbversion, ISC_TRUE); + if (db != NULL) + dns_db_detach(&db); + for (i = 0; rdatalists[i] != NULL; i++) { + while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) { + ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link); + dns_rdata_toregion(rdata, ®ion); + isc_mem_put(mctx, rdata, + sizeof(*rdata) + region.length); + } + } + + return (result); +} + /*% * Convert a config file zone type into a server zone type. */ @@ -503,6 +886,19 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, if (result == ISC_R_SUCCESS) filename = cfg_obj_asstring(obj); + /* + * Unless we're using some alternative database, a master zone + * will be needing a master file. + */ + if (ztype == dns_zone_master && cpval == default_dbtype && + filename == NULL) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "zone '%s': 'file' not specified", + zname); + return (ISC_R_FAILURE); + } + masterformat = dns_masterformat_text; obj = NULL; result= ns_config_get(maps, "masterfile-format", &obj); @@ -577,7 +973,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, * to primary masters (type "master") and slaves * acting as masters (type "slave"), but not to stubs. */ - if (ztype != dns_zone_stub) { + if (ztype != dns_zone_stub && ztype != dns_zone_staticstub) { obj = NULL; result = ns_config_get(maps, "notify", &obj); INSIST(result == ISC_R_SUCCESS); @@ -731,6 +1127,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, */ if (ztype == dns_zone_master) { dns_acl_t *updateacl; + RETERR(configure_zone_acl(zconfig, vconfig, config, allow_update, ac, zone, dns_zone_setupdateacl, @@ -744,7 +1141,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, "address, which is insecure", zname); - RETERR(configure_zone_ssutable(zoptions, zone)); + RETERR(configure_zone_ssutable(zoptions, zone, zname)); obj = NULL; result = ns_config_get(maps, "sig-validity-interval", &obj); @@ -774,12 +1171,6 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, result = ns_config_get(maps, "key-directory", &obj); if (result == ISC_R_SUCCESS) { filename = cfg_obj_asstring(obj); - if (!isc_file_isabsolute(filename)) { - cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, - "key-directory '%s' " - "is not absolute", filename); - return (ISC_R_FAILURE); - } RETERR(dns_zone_setkeydirectory(zone, filename)); } @@ -804,6 +1195,11 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK, cfg_obj_asboolean(obj)); + obj = NULL; + result = ns_config_get(maps, "dnssec-dnskey-kskonly", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY, + cfg_obj_asboolean(obj)); } else if (ztype == dns_zone_slave) { RETERR(configure_zone_acl(zconfig, vconfig, config, allow_update_forwarding, ac, zone, @@ -811,11 +1207,13 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, dns_zone_clearforwardacl)); } - /*% * Primary master functionality. */ if (ztype == dns_zone_master) { + isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE; + isc_boolean_t create = ISC_FALSE; + obj = NULL; result = ns_config_get(maps, "check-wildcard", &obj); if (result == ISC_R_SUCCESS) @@ -825,6 +1223,21 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, dns_zone_setoption(zone, DNS_ZONEOPT_CHECKWILDCARD, check); obj = NULL; + result = ns_config_get(maps, "check-dup-records", &obj); + INSIST(obj != NULL); + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + fail = ISC_FALSE; + check = ISC_TRUE; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + fail = check = ISC_TRUE; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + fail = check = ISC_FALSE; + } else + INSIST(0); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRR, check); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRRFAIL, fail); + + obj = NULL; result = ns_config_get(maps, "check-mx", &obj); INSIST(obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { @@ -874,6 +1287,31 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, INSIST(0); dns_zone_setoption(zone, DNS_ZONEOPT_WARNSRVCNAME, warn); dns_zone_setoption(zone, DNS_ZONEOPT_IGNORESRVCNAME, ignore); + + obj = NULL; + result = ns_config_get(maps, "dnssec-secure-to-insecure", &obj); + INSIST(obj != NULL); + dns_zone_setoption(zone, DNS_ZONEOPT_SECURETOINSECURE, + cfg_obj_asboolean(obj)); + + obj = NULL; + result = cfg_map_get(zoptions, "auto-dnssec", &obj); + if (result == ISC_R_SUCCESS) { + const char *arg = cfg_obj_asstring(obj); + if (strcasecmp(arg, "allow") == 0) + allow = ISC_TRUE; + else if (strcasecmp(arg, "maintain") == 0) + allow = maint = ISC_TRUE; + else if (strcasecmp(arg, "create") == 0) + allow = maint = create = ISC_TRUE; + else if (strcasecmp(arg, "off") == 0) + ; + else + INSIST(0); + dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow); + dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint); + dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, create); + } } /* @@ -982,6 +1420,11 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, cfg_obj_asboolean(obj)); break; + case dns_zone_staticstub: + RETERR(configure_staticstub(zoptions, zone, zname, + default_dbtype)); + break; + default: break; } @@ -989,6 +1432,31 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, return (ISC_R_SUCCESS); } + +#ifdef DLZ +/* + * Set up a DLZ zone as writeable + */ +isc_result_t +ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, + dns_rdataclass_t rdclass, dns_name_t *name) +{ + dns_db_t *db = NULL; + isc_time_t now; + isc_result_t result; + + TIME_NOW(&now); + + dns_zone_settype(zone, dns_zone_dlz); + result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db); + if (result != ISC_R_SUCCESS) + return result; + result = dns_zone_dlzpostload(zone, db); + dns_db_detach(&db); + return result; +} +#endif + isc_boolean_t ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { const cfg_obj_t *zoptions = NULL; @@ -1001,6 +1469,13 @@ ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { if (zonetype_fromconfig(zoptions) != dns_zone_gettype(zone)) return (ISC_FALSE); + /* + * We always reconfigure a static-stub zone for simplicity, assuming + * the amount of data to be loaded is small. + */ + if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) + return (ISC_FALSE); + obj = NULL; (void)cfg_map_get(zoptions, "file", &obj); if (obj != NULL) diff --git a/contrib/bind9/bin/nsupdate/Makefile.in b/contrib/bind9/bin/nsupdate/Makefile.in index f7f6346c9d6b..a65aad9162ed 100644 --- a/contrib/bind9/bin/nsupdate/Makefile.in +++ b/contrib/bind9/bin/nsupdate/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2006-2008 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2006-2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2000-2002 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.29 2008-08-29 23:47:22 tbox Exp $ +# $Id: Makefile.in,v 1.36 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -24,7 +24,7 @@ top_srcdir = @top_srcdir@ @BIND9_MAKE_INCLUDES@ CINCLUDES = ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \ - ${ISC_INCLUDES} @DST_GSSAPI_INC@ + ${ISC_INCLUDES} ${ISCCFG_INCLUDES} @DST_GSSAPI_INC@ CDEFINES = @USE_GSSAPI@ CWARNINGS = @@ -33,6 +33,7 @@ LWRESLIBS = ../../lib/lwres/liblwres.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ @@ -43,7 +44,9 @@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} ${ISCCFGDEPLIBS} -LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCLIBS} ${ISCCFGLIBS} @LIBS@ +LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ + +NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${ISCNOSYMLIBS} @LIBS@ SUBDIRS = @@ -63,8 +66,14 @@ MANOBJS = ${MANPAGES} ${HTMLPAGES} @BIND9_MAKE_RULES@ +nsupdate.@O@: nsupdate.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DSESSION_KEYFILE=\"${localstatedir}/run/named/session.key\" \ + -c ${srcdir}/nsupdate.c + nsupdate@EXEEXT@: nsupdate.@O@ ${UOBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ nsupdate.@O@ ${UOBJS} ${LIBS} + export BASEOBJS="nsupdate.@O@ ${UOBJS}"; \ + ${FINALBUILDCMD} doc man:: ${MANOBJS} diff --git a/contrib/bind9/bin/nsupdate/nsupdate.1 b/contrib/bind9/bin/nsupdate/nsupdate.1 index 6c03486559ef..9d82891dda9f 100644 --- a/contrib/bind9/bin/nsupdate/nsupdate.1 +++ b/contrib/bind9/bin/nsupdate/nsupdate.1 @@ -13,18 +13,18 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: nsupdate.1,v 1.3.48.4 2010-07-10 02:06:17 tbox Exp $ +.\" $Id: nsupdate.1,v 1.13 2010-07-10 01:14:19 tbox Exp $ .\" .hy 0 .ad l .\" Title: nsupdate .\" Author: .\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/> -.\" Date: Jun 30, 2000 +.\" Date: Aug 25, 2009 .\" Manual: BIND9 .\" Source: BIND9 .\" -.TH "NSUPDATE" "1" "Jun 30, 2000" "BIND9" "BIND9" +.TH "NSUPDATE" "1" "Aug 25, 2009" "BIND9" "BIND9" .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) @@ -33,11 +33,11 @@ nsupdate \- Dynamic DNS update utility .SH "SYNOPSIS" .HP 9 -\fBnsupdate\fR [\fB\-d\fR] [\fB\-D\fR] [[\fB\-g\fR] | [\fB\-o\fR] | [\fB\-y\ \fR\fB\fI[hmac:]\fR\fIkeyname:secret\fR\fR] | [\fB\-k\ \fR\fB\fIkeyfile\fR\fR]] [\fB\-t\ \fR\fB\fItimeout\fR\fR] [\fB\-u\ \fR\fB\fIudptimeout\fR\fR] [\fB\-r\ \fR\fB\fIudpretries\fR\fR] [\fB\-R\ \fR\fB\fIrandomdev\fR\fR] [\fB\-v\fR] [filename] +\fBnsupdate\fR [\fB\-d\fR] [\fB\-D\fR] [[\fB\-g\fR] | [\fB\-o\fR] | [\fB\-l\fR] | [\fB\-y\ \fR\fB\fI[hmac:]\fR\fIkeyname:secret\fR\fR] | [\fB\-k\ \fR\fB\fIkeyfile\fR\fR]] [\fB\-t\ \fR\fB\fItimeout\fR\fR] [\fB\-u\ \fR\fB\fIudptimeout\fR\fR] [\fB\-r\ \fR\fB\fIudpretries\fR\fR] [\fB\-R\ \fR\fB\fIrandomdev\fR\fR] [\fB\-v\fR] [filename] .SH "DESCRIPTION" .PP \fBnsupdate\fR -is used to submit Dynamic DNS Update requests as defined in RFC2136 to a name server. This allows resource records to be added or removed from a zone without manually editing the zone file. A single update request can contain requests to add or remove more than one resource record. +is used to submit Dynamic DNS Update requests as defined in RFC 2136 to a name server. This allows resource records to be added or removed from a zone without manually editing the zone file. A single update request can contain requests to add or remove more than one resource record. .PP Zones that are under dynamic control via \fBnsupdate\fR @@ -60,7 +60,11 @@ option makes report additional debugging information to \fB\-d\fR. .PP -Transaction signatures can be used to authenticate the Dynamic DNS updates. These use the TSIG resource record type described in RFC2845 or the SIG(0) record described in RFC3535 and RFC2931 or GSS\-TSIG as described in RFC3645. TSIG relies on a shared secret that should only be known to +The +\fB\-L\fR +option with an integer argument of zero or higher sets the logging debug level. If zero, logging is disabled. +.PP +Transaction signatures can be used to authenticate the Dynamic DNS updates. These use the TSIG resource record type described in RFC 2845 or the SIG(0) record described in RFC 2535 and RFC 2931 or GSS\-TSIG as described in RFC 3645. TSIG relies on a shared secret that should only be known to \fBnsupdate\fR and the name server. Currently, the only supported encryption algorithm for TSIG is HMAC\-MD5, which is defined in RFC 2104. Once other algorithms are defined for TSIG, applications will need to ensure they select the appropriate algorithm as well as the key when authenticating each other. For instance, suitable \fBkey\fR @@ -71,22 +75,22 @@ statements would be added to so that the name server can associate the appropriate secret key and algorithm with the IP address of the client application that will be using TSIG authentication. SIG(0) uses public key cryptography. To use a SIG(0) key, the public key must be stored in a KEY record in a zone served by the name server. \fBnsupdate\fR does not read -\fI/etc/named.conf\fR. GSS\-TSIG uses Kerberos credentials. +\fI/etc/named.conf\fR. +.PP +GSS\-TSIG uses Kerberos credentials. Standard GSS\-TSIG mode is switched on with the +\fB\-g\fR +flag. A non\-standards\-compliant variant of GSS\-TSIG used by Windows 2000 can be switched on with the +\fB\-o\fR +flag. .PP \fBnsupdate\fR uses the \fB\-y\fR or \fB\-k\fR -option to provide the shared secret needed to generate a TSIG record for authenticating Dynamic DNS update requests, default type HMAC\-MD5. These options are mutually exclusive. With the -\fB\-k\fR -option, -\fBnsupdate\fR -reads the shared secret from the file -\fIkeyfile\fR, whose name is of the form -\fIK{name}.+157.+{random}.private\fR. For historical reasons, the file -\fIK{name}.+157.+{random}.key\fR -must also be present. When the +option to provide the shared secret needed to generate a TSIG record for authenticating Dynamic DNS update requests, default type HMAC\-MD5. These options are mutually exclusive. +.PP +When the \fB\-y\fR option is used, a signature is generated from [\fIhmac:\fR]\fIkeyname:secret.\fR @@ -99,17 +103,37 @@ option is discouraged because the shared secret is supplied as a command line ar \fBps\fR(1) or in a history file maintained by the user's shell. .PP -The +With the +\fB\-k\fR +option, +\fBnsupdate\fR +reads the shared secret from the file +\fIkeyfile\fR. Keyfiles may be in two formats: a single file containing a +\fInamed.conf\fR\-format +\fBkey\fR +statement, which may be generated automatically by +\fBddns\-confgen\fR, or a pair of files whose names are of the format +\fIK{name}.+157.+{random}.key\fR +and +\fIK{name}.+157.+{random}.private\fR, which can be generated by +\fBdnssec\-keygen\fR. The \fB\-k\fR may also be used to specify a SIG(0) key used to authenticate Dynamic DNS update requests. In this case, the key specified is not an HMAC\-MD5 key. .PP -The -\fB\-g\fR -and -\fB\-o\fR -specify that GSS\-TSIG is to be used. The -\fB\-o\fR -should only be used with old Microsoft Windows 2000 servers. +\fBnsupdate\fR +can be run in a local\-host only mode using the +\fB\-l\fR +flag. This sets the server address to localhost (disabling the +\fBserver\fR +so that the server address cannot be overridden). Connections to the local server will use a TSIG key found in +\fI/var/run/named/session.key\fR, which is automatically generated by +\fBnamed\fR +if any local master zone has set +\fBupdate\-policy\fR +to +\fBlocal\fR. The location of this key file can be overridden with the +\fB\-k\fR +option. .PP By default, \fBnsupdate\fR @@ -120,6 +144,10 @@ option makes use a TCP connection. This may be preferable when a batch of update requests is made. .PP The +\fB\-p\fR +sets the default port number to use for connections to a name server. The default is 53. +.PP +The \fB\-t\fR option sets the maximum time an update request can take before it is aborted. The default is 300 seconds. Zero can be used to disable the timeout. .PP @@ -367,7 +395,7 @@ with IP address 172.16.1.1 is added. The newly\-added record has a 1 day TTL (86 .sp .PP The prerequisite condition gets the name server to check that there are no resource records of any type for -\fBnickname.example.com\fR. If there are, the update request fails. If this name does not exist, a CNAME for it is added. This ensures that when the CNAME is added, it cannot conflict with the long\-standing rule in RFC1034 that a name must not exist as any other record type if it exists as a CNAME. (The rule has been updated for DNSSEC in RFC2535 to allow CNAMEs to have RRSIG, DNSKEY and NSEC records.) +\fBnickname.example.com\fR. If there are, the update request fails. If this name does not exist, a CNAME for it is added. This ensures that when the CNAME is added, it cannot conflict with the long\-standing rule in RFC 1034 that a name must not exist as any other record type if it exists as a CNAME. (The rule has been updated for DNSSEC in RFC 2535 to allow CNAMEs to have RRSIG, DNSKEY and NSEC records.) .SH "FILES" .PP \fB/etc/resolv.conf\fR @@ -375,6 +403,11 @@ The prerequisite condition gets the name server to check that there are no resou used to identify default name server .RE .PP +\fB/var/run/named/session.key\fR +.RS 4 +sets the default TSIG key for use in local\-only mode +.RE +.PP \fBK{name}.+157.+{random}.key\fR .RS 4 base\-64 encoding of HMAC\-MD5 key created by @@ -388,14 +421,15 @@ base\-64 encoding of HMAC\-MD5 key created by .RE .SH "SEE ALSO" .PP -\fBRFC2136\fR(), -\fBRFC3007\fR(), -\fBRFC2104\fR(), -\fBRFC2845\fR(), -\fBRFC1034\fR(), -\fBRFC2535\fR(), -\fBRFC2931\fR(), +RFC 2136, +RFC 3007, +RFC 2104, +RFC 2845, +RFC 1034, +RFC 2535, +RFC 2931, \fBnamed\fR(8), +\fBddns\-confgen\fR(8), \fBdnssec\-keygen\fR(8). .SH "BUGS" .PP diff --git a/contrib/bind9/bin/nsupdate/nsupdate.c b/contrib/bind9/bin/nsupdate/nsupdate.c index 69d390d3a568..ed01a47ac263 100644 --- a/contrib/bind9/bin/nsupdate/nsupdate.c +++ b/contrib/bind9/bin/nsupdate/nsupdate.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsupdate.c,v 1.163.48.15 2010-12-09 04:30:57 tbox Exp $ */ +/* $Id: nsupdate.c,v 1.193 2011-01-10 05:32:03 marka Exp $ */ /*! \file */ @@ -33,6 +33,7 @@ #include <isc/commandline.h> #include <isc/entropy.h> #include <isc/event.h> +#include <isc/file.h> #include <isc/hash.h> #include <isc/lex.h> #include <isc/log.h> @@ -50,6 +51,8 @@ #include <isc/types.h> #include <isc/util.h> +#include <isccfg/namedconf.h> + #include <dns/callbacks.h> #include <dns/dispatch.h> #include <dns/dnssec.h> @@ -78,6 +81,7 @@ #ifdef GSSAPI #include <dst/gssapi.h> +#include ISC_PLATFORM_KRB5HEADER #endif #include <bind9/getaddresses.h> @@ -106,6 +110,8 @@ extern int h_errno; #define DNSDEFAULTPORT 53 +static isc_uint16_t dnsport = DNSDEFAULTPORT; + #ifndef RESOLV_CONF #define RESOLV_CONF "/etc/resolv.conf" #endif @@ -119,6 +125,7 @@ static isc_boolean_t usevc = ISC_FALSE; static isc_boolean_t usegsstsig = ISC_FALSE; static isc_boolean_t use_win2k_gsstsig = ISC_FALSE; static isc_boolean_t tried_other_gsstsig = ISC_FALSE; +static isc_boolean_t local_only = ISC_FALSE; static isc_taskmgr_t *taskmgr = NULL; static isc_task_t *global_task = NULL; static isc_event_t *global_event = NULL; @@ -148,7 +155,8 @@ static isc_sockaddr_t *userserver = NULL; static isc_sockaddr_t *localaddr = NULL; static isc_sockaddr_t *serveraddr = NULL; static isc_sockaddr_t tempaddr; -static char *keystr = NULL, *keyfile = NULL; +static const char *keyfile = NULL; +static char *keystr = NULL; static isc_entropy_t *entropy = NULL; static isc_boolean_t shuttingdown = ISC_FALSE; static FILE *input; @@ -174,8 +182,10 @@ typedef struct nsu_requestinfo { static void sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, dns_message_t *msg, dns_request_t **request); -static void -fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +ISC_PLATFORM_NORETURN_PRE static void +fatal(const char *format, ...) +ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; static void debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); @@ -406,7 +416,7 @@ reset_system(void) { if (tsigkey != NULL) dns_tsigkey_detach(&tsigkey); if (gssring != NULL) - dns_tsigkeyring_destroy(&gssring); + dns_tsigkeyring_detach(&gssring); tried_other_gsstsig = ISC_FALSE; } } @@ -479,6 +489,19 @@ parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) { return (digestbits); } +static int +basenamelen(const char *file) { + int len = strlen(file); + + if (len > 1 && file[len - 1] == '.') + len -= 1; + else if (len > 8 && strcmp(file + len - 8, ".private") == 0) + len -= 8; + else if (len > 4 && strcmp(file + len - 4, ".key") == 0) + len -= 4; + return (len); +} + static void setup_keystr(void) { unsigned char *secret = NULL; @@ -520,8 +543,7 @@ setup_keystr(void) { isc_buffer_add(&keynamesrc, n - name); debug("namefromtext"); - result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); secretlen = strlen(secretstr) * 3 / 4; @@ -553,21 +575,67 @@ setup_keystr(void) { isc_mem_free(mctx, secret); } -static int -basenamelen(const char *file) { - int len = strlen(file); +/* + * Get a key from a named.conf format keyfile + */ +static isc_result_t +read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) { + cfg_parser_t *pctx = NULL; + cfg_obj_t *sessionkey = NULL; + const cfg_obj_t *key = NULL; + const cfg_obj_t *secretobj = NULL; + const cfg_obj_t *algorithmobj = NULL; + const char *keyname; + const char *secretstr; + const char *algorithm; + isc_result_t result; + int len; - if (len > 1 && file[len - 1] == '.') - len -= 1; - else if (len > 8 && strcmp(file + len - 8, ".private") == 0) - len -= 8; - else if (len > 4 && strcmp(file + len - 4, ".key") == 0) - len -= 4; - return (len); + if (! isc_file_exists(keyfile)) + return (ISC_R_FILENOTFOUND); + + result = cfg_parser_create(mctx, lctx, &pctx); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, + &sessionkey); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = cfg_map_get(sessionkey, "key", &key); + if (result != ISC_R_SUCCESS) + goto cleanup; + + (void) cfg_map_get(key, "secret", &secretobj); + (void) cfg_map_get(key, "algorithm", &algorithmobj); + if (secretobj == NULL || algorithmobj == NULL) + fatal("key must have algorithm and secret"); + + keyname = cfg_obj_asstring(cfg_map_getname(key)); + secretstr = cfg_obj_asstring(secretobj); + algorithm = cfg_obj_asstring(algorithmobj); + + len = strlen(algorithm) + strlen(keyname) + strlen(secretstr) + 3; + keystr = isc_mem_allocate(mctx, len); + snprintf(keystr, len, "%s:%s:%s", algorithm, keyname, secretstr); + setup_keystr(); + + cleanup: + if (pctx != NULL) { + if (sessionkey != NULL) + cfg_obj_destroy(pctx, &sessionkey); + cfg_parser_destroy(&pctx); + } + + if (keystr != NULL) + isc_mem_free(mctx, keystr); + + return (result); } static void -setup_keyfile(void) { +setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) { dst_key_t *dstkey = NULL; isc_result_t result; dns_name_t *hmacname = NULL; @@ -577,15 +645,25 @@ setup_keyfile(void) { if (sig0key != NULL) dst_key_free(&sig0key); - result = dst_key_fromnamedfile(keyfile, + /* Try reading the key from a K* pair */ + result = dst_key_fromnamedfile(keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey); + + /* If that didn't work, try reading it as a session.key keyfile */ + if (result != ISC_R_SUCCESS) { + result = read_sessionkey(mctx, lctx); + if (result == ISC_R_SUCCESS) + return; + } + if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not read key from %.*s.{private,key}: " "%s\n", basenamelen(keyfile), keyfile, isc_result_totext(result)); return; } + switch (dst_key_alg(dstkey)) { case DST_ALG_HMACMD5: hmacname = DNS_TSIG_HMACMD5_NAME; @@ -748,7 +826,7 @@ setup_system(void) { if (servers == NULL) fatal("out of memory"); localhost.s_addr = htonl(INADDR_LOOPBACK); - isc_sockaddr_fromin(&servers[0], &localhost, DNSDEFAULTPORT); + isc_sockaddr_fromin(&servers[0], &localhost, dnsport); } else { servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t)); if (servers == NULL) @@ -757,12 +835,12 @@ setup_system(void) { if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) { struct in_addr in4; memcpy(&in4, lwconf->nameservers[i].address, 4); - isc_sockaddr_fromin(&servers[i], &in4, DNSDEFAULTPORT); + isc_sockaddr_fromin(&servers[i], &in4, dnsport); } else { struct in6_addr in6; memcpy(&in6, lwconf->nameservers[i].address, 16); isc_sockaddr_fromin6(&servers[i], &in6, - DNSDEFAULTPORT); + dnsport); } } } @@ -829,8 +907,13 @@ setup_system(void) { if (keystr != NULL) setup_keystr(); - else if (keyfile != NULL) - setup_keyfile(); + else if (local_only) { + result = read_sessionkey(mctx, lctx); + if (result != ISC_R_SUCCESS) + fatal("can't read key from %s: %s\n", + keyfile, isc_result_totext(result)); + } else if (keyfile != NULL) + setup_keyfile(mctx, lctx); } static void @@ -847,7 +930,7 @@ get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) { INSIST(count == 1); } -#define PARSE_ARGS_FMT "dDMl:y:govk:rR::t:u:" +#define PARSE_ARGS_FMT "dDML:y:ghlovk:p:rR::t:u:" static void pre_parse_args(int argc, char **argv) { @@ -864,10 +947,11 @@ pre_parse_args(int argc, char **argv) { break; case '?': + case 'h': if (isc_commandline_option != '?') fprintf(stderr, "%s: invalid argument -%c\n", argv[0], isc_commandline_option); - fprintf(stderr, "usage: nsupdate [-d] " + fprintf(stderr, "usage: nsupdate [-dD] [-L level] [-l]" "[-g | -o | -y keyname:secret | -k keyfile] " "[-v] [filename]\n"); exit(1); @@ -899,6 +983,9 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) { case 'M': break; case 'l': + local_only = ISC_TRUE; + break; + case 'L': result = isc_parse_uint32(&i, isc_commandline_argument, 10); if (result != ISC_R_SUCCESS) { @@ -925,6 +1012,15 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) { usegsstsig = ISC_TRUE; use_win2k_gsstsig = ISC_TRUE; break; + case 'p': + result = isc_parse_uint16(&dnsport, + isc_commandline_argument, 10); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "bad port number " + "'%s'\n", isc_commandline_argument); + exit(1); + } + break; case 't': result = isc_parse_uint32(&timeout, isc_commandline_argument, 10); @@ -970,6 +1066,22 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) { exit(1); } + if (local_only) { + struct in_addr localhost; + + if (keyfile == NULL) + keyfile = SESSION_KEYFILE; + + if (userserver == NULL) { + userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t)); + if (userserver == NULL) + fatal("out of memory"); + } + + localhost.s_addr = htonl(INADDR_LOOPBACK); + isc_sockaddr_fromin(userserver, &localhost, dnsport); + } + #ifdef GSSAPI if (usegsstsig && (keyfile != NULL || keystr != NULL)) { fprintf(stderr, "%s: cannot specify -g with -k or -y\n", @@ -978,7 +1090,7 @@ parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) { } #else if (usegsstsig) { - fprintf(stderr, "%s: cannot specify -g or -o, " \ + fprintf(stderr, "%s: cannot specify -g or -o, " \ "program not linked with GSS API Library\n", argv[0]); exit(1); @@ -1024,8 +1136,7 @@ parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) { dns_message_takebuffer(msg, &namebuf); isc_buffer_init(&source, word, strlen(word)); isc_buffer_add(&source, strlen(word)); - result = dns_name_fromtext(*namep, &source, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); isc_buffer_invalidate(&source); return (STATUS_MORE); @@ -1227,6 +1338,11 @@ evaluate_server(char *cmdline) { char *word, *server; long port; + if (local_only) { + fprintf(stderr, "cannot reset server in localhost-only mode\n"); + return (STATUS_SYNTAX); + } + word = nsu_strsep(&cmdline, " \t\r\n"); if (*word == 0) { fprintf(stderr, "could not read server name\n"); @@ -1236,7 +1352,7 @@ evaluate_server(char *cmdline) { word = nsu_strsep(&cmdline, " \t\r\n"); if (*word == 0) - port = DNSDEFAULTPORT; + port = dnsport; else { char *endp; port = strtol(word, &endp, 10); @@ -1342,7 +1458,7 @@ evaluate_key(char *cmdline) { isc_buffer_init(&b, namestr, strlen(namestr)); isc_buffer_add(&b, strlen(namestr)); - result = dns_name_fromtext(keyname, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not parse key name\n"); return (STATUS_SYNTAX); @@ -1399,8 +1515,7 @@ evaluate_zone(char *cmdline) { userzone = dns_fixedname_name(&fuserzone); isc_buffer_init(&b, word, strlen(word)); isc_buffer_add(&b, strlen(word)); - result = dns_name_fromtext(userzone, &b, dns_rootname, ISC_FALSE, - NULL); + result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { userzone = NULL; /* Lest it point to an invalid name */ fprintf(stderr, "could not parse zone name\n"); @@ -1852,9 +1967,9 @@ get_next_command(void) { "server address [port] (set master server for zone)\n" "send (send the update request)\n" "show (show the update request)\n" -"answer (show the answer to the last request)\n" +"answer (show the answer to the last request)\n" "quit (quit, any pending update is not sent\n" -"help (display this message_\n" +"help (display this message_\n" "key [hmac:]keyname secret (use TSIG to sign the request)\n" "gsstsig (use GSS_TSIG to sign the request)\n" "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n" @@ -2015,7 +2130,7 @@ send_update(dns_name_t *zonename, isc_sockaddr_t *master, { isc_result_t result; dns_request_t *request = NULL; - unsigned int options = 0; + unsigned int options = DNS_REQUESTOPT_CASE; ddebug("send_update()"); @@ -2248,7 +2363,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) { result = dns_name_totext(&master, ISC_TRUE, &buf); check_result(result, "dns_name_totext"); serverstr[isc_buffer_usedlength(&buf)] = 0; - get_address(serverstr, DNSDEFAULTPORT, &tempaddr); + get_address(serverstr, dnsport, &tempaddr); serveraddr = &tempaddr; } dns_rdata_freestruct(&soa); @@ -2319,9 +2434,60 @@ sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, } #ifdef GSSAPI + +/* + * Get the realm from the users kerberos ticket if possible + */ static void -start_gssrequest(dns_name_t *master) +get_ticket_realm(isc_mem_t *mctx) { + krb5_context ctx; + krb5_error_code rc; + krb5_ccache ccache; + krb5_principal princ; + char *name, *ticket_realm; + + rc = krb5_init_context(&ctx); + if (rc != 0) + return; + + rc = krb5_cc_default(ctx, &ccache); + if (rc != 0) { + krb5_free_context(ctx); + return; + } + + rc = krb5_cc_get_principal(ctx, ccache, &princ); + if (rc != 0) { + krb5_cc_close(ctx, ccache); + krb5_free_context(ctx); + return; + } + + rc = krb5_unparse_name(ctx, princ, &name); + if (rc != 0) { + krb5_free_principal(ctx, princ); + krb5_cc_close(ctx, ccache); + krb5_free_context(ctx); + return; + } + + ticket_realm = strrchr(name, '@'); + if (ticket_realm != NULL) { + realm = isc_mem_strdup(mctx, ticket_realm); + } + + free(name); + krb5_free_principal(ctx, princ); + krb5_cc_close(ctx, ccache); + krb5_free_context(ctx); + if (realm != NULL && debugging) + fprintf(stderr, "Found realm from ticket: %s\n", realm+1); +} + + +static void +start_gssrequest(dns_name_t *master) { gss_ctx_id_t context; isc_buffer_t buf; isc_result_t result; @@ -2332,12 +2498,13 @@ start_gssrequest(dns_name_t *master) dns_fixedname_t fname; char namestr[DNS_NAME_FORMATSIZE]; char keystr[DNS_NAME_FORMATSIZE]; + char *err_message = NULL; debug("start_gssrequest"); usevc = ISC_TRUE; if (gssring != NULL) - dns_tsigkeyring_destroy(&gssring); + dns_tsigkeyring_detach(&gssring); gssring = NULL; result = dns_tsigkeyring_create(mctx, &gssring); @@ -2352,13 +2519,16 @@ start_gssrequest(dns_name_t *master) fatal("out of memory"); } if (userserver == NULL) - get_address(namestr, DNSDEFAULTPORT, kserver); + get_address(namestr, dnsport, kserver); else (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t)); dns_fixedname_init(&fname); servname = dns_fixedname_name(&fname); + if (realm == NULL) + get_ticket_realm(mctx); + result = isc_string_printf(servicename, sizeof(servicename), "DNS/%s%s", namestr, realm ? realm : ""); if (result != ISC_R_SUCCESS) @@ -2366,8 +2536,7 @@ start_gssrequest(dns_name_t *master) isc_result_totext(result)); isc_buffer_init(&buf, servicename, strlen(servicename)); isc_buffer_add(&buf, strlen(servicename)); - result = dns_name_fromtext(servname, &buf, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("dns_name_fromtext(servname) failed: %s", isc_result_totext(result)); @@ -2384,8 +2553,7 @@ start_gssrequest(dns_name_t *master) isc_buffer_init(&buf, keystr, strlen(keystr)); isc_buffer_add(&buf, strlen(keystr)); - result = dns_name_fromtext(keyname, &buf, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) fatal("dns_name_fromtext(keyname) failed: %s", isc_result_totext(result)); @@ -2402,9 +2570,11 @@ start_gssrequest(dns_name_t *master) /* Build first request. */ context = GSS_C_NO_CONTEXT; result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0, - &context, use_win2k_gsstsig); + &context, use_win2k_gsstsig, + mctx, &err_message); if (result == ISC_R_FAILURE) - fatal("Check your Kerberos ticket, it may have expired."); + fatal("tkey query failed: %s", + err_message != NULL ? err_message : "unknown error"); if (result != ISC_R_SUCCESS) fatal("dns_tkey_buildgssquery failed: %s", isc_result_totext(result)); @@ -2453,6 +2623,7 @@ recvgss(isc_task_t *task, isc_event_t *event) { isc_buffer_t buf; dns_name_t *servname; dns_fixedname_t fname; + char *err_message = NULL; UNUSED(task); @@ -2535,14 +2706,14 @@ recvgss(isc_task_t *task, isc_event_t *event) { servname = dns_fixedname_name(&fname); isc_buffer_init(&buf, servicename, strlen(servicename)); isc_buffer_add(&buf, strlen(servicename)); - result = dns_name_fromtext(servname, &buf, dns_rootname, - ISC_FALSE, NULL); + result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); check_result(result, "dns_name_fromtext"); tsigkey = NULL; result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, &context, &tsigkey, gssring, - use_win2k_gsstsig); + use_win2k_gsstsig, + &err_message); switch (result) { case DNS_R_CONTINUE: @@ -2585,7 +2756,9 @@ recvgss(isc_task_t *task, isc_event_t *event) { break; default: - fatal("dns_tkey_negotiategss: %s", isc_result_totext(result)); + fatal("dns_tkey_negotiategss: %s %s", + isc_result_totext(result), + err_message != NULL ? err_message : ""); } done: @@ -2695,8 +2868,8 @@ cleanup(void) { dns_tsigkey_detach(&tsigkey); } if (gssring != NULL) { - ddebug("Destroying GSS-TSIG keyring"); - dns_tsigkeyring_destroy(&gssring); + ddebug("Detaching GSS-TSIG keyring"); + dns_tsigkeyring_detach(&gssring); } if (kserver != NULL) { isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t)); diff --git a/contrib/bind9/bin/nsupdate/nsupdate.docbook b/contrib/bind9/bin/nsupdate/nsupdate.docbook index 4069a2bb2832..2a92af438dac 100644 --- a/contrib/bind9/bin/nsupdate/nsupdate.docbook +++ b/contrib/bind9/bin/nsupdate/nsupdate.docbook @@ -18,10 +18,10 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: nsupdate.docbook,v 1.34.48.5 2010-07-09 23:45:50 tbox Exp $ --> +<!-- $Id: nsupdate.docbook,v 1.44 2010-07-09 23:46:51 tbox Exp $ --> <refentry id="man.nsupdate"> <refentryinfo> - <date>Jun 30, 2000</date> + <date>Aug 25, 2009</date> </refentryinfo> <refmeta> <refentrytitle><application>nsupdate</application></refentrytitle> @@ -61,6 +61,7 @@ <group> <arg><option>-g</option></arg> <arg><option>-o</option></arg> + <arg><option>-l</option></arg> <arg><option>-y <replaceable class="parameter"><optional>hmac:</optional>keyname:secret</replaceable></option></arg> <arg><option>-k <replaceable class="parameter">keyfile</replaceable></option></arg> </group> @@ -76,7 +77,7 @@ <refsect1> <title>DESCRIPTION</title> <para><command>nsupdate</command> - is used to submit Dynamic DNS Update requests as defined in RFC2136 + is used to submit Dynamic DNS Update requests as defined in RFC 2136 to a name server. This allows resource records to be added or removed from a zone without manually editing the zone file. @@ -112,10 +113,14 @@ report additional debugging information to <option>-d</option>. </para> <para> + The <option>-L</option> option with an integer argument of zero or + higher sets the logging debug level. If zero, logging is disabled. + </para> + <para> Transaction signatures can be used to authenticate the Dynamic DNS updates. These use the TSIG resource record type described - in RFC2845 or the SIG(0) record described in RFC3535 and - RFC2931 or GSS-TSIG as described in RFC3645. TSIG relies on + in RFC 2845 or the SIG(0) record described in RFC 2535 and + RFC 2931 or GSS-TSIG as described in RFC 3645. TSIG relies on a shared secret that should only be known to <command>nsupdate</command> and the name server. Currently, the only supported encryption algorithm for TSIG is HMAC-MD5, @@ -132,46 +137,61 @@ record in a zone served by the name server. <command>nsupdate</command> does not read <filename>/etc/named.conf</filename>. - GSS-TSIG uses Kerberos credentials. + </para> + <para> + GSS-TSIG uses Kerberos credentials. Standard GSS-TSIG mode + is switched on with the <option>-g</option> flag. A + non-standards-compliant variant of GSS-TSIG used by Windows + 2000 can be switched on with the <option>-o</option> flag. </para> <para><command>nsupdate</command> uses the <option>-y</option> or <option>-k</option> option to provide the shared secret needed to generate a TSIG record for authenticating Dynamic DNS update requests, default type - HMAC-MD5. These options are mutually exclusive. With the - <option>-k</option> option, <command>nsupdate</command> reads - the shared secret from the file <parameter>keyfile</parameter>, - whose name is of the form - <filename>K{name}.+157.+{random}.private</filename>. For - historical reasons, the file - <filename>K{name}.+157.+{random}.key</filename> must also be - present. When the <option>-y</option> option is used, a - signature is generated from + HMAC-MD5. These options are mutually exclusive. + </para> + <para> + When the <option>-y</option> option is used, a signature is + generated from <optional><parameter>hmac:</parameter></optional><parameter>keyname:secret.</parameter> <parameter>keyname</parameter> is the name of the key, and - <parameter>secret</parameter> is the base64 encoded shared - secret. Use of the <option>-y</option> option is discouraged - because the shared secret is supplied as a command line - argument in clear text. This may be visible in the output - from + <parameter>secret</parameter> is the base64 encoded shared secret. + Use of the <option>-y</option> option is discouraged because the + shared secret is supplied as a command line argument in clear text. + This may be visible in the output from <citerefentry> - <refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum> - </citerefentry> or in a history file maintained by the user's - shell. + <refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum> + </citerefentry> + or in a history file maintained by the user's shell. </para> <para> + With the + <option>-k</option> option, <command>nsupdate</command> reads + the shared secret from the file <parameter>keyfile</parameter>. + Keyfiles may be in two formats: a single file containing + a <filename>named.conf</filename>-format <command>key</command> + statement, which may be generated automatically by + <command>ddns-confgen</command>, or a pair of files whose names are + of the format <filename>K{name}.+157.+{random}.key</filename> and + <filename>K{name}.+157.+{random}.private</filename>, which can be + generated by <command>dnssec-keygen</command>. The <option>-k</option> may also be used to specify a SIG(0) key used to authenticate Dynamic DNS update requests. In this case, the key specified is not an HMAC-MD5 key. </para> <para> - The <option>-g</option> and <option>-o</option> specify that - GSS-TSIG is to be used. The <option>-o</option> should only - be used with old Microsoft Windows 2000 servers. + <command>nsupdate</command> can be run in a local-host only mode + using the <option>-l</option> flag. This sets the server address to + localhost (disabling the <command>server</command> so that the server + address cannot be overridden). Connections to the local server will + use a TSIG key found in <filename>/var/run/named/session.key</filename>, + which is automatically generated by <command>named</command> if any + local master zone has set <command>update-policy</command> to + <command>local</command>. The location of this key file can be + overridden with the <option>-k</option> option. </para> <para> - By default, - <command>nsupdate</command> + By default, <command>nsupdate</command> uses UDP to send update requests to the name server unless they are too large to fit in a UDP request in which case TCP will be used. The @@ -182,6 +202,10 @@ This may be preferable when a batch of update requests is made. </para> <para> + The <option>-p</option> sets the default port number to use for + connections to a name server. The default is 53. + </para> + <para> The <option>-t</option> option sets the maximum time an update request can take before it is aborted. The default is 300 seconds. Zero can be @@ -650,9 +674,9 @@ If there are, the update request fails. If this name does not exist, a CNAME for it is added. This ensures that when the CNAME is added, it cannot conflict with the - long-standing rule in RFC1034 that a name must not exist as any other + long-standing rule in RFC 1034 that a name must not exist as any other record type if it exists as a CNAME. - (The rule has been updated for DNSSEC in RFC2535 to allow CNAMEs to have + (The rule has been updated for DNSSEC in RFC 2535 to allow CNAMEs to have RRSIG, DNSKEY and NSEC records.) </para> </refsect1> @@ -671,6 +695,15 @@ </varlistentry> <varlistentry> + <term><constant>/var/run/named/session.key</constant></term> + <listitem> + <para> + sets the default TSIG key for use in local-only mode + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><constant>K{name}.+157.+{random}.key</constant></term> <listitem> <para> @@ -699,36 +732,26 @@ <refsect1> <title>SEE ALSO</title> - <para><citerefentry> - <refentrytitle>RFC2136</refentrytitle> - </citerefentry>, - <citerefentry> - <refentrytitle>RFC3007</refentrytitle> - </citerefentry>, - <citerefentry> - <refentrytitle>RFC2104</refentrytitle> - </citerefentry>, - <citerefentry> - <refentrytitle>RFC2845</refentrytitle> - </citerefentry>, - <citerefentry> - <refentrytitle>RFC1034</refentrytitle> - </citerefentry>, - <citerefentry> - <refentrytitle>RFC2535</refentrytitle> - </citerefentry>, + <para> + <citetitle>RFC 2136</citetitle>, + <citetitle>RFC 3007</citetitle>, + <citetitle>RFC 2104</citetitle>, + <citetitle>RFC 2845</citetitle>, + <citetitle>RFC 1034</citetitle>, + <citetitle>RFC 2535</citetitle>, + <citetitle>RFC 2931</citetitle>, <citerefentry> - <refentrytitle>RFC2931</refentrytitle> + <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum> </citerefentry>, <citerefentry> - <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum> + <refentrytitle>ddns-confgen</refentrytitle><manvolnum>8</manvolnum> </citerefentry>, <citerefentry> <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum> </citerefentry>. </para> - </refsect1> + <refsect1> <title>BUGS</title> <para> diff --git a/contrib/bind9/bin/nsupdate/nsupdate.html b/contrib/bind9/bin/nsupdate/nsupdate.html index a3836175f562..f48831573e15 100644 --- a/contrib/bind9/bin/nsupdate/nsupdate.html +++ b/contrib/bind9/bin/nsupdate/nsupdate.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: nsupdate.html,v 1.40.48.4 2010-07-10 02:06:17 tbox Exp $ --> +<!-- $Id: nsupdate.html,v 1.50 2010-07-10 01:14:19 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> @@ -29,12 +29,12 @@ </div> <div class="refsynopsisdiv"> <h2>Synopsis</h2> -<div class="cmdsynopsis"><p><code class="command">nsupdate</code> [<code class="option">-d</code>] [<code class="option">-D</code>] [[<code class="option">-g</code>] | [<code class="option">-o</code>] | [<code class="option">-y <em class="replaceable"><code>[<span class="optional">hmac:</span>]keyname:secret</code></em></code>] | [<code class="option">-k <em class="replaceable"><code>keyfile</code></em></code>]] [<code class="option">-t <em class="replaceable"><code>timeout</code></em></code>] [<code class="option">-u <em class="replaceable"><code>udptimeout</code></em></code>] [<code class="option">-r <em class="replaceable"><code>udpretries</code></em></code>] [<code class="option">-R <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-v</code>] [filename]</p></div> +<div class="cmdsynopsis"><p><code class="command">nsupdate</code> [<code class="option">-d</code>] [<code class="option">-D</code>] [[<code class="option">-g</code>] | [<code class="option">-o</code>] | [<code class="option">-l</code>] | [<code class="option">-y <em class="replaceable"><code>[<span class="optional">hmac:</span>]keyname:secret</code></em></code>] | [<code class="option">-k <em class="replaceable"><code>keyfile</code></em></code>]] [<code class="option">-t <em class="replaceable"><code>timeout</code></em></code>] [<code class="option">-u <em class="replaceable"><code>udptimeout</code></em></code>] [<code class="option">-r <em class="replaceable"><code>udpretries</code></em></code>] [<code class="option">-R <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-v</code>] [filename]</p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543452"></a><h2>DESCRIPTION</h2> +<a name="id2543457"></a><h2>DESCRIPTION</h2> <p><span><strong class="command">nsupdate</strong></span> - is used to submit Dynamic DNS Update requests as defined in RFC2136 + is used to submit Dynamic DNS Update requests as defined in RFC 2136 to a name server. This allows resource records to be added or removed from a zone without manually editing the zone file. @@ -70,10 +70,14 @@ report additional debugging information to <code class="option">-d</code>. </p> <p> + The <code class="option">-L</code> option with an integer argument of zero or + higher sets the logging debug level. If zero, logging is disabled. + </p> +<p> Transaction signatures can be used to authenticate the Dynamic DNS updates. These use the TSIG resource record type described - in RFC2845 or the SIG(0) record described in RFC3535 and - RFC2931 or GSS-TSIG as described in RFC3645. TSIG relies on + in RFC 2845 or the SIG(0) record described in RFC 2535 and + RFC 2931 or GSS-TSIG as described in RFC 3645. TSIG relies on a shared secret that should only be known to <span><strong class="command">nsupdate</strong></span> and the name server. Currently, the only supported encryption algorithm for TSIG is HMAC-MD5, @@ -90,44 +94,59 @@ record in a zone served by the name server. <span><strong class="command">nsupdate</strong></span> does not read <code class="filename">/etc/named.conf</code>. - GSS-TSIG uses Kerberos credentials. + </p> +<p> + GSS-TSIG uses Kerberos credentials. Standard GSS-TSIG mode + is switched on with the <code class="option">-g</code> flag. A + non-standards-compliant variant of GSS-TSIG used by Windows + 2000 can be switched on with the <code class="option">-o</code> flag. </p> <p><span><strong class="command">nsupdate</strong></span> uses the <code class="option">-y</code> or <code class="option">-k</code> option to provide the shared secret needed to generate a TSIG record for authenticating Dynamic DNS update requests, default type - HMAC-MD5. These options are mutually exclusive. With the - <code class="option">-k</code> option, <span><strong class="command">nsupdate</strong></span> reads - the shared secret from the file <em class="parameter"><code>keyfile</code></em>, - whose name is of the form - <code class="filename">K{name}.+157.+{random}.private</code>. For - historical reasons, the file - <code class="filename">K{name}.+157.+{random}.key</code> must also be - present. When the <code class="option">-y</code> option is used, a - signature is generated from + HMAC-MD5. These options are mutually exclusive. + </p> +<p> + When the <code class="option">-y</code> option is used, a signature is + generated from [<span class="optional"><em class="parameter"><code>hmac:</code></em></span>]<em class="parameter"><code>keyname:secret.</code></em> <em class="parameter"><code>keyname</code></em> is the name of the key, and - <em class="parameter"><code>secret</code></em> is the base64 encoded shared - secret. Use of the <code class="option">-y</code> option is discouraged - because the shared secret is supplied as a command line - argument in clear text. This may be visible in the output - from - <span class="citerefentry"><span class="refentrytitle">ps</span>(1)</span> or in a history file maintained by the user's - shell. + <em class="parameter"><code>secret</code></em> is the base64 encoded shared secret. + Use of the <code class="option">-y</code> option is discouraged because the + shared secret is supplied as a command line argument in clear text. + This may be visible in the output from + <span class="citerefentry"><span class="refentrytitle">ps</span>(1)</span> + or in a history file maintained by the user's shell. </p> <p> + With the + <code class="option">-k</code> option, <span><strong class="command">nsupdate</strong></span> reads + the shared secret from the file <em class="parameter"><code>keyfile</code></em>. + Keyfiles may be in two formats: a single file containing + a <code class="filename">named.conf</code>-format <span><strong class="command">key</strong></span> + statement, which may be generated automatically by + <span><strong class="command">ddns-confgen</strong></span>, or a pair of files whose names are + of the format <code class="filename">K{name}.+157.+{random}.key</code> and + <code class="filename">K{name}.+157.+{random}.private</code>, which can be + generated by <span><strong class="command">dnssec-keygen</strong></span>. The <code class="option">-k</code> may also be used to specify a SIG(0) key used to authenticate Dynamic DNS update requests. In this case, the key specified is not an HMAC-MD5 key. </p> <p> - The <code class="option">-g</code> and <code class="option">-o</code> specify that - GSS-TSIG is to be used. The <code class="option">-o</code> should only - be used with old Microsoft Windows 2000 servers. + <span><strong class="command">nsupdate</strong></span> can be run in a local-host only mode + using the <code class="option">-l</code> flag. This sets the server address to + localhost (disabling the <span><strong class="command">server</strong></span> so that the server + address cannot be overridden). Connections to the local server will + use a TSIG key found in <code class="filename">/var/run/named/session.key</code>, + which is automatically generated by <span><strong class="command">named</strong></span> if any + local master zone has set <span><strong class="command">update-policy</strong></span> to + <span><strong class="command">local</strong></span>. The location of this key file can be + overridden with the <code class="option">-k</code> option. </p> <p> - By default, - <span><strong class="command">nsupdate</strong></span> + By default, <span><strong class="command">nsupdate</strong></span> uses UDP to send update requests to the name server unless they are too large to fit in a UDP request in which case TCP will be used. The @@ -138,6 +157,10 @@ This may be preferable when a batch of update requests is made. </p> <p> + The <code class="option">-p</code> sets the default port number to use for + connections to a name server. The default is 53. + </p> +<p> The <code class="option">-t</code> option sets the maximum time an update request can take before it is aborted. The default is 300 seconds. Zero can be @@ -169,7 +192,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543730"></a><h2>INPUT FORMAT</h2> +<a name="id2543788"></a><h2>INPUT FORMAT</h2> <p><span><strong class="command">nsupdate</strong></span> reads input from <em class="parameter"><code>filename</code></em> @@ -457,7 +480,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2544642"></a><h2>EXAMPLES</h2> +<a name="id2544700"></a><h2>EXAMPLES</h2> <p> The examples below show how <span><strong class="command">nsupdate</strong></span> @@ -504,19 +527,23 @@ If there are, the update request fails. If this name does not exist, a CNAME for it is added. This ensures that when the CNAME is added, it cannot conflict with the - long-standing rule in RFC1034 that a name must not exist as any other + long-standing rule in RFC 1034 that a name must not exist as any other record type if it exists as a CNAME. - (The rule has been updated for DNSSEC in RFC2535 to allow CNAMEs to have + (The rule has been updated for DNSSEC in RFC 2535 to allow CNAMEs to have RRSIG, DNSKEY and NSEC records.) </p> </div> <div class="refsect1" lang="en"> -<a name="id2544685"></a><h2>FILES</h2> +<a name="id2544744"></a><h2>FILES</h2> <div class="variablelist"><dl> <dt><span class="term"><code class="constant">/etc/resolv.conf</code></span></dt> <dd><p> used to identify default name server </p></dd> +<dt><span class="term"><code class="constant">/var/run/named/session.key</code></span></dt> +<dd><p> + sets the default TSIG key for use in local-only mode + </p></dd> <dt><span class="term"><code class="constant">K{name}.+157.+{random}.key</code></span></dt> <dd><p> base-64 encoding of HMAC-MD5 key created by @@ -530,20 +557,22 @@ </dl></div> </div> <div class="refsect1" lang="en"> -<a name="id2544755"></a><h2>SEE ALSO</h2> -<p><span class="citerefentry"><span class="refentrytitle">RFC2136</span></span>, - <span class="citerefentry"><span class="refentrytitle">RFC3007</span></span>, - <span class="citerefentry"><span class="refentrytitle">RFC2104</span></span>, - <span class="citerefentry"><span class="refentrytitle">RFC2845</span></span>, - <span class="citerefentry"><span class="refentrytitle">RFC1034</span></span>, - <span class="citerefentry"><span class="refentrytitle">RFC2535</span></span>, - <span class="citerefentry"><span class="refentrytitle">RFC2931</span></span>, +<a name="id2544827"></a><h2>SEE ALSO</h2> +<p> + <em class="citetitle">RFC 2136</em>, + <em class="citetitle">RFC 3007</em>, + <em class="citetitle">RFC 2104</em>, + <em class="citetitle">RFC 2845</em>, + <em class="citetitle">RFC 1034</em>, + <em class="citetitle">RFC 2535</em>, + <em class="citetitle">RFC 2931</em>, <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>, + <span class="citerefentry"><span class="refentrytitle">ddns-confgen</span>(8)</span>, <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>. </p> </div> <div class="refsect1" lang="en"> -<a name="id2542163"></a><h2>BUGS</h2> +<a name="id2542154"></a><h2>BUGS</h2> <p> The TSIG key is redundantly stored in two separate files. This is a consequence of nsupdate using the DST library diff --git a/contrib/bind9/bin/rndc/Makefile.in b/contrib/bind9/bin/rndc/Makefile.in index 27d46111a4e5..6c7c56f4abf7 100644 --- a/contrib/bind9/bin/rndc/Makefile.in +++ b/contrib/bind9/bin/rndc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 2000-2002 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.44 2007-06-18 23:47:22 tbox Exp $ +# $Id: Makefile.in,v 1.49 2009-12-05 23:31:40 each Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -32,6 +32,7 @@ CWARNINGS = ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ ISCCCLIBS = ../../lib/isccc/libisccc.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ BIND9LIBS = ../../lib/bind9/libbind9.@A@ @@ -41,26 +42,23 @@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ -RNDCLIBS = ${ISCCFGLIBS} ${ISCCCLIBS} ${BIND9LIBS} ${DNSLIBS} ${ISCLIBS} @LIBS@ +LIBS = ${ISCLIBS} @LIBS@ +NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@ + RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS} -CONFLIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} -SRCS= rndc.c rndc-confgen.c - -SUBDIRS = unix +SRCS= rndc.c -TARGETS = rndc@EXEEXT@ rndc-confgen@EXEEXT@ +TARGETS = rndc@EXEEXT@ -MANPAGES = rndc.8 rndc-confgen.8 rndc.conf.5 +MANPAGES = rndc.8 rndc.conf.5 -HTMLPAGES = rndc.html rndc-confgen.html rndc.conf.html +HTMLPAGES = rndc.html rndc.conf.html MANOBJS = ${MANPAGES} ${HTMLPAGES} -UOBJS = unix/os.@O@ - @BIND9_MAKE_RULES@ rndc.@O@: rndc.c @@ -70,18 +68,10 @@ rndc.@O@: rndc.c -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \ -c ${srcdir}/rndc.c -rndc-confgen.@O@: rndc-confgen.c - ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ - -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \ - -c ${srcdir}/rndc-confgen.c - rndc@EXEEXT@: rndc.@O@ util.@O@ ${RNDCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rndc.@O@ util.@O@ \ - ${RNDCLIBS} - -rndc-confgen@EXEEXT@: rndc-confgen.@O@ util.@O@ ${UOBJS} ${CONFDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rndc-confgen.@O@ util.@O@ \ - ${UOBJS} ${CONFLIBS} + export BASEOBJS="rndc.@O@ util.@O@"; \ + export LIBS0="${ISCCFGLIBS} ${ISCCCLIBS} ${BIND9LIBS} ${DNSLIBS}"; \ + ${FINALBUILDCMD} doc man:: ${MANOBJS} @@ -93,11 +83,9 @@ installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5 -install:: rndc@EXEEXT@ rndc-confgen@EXEEXT@ installdirs +install:: rndc@EXEEXT@ installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} rndc@EXEEXT@ ${DESTDIR}${sbindir} - ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} rndc-confgen@EXEEXT@ ${DESTDIR}${sbindir} ${INSTALL_DATA} ${srcdir}/rndc.8 ${DESTDIR}${mandir}/man8 - ${INSTALL_DATA} ${srcdir}/rndc-confgen.8 ${DESTDIR}${mandir}/man8 ${INSTALL_DATA} ${srcdir}/rndc.conf.5 ${DESTDIR}${mandir}/man5 clean distclean maintainer-clean:: diff --git a/contrib/bind9/bin/rndc/include/rndc/os.h b/contrib/bind9/bin/rndc/include/rndc/os.h index 9f96165d75ac..91986cb0c1dc 100644 --- a/contrib/bind9/bin/rndc/include/rndc/os.h +++ b/contrib/bind9/bin/rndc/include/rndc/os.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: os.h,v 1.9.332.2 2009-01-18 23:47:35 tbox Exp $ */ +/* $Id: os.h,v 1.12 2009-06-10 00:27:21 each Exp $ */ /*! \file */ @@ -27,12 +27,6 @@ ISC_LANG_BEGINDECLS -FILE *safe_create(const char *filename); -/*%< - * Open 'filename' for writing, truncate if necessary. If the file was - * created ensure that only the owner can read/write it. - */ - int set_user(FILE *fd, const char *user); /*%< * Set the owner of the file referenced by 'fd' to 'user'. diff --git a/contrib/bind9/bin/rndc/rndc.8 b/contrib/bind9/bin/rndc/rndc.8 index 285ca9b2eb6e..e4d723bb5197 100644 --- a/contrib/bind9/bin/rndc/rndc.8 +++ b/contrib/bind9/bin/rndc/rndc.8 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: rndc.8,v 1.42.214.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: rndc.8,v 1.43 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/contrib/bind9/bin/rndc/rndc.c b/contrib/bind9/bin/rndc/rndc.c index 133103e3dc73..1976d9ce3322 100644 --- a/contrib/bind9/bin/rndc/rndc.c +++ b/contrib/bind9/bin/rndc/rndc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rndc.c,v 1.122.44.2 2009-01-18 23:47:35 tbox Exp $ */ +/* $Id: rndc.c,v 1.131.20.1.2.1 2011-06-02 23:47:28 tbox Exp $ */ /*! \file */ @@ -79,6 +79,7 @@ static unsigned char databuf[2048]; static isccc_ccmsg_t ccmsg; static isccc_region_t secret; static isc_boolean_t failed = ISC_FALSE; +static isc_boolean_t c_flag = ISC_FALSE; static isc_mem_t *mctx; static int sends, recvs, connects; static char *command; @@ -89,10 +90,13 @@ static isc_uint32_t serial; static void rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task); +ISC_PLATFORM_NORETURN_PRE static void +usage(int status) ISC_PLATFORM_NORETURN_POST; + static void usage(int status) { fprintf(stderr, "\ -Usage: %s [-c config] [-s server] [-p port]\n\ +Usage: %s [-b address] [-c config] [-s server] [-p port]\n\ [-k key-file ] [-y key] [-V] command\n\ \n\ command is one of the following:\n\ @@ -113,10 +117,16 @@ command is one of the following:\n\ notify zone [class [view]]\n\ Resend NOTIFY messages for the zone.\n\ reconfig Reload configuration file and new zones only.\n\ + sign zone [class [view]]\n\ + Update zone keys, and sign as needed.\n\ + loadkeys zone [class [view]]\n\ + Update keys without signing immediately.\n\ stats Write server statistics to the statistics file.\n\ querylog Toggle query logging.\n\ dumpdb [-all|-cache|-zones] [view ...]\n\ Dump cache(s) to the dump file (named_dump.db).\n\ + secroots [view ...]\n\ + Write security roots to the secroots file.\n\ stop Save pending updates to master files and stop the server.\n\ stop -p Save pending updates to master files and stop the server\n\ reporting process id.\n\ @@ -135,6 +145,10 @@ command is one of the following:\n\ validation newstate [view]\n\ Enable / disable DNSSEC validation.\n\ *restart Restart the server.\n\ + addzone [\"file\"] zone [class [view]] { zone-options }\n\ + Add zone to given view. Requires new-zone-file option.\n\ + delzone [\"file\"] zone [class [view]]\n\ + Removes zone from given view. Requires new-zone-file option.\n\ \n\ * == not yet implemented\n\ Version: %s\n", @@ -455,6 +469,10 @@ parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname, fatal("neither %s nor %s was found", admin_conffile, admin_keyfile); key_only = ISC_TRUE; + } else if (! c_flag && isc_file_exists(admin_keyfile)) { + fprintf(stderr, "WARNING: key file (%s) exists, but using " + "default configuration file (%s)\n", + admin_keyfile, admin_conffile); } DO("create parser", cfg_parser_create(mctx, log, pctxp)); @@ -709,6 +727,7 @@ main(int argc, char **argv) { case 'c': admin_conffile = isc_commandline_argument; + c_flag = ISC_TRUE; break; case 'k': diff --git a/contrib/bind9/bin/rndc/rndc.conf.5 b/contrib/bind9/bin/rndc/rndc.conf.5 index d7ad81ea99d2..54c4af9c21f8 100644 --- a/contrib/bind9/bin/rndc/rndc.conf.5 +++ b/contrib/bind9/bin/rndc/rndc.conf.5 @@ -13,7 +13,7 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $Id: rndc.conf.5,v 1.38.366.1 2009-07-11 01:55:21 tbox Exp $ +.\" $Id: rndc.conf.5,v 1.41 2009-07-11 01:12:46 tbox Exp $ .\" .hy 0 .ad l diff --git a/contrib/bind9/bin/rndc/rndc.conf.html b/contrib/bind9/bin/rndc/rndc.conf.html index 114cc15983b1..463b99fd2c24 100644 --- a/contrib/bind9/bin/rndc/rndc.conf.html +++ b/contrib/bind9/bin/rndc/rndc.conf.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: rndc.conf.html,v 1.29.366.1 2009-07-11 01:55:21 tbox Exp $ --> +<!-- $Id: rndc.conf.html,v 1.32 2009-07-11 01:12:46 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> diff --git a/contrib/bind9/bin/rndc/rndc.html b/contrib/bind9/bin/rndc/rndc.html index 0d91784b0ec4..ecc0f318614a 100644 --- a/contrib/bind9/bin/rndc/rndc.html +++ b/contrib/bind9/bin/rndc/rndc.html @@ -14,7 +14,7 @@ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: rndc.html,v 1.31.214.1 2009-07-11 01:55:21 tbox Exp $ --> +<!-- $Id: rndc.html,v 1.32 2009-07-11 01:12:46 tbox Exp $ --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> diff --git a/contrib/bind9/bin/rndc/util.h b/contrib/bind9/bin/rndc/util.h index c5da488d96de..8eba61a57ee2 100644 --- a/contrib/bind9/bin/rndc/util.h +++ b/contrib/bind9/bin/rndc/util.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: util.h,v 1.10 2007-06-19 23:46:59 tbox Exp $ */ +/* $Id: util.h,v 1.12 2009-09-29 23:48:03 tbox Exp $ */ #ifndef RNDC_UTIL_H #define RNDC_UTIL_H 1 @@ -23,6 +23,7 @@ /*! \file */ #include <isc/lang.h> +#include <isc/platform.h> #include <isc/formatcheck.h> @@ -43,8 +44,9 @@ ISC_LANG_BEGINDECLS void notify(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2); -void -fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); +ISC_PLATFORM_NORETURN_PRE void +fatal(const char *format, ...) +ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; ISC_LANG_ENDDECLS diff --git a/contrib/bind9/bin/tools/Makefile.in b/contrib/bind9/bin/tools/Makefile.in new file mode 100644 index 000000000000..35b8285715d2 --- /dev/null +++ b/contrib/bind9/bin/tools/Makefile.in @@ -0,0 +1,103 @@ +# Copyright (C) 2009, 2010 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: Makefile.in,v 1.13 2010-01-07 23:48:53 tbox Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} \ + ${LWRES_INCLUDES} ${OMAPI_INCLUDES} + +CDEFINES = +CWARNINGS = + +DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ +ISCLIBS = ../../lib/isc/libisc.@A@ @DNS_CRYPTO_LIBS@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ +ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ +LWRESLIBS = ../../lib/lwres/liblwres.@A@ + +DNSDEPLIBS = ../../lib/dns/libdns.@A@ +ISCDEPLIBS = ../../lib/isc/libisc.@A@ +ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ +LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ + +LIBS = ${ISCLIBS} @LIBS@ +NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@ + +SUBDIRS = + +TARGETS = arpaname@EXEEXT@ named-journalprint@EXEEXT@ nsec3hash@EXEEXT@ \ + genrandom@EXEEXT@ isc-hmac-fixup@EXEEXT@ +SRCS = arpaname.c named-journalprint.c nsec3hash.c genrandom.c \ + isc-hmac-fixup.c + +MANPAGES = arpaname.1 named-journalprint.8 nsec3hash.8 genrandom.8 \ + isc-hmac-fixup.8 +HTMLPAGES = arpaname.html named-journalprint.html nsec3hash.html \ + genrandom.html isc-hmac-fixup.html +MANOBJS = ${MANPAGES} ${HTMLPAGES} + +@BIND9_MAKE_RULES@ + +arpaname@EXEEXT@: arpaname.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ arpaname.@O@ \ + ${ISCLIBS} ${LIBS} + +named-journalprint@EXEEXT@: named-journalprint.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + export BASEOBJS="named-journalprint.@O@"; \ + export LIBS0="${DNSLIBS}"; \ + ${FINALBUILDCMD} + +nsec3hash@EXEEXT@: nsec3hash.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + export BASEOBJS="nsec3hash.@O@"; \ + export LIBS0="${DNSLIBS}"; \ + ${FINALBUILDCMD} + +isc-hmac-fixup@EXEEXT@: isc-hmac-fixup.@O@ ${ISCDEPLIBS} + export BASEOBJS="isc-hmac-fixup.@O@"; \ + export LIBS0="${ISCLIBS}"; \ + ${FINALBUILDCMD} + +genrandom@EXEEXT@: genrandom.@O@ + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ genrandom.@O@ @GENRANDOMLIB@ ${LIBS} + +doc man:: ${MANOBJS} + +docclean manclean maintainer-clean:: + rm -f ${MANOBJS} + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1 + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + +install:: ${TARGETS} installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} arpaname@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-journalprint@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} nsec3hash@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} genrandom@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} isc-hmac-fixup@EXEEXT@ ${DESTDIR}${sbindir} + ${INSTALL_DATA} ${srcdir}/arpaname.1 ${DESTDIR}${mandir}/man1 + ${INSTALL_DATA} ${srcdir}/isc-hmac-fixup.8 ${DESTDIR}${mandir}/man8 + ${INSTALL_DATA} ${srcdir}/named-journalprint.8 ${DESTDIR}${mandir}/man8 + ${INSTALL_DATA} ${srcdir}/nsec3hash.8 ${DESTDIR}${mandir}/man8 + ${INSTALL_DATA} ${srcdir}/genrandom.8 ${DESTDIR}${mandir}/man8 + +clean distclean:: + rm -f ${TARGETS} diff --git a/contrib/bind9/bin/tools/arpaname.1 b/contrib/bind9/bin/tools/arpaname.1 new file mode 100644 index 000000000000..66623801814f --- /dev/null +++ b/contrib/bind9/bin/tools/arpaname.1 @@ -0,0 +1,48 @@ +.\" 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: arpaname.1,v 1.4 2010-05-19 01:14:14 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: arpaname +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/> +.\" Date: March 4, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "ARPANAME" "1" "March 4, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +arpaname \- translate IP addresses to the corresponding ARPA names +.SH "SYNOPSIS" +.HP 9 +\fBarpaname\fR {\fIipaddress\ \fR...} +.SH "DESCRIPTION" +.PP +\fBarpaname\fR +translates IP addresses (IPv4 and IPv6) to the corresponding IN\-ADDR.ARPA or IP6.ARPA names. +.SH "SEE ALSO" +.PP +BIND 9 Administrator Reference Manual. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/contrib/bind9/bin/tools/arpaname.c b/contrib/bind9/bin/tools/arpaname.c new file mode 100644 index 000000000000..e7f14345dfd6 --- /dev/null +++ b/contrib/bind9/bin/tools/arpaname.c @@ -0,0 +1,53 @@ +/* + * 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: arpaname.c,v 1.4 2009-10-27 03:05:33 marka Exp $ */ + +#include "config.h" + +#include <isc/net.h> + +#include <stdio.h> + +#define UNUSED(x) (void)(x) + +int +main(int argc, char *argv[]) { + unsigned char buf[16]; + int i; + + UNUSED(argc); + + while (argv[1]) { + if (inet_pton(AF_INET6, argv[1], buf) == 1) { + for (i = 15; i >= 0; i--) + fprintf(stdout, "%X.%X.", buf[i] & 0xf, + (buf[i] >> 4) & 0xf); + fprintf(stdout, "IP6.ARPA\n"); + argv++; + continue; + } + if (inet_pton(AF_INET, argv[1], buf) == 1) { + fprintf(stdout, "%u.%u.%u.%u.IN-ADDR.ARPA\n", + buf[3], buf[2], buf[1], buf[0]); + argv++; + continue; + } + return (1); + } + fflush(stdout); + return(ferror(stdout)); +} diff --git a/contrib/bind9/bin/tools/arpaname.docbook b/contrib/bind9/bin/tools/arpaname.docbook new file mode 100644 index 000000000000..a7eb79e9c3b6 --- /dev/null +++ b/contrib/bind9/bin/tools/arpaname.docbook @@ -0,0 +1,76 @@ +<!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: arpaname.docbook,v 1.1 2009-03-04 01:30:27 marka Exp $ --> +<refentry id="man.arpaname"> + <refentryinfo> + <date>March 4, 2009</date> + </refentryinfo> + + <refmeta> + <refentrytitle><application>arpaname</application></refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo>BIND9</refmiscinfo> + </refmeta> + + <refnamediv> + <refname><application>arpaname</application></refname> + <refpurpose>translate IP addresses to the corresponding ARPA names</refpurpose> + </refnamediv> + + <docinfo> + <copyright> + <year>2009</year> + <holder>Internet Systems Consortium, Inc. ("ISC")</holder> + </copyright> + </docinfo> + + <refsynopsisdiv> + <cmdsynopsis> + <command>arpaname</command> + <arg choice="req" rep="repeat"><replaceable class="parameter">ipaddress </replaceable></arg> + </cmdsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>DESCRIPTION</title> + <para> + <command>arpaname</command> translates IP addresses (IPv4 and + IPv6) to the corresponding IN-ADDR.ARPA or IP6.ARPA names. + </para> + </refsect1> + + <refsect1> + <title>SEE ALSO</title> + <para> + <citetitle>BIND 9 Administrator Reference Manual</citetitle>. + </para> + </refsect1> + + <refsect1> + <title>AUTHOR</title> + <para><corpauthor>Internet Systems Consortium</corpauthor> + </para> + </refsect1> + +</refentry><!-- + - Local variables: + - mode: sgml + - End: +--> diff --git a/contrib/bind9/bin/tools/arpaname.html b/contrib/bind9/bin/tools/arpaname.html new file mode 100644 index 000000000000..e44cfbd782e0 --- /dev/null +++ b/contrib/bind9/bin/tools/arpaname.html @@ -0,0 +1,52 @@ +<!-- + - 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: arpaname.html,v 1.4 2010-05-19 01:14:14 tbox Exp $ --> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<title>arpaname</title> +<meta name="generator" content="DocBook XSL Stylesheets V1.71.1"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en"> +<a name="man.arpaname"></a><div class="titlepage"></div> +<div class="refnamediv"> +<h2>Name</h2> +<p><span class="application">arpaname</span> — translate IP addresses to the corresponding ARPA names</p> +</div> +<div class="refsynopsisdiv"> +<h2>Synopsis</h2> +<div class="cmdsynopsis"><p><code class="command">arpaname</code> {<em class="replaceable"><code>ipaddress </code></em>...}</p></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543345"></a><h2>DESCRIPTION</h2> +<p> + <span><strong class="command">arpaname</strong></span> translates IP addresses (IPv4 and + IPv6) to the corresponding IN-ADDR.ARPA or IP6.ARPA names. + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543357"></a><h2>SEE ALSO</h2> +<p> + <em class="citetitle">BIND 9 Administrator Reference Manual</em>. + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543371"></a><h2>AUTHOR</h2> +<p><span class="corpauthor">Internet Systems Consortium</span> + </p> +</div> +</div></body> +</html> diff --git a/contrib/bind9/bin/tools/genrandom.8 b/contrib/bind9/bin/tools/genrandom.8 new file mode 100644 index 000000000000..32a4ff02efb6 --- /dev/null +++ b/contrib/bind9/bin/tools/genrandom.8 @@ -0,0 +1,69 @@ +.\" Copyright (C) 2009, 2010 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: genrandom.8,v 1.8 2010-05-19 01:14:14 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: genrandom +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/> +.\" Date: Feb 19, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "GENRANDOM" "8" "Feb 19, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +genrandom \- generate a file containing random data +.SH "SYNOPSIS" +.HP 10 +\fBgenrandom\fR [\fB\-n\ \fR\fB\fInumber\fR\fR] {\fIsize\fR} {\fIfilename\fR} +.SH "DESCRIPTION" +.PP +\fBgenrandom\fR +generates a file or a set of files containing a specified quantity of pseudo\-random data, which can be used as a source of entropy for other commands on systems with no random device. +.SH "ARGUMENTS" +.PP +\-n \fInumber\fR +.RS 4 +In place of generating one file, generates +\fBnumber\fR +(from 2 to 9) files, appending +\fBnumber\fR +to the name. +.RE +.PP +size +.RS 4 +The size of the file, in kilobytes, to generate. +.RE +.PP +domain +.RS 4 +The file name into which random data should be written. +.RE +.SH "SEE ALSO" +.PP +\fBrand\fR(3), +\fBarc4random\fR(3) +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009, 2010 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/contrib/bind9/bin/tools/genrandom.c b/contrib/bind9/bin/tools/genrandom.c new file mode 100644 index 000000000000..8473be259404 --- /dev/null +++ b/contrib/bind9/bin/tools/genrandom.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2004, 2005, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2000-2003 Internet Software Consortium. + * + * 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: genrandom.c,v 1.7 2010-05-17 23:51:04 tbox Exp $ */ + +/*! \file */ +#include <config.h> + +#include <isc/commandline.h> +#include <isc/print.h> +#include <isc/stdlib.h> +#include <isc/util.h> + +#include <stdio.h> +#include <string.h> + +const char *program = "genrandom"; + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void +usage(void) { + fprintf(stderr, "usage: %s [-n 2..9] k file\n", program); + exit(1); +} + +static void +generate(char *filename, unsigned int bytes) { + FILE *fp; + + fp = fopen(filename, "w"); + if (fp == NULL) { + printf("failed to open %s\n", filename); + exit(1); + } + + while (bytes > 0) { +#ifndef HAVE_ARC4RANDOM + unsigned short int x = (rand() & 0xFFFF); +#else + unsigned short int x = (arc4random() & 0xFFFF); +#endif + unsigned char c = x & 0xFF; + if (putc(c, fp) == EOF) { + printf("error writing to %s\n", filename); + exit(1); + } + c = x >> 8; + if (putc(c, fp) == EOF) { + printf("error writing to %s\n", filename); + exit(1); + } + bytes -= 2; + } + fclose(fp); +} + +int +main(int argc, char **argv) { + unsigned int bytes; + unsigned int k; + char *endp; + int c, i, n = 1; + size_t len; + char *name; + + isc_commandline_errprint = ISC_FALSE; + + while ((c = isc_commandline_parse(argc, argv, "hn:")) != EOF) { + switch (c) { + case 'n': + n = strtol(isc_commandline_argument, &endp, 10); + if ((*endp != 0) || (n <= 1) || (n > 9)) + usage(); + break; + + case '?': + if (isc_commandline_option != '?') + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + case 'h': + usage(); + + default: + fprintf(stderr, "%s: unhandled option -%c\n", + program, isc_commandline_option); + exit(1); + } + } + + if (isc_commandline_index + 2 != argc) + usage(); + + k = strtoul(argv[isc_commandline_index++], &endp, 10); + if (*endp != 0) + usage(); + bytes = k << 10; + +#ifndef HAVE_ARC4RANDOM + srand(0x12345678); +#endif + if (n == 1) { + generate(argv[isc_commandline_index], bytes); + return (0); + } + + len = strlen(argv[isc_commandline_index]) + 2; + name = (char *) malloc(len); + if (name == NULL) { + perror("malloc"); + exit(1); + } + + for (i = 1; i <= n; i++) { + snprintf(name, len, "%s%d", argv[isc_commandline_index], i); + generate(name, bytes); + } + free(name); + + return (0); +} diff --git a/contrib/bind9/bin/tools/genrandom.docbook b/contrib/bind9/bin/tools/genrandom.docbook new file mode 100644 index 000000000000..84e45534a822 --- /dev/null +++ b/contrib/bind9/bin/tools/genrandom.docbook @@ -0,0 +1,119 @@ +<!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, 2010 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: genrandom.docbook,v 1.6 2010-05-17 23:51:05 tbox Exp $ --> +<refentry id="man.genrandom"> + <refentryinfo> + <date>Feb 19, 2009</date> + </refentryinfo> + + <refmeta> + <refentrytitle><application>genrandom</application></refentrytitle> + <manvolnum>8</manvolnum> + <refmiscinfo>BIND9</refmiscinfo> + </refmeta> + + <refnamediv> + <refname><application>genrandom</application></refname> + <refpurpose>generate a file containing random data</refpurpose> + </refnamediv> + + <docinfo> + <copyright> + <year>2009</year> + <year>2010</year> + <holder>Internet Systems Consortium, Inc. ("ISC")</holder> + </copyright> + </docinfo> + + <refsynopsisdiv> + <cmdsynopsis> + <command>genrandom</command> + <arg><option>-n <replaceable class="parameter">number</replaceable></option></arg> + <arg choice="req"><replaceable class="parameter">size</replaceable></arg> + <arg choice="req"><replaceable class="parameter">filename</replaceable></arg> + </cmdsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>DESCRIPTION</title> + <para> + <command>genrandom</command> + generates a file or a set of files containing a specified quantity + of pseudo-random data, which can be used as a source of entropy for + other commands on systems with no random device. + </para> + </refsect1> + + <refsect1> + <title>ARGUMENTS</title> + <variablelist> + <varlistentry> + <term>-n <replaceable class="parameter">number</replaceable></term> + <listitem> + <para> + In place of generating one file, generates <option>number</option> + (from 2 to 9) files, appending <option>number</option> to the name. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>size</term> + <listitem> + <para> + The size of the file, in kilobytes, to generate. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>domain</term> + <listitem> + <para> + The file name into which random data should be written. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>SEE ALSO</title> + <para> + <citerefentry> + <refentrytitle>rand</refentrytitle><manvolnum>3</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>arc4random</refentrytitle><manvolnum>3</manvolnum> + </citerefentry> + </para> + </refsect1> + + <refsect1> + <title>AUTHOR</title> + <para><corpauthor>Internet Systems Consortium</corpauthor> + </para> + </refsect1> + +</refentry><!-- + - Local variables: + - mode: sgml + - End: +--> diff --git a/contrib/bind9/bin/tools/genrandom.html b/contrib/bind9/bin/tools/genrandom.html new file mode 100644 index 000000000000..c14af9bbd0e0 --- /dev/null +++ b/contrib/bind9/bin/tools/genrandom.html @@ -0,0 +1,73 @@ +<!-- + - Copyright (C) 2009, 2010 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: genrandom.html,v 1.8 2010-05-19 01:14:14 tbox Exp $ --> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<title>genrandom</title> +<meta name="generator" content="DocBook XSL Stylesheets V1.71.1"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en"> +<a name="man.genrandom"></a><div class="titlepage"></div> +<div class="refnamediv"> +<h2>Name</h2> +<p><span class="application">genrandom</span> — generate a file containing random data</p> +</div> +<div class="refsynopsisdiv"> +<h2>Synopsis</h2> +<div class="cmdsynopsis"><p><code class="command">genrandom</code> [<code class="option">-n <em class="replaceable"><code>number</code></em></code>] {<em class="replaceable"><code>size</code></em>} {<em class="replaceable"><code>filename</code></em>}</p></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543363"></a><h2>DESCRIPTION</h2> +<p> + <span><strong class="command">genrandom</strong></span> + generates a file or a set of files containing a specified quantity + of pseudo-random data, which can be used as a source of entropy for + other commands on systems with no random device. + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543376"></a><h2>ARGUMENTS</h2> +<div class="variablelist"><dl> +<dt><span class="term">-n <em class="replaceable"><code>number</code></em></span></dt> +<dd><p> + In place of generating one file, generates <code class="option">number</code> + (from 2 to 9) files, appending <code class="option">number</code> to the name. + </p></dd> +<dt><span class="term">size</span></dt> +<dd><p> + The size of the file, in kilobytes, to generate. + </p></dd> +<dt><span class="term">domain</span></dt> +<dd><p> + The file name into which random data should be written. + </p></dd> +</dl></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543436"></a><h2>SEE ALSO</h2> +<p> + <span class="citerefentry"><span class="refentrytitle">rand</span>(3)</span>, + <span class="citerefentry"><span class="refentrytitle">arc4random</span>(3)</span> + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543463"></a><h2>AUTHOR</h2> +<p><span class="corpauthor">Internet Systems Consortium</span> + </p> +</div> +</div></body> +</html> diff --git a/contrib/bind9/bin/tools/isc-hmac-fixup.8 b/contrib/bind9/bin/tools/isc-hmac-fixup.8 new file mode 100644 index 000000000000..99c58c8304cf --- /dev/null +++ b/contrib/bind9/bin/tools/isc-hmac-fixup.8 @@ -0,0 +1,61 @@ +.\" Copyright (C) 2010 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: isc-hmac-fixup.8,v 1.4 2010-05-19 01:14:14 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: isc\-hmac\-fixup +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/> +.\" Date: January 5, 2010 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "ISC\-HMAC\-FIXUP" "1" "January 5, 2010" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +isc\-hmac\-fixup \- fixes HMAC keys generated by older versions of BIND +.SH "SYNOPSIS" +.HP 15 +\fBisc\-hmac\-fixup\fR {\fIalgorithm\fR} {\fIsecret\fR} +.SH "DESCRIPTION" +.PP +Versions of BIND 9 up to and including BIND 9.6 had a bug causing HMAC\-SHA* TSIG keys which were longer than the digest length of the hash algorithm (i.e., SHA1 keys longer than 160 bits, SHA256 keys longer than 256 bits, etc) to be used incorrectly, generating a message authentication code that was incompatible with other DNS implementations. +.PP +This bug has been fixed in BIND 9.7. However, the fix may cause incompatibility between older and newer versions of BIND, when using long keys. +\fBisc\-hmac\-fixup\fR +modifies those keys to restore compatibility. +.PP +To modify a key, run +\fBisc\-hmac\-fixup\fR +and specify the key's algorithm and secret on the command line. If the secret is longer than the digest length of the algorithm (64 bytes for SHA1 through SHA256, or 128 bytes for SHA384 and SHA512), then a new secret will be generated consisting of a hash digest of the old secret. (If the secret did not require conversion, then it will be printed without modification.) +.SH "SECURITY CONSIDERATIONS" +.PP +Secrets that have been converted by +\fBisc\-hmac\-fixup\fR +are shortened, but as this is how the HMAC protocol works in operation anyway, it does not affect security. RFC 2104 notes, "Keys longer than [the digest length] are acceptable but the extra length would not significantly increase the function strength." +.SH "SEE ALSO" +.PP +BIND 9 Administrator Reference Manual, +RFC 2104. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2010 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/contrib/bind9/bin/tools/isc-hmac-fixup.c b/contrib/bind9/bin/tools/isc-hmac-fixup.c new file mode 100644 index 000000000000..09cb85deeebc --- /dev/null +++ b/contrib/bind9/bin/tools/isc-hmac-fixup.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2010 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: isc-hmac-fixup.c,v 1.4 2010-03-10 02:17:52 marka Exp $ */ + +#include <config.h> + +#include <isc/base64.h> +#include <isc/buffer.h> +#include <isc/md5.h> +#include <isc/region.h> +#include <isc/result.h> +#include <isc/sha1.h> +#include <isc/sha2.h> +#include <isc/stdio.h> +#include <isc/string.h> + +#define HMAC_LEN 64 + +int +main(int argc, char **argv) { + isc_buffer_t buf; + unsigned char key[1024]; + char secret[1024]; + char base64[(1024*4)/3]; + isc_region_t r; + isc_result_t result; + + if (argc != 3) { + fprintf(stderr, "Usage:\t%s algorithm secret\n", argv[0]); + fprintf(stderr, "\talgorithm: (MD5 | SHA1 | SHA224 | " + "SHA256 | SHA384 | SHA512)\n"); + return (1); + } + + isc_buffer_init(&buf, secret, sizeof(secret)); + result = isc_base64_decodestring(argv[2], &buf); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "error: %s\n", isc_result_totext(result)); + return (1); + } + isc__buffer_usedregion(&buf, &r); + + if (!strcasecmp(argv[1], "md5") || + !strcasecmp(argv[1], "hmac-md5")) { + if (r.length > HMAC_LEN) { + isc_md5_t md5ctx; + isc_md5_init(&md5ctx); + isc_md5_update(&md5ctx, r.base, r.length); + isc_md5_final(&md5ctx, key); + + r.base = key; + r.length = ISC_MD5_DIGESTLENGTH; + } + } else if (!strcasecmp(argv[1], "sha1") || + !strcasecmp(argv[1], "hmac-sha1")) { + if (r.length > ISC_SHA1_DIGESTLENGTH) { + isc_sha1_t sha1ctx; + isc_sha1_init(&sha1ctx); + isc_sha1_update(&sha1ctx, r.base, r.length); + isc_sha1_final(&sha1ctx, key); + + r.base = key; + r.length = ISC_SHA1_DIGESTLENGTH; + } + } else if (!strcasecmp(argv[1], "sha224") || + !strcasecmp(argv[1], "hmac-sha224")) { + if (r.length > ISC_SHA224_DIGESTLENGTH) { + isc_sha224_t sha224ctx; + isc_sha224_init(&sha224ctx); + isc_sha224_update(&sha224ctx, r.base, r.length); + isc_sha224_final(key, &sha224ctx); + + r.base = key; + r.length = ISC_SHA224_DIGESTLENGTH; + } + } else if (!strcasecmp(argv[1], "sha256") || + !strcasecmp(argv[1], "hmac-sha256")) { + if (r.length > ISC_SHA256_DIGESTLENGTH) { + isc_sha256_t sha256ctx; + isc_sha256_init(&sha256ctx); + isc_sha256_update(&sha256ctx, r.base, r.length); + isc_sha256_final(key, &sha256ctx); + + r.base = key; + r.length = ISC_SHA256_DIGESTLENGTH; + } + } else if (!strcasecmp(argv[1], "sha384") || + !strcasecmp(argv[1], "hmac-sha384")) { + if (r.length > ISC_SHA384_DIGESTLENGTH) { + isc_sha384_t sha384ctx; + isc_sha384_init(&sha384ctx); + isc_sha384_update(&sha384ctx, r.base, r.length); + isc_sha384_final(key, &sha384ctx); + + r.base = key; + r.length = ISC_SHA384_DIGESTLENGTH; + } + } else if (!strcasecmp(argv[1], "sha512") || + !strcasecmp(argv[1], "hmac-sha512")) { + if (r.length > ISC_SHA512_DIGESTLENGTH) { + isc_sha512_t sha512ctx; + isc_sha512_init(&sha512ctx); + isc_sha512_update(&sha512ctx, r.base, r.length); + isc_sha512_final(key, &sha512ctx); + + r.base = key; + r.length = ISC_SHA512_DIGESTLENGTH; + } + } else { + fprintf(stderr, "unknown hmac/digest algorithm: %s\n", argv[1]); + return (1); + } + + isc_buffer_init(&buf, base64, sizeof(base64)); + result = isc_base64_totext(&r, 0, "", &buf); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "error: %s\n", isc_result_totext(result)); + return (1); + } + fprintf(stdout, "%.*s\n", (int)isc_buffer_usedlength(&buf), base64); + return (0); +} diff --git a/contrib/bind9/bin/tools/isc-hmac-fixup.docbook b/contrib/bind9/bin/tools/isc-hmac-fixup.docbook new file mode 100644 index 000000000000..a3039ee814d9 --- /dev/null +++ b/contrib/bind9/bin/tools/isc-hmac-fixup.docbook @@ -0,0 +1,109 @@ +<!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) 2010 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: isc-hmac-fixup.docbook,v 1.2 2010-01-07 21:52:11 each Exp $ --> +<refentry id="man.isc-hmac-fixup"> + <refentryinfo> + <date>January 5, 2010</date> + </refentryinfo> + + <refmeta> + <refentrytitle><application>isc-hmac-fixup</application></refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo>BIND9</refmiscinfo> + </refmeta> + + <refnamediv> + <refname><application>isc-hmac-fixup</application></refname> + <refpurpose>fixes HMAC keys generated by older versions of BIND</refpurpose> + </refnamediv> + + <docinfo> + <copyright> + <year>2010</year> + <holder>Internet Systems Consortium, Inc. ("ISC")</holder> + </copyright> + </docinfo> + + <refsynopsisdiv> + <cmdsynopsis> + <command>isc-hmac-fixup</command> + <arg choice="req"><replaceable class="parameter">algorithm</replaceable></arg> + <arg choice="req"><replaceable class="parameter">secret</replaceable></arg> + </cmdsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>DESCRIPTION</title> + <para> + Versions of BIND 9 up to and including BIND 9.6 had a bug causing + HMAC-SHA* TSIG keys which were longer than the digest length of the + hash algorithm (i.e., SHA1 keys longer than 160 bits, SHA256 keys + longer than 256 bits, etc) to be used incorrectly, generating a + message authentication code that was incompatible with other DNS + implementations. + </para> + <para> + This bug has been fixed in BIND 9.7. However, the fix may + cause incompatibility between older and newer versions of + BIND, when using long keys. <command>isc-hmac-fixup</command> + modifies those keys to restore compatibility. + </para> + <para> + To modify a key, run <command>isc-hmac-fixup</command> and + specify the key's algorithm and secret on the command line. If the + secret is longer than the digest length of the algorithm (64 bytes + for SHA1 through SHA256, or 128 bytes for SHA384 and SHA512), then a + new secret will be generated consisting of a hash digest of the old + secret. (If the secret did not require conversion, then it will be + printed without modification.) + </para> + </refsect1> + + <refsect1> + <title>SECURITY CONSIDERATIONS</title> + <para> + Secrets that have been converted by <command>isc-hmac-fixup</command> + are shortened, but as this is how the HMAC protocol works in + operation anyway, it does not affect security. RFC 2104 notes, + "Keys longer than [the digest length] are acceptable but the + extra length would not significantly increase the function + strength." + </para> + </refsect1> + + <refsect1> + <title>SEE ALSO</title> + <para> + <citetitle>BIND 9 Administrator Reference Manual</citetitle>, + <citetitle>RFC 2104</citetitle>. + </para> + </refsect1> + + <refsect1> + <title>AUTHOR</title> + <para><corpauthor>Internet Systems Consortium</corpauthor> + </para> + </refsect1> + +</refentry><!-- + - Local variables: + - mode: sgml + - End: +--> diff --git a/contrib/bind9/bin/tools/isc-hmac-fixup.html b/contrib/bind9/bin/tools/isc-hmac-fixup.html new file mode 100644 index 000000000000..8b70777cd792 --- /dev/null +++ b/contrib/bind9/bin/tools/isc-hmac-fixup.html @@ -0,0 +1,83 @@ +<!-- + - Copyright (C) 2010 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: isc-hmac-fixup.html,v 1.4 2010-05-19 01:14:14 tbox Exp $ --> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<title>isc-hmac-fixup</title> +<meta name="generator" content="DocBook XSL Stylesheets V1.71.1"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en"> +<a name="man.isc-hmac-fixup"></a><div class="titlepage"></div> +<div class="refnamediv"> +<h2>Name</h2> +<p><span class="application">isc-hmac-fixup</span> — fixes HMAC keys generated by older versions of BIND</p> +</div> +<div class="refsynopsisdiv"> +<h2>Synopsis</h2> +<div class="cmdsynopsis"><p><code class="command">isc-hmac-fixup</code> {<em class="replaceable"><code>algorithm</code></em>} {<em class="replaceable"><code>secret</code></em>}</p></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543351"></a><h2>DESCRIPTION</h2> +<p> + Versions of BIND 9 up to and including BIND 9.6 had a bug causing + HMAC-SHA* TSIG keys which were longer than the digest length of the + hash algorithm (i.e., SHA1 keys longer than 160 bits, SHA256 keys + longer than 256 bits, etc) to be used incorrectly, generating a + message authentication code that was incompatible with other DNS + implementations. + </p> +<p> + This bug has been fixed in BIND 9.7. However, the fix may + cause incompatibility between older and newer versions of + BIND, when using long keys. <span><strong class="command">isc-hmac-fixup</strong></span> + modifies those keys to restore compatibility. + </p> +<p> + To modify a key, run <span><strong class="command">isc-hmac-fixup</strong></span> and + specify the key's algorithm and secret on the command line. If the + secret is longer than the digest length of the algorithm (64 bytes + for SHA1 through SHA256, or 128 bytes for SHA384 and SHA512), then a + new secret will be generated consisting of a hash digest of the old + secret. (If the secret did not require conversion, then it will be + printed without modification.) + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543374"></a><h2>SECURITY CONSIDERATIONS</h2> +<p> + Secrets that have been converted by <span><strong class="command">isc-hmac-fixup</strong></span> + are shortened, but as this is how the HMAC protocol works in + operation anyway, it does not affect security. RFC 2104 notes, + "Keys longer than [the digest length] are acceptable but the + extra length would not significantly increase the function + strength." + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543388"></a><h2>SEE ALSO</h2> +<p> + <em class="citetitle">BIND 9 Administrator Reference Manual</em>, + <em class="citetitle">RFC 2104</em>. + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543405"></a><h2>AUTHOR</h2> +<p><span class="corpauthor">Internet Systems Consortium</span> + </p> +</div> +</div></body> +</html> diff --git a/contrib/bind9/bin/tools/named-journalprint.8 b/contrib/bind9/bin/tools/named-journalprint.8 new file mode 100644 index 000000000000..347b67b1bacd --- /dev/null +++ b/contrib/bind9/bin/tools/named-journalprint.8 @@ -0,0 +1,60 @@ +.\" 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: named-journalprint.8,v 1.4 2010-05-19 01:14:14 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: named\-journalprint +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/> +.\" Date: Feb 18, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "NAMED\-JOURNALPRINT" "8" "Feb 18, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +named\-journalprint \- print zone journal in human\-readable form +.SH "SYNOPSIS" +.HP 19 +\fBnamed\-journalprint\fR {\fIjournal\fR} +.SH "DESCRIPTION" +.PP +\fBnamed\-journalprint\fR +prints the contents of a zone journal file in a human\-readable form. +.PP +Journal files are automatically created by +\fBnamed\fR +when changes are made to dynamic zones (e.g., by +\fBnsupdate\fR). They record each addition or deletion of a resource record, in binary format, allowing the changes to be re\-applied to the zone when the server is restarted after a shutdown or crash. By default, the name of the journal file is formed by appending the extension +\fI.jnl\fR +to the name of the corresponding zone file. +.PP +\fBnamed\-journalprint\fR +converts the contents of a given journal file into a human\-readable text format. Each line begins with "add" or "del", to indicate whether the record was added or deleted, and continues with the resource record in master\-file format. +.SH "SEE ALSO" +.PP +\fBnamed\fR(8), +\fBnsupdate\fR(8), +BIND 9 Administrator Reference Manual. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/contrib/bind9/bin/tools/named-journalprint.c b/contrib/bind9/bin/tools/named-journalprint.c new file mode 100644 index 000000000000..8a00aa7a85d9 --- /dev/null +++ b/contrib/bind9/bin/tools/named-journalprint.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2000, 2001 Internet Software Consortium. + * + * 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: named-journalprint.c,v 1.2 2009-12-04 21:59:23 marka Exp $ */ + +/*! \file */ +#include <config.h> + +#include <isc/log.h> +#include <isc/mem.h> +#include <isc/util.h> + +#include <dns/journal.h> +#include <dns/log.h> +#include <dns/result.h> +#include <dns/types.h> + +#include <stdlib.h> + +/* + * Setup logging to use stderr. + */ +static isc_result_t +setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) { + isc_logdestination_t destination; + isc_logconfig_t *logconfig = NULL; + isc_log_t *log = NULL; + + RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS); + isc_log_setcontext(log); + dns_log_init(log); + dns_log_setcontext(log); + + destination.file.stream = errout; + destination.file.name = NULL; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + RUNTIME_CHECK(isc_log_createchannel(logconfig, "stderr", + ISC_LOG_TOFILEDESC, + ISC_LOG_DYNAMIC, + &destination, 0) == ISC_R_SUCCESS); + RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", + NULL, NULL) == ISC_R_SUCCESS); + + *logp = log; + return (ISC_R_SUCCESS); +} + +int +main(int argc, char **argv) { + char *file; + isc_mem_t *mctx = NULL; + isc_result_t result; + isc_log_t *lctx = NULL; + + if (argc != 2) { + printf("usage: %s journal\n", argv[0]); + return(1); + } + + file = argv[1]; + + RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); + RUNTIME_CHECK(setup_logging(mctx, stderr, &lctx) == ISC_R_SUCCESS); + + result = dns_journal_print(mctx, file, stdout); + if (result == DNS_R_NOJOURNAL) + fprintf(stderr, "%s\n", dns_result_totext(result)); + isc_log_destroy(&lctx); + isc_mem_detach(&mctx); + return(result != ISC_R_SUCCESS ? 1 : 0); +} diff --git a/contrib/bind9/bin/tools/named-journalprint.docbook b/contrib/bind9/bin/tools/named-journalprint.docbook new file mode 100644 index 000000000000..d523f8c1aff2 --- /dev/null +++ b/contrib/bind9/bin/tools/named-journalprint.docbook @@ -0,0 +1,101 @@ +<!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: named-journalprint.docbook,v 1.2 2009-12-04 21:59:23 marka Exp $ --> +<refentry id="man.named-journalprint"> + <refentryinfo> + <date>Feb 18, 2009</date> + </refentryinfo> + + <refmeta> + <refentrytitle><application>named-journalprint</application></refentrytitle> + <manvolnum>8</manvolnum> + <refmiscinfo>BIND9</refmiscinfo> + </refmeta> + + <refnamediv> + <refname><application>named-journalprint</application></refname> + <refpurpose>print zone journal in human-readable form</refpurpose> + </refnamediv> + + <docinfo> + <copyright> + <year>2009</year> + <holder>Internet Systems Consortium, Inc. ("ISC")</holder> + </copyright> + </docinfo> + + <refsynopsisdiv> + <cmdsynopsis> + <command>named-journalprint</command> + <arg choice="req"><replaceable class="parameter">journal</replaceable></arg> + </cmdsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>DESCRIPTION</title> + <para> + <command>named-journalprint</command> + prints the contents of a zone journal file in a human-readable + form. + </para> + <para> + Journal files are automatically created by <command>named</command> + when changes are made to dynamic zones (e.g., by + <command>nsupdate</command>). They record each addition + or deletion of a resource record, in binary format, allowing the + changes to be re-applied to the zone when the server is + restarted after a shutdown or crash. By default, the name of + the journal file is formed by appending the extension + <filename>.jnl</filename> to the name of the corresponding + zone file. + </para> + <para> + <command>named-journalprint</command> converts the contents of a given + journal file into a human-readable text format. Each line begins + with "add" or "del", to indicate whether the record was added or + deleted, and continues with the resource record in master-file + format. + </para> + </refsect1> + + <refsect1> + <title>SEE ALSO</title> + <para> + <citerefentry> + <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>nsupdate</refentrytitle><manvolnum>8</manvolnum> + </citerefentry>, + <citetitle>BIND 9 Administrator Reference Manual</citetitle>. + </para> + </refsect1> + + <refsect1> + <title>AUTHOR</title> + <para><corpauthor>Internet Systems Consortium</corpauthor> + </para> + </refsect1> + +</refentry><!-- + - Local variables: + - mode: sgml + - End: +--> diff --git a/contrib/bind9/bin/tools/named-journalprint.html b/contrib/bind9/bin/tools/named-journalprint.html new file mode 100644 index 000000000000..8878fc506555 --- /dev/null +++ b/contrib/bind9/bin/tools/named-journalprint.html @@ -0,0 +1,73 @@ +<!-- + - 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: named-journalprint.html,v 1.4 2010-05-19 01:14:14 tbox Exp $ --> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<title>named-journalprint</title> +<meta name="generator" content="DocBook XSL Stylesheets V1.71.1"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en"> +<a name="man.named-journalprint"></a><div class="titlepage"></div> +<div class="refnamediv"> +<h2>Name</h2> +<p><span class="application">named-journalprint</span> — print zone journal in human-readable form</p> +</div> +<div class="refsynopsisdiv"> +<h2>Synopsis</h2> +<div class="cmdsynopsis"><p><code class="command">named-journalprint</code> {<em class="replaceable"><code>journal</code></em>}</p></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543342"></a><h2>DESCRIPTION</h2> +<p> + <span><strong class="command">named-journalprint</strong></span> + prints the contents of a zone journal file in a human-readable + form. + </p> +<p> + Journal files are automatically created by <span><strong class="command">named</strong></span> + when changes are made to dynamic zones (e.g., by + <span><strong class="command">nsupdate</strong></span>). They record each addition + or deletion of a resource record, in binary format, allowing the + changes to be re-applied to the zone when the server is + restarted after a shutdown or crash. By default, the name of + the journal file is formed by appending the extension + <code class="filename">.jnl</code> to the name of the corresponding + zone file. + </p> +<p> + <span><strong class="command">named-journalprint</strong></span> converts the contents of a given + journal file into a human-readable text format. Each line begins + with "add" or "del", to indicate whether the record was added or + deleted, and continues with the resource record in master-file + format. + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543378"></a><h2>SEE ALSO</h2> +<p> + <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>, + <span class="citerefentry"><span class="refentrytitle">nsupdate</span>(8)</span>, + <em class="citetitle">BIND 9 Administrator Reference Manual</em>. + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543409"></a><h2>AUTHOR</h2> +<p><span class="corpauthor">Internet Systems Consortium</span> + </p> +</div> +</div></body> +</html> diff --git a/contrib/bind9/bin/tools/nsec3hash.8 b/contrib/bind9/bin/tools/nsec3hash.8 new file mode 100644 index 000000000000..6fba8c886cf9 --- /dev/null +++ b/contrib/bind9/bin/tools/nsec3hash.8 @@ -0,0 +1,70 @@ +.\" 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: nsec3hash.8,v 1.5 2010-05-19 01:14:14 tbox Exp $ +.\" +.hy 0 +.ad l +.\" Title: nsec3hash +.\" Author: +.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/> +.\" Date: Feb 18, 2009 +.\" Manual: BIND9 +.\" Source: BIND9 +.\" +.TH "NSEC3HASH" "8" "Feb 18, 2009" "BIND9" "BIND9" +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.SH "NAME" +nsec3hash \- generate NSEC3 hash +.SH "SYNOPSIS" +.HP 10 +\fBnsec3hash\fR {\fIsalt\fR} {\fIalgorithm\fR} {\fIiterations\fR} {\fIdomain\fR} +.SH "DESCRIPTION" +.PP +\fBnsec3hash\fR +generates an NSEC3 hash based on a set of NSEC3 parameters. This can be used to check the validity of NSEC3 records in a signed zone. +.SH "ARGUMENTS" +.PP +salt +.RS 4 +The salt provided to the hash algorithm. +.RE +.PP +algorithm +.RS 4 +A number indicating the hash algorithm. Currently the only supported hash algorithm for NSEC3 is SHA\-1, which is indicated by the number 1; consequently "1" is the only useful value for this argument. +.RE +.PP +iterations +.RS 4 +The number of additional times the hash should be performed. +.RE +.PP +domain +.RS 4 +The domain name to be hashed. +.RE +.SH "SEE ALSO" +.PP +BIND 9 Administrator Reference Manual, +RFC 5155. +.SH "AUTHOR" +.PP +Internet Systems Consortium +.SH "COPYRIGHT" +Copyright \(co 2009 Internet Systems Consortium, Inc. ("ISC") +.br diff --git a/contrib/bind9/bin/tools/nsec3hash.c b/contrib/bind9/bin/tools/nsec3hash.c new file mode 100644 index 000000000000..0e2a910c9150 --- /dev/null +++ b/contrib/bind9/bin/tools/nsec3hash.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2006, 2008, 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: nsec3hash.c,v 1.6 2009-10-06 21:20:44 each Exp $ */ + +#include <config.h> + +#include <stdlib.h> +#include <stdarg.h> + +#include <isc/base32.h> +#include <isc/buffer.h> +#include <isc/hex.h> +#include <isc/iterated_hash.h> +#include <isc/print.h> +#include <isc/result.h> +#include <isc/string.h> +#include <isc/types.h> + +#include <dns/fixedname.h> +#include <dns/name.h> +#include <dns/nsec3.h> +#include <dns/types.h> + +const char *program = "nsec3hash"; + +ISC_PLATFORM_NORETURN_PRE static void +fatal(const char *format, ...) ISC_PLATFORM_NORETURN_POST; + +static void +fatal(const char *format, ...) { + va_list args; + + fprintf(stderr, "%s: ", program); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + exit(1); +} + +static void +check_result(isc_result_t result, const char *message) { + if (result != ISC_R_SUCCESS) + fatal("%s: %s", message, isc_result_totext(result)); +} + +static void +usage() { + fatal("salt hash iterations domain"); +} + +int +main(int argc, char **argv) { + dns_fixedname_t fixed; + dns_name_t *name; + isc_buffer_t buffer; + isc_region_t region; + isc_result_t result; + unsigned char hash[NSEC3_MAX_HASH_LENGTH]; + unsigned char salt[DNS_NSEC3_SALTSIZE]; + unsigned char text[1024]; + unsigned int hash_alg; + unsigned int length; + unsigned int iterations; + unsigned int salt_length; + + if (argc != 5) + usage(); + + if (strcmp(argv[1], "-") == 0) { + salt_length = 0; + salt[0] = 0; + } else { + isc_buffer_init(&buffer, salt, sizeof(salt)); + result = isc_hex_decodestring(argv[1], &buffer); + check_result(result, "isc_hex_decodestring(salt)"); + salt_length = isc_buffer_usedlength(&buffer); + if (salt_length > DNS_NSEC3_SALTSIZE) + fatal("salt too long"); + } + hash_alg = atoi(argv[2]); + if (hash_alg > 255U) + fatal("hash algorithm too large"); + iterations = atoi(argv[3]); + if (iterations > 0xffffU) + fatal("iterations to large"); + + dns_fixedname_init(&fixed); + name = dns_fixedname_name(&fixed); + isc_buffer_init(&buffer, argv[4], strlen(argv[4])); + isc_buffer_add(&buffer, strlen(argv[4])); + result = dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL); + check_result(result, "dns_name_fromtext() failed"); + + dns_name_downcase(name, name, NULL); + length = isc_iterated_hash(hash, hash_alg, iterations, salt, + salt_length, name->ndata, name->length); + if (length == 0) + fatal("isc_iterated_hash failed"); + region.base = hash; + region.length = length; + isc_buffer_init(&buffer, text, sizeof(text)); + isc_base32hex_totext(®ion, 1, "", &buffer); + fprintf(stdout, "%.*s (salt=%s, hash=%u, iterations=%u)\n", + (int)isc_buffer_usedlength(&buffer), text, argv[1], hash_alg, iterations); + return(0); +} diff --git a/contrib/bind9/bin/tools/nsec3hash.docbook b/contrib/bind9/bin/tools/nsec3hash.docbook new file mode 100644 index 000000000000..48eb4afb41ca --- /dev/null +++ b/contrib/bind9/bin/tools/nsec3hash.docbook @@ -0,0 +1,125 @@ +<!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: nsec3hash.docbook,v 1.3 2009-03-02 23:47:43 tbox Exp $ --> +<refentry id="man.nsec3hash"> + <refentryinfo> + <date>Feb 18, 2009</date> + </refentryinfo> + + <refmeta> + <refentrytitle><application>nsec3hash</application></refentrytitle> + <manvolnum>8</manvolnum> + <refmiscinfo>BIND9</refmiscinfo> + </refmeta> + + <refnamediv> + <refname><application>nsec3hash</application></refname> + <refpurpose>generate NSEC3 hash</refpurpose> + </refnamediv> + + <docinfo> + <copyright> + <year>2009</year> + <holder>Internet Systems Consortium, Inc. ("ISC")</holder> + </copyright> + </docinfo> + + <refsynopsisdiv> + <cmdsynopsis> + <command>nsec3hash</command> + <arg choice="req"><replaceable class="parameter">salt</replaceable></arg> + <arg choice="req"><replaceable class="parameter">algorithm</replaceable></arg> + <arg choice="req"><replaceable class="parameter">iterations</replaceable></arg> + <arg choice="req"><replaceable class="parameter">domain</replaceable></arg> + </cmdsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>DESCRIPTION</title> + <para> + <command>nsec3hash</command> generates an NSEC3 hash based on + a set of NSEC3 parameters. This can be used to check the validity + of NSEC3 records in a signed zone. + </para> + </refsect1> + + <refsect1> + <title>ARGUMENTS</title> + <variablelist> + <varlistentry> + <term>salt</term> + <listitem> + <para> + The salt provided to the hash algorithm. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>algorithm</term> + <listitem> + <para> + A number indicating the hash algorithm. Currently the + only supported hash algorithm for NSEC3 is SHA-1, which is + indicated by the number 1; consequently "1" is the only + useful value for this argument. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>iterations</term> + <listitem> + <para> + The number of additional times the hash should be performed. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>domain</term> + <listitem> + <para> + The domain name to be hashed. + </para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>SEE ALSO</title> + <para> + <citetitle>BIND 9 Administrator Reference Manual</citetitle>, + <citetitle>RFC 5155</citetitle>. + </para> + </refsect1> + + <refsect1> + <title>AUTHOR</title> + <para><corpauthor>Internet Systems Consortium</corpauthor> + </para> + </refsect1> + +</refentry><!-- + - Local variables: + - mode: sgml + - End: +--> diff --git a/contrib/bind9/bin/tools/nsec3hash.html b/contrib/bind9/bin/tools/nsec3hash.html new file mode 100644 index 000000000000..e6c09959f153 --- /dev/null +++ b/contrib/bind9/bin/tools/nsec3hash.html @@ -0,0 +1,78 @@ +<!-- + - 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: nsec3hash.html,v 1.5 2010-05-19 01:14:14 tbox Exp $ --> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<title>nsec3hash</title> +<meta name="generator" content="DocBook XSL Stylesheets V1.71.1"> +</head> +<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en"> +<a name="man.nsec3hash"></a><div class="titlepage"></div> +<div class="refnamediv"> +<h2>Name</h2> +<p><span class="application">nsec3hash</span> — generate NSEC3 hash</p> +</div> +<div class="refsynopsisdiv"> +<h2>Synopsis</h2> +<div class="cmdsynopsis"><p><code class="command">nsec3hash</code> {<em class="replaceable"><code>salt</code></em>} {<em class="replaceable"><code>algorithm</code></em>} {<em class="replaceable"><code>iterations</code></em>} {<em class="replaceable"><code>domain</code></em>}</p></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543367"></a><h2>DESCRIPTION</h2> +<p> + <span><strong class="command">nsec3hash</strong></span> generates an NSEC3 hash based on + a set of NSEC3 parameters. This can be used to check the validity + of NSEC3 records in a signed zone. + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543380"></a><h2>ARGUMENTS</h2> +<div class="variablelist"><dl> +<dt><span class="term">salt</span></dt> +<dd><p> + The salt provided to the hash algorithm. + </p></dd> +<dt><span class="term">algorithm</span></dt> +<dd><p> + A number indicating the hash algorithm. Currently the + only supported hash algorithm for NSEC3 is SHA-1, which is + indicated by the number 1; consequently "1" is the only + useful value for this argument. + </p></dd> +<dt><span class="term">iterations</span></dt> +<dd><p> + The number of additional times the hash should be performed. + </p></dd> +<dt><span class="term">domain</span></dt> +<dd><p> + The domain name to be hashed. + </p></dd> +</dl></div> +</div> +<div class="refsect1" lang="en"> +<a name="id2543442"></a><h2>SEE ALSO</h2> +<p> + <em class="citetitle">BIND 9 Administrator Reference Manual</em>, + <em class="citetitle">RFC 5155</em>. + </p> +</div> +<div class="refsect1" lang="en"> +<a name="id2543459"></a><h2>AUTHOR</h2> +<p><span class="corpauthor">Internet Systems Consortium</span> + </p> +</div> +</div></body> +</html> |