summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorInternet Software Consortium, Inc <@isc.org>2012-01-18 10:10:04 -0700
committerInternet Software Consortium, Inc <@isc.org>2012-01-18 10:10:04 -0700
commit52a7f63e4e1a5cc6705c88c2090499b2caaa0805 (patch)
tree330f8ca530b9d9e0161703f3d85575c1e43dd8d8 /lib
parentcf94dd77f7578bef7bc0ff3feac9aaa548180641 (diff)
downloadbind9-52a7f63e4e1a5cc6705c88c2090499b2caaa0805.tar.gz
9.9.0b1
Diffstat (limited to 'lib')
-rw-r--r--lib/bind9/check.c21
-rw-r--r--lib/dns/adb.c217
-rw-r--r--lib/dns/dst_api.c22
-rw-r--r--lib/dns/dst_internal.h4
-rw-r--r--lib/dns/include/dns/adb.h62
-rw-r--r--lib/dns/include/dns/events.h4
-rw-r--r--lib/dns/include/dns/nsec3.h7
-rw-r--r--lib/dns/include/dns/private.h21
-rw-r--r--lib/dns/include/dns/rpz.h3
-rw-r--r--lib/dns/include/dns/zone.h19
-rw-r--r--lib/dns/include/dst/dst.h11
-rw-r--r--lib/dns/key.c35
-rw-r--r--lib/dns/nsec3.c21
-rw-r--r--lib/dns/private.c73
-rw-r--r--lib/dns/resolver.c52
-rw-r--r--lib/dns/tests/Makefile.in13
-rw-r--r--lib/dns/tests/private_test.c225
-rw-r--r--lib/dns/validator.c57
-rw-r--r--lib/dns/win32/libdns.def5
-rw-r--r--lib/dns/zone.c468
-rw-r--r--lib/isc/hmacsha.c19
-rw-r--r--lib/isc/sha2.c16
-rw-r--r--lib/isc/tests/task_test.c5
23 files changed, 1277 insertions, 103 deletions
diff --git a/lib/bind9/check.c b/lib/bind9/check.c
index 1df7989f..17ef96ee 100644
--- a/lib/bind9/check.c
+++ b/lib/bind9/check.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: check.c,v 1.134 2011-08-30 05:16:14 marka Exp $ */
+/* $Id: check.c,v 1.137 2011-10-29 00:15:56 each Exp $ */
/*! \file */
@@ -1479,10 +1479,10 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
/*
* Master zones can't have both "allow-update" and "update-policy".
*/
- if (ztype == MASTERZONE) {
+ if (ztype == MASTERZONE || ztype == SLAVEZONE) {
isc_result_t res1, res2, res3;
const char *arg;
- isc_boolean_t ddns;
+ isc_boolean_t ddns = ISC_FALSE, signing = ISC_FALSE;
obj = NULL;
res1 = cfg_map_get(zoptions, "allow-update", &obj);
@@ -1500,15 +1500,22 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
ddns = ISC_TF(res1 == ISC_R_SUCCESS || res2 == ISC_R_SUCCESS);
obj = NULL;
+ res1 = cfg_map_get(zoptions, "inline-signing", &obj);
+ if (res1 == ISC_R_SUCCESS)
+ signing = cfg_obj_asboolean(obj);
+
+ obj = NULL;
arg = "off";
res3 = cfg_map_get(zoptions, "auto-dnssec", &obj);
if (res3 == ISC_R_SUCCESS)
arg = cfg_obj_asstring(obj);
- if (strcasecmp(arg, "off") != 0 && !ddns) {
+ if (strcasecmp(arg, "off") != 0 && !ddns && !signing) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
- "'auto-dnssec %s;' requires "
- "dynamic DNS to be configured in the zone",
- arg);
+ "'auto-dnssec %s;' requires%s "
+ "inline-signing to be configured for "
+ "the zone", arg,
+ (ztype == MASTERZONE) ?
+ " dynamic DNS or" : "");
result = ISC_R_FAILURE;
}
if (strcasecmp(arg, "create") == 0) {
diff --git a/lib/dns/adb.c b/lib/dns/adb.c
index ebc43604..b6109ec7 100644
--- a/lib/dns/adb.c
+++ b/lib/dns/adb.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: adb.c,v 1.258 2011-03-13 02:49:28 marka Exp $ */
+/* $Id: adb.c,v 1.262 2011-10-28 04:57:34 marka Exp $ */
/*! \file
*
@@ -34,6 +34,7 @@
#include <isc/netaddr.h>
#include <isc/random.h>
#include <isc/stats.h>
+#include <isc/stdio.h> /* temporary */
#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/task.h>
#include <isc/util.h>
@@ -65,6 +66,24 @@
#define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6')
#define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
+/***
+ *** Constants for EDNS0 packets
+ *** DNS_ADB_EDNS0_MAX_LEN - max udpsize for edns0, should come from
+ *** named.conf
+ *** DNS_ADB_EDNS0_MIN_LEN - min udpsize for edns0
+ *** DNS_ADB_EDNS_RESET_TIME - after this period of time, drop count
+ *** is set to 0 and EDNS may be tried at
+ *** bigger size - surface to user?
+ *** DNS_ADB_EDNS_MAX_DROP_COUNT - after this many times EDNS has been
+ *** reduced, edns->fetch_flag set
+ *** DNS_ADB_EDNS_MAX_DROP_TIME - after this time retry EDNS at larger size
+ ***/
+#define DNS_ADB_EDNS0_MAX_LEN 4096
+#define DNS_ADB_EDNS0_MIN_LEN 512
+#define DNS_ADB_EDNS_RESET_TIME 300 /*make this user configurable?*/
+#define DNS_ADB_EDNS_MAX_DROP_COUNT 5 /*make this user configurable?*/
+#define DNS_ADB_EDNS_MAX_DROP_TIME 3600 /*make this user configurable?*/
+
/*!
* For type 3 negative cache entries, we will remember that the address is
* broken for this long. XXXMLG This is also used for actual addresses, too.
@@ -252,8 +271,34 @@ struct dns_adbentry {
* name.
*/
+
+ unsigned int edns_big_size;
+ unsigned int edns_last_size;
+ unsigned int edns_fetch_flag;
+ unsigned int edns_drop_count;
+ isc_stdtime_t edns_drop_timestamp;
+ isc_stdtime_t edns_expires_timestamp;
+ isc_boolean_t edns_timer_set;
+ /*%<
+ * The above fields beginning with edns_* determine
+ * past success with edns for this server.
+ * edns_big_size - biggest successful size received (e.g., 512)
+ * edns_last_size - last packet size received
+ * edns_fetch_flag - current EDNS state for this server (one of
+ * DNS_FETCHOPT_NOEDNS0, DNS_FETCHOPT_EDNS512 or
+ * 0 meaning use DNS_ADB_EDNS0_MAX_LEN)
+ * edns_drop_count - keeps count of the number of times EDNS udpsize
+ * was dropped - reset to 0 every
+ * DNS_ADB_EDNS_RESET_TIME
+ * edns_drop_timestamp - The time at which the first EDNS drop
+ * in packet size was recorded
+ *
+ * See also dns_adb_drop/setednssize()
+ */
+
ISC_LIST(dns_adblameinfo_t) lameinfo;
ISC_LINK(dns_adbentry_t) plink;
+
};
/*
@@ -1746,6 +1791,13 @@ new_adbentry(dns_adb_t *adb) {
isc_random_get(&r);
e->srtt = (r & 0x1f) + 1;
e->expires = 0;
+ e->edns_big_size = 0;
+ e->edns_last_size = 0;
+ e->edns_fetch_flag = 0;
+ e->edns_drop_timestamp = 0;
+ e->edns_drop_count = 0;
+ e->edns_expires_timestamp = 0;
+ e->edns_timer_set = isc_boolean_false;
ISC_LIST_INIT(e->lameinfo);
ISC_LINK_INIT(e, plink);
LOCK(&adb->entriescntlock);
@@ -3909,6 +3961,169 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
UNLOCK(&adb->entrylocks[bucket]);
}
+unsigned int
+dns_adb_getednsflag(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now)
+{
+ int bucket = 0;
+ int flag_to_use = 0; /* assume max by default */
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ REQUIRE(DNS_ADBADDRINFO_VALID(addr));
+
+ /*
+ * The purpose of this function is to return
+ * edns_fetch_flag, which effectively sets the udpsize for EDNS
+ * or turns off EDNS (if NOEDNS0 has been recorded).
+ *
+ * Also, this function checks to see if the timer needs resetting.
+ * ---> this part should really be done via a callback?
+ */
+
+ bucket = addr->entry->lock_bucket;
+ LOCK(&adb->entrylocks[bucket]);
+
+ if((addr->entry->edns_timer_set) &&
+ (now >= addr->entry->edns_expires_timestamp)) {
+
+ /* Eventually, we may support more sizes */
+ if((addr->entry->edns_big_size <= 512) &&
+ (addr->entry->edns_big_size > 0))
+ flag_to_use = DNS_FETCHOPT_EDNS512;
+
+ addr->entry->edns_fetch_flag = flag_to_use;
+ addr->entry->edns_expires_timestamp = 0;
+ addr->entry->edns_timer_set = isc_boolean_false;
+
+ }
+
+ flag_to_use = addr->entry->edns_fetch_flag;
+
+ UNLOCK(&adb->entrylocks[bucket]);
+
+ return(flag_to_use);
+}
+
+void
+dns_adb_setednssize(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
+ unsigned int length)
+{
+ int bucket = 0;
+ unsigned int length_to_use;
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ REQUIRE(DNS_ADBADDRINFO_VALID(addr));
+
+ bucket = addr->entry->lock_bucket;
+ LOCK(&adb->entrylocks[bucket]);
+
+ /*
+ * The purpose of this function is to record
+ * the maximum sized udp response seen from the
+ * instant server.
+ */
+
+ length_to_use = addr->entry->edns_big_size;
+
+ if (length > DNS_ADB_EDNS0_MAX_LEN)
+ length = DNS_ADB_EDNS0_MAX_LEN;
+ if (length < DNS_ADB_EDNS0_MIN_LEN)
+ length = DNS_ADB_EDNS0_MIN_LEN;
+ if (length > length_to_use)
+ length_to_use = length;
+
+ addr->entry->edns_big_size = length_to_use;
+
+ UNLOCK(&adb->entrylocks[bucket]);
+}
+
+void
+dns_adb_dropednssize(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
+ unsigned int length, isc_stdtime_t now)
+{
+ isc_stdtime_t expires_ts_to_use;
+ isc_boolean_t timer_setting_to_use;
+ unsigned int length_to_use;
+ unsigned int drop_counter_to_use;
+ unsigned int drop_ts_to_use;
+ unsigned int flag_to_use;
+ int bucket = 0;
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ REQUIRE(DNS_ADBADDRINFO_VALID(addr));
+
+ if (length > DNS_ADB_EDNS0_MAX_LEN)
+ length = DNS_ADB_EDNS0_MAX_LEN;
+ if (length < DNS_ADB_EDNS0_MIN_LEN)
+ length = DNS_ADB_EDNS0_MIN_LEN;
+
+ bucket = addr->entry->lock_bucket;
+ LOCK(&adb->entrylocks[bucket]);
+
+ expires_ts_to_use = addr->entry->edns_expires_timestamp;
+ timer_setting_to_use = addr->entry->edns_timer_set;
+ length_to_use = addr->entry->edns_big_size;
+ drop_ts_to_use = addr->entry->edns_drop_timestamp;
+ flag_to_use = addr->entry->edns_fetch_flag;
+
+ /*
+ * This function keeps a count of the number of times
+ * within DNS_ADB_EDNS_RESET_TIME that a particular server
+ * has dropped the udpsize in order to communicate with the
+ * server. If the number of times this occurs exceeds
+ * DNS_ADB_EDNS_MAX_DROP_COUNT, then the udpsize is reduced
+ * by way of edns_fetch_flag for DNS_ADB_EDNS_MAX_DROP_TIME,
+ * after which the largest size is retried again.
+ * NOTE: currently, only 4096 and 512 are supported sizes
+ */
+
+ if (length > length_to_use)
+ length_to_use = length;
+
+ if ((now - addr->entry->edns_drop_timestamp) >=
+ DNS_ADB_EDNS_RESET_TIME) {
+
+ drop_counter_to_use = 1;
+ drop_ts_to_use = now;
+ } else {
+
+ drop_counter_to_use = addr->entry->edns_drop_count + 1;
+
+ if (drop_counter_to_use >= DNS_ADB_EDNS_MAX_DROP_COUNT) {
+ /*
+ * At this point, we are dropping down the
+ * udpsize because we've had too many misses
+ * at larger sizes.
+ */
+ if (timer_setting_to_use == isc_boolean_false) {
+ /*
+ * if we haven't already set a timer,
+ * do so now. After DNS_ADB_EDNS_MAX_DROP_TIME,
+ * we'll go back to the largest size
+ */
+ expires_ts_to_use =
+ now + DNS_ADB_EDNS_MAX_DROP_TIME;
+ timer_setting_to_use = isc_boolean_true;
+ }
+
+ if (length == 0)
+ flag_to_use = DNS_FETCHOPT_NOEDNS0;
+ else /* eventually, more edns sizes here */
+ flag_to_use = DNS_FETCHOPT_EDNS512;
+
+ drop_ts_to_use = 0;
+ drop_counter_to_use = 0;
+ }
+ }
+
+ addr->entry->edns_drop_timestamp = drop_ts_to_use;
+ addr->entry->edns_drop_count = drop_counter_to_use;
+ addr->entry->edns_fetch_flag = flag_to_use;
+ addr->entry->edns_expires_timestamp = expires_ts_to_use;
+ addr->entry->edns_timer_set = timer_setting_to_use;
+
+ UNLOCK(&adb->entrylocks[bucket]);
+}
+
void
dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
unsigned int bits, unsigned int mask)
diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c
index 5a490c05..787d4d48 100644
--- a/lib/dns/dst_api.c
+++ b/lib/dns/dst_api.c
@@ -31,7 +31,7 @@
/*
* Principal Author: Brian Wellington
- * $Id: dst_api.c,v 1.64 2011-09-05 18:00:22 each Exp $
+ * $Id: dst_api.c,v 1.65 2011-10-20 21:20:02 marka Exp $
*/
/*! \file */
@@ -448,7 +448,6 @@ dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
dst_key_free(&key);
return (DST_R_INVALIDPRIVATEKEY);
}
- key->key_id = id;
*keyp = key;
return (ISC_R_SUCCESS);
@@ -599,7 +598,7 @@ dst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass,
isc_uint8_t alg, proto;
isc_uint32_t flags, extflags;
dst_key_t *key = NULL;
- dns_keytag_t id;
+ dns_keytag_t id, rid;
isc_region_t r;
isc_result_t result;
@@ -614,6 +613,7 @@ dst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass,
alg = isc_buffer_getuint8(source);
id = dst_region_computeid(&r, alg);
+ rid = dst_region_computerid(&r, alg);
if (flags & DNS_KEYFLAG_EXTENDED) {
if (isc_buffer_remaininglength(source) < 2)
@@ -627,6 +627,7 @@ dst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass,
if (result != ISC_R_SUCCESS)
return (result);
key->key_id = id;
+ key->key_rid = rid;
*keyp = key;
return (ISC_R_SUCCESS);
@@ -928,13 +929,6 @@ comparekeys(const dst_key_t *key1, const dst_key_t *key2,
if (key1->key_alg != key2->key_alg)
return (ISC_FALSE);
- /*
- * For all algorithms except RSAMD5, revoking the key
- * changes the key ID, increasing it by 128. If we want to
- * be able to find matching keys even if one of them is the
- * revoked version of the other one, then we need to check
- * for that possibility.
- */
if (key1->key_id != key2->key_id) {
if (!match_revoked_key)
return (ISC_FALSE);
@@ -943,11 +937,8 @@ comparekeys(const dst_key_t *key1, const dst_key_t *key2,
if ((key1->key_flags & DNS_KEYFLAG_REVOKE) ==
(key2->key_flags & DNS_KEYFLAG_REVOKE))
return (ISC_FALSE);
- if ((key1->key_flags & DNS_KEYFLAG_REVOKE) != 0 &&
- key1->key_id != ((key2->key_id + 128) & 0xffff))
- return (ISC_FALSE);
- if ((key2->key_flags & DNS_KEYFLAG_REVOKE) != 0 &&
- key2->key_id != ((key1->key_id + 128) & 0xffff))
+ if (key1->key_id != key2->key_rid &&
+ key1->key_rid != key2->key_id)
return (ISC_FALSE);
}
@@ -1652,6 +1643,7 @@ computeid(dst_key_t *key) {
isc_buffer_usedregion(&dnsbuf, &r);
key->key_id = dst_region_computeid(&r, key->key_alg);
+ key->key_rid = dst_region_computerid(&r, key->key_alg);
return (ISC_R_SUCCESS);
}
diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h
index 2ebb0c36..094c4fe2 100644
--- a/lib/dns/dst_internal.h
+++ b/lib/dns/dst_internal.h
@@ -29,7 +29,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst_internal.h,v 1.30 2011-03-17 01:40:39 each Exp $ */
+/* $Id: dst_internal.h,v 1.31 2011-10-20 21:20:02 marka Exp $ */
#ifndef DST_DST_INTERNAL_H
#define DST_DST_INTERNAL_H 1
@@ -94,6 +94,8 @@ struct dst_key {
unsigned int key_alg; /*%< algorithm of the key */
isc_uint32_t key_flags; /*%< flags of the public key */
isc_uint16_t key_id; /*%< identifier of the key */
+ isc_uint16_t key_rid; /*%< identifier of the key when
+ revoked */
isc_uint16_t key_bits; /*%< hmac digest bits */
dns_rdataclass_t key_class; /*%< class of the key record */
dns_ttl_t key_ttl; /*%< default/initial dnskey ttl */
diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h
index bd6bd241..170fc846 100644
--- a/lib/dns/include/dns/adb.h
+++ b/lib/dns/include/dns/adb.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: adb.h,v 1.85 2008-04-03 06:09:04 tbox Exp $ */
+/* $Id: adb.h,v 1.87 2011-10-27 23:46:31 tbox Exp $ */
#ifndef DNS_ADB_H
#define DNS_ADB_H 1
@@ -548,6 +548,64 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
* srtt value. This may include changes made by others.
*/
+unsigned int
+dns_adb_getednsflag(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now);
+/*%
+ * Get the EDNS big size
+ *
+ *\brief
+ * Return the edns_fetchopt_flag from the instant dns_adbentry struct
+ * This value may be DNS_FETCHOPT_NOEDNS0, DNS_FETCHOPT_EDNS512,
+ * or 0. If 0, the default maximum EDNS udp size is assumed.
+ *
+ * Requires:
+ *
+ *\li adb be valid.
+ *
+ *\li addr be valid.
+ */
+
+void
+dns_adb_setednssize(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
+ unsigned int length);
+/*%
+ * Set the EDNS size
+ *
+ *\brief
+ * Record the biggest length of received packet and maintain information
+ * about reductions in udp size.
+ *
+ *\li length - size of packet
+ *\li now - current time in seconds
+ *
+ * Requires:
+ *
+ *\li adb be valid.
+ *
+ *\li addr be valid.
+ */
+
+void
+dns_adb_dropednssize(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
+ unsigned int length, isc_stdtime_t now);
+/*%
+ * Drop the EDNS size
+ *
+ *\brief
+ * Record a notification that the packetsize has been dropped because of
+ * communication failures. If enough of these occur, this server's EDNS size
+ * will be dropped for DNS_ADB_EDNS_MAX_DROP_TIME.
+ *
+ *\li length - size of packet
+ *\li now - current time in seconds
+ *
+ * Requires:
+ *
+ *\li adb be valid.
+ *
+ *\li addr be valid.
+ */
+
void
dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
unsigned int bits, unsigned int mask);
diff --git a/lib/dns/include/dns/events.h b/lib/dns/include/dns/events.h
index 88c2719c..1194decb 100644
--- a/lib/dns/include/dns/events.h
+++ b/lib/dns/include/dns/events.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: events.h,v 1.59 2011-09-02 21:15:36 each Exp $ */
+/* $Id: events.h,v 1.61 2011-10-28 06:20:06 each Exp $ */
#ifndef DNS_EVENTS_H
#define DNS_EVENTS_H 1
@@ -77,6 +77,8 @@
#define DNS_EVENT_ZONESECURESERIAL (ISC_EVENTCLASS_DNS + 47)
#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)
diff --git a/lib/dns/include/dns/nsec3.h b/lib/dns/include/dns/nsec3.h
index ac0c8f2c..bab06dd9 100644
--- a/lib/dns/include/dns/nsec3.h
+++ b/lib/dns/include/dns/nsec3.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2008-2011 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -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.14 2011-10-28 12:20:31 tbox 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.
diff --git a/lib/dns/include/dns/private.h b/lib/dns/include/dns/private.h
index ffedb5ff..43c6d2e2 100644
--- a/lib/dns/include/dns/private.h
+++ b/lib/dns/include/dns/private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009, 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
@@ -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.5 2011-10-28 12:20:31 tbox 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
diff --git a/lib/dns/include/dns/rpz.h b/lib/dns/include/dns/rpz.h
index adafd292..ded26f3b 100644
--- a/lib/dns/include/dns/rpz.h
+++ b/lib/dns/include/dns/rpz.h
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rpz.h,v 1.4 2011-10-13 01:32:34 vjs Exp $ */
+/* $Id: rpz.h,v 1.5 2011-10-28 11:46:50 marka Exp $ */
#ifndef DNS_RPZ_H
#define DNS_RPZ_H 1
@@ -105,6 +105,7 @@ typedef struct {
isc_result_t result;
dns_zone_t *zone;
dns_db_t *db;
+ dns_dbversion_t *version;
dns_dbnode_t *node;
dns_rdataset_t *rdataset;
} m;
diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h
index 1d8e434c..8725cb7d 100644
--- a/lib/dns/include/dns/zone.h
+++ b/lib/dns/include/dns/zone.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.h,v 1.194 2011-09-06 22:29:33 smann Exp $ */
+/* $Id: zone.h,v 1.196 2011-10-28 06:20:06 each Exp $ */
#ifndef DNS_ZONE_H
#define DNS_ZONE_H 1
@@ -1978,6 +1978,23 @@ dns_zone_link(dns_zone_t *zone, dns_zone_t *raw);
void
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 */
diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h
index 598f6659..a5acb41d 100644
--- a/lib/dns/include/dst/dst.h
+++ b/lib/dns/include/dst/dst.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst.h,v 1.33 2011-03-21 19:54:03 each Exp $ */
+/* $Id: dst.h,v 1.34 2011-10-20 21:20:02 marka Exp $ */
#ifndef DST_DST_H
#define DST_DST_H 1
@@ -641,6 +641,9 @@ dst_key_flags(const dst_key_t *key);
dns_keytag_t
dst_key_id(const dst_key_t *key);
+dns_keytag_t
+dst_key_rid(const dst_key_t *key);
+
dns_rdataclass_t
dst_key_class(const dst_key_t *key);
@@ -706,9 +709,11 @@ dst_key_secretsize(const dst_key_t *key, unsigned int *n);
isc_uint16_t
dst_region_computeid(const isc_region_t *source, unsigned int alg);
+isc_uint16_t
+dst_region_computerid(const isc_region_t *source, unsigned int alg);
/*%<
- * Computes the key id of the key stored in the provided region with the
- * given algorithm.
+ * Computes the (revoked) key id of the key stored in the provided
+ * region with the given algorithm.
*
* Requires:
*\li "source" contains a valid, non-NULL region.
diff --git a/lib/dns/key.c b/lib/dns/key.c
index 9882bad1..36c005e8 100644
--- a/lib/dns/key.c
+++ b/lib/dns/key.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: key.c,v 1.10 2011-03-17 23:47:30 tbox Exp $ */
+/* $Id: key.c,v 1.11 2011-10-20 21:20:02 marka Exp $ */
#include <config.h>
@@ -56,6 +56,33 @@ dst_region_computeid(const isc_region_t *source, unsigned int alg) {
return ((isc_uint16_t)(ac & 0xffff));
}
+isc_uint16_t
+dst_region_computerid(const isc_region_t *source, unsigned int alg) {
+ isc_uint32_t ac;
+ const unsigned char *p;
+ int size;
+
+ REQUIRE(source != NULL);
+ REQUIRE(source->length >= 4);
+
+ p = source->base;
+ size = source->length;
+
+ if (alg == DST_ALG_RSAMD5)
+ return ((p[size - 3] << 8) + p[size - 2]);
+
+ ac = ((*p) << 8) + *(p + 1);
+ ac |= DNS_KEYFLAG_REVOKE;
+ for (size -= 2, p +=2; size > 1; size -= 2, p += 2)
+ ac += ((*p) << 8) + *(p + 1);
+
+ if (size > 0)
+ ac += ((*p) << 8);
+ ac += (ac >> 16) & 0xffff;
+
+ return ((isc_uint16_t)(ac & 0xffff));
+}
+
dns_name_t *
dst_key_name(const dst_key_t *key) {
REQUIRE(VALID_KEY(key));
@@ -92,6 +119,12 @@ dst_key_id(const dst_key_t *key) {
return (key->key_id);
}
+dns_keytag_t
+dst_key_rid(const dst_key_t *key) {
+ REQUIRE(VALID_KEY(key));
+ return (key->key_rid);
+}
+
dns_rdataclass_t
dst_key_class(const dst_key_t *key) {
REQUIRE(VALID_KEY(key));
diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c
index 4210135b..2217e5c9 100644
--- a/lib/dns/nsec3.c
+++ b/lib/dns/nsec3.c
@@ -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;
diff --git a/lib/dns/private.c b/lib/dns/private.c
index 9602d59d..74b86e87 100644
--- a/lib/dns/private.c
+++ b/lib/dns/private.c
@@ -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);
+}
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index 9b9e2564..49823d31 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.c,v 1.435 2011-10-12 00:18:11 marka Exp $ */
+/* $Id: resolver.c,v 1.437 2011-10-27 23:46:31 tbox Exp $ */
/*! \file */
@@ -1324,7 +1324,9 @@ fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
* We retry every .8 seconds the first two times through the address
* list, and then we do exponential back-off.
*/
- if (fctx->restarts < 3)
+ if (fctx->restarts == 0)
+ us = 400000;
+ else if (fctx->restarts < 3)
us = 800000;
else
us = (800000 << (fctx->restarts - 2));
@@ -1682,6 +1684,8 @@ resquery_send(resquery_t *query) {
dns_compress_t cctx;
isc_boolean_t cleanup_cctx = ISC_FALSE;
isc_boolean_t secure_domain;
+ unsigned int edns_fetchopt_flag;
+ isc_stdtime_t now;
fctx = query->fctx;
QTRACE("send");
@@ -1792,6 +1796,16 @@ resquery_send(resquery_t *query) {
(void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
/*
+ * Get the fetchopt flag for this server from the adb cache
+ * NOTE: if the NOEDNS flag has been set on addrinfo->flags,
+ * it will over write this below.
+ */
+ isc_stdtime_get(&now);
+ edns_fetchopt_flag = dns_adb_getednsflag(fctx->adb, query->addrinfo,
+ now);
+ query->options |= edns_fetchopt_flag;
+
+ /*
* The ADB does not know about servers with "edns no". Check this,
* and then inform the ADB for future use.
*/
@@ -1825,17 +1839,23 @@ resquery_send(resquery_t *query) {
* * packet loss / link outage.
*/
if (fctx->timeout) {
- if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
- fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&
+ if ((triededns512(fctx, &query->addrinfo->sockaddr) &&
+ fctx->timeouts > MAX_EDNS0_TIMEOUTS) &&
(query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
query->options |= DNS_FETCHOPT_NOEDNS0;
fctx->reason = "disabling EDNS";
} else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
- fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&
+ fctx->timeouts >= 1) &&
(query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
query->options |= DNS_FETCHOPT_EDNS512;
- fctx->reason = "reducing the advertised EDNS UDP "
- "packet size to 512 octets";
+ if (edns_fetchopt_flag != DNS_FETCHOPT_EDNS512) {
+ dns_adb_dropednssize(fctx->adb, query->addrinfo,
+ 512, now);
+ fctx->reason = "reducing the advertised EDNS "
+ "UDP packet size to 512 octets";
+ } else
+ fctx->reason = "continuing to use lower EDNS "
+ "UDP packet size of 512 octets";
}
fctx->timeout = ISC_FALSE;
}
@@ -1901,10 +1921,14 @@ resquery_send(resquery_t *query) {
add_triededns512(fctx, &query->addrinfo->sockaddr);
/*
- * Clear CD if EDNS is not in use.
+ * Clear CD if EDNS is not in use and set NOEDNS0 in adb.
*/
- if ((query->options & DNS_FETCHOPT_NOEDNS0) != 0)
+ if ((query->options & DNS_FETCHOPT_NOEDNS0) != 0) {
fctx->qmessage->flags &= ~DNS_MESSAGEFLAG_CD;
+ dns_adb_changeflags(fctx->adb, query->addrinfo,
+ DNS_FETCHOPT_NOEDNS0,
+ DNS_FETCHOPT_NOEDNS0);
+ }
/*
* Add TSIG record tailored to the current recipient.
@@ -6856,6 +6880,16 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
}
/*
+ * Update the packet received sizes
+ */
+ if (((query->options & DNS_FETCHOPT_NOEDNS0) == 0) &&
+ ((devent->attributes & DNS_DISPATCHATTR_UDP) != 0))
+ dns_adb_setednssize(fctx->adb,
+ query->addrinfo,
+ devent->buffer.length);
+
+
+ /*
* Enforce delegations only zones like NET and COM.
*/
if (!ISFORWARDER(query->addrinfo) &&
diff --git a/lib/dns/tests/Makefile.in b/lib/dns/tests/Makefile.in
index ddf569b4..17d0ca5d 100644
--- a/lib/dns/tests/Makefile.in
+++ b/lib/dns/tests/Makefile.in
@@ -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} \
diff --git a/lib/dns/tests/private_test.c b/lib/dns/tests/private_test.c
new file mode 100644
index 00000000..7e1ba694
--- /dev/null
+++ b/lib/dns/tests/private_test.c
@@ -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());
+}
+
diff --git a/lib/dns/validator.c b/lib/dns/validator.c
index f3bd4d5b..4002181a 100644
--- a/lib/dns/validator.c
+++ b/lib/dns/validator.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.c,v 1.204 2011-06-08 22:13:51 each Exp $ */
+/* $Id: validator.c,v 1.207 2011-10-20 23:46:51 tbox Exp $ */
#include <config.h>
@@ -846,7 +846,7 @@ cnamevalidated(isc_task_t *task, isc_event_t *event) {
* Return ISC_R_IGNORE when the NSEC is not the appropriate one.
*/
static isc_result_t
-nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
+nsecnoexistnodata(dns_validator_t *val, dns_name_t *name, dns_name_t *nsecname,
dns_rdataset_t *nsecset, isc_boolean_t *exists,
isc_boolean_t *data, dns_name_t *wild)
{
@@ -887,9 +887,11 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
if (order == 0) {
/*
- * The names are the same.
+ * The names are the same. If we are validating "."
+ * then atparent should not be set as there is no parent.
*/
- atparent = dns_rdatatype_atparent(val->event->type);
+ atparent = (olabels != 1) &&
+ dns_rdatatype_atparent(val->event->type);
ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa);
if (ns && !soa) {
@@ -1920,13 +1922,14 @@ verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
isc_result_t result;
dns_fixedname_t fixed;
isc_boolean_t ignore = ISC_FALSE;
+ dns_name_t *wild;
val->attributes |= VALATTR_TRIEDVERIFY;
dns_fixedname_init(&fixed);
+ wild = dns_fixedname_name(&fixed);
again:
result = dns_dnssec_verify2(val->event->name, val->event->rdataset,
- key, ignore, val->view->mctx, rdata,
- dns_fixedname_name(&fixed));
+ key, ignore, val->view->mctx, rdata, wild);
if (result == DNS_R_SIGEXPIRED && val->view->acceptexpired) {
ignore = ISC_TRUE;
goto again;
@@ -1941,9 +1944,20 @@ verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
"verify rdataset (keyid=%u): %s",
keyid, isc_result_totext(result));
if (result == DNS_R_FROMWILDCARD) {
- if (!dns_name_equal(val->event->name,
- dns_fixedname_name(&fixed)))
+ if (!dns_name_equal(val->event->name, wild)) {
+ dns_name_t *closest;
+ unsigned int labels;
+
+ /*
+ * Compute the closest encloser in case we need it
+ * for the NSEC3 NOQNAME proof.
+ */
+ closest = dns_fixedname_name(&val->closest);
+ dns_name_copy(wild, closest, NULL);
+ labels = dns_name_countlabels(closest) - 1;
+ dns_name_getlabelsequence(closest, 1, labels, closest);
val->attributes |= VALATTR_NEEDNOQNAME;
+ }
result = ISC_R_SUCCESS;
}
return (result);
@@ -2871,9 +2885,9 @@ findnsec3proofs(dns_validator_t *val) {
dns_name_t *name, tname;
isc_result_t result;
isc_boolean_t exists, data, optout, unknown;
- isc_boolean_t setclosest, setnearest;
+ isc_boolean_t setclosest, setnearest, *setclosestp;
dns_fixedname_t fclosest, fnearest, fzonename;
- dns_name_t *closest, *nearest, *zonename;
+ dns_name_t *closest, *nearest, *zonename, *closestp;
dns_name_t **proofs = val->event->proofs;
dns_rdataset_t *rdataset, trdataset;
@@ -2920,6 +2934,25 @@ findnsec3proofs(dns_validator_t *val) {
if (dns_name_countlabels(zonename) == 0)
return (ISC_R_SUCCESS);
+ /*
+ * If the val->closest is set then we want to use it otherwise
+ * we need to discover it.
+ */
+ if (dns_name_countlabels(dns_fixedname_name(&val->closest)) != 0) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(dns_fixedname_name(&val->closest),
+ namebuf, sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3), "closest encloser from "
+ "wildcard signature '%s'", namebuf);
+ dns_name_copy(dns_fixedname_name(&val->closest), closest, NULL);
+ closestp = NULL;
+ setclosestp = NULL;
+ } else {
+ closestp = closest;
+ setclosestp = &setclosest;
+ }
+
for (result = val_rdataset_first(val, &name, &rdataset);
result == ISC_R_SUCCESS;
result = val_rdataset_next(val, &name, &rdataset))
@@ -2937,8 +2970,8 @@ findnsec3proofs(dns_validator_t *val) {
unknown = ISC_FALSE;
(void)nsec3noexistnodata(val, val->event->name, name, rdataset,
zonename, &exists, &data, &optout,
- &unknown, &setclosest, &setnearest,
- closest, nearest);
+ &unknown, setclosestp, &setnearest,
+ closestp, nearest);
if (setclosest)
proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
if (unknown)
diff --git a/lib/dns/win32/libdns.def b/lib/dns/win32/libdns.def
index 11efee00..5eaaad72 100644
--- a/lib/dns/win32/libdns.def
+++ b/lib/dns/win32/libdns.def
@@ -468,6 +468,7 @@ dns_portlist_add
dns_portlist_create
dns_portlist_detach
dns_private_chains
+dns_private_totext
dns_rbt_addname
dns_rbt_addnode
dns_rbt_create
@@ -830,6 +831,7 @@ dns_zone_iattach
dns_zone_idetach
dns_zone_isdynamic
dns_zone_isforced
+dns_zone_keydone
dns_zone_link
dns_zone_load
dns_zone_loadandthaw
@@ -884,6 +886,7 @@ dns_zone_setnotifydelay
dns_zone_setnotifysrc4
dns_zone_setnotifysrc6
dns_zone_setnotifytype
+dns_zone_setnsec3param
dns_zone_setoption
dns_zone_setorigin
dns_zone_setprivatetype
@@ -977,6 +980,7 @@ dst_key_paramcompare
dst_key_proto
dst_key_pubcompare
dst_key_restore
+dst_key_rid
dst_key_secretsize
dst_key_setbits
dst_key_setflags
@@ -994,6 +998,7 @@ dst_lib_init
dst_lib_init2
dst_lib_initmsgcat
dst_region_computeid
+dst_region_computerid
dst_result_register
dst_result_totext
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 4fe4c7d4..ba9379d0 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.c,v 1.635 2011-10-12 23:46:34 tbox Exp $ */
+/* $Id: zone.c,v 1.643 2011-10-28 12:27:06 marka Exp $ */
/*! \file */
@@ -23,6 +23,7 @@
#include <errno.h>
#include <isc/file.h>
+#include <isc/hex.h>
#include <isc/mutex.h>
#include <isc/print.h>
#include <isc/random.h>
@@ -30,9 +31,9 @@
#include <isc/refcount.h>
#include <isc/rwlock.h>
#include <isc/serial.h>
-#include <isc/strerror.h>
#include <isc/stats.h>
#include <isc/stdtime.h>
+#include <isc/strerror.h>
#include <isc/string.h>
#include <isc/taskpool.h>
#include <isc/timer.h>
@@ -650,6 +651,8 @@ static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
+static isc_result_t zone_send_secureserial(dns_zone_t *zone,
+ isc_uint32_t serial);
#if 0
/* ondestroy example */
@@ -7600,8 +7603,7 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
if (dst_key_alg(dstkey) == sig.algorithm &&
(dst_key_id(dstkey) == sig.keyid ||
- (sig.algorithm != 1 && sig.keyid ==
- ((dst_key_id(dstkey) + 128) & 0xffff)))) {
+ dst_key_rid(dstkey) == sig.keyid)) {
result = dns_dnssec_verify2(keyname,
&kfetch->dnskeyset,
dstkey, ISC_FALSE, mctx, &sigrr,
@@ -8334,6 +8336,7 @@ zone_maintenance(dns_zone_t *zone) {
switch (zone->type) {
case dns_zone_master:
+ case dns_zone_redirect:
case dns_zone_slave:
/*
* Do we need to send out notify messages?
@@ -8370,10 +8373,26 @@ zone_maintenance(dns_zone_t *zone) {
void
dns_zone_markdirty(dns_zone_t *zone) {
+ isc_uint32_t serial;
+ isc_result_t result;
LOCK_ZONE(zone);
- if (zone->type == dns_zone_master)
+ if (zone->type == dns_zone_master) {
+ if (zone->secure != NULL) {
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL) {
+ result = zone_get_from_db(zone, zone->db, NULL,
+ NULL, &serial, NULL,
+ NULL, NULL, NULL,
+ NULL);
+ } else
+ result = DNS_R_NOTLOADED;
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ if (result == ISC_R_SUCCESS)
+ zone_send_secureserial(zone, serial);
+ }
set_resigntime(zone); /* XXXMPA make separate call back */
+ }
zone_needdump(zone, DNS_DUMP_DELAY);
UNLOCK_ZONE(zone);
}
@@ -12383,10 +12402,8 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
break;
}
}
-#if 0
- if (zone->secure != NULL)
+ if (zone->type == dns_zone_master && zone->secure != NULL)
zone_send_secureserial(zone, serial);
-#endif
} else {
if (dump && zone->masterfile != NULL) {
/*
@@ -14791,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)
@@ -15320,3 +15337,436 @@ dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
dns_zone_attach(zone->raw, raw);
UNLOCK(&zone->lock);
}
+
+struct keydone {
+ isc_event_t event;
+ 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";
+ isc_boolean_t commit = ISC_FALSE;
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_dbversion_t *oldver = NULL, *newver = NULL;
+ dns_zone_t *zone;
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ 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);
+
+ zone = event->ev_arg;
+ INSIST(DNS_ZONE_VALID(zone));
+
+ ENTER;
+
+ dns_rdataset_init(&rdataset);
+ 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,
+ "keydone:dns_db_newversion -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ if (db == NULL)
+ goto failure;
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ result = dns_db_findrdataset(db, node, newver, zone->privatetype,
+ dns_rdatatype_none, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ INSIST(!dns_rdataset_isassociated(&rdataset));
+ goto failure;
+ }
+ if (result != ISC_R_SUCCESS) {
+ 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 (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);
+ }
+
+ 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 (!clear_pending)
+ CHECK(result);
+
+ CHECK(zone_journal(zone, &diff, NULL, "keydone"));
+ 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(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (db != NULL) {
+ 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);
+ dns_db_detach(&db);
+ }
+ dns_diff_clear(&diff);
+ isc_event_free(&event);
+ dns_zone_idetach(&zone);
+}
+
+isc_result_t
+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));
+
+ LOCK_ZONE(zone);
+
+ e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
+ zone, sizeof(struct keydone));
+ if (e == NULL) {
+ result = ISC_R_NOMEMORY;
+ 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 = ISC_R_SUCCESS;
+ 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);
+
+ failure:
+ if (e != NULL)
+ isc_event_free(&e);
+ UNLOCK_ZONE(zone);
+ return (result);
+}
diff --git a/lib/isc/hmacsha.c b/lib/isc/hmacsha.c
index 125672d6..8952ad64 100644
--- a/lib/isc/hmacsha.c
+++ b/lib/isc/hmacsha.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005-2007, 2009, 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
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: hmacsha.c,v 1.10 2009-02-06 23:47:42 tbox Exp $ */
+/* $Id: hmacsha.c,v 1.12 2011-10-24 23:46:14 tbox Exp $ */
/*
* This code implements the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384
@@ -224,8 +224,7 @@ isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
void
isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
isc_sha1_invalidate(&ctx->sha1ctx);
- memset(ctx->key, 0, sizeof(ctx->key));
- memset(ctx, 0, sizeof(ctx));
+ memset(ctx, 0, sizeof(*ctx));
}
/*
@@ -292,8 +291,7 @@ isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
void
isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
- memset(ctx->key, 0, sizeof(ctx->key));
- memset(ctx, 0, sizeof(ctx));
+ memset(ctx, 0, sizeof(*ctx));
}
/*
@@ -359,8 +357,7 @@ isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
void
isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
- memset(ctx->key, 0, sizeof(ctx->key));
- memset(ctx, 0, sizeof(ctx));
+ memset(ctx, 0, sizeof(*ctx));
}
/*
@@ -426,8 +423,7 @@ isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
void
isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
- memset(ctx->key, 0, sizeof(ctx->key));
- memset(ctx, 0, sizeof(ctx));
+ memset(ctx, 0, sizeof(*ctx));
}
/*
@@ -493,8 +489,7 @@ isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
void
isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
- memset(ctx->key, 0, sizeof(ctx->key));
- memset(ctx, 0, sizeof(ctx));
+ memset(ctx, 0, sizeof(*ctx));
}
/*
diff --git a/lib/isc/sha2.c b/lib/isc/sha2.c
index 59be8287..d4c7ea82 100644
--- a/lib/isc/sha2.c
+++ b/lib/isc/sha2.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sha2.c,v 1.20 2011-03-12 04:59:49 tbox Exp $ */
+/* $Id: sha2.c,v 1.21 2011-10-24 22:51:29 mgraff Exp $ */
/* $FreeBSD: src/sys/crypto/sha2/sha2.c,v 1.2.2.2 2002/03/05 08:36:47 ume Exp $ */
/* $KAME: sha2.c,v 1.8 2001/11/08 01:07:52 itojun Exp $ */
@@ -905,7 +905,7 @@ isc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) {
}
/* Clean up state data: */
- memset(context, 0, sizeof(context));
+ memset(context, 0, sizeof(*context));
usedspace = 0;
POST(usedspace);
}
@@ -1229,7 +1229,7 @@ void isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) {
}
/* Zero out state data */
- memset(context, 0, sizeof(context));
+ memset(context, 0, sizeof(*context));
}
@@ -1282,7 +1282,7 @@ isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) {
}
/* Zero out state data */
- memset(context, 0, sizeof(context));
+ memset(context, 0, sizeof(*context));
}
#endif /* !ISC_PLATFORM_OPENSSLHASH */
@@ -1313,7 +1313,7 @@ isc_sha224_end(isc_sha224_t *context, char buffer[]) {
#ifdef ISC_PLATFORM_OPENSSLHASH
EVP_MD_CTX_cleanup(context);
#else
- memset(context, 0, sizeof(context));
+ memset(context, 0, sizeof(*context));
#endif
}
memset(digest, 0, ISC_SHA224_DIGESTLENGTH);
@@ -1352,7 +1352,7 @@ isc_sha256_end(isc_sha256_t *context, char buffer[]) {
#ifdef ISC_PLATFORM_OPENSSLHASH
EVP_MD_CTX_cleanup(context);
#else
- memset(context, 0, sizeof(context));
+ memset(context, 0, sizeof(*context));
#endif
}
memset(digest, 0, ISC_SHA256_DIGESTLENGTH);
@@ -1391,7 +1391,7 @@ isc_sha512_end(isc_sha512_t *context, char buffer[]) {
#ifdef ISC_PLATFORM_OPENSSLHASH
EVP_MD_CTX_cleanup(context);
#else
- memset(context, 0, sizeof(context));
+ memset(context, 0, sizeof(*context));
#endif
}
memset(digest, 0, ISC_SHA512_DIGESTLENGTH);
@@ -1430,7 +1430,7 @@ isc_sha384_end(isc_sha384_t *context, char buffer[]) {
#ifdef ISC_PLATFORM_OPENSSLHASH
EVP_MD_CTX_cleanup(context);
#else
- memset(context, 0, sizeof(context));
+ memset(context, 0, sizeof(*context));
#endif
}
memset(digest, 0, ISC_SHA384_DIGESTLENGTH);
diff --git a/lib/isc/tests/task_test.c b/lib/isc/tests/task_test.c
index a8dfd89d..5f03ff17 100644
--- a/lib/isc/tests/task_test.c
+++ b/lib/isc/tests/task_test.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: task_test.c,v 1.3 2011-09-02 23:46:33 tbox Exp $ */
+/* $Id: task_test.c,v 1.4 2011-10-18 02:00:56 marka Exp $ */
/*! \file */
@@ -107,6 +107,9 @@ ATF_TC_BODY(all_events, tc) {
counter = 1;
+ result = isc_mutex_init(&set_lock);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
result = isc_test_begin(NULL, ISC_TRUE);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);