📄 validator.c
字号:
/* * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. *//* $Id: validator.c,v 1.91.2.5.8.21 2005/11/02 02:07:47 marka Exp $ */#include <config.h>#include <isc/mem.h>#include <isc/print.h>#include <isc/string.h>#include <isc/task.h>#include <isc/util.h>#include <dns/db.h>#include <dns/ds.h>#include <dns/dnssec.h>#include <dns/events.h>#include <dns/keytable.h>#include <dns/log.h>#include <dns/message.h>#include <dns/ncache.h>#include <dns/nsec.h>#include <dns/rdata.h>#include <dns/rdatastruct.h>#include <dns/rdataset.h>#include <dns/rdatatype.h>#include <dns/resolver.h>#include <dns/result.h>#include <dns/validator.h>#include <dns/view.h>#define VALIDATOR_MAGIC ISC_MAGIC('V', 'a', 'l', '?')#define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)#define VALATTR_SHUTDOWN 0x0001#define VALATTR_FOUNDNONEXISTENCE 0x0002#define VALATTR_TRIEDVERIFY 0x0004#define VALATTR_NEGATIVE 0x0008#define VALATTR_INSECURITY 0x0010#define VALATTR_DLVTRIED 0x0020#define VALATTR_NEEDNOQNAME 0x0100#define VALATTR_NEEDNOWILDCARD 0x0200#define VALATTR_NEEDNODATA 0x0400#define VALATTR_FOUNDNOQNAME 0x1000#define VALATTR_FOUNDNOWILDCARD 0x2000#define VALATTR_FOUNDNODATA 0x4000#define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0)#define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0)#define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)#define DLVTRIED(val) ((val->attributes & VALATTR_DLVTRIED) != 0)#define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)static voiddestroy(dns_validator_t *val);static isc_result_tget_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo, dns_rdataset_t *rdataset);static isc_result_tvalidate(dns_validator_t *val, isc_boolean_t resume);static isc_result_tvalidatezonekey(dns_validator_t *val);static isc_result_tnsecvalidate(dns_validator_t *val, isc_boolean_t resume);static isc_result_tproveunsecure(dns_validator_t *val, isc_boolean_t resume);static voidvalidator_logv(dns_validator_t *val, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *fmt, va_list ap) ISC_FORMAT_PRINTF(5, 0);static voidvalidator_log(dns_validator_t *val, int level, const char *fmt, ...) ISC_FORMAT_PRINTF(3, 4);static voidvalidator_logcreate(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, const char *caller, const char *operation);static isc_result_tdlv_validatezonekey(dns_validator_t *val);static isc_result_tdlv_validator_start(dns_validator_t *val);static isc_result_tfinddlvsep(dns_validator_t *val, isc_boolean_t resume);static inline voidmarkanswer(dns_validator_t *val) { validator_log(val, ISC_LOG_DEBUG(3), "marking as answer"); if (val->event->rdataset) val->event->rdataset->trust = dns_trust_answer; if (val->event->sigrdataset) val->event->sigrdataset->trust = dns_trust_answer;}static voidvalidator_done(dns_validator_t *val, isc_result_t result) { isc_task_t *task; if (val->event == NULL) return; /* * Caller must be holding the lock. */ val->event->result = result; task = val->event->ev_sender; val->event->ev_sender = val; val->event->ev_type = DNS_EVENT_VALIDATORDONE; val->event->ev_action = val->action; val->event->ev_arg = val->arg; isc_task_sendanddetach(&task, (isc_event_t **)&val->event);}static inline isc_boolean_texit_check(dns_validator_t *val) { /* * Caller must be holding the lock. */ if (!SHUTDOWN(val)) return (ISC_FALSE); INSIST(val->event == NULL); if (val->fetch != NULL || val->subvalidator != NULL) return (ISC_FALSE); return (ISC_TRUE);}static voidauth_nonpending(dns_message_t *message) { isc_result_t result; dns_name_t *name; dns_rdataset_t *rdataset; for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); result == ISC_R_SUCCESS; result = dns_message_nextname(message, DNS_SECTION_AUTHORITY)) { name = NULL; dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name); for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { if (rdataset->trust == dns_trust_pending) rdataset->trust = dns_trust_authauthority; } }}static isc_boolean_tisdelegation(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_nsec, &set); if (result != ISC_R_SUCCESS) return (ISC_FALSE); } INSIST(set.type == dns_rdatatype_nsec); found = ISC_FALSE; result = dns_rdataset_first(&set); if (result == ISC_R_SUCCESS) { dns_rdataset_current(&set, &rdata); found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns); } dns_rdataset_disassociate(&set); return (found);}static voidfetch_callback_validator(isc_task_t *task, isc_event_t *event) { dns_fetchevent_t *devent; dns_validator_t *val; dns_rdataset_t *rdataset; isc_boolean_t want_destroy; isc_result_t result; isc_result_t eresult; UNUSED(task); INSIST(event->ev_type == DNS_EVENT_FETCHDONE); devent = (dns_fetchevent_t *)event; val = devent->ev_arg; rdataset = &val->frdataset; eresult = devent->result; /* Free resources which are not of interest. */ if (devent->node != NULL) dns_db_detachnode(devent->db, &devent->node); if (devent->db != NULL) dns_db_detach(&devent->db); if (dns_rdataset_isassociated(&val->fsigrdataset)) dns_rdataset_disassociate(&val->fsigrdataset); isc_event_free(&event); dns_resolver_destroyfetch(&val->fetch); INSIST(val->event != NULL); validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_validator"); LOCK(&val->lock); if (eresult == ISC_R_SUCCESS) { validator_log(val, ISC_LOG_DEBUG(3), "keyset with trust %d", rdataset->trust); /* * Only extract the dst key if the keyset is secure. */ if (rdataset->trust >= dns_trust_secure) { result = get_dst_key(val, val->siginfo, rdataset); if (result == ISC_R_SUCCESS) val->keyset = &val->frdataset; } result = validate(val, ISC_TRUE); if (result != DNS_R_WAIT) validator_done(val, result); } else { validator_log(val, ISC_LOG_DEBUG(3), "fetch_callback_validator: got %s", isc_result_totext(eresult)); if (eresult == ISC_R_CANCELED) validator_done(val, eresult); else validator_done(val, DNS_R_NOVALIDKEY); } want_destroy = exit_check(val); UNLOCK(&val->lock); if (want_destroy) destroy(val);}static voiddsfetched(isc_task_t *task, isc_event_t *event) { dns_fetchevent_t *devent; dns_validator_t *val; dns_rdataset_t *rdataset; isc_boolean_t want_destroy; isc_result_t result; isc_result_t eresult; UNUSED(task); INSIST(event->ev_type == DNS_EVENT_FETCHDONE); devent = (dns_fetchevent_t *)event; val = devent->ev_arg; rdataset = &val->frdataset; eresult = devent->result; /* Free resources which are not of interest. */ if (devent->node != NULL) dns_db_detachnode(devent->db, &devent->node); if (devent->db != NULL) dns_db_detach(&devent->db); if (dns_rdataset_isassociated(&val->fsigrdataset)) dns_rdataset_disassociate(&val->fsigrdataset); isc_event_free(&event); dns_resolver_destroyfetch(&val->fetch); INSIST(val->event != NULL); validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched"); LOCK(&val->lock); if (eresult == ISC_R_SUCCESS) { validator_log(val, ISC_LOG_DEBUG(3), "dsset with trust %d", rdataset->trust); val->dsset = &val->frdataset; result = validatezonekey(val); if (result != DNS_R_WAIT) validator_done(val, result); } else if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NCACHENXRRSET) { validator_log(val, ISC_LOG_DEBUG(3), "falling back to insecurity proof"); val->attributes |= VALATTR_INSECURITY; result = proveunsecure(val, ISC_FALSE); if (result != DNS_R_WAIT) validator_done(val, result); } else { validator_log(val, ISC_LOG_DEBUG(3), "dsfetched: got %s", isc_result_totext(eresult)); if (eresult == ISC_R_CANCELED) validator_done(val, eresult); else validator_done(val, DNS_R_NOVALIDDS); } want_destroy = exit_check(val); UNLOCK(&val->lock); if (want_destroy) destroy(val);}/* * XXX there's too much duplicated code here. */static voiddsfetched2(isc_task_t *task, isc_event_t *event) { dns_fetchevent_t *devent; dns_validator_t *val; dns_name_t *tname; isc_boolean_t want_destroy; isc_result_t result; isc_result_t eresult; UNUSED(task); INSIST(event->ev_type == DNS_EVENT_FETCHDONE); devent = (dns_fetchevent_t *)event; val = devent->ev_arg; eresult = devent->result; /* Free resources which are not of interest. */ if (devent->node != NULL) dns_db_detachnode(devent->db, &devent->node); if (devent->db != NULL) dns_db_detach(&devent->db); if (dns_rdataset_isassociated(&val->fsigrdataset)) dns_rdataset_disassociate(&val->fsigrdataset); dns_resolver_destroyfetch(&val->fetch); INSIST(val->event != NULL); validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched2"); LOCK(&val->lock); if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NCACHENXRRSET) { /* * There is no DS. If this is a delegation, we're done. */ tname = dns_fixedname_name(&devent->foundname); if (isdelegation(tname, &val->frdataset, eresult)) { if (val->mustbesecure) { validator_log(val, ISC_LOG_WARNING, "must be secure failure"); validator_done(val, DNS_R_MUSTBESECURE); } else { markanswer(val); 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) { /* * Either there is a DS or this is not a zone cut. Continue. */ result = proveunsecure(val, ISC_TRUE); if (result != DNS_R_WAIT) validator_done(val, result); } else { if (eresult == ISC_R_CANCELED) validator_done(val, eresult); else validator_done(val, DNS_R_NOVALIDDS); } isc_event_free(&event); want_destroy = exit_check(val); UNLOCK(&val->lock); if (want_destroy) destroy(val);}static voidkeyvalidated(isc_task_t *task, isc_event_t *event) { dns_validatorevent_t *devent; dns_validator_t *val; isc_boolean_t want_destroy; isc_result_t result; isc_result_t eresult; UNUSED(task); INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE); devent = (dns_validatorevent_t *)event; val = devent->ev_arg; eresult = devent->result; isc_event_free(&event); dns_validator_destroy(&val->subvalidator); INSIST(val->event != NULL); validator_log(val, ISC_LOG_DEBUG(3), "in keyvalidated"); LOCK(&val->lock); if (eresult == ISC_R_SUCCESS) { validator_log(val, ISC_LOG_DEBUG(3), "keyset with trust %d", val->frdataset.trust); /* * Only extract the dst key if the keyset is secure. */ if (val->frdataset.trust >= dns_trust_secure) (void) get_dst_key(val, val->siginfo, &val->frdataset); result = validate(val, ISC_TRUE); if (result != DNS_R_WAIT) validator_done(val, result); } else { validator_log(val, ISC_LOG_DEBUG(3), "keyvalidated: got %s", isc_result_totext(eresult)); validator_done(val, eresult); } want_destroy = exit_check(val); UNLOCK(&val->lock); if (want_destroy) destroy(val);}static voiddsvalidated(isc_task_t *task, isc_event_t *event) { dns_validatorevent_t *devent; dns_validator_t *val; isc_boolean_t want_destroy; isc_result_t result; isc_result_t eresult; UNUSED(task);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -