Esempio n. 1
0
/** fill data into result */
static int
fill_res(struct ub_result* res, struct ub_packed_rrset_key* answer,
	uint8_t* finalcname, struct query_info* rq)
{
	size_t i;
	struct packed_rrset_data* data;
	if(!answer) {
		if(finalcname) {
			if(!fill_canon(res, finalcname))
				return 0; /* out of memory */
		}
		res->data = (char**)calloc(1, sizeof(char*));
		res->len = (int*)calloc(1, sizeof(int));
		return (res->data && res->len);
	}
	data = (struct packed_rrset_data*)answer->entry.data;
	if(query_dname_compare(rq->qname, answer->rk.dname) != 0) {
		if(!fill_canon(res, answer->rk.dname))
			return 0; /* out of memory */
	} else	res->canonname = NULL;
	res->data = (char**)calloc(data->count+1, sizeof(char*));
	res->len = (int*)calloc(data->count+1, sizeof(int));
	if(!res->data || !res->len)
		return 0; /* out of memory */
	for(i=0; i<data->count; i++) {
		/* remove rdlength from rdata */
		res->len[i] = (int)(data->rr_len[i] - 2);
		res->data[i] = memdup(data->rr_data[i]+2, (size_t)res->len[i]);
		if(!res->data[i])
			return 0; /* out of memory */
	}
	res->data[data->count] = NULL;
	res->len[data->count] = 0;
	return 1;
}
Esempio n. 2
0
/* nsec3_cache_compare for rbtree */
int
nsec3_hash_cmp(const void* c1, const void* c2) 
{
	struct nsec3_cached_hash* h1 = (struct nsec3_cached_hash*)c1;
	struct nsec3_cached_hash* h2 = (struct nsec3_cached_hash*)c2;
	uint8_t* s1, *s2;
	size_t s1len, s2len;
	int c = query_dname_compare(h1->dname, h2->dname);
	if(c != 0)
		return c;
	/* compare parameters */
	/* if both malformed, its equal, robustness */
	if(nsec3_get_algo(h1->nsec3, h1->rr) !=
		nsec3_get_algo(h2->nsec3, h2->rr)) {
		if(nsec3_get_algo(h1->nsec3, h1->rr) <
			nsec3_get_algo(h2->nsec3, h2->rr))
			return -1;
		return 1;
	}
	if(nsec3_get_iter(h1->nsec3, h1->rr) !=
		nsec3_get_iter(h2->nsec3, h2->rr)) {
		if(nsec3_get_iter(h1->nsec3, h1->rr) <
			nsec3_get_iter(h2->nsec3, h2->rr))
			return -1;
		return 1;
	}
	(void)nsec3_get_salt(h1->nsec3, h1->rr, &s1, &s1len);
	(void)nsec3_get_salt(h2->nsec3, h2->rr, &s2, &s2len);
	if(s1len != s2len) {
		if(s1len < s2len)
			return -1;
		return 1;
	}
	return memcmp(s1, s2, s1len);
}
Esempio n. 3
0
int 
ub_rrset_compare(void* k1, void* k2)
{
	struct ub_packed_rrset_key* key1 = (struct ub_packed_rrset_key*)k1;
	struct ub_packed_rrset_key* key2 = (struct ub_packed_rrset_key*)k2;
	int c;
	if(key1 == key2)
		return 0;
	if(key1->rk.type != key2->rk.type) {
		if(key1->rk.type < key2->rk.type)
			return -1;
		return 1;
	}
	if(key1->rk.dname_len != key2->rk.dname_len) {
		if(key1->rk.dname_len < key2->rk.dname_len)
			return -1;
		return 1;
	}
	if((c=query_dname_compare(key1->rk.dname, key2->rk.dname)) != 0)
		return c;
	if(key1->rk.rrset_class != key2->rk.rrset_class) {
		if(key1->rk.rrset_class < key2->rk.rrset_class)
			return -1;
		return 1;
	}
	if(key1->rk.flags != key2->rk.flags) {
		if(key1->rk.flags < key2->rk.flags)
			return -1;
		return 1;
	}
	return 0;
}
Esempio n. 4
0
void local_zones_del_data(struct local_zones* zones, 
	uint8_t* name, size_t len, int labs, uint16_t dclass)
{
	/* find zone */
	struct local_zone* z;
	struct local_data* d;
	lock_rw_rdlock(&zones->lock);
	z = local_zones_lookup(zones, name, len, labs, dclass);
	if(!z) {
		/* no such zone, we're done */
		lock_rw_unlock(&zones->lock);
		return;
	}
	lock_rw_wrlock(&z->lock);
	lock_rw_unlock(&zones->lock);

	/* find the domain */
	d = lz_find_node(z, name, len, labs);
	if(d) {
		/* no memory recycling for zone deletions ... */
		d->rrsets = NULL;
		/* did we delete the soa record ? */
		if(query_dname_compare(d->name, z->name) == 0)
			z->soa = NULL;

		/* cleanup the empty nonterminals for this name */
		del_empty_term(z, d, name, len, labs);
	}

	lock_rw_unlock(&z->lock);
}
Esempio n. 5
0
int
iter_ds_toolow(struct dns_msg* msg, struct delegpt* dp)
{
	/* if for query example.com, there is example.com SOA or a subdomain
	 * of example.com, then we are too low and need to fetch NS. */
	size_t i;
	/* if we have a DNAME or CNAME we are probably wrong */
	/* if we have a qtype DS in the answer section, its fine */
	for(i=0; i < msg->rep->an_numrrsets; i++) {
		struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
		if(ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME ||
			ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME) {
			/* not the right answer, maybe too low, check the
			 * RRSIG signer name (if there is any) for a hint
			 * that it is from the dp zone anyway */
			uint8_t* sname;
			size_t slen;
			val_find_rrset_signer(s, &sname, &slen);
			if(sname && query_dname_compare(dp->name, sname)==0)
				return 0; /* it is fine, from the right dp */
			return 1;
		}
		if(ntohs(s->rk.type) == LDNS_RR_TYPE_DS)
			return 0; /* fine, we have a DS record */
	}
	for(i=msg->rep->an_numrrsets;
		i < msg->rep->an_numrrsets + msg->rep->ns_numrrsets; i++) {
		struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
		if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA) {
			if(dname_subdomain_c(s->rk.dname, msg->qinfo.qname))
				return 1; /* point is too low */
			if(query_dname_compare(s->rk.dname, dp->name)==0)
				return 0; /* right dp */
		}
		if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC ||
			ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) {
			uint8_t* sname;
			size_t slen;
			val_find_rrset_signer(s, &sname, &slen);
			if(sname && query_dname_compare(dp->name, sname)==0)
				return 0; /* it is fine, from the right dp */
			return 1;
		}
	}
	/* we do not know */
	return 1;
}
Esempio n. 6
0
/**
 * proveClosestEncloser
 * Given a List of nsec3 RRs, find and prove the closest encloser to qname.
 * @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 qinfo: query that is verified for.
 * @param prove_does_not_exist: If true, then if the closest encloser 
 * 	turns out to be qname, then null is returned.
 * 	If set true, and the return value is true, then you can be 
 * 	certain that the ce.nc_rrset and ce.nc_rr are set properly.
 * @param ce: closest encloser information is returned in here.
 * @return bogus if no closest encloser could be proven.
 * 	secure if a closest encloser could be proven, ce is set.
 * 	insecure if the closest-encloser candidate turns out to prove
 * 		that an insecure delegation exists above the qname.
 */
static enum sec_status
nsec3_prove_closest_encloser(struct module_env* env, struct nsec3_filter* flt, 
	rbtree_t* ct, struct query_info* qinfo, int prove_does_not_exist,
	struct ce_response* ce)
{
	uint8_t* nc;
	size_t nc_len;
	/* robust: clean out ce, in case it gets abused later */
	memset(ce, 0, sizeof(*ce));

	if(!nsec3_find_closest_encloser(env, flt, ct, qinfo, ce)) {
		verbose(VERB_ALGO, "nsec3 proveClosestEncloser: could "
			"not find a candidate for the closest encloser.");
		return sec_status_bogus;
	}
	log_nametypeclass(VERB_ALGO, "ce candidate", ce->ce, 0, 0);

	if(query_dname_compare(ce->ce, qinfo->qname) == 0) {
		if(prove_does_not_exist) {
			verbose(VERB_ALGO, "nsec3 proveClosestEncloser: "
				"proved that qname existed, bad");
			return sec_status_bogus;
		}
		/* otherwise, we need to nothing else to prove that qname 
		 * is its own closest encloser. */
		return sec_status_secure;
	}

	/* If the closest encloser is actually a delegation, then the 
	 * response should have been a referral. If it is a DNAME, then 
	 * it should have been a DNAME response. */
	if(nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_NS) &&
		!nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_SOA)) {
		if(!nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_DS)) {
			verbose(VERB_ALGO, "nsec3 proveClosestEncloser: "
				"closest encloser is insecure delegation");
			return sec_status_insecure;
		}
		verbose(VERB_ALGO, "nsec3 proveClosestEncloser: closest "
			"encloser was a delegation, bad");
		return sec_status_bogus;
	}
	if(nsec3_has_type(ce->ce_rrset, ce->ce_rr, LDNS_RR_TYPE_DNAME)) {
		verbose(VERB_ALGO, "nsec3 proveClosestEncloser: closest "
			"encloser was a DNAME, bad");
		return sec_status_bogus;
	}
	
	/* Otherwise, we need to show that the next closer name is covered. */
	next_closer(qinfo->qname, qinfo->qname_len, ce->ce, &nc, &nc_len);
	if(!find_covering_nsec3(env, flt, ct, nc, nc_len, 
		&ce->nc_rrset, &ce->nc_rr)) {
		verbose(VERB_ALGO, "nsec3: Could not find proof that the "
		          "candidate encloser was the closest encloser");
		return sec_status_bogus;
	}
	return sec_status_secure;
}
Esempio n. 7
0
/** print root forwards */
static int
print_root_fwds(SSL* ssl, struct iter_forwards* fwds, uint8_t* root)
{
	struct delegpt* dp;
	dp = forwards_lookup(fwds, root, LDNS_RR_CLASS_IN);
	if(!dp)
		return ssl_printf(ssl, "off (using root hints)\n");
	/* if dp is returned it must be the root */
	log_assert(query_dname_compare(dp->name, root)==0);
	return ssl_print_name_dp(ssl, NULL, root, LDNS_RR_CLASS_IN, dp);
}
Esempio n. 8
0
/** Test dname_get_shared_topdomain */
static void
dname_test_topdomain(void)
{
	unit_show_func("util/data/dname.c", "dname_get_shared_topdomain");
	unit_assert( query_dname_compare(
		dname_get_shared_topdomain(
			(uint8_t*)"",
			(uint8_t*)""), 
		(uint8_t*)"") == 0);
	unit_assert( query_dname_compare(
		dname_get_shared_topdomain(
			(uint8_t*)"\003www\007example\003com",
			(uint8_t*)"\003www\007example\003com"), 
		(uint8_t*)"\003www\007example\003com") == 0);
	unit_assert( query_dname_compare(
		dname_get_shared_topdomain(
			(uint8_t*)"\003www\007example\003com",
			(uint8_t*)"\003bla\007example\003com"), 
		(uint8_t*)"\007example\003com") == 0);
}
Esempio n. 9
0
/**
 * Answer CH class queries.
 * @param w: worker
 * @param qinfo: query info. Pointer into packet buffer.
 * @param edns: edns info from query.
 * @param pkt: packet buffer.
 * @return: true if a reply is to be sent.
 */
static int
answer_chaos(struct worker* w, struct query_info* qinfo, 
	struct edns_data* edns, sldns_buffer* pkt)
{
	struct config_file* cfg = w->env.cfg;
	if(qinfo->qtype != LDNS_RR_TYPE_ANY && qinfo->qtype != LDNS_RR_TYPE_TXT)
		return 0;
	if(query_dname_compare(qinfo->qname, 
		(uint8_t*)"\002id\006server") == 0 ||
		query_dname_compare(qinfo->qname, 
		(uint8_t*)"\010hostname\004bind") == 0)
	{
		if(cfg->hide_identity) 
			return 0;
		if(cfg->identity==NULL || cfg->identity[0]==0) {
			char buf[MAXHOSTNAMELEN+1];
			if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
				buf[MAXHOSTNAMELEN] = 0;
				chaos_replystr(pkt, buf, edns, w);
			} else 	{
				log_err("gethostname: %s", strerror(errno));
				chaos_replystr(pkt, "no hostname", edns, w);
			}
		}
		else 	chaos_replystr(pkt, cfg->identity, edns, w);
		return 1;
	}
	if(query_dname_compare(qinfo->qname, 
		(uint8_t*)"\007version\006server") == 0 ||
		query_dname_compare(qinfo->qname, 
		(uint8_t*)"\007version\004bind") == 0)
	{
		if(cfg->hide_version) 
			return 0;
		if(cfg->version==NULL || cfg->version[0]==0)
			chaos_replystr(pkt, PACKAGE_STRING, edns, w);
		else 	chaos_replystr(pkt, cfg->version, edns, w);
		return 1;
	}
	return 0;
}
Esempio n. 10
0
/** fill data into result */
static int
fill_res(struct ub_result* res, struct ub_packed_rrset_key* answer,
	uint8_t* finalcname, struct query_info* rq, struct reply_info* rep)
{
	size_t i;
	struct packed_rrset_data* data;
	res->ttl = 0;
	if(!answer) {
		if(finalcname) {
			if(!fill_canon(res, finalcname))
				return 0; /* out of memory */
		}
		if(rep->rrset_count != 0)
			res->ttl = (int)rep->ttl;
		res->data = (char**)calloc(1, sizeof(char*));
		res->len = (int*)calloc(1, sizeof(int));
		return (res->data && res->len);
	}
	data = (struct packed_rrset_data*)answer->entry.data;
	if(query_dname_compare(rq->qname, answer->rk.dname) != 0) {
		if(!fill_canon(res, answer->rk.dname))
			return 0; /* out of memory */
	} else	res->canonname = NULL;
	res->data = (char**)calloc(data->count+1, sizeof(char*));
	res->len = (int*)calloc(data->count+1, sizeof(int));
	if(!res->data || !res->len)
		return 0; /* out of memory */
	for(i=0; i<data->count; i++) {
		/* remove rdlength from rdata */
		res->len[i] = (int)(data->rr_len[i] - 2);
		res->data[i] = memdup(data->rr_data[i]+2, (size_t)res->len[i]);
		if(!res->data[i])
			return 0; /* out of memory */
	}
	/* ttl for positive answers, from CNAME and answer RRs */
	if(data->count != 0) {
		size_t j;
		res->ttl = (int)data->ttl;
		for(j=0; j<rep->an_numrrsets; j++) {
			struct packed_rrset_data* d =
				(struct packed_rrset_data*)rep->rrsets[j]->
				entry.data;
			if((int)d->ttl < res->ttl)
				res->ttl = (int)d->ttl;
		}
	}
	/* ttl for negative answers */
	if(data->count == 0 && rep->rrset_count != 0)
		res->ttl = (int)rep->ttl;
	res->data[data->count] = NULL;
	res->len[data->count] = 0;
	return 1;
}
Esempio n. 11
0
int 
rate_compfunc(void* key1, void* key2)
{
	struct rate_key* k1 = (struct rate_key*)key1;
	struct rate_key* k2 = (struct rate_key*)key2;
	if(k1->namelen != k2->namelen) {
		if(k1->namelen < k2->namelen)
			return -1;
		return 1;
	}
	return query_dname_compare(k1->name, k2->name);
}
Esempio n. 12
0
struct delegpt_ns*
delegpt_find_ns(struct delegpt* dp, uint8_t* name, size_t namelen)
{
	struct delegpt_ns* p = dp->nslist;
	while(p) {
		if(namelen == p->namelen && 
			query_dname_compare(name, p->name) == 0) {
			return p;
		}
		p = p->next;
	}
	return NULL;
}
Esempio n. 13
0
/** check that there is no data element that matches the RRSIG */
static int
no_data_for_rrsig(struct reply_info* rep, struct ub_packed_rrset_key* rrsig)
{
	size_t i;
	for(i=0; i<rep->rrset_count; i++) {
		if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_RRSIG)
			continue;
		if(query_dname_compare(rep->rrsets[i]->rk.dname, 
			rrsig->rk.dname) == 0)
			/* only name is compared right now */
			return 0;
	}
	return 1;
}
Esempio n. 14
0
int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp)
{
	/* no delegation point, do not see how we can go down,
	 * robust check, it should really exist */
	if(!dp) return 0;

	/* see if dp equals the qname, then we cannot go down further */
	if(query_dname_compare(qinfo->qname, dp->name) == 0)
		return 0;
	/* if dp is one label above the name we also cannot go down further */
	if(dname_count_labels(qinfo->qname) == dp->namelabs+1)
		return 0;
	return 1;
}
Esempio n. 15
0
int 
query_info_compare(void* m1, void* m2)
{
	struct query_info* msg1 = (struct query_info*)m1;
	struct query_info* msg2 = (struct query_info*)m2;
	int mc;
	/* from most different to least different for speed */
	COMPARE_IT(msg1->qtype, msg2->qtype);
	if((mc = query_dname_compare(msg1->qname, msg2->qname)) != 0)
		return mc;
	log_assert(msg1->qname_len == msg2->qname_len);
	COMPARE_IT(msg1->qclass, msg2->qclass);
	return 0;
#undef COMPARE_IT
}
Esempio n. 16
0
int 
infra_compfunc(void* key1, void* key2)
{
	struct infra_key* k1 = (struct infra_key*)key1;
	struct infra_key* k2 = (struct infra_key*)key2;
	int r = sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
	if(r != 0)
		return r;
	if(k1->namelen != k2->namelen) {
		if(k1->namelen < k2->namelen)
			return -1;
		return 1;
	}
	return query_dname_compare(k1->zonename, k2->zonename);
}
Esempio n. 17
0
struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep,
	uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass)
{
	size_t i;
	for(i=0; i<rep->rrset_count; i++) {
		struct ub_packed_rrset_key* s = rep->rrsets[i];
		if(ntohs(s->rk.type) == type && 
			ntohs(s->rk.rrset_class) == dclass && 
			namelen == s->rk.dname_len &&
			query_dname_compare(name, s->rk.dname) == 0) {
			return s;
		}
	}
	return NULL;
}
Esempio n. 18
0
int
nsec3_covers(uint8_t* zone, struct nsec3_cached_hash* hash,
	struct ub_packed_rrset_key* rrset, int rr, ldns_buffer* buf)
{
	uint8_t* next, *owner;
	size_t nextlen;
	int len;
	if(!nsec3_get_nextowner(rrset, rr, &next, &nextlen))
		return 0; /* malformed RR proves nothing */

	/* check the owner name is a hashed value . apex
	 * base32 encoded values must have equal length. 
	 * hash_value and next hash value must have equal length. */
	if(nextlen != hash->hash_len || hash->hash_len==0||hash->b32_len==0|| 
		(size_t)*rrset->rk.dname != hash->b32_len ||
		query_dname_compare(rrset->rk.dname+1+
			(size_t)*rrset->rk.dname, zone) != 0)
		return 0; /* bad lengths or owner name */

	/* This is the "normal case: owner < next and owner < hash < next */
	if(label_compare_lower(rrset->rk.dname+1, hash->b32, 
		hash->b32_len) < 0 && 
		memcmp(hash->hash, next, nextlen) < 0)
		return 1;

	/* convert owner name from text to binary */
	ldns_buffer_clear(buf);
	owner = ldns_buffer_begin(buf);
	len = ldns_b32_pton_extended_hex((char*)rrset->rk.dname+1, 
		hash->b32_len, owner, ldns_buffer_limit(buf));
	if(len<1)
		return 0; /* bad owner name in some way */
	if((size_t)len != hash->hash_len || (size_t)len != nextlen)
		return 0; /* wrong length */

	/* this is the end of zone case: next <= owner && 
	 * 	(hash > owner || hash < next) 
	 * this also covers the only-apex case of next==owner.
	 */
	if(memcmp(next, owner, nextlen) <= 0 &&
		( memcmp(hash->hash, owner, nextlen) > 0 ||
		  memcmp(hash->hash, next, nextlen) < 0)) {
		return 1;
	}
	return 0;
}
Esempio n. 19
0
/** see if rrset has signer name as one of the rrsig signers */
static int
rrset_has_signer(struct ub_packed_rrset_key* rrset, uint8_t* name, size_t len)
{
	struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
		entry.data;
	size_t i;
	for(i = d->count; i< d->count+d->rrsig_count; i++) {
		if(d->rr_len[i] > 2+18+len) {
			/* at least rdatalen + signature + signame (+1 sig)*/
			if(query_dname_compare(name, d->rr_data[i]+2+18) == 0)
			{
				return 1;
			}
		}
	}
	return 0;
}
Esempio n. 20
0
/** check if negative cache is still valid */
static void check_zone_invariants(struct val_neg_cache* neg, 
	struct val_neg_zone* zone)
{
	unit_assert(zone->nsec3_hash == 0);
	unit_assert(zone->tree.cmp == &val_neg_data_compare);
	unit_assert(zone->count != 0);

	if(zone->tree.count == 0)
		unit_assert(!zone->in_use);
	else {
		if(!zone->in_use) {
			/* details on error */
			log_nametypeclass(0, "zone", zone->name, 0, 0);
			log_err("inuse %d count=%d tree.count=%d",
				zone->in_use, zone->count, 
				(int)zone->tree.count);
			if(negverbose)
				print_neg_cache(neg);
		}
		unit_assert(zone->in_use);
	}
	
	if(zone->parent) {
		unit_assert(zone->parent->count >= zone->count);
		if(zone->parent->in_use) {
			unit_assert(zone->parent->count > zone->count);
		}
		unit_assert(zone->parent->labs == zone->labs-1);
		/* and parent must be one label shorter */
		unit_assert(zone->name[0] == (zone->len-zone->parent->len-1));
		unit_assert(query_dname_compare(zone->name + zone->name[0]+1,
			zone->parent->name) == 0);
	} else {
		/* must be apex */
		unit_assert(dname_is_root(zone->name));
	}
	/* tree property: */
	unit_assert(zone->count == sum_zone_subtree_inuse(neg, zone));

	/* check structure of zone data tree */
	checkzonetree(zone);
}
Esempio n. 21
0
uint8_t* 
reply_find_final_cname_target(struct query_info* qinfo, struct reply_info* rep)
{
	uint8_t* sname = qinfo->qname;
	size_t snamelen = qinfo->qname_len;
	size_t i;
	for(i=0; i<rep->an_numrrsets; i++) {
		struct ub_packed_rrset_key* s = rep->rrsets[i];
		/* follow CNAME chain (if any) */
		if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && 
			ntohs(s->rk.rrset_class) == qinfo->qclass && 
			snamelen == s->rk.dname_len &&
			query_dname_compare(sname, s->rk.dname) == 0) {
			get_cname_target(s, &sname, &snamelen);
		}
	}
	if(sname != qinfo->qname)
		return sname;
	return NULL;
}
Esempio n. 22
0
int
val_chase_cname(struct query_info* qchase, struct reply_info* rep,
	size_t* cname_skip) {
	size_t i;
	/* skip any DNAMEs, go to the CNAME for next part */
	for(i = *cname_skip; i < rep->an_numrrsets; i++) {
		if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME &&
			query_dname_compare(qchase->qname, rep->rrsets[i]->
				rk.dname) == 0) {
			qchase->qname = NULL;
			get_cname_target(rep->rrsets[i], &qchase->qname,
				&qchase->qname_len);
			if(!qchase->qname)
				return 0; /* bad CNAME rdata */
			(*cname_skip) = i+1;
			return 1;
		}
	}
	return 0; /* CNAME classified but no matching CNAME ?! */
}
Esempio n. 23
0
/**
 * Compare a hashed name with the owner name of an NSEC3 RRset.
 * @param flt: filter with zone name.
 * @param hash: the hashed name.
 * @param s: rrset with owner name.
 * @return true if matches exactly, false if not.
 */
static int
nsec3_hash_matches_owner(struct nsec3_filter* flt, 
	struct nsec3_cached_hash* hash, struct ub_packed_rrset_key* s)
{
	uint8_t* nm = s->rk.dname;
	/* compare, does hash of name based on params in this NSEC3
	 * match the owner name of this NSEC3? 
	 * name must be: <hashlength>base32 . zone name 
	 * so; first label must not be root label (not zero length),
	 * and match the b32 encoded hash length, 
	 * and the label content match the b32 encoded hash
	 * and the rest must be the zone name.
	 */
	if(hash->b32_len != 0 && (size_t)nm[0] == hash->b32_len &&
		label_compare_lower(nm+1, hash->b32, hash->b32_len) == 0 &&
		query_dname_compare(nm+(size_t)nm[0]+1, flt->zone) == 0) {
		return 1;
	}
	return 0;
}
Esempio n. 24
0
/** check point in data tree */
static void check_data(struct val_neg_zone* zone, struct val_neg_data* data)
{
	unit_assert(data->count > 0);
	if(data->parent) {
		unit_assert(data->parent->count >= data->count);
		if(data->parent->in_use) {
			unit_assert(data->parent->count > data->count);
		}
		unit_assert(data->parent->labs == data->labs-1);
		/* and parent must be one label shorter */
		unit_assert(data->name[0] == (data->len-data->parent->len-1));
		unit_assert(query_dname_compare(data->name + data->name[0]+1,
			data->parent->name) == 0);
	} else {
		/* must be apex */
		unit_assert(dname_is_root(data->name));
	}
	/* tree property: */
	unit_assert(data->count == sum_subtree_inuse(zone, data));
}
Esempio n. 25
0
/** 
 * Initialize the filter structure.
 * Finds the zone by looking at available NSEC3 records and best match.
 * 	(skips the unknown flag and unknown algo NSEC3s).
 *
 * @param filter: nsec3 filter structure.
 * @param list: list of rrsets, an array of them.
 * @param num: number of rrsets in list.
 * @param qinfo: 
 *	query name to match a zone for.
 *	query type (if DS a higher zone must be chosen)
 *	qclass, to filter NSEC3s with.
 */
static void
filter_init(struct nsec3_filter* filter, struct ub_packed_rrset_key** list,
	size_t num, struct query_info* qinfo)
{
	size_t i;
	uint8_t* nm;
	size_t nmlen;
	filter->zone = NULL;
	filter->zone_len = 0;
	filter->list = list;
	filter->num = num;
	filter->fclass = qinfo->qclass;
	for(i=0; i<num; i++) {
		/* ignore other stuff in the list */
		if(ntohs(list[i]->rk.type) != LDNS_RR_TYPE_NSEC3 ||
			ntohs(list[i]->rk.rrset_class) != qinfo->qclass) 
			continue;
		/* skip unknown flags, algo */
		if(!nsec3_rrset_has_known(list[i]))
			continue;

		/* since NSEC3s are base32.zonename, we can find the zone
		 * name by stripping off the first label of the record */
		nm = list[i]->rk.dname;
		nmlen = list[i]->rk.dname_len;
		dname_remove_label(&nm, &nmlen);
		/* if we find a domain that can prove about the qname,
		 * and if this domain is closer to the qname */
		if(dname_subdomain_c(qinfo->qname, nm) && (!filter->zone ||
			dname_subdomain_c(nm, filter->zone))) {
			/* for a type DS do not accept a zone equal to qname*/
			if(qinfo->qtype == LDNS_RR_TYPE_DS && 
				query_dname_compare(qinfo->qname, nm) == 0 &&
				!dname_is_root(qinfo->qname))
				continue;
			filter->zone = nm;
			filter->zone_len = nmlen;
		}
	}
}
Esempio n. 26
0
int 
iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
        struct dns_msg* msg, uint16_t dclass)
{
	struct trust_anchor* a;
	/* information not available, !env->anchors can be common */
	if(!env || !env->anchors || !dp || !dp->name)
		return 0;
	/* a trust anchor exists with this name, RRSIGs expected */
	if((a=anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen,
		dclass))) {
		lock_basic_unlock(&a->lock);
		return 1;
	}
	/* see if DS rrset was given, in AUTH section */
	if(msg && msg->rep &&
		reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
		LDNS_RR_TYPE_DS, dclass))
		return 1;
	/* look in key cache */
	if(env->key_cache) {
		struct key_entry_key* kk = key_cache_obtain(env->key_cache,
			dp->name, dp->namelen, dclass, env->scratch, *env->now);
		if(kk) {
			if(query_dname_compare(kk->name, dp->name) == 0) {
			  if(key_entry_isgood(kk) || key_entry_isbad(kk)) {
				regional_free_all(env->scratch);
				return 1;
			  } else if(key_entry_isnull(kk)) {
				regional_free_all(env->scratch);
				return 0;
			  }
			}
			regional_free_all(env->scratch);
		}
	}
	return 0;
}
Esempio n. 27
0
/** 
 * Iterate through NSEC3 list, per RR 
 * This routine gives the next RR in the list (or sets rrset null). 
 * Usage:
 *
 * size_t rrsetnum;
 * int rrnum;
 * struct ub_packed_rrset_key* rrset;
 * for(rrset=filter_first(filter, &rrsetnum, &rrnum); rrset; 
 *	rrset=filter_next(filter, &rrsetnum, &rrnum))
 *		do_stuff;
 * 
 * Also filters out 
 * 	o unknown flag NSEC3s
 * 	o unknown algorithm NSEC3s.
 * @param filter: nsec3 filter structure.
 * @param rrsetnum: in/out rrset number to look at.
 * @param rrnum: in/out rr number in rrset to look at.
 * @returns ptr to the next rrset (or NULL at end).
 */
static struct ub_packed_rrset_key*
filter_next(struct nsec3_filter* filter, size_t* rrsetnum, int* rrnum)
{
	size_t i;
	int r;
	uint8_t* nm;
	size_t nmlen;
	if(!filter->zone) /* empty list */
		return NULL;
	for(i=*rrsetnum; i<filter->num; i++) {
		/* see if RRset qualifies */
		if(ntohs(filter->list[i]->rk.type) != LDNS_RR_TYPE_NSEC3 ||
			ntohs(filter->list[i]->rk.rrset_class) != 
			filter->fclass) 
			continue;
		/* check RRset zone */
		nm = filter->list[i]->rk.dname;
		nmlen = filter->list[i]->rk.dname_len;
		dname_remove_label(&nm, &nmlen);
		if(query_dname_compare(nm, filter->zone) != 0)
			continue;
		if(i == *rrsetnum)
			r = (*rrnum) + 1; /* continue at next RR */
		else	r = 0;		/* new RRset start at first RR */
		for(; r < (int)rrset_get_count(filter->list[i]); r++) {
			/* skip unknown flags, algo */
			if(nsec3_unknown_flags(filter->list[i], r) ||
				!nsec3_known_algo(filter->list[i], r))
				continue;
			/* this one is a good target */
			*rrsetnum = i;
			*rrnum = r;
			return filter->list[i];
		}
	}
	return NULL;
}
Esempio n. 28
0
struct iter_hints_stub* 
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname, 
	uint16_t qclass, struct delegpt* cache_dp)
{
	size_t len;
	int labs;
	struct iter_hints_stub *r;

	/* first lookup the stub */
	labs = dname_count_size_labels(qname, &len);
	r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, qname,
		len, labs, qclass);
	if(!r) return NULL;

	/* If there is no cache (root prime situation) */
	if(cache_dp == NULL) {
		if(r->dp->namelabs != 1)
			return r; /* no cache dp, use any non-root stub */
		return NULL;
	}

	/*
	 * If the stub is same as the delegation we got
	 * And has noprime set, we need to 'prime' to use this stub instead.
	 */
	if(r->noprime && query_dname_compare(cache_dp->name, r->dp->name)==0)
		return r; /* use this stub instead of cached dp */
	
	/* 
	 * If our cached delegation point is above the hint, we need to prime.
	 */
	if(dname_strict_subdomain(r->dp->name, r->dp->namelabs,
		cache_dp->name, cache_dp->namelabs))
		return r; /* need to prime this stub */
	return NULL;
}
Esempio n. 29
0
int
reply_check_cname_chain(struct reply_info* rep) 
{
	/* check only answer section rrs for matching cname chain.
	 * the cache may return changed rdata, but owner names are untouched.*/
	size_t i;
	uint8_t* sname = rep->rrsets[0]->rk.dname;
	size_t snamelen = rep->rrsets[0]->rk.dname_len;
	for(i=0; i<rep->an_numrrsets; i++) {
		uint16_t t = ntohs(rep->rrsets[i]->rk.type);
		if(t == LDNS_RR_TYPE_DNAME)
			continue; /* skip dnames; note TTL 0 not cached */
		/* verify that owner matches current sname */
		if(query_dname_compare(sname, rep->rrsets[i]->rk.dname) != 0){
			/* cname chain broken */
			return 0;
		}
		/* if this is a cname; move on */
		if(t == LDNS_RR_TYPE_CNAME) {
			get_cname_target(rep->rrsets[i], &sname, &snamelen);
		}
	}
	return 1;
}
Esempio n. 30
0
void 
val_fill_reply(struct reply_info* chase, struct reply_info* orig, 
	size_t skip, uint8_t* name, size_t len, uint8_t* signer)
{
	size_t i;
	int seen_dname = 0;
	chase->rrset_count = 0;
	chase->an_numrrsets = 0;
	chase->ns_numrrsets = 0;
	chase->ar_numrrsets = 0;
	/* ANSWER section */
	for(i=skip; i<orig->an_numrrsets; i++) {
		if(!signer) {
			if(query_dname_compare(name, 
				orig->rrsets[i]->rk.dname) == 0)
				chase->rrsets[chase->an_numrrsets++] = 
					orig->rrsets[i];
		} else if(seen_dname && ntohs(orig->rrsets[i]->rk.type) == 
			LDNS_RR_TYPE_CNAME) {
			chase->rrsets[chase->an_numrrsets++] = orig->rrsets[i];
			seen_dname = 0;
		} else if(rrset_has_signer(orig->rrsets[i], name, len)) {
			chase->rrsets[chase->an_numrrsets++] = orig->rrsets[i];
			if(ntohs(orig->rrsets[i]->rk.type) == 
				LDNS_RR_TYPE_DNAME) {
					seen_dname = 1;
			}
		}
	}	
	/* AUTHORITY section */
	for(i = (skip > orig->an_numrrsets)?skip:orig->an_numrrsets;
		i<orig->an_numrrsets+orig->ns_numrrsets; 
		i++) {
		if(!signer) {
			if(query_dname_compare(name, 
				orig->rrsets[i]->rk.dname) == 0)
				chase->rrsets[chase->an_numrrsets+
				    chase->ns_numrrsets++] = orig->rrsets[i];
		} else if(rrset_has_signer(orig->rrsets[i], name, len)) {
			chase->rrsets[chase->an_numrrsets+
				chase->ns_numrrsets++] = orig->rrsets[i];
		}
	}
	/* ADDITIONAL section */
	for(i= (skip>orig->an_numrrsets+orig->ns_numrrsets)?
		skip:orig->an_numrrsets+orig->ns_numrrsets; 
		i<orig->rrset_count; i++) {
		if(!signer) {
			if(query_dname_compare(name, 
				orig->rrsets[i]->rk.dname) == 0)
			    chase->rrsets[chase->an_numrrsets
				+orig->ns_numrrsets+chase->ar_numrrsets++] 
				= orig->rrsets[i];
		} else if(rrset_has_signer(orig->rrsets[i], name, len)) {
			chase->rrsets[chase->an_numrrsets+orig->ns_numrrsets+
				chase->ar_numrrsets++] = orig->rrsets[i];
		}
	}
	chase->rrset_count = chase->an_numrrsets + chase->ns_numrrsets + 
		chase->ar_numrrsets;
}