Coverage Report

Created: 2026-02-26 06:45

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