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