1605. [func] New dns_db_find() option DNS_DBFIND_COVERINGNSEC.
1607. [bug] dig, host and nslookup were still using random()
to generate query ids. [RT# 11013]
-1606. [placeholder] rt10440a
+1606. [bug] DVL insecurity proof was failing.
+
+1605. [func] New dns_db_find() option DNS_DBFIND_COVERINGNSEC.
-1605. [placeholder] rt10440a
1604. [bug] A xfrout_ctx_create() failure would result in
xfrout_ctx_destroy() being called with a
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: db.h,v 1.76 2004/03/05 05:09:41 marka Exp $ */
+/* $Id: db.h,v 1.77 2004/05/14 04:45:57 marka Exp $ */
#ifndef DNS_DB_H
#define DNS_DB_H 1
#define DNS_DBFIND_PENDINGOK 0x08
#define DNS_DBFIND_NOEXACT 0x10
#define DNS_DBFIND_FORCENSEC 0x20
+#define DNS_DBFIND_COVERINGNSEC 0x40
/*
* Options that can be specified for dns_db_addrdataset().
* is only necessary when querying a database that was not secure
* when created.
*
+ * If the DNS_DBFIND_COVERINGNSEC option is set, then look for a
+ * NSEC record that potentially covers 'name' if a answer cannot
+ * be found. Note the returned NSEC needs to be checked to ensure
+ * that it is correct. This only affects answers returned from the
+ * cache.
+ *
* To respond to a query for SIG records, the caller should create a
* rdataset iterator and extract the signatures from each rdataset.
*
* DNS_R_EMPTYNAME The name exists but there is
* no data at the name.
*
+ * DNS_R_COVERINGNSEC The returned data is a NSEC
+ * that potentially covers 'name'.
+ *
* Error results:
*
* ISC_R_NOMEMORY
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: result.h,v 1.105 2004/04/15 23:40:26 marka Exp $ */
+/* $Id: result.h,v 1.106 2004/05/14 04:45:58 marka Exp $ */
#ifndef DNS_RESULT_H
#define DNS_RESULT_H 1
#define DNS_R_DYNAMIC (ISC_RESULTCLASS_DNS + 98)
#define DNS_R_UNKNOWNCOMMAND (ISC_RESULTCLASS_DNS + 99)
#define DNS_R_MUSTBESECURE (ISC_RESULTCLASS_DNS + 100)
+#define DNS_R_COVERINGNSEC (ISC_RESULTCLASS_DNS + 101)
-#define DNS_R_NRESULTS 101 /* Number of results */
+#define DNS_R_NRESULTS 102 /* Number of results */
/*
* DNS wire format rcodes.
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.h,v 1.28 2004/04/15 23:40:26 marka Exp $ */
+/* $Id: validator.h,v 1.29 2004/05/14 04:45:58 marka Exp $ */
#ifndef DNS_VALIDATOR_H
#define DNS_VALIDATOR_H 1
dns_fixedname_t wild;
ISC_LINK(dns_validator_t) link;
dns_rdataset_t * dlv;
+ dns_fixedname_t dlvsep;
+ isc_boolean_t havedlvsep;
isc_boolean_t mustbesecure;
};
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbtdb.c,v 1.198 2004/05/14 01:05:53 marka Exp $ */
+/* $Id: rbtdb.c,v 1.199 2004/05/14 04:45:56 marka Exp $ */
/*
* Principal Author: Bob Halley
/*
* If this is a NONEXISTENT rdataset, we can delete it.
*/
- if ((current->attributes & RDATASET_ATTR_NONEXISTENT)
- != 0) {
+ if (NONEXISTENT(current)) {
if (top_prev != NULL)
top_prev->next = current->next;
else
* Is this a "this rdataset doesn't
* exist" record?
*/
- if ((header->attributes &
- RDATASET_ATTR_NONEXISTENT) != 0)
+ if (NONEXISTENT(header))
header = NULL;
break;
} else
* Is this a "this rdataset doesn't
* exist" record?
*/
- if ((header->attributes &
- RDATASET_ATTR_NONEXISTENT) != 0)
+ if (NONEXISTENT(header))
header = NULL;
break;
} else
node->dirty = 1;
header_prev = header;
}
- } else if ((header->attributes &
- RDATASET_ATTR_NONEXISTENT) == 0) {
+ } else if (EXISTS(header)) {
/*
* We've found an extant rdataset. See if
* we're interested in it.
return (result);
}
+static isc_result_t
+find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
+ isc_stdtime_t now, dns_name_t *foundname,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ dns_rbtnode_t *node;
+ rdatasetheader_t *header, *header_next, *header_prev;
+ rdatasetheader_t *found, *foundsig;
+ isc_boolean_t empty_node;
+ isc_result_t result;
+ dns_fixedname_t fname, forigin;
+ dns_name_t *name, *origin;
+ rbtdb_rdatatype_t matchtype, sigmatchtype, nsectype;
+
+ matchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_nsec, 0);
+ nsectype = RBTDB_RDATATYPE_VALUE(0, dns_rdatatype_nsec);
+ sigmatchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig,
+ dns_rdatatype_nsec);
+
+ do {
+ node = NULL;
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_fixedname_init(&forigin);
+ origin = dns_fixedname_name(&forigin);
+ result = dns_rbtnodechain_current(&search->chain, name,
+ origin, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ LOCK(&(search->rbtdb->node_locks[node->locknum].lock));
+ found = NULL;
+ foundsig = NULL;
+ empty_node = ISC_TRUE;
+ header_prev = NULL;
+ for (header = node->data;
+ header != NULL;
+ header = header_next) {
+ header_next = header->next;
+ if (header->ttl <= now) {
+ /*
+ * This rdataset is stale. If no one else is
+ * using the node, we can clean it up right
+ * now, otherwise we mark it as stale, and the
+ * node as dirty, so it will get cleaned up
+ * later.
+ */
+ if (node->references == 0) {
+ INSIST(header->down == NULL);
+ if (header_prev != NULL)
+ header_prev->next =
+ header->next;
+ else
+ node->data = header->next;
+ free_rdataset(search->rbtdb->common.mctx,
+ header);
+ } else {
+ header->attributes |=
+ RDATASET_ATTR_STALE;
+ node->dirty = 1;
+ header_prev = header;
+ }
+ continue;
+ }
+ if (NONEXISTENT(header) || NXDOMAIN(header)) {
+ header_prev = header;
+ continue;
+ }
+ empty_node = ISC_FALSE;
+ if (header->type == matchtype)
+ found = header;
+ else if (header->type == sigmatchtype)
+ foundsig = header;
+ header_prev = header;
+ }
+ if (found != NULL) {
+ result = dns_name_concatenate(name, origin,
+ foundname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto unlock_node;
+ bind_rdataset(search->rbtdb, node, found,
+ now, rdataset);
+ if (foundsig != NULL)
+ bind_rdataset(search->rbtdb, node, foundsig,
+ now, sigrdataset);
+ new_reference(search->rbtdb, node);
+ *nodep = node;
+ result = DNS_R_COVERINGNSEC;
+ } else if (!empty_node) {
+ result = ISC_R_NOTFOUND;
+ }else
+ result = dns_rbtnodechain_prev(&search->chain, NULL,
+ NULL);
+ unlock_node:
+ UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock));
+ } while (empty_node && result == ISC_R_SUCCESS);
+ return (result);
+}
+
static isc_result_t
cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
rdatasetheader_t *header, *header_prev, *header_next;
rdatasetheader_t *found, *nsheader;
rdatasetheader_t *foundsig, *nssig, *cnamesig;
- rbtdb_rdatatype_t sigtype, nsecype;
+ rbtdb_rdatatype_t sigtype, nsectype;
UNUSED(version);
cache_zonecut_callback, &search);
if (result == DNS_R_PARTIALMATCH) {
+ if ((search.options & DNS_DBFIND_COVERINGNSEC) != 0) {
+ result = find_coveringnsec(&search, nodep, now,
+ foundname, rdataset,
+ sigrdataset);
+ if (result == DNS_R_COVERINGNSEC)
+ goto tree_exit;
+ }
if (search.zonecut != NULL) {
result = setup_delegation(&search, nodep, foundname,
rdataset, sigrdataset);
found = NULL;
foundsig = NULL;
sigtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, type);
- nsecype = RBTDB_RDATATYPE_VALUE(0, type);
+ nsectype = RBTDB_RDATATYPE_VALUE(0, type);
nsheader = NULL;
nssig = NULL;
cnamesig = NULL;
node->dirty = 1;
header_prev = header;
}
- } else if ((header->attributes & RDATASET_ATTR_NONEXISTENT)
- == 0) {
+ } else if (EXISTS(header)) {
/*
* We now know that there is at least one active
* non-stale rdataset at this node.
*/
foundsig = header;
} else if (header->type == RBTDB_RDATATYPE_NCACHEANY ||
- header->type == nsecype) {
+ header->type == nsectype) {
/*
* We've found a negative cache entry.
*/
node->dirty = 1;
header_prev = header;
}
- } else if ((header->attributes & RDATASET_ATTR_NONEXISTENT)
- == 0) {
+ } else if (EXISTS(header)) {
/*
* If we found a type we were looking for, remember
* it.
* Is this a "this rdataset doesn't
* exist" record?
*/
- if ((header->attributes &
- RDATASET_ATTR_NONEXISTENT) != 0)
+ if (NONEXISTENT(header))
header = NULL;
break;
} else
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
rdatasetheader_t *header, *header_next, *found, *foundsig;
- rbtdb_rdatatype_t matchtype, sigmatchtype, nsecype;
+ rbtdb_rdatatype_t matchtype, sigmatchtype, nsectype;
isc_result_t result;
REQUIRE(VALID_RBTDB(rbtdb));
found = NULL;
foundsig = NULL;
matchtype = RBTDB_RDATATYPE_VALUE(type, covers);
- nsecype = RBTDB_RDATATYPE_VALUE(0, type);
+ nsectype = RBTDB_RDATATYPE_VALUE(0, type);
if (covers == 0)
sigmatchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, type);
else
*/
header->attributes |= RDATASET_ATTR_STALE;
rbtnode->dirty = 1;
- } else if ((header->attributes & RDATASET_ATTR_NONEXISTENT) ==
- 0) {
+ } else if (EXISTS(header)) {
if (header->type == matchtype)
found = header;
else if (header->type == RBTDB_RDATATYPE_NCACHEANY ||
- header->type == nsecype)
+ header->type == nsectype)
found = header;
else if (header->type == sigmatchtype)
foundsig = header;
isc_boolean_t header_nx;
isc_boolean_t newheader_nx;
isc_boolean_t merge;
- dns_rdatatype_t nsecype, rdtype, covers;
+ dns_rdatatype_t nsectype, rdtype, covers;
dns_trust_t trust;
/*
newheader_nx = NONEXISTENT(newheader) ? ISC_TRUE : ISC_FALSE;
topheader_prev = NULL;
- nsecype = 0;
+ nsectype = 0;
if (rbtversion == NULL && !newheader_nx) {
rdtype = RBTDB_RDATATYPE_BASE(newheader->type);
if (rdtype == 0) {
rbtnode->dirty = 1;
goto find_header;
}
- nsecype = RBTDB_RDATATYPE_VALUE(covers, 0);
+ nsectype = RBTDB_RDATATYPE_VALUE(covers, 0);
} else {
/*
* We're adding something that isn't a
topheader = NULL;
goto find_header;
}
- nsecype = RBTDB_RDATATYPE_VALUE(0, rdtype);
+ nsectype = RBTDB_RDATATYPE_VALUE(0, rdtype);
}
}
topheader != NULL;
topheader = topheader->next) {
if (topheader->type == newheader->type ||
- topheader->type == nsecype)
+ topheader->type == nsectype)
break;
topheader_prev = topheader;
}
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.c,v 1.287 2004/04/19 23:16:20 marka Exp $ */
+/* $Id: resolver.c,v 1.288 2004/05/14 04:45:56 marka Exp $ */
#include <config.h>
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
- "fctx %p: %s", fctx, (m))
+ "fctx %p(%s'): %s", fctx, fctx->info, (m))
#define FCTXTRACE2(m1, m2) \
isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
- "fctx %p: %s %s", fctx, (m1), (m2))
+ "fctx %p(%s): %s %s", \
+ fctx, fctx->info, (m1), (m2))
#define FTRACE(m) isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
- "fetch %p (fctx %p): %s", \
- fetch, fetch->private, (m))
+ "fetch %p (fctx %p(%s)): %s", \
+ fetch, fetch->private, \
+ fetch->private->info, (m))
#define QTRACE(m) isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
- "resquery %p (fctx %p): %s", \
- query, query->fctx, (m))
+ "resquery %p (fctx %p(%s)): %s", \
+ query, query->fctx, \
+ query->fctx->info, (m))
#else
#define RTRACE(m)
#define RRTRACE(r, m)
dns_rdatatype_t type;
unsigned int options;
unsigned int bucketnum;
+ char * info;
/* Locked by appropriate bucket lock. */
fetchstate state;
isc_boolean_t want_shutdown;
&secure_domain);
if (result != ISC_R_SUCCESS)
secure_domain = ISC_FALSE;
+ if (res->view->dlv != NULL)
+ secure_domain = ISC_TRUE;
if (secure_domain)
fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
} else
dns_name_free(&fctx->name, res->mctx);
dns_db_detach(&fctx->cache);
dns_adb_detach(&fctx->adb);
+ isc_mem_free(res->mctx, fctx->info);
isc_mem_put(res->mctx, fctx, sizeof(*fctx));
LOCK(&res->nlock);
isc_interval_t interval;
dns_fixedname_t qdomain;
unsigned int findoptions = 0;
+ char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
/*
* Caller must be holding the lock for bucket number 'bucketnum'.
fctx = isc_mem_get(res->mctx, sizeof(*fctx));
if (fctx == NULL)
return (ISC_R_NOMEMORY);
+ dns_name_format(name, buf, sizeof(buf));
+ dns_rdatatype_format(type, typebuf, sizeof(typebuf));
+ strcat(buf, "/"); /* checked */
+ strcat(buf, typebuf); /* checked */
+ fctx->info = isc_mem_strdup(res->mctx, buf);
+ if (fctx->info == NULL)
+ goto cleanup_fetch;
FCTXTRACE("create");
dns_name_init(&fctx->name, NULL);
result = dns_name_dup(name, res->mctx, &fctx->name);
if (result != ISC_R_SUCCESS)
- goto cleanup_fetch;
+ goto cleanup_info;
dns_name_init(&fctx->domain, NULL);
dns_rdataset_init(&fctx->nameservers);
cleanup_name:
dns_name_free(&fctx->name, res->mctx);
+ cleanup_info:
+ isc_mem_free(res->mctx, fctx->info);
+
cleanup_fetch:
isc_mem_put(res->mctx, fctx, sizeof(*fctx));
ardataset, &eresult);
if (result != ISC_R_SUCCESS)
goto noanswer_response;
-
goto answer_response;
}
goto cleanup_event;
}
+ answer_response:
/*
- * Cache any NS records that happened to be validate.
+ * Cache any NS/NSEC records that happened to be validated.
*/
result = dns_message_firstname(fctx->rmessage, DNS_SECTION_AUTHORITY);
while (result == ISC_R_SUCCESS) {
for (rdataset = ISC_LIST_HEAD(name->list);
rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link)) {
- if (rdataset->type != dns_rdatatype_ns ||
+ if ((rdataset->type != dns_rdatatype_ns &&
+ rdataset->type != dns_rdatatype_nsec) ||
rdataset->trust != dns_trust_secure)
continue;
for (sigrdataset = ISC_LIST_HEAD(name->list);
sigrdataset != NULL;
sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
if (sigrdataset->type != dns_rdatatype_rrsig ||
- sigrdataset->covers != dns_rdatatype_ns)
+ sigrdataset->covers != rdataset->type)
continue;
break;
}
result = ISC_R_SUCCESS;
- answer_response:
/*
* Respond with an answer, positive or negative,
* as opposed to an error. 'node' must be non-NULL.
if (result != ISC_R_SUCCESS)
return (result);
+ if (res->view->dlv != NULL)
+ secure_domain = ISC_TRUE;
+
if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
need_validation = ISC_FALSE;
else
if (result != ISC_R_SUCCESS)
return (result);
+ if (res->view->dlv != NULL)
+ secure_domain = ISC_TRUE;
+
if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
need_validation = ISC_FALSE;
else
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: result.c,v 1.116 2004/04/15 23:40:25 marka Exp $ */
+/* $Id: result.c,v 1.117 2004/05/14 04:45:57 marka Exp $ */
#include <config.h>
"dynamic zone", /* 98 DNS_R_DYNAMIC */
"unknown command", /* 99 DNS_R_UNKNOWNCOMMAND */
- "must-be-secure" /* 100 DNS_R_MUSTBESECURE */
+ "must-be-secure", /* 100 DNS_R_MUSTBESECURE */
+ "covering NSEC record returned" /* 101 DNS_R_COVERINGNSEC */
};
static const char *rcode_text[DNS_R_NRCODERESULTS] = {
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.c,v 1.121 2004/04/15 23:40:25 marka Exp $ */
+/* $Id: validator.c,v 1.122 2004/05/14 04:45:57 marka Exp $ */
#include <config.h>
#define VALATTR_INSECURITY 0x0010
#define VALATTR_DLV 0x0020
#define VALATTR_DLVTRIED 0x0040
+#define VALATTR_DLVSEPTRIED 0x0080
#define VALATTR_NEEDNOQNAME 0x0100
#define VALATTR_NEEDNOWILDCARD 0x0200
#define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
#define DLV(val) ((val->attributes & VALATTR_DLV) != 0)
#define DLVTRIED(val) ((val->attributes & VALATTR_DLVTRIED) != 0)
+#define DLVSEPTRIED(val) ((val->attributes & VALATTR_DLVSEPTRIED) != 0)
#define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
static isc_result_t
dlv_validatezonekey(dns_validator_t *val);
+static isc_result_t
+finddlvsep(dns_validator_t *val, isc_boolean_t resume);
+
static void
validator_done(dns_validator_t *val, isc_result_t result) {
isc_task_t *task;
static inline isc_result_t
view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
+ dns_fixedname_t fixedname;
+ dns_name_t *foundname;
+ dns_rdata_nsec_t nsec;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+ unsigned int options;
+ char buf1[DNS_NAME_FORMATSIZE];
+ char buf2[DNS_NAME_FORMATSIZE];
+ char buf3[DNS_NAME_FORMATSIZE];
+
if (dns_rdataset_isassociated(&val->frdataset))
dns_rdataset_disassociate(&val->frdataset);
if (dns_rdataset_isassociated(&val->fsigrdataset))
if (val->view->zonetable == NULL)
return (ISC_R_CANCELED);
- return (dns_view_simplefind(val->view, name, type, 0,
- DNS_DBFIND_PENDINGOK, ISC_FALSE,
- &val->frdataset, &val->fsigrdataset));
+
+ options = DNS_DBFIND_PENDINGOK;
+ if (type == dns_rdatatype_dlv)
+ options |= DNS_DBFIND_COVERINGNSEC;
+ dns_fixedname_init(&fixedname);
+ foundname = dns_fixedname_name(&fixedname);
+ result = dns_view_find(val->view, name, type, 0, options,
+ ISC_FALSE, NULL, NULL, foundname,
+ &val->frdataset, &val->fsigrdataset);
+ if (result == DNS_R_NXDOMAIN) {
+ if (dns_rdataset_isassociated(&val->frdataset))
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ } else if (result == DNS_R_COVERINGNSEC) {
+ validator_log(val, ISC_LOG_DEBUG(3), "DNS_R_COVERINGNSEC");
+ /*
+ * Check if the returned NSEC covers the name.
+ */
+ INSIST(type == dns_rdatatype_dlv);
+ if (val->frdataset.trust != dns_trust_secure) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "covering nsec: trust %u",
+ val->frdataset.trust);
+ goto notfound;
+ }
+ result = dns_rdataset_first(&val->frdataset);
+ if (result != ISC_R_SUCCESS)
+ goto notfound;
+ dns_rdataset_current(&val->frdataset, &rdata);
+ if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
+ !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) {
+ /* Parent NSEC record. */
+ if (dns_name_issubdomain(name, foundname)) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "covering nsec: for parent");
+ goto notfound;
+ }
+ }
+ result = dns_rdata_tostruct(&rdata, &nsec, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto notfound;
+ if (dns_name_compare(foundname, &nsec.next) >= 0) {
+ /* End of zone chain. */
+ if (!dns_name_issubdomain(name, &nsec.next)) {
+ /*
+ * XXXMPA We could look for a parent NSEC
+ * at nsec.next and if found retest with
+ * this NSEC.
+ */
+ dns_rdata_freestruct(&nsec);
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "covering nsec: not in zone");
+ goto notfound;
+ }
+ } else if (dns_name_compare(name, &nsec.next) >= 0) {
+ /*
+ * XXXMPA We could check if this NSEC is at a zone
+ * apex and if the qname is not below it and look for
+ * a parent NSEC with the same name. This requires
+ * that we can cache both NSEC records which we
+ * currently don't support.
+ */
+ dns_rdata_freestruct(&nsec);
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "covering nsec: not in range");
+ goto notfound;
+ }
+ if (isc_log_wouldlog(dns_lctx,ISC_LOG_DEBUG(3))) {
+ dns_name_format(name, buf1, sizeof buf1);
+ dns_name_format(foundname, buf2, sizeof buf2);
+ dns_name_format(&nsec.next, buf3, sizeof buf3);
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "covering nsec found: '%s' '%s' '%s'",
+ buf1, buf2, buf3);
+ }
+ if (dns_rdataset_isassociated(&val->frdataset))
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ dns_rdata_freestruct(&nsec);
+ result = DNS_R_NCACHENXDOMAIN;
+ } else if (result != ISC_R_SUCCESS &&
+ result != DNS_R_GLUE &&
+ result != DNS_R_HINT &&
+ result != DNS_R_NCACHENXDOMAIN &&
+ result != DNS_R_NCACHENXRRSET &&
+ result != DNS_R_NXRRSET &&
+ result != DNS_R_HINTNXRRSET &&
+ result != ISC_R_NOTFOUND) {
+ goto notfound;
+ }
+ return (result);
+
+ notfound:
+ if (dns_rdataset_isassociated(&val->frdataset))
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ return (ISC_R_NOTFOUND);
}
static inline isc_boolean_t
return (ISC_FALSE);
}
+static void
+dlv_fetched2(isc_task_t *task, isc_event_t *event) {
+ dns_fetchevent_t *devent;
+ dns_validator_t *val;
+ isc_boolean_t want_destroy;
+ isc_result_t eresult;
+ isc_result_t result;
+
+ UNUSED(task);
+ INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
+ devent = (dns_fetchevent_t *)event;
+ val = devent->ev_arg;
+ eresult = devent->result;
+
+ isc_event_free(&event);
+ dns_resolver_destroyfetch(&val->fetch);
+
+ INSIST(val->event != NULL);
+ validator_log(val, ISC_LOG_DEBUG(3), "in dlv_fetched2: %s",
+ dns_result_totext(eresult));
+
+ LOCK(&val->lock);
+ if (eresult == ISC_R_SUCCESS) {
+ val->havedlvsep = ISC_TRUE;
+ result = proveunsecure(val, ISC_FALSE);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ } else if (eresult == DNS_R_NXRRSET ||
+ eresult == DNS_R_NXDOMAIN ||
+ eresult == DNS_R_NCACHENXRRSET ||
+ eresult == DNS_R_NCACHENXDOMAIN) {
+ result = finddlvsep(val, ISC_TRUE);
+ if (result == ISC_R_SUCCESS) {
+ result = proveunsecure(val, ISC_FALSE);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ } else if (result == ISC_R_NOTFOUND) {
+ validator_done(val, ISC_R_SUCCESS);
+ } else if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ }
+ want_destroy = exit_check(val);
+ UNLOCK(&val->lock);
+ if (want_destroy)
+ destroy(val);
+}
+
+static isc_result_t
+finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
+ dns_fixedname_t dlvfixed;
+ dns_name_t *dlvname;
+ dns_name_t *dlvsep;
+ dns_name_t noroot;
+ isc_result_t result;
+ unsigned int labels;
+
+ if (!resume) {
+ dns_fixedname_init(&val->dlvsep);
+ dlvsep = dns_fixedname_name(&val->dlvsep);
+ dns_name_copy(val->event->name, dlvsep, NULL);
+ val->attributes |= VALATTR_DLVSEPTRIED;
+ } else {
+ dlvsep = dns_fixedname_name(&val->dlvsep);
+ labels = dns_name_countlabels(dlvsep);
+ dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
+ }
+ dns_name_init(&noroot, NULL);
+ dns_fixedname_init(&dlvfixed);
+ dlvname = dns_fixedname_name(&dlvfixed);
+ labels = dns_name_countlabels(dlvsep);
+ dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot);
+ result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL);
+ while (result == ISC_R_NOSPACE) {
+ labels = dns_name_countlabels(dlvsep);
+ dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
+ dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot);
+ result = dns_name_concatenate(&noroot, val->view->dlv,
+ dlvname, NULL);
+ }
+ if (result != ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
+ return (DNS_R_NOVALIDSIG);
+ }
+
+ while (dns_name_countlabels(dlvname) >
+ dns_name_countlabels(val->view->dlv))
+ {
+ result = view_find(val, dlvname, dns_rdatatype_dlv);
+ if (result == ISC_R_SUCCESS) {
+ if (val->frdataset.trust < dns_trust_secure)
+ return (DNS_R_NOVALIDSIG);
+ val->havedlvsep = ISC_TRUE;
+ return (ISC_R_SUCCESS);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ result = create_fetch(val, dlvname, dns_rdatatype_dlv,
+ dlv_fetched2, "finddlvsep");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (DNS_R_WAIT);
+ }
+ if (result != DNS_R_NXRRSET &&
+ result != DNS_R_NXDOMAIN &&
+ result != DNS_R_NCACHENXRRSET &&
+ result != DNS_R_NCACHENXDOMAIN)
+ return (result);
+ /*
+ * Strip first labels from both dlvsep and dlvname.
+ */
+ labels = dns_name_countlabels(dlvsep);
+ dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
+ labels = dns_name_countlabels(dlvname);
+ dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname);
+ }
+ return (ISC_R_NOTFOUND);
+}
+
static isc_result_t
proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
isc_result_t result;
+ isc_result_t tresult;
dns_fixedname_t secroot;
dns_name_t *tname;
/*
* If the name is not under a security root, it must be insecure.
*/
- if (result == ISC_R_NOTFOUND)
- return (ISC_R_SUCCESS);
+ if (val->view->dlv != NULL && !DLVSEPTRIED(val) &&
+ !dns_name_issubdomain(val->event->name, val->view->dlv)) {
+ tresult = finddlvsep(val, ISC_FALSE);
+ if (tresult != ISC_R_NOTFOUND && tresult != ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "finddlvsep returned: %s",
+ dns_result_totext(tresult));
+ return (tresult);
+ }
+ }
- else if (result != ISC_R_SUCCESS)
+ if (result == ISC_R_NOTFOUND) {
+ if (!val->havedlvsep)
+ return (ISC_R_SUCCESS);
+ dns_name_copy(dns_fixedname_name(&val->dlvsep),
+ dns_fixedname_name(&secroot), NULL);
+ } else if (result != ISC_R_SUCCESS)
return (result);
+ else if (val->havedlvsep &&
+ dns_name_issubdomain(dns_fixedname_name(&val->dlvsep),
+ dns_fixedname_name(&secroot))) {
+ dns_name_copy(dns_fixedname_name(&val->dlvsep),
+ dns_fixedname_name(&secroot), NULL);
+ }
if (!resume) {
val->labels =
val->nsecset = NULL;
val->soaname = NULL;
val->seensig = ISC_FALSE;
+ val->havedlvsep = ISC_FALSE;
val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
dns_rdataset_init(&val->frdataset);
dns_rdataset_init(&val->fsigrdataset);
./bin/tests/system/dialup/setup.sh SH 2000,2001,2004
./bin/tests/system/dialup/tests.sh SH 2000,2001,2004
./bin/tests/system/digcomp.pl PERL 2000,2001,2004
+./bin/tests/system/dlv/clean.sh SH 2004
+./bin/tests/system/dlv/setup.sh SH 2004
+./bin/tests/system/dlv/tests.sh SH 2004
+./bin/tests/system/dlv/ns1/named.conf CONF-C 2004
+./bin/tests/system/dlv/ns1/root.db ZONE 2004
+./bin/tests/system/dlv/ns1/rootservers.utld.db ZONE 2004
+./bin/tests/system/dlv/ns2/hints ZONE 2004
+./bin/tests/system/dlv/ns2/named.conf CONF-C 2004
+./bin/tests/system/dlv/ns2/utld.db ZONE 2004
+./bin/tests/system/dlv/ns3/child.db.in ZONE 2004
+./bin/tests/system/dlv/ns3/dlv.db.in ZONE 2004
+./bin/tests/system/dlv/ns3/hints ZONE 2004
+./bin/tests/system/dlv/ns3/named.conf CONF-C 2004
+./bin/tests/system/dlv/ns3/sign.sh SH 2004
+./bin/tests/system/dlv/ns4/child.db ZONE 2004
+./bin/tests/system/dlv/ns4/hints ZONE 2004
+./bin/tests/system/dlv/ns4/named.conf CONF-C 2004
+./bin/tests/system/dlv/ns5/hints ZONE 2004
+./bin/tests/system/dlv/ns5/named.conf CONF-C 2004
./bin/tests/system/dnssec/README TXT.BRIEF 2000,2001,2002,2004
./bin/tests/system/dnssec/clean.sh SH 2000,2001,2002,2004
./bin/tests/system/dnssec/dnssec_update_test.pl PERL 2002,2004