1 1.1 christos /* 2 1.1 christos * validator/val_kentry.c - validator key entry definition. 3 1.1 christos * 4 1.1 christos * Copyright (c) 2007, NLnet Labs. All rights reserved. 5 1.1 christos * 6 1.1 christos * This software is open source. 7 1.1 christos * 8 1.1 christos * Redistribution and use in source and binary forms, with or without 9 1.1 christos * modification, are permitted provided that the following conditions 10 1.1 christos * are met: 11 1.1 christos * 12 1.1 christos * Redistributions of source code must retain the above copyright notice, 13 1.1 christos * this list of conditions and the following disclaimer. 14 1.1 christos * 15 1.1 christos * Redistributions in binary form must reproduce the above copyright notice, 16 1.1 christos * this list of conditions and the following disclaimer in the documentation 17 1.1 christos * and/or other materials provided with the distribution. 18 1.1 christos * 19 1.1 christos * Neither the name of the NLNET LABS nor the names of its contributors may 20 1.1 christos * be used to endorse or promote products derived from this software without 21 1.1 christos * specific prior written permission. 22 1.1 christos * 23 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 1.1 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 1.1 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 1.1 christos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 1.1 christos * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 1.1 christos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 1.1 christos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 1.1 christos * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 1.1 christos * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 1.1 christos * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 1.1 christos * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 1.1 christos */ 35 1.1 christos 36 1.1 christos /** 37 1.1 christos * \file 38 1.1 christos * 39 1.1 christos * This file contains functions for dealing with validator key entries. 40 1.1 christos */ 41 1.1 christos #include "config.h" 42 1.1 christos #include "validator/val_kentry.h" 43 1.1 christos #include "util/data/packed_rrset.h" 44 1.1 christos #include "util/data/dname.h" 45 1.1 christos #include "util/storage/lookup3.h" 46 1.1 christos #include "util/regional.h" 47 1.1 christos #include "util/net_help.h" 48 1.1 christos #include "sldns/rrdef.h" 49 1.1 christos #include "sldns/keyraw.h" 50 1.1 christos 51 1.1 christos size_t 52 1.1 christos key_entry_sizefunc(void* key, void* data) 53 1.1 christos { 54 1.1 christos struct key_entry_key* kk = (struct key_entry_key*)key; 55 1.1 christos struct key_entry_data* kd = (struct key_entry_data*)data; 56 1.1 christos size_t s = sizeof(*kk) + kk->namelen; 57 1.1 christos s += sizeof(*kd) + lock_get_mem(&kk->entry.lock); 58 1.1 christos if(kd->rrset_data) 59 1.1 christos s += packed_rrset_sizeof(kd->rrset_data); 60 1.1 christos if(kd->reason) 61 1.1 christos s += strlen(kd->reason)+1; 62 1.1 christos if(kd->algo) 63 1.1 christos s += strlen((char*)kd->algo)+1; 64 1.1 christos return s; 65 1.1 christos } 66 1.1 christos 67 1.1 christos int 68 1.1 christos key_entry_compfunc(void* k1, void* k2) 69 1.1 christos { 70 1.1 christos struct key_entry_key* n1 = (struct key_entry_key*)k1; 71 1.1 christos struct key_entry_key* n2 = (struct key_entry_key*)k2; 72 1.1 christos if(n1->key_class != n2->key_class) { 73 1.1 christos if(n1->key_class < n2->key_class) 74 1.1 christos return -1; 75 1.1 christos return 1; 76 1.1 christos } 77 1.1 christos return query_dname_compare(n1->name, n2->name); 78 1.1 christos } 79 1.1 christos 80 1.1 christos void 81 1.1 christos key_entry_delkeyfunc(void* key, void* ATTR_UNUSED(userarg)) 82 1.1 christos { 83 1.1 christos struct key_entry_key* kk = (struct key_entry_key*)key; 84 1.1 christos if(!key) 85 1.1 christos return; 86 1.1 christos lock_rw_destroy(&kk->entry.lock); 87 1.1 christos free(kk->name); 88 1.1 christos free(kk); 89 1.1 christos } 90 1.1 christos 91 1.1 christos void 92 1.1 christos key_entry_deldatafunc(void* data, void* ATTR_UNUSED(userarg)) 93 1.1 christos { 94 1.1 christos struct key_entry_data* kd = (struct key_entry_data*)data; 95 1.1 christos free(kd->reason); 96 1.1 christos free(kd->rrset_data); 97 1.1 christos free(kd->algo); 98 1.1 christos free(kd); 99 1.1 christos } 100 1.1 christos 101 1.1 christos void 102 1.1 christos key_entry_hash(struct key_entry_key* kk) 103 1.1 christos { 104 1.1 christos kk->entry.hash = 0x654; 105 1.1 christos kk->entry.hash = hashlittle(&kk->key_class, sizeof(kk->key_class), 106 1.1 christos kk->entry.hash); 107 1.1 christos kk->entry.hash = dname_query_hash(kk->name, kk->entry.hash); 108 1.1 christos } 109 1.1 christos 110 1.1 christos struct key_entry_key* 111 1.1 christos key_entry_copy_toregion(struct key_entry_key* kkey, struct regional* region) 112 1.1 christos { 113 1.1 christos struct key_entry_key* newk; 114 1.1 christos newk = regional_alloc_init(region, kkey, sizeof(*kkey)); 115 1.1 christos if(!newk) 116 1.1 christos return NULL; 117 1.1 christos newk->name = regional_alloc_init(region, kkey->name, kkey->namelen); 118 1.1 christos if(!newk->name) 119 1.1 christos return NULL; 120 1.1 christos newk->entry.key = newk; 121 1.1 christos if(newk->entry.data) { 122 1.1 christos /* copy data element */ 123 1.1 christos struct key_entry_data *d = (struct key_entry_data*) 124 1.1 christos kkey->entry.data; 125 1.1 christos struct key_entry_data *newd; 126 1.1 christos newd = regional_alloc_init(region, d, sizeof(*d)); 127 1.1 christos if(!newd) 128 1.1 christos return NULL; 129 1.1 christos /* copy rrset */ 130 1.1 christos if(d->rrset_data) { 131 1.1 christos newd->rrset_data = regional_alloc_init(region, 132 1.1 christos d->rrset_data, 133 1.1 christos packed_rrset_sizeof(d->rrset_data)); 134 1.1 christos if(!newd->rrset_data) 135 1.1 christos return NULL; 136 1.1 christos packed_rrset_ptr_fixup(newd->rrset_data); 137 1.1 christos } 138 1.1 christos if(d->reason) { 139 1.1 christos newd->reason = regional_strdup(region, d->reason); 140 1.1 christos if(!newd->reason) 141 1.1 christos return NULL; 142 1.1 christos } 143 1.1 christos if(d->algo) { 144 1.1 christos newd->algo = (uint8_t*)regional_strdup(region, 145 1.1 christos (char*)d->algo); 146 1.1 christos if(!newd->algo) 147 1.1 christos return NULL; 148 1.1 christos } 149 1.1 christos newk->entry.data = newd; 150 1.1 christos } 151 1.1 christos return newk; 152 1.1 christos } 153 1.1 christos 154 1.1 christos struct key_entry_key* 155 1.1.1.3 christos key_entry_copy(struct key_entry_key* kkey, int copy_reason) 156 1.1 christos { 157 1.1 christos struct key_entry_key* newk; 158 1.1 christos if(!kkey) 159 1.1 christos return NULL; 160 1.1 christos newk = memdup(kkey, sizeof(*kkey)); 161 1.1 christos if(!newk) 162 1.1 christos return NULL; 163 1.1 christos newk->name = memdup(kkey->name, kkey->namelen); 164 1.1 christos if(!newk->name) { 165 1.1 christos free(newk); 166 1.1 christos return NULL; 167 1.1 christos } 168 1.1 christos lock_rw_init(&newk->entry.lock); 169 1.1 christos newk->entry.key = newk; 170 1.1 christos if(newk->entry.data) { 171 1.1 christos /* copy data element */ 172 1.1 christos struct key_entry_data *d = (struct key_entry_data*) 173 1.1 christos kkey->entry.data; 174 1.1 christos struct key_entry_data *newd; 175 1.1 christos newd = memdup(d, sizeof(*d)); 176 1.1 christos if(!newd) { 177 1.1 christos free(newk->name); 178 1.1 christos free(newk); 179 1.1 christos return NULL; 180 1.1 christos } 181 1.1 christos /* copy rrset */ 182 1.1 christos if(d->rrset_data) { 183 1.1 christos newd->rrset_data = memdup(d->rrset_data, 184 1.1 christos packed_rrset_sizeof(d->rrset_data)); 185 1.1 christos if(!newd->rrset_data) { 186 1.1 christos free(newd); 187 1.1 christos free(newk->name); 188 1.1 christos free(newk); 189 1.1 christos return NULL; 190 1.1 christos } 191 1.1 christos packed_rrset_ptr_fixup(newd->rrset_data); 192 1.1 christos } 193 1.1.1.3 christos if(copy_reason && d->reason && *d->reason != 0) { 194 1.1 christos newd->reason = strdup(d->reason); 195 1.1 christos if(!newd->reason) { 196 1.1 christos free(newd->rrset_data); 197 1.1 christos free(newd); 198 1.1 christos free(newk->name); 199 1.1 christos free(newk); 200 1.1 christos return NULL; 201 1.1 christos } 202 1.1.1.3 christos } else { 203 1.1.1.3 christos newd->reason = NULL; 204 1.1 christos } 205 1.1 christos if(d->algo) { 206 1.1 christos newd->algo = (uint8_t*)strdup((char*)d->algo); 207 1.1 christos if(!newd->algo) { 208 1.1 christos free(newd->rrset_data); 209 1.1 christos free(newd->reason); 210 1.1 christos free(newd); 211 1.1 christos free(newk->name); 212 1.1 christos free(newk); 213 1.1 christos return NULL; 214 1.1 christos } 215 1.1 christos } 216 1.1 christos newk->entry.data = newd; 217 1.1 christos } 218 1.1 christos return newk; 219 1.1 christos } 220 1.1 christos 221 1.1 christos int 222 1.1 christos key_entry_isnull(struct key_entry_key* kkey) 223 1.1 christos { 224 1.1 christos struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 225 1.1 christos return (!d->isbad && d->rrset_data == NULL); 226 1.1 christos } 227 1.1 christos 228 1.1 christos int 229 1.1 christos key_entry_isgood(struct key_entry_key* kkey) 230 1.1 christos { 231 1.1 christos struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 232 1.1 christos return (!d->isbad && d->rrset_data != NULL); 233 1.1 christos } 234 1.1 christos 235 1.1 christos int 236 1.1 christos key_entry_isbad(struct key_entry_key* kkey) 237 1.1 christos { 238 1.1 christos struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 239 1.1 christos return (int)(d->isbad); 240 1.1 christos } 241 1.1 christos 242 1.1 christos char* 243 1.1 christos key_entry_get_reason(struct key_entry_key* kkey) 244 1.1 christos { 245 1.1 christos struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 246 1.1 christos return d->reason; 247 1.1 christos } 248 1.1 christos 249 1.1.1.2 christos sldns_ede_code 250 1.1.1.2 christos key_entry_get_reason_bogus(struct key_entry_key* kkey) 251 1.1.1.2 christos { 252 1.1.1.2 christos struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 253 1.1.1.2 christos return d->reason_bogus; 254 1.1.1.2 christos 255 1.1.1.2 christos } 256 1.1.1.2 christos 257 1.1 christos /** setup key entry in region */ 258 1.1 christos static int 259 1.1 christos key_entry_setup(struct regional* region, 260 1.1 christos uint8_t* name, size_t namelen, uint16_t dclass, 261 1.1 christos struct key_entry_key** k, struct key_entry_data** d) 262 1.1 christos { 263 1.1 christos *k = regional_alloc(region, sizeof(**k)); 264 1.1 christos if(!*k) 265 1.1 christos return 0; 266 1.1 christos memset(*k, 0, sizeof(**k)); 267 1.1 christos (*k)->entry.key = *k; 268 1.1 christos (*k)->name = regional_alloc_init(region, name, namelen); 269 1.1 christos if(!(*k)->name) 270 1.1 christos return 0; 271 1.1 christos (*k)->namelen = namelen; 272 1.1 christos (*k)->key_class = dclass; 273 1.1 christos *d = regional_alloc(region, sizeof(**d)); 274 1.1 christos if(!*d) 275 1.1 christos return 0; 276 1.1 christos (*k)->entry.data = *d; 277 1.1 christos return 1; 278 1.1 christos } 279 1.1 christos 280 1.1 christos struct key_entry_key* 281 1.1 christos key_entry_create_null(struct regional* region, 282 1.1 christos uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl, 283 1.1.1.3 christos sldns_ede_code reason_bogus, const char* reason, 284 1.1 christos time_t now) 285 1.1 christos { 286 1.1 christos struct key_entry_key* k; 287 1.1 christos struct key_entry_data* d; 288 1.1 christos if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) 289 1.1 christos return NULL; 290 1.1 christos d->ttl = now + ttl; 291 1.1 christos d->isbad = 0; 292 1.1.1.3 christos d->reason = (!reason || *reason == 0) 293 1.1.1.3 christos ?NULL :(char*)regional_strdup(region, reason); 294 1.1.1.3 christos /* On allocation error we don't store the reason string */ 295 1.1.1.3 christos d->reason_bogus = reason_bogus; 296 1.1 christos d->rrset_type = LDNS_RR_TYPE_DNSKEY; 297 1.1 christos d->rrset_data = NULL; 298 1.1 christos d->algo = NULL; 299 1.1 christos return k; 300 1.1 christos } 301 1.1 christos 302 1.1 christos struct key_entry_key* 303 1.1 christos key_entry_create_rrset(struct regional* region, 304 1.1 christos uint8_t* name, size_t namelen, uint16_t dclass, 305 1.1.1.3 christos struct ub_packed_rrset_key* rrset, uint8_t* sigalg, 306 1.1.1.3 christos sldns_ede_code reason_bogus, const char* reason, 307 1.1.1.3 christos time_t now) 308 1.1 christos { 309 1.1 christos struct key_entry_key* k; 310 1.1 christos struct key_entry_data* d; 311 1.1 christos struct packed_rrset_data* rd = (struct packed_rrset_data*) 312 1.1 christos rrset->entry.data; 313 1.1 christos if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) 314 1.1 christos return NULL; 315 1.1 christos d->ttl = rd->ttl + now; 316 1.1 christos d->isbad = 0; 317 1.1.1.3 christos d->reason = (!reason || *reason == 0) 318 1.1.1.3 christos ?NULL :(char*)regional_strdup(region, reason); 319 1.1.1.3 christos /* On allocation error we don't store the reason string */ 320 1.1.1.3 christos d->reason_bogus = reason_bogus; 321 1.1 christos d->rrset_type = ntohs(rrset->rk.type); 322 1.1 christos d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region, 323 1.1 christos rd, packed_rrset_sizeof(rd)); 324 1.1 christos if(!d->rrset_data) 325 1.1 christos return NULL; 326 1.1 christos if(sigalg) { 327 1.1 christos d->algo = (uint8_t*)regional_strdup(region, (char*)sigalg); 328 1.1 christos if(!d->algo) 329 1.1 christos return NULL; 330 1.1 christos } else d->algo = NULL; 331 1.1 christos packed_rrset_ptr_fixup(d->rrset_data); 332 1.1 christos return k; 333 1.1 christos } 334 1.1 christos 335 1.1 christos struct key_entry_key* 336 1.1 christos key_entry_create_bad(struct regional* region, 337 1.1.1.3 christos uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl, 338 1.1.1.3 christos sldns_ede_code reason_bogus, const char* reason, 339 1.1 christos time_t now) 340 1.1 christos { 341 1.1 christos struct key_entry_key* k; 342 1.1 christos struct key_entry_data* d; 343 1.1 christos if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) 344 1.1 christos return NULL; 345 1.1 christos d->ttl = now + ttl; 346 1.1 christos d->isbad = 1; 347 1.1.1.3 christos d->reason = (!reason || *reason == 0) 348 1.1.1.3 christos ?NULL :(char*)regional_strdup(region, reason); 349 1.1.1.3 christos /* On allocation error we don't store the reason string */ 350 1.1.1.3 christos d->reason_bogus = reason_bogus; 351 1.1 christos d->rrset_type = LDNS_RR_TYPE_DNSKEY; 352 1.1 christos d->rrset_data = NULL; 353 1.1 christos d->algo = NULL; 354 1.1 christos return k; 355 1.1 christos } 356 1.1 christos 357 1.1 christos struct ub_packed_rrset_key* 358 1.1 christos key_entry_get_rrset(struct key_entry_key* kkey, struct regional* region) 359 1.1 christos { 360 1.1 christos struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 361 1.1 christos struct ub_packed_rrset_key* rrk; 362 1.1 christos struct packed_rrset_data* rrd; 363 1.1 christos if(!d || !d->rrset_data) 364 1.1 christos return NULL; 365 1.1 christos rrk = regional_alloc(region, sizeof(*rrk)); 366 1.1 christos if(!rrk) 367 1.1 christos return NULL; 368 1.1 christos memset(rrk, 0, sizeof(*rrk)); 369 1.1 christos rrk->rk.dname = regional_alloc_init(region, kkey->name, kkey->namelen); 370 1.1 christos if(!rrk->rk.dname) 371 1.1 christos return NULL; 372 1.1 christos rrk->rk.dname_len = kkey->namelen; 373 1.1 christos rrk->rk.type = htons(d->rrset_type); 374 1.1 christos rrk->rk.rrset_class = htons(kkey->key_class); 375 1.1 christos rrk->entry.key = rrk; 376 1.1 christos rrd = regional_alloc_init(region, d->rrset_data, 377 1.1 christos packed_rrset_sizeof(d->rrset_data)); 378 1.1 christos if(!rrd) 379 1.1 christos return NULL; 380 1.1 christos rrk->entry.data = rrd; 381 1.1 christos packed_rrset_ptr_fixup(rrd); 382 1.1 christos return rrk; 383 1.1 christos } 384 1.1 christos 385 1.1 christos /** Get size of key in keyset */ 386 1.1 christos static size_t 387 1.1 christos dnskey_get_keysize(struct packed_rrset_data* data, size_t idx) 388 1.1 christos { 389 1.1 christos unsigned char* pk; 390 1.1 christos unsigned int pklen = 0; 391 1.1 christos int algo; 392 1.1 christos if(data->rr_len[idx] < 2+5) 393 1.1 christos return 0; 394 1.1 christos algo = (int)data->rr_data[idx][2+3]; 395 1.1 christos pk = (unsigned char*)data->rr_data[idx]+2+4; 396 1.1 christos pklen = (unsigned)data->rr_len[idx]-2-4; 397 1.1 christos return sldns_rr_dnskey_key_size_raw(pk, pklen, algo); 398 1.1 christos } 399 1.1 christos 400 1.1 christos /** get dnskey flags from data */ 401 1.1 christos static uint16_t 402 1.1 christos kd_get_flags(struct packed_rrset_data* data, size_t idx) 403 1.1 christos { 404 1.1 christos uint16_t f; 405 1.1 christos if(data->rr_len[idx] < 2+2) 406 1.1 christos return 0; 407 1.1 christos memmove(&f, data->rr_data[idx]+2, 2); 408 1.1 christos f = ntohs(f); 409 1.1 christos return f; 410 1.1 christos } 411 1.1 christos 412 1.1 christos size_t 413 1.1 christos key_entry_keysize(struct key_entry_key* kkey) 414 1.1 christos { 415 1.1 christos struct packed_rrset_data* d; 416 1.1 christos /* compute size of smallest ZSK key in the rrset */ 417 1.1 christos size_t i; 418 1.1 christos size_t bits = 0; 419 1.1 christos if(!key_entry_isgood(kkey)) 420 1.1 christos return 0; 421 1.1 christos d = ((struct key_entry_data*)kkey->entry.data)->rrset_data; 422 1.1 christos for(i=0; i<d->count; i++) { 423 1.1 christos if(!(kd_get_flags(d, i) & DNSKEY_BIT_ZSK)) 424 1.1 christos continue; 425 1.1 christos if(i==0 || dnskey_get_keysize(d, i) < bits) 426 1.1 christos bits = dnskey_get_keysize(d, i); 427 1.1 christos } 428 1.1 christos return bits; 429 1.1 christos } 430