query.c

来自「非常好的dns解析软件」· C语言 代码 · 共 2,425 行 · 第 1/5 页

C
2,425
字号
	if (sigrdatasetp != NULL)		sigrdataset = *sigrdatasetp;	else		sigrdataset = NULL;	mname = NULL;	mrdataset = NULL;	result = dns_message_findname(client->message, section,				      name, rdataset->type, rdataset->covers,				      &mname, &mrdataset);	if (result == ISC_R_SUCCESS) {		/*		 * We've already got an RRset of the given name and type.		 * There's nothing else to do;		 */		CTRACE("query_addrrset: dns_message_findname succeeded: done");		if (dbuf != NULL)			query_releasename(client, namep);		return;	} else if (result == DNS_R_NXDOMAIN) {		/*		 * The name doesn't exist.		 */		if (dbuf != NULL)			query_keepname(client, name, dbuf);		dns_message_addname(client->message, name, section);		*namep = NULL;		mname = name;	} else {		RUNTIME_CHECK(result == DNS_R_NXRRSET);		if (dbuf != NULL)			query_releasename(client, namep);	}	if (rdataset->trust != dns_trust_secure &&	    (section == DNS_SECTION_ANSWER ||	     section == DNS_SECTION_AUTHORITY))		client->query.attributes &= ~NS_QUERYATTR_SECURE;	/*	 * Note: we only add SIGs if we've added the type they cover, so	 * we do not need to check if the SIG rdataset is already in the	 * response.	 */	query_addrdataset(client, mname, rdataset);	*rdatasetp = NULL;	if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {		/*		 * We have a signature.  Add it to the response.		 */		ISC_LIST_APPEND(mname->list, sigrdataset, link);		*sigrdatasetp = NULL;	}	CTRACE("query_addrrset: done");}static inline isc_result_tquery_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,	     isc_boolean_t zero_ttl){	dns_name_t *name;	dns_dbnode_t *node;	isc_result_t result, eresult;	dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;	dns_rdataset_t **sigrdatasetp = NULL;	CTRACE("query_addsoa");	/*	 * Initialization.	 */	eresult = ISC_R_SUCCESS;	name = NULL;	rdataset = NULL;	node = NULL;	/*	 * Get resources and make 'name' be the database origin.	 */	result = dns_message_gettempname(client->message, &name);	if (result != ISC_R_SUCCESS)		return (result);	dns_name_init(name, NULL);	dns_name_clone(dns_db_origin(db), name);	rdataset = query_newrdataset(client);	if (rdataset == NULL) {		eresult = DNS_R_SERVFAIL;		goto cleanup;	}	if (WANTDNSSEC(client)) {		sigrdataset = query_newrdataset(client);		if (sigrdataset == NULL) {			eresult = DNS_R_SERVFAIL;			goto cleanup;		}	}	/*	 * Find the SOA.	 */	result = dns_db_getoriginnode(db, &node);	if (result == ISC_R_SUCCESS) {		result = dns_db_findrdataset(db, node, version,					     dns_rdatatype_soa,					     0, client->now, rdataset,					     sigrdataset);	} else {		dns_fixedname_t foundname;		dns_name_t *fname;		dns_fixedname_init(&foundname);		fname = dns_fixedname_name(&foundname);		result = dns_db_find(db, name, version, dns_rdatatype_soa,				     client->query.dboptions, 0, &node,				     fname, rdataset, sigrdataset);	}	if (result != ISC_R_SUCCESS) {		/*		 * This is bad.  We tried to get the SOA RR at the zone top		 * and it didn't work!		 */		eresult = DNS_R_SERVFAIL;	} else {		/*		 * Extract the SOA MINIMUM.		 */		dns_rdata_soa_t soa;		dns_rdata_t rdata = DNS_RDATA_INIT;		result = dns_rdataset_first(rdataset);		RUNTIME_CHECK(result == ISC_R_SUCCESS);		dns_rdataset_current(rdataset, &rdata);		result = dns_rdata_tostruct(&rdata, &soa, NULL);		if (result != ISC_R_SUCCESS)			goto cleanup;		if (zero_ttl) {			rdataset->ttl = 0;			if (sigrdataset != NULL)				sigrdataset->ttl = 0;		}		/*		 * Add the SOA and its SIG to the response, with the		 * TTLs adjusted per RFC2308 section 3.		 */		if (rdataset->ttl > soa.minimum)			rdataset->ttl = soa.minimum;		if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum)			sigrdataset->ttl = soa.minimum;		if (sigrdataset != NULL)			sigrdatasetp = &sigrdataset;		else			sigrdatasetp = NULL;		query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,			       DNS_SECTION_AUTHORITY);	} cleanup:	query_putrdataset(client, &rdataset);	if (sigrdataset != NULL)		query_putrdataset(client, &sigrdataset);	if (name != NULL)		query_releasename(client, &name);	if (node != NULL)		dns_db_detachnode(db, &node);	return (eresult);}static inline isc_result_tquery_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {	dns_name_t *name, *fname;	dns_dbnode_t *node;	isc_result_t result, eresult;	dns_fixedname_t foundname;	dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;	dns_rdataset_t **sigrdatasetp = NULL;	CTRACE("query_addns");	/*	 * Initialization.	 */	eresult = ISC_R_SUCCESS;	name = NULL;	rdataset = NULL;	node = NULL;	dns_fixedname_init(&foundname);	fname = dns_fixedname_name(&foundname);	/*	 * Get resources and make 'name' be the database origin.	 */	result = dns_message_gettempname(client->message, &name);	if (result != ISC_R_SUCCESS) {		CTRACE("query_addns: dns_message_gettempname failed: done");		return (result);	}	dns_name_init(name, NULL);	dns_name_clone(dns_db_origin(db), name);	rdataset = query_newrdataset(client);	if (rdataset == NULL) {		CTRACE("query_addns: query_newrdataset failed");		eresult = DNS_R_SERVFAIL;		goto cleanup;	}	if (WANTDNSSEC(client)) {		sigrdataset = query_newrdataset(client);		if (sigrdataset == NULL) {			CTRACE("query_addns: query_newrdataset failed");			eresult = DNS_R_SERVFAIL;			goto cleanup;		}	}	/*	 * Find the NS rdataset.	 */	result = dns_db_getoriginnode(db, &node);	if (result == ISC_R_SUCCESS) {		result = dns_db_findrdataset(db, node, version,					     dns_rdatatype_ns,					     0, client->now, rdataset,					     sigrdataset);	} else {		CTRACE("query_addns: calling dns_db_find");		result = dns_db_find(db, name, NULL, dns_rdatatype_ns,				     client->query.dboptions, 0, &node,				     fname, rdataset, sigrdataset);		CTRACE("query_addns: dns_db_find complete");	}	if (result != ISC_R_SUCCESS) {		CTRACE("query_addns: "		       "dns_db_findrdataset or dns_db_find failed");		/*		 * This is bad.  We tried to get the NS rdataset at the zone		 * top and it didn't work!		 */		eresult = DNS_R_SERVFAIL;	} else {		if (sigrdataset != NULL)			sigrdatasetp = &sigrdataset;		else			sigrdatasetp = NULL;		query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,			       DNS_SECTION_AUTHORITY);	} cleanup:	CTRACE("query_addns: cleanup");	query_putrdataset(client, &rdataset);	if (sigrdataset != NULL)		query_putrdataset(client, &sigrdataset);	if (name != NULL)		query_releasename(client, &name);	if (node != NULL)		dns_db_detachnode(db, &node);	CTRACE("query_addns: done");	return (eresult);}static inline isc_result_tquery_addcnamelike(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,		   dns_trust_t trust, dns_name_t **anamep, dns_rdatatype_t type){	dns_rdataset_t *rdataset;	dns_rdatalist_t *rdatalist;	dns_rdata_t *rdata;	isc_result_t result;	isc_region_t r;	/*	 * We assume the name data referred to by tname won't go away.	 */	REQUIRE(anamep != NULL);	rdatalist = NULL;	result = dns_message_gettemprdatalist(client->message, &rdatalist);	if (result != ISC_R_SUCCESS)		return (result);	rdata = NULL;	result = dns_message_gettemprdata(client->message, &rdata);	if (result != ISC_R_SUCCESS)		return (result);	rdataset = NULL;	result = dns_message_gettemprdataset(client->message, &rdataset);	if (result != ISC_R_SUCCESS)		return (result);	dns_rdataset_init(rdataset);	result = dns_name_dup(qname, client->mctx, *anamep);	if (result != ISC_R_SUCCESS) {		dns_message_puttemprdataset(client->message, &rdataset);		return (result);	}	rdatalist->type = type;	rdatalist->covers = 0;	rdatalist->rdclass = client->message->rdclass;	rdatalist->ttl = 0;	dns_name_toregion(tname, &r);	rdata->data = r.base;	rdata->length = r.length;	rdata->rdclass = client->message->rdclass;	rdata->type = type;	ISC_LIST_INIT(rdatalist->rdata);	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)		      == ISC_R_SUCCESS);	rdataset->trust = trust;	query_addrrset(client, anamep, &rdataset, NULL, NULL,		       DNS_SECTION_ANSWER);	if (rdataset != NULL) {		if (dns_rdataset_isassociated(rdataset))			dns_rdataset_disassociate(rdataset);		dns_message_puttemprdataset(client->message, &rdataset);	}	return (ISC_R_SUCCESS);}/* * Mark the RRsets as secure.  Update the cache (db) to reflect the * change in trust level. */static voidmark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,	    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset){	isc_result_t result;	dns_dbnode_t *node = NULL;	rdataset->trust = dns_trust_secure;	sigrdataset->trust = dns_trust_secure;	/*	 * Save the updated secure state.  Ignore failures.	 */	result = dns_db_findnode(db, name, ISC_TRUE, &node);	if (result != ISC_R_SUCCESS)		return;	(void)dns_db_addrdataset(db, node, NULL, client->now, rdataset,				 0, NULL);	(void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset,				 0, NULL);	dns_db_detachnode(db, &node);}/* * Find the secure key that corresponds to rrsig. * Note: 'keyrdataset' maintains state between sucessive calls, * there may be multiple keys with the same keyid. * Return ISC_FALSE if we have exhausted all the possible keys. */static isc_boolean_tget_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,	dns_rdataset_t *keyrdataset, dst_key_t **keyp){ 	isc_result_t result;	dns_dbnode_t *node = NULL;	isc_boolean_t secure = ISC_FALSE;	if (!dns_rdataset_isassociated(keyrdataset)) {		result = dns_db_findnode(db, &rrsig->signer, ISC_FALSE, &node);		if (result != ISC_R_SUCCESS)			return (ISC_FALSE);		result = dns_db_findrdataset(db, node, NULL,					     dns_rdatatype_dnskey, 0,					     client->now, keyrdataset, NULL);		dns_db_detachnode(db, &node);		if (result != ISC_R_SUCCESS)			return (ISC_FALSE);		if (keyrdataset->trust != dns_trust_secure)			return (ISC_FALSE);		result = dns_rdataset_first(keyrdataset);	} else		result = dns_rdataset_next(keyrdataset);	for ( ; result == ISC_R_SUCCESS;	     result = dns_rdataset_next(keyrdataset)) {		dns_rdata_t rdata = DNS_RDATA_INIT;		isc_buffer_t b;		dns_rdataset_current(keyrdataset, &rdata);		isc_buffer_init(&b, rdata.data, rdata.length);		isc_buffer_add(&b, rdata.length);		result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b,                                         client->mctx, keyp);		if (result != ISC_R_SUCCESS)			continue;		if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) &&                    rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&                    dst_key_iszonekey(*keyp)) {			secure = ISC_TRUE;			break;		}		dst_key_free(keyp);	}	return (secure);}static isc_boolean_tverify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset,       dns_rdata_t *rdata, isc_mem_t *mctx, isc_boolean_t acceptexpired){	isc_result_t result;	dns_fixedname_t fixed;	isc_boolean_t ignore = ISC_FALSE;	dns_fixedname_init(&fixed);	again:	result = dns_dnssec_verify2(name, rdataset, key, ignore, mctx,				    rdata, NULL);	if (result == DNS_R_SIGEXPIRED && acceptexpired) {		ignore = ISC_TRUE;		goto again;	}	if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD)		return (ISC_TRUE);	return (ISC_FALSE);}/* * Validate the rdataset if possible with available records. */static isc_boolean_tvalidate(ns_client_t *client, dns_db_t *db, dns_name_t *name,	 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset){	isc_result_t result;	dns_rdata_t rdata = DNS_RDATA_INIT;	dns_rdata_rrsig_t rrsig;	dst_key_t *key = NULL;	dns_rdataset_t keyrdataset;	if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))		return (ISC_FALSE);		for (result = dns_rdataset_first(sigrdataset);	     result == ISC_R_SUCCESS;	     result = dns_rdataset_next(sigrdataset)) {		dns_rdata_reset(&rdata);		dns_rdataset_current(sigrdataset, &rdata);		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);		if (result != ISC_R_SUCCESS)			return (ISC_FALSE);		if (!dns_resolver_algorithm_supported(client->view->resolver,						      name, rrsig.algorithm))			continue;		if (!dns_name_issubdomain(name, &rrsig.signer))			continue;		dns_rdataset_init(&keyrdataset);		do {			if (!get_key(client, db, &rrsig, &keyrdataset, &key))				break;			if (verify(key, name, rdataset, &rdata, client->mctx,				   client->view->acceptexpired)) {				dst_key_free(&key);				dns_rdataset_disassociate(&keyrdataset);				mark_secure(client, db, name, rdataset,					    sigrdataset);				return (ISC_TRUE);			}			dst_key_free(&key);		} while (1);		if (dns_rdataset_isassociated(&keyrdataset))			dns_rdataset_disassociate(&keyrdataset);	}	return (ISC_FALSE);}static voidquery_addbestns(ns_client_t *client) {	dns_db_t *db, *zdb;	dns_dbnode_t *node;	dns_name_t *fname, *zfname;	dns_rdataset_t *rdataset, *sigrdataset, *zrdataset, *zsigrdataset

⌨️ 快捷键说明

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