Coverage Report

Created: 2026-06-09 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/nsec3.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/base32.h>
18
#include <isc/buffer.h>
19
#include <isc/hex.h>
20
#include <isc/iterated_hash.h>
21
#include <isc/md.h>
22
#include <isc/nonce.h>
23
#include <isc/result.h>
24
#include <isc/safe.h>
25
#include <isc/string.h>
26
#include <isc/util.h>
27
28
#include <dns/compress.h>
29
#include <dns/db.h>
30
#include <dns/dbiterator.h>
31
#include <dns/diff.h>
32
#include <dns/fixedname.h>
33
#include <dns/nsec.h>
34
#include <dns/nsec3.h>
35
#include <dns/rdata.h>
36
#include <dns/rdatalist.h>
37
#include <dns/rdataset.h>
38
#include <dns/rdatasetiter.h>
39
#include <dns/rdatastruct.h>
40
#include <dns/zone.h>
41
#include <dns/zoneproperties.h>
42
43
#include <dst/dst.h>
44
45
0
#define OPTOUT(x)  (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
46
0
#define CREATE(x)  (((x) & DNS_NSEC3FLAG_CREATE) != 0)
47
#define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0)
48
0
#define REMOVE(x)  (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
49
50
isc_result_t
51
dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
52
         unsigned int hashalg, unsigned int flags,
53
         unsigned int iterations, const unsigned char *salt,
54
         size_t salt_length, const unsigned char *nexthash,
55
         size_t hash_length, unsigned char *buffer,
56
0
         dns_rdata_t *rdata) {
57
0
  isc_region_t r;
58
0
  unsigned int i;
59
0
  bool found;
60
0
  bool found_ns;
61
0
  bool need_rrsig;
62
0
  unsigned char *nsec_bits, *bm;
63
0
  unsigned int max_type;
64
0
  dns_rdatasetiter_t *rdsiter;
65
0
  unsigned char *p;
66
67
0
  REQUIRE(salt_length < 256U);
68
0
  REQUIRE(hash_length < 256U);
69
0
  REQUIRE(flags <= 0xffU);
70
0
  REQUIRE(hashalg <= 0xffU);
71
0
  REQUIRE(iterations <= 0xffffU);
72
73
0
  switch (hashalg) {
74
0
  case dns_hash_sha1:
75
0
    REQUIRE(hash_length == ISC_SHA1_DIGESTLENGTH);
76
0
    break;
77
0
  }
78
79
0
  memset(buffer, 0, DNS_NSEC3_BUFFERSIZE);
80
81
0
  p = buffer;
82
83
0
  *p++ = hashalg;
84
0
  *p++ = flags;
85
86
0
  *p++ = iterations >> 8;
87
0
  *p++ = iterations;
88
89
0
  *p++ = (unsigned char)salt_length;
90
0
  memmove(p, salt, salt_length);
91
0
  p += salt_length;
92
93
0
  *p++ = (unsigned char)hash_length;
94
0
  memmove(p, nexthash, hash_length);
95
0
  p += hash_length;
96
97
0
  r.length = (unsigned int)(p - buffer);
98
0
  r.base = buffer;
99
100
  /*
101
   * Use the end of the space for a raw bitmap leaving enough
102
   * space for the window identifiers and length octets.
103
   */
104
0
  bm = r.base + r.length + 512;
105
0
  nsec_bits = r.base + r.length;
106
0
  max_type = 0;
107
0
  if (node == NULL) {
108
0
    goto collapse_bitmap;
109
0
  }
110
0
  rdsiter = NULL;
111
0
  RETERR(dns_db_allrdatasets(db, node, version, 0, 0, &rdsiter));
112
0
  found = found_ns = need_rrsig = false;
113
0
  DNS_RDATASETITER_FOREACH(rdsiter) {
114
0
    dns_rdataset_t rdataset = DNS_RDATASET_INIT;
115
0
    dns_rdatasetiter_current(rdsiter, &rdataset);
116
0
    if (!dns_rdatatype_isnsec(rdataset.type) &&
117
0
        rdataset.type != dns_rdatatype_rrsig)
118
0
    {
119
0
      if (rdataset.type > max_type) {
120
0
        max_type = rdataset.type;
121
0
      }
122
0
      dns_nsec_setbit(bm, rdataset.type, 1);
123
      /*
124
       * Work out if we need to set the RRSIG bit for
125
       * this node.  We set the RRSIG bit if either of
126
       * the following conditions are met:
127
       * 1) We have a SOA or DS then we need to set
128
       *    the RRSIG bit as both always will be signed.
129
       * 2) We set the RRSIG bit if we don't have
130
       *    a NS record but do have other data.
131
       */
132
0
      if (rdataset.type == dns_rdatatype_soa ||
133
0
          rdataset.type == dns_rdatatype_ds)
134
0
      {
135
0
        need_rrsig = true;
136
0
      } else if (rdataset.type == dns_rdatatype_ns) {
137
0
        found_ns = true;
138
0
      } else {
139
0
        found = true;
140
0
      }
141
0
    }
142
0
    dns_rdataset_disassociate(&rdataset);
143
0
  }
144
0
  dns_rdatasetiter_destroy(&rdsiter);
145
146
0
  if ((found && !found_ns) || need_rrsig) {
147
0
    if (dns_rdatatype_rrsig > max_type) {
148
0
      max_type = dns_rdatatype_rrsig;
149
0
    }
150
0
    dns_nsec_setbit(bm, dns_rdatatype_rrsig, 1);
151
0
  }
152
153
  /*
154
   * At zone cuts, deny the existence of glue in the parent zone.
155
   */
156
0
  if (dns_nsec_isset(bm, dns_rdatatype_ns) &&
157
0
      !dns_nsec_isset(bm, dns_rdatatype_soa))
158
0
  {
159
0
    for (i = 0; i <= max_type; i++) {
160
0
      if (dns_nsec_isset(bm, i) &&
161
0
          !dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
162
0
      {
163
0
        dns_nsec_setbit(bm, i, 0);
164
0
      }
165
0
    }
166
0
  }
167
168
0
collapse_bitmap:
169
0
  nsec_bits += dns_nsec_compressbitmap(nsec_bits, bm, max_type);
170
0
  r.length = (unsigned int)(nsec_bits - r.base);
171
0
  INSIST(r.length <= DNS_NSEC3_BUFFERSIZE);
172
0
  dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r);
173
174
0
  return ISC_R_SUCCESS;
175
0
}
176
177
bool
178
0
dns_nsec3_typepresent(dns_rdata_t *rdata, dns_rdatatype_t type) {
179
0
  dns_rdata_nsec3_t nsec3;
180
0
  isc_result_t result;
181
0
  bool present;
182
0
  unsigned int i, len, window;
183
184
0
  REQUIRE(rdata != NULL);
185
0
  REQUIRE(rdata->type == dns_rdatatype_nsec3);
186
187
  /* This should never fail */
188
0
  result = dns_rdata_tostruct(rdata, &nsec3, NULL);
189
0
  INSIST(result == ISC_R_SUCCESS);
190
191
0
  present = false;
192
0
  for (i = 0; i < nsec3.typebits.length; i += len) {
193
0
    INSIST(i + 2 <= nsec3.typebits.length);
194
0
    window = nsec3.typebits.base[i];
195
0
    len = nsec3.typebits.base[i + 1];
196
0
    INSIST(len > 0 && len <= 32);
197
0
    i += 2;
198
0
    INSIST(i + len <= nsec3.typebits.length);
199
0
    if (window * 256 > type) {
200
0
      break;
201
0
    }
202
0
    if ((window + 1) * 256 <= type) {
203
0
      continue;
204
0
    }
205
0
    if (type < (window * 256) + len * 8) {
206
0
      present = dns_nsec_isset(&nsec3.typebits.base[i],
207
0
             type % 256);
208
0
    }
209
0
    break;
210
0
  }
211
0
  dns_rdata_freestruct(&nsec3);
212
0
  return present;
213
0
}
214
215
isc_result_t
216
0
dns_nsec3_generate_salt(unsigned char *salt, size_t saltlen) {
217
0
  if (saltlen > 255U) {
218
0
    return ISC_R_RANGE;
219
0
  }
220
0
  isc_nonce_buf(salt, saltlen);
221
0
  return ISC_R_SUCCESS;
222
0
}
223
224
isc_result_t
225
dns_nsec3_hashname(dns_fixedname_t *result,
226
       unsigned char rethash[NSEC3_MAX_HASH_LENGTH],
227
       size_t *hash_length, const dns_name_t *name,
228
       const dns_name_t *origin, dns_hash_t hashalg,
229
       unsigned int iterations, const unsigned char *salt,
230
0
       size_t saltlength) {
231
0
  unsigned char hash[NSEC3_MAX_HASH_LENGTH];
232
0
  unsigned char nametext[DNS_NAME_FORMATSIZE];
233
0
  dns_fixedname_t fixed;
234
0
  dns_name_t *downcased;
235
0
  isc_buffer_t namebuffer;
236
0
  isc_region_t region;
237
0
  size_t len;
238
239
0
  if (rethash == NULL) {
240
0
    rethash = hash;
241
0
  }
242
243
0
  memset(rethash, 0, NSEC3_MAX_HASH_LENGTH);
244
245
0
  downcased = dns_fixedname_initname(&fixed);
246
0
  dns_name_downcase(name, downcased);
247
248
  /* hash the node name */
249
0
  len = isc_iterated_hash(rethash, hashalg, iterations, salt,
250
0
        (int)saltlength, downcased->ndata,
251
0
        downcased->length);
252
0
  if (len == 0U) {
253
0
    return DNS_R_BADALG;
254
0
  }
255
256
0
  SET_IF_NOT_NULL(hash_length, len);
257
258
  /* convert the hash to base32hex non-padded */
259
0
  region.base = rethash;
260
0
  region.length = (unsigned int)len;
261
0
  isc_buffer_init(&namebuffer, nametext, sizeof nametext);
262
0
  isc_base32hexnp_totext(&region, 1, "", &namebuffer);
263
264
  /* convert the hex to a domain name */
265
0
  dns_fixedname_init(result);
266
0
  return dns_name_fromtext(dns_fixedname_name(result), &namebuffer,
267
0
         origin, 0);
268
0
}
269
270
unsigned int
271
0
dns_nsec3_hashlength(dns_hash_t hash) {
272
0
  switch (hash) {
273
0
  case dns_hash_sha1:
274
0
    return ISC_SHA1_DIGESTLENGTH;
275
0
  }
276
0
  return 0;
277
0
}
278
279
bool
280
18
dns_nsec3_supportedhash(dns_hash_t hash) {
281
18
  switch (hash) {
282
2
  case dns_hash_sha1:
283
2
    return true;
284
18
  }
285
16
  return false;
286
18
}
287
288
/*%
289
 * Update a single RR in version 'ver' of 'db' and log the
290
 * update in 'diff'.
291
 *
292
 * Ensures:
293
 * \li  '*tuple' == NULL.  Either the tuple is freed, or its
294
 *      ownership has been transferred to the diff.
295
 */
296
static isc_result_t
297
do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
298
0
       dns_diff_t *diff) {
299
0
  dns_diff_t temp_diff;
300
0
  isc_result_t result;
301
302
  /*
303
   * Create a singleton diff.
304
   */
305
0
  dns_diff_init(diff->mctx, &temp_diff);
306
0
  ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
307
308
  /*
309
   * Apply it to the database.
310
   */
311
0
  result = dns_diff_apply(&temp_diff, db, ver);
312
0
  ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
313
0
  if (result != ISC_R_SUCCESS) {
314
0
    dns_difftuple_free(tuple);
315
0
    return result;
316
0
  }
317
318
  /*
319
   * Merge it into the current pending journal entry.
320
   */
321
0
  dns_diff_appendminimal(diff, tuple);
322
323
  /*
324
   * Do not clear temp_diff.
325
   */
326
0
  return ISC_R_SUCCESS;
327
0
}
328
329
/*%
330
 * Set '*exists' to true iff the given name exists, to false otherwise.
331
 */
332
static isc_result_t
333
name_exists(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name,
334
0
      bool *exists) {
335
0
  isc_result_t result;
336
0
  dns_dbnode_t *node = NULL;
337
0
  dns_rdatasetiter_t *iter = NULL;
338
339
0
  result = dns_db_findnode(db, name, false, &node);
340
0
  if (result == ISC_R_NOTFOUND) {
341
0
    *exists = false;
342
0
    return ISC_R_SUCCESS;
343
0
  }
344
0
  if (result != ISC_R_SUCCESS) {
345
0
    return result;
346
0
  }
347
348
0
  result = dns_db_allrdatasets(db, node, version, 0, (isc_stdtime_t)0,
349
0
             &iter);
350
0
  if (result != ISC_R_SUCCESS) {
351
0
    goto cleanup_node;
352
0
  }
353
354
0
  result = dns_rdatasetiter_first(iter);
355
0
  if (result == ISC_R_SUCCESS) {
356
0
    *exists = true;
357
0
  } else if (result == ISC_R_NOMORE) {
358
0
    *exists = false;
359
0
    result = ISC_R_SUCCESS;
360
0
  } else {
361
0
    *exists = false;
362
0
  }
363
0
  dns_rdatasetiter_destroy(&iter);
364
365
0
cleanup_node:
366
0
  dns_db_detachnode(&node);
367
0
  return result;
368
0
}
369
370
static bool
371
match_nsec3param(const dns_rdata_nsec3_t *nsec3,
372
0
     const dns_rdata_nsec3param_t *nsec3param) {
373
0
  if (nsec3->hash == nsec3param->hash &&
374
0
      nsec3->iterations == nsec3param->iterations &&
375
0
      nsec3->salt.length == nsec3param->salt.length &&
376
0
      !memcmp(nsec3->salt.base, nsec3param->salt.base,
377
0
        nsec3->salt.length))
378
0
  {
379
0
    return true;
380
0
  }
381
0
  return false;
382
0
}
383
384
/*%
385
 * Delete NSEC3 records at "name" which match "param", recording the
386
 * change in "diff".
387
 */
388
static isc_result_t
389
delnsec3(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name,
390
0
   const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff) {
391
0
  dns_dbnode_t *node = NULL;
392
0
  dns_difftuple_t *tuple = NULL;
393
0
  dns_rdata_nsec3_t nsec3;
394
0
  dns_rdataset_t rdataset;
395
0
  isc_result_t result;
396
397
0
  result = dns_db_findnsec3node(db, name, false, &node);
398
0
  if (result == ISC_R_NOTFOUND) {
399
0
    return ISC_R_SUCCESS;
400
0
  }
401
0
  if (result != ISC_R_SUCCESS) {
402
0
    return result;
403
0
  }
404
405
0
  dns_rdataset_init(&rdataset);
406
0
  result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3, 0,
407
0
             (isc_stdtime_t)0, &rdataset, NULL);
408
409
0
  if (result == ISC_R_NOTFOUND) {
410
0
    result = ISC_R_SUCCESS;
411
0
    goto cleanup_node;
412
0
  }
413
0
  if (result != ISC_R_SUCCESS) {
414
0
    goto cleanup_node;
415
0
  }
416
417
0
  DNS_RDATASET_FOREACH(&rdataset) {
418
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
419
0
    dns_rdataset_current(&rdataset, &rdata);
420
0
    CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
421
422
0
    if (!match_nsec3param(&nsec3, nsec3param)) {
423
0
      continue;
424
0
    }
425
426
0
    dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
427
0
             rdataset.ttl, &rdata, &tuple);
428
0
    CHECK(do_one_tuple(&tuple, db, version, diff));
429
0
  }
430
431
0
  result = ISC_R_SUCCESS;
432
433
0
cleanup:
434
0
  dns_rdataset_disassociate(&rdataset);
435
0
cleanup_node:
436
0
  dns_db_detachnode(&node);
437
438
0
  return result;
439
0
}
440
441
static bool
442
0
better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) {
443
0
  dns_rdataset_t rdataset = DNS_RDATASET_INIT;
444
445
0
  if (REMOVE(param->data[1])) {
446
0
    return true;
447
0
  }
448
449
0
  dns_rdataset_clone(nsec3paramset, &rdataset);
450
0
  DNS_RDATASET_FOREACH(&rdataset) {
451
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
452
0
    unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
453
454
0
    if (rdataset.type != dns_rdatatype_nsec3param) {
455
0
      dns_rdata_t tmprdata = DNS_RDATA_INIT;
456
0
      dns_rdataset_current(&rdataset, &tmprdata);
457
0
      if (!dns_nsec3param_fromprivate(&tmprdata, &rdata, buf,
458
0
              sizeof(buf)))
459
0
      {
460
0
        continue;
461
0
      }
462
0
    } else {
463
0
      dns_rdataset_current(&rdataset, &rdata);
464
0
    }
465
466
0
    if (rdata.length != param->length) {
467
0
      continue;
468
0
    }
469
0
    if (rdata.data[0] != param->data[0] || REMOVE(rdata.data[1]) ||
470
0
        rdata.data[2] != param->data[2] ||
471
0
        rdata.data[3] != param->data[3] ||
472
0
        rdata.data[4] != param->data[4] ||
473
0
        memcmp(&rdata.data[5], &param->data[5], param->data[4]))
474
0
    {
475
0
      continue;
476
0
    }
477
0
    if (CREATE(rdata.data[1]) && !CREATE(param->data[1])) {
478
0
      dns_rdataset_disassociate(&rdataset);
479
0
      return true;
480
0
    }
481
0
  }
482
0
  dns_rdataset_disassociate(&rdataset);
483
0
  return false;
484
0
}
485
486
static isc_result_t
487
find_nsec3(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *rdataset,
488
0
     const dns_rdata_nsec3param_t *nsec3param) {
489
0
  DNS_RDATASET_FOREACH(rdataset) {
490
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
491
0
    dns_rdataset_current(rdataset, &rdata);
492
0
    dns_rdata_tostruct(&rdata, nsec3, NULL);
493
494
0
    if (match_nsec3param(nsec3, nsec3param)) {
495
0
      return ISC_R_SUCCESS;
496
0
    }
497
0
  }
498
499
0
  return ISC_R_NOTFOUND;
500
0
}
501
502
isc_result_t
503
dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
504
       const dns_name_t *name,
505
       const dns_rdata_nsec3param_t *nsec3param, dns_ttl_t nsecttl,
506
0
       bool unsecure, dns_diff_t *diff) {
507
0
  dns_dbiterator_t *dbit = NULL;
508
0
  dns_dbnode_t *node = NULL;
509
0
  dns_dbnode_t *newnode = NULL;
510
0
  dns_difftuple_t *tuple = NULL;
511
0
  dns_fixedname_t fixed;
512
0
  dns_fixedname_t fprev;
513
0
  dns_hash_t hash;
514
0
  dns_name_t *hashname;
515
0
  dns_name_t *origin;
516
0
  dns_name_t *prev;
517
0
  dns_name_t empty;
518
0
  dns_rdata_nsec3_t nsec3;
519
0
  dns_rdata_t rdata = DNS_RDATA_INIT;
520
0
  dns_rdataset_t rdataset;
521
0
  int pass;
522
0
  bool exists = false;
523
0
  bool maybe_remove_unsecure = false;
524
0
  uint8_t flags;
525
0
  isc_buffer_t buffer;
526
0
  isc_result_t result;
527
0
  unsigned char *old_next;
528
0
  unsigned char *salt;
529
0
  unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
530
0
  unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
531
0
  unsigned int iterations;
532
0
  unsigned int labels;
533
0
  size_t next_length;
534
0
  unsigned int old_length;
535
0
  unsigned int salt_length;
536
537
0
  hashname = dns_fixedname_initname(&fixed);
538
0
  prev = dns_fixedname_initname(&fprev);
539
540
0
  dns_rdataset_init(&rdataset);
541
542
0
  origin = dns_db_origin(db);
543
544
  /*
545
   * Chain parameters.
546
   */
547
0
  hash = nsec3param->hash;
548
0
  iterations = nsec3param->iterations;
549
0
  salt_length = nsec3param->salt.length;
550
0
  salt = nsec3param->salt.base;
551
552
  /*
553
   * Default flags for a new chain.
554
   */
555
0
  flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
556
557
  /*
558
   * If this is the first NSEC3 in the chain nexthash will
559
   * remain pointing to itself.
560
   */
561
0
  next_length = sizeof(nexthash);
562
0
  CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length, name, origin,
563
0
         hash, iterations, salt, salt_length));
564
0
  INSIST(next_length <= sizeof(nexthash));
565
566
  /*
567
   * Create the node if it doesn't exist and hold
568
   * a reference to it until we have added the NSEC3.
569
   */
570
0
  result = dns_db_findnsec3node(db, hashname, false, &newnode);
571
0
  if (result != ISC_R_SUCCESS) {
572
0
    isc_result_t tresult;
573
574
0
    CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
575
0
    tresult = dns_dbiterator_seek3(dbit, hashname);
576
0
    CHECK(dns_dbiterator_pause(dbit));
577
578
0
    if (tresult != ISC_R_SUCCESS) {
579
      /* Nothing in the NSEC3 space yet. */
580
0
      if (!unsecure) {
581
0
        goto addnsec3;
582
0
      }
583
0
      goto cleanup;
584
0
    }
585
586
0
    goto find_previous;
587
0
  }
588
589
  /*
590
   * Seek the iterator to the 'newnode'.
591
   */
592
0
  CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
593
0
  CHECK(dns_dbiterator_seek(dbit, hashname));
594
0
  CHECK(dns_dbiterator_pause(dbit));
595
0
  result = dns_db_findrdataset(db, newnode, version, dns_rdatatype_nsec3,
596
0
             0, (isc_stdtime_t)0, &rdataset, NULL);
597
  /*
598
   * If we updating a existing NSEC3 then find its
599
   * next field.
600
   */
601
0
  if (result == ISC_R_SUCCESS) {
602
0
    result = find_nsec3(&nsec3, &rdataset, nsec3param);
603
0
    if (result == ISC_R_SUCCESS) {
604
0
      if (!CREATE(nsec3param->flags)) {
605
0
        flags = nsec3.flags;
606
0
      }
607
0
      next_length = nsec3.next.length;
608
0
      INSIST(next_length <= sizeof(nexthash));
609
0
      memmove(nexthash, nsec3.next.base, next_length);
610
0
      dns_rdataset_disassociate(&rdataset);
611
      /*
612
       * If the NSEC3 is not for a unsecure delegation then
613
       * we are just updating it.  If it is for a unsecure
614
       * delegation then we need find out if we need to
615
       * remove the NSEC3 record or not by examining the
616
       * previous NSEC3 record.
617
       */
618
0
      if (!unsecure) {
619
0
        goto addnsec3;
620
0
      } else if (CREATE(nsec3param->flags) && OPTOUT(flags)) {
621
0
        result = dns_nsec3_delnsec3(db, version, name,
622
0
                  nsec3param, diff);
623
0
        goto cleanup;
624
0
      } else {
625
0
        maybe_remove_unsecure = true;
626
0
      }
627
0
    } else {
628
0
      dns_rdataset_disassociate(&rdataset);
629
0
    }
630
0
  }
631
632
0
find_previous:
633
  /*
634
   * Find the previous NSEC3 (if any) and update it if required.
635
   */
636
0
  pass = 0;
637
0
  do {
638
0
    result = dns_dbiterator_prev(dbit);
639
0
    if (result == ISC_R_NOMORE) {
640
0
      pass++;
641
0
      CHECK(dns_dbiterator_last(dbit));
642
0
    }
643
0
    CHECK(dns_dbiterator_current(dbit, &node, prev));
644
0
    CHECK(dns_dbiterator_pause(dbit));
645
0
    result = dns_db_findrdataset(db, node, version,
646
0
               dns_rdatatype_nsec3, 0,
647
0
               (isc_stdtime_t)0, &rdataset, NULL);
648
0
    dns_db_detachnode(&node);
649
0
    if (result != ISC_R_SUCCESS) {
650
0
      continue;
651
0
    }
652
653
0
    result = find_nsec3(&nsec3, &rdataset, nsec3param);
654
0
    if (result == ISC_R_NOTFOUND) {
655
0
      dns_rdataset_disassociate(&rdataset);
656
0
      continue;
657
0
    }
658
659
0
    if (maybe_remove_unsecure) {
660
0
      dns_rdataset_disassociate(&rdataset);
661
      /*
662
       * If we have OPTOUT set in the previous NSEC3 record
663
       * we actually need to delete the NSEC3 record.
664
       * Otherwise we just need to replace the NSEC3 record.
665
       */
666
0
      if (OPTOUT(nsec3.flags)) {
667
0
        result = dns_nsec3_delnsec3(db, version, name,
668
0
                  nsec3param, diff);
669
0
        goto cleanup;
670
0
      }
671
0
      goto addnsec3;
672
0
    } else {
673
      /*
674
       * Is this is a unsecure delegation we are adding?
675
       * If so no change is required.
676
       */
677
0
      if (OPTOUT(nsec3.flags) && unsecure) {
678
0
        dns_rdataset_disassociate(&rdataset);
679
0
        goto cleanup;
680
0
      }
681
0
    }
682
683
0
    old_next = nsec3.next.base;
684
0
    old_length = nsec3.next.length;
685
686
    /*
687
     * Delete the old previous NSEC3.
688
     */
689
0
    CHECK(delnsec3(db, version, prev, nsec3param, diff));
690
691
    /*
692
     * Fixup the previous NSEC3.
693
     */
694
0
    nsec3.next.base = nexthash;
695
0
    nsec3.next.length = (unsigned char)next_length;
696
0
    isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
697
0
    CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
698
0
             dns_rdatatype_nsec3, &nsec3,
699
0
             &buffer));
700
0
    dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
701
0
             rdataset.ttl, &rdata, &tuple);
702
0
    CHECK(do_one_tuple(&tuple, db, version, diff));
703
0
    INSIST(old_length <= sizeof(nexthash));
704
0
    memmove(nexthash, old_next, old_length);
705
0
    if (!CREATE(nsec3param->flags)) {
706
0
      flags = nsec3.flags;
707
0
    }
708
0
    dns_rdata_reset(&rdata);
709
0
    dns_rdataset_disassociate(&rdataset);
710
0
    break;
711
0
  } while (pass < 2);
712
713
0
addnsec3:
714
  /*
715
   * Create the NSEC3 RDATA.
716
   */
717
0
  if (newnode == NULL) {
718
0
    CHECK(dns_db_findnsec3node(db, hashname, true, &newnode));
719
0
  }
720
721
0
  CHECK(dns_db_findnode(db, name, false, &node));
722
0
  CHECK(dns_nsec3_buildrdata(db, version, node, hash, flags, iterations,
723
0
           salt, salt_length, nexthash, next_length,
724
0
           nsec3buf, &rdata));
725
0
  dns_db_detachnode(&node);
726
727
  /*
728
   * Delete the old NSEC3 and record the change.
729
   */
730
0
  CHECK(delnsec3(db, version, hashname, nsec3param, diff));
731
  /*
732
   * Add the new NSEC3 and record the change.
733
   */
734
0
  dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, hashname, nsecttl,
735
0
           &rdata, &tuple);
736
0
  CHECK(do_one_tuple(&tuple, db, version, diff));
737
0
  INSIST(tuple == NULL);
738
0
  dns_rdata_reset(&rdata);
739
0
  dns_db_detachnode(&newnode);
740
741
  /*
742
   * Add missing NSEC3 records for empty nodes
743
   */
744
0
  dns_name_init(&empty);
745
0
  dns_name_clone(name, &empty);
746
0
  do {
747
0
    labels = dns_name_countlabels(&empty) - 1;
748
0
    if (labels <= dns_name_countlabels(origin)) {
749
0
      break;
750
0
    }
751
0
    dns_name_getlabelsequence(&empty, 1, labels, &empty);
752
0
    CHECK(name_exists(db, version, &empty, &exists));
753
0
    if (exists) {
754
0
      break;
755
0
    }
756
0
    CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length, &empty,
757
0
           origin, hash, iterations, salt,
758
0
           salt_length));
759
760
    /*
761
     * Create the node if it doesn't exist and hold
762
     * a reference to it until we have added the NSEC3
763
     * or we discover we don't need to make a change.
764
     */
765
0
    CHECK(dns_db_findnsec3node(db, hashname, true, &newnode));
766
0
    result = dns_db_findrdataset(db, newnode, version,
767
0
               dns_rdatatype_nsec3, 0,
768
0
               (isc_stdtime_t)0, &rdataset, NULL);
769
0
    if (result == ISC_R_SUCCESS) {
770
0
      result = find_nsec3(&nsec3, &rdataset, nsec3param);
771
0
      dns_rdataset_disassociate(&rdataset);
772
0
      if (result == ISC_R_SUCCESS) {
773
0
        dns_db_detachnode(&newnode);
774
0
        break;
775
0
      }
776
0
    } else if (result == ISC_R_NOTFOUND) {
777
      /*
778
       * If we didn't find an NSEC3 in the node,
779
       * then the node must have been newly created
780
       * by dns_db_findnsec3node(). The iterator
781
       * needs to be updated so we can seek for
782
       * the node's predecessor.
783
       */
784
0
      dns_dbiterator_destroy(&dbit);
785
0
      CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY,
786
0
                &dbit));
787
0
    }
788
789
    /*
790
     * Find the previous NSEC3 and update it.
791
     */
792
0
    CHECK(dns_dbiterator_seek(dbit, hashname));
793
0
    pass = 0;
794
0
    do {
795
0
      result = dns_dbiterator_prev(dbit);
796
0
      if (result == ISC_R_NOMORE) {
797
0
        pass++;
798
0
        CHECK(dns_dbiterator_last(dbit));
799
0
      }
800
0
      CHECK(dns_dbiterator_current(dbit, &node, prev));
801
0
      CHECK(dns_dbiterator_pause(dbit));
802
0
      result = dns_db_findrdataset(
803
0
        db, node, version, dns_rdatatype_nsec3, 0,
804
0
        (isc_stdtime_t)0, &rdataset, NULL);
805
0
      dns_db_detachnode(&node);
806
0
      if (result != ISC_R_SUCCESS) {
807
0
        continue;
808
0
      }
809
0
      result = find_nsec3(&nsec3, &rdataset, nsec3param);
810
0
      if (result == ISC_R_NOTFOUND) {
811
0
        dns_rdataset_disassociate(&rdataset);
812
0
        continue;
813
0
      }
814
815
0
      old_next = nsec3.next.base;
816
0
      old_length = nsec3.next.length;
817
818
      /*
819
       * Delete the old previous NSEC3.
820
       */
821
0
      CHECK(delnsec3(db, version, prev, nsec3param, diff));
822
823
      /*
824
       * Fixup the previous NSEC3.
825
       */
826
0
      nsec3.next.base = nexthash;
827
0
      nsec3.next.length = (unsigned char)next_length;
828
0
      isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
829
0
      CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
830
0
               dns_rdatatype_nsec3, &nsec3,
831
0
               &buffer));
832
0
      dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
833
0
               rdataset.ttl, &rdata, &tuple);
834
0
      CHECK(do_one_tuple(&tuple, db, version, diff));
835
0
      INSIST(old_length <= sizeof(nexthash));
836
0
      memmove(nexthash, old_next, old_length);
837
0
      if (!CREATE(nsec3param->flags)) {
838
0
        flags = nsec3.flags;
839
0
      }
840
0
      dns_rdata_reset(&rdata);
841
0
      dns_rdataset_disassociate(&rdataset);
842
0
      break;
843
0
    } while (pass < 2);
844
845
0
    INSIST(pass < 2);
846
847
    /*
848
     * Create the NSEC3 RDATA for the empty node.
849
     */
850
0
    CHECK(dns_nsec3_buildrdata(
851
0
      db, version, NULL, hash, flags, iterations, salt,
852
0
      salt_length, nexthash, next_length, nsec3buf, &rdata));
853
    /*
854
     * Delete the old NSEC3 and record the change.
855
     */
856
0
    CHECK(delnsec3(db, version, hashname, nsec3param, diff));
857
858
    /*
859
     * Add the new NSEC3 and record the change.
860
     */
861
0
    dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, hashname,
862
0
             nsecttl, &rdata, &tuple);
863
0
    CHECK(do_one_tuple(&tuple, db, version, diff));
864
0
    INSIST(tuple == NULL);
865
0
    dns_rdata_reset(&rdata);
866
0
    dns_db_detachnode(&newnode);
867
0
  } while (1);
868
869
  /* result cannot be ISC_R_NOMORE here */
870
0
  INSIST(result != ISC_R_NOMORE);
871
872
0
cleanup:
873
0
  if (dbit != NULL) {
874
0
    dns_dbiterator_destroy(&dbit);
875
0
  }
876
0
  dns_rdataset_cleanup(&rdataset);
877
0
  if (node != NULL) {
878
0
    dns_db_detachnode(&node);
879
0
  }
880
0
  if (newnode != NULL) {
881
0
    dns_db_detachnode(&newnode);
882
0
  }
883
0
  return result;
884
0
}
885
886
/*%
887
 * Add NSEC3 records for "name", recording the change in "diff".
888
 * The existing NSEC3 records are removed.
889
 */
890
isc_result_t
891
dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
892
        const dns_name_t *name, dns_ttl_t nsecttl, bool unsecure,
893
0
        dns_diff_t *diff) {
894
0
  dns_dbnode_t *node = NULL;
895
0
  dns_rdata_nsec3param_t nsec3param;
896
0
  dns_rdataset_t rdataset;
897
0
  isc_result_t result;
898
899
0
  dns_rdataset_init(&rdataset);
900
901
  /*
902
   * Find the NSEC3 parameters for this zone.
903
   */
904
0
  RETERR(dns_db_getoriginnode(db, &node));
905
906
0
  result = dns_db_findrdataset(db, node, version,
907
0
             dns_rdatatype_nsec3param, 0, 0, &rdataset,
908
0
             NULL);
909
0
  dns_db_detachnode(&node);
910
0
  if (result == ISC_R_NOTFOUND) {
911
0
    return ISC_R_SUCCESS;
912
0
  }
913
0
  if (result != ISC_R_SUCCESS) {
914
0
    return result;
915
0
  }
916
917
  /*
918
   * Update each active NSEC3 chain.
919
   */
920
0
  DNS_RDATASET_FOREACH(&rdataset) {
921
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
922
923
0
    dns_rdataset_current(&rdataset, &rdata);
924
0
    CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
925
926
0
    if (nsec3param.flags != 0) {
927
0
      continue;
928
0
    }
929
    /*
930
     * We have a active chain.  Update it.
931
     */
932
0
    CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
933
0
           nsecttl, unsecure, diff));
934
0
  }
935
936
0
cleanup:
937
0
  dns_rdataset_cleanup(&rdataset);
938
0
  if (node != NULL) {
939
0
    dns_db_detachnode(&node);
940
0
  }
941
942
0
  return result;
943
0
}
944
945
bool
946
dns_nsec3param_fromprivate(dns_rdata_t *src, dns_rdata_t *target,
947
0
         unsigned char *buf, size_t buflen) {
948
0
  isc_result_t result;
949
0
  isc_buffer_t buf1;
950
0
  isc_buffer_t buf2;
951
952
  /*
953
   * Algorithm 0 (reserved by RFC 4034) is used to identify
954
   * NSEC3PARAM records from DNSKEY pointers.
955
   */
956
0
  if (src->length < 1 || src->data[0] != 0) {
957
0
    return false;
958
0
  }
959
960
0
  isc_buffer_init(&buf1, src->data + 1, src->length - 1);
961
0
  isc_buffer_add(&buf1, src->length - 1);
962
0
  isc_buffer_setactive(&buf1, src->length - 1);
963
0
  isc_buffer_init(&buf2, buf, (unsigned int)buflen);
964
0
  result = dns_rdata_fromwire(target, src->rdclass,
965
0
            dns_rdatatype_nsec3param, &buf1,
966
0
            DNS_DECOMPRESS_NEVER, &buf2);
967
968
0
  return result == ISC_R_SUCCESS;
969
0
}
970
971
void
972
dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target,
973
       dns_rdatatype_t privatetype, unsigned char *buf,
974
0
       size_t buflen) {
975
0
  REQUIRE(buflen >= (unsigned int)src->length + 1);
976
977
0
  REQUIRE(DNS_RDATA_INITIALIZED(target));
978
979
0
  memmove(buf + 1, src->data, src->length);
980
0
  buf[0] = 0;
981
0
  target->data = buf;
982
0
  target->length = src->length + 1;
983
0
  target->type = privatetype;
984
0
  target->rdclass = src->rdclass;
985
0
  target->flags = 0;
986
0
  ISC_LINK_INIT(target, link);
987
0
}
988
989
static isc_result_t
990
rr_exists(dns_db_t *db, dns_dbversion_t *ver, const dns_name_t *name,
991
0
    const dns_rdata_t *rdata, bool *flag) {
992
0
  dns_rdataset_t rdataset;
993
0
  dns_dbnode_t *node = NULL;
994
0
  isc_result_t result;
995
996
0
  dns_rdataset_init(&rdataset);
997
0
  if (rdata->type == dns_rdatatype_nsec3) {
998
0
    CHECK(dns_db_findnsec3node(db, name, false, &node));
999
0
  } else {
1000
0
    CHECK(dns_db_findnode(db, name, false, &node));
1001
0
  }
1002
0
  result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
1003
0
             (isc_stdtime_t)0, &rdataset, NULL);
1004
0
  if (result == ISC_R_NOTFOUND) {
1005
0
    *flag = false;
1006
0
    result = ISC_R_SUCCESS;
1007
0
    goto cleanup;
1008
0
  }
1009
1010
0
  bool matched = false;
1011
0
  DNS_RDATASET_FOREACH(&rdataset) {
1012
0
    dns_rdata_t myrdata = DNS_RDATA_INIT;
1013
0
    dns_rdataset_current(&rdataset, &myrdata);
1014
0
    if (dns_rdata_casecompare(&myrdata, rdata) == 0) {
1015
0
      matched = true;
1016
0
      break;
1017
0
    }
1018
0
  }
1019
0
  dns_rdataset_disassociate(&rdataset);
1020
0
  *flag = matched;
1021
1022
0
cleanup:
1023
0
  if (node != NULL) {
1024
0
    dns_db_detachnode(&node);
1025
0
  }
1026
0
  return result;
1027
0
}
1028
1029
isc_result_t
1030
dns_nsec3param_salttotext(dns_rdata_nsec3param_t *nsec3param, char *dst,
1031
0
        size_t dstlen) {
1032
0
  isc_buffer_t b;
1033
1034
0
  REQUIRE(nsec3param != NULL);
1035
0
  REQUIRE(dst != NULL);
1036
1037
0
  if (nsec3param->salt.length == 0) {
1038
0
    if (dstlen < 2U) {
1039
0
      return ISC_R_NOSPACE;
1040
0
    }
1041
0
    strlcpy(dst, "-", dstlen);
1042
0
    return ISC_R_SUCCESS;
1043
0
  }
1044
1045
0
  isc_buffer_init(&b, dst, (unsigned int)dstlen);
1046
1047
0
  isc_region_t salt = nsec3param->salt;
1048
0
  RETERR(isc_hex_totext(&salt, 2, "", &b));
1049
1050
0
  if (isc_buffer_availablelength(&b) < 1) {
1051
0
    return ISC_R_NOSPACE;
1052
0
  }
1053
0
  isc_buffer_putuint8(&b, 0);
1054
1055
0
  return ISC_R_SUCCESS;
1056
0
}
1057
1058
isc_result_t
1059
dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
1060
0
          dns_zone_t *zone, bool nonsec, dns_diff_t *diff) {
1061
0
  dns_dbnode_t *node = NULL;
1062
0
  dns_difftuple_t *tuple = NULL;
1063
0
  dns_name_t next;
1064
0
  dns_rdataset_t rdataset;
1065
0
  bool flag;
1066
0
  isc_result_t result = ISC_R_SUCCESS;
1067
0
  unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE + 1];
1068
0
  dns_name_t *origin = dns_zone_getorigin(zone);
1069
0
  dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
1070
1071
0
  dns_name_init(&next);
1072
0
  dns_rdataset_init(&rdataset);
1073
1074
0
  RETERR(dns_db_getoriginnode(db, &node));
1075
1076
  /*
1077
   * Cause all NSEC3 chains to be deleted.
1078
   */
1079
0
  result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
1080
0
             (isc_stdtime_t)0, &rdataset, NULL);
1081
0
  if (result == ISC_R_NOTFOUND) {
1082
0
    goto try_private;
1083
0
  }
1084
0
  CHECK(result);
1085
1086
0
  DNS_RDATASET_FOREACH(&rdataset) {
1087
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
1088
0
    dns_rdata_t private = DNS_RDATA_INIT;
1089
1090
0
    dns_rdataset_current(&rdataset, &rdata);
1091
0
    dns_nsec3param_toprivate(&rdata, &private, privatetype, buf,
1092
0
           sizeof(buf));
1093
0
    buf[2] = DNS_NSEC3FLAG_REMOVE;
1094
0
    if (nonsec) {
1095
0
      buf[2] |= DNS_NSEC3FLAG_NONSEC;
1096
0
    }
1097
1098
0
    CHECK(rr_exists(db, ver, origin, &private, &flag));
1099
1100
0
    if (!flag) {
1101
0
      dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, origin,
1102
0
               0, &private, &tuple);
1103
0
      CHECK(do_one_tuple(&tuple, db, ver, diff));
1104
0
      INSIST(tuple == NULL);
1105
0
    }
1106
0
  }
1107
1108
0
  dns_rdataset_disassociate(&rdataset);
1109
1110
0
try_private:
1111
0
  if (privatetype == 0) {
1112
0
    result = ISC_R_SUCCESS;
1113
0
    goto cleanup;
1114
0
  }
1115
0
  result = dns_db_findrdataset(db, node, ver, privatetype, 0,
1116
0
             (isc_stdtime_t)0, &rdataset, NULL);
1117
0
  if (result == ISC_R_NOTFOUND) {
1118
0
    result = ISC_R_SUCCESS;
1119
0
    goto cleanup;
1120
0
  }
1121
0
  CHECK(result);
1122
1123
0
  DNS_RDATASET_FOREACH(&rdataset) {
1124
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
1125
0
    dns_rdataset_current(&rdataset, &rdata);
1126
0
    INSIST(rdata.length <= sizeof(buf));
1127
0
    memmove(buf, rdata.data, rdata.length);
1128
1129
    /*
1130
     * Private NSEC3 record length >= 6.
1131
     * <0(1), hash(1), flags(1), iterations(2), saltlen(1)>
1132
     */
1133
0
    if (rdata.length < 6 || buf[0] != 0 ||
1134
0
        (buf[2] & DNS_NSEC3FLAG_REMOVE) != 0 ||
1135
0
        (nonsec && (buf[2] & DNS_NSEC3FLAG_NONSEC) != 0))
1136
0
    {
1137
0
      continue;
1138
0
    }
1139
1140
0
    dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin, 0,
1141
0
             &rdata, &tuple);
1142
0
    CHECK(do_one_tuple(&tuple, db, ver, diff));
1143
0
    INSIST(tuple == NULL);
1144
1145
0
    rdata.data = buf;
1146
0
    buf[2] = DNS_NSEC3FLAG_REMOVE;
1147
0
    if (nonsec) {
1148
0
      buf[2] |= DNS_NSEC3FLAG_NONSEC;
1149
0
    }
1150
1151
0
    CHECK(rr_exists(db, ver, origin, &rdata, &flag));
1152
1153
0
    if (!flag) {
1154
0
      dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, origin,
1155
0
               0, &rdata, &tuple);
1156
0
      CHECK(do_one_tuple(&tuple, db, ver, diff));
1157
0
      INSIST(tuple == NULL);
1158
0
    }
1159
0
  }
1160
1161
0
  result = ISC_R_SUCCESS;
1162
1163
0
cleanup:
1164
0
  dns_rdataset_cleanup(&rdataset);
1165
0
  dns_db_detachnode(&node);
1166
0
  return result;
1167
0
}
1168
1169
isc_result_t
1170
dns_nsec3_addnsec3sx(dns_db_t *db, dns_dbversion_t *version,
1171
         const dns_name_t *name, dns_ttl_t nsecttl, bool unsecure,
1172
0
         dns_rdatatype_t type, dns_diff_t *diff) {
1173
0
  dns_dbnode_t *node = NULL;
1174
0
  dns_rdata_nsec3param_t nsec3param;
1175
0
  dns_rdataset_t rdataset;
1176
0
  dns_rdataset_t prdataset;
1177
0
  isc_result_t result;
1178
1179
0
  dns_rdataset_init(&rdataset);
1180
0
  dns_rdataset_init(&prdataset);
1181
1182
  /*
1183
   * Find the NSEC3 parameters for this zone.
1184
   */
1185
0
  RETERR(dns_db_getoriginnode(db, &node));
1186
1187
0
  result = dns_db_findrdataset(db, node, version, type, 0, 0, &prdataset,
1188
0
             NULL);
1189
0
  if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
1190
0
    CHECK(result);
1191
0
  }
1192
1193
0
  result = dns_db_findrdataset(db, node, version,
1194
0
             dns_rdatatype_nsec3param, 0, 0, &rdataset,
1195
0
             NULL);
1196
0
  if (result == ISC_R_NOTFOUND) {
1197
0
    goto try_private;
1198
0
  }
1199
0
  CHECK(result);
1200
1201
  /*
1202
   * Update each active NSEC3 chain.
1203
   */
1204
0
  DNS_RDATASET_FOREACH(&rdataset) {
1205
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
1206
1207
0
    dns_rdataset_current(&rdataset, &rdata);
1208
0
    CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
1209
1210
0
    if (nsec3param.flags != 0) {
1211
0
      continue;
1212
0
    }
1213
1214
    /*
1215
     * We have a active chain.  Update it.
1216
     */
1217
0
    CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
1218
0
           nsecttl, unsecure, diff));
1219
0
  }
1220
1221
0
  dns_rdataset_disassociate(&rdataset);
1222
1223
0
try_private:
1224
0
  if (!dns_rdataset_isassociated(&prdataset)) {
1225
0
    result = ISC_R_SUCCESS;
1226
0
    goto cleanup;
1227
0
  }
1228
1229
  /*
1230
   * Update each active NSEC3 chain.
1231
   */
1232
0
  DNS_RDATASET_FOREACH(&prdataset) {
1233
0
    dns_rdata_t rdata1 = DNS_RDATA_INIT;
1234
0
    dns_rdata_t rdata2 = DNS_RDATA_INIT;
1235
0
    unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
1236
1237
0
    dns_rdataset_current(&prdataset, &rdata1);
1238
0
    if (!dns_nsec3param_fromprivate(&rdata1, &rdata2, buf,
1239
0
            sizeof(buf)))
1240
0
    {
1241
0
      continue;
1242
0
    }
1243
0
    CHECK(dns_rdata_tostruct(&rdata2, &nsec3param, NULL));
1244
1245
0
    if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
1246
0
      continue;
1247
0
    }
1248
0
    if (better_param(&prdataset, &rdata2)) {
1249
0
      continue;
1250
0
    }
1251
1252
    /*
1253
     * We have a active chain.  Update it.
1254
     */
1255
0
    CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
1256
0
           nsecttl, unsecure, diff));
1257
0
  }
1258
1259
0
  result = ISC_R_SUCCESS;
1260
1261
0
cleanup:
1262
0
  dns_rdataset_cleanup(&rdataset);
1263
0
  dns_rdataset_cleanup(&prdataset);
1264
0
  if (node != NULL) {
1265
0
    dns_db_detachnode(&node);
1266
0
  }
1267
1268
0
  return result;
1269
0
}
1270
1271
/*%
1272
 * Determine whether any NSEC3 records that were associated with
1273
 * 'name' should be deleted or if they should continue to exist.
1274
 * true indicates they should be deleted.
1275
 * false indicates they should be retained.
1276
 */
1277
static isc_result_t
1278
deleteit(dns_db_t *db, dns_dbversion_t *ver, const dns_name_t *name,
1279
0
   bool *yesno) {
1280
0
  isc_result_t result;
1281
0
  dns_fixedname_t foundname;
1282
0
  dns_fixedname_init(&foundname);
1283
1284
0
  result = dns_db_find(db, name, ver, dns_rdatatype_any,
1285
0
           DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
1286
0
           (isc_stdtime_t)0, NULL,
1287
0
           dns_fixedname_name(&foundname), NULL, NULL);
1288
0
  if (result == DNS_R_EMPTYNAME || result == ISC_R_SUCCESS ||
1289
0
      result == DNS_R_ZONECUT)
1290
0
  {
1291
0
    *yesno = false;
1292
0
    return ISC_R_SUCCESS;
1293
0
  }
1294
0
  if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
1295
0
      result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN)
1296
0
  {
1297
0
    *yesno = true;
1298
0
    return ISC_R_SUCCESS;
1299
0
  }
1300
  /*
1301
   * Silence compiler.
1302
   */
1303
0
  *yesno = true;
1304
0
  return result;
1305
0
}
1306
1307
isc_result_t
1308
dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version,
1309
       const dns_name_t *name,
1310
0
       const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff) {
1311
0
  dns_dbiterator_t *dbit = NULL;
1312
0
  dns_dbnode_t *node = NULL;
1313
0
  dns_difftuple_t *tuple = NULL;
1314
0
  dns_fixedname_t fixed;
1315
0
  dns_fixedname_t fprev;
1316
0
  dns_hash_t hash;
1317
0
  dns_name_t *hashname;
1318
0
  dns_name_t *origin;
1319
0
  dns_name_t *prev;
1320
0
  dns_name_t empty;
1321
0
  dns_rdata_nsec3_t nsec3;
1322
0
  dns_rdata_t rdata = DNS_RDATA_INIT;
1323
0
  dns_rdataset_t rdataset;
1324
0
  int pass;
1325
0
  bool yesno;
1326
0
  isc_buffer_t buffer;
1327
0
  isc_result_t result;
1328
0
  unsigned char *salt;
1329
0
  unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
1330
0
  unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
1331
0
  unsigned int iterations;
1332
0
  unsigned int labels;
1333
0
  size_t next_length;
1334
0
  unsigned int salt_length;
1335
1336
0
  hashname = dns_fixedname_initname(&fixed);
1337
0
  prev = dns_fixedname_initname(&fprev);
1338
1339
0
  dns_rdataset_init(&rdataset);
1340
1341
0
  origin = dns_db_origin(db);
1342
1343
  /*
1344
   * Chain parameters.
1345
   */
1346
0
  hash = nsec3param->hash;
1347
0
  iterations = nsec3param->iterations;
1348
0
  salt_length = nsec3param->salt.length;
1349
0
  salt = nsec3param->salt.base;
1350
1351
  /*
1352
   * If this is the first NSEC3 in the chain nexthash will
1353
   * remain pointing to itself.
1354
   */
1355
0
  next_length = sizeof(nexthash);
1356
0
  CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length, name, origin,
1357
0
         hash, iterations, salt, salt_length));
1358
1359
0
  CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
1360
1361
0
  result = dns_dbiterator_seek(dbit, hashname);
1362
0
  if (result == ISC_R_NOTFOUND || result == DNS_R_PARTIALMATCH) {
1363
0
    goto cleanup_orphaned_ents;
1364
0
  }
1365
0
  CHECK(result);
1366
1367
0
  CHECK(dns_dbiterator_current(dbit, &node, NULL));
1368
0
  CHECK(dns_dbiterator_pause(dbit));
1369
0
  result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3, 0,
1370
0
             (isc_stdtime_t)0, &rdataset, NULL);
1371
0
  dns_db_detachnode(&node);
1372
0
  if (result == ISC_R_NOTFOUND) {
1373
0
    goto cleanup_orphaned_ents;
1374
0
  }
1375
0
  CHECK(result);
1376
1377
  /*
1378
   * If we find a existing NSEC3 for this chain then save the
1379
   * next field.
1380
   */
1381
0
  result = find_nsec3(&nsec3, &rdataset, nsec3param);
1382
0
  if (result == ISC_R_SUCCESS) {
1383
0
    next_length = nsec3.next.length;
1384
0
    INSIST(next_length <= sizeof(nexthash));
1385
0
    memmove(nexthash, nsec3.next.base, next_length);
1386
0
  }
1387
0
  dns_rdataset_disassociate(&rdataset);
1388
0
  if (result == ISC_R_NOTFOUND) {
1389
0
    result = ISC_R_SUCCESS;
1390
0
    goto cleanup;
1391
0
  }
1392
1393
  /*
1394
   * Find the previous NSEC3 and update it.
1395
   */
1396
0
  pass = 0;
1397
0
  do {
1398
0
    result = dns_dbiterator_prev(dbit);
1399
0
    if (result == ISC_R_NOMORE) {
1400
0
      pass++;
1401
0
      CHECK(dns_dbiterator_last(dbit));
1402
0
    }
1403
0
    CHECK(dns_dbiterator_current(dbit, &node, prev));
1404
0
    CHECK(dns_dbiterator_pause(dbit));
1405
0
    result = dns_db_findrdataset(db, node, version,
1406
0
               dns_rdatatype_nsec3, 0,
1407
0
               (isc_stdtime_t)0, &rdataset, NULL);
1408
0
    dns_db_detachnode(&node);
1409
0
    if (result != ISC_R_SUCCESS) {
1410
0
      continue;
1411
0
    }
1412
0
    result = find_nsec3(&nsec3, &rdataset, nsec3param);
1413
0
    if (result == ISC_R_NOTFOUND) {
1414
0
      dns_rdataset_disassociate(&rdataset);
1415
0
      continue;
1416
0
    }
1417
1418
    /*
1419
     * Delete the old previous NSEC3.
1420
     */
1421
0
    CHECK(delnsec3(db, version, prev, nsec3param, diff));
1422
1423
    /*
1424
     * Fixup the previous NSEC3.
1425
     */
1426
0
    nsec3.next.base = nexthash;
1427
0
    nsec3.next.length = (unsigned char)next_length;
1428
0
    if (CREATE(nsec3param->flags)) {
1429
0
      nsec3.flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
1430
0
    }
1431
0
    isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
1432
0
    CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
1433
0
             dns_rdatatype_nsec3, &nsec3,
1434
0
             &buffer));
1435
0
    dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
1436
0
             rdataset.ttl, &rdata, &tuple);
1437
0
    CHECK(do_one_tuple(&tuple, db, version, diff));
1438
0
    dns_rdata_reset(&rdata);
1439
0
    dns_rdataset_disassociate(&rdataset);
1440
0
    break;
1441
0
  } while (pass < 2);
1442
1443
  /*
1444
   * Delete the old NSEC3 and record the change.
1445
   */
1446
0
  CHECK(delnsec3(db, version, hashname, nsec3param, diff));
1447
1448
  /*
1449
   *  Delete NSEC3 records for now non active nodes.
1450
   */
1451
0
cleanup_orphaned_ents:
1452
0
  dns_name_init(&empty);
1453
0
  dns_name_clone(name, &empty);
1454
0
  do {
1455
0
    labels = dns_name_countlabels(&empty) - 1;
1456
0
    if (labels <= dns_name_countlabels(origin)) {
1457
0
      break;
1458
0
    }
1459
0
    dns_name_getlabelsequence(&empty, 1, labels, &empty);
1460
0
    CHECK(deleteit(db, version, &empty, &yesno));
1461
0
    if (!yesno) {
1462
0
      break;
1463
0
    }
1464
1465
0
    CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length, &empty,
1466
0
           origin, hash, iterations, salt,
1467
0
           salt_length));
1468
0
    result = dns_dbiterator_seek(dbit, hashname);
1469
0
    if (result == ISC_R_NOTFOUND || result == DNS_R_PARTIALMATCH) {
1470
0
      result = ISC_R_SUCCESS;
1471
0
      goto cleanup;
1472
0
    }
1473
0
    CHECK(result);
1474
1475
0
    CHECK(dns_dbiterator_current(dbit, &node, NULL));
1476
0
    CHECK(dns_dbiterator_pause(dbit));
1477
0
    result = dns_db_findrdataset(db, node, version,
1478
0
               dns_rdatatype_nsec3, 0,
1479
0
               (isc_stdtime_t)0, &rdataset, NULL);
1480
0
    dns_db_detachnode(&node);
1481
0
    if (result == ISC_R_NOTFOUND) {
1482
0
      result = ISC_R_SUCCESS;
1483
0
      goto cleanup;
1484
0
    }
1485
0
    CHECK(result);
1486
1487
0
    result = find_nsec3(&nsec3, &rdataset, nsec3param);
1488
0
    if (result == ISC_R_SUCCESS) {
1489
0
      next_length = nsec3.next.length;
1490
0
      INSIST(next_length <= sizeof(nexthash));
1491
0
      memmove(nexthash, nsec3.next.base, next_length);
1492
0
    }
1493
0
    dns_rdataset_disassociate(&rdataset);
1494
0
    if (result == ISC_R_NOTFOUND) {
1495
0
      result = ISC_R_SUCCESS;
1496
0
      goto cleanup;
1497
0
    }
1498
1499
0
    pass = 0;
1500
0
    do {
1501
0
      result = dns_dbiterator_prev(dbit);
1502
0
      if (result == ISC_R_NOMORE) {
1503
0
        pass++;
1504
0
        CHECK(dns_dbiterator_last(dbit));
1505
0
      }
1506
0
      CHECK(dns_dbiterator_current(dbit, &node, prev));
1507
0
      CHECK(dns_dbiterator_pause(dbit));
1508
0
      result = dns_db_findrdataset(
1509
0
        db, node, version, dns_rdatatype_nsec3, 0,
1510
0
        (isc_stdtime_t)0, &rdataset, NULL);
1511
0
      dns_db_detachnode(&node);
1512
0
      if (result != ISC_R_SUCCESS) {
1513
0
        continue;
1514
0
      }
1515
0
      result = find_nsec3(&nsec3, &rdataset, nsec3param);
1516
0
      if (result == ISC_R_NOTFOUND) {
1517
0
        dns_rdataset_disassociate(&rdataset);
1518
0
        continue;
1519
0
      }
1520
1521
      /*
1522
       * Delete the old previous NSEC3.
1523
       */
1524
0
      CHECK(delnsec3(db, version, prev, nsec3param, diff));
1525
1526
      /*
1527
       * Fixup the previous NSEC3.
1528
       */
1529
0
      nsec3.next.base = nexthash;
1530
0
      nsec3.next.length = (unsigned char)next_length;
1531
0
      isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
1532
0
      CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
1533
0
               dns_rdatatype_nsec3, &nsec3,
1534
0
               &buffer));
1535
0
      dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
1536
0
               rdataset.ttl, &rdata, &tuple);
1537
0
      CHECK(do_one_tuple(&tuple, db, version, diff));
1538
0
      dns_rdata_reset(&rdata);
1539
0
      dns_rdataset_disassociate(&rdataset);
1540
0
      break;
1541
0
    } while (pass < 2);
1542
1543
0
    INSIST(pass < 2);
1544
1545
    /*
1546
     * Delete the old NSEC3 and record the change.
1547
     */
1548
0
    CHECK(delnsec3(db, version, hashname, nsec3param, diff));
1549
0
  } while (1);
1550
1551
0
  result = ISC_R_SUCCESS;
1552
1553
0
cleanup:
1554
0
  if (dbit != NULL) {
1555
0
    dns_dbiterator_destroy(&dbit);
1556
0
  }
1557
0
  dns_rdataset_cleanup(&rdataset);
1558
0
  if (node != NULL) {
1559
0
    dns_db_detachnode(&node);
1560
0
  }
1561
0
  return result;
1562
0
}
1563
1564
isc_result_t
1565
dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version,
1566
0
        const dns_name_t *name, dns_diff_t *diff) {
1567
0
  return dns_nsec3_delnsec3sx(db, version, name, 0, diff);
1568
0
}
1569
1570
isc_result_t
1571
dns_nsec3_delnsec3sx(dns_db_t *db, dns_dbversion_t *version,
1572
         const dns_name_t *name, dns_rdatatype_t privatetype,
1573
0
         dns_diff_t *diff) {
1574
0
  dns_dbnode_t *node = NULL;
1575
0
  dns_rdata_nsec3param_t nsec3param;
1576
0
  dns_rdataset_t rdataset;
1577
0
  isc_result_t result;
1578
1579
0
  dns_rdataset_init(&rdataset);
1580
1581
  /*
1582
   * Find the NSEC3 parameters for this zone.
1583
   */
1584
0
  RETERR(dns_db_getoriginnode(db, &node));
1585
1586
0
  result = dns_db_findrdataset(db, node, version,
1587
0
             dns_rdatatype_nsec3param, 0, 0, &rdataset,
1588
0
             NULL);
1589
0
  if (result == ISC_R_NOTFOUND) {
1590
0
    goto try_private;
1591
0
  }
1592
0
  CHECK(result);
1593
1594
  /*
1595
   * Update each active NSEC3 chain.
1596
   */
1597
0
  DNS_RDATASET_FOREACH(&rdataset) {
1598
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
1599
1600
0
    dns_rdataset_current(&rdataset, &rdata);
1601
0
    CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
1602
1603
0
    if (nsec3param.flags != 0) {
1604
0
      continue;
1605
0
    }
1606
    /*
1607
     * We have a active chain.  Update it.
1608
     */
1609
0
    CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
1610
0
  }
1611
0
  dns_rdataset_disassociate(&rdataset);
1612
1613
0
try_private:
1614
0
  if (privatetype == 0) {
1615
0
    result = ISC_R_SUCCESS;
1616
0
    goto cleanup;
1617
0
  }
1618
0
  result = dns_db_findrdataset(db, node, version, privatetype, 0, 0,
1619
0
             &rdataset, NULL);
1620
0
  if (result == ISC_R_NOTFOUND) {
1621
0
    result = ISC_R_SUCCESS;
1622
0
    goto cleanup;
1623
0
  }
1624
0
  CHECK(result);
1625
1626
  /*
1627
   * Update each NSEC3 chain being built.
1628
   */
1629
0
  DNS_RDATASET_FOREACH(&rdataset) {
1630
0
    dns_rdata_t rdata1 = DNS_RDATA_INIT;
1631
0
    dns_rdata_t rdata2 = DNS_RDATA_INIT;
1632
0
    unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
1633
1634
0
    dns_rdataset_current(&rdataset, &rdata1);
1635
0
    if (!dns_nsec3param_fromprivate(&rdata1, &rdata2, buf,
1636
0
            sizeof(buf)))
1637
0
    {
1638
0
      continue;
1639
0
    }
1640
0
    CHECK(dns_rdata_tostruct(&rdata2, &nsec3param, NULL));
1641
1642
0
    if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
1643
0
      continue;
1644
0
    }
1645
0
    if (better_param(&rdataset, &rdata2)) {
1646
0
      continue;
1647
0
    }
1648
1649
    /*
1650
     * We have a active chain.  Update it.
1651
     */
1652
0
    CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
1653
0
  }
1654
1655
0
  result = ISC_R_SUCCESS;
1656
1657
0
cleanup:
1658
0
  dns_rdataset_cleanup(&rdataset);
1659
0
  if (node != NULL) {
1660
0
    dns_db_detachnode(&node);
1661
0
  }
1662
1663
0
  return result;
1664
0
}
1665
1666
isc_result_t
1667
dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version, bool complete,
1668
0
     bool *answer) {
1669
0
  return dns_nsec3_activex(db, version, complete, 0, answer);
1670
0
}
1671
1672
isc_result_t
1673
dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version, bool complete,
1674
0
      dns_rdatatype_t privatetype, bool *answer) {
1675
0
  dns_dbnode_t *node = NULL;
1676
0
  dns_rdataset_t rdataset;
1677
0
  dns_rdata_nsec3param_t nsec3param;
1678
0
  isc_result_t result;
1679
1680
0
  REQUIRE(answer != NULL);
1681
1682
0
  dns_rdataset_init(&rdataset);
1683
1684
0
  RETERR(dns_db_getoriginnode(db, &node));
1685
1686
0
  result = dns_db_findrdataset(db, node, version,
1687
0
             dns_rdatatype_nsec3param, 0, 0, &rdataset,
1688
0
             NULL);
1689
1690
0
  if (result == ISC_R_NOTFOUND) {
1691
0
    goto try_private;
1692
0
  }
1693
1694
0
  if (result != ISC_R_SUCCESS) {
1695
0
    dns_db_detachnode(&node);
1696
0
    return result;
1697
0
  }
1698
1699
0
  bool found = false;
1700
0
  DNS_RDATASET_FOREACH(&rdataset) {
1701
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
1702
0
    dns_rdataset_current(&rdataset, &rdata);
1703
0
    dns_rdata_tostruct(&rdata, &nsec3param, NULL);
1704
1705
0
    if (nsec3param.flags == 0) {
1706
0
      found = true;
1707
0
      break;
1708
0
    }
1709
0
  }
1710
0
  dns_rdataset_disassociate(&rdataset);
1711
0
  *answer = found;
1712
1713
0
try_private:
1714
0
  if (privatetype == 0 || complete) {
1715
0
    dns_db_detachnode(&node);
1716
0
    *answer = false;
1717
0
    return ISC_R_SUCCESS;
1718
0
  }
1719
0
  result = dns_db_findrdataset(db, node, version, privatetype, 0, 0,
1720
0
             &rdataset, NULL);
1721
1722
0
  dns_db_detachnode(&node);
1723
0
  if (result == ISC_R_NOTFOUND) {
1724
0
    *answer = false;
1725
0
    return ISC_R_SUCCESS;
1726
0
  }
1727
0
  if (result != ISC_R_SUCCESS) {
1728
0
    return result;
1729
0
  }
1730
1731
0
  found = false;
1732
0
  DNS_RDATASET_FOREACH(&rdataset) {
1733
0
    dns_rdata_t rdata1 = DNS_RDATA_INIT;
1734
0
    dns_rdata_t rdata2 = DNS_RDATA_INIT;
1735
0
    unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
1736
1737
0
    dns_rdataset_current(&rdataset, &rdata1);
1738
0
    if (!dns_nsec3param_fromprivate(&rdata1, &rdata2, buf,
1739
0
            sizeof(buf)))
1740
0
    {
1741
0
      continue;
1742
0
    }
1743
1744
0
    dns_rdata_tostruct(&rdata2, &nsec3param, NULL);
1745
0
    if (!complete && CREATE(nsec3param.flags)) {
1746
0
      found = true;
1747
0
      break;
1748
0
    }
1749
0
  }
1750
0
  dns_rdataset_disassociate(&rdataset);
1751
0
  *answer = found;
1752
1753
0
  return result;
1754
0
}
1755
1756
unsigned int
1757
0
dns_nsec3_maxiterations(void) {
1758
0
  return DNS_NSEC3_MAXITERATIONS;
1759
0
}
1760
1761
isc_result_t
1762
dns_nsec3_noexistnodata(dns_rdatatype_t type, const dns_name_t *name,
1763
      const dns_name_t *nsec3name, dns_rdataset_t *nsec3set,
1764
      dns_name_t *zonename, bool *exists, bool *data,
1765
      bool *optout, bool *unknown, bool *setclosest,
1766
      bool *setnearest, dns_name_t *closest,
1767
0
      dns_name_t *nearest, dns_nseclog_t logit, void *arg) {
1768
0
  char namebuf[DNS_NAME_FORMATSIZE];
1769
0
  dns_fixedname_t fzone;
1770
0
  dns_fixedname_t qfixed;
1771
0
  dns_label_t hashlabel;
1772
0
  dns_name_t *qname;
1773
0
  dns_name_t *zone;
1774
0
  dns_rdata_nsec3_t nsec3;
1775
0
  dns_rdata_t rdata = DNS_RDATA_INIT;
1776
0
  int order;
1777
0
  int scope;
1778
0
  bool atparent;
1779
0
  bool first;
1780
0
  bool ns;
1781
0
  bool soa;
1782
0
  isc_buffer_t buffer;
1783
0
  isc_result_t answer = ISC_R_IGNORE;
1784
0
  isc_result_t result;
1785
0
  unsigned char hash[NSEC3_MAX_HASH_LENGTH];
1786
0
  unsigned char owner[NSEC3_MAX_HASH_LENGTH];
1787
0
  unsigned int length;
1788
0
  unsigned int qlabels;
1789
0
  unsigned int zlabels;
1790
1791
0
  REQUIRE((exists == NULL && data == NULL) ||
1792
0
    (exists != NULL && data != NULL));
1793
0
  REQUIRE(nsec3set != NULL && nsec3set->type == dns_rdatatype_nsec3);
1794
0
  REQUIRE((setclosest == NULL && closest == NULL) ||
1795
0
    (setclosest != NULL && closest != NULL));
1796
0
  REQUIRE((setnearest == NULL && nearest == NULL) ||
1797
0
    (setnearest != NULL && nearest != NULL));
1798
1799
0
  result = dns_rdataset_first(nsec3set);
1800
0
  if (result != ISC_R_SUCCESS) {
1801
0
    (*logit)(arg, ISC_LOG_DEBUG(3), "failure processing NSEC3 set");
1802
0
    return result;
1803
0
  }
1804
1805
0
  dns_rdataset_current(nsec3set, &rdata);
1806
1807
0
  RETERR(dns_rdata_tostruct(&rdata, &nsec3, NULL));
1808
1809
0
  (*logit)(arg, ISC_LOG_DEBUG(3), "looking for relevant NSEC3");
1810
1811
0
  zone = dns_fixedname_initname(&fzone);
1812
0
  zlabels = dns_name_countlabels(nsec3name);
1813
1814
  /*
1815
   * NSEC3 records must have two or more labels to be valid.
1816
   */
1817
0
  if (zlabels < 2) {
1818
0
    return ISC_R_IGNORE;
1819
0
  }
1820
1821
  /*
1822
   * Strip off the NSEC3 hash to get the zone.
1823
   */
1824
0
  zlabels--;
1825
0
  dns_name_split(nsec3name, zlabels, NULL, zone);
1826
1827
  /*
1828
   * If not below the zone name we can ignore this record.
1829
   */
1830
0
  if (!dns_name_issubdomain(name, zone)) {
1831
0
    return ISC_R_IGNORE;
1832
0
  }
1833
1834
  /*
1835
   * Is this zone the same or deeper than the current zone?
1836
   */
1837
0
  if (dns_name_countlabels(zonename) == 0 ||
1838
0
      dns_name_issubdomain(zone, zonename))
1839
0
  {
1840
0
    dns_name_copy(zone, zonename);
1841
0
  }
1842
1843
0
  if (!dns_name_equal(zone, zonename)) {
1844
0
    return ISC_R_IGNORE;
1845
0
  }
1846
1847
  /*
1848
   * Are we only looking for the most enclosing zone?
1849
   */
1850
0
  if (exists == NULL || data == NULL) {
1851
0
    return ISC_R_SUCCESS;
1852
0
  }
1853
1854
  /*
1855
   * Only set unknown once we are sure that this NSEC3 is from
1856
   * the deepest covering zone.
1857
   */
1858
0
  if (!dns_nsec3_supportedhash(nsec3.hash)) {
1859
0
    SET_IF_NOT_NULL(unknown, true);
1860
0
    return ISC_R_IGNORE;
1861
0
  }
1862
1863
  /*
1864
   * Recover the hash from the first label.
1865
   */
1866
0
  dns_name_getlabel(nsec3name, 0, &hashlabel);
1867
0
  isc_region_consume(&hashlabel, 1);
1868
0
  isc_buffer_init(&buffer, owner, sizeof(owner));
1869
0
  RETERR(isc_base32hex_decoderegion(&hashlabel, &buffer));
1870
1871
  /*
1872
   * The hash lengths should match.  If not ignore the record.
1873
   */
1874
0
  if (isc_buffer_usedlength(&buffer) != nsec3.next.length) {
1875
0
    return ISC_R_IGNORE;
1876
0
  }
1877
1878
  /*
1879
   * Work out what this NSEC3 covers.
1880
   * Inside (<0) or outside (>=0).
1881
   */
1882
0
  scope = memcmp(owner, nsec3.next.base, nsec3.next.length);
1883
1884
  /*
1885
   * Prepare to compute all the hashes.
1886
   */
1887
0
  qname = dns_fixedname_initname(&qfixed);
1888
0
  dns_name_downcase(name, qname);
1889
0
  qlabels = dns_name_countlabels(qname);
1890
0
  first = true;
1891
1892
0
  while (qlabels >= zlabels) {
1893
    /*
1894
     * If there are too many iterations reject the NSEC3 record.
1895
     */
1896
0
    if (nsec3.iterations > DNS_NSEC3_MAXITERATIONS) {
1897
0
      return DNS_R_NSEC3ITERRANGE;
1898
0
    }
1899
1900
0
    length = isc_iterated_hash(hash, nsec3.hash, nsec3.iterations,
1901
0
             nsec3.salt.base, nsec3.salt.length,
1902
0
             qname->ndata, qname->length);
1903
    /*
1904
     * The computed hash length should match.
1905
     */
1906
0
    if (length != nsec3.next.length) {
1907
0
      (*logit)(arg, ISC_LOG_DEBUG(3),
1908
0
         "ignoring NSEC bad length %u vs %u", length,
1909
0
         nsec3.next.length);
1910
0
      return ISC_R_IGNORE;
1911
0
    }
1912
1913
0
    order = memcmp(hash, owner, length);
1914
0
    if (first && order == 0) {
1915
      /*
1916
       * The hashes are the same.
1917
       */
1918
0
      atparent = dns_rdatatype_atparent(type);
1919
0
      ns = dns_nsec3_typepresent(&rdata, dns_rdatatype_ns);
1920
0
      soa = dns_nsec3_typepresent(&rdata, dns_rdatatype_soa);
1921
0
      if (ns && !soa) {
1922
0
        if (!atparent) {
1923
          /*
1924
           * This NSEC3 record is from somewhere
1925
           * higher in the DNS, and at the
1926
           * parent of a delegation. It can not
1927
           * be legitimately used here.
1928
           */
1929
0
          (*logit)(arg, ISC_LOG_DEBUG(3),
1930
0
             "ignoring parent NSEC3");
1931
0
          return ISC_R_IGNORE;
1932
0
        }
1933
0
      } else if (atparent && ns && soa) {
1934
        /*
1935
         * This NSEC3 record is from the child.
1936
         * It can not be legitimately used here.
1937
         */
1938
0
        (*logit)(arg, ISC_LOG_DEBUG(3),
1939
0
           "ignoring child NSEC3");
1940
0
        return ISC_R_IGNORE;
1941
0
      }
1942
0
      if (type == dns_rdatatype_cname ||
1943
0
          type == dns_rdatatype_nsec ||
1944
0
          !dns_nsec3_typepresent(&rdata, dns_rdatatype_cname))
1945
0
      {
1946
0
        *exists = true;
1947
0
        *data = dns_nsec3_typepresent(&rdata, type);
1948
0
        (*logit)(arg, ISC_LOG_DEBUG(3),
1949
0
           "NSEC3 proves name exists (owner) "
1950
0
           "data=%d",
1951
0
           *data);
1952
0
        return ISC_R_SUCCESS;
1953
0
      }
1954
0
      (*logit)(arg, ISC_LOG_DEBUG(3),
1955
0
         "NSEC3 proves CNAME exists");
1956
0
      return ISC_R_IGNORE;
1957
0
    }
1958
1959
0
    if (order == 0 &&
1960
0
        dns_nsec3_typepresent(&rdata, dns_rdatatype_ns) &&
1961
0
        !dns_nsec3_typepresent(&rdata, dns_rdatatype_soa))
1962
0
    {
1963
      /*
1964
       * This NSEC3 record is from somewhere higher in
1965
       * the DNS, and at the parent of a delegation.
1966
       * It can not be legitimately used here.
1967
       */
1968
0
      (*logit)(arg, ISC_LOG_DEBUG(3),
1969
0
         "ignoring parent NSEC3");
1970
0
      return ISC_R_IGNORE;
1971
0
    }
1972
1973
    /*
1974
     * Potential closest encloser.
1975
     */
1976
0
    if (order == 0) {
1977
0
      if (closest != NULL &&
1978
0
          (dns_name_countlabels(closest) == 0 ||
1979
0
           dns_name_issubdomain(qname, closest)) &&
1980
0
          !dns_nsec3_typepresent(&rdata, dns_rdatatype_ds) &&
1981
0
          !dns_nsec3_typepresent(&rdata,
1982
0
               dns_rdatatype_dname) &&
1983
0
          (dns_nsec3_typepresent(&rdata, dns_rdatatype_soa) ||
1984
0
           !dns_nsec3_typepresent(&rdata, dns_rdatatype_ns)))
1985
0
      {
1986
0
        dns_name_format(qname, namebuf,
1987
0
            sizeof(namebuf));
1988
0
        (*logit)(arg, ISC_LOG_DEBUG(3),
1989
0
           "NSEC3 indicates potential closest "
1990
0
           "encloser: '%s'",
1991
0
           namebuf);
1992
0
        dns_name_copy(qname, closest);
1993
0
        *setclosest = true;
1994
0
      }
1995
0
      dns_name_format(qname, namebuf, sizeof(namebuf));
1996
0
      (*logit)(arg, ISC_LOG_DEBUG(3),
1997
0
         "NSEC3 at super-domain %s", namebuf);
1998
0
      return answer;
1999
0
    }
2000
2001
    /*
2002
     * Find if the name does not exist.
2003
     *
2004
     * We continue as we need to find the name closest to the
2005
     * closest encloser that doesn't exist.
2006
     *
2007
     * We also need to continue to ensure that we are not
2008
     * proving the non-existence of a record in a sub-zone.
2009
     * If that would be the case we will return ISC_R_IGNORE
2010
     * above.
2011
     */
2012
0
    if ((scope < 0 && order > 0 &&
2013
0
         memcmp(hash, nsec3.next.base, length) < 0) ||
2014
0
        (scope >= 0 &&
2015
0
         (order > 0 || memcmp(hash, nsec3.next.base, length) < 0)))
2016
0
    {
2017
0
      dns_name_format(qname, namebuf, sizeof(namebuf));
2018
0
      (*logit)(arg, ISC_LOG_DEBUG(3),
2019
0
         "NSEC3 proves "
2020
0
         "name does not exist: '%s'",
2021
0
         namebuf);
2022
0
      if (nearest != NULL &&
2023
0
          (dns_name_countlabels(nearest) == 0 ||
2024
0
           dns_name_issubdomain(nearest, qname)))
2025
0
      {
2026
0
        dns_name_copy(qname, nearest);
2027
0
        *setnearest = true;
2028
0
      }
2029
2030
0
      *exists = false;
2031
0
      *data = false;
2032
0
      if (optout != NULL) {
2033
0
        *optout = ((nsec3.flags &
2034
0
              DNS_NSEC3FLAG_OPTOUT) != 0);
2035
0
        (*logit)(arg, ISC_LOG_DEBUG(3),
2036
0
           *optout ? "NSEC3 indicates optout"
2037
0
             : "NSEC3 indicates secure "
2038
0
               "range");
2039
0
      }
2040
0
      answer = ISC_R_SUCCESS;
2041
0
    }
2042
2043
0
    qlabels--;
2044
0
    if (qlabels > 0) {
2045
0
      dns_name_split(qname, qlabels, NULL, qname);
2046
0
    }
2047
0
    first = false;
2048
0
  }
2049
0
  return answer;
2050
0
}