mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 14:07:59 +00:00
snapshot - partial support for negative answer verification and a couple bug
fixes.
This commit is contained in:
parent
53c892082e
commit
e83cae7fa8
@ -33,7 +33,9 @@
|
||||
#include <dns/events.h>
|
||||
#include <dns/keytable.h>
|
||||
#include <dns/log.h>
|
||||
#include <dns/message.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/nxt.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/rdatatype.h>
|
||||
#include <dns/rdataset.h>
|
||||
@ -75,18 +77,22 @@ struct dns_validator {
|
||||
isc_task_t * task;
|
||||
isc_taskaction_t action;
|
||||
void * arg;
|
||||
dns_name_t * queryname;
|
||||
};
|
||||
|
||||
#define VALIDATOR_MAGIC 0x56616c3fU /* Val?. */
|
||||
#define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
|
||||
|
||||
#define VALATTR_SHUTDOWN 0x01
|
||||
#define VALATTR_NEGATIVE 0x02
|
||||
#define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
|
||||
|
||||
static inline isc_result_t get_dst_key(dns_validator_t *val,
|
||||
dns_siginfo_t *siginfo,
|
||||
dns_rdataset_t *rdataset);
|
||||
static inline isc_result_t validate(dns_validator_t *val, isc_boolean_t resume);
|
||||
static inline isc_result_t nxtvalidate(dns_validator_t *val,
|
||||
isc_boolean_t resume);
|
||||
|
||||
static void validator_log(dns_validator_t *val, int level,
|
||||
const char *fmt, ...);
|
||||
@ -130,6 +136,12 @@ validator_done(dns_validator_t *val, isc_result_t result) {
|
||||
val->event->type = DNS_EVENT_VALIDATORDONE;
|
||||
val->event->action = val->action;
|
||||
val->event->arg = val->arg;
|
||||
if ((val->attributes & VALATTR_NEGATIVE) != 0) {
|
||||
val->event->rdataset = NULL;
|
||||
val->event->sigrdataset = NULL;
|
||||
if (val->queryname != NULL)
|
||||
val->event->name = val->queryname;
|
||||
}
|
||||
isc_task_sendanddetach(&task, (isc_event_t **)&val->event);
|
||||
|
||||
}
|
||||
@ -156,7 +168,10 @@ fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
|
||||
goto free_event;
|
||||
}
|
||||
LOCK(&val->lock);
|
||||
result = validate(val, ISC_TRUE);
|
||||
if (val->attributes & VALATTR_NEGATIVE)
|
||||
result = nxtvalidate(val, ISC_TRUE);
|
||||
else
|
||||
result = validate(val, ISC_TRUE);
|
||||
if (result != DNS_R_CONTINUE) {
|
||||
validator_done(val, result);
|
||||
goto free_event;
|
||||
@ -195,7 +210,10 @@ keyvalidated(isc_task_t *task, isc_event_t *event) {
|
||||
goto free_event;
|
||||
}
|
||||
LOCK(&val->lock);
|
||||
result = validate(val, ISC_TRUE);
|
||||
if (val->attributes & VALATTR_NEGATIVE)
|
||||
result = nxtvalidate(val, ISC_TRUE);
|
||||
else
|
||||
result = validate(val, ISC_TRUE);
|
||||
if (result != DNS_R_WAIT)
|
||||
validator_done(val, result);
|
||||
UNLOCK(&val->lock);
|
||||
@ -513,6 +531,12 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
|
||||
result = dns_dnssec_verify(event->name, event->rdataset,
|
||||
val->key, val->view->mctx, &rdata);
|
||||
if (val->keynode != NULL)
|
||||
dns_keytable_detachkeynode(val->keytable,
|
||||
&val->keynode);
|
||||
else if (val->key != NULL)
|
||||
dst_key_free(val->key);
|
||||
val->key = NULL;
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
event->rdataset->trust = dns_trust_secure;
|
||||
event->sigrdataset->trust = dns_trust_secure;
|
||||
@ -524,6 +548,130 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
static inline isc_result_t
|
||||
nxtvalidate(dns_validator_t *val, isc_boolean_t resume) {
|
||||
dns_name_t *name;
|
||||
dns_rdata_t rdata;
|
||||
dns_message_t *message = val->event->message;
|
||||
isc_result_t result;
|
||||
int order;
|
||||
isc_region_t r;
|
||||
dns_name_t nextname;
|
||||
isc_boolean_t firstname = ISC_TRUE;
|
||||
|
||||
if (!resume) {
|
||||
val->attributes |= VALATTR_NEGATIVE;
|
||||
result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
validator_done(val, ISC_R_NOTFOUND);
|
||||
}
|
||||
else
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
for (;
|
||||
result == ISC_R_SUCCESS;
|
||||
result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
|
||||
{
|
||||
dns_rdataset_t *rdataset, *sigrdataset;
|
||||
|
||||
name = NULL;
|
||||
dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
|
||||
if (!resume || !firstname) {
|
||||
rdataset = ISC_LIST_HEAD(name->list);
|
||||
for (rdataset = ISC_LIST_HEAD(name->list);
|
||||
rdataset != NULL;
|
||||
rdataset = ISC_LIST_NEXT(rdataset, link))
|
||||
{
|
||||
if (rdataset->type != dns_rdatatype_nxt)
|
||||
continue;
|
||||
for (sigrdataset = ISC_LIST_HEAD(name->list);
|
||||
sigrdataset != NULL;
|
||||
sigrdataset = ISC_LIST_NEXT(sigrdataset,
|
||||
link))
|
||||
{
|
||||
if (sigrdataset->type ==
|
||||
dns_rdatatype_sig
|
||||
&&
|
||||
sigrdataset->covers ==
|
||||
rdataset->type)
|
||||
break;
|
||||
}
|
||||
if (sigrdataset != NULL)
|
||||
break;
|
||||
}
|
||||
if (rdataset == NULL)
|
||||
continue;
|
||||
val->event->rdataset = rdataset;
|
||||
val->event->sigrdataset = sigrdataset;
|
||||
val->queryname = val->event->name;
|
||||
val->event->name = name;
|
||||
}
|
||||
firstname = ISC_FALSE;
|
||||
result = validate(val, resume);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
order = dns_name_compare(val->queryname, val->event->name);
|
||||
if (order == 0) {
|
||||
dns_name_t *qname = NULL;
|
||||
dns_rdataset_t *qrdataset = NULL;
|
||||
dns_rdatatype_t qtype;
|
||||
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"nxt owner is the same");
|
||||
result = dns_message_firstname(val->event->message,
|
||||
DNS_SECTION_QUESTION);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_message_currentname(val->event->message,
|
||||
DNS_SECTION_QUESTION,
|
||||
&qname);
|
||||
qrdataset = ISC_LIST_HEAD(qname->list);
|
||||
qtype = qrdataset->type;
|
||||
if (qtype > 128) {
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"invalid type %d", qtype);
|
||||
continue;
|
||||
}
|
||||
dns_rdataset_first(val->event->rdataset);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_rdataset_current(val->event->rdataset, &rdata);
|
||||
if (dns_nxt_typepresent(&rdata, qtype)) {
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"type should not be present");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (order > 0) {
|
||||
result = dns_rdataset_first(val->event->rdataset);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_rdataset_current(val->event->rdataset, &rdata);
|
||||
dns_rdata_toregion(&rdata, &r);
|
||||
dns_name_init(&nextname, NULL);
|
||||
dns_name_fromregion(&nextname, &r);
|
||||
order = dns_name_compare(val->queryname, &nextname);
|
||||
if (order >= 0) {
|
||||
INSIST(val->siginfo != NULL);
|
||||
if (!dns_name_equal(&val->siginfo->signer,
|
||||
&nextname))
|
||||
{
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"next name is not greater");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"nxt owner name is not less");
|
||||
continue;
|
||||
}
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"nxt range and/or bitmask is ok");
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
validator_start(isc_task_t *task, isc_event_t *event) {
|
||||
dns_validator_t *val;
|
||||
@ -544,11 +692,14 @@ validator_start(isc_task_t *task, isc_event_t *event) {
|
||||
* could still get complicated.
|
||||
*/
|
||||
result = validate(val, ISC_FALSE);
|
||||
} else {
|
||||
}
|
||||
else if (val->event->rdataset == NULL &&
|
||||
val->event->sigrdataset == NULL)
|
||||
{
|
||||
/*
|
||||
* This is a nonexistence validation.
|
||||
*/
|
||||
result = ISC_R_NOTIMPLEMENTED;
|
||||
result = nxtvalidate(val, ISC_FALSE);
|
||||
}
|
||||
|
||||
if (result != DNS_R_WAIT)
|
||||
@ -608,6 +759,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name,
|
||||
val->task = task;
|
||||
val->action = action;
|
||||
val->arg = arg;
|
||||
val->queryname = NULL;
|
||||
val->magic = VALIDATOR_MAGIC;
|
||||
|
||||
isc_task_send(task, (isc_event_t **)&event);
|
||||
@ -655,10 +807,10 @@ destroy(dns_validator_t *val) {
|
||||
REQUIRE(val->event == NULL);
|
||||
REQUIRE(val->fetch == NULL);
|
||||
|
||||
if (val->key != NULL)
|
||||
dst_key_free(val->key);
|
||||
if (val->keynode != NULL)
|
||||
dns_keytable_detachkeynode(val->keytable, &val->keynode);
|
||||
else if (val->key != NULL)
|
||||
dst_key_free(val->key);
|
||||
isc_mutex_destroy(&val->lock);
|
||||
mctx = val->view->mctx;
|
||||
dns_view_detach(&val->view);
|
||||
|
Loading…
x
Reference in New Issue
Block a user