2852. [bug] Handle broken DNSSEC trust chains better. [RT #15619]
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
2852. [bug] Handle broken DNSSEC trust chains better. [RT #15619]
|
||||
|
||||
2851. [doc] nslookup.1, removed <informalexample> from the docbook
|
||||
source as it produced bad nroff. [RT #21007]
|
||||
|
||||
|
||||
+3
-1
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: server.c,v 1.556.8.6 2010/01/13 23:48:19 tbox Exp $ */
|
||||
/* $Id: server.c,v 1.556.8.7 2010/02/25 05:05:07 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -5528,6 +5528,8 @@ dumpdone(void *arg, isc_result_t result) {
|
||||
}
|
||||
if (dctx->cache != NULL) {
|
||||
dns_adb_dump(dctx->view->view->adb, dctx->fp);
|
||||
dns_resolver_printbadcache(dctx->view->view->resolver,
|
||||
dctx->fp);
|
||||
dns_db_detach(&dctx->cache);
|
||||
}
|
||||
if (dctx->dumpzones) {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
- PERFORMANCE OF THIS SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.450.4.5 2010/02/03 01:32:43 each Exp $ -->
|
||||
<!-- File: $Id: Bv9ARM-book.xml,v 1.450.4.6 2010/02/25 05:05:07 marka Exp $ -->
|
||||
<book xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<title>BIND 9 Administrator Reference Manual</title>
|
||||
|
||||
@@ -8176,6 +8176,13 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
|
||||
<literal>1800</literal> (30 minutes).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Lame-ttl also controls the amount of time DNSSEC
|
||||
validation failures are cached. There is a minimum
|
||||
of 30 seconds applied to bad cache entries if the
|
||||
lame-ttl is set to less than 30 seconds.
|
||||
</para>
|
||||
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
+13
-2
@@ -14,7 +14,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: ecdb.c,v 1.4 2009/11/06 04:19:28 marka Exp $ */
|
||||
/* $Id: ecdb.c,v 1.4.24.1 2010/02/25 05:05:08 marka Exp $ */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -99,6 +99,7 @@ static isc_result_t rdataset_next(dns_rdataset_t *rdataset);
|
||||
static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
|
||||
static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);
|
||||
static unsigned int rdataset_count(dns_rdataset_t *rdataset);
|
||||
static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
|
||||
|
||||
static dns_rdatasetmethods_t rdataset_methods = {
|
||||
rdataset_disassociate,
|
||||
@@ -113,7 +114,9 @@ static dns_rdatasetmethods_t rdataset_methods = {
|
||||
NULL, /* getclosest */
|
||||
NULL, /* getadditional */
|
||||
NULL, /* setadditional */
|
||||
NULL /* putadditional */
|
||||
NULL, /* putadditional */
|
||||
rdataset_settrust, /* settrust */
|
||||
NULL /* expire */
|
||||
};
|
||||
|
||||
typedef struct ecdb_rdatasetiter {
|
||||
@@ -736,6 +739,14 @@ rdataset_count(dns_rdataset_t *rdataset) {
|
||||
return (count);
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
|
||||
rdatasetheader_t *header = rdataset->private3;
|
||||
|
||||
header--;
|
||||
header->trust = rdataset->trust = trust;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rdataset Iterator Methods
|
||||
*/
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: rdataset.h,v 1.67 2009/01/17 23:47:43 tbox Exp $ */
|
||||
/* $Id: rdataset.h,v 1.67.186.1 2010/02/25 05:05:09 marka Exp $ */
|
||||
|
||||
#ifndef DNS_RDATASET_H
|
||||
#define DNS_RDATASET_H 1
|
||||
@@ -110,6 +110,9 @@ typedef struct dns_rdatasetmethods {
|
||||
dns_rdataset_t *rdataset,
|
||||
dns_rdatasetadditional_t type,
|
||||
dns_rdatatype_t qtype);
|
||||
void (*settrust)(dns_rdataset_t *rdataset,
|
||||
dns_trust_t trust);
|
||||
void (*expire)(dns_rdataset_t *rdataset);
|
||||
} dns_rdatasetmethods_t;
|
||||
|
||||
#define DNS_RDATASET_MAGIC ISC_MAGIC('D','N','S','R')
|
||||
@@ -634,6 +637,19 @@ dns_rdataset_putadditional(dns_acache_t *acache,
|
||||
* information for 'rdataset.'
|
||||
*/
|
||||
|
||||
void
|
||||
dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
|
||||
/*%<
|
||||
* Set the trust of the 'rdataset' to trust in any in the backing database.
|
||||
* The local trust level of 'rdataset' is also set.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_rdataset_expire(dns_rdataset_t *rdataset);
|
||||
/*%<
|
||||
* Mark the rdataset to be expired in the backing database.
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_RDATASET_H */
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: resolver.h,v 1.64 2009/09/01 00:22:26 jinmei Exp $ */
|
||||
/* $Id: resolver.h,v 1.64.104.1 2010/02/25 05:05:09 marka Exp $ */
|
||||
|
||||
#ifndef DNS_RESOLVER_H
|
||||
#define DNS_RESOLVER_H 1
|
||||
@@ -509,6 +509,48 @@ dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state);
|
||||
unsigned int
|
||||
dns_resolver_getoptions(dns_resolver_t *resolver);
|
||||
|
||||
void
|
||||
dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
|
||||
dns_rdatatype_t type, isc_time_t *expire);
|
||||
/*%<
|
||||
* Add a entry to the bad cache for <name,type> that will expire at 'expire'.
|
||||
*
|
||||
* Requires:
|
||||
* \li resolver to be valid.
|
||||
* \li name to be valid.
|
||||
*/
|
||||
|
||||
isc_boolean_t
|
||||
dns_resolver_getbadcache(dns_resolver_t *resolver, dns_name_t *name,
|
||||
dns_rdatatype_t type, isc_time_t *now);
|
||||
/*%<
|
||||
* Check to see if there is a unexpired entry in the bad cache for
|
||||
* <name,type>.
|
||||
*
|
||||
* Requires:
|
||||
* \li resolver to be valid.
|
||||
* \li name to be valid.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name);
|
||||
/*%<
|
||||
* Flush the bad cache of all entries at 'name' if 'name' is non NULL.
|
||||
* Flush the entire bad cache if 'name' is NULL.
|
||||
*
|
||||
* Requires:
|
||||
* \li resolver to be valid.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp);
|
||||
/*%
|
||||
* Print out the contents of the bad cache to 'fp'.
|
||||
*
|
||||
* Requires:
|
||||
* \li resolver to be valid.
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_RESOLVER_H */
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: result.h,v 1.118 2009/10/12 23:48:02 tbox Exp $ */
|
||||
/* $Id: result.h,v 1.118.50.1 2010/02/25 05:05:09 marka Exp $ */
|
||||
|
||||
#ifndef DNS_RESULT_H
|
||||
#define DNS_RESULT_H 1
|
||||
@@ -149,8 +149,9 @@
|
||||
#define DNS_R_DUPLICATE (ISC_RESULTCLASS_DNS + 103)
|
||||
#define DNS_R_INVALIDNSEC3 (ISC_RESULTCLASS_DNS + 104)
|
||||
#define DNS_R_NOTMASTER (ISC_RESULTCLASS_DNS + 105)
|
||||
#define DNS_R_BROKENCHAIN (ISC_RESULTCLASS_DNS + 106)
|
||||
|
||||
#define DNS_R_NRESULTS 106 /*%< Number of results */
|
||||
#define DNS_R_NRESULTS 107 /*%< Number of results */
|
||||
|
||||
/*
|
||||
* DNS wire format rcodes.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: validator.h,v 1.44 2009/01/17 13:20:45 fdupont Exp $ */
|
||||
/* $Id: validator.h,v 1.44.186.1 2010/02/25 05:05:09 marka Exp $ */
|
||||
|
||||
#ifndef DNS_VALIDATOR_H
|
||||
#define DNS_VALIDATOR_H 1
|
||||
@@ -159,6 +159,8 @@ struct dns_validator {
|
||||
isc_boolean_t mustbesecure;
|
||||
unsigned int dlvlabels;
|
||||
unsigned int depth;
|
||||
unsigned int authcount;
|
||||
unsigned int authfail;
|
||||
};
|
||||
|
||||
/*%
|
||||
|
||||
+3
-1
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: ncache.c,v 1.43 2008/09/25 04:02:38 tbox Exp $ */
|
||||
/* $Id: ncache.c,v 1.43.268.1 2010/02/25 05:05:08 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -519,6 +519,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
+28
-2
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: rbtdb.c,v 1.292.8.6 2010/01/04 23:48:10 tbox Exp $ */
|
||||
/* $Id: rbtdb.c,v 1.292.8.7 2010/02/25 05:05:08 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -522,6 +522,8 @@ static void overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
|
||||
static isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx,
|
||||
rdatasetheader_t *newheader);
|
||||
static void prune_tree(isc_task_t *task, isc_event_t *event);
|
||||
static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
|
||||
static void rdataset_expire(dns_rdataset_t *rdataset);
|
||||
|
||||
static dns_rdatasetmethods_t rdataset_methods = {
|
||||
rdataset_disassociate,
|
||||
@@ -536,7 +538,9 @@ static dns_rdatasetmethods_t rdataset_methods = {
|
||||
rdataset_getclosest,
|
||||
rdataset_getadditional,
|
||||
rdataset_setadditional,
|
||||
rdataset_putadditional
|
||||
rdataset_putadditional,
|
||||
rdataset_settrust,
|
||||
rdataset_expire
|
||||
};
|
||||
|
||||
static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
|
||||
@@ -7662,6 +7666,28 @@ rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
|
||||
rdatasetheader_t *header = rdataset->private3;
|
||||
|
||||
header--;
|
||||
header->trust = rdataset->trust = trust;
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_expire(dns_rdataset_t *rdataset) {
|
||||
dns_rbtdb_t *rbtdb = rdataset->private1;
|
||||
dns_rbtnode_t *rbtnode = rdataset->private2;
|
||||
rdatasetheader_t *header = rdataset->private3;
|
||||
|
||||
header--;
|
||||
NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
|
||||
isc_rwlocktype_write);
|
||||
expire_header(rbtdb, header, ISC_FALSE);
|
||||
NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
|
||||
isc_rwlocktype_write);
|
||||
}
|
||||
|
||||
/*
|
||||
* Rdataset Iterator Methods
|
||||
*/
|
||||
|
||||
+3
-1
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: rdatalist.c,v 1.36 2008/09/24 02:46:22 marka Exp $ */
|
||||
/* $Id: rdatalist.c,v 1.36.270.1 2010/02/25 05:05:08 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -46,6 +46,8 @@ static dns_rdatasetmethods_t methods = {
|
||||
isc__rdatalist_getclosest,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
+22
-1
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: rdataset.c,v 1.84 2009/01/17 23:47:43 tbox Exp $ */
|
||||
/* $Id: rdataset.c,v 1.84.186.1 2010/02/25 05:05:08 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -182,6 +182,8 @@ static dns_rdatasetmethods_t question_methods = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -732,3 +734,22 @@ dns_rdataset_putadditional(dns_acache_t *acache,
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
void
|
||||
dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
|
||||
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||
REQUIRE(rdataset->methods != NULL);
|
||||
|
||||
if (rdataset->methods->settrust != NULL)
|
||||
(rdataset->methods->settrust)(rdataset, trust);
|
||||
else
|
||||
rdataset->trust = trust;
|
||||
}
|
||||
|
||||
void
|
||||
dns_rdataset_expire(dns_rdataset_t *rdataset) {
|
||||
REQUIRE(DNS_RDATASET_VALID(rdataset));
|
||||
REQUIRE(rdataset->methods != NULL);
|
||||
|
||||
if (rdataset->methods->expire != NULL)
|
||||
(rdataset->methods->expire)(rdataset);
|
||||
}
|
||||
|
||||
+3
-1
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: rdataslab.c,v 1.50 2009/01/17 23:47:43 tbox Exp $ */
|
||||
/* $Id: rdataslab.c,v 1.50.186.1 2010/02/25 05:05:08 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -436,6 +436,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
+386
-31
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: resolver.c,v 1.413.14.2 2010/01/07 23:48:16 tbox Exp $ */
|
||||
/* $Id: resolver.c,v 1.413.14.3 2010/02/25 05:05:08 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -336,6 +336,18 @@ typedef struct alternate {
|
||||
ISC_LINK(struct alternate) link;
|
||||
} alternate_t;
|
||||
|
||||
typedef struct dns_badcache dns_badcache_t;
|
||||
struct dns_badcache {
|
||||
dns_badcache_t * next;
|
||||
dns_rdatatype_t type;
|
||||
isc_time_t expire;
|
||||
unsigned int hashval;
|
||||
dns_name_t name;
|
||||
};
|
||||
#define DNS_BADCACHE_SIZE 1021
|
||||
#define DNS_BADCACHE_TTL(fctx) \
|
||||
(((fctx)->res->lame_ttl > 30 ) ? (fctx)->res->lame_ttl : 30)
|
||||
|
||||
struct dns_resolver {
|
||||
/* Unlocked. */
|
||||
unsigned int magic;
|
||||
@@ -382,6 +394,13 @@ struct dns_resolver {
|
||||
isc_boolean_t priming;
|
||||
unsigned int spillat; /* clients-per-query */
|
||||
unsigned int nextdisp;
|
||||
|
||||
/* Bad cache. */
|
||||
dns_badcache_t ** badcache;
|
||||
unsigned int badcount;
|
||||
unsigned int badhash;
|
||||
unsigned int badsweep;
|
||||
|
||||
/* Locked by primelock. */
|
||||
dns_fetch_t * primefetch;
|
||||
/* Locked by nlock. */
|
||||
@@ -412,7 +431,8 @@ static void empty_bucket(dns_resolver_t *res);
|
||||
static isc_result_t resquery_send(resquery_t *query);
|
||||
static void resquery_response(isc_task_t *task, isc_event_t *event);
|
||||
static void resquery_connected(isc_task_t *task, isc_event_t *event);
|
||||
static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying);
|
||||
static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying,
|
||||
isc_boolean_t badcache);
|
||||
static isc_boolean_t fctx_destroy(fetchctx_t *fctx);
|
||||
static isc_result_t ncache_adderesult(dns_message_t *message,
|
||||
dns_db_t *cache, dns_dbnode_t *node,
|
||||
@@ -1172,7 +1192,7 @@ process_sendevent(resquery_t *query, isc_event_t *event) {
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fctx_done(fctx, result, __LINE__);
|
||||
else
|
||||
fctx_try(fctx, ISC_TRUE);
|
||||
fctx_try(fctx, ISC_TRUE, ISC_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2073,7 +2093,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fctx_done(fctx, result, __LINE__);
|
||||
else
|
||||
fctx_try(fctx, ISC_TRUE);
|
||||
fctx_try(fctx, ISC_TRUE, ISC_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2135,7 +2155,7 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
|
||||
dns_adb_destroyfind(&find);
|
||||
|
||||
if (want_try)
|
||||
fctx_try(fctx, ISC_TRUE);
|
||||
fctx_try(fctx, ISC_TRUE, ISC_FALSE);
|
||||
else if (want_done)
|
||||
fctx_done(fctx, ISC_R_FAILURE, __LINE__);
|
||||
else if (bucket_empty)
|
||||
@@ -2543,7 +2563,7 @@ isstrictsubdomain(dns_name_t *name1, dns_name_t *name2) {
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
fctx_getaddresses(fetchctx_t *fctx) {
|
||||
fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
isc_result_t result;
|
||||
dns_resolver_t *res;
|
||||
@@ -2762,12 +2782,24 @@ fctx_getaddresses(fetchctx_t *fctx) {
|
||||
*/
|
||||
result = DNS_R_WAIT;
|
||||
} else {
|
||||
isc_time_t expire;
|
||||
isc_interval_t i;
|
||||
/*
|
||||
* We've lost completely. We don't know any
|
||||
* addresses, and the ADB has told us it can't get
|
||||
* them.
|
||||
*/
|
||||
FCTXTRACE("no addresses");
|
||||
isc_interval_set(&i, DNS_BADCACHE_TTL(fctx), 0);
|
||||
result = isc_time_nowplusinterval(&expire, &i);
|
||||
if (badcache &&
|
||||
(fctx->type == dns_rdatatype_dnskey ||
|
||||
fctx->type == dns_rdatatype_dlv ||
|
||||
fctx->type == dns_rdatatype_ds) &&
|
||||
result == ISC_R_SUCCESS)
|
||||
dns_resolver_addbadcache(fctx->res,
|
||||
&fctx->name,
|
||||
fctx->type, &expire);
|
||||
result = ISC_R_FAILURE;
|
||||
}
|
||||
} else {
|
||||
@@ -2990,7 +3022,7 @@ fctx_nextaddress(fetchctx_t *fctx) {
|
||||
}
|
||||
|
||||
static void
|
||||
fctx_try(fetchctx_t *fctx, isc_boolean_t retrying) {
|
||||
fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
|
||||
isc_result_t result;
|
||||
dns_adbaddrinfo_t *addrinfo;
|
||||
|
||||
@@ -3008,7 +3040,7 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying) {
|
||||
fctx_cleanupaltfinds(fctx);
|
||||
fctx_cleanupforwaddrs(fctx);
|
||||
fctx_cleanupaltaddrs(fctx);
|
||||
result = fctx_getaddresses(fctx);
|
||||
result = fctx_getaddresses(fctx, badcache);
|
||||
if (result == DNS_R_WAIT) {
|
||||
/*
|
||||
* Sleep waiting for addresses.
|
||||
@@ -3173,7 +3205,7 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) {
|
||||
/*
|
||||
* Keep trying.
|
||||
*/
|
||||
fctx_try(fctx, ISC_TRUE);
|
||||
fctx_try(fctx, ISC_TRUE, ISC_FALSE);
|
||||
}
|
||||
|
||||
isc_event_free(&event);
|
||||
@@ -3343,7 +3375,7 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
|
||||
if (result != ISC_R_SUCCESS)
|
||||
fctx_done(fctx, result, __LINE__);
|
||||
else
|
||||
fctx_try(fctx, ISC_FALSE);
|
||||
fctx_try(fctx, ISC_FALSE, ISC_FALSE);
|
||||
} else if (bucket_empty)
|
||||
empty_bucket(res);
|
||||
}
|
||||
@@ -3965,6 +3997,8 @@ validated(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
|
||||
|
||||
isc_stdtime_get(&now);
|
||||
|
||||
/*
|
||||
* If chaining, we need to make sure that the right result code is
|
||||
* returned, and that the rdatasets are bound.
|
||||
@@ -4011,35 +4045,80 @@ validated(isc_task_t *task, isc_event_t *event) {
|
||||
inc_stats(fctx->res, dns_resstatscounter_valfail);
|
||||
fctx->valfail++;
|
||||
fctx->vresult = vevent->result;
|
||||
result = ISC_R_NOTFOUND;
|
||||
if (vevent->rdataset != NULL)
|
||||
result = dns_db_findnode(fctx->cache, vevent->name,
|
||||
ISC_TRUE, &node);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
(void)dns_db_deleterdataset(fctx->cache, node, NULL,
|
||||
vevent->type, 0);
|
||||
if (result == ISC_R_SUCCESS && vevent->sigrdataset != NULL)
|
||||
(void)dns_db_deleterdataset(fctx->cache, node, NULL,
|
||||
dns_rdatatype_rrsig,
|
||||
vevent->type);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
dns_db_detachnode(fctx->cache, &node);
|
||||
result = vevent->result;
|
||||
if (fctx->vresult != DNS_R_BROKENCHAIN) {
|
||||
result = ISC_R_NOTFOUND;
|
||||
if (vevent->rdataset != NULL)
|
||||
result = dns_db_findnode(fctx->cache,
|
||||
vevent->name,
|
||||
ISC_TRUE, &node);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
(void)dns_db_deleterdataset(fctx->cache, node,
|
||||
NULL,
|
||||
vevent->type, 0);
|
||||
if (result == ISC_R_SUCCESS &&
|
||||
vevent->sigrdataset != NULL)
|
||||
(void)dns_db_deleterdataset(fctx->cache, node,
|
||||
NULL,
|
||||
dns_rdatatype_rrsig,
|
||||
vevent->type);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
dns_db_detachnode(fctx->cache, &node);
|
||||
}
|
||||
if (fctx->vresult == DNS_R_BROKENCHAIN && !negative) {
|
||||
/*
|
||||
* Cache the data as pending for later validation.
|
||||
*/
|
||||
result = ISC_R_NOTFOUND;
|
||||
if (vevent->rdataset != NULL)
|
||||
result = dns_db_findnode(fctx->cache,
|
||||
vevent->name,
|
||||
ISC_TRUE, &node);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
(void)dns_db_addrdataset(fctx->cache, node,
|
||||
NULL, now,
|
||||
vevent->rdataset, 0,
|
||||
NULL);
|
||||
}
|
||||
if (result == ISC_R_SUCCESS &&
|
||||
vevent->sigrdataset != NULL)
|
||||
(void)dns_db_addrdataset(fctx->cache, node,
|
||||
NULL, now,
|
||||
vevent->sigrdataset,
|
||||
0, NULL);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
dns_db_detachnode(fctx->cache, &node);
|
||||
}
|
||||
result = fctx->vresult;
|
||||
add_bad(fctx, addrinfo, result, badns_validation);
|
||||
isc_event_free(&event);
|
||||
UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
|
||||
INSIST(fctx->validator == NULL);
|
||||
fctx->validator = ISC_LIST_HEAD(fctx->validators);
|
||||
if (fctx->validator != NULL) {
|
||||
if (fctx->validator != NULL)
|
||||
dns_validator_send(fctx->validator);
|
||||
} else if (sentresponse)
|
||||
else if (sentresponse)
|
||||
fctx_done(fctx, result, __LINE__); /* Locks bucket. */
|
||||
else
|
||||
fctx_try(fctx, ISC_TRUE); /* Locks bucket. */
|
||||
else if (result == DNS_R_BROKENCHAIN) {
|
||||
isc_result_t tresult;
|
||||
isc_time_t expire;
|
||||
isc_interval_t i;
|
||||
|
||||
isc_interval_set(&i, DNS_BADCACHE_TTL(fctx), 0);
|
||||
tresult = isc_time_nowplusinterval(&expire, &i);
|
||||
if (negative &&
|
||||
(fctx->type == dns_rdatatype_dnskey ||
|
||||
fctx->type == dns_rdatatype_dlv ||
|
||||
fctx->type == dns_rdatatype_ds) &&
|
||||
tresult == ISC_R_SUCCESS)
|
||||
dns_resolver_addbadcache(fctx->res,
|
||||
&fctx->name,
|
||||
fctx->type, &expire);
|
||||
fctx_done(fctx, result, __LINE__); /* Locks bucket. */
|
||||
} else
|
||||
fctx_try(fctx, ISC_TRUE, ISC_TRUE); /* Locks bucket. */
|
||||
return;
|
||||
}
|
||||
|
||||
isc_stdtime_get(&now);
|
||||
|
||||
if (negative) {
|
||||
dns_rdatatype_t covers;
|
||||
@@ -6102,7 +6181,7 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
|
||||
/*
|
||||
* Try again.
|
||||
*/
|
||||
fctx_try(fctx, ISC_TRUE);
|
||||
fctx_try(fctx, ISC_TRUE, ISC_FALSE);
|
||||
} else {
|
||||
unsigned int n;
|
||||
dns_rdataset_t *nsrdataset = NULL;
|
||||
@@ -6981,7 +7060,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
/*
|
||||
* Try again.
|
||||
*/
|
||||
fctx_try(fctx, !get_nameservers);
|
||||
fctx_try(fctx, !get_nameservers, ISC_FALSE);
|
||||
} else if (resend) {
|
||||
/*
|
||||
* Resend (probably with changed options).
|
||||
@@ -7043,6 +7122,27 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
||||
/***
|
||||
*** Resolver Methods
|
||||
***/
|
||||
static void
|
||||
destroy_badcache(dns_resolver_t *res) {
|
||||
dns_badcache_t *bad, *next;
|
||||
unsigned int i;
|
||||
|
||||
if (res->badcache != NULL) {
|
||||
for (i = 0; i < res->badhash; i++)
|
||||
for (bad = res->badcache[i]; bad != NULL;
|
||||
bad = next) {
|
||||
next = bad->next;
|
||||
isc_mem_put(res->mctx, bad, sizeof(*bad) +
|
||||
bad->name.length);
|
||||
res->badcount--;
|
||||
}
|
||||
isc_mem_put(res->mctx, res->badcache,
|
||||
sizeof(*res->badcache) * res->badhash);
|
||||
res->badcache = NULL;
|
||||
res->badhash = 0;
|
||||
INSIST(res->badcount == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy(dns_resolver_t *res) {
|
||||
@@ -7080,6 +7180,7 @@ destroy(dns_resolver_t *res) {
|
||||
isc_mem_put(res->mctx, a, sizeof(*a));
|
||||
}
|
||||
dns_resolver_reset_algorithms(res);
|
||||
destroy_badcache(res);
|
||||
dns_resolver_resetmustbesecure(res);
|
||||
#if USE_ALGLOCK
|
||||
isc_rwlock_destroy(&res->alglock);
|
||||
@@ -7203,6 +7304,10 @@ dns_resolver_create(dns_view_t *view,
|
||||
ISC_LIST_INIT(res->alternates);
|
||||
res->udpsize = RECV_BUFFER_SIZE;
|
||||
res->algorithms = NULL;
|
||||
res->badcache = NULL;
|
||||
res->badcount = 0;
|
||||
res->badhash = 0;
|
||||
res->badsweep = 0;
|
||||
res->mustbesecure = NULL;
|
||||
res->spillatmin = res->spillat = 10;
|
||||
res->spillatmax = 100;
|
||||
@@ -8046,6 +8151,256 @@ dns_resolver_getudpsize(dns_resolver_t *resolver) {
|
||||
return (resolver->udpsize);
|
||||
}
|
||||
|
||||
void
|
||||
dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name) {
|
||||
unsigned int i;
|
||||
dns_badcache_t *bad, *prev, *next;
|
||||
|
||||
REQUIRE(VALID_RESOLVER(resolver));
|
||||
|
||||
LOCK(&resolver->lock);
|
||||
if (resolver->badcache == NULL)
|
||||
goto unlock;
|
||||
|
||||
if (name != NULL) {
|
||||
isc_time_t now;
|
||||
isc_result_t result;
|
||||
result = isc_time_now(&now);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
isc_time_settoepoch(&now);
|
||||
i = dns_name_hash(name, ISC_FALSE) % resolver->badhash;
|
||||
prev = NULL;
|
||||
for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
|
||||
int n;
|
||||
next = bad->next;
|
||||
n = isc_time_compare(&bad->expire, &now);
|
||||
if (n < 0 || dns_name_equal(name, &bad->name)) {
|
||||
if (prev == NULL)
|
||||
resolver->badcache[i] = bad->next;
|
||||
else
|
||||
prev->next = bad->next;
|
||||
isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
|
||||
bad->name.length);
|
||||
resolver->badcount--;
|
||||
} else
|
||||
prev = bad;
|
||||
}
|
||||
} else
|
||||
destroy_badcache(resolver);
|
||||
|
||||
unlock:
|
||||
UNLOCK(&resolver->lock);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
resizehash(dns_resolver_t *resolver, isc_time_t *now, isc_boolean_t grow) {
|
||||
unsigned int newsize;
|
||||
dns_badcache_t **new, *bad, *next;
|
||||
unsigned int i;
|
||||
|
||||
if (grow)
|
||||
newsize = resolver->badhash * 2 + 1;
|
||||
else
|
||||
newsize = (resolver->badhash - 1) / 2;
|
||||
|
||||
new = isc_mem_get(resolver->mctx,
|
||||
sizeof(*resolver->badcache) * newsize);
|
||||
if (new == NULL)
|
||||
return;
|
||||
memset(new, 0, sizeof(*resolver->badcache) * newsize);
|
||||
for (i = 0; i < resolver->badhash; i++) {
|
||||
for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
|
||||
next = bad->next;
|
||||
if (isc_time_compare(&bad->expire, now) < 0) {
|
||||
isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
|
||||
bad->name.length);
|
||||
resolver->badcount--;
|
||||
} else {
|
||||
bad->next = new[bad->hashval % newsize];
|
||||
new[bad->hashval % newsize] = bad;
|
||||
}
|
||||
}
|
||||
}
|
||||
isc_mem_put(resolver->mctx, resolver->badcache,
|
||||
sizeof(*resolver->badcache) * resolver->badhash);
|
||||
resolver->badhash = newsize;
|
||||
resolver->badcache = new;
|
||||
}
|
||||
|
||||
void
|
||||
dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
|
||||
dns_rdatatype_t type, isc_time_t *expire)
|
||||
{
|
||||
isc_time_t now;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
unsigned int i, hashval;
|
||||
dns_badcache_t *bad, *prev, *next;
|
||||
|
||||
REQUIRE(VALID_RESOLVER(resolver));
|
||||
|
||||
LOCK(&resolver->lock);
|
||||
if (resolver->badcache == NULL) {
|
||||
resolver->badcache = isc_mem_get(resolver->mctx,
|
||||
sizeof(*resolver->badcache) *
|
||||
DNS_BADCACHE_SIZE);
|
||||
if (resolver->badcache == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
resolver->badhash = DNS_BADCACHE_SIZE;
|
||||
memset(resolver->badcache, 0, sizeof(*resolver->badcache) *
|
||||
resolver->badhash);
|
||||
}
|
||||
|
||||
result = isc_time_now(&now);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
isc_time_settoepoch(&now);
|
||||
hashval = dns_name_hash(name, ISC_FALSE);
|
||||
i = hashval % resolver->badhash;
|
||||
prev = NULL;
|
||||
for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
|
||||
next = bad->next;
|
||||
if (bad->type == type && dns_name_equal(name, &bad->name))
|
||||
break;
|
||||
if (isc_time_compare(&bad->expire, &now) < 0) {
|
||||
if (prev == NULL)
|
||||
resolver->badcache[i] = bad->next;
|
||||
else
|
||||
prev->next = bad->next;
|
||||
isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
|
||||
bad->name.length);
|
||||
resolver->badcount--;
|
||||
} else
|
||||
prev = bad;
|
||||
}
|
||||
if (bad == NULL) {
|
||||
isc_buffer_t buffer;
|
||||
bad = isc_mem_get(resolver->mctx, sizeof(*bad) + name->length);
|
||||
if (bad == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
bad->type = type;
|
||||
bad->hashval = hashval;
|
||||
isc_buffer_init(&buffer, bad + 1, name->length);
|
||||
dns_name_init(&bad->name, NULL);
|
||||
dns_name_copy(name, &bad->name, &buffer);
|
||||
bad->next = resolver->badcache[i];
|
||||
resolver->badcache[i] = bad;
|
||||
resolver->badcount++;
|
||||
if (resolver->badcount > resolver->badhash * 8)
|
||||
resizehash(resolver, &now, ISC_TRUE);
|
||||
if (resolver->badcount < resolver->badhash * 2 &&
|
||||
resolver->badhash > DNS_BADCACHE_SIZE)
|
||||
resizehash(resolver, &now, ISC_FALSE);
|
||||
}
|
||||
bad->expire = *expire;
|
||||
cleanup:
|
||||
UNLOCK(&resolver->lock);
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
dns_resolver_getbadcache(dns_resolver_t *resolver, dns_name_t *name,
|
||||
dns_rdatatype_t type, isc_time_t *now)
|
||||
{
|
||||
dns_badcache_t *bad, *prev, *next;
|
||||
isc_boolean_t answer = ISC_FALSE;
|
||||
unsigned int i;
|
||||
|
||||
REQUIRE(VALID_RESOLVER(resolver));
|
||||
|
||||
LOCK(&resolver->lock);
|
||||
if (resolver->badcache == NULL)
|
||||
goto unlock;
|
||||
|
||||
i = dns_name_hash(name, ISC_FALSE) % resolver->badhash;
|
||||
prev = NULL;
|
||||
for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
|
||||
next = bad->next;
|
||||
/*
|
||||
* Search the hash list. Clean out expired records as we go.
|
||||
*/
|
||||
if (isc_time_compare(&bad->expire, now) < 0) {
|
||||
if (prev != NULL)
|
||||
prev->next = bad->next;
|
||||
else
|
||||
resolver->badcache[i] = bad->next;
|
||||
isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
|
||||
bad->name.length);
|
||||
resolver->badcount--;
|
||||
continue;
|
||||
}
|
||||
if (bad->type == type && dns_name_equal(name, &bad->name)) {
|
||||
answer = ISC_TRUE;
|
||||
break;
|
||||
}
|
||||
prev = bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Slow sweep to clean out stale records.
|
||||
*/
|
||||
i = resolver->badsweep++ % resolver->badhash;
|
||||
bad = resolver->badcache[i];
|
||||
if (bad != NULL && isc_time_compare(&bad->expire, now) < 0) {
|
||||
resolver->badcache[i] = bad->next;
|
||||
isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
|
||||
bad->name.length);
|
||||
resolver->badcount--;
|
||||
}
|
||||
|
||||
unlock:
|
||||
UNLOCK(&resolver->lock);
|
||||
return (answer);
|
||||
}
|
||||
|
||||
void
|
||||
dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp) {
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
char typebuf[DNS_RDATATYPE_FORMATSIZE];
|
||||
dns_badcache_t *bad, *next, *prev;
|
||||
isc_time_t now;
|
||||
unsigned int i;
|
||||
isc_uint64_t t;
|
||||
|
||||
LOCK(&resolver->lock);
|
||||
fprintf(fp, ";\n; Bad cache\n;\n");
|
||||
|
||||
if (resolver->badcache == NULL)
|
||||
goto unlock;
|
||||
|
||||
TIME_NOW(&now);
|
||||
for (i = 0; i < resolver->badhash; i++) {
|
||||
prev = NULL;
|
||||
for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
|
||||
next = bad->next;
|
||||
if (isc_time_compare(&bad->expire, &now) < 0) {
|
||||
if (prev != NULL)
|
||||
prev->next = bad->next;
|
||||
else
|
||||
resolver->badcache[i] = bad->next;
|
||||
isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
|
||||
bad->name.length);
|
||||
resolver->badcount--;
|
||||
continue;
|
||||
}
|
||||
prev = bad;
|
||||
dns_name_format(&bad->name, namebuf, sizeof(namebuf));
|
||||
dns_rdatatype_format(bad->type, typebuf,
|
||||
sizeof(typebuf));
|
||||
t = isc_time_microdiff(&bad->expire, &now);
|
||||
t /= 1000;
|
||||
fprintf(fp, "; %s/%s [ttl "
|
||||
"%" ISC_PLATFORM_QUADFORMAT "u]\n",
|
||||
namebuf, typebuf, t);
|
||||
}
|
||||
}
|
||||
|
||||
unlock:
|
||||
UNLOCK(&resolver->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
free_algorithm(void *node, void *arg) {
|
||||
unsigned char *algorithms = node;
|
||||
|
||||
+3
-1
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: result.c,v 1.128 2009/10/12 20:48:12 each Exp $ */
|
||||
/* $Id: result.c,v 1.128.50.1 2010/02/25 05:05:08 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -157,7 +157,9 @@ static const char *text[DNS_R_NRESULTS] = {
|
||||
"MX is an address", /*%< 102 DNS_R_MXISADDRESS */
|
||||
"duplicate query", /*%< 103 DNS_R_DUPLICATE */
|
||||
"invalid NSEC3 owner name (wildcard)", /*%< 104 DNS_R_INVALIDNSEC3 */
|
||||
|
||||
"not master", /*%< 105 DNS_R_NOTMASTER */
|
||||
"broken trust chain", /*%< 106 DNS_R_BROKENCHAIN */
|
||||
};
|
||||
|
||||
static const char *rcode_text[DNS_R_NRCODERESULTS] = {
|
||||
|
||||
+3
-1
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: sdb.c,v 1.71 2009/10/08 23:13:07 marka Exp $ */
|
||||
/* $Id: sdb.c,v 1.71.54.1 2010/02/25 05:05:08 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -1387,6 +1387,8 @@ static dns_rdatasetmethods_t methods = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
+3
-1
@@ -50,7 +50,7 @@
|
||||
* USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: sdlz.c,v 1.22 2009/09/01 00:22:26 jinmei Exp $ */
|
||||
/* $Id: sdlz.c,v 1.22.104.1 2010/02/25 05:05:08 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -1211,6 +1211,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
+136
-22
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: validator.c,v 1.182.16.1 2009/12/30 06:46:36 each Exp $ */
|
||||
/* $Id: validator.c,v 1.182.16.2 2010/02/25 05:05:08 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -177,9 +177,16 @@ static inline void
|
||||
markanswer(dns_validator_t *val) {
|
||||
validator_log(val, ISC_LOG_DEBUG(3), "marking as answer");
|
||||
if (val->event->rdataset != NULL)
|
||||
val->event->rdataset->trust = dns_trust_answer;
|
||||
dns_rdataset_settrust(val->event->rdataset, dns_trust_answer);
|
||||
if (val->event->sigrdataset != NULL)
|
||||
val->event->sigrdataset->trust = dns_trust_answer;
|
||||
dns_rdataset_settrust(val->event->sigrdataset,
|
||||
dns_trust_answer);
|
||||
}
|
||||
|
||||
static inline void
|
||||
marksecure(dns_validatorevent_t *event) {
|
||||
dns_rdataset_settrust(event->rdataset, dns_trust_secure);
|
||||
dns_rdataset_settrust(event->sigrdataset, dns_trust_secure);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -425,7 +432,7 @@ fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
|
||||
if (eresult == ISC_R_CANCELED)
|
||||
validator_done(val, eresult);
|
||||
else
|
||||
validator_done(val, DNS_R_NOVALIDKEY);
|
||||
validator_done(val, DNS_R_BROKENCHAIN);
|
||||
}
|
||||
want_destroy = exit_check(val);
|
||||
UNLOCK(&val->lock);
|
||||
@@ -495,7 +502,7 @@ dsfetched(isc_task_t *task, isc_event_t *event) {
|
||||
if (eresult == ISC_R_CANCELED)
|
||||
validator_done(val, eresult);
|
||||
else
|
||||
validator_done(val, DNS_R_NOVALIDDS);
|
||||
validator_done(val, DNS_R_BROKENCHAIN);
|
||||
}
|
||||
want_destroy = exit_check(val);
|
||||
UNLOCK(&val->lock);
|
||||
@@ -636,10 +643,16 @@ keyvalidated(isc_task_t *task, isc_event_t *event) {
|
||||
if (result != DNS_R_WAIT)
|
||||
validator_done(val, result);
|
||||
} else {
|
||||
if (eresult != DNS_R_BROKENCHAIN) {
|
||||
if (dns_rdataset_isassociated(&val->frdataset))
|
||||
dns_rdataset_expire(&val->frdataset);
|
||||
if (dns_rdataset_isassociated(&val->fsigrdataset))
|
||||
dns_rdataset_expire(&val->fsigrdataset);
|
||||
}
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"keyvalidated: got %s",
|
||||
isc_result_totext(eresult));
|
||||
validator_done(val, eresult);
|
||||
validator_done(val, DNS_R_BROKENCHAIN);
|
||||
}
|
||||
want_destroy = exit_check(val);
|
||||
UNLOCK(&val->lock);
|
||||
@@ -686,10 +699,16 @@ dsvalidated(isc_task_t *task, isc_event_t *event) {
|
||||
if (result != DNS_R_WAIT)
|
||||
validator_done(val, result);
|
||||
} else {
|
||||
if (eresult != DNS_R_BROKENCHAIN) {
|
||||
if (dns_rdataset_isassociated(&val->frdataset))
|
||||
dns_rdataset_expire(&val->frdataset);
|
||||
if (dns_rdataset_isassociated(&val->fsigrdataset))
|
||||
dns_rdataset_expire(&val->fsigrdataset);
|
||||
}
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"dsvalidated: got %s",
|
||||
isc_result_totext(eresult));
|
||||
validator_done(val, eresult);
|
||||
validator_done(val, DNS_R_BROKENCHAIN);
|
||||
}
|
||||
want_destroy = exit_check(val);
|
||||
UNLOCK(&val->lock);
|
||||
@@ -1200,6 +1219,8 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"authvalidated: got %s",
|
||||
isc_result_totext(result));
|
||||
if (result == DNS_R_BROKENCHAIN)
|
||||
val->authfail++;
|
||||
if (result == ISC_R_CANCELED)
|
||||
validator_done(val, result);
|
||||
else {
|
||||
@@ -1272,6 +1293,7 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
|
||||
* \li DNS_R_NCACHENXRRSET
|
||||
* \li DNS_R_NXRRSET
|
||||
* \li DNS_R_NXDOMAIN
|
||||
* \li DNS_R_BROKENCHAIN
|
||||
*/
|
||||
static inline isc_result_t
|
||||
view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
|
||||
@@ -1281,9 +1303,12 @@ view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
isc_result_t result;
|
||||
unsigned int options;
|
||||
isc_time_t now;
|
||||
char buf1[DNS_NAME_FORMATSIZE];
|
||||
char buf2[DNS_NAME_FORMATSIZE];
|
||||
char buf3[DNS_NAME_FORMATSIZE];
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
char typebuf[DNS_RDATATYPE_FORMATSIZE];
|
||||
|
||||
if (dns_rdataset_isassociated(&val->frdataset))
|
||||
dns_rdataset_disassociate(&val->frdataset);
|
||||
@@ -1293,6 +1318,16 @@ view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
|
||||
if (val->view->zonetable == NULL)
|
||||
return (ISC_R_CANCELED);
|
||||
|
||||
if (isc_time_now(&now) == ISC_R_SUCCESS &&
|
||||
dns_resolver_getbadcache(val->view->resolver, name, type, &now)) {
|
||||
|
||||
dns_name_format(name, namebuf, sizeof(namebuf));
|
||||
dns_rdatatype_format(type, typebuf, sizeof(typebuf));
|
||||
validator_log(val, ISC_LOG_INFO, "bad cache hit (%s/%s)",
|
||||
namebuf, typebuf);
|
||||
return (DNS_R_BROKENCHAIN);
|
||||
}
|
||||
|
||||
options = DNS_DBFIND_PENDINGOK;
|
||||
if (type == dns_rdatatype_dlv)
|
||||
options |= DNS_DBFIND_COVERINGNSEC;
|
||||
@@ -1301,6 +1336,7 @@ view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
|
||||
result = dns_view_find(val->view, name, type, 0, options,
|
||||
ISC_FALSE, NULL, NULL, foundname,
|
||||
&val->frdataset, &val->fsigrdataset);
|
||||
|
||||
if (result == DNS_R_NXDOMAIN) {
|
||||
if (dns_rdataset_isassociated(&val->frdataset))
|
||||
dns_rdataset_disassociate(&val->frdataset);
|
||||
@@ -1663,7 +1699,8 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
|
||||
/*
|
||||
* We don't know anything about this key.
|
||||
*/
|
||||
result = create_fetch(val, &siginfo->signer, dns_rdatatype_dnskey,
|
||||
result = create_fetch(val, &siginfo->signer,
|
||||
dns_rdatatype_dnskey,
|
||||
fetch_callback_validator, "get_key");
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
@@ -1678,7 +1715,8 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
|
||||
* This key doesn't exist.
|
||||
*/
|
||||
result = DNS_R_CONTINUE;
|
||||
}
|
||||
} else if (result == DNS_R_BROKENCHAIN)
|
||||
return (result);
|
||||
|
||||
if (dns_rdataset_isassociated(&val->frdataset) &&
|
||||
val->keyset != &val->frdataset)
|
||||
@@ -1930,8 +1968,7 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
"looking for noqname proof");
|
||||
return (nsecvalidate(val, ISC_FALSE));
|
||||
} else if (result == ISC_R_SUCCESS) {
|
||||
event->rdataset->trust = dns_trust_secure;
|
||||
event->sigrdataset->trust = dns_trust_secure;
|
||||
marksecure(event);
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"marking as secure, "
|
||||
"noqname proof not needed");
|
||||
@@ -2108,8 +2145,7 @@ dlv_validatezonekey(dns_validator_t *val) {
|
||||
"no RRSIG matching DLV key");
|
||||
}
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
val->event->rdataset->trust = dns_trust_secure;
|
||||
val->event->sigrdataset->trust = dns_trust_secure;
|
||||
marksecure(val->event);
|
||||
validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (dlv)");
|
||||
return (result);
|
||||
} else if (result == ISC_R_NOMORE && !supported_algorithm) {
|
||||
@@ -2219,8 +2255,7 @@ validatezonekey(dns_validator_t *val) {
|
||||
keynode = nextnode;
|
||||
}
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
event->rdataset->trust = dns_trust_secure;
|
||||
event->sigrdataset->trust = dns_trust_secure;
|
||||
marksecure(event);
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"signed by trusted key; "
|
||||
"marking as secure");
|
||||
@@ -2252,11 +2287,14 @@ validatezonekey(dns_validator_t *val) {
|
||||
*/
|
||||
dns_name_format(val->event->name, namebuf,
|
||||
sizeof(namebuf));
|
||||
validator_log(val, ISC_LOG_DEBUG(2),
|
||||
validator_log(val, ISC_LOG_NOTICE,
|
||||
"unable to find a DNSKEY which verifies "
|
||||
"the DNSKEY RRset and also matches a "
|
||||
"trusted key for '%s'",
|
||||
namebuf);
|
||||
validator_log(val, ISC_LOG_NOTICE,
|
||||
"please check the 'trusted-keys' for "
|
||||
"'%s' in named.conf.", namebuf);
|
||||
return (DNS_R_NOVALIDKEY);
|
||||
}
|
||||
|
||||
@@ -2317,7 +2355,8 @@ validatezonekey(dns_validator_t *val) {
|
||||
dns_rdataset_disassociate(&val->fsigrdataset);
|
||||
validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
|
||||
return (DNS_R_NOVALIDSIG);
|
||||
}
|
||||
} else if (result == DNS_R_BROKENCHAIN)
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2467,8 +2506,7 @@ validatezonekey(dns_validator_t *val) {
|
||||
"no RRSIG matching DS key");
|
||||
}
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
event->rdataset->trust = dns_trust_secure;
|
||||
event->sigrdataset->trust = dns_trust_secure;
|
||||
marksecure(event);
|
||||
validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)");
|
||||
return (result);
|
||||
} else if (result == ISC_R_NOMORE && !supported_algorithm) {
|
||||
@@ -2875,6 +2913,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
"nsecvalidate");
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
val->authcount++;
|
||||
return (DNS_R_WAIT);
|
||||
|
||||
}
|
||||
@@ -2897,8 +2936,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
(val->attributes & VALATTR_FOUNDCLOSEST) != 0) {
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"marking as secure, noqname proof found");
|
||||
val->event->rdataset->trust = dns_trust_secure;
|
||||
val->event->sigrdataset->trust = dns_trust_secure;
|
||||
marksecure(val->event);
|
||||
return (ISC_R_SUCCESS);
|
||||
} else if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0 &&
|
||||
dns_name_countlabels(dns_fixedname_name(&val->wild))
|
||||
@@ -2951,6 +2989,8 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
if (val->authcount == val->authfail)
|
||||
return (DNS_R_BROKENCHAIN);
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"nonexistence proof(s) not found");
|
||||
val->attributes |= VALATTR_INSECURITY;
|
||||
@@ -2982,6 +3022,58 @@ check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
dlvvalidated(isc_task_t *task, isc_event_t *event) {
|
||||
dns_validatorevent_t *devent;
|
||||
dns_validator_t *val;
|
||||
isc_result_t eresult;
|
||||
isc_boolean_t want_destroy;
|
||||
|
||||
UNUSED(task);
|
||||
INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
|
||||
|
||||
devent = (dns_validatorevent_t *)event;
|
||||
val = devent->ev_arg;
|
||||
eresult = devent->result;
|
||||
|
||||
isc_event_free(&event);
|
||||
dns_validator_destroy(&val->subvalidator);
|
||||
|
||||
INSIST(val->event != NULL);
|
||||
|
||||
validator_log(val, ISC_LOG_DEBUG(3), "in dlvvalidated");
|
||||
LOCK(&val->lock);
|
||||
if (CANCELED(val)) {
|
||||
validator_done(val, ISC_R_CANCELED);
|
||||
} else if (eresult == ISC_R_SUCCESS) {
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"dlvset with trust %d", val->frdataset.trust);
|
||||
dns_rdataset_clone(&val->frdataset, &val->dlv);
|
||||
val->havedlvsep = ISC_TRUE;
|
||||
if (dlv_algorithm_supported(val))
|
||||
dlv_validator_start(val);
|
||||
else {
|
||||
markanswer(val);
|
||||
validator_done(val, ISC_R_SUCCESS);
|
||||
}
|
||||
} else {
|
||||
if (eresult != DNS_R_BROKENCHAIN) {
|
||||
if (dns_rdataset_isassociated(&val->frdataset))
|
||||
dns_rdataset_expire(&val->frdataset);
|
||||
if (dns_rdataset_isassociated(&val->fsigrdataset))
|
||||
dns_rdataset_expire(&val->fsigrdataset);
|
||||
}
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"dlvvalidated: got %s",
|
||||
isc_result_totext(eresult));
|
||||
validator_done(val, DNS_R_BROKENCHAIN);
|
||||
}
|
||||
want_destroy = exit_check(val);
|
||||
UNLOCK(&val->lock);
|
||||
if (want_destroy)
|
||||
destroy(val);
|
||||
}
|
||||
|
||||
/*%
|
||||
* Callback from fetching a DLV record.
|
||||
*
|
||||
@@ -3204,6 +3296,24 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
|
||||
namebuf);
|
||||
result = view_find(val, dlvname, dns_rdatatype_dlv);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
if (DNS_TRUST_PENDING(val->frdataset.trust) &&
|
||||
dns_rdataset_isassociated(&val->fsigrdataset))
|
||||
{
|
||||
dns_fixedname_init(&val->fname);
|
||||
dns_name_copy(dlvname,
|
||||
dns_fixedname_name(&val->fname),
|
||||
NULL);
|
||||
result = create_validator(val,
|
||||
dns_fixedname_name(&val->fname),
|
||||
dns_rdatatype_dlv,
|
||||
&val->frdataset,
|
||||
&val->fsigrdataset,
|
||||
dlvvalidated,
|
||||
"finddlvsep");
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
return (DNS_R_WAIT);
|
||||
}
|
||||
if (val->frdataset.trust < dns_trust_secure) {
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"DLV not validated");
|
||||
@@ -3257,6 +3367,7 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
|
||||
* \li DNS_R_NOVALIDSIG
|
||||
* \li DNS_R_NOVALIDNSEC
|
||||
* \li DNS_R_NOTINSECURE
|
||||
* \li DNS_R_BROKENCHAIN
|
||||
*/
|
||||
static isc_result_t
|
||||
proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
|
||||
@@ -3518,7 +3629,8 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto out;
|
||||
return (DNS_R_WAIT);
|
||||
}
|
||||
} else if (result == DNS_R_BROKENCHAIN)
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3744,6 +3856,8 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
||||
val->seensig = ISC_FALSE;
|
||||
val->havedlvsep = ISC_FALSE;
|
||||
val->depth = 0;
|
||||
val->authcount = 0;
|
||||
val->authfail = 0;
|
||||
val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
|
||||
dns_rdataset_init(&val->frdataset);
|
||||
dns_rdataset_init(&val->fsigrdataset);
|
||||
|
||||
+7
-2
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: view.c,v 1.159 2009/11/28 15:57:37 vjs Exp $ */
|
||||
/* $Id: view.c,v 1.159.8.1 2010/02/25 05:05:08 marka Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@@ -1325,10 +1325,11 @@ dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
|
||||
|
||||
(void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name);
|
||||
result = dns_master_dumptostream(view->mctx, view->cachedb, NULL,
|
||||
&dns_master_style_cache, fp);
|
||||
&dns_master_style_cache, fp);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
dns_adb_dump(view->adb, fp);
|
||||
dns_resolver_printbadcache(view->resolver, fp);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
@@ -1360,6 +1361,8 @@ dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) {
|
||||
#ifdef BIND9
|
||||
if (view->acache != NULL)
|
||||
dns_acache_setdb(view->acache, view->cachedb);
|
||||
if (view->resolver != NULL)
|
||||
dns_resolver_flushbadcache(view->resolver, NULL);
|
||||
#endif
|
||||
|
||||
dns_adb_flush(view->adb);
|
||||
@@ -1375,6 +1378,8 @@ dns_view_flushname(dns_view_t *view, dns_name_t *name) {
|
||||
dns_adb_flushname(view->adb, name);
|
||||
if (view->cache == NULL)
|
||||
return (ISC_R_SUCCESS);
|
||||
if (view->resolver != NULL)
|
||||
dns_resolver_flushbadcache(view->resolver, name);
|
||||
return (dns_cache_flushname(view->cache, name));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user