mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
snapshot - includes (untested) code to find unsecured subdomains, which
won't work until the server returns keys/nxts from the parent zones. Also some style fixes.
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
#include <dns/dnssec.h>
|
||||
#include <dns/events.h>
|
||||
#include <dns/keytable.h>
|
||||
#include <dns/keyvalues.h>
|
||||
#include <dns/log.h>
|
||||
#include <dns/message.h>
|
||||
#include <dns/name.h>
|
||||
@@ -78,6 +79,7 @@ struct dns_validator {
|
||||
isc_taskaction_t action;
|
||||
void * arg;
|
||||
dns_name_t * queryname;
|
||||
unsigned int labels;
|
||||
};
|
||||
|
||||
#define VALIDATOR_MAGIC 0x56616c3fU /* Val?. */
|
||||
@@ -179,8 +181,7 @@ fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
|
||||
goto free_event;
|
||||
}
|
||||
UNLOCK(&val->lock);
|
||||
}
|
||||
else
|
||||
} else
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"fetch_callback_validator: got %s",
|
||||
dns_result_totext(devent->result));
|
||||
@@ -227,8 +228,7 @@ keyvalidated(isc_task_t *task, isc_event_t *event) {
|
||||
goto free_event;
|
||||
}
|
||||
UNLOCK(&val->lock);
|
||||
}
|
||||
else
|
||||
} else
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"keyvalidated: got %s",
|
||||
dns_result_totext(devent->result));
|
||||
@@ -241,6 +241,45 @@ keyvalidated(isc_task_t *task, isc_event_t *event) {
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
nullkeyvalidated(isc_task_t *task, isc_event_t *event) {
|
||||
dns_validatorevent_t *devent;
|
||||
dns_validator_t *val;
|
||||
dns_rdataset_t *rdataset;
|
||||
isc_result_t result;
|
||||
|
||||
UNUSED(task);
|
||||
INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
|
||||
devent = (dns_validatorevent_t *)event;
|
||||
rdataset = devent->rdataset;
|
||||
val = devent->ev_arg;
|
||||
|
||||
validator_log(val, ISC_LOG_DEBUG(3), "in nullkeyvalidated");
|
||||
if (devent->result == ISC_R_SUCCESS) {
|
||||
LOCK(&val->lock);
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"proved that name is in an unsecure domain");
|
||||
validator_done(val, ISC_R_SUCCESS);
|
||||
UNLOCK(&val->lock);
|
||||
} else {
|
||||
LOCK(&val->lock);
|
||||
result = proveunsecure(val, ISC_TRUE);
|
||||
if (result != DNS_R_WAIT)
|
||||
validator_done(val, result);
|
||||
UNLOCK(&val->lock);
|
||||
}
|
||||
|
||||
dns_validator_destroy(&val->keyvalidator);
|
||||
|
||||
/* free stuff from the event */
|
||||
isc_mem_put(val->view->mctx, devent->rdataset, sizeof(dns_rdataset_t));
|
||||
isc_mem_put(val->view->mctx, devent->sigrdataset,
|
||||
sizeof(dns_rdataset_t));
|
||||
dns_name_free(devent->name, val->view->mctx);
|
||||
isc_mem_put(val->view->mctx, devent->name, sizeof(dns_name_t));
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to find a key that could have signed 'siginfo' among those
|
||||
* in 'rdataset'. If found, build a dst_key_t for it and point
|
||||
@@ -562,6 +601,8 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
"verify failure: %s",
|
||||
dns_result_totext(result));
|
||||
}
|
||||
if (result == ISC_R_NOMORE)
|
||||
result = ISC_R_NOTFOUND;
|
||||
return (result);
|
||||
}
|
||||
|
||||
@@ -582,8 +623,7 @@ nxtvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
validator_done(val, ISC_R_NOTFOUND);
|
||||
}
|
||||
else
|
||||
} else
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
for (;
|
||||
@@ -642,7 +682,7 @@ nxtvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
&qname);
|
||||
qrdataset = ISC_LIST_HEAD(qname->list);
|
||||
qtype = qrdataset->type;
|
||||
if (qtype > 128) {
|
||||
if (qtype >= 128) {
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"invalid type %d", qtype);
|
||||
continue;
|
||||
@@ -655,8 +695,7 @@ nxtvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
"type should not be present");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (order > 0) {
|
||||
} else if (order > 0) {
|
||||
result = dns_rdataset_first(val->event->rdataset);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_rdataset_current(val->event->rdataset, &rdata);
|
||||
@@ -674,8 +713,7 @@ nxtvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"nxt owner name is not less");
|
||||
continue;
|
||||
@@ -692,6 +730,144 @@ nxtvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
static inline isc_result_t
|
||||
proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
|
||||
isc_result_t result;
|
||||
dns_fixedname_t secroot, fname;
|
||||
dns_name_t *tname;
|
||||
|
||||
dns_fixedname_init(&secroot);
|
||||
dns_fixedname_init(&fname);
|
||||
result = dns_keytable_finddeepestmatch(val->view->secroots,
|
||||
val->event->name,
|
||||
dns_fixedname_name(&secroot));
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
validator_log(val, ISC_LOG_DEBUG(3), "in proveunsecure");
|
||||
|
||||
if (!resume)
|
||||
val->labels = dns_name_depth(dns_fixedname_name(&secroot)) + 1;
|
||||
else
|
||||
val->labels++;
|
||||
for (;
|
||||
val->labels <= dns_name_depth(val->event->name);
|
||||
val->labels++)
|
||||
{
|
||||
dns_rdataset_t rdataset, sigrdataset;
|
||||
|
||||
if (val->labels == dns_name_depth(val->event->name))
|
||||
tname = val->event->name;
|
||||
else {
|
||||
tname = dns_fixedname_name(&fname);
|
||||
result = dns_name_splitatdepth(val->event->name,
|
||||
val->labels,
|
||||
NULL, tname);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
}
|
||||
dns_rdataset_init(&rdataset);
|
||||
dns_rdataset_init(&sigrdataset);
|
||||
result = dns_view_simplefind(val->view, tname,
|
||||
dns_rdatatype_key, 0,
|
||||
DNS_DBFIND_PENDINGOK, ISC_FALSE,
|
||||
&rdataset, &sigrdataset);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
dns_rdata_t rdata;
|
||||
dns_rdataset_t *frdataset = NULL, *fsigrdataset = NULL;
|
||||
dns_name_t *fname = NULL;
|
||||
|
||||
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"found keyset, looking for null key");
|
||||
result = dns_rdataset_first(&rdataset);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
continue;
|
||||
do {
|
||||
dst_key_t *key = NULL;
|
||||
isc_buffer_t b;
|
||||
|
||||
dns_rdataset_current(&rdataset, &rdata);
|
||||
isc_buffer_init(&b, rdata.data, rdata.length,
|
||||
ISC_BUFFERTYPE_BINARY);
|
||||
isc_buffer_add(&b, rdata.length);
|
||||
key = NULL;
|
||||
result = dst_key_fromdns("", &b,
|
||||
val->view->mctx, &key);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
continue;
|
||||
if (dst_key_isnullkey(key)) {
|
||||
dst_key_free(key);
|
||||
break;
|
||||
}
|
||||
dst_key_free(key);
|
||||
result = dns_rdataset_next(&rdataset);
|
||||
} while (result == ISC_R_SUCCESS);
|
||||
if (result == ISC_R_NOMORE)
|
||||
continue;
|
||||
else if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
if (!dns_rdataset_isassociated(&sigrdataset))
|
||||
return (ISC_R_FAILURE);
|
||||
frdataset = isc_mem_get(val->view->mctx,
|
||||
sizeof *frdataset);
|
||||
if (frdataset == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
fsigrdataset = isc_mem_get(val->view->mctx,
|
||||
sizeof *fsigrdataset);
|
||||
if (fsigrdataset == NULL) {
|
||||
isc_mem_put(val->view->mctx, frdataset,
|
||||
sizeof *frdataset);
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
fname = isc_mem_get(val->view->mctx, sizeof *fname);
|
||||
if (fname == NULL) {
|
||||
isc_mem_put(val->view->mctx, fsigrdataset,
|
||||
sizeof *frdataset);
|
||||
isc_mem_put(val->view->mctx, frdataset,
|
||||
sizeof *fsigrdataset);
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
dns_name_init(fname, NULL);
|
||||
result = dns_name_dup(tname, val->view->mctx, fname);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mem_put(val->view->mctx, fsigrdataset,
|
||||
sizeof *frdataset);
|
||||
isc_mem_put(val->view->mctx, frdataset,
|
||||
sizeof *fsigrdataset);
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
dns_rdataset_init(frdataset);
|
||||
dns_rdataset_init(fsigrdataset);
|
||||
dns_rdataset_clone(&rdataset, frdataset);
|
||||
dns_rdataset_clone(&sigrdataset, fsigrdataset);
|
||||
|
||||
result = dns_validator_create(val->view,
|
||||
fname,
|
||||
frdataset,
|
||||
fsigrdataset,
|
||||
NULL,
|
||||
0,
|
||||
val->task,
|
||||
nullkeyvalidated,
|
||||
val,
|
||||
&val->keyvalidator);
|
||||
return (DNS_R_WAIT);
|
||||
} else if (result == ISC_R_NOTFOUND) {
|
||||
/* create a fetch */
|
||||
return (ISC_R_NOTIMPLEMENTED);
|
||||
} else if (result == DNS_R_NCACHENXDOMAIN ||
|
||||
result == DNS_R_NCACHENXRRSET ||
|
||||
result == DNS_R_NXDOMAIN ||
|
||||
result == DNS_R_NXRRSET)
|
||||
{
|
||||
continue;
|
||||
} else
|
||||
return (result);
|
||||
}
|
||||
return (ISC_R_FAILURE); /* Didn't find a null key */
|
||||
}
|
||||
|
||||
static void
|
||||
validator_start(isc_task_t *task, isc_event_t *event) {
|
||||
dns_validator_t *val;
|
||||
@@ -712,14 +888,22 @@ validator_start(isc_task_t *task, isc_event_t *event) {
|
||||
* could still get complicated.
|
||||
*/
|
||||
result = validate(val, ISC_FALSE);
|
||||
}
|
||||
else if (val->event->rdataset == NULL &&
|
||||
} else if (val->event->rdataset != NULL) {
|
||||
/*
|
||||
* This is either an unsecure subdomain or a response from
|
||||
* a broken server.
|
||||
*/
|
||||
result = proveunsecure(val, ISC_FALSE);
|
||||
} else if (val->event->rdataset == NULL &&
|
||||
val->event->sigrdataset == NULL)
|
||||
{
|
||||
/*
|
||||
* This is a nonexistence validation.
|
||||
*/
|
||||
result = nxtvalidate(val, ISC_FALSE);
|
||||
} else {
|
||||
/* This shouldn't happen */
|
||||
INSIST(0);
|
||||
}
|
||||
|
||||
if (result != DNS_R_WAIT)
|
||||
@@ -781,6 +965,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name,
|
||||
val->action = action;
|
||||
val->arg = arg;
|
||||
val->queryname = NULL;
|
||||
val->labels = 0;
|
||||
val->magic = VALIDATOR_MAGIC;
|
||||
|
||||
isc_task_send(task, (isc_event_t **)&event);
|
||||
|
Reference in New Issue
Block a user