"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/lib/dns/nsec3.c" (4 Sep 2020, 56398 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "nsec3.c" see the Fossies "Dox" file reference documentation.

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