mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 15:05:23 +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/dnssec.h>
|
||||||
#include <dns/events.h>
|
#include <dns/events.h>
|
||||||
#include <dns/keytable.h>
|
#include <dns/keytable.h>
|
||||||
|
#include <dns/keyvalues.h>
|
||||||
#include <dns/log.h>
|
#include <dns/log.h>
|
||||||
#include <dns/message.h>
|
#include <dns/message.h>
|
||||||
#include <dns/name.h>
|
#include <dns/name.h>
|
||||||
@@ -78,6 +79,7 @@ struct dns_validator {
|
|||||||
isc_taskaction_t action;
|
isc_taskaction_t action;
|
||||||
void * arg;
|
void * arg;
|
||||||
dns_name_t * queryname;
|
dns_name_t * queryname;
|
||||||
|
unsigned int labels;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define VALIDATOR_MAGIC 0x56616c3fU /* Val?. */
|
#define VALIDATOR_MAGIC 0x56616c3fU /* Val?. */
|
||||||
@@ -179,8 +181,7 @@ fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
|
|||||||
goto free_event;
|
goto free_event;
|
||||||
}
|
}
|
||||||
UNLOCK(&val->lock);
|
UNLOCK(&val->lock);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
"fetch_callback_validator: got %s",
|
"fetch_callback_validator: got %s",
|
||||||
dns_result_totext(devent->result));
|
dns_result_totext(devent->result));
|
||||||
@@ -227,8 +228,7 @@ keyvalidated(isc_task_t *task, isc_event_t *event) {
|
|||||||
goto free_event;
|
goto free_event;
|
||||||
}
|
}
|
||||||
UNLOCK(&val->lock);
|
UNLOCK(&val->lock);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
"keyvalidated: got %s",
|
"keyvalidated: got %s",
|
||||||
dns_result_totext(devent->result));
|
dns_result_totext(devent->result));
|
||||||
@@ -241,6 +241,45 @@ keyvalidated(isc_task_t *task, isc_event_t *event) {
|
|||||||
isc_event_free(&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
|
* 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
|
* 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",
|
"verify failure: %s",
|
||||||
dns_result_totext(result));
|
dns_result_totext(result));
|
||||||
}
|
}
|
||||||
|
if (result == ISC_R_NOMORE)
|
||||||
|
result = ISC_R_NOTFOUND;
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,8 +623,7 @@ nxtvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
|||||||
result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
|
result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
validator_done(val, ISC_R_NOTFOUND);
|
validator_done(val, ISC_R_NOTFOUND);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
result = ISC_R_SUCCESS;
|
result = ISC_R_SUCCESS;
|
||||||
|
|
||||||
for (;
|
for (;
|
||||||
@@ -642,7 +682,7 @@ nxtvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
|||||||
&qname);
|
&qname);
|
||||||
qrdataset = ISC_LIST_HEAD(qname->list);
|
qrdataset = ISC_LIST_HEAD(qname->list);
|
||||||
qtype = qrdataset->type;
|
qtype = qrdataset->type;
|
||||||
if (qtype > 128) {
|
if (qtype >= 128) {
|
||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
"invalid type %d", qtype);
|
"invalid type %d", qtype);
|
||||||
continue;
|
continue;
|
||||||
@@ -655,8 +695,7 @@ nxtvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
|||||||
"type should not be present");
|
"type should not be present");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
} else if (order > 0) {
|
||||||
else if (order > 0) {
|
|
||||||
result = dns_rdataset_first(val->event->rdataset);
|
result = dns_rdataset_first(val->event->rdataset);
|
||||||
INSIST(result == ISC_R_SUCCESS);
|
INSIST(result == ISC_R_SUCCESS);
|
||||||
dns_rdataset_current(val->event->rdataset, &rdata);
|
dns_rdataset_current(val->event->rdataset, &rdata);
|
||||||
@@ -674,8 +713,7 @@ nxtvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
validator_log(val, ISC_LOG_DEBUG(3),
|
validator_log(val, ISC_LOG_DEBUG(3),
|
||||||
"nxt owner name is not less");
|
"nxt owner name is not less");
|
||||||
continue;
|
continue;
|
||||||
@@ -692,6 +730,144 @@ nxtvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
|||||||
return (result);
|
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
|
static void
|
||||||
validator_start(isc_task_t *task, isc_event_t *event) {
|
validator_start(isc_task_t *task, isc_event_t *event) {
|
||||||
dns_validator_t *val;
|
dns_validator_t *val;
|
||||||
@@ -712,14 +888,22 @@ validator_start(isc_task_t *task, isc_event_t *event) {
|
|||||||
* could still get complicated.
|
* could still get complicated.
|
||||||
*/
|
*/
|
||||||
result = validate(val, ISC_FALSE);
|
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)
|
val->event->sigrdataset == NULL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This is a nonexistence validation.
|
* This is a nonexistence validation.
|
||||||
*/
|
*/
|
||||||
result = nxtvalidate(val, ISC_FALSE);
|
result = nxtvalidate(val, ISC_FALSE);
|
||||||
|
} else {
|
||||||
|
/* This shouldn't happen */
|
||||||
|
INSIST(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != DNS_R_WAIT)
|
if (result != DNS_R_WAIT)
|
||||||
@@ -781,6 +965,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name,
|
|||||||
val->action = action;
|
val->action = action;
|
||||||
val->arg = arg;
|
val->arg = arg;
|
||||||
val->queryname = NULL;
|
val->queryname = NULL;
|
||||||
|
val->labels = 0;
|
||||||
val->magic = VALIDATOR_MAGIC;
|
val->magic = VALIDATOR_MAGIC;
|
||||||
|
|
||||||
isc_task_send(task, (isc_event_t **)&event);
|
isc_task_send(task, (isc_event_t **)&event);
|
||||||
|
Reference in New Issue
Block a user