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]
This commit is contained in:
Evan Hunt 2011-10-28 06:20:07 +00:00
parent aeef1449b4
commit 9c03f13e18
23 changed files with 987 additions and 165 deletions

View file

@ -1,3 +1,12 @@
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]

View file

@ -15,7 +15,7 @@
* 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 */
@ -205,8 +205,8 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
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,

View file

@ -15,7 +15,7 @@
* 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
@ -64,7 +64,7 @@
#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);

View file

@ -15,7 +15,7 @@
* 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
@ -343,9 +343,8 @@ isc_result_t
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 */

View file

@ -15,7 +15,7 @@
* 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 */
@ -34,6 +34,7 @@
#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>
@ -73,6 +74,7 @@
#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>
@ -7858,46 +7860,142 @@ newzone_cfgctx_destroy(void **cfgp) {
*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);
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;
}
result = dns_zone_keydone(zone, ptr);
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);
}

View file

@ -15,7 +15,7 @@
* 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>
@ -3068,7 +3068,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
* 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;

View file

@ -15,7 +15,7 @@
* 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 */
@ -154,9 +154,15 @@ command is one of the following:\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\
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",

View file

@ -14,7 +14,7 @@
# 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
@ -126,7 +126,7 @@ zone nsec3.example.
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
@ -140,6 +140,7 @@ send
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.
@ -155,6 +156,27 @@ n=`expr $n + 1`
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`
@ -275,6 +297,22 @@ n=`expr $n + 1`
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

View file

@ -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.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
@ -59,3 +59,4 @@ 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
rm -f signing.out*

View file

@ -15,7 +15,7 @@
* 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
@ -35,6 +35,15 @@ options {
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";

View file

@ -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.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
@ -1330,6 +1330,33 @@ n=`expr $n + 1`
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

View file

@ -12,7 +12,7 @@
# 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
@ -43,3 +43,4 @@ rm -f ns5/bits.bk.signed
rm -f ns5/bits.bk.signed.jnl
rm -f random.data
rm -f dig.out.ns*.test*
rm -f signing.out*

View file

@ -14,7 +14,7 @@
# 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
@ -31,11 +31,9 @@ ret=0
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
@ -43,22 +41,21 @@ if [ $ret != 0 ]; then echo "I:failed"; fi
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
@ -77,21 +74,15 @@ if [ $ret != 0 ]; then echo "I:failed"; fi
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
@ -180,11 +171,9 @@ ret=0
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
@ -260,33 +249,30 @@ ret=0
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
@ -305,21 +291,14 @@ if [ $ret != 0 ]; then echo "I:failed"; fi
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
@ -366,11 +345,9 @@ ret=0
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

View file

@ -18,7 +18,7 @@
- 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>
@ -1556,23 +1556,50 @@ zone "eng.example.com" {
</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>
@ -8730,8 +8757,8 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
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>

View file

@ -15,7 +15,7 @@
* 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
@ -78,6 +78,7 @@
#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)

View file

@ -14,7 +14,7 @@
* 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
@ -241,7 +241,8 @@ dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target,
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.

View file

@ -14,7 +14,7 @@
* 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>
@ -50,6 +50,23 @@ dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
* \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

View file

@ -15,7 +15,7 @@
* 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
@ -1981,6 +1981,20 @@ dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw);
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 */

View file

@ -14,7 +14,7 @@
* 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>
@ -1054,7 +1054,8 @@ rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
#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;
@ -1098,7 +1099,9 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
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));
@ -1129,15 +1132,14 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
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));
@ -1145,7 +1147,9 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
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));
@ -1155,7 +1159,6 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
CHECK(do_one_tuple(&tuple, db, ver, diff));
INSIST(tuple == NULL);
}
dns_rdata_reset(&rdata);
}
if (result != ISC_R_NOMORE)
goto failure;

View file

@ -14,7 +14,7 @@
* 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"
@ -294,3 +294,74 @@ dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
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);
}

View file

@ -12,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.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@
@ -38,12 +38,12 @@ LIBS = @LIBS@ @ATFLIBS@
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@
@ -57,6 +57,11 @@ time_test@EXEEXT@: time_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
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} \

View file

@ -0,0 +1,225 @@
/*
* 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, &params, &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());
}

View file

@ -15,7 +15,7 @@
* 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 */
@ -14808,7 +14808,7 @@ clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
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)
@ -15340,9 +15340,12 @@ dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
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";
@ -15357,6 +15360,7 @@ keydone(isc_task_t *task, isc_event_t *event) {
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);
@ -15398,17 +15402,31 @@ keydone(isc_task_t *task, isc_event_t *event) {
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);
}
@ -15416,8 +15434,13 @@ keydone(isc_task_t *task, isc_event_t *event) {
/* 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;
@ -15445,11 +15468,12 @@ keydone(isc_task_t *task, isc_event_t *event) {
}
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));
@ -15462,11 +15486,280 @@ dns_zone_keydone(dns_zone_t *zone, const char *data) {
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)
goto failure;
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(&param.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,
&param, &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);