00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00068
00069
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
00165
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
00186
00187
00188
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
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
00304 return(0);
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
00353
00354
00355
00356
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
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);
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
00455
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
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
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
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
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
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
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
00815
00816 result = record_nsec3(rawhash, &nsec3, mctx, expected_chains);
00817 check_result(result, "record_nsec3()");
00818
00819
00820
00821
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
00912
00913
00914 if (!innsec3params(&nsec3, nsec3paramset))
00915 continue;
00916
00917
00918
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
01019
01020
01021
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
01177
01178
01179
01180
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
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
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
01442
01443
01444
01445
01446
01447
01448
01449
01450
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
01554
01555
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
01649
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
01666
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
01788
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
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 }