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