Home | History | Annotate | Line # | Download | only in validator
      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 }
    430