1 1.1 christos /* 2 1.1 christos * validator/val_anchor.c - validator trust anchor storage. 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 storage for the trust anchors for the validator. 40 1.1 christos */ 41 1.1 christos #include "config.h" 42 1.1 christos #include <ctype.h> 43 1.1 christos #include "validator/val_anchor.h" 44 1.1 christos #include "validator/val_sigcrypt.h" 45 1.1 christos #include "validator/autotrust.h" 46 1.1 christos #include "util/data/packed_rrset.h" 47 1.1 christos #include "util/data/dname.h" 48 1.1 christos #include "util/log.h" 49 1.1 christos #include "util/net_help.h" 50 1.1 christos #include "util/config_file.h" 51 1.1 christos #include "util/as112.h" 52 1.1 christos #include "sldns/sbuffer.h" 53 1.1 christos #include "sldns/rrdef.h" 54 1.1 christos #include "sldns/str2wire.h" 55 1.1 christos #ifdef HAVE_GLOB_H 56 1.1 christos #include <glob.h> 57 1.1 christos #endif 58 1.1 christos 59 1.1 christos int 60 1.1 christos anchor_cmp(const void* k1, const void* k2) 61 1.1 christos { 62 1.1 christos int m; 63 1.1 christos struct trust_anchor* n1 = (struct trust_anchor*)k1; 64 1.1 christos struct trust_anchor* n2 = (struct trust_anchor*)k2; 65 1.1 christos /* no need to ntohs(class) because sort order is irrelevant */ 66 1.1 christos if(n1->dclass != n2->dclass) { 67 1.1 christos if(n1->dclass < n2->dclass) 68 1.1 christos return -1; 69 1.1 christos return 1; 70 1.1 christos } 71 1.1 christos return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs, 72 1.1 christos &m); 73 1.1 christos } 74 1.1 christos 75 1.1 christos struct val_anchors* 76 1.1 christos anchors_create(void) 77 1.1 christos { 78 1.1 christos struct val_anchors* a = (struct val_anchors*)calloc(1, sizeof(*a)); 79 1.1 christos if(!a) 80 1.1 christos return NULL; 81 1.1 christos a->tree = rbtree_create(anchor_cmp); 82 1.1 christos if(!a->tree) { 83 1.1 christos anchors_delete(a); 84 1.1 christos return NULL; 85 1.1 christos } 86 1.1 christos a->autr = autr_global_create(); 87 1.1 christos if(!a->autr) { 88 1.1 christos anchors_delete(a); 89 1.1 christos return NULL; 90 1.1 christos } 91 1.1 christos lock_basic_init(&a->lock); 92 1.1 christos lock_protect(&a->lock, a, sizeof(*a)); 93 1.1 christos lock_protect(&a->lock, a->autr, sizeof(*a->autr)); 94 1.1 christos return a; 95 1.1 christos } 96 1.1 christos 97 1.1 christos /** delete assembled rrset */ 98 1.1 christos static void 99 1.1 christos assembled_rrset_delete(struct ub_packed_rrset_key* pkey) 100 1.1 christos { 101 1.1 christos if(!pkey) return; 102 1.1 christos if(pkey->entry.data) { 103 1.1 christos struct packed_rrset_data* pd = (struct packed_rrset_data*) 104 1.1 christos pkey->entry.data; 105 1.1 christos free(pd->rr_data); 106 1.1 christos free(pd->rr_ttl); 107 1.1 christos free(pd->rr_len); 108 1.1 christos free(pd); 109 1.1 christos } 110 1.1 christos free(pkey->rk.dname); 111 1.1 christos free(pkey); 112 1.1 christos } 113 1.1 christos 114 1.1 christos /** destroy locks in tree and delete autotrust anchors */ 115 1.1 christos static void 116 1.1.1.2 christos anchors_delfunc(rbnode_type* elem, void* ATTR_UNUSED(arg)) 117 1.1 christos { 118 1.1 christos struct trust_anchor* ta = (struct trust_anchor*)elem; 119 1.1 christos if(!ta) return; 120 1.1 christos if(ta->autr) { 121 1.1 christos autr_point_delete(ta); 122 1.1 christos } else { 123 1.1 christos struct ta_key* p, *np; 124 1.1 christos lock_basic_destroy(&ta->lock); 125 1.1 christos free(ta->name); 126 1.1 christos p = ta->keylist; 127 1.1 christos while(p) { 128 1.1 christos np = p->next; 129 1.1 christos free(p->data); 130 1.1 christos free(p); 131 1.1 christos p = np; 132 1.1 christos } 133 1.1 christos assembled_rrset_delete(ta->ds_rrset); 134 1.1 christos assembled_rrset_delete(ta->dnskey_rrset); 135 1.1 christos free(ta); 136 1.1 christos } 137 1.1 christos } 138 1.1 christos 139 1.1 christos void 140 1.1 christos anchors_delete(struct val_anchors* anchors) 141 1.1 christos { 142 1.1 christos if(!anchors) 143 1.1 christos return; 144 1.1 christos lock_unprotect(&anchors->lock, anchors->autr); 145 1.1 christos lock_unprotect(&anchors->lock, anchors); 146 1.1 christos lock_basic_destroy(&anchors->lock); 147 1.1 christos if(anchors->tree) 148 1.1 christos traverse_postorder(anchors->tree, anchors_delfunc, NULL); 149 1.1 christos free(anchors->tree); 150 1.1 christos autr_global_delete(anchors->autr); 151 1.1 christos free(anchors); 152 1.1 christos } 153 1.1 christos 154 1.1 christos void 155 1.1 christos anchors_init_parents_locked(struct val_anchors* anchors) 156 1.1 christos { 157 1.1 christos struct trust_anchor* node, *prev = NULL, *p; 158 1.1 christos int m; 159 1.1 christos /* nobody else can grab locks because we hold the main lock. 160 1.1 christos * Thus the previous items, after unlocked, are not deleted */ 161 1.1 christos RBTREE_FOR(node, struct trust_anchor*, anchors->tree) { 162 1.1 christos lock_basic_lock(&node->lock); 163 1.1 christos node->parent = NULL; 164 1.1 christos if(!prev || prev->dclass != node->dclass) { 165 1.1 christos prev = node; 166 1.1 christos lock_basic_unlock(&node->lock); 167 1.1 christos continue; 168 1.1 christos } 169 1.1 christos (void)dname_lab_cmp(prev->name, prev->namelabs, node->name, 170 1.1 christos node->namelabs, &m); /* we know prev is smaller */ 171 1.1 christos /* sort order like: . com. bla.com. zwb.com. net. */ 172 1.1 christos /* find the previous, or parent-parent-parent */ 173 1.1 christos for(p = prev; p; p = p->parent) 174 1.1 christos /* looking for name with few labels, a parent */ 175 1.1 christos if(p->namelabs <= m) { 176 1.1 christos /* ==: since prev matched m, this is closest*/ 177 1.1 christos /* <: prev matches more, but is not a parent, 178 1.1 christos * this one is a (grand)parent */ 179 1.1 christos node->parent = p; 180 1.1 christos break; 181 1.1 christos } 182 1.1 christos lock_basic_unlock(&node->lock); 183 1.1 christos prev = node; 184 1.1 christos } 185 1.1 christos } 186 1.1 christos 187 1.1 christos /** initialise parent pointers in the tree */ 188 1.1 christos static void 189 1.1 christos init_parents(struct val_anchors* anchors) 190 1.1 christos { 191 1.1 christos lock_basic_lock(&anchors->lock); 192 1.1 christos anchors_init_parents_locked(anchors); 193 1.1 christos lock_basic_unlock(&anchors->lock); 194 1.1 christos } 195 1.1 christos 196 1.1 christos struct trust_anchor* 197 1.1 christos anchor_find(struct val_anchors* anchors, uint8_t* name, int namelabs, 198 1.1 christos size_t namelen, uint16_t dclass) 199 1.1 christos { 200 1.1 christos struct trust_anchor key; 201 1.1.1.2 christos rbnode_type* n; 202 1.1 christos if(!name) return NULL; 203 1.1 christos key.node.key = &key; 204 1.1 christos key.name = name; 205 1.1 christos key.namelabs = namelabs; 206 1.1 christos key.namelen = namelen; 207 1.1 christos key.dclass = dclass; 208 1.1 christos lock_basic_lock(&anchors->lock); 209 1.1 christos n = rbtree_search(anchors->tree, &key); 210 1.1 christos if(n) { 211 1.1 christos lock_basic_lock(&((struct trust_anchor*)n->key)->lock); 212 1.1 christos } 213 1.1 christos lock_basic_unlock(&anchors->lock); 214 1.1 christos if(!n) 215 1.1 christos return NULL; 216 1.1 christos return (struct trust_anchor*)n->key; 217 1.1 christos } 218 1.1 christos 219 1.1 christos /** create new trust anchor object */ 220 1.1 christos static struct trust_anchor* 221 1.1 christos anchor_new_ta(struct val_anchors* anchors, uint8_t* name, int namelabs, 222 1.1 christos size_t namelen, uint16_t dclass, int lockit) 223 1.1 christos { 224 1.1 christos #ifdef UNBOUND_DEBUG 225 1.1.1.2 christos rbnode_type* r; 226 1.1 christos #endif 227 1.1 christos struct trust_anchor* ta = (struct trust_anchor*)malloc( 228 1.1 christos sizeof(struct trust_anchor)); 229 1.1 christos if(!ta) 230 1.1 christos return NULL; 231 1.1 christos memset(ta, 0, sizeof(*ta)); 232 1.1 christos ta->node.key = ta; 233 1.1 christos ta->name = memdup(name, namelen); 234 1.1 christos if(!ta->name) { 235 1.1 christos free(ta); 236 1.1 christos return NULL; 237 1.1 christos } 238 1.1 christos ta->namelabs = namelabs; 239 1.1 christos ta->namelen = namelen; 240 1.1 christos ta->dclass = dclass; 241 1.1 christos lock_basic_init(&ta->lock); 242 1.1 christos if(lockit) { 243 1.1 christos lock_basic_lock(&anchors->lock); 244 1.1 christos } 245 1.1 christos #ifdef UNBOUND_DEBUG 246 1.1 christos r = 247 1.1 christos #else 248 1.1 christos (void) 249 1.1 christos #endif 250 1.1 christos rbtree_insert(anchors->tree, &ta->node); 251 1.1 christos if(lockit) { 252 1.1 christos lock_basic_unlock(&anchors->lock); 253 1.1 christos } 254 1.1 christos log_assert(r != NULL); 255 1.1 christos return ta; 256 1.1 christos } 257 1.1 christos 258 1.1 christos /** find trustanchor key by exact data match */ 259 1.1 christos static struct ta_key* 260 1.1 christos anchor_find_key(struct trust_anchor* ta, uint8_t* rdata, size_t rdata_len, 261 1.1 christos uint16_t type) 262 1.1 christos { 263 1.1 christos struct ta_key* k; 264 1.1 christos for(k = ta->keylist; k; k = k->next) { 265 1.1 christos if(k->type == type && k->len == rdata_len && 266 1.1 christos memcmp(k->data, rdata, rdata_len) == 0) 267 1.1 christos return k; 268 1.1 christos } 269 1.1 christos return NULL; 270 1.1 christos } 271 1.1 christos 272 1.1 christos /** create new trustanchor key */ 273 1.1 christos static struct ta_key* 274 1.1 christos anchor_new_ta_key(uint8_t* rdata, size_t rdata_len, uint16_t type) 275 1.1 christos { 276 1.1 christos struct ta_key* k = (struct ta_key*)malloc(sizeof(*k)); 277 1.1 christos if(!k) 278 1.1 christos return NULL; 279 1.1 christos memset(k, 0, sizeof(*k)); 280 1.1 christos k->data = memdup(rdata, rdata_len); 281 1.1 christos if(!k->data) { 282 1.1 christos free(k); 283 1.1 christos return NULL; 284 1.1 christos } 285 1.1 christos k->len = rdata_len; 286 1.1 christos k->type = type; 287 1.1 christos return k; 288 1.1 christos } 289 1.1 christos 290 1.1 christos /** 291 1.1 christos * This routine adds a new RR to a trust anchor. The trust anchor may not 292 1.1 christos * exist yet, and is created if not. The RR can be DS or DNSKEY. 293 1.1 christos * This routine will also remove duplicates; storing them only once. 294 1.1 christos * @param anchors: anchor storage. 295 1.1 christos * @param name: name of trust anchor (wireformat) 296 1.1 christos * @param type: type or RR 297 1.1 christos * @param dclass: class of RR 298 1.1 christos * @param rdata: rdata wireformat, starting with rdlength. 299 1.1 christos * If NULL, nothing is stored, but an entry is created. 300 1.1 christos * @param rdata_len: length of rdata including rdlength. 301 1.1 christos * @return: NULL on error, else the trust anchor. 302 1.1 christos */ 303 1.1 christos static struct trust_anchor* 304 1.1 christos anchor_store_new_key(struct val_anchors* anchors, uint8_t* name, uint16_t type, 305 1.1 christos uint16_t dclass, uint8_t* rdata, size_t rdata_len) 306 1.1 christos { 307 1.1 christos struct ta_key* k; 308 1.1 christos struct trust_anchor* ta; 309 1.1 christos int namelabs; 310 1.1 christos size_t namelen; 311 1.1 christos namelabs = dname_count_size_labels(name, &namelen); 312 1.1 christos if(type != LDNS_RR_TYPE_DS && type != LDNS_RR_TYPE_DNSKEY) { 313 1.1 christos log_err("Bad type for trust anchor"); 314 1.1 christos return 0; 315 1.1 christos } 316 1.1 christos /* lookup or create trustanchor */ 317 1.1 christos ta = anchor_find(anchors, name, namelabs, namelen, dclass); 318 1.1 christos if(!ta) { 319 1.1 christos ta = anchor_new_ta(anchors, name, namelabs, namelen, dclass, 1); 320 1.1 christos if(!ta) 321 1.1 christos return NULL; 322 1.1 christos lock_basic_lock(&ta->lock); 323 1.1 christos } 324 1.1 christos if(!rdata) { 325 1.1 christos lock_basic_unlock(&ta->lock); 326 1.1 christos return ta; 327 1.1 christos } 328 1.1 christos /* look for duplicates */ 329 1.1 christos if(anchor_find_key(ta, rdata, rdata_len, type)) { 330 1.1 christos lock_basic_unlock(&ta->lock); 331 1.1 christos return ta; 332 1.1 christos } 333 1.1 christos k = anchor_new_ta_key(rdata, rdata_len, type); 334 1.1 christos if(!k) { 335 1.1 christos lock_basic_unlock(&ta->lock); 336 1.1 christos return NULL; 337 1.1 christos } 338 1.1 christos /* add new key */ 339 1.1 christos if(type == LDNS_RR_TYPE_DS) 340 1.1 christos ta->numDS++; 341 1.1 christos else ta->numDNSKEY++; 342 1.1 christos k->next = ta->keylist; 343 1.1 christos ta->keylist = k; 344 1.1 christos lock_basic_unlock(&ta->lock); 345 1.1 christos return ta; 346 1.1 christos } 347 1.1 christos 348 1.1 christos /** 349 1.1 christos * Add new RR. It converts ldns RR to wire format. 350 1.1 christos * @param anchors: anchor storage. 351 1.1 christos * @param rr: the wirerr. 352 1.1 christos * @param rl: length of rr. 353 1.1 christos * @param dl: length of dname. 354 1.1 christos * @return NULL on error, else the trust anchor. 355 1.1 christos */ 356 1.1 christos static struct trust_anchor* 357 1.1 christos anchor_store_new_rr(struct val_anchors* anchors, uint8_t* rr, size_t rl, 358 1.1 christos size_t dl) 359 1.1 christos { 360 1.1 christos struct trust_anchor* ta; 361 1.1 christos if(!(ta=anchor_store_new_key(anchors, rr, 362 1.1 christos sldns_wirerr_get_type(rr, rl, dl), 363 1.1 christos sldns_wirerr_get_class(rr, rl, dl), 364 1.1 christos sldns_wirerr_get_rdatawl(rr, rl, dl), 365 1.1 christos sldns_wirerr_get_rdatalen(rr, rl, dl)+2))) { 366 1.1 christos return NULL; 367 1.1 christos } 368 1.1 christos log_nametypeclass(VERB_QUERY, "adding trusted key", 369 1.1 christos rr, sldns_wirerr_get_type(rr, rl, dl), 370 1.1 christos sldns_wirerr_get_class(rr, rl, dl)); 371 1.1 christos return ta; 372 1.1 christos } 373 1.1 christos 374 1.1 christos /** 375 1.1 christos * Insert insecure anchor 376 1.1 christos * @param anchors: anchor storage. 377 1.1 christos * @param str: the domain name. 378 1.1 christos * @return NULL on error, Else last trust anchor point 379 1.1 christos */ 380 1.1 christos static struct trust_anchor* 381 1.1 christos anchor_insert_insecure(struct val_anchors* anchors, const char* str) 382 1.1 christos { 383 1.1 christos struct trust_anchor* ta; 384 1.1 christos size_t dname_len = 0; 385 1.1 christos uint8_t* nm = sldns_str2wire_dname(str, &dname_len); 386 1.1 christos if(!nm) { 387 1.1 christos log_err("parse error in domain name '%s'", str); 388 1.1 christos return NULL; 389 1.1 christos } 390 1.1 christos ta = anchor_store_new_key(anchors, nm, LDNS_RR_TYPE_DS, 391 1.1 christos LDNS_RR_CLASS_IN, NULL, 0); 392 1.1 christos free(nm); 393 1.1 christos return ta; 394 1.1 christos } 395 1.1 christos 396 1.1 christos struct trust_anchor* 397 1.1 christos anchor_store_str(struct val_anchors* anchors, sldns_buffer* buffer, 398 1.1 christos const char* str) 399 1.1 christos { 400 1.1 christos struct trust_anchor* ta; 401 1.1 christos uint8_t* rr = sldns_buffer_begin(buffer); 402 1.1 christos size_t len = sldns_buffer_capacity(buffer), dname_len = 0; 403 1.1 christos int status = sldns_str2wire_rr_buf(str, rr, &len, &dname_len, 404 1.1 christos 0, NULL, 0, NULL, 0); 405 1.1 christos if(status != 0) { 406 1.1 christos log_err("error parsing trust anchor %s: at %d: %s", 407 1.1 christos str, LDNS_WIREPARSE_OFFSET(status), 408 1.1 christos sldns_get_errorstr_parse(status)); 409 1.1 christos return NULL; 410 1.1 christos } 411 1.1 christos if(!(ta=anchor_store_new_rr(anchors, rr, len, dname_len))) { 412 1.1 christos log_err("out of memory"); 413 1.1 christos return NULL; 414 1.1 christos } 415 1.1 christos return ta; 416 1.1 christos } 417 1.1 christos 418 1.1 christos /** 419 1.1 christos * Read a file with trust anchors 420 1.1 christos * @param anchors: anchor storage. 421 1.1 christos * @param buffer: parsing buffer. 422 1.1 christos * @param fname: string. 423 1.1 christos * @param onlyone: only one trust anchor allowed in file. 424 1.1 christos * @return NULL on error. Else last trust-anchor point. 425 1.1 christos */ 426 1.1 christos static struct trust_anchor* 427 1.1 christos anchor_read_file(struct val_anchors* anchors, sldns_buffer* buffer, 428 1.1 christos const char* fname, int onlyone) 429 1.1 christos { 430 1.1 christos struct trust_anchor* ta = NULL, *tanew; 431 1.1 christos struct sldns_file_parse_state pst; 432 1.1 christos int status; 433 1.1 christos size_t len, dname_len; 434 1.1 christos uint8_t* rr = sldns_buffer_begin(buffer); 435 1.1 christos int ok = 1; 436 1.1 christos FILE* in = fopen(fname, "r"); 437 1.1 christos if(!in) { 438 1.1 christos log_err("error opening file %s: %s", fname, strerror(errno)); 439 1.1 christos return 0; 440 1.1 christos } 441 1.1 christos memset(&pst, 0, sizeof(pst)); 442 1.1 christos pst.default_ttl = 3600; 443 1.1 christos pst.lineno = 1; 444 1.1 christos while(!feof(in)) { 445 1.1 christos len = sldns_buffer_capacity(buffer); 446 1.1 christos dname_len = 0; 447 1.1 christos status = sldns_fp2wire_rr_buf(in, rr, &len, &dname_len, &pst); 448 1.1 christos if(len == 0) /* empty, $TTL, $ORIGIN */ 449 1.1 christos continue; 450 1.1 christos if(status != 0) { 451 1.1 christos log_err("parse error in %s:%d:%d : %s", fname, 452 1.1 christos pst.lineno, LDNS_WIREPARSE_OFFSET(status), 453 1.1 christos sldns_get_errorstr_parse(status)); 454 1.1 christos ok = 0; 455 1.1 christos break; 456 1.1 christos } 457 1.1 christos if(sldns_wirerr_get_type(rr, len, dname_len) != 458 1.1 christos LDNS_RR_TYPE_DS && sldns_wirerr_get_type(rr, len, 459 1.1 christos dname_len) != LDNS_RR_TYPE_DNSKEY) { 460 1.1 christos continue; 461 1.1 christos } 462 1.1 christos if(!(tanew=anchor_store_new_rr(anchors, rr, len, dname_len))) { 463 1.1 christos log_err("mem error at %s line %d", fname, pst.lineno); 464 1.1 christos ok = 0; 465 1.1 christos break; 466 1.1 christos } 467 1.1 christos if(onlyone && ta && ta != tanew) { 468 1.1 christos log_err("error at %s line %d: no multiple anchor " 469 1.1 christos "domains allowed (you can have multiple " 470 1.1 christos "keys, but they must have the same name).", 471 1.1 christos fname, pst.lineno); 472 1.1 christos ok = 0; 473 1.1 christos break; 474 1.1 christos } 475 1.1 christos ta = tanew; 476 1.1 christos } 477 1.1 christos fclose(in); 478 1.1 christos if(!ok) return NULL; 479 1.1 christos /* empty file is OK when multiple anchors are allowed */ 480 1.1 christos if(!onlyone && !ta) return (struct trust_anchor*)1; 481 1.1 christos return ta; 482 1.1 christos } 483 1.1 christos 484 1.1 christos /** skip file to end of line */ 485 1.1 christos static void 486 1.1.1.8 christos skip_to_eol(FILE* in, int *c) 487 1.1 christos { 488 1.1.1.8 christos while((*c = getc(in)) != EOF ) { 489 1.1.1.8 christos if(*c == '\n') 490 1.1 christos return; 491 1.1 christos } 492 1.1 christos } 493 1.1 christos 494 1.1 christos /** true for special characters in bind configs */ 495 1.1 christos static int 496 1.1 christos is_bind_special(int c) 497 1.1 christos { 498 1.1 christos switch(c) { 499 1.1 christos case '{': 500 1.1 christos case '}': 501 1.1 christos case '"': 502 1.1 christos case ';': 503 1.1 christos return 1; 504 1.1 christos } 505 1.1 christos return 0; 506 1.1 christos } 507 1.1 christos 508 1.1 christos /** 509 1.1 christos * Read a keyword skipping bind comments; spaces, specials, restkeywords. 510 1.1 christos * The file is split into the following tokens: 511 1.1 christos * * special characters, on their own, rdlen=1, { } doublequote ; 512 1.1 christos * * whitespace becomes a single ' ' or tab. Newlines become spaces. 513 1.1 christos * * other words ('keywords') 514 1.1 christos * * comments are skipped if desired 515 1.1 christos * / / C++ style comment to end of line 516 1.1 christos * # to end of line 517 1.1 christos * / * C style comment * / 518 1.1 christos * @param in: file to read from. 519 1.1 christos * @param buf: buffer, what is read is stored after current buffer position. 520 1.1 christos * Space is left in the buffer to write a terminating 0. 521 1.1 christos * @param line: line number is increased per line, for error reports. 522 1.1 christos * @param comments: if 0, comments are not possible and become text. 523 1.1 christos * if 1, comments are skipped entirely. 524 1.1 christos * In BIND files, this is when reading quoted strings, for example 525 1.1 christos * " base 64 text with / / in there " 526 1.1 christos * @return the number of character written to the buffer. 527 1.1 christos * 0 on end of file. 528 1.1 christos */ 529 1.1 christos static int 530 1.1 christos readkeyword_bindfile(FILE* in, sldns_buffer* buf, int* line, int comments) 531 1.1 christos { 532 1.1 christos int c; 533 1.1 christos int numdone = 0; 534 1.1 christos while((c = getc(in)) != EOF ) { 535 1.1 christos if(comments && c == '#') { /* # blabla */ 536 1.1.1.8 christos skip_to_eol(in, &c); 537 1.1.1.8 christos if(c == EOF) return 0; 538 1.1 christos (*line)++; 539 1.1 christos continue; 540 1.1 christos } else if(comments && c=='/' && numdone>0 && /* /_/ bla*/ 541 1.1 christos sldns_buffer_read_u8_at(buf, 542 1.1 christos sldns_buffer_position(buf)-1) == '/') { 543 1.1 christos sldns_buffer_skip(buf, -1); 544 1.1 christos numdone--; 545 1.1.1.8 christos skip_to_eol(in, &c); 546 1.1.1.8 christos if(c == EOF) return 0; 547 1.1 christos (*line)++; 548 1.1 christos continue; 549 1.1 christos } else if(comments && c=='*' && numdone>0 && /* /_* bla *_/ */ 550 1.1 christos sldns_buffer_read_u8_at(buf, 551 1.1 christos sldns_buffer_position(buf)-1) == '/') { 552 1.1 christos sldns_buffer_skip(buf, -1); 553 1.1 christos numdone--; 554 1.1 christos /* skip to end of comment */ 555 1.1 christos while(c != EOF && (c=getc(in)) != EOF ) { 556 1.1 christos if(c == '*') { 557 1.1 christos if((c=getc(in)) == '/') 558 1.1 christos break; 559 1.1 christos } 560 1.1 christos if(c == '\n') 561 1.1 christos (*line)++; 562 1.1 christos } 563 1.1.1.8 christos if(c == EOF) return 0; 564 1.1 christos continue; 565 1.1 christos } 566 1.1 christos /* not a comment, complete the keyword */ 567 1.1 christos if(numdone > 0) { 568 1.1 christos /* check same type */ 569 1.1 christos if(isspace((unsigned char)c)) { 570 1.1 christos ungetc(c, in); 571 1.1 christos return numdone; 572 1.1 christos } 573 1.1 christos if(is_bind_special(c)) { 574 1.1 christos ungetc(c, in); 575 1.1 christos return numdone; 576 1.1 christos } 577 1.1 christos } 578 1.1 christos if(c == '\n') { 579 1.1 christos c = ' '; 580 1.1 christos (*line)++; 581 1.1 christos } 582 1.1 christos /* space for 1 char + 0 string terminator */ 583 1.1 christos if(sldns_buffer_remaining(buf) < 2) { 584 1.1 christos fatal_exit("trusted-keys, %d, string too long", *line); 585 1.1 christos } 586 1.1 christos sldns_buffer_write_u8(buf, (uint8_t)c); 587 1.1 christos numdone++; 588 1.1 christos if(isspace((unsigned char)c)) { 589 1.1 christos /* collate whitespace into ' ' */ 590 1.1 christos while((c = getc(in)) != EOF ) { 591 1.1 christos if(c == '\n') 592 1.1 christos (*line)++; 593 1.1 christos if(!isspace((unsigned char)c)) { 594 1.1 christos ungetc(c, in); 595 1.1 christos break; 596 1.1 christos } 597 1.1 christos } 598 1.1.1.8 christos if(c == EOF) return 0; 599 1.1 christos return numdone; 600 1.1 christos } 601 1.1 christos if(is_bind_special(c)) 602 1.1 christos return numdone; 603 1.1 christos } 604 1.1 christos return numdone; 605 1.1 christos } 606 1.1 christos 607 1.1 christos /** skip through file to { or ; */ 608 1.1 christos static int 609 1.1 christos skip_to_special(FILE* in, sldns_buffer* buf, int* line, int spec) 610 1.1 christos { 611 1.1 christos int rdlen; 612 1.1 christos sldns_buffer_clear(buf); 613 1.1 christos while((rdlen=readkeyword_bindfile(in, buf, line, 1))) { 614 1.1 christos if(rdlen == 1 && isspace((unsigned char)*sldns_buffer_begin(buf))) { 615 1.1 christos sldns_buffer_clear(buf); 616 1.1 christos continue; 617 1.1 christos } 618 1.1 christos if(rdlen != 1 || *sldns_buffer_begin(buf) != (uint8_t)spec) { 619 1.1 christos sldns_buffer_write_u8(buf, 0); 620 1.1 christos log_err("trusted-keys, line %d, expected %c", 621 1.1 christos *line, spec); 622 1.1 christos return 0; 623 1.1 christos } 624 1.1 christos return 1; 625 1.1 christos } 626 1.1 christos log_err("trusted-keys, line %d, expected %c got EOF", *line, spec); 627 1.1 christos return 0; 628 1.1 christos } 629 1.1 christos 630 1.1 christos /** 631 1.1 christos * read contents of trusted-keys{ ... ; clauses and insert keys into storage. 632 1.1 christos * @param anchors: where to store keys 633 1.1 christos * @param buf: buffer to use 634 1.1 christos * @param line: line number in file 635 1.1 christos * @param in: file to read from. 636 1.1 christos * @return 0 on error. 637 1.1 christos */ 638 1.1 christos static int 639 1.1 christos process_bind_contents(struct val_anchors* anchors, sldns_buffer* buf, 640 1.1 christos int* line, FILE* in) 641 1.1 christos { 642 1.1 christos /* loop over contents, collate strings before ; */ 643 1.1 christos /* contents is (numbered): 0 1 2 3 4 5 6 7 8 */ 644 1.1 christos /* name. 257 3 5 base64 base64 */ 645 1.1 christos /* quoted value: 0 "111" 0 0 0 0 0 0 0 */ 646 1.1 christos /* comments value: 1 "000" 1 1 1 "0 0 0 0" 1 */ 647 1.1 christos int contnum = 0; 648 1.1 christos int quoted = 0; 649 1.1 christos int comments = 1; 650 1.1 christos int rdlen; 651 1.1 christos char* str = 0; 652 1.1 christos sldns_buffer_clear(buf); 653 1.1 christos while((rdlen=readkeyword_bindfile(in, buf, line, comments))) { 654 1.1 christos if(rdlen == 1 && sldns_buffer_position(buf) == 1 655 1.1 christos && isspace((unsigned char)*sldns_buffer_begin(buf))) { 656 1.1 christos /* starting whitespace is removed */ 657 1.1 christos sldns_buffer_clear(buf); 658 1.1 christos continue; 659 1.1 christos } else if(rdlen == 1 && sldns_buffer_current(buf)[-1] == '"') { 660 1.1 christos /* remove " from the string */ 661 1.1 christos if(contnum == 0) { 662 1.1 christos quoted = 1; 663 1.1 christos comments = 0; 664 1.1 christos } 665 1.1 christos sldns_buffer_skip(buf, -1); 666 1.1 christos if(contnum > 0 && quoted) { 667 1.1 christos if(sldns_buffer_remaining(buf) < 8+1) { 668 1.1 christos log_err("line %d, too long", *line); 669 1.1 christos return 0; 670 1.1 christos } 671 1.1 christos sldns_buffer_write(buf, " DNSKEY ", 8); 672 1.1 christos quoted = 0; 673 1.1 christos comments = 1; 674 1.1 christos } else if(contnum > 0) 675 1.1 christos comments = !comments; 676 1.1 christos continue; 677 1.1 christos } else if(rdlen == 1 && sldns_buffer_current(buf)[-1] == ';') { 678 1.1 christos 679 1.1 christos if(contnum < 5) { 680 1.1 christos sldns_buffer_write_u8(buf, 0); 681 1.1 christos log_err("line %d, bad key", *line); 682 1.1 christos return 0; 683 1.1 christos } 684 1.1 christos sldns_buffer_skip(buf, -1); 685 1.1 christos sldns_buffer_write_u8(buf, 0); 686 1.1 christos str = strdup((char*)sldns_buffer_begin(buf)); 687 1.1 christos if(!str) { 688 1.1 christos log_err("line %d, allocation failure", *line); 689 1.1 christos return 0; 690 1.1 christos } 691 1.1 christos if(!anchor_store_str(anchors, buf, str)) { 692 1.1 christos log_err("line %d, bad key", *line); 693 1.1 christos free(str); 694 1.1 christos return 0; 695 1.1 christos } 696 1.1 christos free(str); 697 1.1 christos sldns_buffer_clear(buf); 698 1.1 christos contnum = 0; 699 1.1 christos quoted = 0; 700 1.1 christos comments = 1; 701 1.1 christos continue; 702 1.1 christos } else if(rdlen == 1 && sldns_buffer_current(buf)[-1] == '}') { 703 1.1 christos if(contnum > 0) { 704 1.1 christos sldns_buffer_write_u8(buf, 0); 705 1.1 christos log_err("line %d, bad key before }", *line); 706 1.1 christos return 0; 707 1.1 christos } 708 1.1 christos return 1; 709 1.1 christos } else if(rdlen == 1 && 710 1.1 christos isspace((unsigned char)sldns_buffer_current(buf)[-1])) { 711 1.1 christos /* leave whitespace here */ 712 1.1 christos } else { 713 1.1 christos /* not space or whatnot, so actual content */ 714 1.1 christos contnum ++; 715 1.1 christos if(contnum == 1 && !quoted) { 716 1.1 christos if(sldns_buffer_remaining(buf) < 8+1) { 717 1.1 christos log_err("line %d, too long", *line); 718 1.1 christos return 0; 719 1.1 christos } 720 1.1 christos sldns_buffer_write(buf, " DNSKEY ", 8); 721 1.1 christos } 722 1.1 christos } 723 1.1 christos } 724 1.1 christos 725 1.1 christos log_err("line %d, EOF before }", *line); 726 1.1 christos return 0; 727 1.1 christos } 728 1.1 christos 729 1.1 christos /** 730 1.1 christos * Read a BIND9 like file with trust anchors in named.conf format. 731 1.1 christos * @param anchors: anchor storage. 732 1.1 christos * @param buffer: parsing buffer. 733 1.1 christos * @param fname: string. 734 1.1 christos * @return false on error. 735 1.1 christos */ 736 1.1 christos static int 737 1.1 christos anchor_read_bind_file(struct val_anchors* anchors, sldns_buffer* buffer, 738 1.1 christos const char* fname) 739 1.1 christos { 740 1.1 christos int line_nr = 1; 741 1.1 christos FILE* in = fopen(fname, "r"); 742 1.1 christos int rdlen = 0; 743 1.1 christos if(!in) { 744 1.1 christos log_err("error opening file %s: %s", fname, strerror(errno)); 745 1.1 christos return 0; 746 1.1 christos } 747 1.1 christos verbose(VERB_QUERY, "reading in bind-compat-mode: '%s'", fname); 748 1.1 christos /* scan for trusted-keys keyword, ignore everything else */ 749 1.1 christos sldns_buffer_clear(buffer); 750 1.1 christos while((rdlen=readkeyword_bindfile(in, buffer, &line_nr, 1)) != 0) { 751 1.1 christos if(rdlen != 12 || strncmp((char*)sldns_buffer_begin(buffer), 752 1.1 christos "trusted-keys", 12) != 0) { 753 1.1 christos sldns_buffer_clear(buffer); 754 1.1 christos /* ignore everything but trusted-keys */ 755 1.1 christos continue; 756 1.1 christos } 757 1.1 christos if(!skip_to_special(in, buffer, &line_nr, '{')) { 758 1.1 christos log_err("error in trusted key: \"%s\"", fname); 759 1.1 christos fclose(in); 760 1.1 christos return 0; 761 1.1 christos } 762 1.1 christos /* process contents */ 763 1.1 christos if(!process_bind_contents(anchors, buffer, &line_nr, in)) { 764 1.1 christos log_err("error in trusted key: \"%s\"", fname); 765 1.1 christos fclose(in); 766 1.1 christos return 0; 767 1.1 christos } 768 1.1 christos if(!skip_to_special(in, buffer, &line_nr, ';')) { 769 1.1 christos log_err("error in trusted key: \"%s\"", fname); 770 1.1 christos fclose(in); 771 1.1 christos return 0; 772 1.1 christos } 773 1.1 christos sldns_buffer_clear(buffer); 774 1.1 christos } 775 1.1 christos fclose(in); 776 1.1 christos return 1; 777 1.1 christos } 778 1.1 christos 779 1.1 christos /** 780 1.1 christos * Read a BIND9 like files with trust anchors in named.conf format. 781 1.1 christos * Performs wildcard processing of name. 782 1.1 christos * @param anchors: anchor storage. 783 1.1 christos * @param buffer: parsing buffer. 784 1.1 christos * @param pat: pattern string. (can be wildcarded) 785 1.1 christos * @return false on error. 786 1.1 christos */ 787 1.1 christos static int 788 1.1 christos anchor_read_bind_file_wild(struct val_anchors* anchors, sldns_buffer* buffer, 789 1.1 christos const char* pat) 790 1.1 christos { 791 1.1 christos #ifdef HAVE_GLOB 792 1.1 christos glob_t g; 793 1.1 christos size_t i; 794 1.1 christos int r, flags; 795 1.1 christos if(!strchr(pat, '*') && !strchr(pat, '?') && !strchr(pat, '[') && 796 1.1 christos !strchr(pat, '{') && !strchr(pat, '~')) { 797 1.1 christos return anchor_read_bind_file(anchors, buffer, pat); 798 1.1 christos } 799 1.1 christos verbose(VERB_QUERY, "wildcard found, processing %s", pat); 800 1.1 christos flags = 0 801 1.1 christos #ifdef GLOB_ERR 802 1.1 christos | GLOB_ERR 803 1.1 christos #endif 804 1.1 christos #ifdef GLOB_NOSORT 805 1.1 christos | GLOB_NOSORT 806 1.1 christos #endif 807 1.1 christos #ifdef GLOB_BRACE 808 1.1 christos | GLOB_BRACE 809 1.1 christos #endif 810 1.1 christos #ifdef GLOB_TILDE 811 1.1 christos | GLOB_TILDE 812 1.1 christos #endif 813 1.1 christos ; 814 1.1 christos memset(&g, 0, sizeof(g)); 815 1.1 christos r = glob(pat, flags, NULL, &g); 816 1.1 christos if(r) { 817 1.1 christos /* some error */ 818 1.1 christos if(r == GLOB_NOMATCH) { 819 1.1 christos verbose(VERB_QUERY, "trusted-keys-file: " 820 1.1 christos "no matches for %s", pat); 821 1.1 christos return 1; 822 1.1 christos } else if(r == GLOB_NOSPACE) { 823 1.1 christos log_err("wildcard trusted-keys-file %s: " 824 1.1 christos "pattern out of memory", pat); 825 1.1 christos } else if(r == GLOB_ABORTED) { 826 1.1 christos log_err("wildcard trusted-keys-file %s: expansion " 827 1.1 christos "aborted (%s)", pat, strerror(errno)); 828 1.1 christos } else { 829 1.1 christos log_err("wildcard trusted-keys-file %s: expansion " 830 1.1 christos "failed (%s)", pat, strerror(errno)); 831 1.1 christos } 832 1.1 christos /* ignore globs that yield no files */ 833 1.1 christos return 1; 834 1.1 christos } 835 1.1 christos /* process files found, if any */ 836 1.1 christos for(i=0; i<(size_t)g.gl_pathc; i++) { 837 1.1 christos if(!anchor_read_bind_file(anchors, buffer, g.gl_pathv[i])) { 838 1.1 christos log_err("error reading wildcard " 839 1.1 christos "trusted-keys-file: %s", g.gl_pathv[i]); 840 1.1 christos globfree(&g); 841 1.1 christos return 0; 842 1.1 christos } 843 1.1 christos } 844 1.1 christos globfree(&g); 845 1.1 christos return 1; 846 1.1 christos #else /* not HAVE_GLOB */ 847 1.1 christos return anchor_read_bind_file(anchors, buffer, pat); 848 1.1 christos #endif /* HAVE_GLOB */ 849 1.1 christos } 850 1.1 christos 851 1.1 christos /** 852 1.1 christos * Assemble an rrset structure for the type 853 1.1 christos * @param ta: trust anchor. 854 1.1 christos * @param num: number of items to fetch from list. 855 1.1 christos * @param type: fetch only items of this type. 856 1.1 christos * @return rrset or NULL on error. 857 1.1 christos */ 858 1.1 christos static struct ub_packed_rrset_key* 859 1.1 christos assemble_it(struct trust_anchor* ta, size_t num, uint16_t type) 860 1.1 christos { 861 1.1 christos struct ub_packed_rrset_key* pkey = (struct ub_packed_rrset_key*) 862 1.1 christos malloc(sizeof(*pkey)); 863 1.1 christos struct packed_rrset_data* pd; 864 1.1 christos struct ta_key* tk; 865 1.1 christos size_t i; 866 1.1 christos if(!pkey) 867 1.1 christos return NULL; 868 1.1 christos memset(pkey, 0, sizeof(*pkey)); 869 1.1 christos pkey->rk.dname = memdup(ta->name, ta->namelen); 870 1.1 christos if(!pkey->rk.dname) { 871 1.1 christos free(pkey); 872 1.1 christos return NULL; 873 1.1 christos } 874 1.1 christos 875 1.1 christos pkey->rk.dname_len = ta->namelen; 876 1.1 christos pkey->rk.type = htons(type); 877 1.1 christos pkey->rk.rrset_class = htons(ta->dclass); 878 1.1 christos /* The rrset is build in an uncompressed way. This means it 879 1.1 christos * cannot be copied in the normal way. */ 880 1.1 christos pd = (struct packed_rrset_data*)malloc(sizeof(*pd)); 881 1.1 christos if(!pd) { 882 1.1 christos free(pkey->rk.dname); 883 1.1 christos free(pkey); 884 1.1 christos return NULL; 885 1.1 christos } 886 1.1 christos memset(pd, 0, sizeof(*pd)); 887 1.1 christos pd->count = num; 888 1.1 christos pd->trust = rrset_trust_ultimate; 889 1.1 christos pd->rr_len = (size_t*)reallocarray(NULL, num, sizeof(size_t)); 890 1.1 christos if(!pd->rr_len) { 891 1.1 christos free(pd); 892 1.1 christos free(pkey->rk.dname); 893 1.1 christos free(pkey); 894 1.1 christos return NULL; 895 1.1 christos } 896 1.1 christos pd->rr_ttl = (time_t*)reallocarray(NULL, num, sizeof(time_t)); 897 1.1 christos if(!pd->rr_ttl) { 898 1.1 christos free(pd->rr_len); 899 1.1 christos free(pd); 900 1.1 christos free(pkey->rk.dname); 901 1.1 christos free(pkey); 902 1.1 christos return NULL; 903 1.1 christos } 904 1.1 christos pd->rr_data = (uint8_t**)reallocarray(NULL, num, sizeof(uint8_t*)); 905 1.1 christos if(!pd->rr_data) { 906 1.1 christos free(pd->rr_ttl); 907 1.1 christos free(pd->rr_len); 908 1.1 christos free(pd); 909 1.1 christos free(pkey->rk.dname); 910 1.1 christos free(pkey); 911 1.1 christos return NULL; 912 1.1 christos } 913 1.1 christos /* fill in rrs */ 914 1.1 christos i=0; 915 1.1 christos for(tk = ta->keylist; tk; tk = tk->next) { 916 1.1 christos if(tk->type != type) 917 1.1 christos continue; 918 1.1 christos pd->rr_len[i] = tk->len; 919 1.1 christos /* reuse data ptr to allocation in talist */ 920 1.1 christos pd->rr_data[i] = tk->data; 921 1.1 christos pd->rr_ttl[i] = 0; 922 1.1 christos i++; 923 1.1 christos } 924 1.1 christos pkey->entry.data = (void*)pd; 925 1.1 christos return pkey; 926 1.1 christos } 927 1.1 christos 928 1.1 christos /** 929 1.1 christos * Assemble structures for the trust DS and DNSKEY rrsets. 930 1.1 christos * @param ta: trust anchor 931 1.1 christos * @return: false on error. 932 1.1 christos */ 933 1.1 christos static int 934 1.1 christos anchors_assemble(struct trust_anchor* ta) 935 1.1 christos { 936 1.1 christos if(ta->numDS > 0) { 937 1.1 christos ta->ds_rrset = assemble_it(ta, ta->numDS, LDNS_RR_TYPE_DS); 938 1.1 christos if(!ta->ds_rrset) 939 1.1 christos return 0; 940 1.1 christos } 941 1.1 christos if(ta->numDNSKEY > 0) { 942 1.1 christos ta->dnskey_rrset = assemble_it(ta, ta->numDNSKEY, 943 1.1 christos LDNS_RR_TYPE_DNSKEY); 944 1.1 christos if(!ta->dnskey_rrset) 945 1.1 christos return 0; 946 1.1 christos } 947 1.1 christos return 1; 948 1.1 christos } 949 1.1 christos 950 1.1 christos /** 951 1.1 christos * Check DS algos for support, warn if not. 952 1.1 christos * @param ta: trust anchor 953 1.1 christos * @return number of DS anchors with unsupported algorithms. 954 1.1 christos */ 955 1.1 christos static size_t 956 1.1 christos anchors_ds_unsupported(struct trust_anchor* ta) 957 1.1 christos { 958 1.1 christos size_t i, num = 0; 959 1.1 christos for(i=0; i<ta->numDS; i++) { 960 1.1 christos if(!ds_digest_algo_is_supported(ta->ds_rrset, i) || 961 1.1 christos !ds_key_algo_is_supported(ta->ds_rrset, i)) 962 1.1 christos num++; 963 1.1 christos } 964 1.1 christos return num; 965 1.1 christos } 966 1.1 christos 967 1.1 christos /** 968 1.1 christos * Check DNSKEY algos for support, warn if not. 969 1.1 christos * @param ta: trust anchor 970 1.1 christos * @return number of DNSKEY anchors with unsupported algorithms. 971 1.1 christos */ 972 1.1 christos static size_t 973 1.1 christos anchors_dnskey_unsupported(struct trust_anchor* ta) 974 1.1 christos { 975 1.1 christos size_t i, num = 0; 976 1.1 christos for(i=0; i<ta->numDNSKEY; i++) { 977 1.1.1.6 christos if(!dnskey_algo_is_supported(ta->dnskey_rrset, i) || 978 1.1.1.6 christos !dnskey_size_is_supported(ta->dnskey_rrset, i)) 979 1.1 christos num++; 980 1.1 christos } 981 1.1 christos return num; 982 1.1 christos } 983 1.1 christos 984 1.1 christos /** 985 1.1 christos * Assemble the rrsets in the anchors, ready for use by validator. 986 1.1 christos * @param anchors: trust anchor storage. 987 1.1 christos * @return: false on error. 988 1.1 christos */ 989 1.1 christos static int 990 1.1 christos anchors_assemble_rrsets(struct val_anchors* anchors) 991 1.1 christos { 992 1.1 christos struct trust_anchor* ta; 993 1.1 christos struct trust_anchor* next; 994 1.1 christos size_t nods, nokey; 995 1.1 christos lock_basic_lock(&anchors->lock); 996 1.1 christos ta=(struct trust_anchor*)rbtree_first(anchors->tree); 997 1.1.1.2 christos while((rbnode_type*)ta != RBTREE_NULL) { 998 1.1 christos next = (struct trust_anchor*)rbtree_next(&ta->node); 999 1.1 christos lock_basic_lock(&ta->lock); 1000 1.1 christos if(ta->autr || (ta->numDS == 0 && ta->numDNSKEY == 0)) { 1001 1.1 christos lock_basic_unlock(&ta->lock); 1002 1.1 christos ta = next; /* skip */ 1003 1.1 christos continue; 1004 1.1 christos } 1005 1.1 christos if(!anchors_assemble(ta)) { 1006 1.1 christos log_err("out of memory"); 1007 1.1 christos lock_basic_unlock(&ta->lock); 1008 1.1 christos lock_basic_unlock(&anchors->lock); 1009 1.1 christos return 0; 1010 1.1 christos } 1011 1.1 christos nods = anchors_ds_unsupported(ta); 1012 1.1 christos nokey = anchors_dnskey_unsupported(ta); 1013 1.1 christos if(nods) { 1014 1.1.1.4 christos log_nametypeclass(NO_VERBOSE, "warning: unsupported " 1015 1.1 christos "algorithm for trust anchor", 1016 1.1 christos ta->name, LDNS_RR_TYPE_DS, ta->dclass); 1017 1.1 christos } 1018 1.1 christos if(nokey) { 1019 1.1.1.4 christos log_nametypeclass(NO_VERBOSE, "warning: unsupported " 1020 1.1 christos "algorithm for trust anchor", 1021 1.1 christos ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass); 1022 1.1 christos } 1023 1.1 christos if(nods == ta->numDS && nokey == ta->numDNSKEY) { 1024 1.1.1.8 christos char b[LDNS_MAX_DOMAINLEN]; 1025 1.1 christos dname_str(ta->name, b); 1026 1.1 christos log_warn("trust anchor %s has no supported algorithms," 1027 1.1 christos " the anchor is ignored (check if you need to" 1028 1.1 christos " upgrade unbound and " 1029 1.1 christos #ifdef HAVE_LIBRESSL 1030 1.1 christos "libressl" 1031 1.1 christos #else 1032 1.1 christos "openssl" 1033 1.1 christos #endif 1034 1.1 christos ")", b); 1035 1.1 christos (void)rbtree_delete(anchors->tree, &ta->node); 1036 1.1 christos lock_basic_unlock(&ta->lock); 1037 1.1 christos anchors_delfunc(&ta->node, NULL); 1038 1.1 christos ta = next; 1039 1.1 christos continue; 1040 1.1 christos } 1041 1.1 christos lock_basic_unlock(&ta->lock); 1042 1.1 christos ta = next; 1043 1.1 christos } 1044 1.1 christos lock_basic_unlock(&anchors->lock); 1045 1.1 christos return 1; 1046 1.1 christos } 1047 1.1 christos 1048 1.1 christos int 1049 1.1 christos anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg) 1050 1.1 christos { 1051 1.1 christos struct config_strlist* f; 1052 1.1 christos const char** zstr; 1053 1.1 christos char* nm; 1054 1.1 christos sldns_buffer* parsebuf = sldns_buffer_new(65535); 1055 1.1.1.6 christos if(!parsebuf) { 1056 1.1.1.6 christos log_err("malloc error in anchors_apply_cfg."); 1057 1.1.1.6 christos return 0; 1058 1.1.1.6 christos } 1059 1.1 christos if(cfg->insecure_lan_zones) { 1060 1.1 christos for(zstr = as112_zones; *zstr; zstr++) { 1061 1.1 christos if(!anchor_insert_insecure(anchors, *zstr)) { 1062 1.1 christos log_err("error in insecure-lan-zones: %s", *zstr); 1063 1.1 christos sldns_buffer_free(parsebuf); 1064 1.1 christos return 0; 1065 1.1 christos } 1066 1.1 christos } 1067 1.1 christos } 1068 1.1 christos for(f = cfg->domain_insecure; f; f = f->next) { 1069 1.1 christos if(!f->str || f->str[0] == 0) /* empty "" */ 1070 1.1 christos continue; 1071 1.1 christos if(!anchor_insert_insecure(anchors, f->str)) { 1072 1.1 christos log_err("error in domain-insecure: %s", f->str); 1073 1.1 christos sldns_buffer_free(parsebuf); 1074 1.1 christos return 0; 1075 1.1 christos } 1076 1.1 christos } 1077 1.1 christos for(f = cfg->trust_anchor_file_list; f; f = f->next) { 1078 1.1 christos if(!f->str || f->str[0] == 0) /* empty "" */ 1079 1.1 christos continue; 1080 1.1 christos nm = f->str; 1081 1.1 christos if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, 1082 1.1 christos cfg->chrootdir, strlen(cfg->chrootdir)) == 0) 1083 1.1 christos nm += strlen(cfg->chrootdir); 1084 1.1 christos if(!anchor_read_file(anchors, parsebuf, nm, 0)) { 1085 1.1 christos log_err("error reading trust-anchor-file: %s", f->str); 1086 1.1 christos sldns_buffer_free(parsebuf); 1087 1.1 christos return 0; 1088 1.1 christos } 1089 1.1 christos } 1090 1.1 christos for(f = cfg->trusted_keys_file_list; f; f = f->next) { 1091 1.1 christos if(!f->str || f->str[0] == 0) /* empty "" */ 1092 1.1 christos continue; 1093 1.1 christos nm = f->str; 1094 1.1 christos if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, 1095 1.1 christos cfg->chrootdir, strlen(cfg->chrootdir)) == 0) 1096 1.1 christos nm += strlen(cfg->chrootdir); 1097 1.1 christos if(!anchor_read_bind_file_wild(anchors, parsebuf, nm)) { 1098 1.1 christos log_err("error reading trusted-keys-file: %s", f->str); 1099 1.1 christos sldns_buffer_free(parsebuf); 1100 1.1 christos return 0; 1101 1.1 christos } 1102 1.1 christos } 1103 1.1 christos for(f = cfg->trust_anchor_list; f; f = f->next) { 1104 1.1 christos if(!f->str || f->str[0] == 0) /* empty "" */ 1105 1.1 christos continue; 1106 1.1 christos if(!anchor_store_str(anchors, parsebuf, f->str)) { 1107 1.1 christos log_err("error in trust-anchor: \"%s\"", f->str); 1108 1.1 christos sldns_buffer_free(parsebuf); 1109 1.1 christos return 0; 1110 1.1 christos } 1111 1.1 christos } 1112 1.1 christos /* do autr last, so that it sees what anchors are filled by other 1113 1.1 christos * means can can print errors about double config for the name */ 1114 1.1 christos for(f = cfg->auto_trust_anchor_file_list; f; f = f->next) { 1115 1.1 christos if(!f->str || f->str[0] == 0) /* empty "" */ 1116 1.1 christos continue; 1117 1.1 christos nm = f->str; 1118 1.1 christos if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, 1119 1.1 christos cfg->chrootdir, strlen(cfg->chrootdir)) == 0) 1120 1.1 christos nm += strlen(cfg->chrootdir); 1121 1.1 christos if(!autr_read_file(anchors, nm)) { 1122 1.1 christos log_err("error reading auto-trust-anchor-file: %s", 1123 1.1 christos f->str); 1124 1.1 christos sldns_buffer_free(parsebuf); 1125 1.1 christos return 0; 1126 1.1 christos } 1127 1.1 christos } 1128 1.1 christos /* first assemble, since it may delete useless anchors */ 1129 1.1 christos anchors_assemble_rrsets(anchors); 1130 1.1 christos init_parents(anchors); 1131 1.1 christos sldns_buffer_free(parsebuf); 1132 1.1 christos if(verbosity >= VERB_ALGO) autr_debug_print(anchors); 1133 1.1 christos return 1; 1134 1.1 christos } 1135 1.1 christos 1136 1.1 christos struct trust_anchor* 1137 1.1 christos anchors_lookup(struct val_anchors* anchors, 1138 1.1 christos uint8_t* qname, size_t qname_len, uint16_t qclass) 1139 1.1 christos { 1140 1.1 christos struct trust_anchor key; 1141 1.1 christos struct trust_anchor* result; 1142 1.1.1.2 christos rbnode_type* res = NULL; 1143 1.1 christos key.node.key = &key; 1144 1.1 christos key.name = qname; 1145 1.1 christos key.namelabs = dname_count_labels(qname); 1146 1.1 christos key.namelen = qname_len; 1147 1.1 christos key.dclass = qclass; 1148 1.1 christos lock_basic_lock(&anchors->lock); 1149 1.1 christos if(rbtree_find_less_equal(anchors->tree, &key, &res)) { 1150 1.1 christos /* exact */ 1151 1.1 christos result = (struct trust_anchor*)res; 1152 1.1 christos } else { 1153 1.1 christos /* smaller element (or no element) */ 1154 1.1 christos int m; 1155 1.1 christos result = (struct trust_anchor*)res; 1156 1.1 christos if(!result || result->dclass != qclass) { 1157 1.1 christos lock_basic_unlock(&anchors->lock); 1158 1.1 christos return NULL; 1159 1.1 christos } 1160 1.1 christos /* count number of labels matched */ 1161 1.1 christos (void)dname_lab_cmp(result->name, result->namelabs, key.name, 1162 1.1 christos key.namelabs, &m); 1163 1.1 christos while(result) { /* go up until qname is subdomain of stub */ 1164 1.1 christos if(result->namelabs <= m) 1165 1.1 christos break; 1166 1.1 christos result = result->parent; 1167 1.1 christos } 1168 1.1 christos } 1169 1.1 christos if(result) { 1170 1.1 christos lock_basic_lock(&result->lock); 1171 1.1 christos } 1172 1.1 christos lock_basic_unlock(&anchors->lock); 1173 1.1 christos return result; 1174 1.1 christos } 1175 1.1 christos 1176 1.1.1.8 christos /** Get memory usage of assembled key rrset */ 1177 1.1.1.8 christos static size_t 1178 1.1.1.8 christos assembled_rrset_get_mem(struct ub_packed_rrset_key* pkey) 1179 1.1.1.8 christos { 1180 1.1.1.8 christos size_t s; 1181 1.1.1.8 christos if(!pkey) 1182 1.1.1.8 christos return 0; 1183 1.1.1.8 christos s = sizeof(*pkey) + pkey->rk.dname_len; 1184 1.1.1.8 christos if(pkey->entry.data) { 1185 1.1.1.8 christos struct packed_rrset_data* pd = (struct packed_rrset_data*) 1186 1.1.1.8 christos pkey->entry.data; 1187 1.1.1.8 christos s += sizeof(*pd) + pd->count * (sizeof(size_t)+sizeof(time_t)+ 1188 1.1.1.8 christos sizeof(uint8_t*)); 1189 1.1.1.8 christos } 1190 1.1.1.8 christos return s; 1191 1.1.1.8 christos } 1192 1.1.1.8 christos 1193 1.1 christos size_t 1194 1.1 christos anchors_get_mem(struct val_anchors* anchors) 1195 1.1 christos { 1196 1.1 christos struct trust_anchor *ta; 1197 1.1.1.8 christos struct ta_key *k; 1198 1.1.1.8 christos size_t s; 1199 1.1.1.8 christos if(!anchors) return 0; 1200 1.1.1.8 christos s = sizeof(*anchors); 1201 1.1.1.8 christos lock_basic_lock(&anchors->lock); 1202 1.1 christos RBTREE_FOR(ta, struct trust_anchor*, anchors->tree) { 1203 1.1.1.8 christos lock_basic_lock(&ta->lock); 1204 1.1 christos s += sizeof(*ta) + ta->namelen; 1205 1.1 christos /* keys and so on */ 1206 1.1.1.8 christos for(k = ta->keylist; k; k = k->next) { 1207 1.1.1.8 christos s += sizeof(*k) + k->len; 1208 1.1.1.8 christos } 1209 1.1.1.8 christos s += assembled_rrset_get_mem(ta->ds_rrset); 1210 1.1.1.8 christos s += assembled_rrset_get_mem(ta->dnskey_rrset); 1211 1.1.1.8 christos if(ta->autr) { 1212 1.1.1.8 christos struct autr_ta* p; 1213 1.1.1.8 christos s += sizeof(*ta->autr); 1214 1.1.1.8 christos if(ta->autr->file) 1215 1.1.1.8 christos s += strlen(ta->autr->file); 1216 1.1.1.8 christos for(p = ta->autr->keys; p; p=p->next) { 1217 1.1.1.8 christos s += sizeof(*p) + p->rr_len; 1218 1.1.1.8 christos } 1219 1.1.1.8 christos } 1220 1.1.1.8 christos lock_basic_unlock(&ta->lock); 1221 1.1 christos } 1222 1.1.1.8 christos lock_basic_unlock(&anchors->lock); 1223 1.1 christos return s; 1224 1.1 christos } 1225 1.1 christos 1226 1.1 christos int 1227 1.1 christos anchors_add_insecure(struct val_anchors* anchors, uint16_t c, uint8_t* nm) 1228 1.1 christos { 1229 1.1 christos struct trust_anchor key; 1230 1.1 christos key.node.key = &key; 1231 1.1 christos key.name = nm; 1232 1.1 christos key.namelabs = dname_count_size_labels(nm, &key.namelen); 1233 1.1 christos key.dclass = c; 1234 1.1 christos lock_basic_lock(&anchors->lock); 1235 1.1 christos if(rbtree_search(anchors->tree, &key)) { 1236 1.1 christos lock_basic_unlock(&anchors->lock); 1237 1.1 christos /* nothing to do, already an anchor or insecure point */ 1238 1.1 christos return 1; 1239 1.1 christos } 1240 1.1 christos if(!anchor_new_ta(anchors, nm, key.namelabs, key.namelen, c, 0)) { 1241 1.1 christos log_err("out of memory"); 1242 1.1 christos lock_basic_unlock(&anchors->lock); 1243 1.1 christos return 0; 1244 1.1 christos } 1245 1.1 christos /* no other contents in new ta, because it is insecure point */ 1246 1.1 christos anchors_init_parents_locked(anchors); 1247 1.1 christos lock_basic_unlock(&anchors->lock); 1248 1.1 christos return 1; 1249 1.1 christos } 1250 1.1 christos 1251 1.1 christos void 1252 1.1 christos anchors_delete_insecure(struct val_anchors* anchors, uint16_t c, 1253 1.1 christos uint8_t* nm) 1254 1.1 christos { 1255 1.1 christos struct trust_anchor key; 1256 1.1 christos struct trust_anchor* ta; 1257 1.1 christos key.node.key = &key; 1258 1.1 christos key.name = nm; 1259 1.1 christos key.namelabs = dname_count_size_labels(nm, &key.namelen); 1260 1.1 christos key.dclass = c; 1261 1.1 christos lock_basic_lock(&anchors->lock); 1262 1.1 christos if(!(ta=(struct trust_anchor*)rbtree_search(anchors->tree, &key))) { 1263 1.1 christos lock_basic_unlock(&anchors->lock); 1264 1.1 christos /* nothing there */ 1265 1.1 christos return; 1266 1.1 christos } 1267 1.1 christos /* lock it to drive away other threads that use it */ 1268 1.1 christos lock_basic_lock(&ta->lock); 1269 1.1 christos /* see if its really an insecure point */ 1270 1.1 christos if(ta->keylist || ta->autr || ta->numDS || ta->numDNSKEY) { 1271 1.1 christos lock_basic_unlock(&anchors->lock); 1272 1.1 christos lock_basic_unlock(&ta->lock); 1273 1.1 christos /* its not an insecure point, do not remove it */ 1274 1.1 christos return; 1275 1.1 christos } 1276 1.1 christos 1277 1.1 christos /* remove from tree */ 1278 1.1 christos (void)rbtree_delete(anchors->tree, &ta->node); 1279 1.1 christos anchors_init_parents_locked(anchors); 1280 1.1 christos lock_basic_unlock(&anchors->lock); 1281 1.1 christos 1282 1.1 christos /* actual free of data */ 1283 1.1 christos lock_basic_unlock(&ta->lock); 1284 1.1 christos anchors_delfunc(&ta->node, NULL); 1285 1.1 christos } 1286 1.1 christos 1287 1.1.1.2 christos /** compare two keytags, return -1, 0 or 1 */ 1288 1.1.1.2 christos static int 1289 1.1.1.2 christos keytag_compare(const void* x, const void* y) 1290 1.1.1.2 christos { 1291 1.1.1.2 christos if(*(uint16_t*)x == *(uint16_t*)y) 1292 1.1.1.2 christos return 0; 1293 1.1.1.2 christos if(*(uint16_t*)x > *(uint16_t*)y) 1294 1.1.1.2 christos return 1; 1295 1.1.1.2 christos return -1; 1296 1.1.1.2 christos } 1297 1.1.1.2 christos 1298 1.1.1.2 christos size_t 1299 1.1.1.2 christos anchor_list_keytags(struct trust_anchor* ta, uint16_t* list, size_t num) 1300 1.1.1.2 christos { 1301 1.1.1.2 christos size_t i, ret = 0; 1302 1.1.1.2 christos if(ta->numDS == 0 && ta->numDNSKEY == 0) 1303 1.1.1.2 christos return 0; /* insecure point */ 1304 1.1.1.2 christos if(ta->numDS != 0 && ta->ds_rrset) { 1305 1.1.1.2 christos struct packed_rrset_data* d=(struct packed_rrset_data*) 1306 1.1.1.2 christos ta->ds_rrset->entry.data; 1307 1.1.1.2 christos for(i=0; i<d->count; i++) { 1308 1.1.1.2 christos if(ret == num) continue; 1309 1.1.1.2 christos list[ret++] = ds_get_keytag(ta->ds_rrset, i); 1310 1.1.1.2 christos } 1311 1.1.1.2 christos } 1312 1.1.1.2 christos if(ta->numDNSKEY != 0 && ta->dnskey_rrset) { 1313 1.1.1.2 christos struct packed_rrset_data* d=(struct packed_rrset_data*) 1314 1.1.1.2 christos ta->dnskey_rrset->entry.data; 1315 1.1.1.2 christos for(i=0; i<d->count; i++) { 1316 1.1.1.2 christos if(ret == num) continue; 1317 1.1.1.2 christos list[ret++] = dnskey_calc_keytag(ta->dnskey_rrset, i); 1318 1.1.1.2 christos } 1319 1.1.1.2 christos } 1320 1.1.1.2 christos qsort(list, ret, sizeof(*list), keytag_compare); 1321 1.1.1.2 christos return ret; 1322 1.1.1.2 christos } 1323 1.1.1.3 christos 1324 1.1.1.3 christos int 1325 1.1.1.3 christos anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs, 1326 1.1.1.3 christos size_t namelen, uint16_t dclass, uint16_t keytag) 1327 1.1.1.3 christos { 1328 1.1.1.3 christos uint16_t* taglist; 1329 1.1.1.3 christos uint16_t* tl; 1330 1.1.1.3 christos size_t numtag, i; 1331 1.1.1.3 christos struct trust_anchor* anchor = anchor_find(anchors, 1332 1.1.1.3 christos name, namelabs, namelen, dclass); 1333 1.1.1.3 christos if(!anchor) 1334 1.1.1.3 christos return 0; 1335 1.1.1.3 christos if(!anchor->numDS && !anchor->numDNSKEY) { 1336 1.1.1.3 christos lock_basic_unlock(&anchor->lock); 1337 1.1.1.3 christos return 0; 1338 1.1.1.3 christos } 1339 1.1.1.3 christos 1340 1.1.1.3 christos taglist = calloc(anchor->numDS + anchor->numDNSKEY, sizeof(*taglist)); 1341 1.1.1.3 christos if(!taglist) { 1342 1.1.1.3 christos lock_basic_unlock(&anchor->lock); 1343 1.1.1.3 christos return 0; 1344 1.1.1.3 christos } 1345 1.1.1.3 christos 1346 1.1.1.3 christos numtag = anchor_list_keytags(anchor, taglist, 1347 1.1.1.3 christos anchor->numDS+anchor->numDNSKEY); 1348 1.1.1.3 christos lock_basic_unlock(&anchor->lock); 1349 1.1.1.3 christos if(!numtag) { 1350 1.1.1.3 christos free(taglist); 1351 1.1.1.3 christos return 0; 1352 1.1.1.3 christos } 1353 1.1.1.3 christos tl = taglist; 1354 1.1.1.3 christos for(i=0; i<numtag; i++) { 1355 1.1.1.3 christos if(*tl == keytag) { 1356 1.1.1.3 christos free(taglist); 1357 1.1.1.3 christos return 1; 1358 1.1.1.3 christos } 1359 1.1.1.3 christos tl++; 1360 1.1.1.3 christos } 1361 1.1.1.3 christos free(taglist); 1362 1.1.1.3 christos return 0; 1363 1.1.1.3 christos } 1364 1.1.1.7 christos 1365 1.1.1.7 christos struct trust_anchor* 1366 1.1.1.7 christos anchors_find_any_noninsecure(struct val_anchors* anchors) 1367 1.1.1.7 christos { 1368 1.1.1.7 christos struct trust_anchor* ta, *next; 1369 1.1.1.7 christos lock_basic_lock(&anchors->lock); 1370 1.1.1.7 christos ta=(struct trust_anchor*)rbtree_first(anchors->tree); 1371 1.1.1.7 christos while((rbnode_type*)ta != RBTREE_NULL) { 1372 1.1.1.7 christos next = (struct trust_anchor*)rbtree_next(&ta->node); 1373 1.1.1.7 christos lock_basic_lock(&ta->lock); 1374 1.1.1.7 christos if(ta->numDS != 0 || ta->numDNSKEY != 0) { 1375 1.1.1.7 christos /* not an insecurepoint */ 1376 1.1.1.7 christos lock_basic_unlock(&anchors->lock); 1377 1.1.1.7 christos return ta; 1378 1.1.1.7 christos } 1379 1.1.1.7 christos lock_basic_unlock(&ta->lock); 1380 1.1.1.7 christos ta = next; 1381 1.1.1.7 christos } 1382 1.1.1.7 christos lock_basic_unlock(&anchors->lock); 1383 1.1.1.7 christos return NULL; 1384 1.1.1.7 christos } 1385 1.1.1.8 christos 1386 1.1.1.8 christos void 1387 1.1.1.8 christos anchors_swap_tree(struct val_anchors* anchors, struct val_anchors* data) 1388 1.1.1.8 christos { 1389 1.1.1.8 christos rbtree_type* oldtree; 1390 1.1.1.8 christos rbtree_type oldprobe; 1391 1.1.1.8 christos 1392 1.1.1.8 christos if(!anchors || !data) 1393 1.1.1.8 christos return; /* If anchors is NULL, there is no validation. */ 1394 1.1.1.8 christos 1395 1.1.1.8 christos oldtree = anchors->tree; 1396 1.1.1.8 christos oldprobe = anchors->autr->probe; 1397 1.1.1.8 christos 1398 1.1.1.8 christos anchors->tree = data->tree; 1399 1.1.1.8 christos anchors->autr->probe = data->autr->probe; 1400 1.1.1.8 christos 1401 1.1.1.8 christos data->tree = oldtree; 1402 1.1.1.8 christos data->autr->probe = oldprobe; 1403 1.1.1.8 christos } 1404