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
key_entry_sizefunc(void * key,void * data)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
key_entry_compfunc(void * k1,void * k2)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
key_entry_delkeyfunc(void * key,void * ATTR_UNUSED (userarg))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
key_entry_deldatafunc(void * data,void * ATTR_UNUSED (userarg))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
key_entry_hash(struct key_entry_key * kk)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*
key_entry_copy_toregion(struct key_entry_key * kkey,struct regional * region)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*
key_entry_copy(struct key_entry_key * kkey,int copy_reason)155 key_entry_copy(struct key_entry_key* kkey, int copy_reason)
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(copy_reason && d->reason && *d->reason != 0) {
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 } else {
203 newd->reason = NULL;
204 }
205 if(d->algo) {
206 newd->algo = (uint8_t*)strdup((char*)d->algo);
207 if(!newd->algo) {
208 free(newd->rrset_data);
209 free(newd->reason);
210 free(newd);
211 free(newk->name);
212 free(newk);
213 return NULL;
214 }
215 }
216 newk->entry.data = newd;
217 }
218 return newk;
219 }
220
221 int
key_entry_isnull(struct key_entry_key * kkey)222 key_entry_isnull(struct key_entry_key* kkey)
223 {
224 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
225 return (!d->isbad && d->rrset_data == NULL);
226 }
227
228 int
key_entry_isgood(struct key_entry_key * kkey)229 key_entry_isgood(struct key_entry_key* kkey)
230 {
231 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
232 return (!d->isbad && d->rrset_data != NULL);
233 }
234
235 int
key_entry_isbad(struct key_entry_key * kkey)236 key_entry_isbad(struct key_entry_key* kkey)
237 {
238 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
239 return (int)(d->isbad);
240 }
241
242 char*
key_entry_get_reason(struct key_entry_key * kkey)243 key_entry_get_reason(struct key_entry_key* kkey)
244 {
245 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
246 return d->reason;
247 }
248
249 sldns_ede_code
key_entry_get_reason_bogus(struct key_entry_key * kkey)250 key_entry_get_reason_bogus(struct key_entry_key* kkey)
251 {
252 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
253 return d->reason_bogus;
254
255 }
256
257 /** setup key entry in region */
258 static int
key_entry_setup(struct regional * region,uint8_t * name,size_t namelen,uint16_t dclass,struct key_entry_key ** k,struct key_entry_data ** d)259 key_entry_setup(struct regional* region,
260 uint8_t* name, size_t namelen, uint16_t dclass,
261 struct key_entry_key** k, struct key_entry_data** d)
262 {
263 *k = regional_alloc(region, sizeof(**k));
264 if(!*k)
265 return 0;
266 memset(*k, 0, sizeof(**k));
267 (*k)->entry.key = *k;
268 (*k)->name = regional_alloc_init(region, name, namelen);
269 if(!(*k)->name)
270 return 0;
271 (*k)->namelen = namelen;
272 (*k)->key_class = dclass;
273 *d = regional_alloc(region, sizeof(**d));
274 if(!*d)
275 return 0;
276 (*k)->entry.data = *d;
277 return 1;
278 }
279
280 struct key_entry_key*
key_entry_create_null(struct regional * region,uint8_t * name,size_t namelen,uint16_t dclass,time_t ttl,sldns_ede_code reason_bogus,const char * reason,time_t now)281 key_entry_create_null(struct regional* region,
282 uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
283 sldns_ede_code reason_bogus, const char* reason,
284 time_t now)
285 {
286 struct key_entry_key* k;
287 struct key_entry_data* d;
288 if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
289 return NULL;
290 d->ttl = now + ttl;
291 d->isbad = 0;
292 d->reason = (!reason || *reason == 0)
293 ?NULL :(char*)regional_strdup(region, reason);
294 /* On allocation error we don't store the reason string */
295 d->reason_bogus = reason_bogus;
296 d->rrset_type = LDNS_RR_TYPE_DNSKEY;
297 d->rrset_data = NULL;
298 d->algo = NULL;
299 return k;
300 }
301
302 struct key_entry_key*
key_entry_create_rrset(struct regional * region,uint8_t * name,size_t namelen,uint16_t dclass,struct ub_packed_rrset_key * rrset,uint8_t * sigalg,sldns_ede_code reason_bogus,const char * reason,time_t now)303 key_entry_create_rrset(struct regional* region,
304 uint8_t* name, size_t namelen, uint16_t dclass,
305 struct ub_packed_rrset_key* rrset, uint8_t* sigalg,
306 sldns_ede_code reason_bogus, const char* reason,
307 time_t now)
308 {
309 struct key_entry_key* k;
310 struct key_entry_data* d;
311 struct packed_rrset_data* rd = (struct packed_rrset_data*)
312 rrset->entry.data;
313 if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
314 return NULL;
315 d->ttl = rd->ttl + now;
316 d->isbad = 0;
317 d->reason = (!reason || *reason == 0)
318 ?NULL :(char*)regional_strdup(region, reason);
319 /* On allocation error we don't store the reason string */
320 d->reason_bogus = reason_bogus;
321 d->rrset_type = ntohs(rrset->rk.type);
322 d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region,
323 rd, packed_rrset_sizeof(rd));
324 if(!d->rrset_data)
325 return NULL;
326 if(sigalg) {
327 d->algo = (uint8_t*)regional_strdup(region, (char*)sigalg);
328 if(!d->algo)
329 return NULL;
330 } else d->algo = NULL;
331 packed_rrset_ptr_fixup(d->rrset_data);
332 return k;
333 }
334
335 struct key_entry_key*
key_entry_create_bad(struct regional * region,uint8_t * name,size_t namelen,uint16_t dclass,time_t ttl,sldns_ede_code reason_bogus,const char * reason,time_t now)336 key_entry_create_bad(struct regional* region,
337 uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
338 sldns_ede_code reason_bogus, const char* reason,
339 time_t now)
340 {
341 struct key_entry_key* k;
342 struct key_entry_data* d;
343 if(!key_entry_setup(region, name, namelen, dclass, &k, &d))
344 return NULL;
345 d->ttl = now + ttl;
346 d->isbad = 1;
347 d->reason = (!reason || *reason == 0)
348 ?NULL :(char*)regional_strdup(region, reason);
349 /* On allocation error we don't store the reason string */
350 d->reason_bogus = reason_bogus;
351 d->rrset_type = LDNS_RR_TYPE_DNSKEY;
352 d->rrset_data = NULL;
353 d->algo = NULL;
354 return k;
355 }
356
357 struct ub_packed_rrset_key*
key_entry_get_rrset(struct key_entry_key * kkey,struct regional * region)358 key_entry_get_rrset(struct key_entry_key* kkey, struct regional* region)
359 {
360 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
361 struct ub_packed_rrset_key* rrk;
362 struct packed_rrset_data* rrd;
363 if(!d || !d->rrset_data)
364 return NULL;
365 rrk = regional_alloc(region, sizeof(*rrk));
366 if(!rrk)
367 return NULL;
368 memset(rrk, 0, sizeof(*rrk));
369 rrk->rk.dname = regional_alloc_init(region, kkey->name, kkey->namelen);
370 if(!rrk->rk.dname)
371 return NULL;
372 rrk->rk.dname_len = kkey->namelen;
373 rrk->rk.type = htons(d->rrset_type);
374 rrk->rk.rrset_class = htons(kkey->key_class);
375 rrk->entry.key = rrk;
376 rrd = regional_alloc_init(region, d->rrset_data,
377 packed_rrset_sizeof(d->rrset_data));
378 if(!rrd)
379 return NULL;
380 rrk->entry.data = rrd;
381 packed_rrset_ptr_fixup(rrd);
382 return rrk;
383 }
384
385 /** Get size of key in keyset */
386 static size_t
dnskey_get_keysize(struct packed_rrset_data * data,size_t idx)387 dnskey_get_keysize(struct packed_rrset_data* data, size_t idx)
388 {
389 unsigned char* pk;
390 unsigned int pklen = 0;
391 int algo;
392 if(data->rr_len[idx] < 2+5)
393 return 0;
394 algo = (int)data->rr_data[idx][2+3];
395 pk = (unsigned char*)data->rr_data[idx]+2+4;
396 pklen = (unsigned)data->rr_len[idx]-2-4;
397 return sldns_rr_dnskey_key_size_raw(pk, pklen, algo);
398 }
399
400 /** get dnskey flags from data */
401 static uint16_t
kd_get_flags(struct packed_rrset_data * data,size_t idx)402 kd_get_flags(struct packed_rrset_data* data, size_t idx)
403 {
404 uint16_t f;
405 if(data->rr_len[idx] < 2+2)
406 return 0;
407 memmove(&f, data->rr_data[idx]+2, 2);
408 f = ntohs(f);
409 return f;
410 }
411
412 size_t
key_entry_keysize(struct key_entry_key * kkey)413 key_entry_keysize(struct key_entry_key* kkey)
414 {
415 struct packed_rrset_data* d;
416 /* compute size of smallest ZSK key in the rrset */
417 size_t i;
418 size_t bits = 0;
419 if(!key_entry_isgood(kkey))
420 return 0;
421 d = ((struct key_entry_data*)kkey->entry.data)->rrset_data;
422 for(i=0; i<d->count; i++) {
423 if(!(kd_get_flags(d, i) & DNSKEY_BIT_ZSK))
424 continue;
425 if(i==0 || dnskey_get_keysize(d, i) < bits)
426 bits = dnskey_get_keysize(d, i);
427 }
428 return bits;
429 }
430