Coverage Report

Created: 2025-08-03 06:33

/src/bind9/lib/dns/validator.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
5
 *
6
 * This Source Code Form is subject to the terms of the Mozilla Public
7
 * License, v. 2.0. If a copy of the MPL was not distributed with this
8
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9
 *
10
 * See the COPYRIGHT file distributed with this work for additional
11
 * information regarding copyright ownership.
12
 */
13
14
#include <inttypes.h>
15
#include <stdbool.h>
16
17
#include <isc/async.h>
18
#include <isc/atomic.h>
19
#include <isc/base32.h>
20
#include <isc/counter.h>
21
#include <isc/helper.h>
22
#include <isc/job.h>
23
#include <isc/log.h>
24
#include <isc/md.h>
25
#include <isc/mem.h>
26
#include <isc/refcount.h>
27
#include <isc/result.h>
28
#include <isc/string.h>
29
#include <isc/tid.h>
30
#include <isc/util.h>
31
#include <isc/work.h>
32
33
#include <dns/client.h>
34
#include <dns/db.h>
35
#include <dns/dnssec.h>
36
#include <dns/ds.h>
37
#include <dns/ede.h>
38
#include <dns/keytable.h>
39
#include <dns/keyvalues.h>
40
#include <dns/message.h>
41
#include <dns/ncache.h>
42
#include <dns/nsec.h>
43
#include <dns/nsec3.h>
44
#include <dns/rdata.h>
45
#include <dns/rdataset.h>
46
#include <dns/rdatatype.h>
47
#include <dns/resolver.h>
48
#include <dns/validator.h>
49
#include <dns/view.h>
50
51
/*! \file
52
 * \brief
53
 * Basic processing sequences:
54
 *
55
 * \li When called with rdataset and sigrdataset:
56
 *     validator_start -> validate_answer -> proveunsecure
57
 *     validator_start -> validate_answer -> validate_nx (if secure wildcard)
58
 *
59
 * \li When called with rdataset but no sigrdataset:
60
 *     validator_start -> proveunsecure
61
 *
62
 * \li When called with no rdataset or sigrdataset:
63
 *     validator_start -> validate_nx -> proveunsecure
64
 *
65
 * validator_start:   determine what type of validation to do.
66
 * validate_answer:   attempt to perform a positive validation.
67
 * proveunsecure:     attempt to prove the answer comes from an unsecure zone.
68
 * validate_nx:       attempt to prove a negative response.
69
 */
70
71
0
#define VALIDATOR_MAGIC    ISC_MAGIC('V', 'a', 'l', '?')
72
#define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
73
74
enum valattr {
75
  VALATTR_CANCELED = 1 << 1,       /*%< Canceled. */
76
  VALATTR_TRIEDVERIFY = 1 << 2,      /*%< We have found a key and have
77
            attempted a verify. */
78
  VALATTR_COMPLETE = 1 << 3,       /*%< Completion event sent. */
79
  VALATTR_INSECURITY = 1 << 4,       /*%< Attempting proveunsecure. */
80
  VALATTR_MAXVALIDATIONS = 1 << 5,     /*%< Max validations quota */
81
  VALATTR_MAXVALIDATIONFAILS = 1 << 6, /*%< Max validation fails
82
            quota */
83
  VALATTR_OFFLOADED = 1 << 7, /*%< The ownership has been passed to
84
               offloaded thread */
85
86
  /*!
87
   * NSEC proofs to be looked for.
88
   */
89
  VALATTR_NEEDNOQNAME = 1 << 8,
90
  VALATTR_NEEDNOWILDCARD = 1 << 9,
91
  VALATTR_NEEDNODATA = 1 << 10,
92
93
  /*!
94
   * NSEC proofs that have been found.
95
   */
96
  VALATTR_FOUNDNOQNAME = 1 << 12,
97
  VALATTR_FOUNDNOWILDCARD = 1 << 13,
98
  VALATTR_FOUNDNODATA = 1 << 14,
99
  VALATTR_FOUNDCLOSEST = 1 << 15,
100
  VALATTR_FOUNDOPTOUT = 1 << 16,
101
  VALATTR_FOUNDUNKNOWN = 1 << 17,
102
};
103
104
0
#define NEEDNODATA(val)      ((val->attributes & VALATTR_NEEDNODATA) != 0)
105
0
#define NEEDNOQNAME(val)     ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
106
0
#define NEEDNOWILDCARD(val)  ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
107
0
#define FOUNDNODATA(val)     ((val->attributes & VALATTR_FOUNDNODATA) != 0)
108
0
#define FOUNDNOQNAME(val)    ((val->attributes & VALATTR_FOUNDNOQNAME) != 0)
109
0
#define FOUNDNOWILDCARD(val) ((val->attributes & VALATTR_FOUNDNOWILDCARD) != 0)
110
0
#define FOUNDCLOSEST(val)    ((val->attributes & VALATTR_FOUNDCLOSEST) != 0)
111
0
#define FOUNDOPTOUT(val)     ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
112
113
0
#define CANCELING(v) atomic_load(&(v)->canceling)
114
0
#define CANCELED(v)  (((v)->attributes & VALATTR_CANCELED) != 0)
115
0
#define OFFLOADED(v) (((v)->attributes & VALATTR_OFFLOADED) != 0)
116
0
#define COMPLETE(v)  (((v)->attributes & VALATTR_COMPLETE) != 0)
117
118
0
#define NEGATIVE(r) (((r)->attributes.negative))
119
0
#define NXDOMAIN(r) (((r)->attributes.nxdomain))
120
121
0
#define MAXVALIDATIONS(r) (((r)->attributes & VALATTR_MAXVALIDATIONS) != 0)
122
#define MAXVALIDATIONFAILS(r) \
123
0
  (((r)->attributes & VALATTR_MAXVALIDATIONFAILS) != 0)
124
125
static void
126
destroy_validator(dns_validator_t *val);
127
128
static isc_result_t
129
select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset);
130
131
static void
132
resume_answer(void *arg);
133
static void
134
validate_async_done(dns_validator_t *val, isc_result_t result);
135
static isc_result_t
136
validate_async_run(dns_validator_t *val, isc_job_cb cb);
137
static isc_result_t
138
validate_helper_run(dns_validator_t *val, isc_job_cb cb);
139
140
static void
141
validate_dnskey(void *arg);
142
static void
143
validate_dnskey_dsset_done(dns_validator_t *val, isc_result_t result);
144
145
static isc_result_t
146
validate_nx(dns_validator_t *val, bool resume);
147
148
static isc_result_t
149
proveunsecure(dns_validator_t *val, bool have_ds, bool have_dnskey,
150
        bool resume);
151
152
static void
153
validator_logv(dns_validator_t *val, isc_logcategory_t category,
154
         isc_logmodule_t module, int level, const char *fmt, va_list ap)
155
  ISC_FORMAT_PRINTF(5, 0);
156
157
static void
158
validator_log(void *val, int level, const char *fmt, ...)
159
  ISC_FORMAT_PRINTF(3, 4);
160
161
static void
162
validator_logcreate(dns_validator_t *val, dns_name_t *name,
163
        dns_rdatatype_t type, const char *caller,
164
        const char *operation);
165
166
static isc_result_t
167
create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
168
       isc_job_cb callback, const char *caller);
169
170
/*%
171
 * Ensure the validator's rdatasets are marked as expired.
172
 */
173
static void
174
0
expire_rdatasets(dns_validator_t *val) {
175
0
  if (dns_rdataset_isassociated(&val->frdataset)) {
176
0
    dns_rdataset_expire(&val->frdataset);
177
0
  }
178
0
  if (dns_rdataset_isassociated(&val->fsigrdataset)) {
179
0
    dns_rdataset_expire(&val->fsigrdataset);
180
0
  }
181
0
}
182
183
static void
184
validate_extendederror(dns_validator_t *val);
185
186
static void
187
validator_addede(dns_validator_t *val, uint16_t code, const char *extra);
188
189
/*%
190
 * Ensure the validator's rdatasets are disassociated.
191
 */
192
static void
193
0
disassociate_rdatasets(dns_validator_t *val) {
194
0
  if (dns_rdataset_isassociated(&val->fdsset)) {
195
0
    dns_rdataset_disassociate(&val->fdsset);
196
0
  }
197
0
  if (dns_rdataset_isassociated(&val->frdataset)) {
198
0
    dns_rdataset_disassociate(&val->frdataset);
199
0
  }
200
0
  if (dns_rdataset_isassociated(&val->fsigrdataset)) {
201
0
    dns_rdataset_disassociate(&val->fsigrdataset);
202
0
  }
203
0
}
204
205
/*%
206
 * Mark the rdatasets in val->vstat with trust level "answer",
207
 * indicating that they did not validate, but could be cached as insecure.
208
 */
209
static isc_result_t
210
0
markanswer(dns_validator_t *val, const char *where) {
211
0
  validator_log(val, ISC_LOG_DEBUG(3), "marking as answer (%s)", where);
212
0
  if (val->rdataset != NULL) {
213
0
    dns_rdataset_settrust(val->rdataset, dns_trust_answer);
214
0
  }
215
0
  if (val->sigrdataset != NULL) {
216
0
    dns_rdataset_settrust(val->sigrdataset, dns_trust_answer);
217
0
  }
218
219
0
  return ISC_R_SUCCESS;
220
0
}
221
222
/*%
223
 * Mark the RRsets in val->vstat with trust level secure.
224
 */
225
static void
226
0
marksecure(dns_validator_t *val) {
227
0
  dns_rdataset_settrust(val->rdataset, dns_trust_secure);
228
0
  if (val->sigrdataset != NULL) {
229
0
    dns_rdataset_settrust(val->sigrdataset, dns_trust_secure);
230
0
  }
231
0
  val->secure = true;
232
0
}
233
234
/*
235
 * Validator 'val' is finished; send the completion event to the loop
236
 * that called dns_validator_create(), with result `result`.
237
 */
238
static void
239
0
validator_done(dns_validator_t *val, isc_result_t result) {
240
0
  if (COMPLETE(val)) {
241
0
    return;
242
0
  }
243
244
0
  val->attributes |= VALATTR_COMPLETE;
245
0
  val->result = result;
246
247
0
  dns_ede_copy(val->cb_edectx, &val->edectx);
248
249
0
  isc_async_run(val->loop, val->cb, val);
250
0
}
251
252
/*%
253
 * Look in the NSEC record returned from a DS query to see if there is
254
 * a NS RRset at this name.  If it is found we are at a delegation point.
255
 */
256
static bool
257
isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
258
0
       isc_result_t dbresult) {
259
0
  dns_fixedname_t fixed;
260
0
  dns_label_t hashlabel;
261
0
  dns_name_t nsec3name;
262
0
  dns_rdata_nsec3_t nsec3;
263
0
  dns_rdataset_t set;
264
0
  int order;
265
0
  int scope;
266
0
  bool found;
267
0
  isc_buffer_t buffer;
268
0
  isc_result_t result;
269
0
  unsigned char hash[NSEC3_MAX_HASH_LENGTH];
270
0
  unsigned char owner[NSEC3_MAX_HASH_LENGTH];
271
0
  unsigned int length;
272
273
0
  REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
274
275
0
  dns_rdataset_init(&set);
276
0
  if (dbresult == DNS_R_NXRRSET) {
277
0
    dns_rdataset_clone(rdataset, &set);
278
0
  } else {
279
0
    result = dns_ncache_getrdataset(rdataset, name,
280
0
            dns_rdatatype_nsec, &set);
281
0
    if (result == ISC_R_NOTFOUND) {
282
0
      goto trynsec3;
283
0
    }
284
0
    if (result != ISC_R_SUCCESS) {
285
0
      return false;
286
0
    }
287
0
  }
288
289
0
  INSIST(set.type == dns_rdatatype_nsec);
290
291
0
  found = false;
292
0
  result = dns_rdataset_first(&set);
293
0
  if (result == ISC_R_SUCCESS) {
294
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
295
0
    dns_rdataset_current(&set, &rdata);
296
0
    found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
297
0
  }
298
0
  dns_rdataset_disassociate(&set);
299
0
  return found;
300
301
0
trynsec3:
302
  /*
303
   * Iterate over the ncache entry.
304
   */
305
0
  found = false;
306
0
  dns_name_init(&nsec3name);
307
0
  dns_fixedname_init(&fixed);
308
0
  dns_name_downcase(name, dns_fixedname_name(&fixed));
309
0
  name = dns_fixedname_name(&fixed);
310
0
  DNS_RDATASET_FOREACH (rdataset) {
311
0
    dns_ncache_current(rdataset, &nsec3name, &set);
312
0
    if (set.type != dns_rdatatype_nsec3) {
313
0
      dns_rdataset_disassociate(&set);
314
0
      continue;
315
0
    }
316
0
    dns_name_getlabel(&nsec3name, 0, &hashlabel);
317
0
    isc_region_consume(&hashlabel, 1);
318
0
    isc_buffer_init(&buffer, owner, sizeof(owner));
319
0
    result = isc_base32hexnp_decoderegion(&hashlabel, &buffer);
320
0
    if (result != ISC_R_SUCCESS) {
321
0
      dns_rdataset_disassociate(&set);
322
0
      continue;
323
0
    }
324
0
    DNS_RDATASET_FOREACH (&set) {
325
0
      dns_rdata_t rdata = DNS_RDATA_INIT;
326
0
      dns_rdataset_current(&set, &rdata);
327
0
      (void)dns_rdata_tostruct(&rdata, &nsec3, NULL);
328
0
      if (nsec3.hash != 1) {
329
0
        continue;
330
0
      }
331
0
      length = isc_iterated_hash(
332
0
        hash, nsec3.hash, nsec3.iterations, nsec3.salt,
333
0
        nsec3.salt_length, name->ndata, name->length);
334
0
      if (length != isc_buffer_usedlength(&buffer)) {
335
0
        continue;
336
0
      }
337
0
      order = memcmp(hash, owner, length);
338
0
      if (order == 0) {
339
0
        found = dns_nsec3_typepresent(&rdata,
340
0
                    dns_rdatatype_ns);
341
0
        dns_rdataset_disassociate(&set);
342
0
        return found;
343
0
      }
344
0
      if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) == 0) {
345
0
        continue;
346
0
      }
347
      /*
348
       * Does this optout span cover the name?
349
       */
350
0
      scope = memcmp(owner, nsec3.next, nsec3.next_length);
351
0
      if ((scope < 0 && order > 0 &&
352
0
           memcmp(hash, nsec3.next, length) < 0) ||
353
0
          (scope >= 0 &&
354
0
           (order > 0 ||
355
0
            memcmp(hash, nsec3.next, length) < 0)))
356
0
      {
357
0
        dns_rdataset_disassociate(&set);
358
0
        return true;
359
0
      }
360
0
    }
361
0
    dns_rdataset_disassociate(&set);
362
0
  }
363
0
  return found;
364
0
}
365
366
static void
367
resume_answer_with_key_done(void *arg);
368
369
static void
370
0
resume_answer_with_key(void *arg) {
371
0
  dns_validator_t *val = arg;
372
0
  dns_rdataset_t *rdataset = &val->frdataset;
373
374
0
  isc_result_t result = select_signing_key(val, rdataset);
375
0
  if (result == ISC_R_SUCCESS) {
376
0
    val->keyset = &val->frdataset;
377
0
  }
378
379
0
  (void)validate_async_run(val, resume_answer_with_key_done);
380
0
}
381
382
static void
383
0
resume_answer_with_key_done(void *arg) {
384
0
  dns_validator_t *val = arg;
385
386
0
  resume_answer(val);
387
0
}
388
389
/*%
390
 * We have been asked to look for a key.
391
 * If found, resume the validation process.
392
 * If not found, fail the validation process.
393
 */
394
static void
395
0
fetch_callback_dnskey(void *arg) {
396
0
  dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
397
0
  dns_validator_t *val = resp->arg;
398
0
  dns_rdataset_t *rdataset = &val->frdataset;
399
0
  isc_result_t eresult = resp->result;
400
0
  isc_result_t result;
401
0
  bool trustchain;
402
403
  /*
404
   * Set 'trustchain' to true if we're walking a chain of
405
   * trust; false if we're attempting to prove insecurity.
406
   */
407
0
  trustchain = ((val->attributes & VALATTR_INSECURITY) == 0);
408
409
  /* Free resources which are not of interest. */
410
0
  if (resp->node != NULL) {
411
0
    dns_db_detachnode(resp->db, &resp->node);
412
0
  }
413
0
  if (resp->db != NULL) {
414
0
    dns_db_detach(&resp->db);
415
0
  }
416
0
  if (dns_rdataset_isassociated(&val->fsigrdataset)) {
417
0
    dns_rdataset_disassociate(&val->fsigrdataset);
418
0
  }
419
420
0
  validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_dnskey");
421
422
0
  dns_resolver_destroyfetch(&val->fetch);
423
424
0
  if (CANCELED(val) || CANCELING(val)) {
425
0
    result = ISC_R_CANCELED;
426
0
    goto cleanup;
427
0
  }
428
429
0
  if (trustchain) {
430
0
    switch (eresult) {
431
0
    case ISC_R_SUCCESS:
432
0
    case DNS_R_NCACHENXRRSET:
433
      /*
434
       * We have an answer to our DNSKEY query.  Either the
435
       * DNSKEY RRset or a NODATA response.
436
       */
437
0
      validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s",
438
0
              eresult == ISC_R_SUCCESS
439
0
                ? "keyset"
440
0
                : "NCACHENXRRSET",
441
0
              dns_trust_totext(rdataset->trust));
442
      /*
443
       * Only extract the dst key if the keyset exists and is
444
       * secure.
445
       */
446
0
      if (eresult == ISC_R_SUCCESS &&
447
0
          rdataset->trust >= dns_trust_secure)
448
0
      {
449
0
        result = validate_helper_run(
450
0
          val, resume_answer_with_key);
451
0
      } else {
452
0
        result = validate_async_run(val, resume_answer);
453
0
      }
454
0
      break;
455
0
    default:
456
0
      validator_log(val, ISC_LOG_DEBUG(3),
457
0
              "fetch_callback_dnskey: got %s",
458
0
              isc_result_totext(eresult));
459
0
      result = DNS_R_BROKENCHAIN;
460
0
      break;
461
0
    }
462
0
  } else {
463
0
    switch (eresult) {
464
0
    case ISC_R_SUCCESS:
465
      /*
466
       * We have a DS (val->dsrdataset) and
467
       * DNSKEY (val->fdataset).
468
       */
469
0
      result = proveunsecure(val, false, true, true);
470
0
      break;
471
0
    default:
472
0
      validator_log(val, ISC_LOG_DEBUG(3),
473
0
              "fetch_callback_dnskey: got %s",
474
0
              isc_result_totext(eresult));
475
0
      result = DNS_R_BROKENCHAIN;
476
0
      break;
477
0
    }
478
0
  }
479
480
0
cleanup:
481
0
  dns_resolver_freefresp(&resp);
482
0
  validate_async_done(val, result);
483
0
  dns_validator_detach(&val);
484
0
}
485
486
/*%
487
 * We have been asked to look for a DS. This may be part of
488
 * walking a trust chain, or an insecurity proof.
489
 */
490
static void
491
0
fetch_callback_ds(void *arg) {
492
0
  dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
493
0
  dns_validator_t *val = resp->arg;
494
0
  dns_rdataset_t *rdataset = &val->frdataset;
495
0
  isc_result_t eresult = resp->result;
496
0
  isc_result_t result;
497
0
  bool trustchain;
498
499
  /*
500
   * Set 'trustchain' to true if we're walking a chain of
501
   * trust; false if we're attempting to prove insecurity.
502
   */
503
0
  trustchain = ((val->attributes & VALATTR_INSECURITY) == 0);
504
505
  /* Free resources which are not of interest. */
506
0
  if (resp->node != NULL) {
507
0
    dns_db_detachnode(resp->db, &resp->node);
508
0
  }
509
0
  if (resp->db != NULL) {
510
0
    dns_db_detach(&resp->db);
511
0
  }
512
0
  if (dns_rdataset_isassociated(&val->fsigrdataset)) {
513
0
    dns_rdataset_disassociate(&val->fsigrdataset);
514
0
  }
515
516
0
  validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_ds");
517
518
0
  dns_resolver_destroyfetch(&val->fetch);
519
520
0
  if (CANCELED(val) || CANCELING(val)) {
521
0
    result = ISC_R_CANCELED;
522
0
    goto cleanup;
523
0
  }
524
525
0
  if (trustchain) {
526
0
    switch (eresult) {
527
0
    case ISC_R_SUCCESS:
528
      /*
529
       * We looked for a DS record as part of
530
       * following a key chain upwards; resume following
531
       * the chain.
532
       */
533
0
      validator_log(val, ISC_LOG_DEBUG(3),
534
0
              "dsset with trust %s",
535
0
              dns_trust_totext(rdataset->trust));
536
0
      val->dsset = &val->frdataset;
537
0
      result = validate_async_run(val, validate_dnskey);
538
0
      break;
539
0
    case DNS_R_CNAME:
540
0
    case DNS_R_NXRRSET:
541
0
    case DNS_R_NCACHENXRRSET:
542
0
    case DNS_R_SERVFAIL: /* RFC 1034 parent? */
543
      /*
544
       * Failed to find a DS while following the
545
       * chain of trust; now we need to prove insecurity.
546
       */
547
0
      validator_log(val, ISC_LOG_DEBUG(3),
548
0
              "falling back to insecurity proof (%s)",
549
0
              isc_result_totext(eresult));
550
0
      result = proveunsecure(val, false, false, false);
551
0
      break;
552
0
    default:
553
0
      validator_log(val, ISC_LOG_DEBUG(3),
554
0
              "fetch_callback_ds: got %s",
555
0
              isc_result_totext(eresult));
556
0
      result = DNS_R_BROKENCHAIN;
557
0
      break;
558
0
    }
559
0
  } else {
560
0
    switch (eresult) {
561
0
    case DNS_R_NXDOMAIN:
562
0
    case DNS_R_NCACHENXDOMAIN:
563
      /*
564
       * These results only make sense if we're attempting
565
       * an insecurity proof, not when walking a chain of
566
       * trust.
567
       */
568
569
0
      result = proveunsecure(val, false, false, true);
570
0
      break;
571
0
    case ISC_R_SUCCESS:
572
      /*
573
       * There is a DS which may or may not be a zone cut.
574
       * In either case we are still in a secure zone,
575
       * so keep looking for the break in the chain
576
       * of trust.
577
       */
578
0
      result = proveunsecure(val, true, false, true);
579
0
      break;
580
0
    case DNS_R_NXRRSET:
581
0
    case DNS_R_NCACHENXRRSET:
582
0
      if (isdelegation(resp->foundname, &val->frdataset,
583
0
           eresult))
584
0
      {
585
        /*
586
         * Failed to find a DS while trying to prove
587
         * insecurity. If this is a zone cut, that
588
         * means we're insecure.
589
         */
590
0
        result = markanswer(val, "fetch_callback_ds");
591
0
        break;
592
0
      }
593
0
      FALLTHROUGH;
594
0
    case DNS_R_CNAME:
595
      /*
596
       * Not a zone cut, so we have to keep looking for
597
       * the break point in the chain of trust.
598
       */
599
0
      result = proveunsecure(val, false, false, true);
600
0
      break;
601
0
    default:
602
0
      validator_log(val, ISC_LOG_DEBUG(3),
603
0
              "fetch_callback_ds: got %s",
604
0
              isc_result_totext(eresult));
605
0
      result = DNS_R_BROKENCHAIN;
606
0
      break;
607
0
    }
608
0
  }
609
610
0
cleanup:
611
0
  dns_resolver_freefresp(&resp);
612
0
  validate_async_done(val, result);
613
0
  dns_validator_detach(&val);
614
0
}
615
616
/*%
617
 * Callback from when a DNSKEY RRset has been validated.
618
 *
619
 * Resumes the stalled validation process.
620
 */
621
static void
622
0
validator_callback_dnskey(void *arg) {
623
0
  dns_validator_t *subvalidator = (dns_validator_t *)arg;
624
0
  dns_validator_t *val = subvalidator->parent;
625
0
  isc_result_t result = subvalidator->result;
626
627
0
  val->subvalidator = NULL;
628
629
0
  if (CANCELED(val) || CANCELING(val)) {
630
0
    result = ISC_R_CANCELED;
631
0
    goto cleanup;
632
0
  }
633
634
0
  validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_dnskey");
635
0
  if (result == ISC_R_SUCCESS) {
636
0
    validator_log(val, ISC_LOG_DEBUG(3), "keyset with trust %s",
637
0
            dns_trust_totext(val->frdataset.trust));
638
    /*
639
     * Only extract the dst key if the keyset is secure.
640
     */
641
0
    if (val->frdataset.trust >= dns_trust_secure) {
642
0
      result = validate_helper_run(val,
643
0
                 resume_answer_with_key);
644
0
    } else {
645
0
      result = validate_async_run(val, resume_answer);
646
0
    }
647
0
  } else {
648
0
    validator_log(val, ISC_LOG_DEBUG(3),
649
0
            "validator_callback_dnskey: got %s",
650
0
            isc_result_totext(result));
651
0
    if (result != DNS_R_BROKENCHAIN) {
652
0
      expire_rdatasets(val);
653
0
      result = create_fetch(val, &val->siginfo->signer,
654
0
                dns_rdatatype_dnskey,
655
0
                fetch_callback_dnskey,
656
0
                "validator_callback_dnskey");
657
0
      if (result == ISC_R_SUCCESS) {
658
0
        result = DNS_R_WAIT;
659
0
      }
660
0
    }
661
0
  }
662
663
0
cleanup:
664
0
  dns_validator_detach(&subvalidator->parent);
665
0
  dns_validator_shutdown(subvalidator);
666
0
  dns_validator_detach(&subvalidator);
667
0
  validate_async_done(val, result);
668
0
}
669
670
/*%
671
 * Callback when the DS record has been validated.
672
 *
673
 * Resumes validation of the zone key or the unsecure zone proof.
674
 */
675
static void
676
0
validator_callback_ds(void *arg) {
677
0
  dns_validator_t *subvalidator = (dns_validator_t *)arg;
678
0
  dns_validator_t *val = subvalidator->parent;
679
0
  isc_result_t result = subvalidator->result;
680
681
0
  val->subvalidator = NULL;
682
683
0
  if (CANCELED(val) || CANCELING(val)) {
684
0
    result = ISC_R_CANCELED;
685
0
    goto cleanup;
686
0
  }
687
688
0
  validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_ds");
689
0
  if (result == ISC_R_SUCCESS) {
690
0
    bool have_dsset;
691
0
    dns_name_t *name;
692
0
    validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s",
693
0
            val->frdataset.type == dns_rdatatype_ds
694
0
              ? "dsset"
695
0
              : "ds non-existence",
696
0
            dns_trust_totext(val->frdataset.trust));
697
0
    have_dsset = (val->frdataset.type == dns_rdatatype_ds);
698
0
    name = dns_fixedname_name(&val->fname);
699
0
    if ((val->attributes & VALATTR_INSECURITY) != 0 &&
700
0
        val->frdataset.covers == dns_rdatatype_ds &&
701
0
        NEGATIVE(&val->frdataset) &&
702
0
        isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET))
703
0
    {
704
0
      result = markanswer(val, "validator_callback_ds");
705
0
    } else if ((val->attributes & VALATTR_INSECURITY) != 0) {
706
0
      result = proveunsecure(val, have_dsset, false, true);
707
0
    } else {
708
0
      result = validate_async_run(val, validate_dnskey);
709
0
    }
710
0
  } else {
711
0
    validator_log(val, ISC_LOG_DEBUG(3),
712
0
            "validator_callback_ds: got %s",
713
0
            isc_result_totext(result));
714
0
    if (result != DNS_R_BROKENCHAIN) {
715
0
      expire_rdatasets(val);
716
0
      result = create_fetch(val, val->name, dns_rdatatype_ds,
717
0
                fetch_callback_ds,
718
0
                "validator_callback_ds");
719
0
      if (result == ISC_R_SUCCESS) {
720
0
        result = DNS_R_WAIT;
721
0
      }
722
0
    }
723
0
  }
724
725
0
cleanup:
726
0
  dns_validator_detach(&subvalidator->parent);
727
0
  dns_validator_shutdown(subvalidator);
728
0
  dns_validator_detach(&subvalidator);
729
0
  validate_async_done(val, result);
730
0
}
731
732
/*%
733
 * Callback when the CNAME record has been validated.
734
 *
735
 * Resumes validation of the unsecure zone proof.
736
 */
737
static void
738
0
validator_callback_cname(void *arg) {
739
0
  dns_validator_t *subvalidator = (dns_validator_t *)arg;
740
0
  dns_validator_t *val = subvalidator->parent;
741
0
  isc_result_t result;
742
0
  isc_result_t eresult = subvalidator->result;
743
744
0
  INSIST((val->attributes & VALATTR_INSECURITY) != 0);
745
746
0
  val->subvalidator = NULL;
747
748
0
  if (CANCELED(val) || CANCELING(val)) {
749
0
    result = ISC_R_CANCELED;
750
0
    goto cleanup;
751
0
  }
752
753
0
  validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_cname");
754
0
  if (eresult == ISC_R_SUCCESS) {
755
0
    validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s",
756
0
            dns_trust_totext(val->frdataset.trust));
757
0
    result = proveunsecure(val, false, false, true);
758
0
  } else {
759
0
    if (eresult != DNS_R_BROKENCHAIN) {
760
0
      expire_rdatasets(val);
761
0
    }
762
0
    validator_log(val, ISC_LOG_DEBUG(3),
763
0
            "validator_callback_cname: got %s",
764
0
            isc_result_totext(eresult));
765
0
    result = DNS_R_BROKENCHAIN;
766
0
  }
767
768
0
cleanup:
769
0
  dns_validator_detach(&subvalidator->parent);
770
0
  dns_validator_shutdown(subvalidator);
771
0
  dns_validator_detach(&subvalidator);
772
0
  validate_async_done(val, result);
773
0
}
774
775
/*%
776
 * Callback for when NSEC records have been validated.
777
 *
778
 * Looks for NOQNAME, NODATA and OPTOUT proofs.
779
 *
780
 * Resumes the negative response validation by calling validate_nx().
781
 */
782
static void
783
0
validator_callback_nsec(void *arg) {
784
0
  dns_validator_t *subvalidator = (dns_validator_t *)arg;
785
0
  dns_validator_t *val = subvalidator->parent;
786
0
  dns_rdataset_t *rdataset = subvalidator->rdataset;
787
0
  isc_result_t result;
788
0
  isc_result_t eresult = subvalidator->result;
789
0
  bool exists, data;
790
791
0
  val->subvalidator = NULL;
792
793
0
  if (CANCELED(val) || CANCELING(val)) {
794
0
    result = ISC_R_CANCELED;
795
0
    goto cleanup;
796
0
  }
797
798
0
  validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_nsec");
799
0
  if (eresult == ISC_R_SUCCESS) {
800
0
    dns_name_t **proofs = val->proofs;
801
0
    dns_name_t *wild = dns_fixedname_name(&val->wild);
802
803
0
    if (rdataset->type == dns_rdatatype_nsec &&
804
0
        rdataset->trust == dns_trust_secure &&
805
0
        (NEEDNODATA(val) || NEEDNOQNAME(val)) &&
806
0
        !FOUNDNODATA(val) && !FOUNDNOQNAME(val) &&
807
0
        dns_nsec_noexistnodata(val->type, val->name,
808
0
             subvalidator->name, rdataset,
809
0
             &exists, &data, wild, validator_log,
810
0
             val) == ISC_R_SUCCESS)
811
0
    {
812
0
      if (exists && !data) {
813
0
        val->attributes |= VALATTR_FOUNDNODATA;
814
0
        if (NEEDNODATA(val)) {
815
0
          proofs[DNS_VALIDATOR_NODATAPROOF] =
816
0
            subvalidator->name;
817
0
        }
818
0
      }
819
0
      if (!exists) {
820
0
        dns_name_t *closest = NULL;
821
0
        unsigned int clabels;
822
823
0
        val->attributes |= VALATTR_FOUNDNOQNAME;
824
825
0
        closest = dns_fixedname_name(&val->closest);
826
0
        clabels = dns_name_countlabels(closest);
827
        /*
828
         * If we are validating a wildcard response
829
         * clabels will not be zero.  We then need
830
         * to check if the generated wildcard from
831
         * dns_nsec_noexistnodata is consistent with
832
         * the wildcard used to generate the response.
833
         */
834
0
        if (clabels == 0 ||
835
0
            dns_name_countlabels(wild) == clabels + 1)
836
0
        {
837
0
          val->attributes |= VALATTR_FOUNDCLOSEST;
838
0
        }
839
        /*
840
         * The NSEC noqname proof also contains
841
         * the closest encloser.
842
         */
843
0
        if (NEEDNOQNAME(val)) {
844
0
          proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
845
0
            subvalidator->name;
846
0
        }
847
0
      }
848
0
    }
849
850
0
    result = validate_nx(val, true);
851
0
  } else {
852
0
    validator_log(val, ISC_LOG_DEBUG(3),
853
0
            "validator_callback_nsec: got %s",
854
0
            isc_result_totext(eresult));
855
0
    switch (eresult) {
856
0
    case ISC_R_CANCELED:
857
0
    case ISC_R_SHUTTINGDOWN:
858
0
      result = eresult;
859
0
      break;
860
0
    case DNS_R_BROKENCHAIN:
861
0
      val->authfail++;
862
0
      FALLTHROUGH;
863
0
    default:
864
0
      result = validate_nx(val, true);
865
0
      break;
866
0
    }
867
0
  }
868
869
0
cleanup:
870
0
  dns_validator_detach(&subvalidator->parent);
871
0
  dns_validator_shutdown(subvalidator);
872
0
  dns_validator_detach(&subvalidator);
873
0
  validate_async_done(val, result);
874
0
}
875
876
/*%
877
 * Looks for the requested name and type in the view (zones and cache).
878
 *
879
 * Returns:
880
 * \li  ISC_R_SUCCESS
881
 * \li  ISC_R_NOTFOUND
882
 * \li  DNS_R_NCACHENXDOMAIN
883
 * \li  DNS_R_NCACHENXRRSET
884
 * \li  DNS_R_NXRRSET
885
 * \li  DNS_R_NXDOMAIN
886
 * \li  DNS_R_BROKENCHAIN
887
 */
888
static isc_result_t
889
0
view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
890
0
  dns_fixedname_t fixedname;
891
0
  dns_name_t *foundname;
892
0
  isc_result_t result;
893
0
  unsigned int options;
894
895
0
  disassociate_rdatasets(val);
896
897
0
  options = DNS_DBFIND_PENDINGOK;
898
0
  foundname = dns_fixedname_initname(&fixedname);
899
0
  result = dns_view_find(val->view, name, type, 0, options, false, false,
900
0
             NULL, NULL, foundname, &val->frdataset,
901
0
             &val->fsigrdataset);
902
903
0
  if (result == DNS_R_NXDOMAIN) {
904
0
    goto notfound;
905
0
  } else if (result != ISC_R_SUCCESS && result != DNS_R_NCACHENXDOMAIN &&
906
0
       result != DNS_R_NCACHENXRRSET && result != DNS_R_EMPTYNAME &&
907
0
       result != DNS_R_NXRRSET && result != ISC_R_NOTFOUND)
908
0
  {
909
0
    result = ISC_R_NOTFOUND;
910
0
    goto notfound;
911
0
  }
912
913
0
  return result;
914
915
0
notfound:
916
0
  disassociate_rdatasets(val);
917
918
0
  return result;
919
0
}
920
921
/*%
922
 * Checks to make sure we are not going to loop.  As we use a SHARED fetch
923
 * the validation process will stall if looping was to occur.
924
 */
925
static bool
926
check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
927
0
         dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
928
0
  dns_validator_t *parent;
929
930
0
  for (parent = val; parent != NULL; parent = parent->parent) {
931
0
    if (parent->type == type &&
932
0
        dns_name_equal(parent->name, name) &&
933
        /*
934
         * As NSEC3 records are meta data you sometimes
935
         * need to prove a NSEC3 record which says that
936
         * itself doesn't exist.
937
         */
938
0
        (parent->type != dns_rdatatype_nsec3 || rdataset == NULL ||
939
0
         sigrdataset == NULL || parent->message == NULL ||
940
0
         parent->rdataset != NULL || parent->sigrdataset != NULL))
941
0
    {
942
0
      validator_log(val, ISC_LOG_DEBUG(3),
943
0
              "continuing validation would lead to "
944
0
              "deadlock: aborting validation");
945
0
      return true;
946
0
    }
947
0
  }
948
0
  return false;
949
0
}
950
951
/*%
952
 * Start a fetch for the requested name and type.
953
 */
954
static isc_result_t
955
create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
956
0
       isc_job_cb callback, const char *caller) {
957
0
  unsigned int fopts = 0;
958
0
  isc_result_t result;
959
960
0
  disassociate_rdatasets(val);
961
962
0
  if (check_deadlock(val, name, type, NULL, NULL)) {
963
0
    validator_log(val, ISC_LOG_DEBUG(3),
964
0
            "deadlock found (create_fetch)");
965
0
    return DNS_R_NOVALIDSIG;
966
0
  }
967
968
0
  if ((val->options & DNS_VALIDATOR_NOCDFLAG) != 0) {
969
0
    fopts |= DNS_FETCHOPT_NOCDFLAG;
970
0
  }
971
972
0
  if ((val->options & DNS_VALIDATOR_NONTA) != 0) {
973
0
    fopts |= DNS_FETCHOPT_NONTA;
974
0
  }
975
976
0
  validator_logcreate(val, name, type, caller, "fetch");
977
978
0
  dns_validator_ref(val);
979
0
  result = dns_resolver_createfetch(
980
0
    val->view->resolver, name, type, NULL, NULL, NULL, NULL, 0,
981
0
    fopts, 0, val->qc, val->gqc, val->loop, callback, val,
982
0
    &val->edectx, &val->frdataset, &val->fsigrdataset, &val->fetch);
983
0
  if (result != ISC_R_SUCCESS) {
984
0
    dns_validator_detach(&val);
985
0
  }
986
987
0
  return result;
988
0
}
989
990
/*%
991
 * Start a subvalidation process.
992
 */
993
static isc_result_t
994
create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
995
     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
996
0
     isc_job_cb cb, const char *caller) {
997
0
  isc_result_t result;
998
0
  unsigned int vopts = 0;
999
0
  dns_rdataset_t *sig = NULL;
1000
1001
0
  if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) {
1002
0
    sig = sigrdataset;
1003
0
  }
1004
1005
0
  if (check_deadlock(val, name, type, rdataset, sig)) {
1006
0
    validator_log(val, ISC_LOG_DEBUG(3),
1007
0
            "deadlock found (create_validator)");
1008
0
    return DNS_R_NOVALIDSIG;
1009
0
  }
1010
1011
  /* OK to clear other options, but preserve NOCDFLAG and NONTA. */
1012
0
  vopts |= (val->options &
1013
0
      (DNS_VALIDATOR_NOCDFLAG | DNS_VALIDATOR_NONTA));
1014
1015
0
  validator_logcreate(val, name, type, caller, "validator");
1016
0
  result = dns_validator_create(
1017
0
    val->view, name, type, rdataset, sig, NULL, vopts, val->loop,
1018
0
    cb, val, val->nvalidations, val->nfails, val->qc, val->gqc,
1019
0
    &val->edectx, &val->subvalidator);
1020
0
  if (result == ISC_R_SUCCESS) {
1021
0
    dns_validator_attach(val, &val->subvalidator->parent);
1022
0
    val->subvalidator->depth = val->depth + 1;
1023
0
  }
1024
0
  return result;
1025
0
}
1026
1027
/*%
1028
 * Try to find a key that could have signed val->siginfo among those in
1029
 * 'rdataset'.  If found, build a dst_key_t for it and point val->key at
1030
 * it.
1031
 *
1032
 * If val->key is already non-NULL, locate it in the rdataset and then
1033
 * search past it for the *next* key that could have signed 'siginfo', then
1034
 * set val->key to that.
1035
 *
1036
 * Returns ISC_R_SUCCESS if a possible matching key has been found,
1037
 * ISC_R_NOTFOUND if not. Any other value indicates error.
1038
 */
1039
static isc_result_t
1040
0
select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
1041
0
  isc_result_t result;
1042
1043
0
  if (val->key == NULL) {
1044
0
    result = dns_rdataset_first(rdataset);
1045
0
  } else {
1046
0
    dst_key_free(&val->key);
1047
0
    val->key = NULL;
1048
0
    result = dns_rdataset_next(rdataset);
1049
0
  }
1050
0
  if (result == ISC_R_NOMORE) {
1051
0
    return ISC_R_NOTFOUND;
1052
0
  }
1053
1054
0
  for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) {
1055
0
    dns_rdata_rrsig_t *siginfo = val->siginfo;
1056
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
1057
0
    dns_rdata_dnskey_t key;
1058
0
    isc_region_t r;
1059
1060
0
    dns_rdataset_current(rdataset, &rdata);
1061
0
    dns_rdata_tostruct(&rdata, &key, NULL); /* can't fail */
1062
1063
0
    if (key.algorithm != siginfo->algorithm ||
1064
0
        (key.flags & DNS_KEYFLAG_REVOKE) != 0 ||
1065
0
        !dns_dnssec_iszonekey(&key))
1066
0
    {
1067
0
      continue;
1068
0
    }
1069
1070
0
    dns_rdata_toregion(&rdata, &r);
1071
0
    if (dst_region_computeid(&r) != siginfo->keyid) {
1072
0
      continue;
1073
0
    }
1074
1075
0
    result = dns_dnssec_keyfromrdata(&siginfo->signer, &rdata,
1076
0
             val->view->mctx, &val->key);
1077
0
    if (result == ISC_R_SUCCESS) {
1078
      /* found the key we wanted */
1079
0
      break;
1080
0
    }
1081
0
  }
1082
0
  if (result == ISC_R_NOMORE) {
1083
0
    result = ISC_R_NOTFOUND;
1084
0
  }
1085
1086
0
  return result;
1087
0
}
1088
1089
/*%
1090
 * Get the key that generated the signature in val->siginfo.
1091
 */
1092
static isc_result_t
1093
0
seek_dnskey(dns_validator_t *val) {
1094
0
  isc_result_t result;
1095
0
  dns_rdata_rrsig_t *siginfo = val->siginfo;
1096
0
  unsigned int nlabels;
1097
0
  int order;
1098
0
  dns_namereln_t namereln;
1099
1100
  /*
1101
   * Is the signer name appropriate for this signature?
1102
   *
1103
   * The signer name must be at the same level as the owner name
1104
   * or closer to the DNS root.
1105
   */
1106
0
  namereln = dns_name_fullcompare(val->name, &siginfo->signer, &order,
1107
0
          &nlabels);
1108
0
  if (namereln != dns_namereln_subdomain &&
1109
0
      namereln != dns_namereln_equal)
1110
0
  {
1111
0
    return DNS_R_CONTINUE;
1112
0
  }
1113
1114
0
  if (namereln == dns_namereln_equal) {
1115
    /*
1116
     * If this is a self-signed keyset, it must not be a zone key
1117
     * (since seek_dnskey is not called from validate_dnskey).
1118
     */
1119
0
    if (val->rdataset->type == dns_rdatatype_dnskey) {
1120
0
      return DNS_R_CONTINUE;
1121
0
    }
1122
1123
    /*
1124
     * Records appearing in the parent zone at delegation
1125
     * points cannot be self-signed.
1126
     */
1127
0
    if (dns_rdatatype_atparent(val->rdataset->type)) {
1128
0
      return DNS_R_CONTINUE;
1129
0
    }
1130
0
  } else {
1131
    /*
1132
     * SOA and NS RRsets can only be signed by a key with
1133
     * the same name.
1134
     */
1135
0
    if (val->rdataset->type == dns_rdatatype_soa ||
1136
0
        val->rdataset->type == dns_rdatatype_ns)
1137
0
    {
1138
0
      const char *type;
1139
1140
0
      if (val->rdataset->type == dns_rdatatype_soa) {
1141
0
        type = "SOA";
1142
0
      } else {
1143
0
        type = "NS";
1144
0
      }
1145
0
      validator_log(val, ISC_LOG_DEBUG(3),
1146
0
              "%s signer mismatch", type);
1147
0
      return DNS_R_CONTINUE;
1148
0
    }
1149
0
  }
1150
1151
  /*
1152
   * Do we know about this key?
1153
   */
1154
0
  result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey);
1155
0
  switch (result) {
1156
0
  case ISC_R_SUCCESS:
1157
    /*
1158
     * We have an rrset for the given keyname.
1159
     */
1160
0
    val->keyset = &val->frdataset;
1161
0
    if (DNS_TRUST_PENDING(val->frdataset.trust) ||
1162
0
        DNS_TRUST_ANSWER(val->frdataset.trust))
1163
0
    {
1164
      /*
1165
       * We know the key but haven't validated it yet, or
1166
       * we had a key with trust level "answer" and
1167
       * a DS record for the zone has now been added.
1168
       */
1169
0
      result = create_validator(
1170
0
        val, &siginfo->signer, dns_rdatatype_dnskey,
1171
0
        &val->frdataset, &val->fsigrdataset,
1172
0
        validator_callback_dnskey, "seek_dnskey");
1173
0
      if (result != ISC_R_SUCCESS) {
1174
0
        return result;
1175
0
      }
1176
0
      return DNS_R_WAIT;
1177
0
    } else if (val->frdataset.trust < dns_trust_secure) {
1178
      /*
1179
       * The key is legitimately insecure.  There's no
1180
       * point in even attempting verification.
1181
       */
1182
0
      val->key = NULL;
1183
0
      result = ISC_R_SUCCESS;
1184
0
    } else {
1185
      /*
1186
       * See if we've got the key used in the signature.
1187
       */
1188
0
      validator_log(val, ISC_LOG_DEBUG(3),
1189
0
              "keyset with trust %s",
1190
0
              dns_trust_totext(val->frdataset.trust));
1191
1192
      /*
1193
       * Cleanup before passing control to the offload thread
1194
       */
1195
0
      if (dns_rdataset_isassociated(&val->frdataset) &&
1196
0
          val->keyset != &val->frdataset)
1197
0
      {
1198
0
        dns_rdataset_disassociate(&val->frdataset);
1199
0
      }
1200
0
      if (dns_rdataset_isassociated(&val->fsigrdataset)) {
1201
0
        dns_rdataset_disassociate(&val->fsigrdataset);
1202
0
      }
1203
1204
0
      return validate_helper_run(val, resume_answer_with_key);
1205
0
    }
1206
0
    break;
1207
1208
0
  case ISC_R_NOTFOUND:
1209
    /*
1210
     * We don't know anything about this key.
1211
     */
1212
0
    result = create_fetch(val, &siginfo->signer,
1213
0
              dns_rdatatype_dnskey,
1214
0
              fetch_callback_dnskey, "seek_dnskey");
1215
0
    if (result != ISC_R_SUCCESS) {
1216
0
      return result;
1217
0
    }
1218
0
    return DNS_R_WAIT;
1219
1220
0
  case DNS_R_NCACHENXDOMAIN:
1221
0
  case DNS_R_NCACHENXRRSET:
1222
0
  case DNS_R_EMPTYNAME:
1223
0
  case DNS_R_NXDOMAIN:
1224
0
  case DNS_R_NXRRSET:
1225
    /*
1226
     * This key doesn't exist.
1227
     */
1228
0
    result = DNS_R_CONTINUE;
1229
0
    break;
1230
1231
0
  case DNS_R_BROKENCHAIN:
1232
0
    return result;
1233
1234
0
  default:
1235
0
    break;
1236
0
  }
1237
1238
0
  if (dns_rdataset_isassociated(&val->frdataset) &&
1239
0
      val->keyset != &val->frdataset)
1240
0
  {
1241
0
    dns_rdataset_disassociate(&val->frdataset);
1242
0
  }
1243
0
  if (dns_rdataset_isassociated(&val->fsigrdataset)) {
1244
0
    dns_rdataset_disassociate(&val->fsigrdataset);
1245
0
  }
1246
1247
0
  return result;
1248
0
}
1249
1250
/*
1251
 * Compute the tag for a key represented in a DNSKEY rdata.
1252
 */
1253
static dns_keytag_t
1254
0
compute_keytag(dns_rdata_t *rdata) {
1255
0
  isc_region_t r;
1256
1257
0
  dns_rdata_toregion(rdata, &r);
1258
0
  return dst_region_computeid(&r);
1259
0
}
1260
1261
static bool
1262
0
over_max_validations(dns_validator_t *val) {
1263
0
  if (val->nvalidations == NULL ||
1264
0
      isc_counter_used(val->nvalidations) <
1265
0
        isc_counter_getlimit(val->nvalidations))
1266
0
  {
1267
0
    return false;
1268
0
  }
1269
1270
  /* The attribute is set only on failure */
1271
0
  val->attributes |= VALATTR_MAXVALIDATIONS;
1272
0
  return true;
1273
0
}
1274
1275
static void
1276
0
consume_validation(dns_validator_t *val) {
1277
0
  if (val->nvalidations == NULL) {
1278
0
    return;
1279
0
  }
1280
0
  (void)isc_counter_increment(val->nvalidations);
1281
0
}
1282
1283
static bool
1284
0
over_max_fails(dns_validator_t *val) {
1285
0
  if (val->nfails == NULL ||
1286
0
      isc_counter_used(val->nfails) < isc_counter_getlimit(val->nfails))
1287
0
  {
1288
0
    return false;
1289
0
  }
1290
1291
  /* The attribute is set only on failure */
1292
0
  val->attributes |= VALATTR_MAXVALIDATIONFAILS;
1293
0
  return true;
1294
0
}
1295
1296
static void
1297
0
consume_validation_fail(dns_validator_t *val) {
1298
0
  if (val->nfails == NULL) {
1299
0
    return;
1300
0
  }
1301
0
  (void)isc_counter_increment(val->nfails);
1302
0
}
1303
1304
/*%
1305
 * Is the DNSKEY rrset in val->rdataset self-signed?
1306
 */
1307
static isc_result_t
1308
0
selfsigned_dnskey(dns_validator_t *val) {
1309
0
  dns_rdataset_t *rdataset = val->rdataset;
1310
0
  dns_rdataset_t *sigrdataset = val->sigrdataset;
1311
0
  dns_name_t *name = val->name;
1312
0
  isc_result_t result;
1313
0
  isc_mem_t *mctx = val->view->mctx;
1314
1315
0
  if (rdataset->type != dns_rdatatype_dnskey) {
1316
0
    return DNS_R_NOKEYMATCH;
1317
0
  }
1318
1319
0
  DNS_RDATASET_FOREACH (rdataset) {
1320
0
    dns_rdata_t keyrdata = DNS_RDATA_INIT;
1321
0
    dns_rdata_dnskey_t key;
1322
0
    dns_rdata_rrsig_t sig;
1323
0
    dns_keytag_t keytag;
1324
1325
0
    dns_rdataset_current(rdataset, &keyrdata);
1326
0
    result = dns_rdata_tostruct(&keyrdata, &key, NULL);
1327
0
    RUNTIME_CHECK(result == ISC_R_SUCCESS);
1328
0
    keytag = compute_keytag(&keyrdata);
1329
1330
0
    DNS_RDATASET_FOREACH (sigrdataset) {
1331
0
      dns_rdata_t sigrdata = DNS_RDATA_INIT;
1332
0
      dst_key_t *dstkey = NULL;
1333
1334
0
      dns_rdataset_current(sigrdataset, &sigrdata);
1335
0
      result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1336
0
      RUNTIME_CHECK(result == ISC_R_SUCCESS);
1337
1338
0
      if (sig.algorithm != key.algorithm ||
1339
0
          sig.keyid != keytag ||
1340
0
          !dns_name_equal(name, &sig.signer))
1341
0
      {
1342
0
        continue;
1343
0
      }
1344
1345
      /*
1346
       * If the REVOKE bit is not set we have a
1347
       * theoretically self signed DNSKEY RRset.
1348
       * This will be verified later.
1349
       */
1350
0
      if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) {
1351
0
        return ISC_R_SUCCESS;
1352
0
      }
1353
1354
0
      result = dns_dnssec_keyfromrdata(name, &keyrdata, mctx,
1355
0
               &dstkey);
1356
0
      if (result != ISC_R_SUCCESS) {
1357
0
        continue;
1358
0
      }
1359
1360
      /*
1361
       * If this RRset is pending and it is trusted,
1362
       * see if it was self signed by this DNSKEY.
1363
       */
1364
0
      if (DNS_TRUST_PENDING(rdataset->trust) &&
1365
0
          dns_view_istrusted(val->view, name, &key))
1366
0
      {
1367
0
        if (over_max_validations(val)) {
1368
0
          dst_key_free(&dstkey);
1369
0
          return ISC_R_QUOTA;
1370
0
        }
1371
0
        result = dns_dnssec_verify(name, rdataset,
1372
0
                 dstkey, true, mctx,
1373
0
                 &sigrdata, NULL);
1374
0
        switch (result) {
1375
0
        case DNS_R_SIGFUTURE:
1376
0
        case DNS_R_SIGEXPIRED:
1377
          /*
1378
           * Temporal errors don't count towards
1379
           * max validations nor max fails.
1380
           */
1381
0
          break;
1382
0
        case ISC_R_SUCCESS:
1383
0
          consume_validation(val);
1384
          /*
1385
           * The key with the REVOKE flag has
1386
           * self signed the RRset so it is no
1387
           * good.
1388
           */
1389
0
          dns_view_untrust(val->view, name, &key);
1390
0
          break;
1391
0
        default:
1392
0
          consume_validation(val);
1393
0
          if (over_max_fails(val)) {
1394
0
            dst_key_free(&dstkey);
1395
0
            return ISC_R_QUOTA;
1396
0
          }
1397
0
          consume_validation_fail(val);
1398
0
          break;
1399
0
        }
1400
0
      } else if (rdataset->trust >= dns_trust_secure) {
1401
        /*
1402
         * We trust this RRset so if the key is
1403
         * marked revoked remove it.
1404
         */
1405
0
        dns_view_untrust(val->view, name, &key);
1406
0
      }
1407
1408
0
      dst_key_free(&dstkey);
1409
0
    }
1410
0
  }
1411
1412
0
  return DNS_R_NOKEYMATCH;
1413
0
}
1414
1415
/*%
1416
 * Attempt to verify the rdataset using the given key and rdata (RRSIG).
1417
 * The signature was good and from a wildcard record and the QNAME does
1418
 * not match the wildcard we need to look for a NOQNAME proof.
1419
 *
1420
 * Returns:
1421
 * \li  ISC_R_SUCCESS if the verification succeeds.
1422
 * \li  Others if the verification fails.
1423
 */
1424
static isc_result_t
1425
verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
1426
0
       uint16_t keyid) {
1427
0
  isc_result_t result;
1428
0
  dns_fixedname_t fixed;
1429
0
  bool ignore = false;
1430
0
  dns_name_t *wild;
1431
1432
0
  val->attributes |= VALATTR_TRIEDVERIFY;
1433
0
  wild = dns_fixedname_initname(&fixed);
1434
0
  if (over_max_validations(val)) {
1435
0
    return ISC_R_QUOTA;
1436
0
  }
1437
0
again:
1438
0
  result = dns_dnssec_verify(val->name, val->rdataset, key, ignore,
1439
0
           val->view->mctx, rdata, wild);
1440
0
  if ((result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) &&
1441
0
      val->view->acceptexpired)
1442
0
  {
1443
0
    ignore = true;
1444
0
    goto again;
1445
0
  }
1446
1447
0
  if (ignore && (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD))
1448
0
  {
1449
0
    validator_log(val, ISC_LOG_INFO,
1450
0
            "accepted expired %sRRSIG (keyid=%u)",
1451
0
            (result == DNS_R_FROMWILDCARD) ? "wildcard " : "",
1452
0
            keyid);
1453
0
  } else if (result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) {
1454
0
    validator_log(val, ISC_LOG_INFO,
1455
0
            "verify failed due to bad signature (keyid=%u): "
1456
0
            "%s",
1457
0
            keyid, isc_result_totext(result));
1458
0
  } else {
1459
0
    validator_log(val, ISC_LOG_DEBUG(3),
1460
0
            "verify rdataset (keyid=%u): %s", keyid,
1461
0
            isc_result_totext(result));
1462
0
  }
1463
0
  if (result == DNS_R_FROMWILDCARD) {
1464
0
    if (!dns_name_equal(val->name, wild)) {
1465
0
      dns_name_t *closest;
1466
0
      unsigned int labels;
1467
1468
      /*
1469
       * Compute the closest encloser in case we need it
1470
       * for the NSEC3 NOQNAME proof.
1471
       */
1472
0
      closest = dns_fixedname_name(&val->closest);
1473
0
      dns_name_copy(wild, closest);
1474
0
      labels = dns_name_countlabels(closest) - 1;
1475
0
      dns_name_getlabelsequence(closest, 1, labels, closest);
1476
0
      val->attributes |= VALATTR_NEEDNOQNAME;
1477
0
    }
1478
0
    result = ISC_R_SUCCESS;
1479
0
  }
1480
1481
0
  switch (result) {
1482
0
  case DNS_R_SIGFUTURE:
1483
0
  case DNS_R_SIGEXPIRED:
1484
    /*
1485
     * Temporal errors don't count towards max validations nor max
1486
     * fails.
1487
     */
1488
0
    validator_addede(val,
1489
0
         result == DNS_R_SIGEXPIRED
1490
0
           ? DNS_EDE_SIGNATUREEXPIRED
1491
0
           : DNS_EDE_SIGNATURENOTYETVALID,
1492
0
         NULL);
1493
0
    break;
1494
0
  case ISC_R_SUCCESS:
1495
0
    consume_validation(val);
1496
0
    break;
1497
0
  default:
1498
0
    consume_validation(val);
1499
0
    if (over_max_fails(val)) {
1500
0
      result = ISC_R_QUOTA;
1501
0
      break;
1502
0
    }
1503
0
    consume_validation_fail(val);
1504
0
    break;
1505
0
  }
1506
0
  return result;
1507
0
}
1508
1509
/*%
1510
 * Attempts positive response validation of a normal RRset.
1511
 *
1512
 * Returns:
1513
 * \li  ISC_R_SUCCESS Validation completed successfully
1514
 * \li  DNS_R_WAIT  Validation has started but is waiting
1515
 *      for an event.
1516
 * \li  Other return codes are possible and all indicate failure.
1517
 */
1518
1519
static void
1520
validate_answer_iter_next(void *arg);
1521
static void
1522
validate_answer_process(void *arg);
1523
static void
1524
validate_answer_iter_done(dns_validator_t *val, isc_result_t result);
1525
1526
static void
1527
validator_cancel_finish(dns_validator_t *validator);
1528
1529
static void
1530
0
validate_answer_iter_start(dns_validator_t *val) {
1531
0
  isc_result_t result = ISC_R_SUCCESS;
1532
1533
  /*
1534
   * Caller must be holding the validator lock.
1535
   */
1536
1537
0
  val->attributes &= ~VALATTR_OFFLOADED;
1538
0
  if (CANCELING(val)) {
1539
0
    validator_cancel_finish(val);
1540
0
    result = ISC_R_CANCELED;
1541
0
    goto cleanup;
1542
0
  }
1543
1544
0
  if (val->resume) {
1545
    /* We already have a sigrdataset. */
1546
0
    result = ISC_R_SUCCESS;
1547
0
    validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
1548
0
  } else {
1549
0
    result = dns_rdataset_first(val->sigrdataset);
1550
0
  }
1551
1552
0
cleanup:
1553
0
  if (result != ISC_R_SUCCESS) {
1554
0
    validate_answer_iter_done(val, result);
1555
0
    return;
1556
0
  }
1557
1558
0
  val->unsupported_algorithm = 0;
1559
0
  val->unsupported_digest = 0;
1560
0
  result = validate_async_run(val, validate_answer_process);
1561
0
  INSIST(result == DNS_R_WAIT);
1562
0
}
1563
1564
static void
1565
0
validate_answer_iter_next(void *arg) {
1566
0
  dns_validator_t *val = arg;
1567
0
  isc_result_t result;
1568
1569
0
  val->attributes &= ~VALATTR_OFFLOADED;
1570
0
  if (CANCELING(val)) {
1571
0
    validator_cancel_finish(val);
1572
0
    result = ISC_R_CANCELED;
1573
0
    goto cleanup;
1574
0
  }
1575
1576
0
  val->resume = false;
1577
0
  result = dns_rdataset_next(val->sigrdataset);
1578
1579
0
cleanup:
1580
0
  if (result != ISC_R_SUCCESS) {
1581
0
    validate_answer_iter_done(val, result);
1582
0
    return;
1583
0
  }
1584
1585
0
  (void)validate_async_run(val, validate_answer_process);
1586
0
}
1587
1588
static void
1589
validate_answer_finish(void *arg);
1590
1591
static void
1592
validate_answer_signing_key_done(void *arg);
1593
1594
static void
1595
0
validate_answer_signing_key(void *arg) {
1596
0
  dns_validator_t *val = arg;
1597
0
  isc_result_t result = ISC_R_NOTFOUND;
1598
1599
0
  if (CANCELED(val) || CANCELING(val)) {
1600
0
    val->result = ISC_R_CANCELED;
1601
0
  } else {
1602
0
    val->result = verify(val, val->key, &val->rdata,
1603
0
             val->siginfo->keyid);
1604
0
  }
1605
1606
0
  switch (val->result) {
1607
0
  case ISC_R_CANCELED:   /* Validation was canceled */
1608
0
  case ISC_R_SHUTTINGDOWN: /* Server shutting down */
1609
0
  case ISC_R_QUOTA:  /* Validation fails quota reached */
1610
0
  case ISC_R_SUCCESS: /* We found our valid signature, we are done! */
1611
0
    if (val->key != NULL) {
1612
0
      dst_key_free(&val->key);
1613
0
      val->key = NULL;
1614
0
    }
1615
1616
0
    break;
1617
0
  default:
1618
    /* Select next signing key */
1619
0
    result = select_signing_key(val, val->keyset);
1620
0
    break;
1621
0
  }
1622
1623
0
  if (result == ISC_R_SUCCESS) {
1624
0
    INSIST(val->key != NULL);
1625
0
  } else {
1626
0
    INSIST(val->key == NULL);
1627
0
  }
1628
1629
0
  (void)validate_async_run(val, validate_answer_signing_key_done);
1630
0
}
1631
1632
static void
1633
0
validate_answer_signing_key_done(void *arg) {
1634
0
  dns_validator_t *val = arg;
1635
1636
0
  val->attributes &= ~VALATTR_OFFLOADED;
1637
0
  if (CANCELING(val)) {
1638
0
    validator_cancel_finish(val);
1639
0
    val->result = ISC_R_CANCELED;
1640
0
  } else if (val->key != NULL) {
1641
    /* Process with next key if we selected one */
1642
0
    (void)validate_helper_run(val, validate_answer_signing_key);
1643
0
    return;
1644
0
  }
1645
1646
0
  validate_answer_finish(val);
1647
0
}
1648
1649
static void
1650
0
validate_answer_process(void *arg) {
1651
0
  dns_validator_t *val = arg;
1652
0
  isc_result_t result;
1653
1654
0
  val->attributes &= ~VALATTR_OFFLOADED;
1655
0
  if (CANCELING(val)) {
1656
0
    validator_cancel_finish(val);
1657
0
    result = ISC_R_CANCELED;
1658
0
    goto cleanup;
1659
0
  }
1660
1661
0
  dns_rdata_reset(&val->rdata);
1662
1663
0
  dns_rdataset_current(val->sigrdataset, &val->rdata);
1664
0
  if (val->siginfo == NULL) {
1665
0
    val->siginfo = isc_mem_get(val->view->mctx,
1666
0
             sizeof(*val->siginfo));
1667
0
  }
1668
0
  result = dns_rdata_tostruct(&val->rdata, val->siginfo, NULL);
1669
0
  if (result != ISC_R_SUCCESS) {
1670
0
    goto cleanup;
1671
0
  }
1672
1673
  /*
1674
   * At this point we could check that the signature algorithm
1675
   * was known and "sufficiently good".
1676
   */
1677
0
  if (!dns_resolver_algorithm_supported(
1678
0
        val->view->resolver, val->name, val->siginfo->algorithm,
1679
0
        val->siginfo->signature, val->siginfo->siglen))
1680
0
  {
1681
0
    if (val->unsupported_algorithm == 0) {
1682
0
      val->unsupported_algorithm = val->siginfo->algorithm;
1683
      /*
1684
       * XXXMPA save PRIVATEOID/PRIVATEDNS identifier here
1685
       */
1686
0
    }
1687
0
    goto next_key;
1688
0
  }
1689
1690
0
  if (!val->resume) {
1691
0
    result = seek_dnskey(val);
1692
0
    switch (result) {
1693
0
    case ISC_R_SUCCESS:
1694
0
      break;
1695
0
    case DNS_R_CONTINUE:
1696
0
      goto next_key;
1697
0
    case DNS_R_WAIT:
1698
0
      goto cleanup;
1699
0
    default:
1700
0
      goto cleanup;
1701
0
    }
1702
0
  }
1703
1704
  /*
1705
   * There isn't a secure DNSKEY for this signature so move
1706
   * onto the next RRSIG.
1707
   */
1708
0
  if (val->key == NULL) {
1709
0
    val->resume = false;
1710
0
    goto next_key;
1711
0
  }
1712
1713
0
  (void)validate_helper_run(val, validate_answer_signing_key);
1714
0
  return;
1715
1716
0
next_key:
1717
0
  result = validate_async_run(val, validate_answer_iter_next);
1718
0
  goto cleanup;
1719
1720
0
cleanup:
1721
0
  validate_async_done(val, result);
1722
0
}
1723
1724
static void
1725
0
validate_answer_finish(void *arg) {
1726
0
  dns_validator_t *val = arg;
1727
0
  isc_result_t result = ISC_R_UNSET;
1728
1729
0
  if (val->result == ISC_R_SUCCESS) {
1730
0
    dns_rdataset_trimttl(val->rdataset, val->sigrdataset,
1731
0
             val->siginfo, val->start,
1732
0
             val->view->acceptexpired);
1733
0
  }
1734
1735
0
  if (val->key != NULL) {
1736
0
    dst_key_free(&val->key);
1737
0
    val->key = NULL;
1738
0
  }
1739
0
  if (val->keyset != NULL) {
1740
0
    dns_rdataset_disassociate(val->keyset);
1741
0
    val->keyset = NULL;
1742
0
  }
1743
1744
0
  switch (val->result) {
1745
0
  case ISC_R_CANCELED:
1746
0
    validator_log(val, ISC_LOG_DEBUG(3), "validation was canceled");
1747
0
    validate_async_done(val, val->result);
1748
0
    return;
1749
0
  case ISC_R_SHUTTINGDOWN:
1750
0
    validator_log(val, ISC_LOG_DEBUG(3), "server is shutting down");
1751
0
    validate_async_done(val, val->result);
1752
0
    return;
1753
0
  case ISC_R_QUOTA:
1754
0
    if (MAXVALIDATIONS(val)) {
1755
0
      validator_log(val, ISC_LOG_DEBUG(3),
1756
0
              "maximum number of validations exceeded");
1757
0
    } else if (MAXVALIDATIONFAILS(val)) {
1758
0
      validator_log(val, ISC_LOG_DEBUG(3),
1759
0
              "maximum number of validation failures "
1760
0
              "exceeded");
1761
0
    } else {
1762
0
      validator_log(
1763
0
        val, ISC_LOG_DEBUG(3),
1764
0
        "unknown error: validation quota exceeded");
1765
0
    }
1766
0
    validate_async_done(val, val->result);
1767
0
    return;
1768
0
  default:
1769
0
    break;
1770
0
  }
1771
1772
0
  if (NEEDNOQNAME(val)) {
1773
0
    if (val->message == NULL) {
1774
0
      validator_log(val, ISC_LOG_DEBUG(3),
1775
0
              "no message available for noqname proof");
1776
0
      validate_async_done(val, DNS_R_NOVALIDSIG);
1777
0
      return;
1778
0
    }
1779
1780
0
    validator_log(val, ISC_LOG_DEBUG(3),
1781
0
            "looking for noqname proof");
1782
0
    result = validate_nx(val, false);
1783
0
    validate_async_done(val, result);
1784
0
    return;
1785
0
  }
1786
1787
0
  if (val->result == ISC_R_SUCCESS) {
1788
0
    marksecure(val);
1789
0
    validator_log(val, ISC_LOG_DEBUG(3),
1790
0
            "marking as secure, noqname proof not needed");
1791
0
    validate_async_done(val, val->result);
1792
0
    return;
1793
0
  }
1794
1795
0
  validator_log(val, ISC_LOG_DEBUG(3), "verify failure: %s",
1796
0
          isc_result_totext(val->result));
1797
0
  (void)validate_async_run(val, validate_answer_iter_next);
1798
0
}
1799
1800
static void
1801
0
validate_answer_iter_done(dns_validator_t *val, isc_result_t result) {
1802
0
  if (result != ISC_R_NOMORE) {
1803
0
    validator_log(val, ISC_LOG_DEBUG(3),
1804
0
            "failed to iterate signatures: %s",
1805
0
            isc_result_totext(result));
1806
0
    validate_async_done(val, result);
1807
0
    return;
1808
0
  }
1809
1810
0
  if (result != ISC_R_SUCCESS && result != DNS_R_WAIT) {
1811
0
    validate_extendederror(val);
1812
0
  }
1813
1814
0
  validator_log(val, ISC_LOG_INFO, "no valid signature found");
1815
0
  validate_async_done(val, val->result);
1816
0
}
1817
1818
static void
1819
0
resume_answer(void *arg) {
1820
0
  dns_validator_t *val = arg;
1821
1822
0
  val->resume = true;
1823
0
  validate_answer_iter_start(val);
1824
0
}
1825
1826
static void
1827
0
validate_answer(void *arg) {
1828
0
  dns_validator_t *val = arg;
1829
0
  val->resume = false;
1830
0
  validate_answer_iter_start(val);
1831
0
}
1832
1833
static isc_result_t
1834
0
validate_async_run(dns_validator_t *val, isc_job_cb cb) {
1835
0
  isc_async_run(val->loop, cb, val);
1836
0
  return DNS_R_WAIT;
1837
0
}
1838
1839
static isc_result_t
1840
0
validate_helper_run(dns_validator_t *val, isc_job_cb cb) {
1841
0
  val->attributes |= VALATTR_OFFLOADED;
1842
0
  isc_helper_run(val->loop, cb, val);
1843
0
  return DNS_R_WAIT;
1844
0
}
1845
1846
static void
1847
0
validate_async_done(dns_validator_t *val, isc_result_t result) {
1848
0
  if (result == DNS_R_NOVALIDSIG &&
1849
0
      (val->attributes & VALATTR_TRIEDVERIFY) == 0)
1850
0
  {
1851
0
    isc_result_t saved_result = result;
1852
0
    validator_log(val, ISC_LOG_DEBUG(3),
1853
0
            "falling back to insecurity proof");
1854
0
    result = proveunsecure(val, false, false, false);
1855
0
    if (result == DNS_R_NOTINSECURE) {
1856
0
      result = saved_result;
1857
0
    }
1858
0
  }
1859
1860
0
  if (result != DNS_R_WAIT) {
1861
    /* We are still continuing */
1862
0
    validator_done(val, result);
1863
0
    dns_validator_detach(&val);
1864
0
  }
1865
0
}
1866
1867
/*%
1868
 * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset
1869
 * (val->rdataset).
1870
 */
1871
static isc_result_t
1872
check_signer(dns_validator_t *val, dns_rdata_t *keyrdata, uint16_t keyid,
1873
0
       dns_secalg_t algorithm) {
1874
0
  dns_rdata_rrsig_t sig;
1875
0
  dst_key_t *dstkey = NULL;
1876
0
  isc_result_t result = ISC_R_NOMORE;
1877
0
  dns_rdataset_t rdataset = DNS_RDATASET_INIT;
1878
1879
0
  dns_rdataset_clone(val->sigrdataset, &rdataset);
1880
1881
0
  DNS_RDATASET_FOREACH (&rdataset) {
1882
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
1883
1884
0
    dns_rdataset_current(&rdataset, &rdata);
1885
0
    result = dns_rdata_tostruct(&rdata, &sig, NULL);
1886
0
    RUNTIME_CHECK(result == ISC_R_SUCCESS);
1887
0
    if (keyid != sig.keyid || algorithm != sig.algorithm) {
1888
0
      continue;
1889
0
    }
1890
0
    if (dstkey == NULL) {
1891
0
      result = dns_dnssec_keyfromrdata(
1892
0
        val->name, keyrdata, val->view->mctx, &dstkey);
1893
0
      if (result != ISC_R_SUCCESS) {
1894
        /*
1895
         * This really shouldn't happen, but...
1896
         */
1897
0
        continue;
1898
0
      }
1899
0
    }
1900
0
    result = verify(val, dstkey, &rdata, sig.keyid);
1901
0
    if (result == ISC_R_SUCCESS || result == ISC_R_QUOTA) {
1902
0
      break;
1903
0
    }
1904
0
  }
1905
1906
0
  if (dstkey != NULL) {
1907
0
    dst_key_free(&dstkey);
1908
0
  }
1909
0
  dns_rdataset_disassociate(&rdataset);
1910
1911
0
  return result;
1912
0
}
1913
1914
/*
1915
 * get_dsset() is called to look up a DS RRset corresponding to the name
1916
 * of a DNSKEY record, either in the cache or, if necessary, by starting a
1917
 * fetch. This is done in the context of validating a zone key to build a
1918
 * trust chain.
1919
 *
1920
 * Returns:
1921
 * \li  ISC_R_COMPLETE    a DS has not been found; the caller should
1922
 *        stop trying to validate the zone key and
1923
 *        return the result code in '*resp'.
1924
 * \li  DNS_R_CONTINUE    a DS has been found and the caller may
1925
 *        continue the zone key validation.
1926
 */
1927
static isc_result_t
1928
0
get_dsset(dns_validator_t *val, dns_name_t *tname, isc_result_t *resp) {
1929
0
  isc_result_t result;
1930
1931
0
  result = view_find(val, tname, dns_rdatatype_ds);
1932
0
  switch (result) {
1933
0
  case ISC_R_SUCCESS:
1934
    /*
1935
     * We have a DS RRset.
1936
     */
1937
0
    val->dsset = &val->frdataset;
1938
0
    if (DNS_TRUST_PENDING(val->frdataset.trust) ||
1939
0
        DNS_TRUST_ANSWER(val->frdataset.trust))
1940
0
    {
1941
      /*
1942
       * ... which is signed but not yet validated.
1943
       */
1944
0
      result = create_validator(
1945
0
        val, tname, dns_rdatatype_ds, &val->frdataset,
1946
0
        &val->fsigrdataset, validator_callback_ds,
1947
0
        "get_dsset");
1948
0
      *resp = DNS_R_WAIT;
1949
0
      if (result != ISC_R_SUCCESS) {
1950
0
        *resp = result;
1951
0
      }
1952
0
      return ISC_R_COMPLETE;
1953
0
    }
1954
0
    break;
1955
1956
0
  case ISC_R_NOTFOUND:
1957
    /*
1958
     * We don't have the DS.  Find it.
1959
     */
1960
0
    result = create_fetch(val, tname, dns_rdatatype_ds,
1961
0
              fetch_callback_ds, "validate_dnskey");
1962
0
    *resp = DNS_R_WAIT;
1963
0
    if (result != ISC_R_SUCCESS) {
1964
0
      *resp = result;
1965
0
    }
1966
0
    return ISC_R_COMPLETE;
1967
1968
0
  case DNS_R_NCACHENXDOMAIN:
1969
0
  case DNS_R_NCACHENXRRSET:
1970
0
  case DNS_R_EMPTYNAME:
1971
0
  case DNS_R_NXDOMAIN:
1972
0
  case DNS_R_NXRRSET:
1973
0
  case DNS_R_CNAME:
1974
    /*
1975
     * The DS does not exist.
1976
     */
1977
0
    disassociate_rdatasets(val);
1978
0
    validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
1979
0
    *resp = DNS_R_NOVALIDSIG;
1980
0
    return ISC_R_COMPLETE;
1981
1982
0
  case DNS_R_BROKENCHAIN:
1983
0
    *resp = result;
1984
0
    return ISC_R_COMPLETE;
1985
1986
0
  default:
1987
0
    break;
1988
0
  }
1989
1990
0
  return DNS_R_CONTINUE;
1991
0
}
1992
1993
static void
1994
0
validate_dnskey_dsset_done(dns_validator_t *val, isc_result_t result) {
1995
0
  switch (result) {
1996
0
  case ISC_R_CANCELED:
1997
0
  case ISC_R_SHUTTINGDOWN:
1998
    /* Abort, abort, abort! */
1999
0
    break;
2000
0
  case ISC_R_SUCCESS:
2001
0
    marksecure(val);
2002
0
    validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)");
2003
0
    break;
2004
0
  case ISC_R_NOMORE:
2005
0
    if (val->unsupported_algorithm != 0 ||
2006
0
        val->unsupported_digest != 0)
2007
0
    {
2008
0
      validator_log(val, ISC_LOG_DEBUG(3),
2009
0
              "no supported algorithm/digest (DS)");
2010
0
      result = markanswer(val, "validate_dnskey (3)");
2011
0
      validate_extendederror(val);
2012
0
      break;
2013
0
    }
2014
0
    FALLTHROUGH;
2015
0
  default:
2016
0
    validator_log(val, ISC_LOG_INFO,
2017
0
            "no valid signature found (DS)");
2018
0
    result = DNS_R_NOVALIDSIG;
2019
0
    break;
2020
0
  }
2021
2022
0
  if (val->dsset == &val->fdsset) {
2023
0
    val->dsset = NULL;
2024
0
    dns_rdataset_disassociate(&val->fdsset);
2025
0
  }
2026
2027
0
  validate_async_done(val, result);
2028
0
}
2029
2030
static isc_result_t
2031
0
validate_dnskey_dsset(dns_validator_t *val) {
2032
0
  dns_rdata_t dsrdata = DNS_RDATA_INIT;
2033
0
  dns_rdata_t keyrdata = DNS_RDATA_INIT;
2034
0
  isc_result_t result;
2035
0
  dns_rdata_ds_t ds;
2036
0
  dns_rdata_dnskey_t key;
2037
0
  unsigned char *data = 0;
2038
0
  unsigned int datalen = 0;
2039
2040
0
  dns_rdata_reset(&dsrdata);
2041
0
  dns_rdataset_current(val->dsset, &dsrdata);
2042
0
  result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2043
0
  RUNTIME_CHECK(result == ISC_R_SUCCESS);
2044
2045
0
  if (ds.digest_type == DNS_DSDIGEST_SHA1 && val->digest_sha1 == false) {
2046
0
    return DNS_R_BADALG;
2047
0
  }
2048
2049
0
  if (!dns_resolver_ds_digest_supported(val->view->resolver, val->name,
2050
0
                ds.digest_type))
2051
0
  {
2052
0
    if (val->unsupported_digest == 0) {
2053
0
      val->unsupported_digest = ds.digest_type;
2054
0
    }
2055
0
    return DNS_R_BADALG;
2056
0
  }
2057
2058
0
  switch (ds.algorithm) {
2059
0
  case DNS_KEYALG_PRIVATEDNS:
2060
0
  case DNS_KEYALG_PRIVATEOID:
2061
0
    switch (ds.digest_type) {
2062
#if defined(DNS_DSDIGEST_SHA256PRIVATE) && defined(DNS_DSDIGEST_SHA384PRIVATE)
2063
    case DNS_DSDIGEST_SHA256PRIVATE:
2064
    case DNS_DSDIGEST_SHA384PRIVATE:
2065
      data = ds.digest;
2066
      datalen = ds.length;
2067
      break;
2068
#endif
2069
0
    default:
2070
0
      break;
2071
0
    }
2072
0
    break;
2073
0
  default:
2074
0
    break;
2075
0
  }
2076
2077
0
  if (data != NULL || (ds.algorithm != DNS_KEYALG_PRIVATEDNS &&
2078
0
           ds.algorithm != DNS_KEYALG_PRIVATEOID))
2079
0
  {
2080
0
    if (!dns_resolver_algorithm_supported(val->view->resolver,
2081
0
                  val->name, ds.algorithm,
2082
0
                  data, datalen))
2083
0
    {
2084
0
      if (val->unsupported_algorithm == 0) {
2085
0
        val->unsupported_algorithm = ds.algorithm;
2086
0
      }
2087
0
      return DNS_R_BADALG;
2088
0
    }
2089
0
  }
2090
2091
  /*
2092
   * Find the DNSKEY matching the DS...
2093
   */
2094
0
  result = dns_dnssec_matchdskey(val->name, &dsrdata, val->rdataset,
2095
0
               &keyrdata);
2096
0
  if (result != ISC_R_SUCCESS) {
2097
0
    validator_log(val, ISC_LOG_DEBUG(3), "no DNSKEY matching DS");
2098
0
    return DNS_R_NOKEYMATCH;
2099
0
  }
2100
2101
  /*
2102
   * Figure out if the private algorithm is supported now that we have
2103
   * found a matching dnskey.
2104
   */
2105
0
  dns_rdata_tostruct(&keyrdata, &key, NULL);
2106
0
  if (data == NULL && (ds.algorithm == DNS_KEYALG_PRIVATEDNS ||
2107
0
           ds.algorithm == DNS_KEYALG_PRIVATEOID))
2108
0
  {
2109
0
    if (!dns_resolver_algorithm_supported(val->view->resolver,
2110
0
                  val->name, key.algorithm,
2111
0
                  key.data, key.datalen))
2112
0
    {
2113
0
      if (val->unsupported_algorithm == 0) {
2114
0
        val->unsupported_algorithm = key.algorithm;
2115
        /*
2116
         * XXXMPA Save PRIVATEOID / PRIVATEDNS here.
2117
         */
2118
0
      }
2119
0
      return DNS_R_BADALG;
2120
0
    }
2121
0
  }
2122
2123
  /*
2124
   * ... and check that it signed the DNSKEY RRset.
2125
   */
2126
0
  result = check_signer(val, &keyrdata, ds.key_tag, ds.algorithm);
2127
0
  if (result != ISC_R_SUCCESS) {
2128
0
    validator_log(val, ISC_LOG_DEBUG(3),
2129
0
            "no RRSIG matching DS key");
2130
2131
0
    return DNS_R_NOVALIDSIG;
2132
0
  }
2133
2134
0
  return ISC_R_SUCCESS;
2135
0
}
2136
2137
static void
2138
validate_dnskey_dsset_next_done(void *arg);
2139
2140
static void
2141
0
validate_dnskey_dsset_next(void *arg) {
2142
0
  dns_validator_t *val = arg;
2143
2144
0
  if (CANCELED(val) || CANCELING(val)) {
2145
0
    val->result = ISC_R_CANCELED;
2146
0
  } else {
2147
0
    val->result = dns_rdataset_next(val->dsset);
2148
0
  }
2149
2150
0
  if (val->result == ISC_R_SUCCESS) {
2151
    /* continue async run */
2152
0
    val->result = validate_dnskey_dsset(val);
2153
0
  }
2154
2155
0
  validate_async_run(val, validate_dnskey_dsset_next_done);
2156
0
}
2157
2158
static void
2159
0
validate_dnskey_dsset_next_done(void *arg) {
2160
0
  dns_validator_t *val = arg;
2161
0
  isc_result_t result = val->result;
2162
2163
0
  val->attributes &= ~VALATTR_OFFLOADED;
2164
0
  if (CANCELING(val)) {
2165
0
    validator_cancel_finish(val);
2166
0
    result = ISC_R_CANCELED;
2167
0
  }
2168
2169
0
  switch (result) {
2170
0
  case ISC_R_CANCELED:
2171
0
  case ISC_R_SHUTTINGDOWN:
2172
    /* Abort, abort, abort! */
2173
0
    break;
2174
0
  case ISC_R_SUCCESS:
2175
0
  case ISC_R_NOMORE:
2176
    /* We are done */
2177
0
    break;
2178
0
  default:
2179
    /* Continue validation until we have success or no more data */
2180
0
    (void)validate_helper_run(val, validate_dnskey_dsset_next);
2181
0
    return;
2182
0
  }
2183
2184
0
  validate_dnskey_dsset_done(val, result);
2185
0
  return;
2186
0
}
2187
2188
static void
2189
0
validate_dnskey_dsset_first(dns_validator_t *val) {
2190
0
  isc_result_t result;
2191
2192
0
  if (CANCELED(val) || CANCELING(val)) {
2193
0
    result = ISC_R_CANCELED;
2194
0
  } else {
2195
0
    result = dns_rdataset_first(val->dsset);
2196
0
  }
2197
2198
0
  if (result == ISC_R_SUCCESS) {
2199
    /* continue async run */
2200
0
    result = validate_dnskey_dsset(val);
2201
0
    if (result != ISC_R_SUCCESS) {
2202
0
      (void)validate_helper_run(val,
2203
0
              validate_dnskey_dsset_next);
2204
0
      return;
2205
0
    }
2206
0
  }
2207
2208
0
  validate_dnskey_dsset_done(val, result);
2209
0
}
2210
2211
static void
2212
0
validate_dnskey(void *arg) {
2213
0
  dns_validator_t *val = arg;
2214
0
  isc_result_t result = ISC_R_SUCCESS;
2215
0
  dns_keynode_t *keynode = NULL;
2216
0
  dns_rdata_ds_t ds;
2217
2218
0
  if (CANCELED(val) || CANCELING(val)) {
2219
0
    result = ISC_R_CANCELED;
2220
0
    goto cleanup;
2221
0
  }
2222
2223
  /*
2224
   * If we don't already have a DS RRset, check to see if there's
2225
   * a DS style trust anchor configured for this key.
2226
   */
2227
0
  if (val->dsset == NULL) {
2228
0
    result = dns_keytable_find(val->keytable, val->name, &keynode);
2229
0
    if (result == ISC_R_SUCCESS) {
2230
0
      if (dns_keynode_dsset(keynode, &val->fdsset)) {
2231
0
        val->dsset = &val->fdsset;
2232
0
      }
2233
0
      dns_keynode_detach(&keynode);
2234
0
    }
2235
0
  }
2236
2237
  /*
2238
   * No trust anchor for this name, so we look up the DS at the parent.
2239
   */
2240
0
  if (val->dsset == NULL) {
2241
0
    isc_result_t tresult = ISC_R_SUCCESS;
2242
2243
    /*
2244
     * If this is the root name and there was no trust anchor,
2245
     * we can give up now, since there's no DS at the root.
2246
     */
2247
0
    if (dns_name_equal(val->name, dns_rootname)) {
2248
0
      if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) {
2249
0
        validator_log(val, ISC_LOG_DEBUG(3),
2250
0
                "root key failed to validate");
2251
0
      } else {
2252
0
        validator_log(val, ISC_LOG_DEBUG(3),
2253
0
                "no trusted root key");
2254
0
      }
2255
0
      result = DNS_R_NOVALIDSIG;
2256
0
      goto cleanup;
2257
0
    }
2258
2259
    /*
2260
     * Look up the DS RRset for this name.
2261
     */
2262
0
    result = get_dsset(val, val->name, &tresult);
2263
0
    if (result == ISC_R_COMPLETE) {
2264
0
      result = tresult;
2265
0
      goto cleanup;
2266
0
    }
2267
0
  }
2268
2269
  /*
2270
   * We have a DS set.
2271
   */
2272
0
  INSIST(val->dsset != NULL);
2273
2274
0
  if (val->dsset->trust < dns_trust_secure) {
2275
0
    result = markanswer(val, "validate_dnskey (2)");
2276
0
    goto cleanup;
2277
0
  }
2278
2279
  /*
2280
   * Look through the DS record and find the keys that can sign the
2281
   * key set and the matching signature.  For each such key, attempt
2282
   * verification.
2283
   */
2284
0
  val->unsupported_algorithm = 0;
2285
0
  val->unsupported_digest = 0;
2286
2287
  /*
2288
   * If DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present we
2289
   * are required to prefer it over DNS_DSDIGEST_SHA1.  This in
2290
   * practice means that we need to ignore DNS_DSDIGEST_SHA1 if a
2291
   * DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present.
2292
   */
2293
0
  val->digest_sha1 = true;
2294
0
  DNS_RDATASET_FOREACH (val->dsset) {
2295
0
    dns_rdata_t dsrdata = DNS_RDATA_INIT;
2296
0
    dns_rdataset_current(val->dsset, &dsrdata);
2297
0
    result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
2298
0
    RUNTIME_CHECK(result == ISC_R_SUCCESS);
2299
2300
0
    if (!dns_resolver_ds_digest_supported(
2301
0
          val->view->resolver, val->name, ds.digest_type))
2302
0
    {
2303
0
      continue;
2304
0
    }
2305
2306
0
    if (!dns_resolver_algorithm_supported(val->view->resolver,
2307
0
                  val->name, ds.algorithm,
2308
0
                  NULL, 0))
2309
0
    {
2310
0
      continue;
2311
0
    }
2312
2313
0
    if ((ds.digest_type == DNS_DSDIGEST_SHA256 &&
2314
0
         ds.length == ISC_SHA256_DIGESTLENGTH) ||
2315
0
        (ds.digest_type == DNS_DSDIGEST_SHA384 &&
2316
0
         ds.length == ISC_SHA384_DIGESTLENGTH))
2317
0
    {
2318
0
      val->digest_sha1 = false;
2319
0
      break;
2320
0
    }
2321
0
  }
2322
2323
0
  validate_dnskey_dsset_first(val);
2324
0
  return;
2325
2326
0
cleanup:
2327
0
  if (val->dsset == &val->fdsset) {
2328
0
    val->dsset = NULL;
2329
0
    dns_rdataset_disassociate(&val->fdsset);
2330
0
  }
2331
0
  validate_async_done(val, result);
2332
0
}
2333
2334
/*%
2335
 * val_rdataset_first and val_rdataset_next provide iteration methods
2336
 * that hide whether we are iterating across the AUTHORITY section of
2337
 * a message, or a negative cache rdataset.
2338
 */
2339
static isc_result_t
2340
val_rdataset_first(dns_validator_t *val, dns_name_t **namep,
2341
0
       dns_rdataset_t **rdatasetp) {
2342
0
  dns_message_t *message = val->message;
2343
0
  isc_result_t result;
2344
2345
0
  REQUIRE(rdatasetp != NULL);
2346
0
  REQUIRE(namep != NULL);
2347
0
  if (message == NULL) {
2348
0
    REQUIRE(*rdatasetp != NULL);
2349
0
    REQUIRE(*namep != NULL);
2350
0
  } else {
2351
0
    REQUIRE(*rdatasetp == NULL);
2352
0
    REQUIRE(*namep == NULL);
2353
0
  }
2354
2355
0
  if (message != NULL) {
2356
0
    result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2357
0
    if (result != ISC_R_SUCCESS) {
2358
0
      return result;
2359
0
    }
2360
0
    dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep);
2361
0
    *rdatasetp = ISC_LIST_HEAD((*namep)->list);
2362
0
    INSIST(*rdatasetp != NULL);
2363
0
  } else {
2364
0
    result = dns_rdataset_first(val->rdataset);
2365
0
    if (result == ISC_R_SUCCESS) {
2366
0
      dns_ncache_current(val->rdataset, *namep, *rdatasetp);
2367
0
    }
2368
0
  }
2369
0
  return result;
2370
0
}
2371
2372
static isc_result_t
2373
val_rdataset_next(dns_validator_t *val, dns_name_t **namep,
2374
0
      dns_rdataset_t **rdatasetp) {
2375
0
  dns_message_t *message = val->message;
2376
0
  isc_result_t result = ISC_R_SUCCESS;
2377
2378
0
  REQUIRE(rdatasetp != NULL && *rdatasetp != NULL);
2379
0
  REQUIRE(namep != NULL && *namep != NULL);
2380
2381
0
  if (message != NULL) {
2382
0
    dns_rdataset_t *rdataset = *rdatasetp;
2383
0
    rdataset = ISC_LIST_NEXT(rdataset, link);
2384
0
    if (rdataset == NULL) {
2385
0
      *namep = NULL;
2386
0
      result = dns_message_nextname(message,
2387
0
                  DNS_SECTION_AUTHORITY);
2388
0
      if (result == ISC_R_SUCCESS) {
2389
0
        dns_message_currentname(
2390
0
          message, DNS_SECTION_AUTHORITY, namep);
2391
0
        rdataset = ISC_LIST_HEAD((*namep)->list);
2392
0
        INSIST(rdataset != NULL);
2393
0
      }
2394
0
    }
2395
0
    *rdatasetp = rdataset;
2396
0
  } else {
2397
0
    dns_rdataset_disassociate(*rdatasetp);
2398
0
    result = dns_rdataset_next(val->rdataset);
2399
0
    if (result == ISC_R_SUCCESS) {
2400
0
      dns_ncache_current(val->rdataset, *namep, *rdatasetp);
2401
0
    }
2402
0
  }
2403
0
  return result;
2404
0
}
2405
2406
/*%
2407
 * Look for NODATA at the wildcard and NOWILDCARD proofs in the
2408
 * previously validated NSEC records.  As these proofs are mutually
2409
 * exclusive we stop when one is found.
2410
 *
2411
 * Returns
2412
 * \li  ISC_R_SUCCESS
2413
 */
2414
static isc_result_t
2415
checkwildcard(dns_validator_t *val, dns_rdatatype_t type,
2416
0
        dns_name_t *zonename) {
2417
0
  dns_name_t *name, *wild, tname;
2418
0
  isc_result_t result;
2419
0
  bool exists, data;
2420
0
  char namebuf[DNS_NAME_FORMATSIZE];
2421
0
  dns_rdataset_t *rdataset, trdataset;
2422
2423
0
  dns_name_init(&tname);
2424
0
  dns_rdataset_init(&trdataset);
2425
0
  wild = dns_fixedname_name(&val->wild);
2426
2427
0
  if (dns_name_countlabels(wild) == 0) {
2428
0
    validator_log(val, ISC_LOG_DEBUG(3),
2429
0
            "in checkwildcard: no wildcard to check");
2430
0
    return ISC_R_SUCCESS;
2431
0
  }
2432
2433
0
  dns_name_format(wild, namebuf, sizeof(namebuf));
2434
0
  validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
2435
2436
0
  if (val->message == NULL) {
2437
0
    name = &tname;
2438
0
    rdataset = &trdataset;
2439
0
  } else {
2440
0
    name = NULL;
2441
0
    rdataset = NULL;
2442
0
  }
2443
2444
0
  for (result = val_rdataset_first(val, &name, &rdataset);
2445
0
       result == ISC_R_SUCCESS;
2446
0
       result = val_rdataset_next(val, &name, &rdataset))
2447
0
  {
2448
0
    if (rdataset->type != type ||
2449
0
        rdataset->trust != dns_trust_secure)
2450
0
    {
2451
0
      continue;
2452
0
    }
2453
2454
0
    if (rdataset->type == dns_rdatatype_nsec &&
2455
0
        (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2456
0
        !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2457
0
        dns_nsec_noexistnodata(val->type, wild, name, rdataset,
2458
0
             &exists, &data, NULL, validator_log,
2459
0
             val) == ISC_R_SUCCESS)
2460
0
    {
2461
0
      dns_name_t **proofs = val->proofs;
2462
0
      if (exists && !data) {
2463
0
        val->attributes |= VALATTR_FOUNDNODATA;
2464
0
      }
2465
0
      if (exists && !data && NEEDNODATA(val)) {
2466
0
        proofs[DNS_VALIDATOR_NODATAPROOF] = name;
2467
0
      }
2468
0
      if (!exists) {
2469
0
        val->attributes |= VALATTR_FOUNDNOWILDCARD;
2470
0
      }
2471
0
      if (!exists && NEEDNOQNAME(val)) {
2472
0
        proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name;
2473
0
      }
2474
0
      if (dns_rdataset_isassociated(&trdataset)) {
2475
0
        dns_rdataset_disassociate(&trdataset);
2476
0
      }
2477
0
      return ISC_R_SUCCESS;
2478
0
    }
2479
2480
0
    if (rdataset->type == dns_rdatatype_nsec3 &&
2481
0
        (NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
2482
0
        !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
2483
0
        dns_nsec3_noexistnodata(
2484
0
          val->type, wild, name, rdataset, zonename, &exists,
2485
0
          &data, NULL, NULL, NULL, NULL, NULL, NULL,
2486
0
          validator_log, val) == ISC_R_SUCCESS)
2487
0
    {
2488
0
      dns_name_t **proofs = val->proofs;
2489
0
      if (exists && !data) {
2490
0
        val->attributes |= VALATTR_FOUNDNODATA;
2491
0
      }
2492
0
      if (exists && !data && NEEDNODATA(val)) {
2493
0
        proofs[DNS_VALIDATOR_NODATAPROOF] = name;
2494
0
      }
2495
0
      if (!exists) {
2496
0
        val->attributes |= VALATTR_FOUNDNOWILDCARD;
2497
0
      }
2498
0
      if (!exists && NEEDNOQNAME(val)) {
2499
0
        proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name;
2500
0
      }
2501
0
      if (dns_rdataset_isassociated(&trdataset)) {
2502
0
        dns_rdataset_disassociate(&trdataset);
2503
0
      }
2504
0
      return ISC_R_SUCCESS;
2505
0
    }
2506
0
  }
2507
0
  if (result == ISC_R_NOMORE) {
2508
0
    result = ISC_R_SUCCESS;
2509
0
  }
2510
0
  if (dns_rdataset_isassociated(&trdataset)) {
2511
0
    dns_rdataset_disassociate(&trdataset);
2512
0
  }
2513
0
  return result;
2514
0
}
2515
2516
/*
2517
 * Look for the needed proofs for a negative or wildcard response
2518
 * from a zone using NSEC3, and set flags in the validator as they
2519
 * are found.
2520
 */
2521
static isc_result_t
2522
0
findnsec3proofs(dns_validator_t *val) {
2523
0
  dns_name_t *name, tname;
2524
0
  isc_result_t result;
2525
0
  bool exists, data, optout, unknown;
2526
0
  bool setclosest, setnearest, *setclosestp;
2527
0
  dns_fixedname_t fclosest, fnearest, fzonename;
2528
0
  dns_name_t *closest, *nearest, *zonename, *closestp;
2529
0
  dns_name_t **proofs = val->proofs;
2530
0
  dns_rdataset_t *rdataset, trdataset;
2531
2532
0
  dns_name_init(&tname);
2533
0
  dns_rdataset_init(&trdataset);
2534
0
  closest = dns_fixedname_initname(&fclosest);
2535
0
  nearest = dns_fixedname_initname(&fnearest);
2536
0
  zonename = dns_fixedname_initname(&fzonename);
2537
2538
0
  if (val->message == NULL) {
2539
0
    name = &tname;
2540
0
    rdataset = &trdataset;
2541
0
  } else {
2542
0
    name = NULL;
2543
0
    rdataset = NULL;
2544
0
  }
2545
2546
0
  for (result = val_rdataset_first(val, &name, &rdataset);
2547
0
       result == ISC_R_SUCCESS;
2548
0
       result = val_rdataset_next(val, &name, &rdataset))
2549
0
  {
2550
0
    if (rdataset->type != dns_rdatatype_nsec3 ||
2551
0
        rdataset->trust != dns_trust_secure)
2552
0
    {
2553
0
      continue;
2554
0
    }
2555
2556
0
    result = dns_nsec3_noexistnodata(val->type, val->name, name,
2557
0
             rdataset, zonename, NULL, NULL,
2558
0
             NULL, NULL, NULL, NULL, NULL,
2559
0
             NULL, validator_log, val);
2560
0
    if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
2561
0
      if (dns_rdataset_isassociated(&trdataset)) {
2562
0
        dns_rdataset_disassociate(&trdataset);
2563
0
      }
2564
0
      return result;
2565
0
    }
2566
0
  }
2567
0
  if (result != ISC_R_NOMORE) {
2568
0
    result = ISC_R_SUCCESS;
2569
0
  }
2570
0
  POST(result);
2571
2572
0
  if (dns_name_countlabels(zonename) == 0) {
2573
0
    if (dns_rdataset_isassociated(&trdataset)) {
2574
0
      dns_rdataset_disassociate(&trdataset);
2575
0
    }
2576
0
    return ISC_R_SUCCESS;
2577
0
  }
2578
2579
  /*
2580
   * If the val->closest is set then we want to use it otherwise
2581
   * we need to discover it.
2582
   */
2583
0
  if (dns_name_countlabels(dns_fixedname_name(&val->closest)) != 0) {
2584
0
    char namebuf[DNS_NAME_FORMATSIZE];
2585
2586
0
    dns_name_format(dns_fixedname_name(&val->closest), namebuf,
2587
0
        sizeof(namebuf));
2588
0
    validator_log(val, ISC_LOG_DEBUG(3),
2589
0
            "closest encloser from wildcard signature '%s'",
2590
0
            namebuf);
2591
0
    dns_name_copy(dns_fixedname_name(&val->closest), closest);
2592
0
    closestp = NULL;
2593
0
    setclosestp = NULL;
2594
0
  } else {
2595
0
    closestp = closest;
2596
0
    setclosestp = &setclosest;
2597
0
  }
2598
2599
0
  for (result = val_rdataset_first(val, &name, &rdataset);
2600
0
       result == ISC_R_SUCCESS;
2601
0
       result = val_rdataset_next(val, &name, &rdataset))
2602
0
  {
2603
0
    if (rdataset->type != dns_rdatatype_nsec3 ||
2604
0
        rdataset->trust != dns_trust_secure)
2605
0
    {
2606
0
      continue;
2607
0
    }
2608
2609
    /*
2610
     * We process all NSEC3 records to find the closest
2611
     * encloser and nearest name to the closest encloser.
2612
     */
2613
0
    setclosest = setnearest = false;
2614
0
    optout = false;
2615
0
    unknown = false;
2616
0
    result = dns_nsec3_noexistnodata(
2617
0
      val->type, val->name, name, rdataset, zonename, &exists,
2618
0
      &data, &optout, &unknown, setclosestp, &setnearest,
2619
0
      closestp, nearest, validator_log, val);
2620
0
    if (unknown) {
2621
0
      val->attributes |= VALATTR_FOUNDUNKNOWN;
2622
0
    }
2623
0
    if (result == DNS_R_NSEC3ITERRANGE) {
2624
      /*
2625
       * We don't really know which NSEC3 record provides
2626
       * which proof.  Just populate them.
2627
       */
2628
0
      if (NEEDNOQNAME(val) &&
2629
0
          proofs[DNS_VALIDATOR_NOQNAMEPROOF] == NULL)
2630
0
      {
2631
0
        proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
2632
0
      } else if (setclosest) {
2633
0
        proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
2634
0
      } else if (NEEDNODATA(val) &&
2635
0
           proofs[DNS_VALIDATOR_NODATAPROOF] == NULL)
2636
0
      {
2637
0
        proofs[DNS_VALIDATOR_NODATAPROOF] = name;
2638
0
      } else if (NEEDNOWILDCARD(val) &&
2639
0
           proofs[DNS_VALIDATOR_NOWILDCARDPROOF] ==
2640
0
             NULL)
2641
0
      {
2642
0
        proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name;
2643
0
      }
2644
0
      if (dns_rdataset_isassociated(&trdataset)) {
2645
0
        dns_rdataset_disassociate(&trdataset);
2646
0
      }
2647
0
      return result;
2648
0
    }
2649
0
    if (result != ISC_R_SUCCESS) {
2650
0
      continue;
2651
0
    }
2652
0
    if (setclosest) {
2653
0
      proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
2654
0
    }
2655
0
    if (exists && !data && NEEDNODATA(val)) {
2656
0
      val->attributes |= VALATTR_FOUNDNODATA;
2657
0
      proofs[DNS_VALIDATOR_NODATAPROOF] = name;
2658
0
    }
2659
0
    if (!exists && setnearest) {
2660
0
      val->attributes |= VALATTR_FOUNDNOQNAME;
2661
0
      proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
2662
0
      if (optout) {
2663
0
        val->attributes |= VALATTR_FOUNDOPTOUT;
2664
0
      }
2665
0
    }
2666
0
  }
2667
0
  if (result == ISC_R_NOMORE) {
2668
0
    result = ISC_R_SUCCESS;
2669
0
  }
2670
2671
  /*
2672
   * To know we have a valid noqname and optout proofs we need to also
2673
   * have a valid closest encloser.  Otherwise we could still be looking
2674
   * at proofs from the parent zone.
2675
   */
2676
0
  if (dns_name_countlabels(closest) > 0 &&
2677
0
      dns_name_countlabels(nearest) ==
2678
0
        dns_name_countlabels(closest) + 1 &&
2679
0
      dns_name_issubdomain(nearest, closest))
2680
0
  {
2681
0
    val->attributes |= VALATTR_FOUNDCLOSEST;
2682
0
    result = dns_name_concatenate(dns_wildcardname, closest,
2683
0
                dns_fixedname_name(&val->wild));
2684
0
    RUNTIME_CHECK(result == ISC_R_SUCCESS);
2685
0
  } else {
2686
0
    val->attributes &= ~VALATTR_FOUNDNOQNAME;
2687
0
    val->attributes &= ~VALATTR_FOUNDOPTOUT;
2688
0
    proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL;
2689
0
  }
2690
2691
  /*
2692
   * Do we need to check for the wildcard?
2693
   */
2694
0
  if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
2695
0
      ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val)))
2696
0
  {
2697
0
    result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
2698
0
    if (result != ISC_R_SUCCESS) {
2699
0
      if (dns_rdataset_isassociated(&trdataset)) {
2700
0
        dns_rdataset_disassociate(&trdataset);
2701
0
      }
2702
0
      return result;
2703
0
    }
2704
0
  }
2705
0
  if (dns_rdataset_isassociated(&trdataset)) {
2706
0
    dns_rdataset_disassociate(&trdataset);
2707
0
  }
2708
0
  return result;
2709
0
}
2710
2711
/*
2712
 * Start a validator for negative response data.
2713
 *
2714
 * Returns:
2715
 * \li  DNS_R_CONTINUE  Validation skipped, continue
2716
 * \li  DNS_R_WAIT  Validation is in progress
2717
 *
2718
 * \li  Other return codes indicate failure.
2719
 */
2720
static isc_result_t
2721
validate_neg_rrset(dns_validator_t *val, dns_name_t *name,
2722
0
       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
2723
0
  isc_result_t result;
2724
2725
  /*
2726
   * If a signed zone is missing the zone key, bad
2727
   * things could happen.  A query for data in the zone
2728
   * would lead to a query for the zone key, which
2729
   * would return a negative answer, which would contain
2730
   * an SOA and an NSEC signed by the missing key, which
2731
   * would trigger another query for the DNSKEY (since
2732
   * the first one is still in progress), and go into an
2733
   * infinite loop.  Avoid that.
2734
   */
2735
0
  if (val->type == dns_rdatatype_dnskey &&
2736
0
      rdataset->type == dns_rdatatype_nsec &&
2737
0
      dns_name_equal(name, val->name))
2738
0
  {
2739
0
    dns_rdata_t nsec = DNS_RDATA_INIT;
2740
2741
0
    result = dns_rdataset_first(rdataset);
2742
0
    if (result != ISC_R_SUCCESS) {
2743
0
      return result;
2744
0
    }
2745
0
    dns_rdataset_current(rdataset, &nsec);
2746
0
    if (dns_nsec_typepresent(&nsec, dns_rdatatype_soa)) {
2747
0
      return DNS_R_CONTINUE;
2748
0
    }
2749
0
  }
2750
2751
0
  val->nxset = rdataset;
2752
0
  result = create_validator(val, name, rdataset->type, rdataset,
2753
0
          sigrdataset, validator_callback_nsec,
2754
0
          "validate_neg_rrset");
2755
0
  if (result != ISC_R_SUCCESS) {
2756
0
    return result;
2757
0
  }
2758
2759
0
  val->authcount++;
2760
0
  return DNS_R_WAIT;
2761
0
}
2762
2763
/*%
2764
 * Validate the authority section records.
2765
 */
2766
static isc_result_t
2767
0
validate_authority(dns_validator_t *val, bool resume) {
2768
0
  dns_name_t *name;
2769
0
  dns_message_t *message = val->message;
2770
0
  isc_result_t result;
2771
2772
0
  if (!resume) {
2773
0
    result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
2774
0
  } else {
2775
0
    result = ISC_R_SUCCESS;
2776
0
  }
2777
2778
0
  for (; result == ISC_R_SUCCESS;
2779
0
       result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
2780
0
  {
2781
0
    dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
2782
2783
0
    name = NULL;
2784
0
    dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
2785
0
    if (resume) {
2786
0
      rdataset = ISC_LIST_NEXT(val->nxset, link);
2787
0
      val->nxset = NULL;
2788
0
      resume = false;
2789
0
    } else {
2790
0
      rdataset = ISC_LIST_HEAD(name->list);
2791
0
    }
2792
2793
0
    for (; rdataset != NULL;
2794
0
         rdataset = ISC_LIST_NEXT(rdataset, link))
2795
0
    {
2796
0
      if (rdataset->type == dns_rdatatype_rrsig) {
2797
0
        continue;
2798
0
      }
2799
2800
0
      for (sigrdataset = ISC_LIST_HEAD(name->list);
2801
0
           sigrdataset != NULL;
2802
0
           sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
2803
0
      {
2804
0
        if (sigrdataset->type == dns_rdatatype_rrsig &&
2805
0
            sigrdataset->covers == rdataset->type)
2806
0
        {
2807
0
          break;
2808
0
        }
2809
0
      }
2810
2811
0
      result = validate_neg_rrset(val, name, rdataset,
2812
0
                sigrdataset);
2813
0
      if (result != DNS_R_CONTINUE) {
2814
0
        return result;
2815
0
      }
2816
0
    }
2817
0
  }
2818
0
  if (result == ISC_R_NOMORE) {
2819
0
    result = ISC_R_SUCCESS;
2820
0
  }
2821
0
  return result;
2822
0
}
2823
2824
/*%
2825
 * Validate negative cache elements.
2826
 */
2827
static isc_result_t
2828
0
validate_ncache(dns_validator_t *val, bool resume) {
2829
0
  dns_name_t *name;
2830
0
  isc_result_t result;
2831
2832
0
  if (!resume) {
2833
0
    result = dns_rdataset_first(val->rdataset);
2834
0
  } else {
2835
0
    result = dns_rdataset_next(val->rdataset);
2836
0
  }
2837
2838
0
  for (; result == ISC_R_SUCCESS;
2839
0
       result = dns_rdataset_next(val->rdataset))
2840
0
  {
2841
0
    dns_rdataset_t *rdataset, *sigrdataset = NULL;
2842
2843
0
    disassociate_rdatasets(val);
2844
2845
0
    name = dns_fixedname_initname(&val->fname);
2846
0
    rdataset = &val->frdataset;
2847
0
    dns_ncache_current(val->rdataset, name, rdataset);
2848
2849
0
    if (val->frdataset.type == dns_rdatatype_rrsig) {
2850
0
      continue;
2851
0
    }
2852
2853
0
    result = dns_ncache_getsigrdataset(val->rdataset, name,
2854
0
               rdataset->type,
2855
0
               &val->fsigrdataset);
2856
0
    if (result == ISC_R_SUCCESS) {
2857
0
      sigrdataset = &val->fsigrdataset;
2858
0
    }
2859
2860
0
    result = validate_neg_rrset(val, name, rdataset, sigrdataset);
2861
0
    if (result == DNS_R_CONTINUE) {
2862
0
      continue;
2863
0
    }
2864
2865
0
    return result;
2866
0
  }
2867
0
  if (result == ISC_R_NOMORE) {
2868
0
    result = ISC_R_SUCCESS;
2869
0
  }
2870
2871
0
  return result;
2872
0
}
2873
2874
/*%
2875
 * Prove a negative answer is good or that there is a NOQNAME when the
2876
 * answer is from a wildcard.
2877
 *
2878
 * Loop through the authority section looking for NODATA, NOWILDCARD
2879
 * and NOQNAME proofs in the NSEC records by calling
2880
 * validator_callback_nsec().
2881
 *
2882
 * If the required proofs are found we are done.
2883
 *
2884
 * If the proofs are not found attempt to prove this is an unsecure
2885
 * response.
2886
 */
2887
static isc_result_t
2888
0
validate_nx(dns_validator_t *val, bool resume) {
2889
0
  isc_result_t result;
2890
2891
0
  if (resume) {
2892
0
    validator_log(val, ISC_LOG_DEBUG(3), "resuming validate_nx");
2893
0
  }
2894
2895
0
  if (val->message == NULL) {
2896
0
    result = validate_ncache(val, resume);
2897
0
  } else {
2898
0
    result = validate_authority(val, resume);
2899
0
  }
2900
2901
0
  if (result != ISC_R_SUCCESS) {
2902
0
    return result;
2903
0
  }
2904
2905
  /*
2906
   * Do we only need to check for NOQNAME?  To get here we must have
2907
   * had a secure wildcard answer.
2908
   */
2909
0
  if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
2910
0
    if (!FOUNDNOQNAME(val)) {
2911
0
      result = findnsec3proofs(val);
2912
0
      if (result == DNS_R_NSEC3ITERRANGE) {
2913
0
        validator_log(val, ISC_LOG_DEBUG(3),
2914
0
                "too many iterations");
2915
0
        markanswer(val, "validate_nx (3)");
2916
0
        return ISC_R_SUCCESS;
2917
0
      }
2918
0
    }
2919
2920
0
    if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) && !FOUNDOPTOUT(val))
2921
0
    {
2922
0
      validator_log(val, ISC_LOG_DEBUG(3),
2923
0
              "marking as secure, noqname proof found");
2924
0
      marksecure(val);
2925
0
      return ISC_R_SUCCESS;
2926
0
    } else if (FOUNDOPTOUT(val) &&
2927
0
         dns_name_countlabels(
2928
0
           dns_fixedname_name(&val->wild)) != 0)
2929
0
    {
2930
0
      validator_log(val, ISC_LOG_DEBUG(3),
2931
0
              "optout proof found");
2932
0
      val->optout = true;
2933
0
      markanswer(val, "validate_nx (1)");
2934
0
      return ISC_R_SUCCESS;
2935
0
    } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
2936
0
      validator_log(val, ISC_LOG_DEBUG(3),
2937
0
              "unknown NSEC3 hash algorithm found");
2938
0
      markanswer(val, "validate_nx (2)");
2939
0
      return ISC_R_SUCCESS;
2940
0
    }
2941
2942
0
    validator_log(val, ISC_LOG_DEBUG(3), "noqname proof not found");
2943
0
    return DNS_R_NOVALIDNSEC;
2944
0
  }
2945
2946
0
  if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val)) {
2947
0
    result = findnsec3proofs(val);
2948
0
    if (result == DNS_R_NSEC3ITERRANGE) {
2949
0
      validator_log(val, ISC_LOG_DEBUG(3),
2950
0
              "too many iterations");
2951
0
      markanswer(val, "validate_nx (4)");
2952
0
      return ISC_R_SUCCESS;
2953
0
    }
2954
0
  }
2955
2956
  /*
2957
   * Do we need to check for the wildcard?
2958
   */
2959
0
  if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
2960
0
      ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val)))
2961
0
  {
2962
0
    result = checkwildcard(val, dns_rdatatype_nsec, NULL);
2963
0
    if (result != ISC_R_SUCCESS) {
2964
0
      return result;
2965
0
    }
2966
0
  }
2967
2968
0
  if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) ||
2969
0
      (NEEDNOQNAME(val) && FOUNDNOQNAME(val) && NEEDNOWILDCARD(val) &&
2970
0
       FOUNDNOWILDCARD(val) && FOUNDCLOSEST(val)))
2971
0
  {
2972
0
    if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0) {
2973
0
      val->optout = true;
2974
0
    }
2975
0
    validator_log(val, ISC_LOG_DEBUG(3),
2976
0
            "nonexistence proof(s) found");
2977
0
    if (val->message == NULL) {
2978
0
      marksecure(val);
2979
0
    } else {
2980
0
      val->secure = true;
2981
0
    }
2982
0
    return ISC_R_SUCCESS;
2983
0
  }
2984
2985
0
  if (val->authfail != 0 && val->authcount == val->authfail) {
2986
0
    return DNS_R_BROKENCHAIN;
2987
0
  }
2988
2989
0
  return proveunsecure(val, false, false, false);
2990
0
}
2991
2992
/*
2993
 * Check if any of the DS records has a private DNSSEC algorithm.
2994
 */
2995
static bool
2996
0
check_ds_private(dns_rdataset_t *rdataset) {
2997
0
  dns_rdata_ds_t ds;
2998
0
  isc_result_t result;
2999
3000
0
  for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
3001
0
       result = dns_rdataset_next(rdataset))
3002
0
  {
3003
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
3004
0
    dns_rdataset_current(rdataset, &rdata);
3005
0
    result = dns_rdata_tostruct(&rdata, &ds, NULL);
3006
0
    RUNTIME_CHECK(result == ISC_R_SUCCESS);
3007
0
    if (ds.algorithm == DNS_KEYALG_PRIVATEDNS ||
3008
0
        ds.algorithm == DNS_KEYALG_PRIVATEOID)
3009
0
    {
3010
0
      return true;
3011
0
    }
3012
0
  }
3013
0
  return false;
3014
0
}
3015
3016
/*%
3017
 * Check that DS rdataset has at least one record with
3018
 * a supported algorithm and digest.
3019
 */
3020
static bool
3021
check_ds_algs(dns_validator_t *val, dns_name_t *name,
3022
0
        dns_rdataset_t *dsrdataset, dns_rdataset_t *dnskeyset) {
3023
0
  dns_rdata_ds_t ds;
3024
0
  dns_rdata_dnskey_t key;
3025
0
  bool seen_private = false;
3026
0
  uint16_t key_tag = 0;
3027
0
  uint8_t algorithm = 0;
3028
3029
0
  DNS_RDATASET_FOREACH (dsrdataset) {
3030
0
    isc_result_t result;
3031
0
    dns_rdata_t dsrdata = DNS_RDATA_INIT;
3032
0
    dns_rdata_t keyrdata = DNS_RDATA_INIT;
3033
0
    unsigned char *data = NULL;
3034
0
    size_t datalen = 0;
3035
3036
0
    dns_rdataset_current(dsrdataset, &dsrdata);
3037
0
    result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
3038
0
    RUNTIME_CHECK(result == ISC_R_SUCCESS);
3039
3040
    /*
3041
     * Look for a matching DNSKEY to find the PRIVATE
3042
     * DNSSEC algorithm.
3043
     */
3044
0
    if (ds.algorithm == DNS_KEYALG_PRIVATEOID ||
3045
0
        ds.algorithm == DNS_KEYALG_PRIVATEDNS)
3046
0
    {
3047
0
      switch (ds.digest_type) {
3048
#if defined(DNS_DSDIGEST_SHA256PRIVATE) && defined(DNS_DSDIGEST_SHA384PRIVATE)
3049
      case DNS_DSDIGEST_SHA256PRIVATE:
3050
      case DNS_DSDIGEST_SHA384PRIVATE:
3051
        data = ds.digest;
3052
        datalen = ds.length;
3053
        break;
3054
#endif
3055
0
      case DNS_DSDIGEST_SHA1:
3056
0
      case DNS_DSDIGEST_SHA256:
3057
0
      case DNS_DSDIGEST_SHA384:
3058
0
        if (dnskeyset == NULL) {
3059
0
          algorithm = ds.algorithm;
3060
0
          key_tag = ds.key_tag;
3061
0
          seen_private = true;
3062
0
          continue;
3063
0
        }
3064
0
        result = dns_dnssec_matchdskey(
3065
0
          name, &dsrdata, dnskeyset, &keyrdata);
3066
0
        if (result != ISC_R_SUCCESS) {
3067
0
          algorithm = ds.algorithm;
3068
0
          key_tag = ds.key_tag;
3069
0
          seen_private = true;
3070
0
          continue;
3071
0
        }
3072
0
        result = dns_rdata_tostruct(&keyrdata, &key,
3073
0
                  NULL);
3074
0
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
3075
0
        data = key.data;
3076
0
        datalen = key.datalen;
3077
0
        break;
3078
0
      default:
3079
0
        break;
3080
0
      }
3081
0
    }
3082
3083
0
    if (dns_resolver_ds_digest_supported(val->view->resolver, name,
3084
0
                 ds.digest_type) &&
3085
0
        dns_resolver_algorithm_supported(val->view->resolver, name,
3086
0
                 ds.algorithm, data,
3087
0
                 datalen))
3088
0
    {
3089
0
      return true;
3090
0
    }
3091
0
  }
3092
3093
  /*
3094
   * No unsupported alg/digest EDE error is raised here because the prove
3095
   * unsecure flow always runs after a validate/validatenx flow. So if an
3096
   * unsupported alg/digest was found while building the chain of trust,
3097
   * it would be raised already.
3098
   *
3099
   * If we have seen a private algorithm for which we couldn't find a
3100
   * DNSKEY nor extract it from the digest field we must assume the child
3101
   * zone is secure. With PRIVATEDNS and PRIVATEOID we can make that
3102
   * determination if we match a DNSKEY for every DS with these algorithms
3103
   * or extract the algorithm from the digest field. Since we don't know
3104
   * whether the private algorithm is unsupported or not, we are required
3105
   * to treat it as supported.
3106
   */
3107
0
  if (seen_private) {
3108
0
    char namebuf[DNS_NAME_FORMATSIZE];
3109
0
    dns_name_format(name, namebuf, sizeof(namebuf));
3110
0
    validator_log(val, ISC_LOG_INFO,
3111
0
            "No DNSKEY for %s/DS with %s algorithm, tag %u",
3112
0
            namebuf,
3113
0
            algorithm == DNS_KEYALG_PRIVATEDNS ? "PRIVATEDNS"
3114
0
                 : "PRIVATEOID",
3115
0
            key_tag);
3116
0
  }
3117
0
  return seen_private;
3118
0
}
3119
3120
/*%
3121
 * seek_ds is called to look up DS rrsets at the label of val->name
3122
 * indicated by val->labels. This is done while building an insecurity
3123
 * proof, and so it will attempt validation of NXDOMAIN, NXRRSET or CNAME
3124
 * responses.
3125
 *
3126
 * Returns:
3127
 * \li  ISC_R_COMPLETE    a result has been determined and copied
3128
 *        into `*resp`; ISC_R_SUCCESS indicates that
3129
 *        the name has been proven insecure and any
3130
 *        other result indicates failure.
3131
 * \li  DNS_R_CONTINUE    result is indeterminate; caller should
3132
 *        continue walking down labels.
3133
 */
3134
static isc_result_t
3135
0
seek_ds(dns_validator_t *val, isc_result_t *resp) {
3136
0
  isc_result_t result;
3137
0
  char namebuf[DNS_NAME_FORMATSIZE];
3138
0
  dns_fixedname_t fixedfound;
3139
0
  dns_name_t *found = dns_fixedname_initname(&fixedfound);
3140
0
  dns_name_t *tname = dns_fixedname_initname(&val->fname);
3141
3142
0
  if (val->labels == dns_name_countlabels(val->name)) {
3143
0
    dns_name_copy(val->name, tname);
3144
0
  } else {
3145
0
    dns_name_split(val->name, val->labels, NULL, tname);
3146
0
  }
3147
3148
0
  dns_name_format(tname, namebuf, sizeof(namebuf));
3149
0
  validator_log(val, ISC_LOG_DEBUG(3), "checking existence of DS at '%s'",
3150
0
          namebuf);
3151
3152
0
  result = view_find(val, tname, dns_rdatatype_ds);
3153
0
  switch (result) {
3154
0
  case ISC_R_SUCCESS:
3155
    /*
3156
     * There is a DS here.  If it's already been
3157
     * validated, continue walking down labels.
3158
     */
3159
0
    if (val->frdataset.trust >= dns_trust_secure) {
3160
0
      dns_rdataset_t *dssetp = &val->frdataset,
3161
0
               *keysetp = NULL;
3162
3163
0
      if (check_ds_private(&val->frdataset)) {
3164
0
        if (dns_rdataset_isassociated(&val->dsrdataset))
3165
0
        {
3166
0
          dns_rdataset_disassociate(
3167
0
            &val->dsrdataset);
3168
0
        }
3169
0
        dns_rdataset_clone(&val->frdataset,
3170
0
               &val->dsrdataset);
3171
0
        dssetp = &val->dsrdataset;
3172
0
        dns_rdataset_disassociate(&val->frdataset);
3173
0
        result = view_find(val, tname,
3174
0
               dns_rdatatype_dnskey);
3175
0
        switch (result) {
3176
0
        case ISC_R_SUCCESS:
3177
0
          keysetp = &val->frdataset;
3178
0
          break;
3179
0
        case ISC_R_NOTFOUND:
3180
          /*
3181
           * We don't know anything about the
3182
           * DNSKEY.  Find it.
3183
           */
3184
0
          *resp = DNS_R_WAIT;
3185
0
          result = create_fetch(
3186
0
            val, tname,
3187
0
            dns_rdatatype_dnskey,
3188
0
            fetch_callback_dnskey,
3189
0
            "seek_ds");
3190
0
          if (result != ISC_R_SUCCESS) {
3191
0
            *resp = result;
3192
0
          }
3193
0
          return ISC_R_COMPLETE;
3194
0
          break;
3195
0
        default:
3196
0
          validator_log(val, ISC_LOG_DEBUG(3),
3197
0
                  "no DNSKEY found (%s/DS)",
3198
0
                  namebuf);
3199
0
          break;
3200
0
        }
3201
0
      }
3202
0
      if (!check_ds_algs(val, tname, dssetp, keysetp)) {
3203
0
        validator_log(
3204
0
          val, ISC_LOG_DEBUG(3),
3205
0
          "no supported algorithm/digest (%s/DS)",
3206
0
          namebuf);
3207
0
        *resp = markanswer(val, "seek_ds (1)");
3208
0
        return ISC_R_COMPLETE;
3209
0
      }
3210
3211
0
      break;
3212
0
    }
3213
3214
    /*
3215
     * Otherwise, try to validate it now.
3216
     */
3217
0
    result = create_validator(val, tname, dns_rdatatype_ds,
3218
0
            &val->frdataset, &val->fsigrdataset,
3219
0
            validator_callback_ds, "seek_ds");
3220
0
    *resp = DNS_R_WAIT;
3221
0
    if (result != ISC_R_SUCCESS) {
3222
0
      *resp = result;
3223
0
    }
3224
3225
0
    return ISC_R_COMPLETE;
3226
3227
0
  case ISC_R_NOTFOUND:
3228
    /*
3229
     * We don't know anything about the DS.  Find it.
3230
     */
3231
0
    *resp = DNS_R_WAIT;
3232
0
    result = create_fetch(val, tname, dns_rdatatype_ds,
3233
0
              fetch_callback_ds, "seek_ds");
3234
0
    if (result != ISC_R_SUCCESS) {
3235
0
      *resp = result;
3236
0
    }
3237
0
    return ISC_R_COMPLETE;
3238
3239
0
  case DNS_R_NXRRSET:
3240
0
  case DNS_R_NCACHENXRRSET:
3241
    /*
3242
     * There is no DS.  If this is a delegation,
3243
     * we may be done.
3244
     *
3245
     * If we have "trust == answer" then this namespace
3246
     * has switched from insecure to should be secure.
3247
     */
3248
0
    if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3249
0
        DNS_TRUST_ANSWER(val->frdataset.trust))
3250
0
    {
3251
0
      result = create_validator(
3252
0
        val, tname, dns_rdatatype_ds, &val->frdataset,
3253
0
        &val->fsigrdataset, validator_callback_ds,
3254
0
        "seek_ds");
3255
0
      *resp = DNS_R_WAIT;
3256
0
      if (result != ISC_R_SUCCESS) {
3257
0
        *resp = result;
3258
0
      }
3259
0
      return ISC_R_COMPLETE;
3260
0
    }
3261
3262
    /*
3263
     * Zones using NSEC3 don't return a NSEC RRset so
3264
     * we need to use dns_view_findzonecut2 to find
3265
     * the zone cut.
3266
     */
3267
0
    if (result == DNS_R_NXRRSET &&
3268
0
        !dns_rdataset_isassociated(&val->frdataset) &&
3269
0
        dns_view_findzonecut(val->view, tname, found, NULL, 0, 0,
3270
0
           false, false, NULL,
3271
0
           NULL) == ISC_R_SUCCESS &&
3272
0
        dns_name_equal(tname, found))
3273
0
    {
3274
0
      *resp = markanswer(val, "seek_ds (2)");
3275
0
      return ISC_R_COMPLETE;
3276
0
    }
3277
3278
0
    if (val->frdataset.trust < dns_trust_secure) {
3279
      /*
3280
       * This shouldn't happen, since the negative
3281
       * response should have been validated.  Since
3282
       * there's no way of validating existing
3283
       * negative response blobs, give up.
3284
       */
3285
0
      validator_log(val, ISC_LOG_WARNING,
3286
0
              "can't validate existing "
3287
0
              "negative responses (no DS)");
3288
0
      *resp = DNS_R_NOVALIDSIG;
3289
0
      return ISC_R_COMPLETE;
3290
0
    }
3291
3292
0
    if (isdelegation(tname, &val->frdataset, result)) {
3293
0
      *resp = markanswer(val, "seek_ds (3)");
3294
0
      return ISC_R_COMPLETE;
3295
0
    }
3296
3297
0
    break;
3298
3299
0
  case DNS_R_NXDOMAIN:
3300
0
  case DNS_R_NCACHENXDOMAIN:
3301
    /*
3302
     * This is not a zone cut. Assuming things are
3303
     * as expected, continue.
3304
     */
3305
0
    if (!dns_rdataset_isassociated(&val->frdataset)) {
3306
      /*
3307
       * There should be an NSEC here, since we
3308
       * are still in a secure zone.
3309
       */
3310
0
      *resp = DNS_R_NOVALIDNSEC;
3311
0
      return ISC_R_COMPLETE;
3312
0
    } else if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3313
0
         DNS_TRUST_ANSWER(val->frdataset.trust))
3314
0
    {
3315
      /*
3316
       * If we have "trust == answer" then this
3317
       * namespace has switched from insecure to
3318
       * should be secure.
3319
       */
3320
0
      *resp = DNS_R_WAIT;
3321
0
      result = create_validator(
3322
0
        val, tname, dns_rdatatype_ds, &val->frdataset,
3323
0
        &val->fsigrdataset, validator_callback_ds,
3324
0
        "seek_ds");
3325
0
      if (result != ISC_R_SUCCESS) {
3326
0
        *resp = result;
3327
0
      }
3328
0
      return ISC_R_COMPLETE;
3329
0
    } else if (val->frdataset.trust < dns_trust_secure) {
3330
      /*
3331
       * This shouldn't happen, since the negative
3332
       * response should have been validated.  Since
3333
       * there's no way of validating existing
3334
       * negative response blobs, give up.
3335
       */
3336
0
      validator_log(val, ISC_LOG_WARNING,
3337
0
              "can't validate existing "
3338
0
              "negative responses "
3339
0
              "(not a zone cut)");
3340
0
      *resp = DNS_R_NOVALIDSIG;
3341
0
      return ISC_R_COMPLETE;
3342
0
    }
3343
3344
0
    break;
3345
3346
0
  case DNS_R_CNAME:
3347
0
    if (DNS_TRUST_PENDING(val->frdataset.trust) ||
3348
0
        DNS_TRUST_ANSWER(val->frdataset.trust))
3349
0
    {
3350
0
      result = create_validator(
3351
0
        val, tname, dns_rdatatype_cname,
3352
0
        &val->frdataset, &val->fsigrdataset,
3353
0
        validator_callback_cname, "seek_ds (cname)");
3354
0
      *resp = DNS_R_WAIT;
3355
0
      if (result != ISC_R_SUCCESS) {
3356
0
        *resp = result;
3357
0
      }
3358
0
      return ISC_R_COMPLETE;
3359
0
    }
3360
3361
0
    break;
3362
3363
0
  default:
3364
0
    *resp = result;
3365
0
    return ISC_R_COMPLETE;
3366
0
  }
3367
3368
  /*
3369
   * No definite answer yet; continue walking down labels.
3370
   */
3371
0
  return DNS_R_CONTINUE;
3372
0
}
3373
3374
/*%
3375
 * proveunsecure walks down, label by label, from the closest enclosing
3376
 * trust anchor to the name that is being validated, looking for an
3377
 * endpoint in the chain of trust.  That occurs when we can prove that
3378
 * a DS record does not exist at a delegation point, or that a DS exists
3379
 * at a delegation point but we don't support its algorithm/digest.  If
3380
 * no such endpoint is found, then the response should have been secure.
3381
 *
3382
 * Returns:
3383
 * \li  ISC_R_SUCCESS   val->name is in an unsecure zone
3384
 * \li  DNS_R_WAIT    validation is in progress.
3385
 * \li  DNS_R_NOVALIDSIG
3386
 * \li  DNS_R_NOVALIDNSEC
3387
 * \li  DNS_R_NOTINSECURE
3388
 * \li  DNS_R_BROKENCHAIN
3389
 */
3390
static isc_result_t
3391
proveunsecure(dns_validator_t *val, bool have_ds, bool have_dnskey,
3392
0
        bool resume) {
3393
0
  isc_result_t result;
3394
0
  char namebuf[DNS_NAME_FORMATSIZE];
3395
0
  dns_fixedname_t fixedsecroot;
3396
0
  dns_name_t *secroot = dns_fixedname_initname(&fixedsecroot);
3397
0
  unsigned int labels;
3398
3399
0
  INSIST(!(have_ds && have_dnskey));
3400
3401
  /*
3402
   * We're attempting to prove insecurity.
3403
   */
3404
0
  val->attributes |= VALATTR_INSECURITY;
3405
3406
0
  dns_name_copy(val->name, secroot);
3407
3408
  /*
3409
   * If this is a response to a DS query, we need to look in
3410
   * the parent zone for the trust anchor.
3411
   */
3412
0
  labels = dns_name_countlabels(secroot);
3413
0
  if (val->type == dns_rdatatype_ds && labels > 1U) {
3414
0
    dns_name_getlabelsequence(secroot, 1, labels - 1, secroot);
3415
0
  }
3416
3417
0
  result = dns_keytable_finddeepestmatch(val->keytable, secroot, secroot);
3418
0
  if (result == ISC_R_NOTFOUND) {
3419
0
    validator_log(val, ISC_LOG_DEBUG(3), "not beneath secure root");
3420
0
    return markanswer(val, "proveunsecure (1)");
3421
0
  } else if (result != ISC_R_SUCCESS) {
3422
0
    return result;
3423
0
  }
3424
3425
0
  if (!resume) {
3426
    /*
3427
     * We are looking for interruptions in the chain of trust.
3428
     * That can only happen *below* the trust anchor, so we
3429
     * start looking at the next label down.
3430
     */
3431
0
    val->labels = dns_name_countlabels(secroot) + 1;
3432
0
  } else {
3433
0
    validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
3434
3435
    /*
3436
     * If we have a DS rdataset and it is secure, check whether
3437
     * it has a supported algorithm combination.  If not, this is
3438
     * an insecure delegation as far as this resolver is concerned.
3439
     */
3440
0
    if (have_dnskey ||
3441
0
        (have_ds && val->frdataset.trust >= dns_trust_secure))
3442
0
    {
3443
0
      dns_rdataset_t *dssetp = NULL, *keysetp = NULL;
3444
0
      dns_name_t *fname = dns_fixedname_name(&val->fname);
3445
0
      if (have_dnskey) {
3446
0
        dssetp = &val->dsrdataset;
3447
0
        keysetp = &val->frdataset;
3448
0
      } else {
3449
0
        dssetp = &val->frdataset;
3450
0
      }
3451
3452
0
      if (!have_dnskey && check_ds_private(&val->frdataset)) {
3453
0
        if (dns_rdataset_isassociated(&val->dsrdataset))
3454
0
        {
3455
0
          dns_rdataset_disassociate(
3456
0
            &val->dsrdataset);
3457
0
        }
3458
0
        dns_rdataset_clone(&val->frdataset,
3459
0
               &val->dsrdataset);
3460
0
        dssetp = &val->dsrdataset;
3461
0
        dns_rdataset_disassociate(&val->frdataset);
3462
0
        result = view_find(val, fname,
3463
0
               dns_rdatatype_dnskey);
3464
0
        switch (result) {
3465
0
        case ISC_R_SUCCESS:
3466
0
          keysetp = &val->frdataset;
3467
0
          break;
3468
0
        case ISC_R_NOTFOUND:
3469
          /*
3470
           * We don't know anything about the
3471
           * DNSKEY.  Find it.
3472
           */
3473
0
          result = create_fetch(
3474
0
            val, fname,
3475
0
            dns_rdatatype_dnskey,
3476
0
            fetch_callback_dnskey,
3477
0
            "seek_ds");
3478
0
          if (result == ISC_R_SUCCESS) {
3479
0
            result = DNS_R_WAIT;
3480
0
          }
3481
0
          goto out;
3482
0
        default:
3483
0
          validator_log(val, ISC_LOG_DEBUG(3),
3484
0
                  "no DNSKEY found (%s/DS)",
3485
0
                  namebuf);
3486
0
          break;
3487
0
        }
3488
0
      }
3489
0
      if (!check_ds_algs(val, fname, dssetp, keysetp)) {
3490
0
        dns_name_format(fname, namebuf,
3491
0
            sizeof(namebuf));
3492
0
        validator_log(
3493
0
          val, ISC_LOG_DEBUG(3),
3494
0
          "no supported algorithm/digest (%s/DS)",
3495
0
          namebuf);
3496
0
        result = markanswer(val, "proveunsecure (2)");
3497
0
        goto out;
3498
0
      }
3499
0
    }
3500
0
    val->labels++;
3501
0
  }
3502
3503
  /*
3504
   * Walk down through each of the remaining labels in the name,
3505
   * looking for DS records.
3506
   */
3507
0
  while (val->labels <= dns_name_countlabels(val->name)) {
3508
0
    isc_result_t tresult;
3509
3510
0
    result = seek_ds(val, &tresult);
3511
0
    if (result == ISC_R_COMPLETE) {
3512
0
      result = tresult;
3513
0
      goto out;
3514
0
    }
3515
3516
0
    INSIST(result == DNS_R_CONTINUE);
3517
0
    val->labels++;
3518
0
  }
3519
3520
  /* Couldn't complete insecurity proof. */
3521
0
  validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed: %s",
3522
0
          isc_result_totext(result));
3523
0
  return DNS_R_NOTINSECURE;
3524
3525
0
out:
3526
0
  if (result != DNS_R_WAIT) {
3527
0
    disassociate_rdatasets(val);
3528
0
  }
3529
0
  return result;
3530
0
}
3531
3532
/*%
3533
 * Start the validation process.
3534
 *
3535
 * Attempt to validate the answer based on the category it appears to
3536
 * fall in.
3537
 * \li  1. secure positive answer.
3538
 * \li  2. unsecure positive answer.
3539
 * \li  3. a negative answer (secure or unsecure).
3540
 *
3541
 * Note an answer that appears to be a secure positive answer may actually
3542
 * be an unsecure positive answer.
3543
 */
3544
static void
3545
0
validator_start(void *arg) {
3546
0
  dns_validator_t *val = (dns_validator_t *)arg;
3547
0
  isc_result_t result = ISC_R_FAILURE;
3548
3549
0
  if (CANCELED(val) || CANCELING(val)) {
3550
0
    result = ISC_R_CANCELED;
3551
0
    goto cleanup;
3552
0
  }
3553
3554
0
  validator_log(val, ISC_LOG_DEBUG(3), "starting");
3555
3556
0
  if (val->rdataset != NULL && val->sigrdataset != NULL) {
3557
    /*
3558
     * This looks like a simple validation.  We say "looks like"
3559
     * because it might end up requiring an insecurity proof.
3560
     */
3561
0
    validator_log(val, ISC_LOG_DEBUG(3),
3562
0
            "attempting positive response validation");
3563
3564
0
    INSIST(dns_rdataset_isassociated(val->rdataset));
3565
0
    INSIST(dns_rdataset_isassociated(val->sigrdataset));
3566
3567
0
    result = selfsigned_dnskey(val);
3568
0
    switch (result) {
3569
0
    case ISC_R_QUOTA:
3570
0
      goto cleanup;
3571
0
    case ISC_R_SUCCESS:
3572
0
      result = validate_async_run(val, validate_dnskey);
3573
0
      break;
3574
0
    case DNS_R_NOKEYMATCH:
3575
0
      result = validate_async_run(val, validate_answer);
3576
0
      break;
3577
0
    default:
3578
0
      UNREACHABLE();
3579
0
    }
3580
0
  } else if (val->rdataset != NULL && val->rdataset->type != 0) {
3581
    /*
3582
     * This is either an unsecure subdomain or a response
3583
     * from a broken server.
3584
     */
3585
0
    INSIST(dns_rdataset_isassociated(val->rdataset));
3586
0
    validator_log(val, ISC_LOG_DEBUG(3),
3587
0
            "attempting insecurity proof");
3588
3589
0
    result = proveunsecure(val, false, false, false);
3590
0
    if (result == DNS_R_NOTINSECURE) {
3591
0
      validator_log(val, ISC_LOG_INFO,
3592
0
              "got insecure response; "
3593
0
              "parent indicates it should be secure");
3594
0
    }
3595
0
  } else if (val->rdataset == NULL && val->sigrdataset == NULL) {
3596
    /*
3597
     * This is a validation of a negative response.
3598
     */
3599
0
    validator_log(val, ISC_LOG_DEBUG(3),
3600
0
            "attempting negative response validation "
3601
0
            "from message");
3602
3603
0
    if (val->message->rcode == dns_rcode_nxdomain) {
3604
0
      val->attributes |= VALATTR_NEEDNOQNAME;
3605
0
      val->attributes |= VALATTR_NEEDNOWILDCARD;
3606
0
    } else {
3607
0
      val->attributes |= VALATTR_NEEDNODATA;
3608
0
    }
3609
3610
0
    result = validate_nx(val, false);
3611
0
  } else if (val->rdataset != NULL && NEGATIVE(val->rdataset)) {
3612
    /*
3613
     * This is a delayed validation of a negative cache entry.
3614
     */
3615
0
    validator_log(val, ISC_LOG_DEBUG(3),
3616
0
            "attempting negative response validation "
3617
0
            "from cache");
3618
3619
0
    if (NXDOMAIN(val->rdataset)) {
3620
0
      val->attributes |= VALATTR_NEEDNOQNAME;
3621
0
      val->attributes |= VALATTR_NEEDNOWILDCARD;
3622
0
    } else {
3623
0
      val->attributes |= VALATTR_NEEDNODATA;
3624
0
    }
3625
3626
0
    result = validate_nx(val, false);
3627
0
  } else {
3628
0
    UNREACHABLE();
3629
0
  }
3630
3631
0
cleanup:
3632
0
  validate_async_done(val, result);
3633
0
}
3634
3635
isc_result_t
3636
dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
3637
         dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
3638
         dns_message_t *message, unsigned int options,
3639
         isc_loop_t *loop, isc_job_cb cb, void *arg,
3640
         isc_counter_t *nvalidations, isc_counter_t *nfails,
3641
         isc_counter_t *qc, isc_counter_t *gqc,
3642
0
         dns_edectx_t *edectx, dns_validator_t **validatorp) {
3643
0
  isc_result_t result = ISC_R_FAILURE;
3644
0
  dns_validator_t *val = NULL;
3645
0
  dns_keytable_t *kt = NULL;
3646
3647
0
  REQUIRE(name != NULL);
3648
0
  REQUIRE(rdataset != NULL ||
3649
0
    (rdataset == NULL && sigrdataset == NULL && message != NULL));
3650
0
  REQUIRE(validatorp != NULL && *validatorp == NULL);
3651
0
  REQUIRE(edectx != NULL);
3652
3653
0
  result = dns_view_getsecroots(view, &kt);
3654
0
  if (result != ISC_R_SUCCESS) {
3655
0
    return result;
3656
0
  }
3657
3658
0
  val = isc_mem_get(view->mctx, sizeof(*val));
3659
0
  *val = (dns_validator_t){
3660
0
    .tid = isc_tid(),
3661
0
    .result = DNS_R_NOVALIDSIG,
3662
0
    .rdataset = rdataset,
3663
0
    .sigrdataset = sigrdataset,
3664
0
    .name = name,
3665
0
    .type = type,
3666
0
    .options = options,
3667
0
    .keytable = kt,
3668
0
    .link = ISC_LINK_INITIALIZER,
3669
0
    .loop = isc_loop_ref(loop),
3670
0
    .cb = cb,
3671
0
    .arg = arg,
3672
0
    .rdata = DNS_RDATA_INIT,
3673
0
    .cb_edectx = edectx,
3674
0
  };
3675
3676
0
  dns_ede_init(view->mctx, &val->edectx);
3677
3678
0
  isc_refcount_init(&val->references, 1);
3679
0
  dns_view_attach(view, &val->view);
3680
0
  if (message != NULL) {
3681
0
    dns_message_attach(message, &val->message);
3682
0
  }
3683
3684
0
  if (nfails != NULL) {
3685
0
    isc_counter_attach(nfails, &val->nfails);
3686
0
  }
3687
3688
0
  if (nvalidations != NULL) {
3689
0
    isc_counter_attach(nvalidations, &val->nvalidations);
3690
0
  }
3691
3692
0
  if (qc != NULL) {
3693
0
    isc_counter_attach(qc, &val->qc);
3694
0
  }
3695
0
  if (gqc != NULL) {
3696
0
    isc_counter_attach(gqc, &val->gqc);
3697
0
  }
3698
3699
0
  dns_rdataset_init(&val->fdsset);
3700
0
  dns_rdataset_init(&val->frdataset);
3701
0
  dns_rdataset_init(&val->fsigrdataset);
3702
0
  dns_rdataset_init(&val->dsrdataset);
3703
0
  dns_fixedname_init(&val->wild);
3704
0
  dns_fixedname_init(&val->closest);
3705
0
  val->start = isc_stdtime_now();
3706
0
  val->magic = VALIDATOR_MAGIC;
3707
3708
0
  if ((options & DNS_VALIDATOR_DEFER) == 0) {
3709
0
    dns_validator_ref(val);
3710
0
    (void)validate_async_run(val, validator_start);
3711
0
  }
3712
3713
0
  *validatorp = val;
3714
3715
0
  return ISC_R_SUCCESS;
3716
0
}
3717
3718
void
3719
0
dns_validator_send(dns_validator_t *val) {
3720
0
  REQUIRE(VALID_VALIDATOR(val));
3721
0
  REQUIRE(val->tid == isc_tid());
3722
3723
0
  INSIST((val->options & DNS_VALIDATOR_DEFER) != 0);
3724
0
  val->options &= ~DNS_VALIDATOR_DEFER;
3725
3726
0
  dns_validator_ref(val);
3727
0
  (void)validate_async_run(val, validator_start);
3728
0
}
3729
3730
static void
3731
0
validator_cancel_finish(dns_validator_t *validator) {
3732
0
  validator_log(validator, ISC_LOG_DEBUG(3), "validator_cancel_finish");
3733
3734
0
  if (CANCELING(validator) && !CANCELED(validator)) {
3735
0
    if (validator->fetch != NULL) {
3736
0
      dns_resolver_cancelfetch(validator->fetch);
3737
0
    }
3738
0
    if (validator->subvalidator != NULL) {
3739
0
      dns_validator_cancel(validator->subvalidator);
3740
0
    }
3741
0
    if (!COMPLETE(validator)) {
3742
0
      validator->options &= ~DNS_VALIDATOR_DEFER;
3743
0
      validator_done(validator, ISC_R_CANCELED);
3744
0
    }
3745
0
    validator->attributes |= VALATTR_CANCELED;
3746
0
  }
3747
0
}
3748
3749
void
3750
0
dns_validator_cancel(dns_validator_t *validator) {
3751
0
  REQUIRE(VALID_VALIDATOR(validator));
3752
0
  REQUIRE(validator->tid == isc_tid());
3753
3754
0
  validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
3755
3756
0
  atomic_store(&validator->canceling, true);
3757
3758
0
  if (!OFFLOADED(validator)) {
3759
0
    validator_cancel_finish(validator);
3760
0
  }
3761
0
}
3762
3763
static void
3764
0
destroy_validator(dns_validator_t *val) {
3765
0
  isc_mem_t *mctx = NULL;
3766
3767
0
  REQUIRE(val->fetch == NULL);
3768
0
  REQUIRE(val->subvalidator == NULL);
3769
3770
0
  val->magic = 0;
3771
0
  if (val->key != NULL) {
3772
0
    dst_key_free(&val->key);
3773
0
  }
3774
0
  if (val->keytable != NULL) {
3775
0
    dns_keytable_detach(&val->keytable);
3776
0
  }
3777
0
  disassociate_rdatasets(val);
3778
0
  if (dns_rdataset_isassociated(&val->dsrdataset)) {
3779
0
    dns_rdataset_disassociate(&val->dsrdataset);
3780
0
  }
3781
0
  mctx = val->view->mctx;
3782
0
  if (val->siginfo != NULL) {
3783
0
    isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
3784
0
  }
3785
0
  if (val->message != NULL) {
3786
0
    dns_message_detach(&val->message);
3787
0
  }
3788
0
  if (val->nfails != NULL) {
3789
0
    isc_counter_detach(&val->nfails);
3790
0
  }
3791
0
  if (val->nvalidations != NULL) {
3792
0
    isc_counter_detach(&val->nvalidations);
3793
0
  }
3794
0
  if (val->qc != NULL) {
3795
0
    isc_counter_detach(&val->qc);
3796
0
  }
3797
0
  if (val->gqc != NULL) {
3798
0
    isc_counter_detach(&val->gqc);
3799
0
  }
3800
3801
0
  dns_ede_invalidate(&val->edectx);
3802
3803
0
  dns_view_detach(&val->view);
3804
0
  isc_loop_detach(&val->loop);
3805
3806
0
  isc_mem_put(mctx, val, sizeof(*val));
3807
0
}
3808
3809
void
3810
0
dns_validator_shutdown(dns_validator_t *val) {
3811
0
  REQUIRE(VALID_VALIDATOR(val));
3812
0
  REQUIRE(COMPLETE(val));
3813
0
  REQUIRE(val->tid == isc_tid());
3814
3815
0
  validator_log(val, ISC_LOG_DEBUG(4), "dns_validator_shutdown");
3816
3817
  /*
3818
   * The validation is now complete and the owner is no longer interested
3819
   * in any further results. If there are still callback events queued up
3820
   * which hold a validator reference, they should not be allowed to use
3821
   * val->name during logging, because the owner may destroy it after this
3822
   * function is called.
3823
   */
3824
0
  val->name = NULL;
3825
0
}
3826
3827
static void
3828
validator_logv(dns_validator_t *val, isc_logcategory_t category,
3829
0
         isc_logmodule_t module, int level, const char *fmt, va_list ap) {
3830
0
  char msgbuf[2048];
3831
0
  static const char spaces[] = "        *";
3832
0
  int depth = val->depth * 2;
3833
0
  const char *viewname, *sep1, *sep2;
3834
3835
0
  vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
3836
3837
0
  if ((unsigned int)depth >= sizeof spaces) {
3838
0
    depth = sizeof spaces - 1;
3839
0
  }
3840
3841
  /*
3842
   * Log the view name unless it's:
3843
   * * "_default/IN" (which means there's only one view
3844
   *   configured in the server), or
3845
   * * "_dnsclient/IN" (which means this is being called
3846
   *   from an application using dns/client.c).
3847
   */
3848
0
  if (val->view->rdclass == dns_rdataclass_in &&
3849
0
      (strcmp(val->view->name, "_default") == 0 ||
3850
0
       strcmp(val->view->name, DNS_CLIENTVIEW_NAME) == 0))
3851
0
  {
3852
0
    sep1 = viewname = sep2 = "";
3853
0
  } else {
3854
0
    sep1 = "view ";
3855
0
    viewname = val->view->name;
3856
0
    sep2 = ": ";
3857
0
  }
3858
3859
0
  if (val->name != NULL) {
3860
0
    char namebuf[DNS_NAME_FORMATSIZE];
3861
0
    char typebuf[DNS_RDATATYPE_FORMATSIZE];
3862
3863
0
    dns_name_format(val->name, namebuf, sizeof(namebuf));
3864
0
    dns_rdatatype_format(val->type, typebuf, sizeof(typebuf));
3865
0
    isc_log_write(category, module, level,
3866
0
            "%s%s%s%.*svalidating %s/%s: %s", sep1, viewname,
3867
0
            sep2, depth, spaces, namebuf, typebuf, msgbuf);
3868
0
  } else {
3869
0
    isc_log_write(category, module, level,
3870
0
            "%s%s%s%.*svalidator @%p: %s", sep1, viewname,
3871
0
            sep2, depth, spaces, val, msgbuf);
3872
0
  }
3873
0
}
3874
3875
static void
3876
0
validator_log(void *val, int level, const char *fmt, ...) {
3877
0
  va_list ap;
3878
3879
0
  if (!isc_log_wouldlog(level)) {
3880
0
    return;
3881
0
  }
3882
3883
0
  va_start(ap, fmt);
3884
3885
0
  validator_logv(val, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_VALIDATOR,
3886
0
           level, fmt, ap);
3887
0
  va_end(ap);
3888
0
}
3889
3890
static void
3891
validator_logcreate(dns_validator_t *val, dns_name_t *name,
3892
        dns_rdatatype_t type, const char *caller,
3893
0
        const char *operation) {
3894
0
  char namestr[DNS_NAME_FORMATSIZE];
3895
0
  char typestr[DNS_RDATATYPE_FORMATSIZE];
3896
3897
0
  dns_name_format(name, namestr, sizeof(namestr));
3898
0
  dns_rdatatype_format(type, typestr, sizeof(typestr));
3899
0
  validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
3900
0
          caller, operation, namestr, typestr);
3901
0
}
3902
3903
static void
3904
0
validator_addede(dns_validator_t *val, uint16_t code, const char *extra) {
3905
0
  REQUIRE(VALID_VALIDATOR(val));
3906
3907
0
  char bdata[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE +
3908
0
       DNS_EDE_EXTRATEXT_LEN];
3909
0
  isc_buffer_t b;
3910
3911
0
  isc_buffer_init(&b, bdata, sizeof(bdata));
3912
3913
0
  if (extra != NULL) {
3914
0
    isc_buffer_putstr(&b, extra);
3915
0
    isc_buffer_putuint8(&b, ' ');
3916
0
  }
3917
3918
0
  dns_name_totext(val->name, DNS_NAME_OMITFINALDOT, &b);
3919
0
  isc_buffer_putuint8(&b, '/');
3920
0
  dns_rdatatype_totext(val->type, &b);
3921
0
  isc_buffer_putuint8(&b, '\0');
3922
3923
0
  dns_ede_add(&val->edectx, code, bdata);
3924
0
}
3925
3926
static void
3927
0
validate_extendederror(dns_validator_t *val) {
3928
0
  dns_validator_t *edeval = val;
3929
0
  char bdata[DNS_EDE_EXTRATEXT_LEN];
3930
0
  isc_buffer_t b;
3931
3932
0
  REQUIRE(VALID_VALIDATOR(edeval));
3933
3934
0
  isc_buffer_init(&b, bdata, sizeof(bdata));
3935
3936
0
  while (edeval->parent != NULL) {
3937
0
    edeval = edeval->parent;
3938
0
  }
3939
3940
0
  if (val->unsupported_algorithm != 0) {
3941
0
    isc_buffer_clear(&b);
3942
0
    dns_secalg_totext(val->unsupported_algorithm, &b);
3943
0
    isc_buffer_putuint8(&b, '\0');
3944
0
    validator_addede(val, DNS_EDE_DNSKEYALG, bdata);
3945
0
  }
3946
3947
0
  if (val->unsupported_digest != 0) {
3948
0
    isc_buffer_clear(&b);
3949
0
    dns_dsdigest_totext(val->unsupported_digest, &b);
3950
0
    isc_buffer_putuint8(&b, '\0');
3951
0
    validator_addede(val, DNS_EDE_DSDIGESTTYPE, bdata);
3952
0
  }
3953
0
}
3954
3955
#if DNS_VALIDATOR_TRACE
3956
ISC_REFCOUNT_TRACE_IMPL(dns_validator, destroy_validator);
3957
#else
3958
ISC_REFCOUNT_IMPL(dns_validator, destroy_validator);
3959
#endif