Coverage Report

Created: 2025-08-29 06:30

/src/unbound/validator/val_utils.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * validator/val_utils.c - validator utility functions.
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 helper functions for the validator module.
40
 */
41
#include "config.h"
42
#include "validator/val_utils.h"
43
#include "validator/validator.h"
44
#include "validator/val_kentry.h"
45
#include "validator/val_sigcrypt.h"
46
#include "validator/val_anchor.h"
47
#include "validator/val_nsec.h"
48
#include "validator/val_neg.h"
49
#include "services/cache/rrset.h"
50
#include "services/cache/dns.h"
51
#include "util/data/msgreply.h"
52
#include "util/data/packed_rrset.h"
53
#include "util/data/dname.h"
54
#include "util/net_help.h"
55
#include "util/module.h"
56
#include "util/regional.h"
57
#include "util/config_file.h"
58
#include "sldns/wire2str.h"
59
#include "sldns/parseutil.h"
60
61
/** Maximum allowed digest match failures per DS, for DNSKEYs with the same
62
 *  properties */
63
0
#define MAX_DS_MATCH_FAILURES 4
64
65
enum val_classification 
66
val_classify_response(uint16_t query_flags, struct query_info* origqinf,
67
  struct query_info* qinf, struct reply_info* rep, size_t skip)
68
0
{
69
0
  int rcode = (int)FLAGS_GET_RCODE(rep->flags);
70
0
  size_t i;
71
72
  /* Normal Name Error's are easy to detect -- but don't mistake a CNAME
73
   * chain ending in NXDOMAIN. */
74
0
  if(rcode == LDNS_RCODE_NXDOMAIN && rep->an_numrrsets == 0)
75
0
    return VAL_CLASS_NAMEERROR;
76
77
  /* check for referral: nonRD query and it looks like a nodata */
78
0
  if(!(query_flags&BIT_RD) && rep->an_numrrsets == 0 &&
79
0
    rcode == LDNS_RCODE_NOERROR) {
80
    /* SOA record in auth indicates it is NODATA instead.
81
     * All validation requiring NODATA messages have SOA in 
82
     * authority section. */
83
    /* uses fact that answer section is empty */
84
0
    int saw_ns = 0;
85
0
    for(i=0; i<rep->ns_numrrsets; i++) {
86
0
      if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_SOA)
87
0
        return VAL_CLASS_NODATA;
88
0
      if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DS)
89
0
        return VAL_CLASS_REFERRAL;
90
0
      if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS)
91
0
        saw_ns = 1;
92
0
    }
93
0
    return saw_ns?VAL_CLASS_REFERRAL:VAL_CLASS_NODATA;
94
0
  }
95
  /* root referral where NS set is in the answer section */
96
0
  if(!(query_flags&BIT_RD) && rep->ns_numrrsets == 0 &&
97
0
    rep->an_numrrsets == 1 && rcode == LDNS_RCODE_NOERROR &&
98
0
    ntohs(rep->rrsets[0]->rk.type) == LDNS_RR_TYPE_NS &&
99
0
    query_dname_compare(rep->rrsets[0]->rk.dname, 
100
0
      origqinf->qname) != 0)
101
0
    return VAL_CLASS_REFERRAL;
102
103
  /* dump bad messages */
104
0
  if(rcode != LDNS_RCODE_NOERROR && rcode != LDNS_RCODE_NXDOMAIN)
105
0
    return VAL_CLASS_UNKNOWN;
106
  /* next check if the skip into the answer section shows no answer */
107
0
  if(skip>0 && rep->an_numrrsets <= skip)
108
0
    return VAL_CLASS_CNAMENOANSWER;
109
110
  /* Next is NODATA */
111
0
  if(rcode == LDNS_RCODE_NOERROR && rep->an_numrrsets == 0)
112
0
    return VAL_CLASS_NODATA;
113
  
114
  /* We distinguish between CNAME response and other positive/negative
115
   * responses because CNAME answers require extra processing. */
116
117
  /* We distinguish between ANY and CNAME or POSITIVE because 
118
   * ANY responses are validated differently. */
119
0
  if(rcode == LDNS_RCODE_NOERROR && qinf->qtype == LDNS_RR_TYPE_ANY)
120
0
    return VAL_CLASS_ANY;
121
122
  /* For the query type DNAME, the name matters. Equal name is the
123
   * answer looked for, but a subdomain redirects the query. */
124
0
  if(qinf->qtype == LDNS_RR_TYPE_DNAME) {
125
0
    for(i=skip; i<rep->an_numrrsets; i++) {
126
0
      if(rcode == LDNS_RCODE_NOERROR &&
127
0
        ntohs(rep->rrsets[i]->rk.type)
128
0
        == LDNS_RR_TYPE_DNAME &&
129
0
        query_dname_compare(qinf->qname,
130
0
        rep->rrsets[i]->rk.dname) == 0) {
131
        /* type is DNAME and name is equal, it is
132
         * the answer. For the query name a subdomain
133
         * of the rrset.dname it would redirect. */
134
0
        return VAL_CLASS_POSITIVE;
135
0
      }
136
0
      if(ntohs(rep->rrsets[i]->rk.type)
137
0
        == LDNS_RR_TYPE_CNAME)
138
0
        return VAL_CLASS_CNAME;
139
0
    }
140
0
    log_dns_msg("validator: error. failed to classify response message: ",
141
0
      qinf, rep);
142
0
    return VAL_CLASS_UNKNOWN;
143
0
  }
144
145
  /* Note that DNAMEs will be ignored here, unless qtype=DNAME. Unless
146
   * qtype=CNAME, this will yield a CNAME response. */
147
0
  for(i=skip; i<rep->an_numrrsets; i++) {
148
0
    if(rcode == LDNS_RCODE_NOERROR &&
149
0
      ntohs(rep->rrsets[i]->rk.type) == qinf->qtype)
150
0
      return VAL_CLASS_POSITIVE;
151
0
    if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME)
152
0
      return VAL_CLASS_CNAME;
153
0
  }
154
0
  log_dns_msg("validator: error. failed to classify response message: ",
155
0
    qinf, rep);
156
0
  return VAL_CLASS_UNKNOWN;
157
0
}
158
159
/** Get signer name from RRSIG */
160
static void
161
rrsig_get_signer(uint8_t* data, size_t len, uint8_t** sname, size_t* slen)
162
0
{
163
  /* RRSIG rdata is not allowed to be compressed, it is stored
164
   * uncompressed in memory as well, so return a ptr to the name */
165
0
  if(len < 21) {
166
    /* too short RRSig:
167
     * short, byte, byte, long, long, long, short, "." is
168
     * 2  1 1 4 4  4  2 1 = 19
169
     *      and a skip of 18 bytes to the name.
170
     * +2 for the rdatalen is 21 bytes len for root label */
171
0
    *sname = NULL;
172
0
    *slen = 0;
173
0
    return;
174
0
  }
175
0
  data += 20; /* skip the fixed size bits */
176
0
  len -= 20;
177
0
  *slen = dname_valid(data, len);
178
0
  if(!*slen) {
179
    /* bad dname in this rrsig. */
180
0
    *sname = NULL;
181
0
    return;
182
0
  }
183
0
  *sname = data;
184
0
}
185
186
void 
187
val_find_rrset_signer(struct ub_packed_rrset_key* rrset, uint8_t** sname,
188
  size_t* slen)
189
0
{
190
0
  struct packed_rrset_data* d = (struct packed_rrset_data*)
191
0
    rrset->entry.data;
192
  /* return signer for first signature, or NULL */
193
0
  if(d->rrsig_count == 0) {
194
0
    *sname = NULL;
195
0
    *slen = 0;
196
0
    return;
197
0
  }
198
  /* get rrsig signer name out of the signature */
199
0
  rrsig_get_signer(d->rr_data[d->count], d->rr_len[d->count], 
200
0
    sname, slen);
201
0
}
202
203
/**
204
 * Find best signer name in this set of rrsigs.
205
 * @param rrset: which rrsigs to look through.
206
 * @param qinf: the query name that needs validation.
207
 * @param signer_name: the best signer_name. Updated if a better one is found.
208
 * @param signer_len: length of signer name.
209
 * @param matchcount: count of current best name (starts at 0 for no match).
210
 *  Updated if match is improved.
211
 */
212
static void
213
val_find_best_signer(struct ub_packed_rrset_key* rrset, 
214
  struct query_info* qinf, uint8_t** signer_name, size_t* signer_len, 
215
  int* matchcount)
216
0
{
217
0
  struct packed_rrset_data* d = (struct packed_rrset_data*)
218
0
    rrset->entry.data;
219
0
  uint8_t* sign;
220
0
  size_t i;
221
0
  int m;
222
0
  for(i=d->count; i<d->count+d->rrsig_count; i++) {
223
0
    sign = d->rr_data[i]+2+18;
224
    /* look at signatures that are valid (long enough),
225
     * and have a signer name that is a superdomain of qname,
226
     * and then check the number of labels in the shared topdomain
227
     * improve the match if possible */
228
0
    if(d->rr_len[i] > 2+19 && /* rdata, sig + root label*/
229
0
      dname_subdomain_c(qinf->qname, sign)) {
230
0
      (void)dname_lab_cmp(qinf->qname, 
231
0
        dname_count_labels(qinf->qname), 
232
0
        sign, dname_count_labels(sign), &m);
233
0
      if(m > *matchcount) {
234
0
        *matchcount = m;
235
0
        *signer_name = sign;
236
0
        (void)dname_count_size_labels(*signer_name,
237
0
          signer_len);
238
0
      }
239
0
    }
240
0
  }
241
0
}
242
243
/** Detect if the, unsigned, CNAME is under a previous DNAME RR in the
244
 * message, and thus it was generated from that previous DNAME.
245
 */
246
static int
247
cname_under_previous_dname(struct reply_info* rep, size_t cname_idx,
248
  size_t* ret)
249
0
{
250
0
  size_t i;
251
0
  for(i=0; i<cname_idx; i++) {
252
0
    if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DNAME &&
253
0
      dname_strict_subdomain_c(rep->rrsets[cname_idx]->
254
0
      rk.dname, rep->rrsets[i]->rk.dname)) {
255
0
      *ret = i;
256
0
      return 1;
257
0
    }
258
0
  }
259
0
  *ret = 0;
260
0
  return 0;
261
0
}
262
263
void 
264
val_find_signer(enum val_classification subtype, struct query_info* qinf, 
265
  struct reply_info* rep, size_t skip, uint8_t** signer_name, 
266
  size_t* signer_len)
267
0
{
268
0
  size_t i;
269
  
270
0
  if(subtype == VAL_CLASS_POSITIVE) {
271
    /* check for the answer rrset */
272
0
    for(i=skip; i<rep->an_numrrsets; i++) {
273
0
      if(query_dname_compare(qinf->qname, 
274
0
        rep->rrsets[i]->rk.dname) == 0) {
275
0
        val_find_rrset_signer(rep->rrsets[i], 
276
0
          signer_name, signer_len);
277
        /* If there was no signer, and the query
278
         * was for type CNAME, and this is a CNAME,
279
         * and the previous is a DNAME, then this
280
         * is the synthesized CNAME, use the signer
281
         * of the DNAME record. */
282
0
        if(*signer_name == NULL &&
283
0
           qinf->qtype == LDNS_RR_TYPE_CNAME &&
284
0
           ntohs(rep->rrsets[i]->rk.type) ==
285
0
           LDNS_RR_TYPE_CNAME && i > skip &&
286
0
           ntohs(rep->rrsets[i-1]->rk.type) ==
287
0
           LDNS_RR_TYPE_DNAME &&
288
0
           dname_strict_subdomain_c(rep->rrsets[i]->rk.dname, rep->rrsets[i-1]->rk.dname)) {
289
0
          val_find_rrset_signer(rep->rrsets[i-1],
290
0
            signer_name, signer_len);
291
0
        }
292
0
        return;
293
0
      }
294
0
    }
295
0
    *signer_name = NULL;
296
0
    *signer_len = 0;
297
0
  } else if(subtype == VAL_CLASS_CNAME) {
298
0
    size_t j;
299
    /* check for the first signed cname/dname rrset */
300
0
    for(i=skip; i<rep->an_numrrsets; i++) {
301
0
      val_find_rrset_signer(rep->rrsets[i], 
302
0
        signer_name, signer_len);
303
0
      if(*signer_name)
304
0
        return;
305
0
      if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME
306
0
        && cname_under_previous_dname(rep, i, &j)) {
307
0
        val_find_rrset_signer(rep->rrsets[j],
308
0
          signer_name, signer_len);
309
0
        return;
310
0
      }
311
0
      if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_DNAME)
312
0
        break; /* only check CNAME after a DNAME */
313
0
    }
314
0
    *signer_name = NULL;
315
0
    *signer_len = 0;
316
0
  } else if(subtype == VAL_CLASS_NAMEERROR 
317
0
    || subtype == VAL_CLASS_NODATA) {
318
    /*Check to see if the AUTH section NSEC record(s) have rrsigs*/
319
0
    for(i=rep->an_numrrsets; i<
320
0
      rep->an_numrrsets+rep->ns_numrrsets; i++) {
321
0
      if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC
322
0
        || ntohs(rep->rrsets[i]->rk.type) ==
323
0
        LDNS_RR_TYPE_NSEC3) {
324
0
        val_find_rrset_signer(rep->rrsets[i], 
325
0
          signer_name, signer_len);
326
0
        return;
327
0
      }
328
0
    }
329
0
  } else if(subtype == VAL_CLASS_CNAMENOANSWER) {
330
    /* find closest superdomain signer name in authority section
331
     * NSEC and NSEC3s */
332
0
    int matchcount = 0;
333
0
    *signer_name = NULL;
334
0
    *signer_len = 0;
335
0
    for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->
336
0
      ns_numrrsets; i++) { 
337
0
      if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NSEC
338
0
        || ntohs(rep->rrsets[i]->rk.type) == 
339
0
        LDNS_RR_TYPE_NSEC3) {
340
0
        val_find_best_signer(rep->rrsets[i], qinf,
341
0
          signer_name, signer_len, &matchcount);
342
0
      }
343
0
    }
344
0
  } else if(subtype == VAL_CLASS_ANY) {
345
    /* check for one of the answer rrset that has signatures,
346
     * or potentially a DNAME is in use with a different qname */
347
0
    for(i=skip; i<rep->an_numrrsets; i++) {
348
0
      if(query_dname_compare(qinf->qname, 
349
0
        rep->rrsets[i]->rk.dname) == 0) {
350
0
        val_find_rrset_signer(rep->rrsets[i], 
351
0
          signer_name, signer_len);
352
0
        if(*signer_name)
353
0
          return;
354
0
      }
355
0
    }
356
    /* no answer RRSIGs with qname, try a DNAME */
357
0
    if(skip < rep->an_numrrsets &&
358
0
      ntohs(rep->rrsets[skip]->rk.type) ==
359
0
      LDNS_RR_TYPE_DNAME) {
360
0
      val_find_rrset_signer(rep->rrsets[skip], 
361
0
        signer_name, signer_len);
362
0
      if(*signer_name)
363
0
        return;
364
0
    }
365
0
    *signer_name = NULL;
366
0
    *signer_len = 0;
367
0
  } else if(subtype == VAL_CLASS_REFERRAL) {
368
    /* find keys for the item at skip */
369
0
    if(skip < rep->rrset_count) {
370
0
      val_find_rrset_signer(rep->rrsets[skip], 
371
0
        signer_name, signer_len);
372
0
      return;
373
0
    }
374
0
    *signer_name = NULL;
375
0
    *signer_len = 0;
376
0
  } else {
377
0
    verbose(VERB_QUERY, "find_signer: could not find signer name"
378
0
      " for unknown type response");
379
0
    *signer_name = NULL;
380
0
    *signer_len = 0;
381
0
  }
382
0
}
383
384
/** return number of rrs in an rrset */
385
static size_t
386
rrset_get_count(struct ub_packed_rrset_key* rrset)
387
0
{
388
0
  struct packed_rrset_data* d = (struct packed_rrset_data*)
389
0
    rrset->entry.data;
390
0
  if(!d) return 0;
391
0
  return d->count;
392
0
}
393
394
/** return TTL of rrset */
395
static uint32_t
396
rrset_get_ttl(struct ub_packed_rrset_key* rrset)
397
0
{
398
0
  struct packed_rrset_data* d = (struct packed_rrset_data*)
399
0
    rrset->entry.data;
400
0
  if(!d) return 0;
401
0
  return d->ttl;
402
0
}
403
404
static enum sec_status 
405
val_verify_rrset(struct module_env* env, struct val_env* ve,
406
        struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
407
  uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus,
408
  sldns_pkt_section section, struct module_qstate* qstate,
409
  int *verified, char* reasonbuf, size_t reasonlen)
410
0
{
411
0
  enum sec_status sec;
412
0
  struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
413
0
    entry.data;
414
0
  if(d->security == sec_status_secure) {
415
    /* re-verify all other statuses, because keyset may change*/
416
0
    log_nametypeclass(VERB_ALGO, "verify rrset cached", 
417
0
      rrset->rk.dname, ntohs(rrset->rk.type), 
418
0
      ntohs(rrset->rk.rrset_class));
419
0
    *verified = 0;
420
0
    return d->security;
421
0
  }
422
  /* check in the cache if verification has already been done */
423
0
  rrset_check_sec_status(env->rrset_cache, rrset, *env->now);
424
0
  if(d->security == sec_status_secure) {
425
0
    log_nametypeclass(VERB_ALGO, "verify rrset from cache", 
426
0
      rrset->rk.dname, ntohs(rrset->rk.type), 
427
0
      ntohs(rrset->rk.rrset_class));
428
0
    *verified = 0;
429
0
    return d->security;
430
0
  }
431
0
  log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname,
432
0
    ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
433
0
  sec = dnskeyset_verify_rrset(env, ve, rrset, keys, sigalg, reason,
434
0
    reason_bogus, section, qstate, verified, reasonbuf, reasonlen);
435
0
  verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec));
436
0
  regional_free_all(env->scratch);
437
438
  /* update rrset security status 
439
   * only improves security status 
440
   * and bogus is set only once, even if we rechecked the status */
441
0
  if(sec > d->security) {
442
0
    d->security = sec;
443
0
    if(sec == sec_status_secure)
444
0
      d->trust = rrset_trust_validated;
445
0
    else if(sec == sec_status_bogus) {
446
0
      size_t i;
447
      /* update ttl for rrset to fixed value. */
448
0
      d->ttl = ve->bogus_ttl;
449
0
      for(i=0; i<d->count+d->rrsig_count; i++)
450
0
        d->rr_ttl[i] = ve->bogus_ttl;
451
      /* leave RR specific TTL: not used for determine
452
       * if RRset timed out and clients see proper value. */
453
0
      lock_basic_lock(&ve->bogus_lock);
454
0
      ve->num_rrset_bogus++;
455
0
      lock_basic_unlock(&ve->bogus_lock);
456
0
    }
457
    /* if status updated - store in cache for reuse */
458
0
    rrset_update_sec_status(env->rrset_cache, rrset, *env->now);
459
0
  }
460
461
0
  return sec;
462
0
}
463
464
enum sec_status 
465
val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
466
        struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey,
467
  char** reason, sldns_ede_code *reason_bogus,
468
  sldns_pkt_section section, struct module_qstate* qstate,
469
  int* verified, char* reasonbuf, size_t reasonlen)
470
0
{
471
  /* temporary dnskey rrset-key */
472
0
  struct ub_packed_rrset_key dnskey;
473
0
  struct key_entry_data* kd = (struct key_entry_data*)kkey->entry.data;
474
0
  enum sec_status sec;
475
0
  dnskey.rk.type = htons(kd->rrset_type);
476
0
  dnskey.rk.rrset_class = htons(kkey->key_class);
477
0
  dnskey.rk.flags = 0;
478
0
  dnskey.rk.dname = kkey->name;
479
0
  dnskey.rk.dname_len = kkey->namelen;
480
0
  dnskey.entry.key = &dnskey;
481
0
  dnskey.entry.data = kd->rrset_data;
482
0
  sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason,
483
0
    reason_bogus, section, qstate, verified, reasonbuf, reasonlen);
484
0
  return sec;
485
0
}
486
487
/** verify that a DS RR hashes to a key and that key signs the set */
488
static enum sec_status
489
verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
490
  struct ub_packed_rrset_key* dnskey_rrset,
491
        struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason,
492
  sldns_ede_code *reason_bogus, struct module_qstate* qstate,
493
  int *nonechecked, char* reasonbuf, size_t reasonlen)
494
0
{
495
0
  enum sec_status sec = sec_status_bogus;
496
0
  size_t i, num, numchecked = 0, numhashok = 0, numsizesupp = 0;
497
0
  num = rrset_get_count(dnskey_rrset);
498
0
  *nonechecked = 0;
499
0
  for(i=0; i<num; i++) {
500
    /* Skip DNSKEYs that don't match the basic criteria. */
501
0
    if(ds_get_key_algo(ds_rrset, ds_idx) 
502
0
       != dnskey_get_algo(dnskey_rrset, i)
503
0
       || dnskey_calc_keytag(dnskey_rrset, i)
504
0
       != ds_get_keytag(ds_rrset, ds_idx)) {
505
0
      continue;
506
0
    }
507
0
    numchecked++;
508
0
    verbose(VERB_ALGO, "attempt DS match algo %d keytag %d",
509
0
      ds_get_key_algo(ds_rrset, ds_idx),
510
0
      ds_get_keytag(ds_rrset, ds_idx));
511
512
    /* Convert the candidate DNSKEY into a hash using the 
513
     * same DS hash algorithm. */
514
0
    if(!ds_digest_match_dnskey(env, dnskey_rrset, i, ds_rrset, 
515
0
      ds_idx)) {
516
0
      verbose(VERB_ALGO, "DS match attempt failed");
517
0
      if(numchecked > numhashok + MAX_DS_MATCH_FAILURES) {
518
0
        verbose(VERB_ALGO, "DS match attempt reached "
519
0
          "MAX_DS_MATCH_FAILURES (%d); bogus",
520
0
          MAX_DS_MATCH_FAILURES);
521
0
        return sec_status_bogus;
522
0
      }
523
0
      continue;
524
0
    }
525
0
    numhashok++;
526
0
    if(!dnskey_size_is_supported(dnskey_rrset, i)) {
527
0
      verbose(VERB_ALGO, "DS okay but that DNSKEY size is not supported");
528
0
      numsizesupp++;
529
0
      continue;
530
0
    }
531
0
    verbose(VERB_ALGO, "DS match digest ok, trying signature");
532
533
    /* Otherwise, we have a match! Make sure that the DNSKEY 
534
     * verifies *with this key*  */
535
0
    sec = dnskey_verify_rrset(env, ve, dnskey_rrset, dnskey_rrset,
536
0
      i, reason, reason_bogus, LDNS_SECTION_ANSWER, qstate);
537
0
    if(sec == sec_status_secure) {
538
0
      return sec;
539
0
    }
540
    /* If it didn't validate with the DNSKEY, try the next one! */
541
0
  }
542
0
  if(numsizesupp != 0 || sec == sec_status_indeterminate) {
543
    /* there is a working DS, but that DNSKEY is not supported */
544
0
    return sec_status_insecure;
545
0
  }
546
0
  if(numchecked == 0) {
547
0
    algo_needs_reason(ds_get_key_algo(ds_rrset, ds_idx),
548
0
      reason, "no keys have a DS", reasonbuf, reasonlen);
549
0
    *nonechecked = 1;
550
0
  } else if(numhashok == 0) {
551
0
    *reason = "DS hash mismatches key";
552
0
  } else if(!*reason) {
553
0
    *reason = "keyset not secured by DNSKEY that matches DS";
554
0
  }
555
0
  return sec_status_bogus;
556
0
}
557
558
int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset)
559
0
{
560
0
  size_t i, num = rrset_get_count(ds_rrset);
561
0
  int d, digest_algo = 0; /* DS digest algo 0 is not used. */
562
  /* find favorite algo, for now, highest number supported */
563
0
  for(i=0; i<num; i++) {
564
0
    if(!ds_digest_algo_is_supported(ds_rrset, i) ||
565
0
      !ds_key_algo_is_supported(ds_rrset, i)) {
566
0
      continue;
567
0
    }
568
0
    d = ds_get_digest_algo(ds_rrset, i);
569
0
    if(d > digest_algo)
570
0
      digest_algo = d;
571
0
  }
572
0
  return digest_algo;
573
0
}
574
575
enum sec_status
576
val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
577
  struct ub_packed_rrset_key* dnskey_rrset,
578
  struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason,
579
  sldns_ede_code *reason_bogus, struct module_qstate* qstate,
580
  char* reasonbuf, size_t reasonlen)
581
0
{
582
  /* as long as this is false, we can consider this DS rrset to be
583
   * equivalent to no DS rrset. */
584
0
  int has_useful_ds = 0, digest_algo, alg, has_algo_refusal = 0,
585
0
    nonechecked, has_checked_ds = 0;
586
0
  struct algo_needs needs;
587
0
  size_t i, num;
588
0
  enum sec_status sec;
589
590
0
  if(dnskey_rrset->rk.dname_len != ds_rrset->rk.dname_len ||
591
0
    query_dname_compare(dnskey_rrset->rk.dname, ds_rrset->rk.dname)
592
0
    != 0) {
593
0
    verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset "
594
0
      "by name");
595
0
    *reason = "DNSKEY RRset did not match DS RRset by name";
596
0
    return sec_status_bogus;
597
0
  }
598
599
0
  if(sigalg) {
600
    /* harden against algo downgrade is enabled */
601
0
    digest_algo = val_favorite_ds_algo(ds_rrset);
602
0
    algo_needs_init_ds(&needs, ds_rrset, digest_algo, sigalg);
603
0
  } else {
604
    /* accept any key algo, any digest algo */
605
0
    digest_algo = -1;
606
0
  }
607
0
  num = rrset_get_count(ds_rrset);
608
0
  for(i=0; i<num; i++) {
609
    /* Check to see if we can understand this DS. 
610
     * And check it is the strongest digest */
611
0
    if(!ds_digest_algo_is_supported(ds_rrset, i) ||
612
0
      !ds_key_algo_is_supported(ds_rrset, i) ||
613
0
      (sigalg && (ds_get_digest_algo(ds_rrset, i) != digest_algo))) {
614
0
      continue;
615
0
    }
616
617
0
    sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
618
0
      ds_rrset, i, reason, reason_bogus, qstate,
619
0
      &nonechecked, reasonbuf, reasonlen);
620
0
    if(sec == sec_status_insecure) {
621
      /* DNSKEY too large unsupported or algo refused by
622
       * crypto lib. */
623
0
      has_algo_refusal = 1;
624
0
      continue;
625
0
    }
626
0
    if(!nonechecked)
627
0
      has_checked_ds = 1;
628
629
    /* Once we see a single DS with a known digestID and 
630
     * algorithm, we cannot return INSECURE (with a 
631
     * "null" KeyEntry). */
632
0
    has_useful_ds = 1;
633
634
0
    if(sec == sec_status_secure) {
635
0
      if(!sigalg || algo_needs_set_secure(&needs,
636
0
        (uint8_t)ds_get_key_algo(ds_rrset, i))) {
637
0
        verbose(VERB_ALGO, "DS matched DNSKEY.");
638
0
        if(!dnskeyset_size_is_supported(dnskey_rrset)) {
639
0
          verbose(VERB_ALGO, "DS works, but dnskeyset contain keys that are unsupported, treat as insecure");
640
0
          return sec_status_insecure;
641
0
        }
642
0
        return sec_status_secure;
643
0
      }
644
0
    } else if(sigalg && sec == sec_status_bogus) {
645
0
      algo_needs_set_bogus(&needs,
646
0
        (uint8_t)ds_get_key_algo(ds_rrset, i));
647
0
    }
648
0
  }
649
650
  /* None of the DS's worked out. */
651
652
  /* If none of the DSes have been checked, eg. that means no matches
653
   * for keytags, and the other dses are all algo_refusal, it is an
654
   * insecure delegation point, since the only matched DS records
655
   * have an algo refusal, or are unsupported. */
656
0
  if(has_algo_refusal && !has_checked_ds) {
657
0
    verbose(VERB_ALGO, "No supported DS records were found -- "
658
0
      "treating as insecure.");
659
0
    return sec_status_insecure;
660
0
  }
661
  /* If no DSs were understandable, then this is OK. */
662
0
  if(!has_useful_ds) {
663
0
    verbose(VERB_ALGO, "No usable DS records were found -- "
664
0
      "treating as insecure.");
665
0
    return sec_status_insecure;
666
0
  }
667
  /* If any were understandable, then it is bad. */
668
0
  verbose(VERB_QUERY, "Failed to match any usable DS to a DNSKEY.");
669
0
  if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
670
0
    algo_needs_reason(alg, reason, "missing verification of "
671
0
      "DNSKEY signature", reasonbuf, reasonlen);
672
0
  }
673
0
  return sec_status_bogus;
674
0
}
675
676
struct key_entry_key*
677
val_verify_new_DNSKEYs(struct regional* region, struct module_env* env, 
678
  struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset, 
679
  struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason,
680
  sldns_ede_code *reason_bogus, struct module_qstate* qstate,
681
  char* reasonbuf, size_t reasonlen)
682
0
{
683
0
  uint8_t sigalg[ALGO_NEEDS_MAX+1];
684
0
  enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve,
685
0
    dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason, 
686
0
    reason_bogus, qstate, reasonbuf, reasonlen);
687
688
0
  if(sec == sec_status_secure) {
689
0
    return key_entry_create_rrset(region, 
690
0
      ds_rrset->rk.dname, ds_rrset->rk.dname_len,
691
0
      ntohs(ds_rrset->rk.rrset_class), dnskey_rrset,
692
0
      downprot?sigalg:NULL, LDNS_EDE_NONE, NULL,
693
0
      *env->now);
694
0
  } else if(sec == sec_status_insecure) {
695
0
    return key_entry_create_null(region, ds_rrset->rk.dname,
696
0
      ds_rrset->rk.dname_len,
697
0
      ntohs(ds_rrset->rk.rrset_class),
698
0
      rrset_get_ttl(ds_rrset), *reason_bogus, *reason,
699
0
      *env->now);
700
0
  }
701
0
  return key_entry_create_bad(region, ds_rrset->rk.dname,
702
0
    ds_rrset->rk.dname_len, ntohs(ds_rrset->rk.rrset_class),
703
0
    BOGUS_KEY_TTL, *reason_bogus, *reason, *env->now);
704
0
}
705
706
enum sec_status
707
val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
708
  struct ub_packed_rrset_key* dnskey_rrset,
709
  struct ub_packed_rrset_key* ta_ds,
710
  struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason,
711
  sldns_ede_code *reason_bogus, struct module_qstate* qstate,
712
  char* reasonbuf, size_t reasonlen)
713
0
{
714
  /* as long as this is false, we can consider this anchor to be
715
   * equivalent to no anchor. */
716
0
  int has_useful_ta = 0, digest_algo = 0, alg, has_algo_refusal = 0,
717
0
    nonechecked, has_checked_ds = 0;
718
0
  struct algo_needs needs;
719
0
  size_t i, num;
720
0
  enum sec_status sec;
721
722
0
  if(ta_ds && (dnskey_rrset->rk.dname_len != ta_ds->rk.dname_len ||
723
0
    query_dname_compare(dnskey_rrset->rk.dname, ta_ds->rk.dname)
724
0
    != 0)) {
725
0
    verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset "
726
0
      "by name");
727
0
    *reason = "DNSKEY RRset did not match DS RRset by name";
728
0
    if(reason_bogus)
729
0
      *reason_bogus = LDNS_EDE_DNSKEY_MISSING;
730
0
    return sec_status_bogus;
731
0
  }
732
0
  if(ta_dnskey && (dnskey_rrset->rk.dname_len != ta_dnskey->rk.dname_len
733
0
       || query_dname_compare(dnskey_rrset->rk.dname, ta_dnskey->rk.dname)
734
0
    != 0)) {
735
0
    verbose(VERB_QUERY, "DNSKEY RRset did not match anchor RRset "
736
0
      "by name");
737
0
    *reason = "DNSKEY RRset did not match anchor RRset by name";
738
0
    if(reason_bogus)
739
0
      *reason_bogus = LDNS_EDE_DNSKEY_MISSING;
740
0
    return sec_status_bogus;
741
0
  }
742
743
0
  if(ta_ds)
744
0
    digest_algo = val_favorite_ds_algo(ta_ds);
745
0
  if(sigalg) {
746
0
    if(ta_ds)
747
0
      algo_needs_init_ds(&needs, ta_ds, digest_algo, sigalg);
748
0
    else  memset(&needs, 0, sizeof(needs));
749
0
    if(ta_dnskey)
750
0
      algo_needs_init_dnskey_add(&needs, ta_dnskey, sigalg);
751
0
  }
752
0
  if(ta_ds) {
753
0
      num = rrset_get_count(ta_ds);
754
0
      for(i=0; i<num; i++) {
755
    /* Check to see if we can understand this DS. 
756
     * And check it is the strongest digest */
757
0
    if(!ds_digest_algo_is_supported(ta_ds, i) ||
758
0
      !ds_key_algo_is_supported(ta_ds, i) ||
759
0
      ds_get_digest_algo(ta_ds, i) != digest_algo)
760
0
      continue;
761
762
0
    sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
763
0
      ta_ds, i, reason, reason_bogus, qstate, &nonechecked,
764
0
      reasonbuf, reasonlen);
765
0
    if(sec == sec_status_insecure) {
766
0
      has_algo_refusal = 1;
767
0
      continue;
768
0
    }
769
0
    if(!nonechecked)
770
0
      has_checked_ds = 1;
771
772
    /* Once we see a single DS with a known digestID and 
773
     * algorithm, we cannot return INSECURE (with a 
774
     * "null" KeyEntry). */
775
0
    has_useful_ta = 1;
776
777
0
    if(sec == sec_status_secure) {
778
0
      if(!sigalg || algo_needs_set_secure(&needs,
779
0
        (uint8_t)ds_get_key_algo(ta_ds, i))) {
780
0
        verbose(VERB_ALGO, "DS matched DNSKEY.");
781
0
        if(!dnskeyset_size_is_supported(dnskey_rrset)) {
782
0
          verbose(VERB_ALGO, "trustanchor works, but dnskeyset contain keys that are unsupported, treat as insecure");
783
0
          return sec_status_insecure;
784
0
        }
785
0
        return sec_status_secure;
786
0
      }
787
0
    } else if(sigalg && sec == sec_status_bogus) {
788
0
      algo_needs_set_bogus(&needs,
789
0
        (uint8_t)ds_get_key_algo(ta_ds, i));
790
0
    }
791
0
      }
792
0
  }
793
794
  /* None of the DS's worked out: check the DNSKEYs. */
795
0
  if(ta_dnskey) {
796
0
      num = rrset_get_count(ta_dnskey);
797
0
      for(i=0; i<num; i++) {
798
    /* Check to see if we can understand this DNSKEY */
799
0
    if(!dnskey_algo_is_supported(ta_dnskey, i))
800
0
      continue;
801
0
    if(!dnskey_size_is_supported(ta_dnskey, i))
802
0
      continue;
803
804
    /* we saw a useful TA */
805
0
    has_useful_ta = 1;
806
807
0
    sec = dnskey_verify_rrset(env, ve, dnskey_rrset,
808
0
      ta_dnskey, i, reason, reason_bogus, LDNS_SECTION_ANSWER, qstate);
809
0
    if(sec == sec_status_secure) {
810
0
      if(!sigalg || algo_needs_set_secure(&needs,
811
0
        (uint8_t)dnskey_get_algo(ta_dnskey, i))) {
812
0
        verbose(VERB_ALGO, "anchor matched DNSKEY.");
813
0
        if(!dnskeyset_size_is_supported(dnskey_rrset)) {
814
0
          verbose(VERB_ALGO, "trustanchor works, but dnskeyset contain keys that are unsupported, treat as insecure");
815
0
          return sec_status_insecure;
816
0
        }
817
0
        return sec_status_secure;
818
0
      }
819
0
    } else if(sigalg && sec == sec_status_bogus) {
820
0
      algo_needs_set_bogus(&needs,
821
0
        (uint8_t)dnskey_get_algo(ta_dnskey, i));
822
0
    }
823
0
      }
824
0
  }
825
826
  /* If none of the DSes have been checked, eg. that means no matches
827
   * for keytags, and the other dses are all algo_refusal, it is an
828
   * insecure delegation point, since the only matched DS records
829
   * have an algo refusal, or are unsupported. */
830
0
  if(has_algo_refusal && !has_checked_ds) {
831
0
    verbose(VERB_ALGO, "No supported trust anchors were found -- "
832
0
      "treating as insecure.");
833
0
    return sec_status_insecure;
834
0
  }
835
  /* If no DSs were understandable, then this is OK. */
836
0
  if(!has_useful_ta) {
837
0
    verbose(VERB_ALGO, "No usable trust anchors were found -- "
838
0
      "treating as insecure.");
839
0
    return sec_status_insecure;
840
0
  }
841
  /* If any were understandable, then it is bad. */
842
0
  verbose(VERB_QUERY, "Failed to match any usable anchor to a DNSKEY.");
843
0
  if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
844
0
    algo_needs_reason(alg, reason, "missing verification of "
845
0
      "DNSKEY signature", reasonbuf, reasonlen);
846
0
  }
847
0
  return sec_status_bogus;
848
0
}
849
850
struct key_entry_key* 
851
val_verify_new_DNSKEYs_with_ta(struct regional* region, struct module_env* env,
852
  struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
853
  struct ub_packed_rrset_key* ta_ds_rrset,
854
  struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot,
855
  char** reason, sldns_ede_code *reason_bogus,
856
  struct module_qstate* qstate, char* reasonbuf, size_t reasonlen)
857
0
{
858
0
  uint8_t sigalg[ALGO_NEEDS_MAX+1];
859
0
  enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve,
860
0
    dnskey_rrset, ta_ds_rrset, ta_dnskey_rrset,
861
0
    downprot?sigalg:NULL, reason, reason_bogus, qstate,
862
0
    reasonbuf, reasonlen);
863
864
0
  if(sec == sec_status_secure) {
865
0
    return key_entry_create_rrset(region,
866
0
      dnskey_rrset->rk.dname, dnskey_rrset->rk.dname_len,
867
0
      ntohs(dnskey_rrset->rk.rrset_class), dnskey_rrset,
868
0
      downprot?sigalg:NULL, LDNS_EDE_NONE, NULL, *env->now);
869
0
  } else if(sec == sec_status_insecure) {
870
0
    return key_entry_create_null(region, dnskey_rrset->rk.dname,
871
0
      dnskey_rrset->rk.dname_len,
872
0
      ntohs(dnskey_rrset->rk.rrset_class),
873
0
      rrset_get_ttl(dnskey_rrset), *reason_bogus, *reason,
874
0
      *env->now);
875
0
  }
876
0
  return key_entry_create_bad(region, dnskey_rrset->rk.dname,
877
0
    dnskey_rrset->rk.dname_len, ntohs(dnskey_rrset->rk.rrset_class),
878
0
    BOGUS_KEY_TTL, *reason_bogus, *reason, *env->now);
879
0
}
880
881
int
882
val_dsset_isusable(struct ub_packed_rrset_key* ds_rrset)
883
0
{
884
0
  size_t i;
885
0
  for(i=0; i<rrset_get_count(ds_rrset); i++) {
886
0
    if(ds_digest_algo_is_supported(ds_rrset, i) &&
887
0
      ds_key_algo_is_supported(ds_rrset, i))
888
0
      return 1;
889
0
  }
890
0
  if(verbosity < VERB_ALGO)
891
0
    return 0;
892
0
  if(rrset_get_count(ds_rrset) == 0)
893
0
    verbose(VERB_ALGO, "DS is not usable");
894
0
  else {
895
    /* report usability for the first DS RR */
896
0
    sldns_lookup_table *lt;
897
0
    char herr[64], aerr[64];
898
0
    lt = sldns_lookup_by_id(sldns_hashes,
899
0
      (int)ds_get_digest_algo(ds_rrset, 0));
900
0
    if(lt) snprintf(herr, sizeof(herr), "%s", lt->name);
901
0
    else snprintf(herr, sizeof(herr), "%d",
902
0
      (int)ds_get_digest_algo(ds_rrset, 0));
903
0
    lt = sldns_lookup_by_id(sldns_algorithms,
904
0
      (int)ds_get_key_algo(ds_rrset, 0));
905
0
    if(lt) snprintf(aerr, sizeof(aerr), "%s", lt->name);
906
0
    else snprintf(aerr, sizeof(aerr), "%d",
907
0
      (int)ds_get_key_algo(ds_rrset, 0));
908
909
0
    verbose(VERB_ALGO, "DS unsupported, hash %s %s, "
910
0
      "key algorithm %s %s", herr,
911
0
      (ds_digest_algo_is_supported(ds_rrset, 0)?
912
0
      "(supported)":"(unsupported)"), aerr, 
913
0
      (ds_key_algo_is_supported(ds_rrset, 0)?
914
0
      "(supported)":"(unsupported)"));
915
0
  }
916
0
  return 0;
917
0
}
918
919
/** get label count for a signature */
920
static uint8_t
921
rrsig_get_labcount(struct packed_rrset_data* d, size_t sig)
922
0
{
923
0
  if(d->rr_len[sig] < 2+4)
924
0
    return 0; /* bad sig length */
925
0
  return d->rr_data[sig][2+3];
926
0
}
927
928
int 
929
val_rrset_wildcard(struct ub_packed_rrset_key* rrset, uint8_t** wc,
930
  size_t* wc_len)
931
0
{
932
0
  struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
933
0
    entry.data;
934
0
  uint8_t labcount;
935
0
  int labdiff;
936
0
  uint8_t* wn;
937
0
  size_t i, wl;
938
0
  if(d->rrsig_count == 0) {
939
0
    return 1;
940
0
  }
941
0
  labcount = rrsig_get_labcount(d, d->count + 0);
942
  /* check rest of signatures identical */
943
0
  for(i=1; i<d->rrsig_count; i++) {
944
0
    if(labcount != rrsig_get_labcount(d, d->count + i)) {
945
0
      return 0;
946
0
    }
947
0
  }
948
  /* OK the rrsigs check out */
949
  /* if the RRSIG label count is shorter than the number of actual 
950
   * labels, then this rrset was synthesized from a wildcard.
951
   * Note that the RRSIG label count doesn't count the root label. */
952
0
  wn = rrset->rk.dname;
953
0
  wl = rrset->rk.dname_len;
954
  /* skip a leading wildcard label in the dname (RFC4035 2.2) */
955
0
  if(dname_is_wild(wn)) {
956
0
    wn += 2;
957
0
    wl -= 2;
958
0
  }
959
0
  labdiff = (dname_count_labels(wn) - 1) - (int)labcount;
960
0
  if(labdiff > 0) {
961
0
    *wc = wn;
962
0
    dname_remove_labels(wc, &wl, labdiff);
963
0
    *wc_len = wl;
964
0
    return 1;
965
0
  }
966
0
  return 1;
967
0
}
968
969
int
970
val_chase_cname(struct query_info* qchase, struct reply_info* rep,
971
0
  size_t* cname_skip) {
972
0
  size_t i;
973
  /* skip any DNAMEs, go to the CNAME for next part */
974
0
  for(i = *cname_skip; i < rep->an_numrrsets; i++) {
975
0
    if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME &&
976
0
      query_dname_compare(qchase->qname, rep->rrsets[i]->
977
0
        rk.dname) == 0) {
978
0
      qchase->qname = NULL;
979
0
      get_cname_target(rep->rrsets[i], &qchase->qname,
980
0
        &qchase->qname_len);
981
0
      if(!qchase->qname)
982
0
        return 0; /* bad CNAME rdata */
983
0
      (*cname_skip) = i+1;
984
0
      return 1;
985
0
    }
986
0
  }
987
0
  return 0; /* CNAME classified but no matching CNAME ?! */
988
0
}
989
990
/** see if rrset has signer name as one of the rrsig signers */
991
static int
992
rrset_has_signer(struct ub_packed_rrset_key* rrset, uint8_t* name, size_t len)
993
0
{
994
0
  struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
995
0
    entry.data;
996
0
  size_t i;
997
0
  for(i = d->count; i< d->count+d->rrsig_count; i++) {
998
0
    if(d->rr_len[i] > 2+18+len) {
999
      /* at least rdatalen + signature + signame (+1 sig)*/
1000
0
      if(!dname_valid(d->rr_data[i]+2+18, d->rr_len[i]-2-18))
1001
0
        continue;
1002
0
      if(query_dname_compare(name, d->rr_data[i]+2+18) == 0)
1003
0
      {
1004
0
        return 1;
1005
0
      }
1006
0
    }
1007
0
  }
1008
0
  return 0;
1009
0
}
1010
1011
void 
1012
val_fill_reply(struct reply_info* chase, struct reply_info* orig, 
1013
  size_t skip, uint8_t* name, size_t len, uint8_t* signer)
1014
0
{
1015
0
  size_t i, j;
1016
0
  int seen_dname = 0;
1017
0
  chase->rrset_count = 0;
1018
0
  chase->an_numrrsets = 0;
1019
0
  chase->ns_numrrsets = 0;
1020
0
  chase->ar_numrrsets = 0;
1021
  /* ANSWER section */
1022
0
  for(i=skip; i<orig->an_numrrsets; i++) {
1023
0
    if(!signer) {
1024
0
      if(query_dname_compare(name, 
1025
0
        orig->rrsets[i]->rk.dname) == 0)
1026
0
        chase->rrsets[chase->an_numrrsets++] = 
1027
0
          orig->rrsets[i];
1028
0
    } else if(seen_dname && ntohs(orig->rrsets[i]->rk.type) == 
1029
0
      LDNS_RR_TYPE_CNAME) {
1030
0
      chase->rrsets[chase->an_numrrsets++] = orig->rrsets[i];
1031
0
      seen_dname = 0;
1032
0
    } else if(rrset_has_signer(orig->rrsets[i], name, len)) {
1033
0
      chase->rrsets[chase->an_numrrsets++] = orig->rrsets[i];
1034
0
      if(ntohs(orig->rrsets[i]->rk.type) == 
1035
0
        LDNS_RR_TYPE_DNAME) {
1036
0
          seen_dname = 1;
1037
0
      }
1038
0
    } else if(ntohs(orig->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME
1039
0
      && ((struct packed_rrset_data*)orig->rrsets[i]->
1040
0
      entry.data)->rrsig_count == 0 &&
1041
0
      cname_under_previous_dname(orig, i, &j) &&
1042
0
      rrset_has_signer(orig->rrsets[j], name, len)) {
1043
0
      chase->rrsets[chase->an_numrrsets++] = orig->rrsets[j];
1044
0
      chase->rrsets[chase->an_numrrsets++] = orig->rrsets[i];
1045
0
    }
1046
0
  }
1047
  /* AUTHORITY section */
1048
0
  for(i = (skip > orig->an_numrrsets)?skip:orig->an_numrrsets;
1049
0
    i<orig->an_numrrsets+orig->ns_numrrsets; 
1050
0
    i++) {
1051
0
    if(!signer) {
1052
0
      if(query_dname_compare(name, 
1053
0
        orig->rrsets[i]->rk.dname) == 0)
1054
0
        chase->rrsets[chase->an_numrrsets+
1055
0
            chase->ns_numrrsets++] = orig->rrsets[i];
1056
0
    } else if(rrset_has_signer(orig->rrsets[i], name, len)) {
1057
0
      chase->rrsets[chase->an_numrrsets+
1058
0
        chase->ns_numrrsets++] = orig->rrsets[i];
1059
0
    }
1060
0
  }
1061
  /* ADDITIONAL section */
1062
0
  for(i= (skip>orig->an_numrrsets+orig->ns_numrrsets)?
1063
0
    skip:orig->an_numrrsets+orig->ns_numrrsets; 
1064
0
    i<orig->rrset_count; i++) {
1065
0
    if(!signer) {
1066
0
      if(query_dname_compare(name, 
1067
0
        orig->rrsets[i]->rk.dname) == 0)
1068
0
          chase->rrsets[chase->an_numrrsets
1069
0
        +orig->ns_numrrsets+chase->ar_numrrsets++] 
1070
0
        = orig->rrsets[i];
1071
0
    } else if(rrset_has_signer(orig->rrsets[i], name, len)) {
1072
0
      chase->rrsets[chase->an_numrrsets+orig->ns_numrrsets+
1073
0
        chase->ar_numrrsets++] = orig->rrsets[i];
1074
0
    }
1075
0
  }
1076
0
  chase->rrset_count = chase->an_numrrsets + chase->ns_numrrsets + 
1077
0
    chase->ar_numrrsets;
1078
0
}
1079
1080
void val_reply_remove_auth(struct reply_info* rep, size_t index)
1081
0
{
1082
0
  log_assert(index < rep->rrset_count);
1083
0
  log_assert(index >= rep->an_numrrsets);
1084
0
  log_assert(index < rep->an_numrrsets+rep->ns_numrrsets);
1085
0
  memmove(rep->rrsets+index, rep->rrsets+index+1,
1086
0
    sizeof(struct ub_packed_rrset_key*)*
1087
0
    (rep->rrset_count - index - 1));
1088
0
  rep->ns_numrrsets--;
1089
0
  rep->rrset_count--;
1090
0
}
1091
1092
void
1093
val_check_nonsecure(struct module_env* env, struct reply_info* rep) 
1094
0
{
1095
0
  size_t i;
1096
  /* authority */
1097
0
  for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) {
1098
0
    if(((struct packed_rrset_data*)rep->rrsets[i]->entry.data)
1099
0
      ->security != sec_status_secure) {
1100
      /* because we want to return the authentic original
1101
       * message when presented with CD-flagged queries,
1102
       * we need to preserve AUTHORITY section data.
1103
       * However, this rrset is not signed or signed
1104
       * with the wrong keys. Validation has tried to
1105
       * verify this rrset with the keysets of import.
1106
       * But this rrset did not verify.
1107
       * Therefore the message is bogus.
1108
       */
1109
1110
      /* check if authority has an NS record
1111
       * which is bad, and there is an answer section with
1112
       * data.  In that case, delete NS and additional to 
1113
       * be lenient and make a minimal response */
1114
0
      if(rep->an_numrrsets != 0 &&
1115
0
        ntohs(rep->rrsets[i]->rk.type) 
1116
0
        == LDNS_RR_TYPE_NS) {
1117
0
        verbose(VERB_ALGO, "truncate to minimal");
1118
0
        rep->ar_numrrsets = 0;
1119
0
        rep->rrset_count = rep->an_numrrsets +
1120
0
          rep->ns_numrrsets;
1121
        /* remove this unneeded authority rrset */
1122
0
        memmove(rep->rrsets+i, rep->rrsets+i+1, 
1123
0
          sizeof(struct ub_packed_rrset_key*)*
1124
0
          (rep->rrset_count - i - 1));
1125
0
        rep->ns_numrrsets--;
1126
0
        rep->rrset_count--;
1127
0
        i--;
1128
0
        return;
1129
0
      }
1130
1131
0
      log_nametypeclass(VERB_QUERY, "message is bogus, "
1132
0
        "non secure rrset",
1133
0
        rep->rrsets[i]->rk.dname, 
1134
0
        ntohs(rep->rrsets[i]->rk.type),
1135
0
        ntohs(rep->rrsets[i]->rk.rrset_class));
1136
0
      rep->security = sec_status_bogus;
1137
0
      return;
1138
0
    }
1139
0
  }
1140
  /* additional */
1141
0
  if(!env->cfg->val_clean_additional)
1142
0
    return;
1143
0
  for(i=rep->an_numrrsets+rep->ns_numrrsets; i<rep->rrset_count; i++) {
1144
0
    if(((struct packed_rrset_data*)rep->rrsets[i]->entry.data)
1145
0
      ->security != sec_status_secure) {
1146
      /* This does not cause message invalidation. It was
1147
       * simply unsigned data in the additional. The
1148
       * RRSIG must have been truncated off the message.
1149
       *
1150
       * However, we do not want to return possible bogus
1151
       * data to clients that rely on this service for
1152
       * their authentication.
1153
       */
1154
      /* remove this unneeded additional rrset */
1155
0
      memmove(rep->rrsets+i, rep->rrsets+i+1, 
1156
0
        sizeof(struct ub_packed_rrset_key*)*
1157
0
        (rep->rrset_count - i - 1));
1158
0
      rep->ar_numrrsets--;
1159
0
      rep->rrset_count--;
1160
0
      i--;
1161
0
    }
1162
0
  }
1163
0
}
1164
1165
/** check no anchor and unlock */
1166
static int
1167
check_no_anchor(struct val_anchors* anchors, uint8_t* nm, size_t l, uint16_t c)
1168
0
{
1169
0
  struct trust_anchor* ta;
1170
0
  if((ta=anchors_lookup(anchors, nm, l, c))) {
1171
0
    lock_basic_unlock(&ta->lock);
1172
0
  }
1173
0
  return !ta;
1174
0
}
1175
1176
void 
1177
val_mark_indeterminate(struct reply_info* rep, struct val_anchors* anchors, 
1178
  struct rrset_cache* r, struct module_env* env)
1179
0
{
1180
0
  size_t i;
1181
0
  struct packed_rrset_data* d;
1182
0
  for(i=0; i<rep->rrset_count; i++) {
1183
0
    d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data;
1184
0
    if(d->security == sec_status_unchecked &&
1185
0
       check_no_anchor(anchors, rep->rrsets[i]->rk.dname,
1186
0
      rep->rrsets[i]->rk.dname_len, 
1187
0
      ntohs(rep->rrsets[i]->rk.rrset_class))) 
1188
0
    {   
1189
      /* mark as indeterminate */
1190
0
      d->security = sec_status_indeterminate;
1191
0
      rrset_update_sec_status(r, rep->rrsets[i], *env->now);
1192
0
    }
1193
0
  }
1194
0
}
1195
1196
void 
1197
val_mark_insecure(struct reply_info* rep, uint8_t* kname,
1198
  struct rrset_cache* r, struct module_env* env)
1199
0
{
1200
0
  size_t i;
1201
0
  struct packed_rrset_data* d;
1202
0
  for(i=0; i<rep->rrset_count; i++) {
1203
0
    d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data;
1204
0
    if(d->security == sec_status_unchecked &&
1205
0
       dname_subdomain_c(rep->rrsets[i]->rk.dname, kname)) {
1206
      /* mark as insecure */
1207
0
      d->security = sec_status_insecure;
1208
0
      rrset_update_sec_status(r, rep->rrsets[i], *env->now);
1209
0
    }
1210
0
  }
1211
0
}
1212
1213
size_t 
1214
val_next_unchecked(struct reply_info* rep, size_t skip)
1215
0
{
1216
0
  size_t i;
1217
0
  struct packed_rrset_data* d;
1218
0
  for(i=skip+1; i<rep->rrset_count; i++) {
1219
0
    d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data;
1220
0
    if(d->security == sec_status_unchecked) {
1221
0
      return i;
1222
0
    }
1223
0
  }
1224
0
  return rep->rrset_count;
1225
0
}
1226
1227
const char*
1228
val_classification_to_string(enum val_classification subtype)
1229
0
{
1230
0
  switch(subtype) {
1231
0
    case VAL_CLASS_UNTYPED:   return "untyped";
1232
0
    case VAL_CLASS_UNKNOWN:   return "unknown";
1233
0
    case VAL_CLASS_POSITIVE:  return "positive";
1234
0
    case VAL_CLASS_CNAME:     return "cname";
1235
0
    case VAL_CLASS_NODATA:    return "nodata";
1236
0
    case VAL_CLASS_NAMEERROR:   return "nameerror";
1237
0
    case VAL_CLASS_CNAMENOANSWER:   return "cnamenoanswer";
1238
0
    case VAL_CLASS_REFERRAL:  return "referral";
1239
0
    case VAL_CLASS_ANY:     return "qtype_any";
1240
0
    default:
1241
0
      return "bad_val_classification";
1242
0
  }
1243
0
}
1244
1245
/** log a sock_list entry */
1246
static void
1247
sock_list_logentry(enum verbosity_value v, const char* s, struct sock_list* p)
1248
0
{
1249
0
  if(p->len)
1250
0
    log_addr(v, s, &p->addr, p->len);
1251
0
  else  verbose(v, "%s cache", s);
1252
0
}
1253
1254
void val_blacklist(struct sock_list** blacklist, struct regional* region,
1255
  struct sock_list* origin, int cross)
1256
0
{
1257
  /* debug printout */
1258
0
  if(verbosity >= VERB_ALGO) {
1259
0
    struct sock_list* p;
1260
0
    for(p=*blacklist; p; p=p->next)
1261
0
      sock_list_logentry(VERB_ALGO, "blacklist", p);
1262
0
    if(!origin)
1263
0
      verbose(VERB_ALGO, "blacklist add: cache");
1264
0
    for(p=origin; p; p=p->next)
1265
0
      sock_list_logentry(VERB_ALGO, "blacklist add", p);
1266
0
  }
1267
  /* blacklist the IPs or the cache */
1268
0
  if(!origin) {
1269
    /* only add if nothing there. anything else also stops cache*/
1270
0
    if(!*blacklist)
1271
0
      sock_list_insert(blacklist, NULL, 0, region);
1272
0
  } else if(!cross)
1273
0
    sock_list_prepend(blacklist, origin);
1274
0
  else  sock_list_merge(blacklist, region, origin);
1275
0
}
1276
1277
int val_has_signed_nsecs(struct reply_info* rep, char** reason)
1278
0
{
1279
0
  size_t i, num_nsec = 0, num_nsec3 = 0;
1280
0
  struct packed_rrset_data* d;
1281
0
  for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) {
1282
0
    if(rep->rrsets[i]->rk.type == htons(LDNS_RR_TYPE_NSEC))
1283
0
      num_nsec++;
1284
0
    else if(rep->rrsets[i]->rk.type == htons(LDNS_RR_TYPE_NSEC3))
1285
0
      num_nsec3++;
1286
0
    else continue;
1287
0
    d = (struct packed_rrset_data*)rep->rrsets[i]->entry.data;
1288
0
    if(d && d->rrsig_count != 0) {
1289
0
      return 1;
1290
0
    }
1291
0
  }
1292
0
  if(num_nsec == 0 && num_nsec3 == 0)
1293
0
    *reason = "no DNSSEC records";
1294
0
  else if(num_nsec != 0)
1295
0
    *reason = "no signatures over NSECs";
1296
0
  else  *reason = "no signatures over NSEC3s";
1297
0
  return 0;
1298
0
}
1299
1300
struct dns_msg* 
1301
val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t c, 
1302
  struct regional* region, uint8_t* topname)
1303
0
{
1304
0
  struct dns_msg* msg;
1305
0
  struct query_info qinfo;
1306
0
  struct ub_packed_rrset_key *rrset = rrset_cache_lookup(
1307
0
    env->rrset_cache, nm, nmlen, LDNS_RR_TYPE_DS, c, 0, 
1308
0
    *env->now, 0);
1309
0
  if(rrset) {
1310
    /* DS rrset exists. Return it to the validator immediately*/
1311
0
    struct ub_packed_rrset_key* copy = packed_rrset_copy_region(
1312
0
      rrset, region, *env->now);
1313
0
    lock_rw_unlock(&rrset->entry.lock);
1314
0
    if(!copy)
1315
0
      return NULL;
1316
0
    msg = dns_msg_create(nm, nmlen, LDNS_RR_TYPE_DS, c, region, 1);
1317
0
    if(!msg)
1318
0
      return NULL;
1319
0
    msg->rep->rrsets[0] = copy;
1320
0
    msg->rep->rrset_count++;
1321
0
    msg->rep->an_numrrsets++;
1322
0
    return msg;
1323
0
  }
1324
  /* lookup in rrset and negative cache for NSEC/NSEC3 */
1325
0
  qinfo.qname = nm;
1326
0
  qinfo.qname_len = nmlen;
1327
0
  qinfo.qtype = LDNS_RR_TYPE_DS;
1328
0
  qinfo.qclass = c;
1329
0
  qinfo.local_alias = NULL;
1330
  /* do not add SOA to reply message, it is going to be used internal */
1331
0
  msg = val_neg_getmsg(env->neg_cache, &qinfo, region, env->rrset_cache,
1332
0
    env->scratch_buffer, *env->now, 0, topname, env->cfg);
1333
0
  return msg;
1334
0
}