Commit 1ea2595e authored by Mark Andrews's avatar Mark Andrews
Browse files

2117. [bug] DNSSEC fixes: named could fail to cache NSEC records

                        which could lead to validation failures.  named didn't
                        handle negative DS responses that were in the process
                        of being validated.  Check CNAME bit before accepting
                        NODATA proof. To be able to ignore a child NSEC there
                        must be SOA (and NS) set in the bitmap. [RT #16399]
parent e60f01cd
2117. [bug] DNSSEC fixes: named could fail to cache NSEC records
which could lead to validation failures. named didn't
handle negative DS responses that were in the process
of being validated. Check CNAME bit before accepting
NODATA proof. To be able to ignore a child NSEC there
must be SOA (and NS) set in the bitmap. [RT #16399]
2116. [bug] 'rndc reload' could cause the cache to continually
be cleaned. [RT #16401]
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.c,v 1.336 2006/10/18 04:18:54 marka Exp $ */
/* $Id: resolver.c,v 1.337 2006/12/07 06:47:36 marka Exp $ */
/*! \file */
......@@ -4366,7 +4366,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
dns_message_t *message;
dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name;
dns_rdataset_t *rdataset, *ns_rdataset;
isc_boolean_t done, aa, negative_response;
isc_boolean_t aa, negative_response;
dns_rdatatype_t type;
dns_section_t section =
bind8_ns_resp ? DNS_SECTION_ANSWER : DNS_SECTION_AUTHORITY;
......@@ -4425,13 +4425,12 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
/*
* Process the authority section.
*/
done = ISC_FALSE;
ns_name = NULL;
ns_rdataset = NULL;
soa_name = NULL;
ds_name = NULL;
result = dns_message_firstname(message, section);
while (!done && result == ISC_R_SUCCESS) {
while (result == ISC_R_SUCCESS) {
name = NULL;
dns_message_currentname(message, section, &name);
if (dns_name_issubdomain(name, &fctx->domain)) {
......@@ -4493,15 +4492,29 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
dns_trust_additional;
}
}
/*
* A negative response has a SOA record (Type 2)
* and a optional NS RRset (Type 1) or it has neither
* a SOA or a NS RRset (Type 3, handled above) or
* rcode is NXDOMAIN (handled above) in which case
* the NS RRset is allowed (Type 4).
*/
if (soa_name != NULL)
negative_response = ISC_TRUE;
}
result = dns_message_nextname(message, section);
if (result == ISC_R_NOMORE)
break;
else if (result != ISC_R_SUCCESS)
return (result);
}
/*
* A negative response has a SOA record (Type 2)
* and a optional NS RRset (Type 1) or it has neither
* a SOA or a NS RRset (Type 3, handled above) or
* rcode is NXDOMAIN (handled above) in which case
* the NS RRset is allowed (Type 4).
*/
if (soa_name != NULL)
negative_response = ISC_TRUE;
result = dns_message_firstname(message, section);
while (result == ISC_R_SUCCESS) {
name = NULL;
dns_message_currentname(message, section, &name);
if (dns_name_issubdomain(name, &fctx->domain)) {
for (rdataset = ISC_LIST_HEAD(name->list);
rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link)) {
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: validator.c,v 1.145 2006/07/24 22:41:59 marka Exp $ */
/* $Id: validator.c,v 1.146 2006/12/07 06:47:36 marka Exp $ */
/*! \file */
......@@ -579,6 +579,8 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
unsigned int olabels, nlabels, labels;
dns_rdata_nsec_t nsec;
isc_boolean_t atparent;
isc_boolean_t ns;
isc_boolean_t soa;
REQUIRE(exists != NULL);
REQUIRE(data != NULL);
......@@ -610,9 +612,9 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
* The names are the same.
*/
atparent = dns_rdatatype_atparent(val->event->type);
if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
!dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
{
ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa);
if (ns && !soa) {
if (!atparent) {
/*
* This NSEC record is from somewhere higher in
......@@ -623,7 +625,7 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
"ignoring parent nsec");
return (ISC_R_IGNORE);
}
} else if (atparent) {
} else if (atparent && ns && soa) {
/*
* This NSEC record is from the child.
* It can not be legitimately used here.
......@@ -632,12 +634,20 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
"ignoring child nsec");
return (ISC_R_IGNORE);
}
*exists = ISC_TRUE;
*data = dns_nsec_typepresent(&rdata, val->event->type);
validator_log(val, ISC_LOG_DEBUG(3),
"nsec proves name exists (owner) data=%d",
*data);
return (ISC_R_SUCCESS);
if (val->event->type == dns_rdatatype_cname ||
val->event->type == dns_rdatatype_nxt ||
val->event->type == dns_rdatatype_nsec ||
val->event->type == dns_rdatatype_key ||
!dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) {
*exists = ISC_TRUE;
*data = dns_nsec_typepresent(&rdata, val->event->type);
validator_log(val, ISC_LOG_DEBUG(3),
"nsec proves name exists (owner) data=%d",
*data);
return (ISC_R_SUCCESS);
}
validator_log(val, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists");
return (ISC_R_IGNORE);
}
if (relation == dns_namereln_subdomain &&
......@@ -697,6 +707,7 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
result = dns_name_concatenate(dns_wildcardname, &common,
wild, NULL);
if (result != ISC_R_SUCCESS) {
dns_rdata_freestruct(&nsec);
validator_log(val, ISC_LOG_DEBUG(3),
"failure generating wildcard name");
return (result);
......@@ -750,6 +761,7 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
}
} else {
dns_name_t **proofs = val->event->proofs;
dns_name_t *wild = dns_fixedname_name(&val->wild);
if (rdataset->trust == dns_trust_secure)
val->seensig = ISC_TRUE;
......@@ -761,10 +773,9 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
(val->attributes & VALATTR_FOUNDNODATA) == 0 &&
(val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
nsecnoexistnodata(val, val->event->name, devent->name,
rdataset, &exists, &data,
dns_fixedname_name(&val->wild))
rdataset, &exists, &data, wild)
== ISC_R_SUCCESS)
{
{
if (exists && !data) {
val->attributes |= VALATTR_FOUNDNODATA;
if (NEEDNODATA(val))
......@@ -2085,12 +2096,6 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
if (rdataset->type == dns_rdatatype_rrsig)
continue;
if (rdataset->type == dns_rdatatype_soa) {
val->soaset = rdataset;
val->soaname = name;
} else if (rdataset->type == dns_rdatatype_nsec)
val->nsecset = rdataset;
for (sigrdataset = ISC_LIST_HEAD(name->list);
sigrdataset != NULL;
sigrdataset = ISC_LIST_NEXT(sigrdataset,
......@@ -2545,11 +2550,21 @@ proveunsecure(dns_validator_t *val, 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 (val->frdataset.trust == dns_trust_pending) {
result = create_fetch(val, tname,
dns_rdatatype_ds,
dsfetched2,
"proveunsecure");
if (result != ISC_R_SUCCESS)
goto out;
return (DNS_R_WAIT);
}
if (val->frdataset.trust < dns_trust_secure) {
/*
* This shouldn't happen, since the negative
......@@ -2852,9 +2867,6 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
val->keyset = NULL;
val->dsset = NULL;
dns_rdataset_init(&val->dlv);
val->soaset = NULL;
val->nsecset = NULL;
val->soaname = NULL;
val->seensig = ISC_FALSE;
val->havedlvsep = ISC_FALSE;
val->depth = 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment