Coverage Report

Created: 2026-08-13 07:07

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