From bfe32d08c51a606744bd0d6ea518eb95084d2eef Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Mon, 23 May 2011 20:10:03 +0000 Subject: [PATCH] 3116. [func] New 'dnssec-update-mode' option controls updates of DNSSEC records in signed dynamic zones. Set to 'no-resign' to disable automatic RRSIG regeneration while retaining the ability to sign new or changed data. [RT #24533] --- CHANGES | 6 ++ bin/named/config.c | 3 +- bin/named/zoneconf.c | 19 +++-- bin/tests/system/dnssec/clean.sh | 4 +- bin/tests/system/dnssec/ns3/named.conf | 9 ++- .../system/dnssec/ns3/nosign.example.db.in | 28 +++++++ bin/tests/system/dnssec/ns3/sign.sh | 22 +++++- bin/tests/system/dnssec/tests.sh | 45 ++++++++++- doc/arm/Bv9ARM-book.xml | 74 ++++++++++++++----- lib/dns/include/dns/zone.h | 3 +- lib/dns/zone.c | 11 ++- lib/isccfg/namedconf.c | 12 ++- 12 files changed, 202 insertions(+), 34 deletions(-) create mode 100644 bin/tests/system/dnssec/ns3/nosign.example.db.in diff --git a/CHANGES b/CHANGES index 7ddbda4617..0ae3f445d6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +3116. [func] New 'dnssec-update-mode' option controls updates + of DNSSEC records in signed dynamic zones. Set to + 'no-resign' to disable automatic RRSIG regeneration + while retaining the ability to sign new or changed + data. [RT #24533] + 3115. [bug] Named could fail to return requested data when following a CNAME that points into the same zone. [RT #24455] diff --git a/bin/named/config.c b/bin/named/config.c index 00ba064986..fe102d2b02 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.c,v 1.117 2011/04/29 21:37:14 each Exp $ */ +/* $Id: config.c,v 1.118 2011/05/23 20:10:01 each Exp $ */ /*! \file */ @@ -209,6 +209,7 @@ options {\n\ check-srv-cname warn;\n\ zero-no-soa-ttl yes;\n\ update-check-ksk yes;\n\ + dnssec-update-mode maintain;\n\ dnssec-dnskey-kskonly no;\n\ dnssec-loadkeys-interval 60;\n\ try-tcp-refresh yes; /* BIND 8 compat */\n\ diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 5fb74159b7..8764ec1c6c 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.c,v 1.176 2011/05/06 21:23:50 each Exp $ */ +/* $Id: zoneconf.c,v 1.177 2011/05/23 20:10:01 each Exp $ */ /*% */ @@ -1248,7 +1248,6 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, */ 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); @@ -1338,15 +1337,25 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, 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); + } + + obj = NULL; + result = cfg_map_get(zoptions, "dnssec-update-mode", &obj); + if (result == ISC_R_SUCCESS) { + const char *arg = cfg_obj_asstring(obj); + if (strcasecmp(arg, "no-resign") == 0) + dns_zone_setkeyopt(zone, DNS_ZONEKEY_NORESIGN, + ISC_TRUE); + else if (strcasecmp(arg, "maintain") == 0) + ; + else + INSIST(0); } } diff --git a/bin/tests/system/dnssec/clean.sh b/bin/tests/system/dnssec/clean.sh index d5ca8e8fd0..e4c1c2ad5c 100644 --- a/bin/tests/system/dnssec/clean.sh +++ b/bin/tests/system/dnssec/clean.sh @@ -15,7 +15,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: clean.sh,v 1.41 2011/03/07 14:03:49 marka Exp $ +# $Id: clean.sh,v 1.42 2011/05/23 20:10:02 each Exp $ rm -f */K* */keyset-* */dsset-* */dlvset-* */signedkey-* */*.signed rm -f */trusted.conf */managed.conf */tmp* */*.jnl */*.bk @@ -24,6 +24,7 @@ rm -f ns3/unsecure.example.db ns3/bogus.example.db ns3/keyless.example.db rm -f ns3/dynamic.example.db ns3/dynamic.example.db.signed.jnl rm -f ns3/rsasha256.example.db ns3/rsasha512.example.db rm -f ns3/split-dnssec.example.db +rm -f ns3/expiring.example.db ns3/nosign.example.db rm -f ns2/private.secure.example.db rm -f ns2/badparam.db ns2/badparam.db.bad rm -f ns2/single-nsec3.db @@ -56,3 +57,4 @@ rm -f signer/nsec3param.out rm -f ns3/ttlpatch.example.db ns3/ttlpatch.example.db.signed rm -f ns3/ttlpatch.example.db.patched rm -f ns3/split-smart.example.db +rm -f nosign.before diff --git a/bin/tests/system/dnssec/ns3/named.conf b/bin/tests/system/dnssec/ns3/named.conf index 4e320bbccb..2ed281d8d7 100644 --- a/bin/tests/system/dnssec/ns3/named.conf +++ b/bin/tests/system/dnssec/ns3/named.conf @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named.conf,v 1.47 2011/05/19 00:31:57 smann Exp $ */ +/* $Id: named.conf,v 1.48 2011/05/23 20:10:02 each Exp $ */ // NS3 @@ -229,4 +229,11 @@ zone "expiring.example" { file "expiring.example.db.signed"; }; +zone "nosign.example" { + type master; + allow-update { any; }; + dnssec-update-mode no-resign; + file "nosign.example.db.signed"; +}; + include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns3/nosign.example.db.in b/bin/tests/system/dnssec/ns3/nosign.example.db.in new file mode 100644 index 0000000000..c6a1860ca6 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/nosign.example.db.in @@ -0,0 +1,28 @@ +; Copyright (C) 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 +; 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: nosign.example.db.in,v 1.2 2011/05/23 20:10:02 each Exp $ + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 diff --git a/bin/tests/system/dnssec/ns3/sign.sh b/bin/tests/system/dnssec/ns3/sign.sh index 58e9ad1811..24731960bd 100644 --- a/bin/tests/system/dnssec/ns3/sign.sh +++ b/bin/tests/system/dnssec/ns3/sign.sh @@ -15,7 +15,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: sign.sh,v 1.41 2011/05/19 00:31:57 smann Exp $ +# $Id: sign.sh,v 1.42 2011/05/23 20:10:02 each Exp $ SYSTEMTESTTOP=../.. . $SYSTEMTESTTOP/conf.sh @@ -370,6 +370,9 @@ echo '$INCLUDE "'"$signedfile"'"' >> $zonefile : > $signedfile $SIGNER -P -S -r $RANDFILE -D -o $zone $zonefile > /dev/null 2>&1 +# +# Zone with signatures about to expire, but no private key to replace them +# zone="expiring.example." infile="expiring.example.db.in" zonefile="expiring.example.db" @@ -380,3 +383,20 @@ cp $infile $zonefile $SIGNER -S -r $RANDFILE -e now+1mi -o $zone $zonefile > /dev/null 2>&1 rm -f ${zskname}.private ${kskname}.private +# +# Zone with signatures about to expire, and dynamic, but configured +# not to resign with 'auto-resign no;' +# +zone="nosign.example." +infile="nosign.example.db.in" +zonefile="nosign.example.db" +signedfile="nosign.example.db.signed" +kskname=`$KEYGEN -q -r $RANDFILE $zone` +zskname=`$KEYGEN -q -r $RANDFILE -f KSK $zone` +cp $infile $zonefile +$SIGNER -S -r $RANDFILE -e now+1mi -o $zone $zonefile > /dev/null 2>&1 +# preserve a normalized copy of the NS RRSIG for comparison later +$CHECKZONE -D nosign.example nosign.example.db.signed 2>&- | \ + awk '$4 == "RRSIG" && $5 == "NS" {$2 = ""; print}' | \ + sed 's/[ ][ ]*/ /g'> ../nosign.before + diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 58e8637e93..e19bcb6b0a 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -15,7 +15,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: tests.sh,v 1.89 2011/05/19 00:31:57 smann Exp $ +# $Id: tests.sh,v 1.90 2011/05/23 20:10:02 each Exp $ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh @@ -1329,6 +1329,49 @@ ret=0 $DIG +noall +answer +dnssec +nottl -p 5300 expiring.example ns @10.53.0.3 | grep RRSIG > dig.out.ns3.test$n 2>&1 # there must be a signature here [ -s dig.out.ns3.test$n ] || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:testing new records are signed with 'no-resign' ($n)" +ret=0 +( +echo zone nosign.example +echo server 10.53.0.3 5300 +echo update add new.nosign.example 300 in txt "hi there" +echo send +) | $NSUPDATE +sleep 1 +$DIG +noall +answer +dnssec -p 5300 txt new.nosign.example @10.53.0.3 \ + > dig.out.ns3.test$n 2>&1 +grep RRSIG dig.out.ns3.test$n > /dev/null 2>&1 || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:testing expiring records aren't resigned with 'no-resign' ($n)" +ret=0 +$DIG +noall +answer +dnssec +nottl -p 5300 nosign.example ns @10.53.0.3 | \ + grep RRSIG | sed 's/[ ][ ]*/ /g' > dig.out.ns3.test$n 2>&1 +# the NS RRSIG should not be changed +cmp -s nosign.before dig.out.ns3.test$n || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:testing updates fail with no private key ($n)" +ret=0 +rm -f ns3/Knosign.example.*.private +( +echo zone nosign.example +echo server 10.53.0.3 5300 +echo update add fail.nosign.example 300 in txt "reject me" +echo send +) | $NSUPDATE > /dev/null 2>&1 && ret=1 +$DIG +noall +answer +dnssec -p 5300 fail.nosign.example txt @10.53.0.3 \ + > dig.out.ns3.test$n 2>&1 +[ -s dig.out.ns3.test$n ] && ret=1 +n=`expr $n + 1` if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 214cc9c331..79bb52c4d1 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + BIND 9 Administrator Reference Manual @@ -1189,10 +1189,10 @@ zone "eng.example.com" { This command requires that the auto-dnssec zone option to be set - to allow, - maintain, or - create, and also requires - the zone to be configured to allow dynamic DNS. + to allow or + maintain, + and also requires the zone to be configured to + allow dynamic DNS. See for more details. @@ -1218,9 +1218,9 @@ zone "eng.example.com" { This command requires that the auto-dnssec zone option to - be set to maintain or - create, and also requires - the zone to be configured to allow dynamic DNS. + be set to maintain, + and also requires the zone to be configured to + allow dynamic DNS. See for more details. @@ -5062,6 +5062,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] allow-update { address_match_list }; allow-update-forwarding { address_match_list }; update-check-ksk yes_or_no; + dnssec-update-mode ( maintain | no-resign ); dnssec-dnskey-kskonly yes_or_no; dnssec-loadkeys-interval number; dnssec-secure-to-insecure yes_or_no ; @@ -5852,6 +5853,41 @@ options { + + dnssec-update-mode + + + If this option is set to its default value of + maintain in a zone of type + master which is DNSSEC-signed + and configured to allow dynamic updates (see + ), and + if named has access to the + private signing key(s) for the zone, then + named will automatically sign all new + or changed records and maintain signatures for the zone + by regenerating RRSIG records whenever they approach + their expiration date. + + + If the option is changed to no-resign, + then named will sign all new or + changed records, but scheduled maintenance of + signatures is disabled. + + + With either of these settings, named + will reject updates to a DNSSEC-signed zone when the + signing keys are inactive or unavailable to + named. (A planned third option, + external, will disable all automatic + signing and allow DNSSEC data to be submitted into a zone + via dyanmic update; this is not yet implemented.) + + + + + @@ -10052,7 +10088,7 @@ view "external" { min-retry-time number ; max-retry-time number ; key-directory path_name; - auto-dnssec allow|maintain|create|off; + auto-dnssec allow|maintain|off; zero-no-soa-ttl yes_or_no ; }; @@ -10064,6 +10100,7 @@ zone zone_name class allow-transfer { address_match_list }; allow-update-forwarding { address_match_list }; update-check-ksk yes_or_no; + dnssec-update-mode ( maintain | no-resign ); dnssec-dnskey-kskonly yes_or_no; dnssec-loadkeys-interval number; dnssec-secure-to-insecure yes_or_no ; @@ -10666,6 +10703,16 @@ zone zone_name class + + dnssec-update-mode + + + See the description of + dnssec-update-mode in . + + + + dnssec-dnskey-kskonly @@ -11141,7 +11188,7 @@ example.com. NS ns2.example.net. Zones configured for dynamic DNS may also use this option to allow varying levels of automatic DNSSEC key - management. There are four possible settings: + management. There are three possible settings: auto-dnssec allow; permits @@ -11172,13 +11219,6 @@ example.com. NS ns2.example.net. interval is defined by dnssec-loadkeys-interval.) - - auto-dnssec create; includes the - above, but also allows named - to create new keys in the key repository when needed. - (NOTE: This option is not yet implemented; the syntax is - being reserved for future use.) - The default setting is auto-dnssec off. diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 043d0371cb..496dfe2514 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.188 2011/05/06 21:23:51 each Exp $ */ +/* $Id: zone.h,v 1.189 2011/05/23 20:10:03 each Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -93,6 +93,7 @@ typedef enum { #define DNS_ZONEKEY_MAINTAIN 0x00000002U /*%< publish/sign on schedule */ #define DNS_ZONEKEY_CREATE 0x00000004U /*%< make keys when needed */ #define DNS_ZONEKEY_FULLSIGN 0x00000008U /*%< roll to new keys immediately */ +#define DNS_ZONEKEY_NORESIGN 0x00000010U /*%< no automatic resigning */ #ifndef DNS_ZONE_MINREFRESH #define DNS_ZONE_MINREFRESH 300 /*%< 5 minutes */ diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 03cc0f202c..38e3ce6ff0 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.610 2011/05/19 23:47:17 tbox Exp $ */ +/* $Id: zone.c,v 1.611 2011/05/23 20:10:02 each Exp $ */ /*! \file */ @@ -3625,6 +3625,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, } if (zone->type == dns_zone_master && + !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) && dns_zone_isdynamic(zone, ISC_FALSE) && dns_db_issecure(db)) { dns_name_t *name; @@ -4956,10 +4957,14 @@ zone_resigninc(dns_zone_t *zone) { dns_diff_init(zone->mctx, &sig_diff); sig_diff.resign = zone->sigresigninginterval; + /* - * Updates are disabled. Pause for 5 minutes. + * Zone is frozen or automatic resigning is disabled. + * Pause for 5 minutes. */ - if (zone->update_disabled) { + if (zone->update_disabled || + DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN)) + { result = ISC_R_FAILURE; goto failure; } diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 7baca1c38c..491ab71390 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: namedconf.c,v 1.137 2011/05/07 05:55:17 each Exp $ */ +/* $Id: namedconf.c,v 1.138 2011/05/23 20:10:03 each Exp $ */ /*! \file */ @@ -541,13 +541,18 @@ static cfg_type_t cfg_type_bracketed_sockaddrlist = { &cfg_rep_list, &cfg_type_sockaddr }; -static const char *autodnssec_enums[] = { "allow", "maintain", "create", - "off", NULL }; +static const char *autodnssec_enums[] = { "allow", "maintain", "off", NULL }; static cfg_type_t cfg_type_autodnssec = { "autodnssec", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string, &autodnssec_enums }; +static const char *dnssecupdatemode_enums[] = { "maintain", "no-resign", NULL }; +static cfg_type_t cfg_type_dnssecupdatemode = { + "dnssecupdatemode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, + &cfg_rep_string, &dnssecupdatemode_enums +}; + static cfg_type_t cfg_type_rrsetorder = { "rrsetorder", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_rrsetorderingelement @@ -1360,6 +1365,7 @@ zone_clauses[] = { { "dnssec-dnskey-kskonly", &cfg_type_boolean, 0 }, { "dnssec-loadkeys-interval", &cfg_type_uint32, 0 }, { "dnssec-secure-to-insecure", &cfg_type_boolean, 0 }, + { "dnssec-update-mode", &cfg_type_dnssecupdatemode, 0 }, { "forward", &cfg_type_forwardtype, 0 }, { "forwarders", &cfg_type_portiplist, 0 }, { "key-directory", &cfg_type_qstring, 0 },