summaryrefslogtreecommitdiffstats
path: root/lib/dns
diff options
context:
space:
mode:
authordougb <dougb@FreeBSD.org>2010-10-30 21:01:18 +0000
committerdougb <dougb@FreeBSD.org>2010-10-30 21:01:18 +0000
commiteb399bacb260498dc82cc60bff7e32bb7538b8c4 (patch)
tree3b7387d91fd2a2ef9aa09d7a73d475e92199f7d1 /lib/dns
parent6d41f7ac6b360a4d3daf511eefc0708d423832cb (diff)
downloadFreeBSD-src-eb399bacb260498dc82cc60bff7e32bb7538b8c4.zip
FreeBSD-src-eb399bacb260498dc82cc60bff7e32bb7538b8c4.tar.gz
Vendor import of BIND 9.6-ESV-R2
Diffstat (limited to 'lib/dns')
-rw-r--r--lib/dns/adb.c51
-rw-r--r--lib/dns/api6
-rw-r--r--lib/dns/include/dns/diff.h6
-rw-r--r--lib/dns/include/dns/ncache.h11
-rw-r--r--lib/dns/include/dns/rdataset.h2
-rw-r--r--lib/dns/include/dns/resolver.h2
-rw-r--r--lib/dns/include/dns/result.h2
-rw-r--r--lib/dns/include/dns/types.h5
-rw-r--r--lib/dns/include/dns/validator.h2
-rw-r--r--lib/dns/ncache.c150
-rw-r--r--lib/dns/rbtdb.c30
-rw-r--r--lib/dns/rdatalist.c2
-rw-r--r--lib/dns/rdataset.c2
-rw-r--r--lib/dns/rdataslab.c2
-rw-r--r--lib/dns/resolver.c73
-rw-r--r--lib/dns/result.c2
-rw-r--r--lib/dns/sdb.c2
-rw-r--r--lib/dns/sdlz.c2
-rw-r--r--lib/dns/validator.c724
-rw-r--r--lib/dns/view.c2
20 files changed, 691 insertions, 387 deletions
diff --git a/lib/dns/adb.c b/lib/dns/adb.c
index 7056215..28121a7 100644
--- a/lib/dns/adb.c
+++ b/lib/dns/adb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 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.c,v 1.243.42.4 2009/02/03 22:34:28 jinmei Exp $ */
+/* $Id: adb.c,v 1.243.42.4.24.2 2010/08/12 23:46:24 tbox Exp $ */
/*! \file
*
@@ -118,7 +118,6 @@ struct dns_adb {
isc_taskmgr_t *taskmgr;
isc_task_t *task;
- isc_boolean_t overmem;
isc_interval_t tick_interval;
int next_cleanbucket;
@@ -294,8 +293,8 @@ static inline void inc_adb_irefcnt(dns_adb_t *);
static inline void inc_adb_erefcnt(dns_adb_t *);
static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
isc_boolean_t);
-static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
- isc_boolean_t);
+static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t,
+ dns_adbentry_t *, isc_boolean_t);
static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
static void clean_target(dns_adb_t *, dns_name_t *);
@@ -777,7 +776,7 @@ link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) {
int i;
dns_adbentry_t *e;
- if (adb->overmem) {
+ if (isc_mem_isovermem(adb->mctx)) {
for (i = 0; i < 2; i++) {
e = ISC_LIST_TAIL(adb->entries[bucket]);
if (e == NULL)
@@ -943,6 +942,7 @@ clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
dns_adbnamehook_t *namehook;
int addr_bucket;
isc_boolean_t result = ISC_FALSE;
+ isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
addr_bucket = DNS_ADB_INVALIDBUCKET;
namehook = ISC_LIST_HEAD(*namehooks);
@@ -963,7 +963,8 @@ clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
LOCK(&adb->entrylocks[addr_bucket]);
}
- result = dec_entry_refcnt(adb, entry, ISC_FALSE);
+ result = dec_entry_refcnt(adb, overmem, entry,
+ ISC_FALSE);
}
/*
@@ -1235,7 +1236,9 @@ inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
}
static inline isc_boolean_t
-dec_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
+dec_entry_refcnt(dns_adb_t *adb, isc_boolean_t overmem, dns_adbentry_t *entry,
+ isc_boolean_t lock)
+{
int bucket;
isc_boolean_t destroy_entry;
isc_boolean_t result = ISC_FALSE;
@@ -1250,7 +1253,7 @@ dec_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
destroy_entry = ISC_FALSE;
if (entry->refcnt == 0 &&
- (adb->entry_sd[bucket] || entry->expires == 0 || adb->overmem ||
+ (adb->entry_sd[bucket] || entry->expires == 0 || overmem ||
(entry->flags & ENTRY_IS_DEAD) != 0)) {
destroy_entry = ISC_TRUE;
result = unlink_entry(adb, entry);
@@ -1852,7 +1855,7 @@ check_stale_name(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
int victims, max_victims;
isc_boolean_t result;
dns_adbname_t *victim, *next_victim;
- isc_boolean_t overmem = adb->overmem;
+ isc_boolean_t overmem = isc_mem_isovermem(adb->mctx);
int scans = 0;
INSIST(bucket != DNS_ADB_INVALIDBUCKET);
@@ -2049,7 +2052,6 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb, NULL, NULL);
adb->cevent_sent = ISC_FALSE;
adb->shutting_down = ISC_FALSE;
- adb->overmem = ISC_FALSE;
ISC_LIST_INIT(adb->whenshutdown);
isc_mem_attach(mem, &adb->mctx);
@@ -2616,6 +2618,7 @@ dns_adb_destroyfind(dns_adbfind_t **findp) {
dns_adbaddrinfo_t *ai;
int bucket;
dns_adb_t *adb;
+ isc_boolean_t overmem;
REQUIRE(findp != NULL && DNS_ADBFIND_VALID(*findp));
find = *findp;
@@ -2640,13 +2643,14 @@ dns_adb_destroyfind(dns_adbfind_t **findp) {
* Return the find to the memory pool, and decrement the adb's
* reference count.
*/
+ overmem = isc_mem_isovermem(adb->mctx);
ai = ISC_LIST_HEAD(find->list);
while (ai != NULL) {
ISC_LIST_UNLINK(find->list, ai, publink);
entry = ai->entry;
ai->entry = NULL;
INSIST(DNS_ADBENTRY_VALID(entry));
- RUNTIME_CHECK(dec_entry_refcnt(adb, entry, ISC_TRUE) ==
+ RUNTIME_CHECK(dec_entry_refcnt(adb, overmem, entry, ISC_TRUE) ==
ISC_FALSE);
free_adbaddrinfo(adb, &ai);
ai = ISC_LIST_HEAD(find->list);
@@ -3509,6 +3513,7 @@ dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) {
int bucket;
isc_stdtime_t now;
isc_boolean_t want_check_exit = ISC_FALSE;
+ isc_boolean_t overmem;
REQUIRE(DNS_ADB_VALID(adb));
REQUIRE(addrp != NULL);
@@ -3520,13 +3525,14 @@ dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) {
isc_stdtime_get(&now);
*addrp = NULL;
+ overmem = isc_mem_isovermem(adb->mctx);
bucket = addr->entry->lock_bucket;
LOCK(&adb->entrylocks[bucket]);
entry->expires = now + ADB_ENTRY_WINDOW;
- want_check_exit = dec_entry_refcnt(adb, entry, ISC_FALSE);
+ want_check_exit = dec_entry_refcnt(adb, overmem, entry, ISC_FALSE);
UNLOCK(&adb->entrylocks[bucket]);
@@ -3591,6 +3597,14 @@ dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) {
static void
water(void *arg, int mark) {
+ /*
+ * We're going to change the way to handle overmem condition: use
+ * isc_mem_isovermem() instead of storing the state via this callback,
+ * since the latter way tends to cause race conditions.
+ * To minimize the change, and in case we re-enable the callback
+ * approach, however, keep this function at the moment.
+ */
+
dns_adb_t *adb = arg;
isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);
@@ -3598,17 +3612,6 @@ water(void *arg, int mark) {
DP(ISC_LOG_DEBUG(1),
"adb reached %s water mark", overmem ? "high" : "low");
-
- /*
- * We can't use adb->lock as there is potential for water
- * to be called when adb->lock is held.
- */
- LOCK(&adb->overmemlock);
- if (adb->overmem != overmem) {
- adb->overmem = overmem;
- isc_mem_waterack(adb->mctx, mark);
- }
- UNLOCK(&adb->overmemlock);
}
void
diff --git a/lib/dns/api b/lib/dns/api
index e9df7db..b1adf784 100644
--- a/lib/dns/api
+++ b/lib/dns/api
@@ -1,3 +1,3 @@
-LIBINTERFACE = 56
-LIBREVISION = 1
-LIBAGE = 1
+LIBINTERFACE = 57
+LIBREVISION = 0
+LIBAGE = 2
diff --git a/lib/dns/include/dns/diff.h b/lib/dns/include/dns/diff.h
index a13b678..32886c5 100644
--- a/lib/dns/include/dns/diff.h
+++ b/lib/dns/include/dns/diff.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: diff.h,v 1.15.120.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: diff.h,v 1.15.120.2.24.2 2010/06/04 23:49:23 tbox Exp $ */
#ifndef DNS_DIFF_H
#define DNS_DIFF_H 1
@@ -70,7 +70,7 @@ typedef enum {
DNS_DIFFOP_DEL = 1, /*%< Delete an RR. */
DNS_DIFFOP_EXISTS = 2, /*%< Assert RR existence. */
DNS_DIFFOP_ADDRESIGN = 4, /*%< ADD + RESIGN. */
- DNS_DIFFOP_DELRESIGN = 5, /*%< DEL + RESIGN. */
+ DNS_DIFFOP_DELRESIGN = 5 /*%< DEL + RESIGN. */
} dns_diffop_t;
typedef struct dns_difftuple dns_difftuple_t;
diff --git a/lib/dns/include/dns/ncache.h b/lib/dns/include/dns/ncache.h
index 0677211..00f22a7 100644
--- a/lib/dns/include/dns/ncache.h
+++ b/lib/dns/include/dns/ncache.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ncache.h,v 1.25.48.2 2009/12/30 23:47:31 tbox Exp $ */
+/* $Id: ncache.h,v 1.25.48.2.10.2 2010/05/14 23:48:44 tbox Exp $ */
#ifndef DNS_NCACHE_H
#define DNS_NCACHE_H 1
@@ -161,6 +161,13 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
*
*/
+isc_result_t
+dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
+ dns_rdatatype_t covers, dns_rdataset_t *rdataset);
+/*%<
+ * Similar to dns_ncache_getrdataset() but get the rrsig that matches.
+ */
+
void
dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
dns_rdataset_t *rdataset);
diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h
index d435ed0..8104b50 100644
--- a/lib/dns/include/dns/rdataset.h
+++ b/lib/dns/include/dns/rdataset.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdataset.h,v 1.65.50.2.22.2 2010/02/25 10:57:12 tbox Exp $ */
+/* $Id: rdataset.h,v 1.65.50.2.24.1 2010/03/03 22:06:39 marka Exp $ */
#ifndef DNS_RDATASET_H
#define DNS_RDATASET_H 1
diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h
index 8c7ad72..537bf0f 100644
--- a/lib/dns/include/dns/resolver.h
+++ b/lib/dns/include/dns/resolver.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.h,v 1.60.56.3.22.2 2010/02/25 10:57:12 tbox Exp $ */
+/* $Id: resolver.h,v 1.60.56.3.24.1 2010/03/03 22:06:39 marka Exp $ */
#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1
diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h
index a1e7f53..fae43e3 100644
--- a/lib/dns/include/dns/result.h
+++ b/lib/dns/include/dns/result.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: result.h,v 1.116.226.2 2010/02/25 10:57:12 tbox Exp $ */
+/* $Id: result.h,v 1.116.228.1 2010/03/03 22:06:39 marka Exp $ */
#ifndef DNS_RESULT_H
#define DNS_RESULT_H 1
diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h
index 10ce229..3fe8378 100644
--- a/lib/dns/include/dns/types.h
+++ b/lib/dns/include/dns/types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-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: types.h,v 1.130.50.5 2009/12/30 08:34:30 jinmei Exp $ */
+/* $Id: types.h,v 1.130.50.5.10.2 2010/05/14 23:48:44 tbox Exp $ */
#ifndef DNS_TYPES_H
#define DNS_TYPES_H 1
@@ -304,6 +304,7 @@ enum {
#define DNS_TRUST_ADDITIONAL(x) ((x) == dns_trust_additional || \
(x) == dns_trust_pending_additional)
#define DNS_TRUST_GLUE(x) ((x) == dns_trust_glue)
+#define DNS_TRUST_ANSWER(x) ((x) == dns_trust_answer)
/*%
diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h
index 1da4e0c..1f9ec74 100644
--- a/lib/dns/include/dns/validator.h
+++ b/lib/dns/include/dns/validator.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.h,v 1.41.48.3.22.2 2010/02/25 10:57:12 tbox Exp $ */
+/* $Id: validator.h,v 1.41.48.3.24.1 2010/03/03 22:06:39 marka Exp $ */
#ifndef DNS_VALIDATOR_H
#define DNS_VALIDATOR_H 1
diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c
index 733d138..a194084 100644
--- a/lib/dns/ncache.c
+++ b/lib/dns/ncache.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ncache.c,v 1.43.334.2 2010/02/25 10:57:11 tbox Exp $ */
+/* $Id: ncache.c,v 1.43.336.5 2010/05/19 09:56:44 marka Exp $ */
/*! \file */
@@ -40,6 +40,7 @@
*
* owner name
* type
+ * trust
* rdata count
* rdata length These two occur 'rdata count'
* rdata times.
@@ -189,6 +190,8 @@ dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
return (ISC_R_NOSPACE);
isc_buffer_putuint16(&buffer,
rdataset->type);
+ isc_buffer_putuint8(&buffer,
+ (unsigned char)rdataset->trust);
/*
* Copy the rdataset into the buffer.
*/
@@ -245,10 +248,9 @@ dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
* Copy the type and a zero rdata count to the buffer.
*/
isc_buffer_availableregion(&buffer, &r);
- if (r.length < 4)
+ if (r.length < 5)
return (ISC_R_NOSPACE);
- isc_buffer_putuint16(&buffer, 0);
- isc_buffer_putuint16(&buffer, 0);
+ isc_buffer_putuint16(&buffer, 0); /* type */
/*
* RFC2308, section 5, says that negative answers without
* SOAs should not be cached.
@@ -266,6 +268,9 @@ dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
trust = dns_trust_authauthority;
} else
trust = dns_trust_additional;
+ isc_buffer_putuint8(&buffer, (unsigned char)trust); /* trust */
+ isc_buffer_putuint16(&buffer, 0); /* count */
+
/*
* Now add it to the cache.
*/
@@ -335,8 +340,9 @@ dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
isc_buffer_forward(&source, name.length);
remaining.length -= name.length;
- INSIST(remaining.length >= 4);
+ INSIST(remaining.length >= 5);
type = isc_buffer_getuint16(&source);
+ isc_buffer_forward(&source, 1);
rcount = isc_buffer_getuint16(&source);
for (i = 0; i < rcount; i++) {
@@ -506,6 +512,13 @@ rdataset_count(dns_rdataset_t *rdataset) {
return (count);
}
+static void
+rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
+ unsigned char *raw = rdataset->private3;
+
+ raw[-1] = (unsigned char)trust;
+}
+
static dns_rdatasetmethods_t rdataset_methods = {
rdataset_disassociate,
rdataset_first,
@@ -520,7 +533,7 @@ static dns_rdatasetmethods_t rdataset_methods = {
NULL,
NULL,
NULL,
- NULL,
+ rdataset_settrust,
NULL
};
@@ -534,6 +547,8 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
isc_buffer_t source;
dns_name_t tname;
dns_rdatatype_t ttype;
+ dns_trust_t trust = dns_trust_none;
+ dns_rdataset_t clone;
REQUIRE(ncacherdataset != NULL);
REQUIRE(ncacherdataset->type == 0);
@@ -541,9 +556,11 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
REQUIRE(!dns_rdataset_isassociated(rdataset));
REQUIRE(type != dns_rdatatype_rrsig);
- result = dns_rdataset_first(ncacherdataset);
+ dns_rdataset_init(&clone);
+ dns_rdataset_clone(ncacherdataset, &clone);
+ result = dns_rdataset_first(&clone);
while (result == ISC_R_SUCCESS) {
- dns_rdataset_current(ncacherdataset, &rdata);
+ dns_rdataset_current(&clone, &rdata);
isc_buffer_init(&source, rdata.data, rdata.length);
isc_buffer_add(&source, rdata.length);
dns_name_init(&tname, NULL);
@@ -553,16 +570,19 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
isc_buffer_forward(&source, tname.length);
remaining.length -= tname.length;
- INSIST(remaining.length >= 4);
+ INSIST(remaining.length >= 3);
ttype = isc_buffer_getuint16(&source);
if (ttype == type && dns_name_equal(&tname, name)) {
+ trust = isc_buffer_getuint8(&source);
+ INSIST(trust <= dns_trust_ultimate);
isc_buffer_remainingregion(&source, &remaining);
break;
}
- result = dns_rdataset_next(ncacherdataset);
+ result = dns_rdataset_next(&clone);
dns_rdata_reset(&rdata);
}
+ dns_rdataset_disassociate(&clone);
if (result == ISC_R_NOMORE)
return (ISC_R_NOTFOUND);
if (result != ISC_R_SUCCESS)
@@ -575,7 +595,108 @@ dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
rdataset->type = type;
rdataset->covers = 0;
rdataset->ttl = ncacherdataset->ttl;
- rdataset->trust = ncacherdataset->trust;
+ rdataset->trust = trust;
+ rdataset->private1 = NULL;
+ rdataset->private2 = NULL;
+
+ rdataset->private3 = remaining.base;
+
+ /*
+ * Reset iterator state.
+ */
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+ rdataset->private6 = NULL;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
+ dns_rdatatype_t covers, dns_rdataset_t *rdataset)
+{
+ dns_name_t tname;
+ dns_rdata_rrsig_t rrsig;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t clone;
+ dns_rdatatype_t type;
+ dns_trust_t trust = dns_trust_none;
+ isc_buffer_t source;
+ isc_region_t remaining, sigregion;
+ isc_result_t result;
+ unsigned char *raw;
+ unsigned int count;
+
+ REQUIRE(ncacherdataset != NULL);
+ REQUIRE(ncacherdataset->type == 0);
+ REQUIRE(name != NULL);
+ REQUIRE(!dns_rdataset_isassociated(rdataset));
+
+ dns_rdataset_init(&clone);
+ dns_rdataset_clone(ncacherdataset, &clone);
+ result = dns_rdataset_first(&clone);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&clone, &rdata);
+ isc_buffer_init(&source, rdata.data, rdata.length);
+ isc_buffer_add(&source, rdata.length);
+ dns_name_init(&tname, NULL);
+ isc_buffer_remainingregion(&source, &remaining);
+ dns_name_fromregion(&tname, &remaining);
+ INSIST(remaining.length >= tname.length);
+ isc_buffer_forward(&source, tname.length);
+ remaining.length -= tname.length;
+ remaining.base += tname.length;
+
+ INSIST(remaining.length >= 2);
+ type = isc_buffer_getuint16(&source);
+ remaining.length -= 2;
+ remaining.base += 2;
+
+ if (type != dns_rdatatype_rrsig ||
+ !dns_name_equal(&tname, name)) {
+ result = dns_rdataset_next(&clone);
+ dns_rdata_reset(&rdata);
+ continue;
+ }
+
+ INSIST(remaining.length >= 1);
+ trust = isc_buffer_getuint8(&source);
+ INSIST(trust <= dns_trust_ultimate);
+ remaining.length -= 1;
+ remaining.base += 1;
+
+ raw = remaining.base;
+ count = raw[0] * 256 + raw[1];
+ INSIST(count > 0);
+ raw += 2;
+ sigregion.length = raw[0] * 256 + raw[1];
+ raw += 2;
+ sigregion.base = raw;
+ dns_rdata_reset(&rdata);
+ dns_rdata_fromregion(&rdata, rdataset->rdclass,
+ dns_rdatatype_rrsig, &sigregion);
+ (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
+ if (rrsig.covered == covers) {
+ isc_buffer_remainingregion(&source, &remaining);
+ break;
+ }
+
+ result = dns_rdataset_next(&clone);
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&clone);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_NOTFOUND);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ INSIST(remaining.length != 0);
+
+ rdataset->methods = &rdataset_methods;
+ rdataset->rdclass = ncacherdataset->rdclass;
+ rdataset->type = dns_rdatatype_rrsig;
+ rdataset->covers = covers;
+ rdataset->ttl = ncacherdataset->ttl;
+ rdataset->trust = trust;
rdataset->private1 = NULL;
rdataset->private2 = NULL;
@@ -595,6 +716,7 @@ dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
dns_rdataset_t *rdataset)
{
dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_trust_t trust;
isc_region_t remaining, sigregion;
isc_buffer_t source;
dns_name_t tname;
@@ -619,8 +741,10 @@ dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
isc_buffer_forward(&source, found->length);
remaining.length -= found->length;
- INSIST(remaining.length >= 4);
+ INSIST(remaining.length >= 5);
type = isc_buffer_getuint16(&source);
+ trust = isc_buffer_getuint8(&source);
+ INSIST(trust <= dns_trust_ultimate);
isc_buffer_remainingregion(&source, &remaining);
rdataset->methods = &rdataset_methods;
@@ -645,7 +769,7 @@ dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
} else
rdataset->covers = 0;
rdataset->ttl = ncacherdataset->ttl;
- rdataset->trust = ncacherdataset->trust;
+ rdataset->trust = trust;
rdataset->private1 = NULL;
rdataset->private2 = NULL;
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index df3a5f4..538c228 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbtdb.c,v 1.270.12.16.8.3 2010/02/26 00:24:39 marka Exp $ */
+/* $Id: rbtdb.c,v 1.270.12.16.10.3 2010/08/13 07:25:21 marka Exp $ */
/*! \file */
@@ -411,7 +411,6 @@ typedef struct {
rbtdb_version_t * current_version;
rbtdb_version_t * future_version;
rbtdb_versionlist_t open_versions;
- isc_boolean_t overmem;
isc_task_t * task;
dns_dbnode_t *soanode;
dns_dbnode_t *nsnode;
@@ -3209,6 +3208,9 @@ matchparams(rdatasetheader_t *header, rbtdb_search_t *search)
return (ISC_FALSE);
}
+/*
+ * Find node of the NSEC/NSEC3 record that is 'name'.
+ */
static inline isc_result_t
find_closest_nsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
dns_name_t *foundname, dns_rdataset_t *rdataset,
@@ -4928,7 +4930,7 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
if (now == 0)
isc_stdtime_get(&now);
- if (rbtdb->overmem) {
+ if (isc_mem_isovermem(rbtdb->common.mctx)) {
isc_uint32_t val;
isc_random_get(&val);
@@ -4938,8 +4940,8 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
force_expire = ISC_TF(rbtnode->down == NULL && val % 4 == 0);
/*
- * Note that 'log' can be true IFF rbtdb->overmem is also true.
- * rbtdb->overmem can currently only be true for cache
+ * Note that 'log' can be true IFF overmem is also true.
+ * overmem can currently only be true for cache
* databases -- hence all of the "overmem cache" log strings.
*/
log = ISC_TF(isc_log_wouldlog(dns_lctx, level));
@@ -4984,7 +4986,7 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
"reprieve by RETAIN() %s",
printname);
}
- } else if (rbtdb->overmem && log)
+ } else if (isc_mem_isovermem(rbtdb->common.mctx) && log)
isc_log_write(dns_lctx, category, module, level,
"overmem cache: saved %s", printname);
@@ -4996,10 +4998,12 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
static void
overmem(dns_db_t *db, isc_boolean_t overmem) {
- dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ /* This is an empty callback. See adb.c:water() */
- if (IS_CACHE(rbtdb))
- rbtdb->overmem = overmem;
+ UNUSED(db);
+ UNUSED(overmem);
+
+ return;
}
static void
@@ -5943,6 +5947,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
isc_result_t result;
isc_boolean_t delegating;
isc_boolean_t tree_locked = ISC_FALSE;
+ isc_boolean_t cache_is_overmem = ISC_FALSE;
REQUIRE(VALID_RBTDB(rbtdb));
@@ -6030,12 +6035,14 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
* the lock does not necessarily have to be acquired but it will help
* purge stale entries more effectively.
*/
- if (delegating || (IS_CACHE(rbtdb) && rbtdb->overmem)) {
+ if (IS_CACHE(rbtdb) && isc_mem_isovermem(rbtdb->common.mctx))
+ cache_is_overmem = ISC_TRUE;
+ if (delegating || cache_is_overmem) {
tree_locked = ISC_TRUE;
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
}
- if (IS_CACHE(rbtdb) && rbtdb->overmem)
+ if (cache_is_overmem)
overmem_purge(rbtdb, rbtnode->locknum, now, tree_locked);
NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
@@ -7098,7 +7105,6 @@ dns_rbtdb_create
return (result);
}
rbtdb->attributes = 0;
- rbtdb->overmem = ISC_FALSE;
rbtdb->task = NULL;
/*
diff --git a/lib/dns/rdatalist.c b/lib/dns/rdatalist.c
index d072619..97cef94 100644
--- a/lib/dns/rdatalist.c
+++ b/lib/dns/rdatalist.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdatalist.c,v 1.36.336.2 2010/02/25 10:57:12 tbox Exp $ */
+/* $Id: rdatalist.c,v 1.36.338.1 2010/03/03 22:06:39 marka Exp $ */
/*! \file */
diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c
index 946ec9a..4361913 100644
--- a/lib/dns/rdataset.c
+++ b/lib/dns/rdataset.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdataset.c,v 1.82.50.2.22.2 2010/02/25 10:57:12 tbox Exp $ */
+/* $Id: rdataset.c,v 1.82.50.2.24.1 2010/03/03 22:06:39 marka Exp $ */
/*! \file */
diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c
index 4eadff9..8d12eb8 100644
--- a/lib/dns/rdataslab.c
+++ b/lib/dns/rdataslab.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdataslab.c,v 1.48.50.2.22.2 2010/02/25 10:57:12 tbox Exp $ */
+/* $Id: rdataslab.c,v 1.48.50.2.24.1 2010/03/03 22:06:39 marka Exp $ */
/*! \file */
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index 244718f..8803a05 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.c,v 1.384.14.20.8.2 2010/02/25 10:57:12 tbox Exp $ */
+/* $Id: resolver.c,v 1.384.14.20.10.3 2010/06/23 23:46:25 tbox Exp $ */
/*! \file */
@@ -5815,13 +5815,40 @@ answer_response(fetchctx_t *fctx) {
return (result);
}
+static isc_boolean_t
+fctx_decreference(fetchctx_t *fctx) {
+ isc_boolean_t bucket_empty = ISC_FALSE;
+
+ INSIST(fctx->references > 0);
+ fctx->references--;
+ if (fctx->references == 0) {
+ /*
+ * No one cares about the result of this fetch anymore.
+ */
+ if (fctx->pending == 0 && fctx->nqueries == 0 &&
+ ISC_LIST_EMPTY(fctx->validators) && SHUTTINGDOWN(fctx)) {
+ /*
+ * This fctx is already shutdown; we were just
+ * waiting for the last reference to go away.
+ */
+ bucket_empty = fctx_destroy(fctx);
+ } else {
+ /*
+ * Initiate shutdown.
+ */
+ fctx_shutdown(fctx);
+ }
+ }
+ return (bucket_empty);
+}
+
static void
resume_dslookup(isc_task_t *task, isc_event_t *event) {
dns_fetchevent_t *fevent;
dns_resolver_t *res;
fetchctx_t *fctx;
isc_result_t result;
- isc_boolean_t bucket_empty = ISC_FALSE;
+ isc_boolean_t bucket_empty;
isc_boolean_t locked = ISC_FALSE;
unsigned int bucketnum;
dns_rdataset_t nameservers;
@@ -5925,9 +5952,7 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
isc_event_free(&event);
if (!locked)
LOCK(&res->buckets[bucketnum].lock);
- fctx->references--;
- if (fctx->references == 0)
- bucket_empty = fctx_destroy(fctx);
+ bucket_empty = fctx_decreference(fctx);
UNLOCK(&res->buckets[bucketnum].lock);
if (bucket_empty)
empty_bucket(res);
@@ -6752,12 +6777,14 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
&fctx->nsfetch);
if (result != ISC_R_SUCCESS)
fctx_done(fctx, result, __LINE__);
- LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
- fctx->references++;
- UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
- result = fctx_stopidletimer(fctx);
- if (result != ISC_R_SUCCESS)
- fctx_done(fctx, result, __LINE__);
+ else {
+ LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+ fctx->references++;
+ UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+ result = fctx_stopidletimer(fctx);
+ if (result != ISC_R_SUCCESS)
+ fctx_done(fctx, result, __LINE__);
+ }
} else {
/*
* We're done.
@@ -7602,7 +7629,7 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
dns_fetchevent_t *event, *next_event;
fetchctx_t *fctx;
unsigned int bucketnum;
- isc_boolean_t bucket_empty = ISC_FALSE;
+ isc_boolean_t bucket_empty;
REQUIRE(fetchp != NULL);
fetch = *fetchp;
@@ -7630,27 +7657,7 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
}
}
- INSIST(fctx->references > 0);
- fctx->references--;
- if (fctx->references == 0) {
- /*
- * No one cares about the result of this fetch anymore.
- */
- if (fctx->pending == 0 && fctx->nqueries == 0 &&
- ISC_LIST_EMPTY(fctx->validators) &&
- SHUTTINGDOWN(fctx)) {
- /*
- * This fctx is already shutdown; we were just
- * waiting for the last reference to go away.
- */
- bucket_empty = fctx_destroy(fctx);
- } else {
- /*
- * Initiate shutdown.
- */
- fctx_shutdown(fctx);
- }
- }
+ bucket_empty = fctx_decreference(fctx);
UNLOCK(&res->buckets[bucketnum].lock);
diff --git a/lib/dns/result.c b/lib/dns/result.c
index e336197..f241ded 100644
--- a/lib/dns/result.c
+++ b/lib/dns/result.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: result.c,v 1.125.122.2 2010/02/25 10:57:12 tbox Exp $ */
+/* $Id: result.c,v 1.125.124.1 2010/03/03 22:06:39 marka Exp $ */
/*! \file */
diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c
index e0c8786..6ec6209 100644
--- a/lib/dns/sdb.c
+++ b/lib/dns/sdb.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sdb.c,v 1.66.48.3.8.2 2010/02/25 10:57:12 tbox Exp $ */
+/* $Id: sdb.c,v 1.66.48.3.10.1 2010/03/03 22:06:39 marka Exp $ */
/*! \file */
diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c
index caf71b5..f2f7786 100644
--- a/lib/dns/sdlz.c
+++ b/lib/dns/sdlz.c
@@ -50,7 +50,7 @@
* USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sdlz.c,v 1.18.50.3.8.2 2010/02/25 10:57:12 tbox Exp $ */
+/* $Id: sdlz.c,v 1.18.50.3.10.1 2010/03/03 22:06:39 marka Exp $ */
/*! \file */
diff --git a/lib/dns/validator.c b/lib/dns/validator.c
index 7144ae2..90c18bc 100644
--- a/lib/dns/validator.c
+++ b/lib/dns/validator.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.c,v 1.164.12.11.8.3 2010/04/21 04:29:01 marka Exp $ */
+/* $Id: validator.c,v 1.164.12.11.10.6 2010/09/03 02:55:18 marka Exp $ */
#include <config.h>
@@ -120,6 +120,11 @@
#define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
#define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
#define DLVTRIED(val) ((val->attributes & VALATTR_DLVTRIED) != 0)
+#define FOUNDNODATA(val) ((val->attributes & VALATTR_FOUNDNODATA) != 0)
+#define FOUNDNOQNAME(val) ((val->attributes & VALATTR_FOUNDNOQNAME) != 0)
+#define FOUNDNOWILDCARD(val) ((val->attributes & VALATTR_FOUNDNOWILDCARD) != 0)
+#define FOUNDCLOSEST(val) ((val->attributes & VALATTR_FOUNDCLOSEST) != 0)
+#define FOUNDOPTOUT(val) ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
#define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
#define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0)
@@ -174,8 +179,8 @@ startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure);
* Mark the RRsets as a answer.
*/
static inline void
-markanswer(dns_validator_t *val) {
- validator_log(val, ISC_LOG_DEBUG(3), "marking as answer");
+markanswer(dns_validator_t *val, const char *where) {
+ validator_log(val, ISC_LOG_DEBUG(3), "marking as answer (%s)", where);
if (val->event->rdataset != NULL)
dns_rdataset_settrust(val->event->rdataset, dns_trust_answer);
if (val->event->sigrdataset != NULL)
@@ -186,7 +191,8 @@ markanswer(dns_validator_t *val) {
static inline void
marksecure(dns_validatorevent_t *event) {
dns_rdataset_settrust(event->rdataset, dns_trust_secure);
- dns_rdataset_settrust(event->sigrdataset, dns_trust_secure);
+ if (event->sigrdataset != NULL)
+ dns_rdataset_settrust(event->sigrdataset, dns_trust_secure);
}
static void
@@ -563,7 +569,7 @@ dsfetched2(isc_task_t *task, isc_event_t *event) {
"must be secure failure");
validator_done(val, DNS_R_MUSTBESECURE);
} else if (val->view->dlv == NULL || DLVTRIED(val)) {
- markanswer(val);
+ markanswer(val, "dsfetched2");
validator_done(val, ISC_R_SUCCESS);
} else {
result = startfinddlvsep(val, tname);
@@ -689,11 +695,32 @@ dsvalidated(isc_task_t *task, isc_event_t *event) {
if (CANCELED(val)) {
validator_done(val, ISC_R_CANCELED);
} else if (eresult == ISC_R_SUCCESS) {
+ isc_boolean_t have_dsset;
+ dns_name_t *name;
validator_log(val, ISC_LOG_DEBUG(3),
- "dsset with trust %d", val->frdataset.trust);
- if ((val->attributes & VALATTR_INSECURITY) != 0)
- result = proveunsecure(val, ISC_TRUE, ISC_TRUE);
- else
+ "%s with trust %d",
+ val->frdataset.type == dns_rdatatype_ds ?
+ "dsset" : "ds non-existance",
+ val->frdataset.trust);
+ have_dsset = ISC_TF(val->frdataset.type == dns_rdatatype_ds);
+ name = dns_fixedname_name(&val->fname);
+ if ((val->attributes & VALATTR_INSECURITY) != 0 &&
+ val->frdataset.covers == dns_rdatatype_ds &&
+ val->frdataset.type == 0 &&
+ isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET)) {
+ if (val->mustbesecure) {
+ validator_log(val, ISC_LOG_WARNING,
+ "must be secure failure, no DS "
+ "and this is a delegation");
+ result = DNS_R_MUSTBESECURE;
+ } else if (val->view->dlv == NULL || DLVTRIED(val)) {
+ markanswer(val, "dsvalidated");
+ result = ISC_R_SUCCESS;;
+ } else
+ result = startfinddlvsep(val, name);
+ } else if ((val->attributes & VALATTR_INSECURITY) != 0) {
+ result = proveunsecure(val, have_dsset, ISC_TRUE);
+ } else
result = validatezonekey(val);
if (result != DNS_R_WAIT)
validator_done(val, result);
@@ -1138,29 +1165,7 @@ nsec3noexistnodata(dns_validator_t *val, dns_name_t* name,
dns_name_copy(qname, nearest, NULL);
*setnearest = ISC_TRUE;
}
-#if 0
- /*
- * The closest encloser may be the zone name.
- */
- if (closest != NULL &&
- dns_name_countlabels(closest) == 0 &&
- !dns_nsec3_typepresent(&rdata, dns_rdatatype_ds) &&
- !dns_nsec3_typepresent(&rdata, dns_rdatatype_dname) &&
- (dns_nsec3_typepresent(&rdata, dns_rdatatype_soa) ||
- !dns_nsec3_typepresent(&rdata, dns_rdatatype_ns)))
- {
- char namebuf[DNS_NAME_FORMATSIZE];
- dns_name_format(zone, namebuf,
- sizeof(namebuf));
- validator_log(val, ISC_LOG_DEBUG(3),
- "NSEC3 potential closest "
- "encloser from zone name: '%s'",
- namebuf);
- dns_name_copy(zone, closest, NULL);
- *setclosest = ISC_TRUE;
- }
-#endif
*exists = ISC_FALSE;
*data = ISC_FALSE;
if (optout != NULL) {
@@ -1236,10 +1241,8 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
if (rdataset->type == dns_rdatatype_nsec &&
rdataset->trust == dns_trust_secure &&
- ((val->attributes & VALATTR_NEEDNODATA) != 0 ||
- (val->attributes & VALATTR_NEEDNOQNAME) != 0) &&
- (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
- (val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
+ (NEEDNODATA(val) || NEEDNOQNAME(val)) &&
+ !FOUNDNODATA(val) && !FOUNDNOQNAME(val) &&
nsecnoexistnodata(val, val->event->name, devent->name,
rdataset, &exists, &data, wild)
== ISC_R_SUCCESS)
@@ -1643,11 +1646,14 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
* We have an rrset for the given keyname.
*/
val->keyset = &val->frdataset;
- if (DNS_TRUST_PENDING(val->frdataset.trust) &&
+ if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
+ DNS_TRUST_ANSWER(val->frdataset.trust)) &&
dns_rdataset_isassociated(&val->fsigrdataset))
{
/*
- * We know the key but haven't validated it yet.
+ * We know the key but haven't validated it yet or
+ * we have a key of trust answer but a DS/DLV
+ * record for the zone may have been added.
*/
result = create_validator(val, &siginfo->signer,
dns_rdatatype_dnskey,
@@ -1890,7 +1896,7 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
"must be secure failure");
return (DNS_R_MUSTBESECURE);
}
- markanswer(val);
+ markanswer(val, "validate");
return (ISC_R_SUCCESS);
}
@@ -1947,7 +1953,7 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
}
}
val->key = NULL;
- if ((val->attributes & VALATTR_NEEDNOQNAME) != 0) {
+ if (NEEDNOQNAME(val)) {
if (val->event->message == NULL) {
validator_log(val, ISC_LOG_DEBUG(3),
"no message available for noqname proof");
@@ -2144,7 +2150,7 @@ dlv_validatezonekey(dns_validator_t *val) {
}
validator_log(val, ISC_LOG_DEBUG(3),
"no supported algorithm/digest (dlv)");
- markanswer(val);
+ markanswer(val, "dlv_validatezonekey (2)");
return (ISC_R_SUCCESS);
} else
return (DNS_R_NOVALIDSIG);
@@ -2197,8 +2203,12 @@ validatezonekey(dns_validator_t *val) {
result == ISC_R_SUCCESS;
result = dns_rdataset_next(val->event->sigrdataset))
{
- dns_keynode_t *keynode = NULL, *nextnode = NULL;
+ dns_keynode_t *keynode = NULL;
+ dns_fixedname_t fixed;
+ dns_name_t *found;
+ dns_fixedname_init(&fixed);
+ found = dns_fixedname_name(&fixed);
dns_rdata_reset(&sigrdata);
dns_rdataset_current(val->event->sigrdataset,
&sigrdata);
@@ -2213,10 +2223,28 @@ validatezonekey(dns_validator_t *val) {
sig.algorithm,
sig.keyid,
&keynode);
+ if (result == ISC_R_NOTFOUND &&
+ dns_keytable_finddeepestmatch(val->keytable,
+ val->event->name, found) != ISC_R_SUCCESS) {
+ if (val->mustbesecure) {
+ validator_log(val, ISC_LOG_WARNING,
+ "must be secure failure, "
+ "not beneath secure root");
+ return (DNS_R_MUSTBESECURE);
+ } else
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "not beneath secure root");
+ if (val->view->dlv == NULL || DLVTRIED(val)) {
+ markanswer(val, "validatezonekey (1)");
+ return (ISC_R_SUCCESS);
+ }
+ return (startfinddlvsep(val, dns_rootname));
+ }
if (result == DNS_R_PARTIALMATCH ||
result == ISC_R_SUCCESS)
atsep = ISC_TRUE;
while (result == ISC_R_SUCCESS) {
+ dns_keynode_t *nextnode = NULL;
dstkey = dns_keynode_key(keynode);
result = verify(val, dstkey, &sigrdata,
sig.keyid);
@@ -2281,7 +2309,8 @@ validatezonekey(dns_validator_t *val) {
* We have DS records.
*/
val->dsset = &val->frdataset;
- if (DNS_TRUST_PENDING(val->frdataset.trust) &&
+ if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
+ DNS_TRUST_ANSWER(val->frdataset.trust)) &&
dns_rdataset_isassociated(&val->fsigrdataset))
{
result = create_validator(val,
@@ -2344,7 +2373,7 @@ validatezonekey(dns_validator_t *val) {
"must be secure failure");
return (DNS_R_MUSTBESECURE);
}
- markanswer(val);
+ markanswer(val, "validatezonekey (2)");
return (ISC_R_SUCCESS);
}
@@ -2490,7 +2519,7 @@ validatezonekey(dns_validator_t *val) {
}
validator_log(val, ISC_LOG_DEBUG(3),
"no supported algorithm/digest (DS)");
- markanswer(val);
+ markanswer(val, "validatezonekey (3)");
return (ISC_R_SUCCESS);
} else
return (DNS_R_NOVALIDSIG);
@@ -2517,6 +2546,80 @@ start_positive_validation(dns_validator_t *val) {
}
/*%
+ * val_rdataset_first and val_rdataset_next provide iteration methods
+ * that hide whether we are iterating across a message or a negative
+ * cache rdataset.
+ */
+static isc_result_t
+val_rdataset_first(dns_validator_t *val, dns_name_t **namep,
+ dns_rdataset_t **rdatasetp)
+{
+ dns_message_t *message = val->event->message;
+ isc_result_t result;
+
+ REQUIRE(rdatasetp != NULL);
+ REQUIRE(namep != NULL);
+ if (message == NULL) {
+ REQUIRE(*rdatasetp != NULL);
+ REQUIRE(*namep != NULL);
+ } else {
+ REQUIRE(*rdatasetp == NULL);
+ REQUIRE(*namep == NULL);
+ }
+
+ if (message != NULL) {
+ result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep);
+ *rdatasetp = ISC_LIST_HEAD((*namep)->list);
+ INSIST(*rdatasetp != NULL);
+ } else {
+ result = dns_rdataset_first(val->event->rdataset);
+ if (result == ISC_R_SUCCESS)
+ dns_ncache_current(val->event->rdataset, *namep,
+ *rdatasetp);
+ }
+ return (result);
+}
+
+static isc_result_t
+val_rdataset_next(dns_validator_t *val, dns_name_t **namep,
+ dns_rdataset_t **rdatasetp)
+{
+ dns_message_t *message = val->event->message;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(rdatasetp != NULL && *rdatasetp != NULL);
+ REQUIRE(namep != NULL && *namep != NULL);
+
+ if (message != NULL) {
+ dns_rdataset_t *rdataset = *rdatasetp;
+ rdataset = ISC_LIST_NEXT(rdataset, link);
+ if (rdataset == NULL) {
+ *namep = NULL;
+ result = dns_message_nextname(message,
+ DNS_SECTION_AUTHORITY);
+ if (result == ISC_R_SUCCESS) {
+ dns_message_currentname(message,
+ DNS_SECTION_AUTHORITY,
+ namep);
+ rdataset = ISC_LIST_HEAD((*namep)->list);
+ INSIST(rdataset != NULL);
+ }
+ }
+ *rdatasetp = rdataset;
+ } else {
+ dns_rdataset_disassociate(*rdatasetp);
+ result = dns_rdataset_next(val->event->rdataset);
+ if (result == ISC_R_SUCCESS)
+ dns_ncache_current(val->event->rdataset, *namep,
+ *rdatasetp);
+ }
+ return (result);
+}
+
+/*%
* Look for NODATA at the wildcard and NOWILDCARD proofs in the
* previously validated NSEC records. As these proofs are mutually
* exclusive we stop when one is found.
@@ -2527,12 +2630,14 @@ start_positive_validation(dns_validator_t *val) {
static isc_result_t
checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
{
- dns_name_t *name, *wild;
- dns_message_t *message = val->event->message;
+ dns_name_t *name, *wild, tname;
isc_result_t result;
isc_boolean_t exists, data;
char namebuf[DNS_NAME_FORMATSIZE];
+ dns_rdataset_t *rdataset, trdataset;
+ dns_name_init(&tname, NULL);
+ dns_rdataset_init(&trdataset);
wild = dns_fixedname_name(&val->wild);
if (dns_name_countlabels(wild) == 0) {
@@ -2544,103 +2649,91 @@ checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
dns_name_format(wild, namebuf, sizeof(namebuf));
validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
- for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ if (val->event->message == NULL) {
+ name = &tname;
+ rdataset = &trdataset;
+ } else {
+ name = NULL;
+ rdataset = NULL;
+ }
+
+ for (result = val_rdataset_first(val, &name, &rdataset);
result == ISC_R_SUCCESS;
- result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
+ result = val_rdataset_next(val, &name, &rdataset))
{
- dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
-
- name = NULL;
- dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
+ if (rdataset->type != type ||
+ rdataset->trust != dns_trust_secure)
+ continue;
- for (rdataset = ISC_LIST_HEAD(name->list);
- rdataset != NULL;
- rdataset = ISC_LIST_NEXT(rdataset, link))
+ if (rdataset->type == dns_rdatatype_nsec &&
+ (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
+ !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
+ nsecnoexistnodata(val, wild, name, rdataset,
+ &exists, &data, NULL)
+ == ISC_R_SUCCESS)
{
- if (rdataset->type != type)
- continue;
-
- for (sigrdataset = ISC_LIST_HEAD(name->list);
- sigrdataset != NULL;
- sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
- {
- if (sigrdataset->type == dns_rdatatype_rrsig &&
- sigrdataset->covers == rdataset->type)
- break;
- }
- if (sigrdataset == NULL)
- continue;
-
- if (rdataset->trust != dns_trust_secure)
- continue;
-
- if (rdataset->type == dns_rdatatype_nsec &&
- ((val->attributes & VALATTR_NEEDNODATA) != 0 ||
- (val->attributes & VALATTR_NEEDNOWILDCARD) != 0) &&
- (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
- (val->attributes & VALATTR_FOUNDNOWILDCARD) == 0 &&
- nsecnoexistnodata(val, wild, name, rdataset,
- &exists, &data, NULL)
- == ISC_R_SUCCESS)
- {
- dns_name_t **proofs = val->event->proofs;
- if (exists && !data)
- val->attributes |= VALATTR_FOUNDNODATA;
- if (exists && !data && NEEDNODATA(val))
- proofs[DNS_VALIDATOR_NODATAPROOF] =
- name;
- if (!exists)
- val->attributes |=
- VALATTR_FOUNDNOWILDCARD;
- if (!exists && NEEDNOQNAME(val))
- proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
- name;
- return (ISC_R_SUCCESS);
- }
+ dns_name_t **proofs = val->event->proofs;
+ if (exists && !data)
+ val->attributes |= VALATTR_FOUNDNODATA;
+ if (exists && !data && NEEDNODATA(val))
+ proofs[DNS_VALIDATOR_NODATAPROOF] =
+ name;
+ if (!exists)
+ val->attributes |=
+ VALATTR_FOUNDNOWILDCARD;
+ if (!exists && NEEDNOQNAME(val))
+ proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
+ name;
+ if (dns_rdataset_isassociated(&trdataset))
+ dns_rdataset_disassociate(&trdataset);
+ return (ISC_R_SUCCESS);
+ }
- if (rdataset->type == dns_rdatatype_nsec3 &&
- ((val->attributes & VALATTR_NEEDNODATA) != 0 ||
- (val->attributes & VALATTR_NEEDNOWILDCARD) != 0) &&
- (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
- (val->attributes & VALATTR_FOUNDNOWILDCARD) == 0 &&
- nsec3noexistnodata(val, wild, name, rdataset,
- zonename, &exists, &data,
- NULL, NULL, NULL, NULL, NULL,
- NULL) == ISC_R_SUCCESS)
- {
- dns_name_t **proofs = val->event->proofs;
- if (exists && !data)
- val->attributes |= VALATTR_FOUNDNODATA;
- if (exists && !data && NEEDNODATA(val))
- proofs[DNS_VALIDATOR_NODATAPROOF] =
- name;
- if (!exists)
- val->attributes |=
- VALATTR_FOUNDNOWILDCARD;
- if (!exists && NEEDNOQNAME(val))
- proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
- name;
- return (ISC_R_SUCCESS);
- }
+ if (rdataset->type == dns_rdatatype_nsec3 &&
+ (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
+ !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
+ nsec3noexistnodata(val, wild, name, rdataset,
+ zonename, &exists, &data,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL) == ISC_R_SUCCESS)
+ {
+ dns_name_t **proofs = val->event->proofs;
+ if (exists && !data)
+ val->attributes |= VALATTR_FOUNDNODATA;
+ if (exists && !data && NEEDNODATA(val))
+ proofs[DNS_VALIDATOR_NODATAPROOF] =
+ name;
+ if (!exists)
+ val->attributes |=
+ VALATTR_FOUNDNOWILDCARD;
+ if (!exists && NEEDNOQNAME(val))
+ proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
+ name;
+ if (dns_rdataset_isassociated(&trdataset))
+ dns_rdataset_disassociate(&trdataset);
+ return (ISC_R_SUCCESS);
}
}
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
+ if (dns_rdataset_isassociated(&trdataset))
+ dns_rdataset_disassociate(&trdataset);
return (result);
}
-
static isc_result_t
findnsec3proofs(dns_validator_t *val) {
- dns_name_t *name;
- dns_message_t *message = val->event->message;
+ dns_name_t *name, tname;
isc_result_t result;
isc_boolean_t exists, data, optout, unknown;
isc_boolean_t setclosest, setnearest;
dns_fixedname_t fclosest, fnearest, fzonename;
dns_name_t *closest, *nearest, *zonename;
dns_name_t **proofs = val->event->proofs;
+ dns_rdataset_t *rdataset, trdataset;
+ dns_name_init(&tname, NULL);
+ dns_rdataset_init(&trdataset);
dns_fixedname_init(&fclosest);
dns_fixedname_init(&fnearest);
dns_fixedname_init(&fzonename);
@@ -2648,43 +2741,31 @@ findnsec3proofs(dns_validator_t *val) {
nearest = dns_fixedname_name(&fnearest);
zonename = dns_fixedname_name(&fzonename);
- for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
- result == ISC_R_SUCCESS;
- result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
- {
- dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
-
+ if (val->event->message == NULL) {
+ name = &tname;
+ rdataset = &trdataset;
+ } else {
name = NULL;
- dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
-
- for (rdataset = ISC_LIST_HEAD(name->list);
- rdataset != NULL;
- rdataset = ISC_LIST_NEXT(rdataset, link))
- {
- if (rdataset->type != dns_rdatatype_nsec3)
- continue;
-
- for (sigrdataset = ISC_LIST_HEAD(name->list);
- sigrdataset != NULL;
- sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
- {
- if (sigrdataset->type == dns_rdatatype_rrsig &&
- sigrdataset->covers == dns_rdatatype_nsec3)
- break;
- }
- if (sigrdataset == NULL)
- continue;
+ rdataset = NULL;
+ }
- if (rdataset->trust != dns_trust_secure)
- continue;
+ for (result = val_rdataset_first(val, &name, &rdataset);
+ result == ISC_R_SUCCESS;
+ result = val_rdataset_next(val, &name, &rdataset))
+ {
+ if (rdataset->type != dns_rdatatype_nsec3 ||
+ rdataset->trust != dns_trust_secure)
+ continue;
- result = nsec3noexistnodata(val, val->event->name,
- name, rdataset,
- zonename, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL);
- if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS)
- return (result);
+ result = nsec3noexistnodata(val, val->event->name,
+ name, rdataset,
+ zonename, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL);
+ if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
+ if (dns_rdataset_isassociated(&trdataset))
+ dns_rdataset_disassociate(&trdataset);
+ return (result);
}
}
if (result != ISC_R_NOMORE)
@@ -2693,68 +2774,43 @@ findnsec3proofs(dns_validator_t *val) {
if (dns_name_countlabels(zonename) == 0)
return (ISC_R_SUCCESS);
- for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ for (result = val_rdataset_first(val, &name, &rdataset);
result == ISC_R_SUCCESS;
- result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
+ result = val_rdataset_next(val, &name, &rdataset))
{
- dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
-
- name = NULL;
- dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
-
- for (rdataset = ISC_LIST_HEAD(name->list);
- rdataset != NULL;
- rdataset = ISC_LIST_NEXT(rdataset, link))
- {
- if (rdataset->type != dns_rdatatype_nsec3)
- continue;
-
- for (sigrdataset = ISC_LIST_HEAD(name->list);
- sigrdataset != NULL;
- sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
- {
- if (sigrdataset->type == dns_rdatatype_rrsig &&
- sigrdataset->covers == dns_rdatatype_nsec3)
- break;
- }
- if (sigrdataset == NULL)
- continue;
-
- if (rdataset->trust != dns_trust_secure)
- continue;
+ if (rdataset->type != dns_rdatatype_nsec3 ||
+ rdataset->trust != dns_trust_secure)
+ continue;
- /*
- * We process all NSEC3 records to find the closest
- * encloser and nearest name to the closest encloser.
- */
- setclosest = setnearest = ISC_FALSE;
- optout = ISC_FALSE;
- unknown = ISC_FALSE;
- result = nsec3noexistnodata(val, val->event->name,
- name, rdataset,
- zonename, &exists,
- &data, &optout, &unknown,
- &setclosest, &setnearest,
- closest, nearest);
- if (setclosest)
- proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
- if (unknown)
- val->attributes |= VALATTR_FOUNDUNKNOWN;
- if (result != ISC_R_SUCCESS)
- continue;
- if (exists && !data && NEEDNODATA(val)) {
- val->attributes |= VALATTR_FOUNDNODATA;
- proofs[DNS_VALIDATOR_NODATAPROOF] = name;
- }
- if (!exists && setnearest) {
- val->attributes |= VALATTR_FOUNDNOQNAME;
- proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
- if (optout)
- val->attributes |= VALATTR_FOUNDOPTOUT;
- }
+ /*
+ * We process all NSEC3 records to find the closest
+ * encloser and nearest name to the closest encloser.
+ */
+ setclosest = setnearest = ISC_FALSE;
+ optout = ISC_FALSE;
+ unknown = ISC_FALSE;
+ (void)nsec3noexistnodata(val, val->event->name, name, rdataset,
+ zonename, &exists, &data, &optout,
+ &unknown, &setclosest, &setnearest,
+ closest, nearest);
+ if (setclosest)
+ proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
+ if (unknown)
+ val->attributes |= VALATTR_FOUNDUNKNOWN;
+ if (result != ISC_R_SUCCESS)
+ continue;
+ if (exists && !data && NEEDNODATA(val)) {
+ val->attributes |= VALATTR_FOUNDNODATA;
+ proofs[DNS_VALIDATOR_NODATAPROOF] = name;
+ }
+ if (!exists && setnearest) {
+ val->attributes |= VALATTR_FOUNDNOQNAME;
+ proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
+ if (optout)
+ val->attributes |= VALATTR_FOUNDOPTOUT;
}
}
- if (result != ISC_R_NOMORE)
+ if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
/*
@@ -2781,11 +2837,8 @@ findnsec3proofs(dns_validator_t *val) {
/*
* Do we need to check for the wildcard?
*/
- if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
- (val->attributes & VALATTR_FOUNDCLOSEST) != 0 &&
- (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
- (val->attributes & VALATTR_FOUNDNODATA) == 0) ||
- (val->attributes & VALATTR_NEEDNOWILDCARD) != 0)) {
+ if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
+ ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
if (result != ISC_R_SUCCESS)
return (result);
@@ -2794,29 +2847,18 @@ findnsec3proofs(dns_validator_t *val) {
}
/*%
- * Prove a negative answer is good or that there is a NOQNAME when the
- * answer is from a wildcard.
- *
- * Loop through the authority section looking for NODATA, NOWILDCARD
- * and NOQNAME proofs in the NSEC records by calling authvalidated().
- *
- * If the required proofs are found we are done.
- *
- * If the proofs are not found attempt to prove this is a unsecure
- * response.
+ * Validate the authority section records.
*/
static isc_result_t
-nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
+validate_authority(dns_validator_t *val, isc_boolean_t resume) {
dns_name_t *name;
dns_message_t *message = val->event->message;
isc_result_t result;
if (!resume)
result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
- else {
+ else
result = ISC_R_SUCCESS;
- validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
- }
for (;
result == ISC_R_SUCCESS;
@@ -2879,16 +2921,121 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
result = create_validator(val, name, rdataset->type,
rdataset, sigrdataset,
authvalidated,
- "nsecvalidate");
+ "validate_authority");
if (result != ISC_R_SUCCESS)
return (result);
val->authcount++;
return (DNS_R_WAIT);
+ }
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ return (result);
+}
+/*%
+ * Validate the ncache elements.
+ */
+static isc_result_t
+validate_ncache(dns_validator_t *val, isc_boolean_t resume) {
+ dns_name_t *name;
+ isc_result_t result;
+
+ if (!resume)
+ result = dns_rdataset_first(val->event->rdataset);
+ else
+ result = dns_rdataset_next(val->event->rdataset);
+
+ for (;
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(val->event->rdataset))
+ {
+ dns_rdataset_t *rdataset, *sigrdataset = NULL;
+
+ if (dns_rdataset_isassociated(&val->frdataset))
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+
+ dns_fixedname_init(&val->fname);
+ name = dns_fixedname_name(&val->fname);
+ rdataset = &val->frdataset;
+ dns_ncache_current(val->event->rdataset, name, rdataset);
+
+ if (val->frdataset.type == dns_rdatatype_rrsig)
+ continue;
+
+ result = dns_ncache_getsigrdataset(val->event->rdataset, name,
+ rdataset->type,
+ &val->fsigrdataset);
+ if (result == ISC_R_SUCCESS)
+ sigrdataset = &val->fsigrdataset;
+
+ /*
+ * If a signed zone is missing the zone key, bad
+ * things could happen. A query for data in the zone
+ * would lead to a query for the zone key, which
+ * would return a negative answer, which would contain
+ * an SOA and an NSEC signed by the missing key, which
+ * would trigger another query for the DNSKEY (since
+ * the first one is still in progress), and go into an
+ * infinite loop. Avoid that.
+ */
+ if (val->event->type == dns_rdatatype_dnskey &&
+ dns_name_equal(name, val->event->name))
+ {
+ dns_rdata_t nsec = DNS_RDATA_INIT;
+
+ if (rdataset->type != dns_rdatatype_nsec)
+ continue;
+
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdataset_current(rdataset, &nsec);
+ if (dns_nsec_typepresent(&nsec,
+ dns_rdatatype_soa))
+ continue;
}
+ val->currentset = rdataset;
+ result = create_validator(val, name, rdataset->type,
+ rdataset, sigrdataset,
+ authvalidated,
+ "validate_ncache");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ val->authcount++;
+ return (DNS_R_WAIT);
}
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
+ return (result);
+}
+
+/*%
+ * Prove a negative answer is good or that there is a NOQNAME when the
+ * answer is from a wildcard.
+ *
+ * Loop through the authority section looking for NODATA, NOWILDCARD
+ * and NOQNAME proofs in the NSEC records by calling authvalidated().
+ *
+ * If the required proofs are found we are done.
+ *
+ * If the proofs are not found attempt to prove this is a unsecure
+ * response.
+ */
+static isc_result_t
+nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
+ isc_result_t result;
+
+ if (resume)
+ validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
+
+ if (val->event->message == NULL)
+ result = validate_ncache(val, resume);
+ else
+ result = validate_authority(val, resume);
+
if (result != ISC_R_SUCCESS)
return (result);
@@ -2896,31 +3043,28 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
* Do we only need to check for NOQNAME? To get here we must have
* had a secure wildcard answer.
*/
- if ((val->attributes & VALATTR_NEEDNODATA) == 0 &&
- (val->attributes & VALATTR_NEEDNOWILDCARD) == 0 &&
- (val->attributes & VALATTR_NEEDNOQNAME) != 0) {
- if ((val->attributes & VALATTR_FOUNDNOQNAME) == 0)
+ if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
+ if (!FOUNDNOQNAME(val))
findnsec3proofs(val);
- if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
- (val->attributes & VALATTR_FOUNDCLOSEST) != 0) {
+ if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val)) {
validator_log(val, ISC_LOG_DEBUG(3),
"noqname proof found");
validator_log(val, ISC_LOG_DEBUG(3),
"marking as secure");
marksecure(val->event);
return (ISC_R_SUCCESS);
- } else if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0 &&
+ } else if (FOUNDOPTOUT(val) &&
dns_name_countlabels(dns_fixedname_name(&val->wild))
!= 0) {
validator_log(val, ISC_LOG_DEBUG(3),
"optout proof found");
val->event->optout = ISC_TRUE;
- markanswer(val);
+ markanswer(val, "nsecvalidate (1)");
return (ISC_R_SUCCESS);
} else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
validator_log(val, ISC_LOG_DEBUG(3),
"unknown NSEC3 hash algorithm found");
- markanswer(val);
+ markanswer(val, "nsecvalidate (2)");
return (ISC_R_SUCCESS);
}
validator_log(val, ISC_LOG_DEBUG(3),
@@ -2928,35 +3072,29 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
return (DNS_R_NOVALIDNSEC);
}
- if ((val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
- (val->attributes & VALATTR_FOUNDNODATA) == 0)
+ if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val))
findnsec3proofs(val);
/*
* Do we need to check for the wildcard?
*/
- if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
- (val->attributes & VALATTR_FOUNDCLOSEST) != 0 &&
- (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
- (val->attributes & VALATTR_FOUNDNODATA) == 0) ||
- (val->attributes & VALATTR_NEEDNOWILDCARD) != 0)) {
+ if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
+ ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) {
result = checkwildcard(val, dns_rdatatype_nsec, NULL);
if (result != ISC_R_SUCCESS)
return (result);
}
- if (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
- ((val->attributes & VALATTR_FOUNDNODATA) != 0 ||
- (val->attributes & VALATTR_FOUNDOPTOUT) != 0)) ||
- ((val->attributes & VALATTR_NEEDNOQNAME) != 0 &&
- (val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
- (val->attributes & VALATTR_NEEDNOWILDCARD) != 0 &&
- (val->attributes & VALATTR_FOUNDNOWILDCARD) != 0 &&
- (val->attributes & VALATTR_FOUNDCLOSEST) != 0)) {
+ if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) ||
+ (NEEDNOQNAME(val) && FOUNDNOQNAME(val) &&
+ NEEDNOWILDCARD(val) && FOUNDNOWILDCARD(val) &&
+ FOUNDCLOSEST(val))) {
if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
val->event->optout = ISC_TRUE;
validator_log(val, ISC_LOG_DEBUG(3),
"nonexistence proof(s) found");
+ if (val->event->message == NULL)
+ marksecure(val->event);
return (ISC_R_SUCCESS);
}
findnsec3proofs(val);
@@ -3025,7 +3163,7 @@ dlvvalidated(isc_task_t *task, isc_event_t *event) {
if (dlv_algorithm_supported(val))
dlv_validator_start(val);
else {
- markanswer(val);
+ markanswer(val, "dlvvalidated");
validator_done(val, ISC_R_SUCCESS);
}
} else {
@@ -3094,7 +3232,7 @@ dlvfetched(isc_task_t *task, isc_event_t *event) {
validator_log(val, ISC_LOG_DEBUG(3),
"DLV %s found with no supported algorithms",
namebuf);
- markanswer(val);
+ markanswer(val, "dlvfetched (1)");
validator_done(val, ISC_R_SUCCESS);
}
} else if (eresult == DNS_R_NXRRSET ||
@@ -3113,12 +3251,12 @@ dlvfetched(isc_task_t *task, isc_event_t *event) {
validator_log(val, ISC_LOG_DEBUG(3),
"DLV %s found with no supported "
"algorithms", namebuf);
- markanswer(val);
+ markanswer(val, "dlvfetched (2)");
validator_done(val, ISC_R_SUCCESS);
}
} else if (result == ISC_R_NOTFOUND) {
validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
- markanswer(val);
+ markanswer(val, "dlvfetched (3)");
validator_done(val, ISC_R_SUCCESS);
} else {
validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
@@ -3168,7 +3306,7 @@ startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
result = finddlvsep(val, ISC_FALSE);
if (result == ISC_R_NOTFOUND) {
validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
- markanswer(val);
+ markanswer(val, "startfinddlvsep (1)");
return (ISC_R_SUCCESS);
}
if (result != ISC_R_SUCCESS) {
@@ -3185,7 +3323,7 @@ startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
}
validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
"algorithms", namebuf);
- markanswer(val);
+ markanswer(val, "startfinddlvsep (2)");
validator_done(val, ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
}
@@ -3374,7 +3512,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
goto out;
}
if (val->view->dlv == NULL || DLVTRIED(val)) {
- markanswer(val);
+ markanswer(val, "proveunsecure (1)");
return (ISC_R_SUCCESS);
}
return (startfinddlvsep(val, dns_rootname));
@@ -3412,7 +3550,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
"no supported algorithm/digest (%s/DS)",
namebuf);
if (val->view->dlv == NULL || DLVTRIED(val)) {
- markanswer(val);
+ markanswer(val, "proveunsecure (2)");
result = ISC_R_SUCCESS;
goto out;
}
@@ -3442,18 +3580,23 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
namebuf);
result = view_find(val, tname, dns_rdatatype_ds);
-
if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
/*
* There is no DS. If this is a delegation,
* we maybe done.
*/
- if (DNS_TRUST_PENDING(val->frdataset.trust)) {
- result = create_fetch(val, tname,
- dns_rdatatype_ds,
- dsfetched2,
- "proveunsecure");
- if (result != ISC_R_SUCCESS)
+ /*
+ * If we have "trust == answer" then this namespace
+ * has switched from insecure to should be secure.
+ */
+ if (DNS_TRUST_PENDING(val->frdataset.trust) ||
+ DNS_TRUST_ANSWER(val->frdataset.trust)) {
+ result = create_validator(val, tname,
+ dns_rdatatype_ds,
+ &val->frdataset,
+ NULL, dsvalidated,
+ "proveunsecure");
+ if (result != ISC_R_SUCCESS)
goto out;
return (DNS_R_WAIT);
}
@@ -3474,7 +3617,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
return (DNS_R_MUSTBESECURE);
}
if (val->view->dlv == NULL || DLVTRIED(val)) {
- markanswer(val);
+ markanswer(val, "proveunsecure (3)");
return (ISC_R_SUCCESS);
}
return (startfinddlvsep(val, tname));
@@ -3496,7 +3639,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
return (DNS_R_MUSTBESECURE);
}
if (val->view->dlv == NULL || DLVTRIED(val)) {
- markanswer(val);
+ markanswer(val, "proveunsecure (4)");
return (ISC_R_SUCCESS);
}
return (startfinddlvsep(val, tname));
@@ -3521,7 +3664,8 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
}
if (val->view->dlv == NULL ||
DLVTRIED(val)) {
- markanswer(val);
+ markanswer(val,
+ "proveunsecure (5)");
result = ISC_R_SUCCESS;
goto out;
}
@@ -3535,6 +3679,9 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
result = DNS_R_NOVALIDSIG;
goto out;
}
+ /*
+ * Validate / re-validate answer.
+ */
result = create_validator(val, tname, dns_rdatatype_ds,
&val->frdataset,
&val->fsigrdataset,
@@ -3580,14 +3727,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
return (result);
}
-/*
- if ((val->attributes & VALATTR_NEEDOPTOUT) == 0 &&
- val->event->message != NULL) {
- val->attributes |= VALATTR_NEEDOPTOUT;
- return (nsecvalidate(val, ISC_FALSE));
- }
-*/
-
+ /* Couldn't complete insecurity proof */
validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */
@@ -3682,7 +3822,8 @@ validator_start(isc_task_t *task, isc_event_t *event) {
if (result == DNS_R_NOTINSECURE)
result = saved_result;
}
- } else if (val->event->rdataset != NULL) {
+ } else if (val->event->rdataset != NULL &&
+ val->event->rdataset->type != 0) {
/*
* This is either an unsecure subdomain or a response from
* a broken server.
@@ -3708,6 +3849,21 @@ validator_start(isc_task_t *task, isc_event_t *event) {
} else
val->attributes |= VALATTR_NEEDNODATA;
result = nsecvalidate(val, ISC_FALSE);
+ } else if (val->event->rdataset != NULL &&
+ val->event->rdataset->type == 0)
+ {
+ /*
+ * This is a nonexistence validation.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "attempting negative response validation");
+
+ if (val->event->rdataset->covers == dns_rdatatype_any) {
+ val->attributes |= VALATTR_NEEDNOQNAME;
+ val->attributes |= VALATTR_NEEDNOWILDCARD;
+ } else
+ val->attributes |= VALATTR_NEEDNODATA;
+ result = nsecvalidate(val, ISC_FALSE);
} else {
/*
* This shouldn't happen.
diff --git a/lib/dns/view.c b/lib/dns/view.c
index 72163b4..3726eef 100644
--- a/lib/dns/view.c
+++ b/lib/dns/view.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: view.c,v 1.150.84.3.8.2 2010/02/25 10:57:12 tbox Exp $ */
+/* $Id: view.c,v 1.150.84.3.10.1 2010/03/03 22:06:39 marka Exp $ */
/*! \file */
OpenPOWER on IntegriCloud