Пример #1
0
/**
 * Find closest existing parent data for the given name.
 * @param zone: to look in.
 * @param nm: name to look for
 * @param nm_len: length of nm
 * @param labs: labelcount of nm.
 * @return the data or NULL if none found.
 */
static struct val_neg_data* neg_closest_data_parent(
	struct val_neg_zone* zone, uint8_t* nm, size_t nm_len, int labs)
{
	struct val_neg_data key;
	struct val_neg_data* result;
	rbnode_t* res = NULL;
	key.node.key = &key;
	key.name = nm;
	key.len = nm_len;
	key.labs = labs;
	if(rbtree_find_less_equal(&zone->tree, &key, &res)) {
		/* exact match */
		result = (struct val_neg_data*)res;
	} else {
		/* smaller element (or no element) */
		int m;
		result = (struct val_neg_data*)res;
		if(!result)
			return NULL;
		/* count number of labels matched */
		(void)dname_lab_cmp(result->name, result->labs, key.name,
			key.labs, &m);
		while(result) { /* go up until qname is subdomain of stub */
			if(result->labs <= m)
				break;
			result = result->parent;
		}
	}
	return result;
}
Пример #2
0
/** initialise parent pointers in the tree */
static void
fwd_init_parents(struct iter_forwards* fwd)
{
	struct iter_forward_zone* node, *prev = NULL, *p;
	int m;
	RBTREE_FOR(node, struct iter_forward_zone*, fwd->tree) {
		node->parent = NULL;
		if(!prev || prev->dclass != node->dclass) {
			prev = node;
			continue;
		}
		(void)dname_lab_cmp(prev->name, prev->namelabs, node->name,
			node->namelabs, &m); /* we know prev is smaller */
		/* sort order like: . com. bla.com. zwb.com. net. */
		/* find the previous, or parent-parent-parent */
		for(p = prev; p; p = p->parent)
			/* looking for name with few labels, a parent */
			if(p->namelabs <= m) {
				/* ==: since prev matched m, this is closest*/
				/* <: prev matches more, but is not a parent,
				 * this one is a (grand)parent */
				node->parent = p;
				break;
			}
		prev = node;
	}
}
Пример #3
0
/**
 * Find best signer name in this set of rrsigs.
 * @param rrset: which rrsigs to look through.
 * @param qinf: the query name that needs validation.
 * @param signer_name: the best signer_name. Updated if a better one is found.
 * @param signer_len: length of signer name.
 * @param matchcount: count of current best name (starts at 0 for no match).
 * 	Updated if match is improved.
 */
static void
val_find_best_signer(struct ub_packed_rrset_key* rrset, 
	struct query_info* qinf, uint8_t** signer_name, size_t* signer_len, 
	int* matchcount)
{
	struct packed_rrset_data* d = (struct packed_rrset_data*)
		rrset->entry.data;
	uint8_t* sign;
	size_t i;
	int m;
	for(i=d->count; i<d->count+d->rrsig_count; i++) {
		sign = d->rr_data[i]+2+18;
		/* look at signatures that are valid (long enough),
		 * and have a signer name that is a superdomain of qname,
		 * and then check the number of labels in the shared topdomain
		 * improve the match if possible */
		if(d->rr_len[i] > 2+19 && /* rdata, sig + root label*/
			dname_subdomain_c(qinf->qname, sign)) {
			(void)dname_lab_cmp(qinf->qname, 
				dname_count_labels(qinf->qname), 
				sign, dname_count_labels(sign), &m);
			if(m > *matchcount) {
				*matchcount = m;
				*signer_name = sign;
				(void)dname_count_size_labels(*signer_name,
					signer_len);
			}
		}
	}
}
Пример #4
0
void
anchors_init_parents_locked(struct val_anchors* anchors)
{
	struct trust_anchor* node, *prev = NULL, *p;
	int m; 
	/* nobody else can grab locks because we hold the main lock.
	 * Thus the previous items, after unlocked, are not deleted */
	RBTREE_FOR(node, struct trust_anchor*, anchors->tree) {
		lock_basic_lock(&node->lock);
		node->parent = NULL;
		if(!prev || prev->dclass != node->dclass) {
			prev = node;
			lock_basic_unlock(&node->lock);
			continue;
		}
		(void)dname_lab_cmp(prev->name, prev->namelabs, node->name, 
			node->namelabs, &m); /* we know prev is smaller */
		/* sort order like: . com. bla.com. zwb.com. net. */
		/* find the previous, or parent-parent-parent */
		for(p = prev; p; p = p->parent)
			/* looking for name with few labels, a parent */
			if(p->namelabs <= m) {
				/* ==: since prev matched m, this is closest*/
				/* <: prev matches more, but is not a parent,
			 	* this one is a (grand)parent */
				node->parent = p;
				break;
			}
		lock_basic_unlock(&node->lock);
		prev = node;
	}
}
Пример #5
0
struct delegpt* 
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
{
	/* lookup the forward zone in the tree */
	rbnode_t* res = NULL;
	struct iter_forward_zone *result;
	struct iter_forward_zone key;
	key.node.key = &key;
	key.dclass = qclass;
	key.name = qname;
	key.namelabs = dname_count_size_labels(qname, &key.namelen);
	if(rbtree_find_less_equal(fwd->tree, &key, &res)) {
		/* exact */
		result = (struct iter_forward_zone*)res;
	} else {
		/* smaller element (or no element) */
		int m;
		result = (struct iter_forward_zone*)res;
		if(!result || result->dclass != qclass)
			return NULL;
		/* count number of labels matched */
		(void)dname_lab_cmp(result->name, result->namelabs, key.name,
			key.namelabs, &m);
		while(result) { /* go up until qname is subdomain of stub */
			if(result->namelabs <= m)
				break;
			result = result->parent;
		}
	}
	if(result)
		return result->dp;
	return NULL;
}
Пример #6
0
/** setup parent pointers, so that a lookup can be done for closest match */
static void
init_parents(struct local_zones* zones)
{
        struct local_zone* node, *prev = NULL, *p;
        int m;
	lock_rw_wrlock(&zones->lock);
        RBTREE_FOR(node, struct local_zone*, &zones->ztree) {
		lock_rw_wrlock(&node->lock);
                node->parent = NULL;
                if(!prev || prev->dclass != node->dclass) {
                        prev = node;
			lock_rw_unlock(&node->lock);
                        continue;
                }
                (void)dname_lab_cmp(prev->name, prev->namelabs, node->name,
                        node->namelabs, &m); /* we know prev is smaller */
                /* sort order like: . com. bla.com. zwb.com. net. */
                /* find the previous, or parent-parent-parent */
                for(p = prev; p; p = p->parent)
                        /* looking for name with few labels, a parent */
                        if(p->namelabs <= m) {
                                /* ==: since prev matched m, this is closest*/
                                /* <: prev matches more, but is not a parent,
                                 * this one is a (grand)parent */
                                node->parent = p;
                                break;
                        }
                prev = node;

		if(node->override_tree)
			addr_tree_init_parents(node->override_tree);
		lock_rw_unlock(&node->lock);
        }
	lock_rw_unlock(&zones->lock);
}
Пример #7
0
/**
 * Find domain name in tree, returns exact and closest match.
 * @param tree: root of tree.
 * @param dname: pointer to uncompressed dname.
 * @param labs: number of labels in domain name.
 * @param match: closest or exact match.
 *	guaranteed to be smaller or equal to the sought dname.
 *	can be null if the tree is empty.
 * @param matchlabels: number of labels that match with closest match.
 *	can be zero is there is no match.
 * @param insertpt: insert location for dname, if not found.
 * @return: 0 if no exact match.
 */
static int
compress_tree_search(struct compress_tree_node** tree, uint8_t* dname,
	int labs, struct compress_tree_node** match, int* matchlabels,
	struct compress_tree_node*** insertpt)
{
	int c, n, closen=0;
	struct compress_tree_node* p = *tree;
	struct compress_tree_node* close = 0;
	struct compress_tree_node** prev = tree;
	while(p) {
		if((c = dname_lab_cmp(dname, labs, p->dname, p->labs, &n)) 
			== 0) {
			*matchlabels = n;
			*match = p;
			return 1;
		}
		if(c<0) {
			prev = &p->left;
			p = p->left;
		} else	{
			closen = n;
			close = p; /* p->dname is smaller than dname */
			prev = &p->right;
			p = p->right;
		}
	}
	*insertpt = prev;
	*matchlabels = closen;
	*match = close;
	return 0;
}
Пример #8
0
struct local_zone* 
local_zones_tags_lookup(struct local_zones* zones,
        uint8_t* name, size_t len, int labs, uint16_t dclass,
	uint8_t* taglist, size_t taglen, int ignoretags)
{
	rbnode_t* res = NULL;
	struct local_zone *result;
	struct local_zone key;
	int m;
	key.node.key = &key;
	key.dclass = dclass;
	key.name = name;
	key.namelen = len;
	key.namelabs = labs;
	rbtree_find_less_equal(&zones->ztree, &key, &res);
	result = (struct local_zone*)res;
	/* exact or smaller element (or no element) */
	if(!result || result->dclass != dclass)
		return NULL;
	/* count number of labels matched */
	(void)dname_lab_cmp(result->name, result->namelabs, key.name,
		key.namelabs, &m);
	while(result) { /* go up until qname is zone or subdomain of zone */
		if(result->namelabs <= m)
			if(ignoretags || !result->taglist ||
				taglist_intersect(result->taglist, 
				result->taglen, taglist, taglen))
				break;
		result = result->parent;
	}
	return result;
}
Пример #9
0
uint8_t* dname_get_shared_topdomain(uint8_t* d1, uint8_t* d2)
{
    int labs1, labs2, m;
    size_t len = LDNS_MAX_DOMAINLEN;
    labs1 = dname_count_labels(d1);
    labs2 = dname_count_labels(d2);
    (void)dname_lab_cmp(d1, labs1, d2, labs2, &m);
    dname_remove_labels(&d1, &len, labs1-m);
    return d1;
}
Пример #10
0
int name_tree_compare(const void* k1, const void* k2)
{
        struct name_tree_node* x = (struct name_tree_node*)k1;
        struct name_tree_node* y = (struct name_tree_node*)k2;
        int m;
        if(x->dclass != y->dclass) {
                if(x->dclass < y->dclass)
                        return -1;
                return 1;
        }
        return dname_lab_cmp(x->name, x->labs, y->name, y->labs, &m);
}
Пример #11
0
int
dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2)
{
    int m;
    /* check subdomain: d1: www.example.com. and d2: example.com. */
    if(labs2 >= labs1)
        return 0;
    if(dname_lab_cmp(d1, labs1, d2, labs2, &m) > 0) {
        /* subdomain if all labels match */
        return (m == labs2);
    }
    return 0;
}
Пример #12
0
int
fwd_cmp(const void* k1, const void* k2)
{
	int m;
	struct iter_forward_zone* n1 = (struct iter_forward_zone*)k1;
	struct iter_forward_zone* n2 = (struct iter_forward_zone*)k2;
	if(n1->dclass != n2->dclass) {
		if(n1->dclass < n2->dclass)
			return -1;
		return 1;
	}
	return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs, 
		&m);
}
Пример #13
0
int
anchor_cmp(const void* k1, const void* k2)
{
	int m;
	struct trust_anchor* n1 = (struct trust_anchor*)k1;
	struct trust_anchor* n2 = (struct trust_anchor*)k2;
	/* no need to ntohs(class) because sort order is irrelevant */
	if(n1->dclass != n2->dclass) {
		if(n1->dclass < n2->dclass)
			return -1;
		return 1;
	}
	return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs, 
		&m);
}
Пример #14
0
int 
local_zone_cmp(const void* z1, const void* z2)
{
	/* first sort on class, so that hierarchy can be maintained within
	 * a class */
	struct local_zone* a = (struct local_zone*)z1;
	struct local_zone* b = (struct local_zone*)z2;
	int m;
	if(a->dclass != b->dclass) {
		if(a->dclass < b->dclass)
			return -1;
		return 1;
	}
	return dname_lab_cmp(a->name, a->namelabs, b->name, b->namelabs, &m);
}
Пример #15
0
int
dname_subdomain_c(uint8_t* d1, uint8_t* d2)
{
    int m;
    /* check subdomain: d1: www.example.com. and d2: example.com. */
    /*  	or 	    d1: example.com. and d2: example.com. */
    int labs1 = dname_count_labels(d1);
    int labs2 = dname_count_labels(d2);
    if(labs2 > labs1)
        return 0;
    if(dname_lab_cmp(d1, labs1, d2, labs2, &m) < 0) {
        /* must have been example.com , www.example.com - wrong */
        /* or otherwise different dnames */
        return 0;
    }
    return (m == labs2);
}
Пример #16
0
struct trust_anchor* 
anchors_lookup(struct val_anchors* anchors,
        uint8_t* qname, size_t qname_len, uint16_t qclass)
{
	struct trust_anchor key;
	struct trust_anchor* result;
	rbnode_t* res = NULL;
	key.node.key = &key;
	key.name = qname;
	key.namelabs = dname_count_labels(qname);
	key.namelen = qname_len;
	key.dclass = qclass;
	lock_basic_lock(&anchors->lock);
	if(rbtree_find_less_equal(anchors->tree, &key, &res)) {
		/* exact */
		result = (struct trust_anchor*)res;
	} else {
		/* smaller element (or no element) */
		int m;
		result = (struct trust_anchor*)res;
		if(!result || result->dclass != qclass) {
			lock_basic_unlock(&anchors->lock);
			return NULL;
		}
		/* count number of labels matched */
		(void)dname_lab_cmp(result->name, result->namelabs, key.name,
			key.namelabs, &m);
		while(result) { /* go up until qname is subdomain of stub */
			if(result->namelabs <= m)
				break;
			result = result->parent;
		}
	}
	if(result) {
		lock_basic_lock(&result->lock);
	}
	lock_basic_unlock(&anchors->lock);
	return result;
}
Пример #17
0
/** test dname_lab_cmp */
static void
dname_test_dname_lab_cmp(void)
{
	int ml = 0; /* number of labels that matched exactly */
	unit_show_func("util/data/dname.c", "dname_lab_cmp");

	/* test for equality succeeds */
	unit_assert(dname_lab_cmp((uint8_t*)"", 1, (uint8_t*)"", 1, &ml) == 0);
	unit_assert(ml == 1);
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\003net", 2, 
		(uint8_t*)"\003net", 2, 
		&ml) == 0);
	unit_assert(ml == 2);
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\007example\003net", 3, 
		(uint8_t*)"\007example\003net", 3, 
		&ml) == 0);
	unit_assert(ml == 3);
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\004test\007example\003net", 4, 
		(uint8_t*)"\004test\007example\003net", 4, 
		&ml) == 0);
	unit_assert(ml == 4);

	/* root is smaller than anything else */
	unit_assert(dname_lab_cmp(
		(uint8_t*)"", 1, 
		(uint8_t*)"\003net", 2, 
		&ml) == -1);
	unit_assert(ml == 1);
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\003net", 2, 
		(uint8_t*)"", 1, 
		&ml) == 1);
	unit_assert(ml == 1);
	unit_assert(dname_lab_cmp(
		(uint8_t*)"", 1, 
		(uint8_t*)"\007example\003net", 3, 
		&ml) == -1);
	unit_assert(ml == 1);
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\007example\003net", 3, 
		(uint8_t*)"", 1, 
		&ml) == 1);
	unit_assert(ml == 1);

	/* label length makes a difference */
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\004neta", 2, 
		(uint8_t*)"\003net", 2, 
		&ml) != 0);
	unit_assert(ml == 1);
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\002ne", 2, 
		(uint8_t*)"\004neta", 2, 
		&ml) != 0);
	unit_assert(ml == 1);

	/* contents follow the zone apex */
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\003bla\007example\003net", 4, 
		(uint8_t*)"\007example\003net", 3, 
		&ml) == 1);
	unit_assert(ml == 3);
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\007example\003net", 3, 
		(uint8_t*)"\003bla\007example\003net", 4, 
		&ml) == -1);
	unit_assert(ml == 3);

	/* label content makes a difference */
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\003aag\007example\003net", 4, 
		(uint8_t*)"\003bla\007example\003net", 4, 
		&ml) == -1);
	unit_assert(ml == 3);
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\003aag\007example\003net", 4, 
		(uint8_t*)"\003bla\007example\003net", 4, 
		&ml) == -1);
	unit_assert(ml == 3);
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\003bla\003aag\007example\003net", 5, 
		(uint8_t*)"\003aag\003bla\007example\003net", 5, 
		&ml) == -1);
	unit_assert(ml == 3);
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\02sn\003opt\003aag\007example\003net", 6, 
		(uint8_t*)"\02sn\003opt\003bla\007example\003net", 6, 
		&ml) == -1);
	unit_assert(ml == 3);

	/* but lowercase/uppercase does not make a difference. */
	unit_assert(dname_lab_cmp(
		(uint8_t*)"\003bLa\007examPLe\003net", 4, 
		(uint8_t*)"\003bla\007eXAmple\003nET", 4, 
		&ml) == 0);
	unit_assert(ml == 4);
}
Пример #18
0
/** enter implicit transparent zone for local-data: without local-zone: */
static int
lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
{
	/* walk over all items that have no parent zone and find
	 * the name that covers them all (could be the root) and
	 * add that as a transparent zone */
	struct config_strlist* p;
	int have_name = 0;
	int have_other_classes = 0;
	uint16_t dclass = 0;
	uint8_t* nm = 0;
	size_t nmlen = 0;
	int nmlabs = 0;
	int match = 0; /* number of labels match count */

	init_parents(zones); /* to enable local_zones_lookup() */
	for(p = cfg->local_data; p; p = p->next) {
		uint8_t* rr_name;
		uint16_t rr_class;
		size_t len;
		int labs;
		if(!get_rr_nameclass(p->str, &rr_name, &rr_class)) {
			log_err("Bad local-data RR %s", p->str);
			return 0;
		}
		labs = dname_count_size_labels(rr_name, &len);
		lock_rw_rdlock(&zones->lock);
		if(!local_zones_lookup(zones, rr_name, len, labs, rr_class)) {
			if(!have_name) {
				dclass = rr_class;
				nm = rr_name;
				nmlen = len;
				nmlabs = labs;
				match = labs;
				have_name = 1;
			} else {
				int m;
				if(rr_class != dclass) {
					/* process other classes later */
					free(rr_name);
					have_other_classes = 1;
					lock_rw_unlock(&zones->lock);
					continue;
				}
				/* find smallest shared topdomain */
				(void)dname_lab_cmp(nm, nmlabs, 
					rr_name, labs, &m);
				free(rr_name);
				if(m < match)
					match = m;
			}
		} else free(rr_name);
		lock_rw_unlock(&zones->lock);
	}
	if(have_name) {
		uint8_t* n2;
		struct local_zone* z;
		/* allocate zone of smallest shared topdomain to contain em */
		n2 = nm;
		dname_remove_labels(&n2, &nmlen, nmlabs - match);
		n2 = memdup(n2, nmlen);
		free(nm);
		if(!n2) {
			log_err("out of memory");
			return 0;
		}
		log_nametypeclass(VERB_ALGO, "implicit transparent local-zone", 
			n2, 0, dclass);
		if(!(z=lz_enter_zone_dname(zones, n2, nmlen, match, 
			local_zone_transparent, dclass))) {
			return 0;
		}
		lock_rw_unlock(&z->lock);
	}
	if(have_other_classes) { 
		/* restart to setup other class */
		return lz_setup_implicit(zones, cfg);
	}
	return 1;
}