Commit ff30cdeb authored by Mark Andrews's avatar Mark Andrews
Browse files

The validator didn't handle missing DS records correctly.

parent 4d9f3f00
......@@ -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 */
......@@ -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)) {
......
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