Coverage Report

Created: 2025-07-18 07:02

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