summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty/Unbound/src/src/validator/val_kentry.c')
-rw-r--r--3rdParty/Unbound/src/src/validator/val_kentry.c412
1 files changed, 412 insertions, 0 deletions
diff --git a/3rdParty/Unbound/src/src/validator/val_kentry.c b/3rdParty/Unbound/src/src/validator/val_kentry.c
new file mode 100644
index 0000000..ddac140
--- /dev/null
+++ b/3rdParty/Unbound/src/src/validator/val_kentry.c
@@ -0,0 +1,412 @@
+/*
+ * 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 REGENTS 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 <ldns/ldns.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"
+
+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, uint32_t ttl,
+ uint32_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, uint32_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, uint32_t ttl,
+ uint32_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 ldns_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;
+}