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) 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(d->reason) { 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 } 203 if(d->algo) { 204 newd->algo = (uint8_t*)strdup((char*)d->algo); 205 if(!newd->algo) { 206 free(newd->rrset_data); 207 free(newd->reason); 208 free(newd); 209 free(newk->name); 210 free(newk); 211 return NULL; 212 } 213 } 214 newk->entry.data = newd; 215 } 216 return newk; 217 } 218 219 int 220 key_entry_isnull(struct key_entry_key* kkey) 221 { 222 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 223 return (!d->isbad && d->rrset_data == NULL); 224 } 225 226 int 227 key_entry_isgood(struct key_entry_key* kkey) 228 { 229 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 230 return (!d->isbad && d->rrset_data != NULL); 231 } 232 233 int 234 key_entry_isbad(struct key_entry_key* kkey) 235 { 236 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 237 return (int)(d->isbad); 238 } 239 240 void 241 key_entry_set_reason(struct key_entry_key* kkey, char* reason) 242 { 243 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 244 d->reason = reason; 245 } 246 247 void 248 key_entry_set_reason_bogus(struct key_entry_key* kkey, sldns_ede_code ede) 249 { 250 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 251 if (ede != LDNS_EDE_NONE) { /* reason_bogus init is LDNS_EDE_NONE already */ 252 d->reason_bogus = ede; 253 } 254 } 255 256 char* 257 key_entry_get_reason(struct key_entry_key* kkey) 258 { 259 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 260 return d->reason; 261 } 262 263 sldns_ede_code 264 key_entry_get_reason_bogus(struct key_entry_key* kkey) 265 { 266 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 267 return d->reason_bogus; 268 269 } 270 271 /** setup key entry in region */ 272 static int 273 key_entry_setup(struct regional* region, 274 uint8_t* name, size_t namelen, uint16_t dclass, 275 struct key_entry_key** k, struct key_entry_data** d) 276 { 277 *k = regional_alloc(region, sizeof(**k)); 278 if(!*k) 279 return 0; 280 memset(*k, 0, sizeof(**k)); 281 (*k)->entry.key = *k; 282 (*k)->name = regional_alloc_init(region, name, namelen); 283 if(!(*k)->name) 284 return 0; 285 (*k)->namelen = namelen; 286 (*k)->key_class = dclass; 287 *d = regional_alloc(region, sizeof(**d)); 288 if(!*d) 289 return 0; 290 (*k)->entry.data = *d; 291 return 1; 292 } 293 294 struct key_entry_key* 295 key_entry_create_null(struct regional* region, 296 uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl, 297 time_t now) 298 { 299 struct key_entry_key* k; 300 struct key_entry_data* d; 301 if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) 302 return NULL; 303 d->ttl = now + ttl; 304 d->isbad = 0; 305 d->reason = NULL; 306 d->reason_bogus = LDNS_EDE_NONE; 307 d->rrset_type = LDNS_RR_TYPE_DNSKEY; 308 d->rrset_data = NULL; 309 d->algo = NULL; 310 return k; 311 } 312 313 struct key_entry_key* 314 key_entry_create_rrset(struct regional* region, 315 uint8_t* name, size_t namelen, uint16_t dclass, 316 struct ub_packed_rrset_key* rrset, uint8_t* sigalg, time_t now) 317 { 318 struct key_entry_key* k; 319 struct key_entry_data* d; 320 struct packed_rrset_data* rd = (struct packed_rrset_data*) 321 rrset->entry.data; 322 if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) 323 return NULL; 324 d->ttl = rd->ttl + now; 325 d->isbad = 0; 326 d->reason = NULL; 327 d->reason_bogus = LDNS_EDE_NONE; 328 d->rrset_type = ntohs(rrset->rk.type); 329 d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region, 330 rd, packed_rrset_sizeof(rd)); 331 if(!d->rrset_data) 332 return NULL; 333 if(sigalg) { 334 d->algo = (uint8_t*)regional_strdup(region, (char*)sigalg); 335 if(!d->algo) 336 return NULL; 337 } else d->algo = NULL; 338 packed_rrset_ptr_fixup(d->rrset_data); 339 return k; 340 } 341 342 struct key_entry_key* 343 key_entry_create_bad(struct regional* region, 344 uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl, 345 time_t now) 346 { 347 struct key_entry_key* k; 348 struct key_entry_data* d; 349 if(!key_entry_setup(region, name, namelen, dclass, &k, &d)) 350 return NULL; 351 d->ttl = now + ttl; 352 d->isbad = 1; 353 d->reason = NULL; 354 d->reason_bogus = LDNS_EDE_NONE; 355 d->rrset_type = LDNS_RR_TYPE_DNSKEY; 356 d->rrset_data = NULL; 357 d->algo = NULL; 358 return k; 359 } 360 361 struct ub_packed_rrset_key* 362 key_entry_get_rrset(struct key_entry_key* kkey, struct regional* region) 363 { 364 struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data; 365 struct ub_packed_rrset_key* rrk; 366 struct packed_rrset_data* rrd; 367 if(!d || !d->rrset_data) 368 return NULL; 369 rrk = regional_alloc(region, sizeof(*rrk)); 370 if(!rrk) 371 return NULL; 372 memset(rrk, 0, sizeof(*rrk)); 373 rrk->rk.dname = regional_alloc_init(region, kkey->name, kkey->namelen); 374 if(!rrk->rk.dname) 375 return NULL; 376 rrk->rk.dname_len = kkey->namelen; 377 rrk->rk.type = htons(d->rrset_type); 378 rrk->rk.rrset_class = htons(kkey->key_class); 379 rrk->entry.key = rrk; 380 rrd = regional_alloc_init(region, d->rrset_data, 381 packed_rrset_sizeof(d->rrset_data)); 382 if(!rrd) 383 return NULL; 384 rrk->entry.data = rrd; 385 packed_rrset_ptr_fixup(rrd); 386 return rrk; 387 } 388 389 /** Get size of key in keyset */ 390 static size_t 391 dnskey_get_keysize(struct packed_rrset_data* data, size_t idx) 392 { 393 unsigned char* pk; 394 unsigned int pklen = 0; 395 int algo; 396 if(data->rr_len[idx] < 2+5) 397 return 0; 398 algo = (int)data->rr_data[idx][2+3]; 399 pk = (unsigned char*)data->rr_data[idx]+2+4; 400 pklen = (unsigned)data->rr_len[idx]-2-4; 401 return sldns_rr_dnskey_key_size_raw(pk, pklen, algo); 402 } 403 404 /** get dnskey flags from data */ 405 static uint16_t 406 kd_get_flags(struct packed_rrset_data* data, size_t idx) 407 { 408 uint16_t f; 409 if(data->rr_len[idx] < 2+2) 410 return 0; 411 memmove(&f, data->rr_data[idx]+2, 2); 412 f = ntohs(f); 413 return f; 414 } 415 416 size_t 417 key_entry_keysize(struct key_entry_key* kkey) 418 { 419 struct packed_rrset_data* d; 420 /* compute size of smallest ZSK key in the rrset */ 421 size_t i; 422 size_t bits = 0; 423 if(!key_entry_isgood(kkey)) 424 return 0; 425 d = ((struct key_entry_data*)kkey->entry.data)->rrset_data; 426 for(i=0; i<d->count; i++) { 427 if(!(kd_get_flags(d, i) & DNSKEY_BIT_ZSK)) 428 continue; 429 if(i==0 || dnskey_get_keysize(d, i) < bits) 430 bits = dnskey_get_keysize(d, i); 431 } 432 return bits; 433 } 434