dnssectool.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2005, 2007, 2009-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /*! \file */
00019 
00020 /*%
00021  * DNSSEC Support Routines.
00022  */
00023 
00024 #include <config.h>
00025 
00026 #include <stdlib.h>
00027 
00028 #include <isc/base32.h>
00029 #include <isc/buffer.h>
00030 #include <isc/dir.h>
00031 #include <isc/entropy.h>
00032 #include <isc/heap.h>
00033 #include <isc/list.h>
00034 #include <isc/mem.h>
00035 #include <isc/string.h>
00036 #include <isc/time.h>
00037 #include <isc/util.h>
00038 #include <isc/print.h>
00039 
00040 #include <dns/db.h>
00041 #include <dns/dbiterator.h>
00042 #include <dns/dnssec.h>
00043 #include <dns/fixedname.h>
00044 #include <dns/keyvalues.h>
00045 #include <dns/log.h>
00046 #include <dns/name.h>
00047 #include <dns/nsec.h>
00048 #include <dns/nsec3.h>
00049 #include <dns/rdatastruct.h>
00050 #include <dns/rdataclass.h>
00051 #include <dns/rdataset.h>
00052 #include <dns/rdatasetiter.h>
00053 #include <dns/rdatatype.h>
00054 #include <dns/result.h>
00055 #include <dns/secalg.h>
00056 #include <dns/time.h>
00057 
00058 #include "dnssectool.h"
00059 
00060 static isc_heap_t *expected_chains, *found_chains;
00061 
00062 struct nsec3_chain_fixed {
00063         isc_uint8_t     hash;
00064         isc_uint8_t     salt_length;
00065         isc_uint8_t     next_length;
00066         isc_uint16_t    iterations;
00067         /* unsigned char salt[0]; */
00068         /* unsigned char owner[0]; */
00069         /* unsigned char next[0]; */
00070 };
00071 
00072 extern int verbose;
00073 extern const char *program;
00074 
00075 typedef struct entropysource entropysource_t;
00076 
00077 struct entropysource {
00078         isc_entropysource_t *source;
00079         isc_mem_t *mctx;
00080         ISC_LINK(entropysource_t) link;
00081 };
00082 
00083 static ISC_LIST(entropysource_t) sources;
00084 static fatalcallback_t *fatalcallback = NULL;
00085 
00086 void
00087 fatal(const char *format, ...) {
00088         va_list args;
00089 
00090         fprintf(stderr, "%s: fatal: ", program);
00091         va_start(args, format);
00092         vfprintf(stderr, format, args);
00093         va_end(args);
00094         fprintf(stderr, "\n");
00095         if (fatalcallback != NULL)
00096                 (*fatalcallback)();
00097         exit(1);
00098 }
00099 
00100 void
00101 setfatalcallback(fatalcallback_t *callback) {
00102         fatalcallback = callback;
00103 }
00104 
00105 void
00106 check_result(isc_result_t result, const char *message) {
00107         if (result != ISC_R_SUCCESS)
00108                 fatal("%s: %s", message, isc_result_totext(result));
00109 }
00110 
00111 void
00112 vbprintf(int level, const char *fmt, ...) {
00113         va_list ap;
00114         if (level > verbose)
00115                 return;
00116         va_start(ap, fmt);
00117         fprintf(stderr, "%s: ", program);
00118         vfprintf(stderr, fmt, ap);
00119         va_end(ap);
00120 }
00121 
00122 void
00123 version(const char *name) {
00124         fprintf(stderr, "%s %s\n", name, VERSION);
00125         exit(0);
00126 }
00127 
00128 void
00129 type_format(const dns_rdatatype_t type, char *cp, unsigned int size) {
00130         isc_buffer_t b;
00131         isc_region_t r;
00132         isc_result_t result;
00133 
00134         isc_buffer_init(&b, cp, size - 1);
00135         result = dns_rdatatype_totext(type, &b);
00136         check_result(result, "dns_rdatatype_totext()");
00137         isc_buffer_usedregion(&b, &r);
00138         r.base[r.length] = 0;
00139 }
00140 
00141 void
00142 sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) {
00143         char namestr[DNS_NAME_FORMATSIZE];
00144         char algstr[DNS_NAME_FORMATSIZE];
00145 
00146         dns_name_format(&sig->signer, namestr, sizeof(namestr));
00147         dns_secalg_format(sig->algorithm, algstr, sizeof(algstr));
00148         snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid);
00149 }
00150 
00151 void
00152 setup_logging(isc_mem_t *mctx, isc_log_t **logp) {
00153         isc_result_t result;
00154         isc_logdestination_t destination;
00155         isc_logconfig_t *logconfig = NULL;
00156         isc_log_t *log = NULL;
00157         int level;
00158 
00159         if (verbose < 0)
00160                 verbose = 0;
00161         switch (verbose) {
00162         case 0:
00163                 /*
00164                  * We want to see warnings about things like out-of-zone
00165                  * data in the master file even when not verbose.
00166                  */
00167                 level = ISC_LOG_WARNING;
00168                 break;
00169         case 1:
00170                 level = ISC_LOG_INFO;
00171                 break;
00172         default:
00173                 level = ISC_LOG_DEBUG(verbose - 2 + 1);
00174                 break;
00175         }
00176 
00177         RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
00178         isc_log_setcontext(log);
00179         dns_log_init(log);
00180         dns_log_setcontext(log);
00181 
00182         RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS);
00183 
00184         /*
00185          * Set up a channel similar to default_stderr except:
00186          *  - the logging level is passed in
00187          *  - the program name and logging level are printed
00188          *  - no time stamp is printed
00189          */
00190         destination.file.stream = stderr;
00191         destination.file.name = NULL;
00192         destination.file.versions = ISC_LOG_ROLLNEVER;
00193         destination.file.maximum_size = 0;
00194         result = isc_log_createchannel(logconfig, "stderr",
00195                                        ISC_LOG_TOFILEDESC,
00196                                        level,
00197                                        &destination,
00198                                        ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL);
00199         check_result(result, "isc_log_createchannel()");
00200 
00201         RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
00202                                          NULL, NULL) == ISC_R_SUCCESS);
00203 
00204         *logp = log;
00205 }
00206 
00207 void
00208 cleanup_logging(isc_log_t **logp) {
00209         isc_log_t *log;
00210 
00211         REQUIRE(logp != NULL);
00212 
00213         log = *logp;
00214         if (log == NULL)
00215                 return;
00216         isc_log_destroy(&log);
00217         isc_log_setcontext(NULL);
00218         dns_log_setcontext(NULL);
00219         logp = NULL;
00220 }
00221 
00222 void
00223 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
00224         isc_result_t result;
00225         isc_entropysource_t *source = NULL;
00226         entropysource_t *elt;
00227         int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
00228 
00229         REQUIRE(ectx != NULL);
00230 
00231         if (*ectx == NULL) {
00232                 result = isc_entropy_create(mctx, ectx);
00233                 if (result != ISC_R_SUCCESS)
00234                         fatal("could not create entropy object");
00235                 ISC_LIST_INIT(sources);
00236         }
00237 
00238         if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
00239                 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
00240                 randomfile = NULL;
00241         }
00242 
00243         result = isc_entropy_usebestsource(*ectx, &source, randomfile,
00244                                            usekeyboard);
00245 
00246         if (result != ISC_R_SUCCESS)
00247                 fatal("could not initialize entropy source: %s",
00248                       isc_result_totext(result));
00249 
00250         if (source != NULL) {
00251                 elt = isc_mem_get(mctx, sizeof(*elt));
00252                 if (elt == NULL)
00253                         fatal("out of memory");
00254                 elt->source = source;
00255                 elt->mctx = mctx;
00256                 ISC_LINK_INIT(elt, link);
00257                 ISC_LIST_APPEND(sources, elt, link);
00258         }
00259 }
00260 
00261 void
00262 cleanup_entropy(isc_entropy_t **ectx) {
00263         entropysource_t *source;
00264         while (!ISC_LIST_EMPTY(sources)) {
00265                 source = ISC_LIST_HEAD(sources);
00266                 ISC_LIST_UNLINK(sources, source, link);
00267                 isc_entropy_destroysource(&source->source);
00268                 isc_mem_put(source->mctx, source, sizeof(*source));
00269         }
00270         isc_entropy_detach(ectx);
00271 }
00272 
00273 static isc_stdtime_t
00274 time_units(isc_stdtime_t offset, char *suffix, const char *str) {
00275         switch (suffix[0]) {
00276             case 'Y': case 'y':
00277                 return (offset * (365 * 24 * 3600));
00278             case 'M': case 'm':
00279                 switch (suffix[1]) {
00280                     case 'O': case 'o':
00281                         return (offset * (30 * 24 * 3600));
00282                     case 'I': case 'i':
00283                         return (offset * 60);
00284                     case '\0':
00285                         fatal("'%s' ambiguous: use 'mi' for minutes "
00286                               "or 'mo' for months", str);
00287                     default:
00288                         fatal("time value %s is invalid", str);
00289                 }
00290                 /* NOTREACHED */
00291                 break;
00292             case 'W': case 'w':
00293                 return (offset * (7 * 24 * 3600));
00294             case 'D': case 'd':
00295                 return (offset * (24 * 3600));
00296             case 'H': case 'h':
00297                 return (offset * 3600);
00298             case 'S': case 's': case '\0':
00299                 return (offset);
00300             default:
00301                 fatal("time value %s is invalid", str);
00302         }
00303         /* NOTREACHED */
00304         return(0); /* silence compiler warning */
00305 }
00306 
00307 static inline isc_boolean_t
00308 isnone(const char *str) {
00309         return (ISC_TF((strcasecmp(str, "none") == 0) ||
00310                        (strcasecmp(str, "never") == 0)));
00311 }
00312 
00313 dns_ttl_t
00314 strtottl(const char *str) {
00315         const char *orig = str;
00316         dns_ttl_t ttl;
00317         char *endp;
00318 
00319         if (isnone(str))
00320                 return ((dns_ttl_t) 0);
00321 
00322         ttl = strtol(str, &endp, 0);
00323         if (ttl == 0 && endp == str)
00324                 fatal("TTL must be numeric");
00325         ttl = time_units(ttl, endp, orig);
00326         return (ttl);
00327 }
00328 
00329 isc_stdtime_t
00330 strtotime(const char *str, isc_int64_t now, isc_int64_t base,
00331           isc_boolean_t *setp)
00332 {
00333         isc_int64_t val, offset;
00334         isc_result_t result;
00335         const char *orig = str;
00336         char *endp;
00337         size_t n;
00338 
00339         if (isnone(str)) {
00340                 if (setp != NULL)
00341                         *setp = ISC_FALSE;
00342                 return ((isc_stdtime_t) 0);
00343         }
00344 
00345         if (setp != NULL)
00346                 *setp = ISC_TRUE;
00347 
00348         if ((str[0] == '0' || str[0] == '-') && str[1] == '\0')
00349                 return ((isc_stdtime_t) 0);
00350 
00351         /*
00352          * We accept times in the following formats:
00353          *   now([+-]offset)
00354          *   YYYYMMDD([+-]offset)
00355          *   YYYYMMDDhhmmss([+-]offset)
00356          *   [+-]offset
00357          */
00358         n = strspn(str, "0123456789");
00359         if ((n == 8u || n == 14u) &&
00360             (str[n] == '\0' || str[n] == '-' || str[n] == '+'))
00361         {
00362                 char timestr[15];
00363 
00364                 strlcpy(timestr, str, sizeof(timestr));
00365                 timestr[n] = 0;
00366                 if (n == 8u)
00367                         strlcat(timestr, "000000", sizeof(timestr));
00368                 result = dns_time64_fromtext(timestr, &val);
00369                 if (result != ISC_R_SUCCESS)
00370                         fatal("time value %s is invalid: %s", orig,
00371                               isc_result_totext(result));
00372                 base = val;
00373                 str += n;
00374         } else if (strncmp(str, "now", 3) == 0) {
00375                 base = now;
00376                 str += 3;
00377         }
00378 
00379         if (str[0] == '\0')
00380                 return ((isc_stdtime_t) base);
00381         else if (str[0] == '+') {
00382                 offset = strtol(str + 1, &endp, 0);
00383                 offset = time_units((isc_stdtime_t) offset, endp, orig);
00384                 val = base + offset;
00385         } else if (str[0] == '-') {
00386                 offset = strtol(str + 1, &endp, 0);
00387                 offset = time_units((isc_stdtime_t) offset, endp, orig);
00388                 val = base - offset;
00389         } else
00390                 fatal("time value %s is invalid", orig);
00391 
00392         return ((isc_stdtime_t) val);
00393 }
00394 
00395 dns_rdataclass_t
00396 strtoclass(const char *str) {
00397         isc_textregion_t r;
00398         dns_rdataclass_t rdclass;
00399         isc_result_t ret;
00400 
00401         if (str == NULL)
00402                 return dns_rdataclass_in;
00403         DE_CONST(str, r.base);
00404         r.length = strlen(str);
00405         ret = dns_rdataclass_fromtext(&rdclass, &r);
00406         if (ret != ISC_R_SUCCESS)
00407                 fatal("unknown class %s", str);
00408         return (rdclass);
00409 }
00410 
00411 isc_result_t
00412 try_dir(const char *dirname) {
00413         isc_result_t result;
00414         isc_dir_t d;
00415 
00416         isc_dir_init(&d);
00417         result = isc_dir_open(&d, dirname);
00418         if (result == ISC_R_SUCCESS) {
00419                 isc_dir_close(&d);
00420         }
00421         return (result);
00422 }
00423 
00424 /*
00425  * Check private key version compatibility.
00426  */
00427 void
00428 check_keyversion(dst_key_t *key, char *keystr) {
00429         int major, minor;
00430         dst_key_getprivateformat(key, &major, &minor);
00431         INSIST(major <= DST_MAJOR_VERSION); /* invalid private key */
00432 
00433         if (major < DST_MAJOR_VERSION || minor < DST_MINOR_VERSION)
00434                 fatal("Key %s has incompatible format version %d.%d, "
00435                       "use -f to force upgrade to new version.",
00436                       keystr, major, minor);
00437         if (minor > DST_MINOR_VERSION)
00438                 fatal("Key %s has incompatible format version %d.%d, "
00439                       "use -f to force downgrade to current version.",
00440                       keystr, major, minor);
00441 }
00442 
00443 void
00444 set_keyversion(dst_key_t *key) {
00445         int major, minor;
00446         dst_key_getprivateformat(key, &major, &minor);
00447         INSIST(major <= DST_MAJOR_VERSION);
00448 
00449         if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION)
00450                 dst_key_setprivateformat(key, DST_MAJOR_VERSION,
00451                                          DST_MINOR_VERSION);
00452 
00453         /*
00454          * If the key is from a version older than 1.3, set
00455          * set the creation date
00456          */
00457         if (major < 1 || (major == 1 && minor <= 2)) {
00458                 isc_stdtime_t now;
00459                 isc_stdtime_get(&now);
00460                 dst_key_settime(key, DST_TIME_CREATED, now);
00461         }
00462 }
00463 
00464 isc_boolean_t
00465 key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir,
00466               isc_mem_t *mctx, isc_boolean_t *exact)
00467 {
00468         isc_result_t result;
00469         isc_boolean_t conflict = ISC_FALSE;
00470         dns_dnsseckeylist_t matchkeys;
00471         dns_dnsseckey_t *key = NULL;
00472         isc_uint16_t id, oldid;
00473         isc_uint32_t rid, roldid;
00474         dns_secalg_t alg;
00475 
00476         if (exact != NULL)
00477                 *exact = ISC_FALSE;
00478 
00479         id = dst_key_id(dstkey);
00480         rid = dst_key_rid(dstkey);
00481         alg = dst_key_alg(dstkey);
00482 
00483         ISC_LIST_INIT(matchkeys);
00484         result = dns_dnssec_findmatchingkeys(name, dir, mctx, &matchkeys);
00485         if (result == ISC_R_NOTFOUND)
00486                 return (ISC_FALSE);
00487 
00488         while (!ISC_LIST_EMPTY(matchkeys) && !conflict) {
00489                 key = ISC_LIST_HEAD(matchkeys);
00490                 if (dst_key_alg(key->key) != alg)
00491                         goto next;
00492 
00493                 oldid = dst_key_id(key->key);
00494                 roldid = dst_key_rid(key->key);
00495 
00496                 if (oldid == rid || roldid == id || id == oldid) {
00497                         conflict = ISC_TRUE;
00498                         if (id != oldid) {
00499                                 if (verbose > 1)
00500                                         fprintf(stderr, "Key ID %d could "
00501                                                 "collide with %d\n",
00502                                                 id, oldid);
00503                         } else {
00504                                 if (exact != NULL)
00505                                         *exact = ISC_TRUE;
00506                                 if (verbose > 1)
00507                                         fprintf(stderr, "Key ID %d exists\n",
00508                                                 id);
00509                         }
00510                 }
00511 
00512  next:
00513                 ISC_LIST_UNLINK(matchkeys, key, link);
00514                 dns_dnsseckey_destroy(mctx, &key);
00515         }
00516 
00517         /* Finish freeing the list */
00518         while (!ISC_LIST_EMPTY(matchkeys)) {
00519                 key = ISC_LIST_HEAD(matchkeys);
00520                 ISC_LIST_UNLINK(matchkeys, key, link);
00521                 dns_dnsseckey_destroy(mctx, &key);
00522         }
00523 
00524         return (conflict);
00525 }
00526 
00527 isc_boolean_t
00528 is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
00529               dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp)
00530 {
00531         dns_rdataset_t nsset;
00532         isc_result_t result;
00533 
00534         if (dns_name_equal(name, origin))
00535                 return (ISC_FALSE);
00536 
00537         dns_rdataset_init(&nsset);
00538         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns,
00539                                      0, 0, &nsset, NULL);
00540         if (dns_rdataset_isassociated(&nsset)) {
00541                 if (ttlp != NULL)
00542                         *ttlp = nsset.ttl;
00543                 dns_rdataset_disassociate(&nsset);
00544         }
00545 
00546         return (ISC_TF(result == ISC_R_SUCCESS));
00547 }
00548 
00549 static isc_boolean_t
00550 goodsig(dns_name_t *origin, dns_rdata_t *sigrdata, dns_name_t *name,
00551         dns_rdataset_t *keyrdataset, dns_rdataset_t *rdataset, isc_mem_t *mctx)
00552 {
00553         dns_rdata_dnskey_t key;
00554         dns_rdata_rrsig_t sig;
00555         dst_key_t *dstkey = NULL;
00556         isc_result_t result;
00557 
00558         result = dns_rdata_tostruct(sigrdata, &sig, NULL);
00559         check_result(result, "dns_rdata_tostruct()");
00560 
00561         for (result = dns_rdataset_first(keyrdataset);
00562              result == ISC_R_SUCCESS;
00563              result = dns_rdataset_next(keyrdataset)) {
00564                 dns_rdata_t rdata = DNS_RDATA_INIT;
00565                 dns_rdataset_current(keyrdataset, &rdata);
00566                 result = dns_rdata_tostruct(&rdata, &key, NULL);
00567                 check_result(result, "dns_rdata_tostruct()");
00568                 result = dns_dnssec_keyfromrdata(origin, &rdata, mctx,
00569                                                  &dstkey);
00570                 if (result != ISC_R_SUCCESS)
00571                         return (ISC_FALSE);
00572                 if (sig.algorithm != key.algorithm ||
00573                     sig.keyid != dst_key_id(dstkey) ||
00574                     !dns_name_equal(&sig.signer, origin)) {
00575                         dst_key_free(&dstkey);
00576                         continue;
00577                 }
00578                 result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE,
00579                                            mctx, sigrdata);
00580                 dst_key_free(&dstkey);
00581                 if (result == ISC_R_SUCCESS)
00582                         return(ISC_TRUE);
00583         }
00584         return (ISC_FALSE);
00585 }
00586 
00587 static isc_result_t
00588 verifynsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00589            dns_dbnode_t *node, dns_name_t *nextname)
00590 {
00591         unsigned char buffer[DNS_NSEC_BUFFERSIZE];
00592         char namebuf[DNS_NAME_FORMATSIZE];
00593         char nextbuf[DNS_NAME_FORMATSIZE];
00594         char found[DNS_NAME_FORMATSIZE];
00595         dns_rdataset_t rdataset;
00596         dns_rdata_t rdata = DNS_RDATA_INIT;
00597         dns_rdata_t tmprdata = DNS_RDATA_INIT;
00598         dns_rdata_nsec_t nsec;
00599         isc_result_t result;
00600 
00601         dns_rdataset_init(&rdataset);
00602         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
00603                                      0, 0, &rdataset, NULL);
00604         if (result != ISC_R_SUCCESS) {
00605                 dns_name_format(name, namebuf, sizeof(namebuf));
00606                 fprintf(stderr, "Missing NSEC record for %s\n", namebuf);
00607                 goto failure;
00608         }
00609 
00610         result = dns_rdataset_first(&rdataset);
00611         check_result(result, "dns_rdataset_first()");
00612 
00613         dns_rdataset_current(&rdataset, &rdata);
00614         result = dns_rdata_tostruct(&rdata, &nsec, NULL);
00615         check_result(result, "dns_rdata_tostruct()");
00616         /* Check bit next name is consistent */
00617         if (!dns_name_equal(&nsec.next, nextname)) {
00618                 dns_name_format(name, namebuf, sizeof(namebuf));
00619                 dns_name_format(nextname, nextbuf, sizeof(nextbuf));
00620                 dns_name_format(&nsec.next, found, sizeof(found));
00621                 fprintf(stderr, "Bad NSEC record for %s, next name "
00622                                 "mismatch (expected:%s, found:%s)\n", namebuf,
00623                                 nextbuf, found);
00624                 goto failure;
00625         }
00626         /* Check bit map is consistent */
00627         result = dns_nsec_buildrdata(db, ver, node, nextname, buffer,
00628                                      &tmprdata);
00629         check_result(result, "dns_nsec_buildrdata()");
00630         if (dns_rdata_compare(&rdata, &tmprdata) != 0) {
00631                 dns_name_format(name, namebuf, sizeof(namebuf));
00632                 fprintf(stderr, "Bad NSEC record for %s, bit map "
00633                                 "mismatch\n", namebuf);
00634                 goto failure;
00635         }
00636         result = dns_rdataset_next(&rdataset);
00637         if (result != ISC_R_NOMORE) {
00638                 dns_name_format(name, namebuf, sizeof(namebuf));
00639                 fprintf(stderr, "Multipe NSEC records for %s\n", namebuf);
00640                 goto failure;
00641 
00642         }
00643         dns_rdataset_disassociate(&rdataset);
00644         return (ISC_R_SUCCESS);
00645  failure:
00646         if (dns_rdataset_isassociated(&rdataset))
00647                 dns_rdataset_disassociate(&rdataset);
00648         return (ISC_R_FAILURE);
00649 }
00650 
00651 static void
00652 check_no_rrsig(dns_db_t *db, dns_dbversion_t *ver, dns_rdataset_t *rdataset,
00653                dns_name_t *name, dns_dbnode_t *node)
00654 {
00655         char namebuf[DNS_NAME_FORMATSIZE];
00656         char typebuf[80];
00657         dns_rdataset_t sigrdataset;
00658         dns_rdatasetiter_t *rdsiter = NULL;
00659         isc_result_t result;
00660 
00661         dns_rdataset_init(&sigrdataset);
00662         result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
00663         check_result(result, "dns_db_allrdatasets()");
00664         for (result = dns_rdatasetiter_first(rdsiter);
00665              result == ISC_R_SUCCESS;
00666              result = dns_rdatasetiter_next(rdsiter)) {
00667                 dns_rdatasetiter_current(rdsiter, &sigrdataset);
00668                 if (sigrdataset.type == dns_rdatatype_rrsig &&
00669                     sigrdataset.covers == rdataset->type)
00670                         break;
00671                 dns_rdataset_disassociate(&sigrdataset);
00672         }
00673         if (result == ISC_R_SUCCESS) {
00674                 dns_name_format(name, namebuf, sizeof(namebuf));
00675                 type_format(rdataset->type, typebuf, sizeof(typebuf));
00676                 fprintf(stderr, "Warning: Found unexpected signatures for "
00677                         "%s/%s\n", namebuf, typebuf);
00678         }
00679         if (dns_rdataset_isassociated(&sigrdataset))
00680                 dns_rdataset_disassociate(&sigrdataset);
00681         dns_rdatasetiter_destroy(&rdsiter);
00682 }
00683 
00684 static isc_boolean_t
00685 chain_compare(void *arg1, void *arg2) {
00686         struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2;
00687         size_t len;
00688 
00689         /*
00690          * Do each element in turn to get a stable sort.
00691          */
00692         if (e1->hash < e2->hash)
00693                 return (ISC_TRUE);
00694         if (e1->hash > e2->hash)
00695                 return (ISC_FALSE);
00696         if (e1->iterations < e2->iterations)
00697                 return (ISC_TRUE);
00698         if (e1->iterations > e2->iterations)
00699                 return (ISC_FALSE);
00700         if (e1->salt_length < e2->salt_length)
00701                 return (ISC_TRUE);
00702         if (e1->salt_length > e2->salt_length)
00703                 return (ISC_FALSE);
00704         if (e1->next_length < e2->next_length)
00705                 return (ISC_TRUE);
00706         if (e1->next_length > e2->next_length)
00707                 return (ISC_FALSE);
00708         len = e1->salt_length + 2 * e1->next_length;
00709         if (memcmp(e1 + 1, e2 + 1, len) < 0)
00710                 return (ISC_TRUE);
00711         return (ISC_FALSE);
00712 }
00713 
00714 static isc_boolean_t
00715 chain_equal(struct nsec3_chain_fixed *e1, struct nsec3_chain_fixed *e2) {
00716         size_t len;
00717 
00718         if (e1->hash != e2->hash)
00719                 return (ISC_FALSE);
00720         if (e1->iterations != e2->iterations)
00721                 return (ISC_FALSE);
00722         if (e1->salt_length != e2->salt_length)
00723                 return (ISC_FALSE);
00724         if (e1->next_length != e2->next_length)
00725                 return (ISC_FALSE);
00726         len = e1->salt_length + 2 * e1->next_length;
00727         if (memcmp(e1 + 1, e2 + 1, len) != 0)
00728                 return (ISC_FALSE);
00729         return (ISC_TRUE);
00730 }
00731 
00732 static isc_result_t
00733 record_nsec3(const unsigned char *rawhash, const dns_rdata_nsec3_t *nsec3,
00734              isc_mem_t *mctx, isc_heap_t *chains)
00735 {
00736         struct nsec3_chain_fixed *element;
00737         size_t len;
00738         unsigned char *cp;
00739         isc_result_t result;
00740 
00741         len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length;
00742 
00743         element = isc_mem_get(mctx, len);
00744         if (element == NULL)
00745                 return (ISC_R_NOMEMORY);
00746         memset(element, 0, len);
00747         element->hash = nsec3->hash;
00748         element->salt_length = nsec3->salt_length;
00749         element->next_length = nsec3->next_length;
00750         element->iterations = nsec3->iterations;
00751         cp = (unsigned char *)(element + 1);
00752         memmove(cp, nsec3->salt, nsec3->salt_length);
00753         cp += nsec3->salt_length;
00754         memmove(cp, rawhash, nsec3->next_length);
00755         cp += nsec3->next_length;
00756         memmove(cp, nsec3->next, nsec3->next_length);
00757         result = isc_heap_insert(chains, element);
00758         if (result != ISC_R_SUCCESS) {
00759                 fprintf(stderr, "isc_heap_insert failed: %s\n",
00760                         isc_result_totext(result));
00761                 isc_mem_put(mctx, element, len);
00762         }
00763         return (result);
00764 }
00765 
00766 static isc_result_t
00767 match_nsec3(dns_name_t *name, isc_mem_t *mctx,
00768             dns_rdata_nsec3param_t *nsec3param, dns_rdataset_t *rdataset,
00769             unsigned char types[8192], unsigned int maxtype,
00770             unsigned char *rawhash, size_t rhsize)
00771 {
00772         unsigned char cbm[8244];
00773         char namebuf[DNS_NAME_FORMATSIZE];
00774         dns_rdata_nsec3_t nsec3;
00775         isc_result_t result;
00776         unsigned int len;
00777 
00778         /*
00779          * Find matching NSEC3 record.
00780          */
00781         for (result = dns_rdataset_first(rdataset);
00782              result == ISC_R_SUCCESS;
00783              result = dns_rdataset_next(rdataset)) {
00784                 dns_rdata_t rdata = DNS_RDATA_INIT;
00785                 dns_rdataset_current(rdataset, &rdata);
00786                 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
00787                 check_result(result, "dns_rdata_tostruct()");
00788                 if (nsec3.hash == nsec3param->hash &&
00789                     nsec3.next_length == rhsize &&
00790                     nsec3.iterations == nsec3param->iterations &&
00791                     nsec3.salt_length == nsec3param->salt_length &&
00792                     memcmp(nsec3.salt, nsec3param->salt,
00793                            nsec3param->salt_length) == 0)
00794                         break;
00795         }
00796         if (result != ISC_R_SUCCESS) {
00797                 dns_name_format(name, namebuf, sizeof(namebuf));
00798                 fprintf(stderr, "Missing NSEC3 record for %s\n", namebuf);
00799                 return (result);
00800         }
00801 
00802         /*
00803          * Check the type list.
00804          */
00805         len = dns_nsec_compressbitmap(cbm, types, maxtype);
00806         if (nsec3.len != len || memcmp(cbm, nsec3.typebits, len) != 0) {
00807                 dns_name_format(name, namebuf, sizeof(namebuf));
00808                 fprintf(stderr, "Bad NSEC3 record for %s, bit map "
00809                                 "mismatch\n", namebuf);
00810                 return (ISC_R_FAILURE);
00811         }
00812 
00813         /*
00814          * Record chain.
00815          */
00816         result = record_nsec3(rawhash, &nsec3, mctx, expected_chains);
00817         check_result(result, "record_nsec3()");
00818 
00819         /*
00820          * Make sure there is only one NSEC3 record with this set of
00821          * parameters.
00822          */
00823         for (result = dns_rdataset_next(rdataset);
00824              result == ISC_R_SUCCESS;
00825              result = dns_rdataset_next(rdataset)) {
00826                 dns_rdata_t rdata = DNS_RDATA_INIT;
00827                 dns_rdataset_current(rdataset, &rdata);
00828                 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
00829                 check_result(result, "dns_rdata_tostruct()");
00830                 if (nsec3.hash == nsec3param->hash &&
00831                     nsec3.iterations == nsec3param->iterations &&
00832                     nsec3.salt_length == nsec3param->salt_length &&
00833                     memcmp(nsec3.salt, nsec3param->salt,
00834                            nsec3.salt_length) == 0) {
00835                         dns_name_format(name, namebuf, sizeof(namebuf));
00836                         fprintf(stderr, "Multiple NSEC3 records with the "
00837                                 "same parameter set for %s", namebuf);
00838                         result = DNS_R_DUPLICATE;
00839                         break;
00840                 }
00841         }
00842         if (result != ISC_R_NOMORE)
00843                 return (result);
00844 
00845         result = ISC_R_SUCCESS;
00846         return (result);
00847 }
00848 
00849 static isc_boolean_t
00850 innsec3params(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) {
00851         dns_rdata_nsec3param_t nsec3param;
00852         isc_result_t result;
00853 
00854         for (result = dns_rdataset_first(nsec3paramset);
00855              result == ISC_R_SUCCESS;
00856              result = dns_rdataset_next(nsec3paramset)) {
00857                 dns_rdata_t rdata = DNS_RDATA_INIT;
00858 
00859                 dns_rdataset_current(nsec3paramset, &rdata);
00860                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
00861                 check_result(result, "dns_rdata_tostruct()");
00862                 if (nsec3param.flags == 0 &&
00863                     nsec3param.hash == nsec3->hash &&
00864                     nsec3param.iterations == nsec3->iterations &&
00865                     nsec3param.salt_length == nsec3->salt_length &&
00866                     memcmp(nsec3param.salt, nsec3->salt,
00867                            nsec3->salt_length) == 0)
00868                         return (ISC_TRUE);
00869         }
00870         return (ISC_FALSE);
00871 }
00872 
00873 static isc_result_t
00874 record_found(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
00875              dns_name_t *name, dns_dbnode_t *node,
00876              dns_rdataset_t *nsec3paramset)
00877 {
00878         unsigned char owner[NSEC3_MAX_HASH_LENGTH];
00879         dns_rdata_nsec3_t nsec3;
00880         dns_rdataset_t rdataset;
00881         dns_label_t hashlabel;
00882         isc_buffer_t b;
00883         isc_result_t result;
00884 
00885         if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset))
00886                 return (ISC_R_SUCCESS);
00887 
00888         dns_rdataset_init(&rdataset);
00889         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
00890                                      0, 0, &rdataset, NULL);
00891         if (result != ISC_R_SUCCESS)
00892                 return (ISC_R_SUCCESS);
00893 
00894         dns_name_getlabel(name, 0, &hashlabel);
00895         isc_region_consume(&hashlabel, 1);
00896         isc_buffer_init(&b, owner, sizeof(owner));
00897         result = isc_base32hex_decoderegion(&hashlabel, &b);
00898         if (result != ISC_R_SUCCESS)
00899                 goto cleanup;
00900 
00901         for (result = dns_rdataset_first(&rdataset);
00902              result == ISC_R_SUCCESS;
00903              result = dns_rdataset_next(&rdataset)) {
00904                 dns_rdata_t rdata = DNS_RDATA_INIT;
00905                 dns_rdataset_current(&rdataset, &rdata);
00906                 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
00907                 check_result(result, "dns_rdata_tostruct()");
00908                 if (nsec3.next_length != isc_buffer_usedlength(&b))
00909                         continue;
00910                 /*
00911                  * We only care about NSEC3 records that match a NSEC3PARAM
00912                  * record.
00913                  */
00914                 if (!innsec3params(&nsec3, nsec3paramset))
00915                         continue;
00916 
00917                 /*
00918                  * Record chain.
00919                  */
00920                 result = record_nsec3(owner, &nsec3, mctx, found_chains);
00921                 check_result(result, "record_nsec3()");
00922         }
00923 
00924  cleanup:
00925         dns_rdataset_disassociate(&rdataset);
00926         return (ISC_R_SUCCESS);
00927 }
00928 
00929 static isc_boolean_t
00930 isoptout(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
00931          dns_rdata_t *nsec3rdata)
00932 {
00933         dns_rdataset_t rdataset;
00934         dns_rdata_t rdata = DNS_RDATA_INIT;
00935         dns_rdata_nsec3_t nsec3;
00936         dns_rdata_nsec3param_t nsec3param;
00937         dns_fixedname_t fixed;
00938         dns_name_t *hashname;
00939         isc_result_t result;
00940         dns_dbnode_t *node = NULL;
00941         unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
00942         size_t rhsize = sizeof(rawhash);
00943         isc_boolean_t ret;
00944 
00945         result = dns_rdata_tostruct(nsec3rdata, &nsec3param, NULL);
00946         check_result(result, "dns_rdata_tostruct()");
00947 
00948         dns_fixedname_init(&fixed);
00949         result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, origin, origin,
00950                                     nsec3param.hash, nsec3param.iterations,
00951                                     nsec3param.salt, nsec3param.salt_length);
00952         check_result(result, "dns_nsec3_hashname()");
00953 
00954         dns_rdataset_init(&rdataset);
00955         hashname = dns_fixedname_name(&fixed);
00956         result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node);
00957         if (result == ISC_R_SUCCESS)
00958                 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
00959                                              0, 0, &rdataset, NULL);
00960         if (result != ISC_R_SUCCESS)
00961                 return (ISC_FALSE);
00962 
00963         result = dns_rdataset_first(&rdataset);
00964         check_result(result, "dns_rdataset_first()");
00965 
00966         dns_rdataset_current(&rdataset, &rdata);
00967 
00968         result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
00969         if (result != ISC_R_SUCCESS)
00970                 ret = ISC_FALSE;
00971         else
00972                 ret = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
00973 
00974         if (dns_rdataset_isassociated(&rdataset))
00975                 dns_rdataset_disassociate(&rdataset);
00976         if (node != NULL)
00977                 dns_db_detachnode(db, &node);
00978 
00979         return (ret);
00980 }
00981 
00982 static isc_result_t
00983 verifynsec3(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
00984             isc_mem_t *mctx, dns_name_t *name, dns_rdata_t *rdata,
00985             isc_boolean_t delegation, isc_boolean_t empty,
00986             unsigned char types[8192], unsigned int maxtype)
00987 {
00988         char namebuf[DNS_NAME_FORMATSIZE];
00989         char hashbuf[DNS_NAME_FORMATSIZE];
00990         dns_rdataset_t rdataset;
00991         dns_rdata_nsec3param_t nsec3param;
00992         dns_fixedname_t fixed;
00993         dns_name_t *hashname;
00994         isc_result_t result;
00995         dns_dbnode_t *node = NULL;
00996         unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
00997         size_t rhsize = sizeof(rawhash);
00998         isc_boolean_t optout;
00999 
01000         result = dns_rdata_tostruct(rdata, &nsec3param, NULL);
01001         check_result(result, "dns_rdata_tostruct()");
01002 
01003         if (nsec3param.flags != 0)
01004                 return (ISC_R_SUCCESS);
01005 
01006         if (!dns_nsec3_supportedhash(nsec3param.hash))
01007                 return (ISC_R_SUCCESS);
01008 
01009         optout = isoptout(db, ver, origin, rdata);
01010 
01011         dns_fixedname_init(&fixed);
01012         result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, name, origin,
01013                                     nsec3param.hash, nsec3param.iterations,
01014                                     nsec3param.salt, nsec3param.salt_length);
01015         check_result(result, "dns_nsec3_hashname()");
01016 
01017         /*
01018          * We don't use dns_db_find() here as it works with the choosen
01019          * nsec3 chain and we may also be called with uncommitted data
01020          * from dnssec-signzone so the secure status of the zone may not
01021          * be up to date.
01022          */
01023         dns_rdataset_init(&rdataset);
01024         hashname = dns_fixedname_name(&fixed);
01025         result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node);
01026         if (result == ISC_R_SUCCESS)
01027                 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
01028                                              0, 0, &rdataset, NULL);
01029         if (result != ISC_R_SUCCESS &&
01030             (!delegation || (empty && !optout) ||
01031              (!empty && dns_nsec_isset(types, dns_rdatatype_ds))))
01032         {
01033                 dns_name_format(name, namebuf, sizeof(namebuf));
01034                 dns_name_format(hashname, hashbuf, sizeof(hashbuf));
01035                 fprintf(stderr, "Missing NSEC3 record for %s (%s)\n",
01036                         namebuf, hashbuf);
01037         } else if (result == ISC_R_NOTFOUND &&
01038                    delegation && (!empty || optout))
01039         {
01040                 result = ISC_R_SUCCESS;
01041         } else if (result == ISC_R_SUCCESS) {
01042                 result = match_nsec3(name, mctx, &nsec3param, &rdataset,
01043                                      types, maxtype, rawhash, rhsize);
01044         }
01045 
01046         if (dns_rdataset_isassociated(&rdataset))
01047                 dns_rdataset_disassociate(&rdataset);
01048         if (node != NULL)
01049                 dns_db_detachnode(db, &node);
01050 
01051         return (result);
01052 }
01053 
01054 static isc_result_t
01055 verifynsec3s(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
01056              isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *nsec3paramset,
01057              isc_boolean_t delegation, isc_boolean_t empty,
01058              unsigned char types[8192], unsigned int maxtype)
01059 {
01060         isc_result_t result;
01061 
01062         for (result = dns_rdataset_first(nsec3paramset);
01063              result == ISC_R_SUCCESS;
01064              result = dns_rdataset_next(nsec3paramset)) {
01065                 dns_rdata_t rdata = DNS_RDATA_INIT;
01066 
01067                 dns_rdataset_current(nsec3paramset, &rdata);
01068                 result = verifynsec3(db, ver, origin, mctx, name, &rdata,
01069                                      delegation, empty, types, maxtype);
01070                 if (result != ISC_R_SUCCESS)
01071                         break;
01072         }
01073         if (result == ISC_R_NOMORE)
01074                 result = ISC_R_SUCCESS;
01075         return (result);
01076 }
01077 
01078 static void
01079 verifyset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
01080           isc_mem_t *mctx, dns_rdataset_t *rdataset, dns_name_t *name,
01081           dns_dbnode_t *node, dns_rdataset_t *keyrdataset,
01082           unsigned char *act_algorithms, unsigned char *bad_algorithms)
01083 {
01084         unsigned char set_algorithms[256];
01085         char namebuf[DNS_NAME_FORMATSIZE];
01086         char algbuf[80];
01087         char typebuf[80];
01088         dns_rdataset_t sigrdataset;
01089         dns_rdatasetiter_t *rdsiter = NULL;
01090         isc_result_t result;
01091         int i;
01092 
01093         dns_rdataset_init(&sigrdataset);
01094         result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
01095         check_result(result, "dns_db_allrdatasets()");
01096         for (result = dns_rdatasetiter_first(rdsiter);
01097              result == ISC_R_SUCCESS;
01098              result = dns_rdatasetiter_next(rdsiter)) {
01099                 dns_rdatasetiter_current(rdsiter, &sigrdataset);
01100                 if (sigrdataset.type == dns_rdatatype_rrsig &&
01101                     sigrdataset.covers == rdataset->type)
01102                         break;
01103                 dns_rdataset_disassociate(&sigrdataset);
01104         }
01105         if (result != ISC_R_SUCCESS) {
01106                 dns_name_format(name, namebuf, sizeof(namebuf));
01107                 type_format(rdataset->type, typebuf, sizeof(typebuf));
01108                 fprintf(stderr, "No signatures for %s/%s\n", namebuf, typebuf);
01109                 for (i = 0; i < 256; i++)
01110                         if (act_algorithms[i] != 0)
01111                                 bad_algorithms[i] = 1;
01112                 dns_rdatasetiter_destroy(&rdsiter);
01113                 return;
01114         }
01115 
01116         memset(set_algorithms, 0, sizeof(set_algorithms));
01117         for (result = dns_rdataset_first(&sigrdataset);
01118              result == ISC_R_SUCCESS;
01119              result = dns_rdataset_next(&sigrdataset)) {
01120                 dns_rdata_t rdata = DNS_RDATA_INIT;
01121                 dns_rdata_rrsig_t sig;
01122 
01123                 dns_rdataset_current(&sigrdataset, &rdata);
01124                 result = dns_rdata_tostruct(&rdata, &sig, NULL);
01125                 check_result(result, "dns_rdata_tostruct()");
01126                 if (rdataset->ttl != sig.originalttl) {
01127                         dns_name_format(name, namebuf, sizeof(namebuf));
01128                         type_format(rdataset->type, typebuf, sizeof(typebuf));
01129                         fprintf(stderr, "TTL mismatch for %s %s keytag %u\n",
01130                                 namebuf, typebuf, sig.keyid);
01131                         continue;
01132                 }
01133                 if ((set_algorithms[sig.algorithm] != 0) ||
01134                     (act_algorithms[sig.algorithm] == 0))
01135                         continue;
01136                 if (goodsig(origin, &rdata, name, keyrdataset, rdataset, mctx))
01137                         set_algorithms[sig.algorithm] = 1;
01138         }
01139         dns_rdatasetiter_destroy(&rdsiter);
01140         if (memcmp(set_algorithms, act_algorithms, sizeof(set_algorithms))) {
01141                 dns_name_format(name, namebuf, sizeof(namebuf));
01142                 type_format(rdataset->type, typebuf, sizeof(typebuf));
01143                 for (i = 0; i < 256; i++)
01144                         if ((act_algorithms[i] != 0) &&
01145                             (set_algorithms[i] == 0)) {
01146                                 dns_secalg_format(i, algbuf, sizeof(algbuf));
01147                                 fprintf(stderr, "No correct %s signature for "
01148                                         "%s %s\n", algbuf, namebuf, typebuf);
01149                                 bad_algorithms[i] = 1;
01150                         }
01151         }
01152         dns_rdataset_disassociate(&sigrdataset);
01153 }
01154 
01155 static isc_result_t
01156 verifynode(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
01157            isc_mem_t *mctx, dns_name_t *name, dns_dbnode_t *node,
01158            isc_boolean_t delegation, dns_rdataset_t *keyrdataset,
01159            unsigned char *act_algorithms, unsigned char *bad_algorithms,
01160            dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset,
01161            dns_name_t *nextname)
01162 {
01163         unsigned char types[8192];
01164         unsigned int maxtype = 0;
01165         dns_rdataset_t rdataset; dns_rdatasetiter_t *rdsiter = NULL;
01166         isc_result_t result, tresult;
01167 
01168         memset(types, 0, sizeof(types));
01169         result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
01170         check_result(result, "dns_db_allrdatasets()");
01171         result = dns_rdatasetiter_first(rdsiter);
01172         dns_rdataset_init(&rdataset);
01173         while (result == ISC_R_SUCCESS) {
01174                 dns_rdatasetiter_current(rdsiter, &rdataset);
01175                 /*
01176                  * If we are not at a delegation then everything should be
01177                  * signed.  If we are at a delegation then only the DS set
01178                  * is signed.  The NS set is not signed at a delegation but
01179                  * its existance is recorded in the bit map.  Anything else
01180                  * other than NSEC and DS is not signed at a delegation.
01181                  */
01182                 if (rdataset.type != dns_rdatatype_rrsig &&
01183                     rdataset.type != dns_rdatatype_dnskey &&
01184                     (!delegation || rdataset.type == dns_rdatatype_ds ||
01185                      rdataset.type == dns_rdatatype_nsec)) {
01186                         verifyset(db, ver, origin, mctx, &rdataset,
01187                                   name, node, keyrdataset,
01188                                   act_algorithms, bad_algorithms);
01189                         dns_nsec_setbit(types, rdataset.type, 1);
01190                         if (rdataset.type > maxtype)
01191                                 maxtype = rdataset.type;
01192                 } else if (rdataset.type != dns_rdatatype_rrsig &&
01193                            rdataset.type != dns_rdatatype_dnskey) {
01194                         if (rdataset.type == dns_rdatatype_ns)
01195                                 dns_nsec_setbit(types, rdataset.type, 1);
01196                         check_no_rrsig(db, ver, &rdataset, name, node);
01197                 } else
01198                         dns_nsec_setbit(types, rdataset.type, 1);
01199                 dns_rdataset_disassociate(&rdataset);
01200                 result = dns_rdatasetiter_next(rdsiter);
01201         }
01202         if (result != ISC_R_NOMORE)
01203                 fatal("rdataset iteration failed: %s",
01204                       isc_result_totext(result));
01205         dns_rdatasetiter_destroy(&rdsiter);
01206 
01207         result = ISC_R_SUCCESS;
01208 
01209         if (nsecset != NULL && dns_rdataset_isassociated(nsecset))
01210                 result = verifynsec(db, ver, name, node, nextname);
01211 
01212         if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) {
01213                 tresult = verifynsec3s(db, ver, origin, mctx, name,
01214                                        nsec3paramset, delegation, ISC_FALSE,
01215                                        types, maxtype);
01216                 if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS)
01217                         result = tresult;
01218         }
01219         return (result);
01220 }
01221 
01222 static isc_boolean_t
01223 is_empty(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) {
01224         dns_rdatasetiter_t *rdsiter = NULL;
01225         isc_result_t result;
01226 
01227         result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
01228         check_result(result, "dns_db_allrdatasets()");
01229         result = dns_rdatasetiter_first(rdsiter);
01230         dns_rdatasetiter_destroy(&rdsiter);
01231         if (result == ISC_R_NOMORE)
01232                 return (ISC_TRUE);
01233         return (ISC_FALSE);
01234 }
01235 
01236 static void
01237 check_no_nsec(dns_name_t *name, dns_dbnode_t *node, dns_db_t *db,
01238               dns_dbversion_t *ver)
01239 {
01240         dns_rdataset_t rdataset;
01241         isc_result_t result;
01242 
01243         dns_rdataset_init(&rdataset);
01244         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
01245                                      0, 0, &rdataset, NULL);
01246         if (result != ISC_R_NOTFOUND) {
01247                 char namebuf[DNS_NAME_FORMATSIZE];
01248                 dns_name_format(name, namebuf, sizeof(namebuf));
01249                 fatal("unexpected NSEC RRset at %s\n", namebuf);
01250         }
01251 
01252         if (dns_rdataset_isassociated(&rdataset))
01253                 dns_rdataset_disassociate(&rdataset);
01254 }
01255 
01256 static isc_boolean_t
01257 newchain(const struct nsec3_chain_fixed *first,
01258          const struct nsec3_chain_fixed *e)
01259 {
01260         if (first->hash != e->hash ||
01261             first->iterations != e->iterations ||
01262             first->salt_length != e->salt_length ||
01263             first->next_length != e->next_length ||
01264             memcmp(first + 1, e + 1, first->salt_length) != 0)
01265                 return (ISC_TRUE);
01266         return (ISC_FALSE);
01267 }
01268 
01269 static void
01270 free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) {
01271         size_t len;
01272 
01273         len = sizeof(*e) + e->salt_length + 2 * e->next_length;
01274         isc_mem_put(mctx, e, len);
01275 }
01276 
01277 static isc_boolean_t
01278 checknext(const struct nsec3_chain_fixed *first,
01279           const struct nsec3_chain_fixed *e)
01280 {
01281         char buf[512];
01282         const unsigned char *d1 = (const unsigned char *)(first + 1);
01283         const unsigned char *d2 = (const unsigned char *)(e + 1);
01284         isc_buffer_t b;
01285         isc_region_t sr;
01286 
01287         d1 += first->salt_length + first->next_length;
01288         d2 += e->salt_length;
01289 
01290         if (memcmp(d1, d2, first->next_length) == 0)
01291                 return (ISC_TRUE);
01292 
01293         DE_CONST(d1 - first->next_length, sr.base);
01294         sr.length = first->next_length;
01295         isc_buffer_init(&b, buf, sizeof(buf));
01296         isc_base32hex_totext(&sr, 1, "", &b);
01297         fprintf(stderr, "Break in NSEC3 chain at: %.*s\n",
01298                 (int) isc_buffer_usedlength(&b), buf);
01299 
01300         DE_CONST(d1, sr.base);
01301         sr.length = first->next_length;
01302         isc_buffer_init(&b, buf, sizeof(buf));
01303         isc_base32hex_totext(&sr, 1, "", &b);
01304         fprintf(stderr, "Expected: %.*s\n", (int) isc_buffer_usedlength(&b),
01305                 buf);
01306 
01307         DE_CONST(d2, sr.base);
01308         sr.length = first->next_length;
01309         isc_buffer_init(&b, buf, sizeof(buf));
01310         isc_base32hex_totext(&sr, 1, "", &b);
01311         fprintf(stderr, "Found: %.*s\n", (int) isc_buffer_usedlength(&b), buf);
01312 
01313         return (ISC_FALSE);
01314 }
01315 
01316 #define EXPECTEDANDFOUND "Expected and found NSEC3 chains not equal\n"
01317 
01318 static isc_result_t
01319 verify_nsec3_chains(isc_mem_t *mctx) {
01320         isc_result_t result = ISC_R_SUCCESS;
01321         struct nsec3_chain_fixed *e, *f = NULL;
01322         struct nsec3_chain_fixed *first = NULL, *prev = NULL;
01323 
01324         while ((e = isc_heap_element(expected_chains, 1)) != NULL) {
01325                 isc_heap_delete(expected_chains, 1);
01326                 if (f == NULL)
01327                         f = isc_heap_element(found_chains, 1);
01328                 if (f != NULL) {
01329                         isc_heap_delete(found_chains, 1);
01330 
01331                         /*
01332                          * Check that they match.
01333                          */
01334                         if (chain_equal(e, f)) {
01335                                 free_element(mctx, f);
01336                                 f = NULL;
01337                         } else {
01338                                 if (result == ISC_R_SUCCESS)
01339                                         fprintf(stderr, EXPECTEDANDFOUND);
01340                                 result = ISC_R_FAILURE;
01341                                 /*
01342                                  * Attempt to resync found_chain.
01343                                  */
01344                                 while (f != NULL && !chain_compare(e, f)) {
01345                                         free_element(mctx, f);
01346                                         f = isc_heap_element(found_chains, 1);
01347                                         if (f != NULL)
01348                                                 isc_heap_delete(found_chains, 1);
01349                                         if (f != NULL && chain_equal(e, f)) {
01350                                                 free_element(mctx, f);
01351                                                 f = NULL;
01352                                                 break;
01353                                         }
01354                                 }
01355                         }
01356                 } else if (result == ISC_R_SUCCESS) {
01357                         fprintf(stderr, EXPECTEDANDFOUND);
01358                         result = ISC_R_FAILURE;
01359                 }
01360                 if (first == NULL || newchain(first, e)) {
01361                         if (prev != NULL) {
01362                                 if (!checknext(prev, first))
01363                                         result = ISC_R_FAILURE;
01364                                 if (prev != first)
01365                                         free_element(mctx, prev);
01366                         }
01367                         if (first != NULL)
01368                                 free_element(mctx, first);
01369                         prev = first = e;
01370                         continue;
01371                 }
01372                 if (!checknext(prev, e))
01373                         result = ISC_R_FAILURE;
01374                 if (prev != first)
01375                         free_element(mctx, prev);
01376                 prev = e;
01377         }
01378         if (prev != NULL) {
01379                 if (!checknext(prev, first))
01380                         result = ISC_R_FAILURE;
01381                 if (prev != first)
01382                         free_element(mctx, prev);
01383         }
01384         if (first != NULL)
01385                 free_element(mctx, first);
01386         do {
01387                 if (f != NULL) {
01388                         if (result == ISC_R_SUCCESS) {
01389                                 fprintf(stderr, EXPECTEDANDFOUND);
01390                                 result = ISC_R_FAILURE;
01391                         }
01392                         free_element(mctx, f);
01393                 }
01394                 f = isc_heap_element(found_chains, 1);
01395                 if (f != NULL)
01396                         isc_heap_delete(found_chains, 1);
01397         } while (f != NULL);
01398 
01399         return (result);
01400 }
01401 
01402 static isc_result_t
01403 verifyemptynodes(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
01404                  isc_mem_t *mctx, dns_name_t *name, dns_name_t *prevname,
01405                  isc_boolean_t isdelegation, dns_rdataset_t *nsec3paramset)
01406 {
01407         dns_namereln_t reln;
01408         int order;
01409         unsigned int labels, nlabels, i;
01410         dns_name_t suffix;
01411         isc_result_t result = ISC_R_SUCCESS, tresult;
01412 
01413         reln = dns_name_fullcompare(prevname, name, &order, &labels);
01414         if (order >= 0)
01415                 return (result);
01416 
01417         nlabels = dns_name_countlabels(name);
01418 
01419         if (reln == dns_namereln_commonancestor ||
01420             reln == dns_namereln_contains) {
01421                 dns_name_init(&suffix, NULL);
01422                 for (i = labels + 1; i < nlabels; i++) {
01423                         dns_name_getlabelsequence(name, nlabels - i, i,
01424                                                   &suffix);
01425                         if (nsec3paramset != NULL &&
01426                              dns_rdataset_isassociated(nsec3paramset)) {
01427                                 tresult = verifynsec3s(db, ver, origin, mctx,
01428                                                        &suffix, nsec3paramset,
01429                                                        isdelegation, ISC_TRUE,
01430                                                        NULL, 0);
01431                                 if (result == ISC_R_SUCCESS &&
01432                                     tresult != ISC_R_SUCCESS)
01433                                         result = tresult;
01434                         }
01435                 }
01436         }
01437         return (result);
01438 }
01439 
01440 /*%
01441  * Verify that certain things are sane:
01442  *
01443  *   The apex has a DNSKEY record with at least one KSK, and at least
01444  *   one ZSK if the -x flag was not used.
01445  *
01446  *   The DNSKEY record was signed with at least one of the KSKs in this
01447  *   set.
01448  *
01449  *   The rest of the zone was signed with at least one of the ZSKs
01450  *   present in the DNSKEY RRSET.
01451  */
01452 void
01453 verifyzone(dns_db_t *db, dns_dbversion_t *ver,
01454            dns_name_t *origin, isc_mem_t *mctx,
01455            isc_boolean_t ignore_kskflag, isc_boolean_t keyset_kskonly)
01456 {
01457         char algbuf[80];
01458         dns_dbiterator_t *dbiter = NULL;
01459         dns_dbnode_t *node = NULL, *nextnode = NULL;
01460         dns_fixedname_t fname, fnextname, fprevname, fzonecut;
01461         dns_name_t *name, *nextname, *prevname, *zonecut;
01462         dns_rdata_dnskey_t dnskey;
01463         dns_rdata_t rdata = DNS_RDATA_INIT;
01464         dns_rdataset_t keyset, soaset;
01465         dns_rdataset_t keysigs, soasigs;
01466         dns_rdataset_t nsecset, nsecsigs;
01467         dns_rdataset_t nsec3paramset, nsec3paramsigs;
01468         int i;
01469         isc_boolean_t done = ISC_FALSE;
01470         isc_boolean_t first = ISC_TRUE;
01471         isc_boolean_t goodksk = ISC_FALSE;
01472         isc_boolean_t goodzsk = ISC_FALSE;
01473         isc_result_t result, vresult = ISC_R_UNSET;
01474         unsigned char revoked_ksk[256];
01475         unsigned char revoked_zsk[256];
01476         unsigned char standby_ksk[256];
01477         unsigned char standby_zsk[256];
01478         unsigned char ksk_algorithms[256];
01479         unsigned char zsk_algorithms[256];
01480         unsigned char bad_algorithms[256];
01481         unsigned char act_algorithms[256];
01482 
01483         result = isc_heap_create(mctx, chain_compare, NULL, 1024,
01484                                  &expected_chains);
01485         check_result(result, "isc_heap_create()");
01486         result = isc_heap_create(mctx, chain_compare, NULL, 1024,
01487                                  &found_chains);
01488         check_result(result, "isc_heap_create()");
01489 
01490         result = dns_db_findnode(db, origin, ISC_FALSE, &node);
01491         if (result != ISC_R_SUCCESS)
01492                 fatal("failed to find the zone's origin: %s",
01493                       isc_result_totext(result));
01494 
01495         dns_rdataset_init(&keyset);
01496         dns_rdataset_init(&keysigs);
01497         dns_rdataset_init(&soaset);
01498         dns_rdataset_init(&soasigs);
01499         dns_rdataset_init(&nsecset);
01500         dns_rdataset_init(&nsecsigs);
01501         dns_rdataset_init(&nsec3paramset);
01502         dns_rdataset_init(&nsec3paramsigs);
01503         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
01504                                      0, 0, &keyset, &keysigs);
01505         if (result != ISC_R_SUCCESS)
01506                 fatal("Zone contains no DNSSEC keys\n");
01507 
01508         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
01509                                      0, 0, &soaset, &soasigs);
01510         if (result != ISC_R_SUCCESS)
01511                 fatal("Zone contains no SOA record\n");
01512 
01513         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
01514                                      0, 0, &nsecset, &nsecsigs);
01515         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
01516                 fatal("NSEC lookup failed\n");
01517 
01518         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
01519                                      0, 0, &nsec3paramset, &nsec3paramsigs);
01520         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
01521                 fatal("NSEC3PARAM lookup failed\n");
01522 
01523         if (!dns_rdataset_isassociated(&keysigs))
01524                 fatal("DNSKEY is not signed (keys offline or inactive?)\n");
01525 
01526         if (!dns_rdataset_isassociated(&soasigs))
01527                 fatal("SOA is not signed (keys offline or inactive?)\n");
01528 
01529         if (dns_rdataset_isassociated(&nsecset) &&
01530             !dns_rdataset_isassociated(&nsecsigs))
01531                 fatal("NSEC is not signed (keys offline or inactive?)\n");
01532 
01533         if (dns_rdataset_isassociated(&nsec3paramset) &&
01534             !dns_rdataset_isassociated(&nsec3paramsigs))
01535                 fatal("NSEC3PARAM is not signed (keys offline or inactive?)\n");
01536 
01537         if (!dns_rdataset_isassociated(&nsecset) &&
01538             !dns_rdataset_isassociated(&nsec3paramset))
01539                 fatal("No valid NSEC/NSEC3 chain for testing\n");
01540 
01541         dns_db_detachnode(db, &node);
01542 
01543         memset(revoked_ksk, 0, sizeof(revoked_ksk));
01544         memset(revoked_zsk, 0, sizeof(revoked_zsk));
01545         memset(standby_ksk, 0, sizeof(standby_ksk));
01546         memset(standby_zsk, 0, sizeof(standby_zsk));
01547         memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
01548         memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
01549         memset(bad_algorithms, 0, sizeof(bad_algorithms));
01550         memset(act_algorithms, 0, sizeof(act_algorithms));
01551 
01552         /*
01553          * Check that the DNSKEY RR has at least one self signing KSK
01554          * and one ZSK per algorithm in it (or, if -x was used, one
01555          * self-signing KSK).
01556          */
01557         for (result = dns_rdataset_first(&keyset);
01558              result == ISC_R_SUCCESS;
01559              result = dns_rdataset_next(&keyset)) {
01560                 dns_rdataset_current(&keyset, &rdata);
01561                 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
01562                 check_result(result, "dns_rdata_tostruct");
01563 
01564                 if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
01565                         ;
01566                 else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
01567                         if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
01568                             !dns_dnssec_selfsigns(&rdata, origin, &keyset,
01569                                                   &keysigs, ISC_FALSE,
01570                                                   mctx)) {
01571                                 char namebuf[DNS_NAME_FORMATSIZE];
01572                                 char buffer[1024];
01573                                 isc_buffer_t buf;
01574 
01575                                 dns_name_format(origin, namebuf,
01576                                                 sizeof(namebuf));
01577                                 isc_buffer_init(&buf, buffer, sizeof(buffer));
01578                                 result = dns_rdata_totext(&rdata, NULL, &buf);
01579                                 check_result(result, "dns_rdata_totext");
01580                                 fatal("revoked KSK is not self signed:\n"
01581                                       "%s DNSKEY %.*s", namebuf,
01582                                       (int)isc_buffer_usedlength(&buf), buffer);
01583                         }
01584                         if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
01585                              revoked_ksk[dnskey.algorithm] != 255)
01586                                 revoked_ksk[dnskey.algorithm]++;
01587                         else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
01588                                  revoked_zsk[dnskey.algorithm] != 255)
01589                                 revoked_zsk[dnskey.algorithm]++;
01590                 } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
01591                         if (dns_dnssec_selfsigns(&rdata, origin, &keyset,
01592                                                  &keysigs, ISC_FALSE, mctx)) {
01593                                 if (ksk_algorithms[dnskey.algorithm] != 255)
01594                                         ksk_algorithms[dnskey.algorithm]++;
01595                                 goodksk = ISC_TRUE;
01596                         } else {
01597                                 if (standby_ksk[dnskey.algorithm] != 255)
01598                                         standby_ksk[dnskey.algorithm]++;
01599                         }
01600                 } else if (dns_dnssec_selfsigns(&rdata, origin, &keyset,
01601                                                 &keysigs, ISC_FALSE, mctx)) {
01602                         if (zsk_algorithms[dnskey.algorithm] != 255)
01603                                 zsk_algorithms[dnskey.algorithm]++;
01604                         goodzsk = ISC_TRUE;
01605                 } else if (dns_dnssec_signs(&rdata, origin, &soaset,
01606                                             &soasigs, ISC_FALSE, mctx)) {
01607                         if (zsk_algorithms[dnskey.algorithm] != 255)
01608                                 zsk_algorithms[dnskey.algorithm]++;
01609                 } else {
01610                         if (standby_zsk[dnskey.algorithm] != 255)
01611                                 standby_zsk[dnskey.algorithm]++;
01612                 }
01613                 dns_rdata_freestruct(&dnskey);
01614                 dns_rdata_reset(&rdata);
01615         }
01616         dns_rdataset_disassociate(&keysigs);
01617         dns_rdataset_disassociate(&soaset);
01618         dns_rdataset_disassociate(&soasigs);
01619         if (dns_rdataset_isassociated(&nsecsigs))
01620                 dns_rdataset_disassociate(&nsecsigs);
01621         if (dns_rdataset_isassociated(&nsec3paramsigs))
01622                 dns_rdataset_disassociate(&nsec3paramsigs);
01623 
01624         if (ignore_kskflag ) {
01625                 if (!goodksk && !goodzsk)
01626                         fatal("No self-signed DNSKEY found.");
01627         } else if (!goodksk)
01628                 fatal("No self-signed KSK DNSKEY found.  Supply an active\n"
01629                       "key with the KSK flag set, or use '-P'.");
01630 
01631         fprintf(stderr, "Verifying the zone using the following algorithms:");
01632         for (i = 0; i < 256; i++) {
01633                 if (ignore_kskflag)
01634                         act_algorithms[i] = (ksk_algorithms[i] != 0 ||
01635                                              zsk_algorithms[i] != 0) ? 1 : 0;
01636                 else
01637                         act_algorithms[i] = ksk_algorithms[i] != 0 ? 1 : 0;
01638                 if (act_algorithms[i] != 0) {
01639                         dns_secalg_format(i, algbuf, sizeof(algbuf));
01640                         fprintf(stderr, " %s", algbuf);
01641                 }
01642         }
01643         fprintf(stderr, ".\n");
01644 
01645         if (!ignore_kskflag && !keyset_kskonly) {
01646                 for (i = 0; i < 256; i++) {
01647                         /*
01648                          * The counts should both be zero or both be non-zero.
01649                          * Mark the algorithm as bad if this is not met.
01650                          */
01651                         if ((ksk_algorithms[i] != 0) ==
01652                             (zsk_algorithms[i] != 0))
01653                                 continue;
01654                         dns_secalg_format(i, algbuf, sizeof(algbuf));
01655                         fprintf(stderr, "Missing %s for algorithm %s\n",
01656                                 (ksk_algorithms[i] != 0)
01657                                    ? "ZSK"
01658                                    : "self-signed KSK",
01659                                 algbuf);
01660                         bad_algorithms[i] = 1;
01661                 }
01662         }
01663 
01664         /*
01665          * Check that all the other records were signed by keys that are
01666          * present in the DNSKEY RRSET.
01667          */
01668 
01669         dns_fixedname_init(&fname);
01670         name = dns_fixedname_name(&fname);
01671         dns_fixedname_init(&fnextname);
01672         nextname = dns_fixedname_name(&fnextname);
01673         dns_fixedname_init(&fprevname);
01674         prevname = NULL;
01675         dns_fixedname_init(&fzonecut);
01676         zonecut = NULL;
01677 
01678         result = dns_db_createiterator(db, DNS_DB_NONSEC3, &dbiter);
01679         check_result(result, "dns_db_createiterator()");
01680 
01681         result = dns_dbiterator_first(dbiter);
01682         check_result(result, "dns_dbiterator_first()");
01683 
01684         while (!done) {
01685                 isc_boolean_t isdelegation = ISC_FALSE;
01686 
01687                 result = dns_dbiterator_current(dbiter, &node, name);
01688                 check_dns_dbiterator_current(result);
01689                 if (!dns_name_issubdomain(name, origin)) {
01690                         check_no_nsec(name, node, db, ver);
01691                         dns_db_detachnode(db, &node);
01692                         result = dns_dbiterator_next(dbiter);
01693                         if (result == ISC_R_NOMORE)
01694                                 done = ISC_TRUE;
01695                         else
01696                                 check_result(result, "dns_dbiterator_next()");
01697                         continue;
01698                 }
01699                 if (is_delegation(db, ver, origin, name, node, NULL)) {
01700                         zonecut = dns_fixedname_name(&fzonecut);
01701                         dns_name_copy(name, zonecut, NULL);
01702                         isdelegation = ISC_TRUE;
01703                 }
01704                 nextnode = NULL;
01705                 result = dns_dbiterator_next(dbiter);
01706                 while (result == ISC_R_SUCCESS) {
01707                         result = dns_dbiterator_current(dbiter, &nextnode,
01708                                                         nextname);
01709                         check_dns_dbiterator_current(result);
01710                         if (!dns_name_issubdomain(nextname, origin) ||
01711                             (zonecut != NULL &&
01712                              dns_name_issubdomain(nextname, zonecut)))
01713                         {
01714                                 check_no_nsec(nextname, nextnode, db, ver);
01715                                 dns_db_detachnode(db, &nextnode);
01716                                 result = dns_dbiterator_next(dbiter);
01717                                 continue;
01718                         }
01719                         if (is_empty(db, ver, nextnode)) {
01720                                 dns_db_detachnode(db, &nextnode);
01721                                 result = dns_dbiterator_next(dbiter);
01722                                 continue;
01723                         }
01724                         dns_db_detachnode(db, &nextnode);
01725                         break;
01726                 }
01727                 if (result == ISC_R_NOMORE) {
01728                         done = ISC_TRUE;
01729                         nextname = origin;
01730                 } else if (result != ISC_R_SUCCESS)
01731                         fatal("iterating through the database failed: %s",
01732                               isc_result_totext(result));
01733                 result = verifynode(db, ver, origin, mctx, name, node,
01734                                     isdelegation, &keyset, act_algorithms,
01735                                     bad_algorithms, &nsecset, &nsec3paramset,
01736                                     nextname);
01737                 if (vresult == ISC_R_UNSET)
01738                         vresult = ISC_R_SUCCESS;
01739                 if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS)
01740                         vresult = result;
01741                 if (prevname != NULL) {
01742                         result = verifyemptynodes(db, ver, origin, mctx, name,
01743                                                   prevname, isdelegation,
01744                                                   &nsec3paramset);
01745                 } else
01746                         prevname = dns_fixedname_name(&fprevname);
01747                 dns_name_copy(name, prevname, NULL);
01748                 if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS)
01749                         vresult = result;
01750                 dns_db_detachnode(db, &node);
01751         }
01752 
01753         dns_dbiterator_destroy(&dbiter);
01754 
01755         result = dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbiter);
01756         check_result(result, "dns_db_createiterator()");
01757 
01758         for (result = dns_dbiterator_first(dbiter);
01759              result == ISC_R_SUCCESS;
01760              result = dns_dbiterator_next(dbiter) ) {
01761                 result = dns_dbiterator_current(dbiter, &node, name);
01762                 check_dns_dbiterator_current(result);
01763                 result = verifynode(db, ver, origin, mctx, name, node,
01764                                     ISC_FALSE, &keyset, act_algorithms,
01765                                     bad_algorithms, NULL, NULL, NULL);
01766                 check_result(result, "verifynode");
01767                 record_found(db, ver, mctx, name, node, &nsec3paramset);
01768                 dns_db_detachnode(db, &node);
01769         }
01770         dns_dbiterator_destroy(&dbiter);
01771 
01772         dns_rdataset_disassociate(&keyset);
01773         if (dns_rdataset_isassociated(&nsecset))
01774                 dns_rdataset_disassociate(&nsecset);
01775         if (dns_rdataset_isassociated(&nsec3paramset))
01776                 dns_rdataset_disassociate(&nsec3paramset);
01777 
01778         result = verify_nsec3_chains(mctx);
01779         if (vresult == ISC_R_UNSET)
01780                 vresult = ISC_R_SUCCESS;
01781         if (result != ISC_R_SUCCESS && vresult == ISC_R_SUCCESS)
01782                 vresult = result;
01783         isc_heap_destroy(&expected_chains);
01784         isc_heap_destroy(&found_chains);
01785 
01786         /*
01787          * If we made it this far, we have what we consider a properly signed
01788          * zone.  Set the good flag.
01789          */
01790         for (i = 0; i < 256; i++) {
01791                 if (bad_algorithms[i] != 0) {
01792                         if (first)
01793                                 fprintf(stderr, "The zone is not fully signed "
01794                                         "for the following algorithms:");
01795                         dns_secalg_format(i, algbuf, sizeof(algbuf));
01796                         fprintf(stderr, " %s", algbuf);
01797                         first = ISC_FALSE;
01798                 }
01799         }
01800         if (!first) {
01801                 fprintf(stderr, ".\n");
01802                 fatal("DNSSEC completeness test failed.");
01803         }
01804 
01805         if (vresult != ISC_R_SUCCESS)
01806                 fatal("DNSSEC completeness test failed (%s).",
01807                       dns_result_totext(vresult));
01808 
01809         if (goodksk || ignore_kskflag) {
01810                 /*
01811                  * Print the success summary.
01812                  */
01813                 fprintf(stderr, "Zone fully signed:\n");
01814                 for (i = 0; i < 256; i++) {
01815                         if ((ksk_algorithms[i] != 0) ||
01816                             (standby_ksk[i] != 0) ||
01817                             (revoked_zsk[i] != 0) ||
01818                             (zsk_algorithms[i] != 0) ||
01819                             (standby_zsk[i] != 0) ||
01820                             (revoked_zsk[i] != 0)) {
01821                                 dns_secalg_format(i, algbuf, sizeof(algbuf));
01822                                 fprintf(stderr, "Algorithm: %s: KSKs: "
01823                                         "%u active, %u stand-by, %u revoked\n",
01824                                         algbuf, ksk_algorithms[i],
01825                                         standby_ksk[i], revoked_ksk[i]);
01826                                 fprintf(stderr, "%*sZSKs: "
01827                                         "%u active, %u %s, %u revoked\n",
01828                                         (int) strlen(algbuf) + 13, "",
01829                                         zsk_algorithms[i],
01830                                         standby_zsk[i],
01831                                         keyset_kskonly ? "present" : "stand-by",
01832                                         revoked_zsk[i]);
01833                         }
01834                 }
01835         }
01836 }

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