1 1.1 christos /* $NetBSD: zoneverify.c,v 1.1 2024/02/18 20:57:34 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * 6 1.1 christos * SPDX-License-Identifier: MPL-2.0 7 1.1 christos * 8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public 9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this 10 1.1 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 1.1 christos * 12 1.1 christos * See the COPYRIGHT file distributed with this work for additional 13 1.1 christos * information regarding copyright ownership. 14 1.1 christos */ 15 1.1 christos 16 1.1 christos /*! \file */ 17 1.1 christos 18 1.1 christos #include <inttypes.h> 19 1.1 christos #include <stdarg.h> 20 1.1 christos #include <stdbool.h> 21 1.1 christos #include <stdio.h> 22 1.1 christos #include <string.h> 23 1.1 christos 24 1.1 christos #include <isc/base32.h> 25 1.1 christos #include <isc/buffer.h> 26 1.1 christos #include <isc/heap.h> 27 1.1 christos #include <isc/iterated_hash.h> 28 1.1 christos #include <isc/log.h> 29 1.1 christos #include <isc/mem.h> 30 1.1 christos #include <isc/region.h> 31 1.1 christos #include <isc/result.h> 32 1.1 christos #include <isc/types.h> 33 1.1 christos #include <isc/util.h> 34 1.1 christos 35 1.1 christos #include <dns/db.h> 36 1.1 christos #include <dns/dbiterator.h> 37 1.1 christos #include <dns/dnssec.h> 38 1.1 christos #include <dns/fixedname.h> 39 1.1 christos #include <dns/keytable.h> 40 1.1 christos #include <dns/keyvalues.h> 41 1.1 christos #include <dns/log.h> 42 1.1 christos #include <dns/name.h> 43 1.1 christos #include <dns/nsec.h> 44 1.1 christos #include <dns/nsec3.h> 45 1.1 christos #include <dns/rdata.h> 46 1.1 christos #include <dns/rdataset.h> 47 1.1 christos #include <dns/rdatasetiter.h> 48 1.1 christos #include <dns/rdatastruct.h> 49 1.1 christos #include <dns/rdatatype.h> 50 1.1 christos #include <dns/result.h> 51 1.1 christos #include <dns/secalg.h> 52 1.1 christos #include <dns/types.h> 53 1.1 christos #include <dns/zone.h> 54 1.1 christos #include <dns/zoneverify.h> 55 1.1 christos 56 1.1 christos #include <dst/dst.h> 57 1.1 christos 58 1.1 christos typedef struct vctx { 59 1.1 christos isc_mem_t *mctx; 60 1.1 christos dns_zone_t *zone; 61 1.1 christos dns_db_t *db; 62 1.1 christos dns_dbversion_t *ver; 63 1.1 christos dns_name_t *origin; 64 1.1 christos dns_keytable_t *secroots; 65 1.1 christos bool goodksk; 66 1.1 christos bool goodzsk; 67 1.1 christos dns_rdataset_t keyset; 68 1.1 christos dns_rdataset_t keysigs; 69 1.1 christos dns_rdataset_t soaset; 70 1.1 christos dns_rdataset_t soasigs; 71 1.1 christos dns_rdataset_t nsecset; 72 1.1 christos dns_rdataset_t nsecsigs; 73 1.1 christos dns_rdataset_t nsec3paramset; 74 1.1 christos dns_rdataset_t nsec3paramsigs; 75 1.1 christos unsigned char revoked_ksk[256]; 76 1.1 christos unsigned char revoked_zsk[256]; 77 1.1 christos unsigned char standby_ksk[256]; 78 1.1 christos unsigned char standby_zsk[256]; 79 1.1 christos unsigned char ksk_algorithms[256]; 80 1.1 christos unsigned char zsk_algorithms[256]; 81 1.1 christos unsigned char bad_algorithms[256]; 82 1.1 christos unsigned char act_algorithms[256]; 83 1.1 christos isc_heap_t *expected_chains; 84 1.1 christos isc_heap_t *found_chains; 85 1.1 christos } vctx_t; 86 1.1 christos 87 1.1 christos struct nsec3_chain_fixed { 88 1.1 christos uint8_t hash; 89 1.1 christos uint8_t salt_length; 90 1.1 christos uint8_t next_length; 91 1.1 christos uint16_t iterations; 92 1.1 christos /* 93 1.1 christos * The following non-fixed-length data is stored in memory after the 94 1.1 christos * fields declared above for each NSEC3 chain element: 95 1.1 christos * 96 1.1 christos * unsigned char salt[salt_length]; 97 1.1 christos * unsigned char owner[next_length]; 98 1.1 christos * unsigned char next[next_length]; 99 1.1 christos */ 100 1.1 christos }; 101 1.1 christos 102 1.1 christos /* 103 1.1 christos * Helper function used to calculate length of variable-length 104 1.1 christos * data section in object pointed to by 'chain'. 105 1.1 christos */ 106 1.1 christos static size_t 107 1.1 christos chain_length(struct nsec3_chain_fixed *chain) { 108 1.1 christos return (chain->salt_length + 2 * chain->next_length); 109 1.1 christos } 110 1.1 christos 111 1.1 christos /*% 112 1.1 christos * Log a zone verification error described by 'fmt' and the variable arguments 113 1.1 christos * following it. Either use dns_zone_logv() or print to stderr, depending on 114 1.1 christos * whether the function was invoked from within named or by a standalone tool, 115 1.1 christos * respectively. 116 1.1 christos */ 117 1.1 christos static void 118 1.1 christos zoneverify_log_error(const vctx_t *vctx, const char *fmt, ...) { 119 1.1 christos va_list ap; 120 1.1 christos 121 1.1 christos va_start(ap, fmt); 122 1.1 christos if (vctx->zone != NULL) { 123 1.1 christos dns_zone_logv(vctx->zone, DNS_LOGCATEGORY_GENERAL, 124 1.1 christos ISC_LOG_ERROR, NULL, fmt, ap); 125 1.1 christos } else { 126 1.1 christos vfprintf(stderr, fmt, ap); 127 1.1 christos fprintf(stderr, "\n"); 128 1.1 christos } 129 1.1 christos va_end(ap); 130 1.1 christos } 131 1.1 christos 132 1.1 christos static bool 133 1.1 christos is_delegation(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node, 134 1.1 christos uint32_t *ttlp) { 135 1.1 christos dns_rdataset_t nsset; 136 1.1 christos isc_result_t result; 137 1.1 christos 138 1.1 christos if (dns_name_equal(name, vctx->origin)) { 139 1.1 christos return (false); 140 1.1 christos } 141 1.1 christos 142 1.1 christos dns_rdataset_init(&nsset); 143 1.1 christos result = dns_db_findrdataset(vctx->db, node, vctx->ver, 144 1.1 christos dns_rdatatype_ns, 0, 0, &nsset, NULL); 145 1.1 christos if (dns_rdataset_isassociated(&nsset)) { 146 1.1 christos if (ttlp != NULL) { 147 1.1 christos *ttlp = nsset.ttl; 148 1.1 christos } 149 1.1 christos dns_rdataset_disassociate(&nsset); 150 1.1 christos } 151 1.1 christos 152 1.1 christos return ((result == ISC_R_SUCCESS)); 153 1.1 christos } 154 1.1 christos 155 1.1 christos /*% 156 1.1 christos * Return true if version 'ver' of database 'db' contains a DNAME RRset at 157 1.1 christos * 'node'; return false otherwise. 158 1.1 christos */ 159 1.1 christos static bool 160 1.1 christos has_dname(const vctx_t *vctx, dns_dbnode_t *node) { 161 1.1 christos dns_rdataset_t dnameset; 162 1.1 christos isc_result_t result; 163 1.1 christos 164 1.1 christos dns_rdataset_init(&dnameset); 165 1.1 christos result = dns_db_findrdataset(vctx->db, node, vctx->ver, 166 1.1 christos dns_rdatatype_dname, 0, 0, &dnameset, 167 1.1 christos NULL); 168 1.1 christos if (dns_rdataset_isassociated(&dnameset)) { 169 1.1 christos dns_rdataset_disassociate(&dnameset); 170 1.1 christos } 171 1.1 christos 172 1.1 christos return ((result == ISC_R_SUCCESS)); 173 1.1 christos } 174 1.1 christos 175 1.1 christos static bool 176 1.1 christos goodsig(const vctx_t *vctx, dns_rdata_t *sigrdata, const dns_name_t *name, 177 1.1 christos dst_key_t **dstkeys, size_t nkeys, dns_rdataset_t *rdataset) { 178 1.1 christos dns_rdata_rrsig_t sig; 179 1.1 christos isc_result_t result; 180 1.1 christos 181 1.1 christos result = dns_rdata_tostruct(sigrdata, &sig, NULL); 182 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 183 1.1 christos 184 1.1 christos for (size_t key = 0; key < nkeys; key++) { 185 1.1 christos if (sig.algorithm != dst_key_alg(dstkeys[key]) || 186 1.1 christos sig.keyid != dst_key_id(dstkeys[key]) || 187 1.1 christos !dns_name_equal(&sig.signer, vctx->origin)) 188 1.1 christos { 189 1.1 christos continue; 190 1.1 christos } 191 1.1 christos result = dns_dnssec_verify(name, rdataset, dstkeys[key], false, 192 1.1 christos 0, vctx->mctx, sigrdata, NULL); 193 1.1 christos if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) { 194 1.1 christos return (true); 195 1.1 christos } 196 1.1 christos } 197 1.1 christos return (false); 198 1.1 christos } 199 1.1 christos 200 1.1 christos static bool 201 1.1 christos nsec_bitmap_equal(dns_rdata_nsec_t *nsec, dns_rdata_t *rdata) { 202 1.1 christos isc_result_t result; 203 1.1 christos dns_rdata_nsec_t tmpnsec; 204 1.1 christos 205 1.1 christos result = dns_rdata_tostruct(rdata, &tmpnsec, NULL); 206 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 207 1.1 christos 208 1.1 christos if (nsec->len != tmpnsec.len || 209 1.1 christos memcmp(nsec->typebits, tmpnsec.typebits, nsec->len) != 0) 210 1.1 christos { 211 1.1 christos return (false); 212 1.1 christos } 213 1.1 christos return (true); 214 1.1 christos } 215 1.1 christos 216 1.1 christos static isc_result_t 217 1.1 christos verifynsec(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node, 218 1.1 christos const dns_name_t *nextname, isc_result_t *vresult) { 219 1.1 christos unsigned char buffer[DNS_NSEC_BUFFERSIZE]; 220 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 221 1.1 christos char nextbuf[DNS_NAME_FORMATSIZE]; 222 1.1 christos char found[DNS_NAME_FORMATSIZE]; 223 1.1 christos dns_rdataset_t rdataset; 224 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 225 1.1 christos dns_rdata_t tmprdata = DNS_RDATA_INIT; 226 1.1 christos dns_rdata_nsec_t nsec; 227 1.1 christos isc_result_t result; 228 1.1 christos 229 1.1 christos dns_rdataset_init(&rdataset); 230 1.1 christos result = dns_db_findrdataset(vctx->db, node, vctx->ver, 231 1.1 christos dns_rdatatype_nsec, 0, 0, &rdataset, NULL); 232 1.1 christos if (result != ISC_R_SUCCESS) { 233 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 234 1.1 christos zoneverify_log_error(vctx, "Missing NSEC record for %s", 235 1.1 christos namebuf); 236 1.1 christos *vresult = ISC_R_FAILURE; 237 1.1 christos result = ISC_R_SUCCESS; 238 1.1 christos goto done; 239 1.1 christos } 240 1.1 christos 241 1.1 christos result = dns_rdataset_first(&rdataset); 242 1.1 christos if (result != ISC_R_SUCCESS) { 243 1.1 christos zoneverify_log_error(vctx, "dns_rdataset_first(): %s", 244 1.1 christos isc_result_totext(result)); 245 1.1 christos goto done; 246 1.1 christos } 247 1.1 christos 248 1.1 christos dns_rdataset_current(&rdataset, &rdata); 249 1.1 christos result = dns_rdata_tostruct(&rdata, &nsec, NULL); 250 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 251 1.1 christos 252 1.1 christos /* Check next name is consistent */ 253 1.1 christos if (!dns_name_equal(&nsec.next, nextname)) { 254 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 255 1.1 christos dns_name_format(nextname, nextbuf, sizeof(nextbuf)); 256 1.1 christos dns_name_format(&nsec.next, found, sizeof(found)); 257 1.1 christos zoneverify_log_error(vctx, 258 1.1 christos "Bad NSEC record for %s, next name " 259 1.1 christos "mismatch (expected:%s, found:%s)", 260 1.1 christos namebuf, nextbuf, found); 261 1.1 christos *vresult = ISC_R_FAILURE; 262 1.1 christos goto done; 263 1.1 christos } 264 1.1 christos 265 1.1 christos /* Check bit map is consistent */ 266 1.1 christos result = dns_nsec_buildrdata(vctx->db, vctx->ver, node, nextname, 267 1.1 christos buffer, &tmprdata); 268 1.1 christos if (result != ISC_R_SUCCESS) { 269 1.1 christos zoneverify_log_error(vctx, "dns_nsec_buildrdata(): %s", 270 1.1 christos isc_result_totext(result)); 271 1.1 christos goto done; 272 1.1 christos } 273 1.1 christos if (!nsec_bitmap_equal(&nsec, &tmprdata)) { 274 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 275 1.1 christos zoneverify_log_error(vctx, 276 1.1 christos "Bad NSEC record for %s, bit map " 277 1.1 christos "mismatch", 278 1.1 christos namebuf); 279 1.1 christos *vresult = ISC_R_FAILURE; 280 1.1 christos goto done; 281 1.1 christos } 282 1.1 christos 283 1.1 christos result = dns_rdataset_next(&rdataset); 284 1.1 christos if (result != ISC_R_NOMORE) { 285 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 286 1.1 christos zoneverify_log_error(vctx, "Multiple NSEC records for %s", 287 1.1 christos namebuf); 288 1.1 christos *vresult = ISC_R_FAILURE; 289 1.1 christos goto done; 290 1.1 christos } 291 1.1 christos 292 1.1 christos *vresult = ISC_R_SUCCESS; 293 1.1 christos result = ISC_R_SUCCESS; 294 1.1 christos 295 1.1 christos done: 296 1.1 christos if (dns_rdataset_isassociated(&rdataset)) { 297 1.1 christos dns_rdataset_disassociate(&rdataset); 298 1.1 christos } 299 1.1 christos 300 1.1 christos return (result); 301 1.1 christos } 302 1.1 christos 303 1.1 christos static isc_result_t 304 1.1 christos check_no_rrsig(const vctx_t *vctx, const dns_rdataset_t *rdataset, 305 1.1 christos const dns_name_t *name, dns_dbnode_t *node) { 306 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 307 1.1 christos char typebuf[DNS_RDATATYPE_FORMATSIZE]; 308 1.1 christos dns_rdataset_t sigrdataset; 309 1.1 christos dns_rdatasetiter_t *rdsiter = NULL; 310 1.1 christos isc_result_t result; 311 1.1 christos 312 1.1 christos dns_rdataset_init(&sigrdataset); 313 1.1 christos result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, 0, &rdsiter); 314 1.1 christos if (result != ISC_R_SUCCESS) { 315 1.1 christos zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s", 316 1.1 christos isc_result_totext(result)); 317 1.1 christos return (result); 318 1.1 christos } 319 1.1 christos for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; 320 1.1 christos result = dns_rdatasetiter_next(rdsiter)) 321 1.1 christos { 322 1.1 christos dns_rdatasetiter_current(rdsiter, &sigrdataset); 323 1.1 christos if (sigrdataset.type == dns_rdatatype_rrsig && 324 1.1 christos sigrdataset.covers == rdataset->type) 325 1.1 christos { 326 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 327 1.1 christos dns_rdatatype_format(rdataset->type, typebuf, 328 1.1 christos sizeof(typebuf)); 329 1.1 christos zoneverify_log_error( 330 1.1 christos vctx, 331 1.1 christos "Warning: Found unexpected signatures " 332 1.1 christos "for %s/%s", 333 1.1 christos namebuf, typebuf); 334 1.1 christos break; 335 1.1 christos } 336 1.1 christos dns_rdataset_disassociate(&sigrdataset); 337 1.1 christos } 338 1.1 christos if (dns_rdataset_isassociated(&sigrdataset)) { 339 1.1 christos dns_rdataset_disassociate(&sigrdataset); 340 1.1 christos } 341 1.1 christos dns_rdatasetiter_destroy(&rdsiter); 342 1.1 christos 343 1.1 christos return (ISC_R_SUCCESS); 344 1.1 christos } 345 1.1 christos 346 1.1 christos static bool 347 1.1 christos chain_compare(void *arg1, void *arg2) { 348 1.1 christos struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2; 349 1.1 christos /* 350 1.1 christos * Do each element in turn to get a stable sort. 351 1.1 christos */ 352 1.1 christos if (e1->hash < e2->hash) { 353 1.1 christos return (true); 354 1.1 christos } 355 1.1 christos if (e1->hash > e2->hash) { 356 1.1 christos return (false); 357 1.1 christos } 358 1.1 christos if (e1->iterations < e2->iterations) { 359 1.1 christos return (true); 360 1.1 christos } 361 1.1 christos if (e1->iterations > e2->iterations) { 362 1.1 christos return (false); 363 1.1 christos } 364 1.1 christos if (e1->salt_length < e2->salt_length) { 365 1.1 christos return (true); 366 1.1 christos } 367 1.1 christos if (e1->salt_length > e2->salt_length) { 368 1.1 christos return (false); 369 1.1 christos } 370 1.1 christos if (e1->next_length < e2->next_length) { 371 1.1 christos return (true); 372 1.1 christos } 373 1.1 christos if (e1->next_length > e2->next_length) { 374 1.1 christos return (false); 375 1.1 christos } 376 1.1 christos if (memcmp(e1 + 1, e2 + 1, chain_length(e1)) < 0) { 377 1.1 christos return (true); 378 1.1 christos } 379 1.1 christos return (false); 380 1.1 christos } 381 1.1 christos 382 1.1 christos static bool 383 1.1 christos chain_equal(const struct nsec3_chain_fixed *e1, 384 1.1 christos const struct nsec3_chain_fixed *e2, size_t data_length) { 385 1.1 christos if (e1->hash != e2->hash) { 386 1.1 christos return (false); 387 1.1 christos } 388 1.1 christos if (e1->iterations != e2->iterations) { 389 1.1 christos return (false); 390 1.1 christos } 391 1.1 christos if (e1->salt_length != e2->salt_length) { 392 1.1 christos return (false); 393 1.1 christos } 394 1.1 christos if (e1->next_length != e2->next_length) { 395 1.1 christos return (false); 396 1.1 christos } 397 1.1 christos 398 1.1 christos return (memcmp(e1 + 1, e2 + 1, data_length) == 0); 399 1.1 christos } 400 1.1 christos 401 1.1 christos static void 402 1.1 christos record_nsec3(const vctx_t *vctx, const unsigned char *rawhash, 403 1.1 christos const dns_rdata_nsec3_t *nsec3, isc_heap_t *chains) { 404 1.1 christos struct nsec3_chain_fixed *element = NULL; 405 1.1 christos unsigned char *cp = NULL; 406 1.1 christos size_t len; 407 1.1 christos 408 1.1 christos len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length; 409 1.1 christos 410 1.1 christos element = isc_mem_get(vctx->mctx, len); 411 1.1 christos memset(element, 0, len); 412 1.1 christos element->hash = nsec3->hash; 413 1.1 christos element->salt_length = nsec3->salt_length; 414 1.1 christos element->next_length = nsec3->next_length; 415 1.1 christos element->iterations = nsec3->iterations; 416 1.1 christos cp = (unsigned char *)(element + 1); 417 1.1 christos memmove(cp, nsec3->salt, nsec3->salt_length); 418 1.1 christos cp += nsec3->salt_length; 419 1.1 christos memmove(cp, rawhash, nsec3->next_length); 420 1.1 christos cp += nsec3->next_length; 421 1.1 christos memmove(cp, nsec3->next, nsec3->next_length); 422 1.1 christos isc_heap_insert(chains, element); 423 1.1 christos } 424 1.1 christos 425 1.1 christos /* 426 1.1 christos * Check whether any NSEC3 within 'rdataset' matches the parameters in 427 1.1 christos * 'nsec3param'. 428 1.1 christos */ 429 1.1 christos static isc_result_t 430 1.1 christos find_nsec3_match(const dns_rdata_nsec3param_t *nsec3param, 431 1.1 christos dns_rdataset_t *rdataset, size_t rhsize, 432 1.1 christos dns_rdata_nsec3_t *nsec3_match) { 433 1.1 christos isc_result_t result; 434 1.1 christos 435 1.1 christos /* 436 1.1 christos * Find matching NSEC3 record. 437 1.1 christos */ 438 1.1 christos for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; 439 1.1 christos result = dns_rdataset_next(rdataset)) 440 1.1 christos { 441 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 442 1.1 christos dns_rdataset_current(rdataset, &rdata); 443 1.1 christos result = dns_rdata_tostruct(&rdata, nsec3_match, NULL); 444 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 445 1.1 christos if (nsec3_match->hash == nsec3param->hash && 446 1.1 christos nsec3_match->next_length == rhsize && 447 1.1 christos nsec3_match->iterations == nsec3param->iterations && 448 1.1 christos nsec3_match->salt_length == nsec3param->salt_length && 449 1.1 christos memcmp(nsec3_match->salt, nsec3param->salt, 450 1.1 christos nsec3param->salt_length) == 0) 451 1.1 christos { 452 1.1 christos return (ISC_R_SUCCESS); 453 1.1 christos } 454 1.1 christos } 455 1.1 christos 456 1.1 christos return (result); 457 1.1 christos } 458 1.1 christos 459 1.1 christos static isc_result_t 460 1.1 christos match_nsec3(const vctx_t *vctx, const dns_name_t *name, 461 1.1 christos const dns_rdata_nsec3param_t *nsec3param, dns_rdataset_t *rdataset, 462 1.1 christos const unsigned char types[8192], unsigned int maxtype, 463 1.1 christos const unsigned char *rawhash, size_t rhsize, 464 1.1 christos isc_result_t *vresult) { 465 1.1 christos unsigned char cbm[8244]; 466 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 467 1.1 christos dns_rdata_nsec3_t nsec3; 468 1.1 christos isc_result_t result; 469 1.1 christos unsigned int len; 470 1.1 christos 471 1.1 christos result = find_nsec3_match(nsec3param, rdataset, rhsize, &nsec3); 472 1.1 christos if (result != ISC_R_SUCCESS) { 473 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 474 1.1 christos zoneverify_log_error(vctx, "Missing NSEC3 record for %s", 475 1.1 christos namebuf); 476 1.1 christos *vresult = result; 477 1.1 christos return (ISC_R_SUCCESS); 478 1.1 christos } 479 1.1 christos 480 1.1 christos /* 481 1.1 christos * Check the type list. 482 1.1 christos */ 483 1.1 christos len = dns_nsec_compressbitmap(cbm, types, maxtype); 484 1.1 christos if (nsec3.len != len || memcmp(cbm, nsec3.typebits, len) != 0) { 485 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 486 1.1 christos zoneverify_log_error(vctx, 487 1.1 christos "Bad NSEC3 record for %s, bit map " 488 1.1 christos "mismatch", 489 1.1 christos namebuf); 490 1.1 christos *vresult = ISC_R_FAILURE; 491 1.1 christos return (ISC_R_SUCCESS); 492 1.1 christos } 493 1.1 christos 494 1.1 christos /* 495 1.1 christos * Record chain. 496 1.1 christos */ 497 1.1 christos record_nsec3(vctx, rawhash, &nsec3, vctx->expected_chains); 498 1.1 christos 499 1.1 christos /* 500 1.1 christos * Make sure there is only one NSEC3 record with this set of 501 1.1 christos * parameters. 502 1.1 christos */ 503 1.1 christos for (result = dns_rdataset_next(rdataset); result == ISC_R_SUCCESS; 504 1.1 christos result = dns_rdataset_next(rdataset)) 505 1.1 christos { 506 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 507 1.1 christos dns_rdataset_current(rdataset, &rdata); 508 1.1 christos result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 509 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 510 1.1 christos if (nsec3.hash == nsec3param->hash && 511 1.1 christos nsec3.iterations == nsec3param->iterations && 512 1.1 christos nsec3.salt_length == nsec3param->salt_length && 513 1.1 christos memcmp(nsec3.salt, nsec3param->salt, nsec3.salt_length) == 514 1.1 christos 0) 515 1.1 christos { 516 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 517 1.1 christos zoneverify_log_error(vctx, 518 1.1 christos "Multiple NSEC3 records with the " 519 1.1 christos "same parameter set for %s", 520 1.1 christos namebuf); 521 1.1 christos *vresult = DNS_R_DUPLICATE; 522 1.1 christos return (ISC_R_SUCCESS); 523 1.1 christos } 524 1.1 christos } 525 1.1 christos if (result != ISC_R_NOMORE) { 526 1.1 christos return (result); 527 1.1 christos } 528 1.1 christos 529 1.1 christos *vresult = ISC_R_SUCCESS; 530 1.1 christos 531 1.1 christos return (ISC_R_SUCCESS); 532 1.1 christos } 533 1.1 christos 534 1.1 christos static bool 535 1.1 christos innsec3params(const dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) { 536 1.1 christos dns_rdata_nsec3param_t nsec3param; 537 1.1 christos isc_result_t result; 538 1.1 christos 539 1.1 christos for (result = dns_rdataset_first(nsec3paramset); 540 1.1 christos result == ISC_R_SUCCESS; result = dns_rdataset_next(nsec3paramset)) 541 1.1 christos { 542 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 543 1.1 christos 544 1.1 christos dns_rdataset_current(nsec3paramset, &rdata); 545 1.1 christos result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); 546 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 547 1.1 christos if (nsec3param.flags == 0 && nsec3param.hash == nsec3->hash && 548 1.1 christos nsec3param.iterations == nsec3->iterations && 549 1.1 christos nsec3param.salt_length == nsec3->salt_length && 550 1.1 christos memcmp(nsec3param.salt, nsec3->salt, nsec3->salt_length) == 551 1.1 christos 0) 552 1.1 christos { 553 1.1 christos return (true); 554 1.1 christos } 555 1.1 christos } 556 1.1 christos return (false); 557 1.1 christos } 558 1.1 christos 559 1.1 christos static isc_result_t 560 1.1 christos record_found(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node, 561 1.1 christos dns_rdataset_t *nsec3paramset) { 562 1.1 christos unsigned char owner[NSEC3_MAX_HASH_LENGTH]; 563 1.1 christos dns_rdata_nsec3_t nsec3; 564 1.1 christos dns_rdataset_t rdataset; 565 1.1 christos dns_label_t hashlabel; 566 1.1 christos isc_buffer_t b; 567 1.1 christos isc_result_t result; 568 1.1 christos 569 1.1 christos if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset)) 570 1.1 christos { 571 1.1 christos return (ISC_R_SUCCESS); 572 1.1 christos } 573 1.1 christos 574 1.1 christos dns_rdataset_init(&rdataset); 575 1.1 christos result = dns_db_findrdataset(vctx->db, node, vctx->ver, 576 1.1 christos dns_rdatatype_nsec3, 0, 0, &rdataset, 577 1.1 christos NULL); 578 1.1 christos if (result != ISC_R_SUCCESS) { 579 1.1 christos return (ISC_R_SUCCESS); 580 1.1 christos } 581 1.1 christos 582 1.1 christos dns_name_getlabel(name, 0, &hashlabel); 583 1.1 christos isc_region_consume(&hashlabel, 1); 584 1.1 christos isc_buffer_init(&b, owner, sizeof(owner)); 585 1.1 christos result = isc_base32hex_decoderegion(&hashlabel, &b); 586 1.1 christos if (result != ISC_R_SUCCESS) { 587 1.1 christos result = ISC_R_SUCCESS; 588 1.1 christos goto cleanup; 589 1.1 christos } 590 1.1 christos 591 1.1 christos for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; 592 1.1 christos result = dns_rdataset_next(&rdataset)) 593 1.1 christos { 594 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 595 1.1 christos dns_rdataset_current(&rdataset, &rdata); 596 1.1 christos result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 597 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 598 1.1 christos if (nsec3.next_length != isc_buffer_usedlength(&b)) { 599 1.1 christos continue; 600 1.1 christos } 601 1.1 christos 602 1.1 christos /* 603 1.1 christos * We only care about NSEC3 records that match a NSEC3PARAM 604 1.1 christos * record. 605 1.1 christos */ 606 1.1 christos if (!innsec3params(&nsec3, nsec3paramset)) { 607 1.1 christos continue; 608 1.1 christos } 609 1.1 christos 610 1.1 christos /* 611 1.1 christos * Record chain. 612 1.1 christos */ 613 1.1 christos record_nsec3(vctx, owner, &nsec3, vctx->found_chains); 614 1.1 christos } 615 1.1 christos result = ISC_R_SUCCESS; 616 1.1 christos 617 1.1 christos cleanup: 618 1.1 christos dns_rdataset_disassociate(&rdataset); 619 1.1 christos return (result); 620 1.1 christos } 621 1.1 christos 622 1.1 christos static isc_result_t 623 1.1 christos isoptout(const vctx_t *vctx, const dns_rdata_nsec3param_t *nsec3param, 624 1.1 christos bool *optout) { 625 1.1 christos dns_rdataset_t rdataset; 626 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 627 1.1 christos dns_rdata_nsec3_t nsec3; 628 1.1 christos dns_fixedname_t fixed; 629 1.1 christos dns_name_t *hashname; 630 1.1 christos isc_result_t result; 631 1.1 christos dns_dbnode_t *node = NULL; 632 1.1 christos unsigned char rawhash[NSEC3_MAX_HASH_LENGTH]; 633 1.1 christos size_t rhsize = sizeof(rawhash); 634 1.1 christos 635 1.1 christos dns_fixedname_init(&fixed); 636 1.1 christos result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, vctx->origin, 637 1.1 christos vctx->origin, nsec3param->hash, 638 1.1 christos nsec3param->iterations, nsec3param->salt, 639 1.1 christos nsec3param->salt_length); 640 1.1 christos if (result != ISC_R_SUCCESS) { 641 1.1 christos zoneverify_log_error(vctx, "dns_nsec3_hashname(): %s", 642 1.1 christos isc_result_totext(result)); 643 1.1 christos return (result); 644 1.1 christos } 645 1.1 christos 646 1.1 christos dns_rdataset_init(&rdataset); 647 1.1 christos hashname = dns_fixedname_name(&fixed); 648 1.1 christos result = dns_db_findnsec3node(vctx->db, hashname, false, &node); 649 1.1 christos if (result == ISC_R_SUCCESS) { 650 1.1 christos result = dns_db_findrdataset(vctx->db, node, vctx->ver, 651 1.1 christos dns_rdatatype_nsec3, 0, 0, 652 1.1 christos &rdataset, NULL); 653 1.1 christos } 654 1.1 christos if (result != ISC_R_SUCCESS) { 655 1.1 christos *optout = false; 656 1.1 christos result = ISC_R_SUCCESS; 657 1.1 christos goto done; 658 1.1 christos } 659 1.1 christos 660 1.1 christos result = dns_rdataset_first(&rdataset); 661 1.1 christos if (result != ISC_R_SUCCESS) { 662 1.1 christos zoneverify_log_error(vctx, "dns_rdataset_first(): %s", 663 1.1 christos isc_result_totext(result)); 664 1.1 christos goto done; 665 1.1 christos } 666 1.1 christos 667 1.1 christos dns_rdataset_current(&rdataset, &rdata); 668 1.1 christos 669 1.1 christos result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 670 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 671 1.1 christos *optout = ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0); 672 1.1 christos 673 1.1 christos done: 674 1.1 christos if (dns_rdataset_isassociated(&rdataset)) { 675 1.1 christos dns_rdataset_disassociate(&rdataset); 676 1.1 christos } 677 1.1 christos if (node != NULL) { 678 1.1 christos dns_db_detachnode(vctx->db, &node); 679 1.1 christos } 680 1.1 christos 681 1.1 christos return (result); 682 1.1 christos } 683 1.1 christos 684 1.1 christos static isc_result_t 685 1.1 christos verifynsec3(const vctx_t *vctx, const dns_name_t *name, 686 1.1 christos const dns_rdata_t *rdata, bool delegation, bool empty, 687 1.1 christos const unsigned char types[8192], unsigned int maxtype, 688 1.1 christos isc_result_t *vresult) { 689 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 690 1.1 christos char hashbuf[DNS_NAME_FORMATSIZE]; 691 1.1 christos dns_rdataset_t rdataset; 692 1.1 christos dns_rdata_nsec3param_t nsec3param; 693 1.1 christos dns_fixedname_t fixed; 694 1.1 christos dns_name_t *hashname; 695 1.1 christos isc_result_t result, tvresult = ISC_R_UNSET; 696 1.1 christos dns_dbnode_t *node = NULL; 697 1.1 christos unsigned char rawhash[NSEC3_MAX_HASH_LENGTH]; 698 1.1 christos size_t rhsize = sizeof(rawhash); 699 1.1 christos bool optout = false; 700 1.1 christos 701 1.1 christos result = dns_rdata_tostruct(rdata, &nsec3param, NULL); 702 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 703 1.1 christos 704 1.1 christos if (nsec3param.flags != 0) { 705 1.1 christos return (ISC_R_SUCCESS); 706 1.1 christos } 707 1.1 christos 708 1.1 christos if (!dns_nsec3_supportedhash(nsec3param.hash)) { 709 1.1 christos return (ISC_R_SUCCESS); 710 1.1 christos } 711 1.1 christos 712 1.1 christos if (nsec3param.iterations > DNS_NSEC3_MAXITERATIONS) { 713 1.1 christos result = DNS_R_NSEC3ITERRANGE; 714 1.1 christos zoneverify_log_error(vctx, "verifynsec3: %s", 715 1.1 christos isc_result_totext(result)); 716 1.1 christos return (result); 717 1.1 christos } 718 1.1 christos 719 1.1 christos result = isoptout(vctx, &nsec3param, &optout); 720 1.1 christos if (result != ISC_R_SUCCESS) { 721 1.1 christos return (result); 722 1.1 christos } 723 1.1 christos 724 1.1 christos dns_fixedname_init(&fixed); 725 1.1 christos result = dns_nsec3_hashname( 726 1.1 christos &fixed, rawhash, &rhsize, name, vctx->origin, nsec3param.hash, 727 1.1 christos nsec3param.iterations, nsec3param.salt, nsec3param.salt_length); 728 1.1 christos if (result != ISC_R_SUCCESS) { 729 1.1 christos zoneverify_log_error(vctx, "dns_nsec3_hashname(): %s", 730 1.1 christos isc_result_totext(result)); 731 1.1 christos return (result); 732 1.1 christos } 733 1.1 christos 734 1.1 christos /* 735 1.1 christos * We don't use dns_db_find() here as it works with the chosen 736 1.1 christos * nsec3 chain and we may also be called with uncommitted data 737 1.1 christos * from dnssec-signzone so the secure status of the zone may not 738 1.1 christos * be up to date. 739 1.1 christos */ 740 1.1 christos dns_rdataset_init(&rdataset); 741 1.1 christos hashname = dns_fixedname_name(&fixed); 742 1.1 christos result = dns_db_findnsec3node(vctx->db, hashname, false, &node); 743 1.1 christos if (result == ISC_R_SUCCESS) { 744 1.1 christos result = dns_db_findrdataset(vctx->db, node, vctx->ver, 745 1.1 christos dns_rdatatype_nsec3, 0, 0, 746 1.1 christos &rdataset, NULL); 747 1.1 christos } 748 1.1 christos if (result != ISC_R_SUCCESS && 749 1.1 christos (!delegation || (empty && !optout) || 750 1.1 christos (!empty && dns_nsec_isset(types, dns_rdatatype_ds)))) 751 1.1 christos { 752 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 753 1.1 christos dns_name_format(hashname, hashbuf, sizeof(hashbuf)); 754 1.1 christos zoneverify_log_error(vctx, "Missing NSEC3 record for %s (%s)", 755 1.1 christos namebuf, hashbuf); 756 1.1 christos } else if (result == ISC_R_NOTFOUND && delegation && (!empty || optout)) 757 1.1 christos { 758 1.1 christos result = ISC_R_SUCCESS; 759 1.1 christos } else if (result == ISC_R_SUCCESS) { 760 1.1 christos result = match_nsec3(vctx, name, &nsec3param, &rdataset, types, 761 1.1 christos maxtype, rawhash, rhsize, &tvresult); 762 1.1 christos if (result != ISC_R_SUCCESS) { 763 1.1 christos goto done; 764 1.1 christos } 765 1.1 christos result = tvresult; 766 1.1 christos } 767 1.1 christos 768 1.1 christos *vresult = result; 769 1.1 christos result = ISC_R_SUCCESS; 770 1.1 christos 771 1.1 christos done: 772 1.1 christos if (dns_rdataset_isassociated(&rdataset)) { 773 1.1 christos dns_rdataset_disassociate(&rdataset); 774 1.1 christos } 775 1.1 christos if (node != NULL) { 776 1.1 christos dns_db_detachnode(vctx->db, &node); 777 1.1 christos } 778 1.1 christos 779 1.1 christos return (result); 780 1.1 christos } 781 1.1 christos 782 1.1 christos static isc_result_t 783 1.1 christos verifynsec3s(const vctx_t *vctx, const dns_name_t *name, 784 1.1 christos dns_rdataset_t *nsec3paramset, bool delegation, bool empty, 785 1.1 christos const unsigned char types[8192], unsigned int maxtype, 786 1.1 christos isc_result_t *vresult) { 787 1.1 christos isc_result_t result; 788 1.1 christos 789 1.1 christos for (result = dns_rdataset_first(nsec3paramset); 790 1.1 christos result == ISC_R_SUCCESS; result = dns_rdataset_next(nsec3paramset)) 791 1.1 christos { 792 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 793 1.1 christos 794 1.1 christos dns_rdataset_current(nsec3paramset, &rdata); 795 1.1 christos result = verifynsec3(vctx, name, &rdata, delegation, empty, 796 1.1 christos types, maxtype, vresult); 797 1.1 christos if (result != ISC_R_SUCCESS) { 798 1.1 christos return (result); 799 1.1 christos } 800 1.1 christos if (*vresult != ISC_R_SUCCESS) { 801 1.1 christos break; 802 1.1 christos } 803 1.1 christos } 804 1.1 christos if (result == ISC_R_NOMORE) { 805 1.1 christos result = ISC_R_SUCCESS; 806 1.1 christos } 807 1.1 christos return (result); 808 1.1 christos } 809 1.1 christos 810 1.1 christos static isc_result_t 811 1.1 christos verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name, 812 1.1 christos dns_dbnode_t *node, dst_key_t **dstkeys, size_t nkeys) { 813 1.1 christos unsigned char set_algorithms[256] = { 0 }; 814 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 815 1.1 christos char algbuf[DNS_SECALG_FORMATSIZE]; 816 1.1 christos char typebuf[DNS_RDATATYPE_FORMATSIZE]; 817 1.1 christos dns_rdataset_t sigrdataset; 818 1.1 christos dns_rdatasetiter_t *rdsiter = NULL; 819 1.1 christos isc_result_t result; 820 1.1 christos 821 1.1 christos dns_rdataset_init(&sigrdataset); 822 1.1 christos result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, 0, &rdsiter); 823 1.1 christos if (result != ISC_R_SUCCESS) { 824 1.1 christos zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s", 825 1.1 christos isc_result_totext(result)); 826 1.1 christos return (result); 827 1.1 christos } 828 1.1 christos for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; 829 1.1 christos result = dns_rdatasetiter_next(rdsiter)) 830 1.1 christos { 831 1.1 christos dns_rdatasetiter_current(rdsiter, &sigrdataset); 832 1.1 christos if (sigrdataset.type == dns_rdatatype_rrsig && 833 1.1 christos sigrdataset.covers == rdataset->type) 834 1.1 christos { 835 1.1 christos break; 836 1.1 christos } 837 1.1 christos dns_rdataset_disassociate(&sigrdataset); 838 1.1 christos } 839 1.1 christos if (result != ISC_R_SUCCESS) { 840 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 841 1.1 christos dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf)); 842 1.1 christos zoneverify_log_error(vctx, "No signatures for %s/%s", namebuf, 843 1.1 christos typebuf); 844 1.1 christos for (size_t i = 0; i < ARRAY_SIZE(set_algorithms); i++) { 845 1.1 christos if (vctx->act_algorithms[i] != 0) { 846 1.1 christos vctx->bad_algorithms[i] = 1; 847 1.1 christos } 848 1.1 christos } 849 1.1 christos result = ISC_R_SUCCESS; 850 1.1 christos goto done; 851 1.1 christos } 852 1.1 christos 853 1.1 christos for (result = dns_rdataset_first(&sigrdataset); result == ISC_R_SUCCESS; 854 1.1 christos result = dns_rdataset_next(&sigrdataset)) 855 1.1 christos { 856 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 857 1.1 christos dns_rdata_rrsig_t sig; 858 1.1 christos 859 1.1 christos dns_rdataset_current(&sigrdataset, &rdata); 860 1.1 christos result = dns_rdata_tostruct(&rdata, &sig, NULL); 861 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 862 1.1 christos if (rdataset->ttl != sig.originalttl) { 863 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 864 1.1 christos dns_rdatatype_format(rdataset->type, typebuf, 865 1.1 christos sizeof(typebuf)); 866 1.1 christos zoneverify_log_error(vctx, 867 1.1 christos "TTL mismatch for " 868 1.1 christos "%s %s keytag %u", 869 1.1 christos namebuf, typebuf, sig.keyid); 870 1.1 christos continue; 871 1.1 christos } 872 1.1 christos if ((set_algorithms[sig.algorithm] != 0) || 873 1.1 christos (vctx->act_algorithms[sig.algorithm] == 0)) 874 1.1 christos { 875 1.1 christos continue; 876 1.1 christos } 877 1.1 christos if (goodsig(vctx, &rdata, name, dstkeys, nkeys, rdataset)) { 878 1.1 christos dns_rdataset_settrust(rdataset, dns_trust_secure); 879 1.1 christos dns_rdataset_settrust(&sigrdataset, dns_trust_secure); 880 1.1 christos set_algorithms[sig.algorithm] = 1; 881 1.1 christos } 882 1.1 christos } 883 1.1 christos result = ISC_R_SUCCESS; 884 1.1 christos 885 1.1 christos if (memcmp(set_algorithms, vctx->act_algorithms, 886 1.1 christos sizeof(set_algorithms)) != 0) 887 1.1 christos { 888 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 889 1.1 christos dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf)); 890 1.1 christos for (size_t i = 0; i < ARRAY_SIZE(set_algorithms); i++) { 891 1.1 christos if ((vctx->act_algorithms[i] != 0) && 892 1.1 christos (set_algorithms[i] == 0)) 893 1.1 christos { 894 1.1 christos dns_secalg_format(i, algbuf, sizeof(algbuf)); 895 1.1 christos zoneverify_log_error(vctx, 896 1.1 christos "No correct %s signature " 897 1.1 christos "for %s %s", 898 1.1 christos algbuf, namebuf, typebuf); 899 1.1 christos vctx->bad_algorithms[i] = 1; 900 1.1 christos } 901 1.1 christos } 902 1.1 christos } 903 1.1 christos 904 1.1 christos done: 905 1.1 christos if (dns_rdataset_isassociated(&sigrdataset)) { 906 1.1 christos dns_rdataset_disassociate(&sigrdataset); 907 1.1 christos } 908 1.1 christos dns_rdatasetiter_destroy(&rdsiter); 909 1.1 christos 910 1.1 christos return (result); 911 1.1 christos } 912 1.1 christos 913 1.1 christos static isc_result_t 914 1.1 christos verifynode(vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node, 915 1.1 christos bool delegation, dst_key_t **dstkeys, size_t nkeys, 916 1.1 christos dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset, 917 1.1 christos const dns_name_t *nextname, isc_result_t *vresult) { 918 1.1 christos unsigned char types[8192] = { 0 }; 919 1.1 christos unsigned int maxtype = 0; 920 1.1 christos dns_rdataset_t rdataset; 921 1.1 christos dns_rdatasetiter_t *rdsiter = NULL; 922 1.1 christos isc_result_t result, tvresult = ISC_R_UNSET; 923 1.1 christos 924 1.1 christos REQUIRE(vresult != NULL || (nsecset == NULL && nsec3paramset == NULL)); 925 1.1 christos 926 1.1 christos result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, 0, &rdsiter); 927 1.1 christos if (result != ISC_R_SUCCESS) { 928 1.1 christos zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s", 929 1.1 christos isc_result_totext(result)); 930 1.1 christos return (result); 931 1.1 christos } 932 1.1 christos 933 1.1 christos result = dns_rdatasetiter_first(rdsiter); 934 1.1 christos dns_rdataset_init(&rdataset); 935 1.1 christos while (result == ISC_R_SUCCESS) { 936 1.1 christos dns_rdatasetiter_current(rdsiter, &rdataset); 937 1.1 christos /* 938 1.1 christos * If we are not at a delegation then everything should be 939 1.1 christos * signed. If we are at a delegation then only the DS set 940 1.1 christos * is signed. The NS set is not signed at a delegation but 941 1.1 christos * its existence is recorded in the bit map. Anything else 942 1.1 christos * other than NSEC and DS is not signed at a delegation. 943 1.1 christos */ 944 1.1 christos if (rdataset.type != dns_rdatatype_rrsig && 945 1.1 christos rdataset.type != dns_rdatatype_dnskey && 946 1.1 christos (!delegation || rdataset.type == dns_rdatatype_ds || 947 1.1 christos rdataset.type == dns_rdatatype_nsec)) 948 1.1 christos { 949 1.1 christos result = verifyset(vctx, &rdataset, name, node, dstkeys, 950 1.1 christos nkeys); 951 1.1 christos if (result != ISC_R_SUCCESS) { 952 1.1 christos dns_rdataset_disassociate(&rdataset); 953 1.1 christos dns_rdatasetiter_destroy(&rdsiter); 954 1.1 christos return (result); 955 1.1 christos } 956 1.1 christos dns_nsec_setbit(types, rdataset.type, 1); 957 1.1 christos if (rdataset.type > maxtype) { 958 1.1 christos maxtype = rdataset.type; 959 1.1 christos } 960 1.1 christos } else if (rdataset.type != dns_rdatatype_rrsig && 961 1.1 christos rdataset.type != dns_rdatatype_dnskey) 962 1.1 christos { 963 1.1 christos if (rdataset.type == dns_rdatatype_ns) { 964 1.1 christos dns_nsec_setbit(types, rdataset.type, 1); 965 1.1 christos } 966 1.1 christos result = check_no_rrsig(vctx, &rdataset, name, node); 967 1.1 christos if (result != ISC_R_SUCCESS) { 968 1.1 christos dns_rdataset_disassociate(&rdataset); 969 1.1 christos dns_rdatasetiter_destroy(&rdsiter); 970 1.1 christos return (result); 971 1.1 christos } 972 1.1 christos } else { 973 1.1 christos dns_nsec_setbit(types, rdataset.type, 1); 974 1.1 christos } 975 1.1 christos dns_rdataset_disassociate(&rdataset); 976 1.1 christos result = dns_rdatasetiter_next(rdsiter); 977 1.1 christos } 978 1.1 christos dns_rdatasetiter_destroy(&rdsiter); 979 1.1 christos if (result != ISC_R_NOMORE) { 980 1.1 christos zoneverify_log_error(vctx, "rdataset iteration failed: %s", 981 1.1 christos isc_result_totext(result)); 982 1.1 christos return (result); 983 1.1 christos } 984 1.1 christos 985 1.1 christos if (vresult == NULL) { 986 1.1 christos return (ISC_R_SUCCESS); 987 1.1 christos } 988 1.1 christos 989 1.1 christos *vresult = ISC_R_SUCCESS; 990 1.1 christos 991 1.1 christos if (nsecset != NULL && dns_rdataset_isassociated(nsecset)) { 992 1.1 christos result = verifynsec(vctx, name, node, nextname, &tvresult); 993 1.1 christos if (result != ISC_R_SUCCESS) { 994 1.1 christos return (result); 995 1.1 christos } 996 1.1 christos *vresult = tvresult; 997 1.1 christos } 998 1.1 christos 999 1.1 christos if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) { 1000 1.1 christos result = verifynsec3s(vctx, name, nsec3paramset, delegation, 1001 1.1 christos false, types, maxtype, &tvresult); 1002 1.1 christos if (result != ISC_R_SUCCESS) { 1003 1.1 christos return (result); 1004 1.1 christos } 1005 1.1 christos if (*vresult == ISC_R_SUCCESS) { 1006 1.1 christos *vresult = tvresult; 1007 1.1 christos } 1008 1.1 christos } 1009 1.1 christos 1010 1.1 christos return (ISC_R_SUCCESS); 1011 1.1 christos } 1012 1.1 christos 1013 1.1 christos static isc_result_t 1014 1.1 christos is_empty(const vctx_t *vctx, dns_dbnode_t *node, bool *empty) { 1015 1.1 christos dns_rdatasetiter_t *rdsiter = NULL; 1016 1.1 christos isc_result_t result; 1017 1.1 christos 1018 1.1 christos result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, 0, &rdsiter); 1019 1.1 christos if (result != ISC_R_SUCCESS) { 1020 1.1 christos zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s", 1021 1.1 christos isc_result_totext(result)); 1022 1.1 christos return (result); 1023 1.1 christos } 1024 1.1 christos result = dns_rdatasetiter_first(rdsiter); 1025 1.1 christos dns_rdatasetiter_destroy(&rdsiter); 1026 1.1 christos 1027 1.1 christos *empty = (result == ISC_R_NOMORE); 1028 1.1 christos 1029 1.1 christos return (ISC_R_SUCCESS); 1030 1.1 christos } 1031 1.1 christos 1032 1.1 christos static isc_result_t 1033 1.1 christos check_no_nsec(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node) { 1034 1.1 christos bool nsec_exists = false; 1035 1.1 christos dns_rdataset_t rdataset; 1036 1.1 christos isc_result_t result; 1037 1.1 christos 1038 1.1 christos dns_rdataset_init(&rdataset); 1039 1.1 christos result = dns_db_findrdataset(vctx->db, node, vctx->ver, 1040 1.1 christos dns_rdatatype_nsec, 0, 0, &rdataset, NULL); 1041 1.1 christos if (result != ISC_R_NOTFOUND) { 1042 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 1043 1.1 christos dns_name_format(name, namebuf, sizeof(namebuf)); 1044 1.1 christos zoneverify_log_error(vctx, "unexpected NSEC RRset at %s", 1045 1.1 christos namebuf); 1046 1.1 christos nsec_exists = true; 1047 1.1 christos } 1048 1.1 christos 1049 1.1 christos if (dns_rdataset_isassociated(&rdataset)) { 1050 1.1 christos dns_rdataset_disassociate(&rdataset); 1051 1.1 christos } 1052 1.1 christos 1053 1.1 christos return (nsec_exists ? ISC_R_FAILURE : ISC_R_SUCCESS); 1054 1.1 christos } 1055 1.1 christos 1056 1.1 christos static void 1057 1.1 christos free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) { 1058 1.1 christos size_t len; 1059 1.1 christos 1060 1.1 christos len = sizeof(*e) + e->salt_length + 2 * e->next_length; 1061 1.1 christos isc_mem_put(mctx, e, len); 1062 1.1 christos } 1063 1.1 christos 1064 1.1 christos static void 1065 1.1 christos free_element_heap(void *element, void *uap) { 1066 1.1 christos struct nsec3_chain_fixed *e = (struct nsec3_chain_fixed *)element; 1067 1.1 christos isc_mem_t *mctx = (isc_mem_t *)uap; 1068 1.1 christos 1069 1.1 christos free_element(mctx, e); 1070 1.1 christos } 1071 1.1 christos 1072 1.1 christos static bool 1073 1.1 christos _checknext(const vctx_t *vctx, const struct nsec3_chain_fixed *first, 1074 1.1 christos const struct nsec3_chain_fixed *e) { 1075 1.1 christos char buf[512]; 1076 1.1 christos const unsigned char *d1 = (const unsigned char *)(first + 1); 1077 1.1 christos const unsigned char *d2 = (const unsigned char *)(e + 1); 1078 1.1 christos isc_buffer_t b; 1079 1.1 christos isc_region_t sr; 1080 1.1 christos 1081 1.1 christos d1 += first->salt_length + first->next_length; 1082 1.1 christos d2 += e->salt_length; 1083 1.1 christos 1084 1.1 christos if (memcmp(d1, d2, first->next_length) == 0) { 1085 1.1 christos return (true); 1086 1.1 christos } 1087 1.1 christos 1088 1.1 christos DE_CONST(d1 - first->next_length, sr.base); 1089 1.1 christos sr.length = first->next_length; 1090 1.1 christos isc_buffer_init(&b, buf, sizeof(buf)); 1091 1.1 christos isc_base32hex_totext(&sr, 1, "", &b); 1092 1.1 christos zoneverify_log_error(vctx, "Break in NSEC3 chain at: %.*s", 1093 1.1 christos (int)isc_buffer_usedlength(&b), buf); 1094 1.1 christos 1095 1.1 christos DE_CONST(d1, sr.base); 1096 1.1 christos sr.length = first->next_length; 1097 1.1 christos isc_buffer_init(&b, buf, sizeof(buf)); 1098 1.1 christos isc_base32hex_totext(&sr, 1, "", &b); 1099 1.1 christos zoneverify_log_error(vctx, "Expected: %.*s", 1100 1.1 christos (int)isc_buffer_usedlength(&b), buf); 1101 1.1 christos 1102 1.1 christos DE_CONST(d2, sr.base); 1103 1.1 christos sr.length = first->next_length; 1104 1.1 christos isc_buffer_init(&b, buf, sizeof(buf)); 1105 1.1 christos isc_base32hex_totext(&sr, 1, "", &b); 1106 1.1 christos zoneverify_log_error(vctx, "Found: %.*s", 1107 1.1 christos (int)isc_buffer_usedlength(&b), buf); 1108 1.1 christos 1109 1.1 christos return (false); 1110 1.1 christos } 1111 1.1 christos 1112 1.1 christos static bool 1113 1.1 christos checknext(isc_mem_t *mctx, const vctx_t *vctx, 1114 1.1 christos const struct nsec3_chain_fixed *first, struct nsec3_chain_fixed *prev, 1115 1.1 christos const struct nsec3_chain_fixed *cur) { 1116 1.1 christos bool result = _checknext(vctx, prev, cur); 1117 1.1 christos 1118 1.1 christos if (prev != first) { 1119 1.1 christos free_element(mctx, prev); 1120 1.1 christos } 1121 1.1 christos 1122 1.1 christos return (result); 1123 1.1 christos } 1124 1.1 christos 1125 1.1 christos static bool 1126 1.1 christos checklast(isc_mem_t *mctx, const vctx_t *vctx, struct nsec3_chain_fixed *first, 1127 1.1 christos struct nsec3_chain_fixed *prev) { 1128 1.1 christos bool result = _checknext(vctx, prev, first); 1129 1.1 christos if (prev != first) { 1130 1.1 christos free_element(mctx, prev); 1131 1.1 christos } 1132 1.1 christos free_element(mctx, first); 1133 1.1 christos 1134 1.1 christos return (result); 1135 1.1 christos } 1136 1.1 christos 1137 1.1 christos static isc_result_t 1138 1.1 christos verify_nsec3_chains(const vctx_t *vctx, isc_mem_t *mctx) { 1139 1.1 christos isc_result_t result = ISC_R_SUCCESS; 1140 1.1 christos struct nsec3_chain_fixed *e, *f = NULL; 1141 1.1 christos struct nsec3_chain_fixed *first = NULL, *prev = NULL; 1142 1.1 christos 1143 1.1 christos while ((e = isc_heap_element(vctx->expected_chains, 1)) != NULL) { 1144 1.1 christos isc_heap_delete(vctx->expected_chains, 1); 1145 1.1 christos if (f == NULL) { 1146 1.1 christos f = isc_heap_element(vctx->found_chains, 1); 1147 1.1 christos } 1148 1.1 christos if (f != NULL) { 1149 1.1 christos isc_heap_delete(vctx->found_chains, 1); 1150 1.1 christos 1151 1.1 christos /* 1152 1.1 christos * Check that they match. 1153 1.1 christos */ 1154 1.1 christos if (chain_equal(e, f, chain_length(e))) { 1155 1.1 christos free_element(mctx, f); 1156 1.1 christos f = NULL; 1157 1.1 christos } else { 1158 1.1 christos if (result == ISC_R_SUCCESS) { 1159 1.1 christos zoneverify_log_error(vctx, "Expected " 1160 1.1 christos "and found " 1161 1.1 christos "NSEC3 " 1162 1.1 christos "chains not " 1163 1.1 christos "equal"); 1164 1.1 christos } 1165 1.1 christos result = ISC_R_FAILURE; 1166 1.1 christos /* 1167 1.1 christos * Attempt to resync found_chain. 1168 1.1 christos */ 1169 1.1 christos while (f != NULL && !chain_compare(e, f)) { 1170 1.1 christos free_element(mctx, f); 1171 1.1 christos f = isc_heap_element(vctx->found_chains, 1172 1.1 christos 1); 1173 1.1 christos if (f != NULL) { 1174 1.1 christos isc_heap_delete( 1175 1.1 christos vctx->found_chains, 1); 1176 1.1 christos } 1177 1.1 christos if (f != NULL && 1178 1.1 christos chain_equal(e, f, chain_length(e))) 1179 1.1 christos { 1180 1.1 christos free_element(mctx, f); 1181 1.1 christos f = NULL; 1182 1.1 christos break; 1183 1.1 christos } 1184 1.1 christos } 1185 1.1 christos } 1186 1.1 christos } else if (result == ISC_R_SUCCESS) { 1187 1.1 christos zoneverify_log_error(vctx, "Expected and found NSEC3 " 1188 1.1 christos "chains " 1189 1.1 christos "not equal"); 1190 1.1 christos result = ISC_R_FAILURE; 1191 1.1 christos } 1192 1.1 christos 1193 1.1 christos if (first == NULL) { 1194 1.1 christos prev = first = e; 1195 1.1 christos } else if (!chain_equal(first, e, first->salt_length)) { 1196 1.1 christos if (!checklast(mctx, vctx, first, prev)) { 1197 1.1 christos result = ISC_R_FAILURE; 1198 1.1 christos } 1199 1.1 christos 1200 1.1 christos prev = first = e; 1201 1.1 christos } else { 1202 1.1 christos if (!checknext(mctx, vctx, first, prev, e)) { 1203 1.1 christos result = ISC_R_FAILURE; 1204 1.1 christos } 1205 1.1 christos 1206 1.1 christos prev = e; 1207 1.1 christos } 1208 1.1 christos } 1209 1.1 christos if (prev != NULL) { 1210 1.1 christos if (!checklast(mctx, vctx, first, prev)) { 1211 1.1 christos result = ISC_R_FAILURE; 1212 1.1 christos } 1213 1.1 christos } 1214 1.1 christos do { 1215 1.1 christos if (f != NULL) { 1216 1.1 christos if (result == ISC_R_SUCCESS) { 1217 1.1 christos zoneverify_log_error(vctx, "Expected and found " 1218 1.1 christos "NSEC3 chains not " 1219 1.1 christos "equal"); 1220 1.1 christos result = ISC_R_FAILURE; 1221 1.1 christos } 1222 1.1 christos free_element(mctx, f); 1223 1.1 christos } 1224 1.1 christos f = isc_heap_element(vctx->found_chains, 1); 1225 1.1 christos if (f != NULL) { 1226 1.1 christos isc_heap_delete(vctx->found_chains, 1); 1227 1.1 christos } 1228 1.1 christos } while (f != NULL); 1229 1.1 christos 1230 1.1 christos return (result); 1231 1.1 christos } 1232 1.1 christos 1233 1.1 christos static isc_result_t 1234 1.1 christos verifyemptynodes(const vctx_t *vctx, const dns_name_t *name, 1235 1.1 christos const dns_name_t *prevname, bool isdelegation, 1236 1.1 christos dns_rdataset_t *nsec3paramset, isc_result_t *vresult) { 1237 1.1 christos dns_namereln_t reln; 1238 1.1 christos int order; 1239 1.1 christos unsigned int labels, nlabels, i; 1240 1.1 christos dns_name_t suffix; 1241 1.1 christos isc_result_t result, tvresult = ISC_R_UNSET; 1242 1.1 christos 1243 1.1 christos *vresult = ISC_R_SUCCESS; 1244 1.1 christos 1245 1.1 christos reln = dns_name_fullcompare(prevname, name, &order, &labels); 1246 1.1 christos if (order >= 0) { 1247 1.1 christos return (ISC_R_SUCCESS); 1248 1.1 christos } 1249 1.1 christos 1250 1.1 christos nlabels = dns_name_countlabels(name); 1251 1.1 christos 1252 1.1 christos if (reln == dns_namereln_commonancestor || 1253 1.1 christos reln == dns_namereln_contains) 1254 1.1 christos { 1255 1.1 christos dns_name_init(&suffix, NULL); 1256 1.1 christos for (i = labels + 1; i < nlabels; i++) { 1257 1.1 christos dns_name_getlabelsequence(name, nlabels - i, i, 1258 1.1 christos &suffix); 1259 1.1 christos if (nsec3paramset != NULL && 1260 1.1 christos dns_rdataset_isassociated(nsec3paramset)) 1261 1.1 christos { 1262 1.1 christos result = verifynsec3s( 1263 1.1 christos vctx, &suffix, nsec3paramset, 1264 1.1 christos isdelegation, true, NULL, 0, &tvresult); 1265 1.1 christos if (result != ISC_R_SUCCESS) { 1266 1.1 christos return (result); 1267 1.1 christos } 1268 1.1 christos if (*vresult == ISC_R_SUCCESS) { 1269 1.1 christos *vresult = tvresult; 1270 1.1 christos } 1271 1.1 christos } 1272 1.1 christos } 1273 1.1 christos } 1274 1.1 christos 1275 1.1 christos return (ISC_R_SUCCESS); 1276 1.1 christos } 1277 1.1 christos 1278 1.1 christos static void 1279 1.1 christos vctx_init(vctx_t *vctx, isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, 1280 1.1 christos dns_dbversion_t *ver, dns_name_t *origin, dns_keytable_t *secroots) { 1281 1.1 christos memset(vctx, 0, sizeof(*vctx)); 1282 1.1 christos 1283 1.1 christos vctx->mctx = mctx; 1284 1.1 christos vctx->zone = zone; 1285 1.1 christos vctx->db = db; 1286 1.1 christos vctx->ver = ver; 1287 1.1 christos vctx->origin = origin; 1288 1.1 christos vctx->secroots = secroots; 1289 1.1 christos vctx->goodksk = false; 1290 1.1 christos vctx->goodzsk = false; 1291 1.1 christos 1292 1.1 christos dns_rdataset_init(&vctx->keyset); 1293 1.1 christos dns_rdataset_init(&vctx->keysigs); 1294 1.1 christos dns_rdataset_init(&vctx->soaset); 1295 1.1 christos dns_rdataset_init(&vctx->soasigs); 1296 1.1 christos dns_rdataset_init(&vctx->nsecset); 1297 1.1 christos dns_rdataset_init(&vctx->nsecsigs); 1298 1.1 christos dns_rdataset_init(&vctx->nsec3paramset); 1299 1.1 christos dns_rdataset_init(&vctx->nsec3paramsigs); 1300 1.1 christos 1301 1.1 christos vctx->expected_chains = NULL; 1302 1.1 christos isc_heap_create(mctx, chain_compare, NULL, 1024, 1303 1.1 christos &vctx->expected_chains); 1304 1.1 christos 1305 1.1 christos vctx->found_chains = NULL; 1306 1.1 christos isc_heap_create(mctx, chain_compare, NULL, 1024, &vctx->found_chains); 1307 1.1 christos } 1308 1.1 christos 1309 1.1 christos static void 1310 1.1 christos vctx_destroy(vctx_t *vctx) { 1311 1.1 christos if (dns_rdataset_isassociated(&vctx->keyset)) { 1312 1.1 christos dns_rdataset_disassociate(&vctx->keyset); 1313 1.1 christos } 1314 1.1 christos if (dns_rdataset_isassociated(&vctx->keysigs)) { 1315 1.1 christos dns_rdataset_disassociate(&vctx->keysigs); 1316 1.1 christos } 1317 1.1 christos if (dns_rdataset_isassociated(&vctx->soaset)) { 1318 1.1 christos dns_rdataset_disassociate(&vctx->soaset); 1319 1.1 christos } 1320 1.1 christos if (dns_rdataset_isassociated(&vctx->soasigs)) { 1321 1.1 christos dns_rdataset_disassociate(&vctx->soasigs); 1322 1.1 christos } 1323 1.1 christos if (dns_rdataset_isassociated(&vctx->nsecset)) { 1324 1.1 christos dns_rdataset_disassociate(&vctx->nsecset); 1325 1.1 christos } 1326 1.1 christos if (dns_rdataset_isassociated(&vctx->nsecsigs)) { 1327 1.1 christos dns_rdataset_disassociate(&vctx->nsecsigs); 1328 1.1 christos } 1329 1.1 christos if (dns_rdataset_isassociated(&vctx->nsec3paramset)) { 1330 1.1 christos dns_rdataset_disassociate(&vctx->nsec3paramset); 1331 1.1 christos } 1332 1.1 christos if (dns_rdataset_isassociated(&vctx->nsec3paramsigs)) { 1333 1.1 christos dns_rdataset_disassociate(&vctx->nsec3paramsigs); 1334 1.1 christos } 1335 1.1 christos isc_heap_foreach(vctx->expected_chains, free_element_heap, vctx->mctx); 1336 1.1 christos isc_heap_destroy(&vctx->expected_chains); 1337 1.1 christos isc_heap_foreach(vctx->found_chains, free_element_heap, vctx->mctx); 1338 1.1 christos isc_heap_destroy(&vctx->found_chains); 1339 1.1 christos } 1340 1.1 christos 1341 1.1 christos static isc_result_t 1342 1.1 christos check_apex_rrsets(vctx_t *vctx) { 1343 1.1 christos dns_dbnode_t *node = NULL; 1344 1.1 christos isc_result_t result; 1345 1.1 christos 1346 1.1 christos result = dns_db_findnode(vctx->db, vctx->origin, false, &node); 1347 1.1 christos if (result != ISC_R_SUCCESS) { 1348 1.1 christos zoneverify_log_error(vctx, 1349 1.1 christos "failed to find the zone's origin: %s", 1350 1.1 christos isc_result_totext(result)); 1351 1.1 christos return (result); 1352 1.1 christos } 1353 1.1 christos 1354 1.1 christos result = dns_db_findrdataset(vctx->db, node, vctx->ver, 1355 1.1 christos dns_rdatatype_dnskey, 0, 0, &vctx->keyset, 1356 1.1 christos &vctx->keysigs); 1357 1.1 christos if (result != ISC_R_SUCCESS) { 1358 1.1 christos zoneverify_log_error(vctx, "Zone contains no DNSSEC keys"); 1359 1.1 christos goto done; 1360 1.1 christos } 1361 1.1 christos 1362 1.1 christos result = dns_db_findrdataset(vctx->db, node, vctx->ver, 1363 1.1 christos dns_rdatatype_soa, 0, 0, &vctx->soaset, 1364 1.1 christos &vctx->soasigs); 1365 1.1 christos if (result != ISC_R_SUCCESS) { 1366 1.1 christos zoneverify_log_error(vctx, "Zone contains no SOA record"); 1367 1.1 christos goto done; 1368 1.1 christos } 1369 1.1 christos 1370 1.1 christos result = dns_db_findrdataset(vctx->db, node, vctx->ver, 1371 1.1 christos dns_rdatatype_nsec, 0, 0, &vctx->nsecset, 1372 1.1 christos &vctx->nsecsigs); 1373 1.1 christos if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { 1374 1.1 christos zoneverify_log_error(vctx, "NSEC lookup failed"); 1375 1.1 christos goto done; 1376 1.1 christos } 1377 1.1 christos 1378 1.1 christos result = dns_db_findrdataset( 1379 1.1 christos vctx->db, node, vctx->ver, dns_rdatatype_nsec3param, 0, 0, 1380 1.1 christos &vctx->nsec3paramset, &vctx->nsec3paramsigs); 1381 1.1 christos if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { 1382 1.1 christos zoneverify_log_error(vctx, "NSEC3PARAM lookup failed"); 1383 1.1 christos goto done; 1384 1.1 christos } 1385 1.1 christos 1386 1.1 christos if (!dns_rdataset_isassociated(&vctx->keysigs)) { 1387 1.1 christos zoneverify_log_error(vctx, "DNSKEY is not signed " 1388 1.1 christos "(keys offline or inactive?)"); 1389 1.1 christos result = ISC_R_FAILURE; 1390 1.1 christos goto done; 1391 1.1 christos } 1392 1.1 christos 1393 1.1 christos if (!dns_rdataset_isassociated(&vctx->soasigs)) { 1394 1.1 christos zoneverify_log_error(vctx, "SOA is not signed " 1395 1.1 christos "(keys offline or inactive?)"); 1396 1.1 christos result = ISC_R_FAILURE; 1397 1.1 christos goto done; 1398 1.1 christos } 1399 1.1 christos 1400 1.1 christos if (dns_rdataset_isassociated(&vctx->nsecset) && 1401 1.1 christos !dns_rdataset_isassociated(&vctx->nsecsigs)) 1402 1.1 christos { 1403 1.1 christos zoneverify_log_error(vctx, "NSEC is not signed " 1404 1.1 christos "(keys offline or inactive?)"); 1405 1.1 christos result = ISC_R_FAILURE; 1406 1.1 christos goto done; 1407 1.1 christos } 1408 1.1 christos 1409 1.1 christos if (dns_rdataset_isassociated(&vctx->nsec3paramset) && 1410 1.1 christos !dns_rdataset_isassociated(&vctx->nsec3paramsigs)) 1411 1.1 christos { 1412 1.1 christos zoneverify_log_error(vctx, "NSEC3PARAM is not signed " 1413 1.1 christos "(keys offline or inactive?)"); 1414 1.1 christos result = ISC_R_FAILURE; 1415 1.1 christos goto done; 1416 1.1 christos } 1417 1.1 christos 1418 1.1 christos if (!dns_rdataset_isassociated(&vctx->nsecset) && 1419 1.1 christos !dns_rdataset_isassociated(&vctx->nsec3paramset)) 1420 1.1 christos { 1421 1.1 christos zoneverify_log_error(vctx, "No valid NSEC/NSEC3 chain for " 1422 1.1 christos "testing"); 1423 1.1 christos result = ISC_R_FAILURE; 1424 1.1 christos goto done; 1425 1.1 christos } 1426 1.1 christos 1427 1.1 christos result = ISC_R_SUCCESS; 1428 1.1 christos 1429 1.1 christos done: 1430 1.1 christos dns_db_detachnode(vctx->db, &node); 1431 1.1 christos 1432 1.1 christos return (result); 1433 1.1 christos } 1434 1.1 christos 1435 1.1 christos /*% 1436 1.1 christos * Update 'vctx' tables tracking active and standby key algorithms used in the 1437 1.1 christos * verified zone based on the signatures made using 'dnskey' (prepared from 1438 1.1 christos * 'rdata') found at zone apex. Set 'vctx->goodksk' or 'vctx->goodzsk' to true 1439 1.1 christos * if 'dnskey' correctly signs the DNSKEY RRset at zone apex and either 1440 1.1 christos * 'vctx->secroots' is NULL or 'dnskey' is present in 'vctx->secroots'. 1441 1.1 christos * 1442 1.1 christos * The variables to update are chosen based on 'is_ksk', which is true when 1443 1.1 christos * 'dnskey' is a KSK and false otherwise. 1444 1.1 christos */ 1445 1.1 christos static void 1446 1.1 christos check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey, 1447 1.1 christos dns_rdata_t *keyrdata, bool is_ksk) { 1448 1.1 christos unsigned char *active_keys = NULL, *standby_keys = NULL; 1449 1.1 christos dns_keynode_t *keynode = NULL; 1450 1.1 christos bool *goodkey = NULL; 1451 1.1 christos dst_key_t *key = NULL; 1452 1.1 christos isc_result_t result; 1453 1.1 christos dns_rdataset_t dsset; 1454 1.1 christos 1455 1.1 christos active_keys = (is_ksk ? vctx->ksk_algorithms : vctx->zsk_algorithms); 1456 1.1 christos standby_keys = (is_ksk ? vctx->standby_ksk : vctx->standby_zsk); 1457 1.1 christos goodkey = (is_ksk ? &vctx->goodksk : &vctx->goodzsk); 1458 1.1 christos 1459 1.1 christos /* 1460 1.1 christos * First, does this key sign the DNSKEY rrset? 1461 1.1 christos */ 1462 1.1 christos if (!dns_dnssec_selfsigns(keyrdata, vctx->origin, &vctx->keyset, 1463 1.1 christos &vctx->keysigs, false, vctx->mctx)) 1464 1.1 christos { 1465 1.1 christos if (!is_ksk && 1466 1.1 christos dns_dnssec_signs(keyrdata, vctx->origin, &vctx->soaset, 1467 1.1 christos &vctx->soasigs, false, vctx->mctx)) 1468 1.1 christos { 1469 1.1 christos if (active_keys[dnskey->algorithm] != DNS_KEYALG_MAX) { 1470 1.1 christos active_keys[dnskey->algorithm]++; 1471 1.1 christos } 1472 1.1 christos } else { 1473 1.1 christos if (standby_keys[dnskey->algorithm] != DNS_KEYALG_MAX) { 1474 1.1 christos standby_keys[dnskey->algorithm]++; 1475 1.1 christos } 1476 1.1 christos } 1477 1.1 christos return; 1478 1.1 christos } 1479 1.1 christos 1480 1.1 christos if (active_keys[dnskey->algorithm] != DNS_KEYALG_MAX) { 1481 1.1 christos active_keys[dnskey->algorithm]++; 1482 1.1 christos } 1483 1.1 christos 1484 1.1 christos /* 1485 1.1 christos * If a trust anchor table was not supplied, a correctly self-signed 1486 1.1 christos * DNSKEY RRset is good enough. 1487 1.1 christos */ 1488 1.1 christos if (vctx->secroots == NULL) { 1489 1.1 christos *goodkey = true; 1490 1.1 christos return; 1491 1.1 christos } 1492 1.1 christos 1493 1.1 christos /* 1494 1.1 christos * Convert the supplied key rdata to dst_key_t. (If this 1495 1.1 christos * fails we can't go further.) 1496 1.1 christos */ 1497 1.1 christos result = dns_dnssec_keyfromrdata(vctx->origin, keyrdata, vctx->mctx, 1498 1.1 christos &key); 1499 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 1500 1.1 christos 1501 1.1 christos /* 1502 1.1 christos * Look up the supplied key in the trust anchor table. 1503 1.1 christos * If we don't find an exact match, or if the keynode data 1504 1.1 christos * is NULL, then we have neither a DNSKEY nor a DS format 1505 1.1 christos * trust anchor, and can give up. 1506 1.1 christos */ 1507 1.1 christos result = dns_keytable_find(vctx->secroots, vctx->origin, &keynode); 1508 1.1 christos if (result != ISC_R_SUCCESS) { 1509 1.1 christos /* No such trust anchor */ 1510 1.1 christos goto cleanup; 1511 1.1 christos } 1512 1.1 christos 1513 1.1 christos /* 1514 1.1 christos * If the keynode has any DS format trust anchors, that means 1515 1.1 christos * it doesn't have any DNSKEY ones. So, we can check for a DS 1516 1.1 christos * match and then stop. 1517 1.1 christos */ 1518 1.1 christos dns_rdataset_init(&dsset); 1519 1.1 christos if (dns_keynode_dsset(keynode, &dsset)) { 1520 1.1 christos for (result = dns_rdataset_first(&dsset); 1521 1.1 christos result == ISC_R_SUCCESS; 1522 1.1 christos result = dns_rdataset_next(&dsset)) 1523 1.1 christos { 1524 1.1 christos dns_rdata_t dsrdata = DNS_RDATA_INIT; 1525 1.1 christos dns_rdata_t newdsrdata = DNS_RDATA_INIT; 1526 1.1 christos unsigned char buf[DNS_DS_BUFFERSIZE]; 1527 1.1 christos dns_rdata_ds_t ds; 1528 1.1 christos 1529 1.1 christos dns_rdata_reset(&dsrdata); 1530 1.1 christos dns_rdataset_current(&dsset, &dsrdata); 1531 1.1 christos result = dns_rdata_tostruct(&dsrdata, &ds, NULL); 1532 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 1533 1.1 christos 1534 1.1 christos if (ds.key_tag != dst_key_id(key) || 1535 1.1 christos ds.algorithm != dst_key_alg(key)) 1536 1.1 christos { 1537 1.1 christos continue; 1538 1.1 christos } 1539 1.1 christos 1540 1.1 christos result = dns_ds_buildrdata(vctx->origin, keyrdata, 1541 1.1 christos ds.digest_type, buf, 1542 1.1 christos &newdsrdata); 1543 1.1 christos if (result != ISC_R_SUCCESS) { 1544 1.1 christos continue; 1545 1.1 christos } 1546 1.1 christos 1547 1.1 christos if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0) { 1548 1.1 christos dns_rdataset_settrust(&vctx->keyset, 1549 1.1 christos dns_trust_secure); 1550 1.1 christos dns_rdataset_settrust(&vctx->keysigs, 1551 1.1 christos dns_trust_secure); 1552 1.1 christos *goodkey = true; 1553 1.1 christos break; 1554 1.1 christos } 1555 1.1 christos } 1556 1.1 christos dns_rdataset_disassociate(&dsset); 1557 1.1 christos 1558 1.1 christos goto cleanup; 1559 1.1 christos } 1560 1.1 christos 1561 1.1 christos cleanup: 1562 1.1 christos if (keynode != NULL) { 1563 1.1 christos dns_keytable_detachkeynode(vctx->secroots, &keynode); 1564 1.1 christos } 1565 1.1 christos if (key != NULL) { 1566 1.1 christos dst_key_free(&key); 1567 1.1 christos } 1568 1.1 christos } 1569 1.1 christos 1570 1.1 christos /*% 1571 1.1 christos * Check that the DNSKEY RR has at least one self signing KSK and one ZSK per 1572 1.1 christos * algorithm in it (or, if -x was used, one self-signing KSK). 1573 1.1 christos */ 1574 1.1 christos static isc_result_t 1575 1.1 christos check_dnskey(vctx_t *vctx) { 1576 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 1577 1.1 christos dns_rdata_dnskey_t dnskey; 1578 1.1 christos isc_result_t result; 1579 1.1 christos bool is_ksk; 1580 1.1 christos 1581 1.1 christos for (result = dns_rdataset_first(&vctx->keyset); 1582 1.1 christos result == ISC_R_SUCCESS; result = dns_rdataset_next(&vctx->keyset)) 1583 1.1 christos { 1584 1.1 christos dns_rdataset_current(&vctx->keyset, &rdata); 1585 1.1 christos result = dns_rdata_tostruct(&rdata, &dnskey, NULL); 1586 1.1 christos RUNTIME_CHECK(result == ISC_R_SUCCESS); 1587 1.1 christos is_ksk = ((dnskey.flags & DNS_KEYFLAG_KSK) != 0); 1588 1.1 christos 1589 1.1 christos if ((dnskey.flags & DNS_KEYOWNER_ZONE) != 0 && 1590 1.1 christos (dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) 1591 1.1 christos { 1592 1.1 christos if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && 1593 1.1 christos !dns_dnssec_selfsigns(&rdata, vctx->origin, 1594 1.1 christos &vctx->keyset, &vctx->keysigs, 1595 1.1 christos false, vctx->mctx)) 1596 1.1 christos { 1597 1.1 christos char namebuf[DNS_NAME_FORMATSIZE]; 1598 1.1 christos char buffer[1024]; 1599 1.1 christos isc_buffer_t buf; 1600 1.1 christos 1601 1.1 christos dns_name_format(vctx->origin, namebuf, 1602 1.1 christos sizeof(namebuf)); 1603 1.1 christos isc_buffer_init(&buf, buffer, sizeof(buffer)); 1604 1.1 christos result = dns_rdata_totext(&rdata, NULL, &buf); 1605 1.1 christos if (result != ISC_R_SUCCESS) { 1606 1.1 christos zoneverify_log_error( 1607 1.1 christos vctx, "dns_rdata_totext: %s", 1608 1.1 christos isc_result_totext(result)); 1609 1.1 christos return (ISC_R_FAILURE); 1610 1.1 christos } 1611 1.1 christos zoneverify_log_error( 1612 1.1 christos vctx, 1613 1.1 christos "revoked KSK is not self signed:\n" 1614 1.1 christos "%s DNSKEY %.*s", 1615 1.1 christos namebuf, 1616 1.1 christos (int)isc_buffer_usedlength(&buf), 1617 1.1 christos buffer); 1618 1.1 christos return (ISC_R_FAILURE); 1619 1.1 christos } 1620 1.1 christos if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && 1621 1.1 christos vctx->revoked_ksk[dnskey.algorithm] != 1622 1.1 christos DNS_KEYALG_MAX) 1623 1.1 christos { 1624 1.1 christos vctx->revoked_ksk[dnskey.algorithm]++; 1625 1.1 christos } else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && 1626 1.1 christos vctx->revoked_zsk[dnskey.algorithm] != 1627 1.1 christos DNS_KEYALG_MAX) 1628 1.1 christos { 1629 1.1 christos vctx->revoked_zsk[dnskey.algorithm]++; 1630 1.1 christos } 1631 1.1 christos } else { 1632 1.1 christos check_dnskey_sigs(vctx, &dnskey, &rdata, is_ksk); 1633 1.1 christos } 1634 1.1 christos dns_rdata_freestruct(&dnskey); 1635 1.1 christos dns_rdata_reset(&rdata); 1636 1.1 christos } 1637 1.1 christos 1638 1.1 christos return (ISC_R_SUCCESS); 1639 1.1 christos } 1640 1.1 christos 1641 1.1 christos static void 1642 1.1 christos determine_active_algorithms(vctx_t *vctx, bool ignore_kskflag, 1643 1.1 christos bool keyset_kskonly, 1644 1.1 christos void (*report)(const char *, ...)) { 1645 1.1 christos char algbuf[DNS_SECALG_FORMATSIZE]; 1646 1.1 christos 1647 1.1 christos report("Verifying the zone using the following algorithms:"); 1648 1.1 christos 1649 1.1 christos for (size_t i = 0; i < ARRAY_SIZE(vctx->act_algorithms); i++) { 1650 1.1 christos if (ignore_kskflag) { 1651 1.1 christos vctx->act_algorithms[i] = (vctx->ksk_algorithms[i] != 1652 1.1 christos 0 || 1653 1.1 christos vctx->zsk_algorithms[i] != 0) 1654 1.1 christos ? 1 1655 1.1 christos : 0; 1656 1.1 christos } else { 1657 1.1 christos vctx->act_algorithms[i] = vctx->ksk_algorithms[i] != 0 1658 1.1 christos ? 1 1659 1.1 christos : 0; 1660 1.1 christos } 1661 1.1 christos if (vctx->act_algorithms[i] != 0) { 1662 1.1 christos dns_secalg_format(i, algbuf, sizeof(algbuf)); 1663 1.1 christos report("- %s", algbuf); 1664 1.1 christos } 1665 1.1 christos } 1666 1.1 christos 1667 1.1 christos if (ignore_kskflag || keyset_kskonly) { 1668 1.1 christos return; 1669 1.1 christos } 1670 1.1 christos 1671 1.1 christos for (size_t i = 0; i < ARRAY_SIZE(vctx->ksk_algorithms); i++) { 1672 1.1 christos /* 1673 1.1 christos * The counts should both be zero or both be non-zero. Mark 1674 1.1 christos * the algorithm as bad if this is not met. 1675 1.1 christos */ 1676 1.1 christos if ((vctx->ksk_algorithms[i] != 0) == 1677 1.1 christos (vctx->zsk_algorithms[i] != 0)) 1678 1.1 christos { 1679 1.1 christos continue; 1680 1.1 christos } 1681 1.1 christos dns_secalg_format(i, algbuf, sizeof(algbuf)); 1682 1.1 christos zoneverify_log_error(vctx, "Missing %s for algorithm %s", 1683 1.1 christos (vctx->ksk_algorithms[i] != 0) ? "ZSK" 1684 1.1 christos : "self-" 1685 1.1 christos "signed " 1686 1.1 christos "KSK", 1687 1.1 christos algbuf); 1688 1.1 christos vctx->bad_algorithms[i] = 1; 1689 1.1 christos } 1690 1.1 christos } 1691 1.1 christos 1692 1.1 christos /*% 1693 1.1 christos * Check that all the records not yet verified were signed by keys that are 1694 1.1 christos * present in the DNSKEY RRset. 1695 1.1 christos */ 1696 1.1 christos static isc_result_t 1697 1.1 christos verify_nodes(vctx_t *vctx, isc_result_t *vresult) { 1698 1.1 christos dns_fixedname_t fname, fnextname, fprevname, fzonecut; 1699 1.1 christos dns_name_t *name, *nextname, *prevname, *zonecut; 1700 1.1 christos dns_dbnode_t *node = NULL, *nextnode; 1701 1.1 christos dns_dbiterator_t *dbiter = NULL; 1702 1.1 christos dst_key_t **dstkeys; 1703 1.1 christos size_t count, nkeys = 0; 1704 1.1 christos bool done = false; 1705 1.1 christos isc_result_t tvresult = ISC_R_UNSET; 1706 1.1 christos isc_result_t result; 1707 1.1 christos 1708 1.1 christos name = dns_fixedname_initname(&fname); 1709 1.1 christos nextname = dns_fixedname_initname(&fnextname); 1710 1.1 christos dns_fixedname_init(&fprevname); 1711 1.1 christos prevname = NULL; 1712 1.1 christos dns_fixedname_init(&fzonecut); 1713 1.1 christos zonecut = NULL; 1714 1.1 christos 1715 1.1 christos count = dns_rdataset_count(&vctx->keyset); 1716 1.1 christos dstkeys = isc_mem_get(vctx->mctx, sizeof(*dstkeys) * count); 1717 1.1 christos 1718 1.1 christos for (result = dns_rdataset_first(&vctx->keyset); 1719 1.1 christos result == ISC_R_SUCCESS; result = dns_rdataset_next(&vctx->keyset)) 1720 1.1 christos { 1721 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 1722 1.1 christos dns_rdataset_current(&vctx->keyset, &rdata); 1723 1.1 christos dstkeys[nkeys] = NULL; 1724 1.1 christos result = dns_dnssec_keyfromrdata(vctx->origin, &rdata, 1725 1.1 christos vctx->mctx, &dstkeys[nkeys]); 1726 1.1 christos if (result == ISC_R_SUCCESS) { 1727 1.1 christos nkeys++; 1728 1.1 christos } 1729 1.1 christos } 1730 1.1 christos 1731 1.1 christos result = dns_db_createiterator(vctx->db, DNS_DB_NONSEC3, &dbiter); 1732 1.1 christos if (result != ISC_R_SUCCESS) { 1733 1.1 christos zoneverify_log_error(vctx, "dns_db_createiterator(): %s", 1734 1.1 christos isc_result_totext(result)); 1735 1.1 christos goto done; 1736 1.1 christos } 1737 1.1 christos 1738 1.1 christos result = dns_dbiterator_first(dbiter); 1739 1.1 christos if (result != ISC_R_SUCCESS) { 1740 1.1 christos zoneverify_log_error(vctx, "dns_dbiterator_first(): %s", 1741 1.1 christos isc_result_totext(result)); 1742 1.1 christos goto done; 1743 1.1 christos } 1744 1.1 christos 1745 1.1 christos while (!done) { 1746 1.1 christos bool isdelegation = false; 1747 1.1 christos 1748 1.1 christos result = dns_dbiterator_current(dbiter, &node, name); 1749 1.1 christos if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 1750 1.1 christos zoneverify_log_error(vctx, 1751 1.1 christos "dns_dbiterator_current(): %s", 1752 1.1 christos isc_result_totext(result)); 1753 1.1 christos goto done; 1754 1.1 christos } 1755 1.1 christos if (!dns_name_issubdomain(name, vctx->origin)) { 1756 1.1 christos result = check_no_nsec(vctx, name, node); 1757 1.1 christos if (result != ISC_R_SUCCESS) { 1758 1.1 christos dns_db_detachnode(vctx->db, &node); 1759 1.1 christos goto done; 1760 1.1 christos } 1761 1.1 christos dns_db_detachnode(vctx->db, &node); 1762 1.1 christos result = dns_dbiterator_next(dbiter); 1763 1.1 christos if (result == ISC_R_NOMORE) { 1764 1.1 christos done = true; 1765 1.1 christos } else if (result != ISC_R_SUCCESS) { 1766 1.1 christos zoneverify_log_error(vctx, 1767 1.1 christos "dns_dbiterator_next(): " 1768 1.1 christos "%s", 1769 1.1 christos isc_result_totext(result)); 1770 1.1 christos goto done; 1771 1.1 christos } 1772 1.1 christos continue; 1773 1.1 christos } 1774 1.1 christos if (is_delegation(vctx, name, node, NULL)) { 1775 1.1 christos zonecut = dns_fixedname_name(&fzonecut); 1776 1.1 christos dns_name_copynf(name, zonecut); 1777 1.1 christos isdelegation = true; 1778 1.1 christos } else if (has_dname(vctx, node)) { 1779 1.1 christos zonecut = dns_fixedname_name(&fzonecut); 1780 1.1 christos dns_name_copynf(name, zonecut); 1781 1.1 christos } 1782 1.1 christos nextnode = NULL; 1783 1.1 christos result = dns_dbiterator_next(dbiter); 1784 1.1 christos while (result == ISC_R_SUCCESS) { 1785 1.1 christos bool empty; 1786 1.1 christos result = dns_dbiterator_current(dbiter, &nextnode, 1787 1.1 christos nextname); 1788 1.1 christos if (result != ISC_R_SUCCESS && 1789 1.1 christos result != DNS_R_NEWORIGIN) 1790 1.1 christos { 1791 1.1 christos zoneverify_log_error(vctx, 1792 1.1 christos "dns_dbiterator_current():" 1793 1.1 christos " %s", 1794 1.1 christos isc_result_totext(result)); 1795 1.1 christos dns_db_detachnode(vctx->db, &node); 1796 1.1 christos goto done; 1797 1.1 christos } 1798 1.1 christos if (!dns_name_issubdomain(nextname, vctx->origin) || 1799 1.1 christos (zonecut != NULL && 1800 1.1 christos dns_name_issubdomain(nextname, zonecut))) 1801 1.1 christos { 1802 1.1 christos result = check_no_nsec(vctx, nextname, 1803 1.1 christos nextnode); 1804 1.1 christos if (result != ISC_R_SUCCESS) { 1805 1.1 christos dns_db_detachnode(vctx->db, &node); 1806 1.1 christos dns_db_detachnode(vctx->db, &nextnode); 1807 1.1 christos goto done; 1808 1.1 christos } 1809 1.1 christos dns_db_detachnode(vctx->db, &nextnode); 1810 1.1 christos result = dns_dbiterator_next(dbiter); 1811 1.1 christos continue; 1812 1.1 christos } 1813 1.1 christos result = is_empty(vctx, nextnode, &empty); 1814 1.1 christos dns_db_detachnode(vctx->db, &nextnode); 1815 1.1 christos if (result != ISC_R_SUCCESS) { 1816 1.1 christos dns_db_detachnode(vctx->db, &node); 1817 1.1 christos goto done; 1818 1.1 christos } 1819 1.1 christos if (empty) { 1820 1.1 christos result = dns_dbiterator_next(dbiter); 1821 1.1 christos continue; 1822 1.1 christos } 1823 1.1 christos break; 1824 1.1 christos } 1825 1.1 christos if (result == ISC_R_NOMORE) { 1826 1.1 christos done = true; 1827 1.1 christos nextname = vctx->origin; 1828 1.1 christos } else if (result != ISC_R_SUCCESS) { 1829 1.1 christos zoneverify_log_error(vctx, 1830 1.1 christos "iterating through the database " 1831 1.1 christos "failed: %s", 1832 1.1 christos isc_result_totext(result)); 1833 1.1 christos dns_db_detachnode(vctx->db, &node); 1834 1.1 christos goto done; 1835 1.1 christos } 1836 1.1 christos result = verifynode(vctx, name, node, isdelegation, dstkeys, 1837 1.1 christos nkeys, &vctx->nsecset, &vctx->nsec3paramset, 1838 1.1 christos nextname, &tvresult); 1839 1.1 christos if (result != ISC_R_SUCCESS) { 1840 1.1 christos dns_db_detachnode(vctx->db, &node); 1841 1.1 christos goto done; 1842 1.1 christos } 1843 1.1 christos if (*vresult == ISC_R_UNSET) { 1844 1.1 christos *vresult = ISC_R_SUCCESS; 1845 1.1 christos } 1846 1.1 christos if (*vresult == ISC_R_SUCCESS) { 1847 1.1 christos *vresult = tvresult; 1848 1.1 christos } 1849 1.1 christos if (prevname != NULL) { 1850 1.1 christos result = verifyemptynodes( 1851 1.1 christos vctx, name, prevname, isdelegation, 1852 1.1 christos &vctx->nsec3paramset, &tvresult); 1853 1.1 christos if (result != ISC_R_SUCCESS) { 1854 1.1 christos dns_db_detachnode(vctx->db, &node); 1855 1.1 christos goto done; 1856 1.1 christos } 1857 1.1 christos } else { 1858 1.1 christos prevname = dns_fixedname_name(&fprevname); 1859 1.1 christos } 1860 1.1 christos dns_name_copynf(name, prevname); 1861 1.1 christos if (*vresult == ISC_R_SUCCESS) { 1862 1.1 christos *vresult = tvresult; 1863 1.1 christos } 1864 1.1 christos dns_db_detachnode(vctx->db, &node); 1865 1.1 christos } 1866 1.1 christos 1867 1.1 christos dns_dbiterator_destroy(&dbiter); 1868 1.1 christos 1869 1.1 christos result = dns_db_createiterator(vctx->db, DNS_DB_NSEC3ONLY, &dbiter); 1870 1.1 christos if (result != ISC_R_SUCCESS) { 1871 1.1 christos zoneverify_log_error(vctx, "dns_db_createiterator(): %s", 1872 1.1 christos isc_result_totext(result)); 1873 1.1 christos return (result); 1874 1.1 christos } 1875 1.1 christos 1876 1.1 christos for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; 1877 1.1 christos result = dns_dbiterator_next(dbiter)) 1878 1.1 christos { 1879 1.1 christos result = dns_dbiterator_current(dbiter, &node, name); 1880 1.1 christos if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 1881 1.1 christos zoneverify_log_error(vctx, 1882 1.1 christos "dns_dbiterator_current(): %s", 1883 1.1 christos isc_result_totext(result)); 1884 1.1 christos goto done; 1885 1.1 christos } 1886 1.1 christos result = verifynode(vctx, name, node, false, dstkeys, nkeys, 1887 1.1 christos NULL, NULL, NULL, NULL); 1888 1.1 christos if (result != ISC_R_SUCCESS) { 1889 1.1 christos zoneverify_log_error(vctx, "verifynode: %s", 1890 1.1 christos isc_result_totext(result)); 1891 1.1 christos dns_db_detachnode(vctx->db, &node); 1892 1.1 christos goto done; 1893 1.1 christos } 1894 1.1 christos result = record_found(vctx, name, node, &vctx->nsec3paramset); 1895 1.1 christos dns_db_detachnode(vctx->db, &node); 1896 1.1 christos if (result != ISC_R_SUCCESS) { 1897 1.1 christos goto done; 1898 1.1 christos } 1899 1.1 christos } 1900 1.1 christos 1901 1.1 christos result = ISC_R_SUCCESS; 1902 1.1 christos 1903 1.1 christos done: 1904 1.1 christos while (nkeys-- > 0U) { 1905 1.1 christos dst_key_free(&dstkeys[nkeys]); 1906 1.1 christos } 1907 1.1 christos isc_mem_put(vctx->mctx, dstkeys, sizeof(*dstkeys) * count); 1908 1.1 christos if (dbiter != NULL) { 1909 1.1 christos dns_dbiterator_destroy(&dbiter); 1910 1.1 christos } 1911 1.1 christos 1912 1.1 christos return (result); 1913 1.1 christos } 1914 1.1 christos 1915 1.1 christos static isc_result_t 1916 1.1 christos check_bad_algorithms(const vctx_t *vctx, void (*report)(const char *, ...)) { 1917 1.1 christos char algbuf[DNS_SECALG_FORMATSIZE]; 1918 1.1 christos bool first = true; 1919 1.1 christos 1920 1.1 christos for (size_t i = 0; i < ARRAY_SIZE(vctx->bad_algorithms); i++) { 1921 1.1 christos if (vctx->bad_algorithms[i] == 0) { 1922 1.1 christos continue; 1923 1.1 christos } 1924 1.1 christos if (first) { 1925 1.1 christos report("The zone is not fully signed " 1926 1.1 christos "for the following algorithms:"); 1927 1.1 christos } 1928 1.1 christos dns_secalg_format(i, algbuf, sizeof(algbuf)); 1929 1.1 christos report(" %s", algbuf); 1930 1.1 christos first = false; 1931 1.1 christos } 1932 1.1 christos 1933 1.1 christos if (!first) { 1934 1.1 christos report("."); 1935 1.1 christos } 1936 1.1 christos 1937 1.1 christos return (first ? ISC_R_SUCCESS : ISC_R_FAILURE); 1938 1.1 christos } 1939 1.1 christos 1940 1.1 christos static void 1941 1.1 christos print_summary(const vctx_t *vctx, bool keyset_kskonly, 1942 1.1 christos void (*report)(const char *, ...)) { 1943 1.1 christos char algbuf[DNS_SECALG_FORMATSIZE]; 1944 1.1 christos 1945 1.1 christos report("Zone fully signed:"); 1946 1.1 christos for (size_t i = 0; i < ARRAY_SIZE(vctx->ksk_algorithms); i++) { 1947 1.1 christos if ((vctx->ksk_algorithms[i] == 0) && 1948 1.1 christos (vctx->standby_ksk[i] == 0) && 1949 1.1 christos (vctx->revoked_ksk[i] == 0) && 1950 1.1 christos (vctx->zsk_algorithms[i] == 0) && 1951 1.1 christos (vctx->standby_zsk[i] == 0) && (vctx->revoked_zsk[i] == 0)) 1952 1.1 christos { 1953 1.1 christos continue; 1954 1.1 christos } 1955 1.1 christos dns_secalg_format(i, algbuf, sizeof(algbuf)); 1956 1.1 christos report("Algorithm: %s: KSKs: " 1957 1.1 christos "%u active, %u stand-by, %u revoked", 1958 1.1 christos algbuf, vctx->ksk_algorithms[i], vctx->standby_ksk[i], 1959 1.1 christos vctx->revoked_ksk[i]); 1960 1.1 christos report("%*sZSKs: " 1961 1.1 christos "%u active, %u %s, %u revoked", 1962 1.1 christos (int)strlen(algbuf) + 13, "", vctx->zsk_algorithms[i], 1963 1.1 christos vctx->standby_zsk[i], 1964 1.1 christos keyset_kskonly ? "present" : "stand-by", 1965 1.1 christos vctx->revoked_zsk[i]); 1966 1.1 christos } 1967 1.1 christos } 1968 1.1 christos 1969 1.1 christos isc_result_t 1970 1.1 christos dns_zoneverify_dnssec(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, 1971 1.1 christos dns_name_t *origin, dns_keytable_t *secroots, 1972 1.1 christos isc_mem_t *mctx, bool ignore_kskflag, bool keyset_kskonly, 1973 1.1 christos void (*report)(const char *, ...)) { 1974 1.1 christos const char *keydesc = (secroots == NULL ? "self-signed" : "trusted"); 1975 1.1 christos isc_result_t result, vresult = ISC_R_UNSET; 1976 1.1 christos vctx_t vctx; 1977 1.1 christos 1978 1.1 christos vctx_init(&vctx, mctx, zone, db, ver, origin, secroots); 1979 1.1 christos 1980 1.1 christos result = check_apex_rrsets(&vctx); 1981 1.1 christos if (result != ISC_R_SUCCESS) { 1982 1.1 christos goto done; 1983 1.1 christos } 1984 1.1 christos 1985 1.1 christos result = check_dnskey(&vctx); 1986 1.1 christos if (result != ISC_R_SUCCESS) { 1987 1.1 christos goto done; 1988 1.1 christos } 1989 1.1 christos 1990 1.1 christos if (ignore_kskflag) { 1991 1.1 christos if (!vctx.goodksk && !vctx.goodzsk) { 1992 1.1 christos zoneverify_log_error(&vctx, "No %s DNSKEY found", 1993 1.1 christos keydesc); 1994 1.1 christos result = ISC_R_FAILURE; 1995 1.1 christos goto done; 1996 1.1 christos } 1997 1.1 christos } else if (!vctx.goodksk) { 1998 1.1 christos zoneverify_log_error(&vctx, "No %s KSK DNSKEY found", keydesc); 1999 1.1 christos result = ISC_R_FAILURE; 2000 1.1 christos goto done; 2001 1.1 christos } 2002 1.1 christos 2003 1.1 christos determine_active_algorithms(&vctx, ignore_kskflag, keyset_kskonly, 2004 1.1 christos report); 2005 1.1 christos 2006 1.1 christos result = verify_nodes(&vctx, &vresult); 2007 1.1 christos if (result != ISC_R_SUCCESS) { 2008 1.1 christos goto done; 2009 1.1 christos } 2010 1.1 christos 2011 1.1 christos result = verify_nsec3_chains(&vctx, mctx); 2012 1.1 christos if (vresult == ISC_R_UNSET) { 2013 1.1 christos vresult = ISC_R_SUCCESS; 2014 1.1 christos } 2015 1.1 christos if (result != ISC_R_SUCCESS && vresult == ISC_R_SUCCESS) { 2016 1.1 christos vresult = result; 2017 1.1 christos } 2018 1.1 christos 2019 1.1 christos result = check_bad_algorithms(&vctx, report); 2020 1.1 christos if (result != ISC_R_SUCCESS) { 2021 1.1 christos report("DNSSEC completeness test failed."); 2022 1.1 christos goto done; 2023 1.1 christos } 2024 1.1 christos 2025 1.1 christos result = vresult; 2026 1.1 christos if (result != ISC_R_SUCCESS) { 2027 1.1 christos report("DNSSEC completeness test failed (%s).", 2028 1.1 christos dns_result_totext(result)); 2029 1.1 christos goto done; 2030 1.1 christos } 2031 1.1 christos 2032 1.1 christos if (vctx.goodksk || ignore_kskflag) { 2033 1.1 christos print_summary(&vctx, keyset_kskonly, report); 2034 1.1 christos } 2035 1.1 christos 2036 1.1 christos done: 2037 1.1 christos vctx_destroy(&vctx); 2038 1.1 christos 2039 1.1 christos return (result); 2040 1.1 christos } 2041