xref: /freebsd/contrib/unbound/validator/val_anchor.c (revision b7579f77d18196a58ff700756c84dc9a302a7f67)
1*b7579f77SDag-Erling Smørgrav /*
2*b7579f77SDag-Erling Smørgrav  * validator/val_anchor.c - validator trust anchor storage.
3*b7579f77SDag-Erling Smørgrav  *
4*b7579f77SDag-Erling Smørgrav  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5*b7579f77SDag-Erling Smørgrav  *
6*b7579f77SDag-Erling Smørgrav  * This software is open source.
7*b7579f77SDag-Erling Smørgrav  *
8*b7579f77SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
9*b7579f77SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
10*b7579f77SDag-Erling Smørgrav  * are met:
11*b7579f77SDag-Erling Smørgrav  *
12*b7579f77SDag-Erling Smørgrav  * Redistributions of source code must retain the above copyright notice,
13*b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer.
14*b7579f77SDag-Erling Smørgrav  *
15*b7579f77SDag-Erling Smørgrav  * Redistributions in binary form must reproduce the above copyright notice,
16*b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer in the documentation
17*b7579f77SDag-Erling Smørgrav  * and/or other materials provided with the distribution.
18*b7579f77SDag-Erling Smørgrav  *
19*b7579f77SDag-Erling Smørgrav  * Neither the name of the NLNET LABS nor the names of its contributors may
20*b7579f77SDag-Erling Smørgrav  * be used to endorse or promote products derived from this software without
21*b7579f77SDag-Erling Smørgrav  * specific prior written permission.
22*b7579f77SDag-Erling Smørgrav  *
23*b7579f77SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24*b7579f77SDag-Erling Smørgrav  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25*b7579f77SDag-Erling Smørgrav  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26*b7579f77SDag-Erling Smørgrav  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
27*b7579f77SDag-Erling Smørgrav  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28*b7579f77SDag-Erling Smørgrav  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29*b7579f77SDag-Erling Smørgrav  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30*b7579f77SDag-Erling Smørgrav  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31*b7579f77SDag-Erling Smørgrav  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32*b7579f77SDag-Erling Smørgrav  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33*b7579f77SDag-Erling Smørgrav  * POSSIBILITY OF SUCH DAMAGE.
34*b7579f77SDag-Erling Smørgrav  */
35*b7579f77SDag-Erling Smørgrav 
36*b7579f77SDag-Erling Smørgrav /**
37*b7579f77SDag-Erling Smørgrav  * \file
38*b7579f77SDag-Erling Smørgrav  *
39*b7579f77SDag-Erling Smørgrav  * This file contains storage for the trust anchors for the validator.
40*b7579f77SDag-Erling Smørgrav  */
41*b7579f77SDag-Erling Smørgrav #include "config.h"
42*b7579f77SDag-Erling Smørgrav #include <ctype.h>
43*b7579f77SDag-Erling Smørgrav #include <ldns/dname.h>
44*b7579f77SDag-Erling Smørgrav #include <ldns/host2wire.h>
45*b7579f77SDag-Erling Smørgrav #include "validator/val_anchor.h"
46*b7579f77SDag-Erling Smørgrav #include "validator/val_sigcrypt.h"
47*b7579f77SDag-Erling Smørgrav #include "validator/autotrust.h"
48*b7579f77SDag-Erling Smørgrav #include "util/data/packed_rrset.h"
49*b7579f77SDag-Erling Smørgrav #include "util/data/dname.h"
50*b7579f77SDag-Erling Smørgrav #include "util/log.h"
51*b7579f77SDag-Erling Smørgrav #include "util/net_help.h"
52*b7579f77SDag-Erling Smørgrav #include "util/config_file.h"
53*b7579f77SDag-Erling Smørgrav #ifdef HAVE_GLOB_H
54*b7579f77SDag-Erling Smørgrav #include <glob.h>
55*b7579f77SDag-Erling Smørgrav #endif
56*b7579f77SDag-Erling Smørgrav 
57*b7579f77SDag-Erling Smørgrav int
58*b7579f77SDag-Erling Smørgrav anchor_cmp(const void* k1, const void* k2)
59*b7579f77SDag-Erling Smørgrav {
60*b7579f77SDag-Erling Smørgrav 	int m;
61*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* n1 = (struct trust_anchor*)k1;
62*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* n2 = (struct trust_anchor*)k2;
63*b7579f77SDag-Erling Smørgrav 	/* no need to ntohs(class) because sort order is irrelevant */
64*b7579f77SDag-Erling Smørgrav 	if(n1->dclass != n2->dclass) {
65*b7579f77SDag-Erling Smørgrav 		if(n1->dclass < n2->dclass)
66*b7579f77SDag-Erling Smørgrav 			return -1;
67*b7579f77SDag-Erling Smørgrav 		return 1;
68*b7579f77SDag-Erling Smørgrav 	}
69*b7579f77SDag-Erling Smørgrav 	return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs,
70*b7579f77SDag-Erling Smørgrav 		&m);
71*b7579f77SDag-Erling Smørgrav }
72*b7579f77SDag-Erling Smørgrav 
73*b7579f77SDag-Erling Smørgrav struct val_anchors*
74*b7579f77SDag-Erling Smørgrav anchors_create(void)
75*b7579f77SDag-Erling Smørgrav {
76*b7579f77SDag-Erling Smørgrav 	struct val_anchors* a = (struct val_anchors*)calloc(1, sizeof(*a));
77*b7579f77SDag-Erling Smørgrav 	if(!a)
78*b7579f77SDag-Erling Smørgrav 		return NULL;
79*b7579f77SDag-Erling Smørgrav 	a->tree = rbtree_create(anchor_cmp);
80*b7579f77SDag-Erling Smørgrav 	if(!a->tree) {
81*b7579f77SDag-Erling Smørgrav 		anchors_delete(a);
82*b7579f77SDag-Erling Smørgrav 		return NULL;
83*b7579f77SDag-Erling Smørgrav 	}
84*b7579f77SDag-Erling Smørgrav 	a->autr = autr_global_create();
85*b7579f77SDag-Erling Smørgrav 	if(!a->autr) {
86*b7579f77SDag-Erling Smørgrav 		anchors_delete(a);
87*b7579f77SDag-Erling Smørgrav 		return NULL;
88*b7579f77SDag-Erling Smørgrav 	}
89*b7579f77SDag-Erling Smørgrav 	lock_basic_init(&a->lock);
90*b7579f77SDag-Erling Smørgrav 	lock_protect(&a->lock, a, sizeof(*a));
91*b7579f77SDag-Erling Smørgrav 	lock_protect(&a->lock, a->autr, sizeof(*a->autr));
92*b7579f77SDag-Erling Smørgrav 	return a;
93*b7579f77SDag-Erling Smørgrav }
94*b7579f77SDag-Erling Smørgrav 
95*b7579f77SDag-Erling Smørgrav /** delete assembled rrset */
96*b7579f77SDag-Erling Smørgrav static void
97*b7579f77SDag-Erling Smørgrav assembled_rrset_delete(struct ub_packed_rrset_key* pkey)
98*b7579f77SDag-Erling Smørgrav {
99*b7579f77SDag-Erling Smørgrav 	if(!pkey) return;
100*b7579f77SDag-Erling Smørgrav 	if(pkey->entry.data) {
101*b7579f77SDag-Erling Smørgrav 		struct packed_rrset_data* pd = (struct packed_rrset_data*)
102*b7579f77SDag-Erling Smørgrav 			pkey->entry.data;
103*b7579f77SDag-Erling Smørgrav 		free(pd->rr_data);
104*b7579f77SDag-Erling Smørgrav 		free(pd->rr_ttl);
105*b7579f77SDag-Erling Smørgrav 		free(pd->rr_len);
106*b7579f77SDag-Erling Smørgrav 		free(pd);
107*b7579f77SDag-Erling Smørgrav 	}
108*b7579f77SDag-Erling Smørgrav 	free(pkey->rk.dname);
109*b7579f77SDag-Erling Smørgrav 	free(pkey);
110*b7579f77SDag-Erling Smørgrav }
111*b7579f77SDag-Erling Smørgrav 
112*b7579f77SDag-Erling Smørgrav /** destroy locks in tree and delete autotrust anchors */
113*b7579f77SDag-Erling Smørgrav static void
114*b7579f77SDag-Erling Smørgrav anchors_delfunc(rbnode_t* elem, void* ATTR_UNUSED(arg))
115*b7579f77SDag-Erling Smørgrav {
116*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* ta = (struct trust_anchor*)elem;
117*b7579f77SDag-Erling Smørgrav 	if(!ta) return;
118*b7579f77SDag-Erling Smørgrav 	if(ta->autr) {
119*b7579f77SDag-Erling Smørgrav 		autr_point_delete(ta);
120*b7579f77SDag-Erling Smørgrav 	} else {
121*b7579f77SDag-Erling Smørgrav 		struct ta_key* p, *np;
122*b7579f77SDag-Erling Smørgrav 		lock_basic_destroy(&ta->lock);
123*b7579f77SDag-Erling Smørgrav 		free(ta->name);
124*b7579f77SDag-Erling Smørgrav 		p = ta->keylist;
125*b7579f77SDag-Erling Smørgrav 		while(p) {
126*b7579f77SDag-Erling Smørgrav 			np = p->next;
127*b7579f77SDag-Erling Smørgrav 			free(p->data);
128*b7579f77SDag-Erling Smørgrav 			free(p);
129*b7579f77SDag-Erling Smørgrav 			p = np;
130*b7579f77SDag-Erling Smørgrav 		}
131*b7579f77SDag-Erling Smørgrav 		assembled_rrset_delete(ta->ds_rrset);
132*b7579f77SDag-Erling Smørgrav 		assembled_rrset_delete(ta->dnskey_rrset);
133*b7579f77SDag-Erling Smørgrav 		free(ta);
134*b7579f77SDag-Erling Smørgrav 	}
135*b7579f77SDag-Erling Smørgrav }
136*b7579f77SDag-Erling Smørgrav 
137*b7579f77SDag-Erling Smørgrav void
138*b7579f77SDag-Erling Smørgrav anchors_delete(struct val_anchors* anchors)
139*b7579f77SDag-Erling Smørgrav {
140*b7579f77SDag-Erling Smørgrav 	if(!anchors)
141*b7579f77SDag-Erling Smørgrav 		return;
142*b7579f77SDag-Erling Smørgrav 	lock_unprotect(&anchors->lock, anchors->autr);
143*b7579f77SDag-Erling Smørgrav 	lock_unprotect(&anchors->lock, anchors);
144*b7579f77SDag-Erling Smørgrav 	lock_basic_destroy(&anchors->lock);
145*b7579f77SDag-Erling Smørgrav 	if(anchors->tree)
146*b7579f77SDag-Erling Smørgrav 		traverse_postorder(anchors->tree, anchors_delfunc, NULL);
147*b7579f77SDag-Erling Smørgrav 	free(anchors->tree);
148*b7579f77SDag-Erling Smørgrav 	autr_global_delete(anchors->autr);
149*b7579f77SDag-Erling Smørgrav 	free(anchors);
150*b7579f77SDag-Erling Smørgrav }
151*b7579f77SDag-Erling Smørgrav 
152*b7579f77SDag-Erling Smørgrav void
153*b7579f77SDag-Erling Smørgrav anchors_init_parents_locked(struct val_anchors* anchors)
154*b7579f77SDag-Erling Smørgrav {
155*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* node, *prev = NULL, *p;
156*b7579f77SDag-Erling Smørgrav 	int m;
157*b7579f77SDag-Erling Smørgrav 	/* nobody else can grab locks because we hold the main lock.
158*b7579f77SDag-Erling Smørgrav 	 * Thus the previous items, after unlocked, are not deleted */
159*b7579f77SDag-Erling Smørgrav 	RBTREE_FOR(node, struct trust_anchor*, anchors->tree) {
160*b7579f77SDag-Erling Smørgrav 		lock_basic_lock(&node->lock);
161*b7579f77SDag-Erling Smørgrav 		node->parent = NULL;
162*b7579f77SDag-Erling Smørgrav 		if(!prev || prev->dclass != node->dclass) {
163*b7579f77SDag-Erling Smørgrav 			prev = node;
164*b7579f77SDag-Erling Smørgrav 			lock_basic_unlock(&node->lock);
165*b7579f77SDag-Erling Smørgrav 			continue;
166*b7579f77SDag-Erling Smørgrav 		}
167*b7579f77SDag-Erling Smørgrav 		(void)dname_lab_cmp(prev->name, prev->namelabs, node->name,
168*b7579f77SDag-Erling Smørgrav 			node->namelabs, &m); /* we know prev is smaller */
169*b7579f77SDag-Erling Smørgrav 		/* sort order like: . com. bla.com. zwb.com. net. */
170*b7579f77SDag-Erling Smørgrav 		/* find the previous, or parent-parent-parent */
171*b7579f77SDag-Erling Smørgrav 		for(p = prev; p; p = p->parent)
172*b7579f77SDag-Erling Smørgrav 			/* looking for name with few labels, a parent */
173*b7579f77SDag-Erling Smørgrav 			if(p->namelabs <= m) {
174*b7579f77SDag-Erling Smørgrav 				/* ==: since prev matched m, this is closest*/
175*b7579f77SDag-Erling Smørgrav 				/* <: prev matches more, but is not a parent,
176*b7579f77SDag-Erling Smørgrav 			 	* this one is a (grand)parent */
177*b7579f77SDag-Erling Smørgrav 				node->parent = p;
178*b7579f77SDag-Erling Smørgrav 				break;
179*b7579f77SDag-Erling Smørgrav 			}
180*b7579f77SDag-Erling Smørgrav 		lock_basic_unlock(&node->lock);
181*b7579f77SDag-Erling Smørgrav 		prev = node;
182*b7579f77SDag-Erling Smørgrav 	}
183*b7579f77SDag-Erling Smørgrav }
184*b7579f77SDag-Erling Smørgrav 
185*b7579f77SDag-Erling Smørgrav /** initialise parent pointers in the tree */
186*b7579f77SDag-Erling Smørgrav static void
187*b7579f77SDag-Erling Smørgrav init_parents(struct val_anchors* anchors)
188*b7579f77SDag-Erling Smørgrav {
189*b7579f77SDag-Erling Smørgrav 	lock_basic_lock(&anchors->lock);
190*b7579f77SDag-Erling Smørgrav 	anchors_init_parents_locked(anchors);
191*b7579f77SDag-Erling Smørgrav 	lock_basic_unlock(&anchors->lock);
192*b7579f77SDag-Erling Smørgrav }
193*b7579f77SDag-Erling Smørgrav 
194*b7579f77SDag-Erling Smørgrav struct trust_anchor*
195*b7579f77SDag-Erling Smørgrav anchor_find(struct val_anchors* anchors, uint8_t* name, int namelabs,
196*b7579f77SDag-Erling Smørgrav 	size_t namelen, uint16_t dclass)
197*b7579f77SDag-Erling Smørgrav {
198*b7579f77SDag-Erling Smørgrav 	struct trust_anchor key;
199*b7579f77SDag-Erling Smørgrav 	rbnode_t* n;
200*b7579f77SDag-Erling Smørgrav 	if(!name) return NULL;
201*b7579f77SDag-Erling Smørgrav 	key.node.key = &key;
202*b7579f77SDag-Erling Smørgrav 	key.name = name;
203*b7579f77SDag-Erling Smørgrav 	key.namelabs = namelabs;
204*b7579f77SDag-Erling Smørgrav 	key.namelen = namelen;
205*b7579f77SDag-Erling Smørgrav 	key.dclass = dclass;
206*b7579f77SDag-Erling Smørgrav 	lock_basic_lock(&anchors->lock);
207*b7579f77SDag-Erling Smørgrav 	n = rbtree_search(anchors->tree, &key);
208*b7579f77SDag-Erling Smørgrav 	if(n) {
209*b7579f77SDag-Erling Smørgrav 		lock_basic_lock(&((struct trust_anchor*)n->key)->lock);
210*b7579f77SDag-Erling Smørgrav 	}
211*b7579f77SDag-Erling Smørgrav 	lock_basic_unlock(&anchors->lock);
212*b7579f77SDag-Erling Smørgrav 	if(!n)
213*b7579f77SDag-Erling Smørgrav 		return NULL;
214*b7579f77SDag-Erling Smørgrav 	return (struct trust_anchor*)n->key;
215*b7579f77SDag-Erling Smørgrav }
216*b7579f77SDag-Erling Smørgrav 
217*b7579f77SDag-Erling Smørgrav /** create new trust anchor object */
218*b7579f77SDag-Erling Smørgrav static struct trust_anchor*
219*b7579f77SDag-Erling Smørgrav anchor_new_ta(struct val_anchors* anchors, uint8_t* name, int namelabs,
220*b7579f77SDag-Erling Smørgrav 	size_t namelen, uint16_t dclass, int lockit)
221*b7579f77SDag-Erling Smørgrav {
222*b7579f77SDag-Erling Smørgrav #ifdef UNBOUND_DEBUG
223*b7579f77SDag-Erling Smørgrav 	rbnode_t* r;
224*b7579f77SDag-Erling Smørgrav #endif
225*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* ta = (struct trust_anchor*)malloc(
226*b7579f77SDag-Erling Smørgrav 		sizeof(struct trust_anchor));
227*b7579f77SDag-Erling Smørgrav 	if(!ta)
228*b7579f77SDag-Erling Smørgrav 		return NULL;
229*b7579f77SDag-Erling Smørgrav 	memset(ta, 0, sizeof(*ta));
230*b7579f77SDag-Erling Smørgrav 	ta->node.key = ta;
231*b7579f77SDag-Erling Smørgrav 	ta->name = memdup(name, namelen);
232*b7579f77SDag-Erling Smørgrav 	if(!ta->name) {
233*b7579f77SDag-Erling Smørgrav 		free(ta);
234*b7579f77SDag-Erling Smørgrav 		return NULL;
235*b7579f77SDag-Erling Smørgrav 	}
236*b7579f77SDag-Erling Smørgrav 	ta->namelabs = namelabs;
237*b7579f77SDag-Erling Smørgrav 	ta->namelen = namelen;
238*b7579f77SDag-Erling Smørgrav 	ta->dclass = dclass;
239*b7579f77SDag-Erling Smørgrav 	lock_basic_init(&ta->lock);
240*b7579f77SDag-Erling Smørgrav 	if(lockit) {
241*b7579f77SDag-Erling Smørgrav 		lock_basic_lock(&anchors->lock);
242*b7579f77SDag-Erling Smørgrav 	}
243*b7579f77SDag-Erling Smørgrav #ifdef UNBOUND_DEBUG
244*b7579f77SDag-Erling Smørgrav 	r =
245*b7579f77SDag-Erling Smørgrav #endif
246*b7579f77SDag-Erling Smørgrav 	rbtree_insert(anchors->tree, &ta->node);
247*b7579f77SDag-Erling Smørgrav 	if(lockit) {
248*b7579f77SDag-Erling Smørgrav 		lock_basic_unlock(&anchors->lock);
249*b7579f77SDag-Erling Smørgrav 	}
250*b7579f77SDag-Erling Smørgrav 	log_assert(r != NULL);
251*b7579f77SDag-Erling Smørgrav 	return ta;
252*b7579f77SDag-Erling Smørgrav }
253*b7579f77SDag-Erling Smørgrav 
254*b7579f77SDag-Erling Smørgrav /** find trustanchor key by exact data match */
255*b7579f77SDag-Erling Smørgrav static struct ta_key*
256*b7579f77SDag-Erling Smørgrav anchor_find_key(struct trust_anchor* ta, uint8_t* rdata, size_t rdata_len,
257*b7579f77SDag-Erling Smørgrav 	uint16_t type)
258*b7579f77SDag-Erling Smørgrav {
259*b7579f77SDag-Erling Smørgrav 	struct ta_key* k;
260*b7579f77SDag-Erling Smørgrav 	for(k = ta->keylist; k; k = k->next) {
261*b7579f77SDag-Erling Smørgrav 		if(k->type == type && k->len == rdata_len &&
262*b7579f77SDag-Erling Smørgrav 			memcmp(k->data, rdata, rdata_len) == 0)
263*b7579f77SDag-Erling Smørgrav 			return k;
264*b7579f77SDag-Erling Smørgrav 	}
265*b7579f77SDag-Erling Smørgrav 	return NULL;
266*b7579f77SDag-Erling Smørgrav }
267*b7579f77SDag-Erling Smørgrav 
268*b7579f77SDag-Erling Smørgrav /** create new trustanchor key */
269*b7579f77SDag-Erling Smørgrav static struct ta_key*
270*b7579f77SDag-Erling Smørgrav anchor_new_ta_key(uint8_t* rdata, size_t rdata_len, uint16_t type)
271*b7579f77SDag-Erling Smørgrav {
272*b7579f77SDag-Erling Smørgrav 	struct ta_key* k = (struct ta_key*)malloc(sizeof(*k));
273*b7579f77SDag-Erling Smørgrav 	if(!k)
274*b7579f77SDag-Erling Smørgrav 		return NULL;
275*b7579f77SDag-Erling Smørgrav 	memset(k, 0, sizeof(*k));
276*b7579f77SDag-Erling Smørgrav 	k->data = memdup(rdata, rdata_len);
277*b7579f77SDag-Erling Smørgrav 	if(!k->data) {
278*b7579f77SDag-Erling Smørgrav 		free(k);
279*b7579f77SDag-Erling Smørgrav 		return NULL;
280*b7579f77SDag-Erling Smørgrav 	}
281*b7579f77SDag-Erling Smørgrav 	k->len = rdata_len;
282*b7579f77SDag-Erling Smørgrav 	k->type = type;
283*b7579f77SDag-Erling Smørgrav 	return k;
284*b7579f77SDag-Erling Smørgrav }
285*b7579f77SDag-Erling Smørgrav 
286*b7579f77SDag-Erling Smørgrav /**
287*b7579f77SDag-Erling Smørgrav  * This routine adds a new RR to a trust anchor. The trust anchor may not
288*b7579f77SDag-Erling Smørgrav  * exist yet, and is created if not. The RR can be DS or DNSKEY.
289*b7579f77SDag-Erling Smørgrav  * This routine will also remove duplicates; storing them only once.
290*b7579f77SDag-Erling Smørgrav  * @param anchors: anchor storage.
291*b7579f77SDag-Erling Smørgrav  * @param name: name of trust anchor (wireformat)
292*b7579f77SDag-Erling Smørgrav  * @param type: type or RR
293*b7579f77SDag-Erling Smørgrav  * @param dclass: class of RR
294*b7579f77SDag-Erling Smørgrav  * @param rdata: rdata wireformat, starting with rdlength.
295*b7579f77SDag-Erling Smørgrav  *	If NULL, nothing is stored, but an entry is created.
296*b7579f77SDag-Erling Smørgrav  * @param rdata_len: length of rdata including rdlength.
297*b7579f77SDag-Erling Smørgrav  * @return: NULL on error, else the trust anchor.
298*b7579f77SDag-Erling Smørgrav  */
299*b7579f77SDag-Erling Smørgrav static struct trust_anchor*
300*b7579f77SDag-Erling Smørgrav anchor_store_new_key(struct val_anchors* anchors, uint8_t* name, uint16_t type,
301*b7579f77SDag-Erling Smørgrav 	uint16_t dclass, uint8_t* rdata, size_t rdata_len)
302*b7579f77SDag-Erling Smørgrav {
303*b7579f77SDag-Erling Smørgrav 	struct ta_key* k;
304*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* ta;
305*b7579f77SDag-Erling Smørgrav 	int namelabs;
306*b7579f77SDag-Erling Smørgrav 	size_t namelen;
307*b7579f77SDag-Erling Smørgrav 	namelabs = dname_count_size_labels(name, &namelen);
308*b7579f77SDag-Erling Smørgrav 	if(type != LDNS_RR_TYPE_DS && type != LDNS_RR_TYPE_DNSKEY) {
309*b7579f77SDag-Erling Smørgrav 		log_err("Bad type for trust anchor");
310*b7579f77SDag-Erling Smørgrav 		return 0;
311*b7579f77SDag-Erling Smørgrav 	}
312*b7579f77SDag-Erling Smørgrav 	/* lookup or create trustanchor */
313*b7579f77SDag-Erling Smørgrav 	ta = anchor_find(anchors, name, namelabs, namelen, dclass);
314*b7579f77SDag-Erling Smørgrav 	if(!ta) {
315*b7579f77SDag-Erling Smørgrav 		ta = anchor_new_ta(anchors, name, namelabs, namelen, dclass, 1);
316*b7579f77SDag-Erling Smørgrav 		if(!ta)
317*b7579f77SDag-Erling Smørgrav 			return NULL;
318*b7579f77SDag-Erling Smørgrav 		lock_basic_lock(&ta->lock);
319*b7579f77SDag-Erling Smørgrav 	}
320*b7579f77SDag-Erling Smørgrav 	if(!rdata) {
321*b7579f77SDag-Erling Smørgrav 		lock_basic_unlock(&ta->lock);
322*b7579f77SDag-Erling Smørgrav 		return ta;
323*b7579f77SDag-Erling Smørgrav 	}
324*b7579f77SDag-Erling Smørgrav 	/* look for duplicates */
325*b7579f77SDag-Erling Smørgrav 	if(anchor_find_key(ta, rdata, rdata_len, type)) {
326*b7579f77SDag-Erling Smørgrav 		lock_basic_unlock(&ta->lock);
327*b7579f77SDag-Erling Smørgrav 		return ta;
328*b7579f77SDag-Erling Smørgrav 	}
329*b7579f77SDag-Erling Smørgrav 	k = anchor_new_ta_key(rdata, rdata_len, type);
330*b7579f77SDag-Erling Smørgrav 	if(!k) {
331*b7579f77SDag-Erling Smørgrav 		lock_basic_unlock(&ta->lock);
332*b7579f77SDag-Erling Smørgrav 		return NULL;
333*b7579f77SDag-Erling Smørgrav 	}
334*b7579f77SDag-Erling Smørgrav 	/* add new key */
335*b7579f77SDag-Erling Smørgrav 	if(type == LDNS_RR_TYPE_DS)
336*b7579f77SDag-Erling Smørgrav 		ta->numDS++;
337*b7579f77SDag-Erling Smørgrav 	else	ta->numDNSKEY++;
338*b7579f77SDag-Erling Smørgrav 	k->next = ta->keylist;
339*b7579f77SDag-Erling Smørgrav 	ta->keylist = k;
340*b7579f77SDag-Erling Smørgrav 	lock_basic_unlock(&ta->lock);
341*b7579f77SDag-Erling Smørgrav 	return ta;
342*b7579f77SDag-Erling Smørgrav }
343*b7579f77SDag-Erling Smørgrav 
344*b7579f77SDag-Erling Smørgrav /**
345*b7579f77SDag-Erling Smørgrav  * Add new RR. It converts ldns RR to wire format.
346*b7579f77SDag-Erling Smørgrav  * @param anchors: anchor storage.
347*b7579f77SDag-Erling Smørgrav  * @param buffer: parsing buffer.
348*b7579f77SDag-Erling Smørgrav  * @param rr: the rr (allocated by caller).
349*b7579f77SDag-Erling Smørgrav  * @return NULL on error, else the trust anchor.
350*b7579f77SDag-Erling Smørgrav  */
351*b7579f77SDag-Erling Smørgrav static struct trust_anchor*
352*b7579f77SDag-Erling Smørgrav anchor_store_new_rr(struct val_anchors* anchors, ldns_buffer* buffer,
353*b7579f77SDag-Erling Smørgrav 	ldns_rr* rr)
354*b7579f77SDag-Erling Smørgrav {
355*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* ta;
356*b7579f77SDag-Erling Smørgrav 	ldns_rdf* owner = ldns_rr_owner(rr);
357*b7579f77SDag-Erling Smørgrav 	ldns_status status;
358*b7579f77SDag-Erling Smørgrav 	ldns_buffer_clear(buffer);
359*b7579f77SDag-Erling Smørgrav 	ldns_buffer_skip(buffer, 2); /* skip rdatalen */
360*b7579f77SDag-Erling Smørgrav 	status = ldns_rr_rdata2buffer_wire(buffer, rr);
361*b7579f77SDag-Erling Smørgrav 	if(status != LDNS_STATUS_OK) {
362*b7579f77SDag-Erling Smørgrav 		log_err("error converting trustanchor to wireformat: %s",
363*b7579f77SDag-Erling Smørgrav 			ldns_get_errorstr_by_id(status));
364*b7579f77SDag-Erling Smørgrav 		return NULL;
365*b7579f77SDag-Erling Smørgrav 	}
366*b7579f77SDag-Erling Smørgrav 	ldns_buffer_flip(buffer);
367*b7579f77SDag-Erling Smørgrav 	ldns_buffer_write_u16_at(buffer, 0, ldns_buffer_limit(buffer) - 2);
368*b7579f77SDag-Erling Smørgrav 
369*b7579f77SDag-Erling Smørgrav 	if(!(ta=anchor_store_new_key(anchors, ldns_rdf_data(owner),
370*b7579f77SDag-Erling Smørgrav 		ldns_rr_get_type(rr), ldns_rr_get_class(rr),
371*b7579f77SDag-Erling Smørgrav 		ldns_buffer_begin(buffer), ldns_buffer_limit(buffer)))) {
372*b7579f77SDag-Erling Smørgrav 		return NULL;
373*b7579f77SDag-Erling Smørgrav 	}
374*b7579f77SDag-Erling Smørgrav 	log_nametypeclass(VERB_QUERY, "adding trusted key",
375*b7579f77SDag-Erling Smørgrav 		ldns_rdf_data(owner),
376*b7579f77SDag-Erling Smørgrav 		ldns_rr_get_type(rr), ldns_rr_get_class(rr));
377*b7579f77SDag-Erling Smørgrav 	return ta;
378*b7579f77SDag-Erling Smørgrav }
379*b7579f77SDag-Erling Smørgrav 
380*b7579f77SDag-Erling Smørgrav /**
381*b7579f77SDag-Erling Smørgrav  * Insert insecure anchor
382*b7579f77SDag-Erling Smørgrav  * @param anchors: anchor storage.
383*b7579f77SDag-Erling Smørgrav  * @param str: the domain name.
384*b7579f77SDag-Erling Smørgrav  * @return NULL on error, Else last trust anchor point
385*b7579f77SDag-Erling Smørgrav  */
386*b7579f77SDag-Erling Smørgrav static struct trust_anchor*
387*b7579f77SDag-Erling Smørgrav anchor_insert_insecure(struct val_anchors* anchors, const char* str)
388*b7579f77SDag-Erling Smørgrav {
389*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* ta;
390*b7579f77SDag-Erling Smørgrav 	ldns_rdf* nm = ldns_dname_new_frm_str(str);
391*b7579f77SDag-Erling Smørgrav 	if(!nm) {
392*b7579f77SDag-Erling Smørgrav 		log_err("parse error in domain name '%s'", str);
393*b7579f77SDag-Erling Smørgrav 		return NULL;
394*b7579f77SDag-Erling Smørgrav 	}
395*b7579f77SDag-Erling Smørgrav 	ta = anchor_store_new_key(anchors, ldns_rdf_data(nm), LDNS_RR_TYPE_DS,
396*b7579f77SDag-Erling Smørgrav 		LDNS_RR_CLASS_IN, NULL, 0);
397*b7579f77SDag-Erling Smørgrav 	ldns_rdf_deep_free(nm);
398*b7579f77SDag-Erling Smørgrav 	return ta;
399*b7579f77SDag-Erling Smørgrav }
400*b7579f77SDag-Erling Smørgrav 
401*b7579f77SDag-Erling Smørgrav struct trust_anchor*
402*b7579f77SDag-Erling Smørgrav anchor_store_str(struct val_anchors* anchors, ldns_buffer* buffer,
403*b7579f77SDag-Erling Smørgrav 	const char* str)
404*b7579f77SDag-Erling Smørgrav {
405*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* ta;
406*b7579f77SDag-Erling Smørgrav 	ldns_rr* rr = NULL;
407*b7579f77SDag-Erling Smørgrav 	ldns_status status = ldns_rr_new_frm_str(&rr, str, 0, NULL, NULL);
408*b7579f77SDag-Erling Smørgrav 	if(status != LDNS_STATUS_OK) {
409*b7579f77SDag-Erling Smørgrav 		log_err("error parsing trust anchor: %s",
410*b7579f77SDag-Erling Smørgrav 			ldns_get_errorstr_by_id(status));
411*b7579f77SDag-Erling Smørgrav 		ldns_rr_free(rr);
412*b7579f77SDag-Erling Smørgrav 		return NULL;
413*b7579f77SDag-Erling Smørgrav 	}
414*b7579f77SDag-Erling Smørgrav 	if(!(ta=anchor_store_new_rr(anchors, buffer, rr))) {
415*b7579f77SDag-Erling Smørgrav 		log_err("out of memory");
416*b7579f77SDag-Erling Smørgrav 		ldns_rr_free(rr);
417*b7579f77SDag-Erling Smørgrav 		return NULL;
418*b7579f77SDag-Erling Smørgrav 	}
419*b7579f77SDag-Erling Smørgrav 	ldns_rr_free(rr);
420*b7579f77SDag-Erling Smørgrav 	return ta;
421*b7579f77SDag-Erling Smørgrav }
422*b7579f77SDag-Erling Smørgrav 
423*b7579f77SDag-Erling Smørgrav /**
424*b7579f77SDag-Erling Smørgrav  * Read a file with trust anchors
425*b7579f77SDag-Erling Smørgrav  * @param anchors: anchor storage.
426*b7579f77SDag-Erling Smørgrav  * @param buffer: parsing buffer.
427*b7579f77SDag-Erling Smørgrav  * @param fname: string.
428*b7579f77SDag-Erling Smørgrav  * @param onlyone: only one trust anchor allowed in file.
429*b7579f77SDag-Erling Smørgrav  * @return NULL on error. Else last trust-anchor point.
430*b7579f77SDag-Erling Smørgrav  */
431*b7579f77SDag-Erling Smørgrav static struct trust_anchor*
432*b7579f77SDag-Erling Smørgrav anchor_read_file(struct val_anchors* anchors, ldns_buffer* buffer,
433*b7579f77SDag-Erling Smørgrav 	const char* fname, int onlyone)
434*b7579f77SDag-Erling Smørgrav {
435*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* ta = NULL, *tanew;
436*b7579f77SDag-Erling Smørgrav 	uint32_t default_ttl = 3600;
437*b7579f77SDag-Erling Smørgrav 	ldns_rdf* origin = NULL, *prev = NULL;
438*b7579f77SDag-Erling Smørgrav 	int line_nr = 1;
439*b7579f77SDag-Erling Smørgrav 	ldns_status status;
440*b7579f77SDag-Erling Smørgrav 	ldns_rr* rr;
441*b7579f77SDag-Erling Smørgrav 	int ok = 1;
442*b7579f77SDag-Erling Smørgrav 	FILE* in = fopen(fname, "r");
443*b7579f77SDag-Erling Smørgrav 	if(!in) {
444*b7579f77SDag-Erling Smørgrav 		log_err("error opening file %s: %s", fname, strerror(errno));
445*b7579f77SDag-Erling Smørgrav 		return 0;
446*b7579f77SDag-Erling Smørgrav 	}
447*b7579f77SDag-Erling Smørgrav 	while(!feof(in)) {
448*b7579f77SDag-Erling Smørgrav 		rr = NULL;
449*b7579f77SDag-Erling Smørgrav 		status = ldns_rr_new_frm_fp_l(&rr, in, &default_ttl, &origin,
450*b7579f77SDag-Erling Smørgrav 			&prev, &line_nr);
451*b7579f77SDag-Erling Smørgrav 		if(status == LDNS_STATUS_SYNTAX_EMPTY /* empty line */
452*b7579f77SDag-Erling Smørgrav 			|| status == LDNS_STATUS_SYNTAX_TTL /* $TTL */
453*b7579f77SDag-Erling Smørgrav 			|| status == LDNS_STATUS_SYNTAX_ORIGIN /* $ORIGIN */)
454*b7579f77SDag-Erling Smørgrav 			continue;
455*b7579f77SDag-Erling Smørgrav 		if(status != LDNS_STATUS_OK) {
456*b7579f77SDag-Erling Smørgrav 			log_err("parse error in %s:%d : %s", fname, line_nr,
457*b7579f77SDag-Erling Smørgrav 				ldns_get_errorstr_by_id(status));
458*b7579f77SDag-Erling Smørgrav 			ldns_rr_free(rr);
459*b7579f77SDag-Erling Smørgrav 			ok = 0;
460*b7579f77SDag-Erling Smørgrav 			break;
461*b7579f77SDag-Erling Smørgrav 		}
462*b7579f77SDag-Erling Smørgrav 		if(ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS &&
463*b7579f77SDag-Erling Smørgrav 			ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY) {
464*b7579f77SDag-Erling Smørgrav 			ldns_rr_free(rr);
465*b7579f77SDag-Erling Smørgrav 			continue;
466*b7579f77SDag-Erling Smørgrav 		}
467*b7579f77SDag-Erling Smørgrav 		if(!(tanew=anchor_store_new_rr(anchors, buffer, rr))) {
468*b7579f77SDag-Erling Smørgrav 			log_err("error at %s line %d", fname, line_nr);
469*b7579f77SDag-Erling Smørgrav 			ldns_rr_free(rr);
470*b7579f77SDag-Erling Smørgrav 			ok = 0;
471*b7579f77SDag-Erling Smørgrav 			break;
472*b7579f77SDag-Erling Smørgrav 		}
473*b7579f77SDag-Erling Smørgrav 		if(onlyone && ta && ta != tanew) {
474*b7579f77SDag-Erling Smørgrav 			log_err("error at %s line %d: no multiple anchor "
475*b7579f77SDag-Erling Smørgrav 				"domains allowed (you can have multiple "
476*b7579f77SDag-Erling Smørgrav 				"keys, but they must have the same name).",
477*b7579f77SDag-Erling Smørgrav 				fname, line_nr);
478*b7579f77SDag-Erling Smørgrav 			ldns_rr_free(rr);
479*b7579f77SDag-Erling Smørgrav 			ok = 0;
480*b7579f77SDag-Erling Smørgrav 			break;
481*b7579f77SDag-Erling Smørgrav 		}
482*b7579f77SDag-Erling Smørgrav 		ta = tanew;
483*b7579f77SDag-Erling Smørgrav 		ldns_rr_free(rr);
484*b7579f77SDag-Erling Smørgrav 	}
485*b7579f77SDag-Erling Smørgrav 	ldns_rdf_deep_free(origin);
486*b7579f77SDag-Erling Smørgrav 	ldns_rdf_deep_free(prev);
487*b7579f77SDag-Erling Smørgrav 	fclose(in);
488*b7579f77SDag-Erling Smørgrav 	if(!ok) return NULL;
489*b7579f77SDag-Erling Smørgrav 	/* empty file is OK when multiple anchors are allowed */
490*b7579f77SDag-Erling Smørgrav 	if(!onlyone && !ta) return (struct trust_anchor*)1;
491*b7579f77SDag-Erling Smørgrav 	return ta;
492*b7579f77SDag-Erling Smørgrav }
493*b7579f77SDag-Erling Smørgrav 
494*b7579f77SDag-Erling Smørgrav /** skip file to end of line */
495*b7579f77SDag-Erling Smørgrav static void
496*b7579f77SDag-Erling Smørgrav skip_to_eol(FILE* in)
497*b7579f77SDag-Erling Smørgrav {
498*b7579f77SDag-Erling Smørgrav 	int c;
499*b7579f77SDag-Erling Smørgrav 	while((c = getc(in)) != EOF ) {
500*b7579f77SDag-Erling Smørgrav 		if(c == '\n')
501*b7579f77SDag-Erling Smørgrav 			return;
502*b7579f77SDag-Erling Smørgrav 	}
503*b7579f77SDag-Erling Smørgrav }
504*b7579f77SDag-Erling Smørgrav 
505*b7579f77SDag-Erling Smørgrav /** true for special characters in bind configs */
506*b7579f77SDag-Erling Smørgrav static int
507*b7579f77SDag-Erling Smørgrav is_bind_special(int c)
508*b7579f77SDag-Erling Smørgrav {
509*b7579f77SDag-Erling Smørgrav 	switch(c) {
510*b7579f77SDag-Erling Smørgrav 		case '{':
511*b7579f77SDag-Erling Smørgrav 		case '}':
512*b7579f77SDag-Erling Smørgrav 		case '"':
513*b7579f77SDag-Erling Smørgrav 		case ';':
514*b7579f77SDag-Erling Smørgrav 			return 1;
515*b7579f77SDag-Erling Smørgrav 	}
516*b7579f77SDag-Erling Smørgrav 	return 0;
517*b7579f77SDag-Erling Smørgrav }
518*b7579f77SDag-Erling Smørgrav 
519*b7579f77SDag-Erling Smørgrav /**
520*b7579f77SDag-Erling Smørgrav  * Read a keyword skipping bind comments; spaces, specials, restkeywords.
521*b7579f77SDag-Erling Smørgrav  * The file is split into the following tokens:
522*b7579f77SDag-Erling Smørgrav  *	* special characters, on their own, rdlen=1, { } doublequote ;
523*b7579f77SDag-Erling Smørgrav  *	* whitespace becomes a single ' ' or tab. Newlines become spaces.
524*b7579f77SDag-Erling Smørgrav  *	* other words ('keywords')
525*b7579f77SDag-Erling Smørgrav  *	* comments are skipped if desired
526*b7579f77SDag-Erling Smørgrav  *		/ / C++ style comment to end of line
527*b7579f77SDag-Erling Smørgrav  *		# to end of line
528*b7579f77SDag-Erling Smørgrav  *		/ * C style comment * /
529*b7579f77SDag-Erling Smørgrav  * @param in: file to read from.
530*b7579f77SDag-Erling Smørgrav  * @param buf: buffer, what is read is stored after current buffer position.
531*b7579f77SDag-Erling Smørgrav  *	Space is left in the buffer to write a terminating 0.
532*b7579f77SDag-Erling Smørgrav  * @param line: line number is increased per line, for error reports.
533*b7579f77SDag-Erling Smørgrav  * @param comments: if 0, comments are not possible and become text.
534*b7579f77SDag-Erling Smørgrav  *	if 1, comments are skipped entirely.
535*b7579f77SDag-Erling Smørgrav  *	In BIND files, this is when reading quoted strings, for example
536*b7579f77SDag-Erling Smørgrav  *	" base 64 text with / / in there "
537*b7579f77SDag-Erling Smørgrav  * @return the number of character written to the buffer.
538*b7579f77SDag-Erling Smørgrav  *	0 on end of file.
539*b7579f77SDag-Erling Smørgrav  */
540*b7579f77SDag-Erling Smørgrav static int
541*b7579f77SDag-Erling Smørgrav readkeyword_bindfile(FILE* in, ldns_buffer* buf, int* line, int comments)
542*b7579f77SDag-Erling Smørgrav {
543*b7579f77SDag-Erling Smørgrav 	int c;
544*b7579f77SDag-Erling Smørgrav 	int numdone = 0;
545*b7579f77SDag-Erling Smørgrav 	while((c = getc(in)) != EOF ) {
546*b7579f77SDag-Erling Smørgrav 		if(comments && c == '#') {	/*   # blabla   */
547*b7579f77SDag-Erling Smørgrav 			skip_to_eol(in);
548*b7579f77SDag-Erling Smørgrav 			(*line)++;
549*b7579f77SDag-Erling Smørgrav 			continue;
550*b7579f77SDag-Erling Smørgrav 		} else if(comments && c=='/' && numdone>0 && /* /_/ bla*/
551*b7579f77SDag-Erling Smørgrav 			ldns_buffer_read_u8_at(buf,
552*b7579f77SDag-Erling Smørgrav 			ldns_buffer_position(buf)-1) == '/') {
553*b7579f77SDag-Erling Smørgrav 			ldns_buffer_skip(buf, -1);
554*b7579f77SDag-Erling Smørgrav 			numdone--;
555*b7579f77SDag-Erling Smørgrav 			skip_to_eol(in);
556*b7579f77SDag-Erling Smørgrav 			(*line)++;
557*b7579f77SDag-Erling Smørgrav 			continue;
558*b7579f77SDag-Erling Smørgrav 		} else if(comments && c=='*' && numdone>0 && /* /_* bla *_/ */
559*b7579f77SDag-Erling Smørgrav 			ldns_buffer_read_u8_at(buf,
560*b7579f77SDag-Erling Smørgrav 			ldns_buffer_position(buf)-1) == '/') {
561*b7579f77SDag-Erling Smørgrav 			ldns_buffer_skip(buf, -1);
562*b7579f77SDag-Erling Smørgrav 			numdone--;
563*b7579f77SDag-Erling Smørgrav 			/* skip to end of comment */
564*b7579f77SDag-Erling Smørgrav 			while(c != EOF && (c=getc(in)) != EOF ) {
565*b7579f77SDag-Erling Smørgrav 				if(c == '*') {
566*b7579f77SDag-Erling Smørgrav 					if((c=getc(in)) == '/')
567*b7579f77SDag-Erling Smørgrav 						break;
568*b7579f77SDag-Erling Smørgrav 				}
569*b7579f77SDag-Erling Smørgrav 				if(c == '\n')
570*b7579f77SDag-Erling Smørgrav 					(*line)++;
571*b7579f77SDag-Erling Smørgrav 			}
572*b7579f77SDag-Erling Smørgrav 			continue;
573*b7579f77SDag-Erling Smørgrav 		}
574*b7579f77SDag-Erling Smørgrav 		/* not a comment, complete the keyword */
575*b7579f77SDag-Erling Smørgrav 		if(numdone > 0) {
576*b7579f77SDag-Erling Smørgrav 			/* check same type */
577*b7579f77SDag-Erling Smørgrav 			if(isspace(c)) {
578*b7579f77SDag-Erling Smørgrav 				ungetc(c, in);
579*b7579f77SDag-Erling Smørgrav 				return numdone;
580*b7579f77SDag-Erling Smørgrav 			}
581*b7579f77SDag-Erling Smørgrav 			if(is_bind_special(c)) {
582*b7579f77SDag-Erling Smørgrav 				ungetc(c, in);
583*b7579f77SDag-Erling Smørgrav 				return numdone;
584*b7579f77SDag-Erling Smørgrav 			}
585*b7579f77SDag-Erling Smørgrav 		}
586*b7579f77SDag-Erling Smørgrav 		if(c == '\n') {
587*b7579f77SDag-Erling Smørgrav 			c = ' ';
588*b7579f77SDag-Erling Smørgrav 			(*line)++;
589*b7579f77SDag-Erling Smørgrav 		}
590*b7579f77SDag-Erling Smørgrav 		/* space for 1 char + 0 string terminator */
591*b7579f77SDag-Erling Smørgrav 		if(ldns_buffer_remaining(buf) < 2) {
592*b7579f77SDag-Erling Smørgrav 			fatal_exit("trusted-keys, %d, string too long", *line);
593*b7579f77SDag-Erling Smørgrav 		}
594*b7579f77SDag-Erling Smørgrav 		ldns_buffer_write_u8(buf, (uint8_t)c);
595*b7579f77SDag-Erling Smørgrav 		numdone++;
596*b7579f77SDag-Erling Smørgrav 		if(isspace(c)) {
597*b7579f77SDag-Erling Smørgrav 			/* collate whitespace into ' ' */
598*b7579f77SDag-Erling Smørgrav 			while((c = getc(in)) != EOF ) {
599*b7579f77SDag-Erling Smørgrav 				if(c == '\n')
600*b7579f77SDag-Erling Smørgrav 					(*line)++;
601*b7579f77SDag-Erling Smørgrav 				if(!isspace(c)) {
602*b7579f77SDag-Erling Smørgrav 					ungetc(c, in);
603*b7579f77SDag-Erling Smørgrav 					break;
604*b7579f77SDag-Erling Smørgrav 				}
605*b7579f77SDag-Erling Smørgrav 			}
606*b7579f77SDag-Erling Smørgrav 			return numdone;
607*b7579f77SDag-Erling Smørgrav 		}
608*b7579f77SDag-Erling Smørgrav 		if(is_bind_special(c))
609*b7579f77SDag-Erling Smørgrav 			return numdone;
610*b7579f77SDag-Erling Smørgrav 	}
611*b7579f77SDag-Erling Smørgrav 	return numdone;
612*b7579f77SDag-Erling Smørgrav }
613*b7579f77SDag-Erling Smørgrav 
614*b7579f77SDag-Erling Smørgrav /** skip through file to { or ; */
615*b7579f77SDag-Erling Smørgrav static int
616*b7579f77SDag-Erling Smørgrav skip_to_special(FILE* in, ldns_buffer* buf, int* line, int spec)
617*b7579f77SDag-Erling Smørgrav {
618*b7579f77SDag-Erling Smørgrav 	int rdlen;
619*b7579f77SDag-Erling Smørgrav 	ldns_buffer_clear(buf);
620*b7579f77SDag-Erling Smørgrav 	while((rdlen=readkeyword_bindfile(in, buf, line, 1))) {
621*b7579f77SDag-Erling Smørgrav 		if(rdlen == 1 && isspace((int)*ldns_buffer_begin(buf))) {
622*b7579f77SDag-Erling Smørgrav 			ldns_buffer_clear(buf);
623*b7579f77SDag-Erling Smørgrav 			continue;
624*b7579f77SDag-Erling Smørgrav 		}
625*b7579f77SDag-Erling Smørgrav 		if(rdlen != 1 || *ldns_buffer_begin(buf) != (uint8_t)spec) {
626*b7579f77SDag-Erling Smørgrav 			ldns_buffer_write_u8(buf, 0);
627*b7579f77SDag-Erling Smørgrav 			log_err("trusted-keys, line %d, expected %c",
628*b7579f77SDag-Erling Smørgrav 				*line, spec);
629*b7579f77SDag-Erling Smørgrav 			return 0;
630*b7579f77SDag-Erling Smørgrav 		}
631*b7579f77SDag-Erling Smørgrav 		return 1;
632*b7579f77SDag-Erling Smørgrav 	}
633*b7579f77SDag-Erling Smørgrav 	log_err("trusted-keys, line %d, expected %c got EOF", *line, spec);
634*b7579f77SDag-Erling Smørgrav 	return 0;
635*b7579f77SDag-Erling Smørgrav }
636*b7579f77SDag-Erling Smørgrav 
637*b7579f77SDag-Erling Smørgrav /**
638*b7579f77SDag-Erling Smørgrav  * read contents of trusted-keys{ ... ; clauses and insert keys into storage.
639*b7579f77SDag-Erling Smørgrav  * @param anchors: where to store keys
640*b7579f77SDag-Erling Smørgrav  * @param buf: buffer to use
641*b7579f77SDag-Erling Smørgrav  * @param line: line number in file
642*b7579f77SDag-Erling Smørgrav  * @param in: file to read from.
643*b7579f77SDag-Erling Smørgrav  * @return 0 on error.
644*b7579f77SDag-Erling Smørgrav  */
645*b7579f77SDag-Erling Smørgrav static int
646*b7579f77SDag-Erling Smørgrav process_bind_contents(struct val_anchors* anchors, ldns_buffer* buf,
647*b7579f77SDag-Erling Smørgrav 	int* line, FILE* in)
648*b7579f77SDag-Erling Smørgrav {
649*b7579f77SDag-Erling Smørgrav 	/* loop over contents, collate strings before ; */
650*b7579f77SDag-Erling Smørgrav 	/* contents is (numbered): 0   1    2  3 4   5  6 7 8    */
651*b7579f77SDag-Erling Smørgrav 	/*                           name. 257 3 5 base64 base64 */
652*b7579f77SDag-Erling Smørgrav 	/* quoted value:           0 "111"  0  0 0   0  0 0 0    */
653*b7579f77SDag-Erling Smørgrav 	/* comments value:         1 "000"  1  1  1 "0  0 0 0"  1 */
654*b7579f77SDag-Erling Smørgrav 	int contnum = 0;
655*b7579f77SDag-Erling Smørgrav 	int quoted = 0;
656*b7579f77SDag-Erling Smørgrav 	int comments = 1;
657*b7579f77SDag-Erling Smørgrav 	int rdlen;
658*b7579f77SDag-Erling Smørgrav 	char* str = 0;
659*b7579f77SDag-Erling Smørgrav 	ldns_buffer_clear(buf);
660*b7579f77SDag-Erling Smørgrav 	while((rdlen=readkeyword_bindfile(in, buf, line, comments))) {
661*b7579f77SDag-Erling Smørgrav 		if(rdlen == 1 && ldns_buffer_position(buf) == 1
662*b7579f77SDag-Erling Smørgrav 			&& isspace((int)*ldns_buffer_begin(buf))) {
663*b7579f77SDag-Erling Smørgrav 			/* starting whitespace is removed */
664*b7579f77SDag-Erling Smørgrav 			ldns_buffer_clear(buf);
665*b7579f77SDag-Erling Smørgrav 			continue;
666*b7579f77SDag-Erling Smørgrav 		} else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == '"') {
667*b7579f77SDag-Erling Smørgrav 			/* remove " from the string */
668*b7579f77SDag-Erling Smørgrav 			if(contnum == 0) {
669*b7579f77SDag-Erling Smørgrav 				quoted = 1;
670*b7579f77SDag-Erling Smørgrav 				comments = 0;
671*b7579f77SDag-Erling Smørgrav 			}
672*b7579f77SDag-Erling Smørgrav 			ldns_buffer_skip(buf, -1);
673*b7579f77SDag-Erling Smørgrav 			if(contnum > 0 && quoted) {
674*b7579f77SDag-Erling Smørgrav 				if(ldns_buffer_remaining(buf) < 8+1) {
675*b7579f77SDag-Erling Smørgrav 					log_err("line %d, too long", *line);
676*b7579f77SDag-Erling Smørgrav 					return 0;
677*b7579f77SDag-Erling Smørgrav 				}
678*b7579f77SDag-Erling Smørgrav 				ldns_buffer_write(buf, " DNSKEY ", 8);
679*b7579f77SDag-Erling Smørgrav 				quoted = 0;
680*b7579f77SDag-Erling Smørgrav 				comments = 1;
681*b7579f77SDag-Erling Smørgrav 			} else if(contnum > 0)
682*b7579f77SDag-Erling Smørgrav 				comments = !comments;
683*b7579f77SDag-Erling Smørgrav 			continue;
684*b7579f77SDag-Erling Smørgrav 		} else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == ';') {
685*b7579f77SDag-Erling Smørgrav 
686*b7579f77SDag-Erling Smørgrav 			if(contnum < 5) {
687*b7579f77SDag-Erling Smørgrav 				ldns_buffer_write_u8(buf, 0);
688*b7579f77SDag-Erling Smørgrav 				log_err("line %d, bad key", *line);
689*b7579f77SDag-Erling Smørgrav 				return 0;
690*b7579f77SDag-Erling Smørgrav 			}
691*b7579f77SDag-Erling Smørgrav 			ldns_buffer_skip(buf, -1);
692*b7579f77SDag-Erling Smørgrav 			ldns_buffer_write_u8(buf, 0);
693*b7579f77SDag-Erling Smørgrav 			str = strdup((char*)ldns_buffer_begin(buf));
694*b7579f77SDag-Erling Smørgrav 			if(!str) {
695*b7579f77SDag-Erling Smørgrav 				log_err("line %d, allocation failure", *line);
696*b7579f77SDag-Erling Smørgrav 				return 0;
697*b7579f77SDag-Erling Smørgrav 			}
698*b7579f77SDag-Erling Smørgrav 			if(!anchor_store_str(anchors, buf, str)) {
699*b7579f77SDag-Erling Smørgrav 				log_err("line %d, bad key", *line);
700*b7579f77SDag-Erling Smørgrav 				free(str);
701*b7579f77SDag-Erling Smørgrav 				return 0;
702*b7579f77SDag-Erling Smørgrav 			}
703*b7579f77SDag-Erling Smørgrav 			free(str);
704*b7579f77SDag-Erling Smørgrav 			ldns_buffer_clear(buf);
705*b7579f77SDag-Erling Smørgrav 			contnum = 0;
706*b7579f77SDag-Erling Smørgrav 			quoted = 0;
707*b7579f77SDag-Erling Smørgrav 			comments = 1;
708*b7579f77SDag-Erling Smørgrav 			continue;
709*b7579f77SDag-Erling Smørgrav 		} else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == '}') {
710*b7579f77SDag-Erling Smørgrav 			if(contnum > 0) {
711*b7579f77SDag-Erling Smørgrav 				ldns_buffer_write_u8(buf, 0);
712*b7579f77SDag-Erling Smørgrav 				log_err("line %d, bad key before }", *line);
713*b7579f77SDag-Erling Smørgrav 				return 0;
714*b7579f77SDag-Erling Smørgrav 			}
715*b7579f77SDag-Erling Smørgrav 			return 1;
716*b7579f77SDag-Erling Smørgrav 		} else if(rdlen == 1 &&
717*b7579f77SDag-Erling Smørgrav 			isspace((int)ldns_buffer_current(buf)[-1])) {
718*b7579f77SDag-Erling Smørgrav 			/* leave whitespace here */
719*b7579f77SDag-Erling Smørgrav 		} else {
720*b7579f77SDag-Erling Smørgrav 			/* not space or whatnot, so actual content */
721*b7579f77SDag-Erling Smørgrav 			contnum ++;
722*b7579f77SDag-Erling Smørgrav 			if(contnum == 1 && !quoted) {
723*b7579f77SDag-Erling Smørgrav 				if(ldns_buffer_remaining(buf) < 8+1) {
724*b7579f77SDag-Erling Smørgrav 					log_err("line %d, too long", *line);
725*b7579f77SDag-Erling Smørgrav 					return 0;
726*b7579f77SDag-Erling Smørgrav 				}
727*b7579f77SDag-Erling Smørgrav 				ldns_buffer_write(buf, " DNSKEY ", 8);
728*b7579f77SDag-Erling Smørgrav 			}
729*b7579f77SDag-Erling Smørgrav 		}
730*b7579f77SDag-Erling Smørgrav 	}
731*b7579f77SDag-Erling Smørgrav 
732*b7579f77SDag-Erling Smørgrav 	log_err("line %d, EOF before }", *line);
733*b7579f77SDag-Erling Smørgrav 	return 0;
734*b7579f77SDag-Erling Smørgrav }
735*b7579f77SDag-Erling Smørgrav 
736*b7579f77SDag-Erling Smørgrav /**
737*b7579f77SDag-Erling Smørgrav  * Read a BIND9 like file with trust anchors in named.conf format.
738*b7579f77SDag-Erling Smørgrav  * @param anchors: anchor storage.
739*b7579f77SDag-Erling Smørgrav  * @param buffer: parsing buffer.
740*b7579f77SDag-Erling Smørgrav  * @param fname: string.
741*b7579f77SDag-Erling Smørgrav  * @return false on error.
742*b7579f77SDag-Erling Smørgrav  */
743*b7579f77SDag-Erling Smørgrav static int
744*b7579f77SDag-Erling Smørgrav anchor_read_bind_file(struct val_anchors* anchors, ldns_buffer* buffer,
745*b7579f77SDag-Erling Smørgrav 	const char* fname)
746*b7579f77SDag-Erling Smørgrav {
747*b7579f77SDag-Erling Smørgrav 	int line_nr = 1;
748*b7579f77SDag-Erling Smørgrav 	FILE* in = fopen(fname, "r");
749*b7579f77SDag-Erling Smørgrav 	int rdlen = 0;
750*b7579f77SDag-Erling Smørgrav 	if(!in) {
751*b7579f77SDag-Erling Smørgrav 		log_err("error opening file %s: %s", fname, strerror(errno));
752*b7579f77SDag-Erling Smørgrav 		return 0;
753*b7579f77SDag-Erling Smørgrav 	}
754*b7579f77SDag-Erling Smørgrav 	verbose(VERB_QUERY, "reading in bind-compat-mode: '%s'", fname);
755*b7579f77SDag-Erling Smørgrav 	/* scan for  trusted-keys  keyword, ignore everything else */
756*b7579f77SDag-Erling Smørgrav 	ldns_buffer_clear(buffer);
757*b7579f77SDag-Erling Smørgrav 	while((rdlen=readkeyword_bindfile(in, buffer, &line_nr, 1)) != 0) {
758*b7579f77SDag-Erling Smørgrav 		if(rdlen != 12 || strncmp((char*)ldns_buffer_begin(buffer),
759*b7579f77SDag-Erling Smørgrav 			"trusted-keys", 12) != 0) {
760*b7579f77SDag-Erling Smørgrav 			ldns_buffer_clear(buffer);
761*b7579f77SDag-Erling Smørgrav 			/* ignore everything but trusted-keys */
762*b7579f77SDag-Erling Smørgrav 			continue;
763*b7579f77SDag-Erling Smørgrav 		}
764*b7579f77SDag-Erling Smørgrav 		if(!skip_to_special(in, buffer, &line_nr, '{')) {
765*b7579f77SDag-Erling Smørgrav 			log_err("error in trusted key: \"%s\"", fname);
766*b7579f77SDag-Erling Smørgrav 			fclose(in);
767*b7579f77SDag-Erling Smørgrav 			return 0;
768*b7579f77SDag-Erling Smørgrav 		}
769*b7579f77SDag-Erling Smørgrav 		/* process contents */
770*b7579f77SDag-Erling Smørgrav 		if(!process_bind_contents(anchors, buffer, &line_nr, in)) {
771*b7579f77SDag-Erling Smørgrav 			log_err("error in trusted key: \"%s\"", fname);
772*b7579f77SDag-Erling Smørgrav 			fclose(in);
773*b7579f77SDag-Erling Smørgrav 			return 0;
774*b7579f77SDag-Erling Smørgrav 		}
775*b7579f77SDag-Erling Smørgrav 		if(!skip_to_special(in, buffer, &line_nr, ';')) {
776*b7579f77SDag-Erling Smørgrav 			log_err("error in trusted key: \"%s\"", fname);
777*b7579f77SDag-Erling Smørgrav 			fclose(in);
778*b7579f77SDag-Erling Smørgrav 			return 0;
779*b7579f77SDag-Erling Smørgrav 		}
780*b7579f77SDag-Erling Smørgrav 		ldns_buffer_clear(buffer);
781*b7579f77SDag-Erling Smørgrav 	}
782*b7579f77SDag-Erling Smørgrav 	fclose(in);
783*b7579f77SDag-Erling Smørgrav 	return 1;
784*b7579f77SDag-Erling Smørgrav }
785*b7579f77SDag-Erling Smørgrav 
786*b7579f77SDag-Erling Smørgrav /**
787*b7579f77SDag-Erling Smørgrav  * Read a BIND9 like files with trust anchors in named.conf format.
788*b7579f77SDag-Erling Smørgrav  * Performs wildcard processing of name.
789*b7579f77SDag-Erling Smørgrav  * @param anchors: anchor storage.
790*b7579f77SDag-Erling Smørgrav  * @param buffer: parsing buffer.
791*b7579f77SDag-Erling Smørgrav  * @param pat: pattern string. (can be wildcarded)
792*b7579f77SDag-Erling Smørgrav  * @return false on error.
793*b7579f77SDag-Erling Smørgrav  */
794*b7579f77SDag-Erling Smørgrav static int
795*b7579f77SDag-Erling Smørgrav anchor_read_bind_file_wild(struct val_anchors* anchors, ldns_buffer* buffer,
796*b7579f77SDag-Erling Smørgrav 	const char* pat)
797*b7579f77SDag-Erling Smørgrav {
798*b7579f77SDag-Erling Smørgrav #ifdef HAVE_GLOB
799*b7579f77SDag-Erling Smørgrav 	glob_t g;
800*b7579f77SDag-Erling Smørgrav 	size_t i;
801*b7579f77SDag-Erling Smørgrav 	int r, flags;
802*b7579f77SDag-Erling Smørgrav 	if(!strchr(pat, '*') && !strchr(pat, '?') && !strchr(pat, '[') &&
803*b7579f77SDag-Erling Smørgrav 		!strchr(pat, '{') && !strchr(pat, '~')) {
804*b7579f77SDag-Erling Smørgrav 		return anchor_read_bind_file(anchors, buffer, pat);
805*b7579f77SDag-Erling Smørgrav 	}
806*b7579f77SDag-Erling Smørgrav 	verbose(VERB_QUERY, "wildcard found, processing %s", pat);
807*b7579f77SDag-Erling Smørgrav 	flags = 0
808*b7579f77SDag-Erling Smørgrav #ifdef GLOB_ERR
809*b7579f77SDag-Erling Smørgrav 		| GLOB_ERR
810*b7579f77SDag-Erling Smørgrav #endif
811*b7579f77SDag-Erling Smørgrav #ifdef GLOB_NOSORT
812*b7579f77SDag-Erling Smørgrav 		| GLOB_NOSORT
813*b7579f77SDag-Erling Smørgrav #endif
814*b7579f77SDag-Erling Smørgrav #ifdef GLOB_BRACE
815*b7579f77SDag-Erling Smørgrav 		| GLOB_BRACE
816*b7579f77SDag-Erling Smørgrav #endif
817*b7579f77SDag-Erling Smørgrav #ifdef GLOB_TILDE
818*b7579f77SDag-Erling Smørgrav 		| GLOB_TILDE
819*b7579f77SDag-Erling Smørgrav #endif
820*b7579f77SDag-Erling Smørgrav 	;
821*b7579f77SDag-Erling Smørgrav 	memset(&g, 0, sizeof(g));
822*b7579f77SDag-Erling Smørgrav 	r = glob(pat, flags, NULL, &g);
823*b7579f77SDag-Erling Smørgrav 	if(r) {
824*b7579f77SDag-Erling Smørgrav 		/* some error */
825*b7579f77SDag-Erling Smørgrav 		if(r == GLOB_NOMATCH) {
826*b7579f77SDag-Erling Smørgrav 			verbose(VERB_QUERY, "trusted-keys-file: "
827*b7579f77SDag-Erling Smørgrav 				"no matches for %s", pat);
828*b7579f77SDag-Erling Smørgrav 			return 1;
829*b7579f77SDag-Erling Smørgrav 		} else if(r == GLOB_NOSPACE) {
830*b7579f77SDag-Erling Smørgrav 			log_err("wildcard trusted-keys-file %s: "
831*b7579f77SDag-Erling Smørgrav 				"pattern out of memory", pat);
832*b7579f77SDag-Erling Smørgrav 		} else if(r == GLOB_ABORTED) {
833*b7579f77SDag-Erling Smørgrav 			log_err("wildcard trusted-keys-file %s: expansion "
834*b7579f77SDag-Erling Smørgrav 				"aborted (%s)", pat, strerror(errno));
835*b7579f77SDag-Erling Smørgrav 		} else {
836*b7579f77SDag-Erling Smørgrav 			log_err("wildcard trusted-keys-file %s: expansion "
837*b7579f77SDag-Erling Smørgrav 				"failed (%s)", pat, strerror(errno));
838*b7579f77SDag-Erling Smørgrav 		}
839*b7579f77SDag-Erling Smørgrav 		return 0;
840*b7579f77SDag-Erling Smørgrav 	}
841*b7579f77SDag-Erling Smørgrav 	/* process files found, if any */
842*b7579f77SDag-Erling Smørgrav 	for(i=0; i<(size_t)g.gl_pathc; i++) {
843*b7579f77SDag-Erling Smørgrav 		if(!anchor_read_bind_file(anchors, buffer, g.gl_pathv[i])) {
844*b7579f77SDag-Erling Smørgrav 			log_err("error reading wildcard "
845*b7579f77SDag-Erling Smørgrav 				"trusted-keys-file: %s", g.gl_pathv[i]);
846*b7579f77SDag-Erling Smørgrav 			globfree(&g);
847*b7579f77SDag-Erling Smørgrav 			return 0;
848*b7579f77SDag-Erling Smørgrav 		}
849*b7579f77SDag-Erling Smørgrav 	}
850*b7579f77SDag-Erling Smørgrav 	globfree(&g);
851*b7579f77SDag-Erling Smørgrav 	return 1;
852*b7579f77SDag-Erling Smørgrav #else /* not HAVE_GLOB */
853*b7579f77SDag-Erling Smørgrav 	return anchor_read_bind_file(anchors, buffer, pat);
854*b7579f77SDag-Erling Smørgrav #endif /* HAVE_GLOB */
855*b7579f77SDag-Erling Smørgrav }
856*b7579f77SDag-Erling Smørgrav 
857*b7579f77SDag-Erling Smørgrav /**
858*b7579f77SDag-Erling Smørgrav  * Assemble an rrset structure for the type
859*b7579f77SDag-Erling Smørgrav  * @param ta: trust anchor.
860*b7579f77SDag-Erling Smørgrav  * @param num: number of items to fetch from list.
861*b7579f77SDag-Erling Smørgrav  * @param type: fetch only items of this type.
862*b7579f77SDag-Erling Smørgrav  * @return rrset or NULL on error.
863*b7579f77SDag-Erling Smørgrav  */
864*b7579f77SDag-Erling Smørgrav static struct ub_packed_rrset_key*
865*b7579f77SDag-Erling Smørgrav assemble_it(struct trust_anchor* ta, size_t num, uint16_t type)
866*b7579f77SDag-Erling Smørgrav {
867*b7579f77SDag-Erling Smørgrav 	struct ub_packed_rrset_key* pkey = (struct ub_packed_rrset_key*)
868*b7579f77SDag-Erling Smørgrav 		malloc(sizeof(*pkey));
869*b7579f77SDag-Erling Smørgrav 	struct packed_rrset_data* pd;
870*b7579f77SDag-Erling Smørgrav 	struct ta_key* tk;
871*b7579f77SDag-Erling Smørgrav 	size_t i;
872*b7579f77SDag-Erling Smørgrav 	if(!pkey)
873*b7579f77SDag-Erling Smørgrav 		return NULL;
874*b7579f77SDag-Erling Smørgrav 	memset(pkey, 0, sizeof(*pkey));
875*b7579f77SDag-Erling Smørgrav 	pkey->rk.dname = memdup(ta->name, ta->namelen);
876*b7579f77SDag-Erling Smørgrav 	if(!pkey->rk.dname) {
877*b7579f77SDag-Erling Smørgrav 		free(pkey);
878*b7579f77SDag-Erling Smørgrav 		return NULL;
879*b7579f77SDag-Erling Smørgrav 	}
880*b7579f77SDag-Erling Smørgrav 
881*b7579f77SDag-Erling Smørgrav 	pkey->rk.dname_len = ta->namelen;
882*b7579f77SDag-Erling Smørgrav 	pkey->rk.type = htons(type);
883*b7579f77SDag-Erling Smørgrav 	pkey->rk.rrset_class = htons(ta->dclass);
884*b7579f77SDag-Erling Smørgrav 	/* The rrset is build in an uncompressed way. This means it
885*b7579f77SDag-Erling Smørgrav 	 * cannot be copied in the normal way. */
886*b7579f77SDag-Erling Smørgrav 	pd = (struct packed_rrset_data*)malloc(sizeof(*pd));
887*b7579f77SDag-Erling Smørgrav 	if(!pd) {
888*b7579f77SDag-Erling Smørgrav 		free(pkey->rk.dname);
889*b7579f77SDag-Erling Smørgrav 		free(pkey);
890*b7579f77SDag-Erling Smørgrav 		return NULL;
891*b7579f77SDag-Erling Smørgrav 	}
892*b7579f77SDag-Erling Smørgrav 	memset(pd, 0, sizeof(*pd));
893*b7579f77SDag-Erling Smørgrav 	pd->count = num;
894*b7579f77SDag-Erling Smørgrav 	pd->trust = rrset_trust_ultimate;
895*b7579f77SDag-Erling Smørgrav 	pd->rr_len = (size_t*)malloc(num*sizeof(size_t));
896*b7579f77SDag-Erling Smørgrav 	if(!pd->rr_len) {
897*b7579f77SDag-Erling Smørgrav 		free(pd);
898*b7579f77SDag-Erling Smørgrav 		free(pkey->rk.dname);
899*b7579f77SDag-Erling Smørgrav 		free(pkey);
900*b7579f77SDag-Erling Smørgrav 		return NULL;
901*b7579f77SDag-Erling Smørgrav 	}
902*b7579f77SDag-Erling Smørgrav 	pd->rr_ttl = (uint32_t*)malloc(num*sizeof(uint32_t));
903*b7579f77SDag-Erling Smørgrav 	if(!pd->rr_ttl) {
904*b7579f77SDag-Erling Smørgrav 		free(pd->rr_len);
905*b7579f77SDag-Erling Smørgrav 		free(pd);
906*b7579f77SDag-Erling Smørgrav 		free(pkey->rk.dname);
907*b7579f77SDag-Erling Smørgrav 		free(pkey);
908*b7579f77SDag-Erling Smørgrav 		return NULL;
909*b7579f77SDag-Erling Smørgrav 	}
910*b7579f77SDag-Erling Smørgrav 	pd->rr_data = (uint8_t**)malloc(num*sizeof(uint8_t*));
911*b7579f77SDag-Erling Smørgrav 	if(!pd->rr_data) {
912*b7579f77SDag-Erling Smørgrav 		free(pd->rr_ttl);
913*b7579f77SDag-Erling Smørgrav 		free(pd->rr_len);
914*b7579f77SDag-Erling Smørgrav 		free(pd);
915*b7579f77SDag-Erling Smørgrav 		free(pkey->rk.dname);
916*b7579f77SDag-Erling Smørgrav 		free(pkey);
917*b7579f77SDag-Erling Smørgrav 		return NULL;
918*b7579f77SDag-Erling Smørgrav 	}
919*b7579f77SDag-Erling Smørgrav 	/* fill in rrs */
920*b7579f77SDag-Erling Smørgrav 	i=0;
921*b7579f77SDag-Erling Smørgrav 	for(tk = ta->keylist; tk; tk = tk->next) {
922*b7579f77SDag-Erling Smørgrav 		if(tk->type != type)
923*b7579f77SDag-Erling Smørgrav 			continue;
924*b7579f77SDag-Erling Smørgrav 		pd->rr_len[i] = tk->len;
925*b7579f77SDag-Erling Smørgrav 		/* reuse data ptr to allocation in talist */
926*b7579f77SDag-Erling Smørgrav 		pd->rr_data[i] = tk->data;
927*b7579f77SDag-Erling Smørgrav 		pd->rr_ttl[i] = 0;
928*b7579f77SDag-Erling Smørgrav 		i++;
929*b7579f77SDag-Erling Smørgrav 	}
930*b7579f77SDag-Erling Smørgrav 	pkey->entry.data = (void*)pd;
931*b7579f77SDag-Erling Smørgrav 	return pkey;
932*b7579f77SDag-Erling Smørgrav }
933*b7579f77SDag-Erling Smørgrav 
934*b7579f77SDag-Erling Smørgrav /**
935*b7579f77SDag-Erling Smørgrav  * Assemble structures for the trust DS and DNSKEY rrsets.
936*b7579f77SDag-Erling Smørgrav  * @param ta: trust anchor
937*b7579f77SDag-Erling Smørgrav  * @return: false on error.
938*b7579f77SDag-Erling Smørgrav  */
939*b7579f77SDag-Erling Smørgrav static int
940*b7579f77SDag-Erling Smørgrav anchors_assemble(struct trust_anchor* ta)
941*b7579f77SDag-Erling Smørgrav {
942*b7579f77SDag-Erling Smørgrav 	if(ta->numDS > 0) {
943*b7579f77SDag-Erling Smørgrav 		ta->ds_rrset = assemble_it(ta, ta->numDS, LDNS_RR_TYPE_DS);
944*b7579f77SDag-Erling Smørgrav 		if(!ta->ds_rrset)
945*b7579f77SDag-Erling Smørgrav 			return 0;
946*b7579f77SDag-Erling Smørgrav 	}
947*b7579f77SDag-Erling Smørgrav 	if(ta->numDNSKEY > 0) {
948*b7579f77SDag-Erling Smørgrav 		ta->dnskey_rrset = assemble_it(ta, ta->numDNSKEY,
949*b7579f77SDag-Erling Smørgrav 			LDNS_RR_TYPE_DNSKEY);
950*b7579f77SDag-Erling Smørgrav 		if(!ta->dnskey_rrset)
951*b7579f77SDag-Erling Smørgrav 			return 0;
952*b7579f77SDag-Erling Smørgrav 	}
953*b7579f77SDag-Erling Smørgrav 	return 1;
954*b7579f77SDag-Erling Smørgrav }
955*b7579f77SDag-Erling Smørgrav 
956*b7579f77SDag-Erling Smørgrav /**
957*b7579f77SDag-Erling Smørgrav  * Check DS algos for support, warn if not.
958*b7579f77SDag-Erling Smørgrav  * @param ta: trust anchor
959*b7579f77SDag-Erling Smørgrav  * @return number of DS anchors with unsupported algorithms.
960*b7579f77SDag-Erling Smørgrav  */
961*b7579f77SDag-Erling Smørgrav static size_t
962*b7579f77SDag-Erling Smørgrav anchors_ds_unsupported(struct trust_anchor* ta)
963*b7579f77SDag-Erling Smørgrav {
964*b7579f77SDag-Erling Smørgrav 	size_t i, num = 0;
965*b7579f77SDag-Erling Smørgrav 	for(i=0; i<ta->numDS; i++) {
966*b7579f77SDag-Erling Smørgrav 		if(!ds_digest_algo_is_supported(ta->ds_rrset, i) ||
967*b7579f77SDag-Erling Smørgrav 			!ds_key_algo_is_supported(ta->ds_rrset, i))
968*b7579f77SDag-Erling Smørgrav 			num++;
969*b7579f77SDag-Erling Smørgrav 	}
970*b7579f77SDag-Erling Smørgrav 	return num;
971*b7579f77SDag-Erling Smørgrav }
972*b7579f77SDag-Erling Smørgrav 
973*b7579f77SDag-Erling Smørgrav /**
974*b7579f77SDag-Erling Smørgrav  * Check DNSKEY algos for support, warn if not.
975*b7579f77SDag-Erling Smørgrav  * @param ta: trust anchor
976*b7579f77SDag-Erling Smørgrav  * @return number of DNSKEY anchors with unsupported algorithms.
977*b7579f77SDag-Erling Smørgrav  */
978*b7579f77SDag-Erling Smørgrav static size_t
979*b7579f77SDag-Erling Smørgrav anchors_dnskey_unsupported(struct trust_anchor* ta)
980*b7579f77SDag-Erling Smørgrav {
981*b7579f77SDag-Erling Smørgrav 	size_t i, num = 0;
982*b7579f77SDag-Erling Smørgrav 	for(i=0; i<ta->numDNSKEY; i++) {
983*b7579f77SDag-Erling Smørgrav 		if(!dnskey_algo_is_supported(ta->dnskey_rrset, i))
984*b7579f77SDag-Erling Smørgrav 			num++;
985*b7579f77SDag-Erling Smørgrav 	}
986*b7579f77SDag-Erling Smørgrav 	return num;
987*b7579f77SDag-Erling Smørgrav }
988*b7579f77SDag-Erling Smørgrav 
989*b7579f77SDag-Erling Smørgrav /**
990*b7579f77SDag-Erling Smørgrav  * Assemble the rrsets in the anchors, ready for use by validator.
991*b7579f77SDag-Erling Smørgrav  * @param anchors: trust anchor storage.
992*b7579f77SDag-Erling Smørgrav  * @return: false on error.
993*b7579f77SDag-Erling Smørgrav  */
994*b7579f77SDag-Erling Smørgrav static int
995*b7579f77SDag-Erling Smørgrav anchors_assemble_rrsets(struct val_anchors* anchors)
996*b7579f77SDag-Erling Smørgrav {
997*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* ta;
998*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* next;
999*b7579f77SDag-Erling Smørgrav 	size_t nods, nokey;
1000*b7579f77SDag-Erling Smørgrav 	lock_basic_lock(&anchors->lock);
1001*b7579f77SDag-Erling Smørgrav 	ta=(struct trust_anchor*)rbtree_first(anchors->tree);
1002*b7579f77SDag-Erling Smørgrav 	while((rbnode_t*)ta != RBTREE_NULL) {
1003*b7579f77SDag-Erling Smørgrav 		next = (struct trust_anchor*)rbtree_next(&ta->node);
1004*b7579f77SDag-Erling Smørgrav 		lock_basic_lock(&ta->lock);
1005*b7579f77SDag-Erling Smørgrav 		if(ta->autr || (ta->numDS == 0 && ta->numDNSKEY == 0)) {
1006*b7579f77SDag-Erling Smørgrav 			lock_basic_unlock(&ta->lock);
1007*b7579f77SDag-Erling Smørgrav 			ta = next; /* skip */
1008*b7579f77SDag-Erling Smørgrav 			continue;
1009*b7579f77SDag-Erling Smørgrav 		}
1010*b7579f77SDag-Erling Smørgrav 		if(!anchors_assemble(ta)) {
1011*b7579f77SDag-Erling Smørgrav 			log_err("out of memory");
1012*b7579f77SDag-Erling Smørgrav 			lock_basic_unlock(&ta->lock);
1013*b7579f77SDag-Erling Smørgrav 			lock_basic_unlock(&anchors->lock);
1014*b7579f77SDag-Erling Smørgrav 			return 0;
1015*b7579f77SDag-Erling Smørgrav 		}
1016*b7579f77SDag-Erling Smørgrav 		nods = anchors_ds_unsupported(ta);
1017*b7579f77SDag-Erling Smørgrav 		nokey = anchors_dnskey_unsupported(ta);
1018*b7579f77SDag-Erling Smørgrav 		if(nods) {
1019*b7579f77SDag-Erling Smørgrav 			log_nametypeclass(0, "warning: unsupported "
1020*b7579f77SDag-Erling Smørgrav 				"algorithm for trust anchor",
1021*b7579f77SDag-Erling Smørgrav 				ta->name, LDNS_RR_TYPE_DS, ta->dclass);
1022*b7579f77SDag-Erling Smørgrav 		}
1023*b7579f77SDag-Erling Smørgrav 		if(nokey) {
1024*b7579f77SDag-Erling Smørgrav 			log_nametypeclass(0, "warning: unsupported "
1025*b7579f77SDag-Erling Smørgrav 				"algorithm for trust anchor",
1026*b7579f77SDag-Erling Smørgrav 				ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass);
1027*b7579f77SDag-Erling Smørgrav 		}
1028*b7579f77SDag-Erling Smørgrav 		if(nods == ta->numDS && nokey == ta->numDNSKEY) {
1029*b7579f77SDag-Erling Smørgrav 			char b[257];
1030*b7579f77SDag-Erling Smørgrav 			dname_str(ta->name, b);
1031*b7579f77SDag-Erling Smørgrav 			log_warn("trust anchor %s has no supported algorithms,"
1032*b7579f77SDag-Erling Smørgrav 				" the anchor is ignored (check if you need to"
1033*b7579f77SDag-Erling Smørgrav 				" upgrade unbound and openssl)", b);
1034*b7579f77SDag-Erling Smørgrav 			(void)rbtree_delete(anchors->tree, &ta->node);
1035*b7579f77SDag-Erling Smørgrav 			lock_basic_unlock(&ta->lock);
1036*b7579f77SDag-Erling Smørgrav 			anchors_delfunc(&ta->node, NULL);
1037*b7579f77SDag-Erling Smørgrav 			ta = next;
1038*b7579f77SDag-Erling Smørgrav 			continue;
1039*b7579f77SDag-Erling Smørgrav 		}
1040*b7579f77SDag-Erling Smørgrav 		lock_basic_unlock(&ta->lock);
1041*b7579f77SDag-Erling Smørgrav 		ta = next;
1042*b7579f77SDag-Erling Smørgrav 	}
1043*b7579f77SDag-Erling Smørgrav 	lock_basic_unlock(&anchors->lock);
1044*b7579f77SDag-Erling Smørgrav 	return 1;
1045*b7579f77SDag-Erling Smørgrav }
1046*b7579f77SDag-Erling Smørgrav 
1047*b7579f77SDag-Erling Smørgrav int
1048*b7579f77SDag-Erling Smørgrav anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg)
1049*b7579f77SDag-Erling Smørgrav {
1050*b7579f77SDag-Erling Smørgrav 	struct config_strlist* f;
1051*b7579f77SDag-Erling Smørgrav 	char* nm;
1052*b7579f77SDag-Erling Smørgrav 	ldns_buffer* parsebuf = ldns_buffer_new(65535);
1053*b7579f77SDag-Erling Smørgrav 	for(f = cfg->domain_insecure; f; f = f->next) {
1054*b7579f77SDag-Erling Smørgrav 		if(!f->str || f->str[0] == 0) /* empty "" */
1055*b7579f77SDag-Erling Smørgrav 			continue;
1056*b7579f77SDag-Erling Smørgrav 		if(!anchor_insert_insecure(anchors, f->str)) {
1057*b7579f77SDag-Erling Smørgrav 			log_err("error in domain-insecure: %s", f->str);
1058*b7579f77SDag-Erling Smørgrav 			ldns_buffer_free(parsebuf);
1059*b7579f77SDag-Erling Smørgrav 			return 0;
1060*b7579f77SDag-Erling Smørgrav 		}
1061*b7579f77SDag-Erling Smørgrav 	}
1062*b7579f77SDag-Erling Smørgrav 	for(f = cfg->trust_anchor_file_list; f; f = f->next) {
1063*b7579f77SDag-Erling Smørgrav 		if(!f->str || f->str[0] == 0) /* empty "" */
1064*b7579f77SDag-Erling Smørgrav 			continue;
1065*b7579f77SDag-Erling Smørgrav 		nm = f->str;
1066*b7579f77SDag-Erling Smørgrav 		if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
1067*b7579f77SDag-Erling Smørgrav 			cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
1068*b7579f77SDag-Erling Smørgrav 			nm += strlen(cfg->chrootdir);
1069*b7579f77SDag-Erling Smørgrav 		if(!anchor_read_file(anchors, parsebuf, nm, 0)) {
1070*b7579f77SDag-Erling Smørgrav 			log_err("error reading trust-anchor-file: %s", f->str);
1071*b7579f77SDag-Erling Smørgrav 			ldns_buffer_free(parsebuf);
1072*b7579f77SDag-Erling Smørgrav 			return 0;
1073*b7579f77SDag-Erling Smørgrav 		}
1074*b7579f77SDag-Erling Smørgrav 	}
1075*b7579f77SDag-Erling Smørgrav 	for(f = cfg->trusted_keys_file_list; f; f = f->next) {
1076*b7579f77SDag-Erling Smørgrav 		if(!f->str || f->str[0] == 0) /* empty "" */
1077*b7579f77SDag-Erling Smørgrav 			continue;
1078*b7579f77SDag-Erling Smørgrav 		nm = f->str;
1079*b7579f77SDag-Erling Smørgrav 		if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
1080*b7579f77SDag-Erling Smørgrav 			cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
1081*b7579f77SDag-Erling Smørgrav 			nm += strlen(cfg->chrootdir);
1082*b7579f77SDag-Erling Smørgrav 		if(!anchor_read_bind_file_wild(anchors, parsebuf, nm)) {
1083*b7579f77SDag-Erling Smørgrav 			log_err("error reading trusted-keys-file: %s", f->str);
1084*b7579f77SDag-Erling Smørgrav 			ldns_buffer_free(parsebuf);
1085*b7579f77SDag-Erling Smørgrav 			return 0;
1086*b7579f77SDag-Erling Smørgrav 		}
1087*b7579f77SDag-Erling Smørgrav 	}
1088*b7579f77SDag-Erling Smørgrav 	for(f = cfg->trust_anchor_list; f; f = f->next) {
1089*b7579f77SDag-Erling Smørgrav 		if(!f->str || f->str[0] == 0) /* empty "" */
1090*b7579f77SDag-Erling Smørgrav 			continue;
1091*b7579f77SDag-Erling Smørgrav 		if(!anchor_store_str(anchors, parsebuf, f->str)) {
1092*b7579f77SDag-Erling Smørgrav 			log_err("error in trust-anchor: \"%s\"", f->str);
1093*b7579f77SDag-Erling Smørgrav 			ldns_buffer_free(parsebuf);
1094*b7579f77SDag-Erling Smørgrav 			return 0;
1095*b7579f77SDag-Erling Smørgrav 		}
1096*b7579f77SDag-Erling Smørgrav 	}
1097*b7579f77SDag-Erling Smørgrav 	if(cfg->dlv_anchor_file && cfg->dlv_anchor_file[0] != 0) {
1098*b7579f77SDag-Erling Smørgrav 		struct trust_anchor* dlva;
1099*b7579f77SDag-Erling Smørgrav 		nm = cfg->dlv_anchor_file;
1100*b7579f77SDag-Erling Smørgrav 		if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
1101*b7579f77SDag-Erling Smørgrav 			cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
1102*b7579f77SDag-Erling Smørgrav 			nm += strlen(cfg->chrootdir);
1103*b7579f77SDag-Erling Smørgrav 		if(!(dlva = anchor_read_file(anchors, parsebuf,
1104*b7579f77SDag-Erling Smørgrav 			nm, 1))) {
1105*b7579f77SDag-Erling Smørgrav 			log_err("error reading dlv-anchor-file: %s",
1106*b7579f77SDag-Erling Smørgrav 				cfg->dlv_anchor_file);
1107*b7579f77SDag-Erling Smørgrav 			ldns_buffer_free(parsebuf);
1108*b7579f77SDag-Erling Smørgrav 			return 0;
1109*b7579f77SDag-Erling Smørgrav 		}
1110*b7579f77SDag-Erling Smørgrav 		lock_basic_lock(&anchors->lock);
1111*b7579f77SDag-Erling Smørgrav 		anchors->dlv_anchor = dlva;
1112*b7579f77SDag-Erling Smørgrav 		lock_basic_unlock(&anchors->lock);
1113*b7579f77SDag-Erling Smørgrav 	}
1114*b7579f77SDag-Erling Smørgrav 	for(f = cfg->dlv_anchor_list; f; f = f->next) {
1115*b7579f77SDag-Erling Smørgrav 		struct trust_anchor* dlva;
1116*b7579f77SDag-Erling Smørgrav 		if(!f->str || f->str[0] == 0) /* empty "" */
1117*b7579f77SDag-Erling Smørgrav 			continue;
1118*b7579f77SDag-Erling Smørgrav 		if(!(dlva = anchor_store_str(
1119*b7579f77SDag-Erling Smørgrav 			anchors, parsebuf, f->str))) {
1120*b7579f77SDag-Erling Smørgrav 			log_err("error in dlv-anchor: \"%s\"", f->str);
1121*b7579f77SDag-Erling Smørgrav 			ldns_buffer_free(parsebuf);
1122*b7579f77SDag-Erling Smørgrav 			return 0;
1123*b7579f77SDag-Erling Smørgrav 		}
1124*b7579f77SDag-Erling Smørgrav 		lock_basic_lock(&anchors->lock);
1125*b7579f77SDag-Erling Smørgrav 		anchors->dlv_anchor = dlva;
1126*b7579f77SDag-Erling Smørgrav 		lock_basic_unlock(&anchors->lock);
1127*b7579f77SDag-Erling Smørgrav 	}
1128*b7579f77SDag-Erling Smørgrav 	/* do autr last, so that it sees what anchors are filled by other
1129*b7579f77SDag-Erling Smørgrav 	 * means can can print errors about double config for the name */
1130*b7579f77SDag-Erling Smørgrav 	for(f = cfg->auto_trust_anchor_file_list; f; f = f->next) {
1131*b7579f77SDag-Erling Smørgrav 		if(!f->str || f->str[0] == 0) /* empty "" */
1132*b7579f77SDag-Erling Smørgrav 			continue;
1133*b7579f77SDag-Erling Smørgrav 		nm = f->str;
1134*b7579f77SDag-Erling Smørgrav 		if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
1135*b7579f77SDag-Erling Smørgrav 			cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
1136*b7579f77SDag-Erling Smørgrav 			nm += strlen(cfg->chrootdir);
1137*b7579f77SDag-Erling Smørgrav 		if(!autr_read_file(anchors, nm)) {
1138*b7579f77SDag-Erling Smørgrav 			log_err("error reading auto-trust-anchor-file: %s",
1139*b7579f77SDag-Erling Smørgrav 				f->str);
1140*b7579f77SDag-Erling Smørgrav 			ldns_buffer_free(parsebuf);
1141*b7579f77SDag-Erling Smørgrav 			return 0;
1142*b7579f77SDag-Erling Smørgrav 		}
1143*b7579f77SDag-Erling Smørgrav 	}
1144*b7579f77SDag-Erling Smørgrav 	/* first assemble, since it may delete useless anchors */
1145*b7579f77SDag-Erling Smørgrav 	anchors_assemble_rrsets(anchors);
1146*b7579f77SDag-Erling Smørgrav 	init_parents(anchors);
1147*b7579f77SDag-Erling Smørgrav 	ldns_buffer_free(parsebuf);
1148*b7579f77SDag-Erling Smørgrav 	if(verbosity >= VERB_ALGO) autr_debug_print(anchors);
1149*b7579f77SDag-Erling Smørgrav 	return 1;
1150*b7579f77SDag-Erling Smørgrav }
1151*b7579f77SDag-Erling Smørgrav 
1152*b7579f77SDag-Erling Smørgrav struct trust_anchor*
1153*b7579f77SDag-Erling Smørgrav anchors_lookup(struct val_anchors* anchors,
1154*b7579f77SDag-Erling Smørgrav         uint8_t* qname, size_t qname_len, uint16_t qclass)
1155*b7579f77SDag-Erling Smørgrav {
1156*b7579f77SDag-Erling Smørgrav 	struct trust_anchor key;
1157*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* result;
1158*b7579f77SDag-Erling Smørgrav 	rbnode_t* res = NULL;
1159*b7579f77SDag-Erling Smørgrav 	key.node.key = &key;
1160*b7579f77SDag-Erling Smørgrav 	key.name = qname;
1161*b7579f77SDag-Erling Smørgrav 	key.namelabs = dname_count_labels(qname);
1162*b7579f77SDag-Erling Smørgrav 	key.namelen = qname_len;
1163*b7579f77SDag-Erling Smørgrav 	key.dclass = qclass;
1164*b7579f77SDag-Erling Smørgrav 	lock_basic_lock(&anchors->lock);
1165*b7579f77SDag-Erling Smørgrav 	if(rbtree_find_less_equal(anchors->tree, &key, &res)) {
1166*b7579f77SDag-Erling Smørgrav 		/* exact */
1167*b7579f77SDag-Erling Smørgrav 		result = (struct trust_anchor*)res;
1168*b7579f77SDag-Erling Smørgrav 	} else {
1169*b7579f77SDag-Erling Smørgrav 		/* smaller element (or no element) */
1170*b7579f77SDag-Erling Smørgrav 		int m;
1171*b7579f77SDag-Erling Smørgrav 		result = (struct trust_anchor*)res;
1172*b7579f77SDag-Erling Smørgrav 		if(!result || result->dclass != qclass) {
1173*b7579f77SDag-Erling Smørgrav 			lock_basic_unlock(&anchors->lock);
1174*b7579f77SDag-Erling Smørgrav 			return NULL;
1175*b7579f77SDag-Erling Smørgrav 		}
1176*b7579f77SDag-Erling Smørgrav 		/* count number of labels matched */
1177*b7579f77SDag-Erling Smørgrav 		(void)dname_lab_cmp(result->name, result->namelabs, key.name,
1178*b7579f77SDag-Erling Smørgrav 			key.namelabs, &m);
1179*b7579f77SDag-Erling Smørgrav 		while(result) { /* go up until qname is subdomain of stub */
1180*b7579f77SDag-Erling Smørgrav 			if(result->namelabs <= m)
1181*b7579f77SDag-Erling Smørgrav 				break;
1182*b7579f77SDag-Erling Smørgrav 			result = result->parent;
1183*b7579f77SDag-Erling Smørgrav 		}
1184*b7579f77SDag-Erling Smørgrav 	}
1185*b7579f77SDag-Erling Smørgrav 	if(result) {
1186*b7579f77SDag-Erling Smørgrav 		lock_basic_lock(&result->lock);
1187*b7579f77SDag-Erling Smørgrav 	}
1188*b7579f77SDag-Erling Smørgrav 	lock_basic_unlock(&anchors->lock);
1189*b7579f77SDag-Erling Smørgrav 	return result;
1190*b7579f77SDag-Erling Smørgrav }
1191*b7579f77SDag-Erling Smørgrav 
1192*b7579f77SDag-Erling Smørgrav size_t
1193*b7579f77SDag-Erling Smørgrav anchors_get_mem(struct val_anchors* anchors)
1194*b7579f77SDag-Erling Smørgrav {
1195*b7579f77SDag-Erling Smørgrav 	struct trust_anchor *ta;
1196*b7579f77SDag-Erling Smørgrav 	size_t s = sizeof(*anchors);
1197*b7579f77SDag-Erling Smørgrav 	RBTREE_FOR(ta, struct trust_anchor*, anchors->tree) {
1198*b7579f77SDag-Erling Smørgrav 		s += sizeof(*ta) + ta->namelen;
1199*b7579f77SDag-Erling Smørgrav 		/* keys and so on */
1200*b7579f77SDag-Erling Smørgrav 	}
1201*b7579f77SDag-Erling Smørgrav 	return s;
1202*b7579f77SDag-Erling Smørgrav }
1203*b7579f77SDag-Erling Smørgrav 
1204*b7579f77SDag-Erling Smørgrav int
1205*b7579f77SDag-Erling Smørgrav anchors_add_insecure(struct val_anchors* anchors, uint16_t c, uint8_t* nm)
1206*b7579f77SDag-Erling Smørgrav {
1207*b7579f77SDag-Erling Smørgrav 	struct trust_anchor key;
1208*b7579f77SDag-Erling Smørgrav 	key.node.key = &key;
1209*b7579f77SDag-Erling Smørgrav 	key.name = nm;
1210*b7579f77SDag-Erling Smørgrav 	key.namelabs = dname_count_size_labels(nm, &key.namelen);
1211*b7579f77SDag-Erling Smørgrav 	key.dclass = c;
1212*b7579f77SDag-Erling Smørgrav 	lock_basic_lock(&anchors->lock);
1213*b7579f77SDag-Erling Smørgrav 	if(rbtree_search(anchors->tree, &key)) {
1214*b7579f77SDag-Erling Smørgrav 		lock_basic_unlock(&anchors->lock);
1215*b7579f77SDag-Erling Smørgrav 		/* nothing to do, already an anchor or insecure point */
1216*b7579f77SDag-Erling Smørgrav 		return 1;
1217*b7579f77SDag-Erling Smørgrav 	}
1218*b7579f77SDag-Erling Smørgrav 	if(!anchor_new_ta(anchors, nm, key.namelabs, key.namelen, c, 0)) {
1219*b7579f77SDag-Erling Smørgrav 		log_err("out of memory");
1220*b7579f77SDag-Erling Smørgrav 		lock_basic_unlock(&anchors->lock);
1221*b7579f77SDag-Erling Smørgrav 		return 0;
1222*b7579f77SDag-Erling Smørgrav 	}
1223*b7579f77SDag-Erling Smørgrav 	/* no other contents in new ta, because it is insecure point */
1224*b7579f77SDag-Erling Smørgrav 	anchors_init_parents_locked(anchors);
1225*b7579f77SDag-Erling Smørgrav 	lock_basic_unlock(&anchors->lock);
1226*b7579f77SDag-Erling Smørgrav 	return 1;
1227*b7579f77SDag-Erling Smørgrav }
1228*b7579f77SDag-Erling Smørgrav 
1229*b7579f77SDag-Erling Smørgrav void
1230*b7579f77SDag-Erling Smørgrav anchors_delete_insecure(struct val_anchors* anchors, uint16_t c,
1231*b7579f77SDag-Erling Smørgrav         uint8_t* nm)
1232*b7579f77SDag-Erling Smørgrav {
1233*b7579f77SDag-Erling Smørgrav 	struct trust_anchor key;
1234*b7579f77SDag-Erling Smørgrav 	struct trust_anchor* ta;
1235*b7579f77SDag-Erling Smørgrav 	key.node.key = &key;
1236*b7579f77SDag-Erling Smørgrav 	key.name = nm;
1237*b7579f77SDag-Erling Smørgrav 	key.namelabs = dname_count_size_labels(nm, &key.namelen);
1238*b7579f77SDag-Erling Smørgrav 	key.dclass = c;
1239*b7579f77SDag-Erling Smørgrav 	lock_basic_lock(&anchors->lock);
1240*b7579f77SDag-Erling Smørgrav 	if(!(ta=(struct trust_anchor*)rbtree_search(anchors->tree, &key))) {
1241*b7579f77SDag-Erling Smørgrav 		lock_basic_unlock(&anchors->lock);
1242*b7579f77SDag-Erling Smørgrav 		/* nothing there */
1243*b7579f77SDag-Erling Smørgrav 		return;
1244*b7579f77SDag-Erling Smørgrav 	}
1245*b7579f77SDag-Erling Smørgrav 	/* lock it to drive away other threads that use it */
1246*b7579f77SDag-Erling Smørgrav 	lock_basic_lock(&ta->lock);
1247*b7579f77SDag-Erling Smørgrav 	/* see if its really an insecure point */
1248*b7579f77SDag-Erling Smørgrav 	if(ta->keylist || ta->autr || ta->numDS || ta->numDNSKEY) {
1249*b7579f77SDag-Erling Smørgrav 		lock_basic_unlock(&ta->lock);
1250*b7579f77SDag-Erling Smørgrav 		/* its not an insecure point, do not remove it */
1251*b7579f77SDag-Erling Smørgrav 		return;
1252*b7579f77SDag-Erling Smørgrav 	}
1253*b7579f77SDag-Erling Smørgrav 
1254*b7579f77SDag-Erling Smørgrav 	/* remove from tree */
1255*b7579f77SDag-Erling Smørgrav 	(void)rbtree_delete(anchors->tree, &ta->node);
1256*b7579f77SDag-Erling Smørgrav 	anchors_init_parents_locked(anchors);
1257*b7579f77SDag-Erling Smørgrav 	lock_basic_unlock(&anchors->lock);
1258*b7579f77SDag-Erling Smørgrav 
1259*b7579f77SDag-Erling Smørgrav 	/* actual free of data */
1260*b7579f77SDag-Erling Smørgrav 	lock_basic_unlock(&ta->lock);
1261*b7579f77SDag-Erling Smørgrav 	anchors_delfunc(&ta->node, NULL);
1262*b7579f77SDag-Erling Smørgrav }
1263*b7579f77SDag-Erling Smørgrav 
1264