コード例 #1
0
ファイル: val_utils.c プロジェクト: RS-liuyang/rsdns
struct dns_msg* 
val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t c, 
	struct regional* region)
{
	struct dns_msg* msg;
	struct query_info qinfo;
	struct ub_packed_rrset_key *rrset = rrset_cache_lookup(
		env->rrset_cache, nm, nmlen, LDNS_RR_TYPE_DS, c, 0, 
		*env->now, 0);
	if(rrset) {
		/* DS rrset exists. Return it to the validator immediately*/
		struct ub_packed_rrset_key* copy = packed_rrset_copy_region(
			rrset, region, *env->now);
		lock_rw_unlock(&rrset->entry.lock);
		if(!copy)
			return NULL;
		msg = dns_msg_create(nm, nmlen, LDNS_RR_TYPE_DS, c, region, 1);
		if(!msg)
			return NULL;
		msg->rep->rrsets[0] = copy;
		msg->rep->rrset_count++;
		msg->rep->an_numrrsets++;
		return msg;
	}
	/* lookup in rrset and negative cache for NSEC/NSEC3 */
	qinfo.qname = nm;
	qinfo.qname_len = nmlen;
	qinfo.qtype = LDNS_RR_TYPE_DS;
	qinfo.qclass = c;
	/* do not add SOA to reply message, it is going to be used internal */
	msg = val_neg_getmsg(env->neg_cache, &qinfo, region, env->rrset_cache,
		env->scratch_buffer, *env->now, 0);
	return msg;
}
コード例 #2
0
ファイル: dns.c プロジェクト: derekmarcotte/freebsd
/** Fill TYPE_ANY response with some data from cache */
static struct dns_msg*
fill_any(struct module_env* env,
	uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
	struct regional* region)
{
	time_t now = *env->now;
	struct dns_msg* msg = NULL;
	uint16_t lookup[] = {LDNS_RR_TYPE_A, LDNS_RR_TYPE_AAAA,
		LDNS_RR_TYPE_MX, LDNS_RR_TYPE_SOA, LDNS_RR_TYPE_NS,
		LDNS_RR_TYPE_DNAME, 0};
	int i, num=6; /* number of RR types to look up */
	log_assert(lookup[num] == 0);

	for(i=0; i<num; i++) {
		/* look up this RR for inclusion in type ANY response */
		struct ub_packed_rrset_key* rrset = rrset_cache_lookup(
			env->rrset_cache, qname, qnamelen, lookup[i],
			qclass, 0, now, 0);
		struct packed_rrset_data *d;
		if(!rrset)
			continue;

		/* only if rrset from answer section */
		d = (struct packed_rrset_data*)rrset->entry.data;
		if(d->trust == rrset_trust_add_noAA ||
			d->trust == rrset_trust_auth_noAA ||
			d->trust == rrset_trust_add_AA ||
			d->trust == rrset_trust_auth_AA) {
			lock_rw_unlock(&rrset->entry.lock);
			continue;
		}

		/* create msg if none */
		if(!msg) {
			msg = dns_msg_create(qname, qnamelen, qtype, qclass,
				region, (size_t)(num-i));
			if(!msg) {
				lock_rw_unlock(&rrset->entry.lock);
				return NULL;
			}
		}

		/* add RRset to response */
		if(!dns_msg_ansadd(msg, region, rrset, now)) {
			lock_rw_unlock(&rrset->entry.lock);
			return NULL;
		}
		lock_rw_unlock(&rrset->entry.lock);
	}
	return msg;
}
コード例 #3
0
ファイル: dns.c プロジェクト: derekmarcotte/freebsd
struct delegpt* 
dns_cache_find_delegation(struct module_env* env, uint8_t* qname, 
	size_t qnamelen, uint16_t qtype, uint16_t qclass, 
	struct regional* region, struct dns_msg** msg, time_t now)
{
	/* try to find closest NS rrset */
	struct ub_packed_rrset_key* nskey;
	struct packed_rrset_data* nsdata;
	struct delegpt* dp;

	nskey = find_closest_of_type(env, qname, qnamelen, qclass, now,
		LDNS_RR_TYPE_NS, 0);
	if(!nskey) /* hope the caller has hints to prime or something */
		return NULL;
	nsdata = (struct packed_rrset_data*)nskey->entry.data;
	/* got the NS key, create delegation point */
	dp = delegpt_create(region);
	if(!dp || !delegpt_set_name(dp, region, nskey->rk.dname)) {
		lock_rw_unlock(&nskey->entry.lock);
		log_err("find_delegation: out of memory");
		return NULL;
	}
	/* create referral message */
	if(msg) {
		/* allocate the array to as much as we could need:
		 *	NS rrset + DS/NSEC rrset +
		 *	A rrset for every NS RR
		 *	AAAA rrset for every NS RR
		 */
		*msg = dns_msg_create(qname, qnamelen, qtype, qclass, region, 
			2 + nsdata->count*2);
		if(!*msg || !dns_msg_authadd(*msg, region, nskey, now)) {
			lock_rw_unlock(&nskey->entry.lock);
			log_err("find_delegation: out of memory");
			return NULL;
		}
	}
	if(!delegpt_rrset_add_ns(dp, region, nskey, 0))
		log_err("find_delegation: addns out of memory");
	lock_rw_unlock(&nskey->entry.lock); /* first unlock before next lookup*/
	/* find and add DS/NSEC (if any) */
	if(msg)
		find_add_ds(env, region, *msg, dp, now);
	/* find and add A entries */
	if(!find_add_addrs(env, qclass, region, dp, now, msg))
		log_err("find_delegation: addrs out of memory");
	return dp;
}
コード例 #4
0
ファイル: val_neg.c プロジェクト: stasic/debian-unbound
struct dns_msg* 
val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo, 
	struct regional* region, struct rrset_cache* rrset_cache, 
	ldns_buffer* buf, uint32_t now, int addsoa, uint8_t* topname)
{
	struct dns_msg* msg;
	struct ub_packed_rrset_key* rrset;
	uint8_t* zname;
	size_t zname_len;
	int zname_labs;
	struct val_neg_zone* zone;

	/* only for DS queries */
	if(qinfo->qtype != LDNS_RR_TYPE_DS)
		return NULL;
	log_assert(!topname || dname_subdomain_c(qinfo->qname, topname));

	/* see if info from neg cache is available 
	 * For NSECs, because there is no optout; a DS next to a delegation
	 * always has exactly an NSEC for it itself; check its DS bit.
	 * flags=0 (not the zone apex).
	 */
	rrset = grab_nsec(rrset_cache, qinfo->qname, qinfo->qname_len,
		LDNS_RR_TYPE_NSEC, qinfo->qclass, 0, region, 1, 
		qinfo->qtype, now);
	if(rrset) {
		/* return msg with that rrset */
		if(!(msg = dns_msg_create(qinfo->qname, qinfo->qname_len, 
			qinfo->qtype, qinfo->qclass, region, 2))) 
			return NULL;
		/* TTL already subtracted in grab_nsec */
		if(!dns_msg_authadd(msg, region, rrset, 0)) 
			return NULL;
		if(addsoa && !add_soa(rrset_cache, now, region, msg, NULL))
			return NULL;
		return msg;
	}

	/* check NSEC3 neg cache for type DS */
	/* need to look one zone higher for DS type */
	zname = qinfo->qname;
	zname_len = qinfo->qname_len;
	dname_remove_label(&zname, &zname_len);
	zname_labs = dname_count_labels(zname);

	/* lookup closest zone */
	lock_basic_lock(&neg->lock);
	zone = neg_closest_zone_parent(neg, zname, zname_len, zname_labs, 
		qinfo->qclass);
	while(zone && !zone->in_use)
		zone = zone->parent;
	/* check that the zone is not too high up so that we do not pick data
	 * out of a zone that is above the last-seen key (or trust-anchor). */
	if(zone && topname) {
		if(!dname_subdomain_c(zone->name, topname))
			zone = NULL;
	}
	if(!zone) {
		lock_basic_unlock(&neg->lock);
		return NULL;
	}

	msg = neg_nsec3_proof_ds(zone, qinfo->qname, qinfo->qname_len, 
		zname_labs+1, buf, rrset_cache, region, now, topname);
	if(msg && addsoa && !add_soa(rrset_cache, now, region, msg, zone)) {
		lock_basic_unlock(&neg->lock);
		return NULL;
	}
	lock_basic_unlock(&neg->lock);
	return msg;
}
コード例 #5
0
ファイル: val_neg.c プロジェクト: stasic/debian-unbound
/** neg cache nsec3 proof procedure*/
static struct dns_msg*
neg_nsec3_proof_ds(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len,
		int qlabs, ldns_buffer* buf, struct rrset_cache* rrset_cache,
		struct regional* region, uint32_t now, uint8_t* topname)
{
	struct dns_msg* msg;
	struct val_neg_data* data;
	uint8_t hashnc[SHA_DIGEST_LENGTH];
	size_t nclen;
	struct ub_packed_rrset_key* ce_rrset, *nc_rrset;
	struct nsec3_cached_hash c;
	uint8_t nc_b32[257];

	/* for NSEC3 ; determine the closest encloser for which we
	 * can find an exact match. Remember the hashed lower name,
	 * since that is the one we need a closest match for. 
	 * If we find a match straight away, then it becomes NODATA.
	 * Otherwise, NXDOMAIN or if OPTOUT, an insecure delegation.
	 * Also check that parameters are the same on closest encloser
	 * and on closest match.
	 */
	if(!zone->nsec3_hash) 
		return NULL; /* not nsec3 zone */

	if(!(data=neg_find_nsec3_ce(zone, qname, qname_len, qlabs, buf,
		hashnc, &nclen))) {
		return NULL;
	}

	/* grab the ce rrset */
	ce_rrset = grab_nsec(rrset_cache, data->name, data->len, 
		LDNS_RR_TYPE_NSEC3, zone->dclass, 0, region, 1, 
		LDNS_RR_TYPE_DS, now);
	if(!ce_rrset)
		return NULL;
	if(!neg_params_ok(zone, ce_rrset))
		return NULL;

	if(nclen == 0) {
		/* exact match, just check the type bits */
		/* need: -SOA, -DS, +NS */
		if(nsec3_has_type(ce_rrset, 0, LDNS_RR_TYPE_SOA) ||
			nsec3_has_type(ce_rrset, 0, LDNS_RR_TYPE_DS) ||
			!nsec3_has_type(ce_rrset, 0, LDNS_RR_TYPE_NS))
			return NULL;
		if(!(msg = dns_msg_create(qname, qname_len, 
			LDNS_RR_TYPE_DS, zone->dclass, region, 1))) 
			return NULL;
		/* TTL reduced in grab_nsec */
		if(!dns_msg_authadd(msg, region, ce_rrset, 0)) 
			return NULL;
		return msg;
	}

	/* optout is not allowed without knowing the trust-anchor in use,
	 * otherwise the optout could spoof away that anchor */
	if(!topname)
		return NULL;

	/* if there is no exact match, it must be in an optout span
	 * (an existing DS implies an NSEC3 must exist) */
	nc_rrset = neg_nsec3_getnc(zone, hashnc, nclen, rrset_cache, 
		region, now, nc_b32, sizeof(nc_b32));
	if(!nc_rrset) 
		return NULL;
	if(!neg_params_ok(zone, nc_rrset))
		return NULL;
	if(!nsec3_has_optout(nc_rrset, 0))
		return NULL;
	c.hash = hashnc;
	c.hash_len = nclen;
	c.b32 = nc_b32+1;
	c.b32_len = (size_t)nc_b32[0];
	if(nsec3_covers(zone->name, &c, nc_rrset, 0, buf)) {
		/* nc_rrset covers the next closer name.
		 * ce_rrset equals a closer encloser.
		 * nc_rrset is optout.
		 * No need to check wildcard for type DS */
		/* capacity=3: ce + nc + soa(if needed) */
		if(!(msg = dns_msg_create(qname, qname_len, 
			LDNS_RR_TYPE_DS, zone->dclass, region, 3))) 
			return NULL;
		/* now=0 because TTL was reduced in grab_nsec */
		if(!dns_msg_authadd(msg, region, ce_rrset, 0)) 
			return NULL;
		if(!dns_msg_authadd(msg, region, nc_rrset, 0)) 
			return NULL;
		return msg;
	}
	return NULL;
}