+3185. [func] New 'rndc signing' option for auto-dnssec zones:
+ - 'rndc signing -list' displays the current
+ state of signing operations
+ - 'rndc signing -clear' clears the signing state
+ records for keys that have fully signed the zone
+ - 'rndc signing -nsec3param' sets the NSEC3
+ parameters for the zone
+ The 'rndc keydone' syntax is removed. [RT #23729]
+
3184. [bug] named had excessive cpu usage when a redirect zone was
configured. [RT #26013]
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: control.c,v 1.45 2011/10/25 01:54:18 marka Exp $ */
+/* $Id: control.c,v 1.46 2011/10/28 06:20:04 each Exp $ */
/*! \file */
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 if (command_compare(command, NS_COMMAND_KEYDONE)) {
- result = ns_server_keydone(ns_g_server, command);
+ } else if (command_compare(command, NS_COMMAND_SIGNING)) {
+ result = ns_server_signing(ns_g_server, command, text);
} else {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: control.h,v 1.35 2011/10/25 01:54:19 marka Exp $ */
+/* $Id: control.h,v 1.36 2011/10/28 06:20:04 each Exp $ */
#ifndef NAMED_CONTROL_H
#define NAMED_CONTROL_H 1
#define NS_COMMAND_ADDZONE "addzone"
#define NS_COMMAND_DELZONE "delzone"
#define NS_COMMAND_SYNC "sync"
-#define NS_COMMAND_KEYDONE "keydone"
+#define NS_COMMAND_SIGNING "signing"
isc_result_t
ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp);
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: server.h,v 1.114 2011/10/25 01:54:19 marka Exp $ */
+/* $Id: server.h,v 1.115 2011/10/28 06:20:04 each Exp $ */
#ifndef NAMED_SERVER_H
#define NAMED_SERVER_H 1
ns_server_del_zone(ns_server_t *server, char *args);
/*%
- * Deletes the matching key done private record from the zone.
+ * Lists the status of the signing records for a given zone.
*/
isc_result_t
-ns_server_keydone(ns_server_t *server, char *args);
-
+ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text);
#endif /* NAMED_SERVER_H */
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: server.c,v 1.623 2011/10/25 01:54:19 marka Exp $ */
+/* $Id: server.c,v 1.624 2011/10/28 06:20:04 each Exp $ */
/*! \file */
#include <isc/entropy.h>
#include <isc/file.h>
#include <isc/hash.h>
+#include <isc/hex.h>
#include <isc/httpd.h>
#include <isc/lex.h>
#include <isc/parseint.h>
#include <dns/order.h>
#include <dns/peer.h>
#include <dns/portlist.h>
+#include <dns/private.h>
#include <dns/rbt.h>
#include <dns/rdataclass.h>
#include <dns/rdataset.h>
*cfgp = NULL;
}
-/*
- * Act on a "keydone" command from the command channel.
- */
isc_result_t
-ns_server_keydone(ns_server_t *server, char *args) {
- isc_result_t result;
+ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text) {
+ isc_result_t result = ISC_R_SUCCESS;
dns_zone_t *zone = NULL;
- const char *ptr = NULL;
-
+ dns_name_t *origin;
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_rdatatype_t privatetype;
+ dns_rdataset_t privset;
+ isc_boolean_t first = ISC_TRUE;
+ isc_boolean_t list = ISC_FALSE, clear = ISC_FALSE;
+ isc_boolean_t chain = ISC_FALSE;
+ char keystr[DNS_SECALG_FORMATSIZE + 7];
+ isc_uint8_t hash = 0, flags = 0, iter = 0, saltlen = 0;
+ unsigned char salt[255];
+ const char *ptr;
+ size_t n;
+
+ dns_rdataset_init(&privset);
+
+ (void) next_token(&args, " \t");
ptr = next_token(&args, " \t");
- if (ptr == NULL)
- return (ISC_R_UNEXPECTEDEND);
+ if (strcasecmp(ptr, "-list") == 0)
+ list = ISC_TRUE;
+ else if (strcasecmp(ptr, "-clear") == 0) {
+ clear = ISC_TRUE;
+ ptr = next_token(&args, " \t");
+ memcpy(keystr, ptr, sizeof(keystr));
+ } else if(strcasecmp(ptr, "-nsec3param") == 0) {
+ const char *hashstr, *flagstr, *iterstr;
+ isc_buffer_t buf;
+ char nbuf[512];
- ptr = next_token(&args, " \t");
- if (ptr == NULL)
- return (ISC_R_UNEXPECTEDEND);
- /*
- * Is the rdata sane?
- */
- if (strspn(ptr, "0123456789ABCDEFabcdef") != 10U ||
- strncmp(ptr, "00", 2) == 0 || strcmp(ptr + 6, "0001") != 0)
- return (DNS_R_SYNTAX);
+ chain = ISC_TRUE;
+ hashstr = next_token(&args, " \t");
- /*
- * Find the zone.
- */
- result = zone_from_args(server, args, &zone, NULL, ISC_FALSE);
- if (result != ISC_R_SUCCESS)
- return (result);
+ if (strcasecmp(hashstr, "none") == 0)
+ hash = 0;
+ else {
+ flagstr = next_token(&args, " \t");
+ iterstr = next_token(&args, " \t");
+ n = snprintf(nbuf, sizeof(nbuf), "%s %s %s",
+ hashstr, flagstr, iterstr);
+ if (n == sizeof(nbuf))
+ return (ISC_R_NOSPACE);
+ n = sscanf(nbuf, "%hhd %hhd %hhd",
+ &hash, &flags, &iter);
+ if (n != 3)
+ return (ISC_R_BADNUMBER);
+
+ ptr = next_token(&args, " \t");
+ isc_buffer_init(&buf, salt, sizeof(salt));
+ CHECK(isc_hex_decodestring(ptr, &buf));
+ saltlen = isc_buffer_usedlength(&buf);
+ }
+ } else
+ CHECK(ISC_R_NOTFOUND);
+
+ CHECK(zone_from_args(server, args, &zone, NULL, ISC_FALSE));
if (zone == NULL)
- return(ISC_R_NOTFOUND);
+ CHECK(ISC_R_UNEXPECTEDEND);
- if (dns_zone_gettype(zone) != dns_zone_master) {
- result = DNS_R_NOTMASTER;
- goto cleanup;
- }
+ if (clear) {
+ result = dns_zone_keydone(zone, keystr);
+ if (result == ISC_R_SUCCESS) {
+ isc_buffer_putstr(text, "request queued");
+ isc_buffer_putuint8(text, 0);
+ } else
+ CHECK(result);
+ } else if (chain) {
+ result = dns_zone_setnsec3param(zone, hash, flags, iter,
+ saltlen, salt, ISC_TRUE);
+ if (result == ISC_R_SUCCESS) {
+ isc_buffer_putstr(text, "request queued");
+ isc_buffer_putuint8(text, 0);
+ } else
+ CHECK(result);
+ } else {
+ privatetype = dns_zone_getprivatetype(zone);
+ origin = dns_zone_getorigin(zone);
+ CHECK(dns_zone_getdb(zone, &db));
+ CHECK(dns_db_findnode(db, origin, ISC_FALSE, &node));
+ dns_db_currentversion(db, &version);
+
+ result = dns_db_findrdataset(db, node, version, privatetype,
+ dns_rdatatype_none, 0,
+ &privset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ isc_buffer_putstr(text, "No signing records found");
+ isc_buffer_putuint8(text, 0);
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
+ for (result = dns_rdataset_first(&privset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&privset))
+ {
+ dns_rdata_t priv = DNS_RDATA_INIT;
+ char output[BUFSIZ];
+ isc_buffer_t buf;
+
+ dns_rdataset_current(&privset, &priv);
- result = dns_zone_keydone(zone, ptr);
+ isc_buffer_init(&buf, output, sizeof(output));
+ CHECK(dns_private_totext(&priv, &buf));
+
+ if (!first)
+ isc_buffer_putstr(text, "\n");
+ first = ISC_FALSE;
+
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "%s", output);
+ if (n >= isc_buffer_availablelength(text))
+ CHECK(ISC_R_NOSPACE);
+
+ isc_buffer_add(text, n);
+ }
+
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ }
cleanup:
- dns_zone_detach(&zone);
+ if (dns_rdataset_isassociated(&privset))
+ dns_rdataset_disassociate(&privset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (version != NULL)
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
return (result);
}
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: update.c,v 1.197 2011/08/31 06:49:09 marka Exp $ */
+/* $Id: update.c,v 1.198 2011/10/28 06:20:04 each Exp $ */
#include <config.h>
* remove any NSEC chain present will also be removed.
*/
CHECK(dns_nsec3param_deletechains(db, ver, zone,
- &diff));
+ ISC_TRUE, &diff));
} else if (has_dnskey && isdnssec(db, ver, privatetype)) {
isc_uint32_t interval;
dns_update_log_t log;
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rndc.c,v 1.135 2011/10/25 01:54:19 marka Exp $ */
+/* $Id: rndc.c,v 1.136 2011/10/28 06:20:05 each Exp $ */
/*! \file */
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\
- keydone rdata zone [class [view]]\n\
- Remove the private record with the corresponding rdata from\n\
- the given zone.\n\
+ signing -list zone [class [view]]\n\
+ List the private records showing the state of DNSSEC\n\
+ signing in the given zone.\n\
+ signing -clear <keyid>/<algorithm> zone [class [view]]\n\
+ Remove the private record that indicating the given key\n\
+ has finished signing the given zone.\n\
+ signing -clear all zone [class [view]]\n\
+ Remove the private records for all keys that have\n\
+ finished signing the given zone.\n\
\n\
* == not yet implemented\n\
Version: %s\n",
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: tests.sh,v 1.36 2011/10/20 21:20:01 marka Exp $
+# $Id: tests.sh,v 1.37 2011/10/28 06:20:05 each Exp $
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
update add nsec3.example. 3600 NSEC3PARAM 1 0 10 BEEF
send
zone autonsec3.example.
-update add autonsec3.example. 3600 NSEC3PARAM 1 1 10 BEEF
+update add autonsec3.example. 3600 NSEC3PARAM 1 0 20 DEAF
send
zone nsec3.optout.example.
update add nsec3.optout.example. 3600 NSEC3PARAM 1 0 10 BEEF
END
# try to convert nsec.example; this should fail due to non-NSEC key
+echo "I:preset nsec3param in unsigned zone via nsupdate ($n)"
$NSUPDATE > nsupdate.out 2>&1 <<END
server 10.53.0.3 5300
zone nsec.example.
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+echo "I:checking for nsec3param signing record ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list autonsec3.example. > signing.out.test$n 2>&1
+grep "Pending NSEC3 chain 1 0 20 DEAF" signing.out.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:resetting nsec3param via rndc signing ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -clear all autonsec3.example. > /dev/null 2>&1
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -nsec3param 1 1 10 beef autonsec3.example. > /dev/null 2>&1
+sleep 1
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list autonsec3.example. > signing.out.test$n 2>&1
+grep "Pending NSEC3 chain 1 1 10 BEEF" signing.out.test$n > /dev/null || ret=1
+num=`grep "Pending " signing.out.test$n | wc -l`
+[ $num -eq 1 ] || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
echo "I:signing preset nsec3 zone"
zsk=`cat autozsk.key`
ksk=`cat autoksk.key`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+echo "I:checking NSEC3->NSEC conversion with 'rndc signing -nsec3param none' ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -nsec3param none autonsec3.example. > /dev/null 2>&1
+sleep 2
+# this command should result in an empty file:
+$DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.nx.test$n || ret=1
+grep "NSEC3PARAM" dig.out.ns3.nx.test$n > /dev/null && ret=1
+$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
echo "I:checking TTLs of imported DNSKEYs (no default) ($n)"
ret=0
$DIG $DIGOPTS +tcp +noall +answer dnskey ttl1.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: clean.sh,v 1.43 2011/10/11 19:26:06 each Exp $
+# $Id: clean.sh,v 1.44 2011/10/28 06:20:05 each Exp $
rm -f */K* */keyset-* */dsset-* */dlvset-* */signedkey-* */*.signed
rm -f */trusted.conf */managed.conf */tmp* */*.jnl */*.bk
rm -f ns3/ttlpatch.example.db.patched
rm -f ns3/split-smart.example.db
rm -f nosign.before
+rm -f signing.out*
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: named.conf,v 1.48 2011/05/23 20:10:02 each Exp $ */
+/* $Id: named.conf,v 1.49 2011/10/28 06:20:05 each Exp $ */
// NS3
dnssec-validation yes;
};
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
+};
+
zone "." {
type hint;
file "../../common/root.hint";
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: tests.sh,v 1.100 2011/10/26 05:32:56 marka Exp $
+# $Id: tests.sh,v 1.101 2011/10/28 06:20:05 each Exp $
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+echo "I:check rndc signing -list output ($n)"
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list dynamic.example 2>&1 > signing.out
+grep "No signing records found" signing.out > /dev/null 2>&1 || {
+ ret=1
+ sed 's/^/I:ns3 /' signing.out
+}
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list update-nsec3.example 2>&1 > signing.out
+grep "Done signing with key .*/NSEC3RSASHA1" signing.out > /dev/null 2>&1 || {
+ ret=1
+ sed 's/^/I:ns3 /' signing.out
+}
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:clear signing records ($n)"
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -clear all update-nsec3.example > /dev/null || ret=1
+sleep 1
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list update-nsec3.example 2>&1 > signing.out
+grep "No signing records found" signing.out > /dev/null 2>&1 || {
+ ret=1
+ sed 's/^/I:ns3 /' signing.out
+}
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
echo "I:checking that a insecure zone beneath a cname resolves ($n)"
ret=0
$DIG $DIGOPTS soa insecure.below-cname.example. @10.53.0.4 > dig.out.ns4.test$n || ret=1
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: clean.sh,v 1.4 2011/10/25 01:54:19 marka Exp $
+# $Id: clean.sh,v 1.5 2011/10/28 06:20:05 each Exp $
rm -f */named.memstats
rm -f */named.run
rm -f ns5/bits.bk.signed.jnl
rm -f random.data
rm -f dig.out.ns*.test*
+rm -f signing.out*
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: tests.sh,v 1.5 2011/10/26 20:56:45 marka Exp $
+# $Id: tests.sh,v 1.6 2011/10/28 06:20:05 each Exp $
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
for i in 1 2 3 4 5 6 7 8 9 10
do
ret=0
- $DIG $DIGOPTS @10.53.0.3 -p 5300 bits TYPE65534 > dig.out.ns3.test$n
- grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
- grep "ANSWER: 3," dig.out.ns3.test$n > /dev/null || ret=1
- records=`grep 'TYPE65534.*05[0-9A-F][0-9A-F][0-9A-F][0-9A-F]0001$' dig.out.ns3.test$n | wc -l`
- [ $records = 2 ] || ret=1
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list bits > signing.out.test$n 2>&1
+ keys=`grep '^Done signing' signing.out.test$n | wc -l`
+ [ $keys = 2 ] || ret=1
if [ $ret = 0 ]; then break; fi
sleep 1
done
status=`expr $status + $ret`
n=`expr $n + 1`
-echo "I:checking removal of private type record via 'rndc keydone' ($n)"
+echo "I:checking removal of private type record via 'rndc signing -clear' ($n)"
ret=0
-$DIG $DIGOPTS @10.53.0.3 -p 5300 bits TYPE65534 > dig.out.ns3.test$n
-records=`sed -n -e 's/.*TYPE65534.*\(05[0-9A-F][0-9A-F][0-9A-F][0-9A-F]0001\)$/\1/p' dig.out.ns3.test$n`
-for record in $records
-do
- $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 keydone "${record}" bits || ret=1
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list bits > signing.out.test$n 2>&1
+keys=`sed -n -e 's/Done signing with key \(.*\)$/\1/p' signing.out.test$n`
+for key in $keys; do
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -clear ${key} bits > /dev/null || ret=1
break; # We only want to remove 1 record for now.
done 2>&1 |sed 's/^/I:ns3 /'
for i in 1 2 3 4 5 6 7 8 9 10
do
ans=0
- $DIG $DIGOPTS @10.53.0.3 -p 5300 bits TYPE65534 > dig.out.ns3.test$n
- grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ans=1
- [ $ans = 1 ] || break
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list bits > signing.out.test$n 2>&1
+ num=`grep "Done signing with" signing.out.test$n | wc -l`
+ [ $num = 1 ] && break
sleep 1
done
[ $ans = 0 ] || ret=1
status=`expr $status + $ret`
n=`expr $n + 1`
-echo "I:checking removal of remaining private type record via 'rndc keydone' ($n)"
+echo "I:checking removal of remaining private type record via 'rndc signing -clear all' ($n)"
ret=0
-$DIG $DIGOPTS @10.53.0.3 -p 5300 bits TYPE65534 > dig.out.ns3.test$n
-records=`sed -n -e 's/.*TYPE65534.*\(05[0-9A-F][0-9A-F][0-9A-F][0-9A-F]0001\)$/\1/p' dig.out.ns3.test$n`
-for record in $records
-do
- $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 keydone "${record}" bits || ret=1
-done 2>&1 |sed 's/^/I:ns3 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -clear all bits > /dev/null || ret=1
for i in 1 2 3 4 5 6 7 8 9 10
do
ans=0
- $DIG $DIGOPTS @10.53.0.3 -p 5300 bits TYPE65534 > dig.out.ns3.test$n
- grep "ANSWER: 0," dig.out.ns3.test$n > /dev/null || ans=1
- grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ans=1
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list bits > signing.out.test$n 2>&1
+ grep "No signing records found" signing.out.test$n > /dev/null || ans=1
[ $ans = 1 ] || break
sleep 1
done
for i in 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
do
ret=0
- $DIG $DIGOPTS @10.53.0.3 -p 5300 noixfr TYPE65534 > dig.out.ns3.test$n
- grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
- grep "ANSWER: 3," dig.out.ns3.test$n > /dev/null || ret=1
- records=`grep "TYPE65534.*05[0-9A-F][0-9A-F][0-9A-F][0-9A-F]0001" dig.out.ns3.test$n | wc -l`
- [ $records = 2 ] || ret=1
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list noixfr > signing.out.test$n 2>&1
+ keys=`grep '^Done signing' signing.out.test$n | wc -l`
+ [ $keys = 2 ] || ret=1
if [ $ret = 0 ]; then break; fi
sleep 1
done
for i in 1 2 3 4 5 6 7 8 9 10
do
ret=0
- $DIG $DIGOPTS @10.53.0.3 -p 5300 master TYPE65534 > dig.out.ns3.test$n
- grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
- grep "ANSWER: 3," dig.out.ns3.test$n > /dev/null || ret=1
- records=`grep 'TYPE65534.*05[0-9A-F][0-9A-F][0-9A-F][0-9A-F]0001$' dig.out.ns3.test$n | wc -l`
- [ $records = 2 ] || ret=1
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list master > signing.out.test$n 2>&1
+ keys=`grep '^Done signing' signing.out.test$n | wc -l`
+ [ $keys = 2 ] || ret=1
if [ $ret = 0 ]; then break; fi
sleep 1
done
if [ $ret != 0 ]; then echo "I:failed"; fi
n=`expr $n + 1`
-echo "I:checking removal of private type record via 'rndc keydone' (master) ($n)"
+echo "I:checking removal of private type record via 'rndc signing -clear' (master) ($n)"
ret=0
-$DIG $DIGOPTS @10.53.0.3 -p 5300 master TYPE65534 > dig.out.ns3.test$n
-records=`sed -n -e 's/.*TYPE65534.*\(05[0-9A-F][0-9A-F][0-9A-F][0-9A-F]0001\)$/\1/p' dig.out.ns3.test$n`
-for record in $records
-do
- $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 keydone "${record}" master || ret=1
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list master > signing.out.test$n 2>&1
+keys=`sed -n -e 's/Done signing with key \(.*\)$/\1/p' signing.out.test$n`
+for key in $keys; do
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -clear ${key} master > /dev/null || ret=1
break; # We only want to remove 1 record for now.
done 2>&1 |sed 's/^/I:ns3 /'
for i in 1 2 3 4 5 6 7 8 9
do
ans=0
- $DIG $DIGOPTS @10.53.0.3 -p 5300 master TYPE65534 > dig.out.ns3.test$n
- grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ans=1
- [ $ans = 1 ] || break
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list master > signing.out.test$n 2>&1
+ num=`grep "Done signing with" signing.out.test$n | wc -l`
+ [ $num = 1 ] && break
sleep 1
done
[ $ans = 0 ] || ret=1
status=`expr $status + $ret`
n=`expr $n + 1`
-echo "I:checking removal of remaining private type record via 'rndc keydone' (master) ($n)"
+echo "I:checking removal of remaining private type record via 'rndc signing -clear' (master) ($n)"
ret=0
-$DIG $DIGOPTS @10.53.0.3 -p 5300 master TYPE65534 > dig.out.ns3.test$n
-records=`sed -n -e 's/.*TYPE65534.*\(05[0-9A-F][0-9A-F][0-9A-F][0-9A-F]0001\)$/\1/p' dig.out.ns3.test$n`
-for record in $records
-do
- $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 keydone "${record}" master || ret=1
-done 2>&1 |sed 's/^/I:ns3 /'
-
-for i in 1 2 3 4 5 6 7 8 9
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -clear all master > /dev/null || ret=1
+for i in 1 2 3 4 5 6 7 8 9 10
do
ans=0
- $DIG $DIGOPTS @10.53.0.3 -p 5300 master TYPE65534 > dig.out.ns3.test$n
- grep "ANSWER: 0," dig.out.ns3.test$n > /dev/null || ans=1
- grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ans=1
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list master > signing.out.test$n 2>&1
+ grep "No signing records found" signing.out.test$n > /dev/null || ans=1
[ $ans = 1 ] || break
sleep 1
done
for i in 1 2 3 4 5 6 7 8 9 10
do
ret=0
- $DIG $DIGOPTS @10.53.0.3 -p 5300 dynamic TYPE65534 > dig.out.ns3.test$n
- grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
- grep "ANSWER: 3," dig.out.ns3.test$n > /dev/null || ret=1
- records=`grep 'TYPE65534.*05[0-9A-F][0-9A-F][0-9A-F][0-9A-F]0001$' dig.out.ns3.test$n | wc -l`
- [ $records = 2 ] || ret=1
+ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list dynamic > signing.out.test$n 2>&1
+ keys=`grep '^Done signing' signing.out.test$n | wc -l`
+ [ $keys = 2 ] || ret=1
if [ $ret = 0 ]; then break; fi
sleep 1
done
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- File: $Id: Bv9ARM-book.xml,v 1.508 2011/10/26 15:23:37 each Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.509 2011/10/28 06:20:05 each Exp $ -->
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<title>BIND 9 Administrator Reference Manual</title>
</varlistentry>
<varlistentry>
- <term><userinput>keydone
- <replaceable>rdata</replaceable>
+ <term><userinput>signing
+ <optional>( -list | -clear <replaceable>keyid/algorithm</replaceable> | -clear <literal>all</literal> | -nsec3param ( <replaceable>parameters</replaceable> | <literal>none</literal> ) ) </optional>
<replaceable>zone</replaceable>
<optional><replaceable>class</replaceable>
<optional><replaceable>view</replaceable></optional></optional>
</userinput></term>
<listitem>
<para>
- Remove the <command>sig-signing-type</command> record
- which matches the <replaceable>rdata</replaceable>
- (in hexadecimal) from the specified zone. Only
- <replaceable>rdata</replaceable> that
- indicate that named has finished signing the zone
- with the corresponding key will be removed. (i.e.
- the first two characters are not "00", the
- last four characters are "0001" and the total
- length is 10 hexadecimal characters.
+ List, edit, or remove the DNSSEC signing state for
+ the specified zone. The status of ongoing DNSSEC
+ operations (such as signing or generating
+ NSEC3 chains) is stored in the zone in the form
+ of DNS resource records of type
+ <command>sig-signing-type</command>.
+ <command>rndc signing -list</command> converts
+ these records into a human-readable form,
+ indicating which keys are currently signing
+ or have finished signing the zone, and which NSEC3
+ NSEC3 chains are being created or removed.
+ </para>
+ <para>
+ <command>rndc signing -clear</command> can remove
+ a single key (specified in the same format that
+ <command>rndc signing -list</command> uses to
+ display it), or all keys. In either case, only
+ completed keys are removed; any record indicating
+ that a key has not yet finished signing the zone
+ will be retained.
+ </para>
+ <para>
+ <command>rndc signing -nsec3param</command> sets
+ the NSEC3 parameters for a zone. This is the
+ only supported mechanism for using NSEC3 with
+ <command>inline-signing</command> zones.
+ Parameters are specified in the same format as
+ an NSEC3PARAM resource record: hash algorithm,
+ flags, iterations, salt. For example, to set an
+ NSEC3 chain using the SHA-1 hash algorithm,
+ no opt-out flag, 10 iterations, and a salt value
+ of "FFFF", use:
+ <command>rndc signing -nsec3param 1 0 10 FFFF</command>.
+ <command>rndc signing -nsec3param none</command>
+ removes an existing NSEC3 chain and replaces it
+ with NSEC.
</para>
</listitem>
</varlistentry>
These records can be removed from the zone once named
has completed signing the zone with the matching key
using <command>nsupdate</command> or
- <command>rndc keydone</command>.
- <command>rndc keydone</command> is the only supported
+ <command>rndc signing -clear</command>.
+ <command>rndc signing -clear</command> is the only supported
way to remove these records from
<command>inline-signing</command> zones.
</para>
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: events.h,v 1.60 2011/10/25 01:54:22 marka Exp $ */
+/* $Id: events.h,v 1.61 2011/10/28 06:20:06 each Exp $ */
#ifndef DNS_EVENTS_H
#define DNS_EVENTS_H 1
#define DNS_EVENT_ZONESECUREDB (ISC_EVENTCLASS_DNS + 48)
#define DNS_EVENT_ZONELOAD (ISC_EVENTCLASS_DNS + 49)
#define DNS_EVENT_KEYDONE (ISC_EVENTCLASS_DNS + 50)
+#define DNS_EVENT_SETNSEC3PARAM (ISC_EVENTCLASS_DNS + 51)
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsec3.h,v 1.12 2010/05/18 02:38:10 tbox Exp $ */
+/* $Id: nsec3.h,v 1.13 2011/10/28 06:20:06 each Exp $ */
#ifndef DNS_NSEC3_H
#define DNS_NSEC3_H 1
isc_result_t
dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
- dns_zone_t *zone, dns_diff_t *diff);
+ dns_zone_t *zone, isc_boolean_t nonsec,
+ dns_diff_t *diff);
/*%<
* Mark NSEC3PARAM for deletion.
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: private.h,v 1.3 2009/10/09 23:48:09 tbox Exp $ */
+/* $Id: private.h,v 1.4 2011/10/28 06:20:06 each Exp $ */
#include <isc/lang.h>
#include <isc/types.h>
* \li other on error
*/
+isc_result_t
+dns_private_totext(dns_rdata_t *private, isc_buffer_t *buffer);
+/*%<
+ * Convert a private-type RR 'private' to human-readable form,
+ * and place the result in 'buffer'. The text should indicate
+ * which action the private-type record specifies and whether the
+ * action has been completed.
+ *
+ * Requires:
+ * \li 'private' is a valid rdata containing at least five bytes
+ * \li 'buffer' is a valid buffer
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li other on error
+ */
+
ISC_LANG_ENDDECLS
#endif
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.h,v 1.195 2011/10/25 01:54:22 marka Exp $ */
+/* $Id: zone.h,v 1.196 2011/10/28 06:20:06 each Exp $ */
#ifndef DNS_ZONE_H
#define DNS_ZONE_H 1
isc_result_t
dns_zone_keydone(dns_zone_t *zone, const char *data);
+isc_result_t
+dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
+ isc_uint8_t iter, isc_uint8_t saltlen,
+ unsigned char *salt, isc_boolean_t replace);
+/*%
+ * Set the NSEC3 parameters for the zone.
+ *
+ * If 'replace' is ISC_TRUE, then the existing NSEC3 chain, if any, will
+ * be replaced with the new one. If 'hash' is zero, then the replacement
+ * chain will be NSEC rather than NSEC3.
+ *
+ * Requires:
+ * \li 'zone' to be valid.
+ */
ISC_LANG_ENDDECLS
#endif /* DNS_ZONE_H */
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsec3.c,v 1.23 2011/06/10 01:51:09 each Exp $ */
+/* $Id: nsec3.c,v 1.24 2011/10/28 06:20:06 each Exp $ */
#include <config.h>
#ifdef BIND9
isc_result_t
dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
- dns_zone_t *zone, dns_diff_t *diff)
+ dns_zone_t *zone, isc_boolean_t nonsec,
+ dns_diff_t *diff)
{
dns_dbnode_t *node = NULL;
dns_difftuple_t *tuple = NULL;
dns_nsec3param_toprivate(&rdata, &private, privatetype,
buf, sizeof(buf));
- buf[2] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC;
+ buf[2] = DNS_NSEC3FLAG_REMOVE;
+ if (nonsec)
+ buf[2] |= DNS_NSEC3FLAG_NONSEC;
CHECK(rr_exists(db, ver, origin, &private, &flag));
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_reset(&rdata);
dns_rdataset_current(&rdataset, &rdata);
INSIST(rdata.length <= sizeof(buf));
memcpy(buf, rdata.data, rdata.length);
- if (buf[0] != 0 ||
- buf[2] == (DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC)) {
- dns_rdata_reset(&rdata);
+ if (buf[0] != 0 || (buf[2] & DNS_NSEC3FLAG_REMOVE) != 0 ||
+ (nonsec && (buf[2] & DNS_NSEC3FLAG_NONSEC) != 0))
continue;
- }
CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin,
0, &rdata, &tuple));
INSIST(tuple == NULL);
rdata.data = buf;
- buf[2] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC;
+ buf[2] = DNS_NSEC3FLAG_REMOVE;
+ if (nonsec)
+ buf[2] |= DNS_NSEC3FLAG_NONSEC;
CHECK(rr_exists(db, ver, origin, &rdata, &flag));
CHECK(do_one_tuple(&tuple, db, ver, diff));
INSIST(tuple == NULL);
}
- dns_rdata_reset(&rdata);
}
if (result != ISC_R_NOMORE)
goto failure;
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: private.c,v 1.6 2011/06/10 01:51:09 each Exp $ */
+/* $Id: private.c,v 1.7 2011/10/28 06:20:06 each Exp $ */
#include "config.h"
dns_db_detachnode(db, &node);
return (result);
}
+
+isc_result_t
+dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) {
+ isc_result_t result;
+
+ if (private->data[0] == 0) {
+ unsigned char nsec3buf[DNS_NSEC3PARAM_BUFFERSIZE];
+ unsigned char newbuf[DNS_NSEC3PARAM_BUFFERSIZE];
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec3param_t nsec3param;
+ isc_boolean_t remove, init, nonsec;
+ isc_buffer_t b;
+
+ if (!dns_nsec3param_fromprivate(private, &rdata, nsec3buf,
+ sizeof(nsec3buf)))
+ CHECK(ISC_R_FAILURE);
+
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
+
+ remove = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0);
+ init = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0);
+ nonsec = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_NONSEC) != 0);
+
+ nsec3param.flags &= ~(DNS_NSEC3FLAG_CREATE|
+ DNS_NSEC3FLAG_REMOVE|
+ DNS_NSEC3FLAG_INITIAL|
+ DNS_NSEC3FLAG_NONSEC);
+
+ if (init)
+ isc_buffer_putstr(buf, "Pending NSEC3 chain ");
+ else if (remove)
+ isc_buffer_putstr(buf, "Removing NSEC3 chain ");
+ else
+ isc_buffer_putstr(buf, "Creating NSEC3 chain ");
+
+ dns_rdata_reset(&rdata);
+ isc_buffer_init(&b, newbuf, sizeof(newbuf));
+ CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_in,
+ dns_rdatatype_nsec3param,
+ &nsec3param, &b));
+
+ CHECK(dns_rdata_totext(&rdata, NULL, buf));
+
+ if (remove && !nonsec)
+ isc_buffer_putstr(buf, " / creating NSEC chain");
+ } else {
+ unsigned char alg = private->data[0];
+ dns_keytag_t keyid = (private->data[2] | private->data[1] << 8);
+ char keybuf[BUFSIZ], algbuf[DNS_SECALG_FORMATSIZE];
+ isc_boolean_t remove = ISC_TF(private->data[3] != 0);
+ isc_boolean_t complete = ISC_TF(private->data[4] != 0);
+
+ if (remove && complete)
+ isc_buffer_putstr(buf, "Done removing signatures for ");
+ else if (remove)
+ isc_buffer_putstr(buf, "Removing signatures for ");
+ else if (complete)
+ isc_buffer_putstr(buf, "Done signing with ");
+ else
+ isc_buffer_putstr(buf, "Signing with ");
+
+ dns_secalg_format(alg, algbuf, sizeof(algbuf));
+ sprintf(keybuf, "key %d/%s", keyid, algbuf);
+ isc_buffer_putstr(buf, keybuf);
+ }
+
+ isc_buffer_putuint8(buf, 0);
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.9 2011/10/12 23:09:35 marka Exp $
+# $Id: Makefile.in,v 1.10 2011/10/28 06:20:07 each Exp $
srcdir = @srcdir@
VPATH = @srcdir@
OBJS = dnstest.@O@
SRCS = dnstest.c master_test.c dbiterator_test.c time_test.c \
- update_test.c zonemgr_test.c zt_test.c
+ private_test.c update_test.c zonemgr_test.c zt_test.c
SUBDIRS =
TARGETS = master_test@EXEEXT@ dbiterator_test@EXEEXT@ time_test@EXEEXT@ \
- update_test@EXEEXT@ zonemgr_test@EXEEXT@ zt_test@EXEEXT@ \
- dbversion_test@EXEEXT@
+ private_test@EXEEXT@ update_test@EXEEXT@ zonemgr_test@EXEEXT@ \
+ zt_test@EXEEXT@ dbversion_test@EXEEXT@
@BIND9_MAKE_RULES@
time_test.@O@ dnstest.@O@ ${DNSLIBS} \
${ISCLIBS} ${LIBS}
+private_test@EXEEXT@: private_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ private_test.@O@ dnstest.@O@ ${DNSLIBS} \
+ ${ISCLIBS} ${LIBS}
+
update_test@EXEEXT@: update_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
update_test.@O@ dnstest.@O@ ${DNSLIBS} \
--- /dev/null
+/*
+ * 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: private_test.c,v 1.2 2011/10/28 06:20:07 each Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <atf-c.h>
+
+#include <unistd.h>
+
+#include <isc/buffer.h>
+
+#include <dns/nsec3.h>
+#include <dns/private.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+
+#include <dst/dst.h>
+
+#include "dnstest.h"
+
+static dns_rdatatype_t privatetype = 65534;
+
+typedef struct {
+ unsigned char alg;
+ dns_keytag_t keyid;
+ isc_boolean_t remove;
+ isc_boolean_t complete;
+} signing_testcase_t;
+
+typedef struct {
+ unsigned char hash;
+ unsigned char flags;
+ unsigned int iterations;
+ unsigned long salt;
+ isc_boolean_t remove;
+ isc_boolean_t pending;
+ isc_boolean_t nonsec;
+} nsec3_testcase_t;
+
+/*
+ * Helper functions
+ */
+static void
+make_signing(signing_testcase_t *testcase, dns_rdata_t *private,
+ unsigned char *buf)
+{
+ dns_rdata_init(private);
+
+ buf[0] = testcase->alg;
+ buf[1] = (testcase->keyid & 0xff00) >> 8;
+ buf[2] = (testcase->keyid & 0xff);
+ buf[3] = testcase->remove;
+ buf[4] = testcase->complete;
+ private->data = buf;
+ private->length = sizeof(buf);
+ private->type = privatetype;
+ private->rdclass = dns_rdataclass_in;
+}
+
+static void
+make_nsec3(nsec3_testcase_t *testcase, dns_rdata_t *private,
+ unsigned char *pbuf)
+{
+ dns_rdata_nsec3param_t params;
+ dns_rdata_t nsec3param = DNS_RDATA_INIT;
+ unsigned char bufdata[BUFSIZ];
+ isc_buffer_t buf;
+ isc_uint32_t salt;
+ unsigned char *sp;
+ int slen = 4;
+
+ /* for simplicity, we're using a maximum salt length of 4 */
+ salt = htonl(testcase->salt);
+ sp = (unsigned char *) &salt;
+ while (*sp == '\0' && slen > 0) {
+ slen--;
+ sp++;
+ }
+
+ params.common.rdclass = dns_rdataclass_in;
+ params.common.rdtype = dns_rdatatype_nsec3param;
+ params.hash = testcase->hash;
+ params.iterations = testcase->iterations;
+ params.salt = sp;
+ params.salt_length = slen;
+
+ params.flags = testcase->flags;
+ if (testcase->remove) {
+ params.flags |= DNS_NSEC3FLAG_REMOVE;
+ if (testcase->nonsec)
+ params.flags |= DNS_NSEC3FLAG_NONSEC;
+ } else {
+ params.flags |= DNS_NSEC3FLAG_CREATE;
+ if (testcase->pending)
+ params.flags |= DNS_NSEC3FLAG_INITIAL;
+ }
+
+ isc_buffer_init(&buf, bufdata, sizeof(bufdata));
+ dns_rdata_fromstruct(&nsec3param, dns_rdataclass_in,
+ dns_rdatatype_nsec3param, ¶ms, &buf);
+
+ dns_rdata_init(private);
+
+ dns_nsec3param_toprivate(&nsec3param, private, privatetype,
+ pbuf, DNS_NSEC3PARAM_BUFFERSIZE + 1);
+}
+
+/*
+ * Individual unit tests
+ */
+ATF_TC(private_signing_totext);
+ATF_TC_HEAD(private_signing_totext, tc) {
+ atf_tc_set_md_var(tc, "descr",
+ "convert private signing records to text");
+}
+ATF_TC_BODY(private_signing_totext, tc) {
+ isc_result_t result;
+ dns_rdata_t private;
+ int i;
+
+ signing_testcase_t testcases[] = {
+ { DST_ALG_RSASHA512, 12345, 0, 0 },
+ { DST_ALG_RSASHA256, 54321, 1, 0 },
+ { DST_ALG_NSEC3RSASHA1, 22222, 0, 1 },
+ { DST_ALG_RSASHA1, 33333, 1, 1 }
+ };
+ const char *results[] = {
+ "Signing with key 12345/RSASHA512",
+ "Removing signatures for key 54321/RSASHA256",
+ "Done signing with key 22222/NSEC3RSASHA1",
+ "Done removing signatures for key 33333/RSASHA1"
+ };
+ int ncases = 4;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, ISC_TRUE);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ for (i = 0; i < ncases; i++) {
+ unsigned char data[5];
+ char output[BUFSIZ];
+ isc_buffer_t buf;
+
+ isc_buffer_init(&buf, output, sizeof(output));
+
+ make_signing(&testcases[i], &private, data);
+ dns_private_totext(&private, &buf);
+ ATF_CHECK_STREQ(output, results[i]);
+ }
+
+ dns_test_end();
+}
+
+ATF_TC(private_nsec3_totext);
+ATF_TC_HEAD(private_nsec3_totext, tc) {
+ atf_tc_set_md_var(tc, "descr", "convert private chain records to text");
+}
+ATF_TC_BODY(private_nsec3_totext, tc) {
+ isc_result_t result;
+ dns_rdata_t private;
+ int i;
+
+ nsec3_testcase_t testcases[] = {
+ { 1, 0, 1, 0xbeef, 0, 0, 0 },
+ { 1, 1, 10, 0xdadd, 0, 0, 0 },
+ { 1, 0, 20, 0xbead, 0, 1, 0 },
+ { 1, 0, 30, 0xdeaf, 1, 0, 0 },
+ { 1, 0, 100, 0xfeedabee, 1, 0, 1 },
+ };
+ const char *results[] = {
+ "Creating NSEC3 chain 1 0 1 BEEF",
+ "Creating NSEC3 chain 1 1 10 DADD",
+ "Pending NSEC3 chain 1 0 20 BEAD",
+ "Removing NSEC3 chain 1 0 30 DEAF / creating NSEC chain",
+ "Removing NSEC3 chain 1 0 100 FEEDABEE"
+ };
+ int ncases = 5;
+
+ UNUSED(tc);
+
+ result = dns_test_begin(NULL, ISC_TRUE);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ for (i = 0; i < ncases; i++) {
+ unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
+ char output[BUFSIZ];
+ isc_buffer_t buf;
+
+ isc_buffer_init(&buf, output, sizeof(output));
+
+ make_nsec3(&testcases[i], &private, data);
+ dns_private_totext(&private, &buf);
+ ATF_CHECK_STREQ(output, results[i]);
+ }
+
+ dns_test_end();
+}
+
+/*
+ * Main
+ */
+ATF_TP_ADD_TCS(tp) {
+ ATF_TP_ADD_TC(tp, private_signing_totext);
+ ATF_TP_ADD_TC(tp, private_nsec3_totext);
+ return (atf_no_error());
+}
+
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.c,v 1.641 2011/10/28 00:36:54 marka Exp $ */
+/* $Id: zone.c,v 1.642 2011/10/28 06:20:06 each Exp $ */
/*! \file */
if (result != ISC_R_NOTFOUND)
goto failure;
- result = dns_nsec3param_deletechains(db, ver, zone, diff);
+ result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff);
failure:
if (node != NULL)
struct keydone {
isc_event_t event;
- unsigned int data[5];
+ isc_boolean_t all;
+ unsigned char data[5];
};
+#define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
+
static void
keydone(isc_task_t *task, isc_event_t *event) {
const char *me = "keydone";
dns_diff_t diff;
struct keydone *keydone = (struct keydone *)event;
dns_update_log_t log = { update_log_cb, NULL };
+ isc_boolean_t clear_pending = ISC_FALSE;
UNUSED(task);
INSIST(!dns_rdataset_isassociated(&rdataset));
goto failure;
}
+
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset)) {
+ isc_boolean_t found = ISC_FALSE;
+
dns_rdataset_current(&rdataset, &rdata);
- if (rdata.length != 5 ||
- memcmp(rdata.data, keydone->data, 5) != 0) {
- dns_rdata_reset(&rdata);
- continue;
- }
- CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
- &zone->origin, rdataset.ttl, &rdata));
+
+ if (keydone->all) {
+ if (rdata.length == 5 && rdata.data[0] != 0 &&
+ rdata.data[3] == 0 && rdata.data[4] == 1)
+ found = ISC_TRUE;
+ else if (rdata.data[0] == 0 &&
+ (rdata.data[2] & PENDINGFLAGS) != 0) {
+ found = ISC_TRUE;
+ clear_pending = ISC_TRUE;
+ }
+ } else if (rdata.length == 5 &&
+ memcmp(rdata.data, keydone->data, 5) == 0)
+ found = ISC_TRUE;
+
+ if (found)
+ CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
+ &zone->origin, rdataset.ttl,
+ &rdata));
dns_rdata_reset(&rdata);
}
/* Write changes to journal file. */
CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
zone->updatemethod));
- CHECK(dns_update_signatures(&log, zone, db, oldver, newver,
- &diff, zone->sigvalidityinterval));
+
+ result = dns_update_signatures(&log, zone, db,
+ oldver, newver, &diff,
+ zone->sigvalidityinterval);
+ if (!clear_pending)
+ CHECK(result);
+
CHECK(zone_journal(zone, &diff, NULL, "keydone"));
commit = ISC_TRUE;
}
isc_result_t
-dns_zone_keydone(dns_zone_t *zone, const char *data) {
- isc_result_t result;
+dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
+ isc_result_t result = ISC_R_SUCCESS;
isc_event_t *e;
isc_buffer_t b;
dns_zone_t *dummy = NULL;
+ struct keydone *kd;
REQUIRE(DNS_ZONE_VALID(zone));
goto failure;
}
- isc_buffer_init(&b, ((struct keydone*)e)->data,
- sizeof(((struct keydone*)e)->data));
- result = isc_hex_decodestring(data, &b);
- if (result != ISC_R_SUCCESS)
+ kd = (struct keydone *) e;
+ if (strcasecmp(keystr, "all") == 0)
+ kd->all = ISC_TRUE;
+ else {
+ isc_textregion_t r;
+ char *algstr;
+ dns_keytag_t keyid;
+ dns_secalg_t alg;
+ size_t n;
+
+ kd->all = ISC_FALSE;
+
+ n = sscanf(keystr, "%hd/", &keyid);
+ if (n == 0)
+ CHECK(ISC_R_FAILURE);
+
+ algstr = strchr(keystr, '/');
+ if (algstr != NULL)
+ algstr++;
+ else
+ CHECK(ISC_R_FAILURE);
+
+ DE_CONST(algstr, r.base);
+ r.length = strlen(algstr);
+ result = dns_secalg_fromtext(&alg, (isc_textregion_t *) &r);
+
+ if (result != ISC_R_SUCCESS) {
+ n = sscanf(algstr, "%hhd", &alg);
+ if (n == 0)
+ CHECK(result);
+ }
+
+ /* construct a private-type rdata */
+ isc_buffer_init(&b, kd->data, sizeof(kd->data));
+ isc_buffer_putuint8(&b, alg);
+ isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
+ isc_buffer_putuint8(&b, (keyid & 0xff));
+ isc_buffer_putuint8(&b, 0);
+ isc_buffer_putuint8(&b, 1);
+ }
+
+ zone_iattach(zone, &dummy);
+ isc_task_send(zone->task, &e);
+
+ failure:
+ if (e != NULL)
+ isc_event_free(&e);
+ UNLOCK_ZONE(zone);
+ return (result);
+}
+
+struct nsec3param {
+ isc_event_t event;
+ unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
+ unsigned int length;
+ isc_boolean_t nsec;
+ isc_boolean_t replace;
+};
+
+static void
+setnsec3param(isc_task_t *task, isc_event_t *event) {
+ const char *me = "setnsec3param";
+ isc_boolean_t commit = ISC_FALSE;
+ isc_result_t result;
+ dns_dbversion_t *oldver = NULL, *newver = NULL;
+ dns_zone_t *zone;
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t prdataset, nrdataset;
+ dns_diff_t diff;
+ struct nsec3param *np = (struct nsec3param *)event;
+ dns_update_log_t log = { update_log_cb, NULL };
+ dns_rdata_t rdata;
+ isc_boolean_t nseconly;
+ isc_boolean_t exists = ISC_FALSE;
+
+ UNUSED(task);
+
+ zone = event->ev_arg;
+ INSIST(DNS_ZONE_VALID(zone));
+
+ ENTER;
+
+ dns_rdataset_init(&prdataset);
+ dns_rdataset_init(&nrdataset);
+ dns_diff_init(zone->mctx, &diff);
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL) {
+ dns_db_attach(zone->db, &db);
+ dns_db_currentversion(db, &oldver);
+ result = dns_db_newversion(db, &newver);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "setnsec3param:dns_db_newversion -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ if (db == NULL)
+ goto failure;
+
+ CHECK(dns_db_getoriginnode(db, &node));
+
+ /*
+ * Does a private-type record already exist for this chain?
+ */
+ result = dns_db_findrdataset(db, node, newver, zone->privatetype,
+ dns_rdatatype_none, 0, &prdataset, NULL);
+ if (result == ISC_R_SUCCESS) {
+ for (result = dns_rdataset_first(&prdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&prdataset)) {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(&prdataset, &rdata);
+
+ if (np->length == rdata.length &&
+ memcmp(rdata.data, np->data, np->length) == 0) {
+ exists = ISC_TRUE;
+ break;
+ }
+ }
+ } else if (result != ISC_R_NOTFOUND) {
+ INSIST(!dns_rdataset_isassociated(&prdataset));
+ goto failure;
+ }
+
+ /*
+ * Does the chain already exist?
+ */
+ result = dns_db_findrdataset(db, node, newver,
+ dns_rdatatype_nsec3param,
+ dns_rdatatype_none, 0, &nrdataset, NULL);
+ if (result == ISC_R_SUCCESS) {
+ for (result = dns_rdataset_first(&nrdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&nrdataset)) {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(&nrdataset, &rdata);
+
+ if (np->length == (rdata.length + 1) &&
+ memcmp(rdata.data, np->data + 1,
+ np->length - 1) == 0)
+ {
+ exists = ISC_TRUE;
+ break;
+ }
+ }
+ } else if (result != ISC_R_NOTFOUND) {
+ INSIST(!dns_rdataset_isassociated(&nrdataset));
goto failure;
+ }
+
+
+ /*
+ * We need to remove any existing NSEC3 chains.
+ */
+ if (!exists && np->replace && (np->length != 0 || np->nsec))
+ CHECK(dns_nsec3param_deletechains(db, newver, zone,
+ !np->nsec, &diff));
+
+ if (!exists && np->length != 0) {
+ /*
+ * We're creating an NSEC3 chain.
+ *
+ * If the zone is not currently capable of supporting
+ * an NSEC3 chain, add the INITIAL flag, so these
+ * parameters can be used later when NSEC3 becomes
+ * available.
+ */
+ dns_rdata_init(&rdata);
+
+ np->data[2] |= DNS_NSEC3FLAG_CREATE;
+ result = dns_nsec_nseconly(db, newver, &nseconly);
+ if (result == ISC_R_NOTFOUND || nseconly)
+ np->data[2] |= DNS_NSEC3FLAG_INITIAL;
+
+ rdata.length = np->length;
+ rdata.data = np->data;
+ rdata.type = zone->privatetype;
+ rdata.rdclass = zone->rdclass;
+ CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
+ &zone->origin, 0, &rdata));
+ }
+
+ if (!ISC_LIST_EMPTY(diff.tuples)) {
+ /* Write changes to journal file. */
+ CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
+ zone->updatemethod));
+ result = dns_update_signatures(&log, zone, db,
+ oldver, newver, &diff,
+ zone->sigvalidityinterval);
+ if (result != ISC_R_NOTFOUND)
+ CHECK(result);
+ CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
+ commit = ISC_TRUE;
+
+ LOCK_ZONE(zone);
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
+ zone_needdump(zone, 30);
+ UNLOCK_ZONE(zone);
+ }
+
+ failure:
+ if (dns_rdataset_isassociated(&prdataset))
+ dns_rdataset_disassociate(&prdataset);
+ if (dns_rdataset_isassociated(&nrdataset))
+ dns_rdataset_disassociate(&nrdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (oldver != NULL)
+ dns_db_closeversion(db, &oldver, ISC_FALSE);
+ if (newver != NULL)
+ dns_db_closeversion(db, &newver, commit);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (commit)
+ resume_addnsec3chain(zone);
+ dns_diff_clear(&diff);
+ isc_event_free(&event);
+ dns_zone_idetach(&zone);
+}
+
+isc_result_t
+dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
+ isc_uint8_t iter, isc_uint8_t saltlen,
+ unsigned char *salt, isc_boolean_t replace)
+{
+ isc_result_t result;
+ dns_rdata_nsec3param_t param;
+ dns_rdata_t nrdata = DNS_RDATA_INIT;
+ dns_rdata_t prdata = DNS_RDATA_INIT;
+ unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
+ struct nsec3param *np;
+ dns_zone_t *dummy = NULL;
+ isc_buffer_t b;
+ isc_event_t *e;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(salt != NULL);
+
+ LOCK_ZONE(zone);
+
+ e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
+ setnsec3param, zone, sizeof(struct nsec3param));
+ if (e == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+
+ np = (struct nsec3param *) e;
+ np->replace = replace;
+ if (hash == 0) {
+ np->length = 0;
+ np->nsec = ISC_TRUE;
+ } else {
+ param.common.rdclass = zone->rdclass;
+ param.common.rdtype = dns_rdatatype_nsec3param;
+ ISC_LINK_INIT(¶m.common, link);
+ param.mctx = NULL;
+ param.hash = hash;
+ param.flags = flags;
+ param.iterations = iter;
+ param.salt_length = saltlen;
+ param.salt = salt;
+ isc_buffer_init(&b, nbuf, sizeof(nbuf));
+ CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
+ dns_rdatatype_nsec3param,
+ ¶m, &b));
+ dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
+ np->data, sizeof(np->data));
+ np->length = prdata.length;
+ }
zone_iattach(zone, &dummy);
isc_task_send(zone->task, &e);