Coverage Report

Created: 2023-03-26 06:08

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