nsec3.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006, 2008-2015  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /* $Id$ */
00018 
00019 #include <config.h>
00020 
00021 #include <isc/base32.h>
00022 #include <isc/buffer.h>
00023 #include <isc/hex.h>
00024 #include <isc/iterated_hash.h>
00025 #include <isc/log.h>
00026 #include <isc/string.h>
00027 #include <isc/util.h>
00028 
00029 #include <dst/dst.h>
00030 
00031 #include <dns/db.h>
00032 #include <dns/zone.h>
00033 #include <dns/compress.h>
00034 #include <dns/dbiterator.h>
00035 #include <dns/diff.h>
00036 #include <dns/fixedname.h>
00037 #include <dns/nsec.h>
00038 #include <dns/nsec3.h>
00039 #include <dns/rdata.h>
00040 #include <dns/rdatalist.h>
00041 #include <dns/rdataset.h>
00042 #include <dns/rdatasetiter.h>
00043 #include <dns/rdatastruct.h>
00044 #include <dns/result.h>
00045 
00046 #define CHECK(x) do { \
00047         result = (x); \
00048         if (result != ISC_R_SUCCESS) \
00049                 goto failure; \
00050         } while (0)
00051 
00052 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
00053 #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
00054 #define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0)
00055 #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
00056 
00057 isc_result_t
00058 dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
00059                      dns_dbnode_t *node, unsigned int hashalg,
00060                      unsigned int flags, unsigned int iterations,
00061                      const unsigned char *salt, size_t salt_length,
00062                      const unsigned char *nexthash, size_t hash_length,
00063                      unsigned char *buffer, dns_rdata_t *rdata)
00064 {
00065         isc_result_t result;
00066         dns_rdataset_t rdataset;
00067         isc_region_t r;
00068         unsigned int i;
00069         isc_boolean_t found;
00070         isc_boolean_t found_ns;
00071         isc_boolean_t need_rrsig;
00072 
00073         unsigned char *nsec_bits, *bm;
00074         unsigned int max_type;
00075         dns_rdatasetiter_t *rdsiter;
00076         unsigned char *p;
00077 
00078         REQUIRE(salt_length < 256U);
00079         REQUIRE(hash_length < 256U);
00080         REQUIRE(flags <= 0xffU);
00081         REQUIRE(hashalg <= 0xffU);
00082         REQUIRE(iterations <= 0xffffU);
00083 
00084         switch (hashalg) {
00085         case dns_hash_sha1:
00086                 REQUIRE(hash_length == ISC_SHA1_DIGESTLENGTH);
00087                 break;
00088         }
00089 
00090         memset(buffer, 0, DNS_NSEC3_BUFFERSIZE);
00091 
00092         p = buffer;
00093 
00094         *p++ = hashalg;
00095         *p++ = flags;
00096 
00097         *p++ = iterations >> 8;
00098         *p++ = iterations;
00099 
00100         *p++ = (unsigned char)salt_length;
00101         memmove(p, salt, salt_length);
00102         p += salt_length;
00103 
00104         *p++ = (unsigned char)hash_length;
00105         memmove(p, nexthash, hash_length);
00106         p += hash_length;
00107 
00108         r.length = (unsigned int)(p - buffer);
00109         r.base = buffer;
00110 
00111         /*
00112          * Use the end of the space for a raw bitmap leaving enough
00113          * space for the window identifiers and length octets.
00114          */
00115         bm = r.base + r.length + 512;
00116         nsec_bits = r.base + r.length;
00117         max_type = 0;
00118         if (node == NULL)
00119                 goto collapse_bitmap;
00120         dns_rdataset_init(&rdataset);
00121         rdsiter = NULL;
00122         result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
00123         if (result != ISC_R_SUCCESS)
00124                 return (result);
00125         found = found_ns = need_rrsig = ISC_FALSE;
00126         for (result = dns_rdatasetiter_first(rdsiter);
00127              result == ISC_R_SUCCESS;
00128              result = dns_rdatasetiter_next(rdsiter))
00129         {
00130                 dns_rdatasetiter_current(rdsiter, &rdataset);
00131                 if (rdataset.type != dns_rdatatype_nsec &&
00132                     rdataset.type != dns_rdatatype_nsec3 &&
00133                     rdataset.type != dns_rdatatype_rrsig) {
00134                         if (rdataset.type > max_type)
00135                                 max_type = rdataset.type;
00136                         dns_nsec_setbit(bm, rdataset.type, 1);
00137                         /*
00138                          * Work out if we need to set the RRSIG bit for
00139                          * this node.  We set the RRSIG bit if either of
00140                          * the following conditions are met:
00141                          * 1) We have a SOA or DS then we need to set
00142                          *    the RRSIG bit as both always will be signed.
00143                          * 2) We set the RRSIG bit if we don't have
00144                          *    a NS record but do have other data.
00145                          */
00146                         if (rdataset.type == dns_rdatatype_soa ||
00147                             rdataset.type == dns_rdatatype_ds)
00148                                 need_rrsig = ISC_TRUE;
00149                         else if (rdataset.type == dns_rdatatype_ns)
00150                                 found_ns = ISC_TRUE;
00151                         else
00152                                 found = ISC_TRUE;
00153                 }
00154                 dns_rdataset_disassociate(&rdataset);
00155         }
00156         if ((found && !found_ns) || need_rrsig) {
00157                 if (dns_rdatatype_rrsig > max_type)
00158                         max_type = dns_rdatatype_rrsig;
00159                 dns_nsec_setbit(bm, dns_rdatatype_rrsig, 1);
00160         }
00161 
00162         /*
00163          * At zone cuts, deny the existence of glue in the parent zone.
00164          */
00165         if (dns_nsec_isset(bm, dns_rdatatype_ns) &&
00166             ! dns_nsec_isset(bm, dns_rdatatype_soa)) {
00167                 for (i = 0; i <= max_type; i++) {
00168                         if (dns_nsec_isset(bm, i) &&
00169                             ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
00170                                 dns_nsec_setbit(bm, i, 0);
00171                 }
00172         }
00173 
00174         dns_rdatasetiter_destroy(&rdsiter);
00175         if (result != ISC_R_NOMORE)
00176                 return (result);
00177 
00178  collapse_bitmap:
00179         nsec_bits += dns_nsec_compressbitmap(nsec_bits, bm, max_type);
00180         r.length = (unsigned int)(nsec_bits - r.base);
00181         INSIST(r.length <= DNS_NSEC3_BUFFERSIZE);
00182         dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r);
00183 
00184         return (ISC_R_SUCCESS);
00185 }
00186 
00187 isc_boolean_t
00188 dns_nsec3_typepresent(dns_rdata_t *rdata, dns_rdatatype_t type) {
00189         dns_rdata_nsec3_t nsec3;
00190         isc_result_t result;
00191         isc_boolean_t present;
00192         unsigned int i, len, window;
00193 
00194         REQUIRE(rdata != NULL);
00195         REQUIRE(rdata->type == dns_rdatatype_nsec3);
00196 
00197         /* This should never fail */
00198         result = dns_rdata_tostruct(rdata, &nsec3, NULL);
00199         INSIST(result == ISC_R_SUCCESS);
00200 
00201         present = ISC_FALSE;
00202         for (i = 0; i < nsec3.len; i += len) {
00203                 INSIST(i + 2 <= nsec3.len);
00204                 window = nsec3.typebits[i];
00205                 len = nsec3.typebits[i + 1];
00206                 INSIST(len > 0 && len <= 32);
00207                 i += 2;
00208                 INSIST(i + len <= nsec3.len);
00209                 if (window * 256 > type)
00210                         break;
00211                 if ((window + 1) * 256 <= type)
00212                         continue;
00213                 if (type < (window * 256) + len * 8)
00214                         present = ISC_TF(dns_nsec_isset(&nsec3.typebits[i],
00215                                                         type % 256));
00216                 break;
00217         }
00218         dns_rdata_freestruct(&nsec3);
00219         return (present);
00220 }
00221 
00222 isc_result_t
00223 dns_nsec3_hashname(dns_fixedname_t *result,
00224                    unsigned char rethash[NSEC3_MAX_HASH_LENGTH],
00225                    size_t *hash_length, dns_name_t *name, dns_name_t *origin,
00226                    dns_hash_t hashalg, unsigned int iterations,
00227                    const unsigned char *salt, size_t saltlength)
00228 {
00229         unsigned char hash[NSEC3_MAX_HASH_LENGTH];
00230         unsigned char nametext[DNS_NAME_FORMATSIZE];
00231         dns_fixedname_t fixed;
00232         dns_name_t *downcased;
00233         isc_buffer_t namebuffer;
00234         isc_region_t region;
00235         size_t len;
00236 
00237         if (rethash == NULL)
00238                 rethash = hash;
00239 
00240         memset(rethash, 0, NSEC3_MAX_HASH_LENGTH);
00241 
00242         dns_fixedname_init(&fixed);
00243         downcased = dns_fixedname_name(&fixed);
00244         dns_name_downcase(name, downcased, NULL);
00245 
00246         /* hash the node name */
00247         len = isc_iterated_hash(rethash, hashalg, iterations,
00248                                 salt, (int)saltlength,
00249                                 downcased->ndata, downcased->length);
00250         if (len == 0U)
00251                 return (DNS_R_BADALG);
00252 
00253         if (hash_length != NULL)
00254                 *hash_length = len;
00255 
00256         /* convert the hash to base32hex non-padded */
00257         region.base = rethash;
00258         region.length = (unsigned int)len;
00259         isc_buffer_init(&namebuffer, nametext, sizeof nametext);
00260         isc_base32hexnp_totext(&region, 1, "", &namebuffer);
00261 
00262         /* convert the hex to a domain name */
00263         dns_fixedname_init(result);
00264         return (dns_name_fromtext(dns_fixedname_name(result), &namebuffer,
00265                                   origin, 0, NULL));
00266 }
00267 
00268 unsigned int
00269 dns_nsec3_hashlength(dns_hash_t hash) {
00270 
00271         switch (hash) {
00272         case dns_hash_sha1:
00273                 return(ISC_SHA1_DIGESTLENGTH);
00274         }
00275         return (0);
00276 }
00277 
00278 isc_boolean_t
00279 dns_nsec3_supportedhash(dns_hash_t hash) {
00280         switch (hash) {
00281         case dns_hash_sha1:
00282                 return (ISC_TRUE);
00283         }
00284         return (ISC_FALSE);
00285 }
00286 
00287 /*%
00288  * Update a single RR in version 'ver' of 'db' and log the
00289  * update in 'diff'.
00290  *
00291  * Ensures:
00292  * \li  '*tuple' == NULL.  Either the tuple is freed, or its
00293  *      ownership has been transferred to the diff.
00294  */
00295 static isc_result_t
00296 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
00297              dns_diff_t *diff)
00298 {
00299         dns_diff_t temp_diff;
00300         isc_result_t result;
00301 
00302         /*
00303          * Create a singleton diff.
00304          */
00305         dns_diff_init(diff->mctx, &temp_diff);
00306         ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
00307 
00308         /*
00309          * Apply it to the database.
00310          */
00311         result = dns_diff_apply(&temp_diff, db, ver);
00312         ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
00313         if (result != ISC_R_SUCCESS) {
00314                 dns_difftuple_free(tuple);
00315                 return (result);
00316         }
00317 
00318         /*
00319          * Merge it into the current pending journal entry.
00320          */
00321         dns_diff_appendminimal(diff, tuple);
00322 
00323         /*
00324          * Do not clear temp_diff.
00325          */
00326         return (ISC_R_SUCCESS);
00327 }
00328 
00329 /*%
00330  * Set '*exists' to true iff the given name exists, to false otherwise.
00331  */
00332 static isc_result_t
00333 name_exists(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
00334             isc_boolean_t *exists)
00335 {
00336         isc_result_t result;
00337         dns_dbnode_t *node = NULL;
00338         dns_rdatasetiter_t *iter = NULL;
00339 
00340         result = dns_db_findnode(db, name, ISC_FALSE, &node);
00341         if (result == ISC_R_NOTFOUND) {
00342                 *exists = ISC_FALSE;
00343                 return (ISC_R_SUCCESS);
00344         }
00345         if (result != ISC_R_SUCCESS)
00346                 return (result);
00347 
00348         result = dns_db_allrdatasets(db, node, version,
00349                                      (isc_stdtime_t) 0, &iter);
00350         if (result != ISC_R_SUCCESS)
00351                 goto cleanup_node;
00352 
00353         result = dns_rdatasetiter_first(iter);
00354         if (result == ISC_R_SUCCESS) {
00355                 *exists = ISC_TRUE;
00356         } else if (result == ISC_R_NOMORE) {
00357                 *exists = ISC_FALSE;
00358                 result = ISC_R_SUCCESS;
00359         } else
00360                 *exists = ISC_FALSE;
00361         dns_rdatasetiter_destroy(&iter);
00362 
00363  cleanup_node:
00364         dns_db_detachnode(db, &node);
00365         return (result);
00366 }
00367 
00368 static isc_boolean_t
00369 match_nsec3param(const dns_rdata_nsec3_t *nsec3,
00370                  const dns_rdata_nsec3param_t *nsec3param)
00371 {
00372         if (nsec3->hash == nsec3param->hash &&
00373             nsec3->iterations == nsec3param->iterations &&
00374             nsec3->salt_length == nsec3param->salt_length &&
00375             !memcmp(nsec3->salt, nsec3param->salt, nsec3->salt_length))
00376                 return (ISC_TRUE);
00377         return (ISC_FALSE);
00378 }
00379 
00380 /*%
00381  * Delete NSEC3 records at "name" which match "param", recording the
00382  * change in "diff".
00383  */
00384 static isc_result_t
00385 delete(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
00386        const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
00387 {
00388         dns_dbnode_t *node = NULL ;
00389         dns_difftuple_t *tuple = NULL;
00390         dns_rdata_nsec3_t nsec3;
00391         dns_rdataset_t rdataset;
00392         isc_result_t result;
00393 
00394         result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
00395         if (result == ISC_R_NOTFOUND)
00396                 return (ISC_R_SUCCESS);
00397         if (result != ISC_R_SUCCESS)
00398                 return (result);
00399 
00400         dns_rdataset_init(&rdataset);
00401         result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3, 0,
00402                                      (isc_stdtime_t) 0, &rdataset, NULL);
00403 
00404         if (result == ISC_R_NOTFOUND) {
00405                 result = ISC_R_SUCCESS;
00406                 goto cleanup_node;
00407         }
00408         if (result != ISC_R_SUCCESS)
00409                 goto cleanup_node;
00410 
00411         for (result = dns_rdataset_first(&rdataset);
00412              result == ISC_R_SUCCESS;
00413              result = dns_rdataset_next(&rdataset))
00414         {
00415                 dns_rdata_t rdata = DNS_RDATA_INIT;
00416                 dns_rdataset_current(&rdataset, &rdata);
00417                 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
00418 
00419                 if (!match_nsec3param(&nsec3, nsec3param))
00420                         continue;
00421 
00422                 result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
00423                                               rdataset.ttl, &rdata, &tuple);
00424                 if (result != ISC_R_SUCCESS)
00425                         goto failure;
00426                 result = do_one_tuple(&tuple, db, version, diff);
00427                 if (result != ISC_R_SUCCESS)
00428                         goto failure;
00429         }
00430         if (result != ISC_R_NOMORE)
00431                 goto failure;
00432         result = ISC_R_SUCCESS;
00433 
00434  failure:
00435         dns_rdataset_disassociate(&rdataset);
00436  cleanup_node:
00437         dns_db_detachnode(db, &node);
00438 
00439         return (result);
00440 }
00441 
00442 static isc_boolean_t
00443 better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) {
00444         dns_rdataset_t rdataset;
00445         isc_result_t result;
00446 
00447         if (REMOVE(param->data[1]))
00448                 return (ISC_TRUE);
00449 
00450         dns_rdataset_init(&rdataset);
00451         dns_rdataset_clone(nsec3paramset, &rdataset);
00452         for (result = dns_rdataset_first(&rdataset);
00453              result == ISC_R_SUCCESS;
00454              result = dns_rdataset_next(&rdataset)) {
00455                 dns_rdata_t rdata =  DNS_RDATA_INIT;
00456                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
00457 
00458                 if (rdataset.type != dns_rdatatype_nsec3param) {
00459                         dns_rdata_t tmprdata =  DNS_RDATA_INIT;
00460                         dns_rdataset_current(&rdataset, &tmprdata);
00461                         if (!dns_nsec3param_fromprivate(&tmprdata, &rdata,
00462                                                         buf, sizeof(buf)))
00463                                 continue;
00464                 } else
00465                         dns_rdataset_current(&rdataset, &rdata);
00466 
00467                 if (rdata.length != param->length)
00468                         continue;
00469                 if (rdata.data[0] != param->data[0] ||
00470                     REMOVE(rdata.data[1]) ||
00471                     rdata.data[2] != param->data[2] ||
00472                     rdata.data[3] != param->data[3] ||
00473                     rdata.data[4] != param->data[4] ||
00474                     memcmp(&rdata.data[5], &param->data[5], param->data[4]))
00475                         continue;
00476                 if (CREATE(rdata.data[1]) && !CREATE(param->data[1])) {
00477                         dns_rdataset_disassociate(&rdataset);
00478                         return (ISC_TRUE);
00479                 }
00480         }
00481         dns_rdataset_disassociate(&rdataset);
00482         return (ISC_FALSE);
00483 }
00484 
00485 static isc_result_t
00486 find_nsec3(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *rdataset,
00487            const dns_rdata_nsec3param_t *nsec3param)
00488 {
00489         isc_result_t result;
00490         for (result = dns_rdataset_first(rdataset);
00491              result == ISC_R_SUCCESS;
00492              result = dns_rdataset_next(rdataset)) {
00493                 dns_rdata_t rdata = DNS_RDATA_INIT;
00494 
00495                 dns_rdataset_current(rdataset, &rdata);
00496                 CHECK(dns_rdata_tostruct(&rdata, nsec3, NULL));
00497                 dns_rdata_reset(&rdata);
00498                 if (match_nsec3param(nsec3, nsec3param))
00499                         break;
00500         }
00501  failure:
00502         return (result);
00503 }
00504 
00505 isc_result_t
00506 dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
00507                    dns_name_t *name, const dns_rdata_nsec3param_t *nsec3param,
00508                    dns_ttl_t nsecttl, isc_boolean_t unsecure, dns_diff_t *diff)
00509 {
00510         dns_dbiterator_t *dbit = NULL;
00511         dns_dbnode_t *node = NULL;
00512         dns_dbnode_t *newnode = NULL;
00513         dns_difftuple_t *tuple = NULL;
00514         dns_fixedname_t fixed;
00515         dns_fixedname_t fprev;
00516         dns_hash_t hash;
00517         dns_name_t *hashname;
00518         dns_name_t *origin;
00519         dns_name_t *prev;
00520         dns_name_t empty;
00521         dns_rdata_nsec3_t nsec3;
00522         dns_rdata_t rdata = DNS_RDATA_INIT;
00523         dns_rdataset_t rdataset;
00524         int pass;
00525         isc_boolean_t exists = ISC_FALSE;
00526         isc_boolean_t maybe_remove_unsecure = ISC_FALSE;
00527         isc_uint8_t flags;
00528         isc_buffer_t buffer;
00529         isc_result_t result;
00530         unsigned char *old_next;
00531         unsigned char *salt;
00532         unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
00533         unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
00534         unsigned int iterations;
00535         unsigned int labels;
00536         size_t next_length;
00537         unsigned int old_length;
00538         unsigned int salt_length;
00539 
00540         dns_fixedname_init(&fixed);
00541         hashname = dns_fixedname_name(&fixed);
00542         dns_fixedname_init(&fprev);
00543         prev = dns_fixedname_name(&fprev);
00544 
00545         dns_rdataset_init(&rdataset);
00546 
00547         origin = dns_db_origin(db);
00548 
00549         /*
00550          * Chain parameters.
00551          */
00552         hash = nsec3param->hash;
00553         iterations = nsec3param->iterations;
00554         salt_length = nsec3param->salt_length;
00555         salt = nsec3param->salt;
00556 
00557         /*
00558          * Default flags for a new chain.
00559          */
00560         flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
00561 
00562         /*
00563          * If this is the first NSEC3 in the chain nexthash will
00564          * remain pointing to itself.
00565          */
00566         next_length = sizeof(nexthash);
00567         CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
00568                                  name, origin, hash, iterations,
00569                                  salt, salt_length));
00570         INSIST(next_length <= sizeof(nexthash));
00571 
00572         /*
00573          * Create the node if it doesn't exist and hold
00574          * a reference to it until we have added the NSEC3.
00575          */
00576         CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
00577 
00578         /*
00579          * Seek the iterator to the 'newnode'.
00580          */
00581         CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
00582         CHECK(dns_dbiterator_seek(dbit, hashname));
00583         CHECK(dns_dbiterator_pause(dbit));
00584         result = dns_db_findrdataset(db, newnode, version, dns_rdatatype_nsec3,
00585                                      0, (isc_stdtime_t) 0, &rdataset, NULL);
00586         /*
00587          * If we updating a existing NSEC3 then find its
00588          * next field.
00589          */
00590         if (result == ISC_R_SUCCESS) {
00591                 result = find_nsec3(&nsec3, &rdataset, nsec3param);
00592                 if (result == ISC_R_SUCCESS) {
00593                         if (!CREATE(nsec3param->flags))
00594                                 flags = nsec3.flags;
00595                         next_length = nsec3.next_length;
00596                         INSIST(next_length <= sizeof(nexthash));
00597                         memmove(nexthash, nsec3.next, next_length);
00598                         dns_rdataset_disassociate(&rdataset);
00599                         /*
00600                          * If the NSEC3 is not for a unsecure delegation then
00601                          * we are just updating it.  If it is for a unsecure
00602                          * delegation then we need find out if we need to
00603                          * remove the NSEC3 record or not by examining the
00604                          * previous NSEC3 record.
00605                          */
00606                         if (!unsecure)
00607                                 goto addnsec3;
00608                         else if (CREATE(nsec3param->flags) && OPTOUT(flags)) {
00609                                 result = dns_nsec3_delnsec3(db, version, name,
00610                                                             nsec3param, diff);
00611                                 goto failure;
00612                         } else
00613                                 maybe_remove_unsecure = ISC_TRUE;
00614                 } else {
00615                         dns_rdataset_disassociate(&rdataset);
00616                         if (result != ISC_R_NOMORE)
00617                                 goto failure;
00618                 }
00619         }
00620 
00621         /*
00622          * Find the previous NSEC3 (if any) and update it if required.
00623          */
00624         pass = 0;
00625         do {
00626                 result = dns_dbiterator_prev(dbit);
00627                 if (result == ISC_R_NOMORE) {
00628                         pass++;
00629                         CHECK(dns_dbiterator_last(dbit));
00630                 }
00631                 CHECK(dns_dbiterator_current(dbit, &node, prev));
00632                 CHECK(dns_dbiterator_pause(dbit));
00633                 result = dns_db_findrdataset(db, node, version,
00634                                              dns_rdatatype_nsec3, 0,
00635                                              (isc_stdtime_t) 0, &rdataset,
00636                                              NULL);
00637                 dns_db_detachnode(db, &node);
00638                 if (result != ISC_R_SUCCESS)
00639                         continue;
00640 
00641                 result = find_nsec3(&nsec3, &rdataset, nsec3param);
00642                 if (result == ISC_R_NOMORE) {
00643                         dns_rdataset_disassociate(&rdataset);
00644                         continue;
00645                 }
00646                 if (result != ISC_R_SUCCESS)
00647                         goto failure;
00648 
00649                 if (maybe_remove_unsecure) {
00650                         dns_rdataset_disassociate(&rdataset);
00651                         /*
00652                          * If we have OPTOUT set in the previous NSEC3 record
00653                          * we actually need to delete the NSEC3 record.
00654                          * Otherwise we just need to replace the NSEC3 record.
00655                          */
00656                         if (OPTOUT(nsec3.flags)) {
00657                                 result = dns_nsec3_delnsec3(db, version, name,
00658                                                             nsec3param, diff);
00659                                 goto failure;
00660                         }
00661                         goto addnsec3;
00662                 } else {
00663                         /*
00664                          * Is this is a unsecure delegation we are adding?
00665                          * If so no change is required.
00666                          */
00667                         if (OPTOUT(nsec3.flags) && unsecure) {
00668                                 dns_rdataset_disassociate(&rdataset);
00669                                 goto failure;
00670                         }
00671                 }
00672 
00673                 old_next = nsec3.next;
00674                 old_length = nsec3.next_length;
00675 
00676                 /*
00677                  * Delete the old previous NSEC3.
00678                  */
00679                 CHECK(delete(db, version, prev, nsec3param, diff));
00680 
00681                 /*
00682                  * Fixup the previous NSEC3.
00683                  */
00684                 nsec3.next = nexthash;
00685                 nsec3.next_length = (unsigned char)next_length;
00686                 isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
00687                 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
00688                                            dns_rdatatype_nsec3, &nsec3,
00689                                            &buffer));
00690                 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
00691                                            rdataset.ttl, &rdata, &tuple));
00692                 CHECK(do_one_tuple(&tuple, db, version, diff));
00693                 INSIST(old_length <= sizeof(nexthash));
00694                 memmove(nexthash, old_next, old_length);
00695                 if (!CREATE(nsec3param->flags))
00696                         flags = nsec3.flags;
00697                 dns_rdata_reset(&rdata);
00698                 dns_rdataset_disassociate(&rdataset);
00699                 break;
00700         } while (pass < 2);
00701 
00702  addnsec3:
00703         /*
00704          * Create the NSEC3 RDATA.
00705          */
00706         CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
00707         CHECK(dns_nsec3_buildrdata(db, version, node, hash, flags, iterations,
00708                                    salt, salt_length, nexthash, next_length,
00709                                    nsec3buf, &rdata));
00710         dns_db_detachnode(db, &node);
00711 
00712         /*
00713          * Delete the old NSEC3 and record the change.
00714          */
00715         CHECK(delete(db, version, hashname, nsec3param, diff));
00716         /*
00717          * Add the new NSEC3 and record the change.
00718          */
00719         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
00720                                    hashname, nsecttl, &rdata, &tuple));
00721         CHECK(do_one_tuple(&tuple, db, version, diff));
00722         INSIST(tuple == NULL);
00723         dns_rdata_reset(&rdata);
00724         dns_db_detachnode(db, &newnode);
00725 
00726         /*
00727          * Add missing NSEC3 records for empty nodes
00728          */
00729         dns_name_init(&empty, NULL);
00730         dns_name_clone(name, &empty);
00731         do {
00732                 labels = dns_name_countlabels(&empty) - 1;
00733                 if (labels <= dns_name_countlabels(origin))
00734                         break;
00735                 dns_name_getlabelsequence(&empty, 1, labels, &empty);
00736                 CHECK(name_exists(db, version, &empty, &exists));
00737                 if (exists)
00738                         break;
00739                 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
00740                                          &empty, origin, hash, iterations,
00741                                          salt, salt_length));
00742 
00743                 /*
00744                  * Create the node if it doesn't exist and hold
00745                  * a reference to it until we have added the NSEC3
00746                  * or we discover we don't need to add make a change.
00747                  */
00748                 CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
00749                 result = dns_db_findrdataset(db, newnode, version,
00750                                              dns_rdatatype_nsec3, 0,
00751                                              (isc_stdtime_t) 0, &rdataset,
00752                                              NULL);
00753                 if (result == ISC_R_SUCCESS) {
00754                         result = find_nsec3(&nsec3, &rdataset, nsec3param);
00755                         dns_rdataset_disassociate(&rdataset);
00756                         if (result == ISC_R_SUCCESS) {
00757                                 dns_db_detachnode(db, &newnode);
00758                                 break;
00759                         }
00760                         if (result != ISC_R_NOMORE)
00761                                 goto failure;
00762                 }
00763 
00764                 /*
00765                  * Find the previous NSEC3 and update it.
00766                  */
00767                 CHECK(dns_dbiterator_seek(dbit, hashname));
00768                 pass = 0;
00769                 do {
00770                         result = dns_dbiterator_prev(dbit);
00771                         if (result == ISC_R_NOMORE) {
00772                                 pass++;
00773                                 CHECK(dns_dbiterator_last(dbit));
00774                         }
00775                         CHECK(dns_dbiterator_current(dbit, &node, prev));
00776                         CHECK(dns_dbiterator_pause(dbit));
00777                         result = dns_db_findrdataset(db, node, version,
00778                                                      dns_rdatatype_nsec3, 0,
00779                                                      (isc_stdtime_t) 0,
00780                                                      &rdataset, NULL);
00781                         dns_db_detachnode(db, &node);
00782                         if (result != ISC_R_SUCCESS)
00783                                 continue;
00784                         result = find_nsec3(&nsec3, &rdataset, nsec3param);
00785                         if (result == ISC_R_NOMORE) {
00786                                 dns_rdataset_disassociate(&rdataset);
00787                                 continue;
00788                         }
00789                         if (result != ISC_R_SUCCESS)
00790                                 goto failure;
00791 
00792                         old_next = nsec3.next;
00793                         old_length = nsec3.next_length;
00794 
00795                         /*
00796                          * Delete the old previous NSEC3.
00797                          */
00798                         CHECK(delete(db, version, prev, nsec3param, diff));
00799 
00800                         /*
00801                          * Fixup the previous NSEC3.
00802                          */
00803                         nsec3.next = nexthash;
00804                         nsec3.next_length = (unsigned char)next_length;
00805                         isc_buffer_init(&buffer, nsec3buf,
00806                                         sizeof(nsec3buf));
00807                         CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
00808                                                    dns_rdatatype_nsec3, &nsec3,
00809                                                    &buffer));
00810                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
00811                                                    prev, rdataset.ttl, &rdata,
00812                                                    &tuple));
00813                         CHECK(do_one_tuple(&tuple, db, version, diff));
00814                         INSIST(old_length <= sizeof(nexthash));
00815                         memmove(nexthash, old_next, old_length);
00816                         if (!CREATE(nsec3param->flags))
00817                                 flags = nsec3.flags;
00818                         dns_rdata_reset(&rdata);
00819                         dns_rdataset_disassociate(&rdataset);
00820                         break;
00821                 } while (pass < 2);
00822 
00823                 INSIST(pass < 2);
00824 
00825                 /*
00826                  * Create the NSEC3 RDATA for the empty node.
00827                  */
00828                 CHECK(dns_nsec3_buildrdata(db, version, NULL, hash, flags,
00829                                            iterations, salt, salt_length,
00830                                            nexthash, next_length, nsec3buf,
00831                                            &rdata));
00832                 /*
00833                  * Delete the old NSEC3 and record the change.
00834                  */
00835                 CHECK(delete(db, version, hashname, nsec3param, diff));
00836 
00837                 /*
00838                  * Add the new NSEC3 and record the change.
00839                  */
00840                 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
00841                                            hashname, nsecttl, &rdata, &tuple));
00842                 CHECK(do_one_tuple(&tuple, db, version, diff));
00843                 INSIST(tuple == NULL);
00844                 dns_rdata_reset(&rdata);
00845                 dns_db_detachnode(db, &newnode);
00846         } while (1);
00847 
00848         /* result cannot be ISC_R_NOMORE here */
00849         INSIST(result != ISC_R_NOMORE);
00850 
00851  failure:
00852         if (dbit != NULL)
00853                 dns_dbiterator_destroy(&dbit);
00854         if (dns_rdataset_isassociated(&rdataset))
00855                 dns_rdataset_disassociate(&rdataset);
00856         if (node != NULL)
00857                 dns_db_detachnode(db, &node);
00858         if (newnode != NULL)
00859                 dns_db_detachnode(db, &newnode);
00860         return (result);
00861 }
00862 
00863 /*%
00864  * Add NSEC3 records for "name", recording the change in "diff".
00865  * The existing NSEC3 records are removed.
00866  */
00867 isc_result_t
00868 dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
00869                     dns_name_t *name, dns_ttl_t nsecttl,
00870                     isc_boolean_t unsecure, dns_diff_t *diff)
00871 {
00872         dns_dbnode_t *node = NULL;
00873         dns_rdata_nsec3param_t nsec3param;
00874         dns_rdataset_t rdataset;
00875         isc_result_t result;
00876 
00877         dns_rdataset_init(&rdataset);
00878 
00879         /*
00880          * Find the NSEC3 parameters for this zone.
00881          */
00882         result = dns_db_getoriginnode(db, &node);
00883         if (result != ISC_R_SUCCESS)
00884                 return (result);
00885 
00886         result = dns_db_findrdataset(db, node, version,
00887                                      dns_rdatatype_nsec3param, 0, 0,
00888                                      &rdataset, NULL);
00889         dns_db_detachnode(db, &node);
00890         if (result == ISC_R_NOTFOUND)
00891                 return (ISC_R_SUCCESS);
00892         if (result != ISC_R_SUCCESS)
00893                 return (result);
00894 
00895         /*
00896          * Update each active NSEC3 chain.
00897          */
00898         for (result = dns_rdataset_first(&rdataset);
00899              result == ISC_R_SUCCESS;
00900              result = dns_rdataset_next(&rdataset)) {
00901                 dns_rdata_t rdata = DNS_RDATA_INIT;
00902 
00903                 dns_rdataset_current(&rdataset, &rdata);
00904                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
00905 
00906                 if (nsec3param.flags != 0)
00907                         continue;
00908                 /*
00909                  * We have a active chain.  Update it.
00910                  */
00911                 CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
00912                                          nsecttl, unsecure, diff));
00913         }
00914         if (result == ISC_R_NOMORE)
00915                 result = ISC_R_SUCCESS;
00916 
00917  failure:
00918         if (dns_rdataset_isassociated(&rdataset))
00919                 dns_rdataset_disassociate(&rdataset);
00920         if (node != NULL)
00921                 dns_db_detachnode(db, &node);
00922 
00923         return (result);
00924 }
00925 
00926 isc_boolean_t
00927 dns_nsec3param_fromprivate(dns_rdata_t *src, dns_rdata_t *target,
00928                            unsigned char *buf, size_t buflen)
00929 {
00930         dns_decompress_t dctx;
00931         isc_result_t result;
00932         isc_buffer_t buf1;
00933         isc_buffer_t buf2;
00934 
00935         /*
00936          * Algorithm 0 (reserved by RFC 4034) is used to identify
00937          * NSEC3PARAM records from DNSKEY pointers.
00938          */
00939         if (src->length < 1 || src->data[0] != 0)
00940                 return (ISC_FALSE);
00941 
00942         isc_buffer_init(&buf1, src->data + 1, src->length - 1);
00943         isc_buffer_add(&buf1, src->length - 1);
00944         isc_buffer_setactive(&buf1, src->length - 1);
00945         isc_buffer_init(&buf2, buf, (unsigned int)buflen);
00946         dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
00947         result = dns_rdata_fromwire(target, src->rdclass,
00948                                     dns_rdatatype_nsec3param,
00949                                     &buf1, &dctx, 0, &buf2);
00950         dns_decompress_invalidate(&dctx);
00951 
00952         return (ISC_TF(result == ISC_R_SUCCESS));
00953 }
00954 
00955 void
00956 dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target,
00957                          dns_rdatatype_t privatetype,
00958                          unsigned char *buf, size_t buflen)
00959 {
00960         REQUIRE(buflen >= src->length + 1);
00961 
00962         REQUIRE(DNS_RDATA_INITIALIZED(target));
00963 
00964         memmove(buf + 1, src->data, src->length);
00965         buf[0] = 0;
00966         target->data = buf;
00967         target->length = src->length + 1;
00968         target->type = privatetype;
00969         target->rdclass = src->rdclass;
00970         target->flags = 0;
00971         ISC_LINK_INIT(target, link);
00972 }
00973 
00974 static isc_result_t
00975 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00976           const dns_rdata_t *rdata, isc_boolean_t *flag)
00977 {
00978         dns_rdataset_t rdataset;
00979         dns_dbnode_t *node = NULL;
00980         isc_result_t result;
00981 
00982         dns_rdataset_init(&rdataset);
00983         if (rdata->type == dns_rdatatype_nsec3)
00984                 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
00985         else
00986                 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
00987         result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
00988                                      (isc_stdtime_t) 0, &rdataset, NULL);
00989         if (result == ISC_R_NOTFOUND) {
00990                 *flag = ISC_FALSE;
00991                 result = ISC_R_SUCCESS;
00992                 goto failure;
00993         }
00994 
00995         for (result = dns_rdataset_first(&rdataset);
00996              result == ISC_R_SUCCESS;
00997              result = dns_rdataset_next(&rdataset)) {
00998                 dns_rdata_t myrdata = DNS_RDATA_INIT;
00999                 dns_rdataset_current(&rdataset, &myrdata);
01000                 if (!dns_rdata_casecompare(&myrdata, rdata))
01001                         break;
01002         }
01003         dns_rdataset_disassociate(&rdataset);
01004         if (result == ISC_R_SUCCESS) {
01005                 *flag = ISC_TRUE;
01006         } else if (result == ISC_R_NOMORE) {
01007                 *flag = ISC_FALSE;
01008                 result = ISC_R_SUCCESS;
01009         }
01010 
01011  failure:
01012         if (node != NULL)
01013                 dns_db_detachnode(db, &node);
01014         return (result);
01015 }
01016 
01017 isc_result_t
01018 dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
01019                             dns_zone_t *zone, isc_boolean_t nonsec,
01020                             dns_diff_t *diff)
01021 {
01022         dns_dbnode_t *node = NULL;
01023         dns_difftuple_t *tuple = NULL;
01024         dns_name_t next;
01025         dns_rdata_t rdata = DNS_RDATA_INIT;
01026         dns_rdataset_t rdataset;
01027         isc_boolean_t flag;
01028         isc_result_t result = ISC_R_SUCCESS;
01029         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE + 1];
01030         dns_name_t *origin = dns_zone_getorigin(zone);
01031         dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
01032 
01033         dns_name_init(&next, NULL);
01034         dns_rdataset_init(&rdataset);
01035 
01036         result = dns_db_getoriginnode(db, &node);
01037         if (result != ISC_R_SUCCESS)
01038                 return (result);
01039 
01040         /*
01041          * Cause all NSEC3 chains to be deleted.
01042          */
01043         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
01044                                      0, (isc_stdtime_t) 0, &rdataset, NULL);
01045         if (result == ISC_R_NOTFOUND)
01046                 goto try_private;
01047         if (result != ISC_R_SUCCESS)
01048                 goto failure;
01049 
01050         for (result = dns_rdataset_first(&rdataset);
01051              result == ISC_R_SUCCESS;
01052              result = dns_rdataset_next(&rdataset)) {
01053                 dns_rdata_t private = DNS_RDATA_INIT;
01054 
01055                 dns_rdataset_current(&rdataset, &rdata);
01056 
01057                 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin,
01058                                            rdataset.ttl, &rdata, &tuple));
01059                 CHECK(do_one_tuple(&tuple, db, ver, diff));
01060                 INSIST(tuple == NULL);
01061 
01062                 dns_nsec3param_toprivate(&rdata, &private, privatetype,
01063                                          buf, sizeof(buf));
01064                 buf[2] = DNS_NSEC3FLAG_REMOVE;
01065                 if (nonsec)
01066                         buf[2] |= DNS_NSEC3FLAG_NONSEC;
01067 
01068                 CHECK(rr_exists(db, ver, origin, &private, &flag));
01069 
01070                 if (!flag) {
01071                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
01072                                                    origin, 0, &private,
01073                                                    &tuple));
01074                         CHECK(do_one_tuple(&tuple, db, ver, diff));
01075                         INSIST(tuple == NULL);
01076                 }
01077                 dns_rdata_reset(&rdata);
01078         }
01079         if (result != ISC_R_NOMORE)
01080                 goto failure;
01081 
01082         dns_rdataset_disassociate(&rdataset);
01083 
01084  try_private:
01085         if (privatetype == 0)
01086                 goto success;
01087         result = dns_db_findrdataset(db, node, ver, privatetype, 0,
01088                                      (isc_stdtime_t) 0, &rdataset, NULL);
01089         if (result == ISC_R_NOTFOUND)
01090                 goto success;
01091         if (result != ISC_R_SUCCESS)
01092                 goto failure;
01093 
01094         for (result = dns_rdataset_first(&rdataset);
01095              result == ISC_R_SUCCESS;
01096              result = dns_rdataset_next(&rdataset)) {
01097                 dns_rdata_reset(&rdata);
01098                 dns_rdataset_current(&rdataset, &rdata);
01099                 INSIST(rdata.length <= sizeof(buf));
01100                 memmove(buf, rdata.data, rdata.length);
01101 
01102                 /*
01103                  * Private NSEC3 record length >= 6.
01104                  * <0(1), hash(1), flags(1), iterations(2), saltlen(1)>
01105                  */
01106                 if (rdata.length < 6 || buf[0] != 0 ||
01107                     (buf[2] & DNS_NSEC3FLAG_REMOVE) != 0 ||
01108                     (nonsec && (buf[2] & DNS_NSEC3FLAG_NONSEC) != 0))
01109                         continue;
01110 
01111                 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin,
01112                                            0, &rdata, &tuple));
01113                 CHECK(do_one_tuple(&tuple, db, ver, diff));
01114                 INSIST(tuple == NULL);
01115 
01116                 rdata.data = buf;
01117                 buf[2] = DNS_NSEC3FLAG_REMOVE;
01118                 if (nonsec)
01119                         buf[2] |= DNS_NSEC3FLAG_NONSEC;
01120 
01121                 CHECK(rr_exists(db, ver, origin, &rdata, &flag));
01122 
01123                 if (!flag) {
01124                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
01125                                                    origin, 0, &rdata, &tuple));
01126                         CHECK(do_one_tuple(&tuple, db, ver, diff));
01127                         INSIST(tuple == NULL);
01128                 }
01129         }
01130         if (result != ISC_R_NOMORE)
01131                 goto failure;
01132  success:
01133         result = ISC_R_SUCCESS;
01134 
01135  failure:
01136         if (dns_rdataset_isassociated(&rdataset))
01137                 dns_rdataset_disassociate(&rdataset);
01138         dns_db_detachnode(db, &node);
01139         return (result);
01140 }
01141 
01142 isc_result_t
01143 dns_nsec3_addnsec3sx(dns_db_t *db, dns_dbversion_t *version,
01144                      dns_name_t *name, dns_ttl_t nsecttl,
01145                      isc_boolean_t unsecure, dns_rdatatype_t type,
01146                      dns_diff_t *diff)
01147 {
01148         dns_dbnode_t *node = NULL;
01149         dns_rdata_nsec3param_t nsec3param;
01150         dns_rdataset_t rdataset;
01151         dns_rdataset_t prdataset;
01152         isc_result_t result;
01153 
01154         dns_rdataset_init(&rdataset);
01155         dns_rdataset_init(&prdataset);
01156 
01157         /*
01158          * Find the NSEC3 parameters for this zone.
01159          */
01160         result = dns_db_getoriginnode(db, &node);
01161         if (result != ISC_R_SUCCESS)
01162                 return (result);
01163 
01164         result = dns_db_findrdataset(db, node, version, type, 0, 0,
01165                                      &prdataset, NULL);
01166         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
01167                 goto failure;
01168 
01169         result = dns_db_findrdataset(db, node, version,
01170                                      dns_rdatatype_nsec3param, 0, 0,
01171                                      &rdataset, NULL);
01172         if (result == ISC_R_NOTFOUND)
01173                 goto try_private;
01174         if (result != ISC_R_SUCCESS)
01175                 goto failure;
01176 
01177         /*
01178          * Update each active NSEC3 chain.
01179          */
01180         for (result = dns_rdataset_first(&rdataset);
01181              result == ISC_R_SUCCESS;
01182              result = dns_rdataset_next(&rdataset)) {
01183                 dns_rdata_t rdata = DNS_RDATA_INIT;
01184 
01185                 dns_rdataset_current(&rdataset, &rdata);
01186                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
01187 
01188                 if (nsec3param.flags != 0)
01189                         continue;
01190 
01191                 /*
01192                  * We have a active chain.  Update it.
01193                  */
01194                 CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
01195                                          nsecttl, unsecure, diff));
01196         }
01197         if (result != ISC_R_NOMORE)
01198                 goto failure;
01199 
01200         dns_rdataset_disassociate(&rdataset);
01201 
01202  try_private:
01203         if (!dns_rdataset_isassociated(&prdataset))
01204                 goto success;
01205         /*
01206          * Update each active NSEC3 chain.
01207          */
01208         for (result = dns_rdataset_first(&prdataset);
01209              result == ISC_R_SUCCESS;
01210              result = dns_rdataset_next(&prdataset)) {
01211                 dns_rdata_t rdata1 = DNS_RDATA_INIT;
01212                 dns_rdata_t rdata2 = DNS_RDATA_INIT;
01213                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
01214 
01215                 dns_rdataset_current(&prdataset, &rdata1);
01216                 if (!dns_nsec3param_fromprivate(&rdata1, &rdata2,
01217                                                 buf, sizeof(buf)))
01218                         continue;
01219                 CHECK(dns_rdata_tostruct(&rdata2, &nsec3param, NULL));
01220 
01221                 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
01222                         continue;
01223                 if (better_param(&prdataset, &rdata2))
01224                         continue;
01225 
01226                 /*
01227                  * We have a active chain.  Update it.
01228                  */
01229                 CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
01230                                          nsecttl, unsecure, diff));
01231         }
01232         if (result == ISC_R_NOMORE)
01233  success:
01234                 result = ISC_R_SUCCESS;
01235  failure:
01236         if (dns_rdataset_isassociated(&rdataset))
01237                 dns_rdataset_disassociate(&rdataset);
01238         if (dns_rdataset_isassociated(&prdataset))
01239                 dns_rdataset_disassociate(&prdataset);
01240         if (node != NULL)
01241                 dns_db_detachnode(db, &node);
01242 
01243         return (result);
01244 }
01245 
01246 /*%
01247  * Determine whether any NSEC3 records that were associated with
01248  * 'name' should be deleted or if they should continue to exist.
01249  * ISC_TRUE indicates they should be deleted.
01250  * ISC_FALSE indicates they should be retained.
01251  */
01252 static isc_result_t
01253 deleteit(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
01254          isc_boolean_t *yesno)
01255 {
01256         isc_result_t result;
01257         dns_fixedname_t foundname;
01258         dns_fixedname_init(&foundname);
01259 
01260         result = dns_db_find(db, name, ver, dns_rdatatype_any,
01261                              DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
01262                              (isc_stdtime_t) 0, NULL,
01263                              dns_fixedname_name(&foundname),
01264                              NULL, NULL);
01265         if (result == DNS_R_EMPTYNAME || result == ISC_R_SUCCESS ||
01266             result ==  DNS_R_ZONECUT) {
01267                 *yesno = ISC_FALSE;
01268                 return (ISC_R_SUCCESS);
01269         }
01270         if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
01271             result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) {
01272                 *yesno = ISC_TRUE;
01273                 return (ISC_R_SUCCESS);
01274         }
01275         /*
01276          * Silence compiler.
01277          */
01278         *yesno = ISC_TRUE;
01279         return (result);
01280 }
01281 
01282 isc_result_t
01283 dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
01284                    const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
01285 {
01286         dns_dbiterator_t *dbit = NULL;
01287         dns_dbnode_t *node = NULL;
01288         dns_difftuple_t *tuple = NULL;
01289         dns_fixedname_t fixed;
01290         dns_fixedname_t fprev;
01291         dns_hash_t hash;
01292         dns_name_t *hashname;
01293         dns_name_t *origin;
01294         dns_name_t *prev;
01295         dns_name_t empty;
01296         dns_rdata_nsec3_t nsec3;
01297         dns_rdata_t rdata = DNS_RDATA_INIT;
01298         dns_rdataset_t rdataset;
01299         int pass;
01300         isc_boolean_t yesno;
01301         isc_buffer_t buffer;
01302         isc_result_t result;
01303         unsigned char *salt;
01304         unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
01305         unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
01306         unsigned int iterations;
01307         unsigned int labels;
01308         size_t next_length;
01309         unsigned int salt_length;
01310 
01311         dns_fixedname_init(&fixed);
01312         hashname = dns_fixedname_name(&fixed);
01313         dns_fixedname_init(&fprev);
01314         prev = dns_fixedname_name(&fprev);
01315 
01316         dns_rdataset_init(&rdataset);
01317 
01318         origin = dns_db_origin(db);
01319 
01320         /*
01321          * Chain parameters.
01322          */
01323         hash = nsec3param->hash;
01324         iterations = nsec3param->iterations;
01325         salt_length = nsec3param->salt_length;
01326         salt = nsec3param->salt;
01327 
01328         /*
01329          * If this is the first NSEC3 in the chain nexthash will
01330          * remain pointing to itself.
01331          */
01332         next_length = sizeof(nexthash);
01333         CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
01334                                  name, origin, hash, iterations,
01335                                  salt, salt_length));
01336 
01337         CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
01338 
01339         result = dns_dbiterator_seek(dbit, hashname);
01340         if (result == ISC_R_NOTFOUND)
01341                 goto success;
01342         if (result != ISC_R_SUCCESS)
01343                 goto failure;
01344 
01345         CHECK(dns_dbiterator_current(dbit, &node, NULL));
01346         CHECK(dns_dbiterator_pause(dbit));
01347         result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3,
01348                                      0, (isc_stdtime_t) 0, &rdataset, NULL);
01349         dns_db_detachnode(db, &node);
01350         if (result == ISC_R_NOTFOUND)
01351                 goto success;
01352         if (result != ISC_R_SUCCESS)
01353                 goto failure;
01354 
01355         /*
01356          * If we find a existing NSEC3 for this chain then save the
01357          * next field.
01358          */
01359         result = find_nsec3(&nsec3, &rdataset, nsec3param);
01360         if (result == ISC_R_SUCCESS) {
01361                 next_length = nsec3.next_length;
01362                 INSIST(next_length <= sizeof(nexthash));
01363                 memmove(nexthash, nsec3.next, next_length);
01364         }
01365         dns_rdataset_disassociate(&rdataset);
01366         if (result == ISC_R_NOMORE)
01367                 goto success;
01368         if (result != ISC_R_SUCCESS)
01369                 goto failure;
01370 
01371         /*
01372          * Find the previous NSEC3 and update it.
01373          */
01374         pass = 0;
01375         do {
01376                 result = dns_dbiterator_prev(dbit);
01377                 if (result == ISC_R_NOMORE) {
01378                         pass++;
01379                         CHECK(dns_dbiterator_last(dbit));
01380                 }
01381                 CHECK(dns_dbiterator_current(dbit, &node, prev));
01382                 CHECK(dns_dbiterator_pause(dbit));
01383                 result = dns_db_findrdataset(db, node, version,
01384                                              dns_rdatatype_nsec3, 0,
01385                                              (isc_stdtime_t) 0, &rdataset,
01386                                              NULL);
01387                 dns_db_detachnode(db, &node);
01388                 if (result != ISC_R_SUCCESS)
01389                         continue;
01390                 result = find_nsec3(&nsec3, &rdataset, nsec3param);
01391                 if (result == ISC_R_NOMORE) {
01392                         dns_rdataset_disassociate(&rdataset);
01393                         continue;
01394                 }
01395                 if (result != ISC_R_SUCCESS)
01396                         goto failure;
01397 
01398                 /*
01399                  * Delete the old previous NSEC3.
01400                  */
01401                 CHECK(delete(db, version, prev, nsec3param, diff));
01402 
01403                 /*
01404                  * Fixup the previous NSEC3.
01405                  */
01406                 nsec3.next = nexthash;
01407                 nsec3.next_length = (unsigned char)next_length;
01408                 if (CREATE(nsec3param->flags))
01409                         nsec3.flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
01410                 isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
01411                 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
01412                                            dns_rdatatype_nsec3, &nsec3,
01413                                            &buffer));
01414                 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
01415                                            rdataset.ttl, &rdata, &tuple));
01416                 CHECK(do_one_tuple(&tuple, db, version, diff));
01417                 dns_rdata_reset(&rdata);
01418                 dns_rdataset_disassociate(&rdataset);
01419                 break;
01420         } while (pass < 2);
01421 
01422         /*
01423          * Delete the old NSEC3 and record the change.
01424          */
01425         CHECK(delete(db, version, hashname, nsec3param, diff));
01426 
01427         /*
01428          *  Delete NSEC3 records for now non active nodes.
01429          */
01430         dns_name_init(&empty, NULL);
01431         dns_name_clone(name, &empty);
01432         do {
01433                 labels = dns_name_countlabels(&empty) - 1;
01434                 if (labels <= dns_name_countlabels(origin))
01435                         break;
01436                 dns_name_getlabelsequence(&empty, 1, labels, &empty);
01437                 CHECK(deleteit(db, version, &empty, &yesno));
01438                 if (!yesno)
01439                         break;
01440 
01441                 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
01442                                          &empty, origin, hash, iterations,
01443                                          salt, salt_length));
01444                 result = dns_dbiterator_seek(dbit, hashname);
01445                 if (result == ISC_R_NOTFOUND)
01446                         goto success;
01447                 if (result != ISC_R_SUCCESS)
01448                         goto failure;
01449 
01450                 CHECK(dns_dbiterator_current(dbit, &node, NULL));
01451                 CHECK(dns_dbiterator_pause(dbit));
01452                 result = dns_db_findrdataset(db, node, version,
01453                                              dns_rdatatype_nsec3, 0,
01454                                              (isc_stdtime_t) 0, &rdataset,
01455                                              NULL);
01456                 dns_db_detachnode(db, &node);
01457                 if (result == ISC_R_NOTFOUND)
01458                         goto success;
01459                 if (result != ISC_R_SUCCESS)
01460                         goto failure;
01461 
01462                 result = find_nsec3(&nsec3, &rdataset, nsec3param);
01463                 if (result == ISC_R_SUCCESS) {
01464                         next_length = nsec3.next_length;
01465                         INSIST(next_length <= sizeof(nexthash));
01466                         memmove(nexthash, nsec3.next, next_length);
01467                 }
01468                 dns_rdataset_disassociate(&rdataset);
01469                 if (result == ISC_R_NOMORE)
01470                         goto success;
01471                 if (result != ISC_R_SUCCESS)
01472                         goto failure;
01473 
01474                 pass = 0;
01475                 do {
01476                         result = dns_dbiterator_prev(dbit);
01477                         if (result == ISC_R_NOMORE) {
01478                                 pass++;
01479                                 CHECK(dns_dbiterator_last(dbit));
01480                         }
01481                         CHECK(dns_dbiterator_current(dbit, &node, prev));
01482                         CHECK(dns_dbiterator_pause(dbit));
01483                         result = dns_db_findrdataset(db, node, version,
01484                                                      dns_rdatatype_nsec3, 0,
01485                                                      (isc_stdtime_t) 0,
01486                                                      &rdataset, NULL);
01487                         dns_db_detachnode(db, &node);
01488                         if (result != ISC_R_SUCCESS)
01489                                 continue;
01490                         result = find_nsec3(&nsec3, &rdataset, nsec3param);
01491                         if (result == ISC_R_NOMORE) {
01492                                 dns_rdataset_disassociate(&rdataset);
01493                                 continue;
01494                         }
01495                         if (result != ISC_R_SUCCESS)
01496                                 goto failure;
01497 
01498                         /*
01499                          * Delete the old previous NSEC3.
01500                          */
01501                         CHECK(delete(db, version, prev, nsec3param, diff));
01502 
01503                         /*
01504                          * Fixup the previous NSEC3.
01505                          */
01506                         nsec3.next = nexthash;
01507                         nsec3.next_length = (unsigned char)next_length;
01508                         isc_buffer_init(&buffer, nsec3buf,
01509                                         sizeof(nsec3buf));
01510                         CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
01511                                                    dns_rdatatype_nsec3, &nsec3,
01512                                                    &buffer));
01513                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
01514                                                    prev, rdataset.ttl, &rdata,
01515                                                    &tuple));
01516                         CHECK(do_one_tuple(&tuple, db, version, diff));
01517                         dns_rdata_reset(&rdata);
01518                         dns_rdataset_disassociate(&rdataset);
01519                         break;
01520                 } while (pass < 2);
01521 
01522                 INSIST(pass < 2);
01523 
01524                 /*
01525                  * Delete the old NSEC3 and record the change.
01526                  */
01527                 CHECK(delete(db, version, hashname, nsec3param, diff));
01528         } while (1);
01529 
01530  success:
01531         result = ISC_R_SUCCESS;
01532 
01533  failure:
01534         if (dbit != NULL)
01535                 dns_dbiterator_destroy(&dbit);
01536         if (dns_rdataset_isassociated(&rdataset))
01537                 dns_rdataset_disassociate(&rdataset);
01538         if (node != NULL)
01539                 dns_db_detachnode(db, &node);
01540         return (result);
01541 }
01542 
01543 isc_result_t
01544 dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
01545                     dns_diff_t *diff)
01546 {
01547         return (dns_nsec3_delnsec3sx(db, version, name, 0, diff));
01548 }
01549 
01550 isc_result_t
01551 dns_nsec3_delnsec3sx(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
01552                      dns_rdatatype_t privatetype, dns_diff_t *diff)
01553 {
01554         dns_dbnode_t *node = NULL;
01555         dns_rdata_nsec3param_t nsec3param;
01556         dns_rdataset_t rdataset;
01557         isc_result_t result;
01558 
01559         dns_rdataset_init(&rdataset);
01560 
01561         /*
01562          * Find the NSEC3 parameters for this zone.
01563          */
01564         result = dns_db_getoriginnode(db, &node);
01565         if (result != ISC_R_SUCCESS)
01566                 return (result);
01567 
01568         result = dns_db_findrdataset(db, node, version,
01569                                      dns_rdatatype_nsec3param, 0, 0,
01570                                      &rdataset, NULL);
01571         if (result == ISC_R_NOTFOUND)
01572                 goto try_private;
01573         if (result != ISC_R_SUCCESS)
01574                 goto failure;
01575 
01576         /*
01577          * Update each active NSEC3 chain.
01578          */
01579         for (result = dns_rdataset_first(&rdataset);
01580              result == ISC_R_SUCCESS;
01581              result = dns_rdataset_next(&rdataset)) {
01582                 dns_rdata_t rdata = DNS_RDATA_INIT;
01583 
01584                 dns_rdataset_current(&rdataset, &rdata);
01585                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
01586 
01587                 if (nsec3param.flags != 0)
01588                         continue;
01589                 /*
01590                  * We have a active chain.  Update it.
01591                  */
01592                 CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
01593         }
01594         dns_rdataset_disassociate(&rdataset);
01595 
01596  try_private:
01597         if (privatetype == 0)
01598                 goto success;
01599         result = dns_db_findrdataset(db, node, version, privatetype, 0, 0,
01600                                      &rdataset, NULL);
01601         if (result == ISC_R_NOTFOUND)
01602                 goto success;
01603         if (result != ISC_R_SUCCESS)
01604                 goto failure;
01605 
01606         /*
01607          * Update each NSEC3 chain being built.
01608          */
01609         for (result = dns_rdataset_first(&rdataset);
01610              result == ISC_R_SUCCESS;
01611              result = dns_rdataset_next(&rdataset)) {
01612                 dns_rdata_t rdata1 = DNS_RDATA_INIT;
01613                 dns_rdata_t rdata2 = DNS_RDATA_INIT;
01614                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
01615 
01616                 dns_rdataset_current(&rdataset, &rdata1);
01617                 if (!dns_nsec3param_fromprivate(&rdata1,  &rdata2,
01618                                                 buf, sizeof(buf)))
01619                         continue;
01620                 CHECK(dns_rdata_tostruct(&rdata2, &nsec3param, NULL));
01621 
01622                 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
01623                         continue;
01624                 if (better_param(&rdataset, &rdata2))
01625                         continue;
01626 
01627                 /*
01628                  * We have a active chain.  Update it.
01629                  */
01630                 CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
01631         }
01632         if (result == ISC_R_NOMORE)
01633  success:
01634                 result = ISC_R_SUCCESS;
01635 
01636  failure:
01637         if (dns_rdataset_isassociated(&rdataset))
01638                 dns_rdataset_disassociate(&rdataset);
01639         if (node != NULL)
01640                 dns_db_detachnode(db, &node);
01641 
01642         return (result);
01643 }
01644 
01645 isc_result_t
01646 dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
01647                  isc_boolean_t complete, isc_boolean_t *answer)
01648 {
01649         return (dns_nsec3_activex(db, version, complete, 0, answer));
01650 }
01651 
01652 isc_result_t
01653 dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version,
01654                   isc_boolean_t complete, dns_rdatatype_t privatetype,
01655                   isc_boolean_t *answer)
01656 {
01657         dns_dbnode_t *node = NULL;
01658         dns_rdataset_t rdataset;
01659         dns_rdata_nsec3param_t nsec3param;
01660         isc_result_t result;
01661 
01662         REQUIRE(answer != NULL);
01663 
01664         dns_rdataset_init(&rdataset);
01665 
01666         result = dns_db_getoriginnode(db, &node);
01667         if (result != ISC_R_SUCCESS)
01668                 return (result);
01669 
01670         result = dns_db_findrdataset(db, node, version,
01671                                      dns_rdatatype_nsec3param, 0, 0,
01672                                      &rdataset, NULL);
01673 
01674         if (result == ISC_R_NOTFOUND)
01675                 goto try_private;
01676 
01677         if (result != ISC_R_SUCCESS) {
01678                 dns_db_detachnode(db, &node);
01679                 return (result);
01680         }
01681         for (result = dns_rdataset_first(&rdataset);
01682              result == ISC_R_SUCCESS;
01683              result = dns_rdataset_next(&rdataset)) {
01684                 dns_rdata_t rdata = DNS_RDATA_INIT;
01685 
01686                 dns_rdataset_current(&rdataset, &rdata);
01687                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
01688                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01689 
01690                 if (nsec3param.flags == 0)
01691                         break;
01692         }
01693         dns_rdataset_disassociate(&rdataset);
01694         if (result == ISC_R_SUCCESS) {
01695                 dns_db_detachnode(db, &node);
01696                 *answer = ISC_TRUE;
01697                 return (ISC_R_SUCCESS);
01698         }
01699         if (result == ISC_R_NOMORE)
01700                 *answer = ISC_FALSE;
01701 
01702  try_private:
01703         if (privatetype == 0 || complete) {
01704                 *answer = ISC_FALSE;
01705                 return (ISC_R_SUCCESS);
01706         }
01707         result = dns_db_findrdataset(db, node, version, privatetype, 0, 0,
01708                                      &rdataset, NULL);
01709 
01710         dns_db_detachnode(db, &node);
01711         if (result == ISC_R_NOTFOUND) {
01712                 *answer = ISC_FALSE;
01713                 return (ISC_R_SUCCESS);
01714         }
01715         if (result != ISC_R_SUCCESS)
01716                 return (result);
01717 
01718         for (result = dns_rdataset_first(&rdataset);
01719              result == ISC_R_SUCCESS;
01720              result = dns_rdataset_next(&rdataset)) {
01721                 dns_rdata_t rdata1 = DNS_RDATA_INIT;
01722                 dns_rdata_t rdata2 = DNS_RDATA_INIT;
01723                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
01724 
01725                 dns_rdataset_current(&rdataset, &rdata1);
01726                 if (!dns_nsec3param_fromprivate(&rdata1, &rdata2,
01727                                                 buf, sizeof(buf)))
01728                         continue;
01729                 result = dns_rdata_tostruct(&rdata2, &nsec3param, NULL);
01730                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01731 
01732                 if (!complete && CREATE(nsec3param.flags))
01733                         break;
01734         }
01735         dns_rdataset_disassociate(&rdataset);
01736         if (result == ISC_R_SUCCESS) {
01737                 *answer = ISC_TRUE;
01738                 result = ISC_R_SUCCESS;
01739         }
01740         if (result == ISC_R_NOMORE) {
01741                 *answer = ISC_FALSE;
01742                 result = ISC_R_SUCCESS;
01743         }
01744 
01745         return (result);
01746 }
01747 
01748 isc_result_t
01749 dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version,
01750                         isc_mem_t *mctx, unsigned int *iterationsp)
01751 {
01752         dns_dbnode_t *node = NULL;
01753         dns_rdataset_t rdataset;
01754         dst_key_t *key = NULL;
01755         isc_buffer_t buffer;
01756         isc_result_t result;
01757         unsigned int bits, minbits = 4096;
01758 
01759         result = dns_db_getoriginnode(db, &node);
01760         if (result != ISC_R_SUCCESS)
01761                 return (result);
01762 
01763         dns_rdataset_init(&rdataset);
01764         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
01765                                      0, 0, &rdataset, NULL);
01766         dns_db_detachnode(db, &node);
01767         if (result == ISC_R_NOTFOUND) {
01768                 *iterationsp = 0;
01769                 return (ISC_R_SUCCESS);
01770         }
01771         if (result != ISC_R_SUCCESS)
01772                 goto failure;
01773 
01774         for (result = dns_rdataset_first(&rdataset);
01775              result == ISC_R_SUCCESS;
01776              result = dns_rdataset_next(&rdataset)) {
01777                 dns_rdata_t rdata = DNS_RDATA_INIT;
01778 
01779                 dns_rdataset_current(&rdataset, &rdata);
01780                 isc_buffer_init(&buffer, rdata.data, rdata.length);
01781                 isc_buffer_add(&buffer, rdata.length);
01782                 CHECK(dst_key_fromdns(dns_db_origin(db), rdataset.rdclass,
01783                                       &buffer, mctx, &key));
01784                 bits = dst_key_size(key);
01785                 dst_key_free(&key);
01786                 if (minbits > bits)
01787                         minbits = bits;
01788         }
01789         if (result != ISC_R_NOMORE)
01790                 goto failure;
01791 
01792         if (minbits <= 1024)
01793                 *iterationsp = 150;
01794         else if (minbits <= 2048)
01795                 *iterationsp = 500;
01796         else
01797                 *iterationsp = 2500;
01798         result = ISC_R_SUCCESS;
01799 
01800  failure:
01801         if (dns_rdataset_isassociated(&rdataset))
01802                 dns_rdataset_disassociate(&rdataset);
01803         return (result);
01804 }
01805 
01806 isc_result_t
01807 dns_nsec3_noexistnodata(dns_rdatatype_t type, dns_name_t* name,
01808                         dns_name_t *nsec3name, dns_rdataset_t *nsec3set,
01809                         dns_name_t *zonename, isc_boolean_t *exists,
01810                         isc_boolean_t *data, isc_boolean_t *optout,
01811                         isc_boolean_t *unknown, isc_boolean_t *setclosest,
01812                         isc_boolean_t *setnearest, dns_name_t *closest,
01813                         dns_name_t *nearest, dns_nseclog_t logit, void *arg)
01814 {
01815         char namebuf[DNS_NAME_FORMATSIZE];
01816         dns_fixedname_t fzone;
01817         dns_fixedname_t qfixed;
01818         dns_label_t hashlabel;
01819         dns_name_t *qname;
01820         dns_name_t *zone;
01821         dns_rdata_nsec3_t nsec3;
01822         dns_rdata_t rdata = DNS_RDATA_INIT;
01823         int order;
01824         int scope;
01825         isc_boolean_t atparent;
01826         isc_boolean_t first;
01827         isc_boolean_t ns;
01828         isc_boolean_t soa;
01829         isc_buffer_t buffer;
01830         isc_result_t answer = ISC_R_IGNORE;
01831         isc_result_t result;
01832         unsigned char hash[NSEC3_MAX_HASH_LENGTH];
01833         unsigned char owner[NSEC3_MAX_HASH_LENGTH];
01834         unsigned int length;
01835         unsigned int qlabels;
01836         unsigned int zlabels;
01837 
01838         REQUIRE((exists == NULL && data == NULL) ||
01839                 (exists != NULL && data != NULL));
01840         REQUIRE(nsec3set != NULL && nsec3set->type == dns_rdatatype_nsec3);
01841         REQUIRE((setclosest == NULL && closest == NULL) ||
01842                 (setclosest != NULL && closest != NULL));
01843         REQUIRE((setnearest == NULL && nearest == NULL) ||
01844                 (setnearest != NULL && nearest != NULL));
01845 
01846         result = dns_rdataset_first(nsec3set);
01847         if (result != ISC_R_SUCCESS) {
01848                 (*logit)(arg, ISC_LOG_DEBUG(3), "failure processing NSEC3 set");
01849                 return (result);
01850         }
01851 
01852         dns_rdataset_current(nsec3set, &rdata);
01853 
01854         result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
01855         if (result != ISC_R_SUCCESS)
01856                 return (result);
01857 
01858         (*logit)(arg, ISC_LOG_DEBUG(3), "looking for relevant NSEC3");
01859 
01860         dns_fixedname_init(&fzone);
01861         zone = dns_fixedname_name(&fzone);
01862         zlabels = dns_name_countlabels(nsec3name);
01863 
01864         /*
01865          * NSEC3 records must have two or more labels to be valid.
01866          */
01867         if (zlabels < 2)
01868                 return (ISC_R_IGNORE);
01869 
01870         /*
01871          * Strip off the NSEC3 hash to get the zone.
01872          */
01873         zlabels--;
01874         dns_name_split(nsec3name, zlabels, NULL, zone);
01875 
01876         /*
01877          * If not below the zone name we can ignore this record.
01878          */
01879         if (!dns_name_issubdomain(name, zone))
01880                 return (ISC_R_IGNORE);
01881 
01882         /*
01883          * Is this zone the same or deeper than the current zone?
01884          */
01885         if (dns_name_countlabels(zonename) == 0 ||
01886             dns_name_issubdomain(zone, zonename))
01887                 dns_name_copy(zone, zonename, NULL);
01888 
01889         if (!dns_name_equal(zone, zonename))
01890                 return (ISC_R_IGNORE);
01891 
01892         /*
01893          * Are we only looking for the most enclosing zone?
01894          */
01895         if (exists == NULL || data == NULL)
01896                 return (ISC_R_SUCCESS);
01897 
01898         /*
01899          * Only set unknown once we are sure that this NSEC3 is from
01900          * the deepest covering zone.
01901          */
01902         if (!dns_nsec3_supportedhash(nsec3.hash)) {
01903                 if (unknown != NULL)
01904                         *unknown = ISC_TRUE;
01905                 return (ISC_R_IGNORE);
01906         }
01907 
01908         /*
01909          * Recover the hash from the first label.
01910          */
01911         dns_name_getlabel(nsec3name, 0, &hashlabel);
01912         isc_region_consume(&hashlabel, 1);
01913         isc_buffer_init(&buffer, owner, sizeof(owner));
01914         result = isc_base32hex_decoderegion(&hashlabel, &buffer);
01915         if (result != ISC_R_SUCCESS)
01916                 return (result);
01917 
01918         /*
01919          * The hash lengths should match.  If not ignore the record.
01920          */
01921         if (isc_buffer_usedlength(&buffer) != nsec3.next_length)
01922                 return (ISC_R_IGNORE);
01923 
01924         /*
01925          * Work out what this NSEC3 covers.
01926          * Inside (<0) or outside (>=0).
01927          */
01928         scope = memcmp(owner, nsec3.next, nsec3.next_length);
01929 
01930         /*
01931          * Prepare to compute all the hashes.
01932          */
01933         dns_fixedname_init(&qfixed);
01934         qname = dns_fixedname_name(&qfixed);
01935         dns_name_downcase(name, qname, NULL);
01936         qlabels = dns_name_countlabels(qname);
01937         first = ISC_TRUE;
01938 
01939         while (qlabels >= zlabels) {
01940                 length = isc_iterated_hash(hash, nsec3.hash, nsec3.iterations,
01941                                            nsec3.salt, nsec3.salt_length,
01942                                            qname->ndata, qname->length);
01943                 /*
01944                  * The computed hash length should match.
01945                  */
01946                 if (length != nsec3.next_length) {
01947                         (*logit)(arg, ISC_LOG_DEBUG(3),
01948                                  "ignoring NSEC bad length %u vs %u",
01949                                  length, nsec3.next_length);
01950                         return (ISC_R_IGNORE);
01951                 }
01952 
01953                 order = memcmp(hash, owner, length);
01954                 if (first && order == 0) {
01955                         /*
01956                          * The hashes are the same.
01957                          */
01958                         atparent = dns_rdatatype_atparent(type);
01959                         ns = dns_nsec3_typepresent(&rdata, dns_rdatatype_ns);
01960                         soa = dns_nsec3_typepresent(&rdata, dns_rdatatype_soa);
01961                         if (ns && !soa) {
01962                                 if (!atparent) {
01963                                         /*
01964                                          * This NSEC3 record is from somewhere
01965                                          * higher in the DNS, and at the
01966                                          * parent of a delegation. It can not
01967                                          * be legitimately used here.
01968                                          */
01969                                         (*logit)(arg, ISC_LOG_DEBUG(3),
01970                                                  "ignoring parent NSEC3");
01971                                         return (ISC_R_IGNORE);
01972                                 }
01973                         } else if (atparent && ns && soa) {
01974                                 /*
01975                                  * This NSEC3 record is from the child.
01976                                  * It can not be legitimately used here.
01977                                  */
01978                                 (*logit)(arg, ISC_LOG_DEBUG(3),
01979                                          "ignoring child NSEC3");
01980                                 return (ISC_R_IGNORE);
01981                         }
01982                         if (type == dns_rdatatype_cname ||
01983                             type == dns_rdatatype_nxt ||
01984                             type == dns_rdatatype_nsec ||
01985                             type == dns_rdatatype_key ||
01986                             !dns_nsec3_typepresent(&rdata, dns_rdatatype_cname)) {
01987                                 *exists = ISC_TRUE;
01988                                 *data = dns_nsec3_typepresent(&rdata, type);
01989                                 (*logit)(arg, ISC_LOG_DEBUG(3),
01990                                          "NSEC3 proves name exists (owner) "
01991                                          "data=%d", *data);
01992                                 return (ISC_R_SUCCESS);
01993                         }
01994                         (*logit)(arg, ISC_LOG_DEBUG(3),
01995                                  "NSEC3 proves CNAME exists");
01996                         return (ISC_R_IGNORE);
01997                 }
01998 
01999                 if (order == 0 &&
02000                     dns_nsec3_typepresent(&rdata, dns_rdatatype_ns) &&
02001                     !dns_nsec3_typepresent(&rdata, dns_rdatatype_soa))
02002                 {
02003                         /*
02004                          * This NSEC3 record is from somewhere higher in
02005                          * the DNS, and at the parent of a delegation.
02006                          * It can not be legitimately used here.
02007                          */
02008                         (*logit)(arg, ISC_LOG_DEBUG(3),
02009                                  "ignoring parent NSEC3");
02010                         return (ISC_R_IGNORE);
02011                 }
02012 
02013                 /*
02014                  * Potential closest encloser.
02015                  */
02016                 if (order == 0) {
02017                         if (closest != NULL &&
02018                             (dns_name_countlabels(closest) == 0 ||
02019                              dns_name_issubdomain(qname, closest)) &&
02020                             !dns_nsec3_typepresent(&rdata, dns_rdatatype_ds) &&
02021                             !dns_nsec3_typepresent(&rdata, dns_rdatatype_dname) &&
02022                             (dns_nsec3_typepresent(&rdata, dns_rdatatype_soa) ||
02023                              !dns_nsec3_typepresent(&rdata, dns_rdatatype_ns)))
02024                         {
02025 
02026                                 dns_name_format(qname, namebuf,
02027                                                 sizeof(namebuf));
02028                                 (*logit)(arg, ISC_LOG_DEBUG(3),
02029                                          "NSEC3 indicates potential closest "
02030                                          "encloser: '%s'", namebuf);
02031                                 dns_name_copy(qname, closest, NULL);
02032                                 *setclosest = ISC_TRUE;
02033                         }
02034                         dns_name_format(qname, namebuf, sizeof(namebuf));
02035                         (*logit)(arg, ISC_LOG_DEBUG(3),
02036                                  "NSEC3 at super-domain %s", namebuf);
02037                         return (answer);
02038                 }
02039 
02040                 /*
02041                  * Find if the name does not exist.
02042                  *
02043                  * We continue as we need to find the name closest to the
02044                  * closest encloser that doesn't exist.
02045                  *
02046                  * We also need to continue to ensure that we are not
02047                  * proving the non-existence of a record in a sub-zone.
02048                  * If that would be the case we will return ISC_R_IGNORE
02049                  * above.
02050                  */
02051                 if ((scope < 0 && order > 0 &&
02052                      memcmp(hash, nsec3.next, length) < 0) ||
02053                     (scope >= 0 && (order > 0 ||
02054                                     memcmp(hash, nsec3.next, length) < 0)))
02055                 {
02056                         dns_name_format(qname, namebuf, sizeof(namebuf));
02057                         (*logit)(arg, ISC_LOG_DEBUG(3), "NSEC3 proves "
02058                                  "name does not exist: '%s'", namebuf);
02059                         if (nearest != NULL &&
02060                             (dns_name_countlabels(nearest) == 0 ||
02061                              dns_name_issubdomain(nearest, qname))) {
02062                                 dns_name_copy(qname, nearest, NULL);
02063                                 *setnearest = ISC_TRUE;
02064                         }
02065 
02066                         *exists = ISC_FALSE;
02067                         *data = ISC_FALSE;
02068                         if (optout != NULL) {
02069                                 if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0)
02070                                         (*logit)(arg, ISC_LOG_DEBUG(3),
02071                                                  "NSEC3 indicates optout");
02072                                 else
02073                                         (*logit)(arg, ISC_LOG_DEBUG(3),
02074                                                  "NSEC3 indicates secure range");
02075                                 *optout =
02076                                     ISC_TF(nsec3.flags & DNS_NSEC3FLAG_OPTOUT);
02077                         }
02078                         answer = ISC_R_SUCCESS;
02079                 }
02080 
02081                 qlabels--;
02082                 if (qlabels > 0)
02083                         dns_name_split(qname, qlabels, NULL, qname);
02084                 first = ISC_FALSE;
02085         }
02086         return (answer);
02087 }

Generated on Tue Apr 28 17:40:58 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha