diff options
Diffstat (limited to 'external/unbound/validator/val_kentry.c')
-rw-r--r-- | external/unbound/validator/val_kentry.c | 413 |
1 files changed, 413 insertions, 0 deletions
diff --git a/external/unbound/validator/val_kentry.c b/external/unbound/validator/val_kentry.c new file mode 100644 index 000000000..f99f18e89 --- /dev/null +++ b/external/unbound/validator/val_kentry.c @@ -0,0 +1,413 @@ +/* + * validator/val_kentry.c - validator key entry definition. + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains functions for dealing with validator key entries. + */ +#include "config.h" +#include "validator/val_kentry.h" +#include "util/data/packed_rrset.h" +#include "util/data/dname.h" +#include "util/storage/lookup3.h" +#include "util/regional.h" +#include "util/net_help.h" +#include "ldns/rrdef.h" +#include "ldns/keyraw.h" + +size_t +key_entry_sizefunc(void* key, void* data) +{ + struct key_entry_key* kk = (struct key_entry_key*)key; + struct key_entry_data* kd = (struct key_entry_data*)data; + size_t s = sizeof(*kk) + kk->namelen; + s += sizeof(*kd) + lock_get_mem(&kk->entry.lock); + if(kd->rrset_data) + s += packed_rrset_sizeof(kd->rrset_data); + if(kd->reason) + s += strlen(kd->reason)+1; + if(kd->algo) + s += strlen((char*)kd->algo)+1; + return s; +} + +int +key_entry_compfunc(void* k1, void* k2) +{ + struct key_entry_key* n1 = (struct key_entry_key*)k1; + struct key_entry_key* n2 = (struct key_entry_key*)k2; + if(n1->key_class != n2->key_class) { + if(n1->key_class < n2->key_class) + return -1; + return 1; + } + return query_dname_compare(n1->name, n2->name); +} + +void +key_entry_delkeyfunc(void* key, void* ATTR_UNUSED(userarg)) +{ + struct key_entry_key* kk = (struct key_entry_key*)key; + if(!key) + return; + lock_rw_destroy(&kk->entry.lock); + free(kk->name); + free(kk); +} + +void +key_entry_deldatafunc(void* data, void* ATTR_UNUSED(userarg)) +{ + struct key_entry_data* kd = (struct key_entry_data*)data; + free(kd->reason); + free(kd->rrset_data); + free(kd->algo); + free(kd); +} + +void +key_entry_hash(struct key_entry_key* kk) +{ + kk->entry.hash = 0x654; + kk->entry.hash = hashlittle(&kk->key_class, sizeof(kk->key_class), + kk->entry.hash); + kk->entry.hash = dname_query_hash(kk->name, kk->entry.hash); +} + +struct key_entry_key* +key_entry_copy_toregion(struct key_entry_key* kkey, struct regional* region) +{ + struct key_entry_key* newk; + newk = regional_alloc_init(region, kkey, sizeof(*kkey)); + if(!newk) + return NULL; + newk->name = regional_alloc_init(region, kkey->name, kkey->namelen); + if(!newk->name) + return NULL; + newk->entry.key = newk; + if(newk->entry.data) { + /* copy data element */ + struct key_entry_data *d = (struct key_entry_data*) + kkey->entry.data; + struct key_entry_data *newd; + newd = regional_alloc_init(region, d, sizeof(*d)); + if(!newd) + return NULL; + /* copy rrset */ + if(d->rrset_data) { + newd->rrset_data = regional_alloc_init(region, + d->rrset_data, + packed_rrset_sizeof(d->rrset_data)); + if(!newd->rrset_data) + return NULL; + packed_rrset_ptr_fixup(newd->rrset_data); + } + if(d->reason) { + newd->reason = regional_strdup(region, d->reason); + if(!newd->reason) + return NULL; + } + if(d->algo) { + newd->algo = (uint8_t*)regional_strdup(region, + (char*)d->algo); + if(!newd->algo) + return NULL; + } + newk->entry.data = newd; + } + return newk; +} + +struct key_entry_key* +key_entry_copy(struct key_entry_key* kkey) +{ + struct key_entry_key* newk; + if(!kkey) + return NULL; + newk = memdup(kkey, sizeof(*kkey)); + if(!newk) + return NULL; + newk->name = memdup(kkey->name, kkey->namelen); + if(!newk->name) { + free(newk); + return NULL; + } + lock_rw_init(&newk->entry.lock); + newk->entry.key = newk; + if(newk->entry.data) { + /* copy data element */ + struct key_entry_data *d = (struct key_entry_data*) + kkey->entry.data; + struct key_entry_data *newd; + newd = memdup(d, sizeof(*d)); + if(!newd) { + free(newk->name); + free(newk); + return NULL; + } + /* copy rrset */ + if(d->rrset_data) { + newd->rrset_data = memdup(d->rrset_data, + packed_rrset_sizeof(d->rrset_data)); + if(!newd->rrset_data) { + free(newd); + free(newk->name); + free(newk); + return NULL; + } + packed_rrset_ptr_fixup(newd->rrset_data); + } + if(d->reason) { + newd->reason = strdup(d->reason); + if(!newd->reason) { + free(newd->rrset_data); + free(newd); + free(newk->name); + free(newk); + return NULL; + } + } + if(d->algo) { + newd->algo = (uint8_t*)strdup((char*)d->algo); + if(!newd->algo) { + free(newd->rrset_data); + free(newd->reason); + free(newd); + free(newk->name); + free(newk); + return NULL; + } + } + newk->entry.data = newd; + } + return newk; +} + +int +key_entry_isnull(struct key_entry_key* kkey) +{ + struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; + return (!d->isbad && d->rrset_data == NULL); +} + +int +key_entry_isgood(struct key_entry_key* kkey) +{ + struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; + return (!d->isbad && d->rrset_data != NULL); +} + +int +key_entry_isbad(struct key_entry_key* kkey) +{ + struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; + return (int)(d->isbad); +} + +void +key_entry_set_reason(struct key_entry_key* kkey, char* reason) +{ + struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; + d->reason = reason; +} + +char* +key_entry_get_reason(struct key_entry_key* kkey) +{ + struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; + return d->reason; +} + +/** setup key entry in region */ +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) +{ + *k = regional_alloc(region, sizeof(**k)); + if(!*k) + return 0; + memset(*k, 0, sizeof(**k)); + (*k)->entry.key = *k; + (*k)->name = regional_alloc_init(region, name, namelen); + if(!(*k)->name) + return 0; + (*k)->namelen = namelen; + (*k)->key_class = dclass; + *d = regional_alloc(region, sizeof(**d)); + if(!*d) + return 0; + (*k)->entry.data = *d; + return 1; +} + +struct key_entry_key* +key_entry_create_null(struct regional* region, + uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl, + time_t now) +{ + struct key_entry_key* k; + struct key_entry_data* d; + if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) + return NULL; + d->ttl = now + ttl; + d->isbad = 0; + d->reason = NULL; + d->rrset_type = LDNS_RR_TYPE_DNSKEY; + d->rrset_data = NULL; + d->algo = NULL; + return k; +} + +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, time_t now) +{ + struct key_entry_key* k; + struct key_entry_data* d; + struct packed_rrset_data* rd = (struct packed_rrset_data*) + rrset->entry.data; + if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) + return NULL; + d->ttl = rd->ttl + now; + d->isbad = 0; + d->reason = NULL; + d->rrset_type = ntohs(rrset->rk.type); + d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region, + rd, packed_rrset_sizeof(rd)); + if(!d->rrset_data) + return NULL; + if(sigalg) { + d->algo = (uint8_t*)regional_strdup(region, (char*)sigalg); + if(!d->algo) + return NULL; + } else d->algo = NULL; + packed_rrset_ptr_fixup(d->rrset_data); + return k; +} + +struct key_entry_key* +key_entry_create_bad(struct regional* region, + uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl, + time_t now) +{ + struct key_entry_key* k; + struct key_entry_data* d; + if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) + return NULL; + d->ttl = now + ttl; + d->isbad = 1; + d->reason = NULL; + d->rrset_type = LDNS_RR_TYPE_DNSKEY; + d->rrset_data = NULL; + d->algo = NULL; + return k; +} + +struct ub_packed_rrset_key* +key_entry_get_rrset(struct key_entry_key* kkey, struct regional* region) +{ + struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; + struct ub_packed_rrset_key* rrk; + struct packed_rrset_data* rrd; + if(!d || !d->rrset_data) + return NULL; + rrk = regional_alloc(region, sizeof(*rrk)); + if(!rrk) + return NULL; + memset(rrk, 0, sizeof(*rrk)); + rrk->rk.dname = regional_alloc_init(region, kkey->name, kkey->namelen); + if(!rrk->rk.dname) + return NULL; + rrk->rk.dname_len = kkey->namelen; + rrk->rk.type = htons(d->rrset_type); + rrk->rk.rrset_class = htons(kkey->key_class); + rrk->entry.key = rrk; + rrd = regional_alloc_init(region, d->rrset_data, + packed_rrset_sizeof(d->rrset_data)); + if(!rrd) + return NULL; + rrk->entry.data = rrd; + packed_rrset_ptr_fixup(rrd); + return rrk; +} + +/** Get size of key in keyset */ +static size_t +dnskey_get_keysize(struct packed_rrset_data* data, size_t idx) +{ + unsigned char* pk; + unsigned int pklen = 0; + int algo; + if(data->rr_len[idx] < 2+5) + return 0; + algo = (int)data->rr_data[idx][2+3]; + pk = (unsigned char*)data->rr_data[idx]+2+4; + pklen = (unsigned)data->rr_len[idx]-2-4; + return sldns_rr_dnskey_key_size_raw(pk, pklen, algo); +} + +/** get dnskey flags from data */ +static uint16_t +kd_get_flags(struct packed_rrset_data* data, size_t idx) +{ + uint16_t f; + if(data->rr_len[idx] < 2+2) + return 0; + memmove(&f, data->rr_data[idx]+2, 2); + f = ntohs(f); + return f; +} + +size_t +key_entry_keysize(struct key_entry_key* kkey) +{ + struct packed_rrset_data* d; + /* compute size of smallest ZSK key in the rrset */ + size_t i; + size_t bits = 0; + if(!key_entry_isgood(kkey)) + return 0; + d = ((struct key_entry_data*)kkey->entry.data)->rrset_data; + for(i=0; i<d->count; i++) { + if(!(kd_get_flags(d, i) & DNSKEY_BIT_ZSK)) + continue; + if(i==0 || dnskey_get_keysize(d, i) < bits) + bits = dnskey_get_keysize(d, i); + } + return bits; +} |