diff options
author | Internet Software Consortium, Inc <@isc.org> | 2012-01-18 10:10:04 -0700 |
---|---|---|
committer | Internet Software Consortium, Inc <@isc.org> | 2012-01-18 10:10:04 -0700 |
commit | 52a7f63e4e1a5cc6705c88c2090499b2caaa0805 (patch) | |
tree | 330f8ca530b9d9e0161703f3d85575c1e43dd8d8 /lib | |
parent | cf94dd77f7578bef7bc0ff3feac9aaa548180641 (diff) | |
download | bind9-52a7f63e4e1a5cc6705c88c2090499b2caaa0805.tar.gz |
9.9.0b1
Diffstat (limited to 'lib')
-rw-r--r-- | lib/bind9/check.c | 21 | ||||
-rw-r--r-- | lib/dns/adb.c | 217 | ||||
-rw-r--r-- | lib/dns/dst_api.c | 22 | ||||
-rw-r--r-- | lib/dns/dst_internal.h | 4 | ||||
-rw-r--r-- | lib/dns/include/dns/adb.h | 62 | ||||
-rw-r--r-- | lib/dns/include/dns/events.h | 4 | ||||
-rw-r--r-- | lib/dns/include/dns/nsec3.h | 7 | ||||
-rw-r--r-- | lib/dns/include/dns/private.h | 21 | ||||
-rw-r--r-- | lib/dns/include/dns/rpz.h | 3 | ||||
-rw-r--r-- | lib/dns/include/dns/zone.h | 19 | ||||
-rw-r--r-- | lib/dns/include/dst/dst.h | 11 | ||||
-rw-r--r-- | lib/dns/key.c | 35 | ||||
-rw-r--r-- | lib/dns/nsec3.c | 21 | ||||
-rw-r--r-- | lib/dns/private.c | 73 | ||||
-rw-r--r-- | lib/dns/resolver.c | 52 | ||||
-rw-r--r-- | lib/dns/tests/Makefile.in | 13 | ||||
-rw-r--r-- | lib/dns/tests/private_test.c | 225 | ||||
-rw-r--r-- | lib/dns/validator.c | 57 | ||||
-rw-r--r-- | lib/dns/win32/libdns.def | 5 | ||||
-rw-r--r-- | lib/dns/zone.c | 468 | ||||
-rw-r--r-- | lib/isc/hmacsha.c | 19 | ||||
-rw-r--r-- | lib/isc/sha2.c | 16 | ||||
-rw-r--r-- | lib/isc/tests/task_test.c | 5 |
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, ¶ms, &buf); + + dns_rdata_init(private); + + dns_nsec3param_toprivate(&nsec3param, private, privatetype, + pbuf, DNS_NSEC3PARAM_BUFFERSIZE + 1); +} + +/* + * Individual unit tests + */ +ATF_TC(private_signing_totext); +ATF_TC_HEAD(private_signing_totext, tc) { + atf_tc_set_md_var(tc, "descr", + "convert private signing records to text"); +} +ATF_TC_BODY(private_signing_totext, tc) { + isc_result_t result; + dns_rdata_t private; + int i; + + signing_testcase_t testcases[] = { + { DST_ALG_RSASHA512, 12345, 0, 0 }, + { DST_ALG_RSASHA256, 54321, 1, 0 }, + { DST_ALG_NSEC3RSASHA1, 22222, 0, 1 }, + { DST_ALG_RSASHA1, 33333, 1, 1 } + }; + const char *results[] = { + "Signing with key 12345/RSASHA512", + "Removing signatures for key 54321/RSASHA256", + "Done signing with key 22222/NSEC3RSASHA1", + "Done removing signatures for key 33333/RSASHA1" + }; + int ncases = 4; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + for (i = 0; i < ncases; i++) { + unsigned char data[5]; + char output[BUFSIZ]; + isc_buffer_t buf; + + isc_buffer_init(&buf, output, sizeof(output)); + + make_signing(&testcases[i], &private, data); + dns_private_totext(&private, &buf); + ATF_CHECK_STREQ(output, results[i]); + } + + dns_test_end(); +} + +ATF_TC(private_nsec3_totext); +ATF_TC_HEAD(private_nsec3_totext, tc) { + atf_tc_set_md_var(tc, "descr", "convert private chain records to text"); +} +ATF_TC_BODY(private_nsec3_totext, tc) { + isc_result_t result; + dns_rdata_t private; + int i; + + nsec3_testcase_t testcases[] = { + { 1, 0, 1, 0xbeef, 0, 0, 0 }, + { 1, 1, 10, 0xdadd, 0, 0, 0 }, + { 1, 0, 20, 0xbead, 0, 1, 0 }, + { 1, 0, 30, 0xdeaf, 1, 0, 0 }, + { 1, 0, 100, 0xfeedabee, 1, 0, 1 }, + }; + const char *results[] = { + "Creating NSEC3 chain 1 0 1 BEEF", + "Creating NSEC3 chain 1 1 10 DADD", + "Pending NSEC3 chain 1 0 20 BEAD", + "Removing NSEC3 chain 1 0 30 DEAF / creating NSEC chain", + "Removing NSEC3 chain 1 0 100 FEEDABEE" + }; + int ncases = 5; + + UNUSED(tc); + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + for (i = 0; i < ncases; i++) { + unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1]; + char output[BUFSIZ]; + isc_buffer_t buf; + + isc_buffer_init(&buf, output, sizeof(output)); + + make_nsec3(&testcases[i], &private, data); + dns_private_totext(&private, &buf); + ATF_CHECK_STREQ(output, results[i]); + } + + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, private_signing_totext); + ATF_TP_ADD_TC(tp, private_nsec3_totext); + return (atf_no_error()); +} + 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(¶m.common, link); + param.mctx = NULL; + param.hash = hash; + param.flags = flags; + param.iterations = iter; + param.salt_length = saltlen; + param.salt = salt; + isc_buffer_init(&b, nbuf, sizeof(nbuf)); + CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass, + dns_rdatatype_nsec3param, + ¶m, &b)); + dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype, + np->data, sizeof(np->data)); + np->length = prdata.length; + } + + zone_iattach(zone, &dummy); + isc_task_send(zone->task, &e); + + 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); |