mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
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]
This commit is contained in:
7
CHANGES
7
CHANGES
@@ -1,3 +1,10 @@
|
||||
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;
|
||||
|
Reference in New Issue
Block a user