1238106Sdes/* 2238106Sdes * validator/val_kentry.c - validator key entry definition. 3238106Sdes * 4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved. 5238106Sdes * 6238106Sdes * This software is open source. 7238106Sdes * 8238106Sdes * Redistribution and use in source and binary forms, with or without 9238106Sdes * modification, are permitted provided that the following conditions 10238106Sdes * are met: 11238106Sdes * 12238106Sdes * Redistributions of source code must retain the above copyright notice, 13238106Sdes * this list of conditions and the following disclaimer. 14238106Sdes * 15238106Sdes * Redistributions in binary form must reproduce the above copyright notice, 16238106Sdes * this list of conditions and the following disclaimer in the documentation 17238106Sdes * and/or other materials provided with the distribution. 18238106Sdes * 19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may 20238106Sdes * be used to endorse or promote products derived from this software without 21238106Sdes * specific prior written permission. 22238106Sdes * 23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24266114Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25266114Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26266114Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27266114Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28266114Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29266114Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30266114Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31266114Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32266114Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33266114Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34238106Sdes */ 35238106Sdes 36238106Sdes/** 37238106Sdes * \file 38238106Sdes * 39238106Sdes * This file contains functions for dealing with validator key entries. 40238106Sdes */ 41238106Sdes#include "config.h" 42238106Sdes#include "validator/val_kentry.h" 43238106Sdes#include "util/data/packed_rrset.h" 44238106Sdes#include "util/data/dname.h" 45238106Sdes#include "util/storage/lookup3.h" 46238106Sdes#include "util/regional.h" 47238106Sdes#include "util/net_help.h" 48287917Sdes#include "sldns/rrdef.h" 49287917Sdes#include "sldns/keyraw.h" 50238106Sdes 51238106Sdessize_t 52238106Sdeskey_entry_sizefunc(void* key, void* data) 53238106Sdes{ 54238106Sdes struct key_entry_key* kk = (struct key_entry_key*)key; 55238106Sdes struct key_entry_data* kd = (struct key_entry_data*)data; 56238106Sdes size_t s = sizeof(*kk) + kk->namelen; 57238106Sdes s += sizeof(*kd) + lock_get_mem(&kk->entry.lock); 58238106Sdes if(kd->rrset_data) 59238106Sdes s += packed_rrset_sizeof(kd->rrset_data); 60238106Sdes if(kd->reason) 61238106Sdes s += strlen(kd->reason)+1; 62238106Sdes if(kd->algo) 63238106Sdes s += strlen((char*)kd->algo)+1; 64238106Sdes return s; 65238106Sdes} 66238106Sdes 67238106Sdesint 68238106Sdeskey_entry_compfunc(void* k1, void* k2) 69238106Sdes{ 70238106Sdes struct key_entry_key* n1 = (struct key_entry_key*)k1; 71238106Sdes struct key_entry_key* n2 = (struct key_entry_key*)k2; 72238106Sdes if(n1->key_class != n2->key_class) { 73238106Sdes if(n1->key_class < n2->key_class) 74238106Sdes return -1; 75238106Sdes return 1; 76238106Sdes } 77238106Sdes return query_dname_compare(n1->name, n2->name); 78238106Sdes} 79238106Sdes 80238106Sdesvoid 81238106Sdeskey_entry_delkeyfunc(void* key, void* ATTR_UNUSED(userarg)) 82238106Sdes{ 83238106Sdes struct key_entry_key* kk = (struct key_entry_key*)key; 84238106Sdes if(!key) 85238106Sdes return; 86238106Sdes lock_rw_destroy(&kk->entry.lock); 87238106Sdes free(kk->name); 88238106Sdes free(kk); 89238106Sdes} 90238106Sdes 91238106Sdesvoid 92238106Sdeskey_entry_deldatafunc(void* data, void* ATTR_UNUSED(userarg)) 93238106Sdes{ 94238106Sdes struct key_entry_data* kd = (struct key_entry_data*)data; 95238106Sdes free(kd->reason); 96238106Sdes free(kd->rrset_data); 97238106Sdes free(kd->algo); 98238106Sdes free(kd); 99238106Sdes} 100238106Sdes 101238106Sdesvoid 102238106Sdeskey_entry_hash(struct key_entry_key* kk) 103238106Sdes{ 104238106Sdes kk->entry.hash = 0x654; 105238106Sdes kk->entry.hash = hashlittle(&kk->key_class, sizeof(kk->key_class), 106238106Sdes kk->entry.hash); 107238106Sdes kk->entry.hash = dname_query_hash(kk->name, kk->entry.hash); 108238106Sdes} 109238106Sdes 110238106Sdesstruct key_entry_key* 111238106Sdeskey_entry_copy_toregion(struct key_entry_key* kkey, struct regional* region) 112238106Sdes{ 113238106Sdes struct key_entry_key* newk; 114238106Sdes newk = regional_alloc_init(region, kkey, sizeof(*kkey)); 115238106Sdes if(!newk) 116238106Sdes return NULL; 117238106Sdes newk->name = regional_alloc_init(region, kkey->name, kkey->namelen); 118238106Sdes if(!newk->name) 119238106Sdes return NULL; 120238106Sdes newk->entry.key = newk; 121238106Sdes if(newk->entry.data) { 122238106Sdes /* copy data element */ 123238106Sdes struct key_entry_data *d = (struct key_entry_data*) 124238106Sdes kkey->entry.data; 125238106Sdes struct key_entry_data *newd; 126238106Sdes newd = regional_alloc_init(region, d, sizeof(*d)); 127238106Sdes if(!newd) 128238106Sdes return NULL; 129238106Sdes /* copy rrset */ 130238106Sdes if(d->rrset_data) { 131238106Sdes newd->rrset_data = regional_alloc_init(region, 132238106Sdes d->rrset_data, 133238106Sdes packed_rrset_sizeof(d->rrset_data)); 134238106Sdes if(!newd->rrset_data) 135238106Sdes return NULL; 136238106Sdes packed_rrset_ptr_fixup(newd->rrset_data); 137238106Sdes } 138238106Sdes if(d->reason) { 139238106Sdes newd->reason = regional_strdup(region, d->reason); 140238106Sdes if(!newd->reason) 141238106Sdes return NULL; 142238106Sdes } 143238106Sdes if(d->algo) { 144238106Sdes newd->algo = (uint8_t*)regional_strdup(region, 145238106Sdes (char*)d->algo); 146238106Sdes if(!newd->algo) 147238106Sdes return NULL; 148238106Sdes } 149238106Sdes newk->entry.data = newd; 150238106Sdes } 151238106Sdes return newk; 152238106Sdes} 153238106Sdes 154238106Sdesstruct key_entry_key* 155238106Sdeskey_entry_copy(struct key_entry_key* kkey) 156238106Sdes{ 157238106Sdes struct key_entry_key* newk; 158238106Sdes if(!kkey) 159238106Sdes return NULL; 160238106Sdes newk = memdup(kkey, sizeof(*kkey)); 161238106Sdes if(!newk) 162238106Sdes return NULL; 163238106Sdes newk->name = memdup(kkey->name, kkey->namelen); 164238106Sdes if(!newk->name) { 165238106Sdes free(newk); 166238106Sdes return NULL; 167238106Sdes } 168238106Sdes lock_rw_init(&newk->entry.lock); 169238106Sdes newk->entry.key = newk; 170238106Sdes if(newk->entry.data) { 171238106Sdes /* copy data element */ 172238106Sdes struct key_entry_data *d = (struct key_entry_data*) 173238106Sdes kkey->entry.data; 174238106Sdes struct key_entry_data *newd; 175238106Sdes newd = memdup(d, sizeof(*d)); 176238106Sdes if(!newd) { 177238106Sdes free(newk->name); 178238106Sdes free(newk); 179238106Sdes return NULL; 180238106Sdes } 181238106Sdes /* copy rrset */ 182238106Sdes if(d->rrset_data) { 183238106Sdes newd->rrset_data = memdup(d->rrset_data, 184238106Sdes packed_rrset_sizeof(d->rrset_data)); 185238106Sdes if(!newd->rrset_data) { 186238106Sdes free(newd); 187238106Sdes free(newk->name); 188238106Sdes free(newk); 189238106Sdes return NULL; 190238106Sdes } 191238106Sdes packed_rrset_ptr_fixup(newd->rrset_data); 192238106Sdes } 193238106Sdes if(d->reason) { 194238106Sdes newd->reason = strdup(d->reason); 195238106Sdes if(!newd->reason) { 196238106Sdes free(newd->rrset_data); 197238106Sdes free(newd); 198238106Sdes free(newk->name); 199238106Sdes free(newk); 200238106Sdes return NULL; 201238106Sdes } 202238106Sdes } 203238106Sdes if(d->algo) { 204238106Sdes newd->algo = (uint8_t*)strdup((char*)d->algo); 205238106Sdes if(!newd->algo) { 206238106Sdes free(newd->rrset_data); 207238106Sdes free(newd->reason); 208238106Sdes free(newd); 209238106Sdes free(newk->name); 210238106Sdes free(newk); 211238106Sdes return NULL; 212238106Sdes } 213238106Sdes } 214238106Sdes newk->entry.data = newd; 215238106Sdes } 216238106Sdes return newk; 217238106Sdes} 218238106Sdes 219238106Sdesint 220238106Sdeskey_entry_isnull(struct key_entry_key* kkey) 221238106Sdes{ 222238106Sdes struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 223238106Sdes return (!d->isbad && d->rrset_data == NULL); 224238106Sdes} 225238106Sdes 226238106Sdesint 227238106Sdeskey_entry_isgood(struct key_entry_key* kkey) 228238106Sdes{ 229238106Sdes struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 230238106Sdes return (!d->isbad && d->rrset_data != NULL); 231238106Sdes} 232238106Sdes 233238106Sdesint 234238106Sdeskey_entry_isbad(struct key_entry_key* kkey) 235238106Sdes{ 236238106Sdes struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 237238106Sdes return (int)(d->isbad); 238238106Sdes} 239238106Sdes 240238106Sdesvoid 241238106Sdeskey_entry_set_reason(struct key_entry_key* kkey, char* reason) 242238106Sdes{ 243238106Sdes struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 244238106Sdes d->reason = reason; 245238106Sdes} 246238106Sdes 247238106Sdeschar* 248238106Sdeskey_entry_get_reason(struct key_entry_key* kkey) 249238106Sdes{ 250238106Sdes struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 251238106Sdes return d->reason; 252238106Sdes} 253238106Sdes 254238106Sdes/** setup key entry in region */ 255238106Sdesstatic int 256238106Sdeskey_entry_setup(struct regional* region, 257238106Sdes uint8_t* name, size_t namelen, uint16_t dclass, 258238106Sdes struct key_entry_key** k, struct key_entry_data** d) 259238106Sdes{ 260238106Sdes *k = regional_alloc(region, sizeof(**k)); 261238106Sdes if(!*k) 262238106Sdes return 0; 263238106Sdes memset(*k, 0, sizeof(**k)); 264238106Sdes (*k)->entry.key = *k; 265238106Sdes (*k)->name = regional_alloc_init(region, name, namelen); 266238106Sdes if(!(*k)->name) 267238106Sdes return 0; 268238106Sdes (*k)->namelen = namelen; 269238106Sdes (*k)->key_class = dclass; 270238106Sdes *d = regional_alloc(region, sizeof(**d)); 271238106Sdes if(!*d) 272238106Sdes return 0; 273238106Sdes (*k)->entry.data = *d; 274238106Sdes return 1; 275238106Sdes} 276238106Sdes 277238106Sdesstruct key_entry_key* 278238106Sdeskey_entry_create_null(struct regional* region, 279266114Sdes uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl, 280266114Sdes time_t now) 281238106Sdes{ 282238106Sdes struct key_entry_key* k; 283238106Sdes struct key_entry_data* d; 284238106Sdes if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) 285238106Sdes return NULL; 286238106Sdes d->ttl = now + ttl; 287238106Sdes d->isbad = 0; 288238106Sdes d->reason = NULL; 289238106Sdes d->rrset_type = LDNS_RR_TYPE_DNSKEY; 290238106Sdes d->rrset_data = NULL; 291238106Sdes d->algo = NULL; 292238106Sdes return k; 293238106Sdes} 294238106Sdes 295238106Sdesstruct key_entry_key* 296238106Sdeskey_entry_create_rrset(struct regional* region, 297238106Sdes uint8_t* name, size_t namelen, uint16_t dclass, 298266114Sdes struct ub_packed_rrset_key* rrset, uint8_t* sigalg, time_t now) 299238106Sdes{ 300238106Sdes struct key_entry_key* k; 301238106Sdes struct key_entry_data* d; 302238106Sdes struct packed_rrset_data* rd = (struct packed_rrset_data*) 303238106Sdes rrset->entry.data; 304238106Sdes if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) 305238106Sdes return NULL; 306238106Sdes d->ttl = rd->ttl + now; 307238106Sdes d->isbad = 0; 308238106Sdes d->reason = NULL; 309238106Sdes d->rrset_type = ntohs(rrset->rk.type); 310238106Sdes d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region, 311238106Sdes rd, packed_rrset_sizeof(rd)); 312238106Sdes if(!d->rrset_data) 313238106Sdes return NULL; 314238106Sdes if(sigalg) { 315238106Sdes d->algo = (uint8_t*)regional_strdup(region, (char*)sigalg); 316238106Sdes if(!d->algo) 317238106Sdes return NULL; 318238106Sdes } else d->algo = NULL; 319238106Sdes packed_rrset_ptr_fixup(d->rrset_data); 320238106Sdes return k; 321238106Sdes} 322238106Sdes 323238106Sdesstruct key_entry_key* 324238106Sdeskey_entry_create_bad(struct regional* region, 325266114Sdes uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl, 326266114Sdes time_t now) 327238106Sdes{ 328238106Sdes struct key_entry_key* k; 329238106Sdes struct key_entry_data* d; 330238106Sdes if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) 331238106Sdes return NULL; 332238106Sdes d->ttl = now + ttl; 333238106Sdes d->isbad = 1; 334238106Sdes d->reason = NULL; 335238106Sdes d->rrset_type = LDNS_RR_TYPE_DNSKEY; 336238106Sdes d->rrset_data = NULL; 337238106Sdes d->algo = NULL; 338238106Sdes return k; 339238106Sdes} 340238106Sdes 341238106Sdesstruct ub_packed_rrset_key* 342238106Sdeskey_entry_get_rrset(struct key_entry_key* kkey, struct regional* region) 343238106Sdes{ 344238106Sdes struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 345238106Sdes struct ub_packed_rrset_key* rrk; 346238106Sdes struct packed_rrset_data* rrd; 347238106Sdes if(!d || !d->rrset_data) 348238106Sdes return NULL; 349238106Sdes rrk = regional_alloc(region, sizeof(*rrk)); 350238106Sdes if(!rrk) 351238106Sdes return NULL; 352238106Sdes memset(rrk, 0, sizeof(*rrk)); 353238106Sdes rrk->rk.dname = regional_alloc_init(region, kkey->name, kkey->namelen); 354238106Sdes if(!rrk->rk.dname) 355238106Sdes return NULL; 356238106Sdes rrk->rk.dname_len = kkey->namelen; 357238106Sdes rrk->rk.type = htons(d->rrset_type); 358238106Sdes rrk->rk.rrset_class = htons(kkey->key_class); 359238106Sdes rrk->entry.key = rrk; 360238106Sdes rrd = regional_alloc_init(region, d->rrset_data, 361238106Sdes packed_rrset_sizeof(d->rrset_data)); 362238106Sdes if(!rrd) 363238106Sdes return NULL; 364238106Sdes rrk->entry.data = rrd; 365238106Sdes packed_rrset_ptr_fixup(rrd); 366238106Sdes return rrk; 367238106Sdes} 368238106Sdes 369238106Sdes/** Get size of key in keyset */ 370238106Sdesstatic size_t 371238106Sdesdnskey_get_keysize(struct packed_rrset_data* data, size_t idx) 372238106Sdes{ 373238106Sdes unsigned char* pk; 374238106Sdes unsigned int pklen = 0; 375238106Sdes int algo; 376238106Sdes if(data->rr_len[idx] < 2+5) 377238106Sdes return 0; 378238106Sdes algo = (int)data->rr_data[idx][2+3]; 379238106Sdes pk = (unsigned char*)data->rr_data[idx]+2+4; 380238106Sdes pklen = (unsigned)data->rr_len[idx]-2-4; 381266114Sdes return sldns_rr_dnskey_key_size_raw(pk, pklen, algo); 382238106Sdes} 383238106Sdes 384238106Sdes/** get dnskey flags from data */ 385238106Sdesstatic uint16_t 386238106Sdeskd_get_flags(struct packed_rrset_data* data, size_t idx) 387238106Sdes{ 388238106Sdes uint16_t f; 389238106Sdes if(data->rr_len[idx] < 2+2) 390238106Sdes return 0; 391238106Sdes memmove(&f, data->rr_data[idx]+2, 2); 392238106Sdes f = ntohs(f); 393238106Sdes return f; 394238106Sdes} 395238106Sdes 396238106Sdessize_t 397238106Sdeskey_entry_keysize(struct key_entry_key* kkey) 398238106Sdes{ 399238106Sdes struct packed_rrset_data* d; 400238106Sdes /* compute size of smallest ZSK key in the rrset */ 401238106Sdes size_t i; 402238106Sdes size_t bits = 0; 403238106Sdes if(!key_entry_isgood(kkey)) 404238106Sdes return 0; 405238106Sdes d = ((struct key_entry_data*)kkey->entry.data)->rrset_data; 406238106Sdes for(i=0; i<d->count; i++) { 407238106Sdes if(!(kd_get_flags(d, i) & DNSKEY_BIT_ZSK)) 408238106Sdes continue; 409238106Sdes if(i==0 || dnskey_get_keysize(d, i) < bits) 410238106Sdes bits = dnskey_get_keysize(d, i); 411238106Sdes } 412238106Sdes return bits; 413238106Sdes} 414