Coverage Report

Created: 2025-08-26 06:59

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