mirror of
https://github.com/isc-projects/bind9.git
synced 2026-03-03 22:10:35 -05:00
The validator didn't handle missing DS records correctly.
This commit is contained in:
parent
4d9f3f00d9
commit
ff30cdeb78
3 changed files with 254 additions and 13 deletions
|
|
@ -15,7 +15,7 @@
|
|||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: ncache.h,v 1.15 2002/02/20 03:34:35 marka Exp $ */
|
||||
/* $Id: ncache.h,v 1.16 2002/07/19 03:29:15 marka Exp $ */
|
||||
|
||||
#ifndef DNS_NCACHE_H
|
||||
#define DNS_NCACHE_H 1
|
||||
|
|
@ -125,6 +125,34 @@ dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
|
|||
* dns_name_towire().
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
|
||||
dns_rdatatype_t type, dns_rdataset_t *rdataset);
|
||||
/*
|
||||
* Search the negative caching rdataset for an rdataset with the
|
||||
* specified name and type.
|
||||
*
|
||||
* Requires:
|
||||
* 'ncacherdataset' is a valid negative caching rdataset.
|
||||
*
|
||||
* 'ncacherdataset' is not empty.
|
||||
*
|
||||
* 'name' is a valid name.
|
||||
*
|
||||
* 'type' is not SIG, or a meta-RR type.
|
||||
*
|
||||
* 'rdataset' is a valid disassociated rdataset.
|
||||
*
|
||||
* Ensures:
|
||||
* On a return of ISC_R_SUCCESS, 'rdataset' is bound to the found
|
||||
* rdataset.
|
||||
*
|
||||
* Returns:
|
||||
* ISC_R_SUCCESS - the rdataset was found.
|
||||
* ISC_R_NOTFOUND - the rdataset was not found.
|
||||
*
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_NCACHE_H */
|
||||
|
|
|
|||
169
lib/dns/ncache.c
169
lib/dns/ncache.c
|
|
@ -15,7 +15,7 @@
|
|||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: ncache.c,v 1.29 2002/02/20 03:34:15 marka Exp $ */
|
||||
/* $Id: ncache.c,v 1.30 2002/07/19 03:29:15 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
|
@ -378,3 +378,170 @@ dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
|
|||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_disassociate(dns_rdataset_t *rdataset) {
|
||||
UNUSED(rdataset);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rdataset_first(dns_rdataset_t *rdataset) {
|
||||
unsigned char *raw = rdataset->private3;
|
||||
unsigned int count;
|
||||
|
||||
count = raw[0] * 256 + raw[1];
|
||||
if (count == 0) {
|
||||
rdataset->private5 = NULL;
|
||||
return (ISC_R_NOMORE);
|
||||
}
|
||||
raw += 2;
|
||||
/*
|
||||
* The private4 field is the number of rdata beyond the cursor
|
||||
* position, so we decrement the total count by one before storing
|
||||
* it.
|
||||
*/
|
||||
count--;
|
||||
rdataset->private4 = (void *)count;
|
||||
rdataset->private5 = raw;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rdataset_next(dns_rdataset_t *rdataset) {
|
||||
unsigned int count;
|
||||
unsigned int length;
|
||||
unsigned char *raw;
|
||||
|
||||
count = (unsigned int)rdataset->private4;
|
||||
if (count == 0)
|
||||
return (ISC_R_NOMORE);
|
||||
count--;
|
||||
rdataset->private4 = (void *)count;
|
||||
raw = rdataset->private5;
|
||||
length = raw[0] * 256 + raw[1];
|
||||
raw += length + 2;
|
||||
rdataset->private5 = raw;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
|
||||
unsigned char *raw = rdataset->private5;
|
||||
isc_region_t r;
|
||||
|
||||
REQUIRE(raw != NULL);
|
||||
|
||||
r.length = raw[0] * 256 + raw[1];
|
||||
raw += 2;
|
||||
r.base = raw;
|
||||
dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
|
||||
}
|
||||
|
||||
static void
|
||||
rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
|
||||
*target = *source;
|
||||
|
||||
/*
|
||||
* Reset iterator state.
|
||||
*/
|
||||
target->private4 = NULL;
|
||||
target->private5 = NULL;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
rdataset_count(dns_rdataset_t *rdataset) {
|
||||
unsigned char *raw = rdataset->private3;
|
||||
unsigned int count;
|
||||
|
||||
count = raw[0] * 256 + raw[1];
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
static dns_rdatasetmethods_t rdataset_methods = {
|
||||
rdataset_disassociate,
|
||||
rdataset_first,
|
||||
rdataset_next,
|
||||
rdataset_current,
|
||||
rdataset_clone,
|
||||
rdataset_count
|
||||
};
|
||||
|
||||
isc_result_t
|
||||
dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
|
||||
dns_rdatatype_t type, dns_rdataset_t *rdataset)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
isc_region_t remaining;
|
||||
isc_buffer_t source;
|
||||
dns_name_t tname;
|
||||
dns_rdatatype_t ttype;
|
||||
unsigned int i, rcount;
|
||||
isc_uint16_t length;
|
||||
|
||||
REQUIRE(ncacherdataset != NULL);
|
||||
REQUIRE(ncacherdataset->type == 0);
|
||||
REQUIRE(name != NULL);
|
||||
REQUIRE(!dns_rdataset_isassociated(rdataset));
|
||||
REQUIRE(type != dns_rdatatype_sig);
|
||||
|
||||
result = dns_rdataset_first(ncacherdataset);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
dns_rdataset_current(ncacherdataset, &rdata);
|
||||
INSIST(dns_rdataset_next(ncacherdataset) == ISC_R_NOMORE);
|
||||
isc_buffer_init(&source, rdata.data, rdata.length);
|
||||
isc_buffer_add(&source, rdata.length);
|
||||
|
||||
do {
|
||||
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;
|
||||
|
||||
INSIST(remaining.length >= 4);
|
||||
ttype = isc_buffer_getuint16(&source);
|
||||
|
||||
if (ttype == type && dns_name_equal(&tname, name)) {
|
||||
isc_buffer_remainingregion(&source, &remaining);
|
||||
break;
|
||||
}
|
||||
|
||||
rcount = isc_buffer_getuint16(&source);
|
||||
for (i = 0; i < rcount; i++) {
|
||||
isc_buffer_remainingregion(&source, &remaining);
|
||||
INSIST(remaining.length >= 2);
|
||||
length = isc_buffer_getuint16(&source);
|
||||
isc_buffer_remainingregion(&source, &remaining);
|
||||
INSIST(remaining.length >= length);
|
||||
isc_buffer_forward(&source, length);
|
||||
}
|
||||
isc_buffer_remainingregion(&source, &remaining);
|
||||
} while (remaining.length > 0);
|
||||
|
||||
if (remaining.length == 0)
|
||||
return (ISC_R_NOTFOUND);
|
||||
|
||||
rdataset->methods = &rdataset_methods;
|
||||
rdataset->rdclass = ncacherdataset->rdclass;
|
||||
rdataset->type = type;
|
||||
rdataset->covers = 0;
|
||||
rdataset->ttl = ncacherdataset->ttl;
|
||||
rdataset->trust = ncacherdataset->trust;
|
||||
rdataset->private1 = NULL;
|
||||
rdataset->private2 = NULL;
|
||||
|
||||
rdataset->private3 = remaining.base;
|
||||
|
||||
/*
|
||||
* Reset iterator state.
|
||||
*/
|
||||
rdataset->private4 = NULL;
|
||||
rdataset->private5 = NULL;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: validator.c,v 1.108 2002/07/15 03:25:28 marka Exp $ */
|
||||
/* $Id: validator.c,v 1.109 2002/07/19 03:29:15 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
#include <dns/keytable.h>
|
||||
#include <dns/log.h>
|
||||
#include <dns/message.h>
|
||||
#include <dns/ncache.h>
|
||||
#include <dns/nxt.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/rdatastruct.h>
|
||||
|
|
@ -42,7 +43,7 @@
|
|||
#include <dns/view.h>
|
||||
|
||||
#define VALIDATOR_MAGIC ISC_MAGIC('V', 'a', 'l', '?')
|
||||
#define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
|
||||
#define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
|
||||
|
||||
#define VALATTR_SHUTDOWN 0x01
|
||||
#define VALATTR_FOUNDNONEXISTENCE 0x02
|
||||
|
|
@ -142,6 +143,39 @@ auth_nonpending(dns_message_t *message) {
|
|||
}
|
||||
}
|
||||
|
||||
static isc_boolean_t
|
||||
isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
|
||||
isc_result_t dbresult)
|
||||
{
|
||||
dns_rdataset_t set;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
isc_boolean_t found;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
|
||||
|
||||
dns_rdataset_init(&set);
|
||||
if (dbresult == DNS_R_NXRRSET)
|
||||
dns_rdataset_clone(rdataset, &set);
|
||||
else {
|
||||
result = dns_ncache_getrdataset(rdataset, name,
|
||||
dns_rdatatype_nxt, &set);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
INSIST(set.type == dns_rdatatype_nxt);
|
||||
|
||||
found = ISC_FALSE;
|
||||
result = dns_rdataset_first(&set);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
dns_rdataset_current(&set, &rdata);
|
||||
found = dns_nxt_typepresent(&rdata, dns_rdatatype_ns);
|
||||
}
|
||||
dns_rdataset_disassociate(&set);
|
||||
return (found);
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
|
||||
dns_fetchevent_t *devent;
|
||||
|
|
@ -256,6 +290,7 @@ dsfetched2(isc_task_t *task, isc_event_t *event) {
|
|||
dns_fetchevent_t *devent;
|
||||
dns_validator_t *val;
|
||||
dns_rdataset_t *rdataset;
|
||||
dns_name_t *tname;
|
||||
isc_boolean_t want_destroy;
|
||||
isc_result_t result;
|
||||
isc_result_t eresult;
|
||||
|
|
@ -267,7 +302,6 @@ dsfetched2(isc_task_t *task, isc_event_t *event) {
|
|||
rdataset = &val->frdataset;
|
||||
eresult = devent->result;
|
||||
|
||||
isc_event_free(&event);
|
||||
dns_resolver_destroyfetch(&val->fetch);
|
||||
|
||||
INSIST(val->event != NULL);
|
||||
|
|
@ -276,10 +310,17 @@ dsfetched2(isc_task_t *task, isc_event_t *event) {
|
|||
LOCK(&val->lock);
|
||||
if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NCACHENXRRSET) {
|
||||
/*
|
||||
* There is no DS. We're done.
|
||||
* There is no DS. If this is a delegation, we're done.
|
||||
*/
|
||||
val->event->rdataset->trust = dns_trust_answer;
|
||||
validator_done(val, ISC_R_SUCCESS);
|
||||
tname = dns_fixedname_name(&devent->foundname);
|
||||
if (isdelegation(tname, &val->frdataset, eresult)) {
|
||||
val->event->rdataset->trust = dns_trust_answer;
|
||||
validator_done(val, ISC_R_SUCCESS);
|
||||
} else {
|
||||
result = proveunsecure(val, ISC_TRUE);
|
||||
if (result != DNS_R_WAIT)
|
||||
validator_done(val, result);
|
||||
}
|
||||
} else if (eresult == ISC_R_SUCCESS ||
|
||||
eresult == DNS_R_NXDOMAIN ||
|
||||
eresult == DNS_R_NCACHENXDOMAIN)
|
||||
|
|
@ -296,6 +337,7 @@ dsfetched2(isc_task_t *task, isc_event_t *event) {
|
|||
else
|
||||
validator_done(val, DNS_R_NOVALIDDS);
|
||||
}
|
||||
isc_event_free(&event);
|
||||
want_destroy = exit_check(val);
|
||||
UNLOCK(&val->lock);
|
||||
if (want_destroy)
|
||||
|
|
@ -1480,7 +1522,8 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
|
|||
result = view_find(val, tname, dns_rdatatype_ds);
|
||||
if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
|
||||
/*
|
||||
* There is no DS. We're hopefully done.
|
||||
* There is no DS. If this is a delegation,
|
||||
* we're done.
|
||||
*/
|
||||
if (val->frdataset.trust < dns_trust_secure) {
|
||||
/*
|
||||
|
|
@ -1492,11 +1535,14 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
|
|||
result = DNS_R_NOVALIDSIG;
|
||||
goto out;
|
||||
}
|
||||
val->event->rdataset->trust = dns_trust_answer;
|
||||
return (ISC_R_SUCCESS);
|
||||
if (isdelegation(tname, &val->frdataset, result)) {
|
||||
val->event->rdataset->trust = dns_trust_answer;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
continue;
|
||||
} else if (result == ISC_R_SUCCESS) {
|
||||
/*
|
||||
* There is a DS here. Verify that it's secure and
|
||||
* There is a DS here. Verify that it's secure and
|
||||
* continue.
|
||||
*/
|
||||
if (val->frdataset.trust >= dns_trust_secure)
|
||||
|
|
@ -1518,7 +1564,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
|
|||
result == DNS_R_NCACHENXDOMAIN)
|
||||
{
|
||||
/*
|
||||
* This is not a zone cut. Assuming things are
|
||||
* This is not a zone cut. Assuming things are
|
||||
* as expected, continue.
|
||||
*/
|
||||
if (!dns_rdataset_isassociated(&val->frdataset)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue