Пример #1
0
/**
 * findCoveringNSEC3
 * Given a name, find a covering NSEC3 from among a list of NSEC3s.
 *
 * @param env: module environment with temporary region and buffer.
 * @param flt: the NSEC3 RR filter, contains zone name and RRs.
 * @param ct: cached hashes table.
 * @param nm: name to check if covered.
 * @param nmlen: length of name.
 * @param rrset: covering NSEC3 rrset is returned here.
 * @param rr: rr of cover is returned here.
 * @return true if a covering NSEC3 is found, false if not.
 */
static int
find_covering_nsec3(struct module_env* env, struct nsec3_filter* flt,
        rbtree_t* ct, uint8_t* nm, size_t nmlen, 
	struct ub_packed_rrset_key** rrset, int* rr)
{
	size_t i_rs;
	int i_rr;
	struct ub_packed_rrset_key* s;
	struct nsec3_cached_hash* hash;
	int r;

	/* this loop skips other-zone and unknown NSEC3s, also non-NSEC3 RRs */
	for(s=filter_first(flt, &i_rs, &i_rr); s; 
		s=filter_next(flt, &i_rs, &i_rr)) {
		/* get name hashed for this NSEC3 RR */
		r = nsec3_hash_name(ct, env->scratch, env->scratch_buffer,
			s, i_rr, nm, nmlen, &hash);
		if(r == 0) {
			log_err("nsec3: malloc failure");
			break; /* alloc failure */
		} else if(r < 0)
			continue; /* malformed NSEC3 */
		else if(nsec3_covers(flt->zone, hash, s, i_rr, 
			env->scratch_buffer)) {
			*rrset = s; /* rrset with this name */
			*rr = i_rr; /* covers hash with these parameters */
			return 1;
		}
	}
	*rrset = NULL;
	*rr = 0;
	return 0;
}
Пример #2
0
/** 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;
}