mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 22:45:39 +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
|
2116. [bug] 'rndc reload' could cause the cache to continually
|
||||||
be cleaned. [RT #16401]
|
be cleaned. [RT #16401]
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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 */
|
/*! \file */
|
||||||
|
|
||||||
@@ -4366,7 +4366,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
|
|||||||
dns_message_t *message;
|
dns_message_t *message;
|
||||||
dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name;
|
dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name;
|
||||||
dns_rdataset_t *rdataset, *ns_rdataset;
|
dns_rdataset_t *rdataset, *ns_rdataset;
|
||||||
isc_boolean_t done, aa, negative_response;
|
isc_boolean_t aa, negative_response;
|
||||||
dns_rdatatype_t type;
|
dns_rdatatype_t type;
|
||||||
dns_section_t section =
|
dns_section_t section =
|
||||||
bind8_ns_resp ? DNS_SECTION_ANSWER : DNS_SECTION_AUTHORITY;
|
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.
|
* Process the authority section.
|
||||||
*/
|
*/
|
||||||
done = ISC_FALSE;
|
|
||||||
ns_name = NULL;
|
ns_name = NULL;
|
||||||
ns_rdataset = NULL;
|
ns_rdataset = NULL;
|
||||||
soa_name = NULL;
|
soa_name = NULL;
|
||||||
ds_name = NULL;
|
ds_name = NULL;
|
||||||
result = dns_message_firstname(message, section);
|
result = dns_message_firstname(message, section);
|
||||||
while (!done && result == ISC_R_SUCCESS) {
|
while (result == ISC_R_SUCCESS) {
|
||||||
name = NULL;
|
name = NULL;
|
||||||
dns_message_currentname(message, section, &name);
|
dns_message_currentname(message, section, &name);
|
||||||
if (dns_name_issubdomain(name, &fctx->domain)) {
|
if (dns_name_issubdomain(name, &fctx->domain)) {
|
||||||
@@ -4493,15 +4492,29 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
|
|||||||
dns_trust_additional;
|
dns_trust_additional;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
}
|
||||||
* A negative response has a SOA record (Type 2)
|
result = dns_message_nextname(message, section);
|
||||||
* and a optional NS RRset (Type 1) or it has neither
|
if (result == ISC_R_NOMORE)
|
||||||
* a SOA or a NS RRset (Type 3, handled above) or
|
break;
|
||||||
* rcode is NXDOMAIN (handled above) in which case
|
else if (result != ISC_R_SUCCESS)
|
||||||
* the NS RRset is allowed (Type 4).
|
return (result);
|
||||||
*/
|
}
|
||||||
if (soa_name != NULL)
|
|
||||||
negative_response = ISC_TRUE;
|
/*
|
||||||
|
* 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);
|
for (rdataset = ISC_LIST_HEAD(name->list);
|
||||||
rdataset != NULL;
|
rdataset != NULL;
|
||||||
rdataset = ISC_LIST_NEXT(rdataset, link)) {
|
rdataset = ISC_LIST_NEXT(rdataset, link)) {
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* PERFORMANCE OF THIS SOFTWARE.
|
* 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 */
|
/*! \file */
|
||||||
|
|
||||||
@@ -579,6 +579,8 @@ nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
|
|||||||
unsigned int olabels, nlabels, labels;
|
unsigned int olabels, nlabels, labels;
|
||||||
dns_rdata_nsec_t nsec;
|
dns_rdata_nsec_t nsec;
|
||||||
isc_boolean_t atparent;
|
isc_boolean_t atparent;
|
||||||
|
isc_boolean_t ns;
|
||||||
|
isc_boolean_t soa;
|
||||||
|
|
||||||
REQUIRE(exists != NULL);
|
REQUIRE(exists != NULL);
|
||||||
REQUIRE(data != 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.
|
* The names are the same.
|
||||||
*/
|
*/
|
||||||
atparent = dns_rdatatype_atparent(val->event->type);
|
atparent = dns_rdatatype_atparent(val->event->type);
|
||||||
if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
|
ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
|
||||||
!dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
|
soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa);
|
||||||
{
|
if (ns && !soa) {
|
||||||
if (!atparent) {
|
if (!atparent) {
|
||||||
/*
|
/*
|
||||||
* This NSEC record is from somewhere higher in
|
* 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");
|
"ignoring parent nsec");
|
||||||
return (ISC_R_IGNORE);
|
return (ISC_R_IGNORE);
|
||||||
}
|
}
|
||||||
} else if (atparent) {
|
} else if (atparent && ns && soa) {
|
||||||
/*
|
/*
|
||||||
* This NSEC record is from the child.
|
* This NSEC record is from the child.
|
||||||
* It can not be legitimately used here.
|
* 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");
|
"ignoring child nsec");
|
||||||
return (ISC_R_IGNORE);
|
return (ISC_R_IGNORE);
|
||||||
}
|
}
|
||||||
*exists = ISC_TRUE;
|
if (val->event->type == dns_rdatatype_cname ||
|
||||||
*data = dns_nsec_typepresent(&rdata, val->event->type);
|
val->event->type == dns_rdatatype_nxt ||
|
||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
val->event->type == dns_rdatatype_nsec ||
|
||||||
"nsec proves name exists (owner) data=%d",
|
val->event->type == dns_rdatatype_key ||
|
||||||
*data);
|
!dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) {
|
||||||
return (ISC_R_SUCCESS);
|
*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 &&
|
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,
|
result = dns_name_concatenate(dns_wildcardname, &common,
|
||||||
wild, NULL);
|
wild, NULL);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
dns_rdata_freestruct(&nsec);
|
||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
"failure generating wildcard name");
|
"failure generating wildcard name");
|
||||||
return (result);
|
return (result);
|
||||||
@@ -750,6 +761,7 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dns_name_t **proofs = val->event->proofs;
|
dns_name_t **proofs = val->event->proofs;
|
||||||
|
dns_name_t *wild = dns_fixedname_name(&val->wild);
|
||||||
|
|
||||||
if (rdataset->trust == dns_trust_secure)
|
if (rdataset->trust == dns_trust_secure)
|
||||||
val->seensig = ISC_TRUE;
|
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_FOUNDNODATA) == 0 &&
|
||||||
(val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
|
(val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
|
||||||
nsecnoexistnodata(val, val->event->name, devent->name,
|
nsecnoexistnodata(val, val->event->name, devent->name,
|
||||||
rdataset, &exists, &data,
|
rdataset, &exists, &data, wild)
|
||||||
dns_fixedname_name(&val->wild))
|
|
||||||
== ISC_R_SUCCESS)
|
== ISC_R_SUCCESS)
|
||||||
{
|
{
|
||||||
if (exists && !data) {
|
if (exists && !data) {
|
||||||
val->attributes |= VALATTR_FOUNDNODATA;
|
val->attributes |= VALATTR_FOUNDNODATA;
|
||||||
if (NEEDNODATA(val))
|
if (NEEDNODATA(val))
|
||||||
@@ -2085,12 +2096,6 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
|||||||
if (rdataset->type == dns_rdatatype_rrsig)
|
if (rdataset->type == dns_rdatatype_rrsig)
|
||||||
continue;
|
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);
|
for (sigrdataset = ISC_LIST_HEAD(name->list);
|
||||||
sigrdataset != NULL;
|
sigrdataset != NULL;
|
||||||
sigrdataset = ISC_LIST_NEXT(sigrdataset,
|
sigrdataset = ISC_LIST_NEXT(sigrdataset,
|
||||||
@@ -2545,11 +2550,21 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
|
|||||||
namebuf);
|
namebuf);
|
||||||
|
|
||||||
result = view_find(val, tname, dns_rdatatype_ds);
|
result = view_find(val, tname, dns_rdatatype_ds);
|
||||||
|
|
||||||
if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
|
if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
|
||||||
/*
|
/*
|
||||||
* There is no DS. If this is a delegation,
|
* There is no DS. If this is a delegation,
|
||||||
* we maybe done.
|
* 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) {
|
if (val->frdataset.trust < dns_trust_secure) {
|
||||||
/*
|
/*
|
||||||
* This shouldn't happen, since the negative
|
* 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->keyset = NULL;
|
||||||
val->dsset = NULL;
|
val->dsset = NULL;
|
||||||
dns_rdataset_init(&val->dlv);
|
dns_rdataset_init(&val->dlv);
|
||||||
val->soaset = NULL;
|
|
||||||
val->nsecset = NULL;
|
|
||||||
val->soaname = NULL;
|
|
||||||
val->seensig = ISC_FALSE;
|
val->seensig = ISC_FALSE;
|
||||||
val->havedlvsep = ISC_FALSE;
|
val->havedlvsep = ISC_FALSE;
|
||||||
val->depth = 0;
|
val->depth = 0;
|
||||||
|
Reference in New Issue
Block a user