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