⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 validator.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2000-2002  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 INTERNET SOFTWARE CONSORTIUM * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * INTERNET SOFTWARE CONSORTIUM 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 2002/08/05 06:57:12 marka Exp $ */#include <config.h>#include <isc/mem.h>#include <isc/print.h>#include <isc/task.h>#include <isc/util.h>#include <dns/db.h>#include <dns/dnssec.h>#include <dns/events.h>#include <dns/keytable.h>#include <dns/log.h>#include <dns/message.h>#include <dns/nxt.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		0x01#define VALATTR_FOUNDNONEXISTENCE	0x02#define VALATTR_TRIEDVERIFY		0x04#define SHUTDOWN(v)		(((v)->attributes & VALATTR_SHUTDOWN) != 0)static voidnullkeyvalidated(isc_task_t *task, isc_event_t *event);static inline isc_boolean_tcontainsnullkey(dns_validator_t *val, dns_rdataset_t *rdataset);static inline isc_result_tget_dst_key(dns_validator_t *val, dns_rdata_sig_t *siginfo,	    dns_rdataset_t *rdataset);static inline isc_result_tvalidate(dns_validator_t *val, isc_boolean_t resume);static inline isc_result_tnxtvalidate(dns_validator_t *val, isc_boolean_t resume);static inline isc_result_tproveunsecure(dns_validator_t *val, isc_boolean_t resume);static voidvalidator_log(dns_validator_t *val, int level, const char *fmt, ...)     ISC_FORMAT_PRINTF(3, 4);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 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 voidfetch_callback_validator(isc_task_t *task, isc_event_t *event) {	dns_fetchevent_t *devent;	dns_validator_t *val;	dns_rdataset_t *rdataset;	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;	isc_event_free(&event);	dns_resolver_destroyfetch(&val->fetch);	if (SHUTDOWN(val)) {		dns_validator_destroy(&val);		return;	}	if (val->event == NULL) {		validator_log(val, ISC_LOG_DEBUG(3),			      "fetch_callback_validator: event == NULL");		return;	}	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);			goto out;		}	} else {		validator_log(val, ISC_LOG_DEBUG(3),			      "fetch_callback_validator: got %s",			      dns_result_totext(eresult));		validator_done(val, DNS_R_NOVALIDKEY);	} out:	UNLOCK(&val->lock);	/*	 * Free stuff from the event.	 */	if (dns_rdataset_isassociated(&val->frdataset) &&	    val->keyset != &val->frdataset)		dns_rdataset_disassociate(&val->frdataset);	if (dns_rdataset_isassociated(&val->fsigrdataset))		dns_rdataset_disassociate(&val->fsigrdataset);}static voidfetch_callback_nullkey(isc_task_t *task, isc_event_t *event) {	dns_fetchevent_t *devent;	dns_validator_t *val;	dns_rdataset_t *rdataset, *sigrdataset;	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;	sigrdataset = &val->fsigrdataset;	eresult = devent->result;	dns_resolver_destroyfetch(&val->fetch);	if (SHUTDOWN(val)) {		dns_validator_destroy(&val);		isc_event_free(&event);		return;	}	if (val->event == NULL) {		validator_log(val, ISC_LOG_DEBUG(3),			      "fetch_callback_nullkey: event == NULL");		isc_event_free(&event);		return;	}	validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_nullkey");	LOCK(&val->lock);	if (eresult == ISC_R_SUCCESS) {		if (!containsnullkey(val, rdataset)) {			/*			 * No null key.			 */			validator_log(val, ISC_LOG_DEBUG(3),				      "found a keyset, no null key");			result = proveunsecure(val, ISC_TRUE);			if (result != DNS_R_WAIT)				validator_done(val, result);			else {				/*				 * Don't free rdataset & sigrdataset, since				 * they'll be freed in nullkeyvalidated.				 */				isc_event_free(&event);				UNLOCK(&val->lock);				return;			}		} else {			validator_log(val, ISC_LOG_DEBUG(3),				      "found a keyset with a null key");			if (rdataset->trust >= dns_trust_secure) {				validator_log(val, ISC_LOG_DEBUG(3),					      "insecurity proof succeeded");				val->event->rdataset->trust = dns_trust_answer;				validator_done(val, ISC_R_SUCCESS);			} else if (!dns_rdataset_isassociated(sigrdataset)) {				validator_log(val, ISC_LOG_DEBUG(3),					      "insecurity proof failed");				validator_done(val, DNS_R_NOTINSECURE);			} else {				dns_name_t *tname;				tname = dns_fixedname_name(&devent->foundname);				result = dns_validator_create(val->view, tname,							   dns_rdatatype_key,							   rdataset,							   sigrdataset, NULL,							   0, val->task,							   nullkeyvalidated,							   val,							   &val->keyvalidator);				if (result != ISC_R_SUCCESS)					validator_done(val, result);				/*				 * Don't free rdataset & sigrdataset, since				 * they'll be freed in nullkeyvalidated.				 */				isc_event_free(&event);				UNLOCK(&val->lock);				return;			}		}	} else if (eresult ==  DNS_R_NCACHENXDOMAIN ||		   eresult == DNS_R_NCACHENXRRSET ||		   eresult == DNS_R_NXDOMAIN ||		   eresult == DNS_R_NXRRSET)	{		/*		 * No keys.		 */		validator_log(val, ISC_LOG_DEBUG(3),			      "no keys found");		result = proveunsecure(val, ISC_TRUE);		if (result != DNS_R_WAIT)			validator_done(val, result);	} else {		validator_log(val, ISC_LOG_DEBUG(3),			      "fetch_callback_nullkey: got %s",			      dns_result_totext(eresult));		validator_done(val, DNS_R_NOVALIDKEY);	}	UNLOCK(&val->lock);	/*	 * Free stuff from the event.	 */	if (dns_rdataset_isassociated(&val->frdataset))		dns_rdataset_disassociate(&val->frdataset);	if (dns_rdataset_isassociated(&val->fsigrdataset))		dns_rdataset_disassociate(&val->fsigrdataset);	isc_event_free(&event);}static voidkeyvalidated(isc_task_t *task, isc_event_t *event) {	dns_validatorevent_t *devent;	dns_validator_t *val;	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);	if (SHUTDOWN(val)) {		dns_validator_destroy(&val);		return;	}	if (val->event == NULL)		return;	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);			goto out;		}	} else {		validator_log(val, ISC_LOG_DEBUG(3),			      "keyvalidated: got %s",			      dns_result_totext(eresult));		validator_done(val, eresult);	} out:	UNLOCK(&val->lock);	dns_validator_destroy(&val->keyvalidator);	/*	 * Free stuff from the event.	 */	if (dns_rdataset_isassociated(&val->frdataset))		dns_rdataset_disassociate(&val->frdataset);	if (dns_rdataset_isassociated(&val->fsigrdataset))		dns_rdataset_disassociate(&val->fsigrdataset);}static isc_boolean_tnxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,		      dns_rdataset_t *nxtset, dns_rdataset_t *signxtset){	int order;	dns_rdata_t rdata = DNS_RDATA_INIT;	isc_boolean_t isnxdomain;	isc_result_t result;	INSIST(DNS_MESSAGE_VALID(val->event->message));	if (val->event->message->rcode == dns_rcode_nxdomain)		isnxdomain = ISC_TRUE;	else		isnxdomain = ISC_FALSE;	result = dns_rdataset_first(nxtset);	if (result != ISC_R_SUCCESS) {		validator_log(val, ISC_LOG_DEBUG(3),			"failure processing NXT set");		return (ISC_FALSE);	}	dns_rdataset_current(nxtset, &rdata);	validator_log(val, ISC_LOG_DEBUG(3),		      "looking for relevant nxt");	order = dns_name_compare(val->event->name, nxtname);	if (order == 0) {		/*		 * The names are the same.  Look for the type present bit.		 */		if (isnxdomain) {			validator_log(val, ISC_LOG_DEBUG(3),				      "NXT record seen at nonexistent name");			return (ISC_FALSE);		}		if (val->event->type >= 128) {			validator_log(val, ISC_LOG_DEBUG(3), "invalid type %d",				      val->event->type);			return (ISC_FALSE);		}		if (dns_nxt_typepresent(&rdata, val->event->type)) {			validator_log(val, ISC_LOG_DEBUG(3),				      "type should not be present");			return (ISC_FALSE);		}		validator_log(val, ISC_LOG_DEBUG(3), "nxt bitmask ok");	} else if (order > 0) {		dns_rdata_nxt_t nxt;		/*		 * The NXT owner name is less than the nonexistent name.		 */		if (!isnxdomain) {			validator_log(val, ISC_LOG_DEBUG(3),				      "missing NXT record at name");			return (ISC_FALSE);		}		if (dns_name_issubdomain(val->event->name, nxtname) &&		    dns_nxt_typepresent(&rdata, dns_rdatatype_ns) &&		    !dns_nxt_typepresent(&rdata, dns_rdatatype_soa))		{			/*			 * This NXT record is from somewhere higher in			 * the DNS, and at the parent of a delegation.			 * It can not be legitimately used here.			 */			validator_log(val, ISC_LOG_DEBUG(3),				      "ignoring parent nxt");			return (ISC_FALSE);		}		result = dns_rdata_tostruct(&rdata, &nxt, NULL);		if (result != ISC_R_SUCCESS)			return (ISC_FALSE);		dns_rdata_reset(&rdata);		order = dns_name_compare(val->event->name, &nxt.next);		if (order >= 0) {			/*			 * The NXT next name is less than the nonexistent			 * name.  This is only ok if the next name is the zone			 * name.			 */			dns_rdata_sig_t siginfo;			result = dns_rdataset_first(signxtset);			if (result != ISC_R_SUCCESS) {				validator_log(val, ISC_LOG_DEBUG(3),					"failure processing SIG NXT set");				dns_rdata_freestruct(&nxt);				return (ISC_FALSE);			}			dns_rdataset_current(signxtset, &rdata);			result = dns_rdata_tostruct(&rdata, &siginfo, NULL);			if (result != ISC_R_SUCCESS) {				validator_log(val, ISC_LOG_DEBUG(3),					"failure processing SIG NXT set");				dns_rdata_freestruct(&nxt);				return (ISC_FALSE);			}			if (!dns_name_equal(&siginfo.signer, &nxt.next)) {				validator_log(val, ISC_LOG_DEBUG(3),					"next name is not greater");				dns_rdata_freestruct(&nxt);				return (ISC_FALSE);			}			validator_log(val, ISC_LOG_DEBUG(3),				      "nxt points to zone apex, ok");		}		dns_rdata_freestruct(&nxt);		validator_log(val, ISC_LOG_DEBUG(3),			      "nxt range ok");	} else {		validator_log(val, ISC_LOG_DEBUG(3),			"nxt owner name is not less");		/*		 * The NXT owner name is greater than the supposedly		 * nonexistent name.  This NXT is irrelevant.		 */		return (ISC_FALSE);	}	return (ISC_TRUE);}static voidauthvalidated(isc_task_t *task, isc_event_t *event) {	dns_validatorevent_t *devent;	dns_validator_t *val;	dns_rdataset_t *rdataset, *sigrdataset;	isc_result_t result;	isc_result_t eresult;	UNUSED(task);	INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);	devent = (dns_validatorevent_t *)event;	rdataset = devent->rdataset;	sigrdataset = devent->sigrdataset;	val = devent->ev_arg;	eresult = devent->result;	dns_validator_destroy(&val->authvalidator);	if (SHUTDOWN(val)) {		dns_validator_destroy(&val);		return;	}	if (val->event == NULL)		return;	validator_log(val, ISC_LOG_DEBUG(3), "in authvalidated");	LOCK(&val->lock);	if (eresult != ISC_R_SUCCESS) {		validator_log(val, ISC_LOG_DEBUG(3),			      "authvalidated: got %s",			      dns_result_totext(eresult));		result = nxtvalidate(val, ISC_TRUE);		if (result != DNS_R_WAIT)			validator_done(val, result);	} else {		if (rdataset->type == dns_rdatatype_nxt &&		    nxtprovesnonexistence(val, devent->name, rdataset,			    		  sigrdataset))			val->attributes |= VALATTR_FOUNDNONEXISTENCE;		result = nxtvalidate(val, ISC_TRUE);		if (result != DNS_R_WAIT)			validator_done(val, result);	}	UNLOCK(&val->lock);	/*	 * Free stuff from the event.	 */	isc_event_free(&event);}static voidnegauthvalidated(isc_task_t *task, isc_event_t *event) {	dns_validatorevent_t *devent;	dns_validator_t *val;	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->authvalidator);	if (SHUTDOWN(val)) {		dns_validator_destroy(&val);		return;	}	if (val->event == NULL)		return;	validator_log(val, ISC_LOG_DEBUG(3), "in negauthvalidated");	LOCK(&val->lock);	if (eresult == ISC_R_SUCCESS) {		val->attributes |= VALATTR_FOUNDNONEXISTENCE;		validator_log(val, ISC_LOG_DEBUG(3),			      "nonexistence proof found");		auth_nonpending(val->event->message);		validator_done(val, ISC_R_SUCCESS);	} else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -