1 /*
2  * validator/val_kentry.c - validator key entry definition.
3  *
4  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5  *
6  * This software is open source.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * Neither the name of the NLNET LABS nor the names of its contributors may
20  * be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /**
37  * \file
38  *
39  * This file contains functions for dealing with validator key entries.
40  */
41 #include "config.h"
42 #include "validator/val_kentry.h"
43 #include "util/data/packed_rrset.h"
44 #include "util/data/dname.h"
45 #include "util/storage/lookup3.h"
46 #include "util/regional.h"
47 #include "util/net_help.h"
48 #include "sldns/rrdef.h"
49 #include "sldns/keyraw.h"
50 
51 size_t
52 key_entry_sizefunc(void* key, void* data)
53 {
54 	struct key_entry_key* kk = (struct key_entry_key*)key;
55 	struct key_entry_data* kd = (struct key_entry_data*)data;
56 	size_t s = sizeof(*kk) + kk->namelen;
57 	s += sizeof(*kd) + lock_get_mem(&kk->entry.lock);
58 	if(kd->rrset_data)
59 		s += packed_rrset_sizeof(kd->rrset_data);
60 	if(kd->reason)
61 		s += strlen(kd->reason)+1;
62 	if(kd->algo)
63 		s += strlen((char*)kd->algo)+1;
64 	return s;
65 }
66 
67 int
68 key_entry_compfunc(void* k1, void* k2)
69 {
70 	struct key_entry_key* n1 = (struct key_entry_key*)k1;
71 	struct key_entry_key* n2 = (struct key_entry_key*)k2;
72 	if(n1->key_class != n2->key_class) {
73 		if(n1->key_class < n2->key_class)
74 			return -1;
75 		return 1;
76 	}
77 	return query_dname_compare(n1->name, n2->name);
78 }
79 
80 void
81 key_entry_delkeyfunc(void* key, void* ATTR_UNUSED(userarg))
82 {
83 	struct key_entry_key* kk = (struct key_entry_key*)key;
84 	if(!key)
85 		return;
86 	lock_rw_destroy(&kk->entry.lock);
87 	free(kk->name);
88 	free(kk);
89 }
90 
91 void
92 key_entry_deldatafunc(void* data, void* ATTR_UNUSED(userarg))
93 {
94 	struct key_entry_data* kd = (struct key_entry_data*)data;
95 	free(kd->reason);
96 	free(kd->rrset_data);
97 	free(kd->algo);
98 	free(kd);
99 }
100 
101 void
102 key_entry_hash(struct key_entry_key* kk)
103 {
104 	kk->entry.hash = 0x654;
105 	kk->entry.hash = hashlittle(&kk->key_class, sizeof(kk->key_class),
106 		kk->entry.hash);
107 	kk->entry.hash = dname_query_hash(kk->name, kk->entry.hash);
108 }
109 
110 struct key_entry_key*
111 key_entry_copy_toregion(struct key_entry_key* kkey, struct regional* region)
112 {
113 	struct key_entry_key* newk;
114 	newk = regional_alloc_init(region, kkey, sizeof(*kkey));
115 	if(!newk)
116 		return NULL;
117 	newk->name = regional_alloc_init(region, kkey->name, kkey->namelen);
118 	if(!newk->name)
119 		return NULL;
120 	newk->entry.key = newk;
121 	if(newk->entry.data) {
122 		/* copy data element */
123 		struct key_entry_data *d = (struct key_entry_data*)
124 			kkey->entry.data;
125 		struct key_entry_data *newd;
126 		newd = regional_alloc_init(region, d, sizeof(*d));
127 		if(!newd)
128 			return NULL;
129 		/* copy rrset */
130 		if(d->rrset_data) {
131 			newd->rrset_data = regional_alloc_init(region,
132 				d->rrset_data,
133 				packed_rrset_sizeof(d->rrset_data));
134 			if(!newd->rrset_data)
135 				return NULL;
136 			packed_rrset_ptr_fixup(newd->rrset_data);
137 		}
138 		if(d->reason) {
139 			newd->reason = regional_strdup(region, d->reason);
140 			if(!newd->reason)
141 				return NULL;
142 		}
143 		if(d->algo) {
144 			newd->algo = (uint8_t*)regional_strdup(region,
145 				(char*)d->algo);
146 			if(!newd->algo)
147 				return NULL;
148 		}
149 		newk->entry.data = newd;
150 	}
151 	return newk;
152 }
153 
154 struct key_entry_key*
155 key_entry_copy(struct key_entry_key* kkey)
156 {
157 	struct key_entry_key* newk;
158 	if(!kkey)
159 		return NULL;
160 	newk = memdup(kkey, sizeof(*kkey));
161 	if(!newk)
162 		return NULL;
163 	newk->name = memdup(kkey->name, kkey->namelen);
164 	if(!newk->name) {
165 		free(newk);
166 		return NULL;
167 	}
168 	lock_rw_init(&newk->entry.lock);
169 	newk->entry.key = newk;
170 	if(newk->entry.data) {
171 		/* copy data element */
172 		struct key_entry_data *d = (struct key_entry_data*)
173 			kkey->entry.data;
174 		struct key_entry_data *newd;
175 		newd = memdup(d, sizeof(*d));
176 		if(!newd) {
177 			free(newk->name);
178 			free(newk);
179 			return NULL;
180 		}
181 		/* copy rrset */
182 		if(d->rrset_data) {
183 			newd->rrset_data = memdup(d->rrset_data,
184 				packed_rrset_sizeof(d->rrset_data));
185 			if(!newd->rrset_data) {
186 				free(newd);
187 				free(newk->name);
188 				free(newk);
189 				return NULL;
190 			}
191 			packed_rrset_ptr_fixup(newd->rrset_data);
192 		}
193 		if(d->reason) {
194 			newd->reason = strdup(d->reason);
195 			if(!newd->reason) {
196 				free(newd->rrset_data);
197 				free(newd);
198 				free(newk->name);
199 				free(newk);
200 				return NULL;
201 			}
202 		}
203 		if(d->algo) {
204 			newd->algo = (uint8_t*)strdup((char*)d->algo);
205 			if(!newd->algo) {
206 				free(newd->rrset_data);
207 				free(newd->reason);
208 				free(newd);
209 				free(newk->name);
210 				free(newk);
211 				return NULL;
212 			}
213 		}
214 		newk->entry.data = newd;
215 	}
216 	return newk;
217 }
218 
219 int
220 key_entry_isnull(struct key_entry_key* kkey)
221 {
222 	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
223 	return (!d->isbad && d->rrset_data == NULL);
224 }
225 
226 int
227 key_entry_isgood(struct key_entry_key* kkey)
228 {
229 	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
230 	return (!d->isbad && d->rrset_data != NULL);
231 }
232 
233 int
234 key_entry_isbad(struct key_entry_key* kkey)
235 {
236 	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
237 	return (int)(d->isbad);
238 }
239 
240 void
241 key_entry_set_reason(struct key_entry_key* kkey, char* reason)
242 {
243 	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
244 	d->reason = reason;
245 }
246 
247 void
248 key_entry_set_reason_bogus(struct key_entry_key* kkey, sldns_ede_code ede)
249 {
250 	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
251 	if (ede != LDNS_EDE_NONE) { /* reason_bogus init is LDNS_EDE_NONE already */
252 		d->reason_bogus = ede;
253 	}
254 }
255 
256 char*
257 key_entry_get_reason(struct key_entry_key* kkey)
258 {
259 	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
260 	return d->reason;
261 }
262 
263 sldns_ede_code
264 key_entry_get_reason_bogus(struct key_entry_key* kkey)
265 {
266 	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
267 	return d->reason_bogus;
268 
269 }
270 
271 /** setup key entry in region */
272 static int
273 key_entry_setup(struct regional* region,
274 	uint8_t* name, size_t namelen, uint16_t dclass,
275 	struct key_entry_key** k, struct key_entry_data** d)
276 {
277 	*k = regional_alloc(region, sizeof(**k));
278 	if(!*k)
279 		return 0;
280 	memset(*k, 0, sizeof(**k));
281 	(*k)->entry.key = *k;
282 	(*k)->name = regional_alloc_init(region, name, namelen);
283 	if(!(*k)->name)
284 		return 0;
285 	(*k)->namelen = namelen;
286 	(*k)->key_class = dclass;
287 	*d = regional_alloc(region, sizeof(**d));
288 	if(!*d)
289 		return 0;
290 	(*k)->entry.data = *d;
291 	return 1;
292 }
293 
294 struct key_entry_key*
295 key_entry_create_null(struct regional* region,
296 	uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
297 	time_t now)
298 {
299 	struct key_entry_key* k;
300 	struct key_entry_data* d;
301 	if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
302 		return NULL;
303 	d->ttl = now + ttl;
304 	d->isbad = 0;
305 	d->reason = NULL;
306 	d->reason_bogus = LDNS_EDE_NONE;
307 	d->rrset_type = LDNS_RR_TYPE_DNSKEY;
308 	d->rrset_data = NULL;
309 	d->algo = NULL;
310 	return k;
311 }
312 
313 struct key_entry_key*
314 key_entry_create_rrset(struct regional* region,
315 	uint8_t* name, size_t namelen, uint16_t dclass,
316 	struct ub_packed_rrset_key* rrset, uint8_t* sigalg, time_t now)
317 {
318 	struct key_entry_key* k;
319 	struct key_entry_data* d;
320 	struct packed_rrset_data* rd = (struct packed_rrset_data*)
321 		rrset->entry.data;
322 	if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
323 		return NULL;
324 	d->ttl = rd->ttl + now;
325 	d->isbad = 0;
326 	d->reason = NULL;
327 	d->reason_bogus = LDNS_EDE_NONE;
328 	d->rrset_type = ntohs(rrset->rk.type);
329 	d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region,
330 		rd, packed_rrset_sizeof(rd));
331 	if(!d->rrset_data)
332 		return NULL;
333 	if(sigalg) {
334 		d->algo = (uint8_t*)regional_strdup(region, (char*)sigalg);
335 		if(!d->algo)
336 			return NULL;
337 	} else d->algo = NULL;
338 	packed_rrset_ptr_fixup(d->rrset_data);
339 	return k;
340 }
341 
342 struct key_entry_key*
343 key_entry_create_bad(struct regional* region,
344 	uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
345 	time_t now)
346 {
347 	struct key_entry_key* k;
348 	struct key_entry_data* d;
349 	if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
350 		return NULL;
351 	d->ttl = now + ttl;
352 	d->isbad = 1;
353 	d->reason = NULL;
354 	d->reason_bogus = LDNS_EDE_NONE;
355 	d->rrset_type = LDNS_RR_TYPE_DNSKEY;
356 	d->rrset_data = NULL;
357 	d->algo = NULL;
358 	return k;
359 }
360 
361 struct ub_packed_rrset_key*
362 key_entry_get_rrset(struct key_entry_key* kkey, struct regional* region)
363 {
364 	struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
365 	struct ub_packed_rrset_key* rrk;
366 	struct packed_rrset_data* rrd;
367 	if(!d || !d->rrset_data)
368 		return NULL;
369 	rrk = regional_alloc(region, sizeof(*rrk));
370 	if(!rrk)
371 		return NULL;
372 	memset(rrk, 0, sizeof(*rrk));
373 	rrk->rk.dname = regional_alloc_init(region, kkey->name, kkey->namelen);
374 	if(!rrk->rk.dname)
375 		return NULL;
376 	rrk->rk.dname_len = kkey->namelen;
377 	rrk->rk.type = htons(d->rrset_type);
378 	rrk->rk.rrset_class = htons(kkey->key_class);
379 	rrk->entry.key = rrk;
380 	rrd = regional_alloc_init(region, d->rrset_data,
381 		packed_rrset_sizeof(d->rrset_data));
382 	if(!rrd)
383 		return NULL;
384 	rrk->entry.data = rrd;
385 	packed_rrset_ptr_fixup(rrd);
386 	return rrk;
387 }
388 
389 /** Get size of key in keyset */
390 static size_t
391 dnskey_get_keysize(struct packed_rrset_data* data, size_t idx)
392 {
393 	unsigned char* pk;
394 	unsigned int pklen = 0;
395 	int algo;
396 	if(data->rr_len[idx] < 2+5)
397 		return 0;
398 	algo = (int)data->rr_data[idx][2+3];
399 	pk = (unsigned char*)data->rr_data[idx]+2+4;
400 	pklen = (unsigned)data->rr_len[idx]-2-4;
401 	return sldns_rr_dnskey_key_size_raw(pk, pklen, algo);
402 }
403 
404 /** get dnskey flags from data */
405 static uint16_t
406 kd_get_flags(struct packed_rrset_data* data, size_t idx)
407 {
408 	uint16_t f;
409 	if(data->rr_len[idx] < 2+2)
410 		return 0;
411 	memmove(&f, data->rr_data[idx]+2, 2);
412 	f = ntohs(f);
413 	return f;
414 }
415 
416 size_t
417 key_entry_keysize(struct key_entry_key* kkey)
418 {
419 	struct packed_rrset_data* d;
420 	/* compute size of smallest ZSK key in the rrset */
421 	size_t i;
422 	size_t bits = 0;
423 	if(!key_entry_isgood(kkey))
424 		return 0;
425 	d = ((struct key_entry_data*)kkey->entry.data)->rrset_data;
426 	for(i=0; i<d->count; i++) {
427 		if(!(kd_get_flags(d, i) & DNSKEY_BIT_ZSK))
428 			continue;
429 		if(i==0 || dnskey_get_keysize(d, i) < bits)
430 			bits = dnskey_get_keysize(d, i);
431 	}
432 	return bits;
433 }
434