]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/unbound/validator/val_kentry.c
unbound: Vendor import 1.19.1
[FreeBSD/FreeBSD.git] / contrib / unbound / validator / val_kentry.c
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, 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 
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 
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 
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*
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
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
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* 
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* 
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* 
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* 
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
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
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 
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 }