1 /*
2 * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 *
11 * Portions Copyright (C) Network Associates, Inc.
12 *
13 * Permission to use, copy, modify, and/or distribute this software for any
14 * purpose with or without fee is hereby granted, provided that the above
15 * copyright notice and this permission notice appear in all copies.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
18 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
20 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
23 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 */
25
26 /*! \file */
27
28 #include <config.h>
29
30 #include <stdbool.h>
31 #include <stdlib.h>
32 #include <time.h>
33 #include <unistd.h>
34
35 #include <isc/app.h>
36 #include <isc/base32.h>
37 #include <isc/commandline.h>
38 #include <isc/entropy.h>
39 #include <isc/event.h>
40 #include <isc/file.h>
41 #include <isc/hash.h>
42 #include <isc/hex.h>
43 #include <isc/mem.h>
44 #include <isc/mutex.h>
45 #include <isc/os.h>
46 #include <isc/platform.h>
47 #include <isc/print.h>
48 #include <isc/random.h>
49 #include <isc/rwlock.h>
50 #include <isc/serial.h>
51 #include <isc/safe.h>
52 #include <isc/stdio.h>
53 #include <isc/stdlib.h>
54 #include <isc/string.h>
55 #include <isc/task.h>
56 #include <isc/time.h>
57 #include <isc/util.h>
58
59 #include <dns/db.h>
60 #include <dns/dbiterator.h>
61 #include <dns/diff.h>
62 #include <dns/dnssec.h>
63 #include <dns/ds.h>
64 #include <dns/fixedname.h>
65 #include <dns/keyvalues.h>
66 #include <dns/log.h>
67 #include <dns/master.h>
68 #include <dns/masterdump.h>
69 #include <dns/nsec.h>
70 #include <dns/nsec3.h>
71 #include <dns/rdata.h>
72 #include <dns/rdatalist.h>
73 #include <dns/rdataset.h>
74 #include <dns/rdataclass.h>
75 #include <dns/rdatasetiter.h>
76 #include <dns/rdatastruct.h>
77 #include <dns/rdatatype.h>
78 #include <dns/result.h>
79 #include <dns/soa.h>
80 #include <dns/time.h>
81 #include <dns/update.h>
82
83 #include <dst/dst.h>
84
85 #ifdef PKCS11CRYPTO
86 #include <pk11/result.h>
87 #endif
88
89 #include "dnssectool.h"
90
91 const char *program = "dnssec-signzone";
92 int verbose;
93
94 typedef struct hashlist hashlist_t;
95
96 static int nsec_datatype = dns_rdatatype_nsec;
97
98 #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
99 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
100
101 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
102
103 #define BUFSIZE 2048
104 #define MAXDSKEYS 8
105
106 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
107 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
108 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
109
110 #define SOA_SERIAL_KEEP 0
111 #define SOA_SERIAL_INCREMENT 1
112 #define SOA_SERIAL_UNIXTIME 2
113 #define SOA_SERIAL_DATE 3
114
115 typedef struct signer_event sevent_t;
116 struct signer_event {
117 ISC_EVENT_COMMON(sevent_t);
118 dns_fixedname_t *fname;
119 dns_dbnode_t *node;
120 };
121
122 static dns_dnsseckeylist_t keylist;
123 static unsigned int keycount = 0;
124 isc_rwlock_t keylist_lock;
125 static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now;
126 static int cycle = -1;
127 static int jitter = 0;
128 static bool tryverify = false;
129 static bool printstats = false;
130 static isc_mem_t *mctx = NULL;
131 static isc_entropy_t *ectx = NULL;
132 static dns_ttl_t zone_soa_min_ttl;
133 static dns_ttl_t soa_ttl;
134 static FILE *outfp = NULL;
135 static char *tempfile = NULL;
136 static const dns_master_style_t *masterstyle;
137 static dns_masterformat_t inputformat = dns_masterformat_text;
138 static dns_masterformat_t outputformat = dns_masterformat_text;
139 static uint32_t rawversion = 1, serialnum = 0;
140 static bool snset = false;
141 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
142 static unsigned int nverified = 0, nverifyfailed = 0;
143 static const char *directory = NULL, *dsdir = NULL;
144 static isc_mutex_t namelock, statslock;
145 static isc_taskmgr_t *taskmgr = NULL;
146 static dns_db_t *gdb; /* The database */
147 static dns_dbversion_t *gversion; /* The database version */
148 static dns_dbiterator_t *gdbiter; /* The database iterator */
149 static dns_rdataclass_t gclass; /* The class */
150 static dns_name_t *gorigin; /* The database origin */
151 static int nsec3flags = 0;
152 static dns_iterations_t nsec3iter = 10U;
153 static unsigned char saltbuf[255];
154 static unsigned char *gsalt = saltbuf;
155 static size_t salt_length = 0;
156 static isc_task_t *master = NULL;
157 static unsigned int ntasks = 0;
158 static bool shuttingdown = false, finished = false;
159 static bool nokeys = false;
160 static bool removefile = false;
161 static bool generateds = false;
162 static bool ignore_kskflag = false;
163 static bool keyset_kskonly = false;
164 static dns_name_t *dlv = NULL;
165 static dns_fixedname_t dlv_fixed;
166 static dns_master_style_t *dsstyle = NULL;
167 static unsigned int serialformat = SOA_SERIAL_KEEP;
168 static unsigned int hash_length = 0;
169 static bool unknownalg = false;
170 static bool disable_zone_check = false;
171 static bool update_chain = false;
172 static bool set_keyttl = false;
173 static dns_ttl_t keyttl;
174 static bool smartsign = false;
175 static bool remove_orphansigs = false;
176 static bool remove_inactkeysigs = false;
177 static bool output_dnssec_only = false;
178 static bool output_stdout = false;
179 static bool set_maxttl = false;
180 static dns_ttl_t maxttl = 0;
181 static bool no_max_check = false;
182
183 #define INCSTAT(counter) \
184 if (printstats) { \
185 LOCK(&statslock); \
186 counter++; \
187 UNLOCK(&statslock); \
188 }
189
190 static void
191 sign(isc_task_t *task, isc_event_t *event);
192
193 /*%
194 * Store a copy of 'name' in 'fzonecut' and return a pointer to that copy.
195 */
196 static dns_name_t *
savezonecut(dns_fixedname_t * fzonecut,dns_name_t * name)197 savezonecut(dns_fixedname_t *fzonecut, dns_name_t *name) {
198 dns_name_t *result;
199
200 result = dns_fixedname_initname(fzonecut);
201 dns_name_copy(name, result, NULL);
202
203 return (result);
204 }
205
206 static void
dumpnode(dns_name_t * name,dns_dbnode_t * node)207 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
208 dns_rdataset_t rds;
209 dns_rdatasetiter_t *iter = NULL;
210 isc_buffer_t *buffer = NULL;
211 isc_region_t r;
212 isc_result_t result;
213 unsigned bufsize = 4096;
214
215 if (outputformat != dns_masterformat_text)
216 return;
217
218 if (!output_dnssec_only) {
219 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node,
220 name, masterstyle, outfp);
221 check_result(result, "dns_master_dumpnodetostream");
222 return;
223 }
224
225 result = dns_db_allrdatasets(gdb, node, gversion, 0, &iter);
226 check_result(result, "dns_db_allrdatasets");
227
228 dns_rdataset_init(&rds);
229
230 result = isc_buffer_allocate(mctx, &buffer, bufsize);
231 check_result(result, "isc_buffer_allocate");
232
233 for (result = dns_rdatasetiter_first(iter);
234 result == ISC_R_SUCCESS;
235 result = dns_rdatasetiter_next(iter)) {
236
237 dns_rdatasetiter_current(iter, &rds);
238
239 if (rds.type != dns_rdatatype_rrsig &&
240 rds.type != dns_rdatatype_nsec &&
241 rds.type != dns_rdatatype_nsec3 &&
242 rds.type != dns_rdatatype_nsec3param &&
243 (!smartsign || rds.type != dns_rdatatype_dnskey)) {
244 dns_rdataset_disassociate(&rds);
245 continue;
246 }
247
248 for (;;) {
249 result = dns_master_rdatasettotext(name, &rds,
250 masterstyle, buffer);
251 if (result != ISC_R_NOSPACE)
252 break;
253
254 bufsize <<= 1;
255 isc_buffer_free(&buffer);
256 result = isc_buffer_allocate(mctx, &buffer, bufsize);
257 check_result(result, "isc_buffer_allocate");
258 }
259 check_result(result, "dns_master_rdatasettotext");
260
261 isc_buffer_usedregion(buffer, &r);
262 result = isc_stdio_write(r.base, 1, r.length, outfp, NULL);
263 check_result(result, "isc_stdio_write");
264 isc_buffer_clear(buffer);
265
266 dns_rdataset_disassociate(&rds);
267 }
268
269 isc_buffer_free(&buffer);
270 dns_rdatasetiter_destroy(&iter);
271 }
272
273 /*%
274 * Sign the given RRset with given key, and add the signature record to the
275 * given tuple.
276 */
277 static void
signwithkey(dns_name_t * name,dns_rdataset_t * rdataset,dst_key_t * key,dns_ttl_t ttl,dns_diff_t * add,const char * logmsg)278 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
279 dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
280 {
281 isc_result_t result;
282 isc_stdtime_t jendtime, expiry;
283 char keystr[DST_KEY_FORMATSIZE];
284 dns_rdata_t trdata = DNS_RDATA_INIT;
285 unsigned char array[BUFSIZE];
286 isc_buffer_t b;
287 dns_difftuple_t *tuple;
288
289 dst_key_format(key, keystr, sizeof(keystr));
290 vbprintf(1, "\t%s %s\n", logmsg, keystr);
291
292 if (rdataset->type == dns_rdatatype_dnskey)
293 expiry = dnskey_endtime;
294 else
295 expiry = endtime;
296
297 jendtime = (jitter != 0) ? isc_random_jitter(expiry, jitter) : expiry;
298 isc_buffer_init(&b, array, sizeof(array));
299 result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
300 mctx, &b, &trdata);
301 isc_entropy_stopcallbacksources(ectx);
302 if (result != ISC_R_SUCCESS) {
303 fatal("dnskey '%s' failed to sign data: %s",
304 keystr, isc_result_totext(result));
305 }
306 INCSTAT(nsigned);
307
308 if (tryverify) {
309 result = dns_dnssec_verify(name, rdataset, key,
310 true, mctx, &trdata);
311 if (result == ISC_R_SUCCESS) {
312 vbprintf(3, "\tsignature verified\n");
313 INCSTAT(nverified);
314 } else {
315 vbprintf(3, "\tsignature failed to verify\n");
316 INCSTAT(nverifyfailed);
317 }
318 }
319
320 tuple = NULL;
321 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN,
322 name, ttl, &trdata, &tuple);
323 check_result(result, "dns_difftuple_create");
324 dns_diff_append(add, &tuple);
325 }
326
327 static inline bool
issigningkey(dns_dnsseckey_t * key)328 issigningkey(dns_dnsseckey_t *key) {
329 return (key->force_sign || key->hint_sign);
330 }
331
332 static inline bool
ispublishedkey(dns_dnsseckey_t * key)333 ispublishedkey(dns_dnsseckey_t *key) {
334 return ((key->force_publish || key->hint_publish) &&
335 !key->hint_remove);
336 }
337
338 static inline bool
iszonekey(dns_dnsseckey_t * key)339 iszonekey(dns_dnsseckey_t *key) {
340 return (dns_name_equal(dst_key_name(key->key), gorigin) &&
341 dst_key_iszonekey(key->key));
342 }
343
344 static inline bool
isksk(dns_dnsseckey_t * key)345 isksk(dns_dnsseckey_t *key) {
346 return (key->ksk);
347 }
348
349 static inline bool
iszsk(dns_dnsseckey_t * key)350 iszsk(dns_dnsseckey_t *key) {
351 return (ignore_kskflag || !key->ksk);
352 }
353
354 /*%
355 * Find the key that generated an RRSIG, if it is in the key list. If
356 * so, return a pointer to it, otherwise return NULL.
357 *
358 * No locking is performed here, this must be done by the caller.
359 */
360 static dns_dnsseckey_t *
keythatsigned_unlocked(dns_rdata_rrsig_t * rrsig)361 keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
362 dns_dnsseckey_t *key;
363
364 for (key = ISC_LIST_HEAD(keylist);
365 key != NULL;
366 key = ISC_LIST_NEXT(key, link)) {
367 if (rrsig->keyid == dst_key_id(key->key) &&
368 rrsig->algorithm == dst_key_alg(key->key) &&
369 dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
370 return (key);
371 }
372 return (NULL);
373 }
374
375 /*%
376 * Finds the key that generated a RRSIG, if possible. First look at the keys
377 * that we've loaded already, and then see if there's a key on disk.
378 */
379 static dns_dnsseckey_t *
keythatsigned(dns_rdata_rrsig_t * rrsig)380 keythatsigned(dns_rdata_rrsig_t *rrsig) {
381 isc_result_t result;
382 dst_key_t *pubkey = NULL, *privkey = NULL;
383 dns_dnsseckey_t *key = NULL;
384
385 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
386 key = keythatsigned_unlocked(rrsig);
387 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
388 if (key != NULL)
389 return (key);
390
391 /*
392 * We did not find the key in our list. Get a write lock now, since
393 * we may be modifying the bits. We could do the tryupgrade() dance,
394 * but instead just get a write lock and check once again to see if
395 * it is on our list. It's possible someone else may have added it
396 * after all.
397 */
398 isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
399 key = keythatsigned_unlocked(rrsig);
400 if (key != NULL) {
401 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
402 return (key);
403 }
404
405 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
406 rrsig->algorithm, DST_TYPE_PUBLIC,
407 directory, mctx, &pubkey);
408 if (result != ISC_R_SUCCESS) {
409 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
410 return (NULL);
411 }
412
413 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
414 rrsig->algorithm,
415 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
416 directory, mctx, &privkey);
417 if (result == ISC_R_SUCCESS) {
418 dst_key_free(&pubkey);
419 result = dns_dnsseckey_create(mctx, &privkey, &key);
420 } else
421 result = dns_dnsseckey_create(mctx, &pubkey, &key);
422
423 if (result == ISC_R_SUCCESS) {
424 key->force_publish = false;
425 key->force_sign = false;
426 key->index = keycount++;
427 ISC_LIST_APPEND(keylist, key, link);
428 }
429
430 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
431 return (key);
432 }
433
434 /*%
435 * Check to see if we expect to find a key at this name. If we see a RRSIG
436 * and can't find the signing key that we expect to find, we drop the rrsig.
437 * I'm not sure if this is completely correct, but it seems to work.
438 */
439 static bool
expecttofindkey(dns_name_t * name)440 expecttofindkey(dns_name_t *name) {
441 unsigned int options = DNS_DBFIND_NOWILD;
442 dns_fixedname_t fname;
443 isc_result_t result;
444 char namestr[DNS_NAME_FORMATSIZE];
445
446 dns_fixedname_init(&fname);
447 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
448 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
449 switch (result) {
450 case ISC_R_SUCCESS:
451 case DNS_R_NXDOMAIN:
452 case DNS_R_NXRRSET:
453 return (true);
454 case DNS_R_DELEGATION:
455 case DNS_R_CNAME:
456 case DNS_R_DNAME:
457 return (false);
458 }
459 dns_name_format(name, namestr, sizeof(namestr));
460 fatal("failure looking for '%s DNSKEY' in database: %s",
461 namestr, isc_result_totext(result));
462 /* NOTREACHED */
463 return (false); /* removes a warning */
464 }
465
466 static inline bool
setverifies(dns_name_t * name,dns_rdataset_t * set,dst_key_t * key,dns_rdata_t * rrsig)467 setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
468 dns_rdata_t *rrsig)
469 {
470 isc_result_t result;
471 result = dns_dnssec_verify(name, set, key, false, mctx, rrsig);
472 if (result == ISC_R_SUCCESS) {
473 INCSTAT(nverified);
474 return (true);
475 } else {
476 INCSTAT(nverifyfailed);
477 return (false);
478 }
479 }
480
481 /*%
482 * Signs a set. Goes through contortions to decide if each RRSIG should
483 * be dropped or retained, and then determines if any new SIGs need to
484 * be generated.
485 */
486 static void
signset(dns_diff_t * del,dns_diff_t * add,dns_dbnode_t * node,dns_name_t * name,dns_rdataset_t * set)487 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
488 dns_rdataset_t *set)
489 {
490 dns_rdataset_t sigset;
491 dns_rdata_t sigrdata = DNS_RDATA_INIT;
492 dns_rdata_rrsig_t rrsig;
493 dns_dnsseckey_t *key;
494 isc_result_t result;
495 bool nosigs = false;
496 bool *wassignedby, *nowsignedby;
497 int arraysize;
498 dns_difftuple_t *tuple;
499 dns_ttl_t ttl;
500 int i;
501 char namestr[DNS_NAME_FORMATSIZE];
502 char typestr[TYPE_FORMATSIZE];
503 char sigstr[SIG_FORMATSIZE];
504
505 dns_name_format(name, namestr, sizeof(namestr));
506 type_format(set->type, typestr, sizeof(typestr));
507
508 ttl = ISC_MIN(set->ttl, endtime - starttime);
509
510 dns_rdataset_init(&sigset);
511 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
512 set->type, 0, &sigset, NULL);
513 if (result == ISC_R_NOTFOUND) {
514 vbprintf(2, "no existing signatures for %s/%s\n",
515 namestr, typestr);
516 result = ISC_R_SUCCESS;
517 nosigs = true;
518 }
519 if (result != ISC_R_SUCCESS)
520 fatal("failed while looking for '%s RRSIG %s': %s",
521 namestr, typestr, isc_result_totext(result));
522
523 vbprintf(1, "%s/%s:\n", namestr, typestr);
524
525 arraysize = keycount;
526 if (!nosigs)
527 arraysize += dns_rdataset_count(&sigset);
528 wassignedby = isc_mem_get(mctx, arraysize * sizeof(bool));
529 nowsignedby = isc_mem_get(mctx, arraysize * sizeof(bool));
530 if (wassignedby == NULL || nowsignedby == NULL)
531 fatal("out of memory");
532
533 for (i = 0; i < arraysize; i++)
534 wassignedby[i] = nowsignedby[i] = false;
535
536 if (nosigs)
537 result = ISC_R_NOMORE;
538 else
539 result = dns_rdataset_first(&sigset);
540
541 while (result == ISC_R_SUCCESS) {
542 bool expired, future;
543 bool keep = false, resign = false;
544
545 dns_rdataset_current(&sigset, &sigrdata);
546
547 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
548 check_result(result, "dns_rdata_tostruct");
549
550 future = isc_serial_lt(now, rrsig.timesigned);
551
552 key = keythatsigned(&rrsig);
553 sig_format(&rrsig, sigstr, sizeof(sigstr));
554 if (key != NULL && issigningkey(key))
555 expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
556 else
557 expired = isc_serial_gt(now, rrsig.timeexpire);
558
559 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
560 /* rrsig is dropped and not replaced */
561 vbprintf(2, "\trrsig by %s dropped - "
562 "invalid validity period\n",
563 sigstr);
564 } else if (key == NULL && !future &&
565 expecttofindkey(&rrsig.signer)) {
566 /* rrsig is dropped and not replaced */
567 vbprintf(2, "\trrsig by %s dropped - "
568 "private dnskey not found\n",
569 sigstr);
570 } else if (key == NULL || future) {
571 keep = (!expired && !remove_orphansigs);
572 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
573 keep ? "retained" : "dropped", sigstr);
574 } else if (!dns_dnssec_keyactive(key->key, now) &&
575 remove_inactkeysigs) {
576 keep = false;
577 vbprintf(2, "\trrsig by %s dropped - key inactive\n",
578 sigstr);
579 } else if (issigningkey(key)) {
580 wassignedby[key->index] = true;
581
582 if (!expired && rrsig.originalttl == set->ttl &&
583 setverifies(name, set, key->key, &sigrdata)) {
584 vbprintf(2, "\trrsig by %s retained\n", sigstr);
585 keep = true;
586 } else {
587 vbprintf(2, "\trrsig by %s dropped - %s\n",
588 sigstr, expired ? "expired" :
589 rrsig.originalttl != set->ttl ?
590 "ttl change" : "failed to verify");
591 resign = true;
592 }
593 } else if (!ispublishedkey(key) && remove_orphansigs) {
594 vbprintf(2, "\trrsig by %s dropped - dnskey removed\n",
595 sigstr);
596 } else if (iszonekey(key)) {
597 wassignedby[key->index] = true;
598
599 if (!expired && rrsig.originalttl == set->ttl &&
600 setverifies(name, set, key->key, &sigrdata)) {
601 vbprintf(2, "\trrsig by %s retained\n", sigstr);
602 keep = true;
603 } else {
604 vbprintf(2, "\trrsig by %s dropped - %s\n",
605 sigstr, expired ? "expired" :
606 rrsig.originalttl != set->ttl ?
607 "ttl change" : "failed to verify");
608 }
609 } else if (!expired) {
610 vbprintf(2, "\trrsig by %s retained\n", sigstr);
611 keep = true;
612 } else {
613 vbprintf(2, "\trrsig by %s expired\n", sigstr);
614 }
615
616 if (keep) {
617 if (key != NULL)
618 nowsignedby[key->index] = true;
619 INCSTAT(nretained);
620 if (sigset.ttl != ttl) {
621 vbprintf(2, "\tfixing ttl %s\n", sigstr);
622 tuple = NULL;
623 result = dns_difftuple_create(mctx,
624 DNS_DIFFOP_DELRESIGN,
625 name, sigset.ttl,
626 &sigrdata, &tuple);
627 check_result(result, "dns_difftuple_create");
628 dns_diff_append(del, &tuple);
629 result = dns_difftuple_create(mctx,
630 DNS_DIFFOP_ADDRESIGN,
631 name, ttl,
632 &sigrdata, &tuple);
633 check_result(result, "dns_difftuple_create");
634 dns_diff_append(add, &tuple);
635 }
636 } else {
637 tuple = NULL;
638 vbprintf(2, "removing signature by %s\n", sigstr);
639 result = dns_difftuple_create(mctx,
640 DNS_DIFFOP_DELRESIGN,
641 name, sigset.ttl,
642 &sigrdata, &tuple);
643 check_result(result, "dns_difftuple_create");
644 dns_diff_append(del, &tuple);
645 INCSTAT(ndropped);
646 }
647
648 if (resign) {
649 INSIST(!keep);
650
651 signwithkey(name, set, key->key, ttl, add,
652 "resigning with dnskey");
653 nowsignedby[key->index] = true;
654 }
655
656 dns_rdata_reset(&sigrdata);
657 dns_rdata_freestruct(&rrsig);
658 result = dns_rdataset_next(&sigset);
659 }
660 if (result == ISC_R_NOMORE)
661 result = ISC_R_SUCCESS;
662
663 check_result(result, "dns_rdataset_first/next");
664 if (dns_rdataset_isassociated(&sigset))
665 dns_rdataset_disassociate(&sigset);
666
667 for (key = ISC_LIST_HEAD(keylist);
668 key != NULL;
669 key = ISC_LIST_NEXT(key, link))
670 {
671 if (nowsignedby[key->index])
672 continue;
673
674 if (!issigningkey(key))
675 continue;
676
677 if (set->type == dns_rdatatype_dnskey &&
678 dns_name_equal(name, gorigin)) {
679 bool have_ksk;
680 dns_dnsseckey_t *tmpkey;
681
682 have_ksk = isksk(key);
683 for (tmpkey = ISC_LIST_HEAD(keylist);
684 tmpkey != NULL;
685 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
686 if (dst_key_alg(key->key) !=
687 dst_key_alg(tmpkey->key))
688 continue;
689 if (REVOKE(tmpkey->key))
690 continue;
691 if (isksk(tmpkey))
692 have_ksk = true;
693 }
694 if (isksk(key) || !have_ksk ||
695 (iszsk(key) && !keyset_kskonly))
696 signwithkey(name, set, key->key, ttl, add,
697 "signing with dnskey");
698 } else if (set->type == dns_rdatatype_cds ||
699 set->type == dns_rdatatype_cdnskey ||
700 iszsk(key)) {
701 signwithkey(name, set, key->key, ttl, add,
702 "signing with dnskey");
703 }
704 }
705
706 isc_mem_put(mctx, wassignedby, arraysize * sizeof(bool));
707 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(bool));
708 }
709
710 struct hashlist {
711 unsigned char *hashbuf;
712 size_t entries;
713 size_t size;
714 size_t length;
715 };
716
717 static void
hashlist_init(hashlist_t * l,unsigned int nodes,unsigned int length)718 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
719
720 l->entries = 0;
721 l->length = length + 1;
722
723 if (nodes != 0) {
724 l->size = nodes;
725 l->hashbuf = malloc(l->size * l->length);
726 if (l->hashbuf == NULL)
727 l->size = 0;
728 } else {
729 l->size = 0;
730 l->hashbuf = NULL;
731 }
732 }
733
734 static void
hashlist_free(hashlist_t * l)735 hashlist_free(hashlist_t *l) {
736 if (l->hashbuf) {
737 free(l->hashbuf);
738 l->hashbuf = NULL;
739 l->entries = 0;
740 l->length = 0;
741 l->size = 0;
742 }
743 }
744
745 static void
hashlist_add(hashlist_t * l,const unsigned char * hash,size_t len)746 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
747 {
748
749 REQUIRE(len <= l->length);
750
751 if (l->entries == l->size) {
752 l->size = l->size * 2 + 100;
753 l->hashbuf = realloc(l->hashbuf, l->size * l->length);
754 if (l->hashbuf == NULL)
755 fatal("unable to grow hashlist: out of memory");
756 }
757 memset(l->hashbuf + l->entries * l->length, 0, l->length);
758 memmove(l->hashbuf + l->entries * l->length, hash, len);
759 l->entries++;
760 }
761
762 static void
hashlist_add_dns_name(hashlist_t * l,dns_name_t * name,unsigned int hashalg,unsigned int iterations,const unsigned char * salt,size_t salt_len,bool speculative)763 hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
764 unsigned int hashalg, unsigned int iterations,
765 const unsigned char *salt, size_t salt_len,
766 bool speculative)
767 {
768 char nametext[DNS_NAME_FORMATSIZE];
769 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
770 unsigned int len;
771 size_t i;
772
773 len = isc_iterated_hash(hash, hashalg, iterations,
774 salt, (int)salt_len,
775 name->ndata, name->length);
776 if (verbose) {
777 dns_name_format(name, nametext, sizeof nametext);
778 for (i = 0 ; i < len; i++)
779 fprintf(stderr, "%02x", hash[i]);
780 fprintf(stderr, " %s\n", nametext);
781 }
782 hash[len++] = speculative ? 1 : 0;
783 hashlist_add(l, hash, len);
784 }
785
786 static int
hashlist_comp(const void * a,const void * b)787 hashlist_comp(const void *a, const void *b) {
788 return (isc_safe_memcompare(a, b, hash_length + 1));
789 }
790
791 static void
hashlist_sort(hashlist_t * l)792 hashlist_sort(hashlist_t *l) {
793 INSIST(l->hashbuf != NULL || l->length == 0);
794 if (l->length > 0) {
795 qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
796 }
797 }
798
799 static bool
hashlist_hasdup(hashlist_t * l)800 hashlist_hasdup(hashlist_t *l) {
801 unsigned char *current;
802 unsigned char *next = l->hashbuf;
803 size_t entries = l->entries;
804
805 /*
806 * Skip initial speculative wild card hashes.
807 */
808 while (entries > 0U && next[l->length-1] != 0U) {
809 next += l->length;
810 entries--;
811 }
812
813 current = next;
814 while (entries-- > 1U) {
815 next += l->length;
816 if (next[l->length-1] != 0)
817 continue;
818 if (isc_safe_memequal(current, next, l->length - 1))
819 return (true);
820 current = next;
821 }
822 return (false);
823 }
824
825 static const unsigned char *
hashlist_findnext(const hashlist_t * l,const unsigned char hash[NSEC3_MAX_HASH_LENGTH])826 hashlist_findnext(const hashlist_t *l,
827 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
828 {
829 size_t entries = l->entries;
830 const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
831 l->length, hashlist_comp);
832 INSIST(next != NULL);
833
834 do {
835 if (next < l->hashbuf + (l->entries - 1) * l->length)
836 next += l->length;
837 else
838 next = l->hashbuf;
839 if (next[l->length - 1] == 0)
840 break;
841 } while (entries-- > 1U);
842 INSIST(entries != 0U);
843 return (next);
844 }
845
846 static bool
hashlist_exists(const hashlist_t * l,const unsigned char hash[NSEC3_MAX_HASH_LENGTH])847 hashlist_exists(const hashlist_t *l,
848 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
849 {
850 if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
851 return (true);
852 else
853 return (false);
854 }
855
856 static void
addnowildcardhash(hashlist_t * l,dns_name_t * name,unsigned int hashalg,unsigned int iterations,const unsigned char * salt,size_t salt_len)857 addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
858 unsigned int hashalg, unsigned int iterations,
859 const unsigned char *salt, size_t salt_len)
860 {
861 dns_fixedname_t fixed;
862 dns_name_t *wild;
863 dns_dbnode_t *node = NULL;
864 isc_result_t result;
865 char namestr[DNS_NAME_FORMATSIZE];
866
867 wild = dns_fixedname_initname(&fixed);
868
869 result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
870 if (result == ISC_R_NOSPACE)
871 return;
872 check_result(result,"addnowildcardhash: dns_name_concatenate()");
873
874 result = dns_db_findnode(gdb, wild, false, &node);
875 if (result == ISC_R_SUCCESS) {
876 dns_db_detachnode(gdb, &node);
877 return;
878 }
879
880 if (verbose) {
881 dns_name_format(wild, namestr, sizeof(namestr));
882 fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
883 }
884
885 hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_len,
886 true);
887 }
888
889 static void
opendb(const char * prefix,dns_name_t * name,dns_rdataclass_t rdclass,dns_db_t ** dbp)890 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
891 dns_db_t **dbp)
892 {
893 char filename[PATH_MAX];
894 isc_buffer_t b;
895 isc_result_t result;
896
897 isc_buffer_init(&b, filename, sizeof(filename));
898 if (dsdir != NULL) {
899 /* allow room for a trailing slash */
900 if (strlen(dsdir) >= isc_buffer_availablelength(&b))
901 fatal("path '%s' is too long", dsdir);
902 isc_buffer_putstr(&b, dsdir);
903 if (dsdir[strlen(dsdir) - 1] != '/')
904 isc_buffer_putstr(&b, "/");
905 }
906 if (strlen(prefix) > isc_buffer_availablelength(&b))
907 fatal("path '%s' is too long", dsdir);
908 isc_buffer_putstr(&b, prefix);
909 result = dns_name_tofilenametext(name, false, &b);
910 check_result(result, "dns_name_tofilenametext()");
911 if (isc_buffer_availablelength(&b) == 0) {
912 char namestr[DNS_NAME_FORMATSIZE];
913 dns_name_format(name, namestr, sizeof(namestr));
914 fatal("name '%s' is too long", namestr);
915 }
916 isc_buffer_putuint8(&b, 0);
917
918 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
919 rdclass, 0, NULL, dbp);
920 check_result(result, "dns_db_create()");
921
922 result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT);
923 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
924 dns_db_detach(dbp);
925 }
926
927 /*%
928 * Load the DS set for a child zone, if a dsset-* file can be found.
929 * If not, try to find a keyset-* file from an earlier version of
930 * dnssec-signzone, and build DS records from that.
931 */
932 static isc_result_t
loadds(dns_name_t * name,uint32_t ttl,dns_rdataset_t * dsset)933 loadds(dns_name_t *name, uint32_t ttl, dns_rdataset_t *dsset) {
934 dns_db_t *db = NULL;
935 dns_dbversion_t *ver = NULL;
936 dns_dbnode_t *node = NULL;
937 isc_result_t result;
938 dns_rdataset_t keyset;
939 dns_rdata_t key, ds;
940 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
941 dns_diff_t diff;
942 dns_difftuple_t *tuple = NULL;
943
944 opendb("dsset-", name, gclass, &db);
945 if (db != NULL) {
946 result = dns_db_findnode(db, name, false, &node);
947 if (result == ISC_R_SUCCESS) {
948 dns_rdataset_init(dsset);
949 result = dns_db_findrdataset(db, node, NULL,
950 dns_rdatatype_ds, 0, 0,
951 dsset, NULL);
952 dns_db_detachnode(db, &node);
953 if (result == ISC_R_SUCCESS) {
954 vbprintf(2, "found DS records\n");
955 dsset->ttl = ttl;
956 dns_db_detach(&db);
957 return (result);
958 }
959 }
960 dns_db_detach(&db);
961 }
962
963 /* No DS records found; try again, looking for DNSKEY records */
964 opendb("keyset-", name, gclass, &db);
965 if (db == NULL) {
966 return (ISC_R_NOTFOUND);
967 }
968
969 result = dns_db_findnode(db, name, false, &node);
970 if (result != ISC_R_SUCCESS) {
971 dns_db_detach(&db);
972 return (result);
973 }
974
975 dns_rdataset_init(&keyset);
976 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
977 &keyset, NULL);
978 if (result != ISC_R_SUCCESS) {
979 dns_db_detachnode(db, &node);
980 dns_db_detach(&db);
981 return (result);
982 }
983 vbprintf(2, "found DNSKEY records\n");
984
985 result = dns_db_newversion(db, &ver);
986 check_result(result, "dns_db_newversion");
987 dns_diff_init(mctx, &diff);
988
989 for (result = dns_rdataset_first(&keyset);
990 result == ISC_R_SUCCESS;
991 result = dns_rdataset_next(&keyset))
992 {
993 dns_rdata_init(&key);
994 dns_rdata_init(&ds);
995 dns_rdataset_current(&keyset, &key);
996 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
997 dsbuf, &ds);
998 check_result(result, "dns_ds_buildrdata");
999
1000 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
1001 ttl, &ds, &tuple);
1002 check_result(result, "dns_difftuple_create");
1003 dns_diff_append(&diff, &tuple);
1004
1005 dns_rdata_reset(&ds);
1006 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
1007 dsbuf, &ds);
1008 check_result(result, "dns_ds_buildrdata");
1009
1010 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
1011 ttl, &ds, &tuple);
1012 check_result(result, "dns_difftuple_create");
1013 dns_diff_append(&diff, &tuple);
1014 }
1015
1016 result = dns_diff_apply(&diff, db, ver);
1017 check_result(result, "dns_diff_apply");
1018 dns_diff_clear(&diff);
1019
1020 dns_db_closeversion(db, &ver, true);
1021
1022 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
1023 dsset, NULL);
1024 check_result(result, "dns_db_findrdataset");
1025
1026 dns_rdataset_disassociate(&keyset);
1027 dns_db_detachnode(db, &node);
1028 dns_db_detach(&db);
1029 return (result);
1030 }
1031
1032 static bool
secure(dns_name_t * name,dns_dbnode_t * node)1033 secure(dns_name_t *name, dns_dbnode_t *node) {
1034 dns_rdataset_t dsset;
1035 isc_result_t result;
1036
1037 if (dns_name_equal(name, gorigin))
1038 return (false);
1039
1040 dns_rdataset_init(&dsset);
1041 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
1042 0, 0, &dsset, NULL);
1043 if (dns_rdataset_isassociated(&dsset))
1044 dns_rdataset_disassociate(&dsset);
1045
1046 return (result == ISC_R_SUCCESS);
1047 }
1048
1049 /*%
1050 * Signs all records at a name.
1051 */
1052 static void
signname(dns_dbnode_t * node,dns_name_t * name)1053 signname(dns_dbnode_t *node, dns_name_t *name) {
1054 isc_result_t result;
1055 dns_rdataset_t rdataset;
1056 dns_rdatasetiter_t *rdsiter;
1057 bool isdelegation = false;
1058 dns_diff_t del, add;
1059 char namestr[DNS_NAME_FORMATSIZE];
1060
1061 dns_rdataset_init(&rdataset);
1062 dns_name_format(name, namestr, sizeof(namestr));
1063
1064 /*
1065 * Determine if this is a delegation point.
1066 */
1067 if (is_delegation(gdb, gversion, gorigin, name, node, NULL))
1068 isdelegation = true;
1069
1070 /*
1071 * Now iterate through the rdatasets.
1072 */
1073 dns_diff_init(mctx, &del);
1074 dns_diff_init(mctx, &add);
1075 rdsiter = NULL;
1076 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1077 check_result(result, "dns_db_allrdatasets()");
1078 result = dns_rdatasetiter_first(rdsiter);
1079 while (result == ISC_R_SUCCESS) {
1080 dns_rdatasetiter_current(rdsiter, &rdataset);
1081
1082 /* If this is a RRSIG set, skip it. */
1083 if (rdataset.type == dns_rdatatype_rrsig)
1084 goto skip;
1085
1086 /*
1087 * If this name is a delegation point, skip all records
1088 * except NSEC and DS sets. Otherwise check that there
1089 * isn't a DS record.
1090 */
1091 if (isdelegation) {
1092 if (rdataset.type != nsec_datatype &&
1093 rdataset.type != dns_rdatatype_ds)
1094 goto skip;
1095 } else if (rdataset.type == dns_rdatatype_ds) {
1096 char namebuf[DNS_NAME_FORMATSIZE];
1097 dns_name_format(name, namebuf, sizeof(namebuf));
1098 fatal("'%s': found DS RRset without NS RRset\n",
1099 namebuf);
1100 }
1101
1102 signset(&del, &add, node, name, &rdataset);
1103
1104 skip:
1105 dns_rdataset_disassociate(&rdataset);
1106 result = dns_rdatasetiter_next(rdsiter);
1107 }
1108 if (result != ISC_R_NOMORE)
1109 fatal("rdataset iteration for name '%s' failed: %s",
1110 namestr, isc_result_totext(result));
1111
1112 dns_rdatasetiter_destroy(&rdsiter);
1113
1114 result = dns_diff_applysilently(&del, gdb, gversion);
1115 if (result != ISC_R_SUCCESS)
1116 fatal("failed to delete SIGs at node '%s': %s",
1117 namestr, isc_result_totext(result));
1118
1119 result = dns_diff_applysilently(&add, gdb, gversion);
1120 if (result != ISC_R_SUCCESS)
1121 fatal("failed to add SIGs at node '%s': %s",
1122 namestr, isc_result_totext(result));
1123
1124 dns_diff_clear(&del);
1125 dns_diff_clear(&add);
1126 }
1127
1128 /*
1129 * See if the node contains any non RRSIG/NSEC records and report to
1130 * caller. Clean out extraneous RRSIG records for node.
1131 */
1132 static inline bool
active_node(dns_dbnode_t * node)1133 active_node(dns_dbnode_t *node) {
1134 dns_rdatasetiter_t *rdsiter = NULL;
1135 dns_rdatasetiter_t *rdsiter2 = NULL;
1136 bool active = false;
1137 isc_result_t result;
1138 dns_rdataset_t rdataset;
1139 dns_rdatatype_t type;
1140 dns_rdatatype_t covers;
1141 bool found;
1142
1143 dns_rdataset_init(&rdataset);
1144 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1145 check_result(result, "dns_db_allrdatasets()");
1146 result = dns_rdatasetiter_first(rdsiter);
1147 while (result == ISC_R_SUCCESS) {
1148 dns_rdatasetiter_current(rdsiter, &rdataset);
1149 if (rdataset.type != dns_rdatatype_nsec &&
1150 rdataset.type != dns_rdatatype_nsec3 &&
1151 rdataset.type != dns_rdatatype_rrsig)
1152 active = true;
1153 dns_rdataset_disassociate(&rdataset);
1154 if (!active)
1155 result = dns_rdatasetiter_next(rdsiter);
1156 else
1157 result = ISC_R_NOMORE;
1158 }
1159 if (result != ISC_R_NOMORE)
1160 fatal("rdataset iteration failed: %s",
1161 isc_result_totext(result));
1162
1163 if (!active && nsec_datatype == dns_rdatatype_nsec) {
1164 /*%
1165 * The node is empty of everything but NSEC / RRSIG records.
1166 */
1167 for (result = dns_rdatasetiter_first(rdsiter);
1168 result == ISC_R_SUCCESS;
1169 result = dns_rdatasetiter_next(rdsiter)) {
1170 dns_rdatasetiter_current(rdsiter, &rdataset);
1171 result = dns_db_deleterdataset(gdb, node, gversion,
1172 rdataset.type,
1173 rdataset.covers);
1174 check_result(result, "dns_db_deleterdataset()");
1175 dns_rdataset_disassociate(&rdataset);
1176 }
1177 if (result != ISC_R_NOMORE)
1178 fatal("rdataset iteration failed: %s",
1179 isc_result_totext(result));
1180 } else {
1181 /*
1182 * Delete RRSIGs for types that no longer exist.
1183 */
1184 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
1185 check_result(result, "dns_db_allrdatasets()");
1186 for (result = dns_rdatasetiter_first(rdsiter);
1187 result == ISC_R_SUCCESS;
1188 result = dns_rdatasetiter_next(rdsiter)) {
1189 dns_rdatasetiter_current(rdsiter, &rdataset);
1190 type = rdataset.type;
1191 covers = rdataset.covers;
1192 dns_rdataset_disassociate(&rdataset);
1193 /*
1194 * Delete the NSEC chain if we are signing with
1195 * NSEC3.
1196 */
1197 if (nsec_datatype == dns_rdatatype_nsec3 &&
1198 (type == dns_rdatatype_nsec ||
1199 covers == dns_rdatatype_nsec)) {
1200 result = dns_db_deleterdataset(gdb, node,
1201 gversion, type,
1202 covers);
1203 check_result(result,
1204 "dns_db_deleterdataset(nsec/rrsig)");
1205 continue;
1206 }
1207 if (type != dns_rdatatype_rrsig)
1208 continue;
1209 found = false;
1210 for (result = dns_rdatasetiter_first(rdsiter2);
1211 !found && result == ISC_R_SUCCESS;
1212 result = dns_rdatasetiter_next(rdsiter2)) {
1213 dns_rdatasetiter_current(rdsiter2, &rdataset);
1214 if (rdataset.type == covers)
1215 found = true;
1216 dns_rdataset_disassociate(&rdataset);
1217 }
1218 if (!found) {
1219 if (result != ISC_R_NOMORE)
1220 fatal("rdataset iteration failed: %s",
1221 isc_result_totext(result));
1222 result = dns_db_deleterdataset(gdb, node,
1223 gversion, type,
1224 covers);
1225 check_result(result,
1226 "dns_db_deleterdataset(rrsig)");
1227 } else if (result != ISC_R_NOMORE &&
1228 result != ISC_R_SUCCESS)
1229 fatal("rdataset iteration failed: %s",
1230 isc_result_totext(result));
1231 }
1232 if (result != ISC_R_NOMORE)
1233 fatal("rdataset iteration failed: %s",
1234 isc_result_totext(result));
1235 dns_rdatasetiter_destroy(&rdsiter2);
1236 }
1237 dns_rdatasetiter_destroy(&rdsiter);
1238
1239 return (active);
1240 }
1241
1242 /*%
1243 * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
1244 */
1245 static void
get_soa_ttls(void)1246 get_soa_ttls(void) {
1247 dns_rdataset_t soaset;
1248 dns_fixedname_t fname;
1249 dns_name_t *name;
1250 isc_result_t result;
1251 dns_rdata_t rdata = DNS_RDATA_INIT;
1252
1253 name = dns_fixedname_initname(&fname);
1254 dns_rdataset_init(&soaset);
1255 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1256 0, 0, NULL, name, &soaset, NULL);
1257 if (result != ISC_R_SUCCESS)
1258 fatal("failed to find an SOA at the zone apex: %s",
1259 isc_result_totext(result));
1260
1261 result = dns_rdataset_first(&soaset);
1262 check_result(result, "dns_rdataset_first");
1263 dns_rdataset_current(&soaset, &rdata);
1264 zone_soa_min_ttl = dns_soa_getminimum(&rdata);
1265 soa_ttl = soaset.ttl;
1266 if (set_maxttl) {
1267 zone_soa_min_ttl = ISC_MIN(zone_soa_min_ttl, maxttl);
1268 soa_ttl = ISC_MIN(soa_ttl, maxttl);
1269 }
1270 dns_rdataset_disassociate(&soaset);
1271 }
1272
1273 /*%
1274 * Increment (or set if nonzero) the SOA serial
1275 */
1276 static isc_result_t
setsoaserial(uint32_t serial,dns_updatemethod_t method)1277 setsoaserial(uint32_t serial, dns_updatemethod_t method) {
1278 isc_result_t result;
1279 dns_dbnode_t *node = NULL;
1280 dns_rdataset_t rdataset;
1281 dns_rdata_t rdata = DNS_RDATA_INIT;
1282 uint32_t old_serial, new_serial;
1283
1284 result = dns_db_getoriginnode(gdb, &node);
1285 if (result != ISC_R_SUCCESS)
1286 return result;
1287
1288 dns_rdataset_init(&rdataset);
1289
1290 result = dns_db_findrdataset(gdb, node, gversion,
1291 dns_rdatatype_soa, 0,
1292 0, &rdataset, NULL);
1293 if (result != ISC_R_SUCCESS)
1294 goto cleanup;
1295
1296 result = dns_rdataset_first(&rdataset);
1297 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1298
1299 dns_rdataset_current(&rdataset, &rdata);
1300
1301 old_serial = dns_soa_getserial(&rdata);
1302
1303 if (method == dns_updatemethod_date ||
1304 method == dns_updatemethod_unixtime) {
1305 new_serial = dns_update_soaserial(old_serial, method);
1306 } else if (serial != 0 || method == dns_updatemethod_none) {
1307 /* Set SOA serial to the value provided. */
1308 new_serial = serial;
1309 } else {
1310 /* Increment SOA serial using RFC 1982 arithmetics */
1311 new_serial = (old_serial + 1) & 0xFFFFFFFF;
1312 if (new_serial == 0)
1313 new_serial = 1;
1314 }
1315
1316 /* If the new serial is not likely to cause a zone transfer
1317 * (a/ixfr) from servers having the old serial, warn the user.
1318 *
1319 * RFC1982 section 7 defines the maximum increment to be
1320 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1321 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1322 */
1323 if (new_serial == old_serial ||
1324 (new_serial - old_serial) > 0x7fffffffU)
1325 fprintf(stderr, "%s: warning: Serial number not advanced, "
1326 "zone may not transfer\n", program);
1327
1328 dns_soa_setserial(new_serial, &rdata);
1329
1330 result = dns_db_deleterdataset(gdb, node, gversion,
1331 dns_rdatatype_soa, 0);
1332 check_result(result, "dns_db_deleterdataset");
1333 if (result != ISC_R_SUCCESS)
1334 goto cleanup;
1335
1336 result = dns_db_addrdataset(gdb, node, gversion,
1337 0, &rdataset, 0, NULL);
1338 check_result(result, "dns_db_addrdataset");
1339 if (result != ISC_R_SUCCESS)
1340 goto cleanup;
1341
1342 cleanup:
1343 dns_rdataset_disassociate(&rdataset);
1344 if (node != NULL)
1345 dns_db_detachnode(gdb, &node);
1346 dns_rdata_reset(&rdata);
1347
1348 return (result);
1349 }
1350
1351 /*%
1352 * Delete any RRSIG records at a node.
1353 */
1354 static void
cleannode(dns_db_t * db,dns_dbversion_t * dbversion,dns_dbnode_t * node)1355 cleannode(dns_db_t *db, dns_dbversion_t *dbversion, dns_dbnode_t *node) {
1356 dns_rdatasetiter_t *rdsiter = NULL;
1357 dns_rdataset_t set;
1358 isc_result_t result, dresult;
1359
1360 if (outputformat != dns_masterformat_text || !disable_zone_check)
1361 return;
1362
1363 dns_rdataset_init(&set);
1364 result = dns_db_allrdatasets(db, node, dbversion, 0, &rdsiter);
1365 check_result(result, "dns_db_allrdatasets");
1366 result = dns_rdatasetiter_first(rdsiter);
1367 while (result == ISC_R_SUCCESS) {
1368 bool destroy = false;
1369 dns_rdatatype_t covers = 0;
1370 dns_rdatasetiter_current(rdsiter, &set);
1371 if (set.type == dns_rdatatype_rrsig) {
1372 covers = set.covers;
1373 destroy = true;
1374 }
1375 dns_rdataset_disassociate(&set);
1376 result = dns_rdatasetiter_next(rdsiter);
1377 if (destroy) {
1378 dresult = dns_db_deleterdataset(db, node, dbversion,
1379 dns_rdatatype_rrsig,
1380 covers);
1381 check_result(dresult, "dns_db_deleterdataset");
1382 }
1383 }
1384 if (result != ISC_R_NOMORE)
1385 fatal("rdataset iteration failed: %s",
1386 isc_result_totext(result));
1387 dns_rdatasetiter_destroy(&rdsiter);
1388 }
1389
1390 /*%
1391 * Set up the iterator and global state before starting the tasks.
1392 */
1393 static void
presign(void)1394 presign(void) {
1395 isc_result_t result;
1396
1397 gdbiter = NULL;
1398 result = dns_db_createiterator(gdb, 0, &gdbiter);
1399 check_result(result, "dns_db_createiterator()");
1400 }
1401
1402 /*%
1403 * Clean up the iterator and global state after the tasks complete.
1404 */
1405 static void
postsign(void)1406 postsign(void) {
1407 dns_dbiterator_destroy(&gdbiter);
1408 }
1409
1410 /*%
1411 * Sign the apex of the zone.
1412 * Note the origin may not be the first node if there are out of zone
1413 * records.
1414 */
1415 static void
signapex(void)1416 signapex(void) {
1417 dns_dbnode_t *node = NULL;
1418 dns_fixedname_t fixed;
1419 dns_name_t *name;
1420 isc_result_t result;
1421
1422 name = dns_fixedname_initname(&fixed);
1423 result = dns_dbiterator_seek(gdbiter, gorigin);
1424 check_result(result, "dns_dbiterator_seek()");
1425 result = dns_dbiterator_current(gdbiter, &node, name);
1426 check_dns_dbiterator_current(result);
1427 signname(node, name);
1428 dumpnode(name, node);
1429 cleannode(gdb, gversion, node);
1430 dns_db_detachnode(gdb, &node);
1431 result = dns_dbiterator_first(gdbiter);
1432 if (result == ISC_R_NOMORE)
1433 finished = true;
1434 else if (result != ISC_R_SUCCESS)
1435 fatal("failure iterating database: %s",
1436 isc_result_totext(result));
1437 }
1438
1439 /*%
1440 * Assigns a node to a worker thread. This is protected by the master task's
1441 * lock.
1442 */
1443 static void
assignwork(isc_task_t * task,isc_task_t * worker)1444 assignwork(isc_task_t *task, isc_task_t *worker) {
1445 dns_fixedname_t *fname;
1446 dns_name_t *name;
1447 dns_dbnode_t *node;
1448 sevent_t *sevent;
1449 dns_rdataset_t nsec;
1450 bool found;
1451 isc_result_t result;
1452 static dns_name_t *zonecut = NULL; /* Protected by namelock. */
1453 static dns_fixedname_t fzonecut; /* Protected by namelock. */
1454 static unsigned int ended = 0; /* Protected by namelock. */
1455
1456 if (shuttingdown)
1457 return;
1458
1459 LOCK(&namelock);
1460 if (finished) {
1461 ended++;
1462 if (ended == ntasks) {
1463 isc_task_detach(&task);
1464 isc_app_shutdown();
1465 }
1466 goto unlock;
1467 }
1468
1469 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1470 if (fname == NULL)
1471 fatal("out of memory");
1472 name = dns_fixedname_initname(fname);
1473 node = NULL;
1474 found = false;
1475 while (!found) {
1476 result = dns_dbiterator_current(gdbiter, &node, name);
1477 check_dns_dbiterator_current(result);
1478 /*
1479 * The origin was handled by signapex().
1480 */
1481 if (dns_name_equal(name, gorigin)) {
1482 dns_db_detachnode(gdb, &node);
1483 goto next;
1484 }
1485 /*
1486 * Sort the zone data from the glue and out-of-zone data.
1487 * For NSEC zones nodes with zone data have NSEC records.
1488 * For NSEC3 zones the NSEC3 nodes are zone data but
1489 * outside of the zone name space. For the rest we need
1490 * to track the bottom of zone cuts.
1491 * Nodes which don't need to be signed are dumped here.
1492 */
1493 dns_rdataset_init(&nsec);
1494 result = dns_db_findrdataset(gdb, node, gversion,
1495 nsec_datatype, 0, 0,
1496 &nsec, NULL);
1497 if (dns_rdataset_isassociated(&nsec))
1498 dns_rdataset_disassociate(&nsec);
1499 if (result == ISC_R_SUCCESS) {
1500 found = true;
1501 } else if (nsec_datatype == dns_rdatatype_nsec3) {
1502 if (dns_name_issubdomain(name, gorigin) &&
1503 (zonecut == NULL ||
1504 !dns_name_issubdomain(name, zonecut))) {
1505 if (is_delegation(gdb, gversion, gorigin,
1506 name, node, NULL))
1507 {
1508 zonecut = savezonecut(&fzonecut, name);
1509 if (!OPTOUT(nsec3flags) ||
1510 secure(name, node))
1511 found = true;
1512 } else if (has_dname(gdb, gversion, node)) {
1513 zonecut = savezonecut(&fzonecut, name);
1514 found = true;
1515 } else {
1516 found = true;
1517 }
1518 }
1519 }
1520
1521 if (!found) {
1522 dumpnode(name, node);
1523 dns_db_detachnode(gdb, &node);
1524 }
1525
1526 next:
1527 result = dns_dbiterator_next(gdbiter);
1528 if (result == ISC_R_NOMORE) {
1529 finished = true;
1530 break;
1531 } else if (result != ISC_R_SUCCESS)
1532 fatal("failure iterating database: %s",
1533 isc_result_totext(result));
1534 }
1535 if (!found) {
1536 ended++;
1537 if (ended == ntasks) {
1538 isc_task_detach(&task);
1539 isc_app_shutdown();
1540 }
1541 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1542 goto unlock;
1543 }
1544 sevent = (sevent_t *)
1545 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1546 sign, NULL, sizeof(sevent_t));
1547 if (sevent == NULL)
1548 fatal("failed to allocate event\n");
1549
1550 sevent->node = node;
1551 sevent->fname = fname;
1552 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1553 unlock:
1554 UNLOCK(&namelock);
1555 }
1556
1557 /*%
1558 * Start a worker task
1559 */
1560 static void
startworker(isc_task_t * task,isc_event_t * event)1561 startworker(isc_task_t *task, isc_event_t *event) {
1562 isc_task_t *worker;
1563
1564 worker = (isc_task_t *)event->ev_arg;
1565 assignwork(task, worker);
1566 isc_event_free(&event);
1567 }
1568
1569 /*%
1570 * Write a node to the output file, and restart the worker task.
1571 */
1572 static void
writenode(isc_task_t * task,isc_event_t * event)1573 writenode(isc_task_t *task, isc_event_t *event) {
1574 isc_task_t *worker;
1575 sevent_t *sevent = (sevent_t *)event;
1576
1577 worker = (isc_task_t *)event->ev_sender;
1578 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1579 cleannode(gdb, gversion, sevent->node);
1580 dns_db_detachnode(gdb, &sevent->node);
1581 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1582 assignwork(task, worker);
1583 isc_event_free(&event);
1584 }
1585
1586 /*%
1587 * Sign a database node.
1588 */
1589 static void
sign(isc_task_t * task,isc_event_t * event)1590 sign(isc_task_t *task, isc_event_t *event) {
1591 dns_fixedname_t *fname;
1592 dns_dbnode_t *node;
1593 sevent_t *sevent, *wevent;
1594
1595 sevent = (sevent_t *)event;
1596 node = sevent->node;
1597 fname = sevent->fname;
1598 isc_event_free(&event);
1599
1600 signname(node, dns_fixedname_name(fname));
1601 wevent = (sevent_t *)
1602 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1603 writenode, NULL, sizeof(sevent_t));
1604 if (wevent == NULL)
1605 fatal("failed to allocate event\n");
1606 wevent->node = node;
1607 wevent->fname = fname;
1608 isc_task_send(master, ISC_EVENT_PTR(&wevent));
1609 }
1610
1611 /*%
1612 * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
1613 */
1614 static void
add_ds(dns_name_t * name,dns_dbnode_t * node,uint32_t nsttl)1615 add_ds(dns_name_t *name, dns_dbnode_t *node, uint32_t nsttl) {
1616 dns_rdataset_t dsset;
1617 dns_rdataset_t sigdsset;
1618 isc_result_t result;
1619
1620 dns_rdataset_init(&dsset);
1621 dns_rdataset_init(&sigdsset);
1622 result = dns_db_findrdataset(gdb, node, gversion,
1623 dns_rdatatype_ds,
1624 0, 0, &dsset, &sigdsset);
1625 if (result == ISC_R_SUCCESS) {
1626 dns_rdataset_disassociate(&dsset);
1627 result = dns_db_deleterdataset(gdb, node, gversion,
1628 dns_rdatatype_ds, 0);
1629 check_result(result, "dns_db_deleterdataset");
1630 }
1631
1632 result = loadds(name, nsttl, &dsset);
1633 if (result == ISC_R_SUCCESS) {
1634 result = dns_db_addrdataset(gdb, node, gversion, 0,
1635 &dsset, 0, NULL);
1636 check_result(result, "dns_db_addrdataset");
1637 dns_rdataset_disassociate(&dsset);
1638 if (dns_rdataset_isassociated(&sigdsset))
1639 dns_rdataset_disassociate(&sigdsset);
1640 } else if (dns_rdataset_isassociated(&sigdsset)) {
1641 result = dns_db_deleterdataset(gdb, node, gversion,
1642 dns_rdatatype_rrsig,
1643 dns_rdatatype_ds);
1644 check_result(result, "dns_db_deleterdataset");
1645 dns_rdataset_disassociate(&sigdsset);
1646 }
1647 }
1648
1649 /*
1650 * Remove records of the given type and their signatures.
1651 */
1652 static void
remove_records(dns_dbnode_t * node,dns_rdatatype_t which,bool checknsec)1653 remove_records(dns_dbnode_t *node, dns_rdatatype_t which,
1654 bool checknsec)
1655 {
1656 isc_result_t result;
1657 dns_rdatatype_t type, covers;
1658 dns_rdatasetiter_t *rdsiter = NULL;
1659 dns_rdataset_t rdataset;
1660
1661 dns_rdataset_init(&rdataset);
1662
1663 /*
1664 * Delete any records of the given type at the apex.
1665 */
1666 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1667 check_result(result, "dns_db_allrdatasets()");
1668 for (result = dns_rdatasetiter_first(rdsiter);
1669 result == ISC_R_SUCCESS;
1670 result = dns_rdatasetiter_next(rdsiter)) {
1671 dns_rdatasetiter_current(rdsiter, &rdataset);
1672 type = rdataset.type;
1673 covers = rdataset.covers;
1674 dns_rdataset_disassociate(&rdataset);
1675 if (type == which || covers == which) {
1676 if (which == dns_rdatatype_nsec &&
1677 checknsec && !update_chain)
1678 fatal("Zone contains NSEC records. Use -u "
1679 "to update to NSEC3.");
1680 if (which == dns_rdatatype_nsec3param &&
1681 checknsec && !update_chain)
1682 fatal("Zone contains NSEC3 chains. Use -u "
1683 "to update to NSEC.");
1684 result = dns_db_deleterdataset(gdb, node, gversion,
1685 type, covers);
1686 check_result(result, "dns_db_deleterdataset()");
1687 continue;
1688 }
1689 }
1690 dns_rdatasetiter_destroy(&rdsiter);
1691 }
1692
1693 /*
1694 * Remove signatures covering the given type. If type == 0,
1695 * then remove all signatures, unless this is a delegation, in
1696 * which case remove all signatures except for DS or nsec_datatype
1697 */
1698 static void
remove_sigs(dns_dbnode_t * node,bool delegation,dns_rdatatype_t which)1699 remove_sigs(dns_dbnode_t *node, bool delegation,
1700 dns_rdatatype_t which)
1701 {
1702 isc_result_t result;
1703 dns_rdatatype_t type, covers;
1704 dns_rdatasetiter_t *rdsiter = NULL;
1705 dns_rdataset_t rdataset;
1706
1707 dns_rdataset_init(&rdataset);
1708 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1709 check_result(result, "dns_db_allrdatasets()");
1710 for (result = dns_rdatasetiter_first(rdsiter);
1711 result == ISC_R_SUCCESS;
1712 result = dns_rdatasetiter_next(rdsiter)) {
1713 dns_rdatasetiter_current(rdsiter, &rdataset);
1714 type = rdataset.type;
1715 covers = rdataset.covers;
1716 dns_rdataset_disassociate(&rdataset);
1717
1718 if (type != dns_rdatatype_rrsig)
1719 continue;
1720
1721 if (which == 0 && delegation &&
1722 (dns_rdatatype_atparent(covers) ||
1723 (nsec_datatype == dns_rdatatype_nsec &&
1724 covers == nsec_datatype)))
1725 continue;
1726
1727 if (which != 0 && covers != which)
1728 continue;
1729
1730 result = dns_db_deleterdataset(gdb, node, gversion,
1731 type, covers);
1732 check_result(result, "dns_db_deleterdataset()");
1733 }
1734 dns_rdatasetiter_destroy(&rdsiter);
1735 }
1736
1737 /*%
1738 * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
1739 */
1740 static void
nsecify(void)1741 nsecify(void) {
1742 dns_dbiterator_t *dbiter = NULL;
1743 dns_dbnode_t *node = NULL, *nextnode = NULL;
1744 dns_fixedname_t fname, fnextname, fzonecut;
1745 dns_name_t *name, *nextname, *zonecut;
1746 dns_rdataset_t rdataset;
1747 dns_rdatasetiter_t *rdsiter = NULL;
1748 dns_rdatatype_t type, covers;
1749 bool done = false;
1750 isc_result_t result;
1751 uint32_t nsttl = 0;
1752
1753 dns_rdataset_init(&rdataset);
1754 name = dns_fixedname_initname(&fname);
1755 nextname = dns_fixedname_initname(&fnextname);
1756 zonecut = NULL;
1757
1758 /*
1759 * Remove any NSEC3 chains.
1760 */
1761 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
1762 check_result(result, "dns_db_createiterator()");
1763 for (result = dns_dbiterator_first(dbiter);
1764 result == ISC_R_SUCCESS;
1765 result = dns_dbiterator_next(dbiter)) {
1766 result = dns_dbiterator_current(dbiter, &node, name);
1767 check_dns_dbiterator_current(result);
1768 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1769 check_result(result, "dns_db_allrdatasets()");
1770 for (result = dns_rdatasetiter_first(rdsiter);
1771 result == ISC_R_SUCCESS;
1772 result = dns_rdatasetiter_next(rdsiter)) {
1773 dns_rdatasetiter_current(rdsiter, &rdataset);
1774 type = rdataset.type;
1775 covers = rdataset.covers;
1776 dns_rdataset_disassociate(&rdataset);
1777 result = dns_db_deleterdataset(gdb, node, gversion,
1778 type, covers);
1779 check_result(result,
1780 "dns_db_deleterdataset(nsec3param/rrsig)");
1781 }
1782 dns_rdatasetiter_destroy(&rdsiter);
1783 dns_db_detachnode(gdb, &node);
1784 }
1785 dns_dbiterator_destroy(&dbiter);
1786
1787 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1788 check_result(result, "dns_db_createiterator()");
1789
1790 result = dns_dbiterator_first(dbiter);
1791 check_result(result, "dns_dbiterator_first()");
1792
1793 while (!done) {
1794 result = dns_dbiterator_current(dbiter, &node, name);
1795 check_dns_dbiterator_current(result);
1796 /*
1797 * Skip out-of-zone records.
1798 */
1799 if (!dns_name_issubdomain(name, gorigin)) {
1800 result = dns_dbiterator_next(dbiter);
1801 if (result == ISC_R_NOMORE)
1802 done = true;
1803 else
1804 check_result(result, "dns_dbiterator_next()");
1805 dns_db_detachnode(gdb, &node);
1806 continue;
1807 }
1808
1809 if (dns_name_equal(name, gorigin)) {
1810 remove_records(node, dns_rdatatype_nsec3param,
1811 true);
1812 /* Clean old rrsigs at apex. */
1813 (void)active_node(node);
1814 }
1815
1816 if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) {
1817 zonecut = savezonecut(&fzonecut, name);
1818 remove_sigs(node, true, 0);
1819 if (generateds)
1820 add_ds(name, node, nsttl);
1821 } else if (has_dname(gdb, gversion, node)) {
1822 zonecut = savezonecut(&fzonecut, name);
1823 }
1824
1825 result = dns_dbiterator_next(dbiter);
1826 nextnode = NULL;
1827 while (result == ISC_R_SUCCESS) {
1828 bool active = false;
1829 result = dns_dbiterator_current(dbiter, &nextnode,
1830 nextname);
1831 check_dns_dbiterator_current(result);
1832 active = active_node(nextnode);
1833 if (!active) {
1834 dns_db_detachnode(gdb, &nextnode);
1835 result = dns_dbiterator_next(dbiter);
1836 continue;
1837 }
1838 if (!dns_name_issubdomain(nextname, gorigin) ||
1839 (zonecut != NULL &&
1840 dns_name_issubdomain(nextname, zonecut)))
1841 {
1842 remove_sigs(nextnode, false, 0);
1843 remove_records(nextnode, dns_rdatatype_nsec,
1844 false);
1845 dns_db_detachnode(gdb, &nextnode);
1846 result = dns_dbiterator_next(dbiter);
1847 continue;
1848 }
1849 dns_db_detachnode(gdb, &nextnode);
1850 break;
1851 }
1852 if (result == ISC_R_NOMORE) {
1853 dns_name_clone(gorigin, nextname);
1854 done = true;
1855 } else if (result != ISC_R_SUCCESS)
1856 fatal("iterating through the database failed: %s",
1857 isc_result_totext(result));
1858 dns_dbiterator_pause(dbiter);
1859 result = dns_nsec_build(gdb, gversion, node, nextname,
1860 zone_soa_min_ttl);
1861 check_result(result, "dns_nsec_build()");
1862 dns_db_detachnode(gdb, &node);
1863 }
1864
1865 dns_dbiterator_destroy(&dbiter);
1866 }
1867
1868 static void
addnsec3param(const unsigned char * salt,size_t salt_len,dns_iterations_t iterations)1869 addnsec3param(const unsigned char *salt, size_t salt_len,
1870 dns_iterations_t iterations)
1871 {
1872 dns_dbnode_t *node = NULL;
1873 dns_rdata_nsec3param_t nsec3param;
1874 unsigned char nsec3parambuf[5 + 255];
1875 dns_rdatalist_t rdatalist;
1876 dns_rdataset_t rdataset;
1877 dns_rdata_t rdata = DNS_RDATA_INIT;
1878 isc_buffer_t b;
1879 isc_result_t result;
1880
1881 dns_rdataset_init(&rdataset);
1882
1883 nsec3param.common.rdclass = gclass;
1884 nsec3param.common.rdtype = dns_rdatatype_nsec3param;
1885 ISC_LINK_INIT(&nsec3param.common, link);
1886 nsec3param.mctx = NULL;
1887 nsec3param.flags = 0;
1888 nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
1889 nsec3param.iterations = iterations;
1890 nsec3param.salt_length = (unsigned char)salt_len;
1891 DE_CONST(salt, nsec3param.salt);
1892
1893 isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
1894 result = dns_rdata_fromstruct(&rdata, gclass,
1895 dns_rdatatype_nsec3param,
1896 &nsec3param, &b);
1897 check_result(result, "dns_rdata_fromstruct()");
1898 dns_rdatalist_init(&rdatalist);
1899 rdatalist.rdclass = rdata.rdclass;
1900 rdatalist.type = rdata.type;
1901 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
1902 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
1903 check_result(result, "dns_rdatalist_tordataset()");
1904
1905 result = dns_db_findnode(gdb, gorigin, true, &node);
1906 check_result(result, "dns_db_findnode(gorigin)");
1907
1908 /*
1909 * Delete any current NSEC3PARAM records.
1910 */
1911 result = dns_db_deleterdataset(gdb, node, gversion,
1912 dns_rdatatype_nsec3param, 0);
1913 if (result == DNS_R_UNCHANGED)
1914 result = ISC_R_SUCCESS;
1915 check_result(result, "dddnsec3param: dns_db_deleterdataset()");
1916
1917 result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
1918 DNS_DBADD_MERGE, NULL);
1919 if (result == DNS_R_UNCHANGED)
1920 result = ISC_R_SUCCESS;
1921 check_result(result, "addnsec3param: dns_db_addrdataset()");
1922 dns_db_detachnode(gdb, &node);
1923 }
1924
1925 static void
addnsec3(dns_name_t * name,dns_dbnode_t * node,const unsigned char * salt,size_t salt_len,unsigned int iterations,hashlist_t * hashlist,dns_ttl_t ttl)1926 addnsec3(dns_name_t *name, dns_dbnode_t *node,
1927 const unsigned char *salt, size_t salt_len,
1928 unsigned int iterations, hashlist_t *hashlist,
1929 dns_ttl_t ttl)
1930 {
1931 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
1932 const unsigned char *nexthash;
1933 unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
1934 dns_fixedname_t hashname;
1935 dns_rdatalist_t rdatalist;
1936 dns_rdataset_t rdataset;
1937 dns_rdata_t rdata = DNS_RDATA_INIT;
1938 isc_result_t result;
1939 dns_dbnode_t *nsec3node = NULL;
1940 char namebuf[DNS_NAME_FORMATSIZE];
1941 size_t hash_len;
1942
1943 dns_name_format(name, namebuf, sizeof(namebuf));
1944
1945 dns_fixedname_init(&hashname);
1946 dns_rdataset_init(&rdataset);
1947
1948 dns_name_downcase(name, name, NULL);
1949 result = dns_nsec3_hashname(&hashname, hash, &hash_len,
1950 name, gorigin, dns_hash_sha1, iterations,
1951 salt, salt_len);
1952 check_result(result, "addnsec3: dns_nsec3_hashname()");
1953 nexthash = hashlist_findnext(hashlist, hash);
1954 result = dns_nsec3_buildrdata(gdb, gversion, node,
1955 unknownalg ?
1956 DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
1957 nsec3flags, iterations,
1958 salt, salt_len,
1959 nexthash, ISC_SHA1_DIGESTLENGTH,
1960 nsec3buffer, &rdata);
1961 check_result(result, "addnsec3: dns_nsec3_buildrdata()");
1962 dns_rdatalist_init(&rdatalist);
1963 rdatalist.rdclass = rdata.rdclass;
1964 rdatalist.type = rdata.type;
1965 rdatalist.ttl = ttl;
1966 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
1967 result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
1968 check_result(result, "dns_rdatalist_tordataset()");
1969 result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
1970 true, &nsec3node);
1971 check_result(result, "addnsec3: dns_db_findnode()");
1972 result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
1973 0, NULL);
1974 if (result == DNS_R_UNCHANGED)
1975 result = ISC_R_SUCCESS;
1976 check_result(result, "addnsec3: dns_db_addrdataset()");
1977 dns_db_detachnode(gdb, &nsec3node);
1978 }
1979
1980 /*%
1981 * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
1982 *
1983 * Extract the hash from the first label of 'name' then see if it
1984 * is in hashlist. If 'name' is not in the hashlist then delete the
1985 * any NSEC3 records which have the same parameters as the chain we
1986 * are building.
1987 *
1988 * XXXMPA Should we also check that it of the form <hash>.<origin>?
1989 */
1990 static void
nsec3clean(dns_name_t * name,dns_dbnode_t * node,unsigned int hashalg,unsigned int iterations,const unsigned char * salt,size_t salt_len,hashlist_t * hashlist)1991 nsec3clean(dns_name_t *name, dns_dbnode_t *node,
1992 unsigned int hashalg, unsigned int iterations,
1993 const unsigned char *salt, size_t salt_len, hashlist_t *hashlist)
1994 {
1995 dns_label_t label;
1996 dns_rdata_nsec3_t nsec3;
1997 dns_rdata_t rdata, delrdata;
1998 dns_rdatalist_t rdatalist;
1999 dns_rdataset_t rdataset, delrdataset;
2000 bool delete_rrsigs = false;
2001 isc_buffer_t target;
2002 isc_result_t result;
2003 unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
2004 bool exists;
2005
2006 /*
2007 * Get the first label.
2008 */
2009 dns_name_getlabel(name, 0, &label);
2010
2011 /*
2012 * We want just the label contents.
2013 */
2014 isc_region_consume(&label, 1);
2015
2016 /*
2017 * Decode base32hex string.
2018 */
2019 isc_buffer_init(&target, hash, sizeof(hash) - 1);
2020 result = isc_base32hex_decoderegion(&label, &target);
2021 if (result != ISC_R_SUCCESS)
2022 return;
2023
2024 hash[isc_buffer_usedlength(&target)] = 0;
2025
2026 exists = hashlist_exists(hashlist, hash);
2027
2028 /*
2029 * Verify that the NSEC3 parameters match the current ones
2030 * otherwise we are dealing with a different NSEC3 chain.
2031 */
2032 dns_rdataset_init(&rdataset);
2033 dns_rdataset_init(&delrdataset);
2034
2035 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
2036 0, 0, &rdataset, NULL);
2037 if (result != ISC_R_SUCCESS)
2038 return;
2039
2040 /*
2041 * Delete any NSEC3 records which are not part of the current
2042 * NSEC3 chain.
2043 */
2044 for (result = dns_rdataset_first(&rdataset);
2045 result == ISC_R_SUCCESS;
2046 result = dns_rdataset_next(&rdataset)) {
2047 dns_rdata_init(&rdata);
2048 dns_rdataset_current(&rdataset, &rdata);
2049 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2050 check_result(result, "dns_rdata_tostruct");
2051 if (exists && nsec3.hash == hashalg &&
2052 nsec3.iterations == iterations &&
2053 nsec3.salt_length == salt_len &&
2054 isc_safe_memequal(nsec3.salt, salt, salt_len))
2055 continue;
2056 dns_rdatalist_init(&rdatalist);
2057 rdatalist.rdclass = rdata.rdclass;
2058 rdatalist.type = rdata.type;
2059 if (set_maxttl)
2060 rdatalist.ttl = ISC_MIN(rdataset.ttl, maxttl);
2061 dns_rdata_init(&delrdata);
2062 dns_rdata_clone(&rdata, &delrdata);
2063 ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
2064 result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
2065 check_result(result, "dns_rdatalist_tordataset()");
2066 result = dns_db_subtractrdataset(gdb, node, gversion,
2067 &delrdataset, 0, NULL);
2068 dns_rdataset_disassociate(&delrdataset);
2069 if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET)
2070 check_result(result, "dns_db_subtractrdataset(NSEC3)");
2071 delete_rrsigs = true;
2072 }
2073 dns_rdataset_disassociate(&rdataset);
2074 if (result != ISC_R_NOMORE)
2075 check_result(result, "dns_rdataset_first/next");
2076
2077 if (!delete_rrsigs)
2078 return;
2079 /*
2080 * Delete the NSEC3 RRSIGs
2081 */
2082 result = dns_db_deleterdataset(gdb, node, gversion,
2083 dns_rdatatype_rrsig,
2084 dns_rdatatype_nsec3);
2085 if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
2086 check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
2087 }
2088
2089 static void
rrset_cleanup(dns_name_t * name,dns_rdataset_t * rdataset,dns_diff_t * add,dns_diff_t * del)2090 rrset_cleanup(dns_name_t *name, dns_rdataset_t *rdataset,
2091 dns_diff_t *add, dns_diff_t *del)
2092 {
2093 isc_result_t result;
2094 unsigned int count1 = 0;
2095 dns_rdataset_t tmprdataset;
2096 char namestr[DNS_NAME_FORMATSIZE];
2097 char typestr[TYPE_FORMATSIZE];
2098
2099 dns_name_format(name, namestr, sizeof(namestr));
2100 type_format(rdataset->type, typestr, sizeof(typestr));
2101
2102 dns_rdataset_init(&tmprdataset);
2103 for (result = dns_rdataset_first(rdataset);
2104 result == ISC_R_SUCCESS;
2105 result = dns_rdataset_next(rdataset)) {
2106 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2107 unsigned int count2 = 0;
2108
2109 count1++;
2110 dns_rdataset_current(rdataset, &rdata1);
2111 dns_rdataset_clone(rdataset, &tmprdataset);
2112 for (result = dns_rdataset_first(&tmprdataset);
2113 result == ISC_R_SUCCESS;
2114 result = dns_rdataset_next(&tmprdataset)) {
2115 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2116 dns_difftuple_t *tuple = NULL;
2117 count2++;
2118 dns_rdataset_current(&tmprdataset, &rdata2);
2119 if (count1 < count2 &&
2120 dns_rdata_casecompare(&rdata1, &rdata2) == 0)
2121 {
2122 vbprintf(2, "removing duplicate at %s/%s\n",
2123 namestr, typestr);
2124 result = dns_difftuple_create(mctx,
2125 DNS_DIFFOP_DELRESIGN,
2126 name, rdataset->ttl,
2127 &rdata2, &tuple);
2128 check_result(result, "dns_difftuple_create");
2129 dns_diff_append(del, &tuple);
2130 } else if (set_maxttl && rdataset->ttl > maxttl) {
2131 vbprintf(2, "reducing ttl of %s/%s "
2132 "from %d to %d\n",
2133 namestr, typestr,
2134 rdataset->ttl, maxttl);
2135 result = dns_difftuple_create(mctx,
2136 DNS_DIFFOP_DELRESIGN,
2137 name, rdataset->ttl,
2138 &rdata2, &tuple);
2139 check_result(result, "dns_difftuple_create");
2140 dns_diff_append(del, &tuple);
2141 tuple = NULL;
2142 result = dns_difftuple_create(mctx,
2143 DNS_DIFFOP_ADDRESIGN,
2144 name, maxttl,
2145 &rdata2, &tuple);
2146 check_result(result, "dns_difftuple_create");
2147 dns_diff_append(add, &tuple);
2148 }
2149 }
2150 dns_rdataset_disassociate(&tmprdataset);
2151 }
2152 }
2153
2154 static void
cleanup_zone(void)2155 cleanup_zone(void) {
2156 isc_result_t result;
2157 dns_dbiterator_t *dbiter = NULL;
2158 dns_rdatasetiter_t *rdsiter = NULL;
2159 dns_diff_t add, del;
2160 dns_dbnode_t *node = NULL;
2161 dns_rdataset_t rdataset;
2162 dns_fixedname_t fname;
2163 dns_name_t *name;
2164
2165 dns_diff_init(mctx, &add);
2166 dns_diff_init(mctx, &del);
2167 name = dns_fixedname_initname(&fname);
2168 dns_rdataset_init(&rdataset);
2169
2170 result = dns_db_createiterator(gdb, 0, &dbiter);
2171 check_result(result, "dns_db_createiterator()");
2172
2173 for (result = dns_dbiterator_first(dbiter);
2174 result == ISC_R_SUCCESS;
2175 result = dns_dbiterator_next(dbiter)) {
2176
2177 result = dns_dbiterator_current(dbiter, &node, name);
2178 check_dns_dbiterator_current(result);
2179 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2180 check_result(result, "dns_db_allrdatasets()");
2181 for (result = dns_rdatasetiter_first(rdsiter);
2182 result == ISC_R_SUCCESS;
2183 result = dns_rdatasetiter_next(rdsiter)) {
2184 dns_rdatasetiter_current(rdsiter, &rdataset);
2185 rrset_cleanup(name, &rdataset, &add, &del);
2186 dns_rdataset_disassociate(&rdataset);
2187 }
2188 if (result != ISC_R_NOMORE)
2189 fatal("rdatasets iteration failed.");
2190 dns_rdatasetiter_destroy(&rdsiter);
2191 dns_db_detachnode(gdb, &node);
2192 }
2193 if (result != ISC_R_NOMORE)
2194 fatal("zone iteration failed.");
2195
2196 result = dns_diff_applysilently(&del, gdb, gversion);
2197 check_result(result, "dns_diff_applysilently");
2198
2199 result = dns_diff_applysilently(&add, gdb, gversion);
2200 check_result(result, "dns_diff_applysilently");
2201
2202 dns_diff_clear(&del);
2203 dns_diff_clear(&add);
2204 dns_dbiterator_destroy(&dbiter);
2205 }
2206
2207 /*
2208 * Generate NSEC3 records for the zone.
2209 */
2210 static void
nsec3ify(unsigned int hashalg,dns_iterations_t iterations,const unsigned char * salt,size_t salt_len,hashlist_t * hashlist)2211 nsec3ify(unsigned int hashalg, dns_iterations_t iterations,
2212 const unsigned char *salt, size_t salt_len, hashlist_t *hashlist)
2213 {
2214 dns_dbiterator_t *dbiter = NULL;
2215 dns_dbnode_t *node = NULL, *nextnode = NULL;
2216 dns_fixedname_t fname, fnextname, fzonecut;
2217 dns_name_t *name, *nextname, *zonecut;
2218 dns_rdataset_t rdataset;
2219 int order;
2220 bool active;
2221 bool done = false;
2222 isc_result_t result;
2223 uint32_t nsttl = 0;
2224 unsigned int count, nlabels;
2225
2226 dns_rdataset_init(&rdataset);
2227 name = dns_fixedname_initname(&fname);
2228 nextname = dns_fixedname_initname(&fnextname);
2229 zonecut = NULL;
2230
2231 /*
2232 * Walk the zone generating the hash names.
2233 */
2234 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2235 check_result(result, "dns_db_createiterator()");
2236
2237 result = dns_dbiterator_first(dbiter);
2238 check_result(result, "dns_dbiterator_first()");
2239
2240 while (!done) {
2241 result = dns_dbiterator_current(dbiter, &node, name);
2242 check_dns_dbiterator_current(result);
2243 /*
2244 * Skip out-of-zone records.
2245 */
2246 if (!dns_name_issubdomain(name, gorigin)) {
2247 result = dns_dbiterator_next(dbiter);
2248 if (result == ISC_R_NOMORE)
2249 done = true;
2250 else
2251 check_result(result, "dns_dbiterator_next()");
2252 dns_db_detachnode(gdb, &node);
2253 continue;
2254 }
2255
2256 if (dns_name_equal(name, gorigin)) {
2257 remove_records(node, dns_rdatatype_nsec, true);
2258 /* Clean old rrsigs at apex. */
2259 (void)active_node(node);
2260 }
2261
2262 if (has_dname(gdb, gversion, node)) {
2263 zonecut = savezonecut(&fzonecut, name);
2264 }
2265
2266 result = dns_dbiterator_next(dbiter);
2267 nextnode = NULL;
2268 while (result == ISC_R_SUCCESS) {
2269 result = dns_dbiterator_current(dbiter, &nextnode,
2270 nextname);
2271 check_dns_dbiterator_current(result);
2272 active = active_node(nextnode);
2273 if (!active) {
2274 dns_db_detachnode(gdb, &nextnode);
2275 result = dns_dbiterator_next(dbiter);
2276 continue;
2277 }
2278 if (!dns_name_issubdomain(nextname, gorigin) ||
2279 (zonecut != NULL &&
2280 dns_name_issubdomain(nextname, zonecut))) {
2281 remove_sigs(nextnode, false, 0);
2282 dns_db_detachnode(gdb, &nextnode);
2283 result = dns_dbiterator_next(dbiter);
2284 continue;
2285 }
2286 if (is_delegation(gdb, gversion, gorigin,
2287 nextname, nextnode, &nsttl))
2288 {
2289 zonecut = savezonecut(&fzonecut, nextname);
2290 remove_sigs(nextnode, true, 0);
2291 if (generateds)
2292 add_ds(nextname, nextnode, nsttl);
2293 if (OPTOUT(nsec3flags) &&
2294 !secure(nextname, nextnode)) {
2295 dns_db_detachnode(gdb, &nextnode);
2296 result = dns_dbiterator_next(dbiter);
2297 continue;
2298 }
2299 } else if (has_dname(gdb, gversion, nextnode)) {
2300 zonecut = savezonecut(&fzonecut, nextname);
2301 }
2302 dns_db_detachnode(gdb, &nextnode);
2303 break;
2304 }
2305 if (result == ISC_R_NOMORE) {
2306 dns_name_copy(gorigin, nextname, NULL);
2307 done = true;
2308 } else if (result != ISC_R_SUCCESS)
2309 fatal("iterating through the database failed: %s",
2310 isc_result_totext(result));
2311 dns_name_downcase(name, name, NULL);
2312 hashlist_add_dns_name(hashlist, name, hashalg, iterations,
2313 salt, salt_len, false);
2314 dns_db_detachnode(gdb, &node);
2315 /*
2316 * Add hashes for empty nodes. Use closest encloser logic.
2317 * The closest encloser either has data or is a empty
2318 * node for another <name,nextname> span so we don't add
2319 * it here. Empty labels on nextname are within the span.
2320 */
2321 dns_name_downcase(nextname, nextname, NULL);
2322 dns_name_fullcompare(name, nextname, &order, &nlabels);
2323 addnowildcardhash(hashlist, name, hashalg, iterations,
2324 salt, salt_len);
2325 count = dns_name_countlabels(nextname);
2326 while (count > nlabels + 1) {
2327 count--;
2328 dns_name_split(nextname, count, NULL, nextname);
2329 hashlist_add_dns_name(hashlist, nextname, hashalg,
2330 iterations, salt, salt_len,
2331 false);
2332 addnowildcardhash(hashlist, nextname, hashalg,
2333 iterations, salt, salt_len);
2334 }
2335 }
2336 dns_dbiterator_destroy(&dbiter);
2337
2338 /*
2339 * We have all the hashes now so we can sort them.
2340 */
2341 hashlist_sort(hashlist);
2342
2343 /*
2344 * Check for duplicate hashes. If found the salt needs to
2345 * be changed.
2346 */
2347 if (hashlist_hasdup(hashlist))
2348 fatal("Duplicate hash detected. Pick a different salt.");
2349
2350 /*
2351 * Generate the nsec3 records.
2352 */
2353 zonecut = NULL;
2354 done = false;
2355
2356 addnsec3param(salt, salt_len, iterations);
2357
2358 /*
2359 * Clean out NSEC3 records which don't match this chain.
2360 */
2361 result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2362 check_result(result, "dns_db_createiterator()");
2363
2364 for (result = dns_dbiterator_first(dbiter);
2365 result == ISC_R_SUCCESS;
2366 result = dns_dbiterator_next(dbiter)) {
2367 result = dns_dbiterator_current(dbiter, &node, name);
2368 check_dns_dbiterator_current(result);
2369 nsec3clean(name, node, hashalg, iterations, salt, salt_len,
2370 hashlist);
2371 dns_db_detachnode(gdb, &node);
2372 }
2373 dns_dbiterator_destroy(&dbiter);
2374
2375 /*
2376 * Generate / complete the new chain.
2377 */
2378 result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2379 check_result(result, "dns_db_createiterator()");
2380
2381 result = dns_dbiterator_first(dbiter);
2382 check_result(result, "dns_dbiterator_first()");
2383
2384 while (!done) {
2385 result = dns_dbiterator_current(dbiter, &node, name);
2386 check_dns_dbiterator_current(result);
2387 /*
2388 * Skip out-of-zone records.
2389 */
2390 if (!dns_name_issubdomain(name, gorigin)) {
2391 result = dns_dbiterator_next(dbiter);
2392 if (result == ISC_R_NOMORE)
2393 done = true;
2394 else
2395 check_result(result, "dns_dbiterator_next()");
2396 dns_db_detachnode(gdb, &node);
2397 continue;
2398 }
2399
2400 if (has_dname(gdb, gversion, node)) {
2401 zonecut = savezonecut(&fzonecut, name);
2402 }
2403
2404 result = dns_dbiterator_next(dbiter);
2405 nextnode = NULL;
2406 while (result == ISC_R_SUCCESS) {
2407 result = dns_dbiterator_current(dbiter, &nextnode,
2408 nextname);
2409 check_dns_dbiterator_current(result);
2410 active = active_node(nextnode);
2411 if (!active) {
2412 dns_db_detachnode(gdb, &nextnode);
2413 result = dns_dbiterator_next(dbiter);
2414 continue;
2415 }
2416 if (!dns_name_issubdomain(nextname, gorigin) ||
2417 (zonecut != NULL &&
2418 dns_name_issubdomain(nextname, zonecut))) {
2419 dns_db_detachnode(gdb, &nextnode);
2420 result = dns_dbiterator_next(dbiter);
2421 continue;
2422 }
2423 if (is_delegation(gdb, gversion, gorigin,
2424 nextname, nextnode, NULL))
2425 {
2426 zonecut = savezonecut(&fzonecut, nextname);
2427 if (OPTOUT(nsec3flags) &&
2428 !secure(nextname, nextnode)) {
2429 dns_db_detachnode(gdb, &nextnode);
2430 result = dns_dbiterator_next(dbiter);
2431 continue;
2432 }
2433 } else if (has_dname(gdb, gversion, nextnode)) {
2434 zonecut = savezonecut(&fzonecut, nextname);
2435 }
2436 dns_db_detachnode(gdb, &nextnode);
2437 break;
2438 }
2439 if (result == ISC_R_NOMORE) {
2440 dns_name_copy(gorigin, nextname, NULL);
2441 done = true;
2442 } else if (result != ISC_R_SUCCESS)
2443 fatal("iterating through the database failed: %s",
2444 isc_result_totext(result));
2445 /*
2446 * We need to pause here to release the lock on the database.
2447 */
2448 dns_dbiterator_pause(dbiter);
2449 addnsec3(name, node, salt, salt_len, iterations,
2450 hashlist, zone_soa_min_ttl);
2451 dns_db_detachnode(gdb, &node);
2452 /*
2453 * Add NSEC3's for empty nodes. Use closest encloser logic.
2454 */
2455 dns_name_fullcompare(name, nextname, &order, &nlabels);
2456 count = dns_name_countlabels(nextname);
2457 while (count > nlabels + 1) {
2458 count--;
2459 dns_name_split(nextname, count, NULL, nextname);
2460 addnsec3(nextname, NULL, salt, salt_len,
2461 iterations, hashlist, zone_soa_min_ttl);
2462 }
2463 }
2464 dns_dbiterator_destroy(&dbiter);
2465 }
2466
2467 /*%
2468 * Load the zone file from disk
2469 */
2470 static void
loadzone(char * file,char * origin,dns_rdataclass_t rdclass,dns_db_t ** db)2471 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
2472 isc_buffer_t b;
2473 int len;
2474 dns_fixedname_t fname;
2475 dns_name_t *name;
2476 isc_result_t result;
2477
2478 len = strlen(origin);
2479 isc_buffer_init(&b, origin, len);
2480 isc_buffer_add(&b, len);
2481
2482 name = dns_fixedname_initname(&fname);
2483 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
2484 if (result != ISC_R_SUCCESS)
2485 fatal("failed converting name '%s' to dns format: %s",
2486 origin, isc_result_totext(result));
2487
2488 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
2489 rdclass, 0, NULL, db);
2490 check_result(result, "dns_db_create()");
2491
2492 result = dns_db_load2(*db, file, inputformat);
2493 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
2494 fatal("failed loading zone from '%s': %s",
2495 file, isc_result_totext(result));
2496 }
2497
2498 /*%
2499 * Finds all public zone keys in the zone, and attempts to load the
2500 * private keys from disk.
2501 */
2502 static void
loadzonekeys(bool preserve_keys,bool load_public)2503 loadzonekeys(bool preserve_keys, bool load_public) {
2504 dns_dbnode_t *node;
2505 dns_dbversion_t *currentversion = NULL;
2506 isc_result_t result;
2507 dns_rdataset_t rdataset, keysigs, soasigs;
2508
2509 node = NULL;
2510 result = dns_db_findnode(gdb, gorigin, false, &node);
2511 if (result != ISC_R_SUCCESS)
2512 fatal("failed to find the zone's origin: %s",
2513 isc_result_totext(result));
2514
2515 dns_db_currentversion(gdb, ¤tversion);
2516
2517 dns_rdataset_init(&rdataset);
2518 dns_rdataset_init(&soasigs);
2519 dns_rdataset_init(&keysigs);
2520
2521 /* Make note of the keys which signed the SOA, if any */
2522 result = dns_db_findrdataset(gdb, node, currentversion,
2523 dns_rdatatype_soa, 0, 0,
2524 &rdataset, &soasigs);
2525 if (result != ISC_R_SUCCESS)
2526 goto cleanup;
2527
2528 /* Preserve the TTL of the DNSKEY RRset, if any */
2529 dns_rdataset_disassociate(&rdataset);
2530 result = dns_db_findrdataset(gdb, node, currentversion,
2531 dns_rdatatype_dnskey, 0, 0,
2532 &rdataset, &keysigs);
2533
2534 if (result != ISC_R_SUCCESS)
2535 goto cleanup;
2536
2537 if (set_keyttl && keyttl != rdataset.ttl) {
2538 fprintf(stderr, "User-specified TTL %u conflicts "
2539 "with existing DNSKEY RRset TTL.\n",
2540 keyttl);
2541 fprintf(stderr, "Imported keys will use the RRSet "
2542 "TTL %u instead.\n",
2543 rdataset.ttl);
2544 }
2545 keyttl = rdataset.ttl;
2546
2547 /* Load keys corresponding to the existing DNSKEY RRset. */
2548 result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx,
2549 &rdataset, &keysigs, &soasigs,
2550 preserve_keys, load_public,
2551 &keylist);
2552 if (result != ISC_R_SUCCESS)
2553 fatal("failed to load the zone keys: %s",
2554 isc_result_totext(result));
2555
2556 cleanup:
2557 if (dns_rdataset_isassociated(&rdataset))
2558 dns_rdataset_disassociate(&rdataset);
2559 if (dns_rdataset_isassociated(&keysigs))
2560 dns_rdataset_disassociate(&keysigs);
2561 if (dns_rdataset_isassociated(&soasigs))
2562 dns_rdataset_disassociate(&soasigs);
2563 dns_db_detachnode(gdb, &node);
2564 dns_db_closeversion(gdb, ¤tversion, false);
2565 }
2566
2567 static void
loadexplicitkeys(char * keyfiles[],int n,bool setksk)2568 loadexplicitkeys(char *keyfiles[], int n, bool setksk) {
2569 isc_result_t result;
2570 int i;
2571
2572 for (i = 0; i < n; i++) {
2573 dns_dnsseckey_t *key = NULL;
2574 dst_key_t *newkey = NULL;
2575
2576 result = dst_key_fromnamedfile(keyfiles[i], directory,
2577 DST_TYPE_PUBLIC |
2578 DST_TYPE_PRIVATE,
2579 mctx, &newkey);
2580 if (result != ISC_R_SUCCESS)
2581 fatal("cannot load dnskey %s: %s", keyfiles[i],
2582 isc_result_totext(result));
2583
2584 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
2585 fatal("key %s not at origin\n", keyfiles[i]);
2586
2587 if (!dst_key_isprivate(newkey))
2588 fatal("cannot sign zone with non-private dnskey %s",
2589 keyfiles[i]);
2590
2591 /* Skip any duplicates */
2592 for (key = ISC_LIST_HEAD(keylist);
2593 key != NULL;
2594 key = ISC_LIST_NEXT(key, link)) {
2595 if (dst_key_id(key->key) == dst_key_id(newkey) &&
2596 dst_key_alg(key->key) == dst_key_alg(newkey))
2597 break;
2598 }
2599
2600 if (key == NULL) {
2601 /* We haven't seen this key before */
2602 dns_dnsseckey_create(mctx, &newkey, &key);
2603 ISC_LIST_APPEND(keylist, key, link);
2604 key->source = dns_keysource_user;
2605 } else {
2606 dst_key_free(&key->key);
2607 key->key = newkey;
2608 }
2609
2610 key->force_publish = true;
2611 key->force_sign = true;
2612
2613 if (setksk)
2614 key->ksk = true;
2615 }
2616 }
2617
2618 static void
report(const char * format,...)2619 report(const char *format, ...) {
2620 va_list args;
2621 va_start(args, format);
2622 vfprintf(stderr, format, args);
2623 va_end(args);
2624 putc('\n', stderr);
2625 }
2626
2627 static void
build_final_keylist(void)2628 build_final_keylist(void) {
2629 isc_result_t result;
2630 dns_dbversion_t *ver = NULL;
2631 dns_diff_t diff;
2632 dns_dnsseckeylist_t matchkeys;
2633 char name[DNS_NAME_FORMATSIZE];
2634
2635 /*
2636 * Find keys that match this zone in the key repository.
2637 */
2638 ISC_LIST_INIT(matchkeys);
2639 result = dns_dnssec_findmatchingkeys(gorigin, directory,
2640 mctx, &matchkeys);
2641 if (result == ISC_R_NOTFOUND)
2642 result = ISC_R_SUCCESS;
2643 check_result(result, "dns_dnssec_findmatchingkeys");
2644
2645 result = dns_db_newversion(gdb, &ver);
2646 check_result(result, "dns_db_newversion");
2647
2648 dns_diff_init(mctx, &diff);
2649
2650 /*
2651 * Update keylist with information from from the key repository.
2652 */
2653 dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
2654 &diff, ignore_kskflag, mctx, report);
2655
2656 dns_name_format(gorigin, name, sizeof(name));
2657
2658 result = dns_diff_applysilently(&diff, gdb, ver);
2659 if (result != ISC_R_SUCCESS)
2660 fatal("failed to update DNSKEY RRset at node '%s': %s",
2661 name, isc_result_totext(result));
2662
2663 dns_db_closeversion(gdb, &ver, true);
2664
2665 dns_diff_clear(&diff);
2666 }
2667
2668 static void
warnifallksk(dns_db_t * db)2669 warnifallksk(dns_db_t *db) {
2670 dns_dbversion_t *currentversion = NULL;
2671 dns_dbnode_t *node = NULL;
2672 dns_rdataset_t rdataset;
2673 dns_rdata_t rdata = DNS_RDATA_INIT;
2674 isc_result_t result;
2675 dns_rdata_dnskey_t dnskey;
2676 bool have_non_ksk = false;
2677
2678 dns_db_currentversion(db, ¤tversion);
2679
2680 result = dns_db_findnode(db, gorigin, false, &node);
2681 if (result != ISC_R_SUCCESS)
2682 fatal("failed to find the zone's origin: %s",
2683 isc_result_totext(result));
2684
2685 dns_rdataset_init(&rdataset);
2686 result = dns_db_findrdataset(db, node, currentversion,
2687 dns_rdatatype_dnskey, 0, 0, &rdataset,
2688 NULL);
2689 if (result != ISC_R_SUCCESS)
2690 fatal("failed to find keys at the zone apex: %s",
2691 isc_result_totext(result));
2692 result = dns_rdataset_first(&rdataset);
2693 check_result(result, "dns_rdataset_first");
2694 while (result == ISC_R_SUCCESS) {
2695 dns_rdata_reset(&rdata);
2696 dns_rdataset_current(&rdataset, &rdata);
2697 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2698 check_result(result, "dns_rdata_tostruct");
2699 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
2700 have_non_ksk = true;
2701 result = ISC_R_NOMORE;
2702 } else
2703 result = dns_rdataset_next(&rdataset);
2704 dns_rdata_freestruct(&dnskey);
2705 }
2706 dns_rdataset_disassociate(&rdataset);
2707 dns_db_detachnode(db, &node);
2708 dns_db_closeversion(db, ¤tversion, false);
2709 if (!have_non_ksk && !ignore_kskflag) {
2710 if (disable_zone_check)
2711 fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
2712 "supply a ZSK or use '-z'.\n",
2713 program);
2714 else
2715 fatal("No non-KSK DNSKEY found; "
2716 "supply a ZSK or use '-z'.");
2717 }
2718 }
2719
2720 static void
set_nsec3params(bool update,bool set_salt,bool set_optout,bool set_iter)2721 set_nsec3params(bool update, bool set_salt,
2722 bool set_optout, bool set_iter)
2723 {
2724 isc_result_t result;
2725 dns_dbversion_t *ver = NULL;
2726 dns_dbnode_t *node = NULL;
2727 dns_rdataset_t rdataset;
2728 dns_rdata_t rdata = DNS_RDATA_INIT;
2729 dns_rdata_nsec3_t nsec3;
2730 dns_fixedname_t fname;
2731 dns_name_t *hashname;
2732 unsigned char orig_salt[255];
2733 size_t orig_saltlen;
2734 dns_hash_t orig_hash;
2735 uint16_t orig_iter;
2736
2737 dns_db_currentversion(gdb, &ver);
2738 dns_rdataset_init(&rdataset);
2739
2740 orig_saltlen = sizeof(orig_salt);
2741 result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
2742 &orig_iter, orig_salt,
2743 &orig_saltlen);
2744 if (result != ISC_R_SUCCESS)
2745 goto cleanup;
2746
2747 nsec_datatype = dns_rdatatype_nsec3;
2748
2749 if (!update && set_salt) {
2750 if (salt_length != orig_saltlen ||
2751 !isc_safe_memequal(saltbuf, orig_salt, salt_length))
2752 fatal("An NSEC3 chain exists with a different salt. "
2753 "Use -u to update it.");
2754 } else if (!set_salt) {
2755 salt_length = orig_saltlen;
2756 memmove(saltbuf, orig_salt, orig_saltlen);
2757 gsalt = saltbuf;
2758 }
2759
2760 if (!update && set_iter) {
2761 if (nsec3iter != orig_iter)
2762 fatal("An NSEC3 chain exists with different "
2763 "iterations. Use -u to update it.");
2764 } else if (!set_iter)
2765 nsec3iter = orig_iter;
2766
2767 /*
2768 * Find an NSEC3 record to get the current OPTOUT value.
2769 * (This assumes all NSEC3 records agree.)
2770 */
2771
2772 hashname = dns_fixedname_initname(&fname);
2773 result = dns_nsec3_hashname(&fname, NULL, NULL,
2774 gorigin, gorigin, dns_hash_sha1,
2775 orig_iter, orig_salt, orig_saltlen);
2776 check_result(result, "dns_nsec3_hashname");
2777
2778 result = dns_db_findnsec3node(gdb, hashname, false, &node);
2779 if (result != ISC_R_SUCCESS)
2780 goto cleanup;
2781
2782 result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3,
2783 0, 0, &rdataset, NULL);
2784 if (result != ISC_R_SUCCESS)
2785 goto cleanup;
2786
2787 result = dns_rdataset_first(&rdataset);
2788 check_result(result, "dns_rdataset_first");
2789 dns_rdataset_current(&rdataset, &rdata);
2790 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2791 check_result(result, "dns_rdata_tostruct");
2792
2793 if (!update && set_optout) {
2794 if (nsec3flags != nsec3.flags)
2795 fatal("An NSEC3 chain exists with%s OPTOUT. "
2796 "Use -u -%s to %s it.",
2797 OPTOUT(nsec3.flags) ? "" : "out",
2798 OPTOUT(nsec3.flags) ? "AA" : "A",
2799 OPTOUT(nsec3.flags) ? "clear" : "set");
2800 } else if (!set_optout)
2801 nsec3flags = nsec3.flags;
2802
2803 dns_rdata_freestruct(&nsec3);
2804
2805 cleanup:
2806 if (dns_rdataset_isassociated(&rdataset))
2807 dns_rdataset_disassociate(&rdataset);
2808 if (node != NULL)
2809 dns_db_detachnode(gdb, &node);
2810 dns_db_closeversion(gdb, &ver, false);
2811 }
2812
2813 static void
writeset(const char * prefix,dns_rdatatype_t type)2814 writeset(const char *prefix, dns_rdatatype_t type) {
2815 char *filename;
2816 char namestr[DNS_NAME_FORMATSIZE];
2817 dns_db_t *db = NULL;
2818 dns_dbversion_t *dbversion = NULL;
2819 dns_diff_t diff;
2820 dns_difftuple_t *tuple = NULL;
2821 dns_fixedname_t fixed;
2822 dns_name_t *name;
2823 dns_rdata_t rdata, ds;
2824 bool have_ksk = false;
2825 bool have_non_ksk = false;
2826 isc_buffer_t b;
2827 isc_buffer_t namebuf;
2828 isc_region_t r;
2829 isc_result_t result;
2830 dns_dnsseckey_t *key, *tmpkey;
2831 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
2832 unsigned char keybuf[DST_KEY_MAXSIZE];
2833 unsigned int filenamelen;
2834 const dns_master_style_t *style =
2835 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
2836
2837 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
2838 result = dns_name_tofilenametext(gorigin, false, &namebuf);
2839 check_result(result, "dns_name_tofilenametext");
2840 isc_buffer_putuint8(&namebuf, 0);
2841 filenamelen = strlen(prefix) + strlen(namestr) + 1;
2842 if (dsdir != NULL)
2843 filenamelen += strlen(dsdir) + 1;
2844 filename = isc_mem_get(mctx, filenamelen);
2845 if (filename == NULL)
2846 fatal("out of memory");
2847 if (dsdir != NULL)
2848 snprintf(filename, filenamelen, "%s/", dsdir);
2849 else
2850 filename[0] = 0;
2851 strlcat(filename, prefix, filenamelen);
2852 strlcat(filename, namestr, filenamelen);
2853
2854 dns_diff_init(mctx, &diff);
2855
2856 if (type == dns_rdatatype_dlv) {
2857 dns_name_t tname;
2858 unsigned int labels;
2859
2860 dns_name_init(&tname, NULL);
2861 name = dns_fixedname_initname(&fixed);
2862 labels = dns_name_countlabels(gorigin);
2863 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
2864 result = dns_name_concatenate(&tname, dlv, name, NULL);
2865 check_result(result, "dns_name_concatenate");
2866 } else
2867 name = gorigin;
2868
2869 for (key = ISC_LIST_HEAD(keylist);
2870 key != NULL;
2871 key = ISC_LIST_NEXT(key, link))
2872 {
2873 if (REVOKE(key->key))
2874 continue;
2875 if (isksk(key)) {
2876 have_ksk = true;
2877 have_non_ksk = false;
2878 } else {
2879 have_ksk = false;
2880 have_non_ksk = true;
2881 }
2882 for (tmpkey = ISC_LIST_HEAD(keylist);
2883 tmpkey != NULL;
2884 tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
2885 if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
2886 continue;
2887 if (REVOKE(tmpkey->key))
2888 continue;
2889 if (isksk(tmpkey))
2890 have_ksk = true;
2891 else
2892 have_non_ksk = true;
2893 }
2894 if (have_ksk && have_non_ksk && !isksk(key))
2895 continue;
2896 dns_rdata_init(&rdata);
2897 dns_rdata_init(&ds);
2898 isc_buffer_init(&b, keybuf, sizeof(keybuf));
2899 result = dst_key_todns(key->key, &b);
2900 check_result(result, "dst_key_todns");
2901 isc_buffer_usedregion(&b, &r);
2902 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
2903 if (type != dns_rdatatype_dnskey) {
2904 result = dns_ds_buildrdata(gorigin, &rdata,
2905 DNS_DSDIGEST_SHA1,
2906 dsbuf, &ds);
2907 check_result(result, "dns_ds_buildrdata");
2908 if (type == dns_rdatatype_dlv)
2909 ds.type = dns_rdatatype_dlv;
2910 result = dns_difftuple_create(mctx,
2911 DNS_DIFFOP_ADDRESIGN,
2912 name, 0, &ds, &tuple);
2913 check_result(result, "dns_difftuple_create");
2914 dns_diff_append(&diff, &tuple);
2915
2916 dns_rdata_reset(&ds);
2917 result = dns_ds_buildrdata(gorigin, &rdata,
2918 DNS_DSDIGEST_SHA256,
2919 dsbuf, &ds);
2920 check_result(result, "dns_ds_buildrdata");
2921 if (type == dns_rdatatype_dlv)
2922 ds.type = dns_rdatatype_dlv;
2923 result = dns_difftuple_create(mctx,
2924 DNS_DIFFOP_ADDRESIGN,
2925 name, 0, &ds, &tuple);
2926
2927 } else
2928 result = dns_difftuple_create(mctx,
2929 DNS_DIFFOP_ADDRESIGN,
2930 gorigin, zone_soa_min_ttl,
2931 &rdata, &tuple);
2932 check_result(result, "dns_difftuple_create");
2933 dns_diff_append(&diff, &tuple);
2934 }
2935
2936 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
2937 gclass, 0, NULL, &db);
2938 check_result(result, "dns_db_create");
2939
2940 result = dns_db_newversion(db, &dbversion);
2941 check_result(result, "dns_db_newversion");
2942
2943 result = dns_diff_apply(&diff, db, dbversion);
2944 check_result(result, "dns_diff_apply");
2945 dns_diff_clear(&diff);
2946
2947 result = dns_master_dump(mctx, db, dbversion, style, filename);
2948 check_result(result, "dns_master_dump");
2949
2950 isc_mem_put(mctx, filename, filenamelen);
2951
2952 dns_db_closeversion(db, &dbversion, false);
2953 dns_db_detach(&db);
2954 }
2955
2956 static void
print_time(FILE * fp)2957 print_time(FILE *fp) {
2958 time_t currenttime = time(NULL);
2959 struct tm t, *tm = localtime_r(¤ttime, &t);
2960 unsigned int flen;
2961 char timebuf[80];
2962
2963 if (tm == NULL || outputformat != dns_masterformat_text) {
2964 return;
2965 }
2966
2967 flen = strftime(timebuf, sizeof(timebuf), "%a %b %e %H:%M:%S %Y", tm);
2968 INSIST(flen > 0U && flen < sizeof(timebuf));
2969 fprintf(fp, "; File written on %s\n", timebuf);
2970 }
2971
2972 static void
print_version(FILE * fp)2973 print_version(FILE *fp) {
2974 if (outputformat != dns_masterformat_text)
2975 return;
2976
2977 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
2978 }
2979
2980 ISC_PLATFORM_NORETURN_PRE static void
2981 usage(void) ISC_PLATFORM_NORETURN_POST;
2982
2983 static void
usage(void)2984 usage(void) {
2985 fprintf(stderr, "Usage:\n");
2986 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
2987
2988 fprintf(stderr, "\n");
2989
2990 fprintf(stderr, "Version: %s\n", VERSION);
2991
2992 fprintf(stderr, "Options: (default value in parenthesis) \n");
2993 fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
2994 "\t\tfor the zone and determines how they are to "
2995 "be used\n");
2996 fprintf(stderr, "\t-K directory:\n");
2997 fprintf(stderr, "\t\tdirectory to find key files (.)\n");
2998 fprintf(stderr, "\t-d directory:\n");
2999 fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
3000 fprintf(stderr, "\t-g:\t");
3001 fprintf(stderr, "update DS records based on child zones' "
3002 "dsset-* files\n");
3003 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
3004 fprintf(stderr, "\t\tRRSIG start time "
3005 "- absolute|offset (now - 1 hour)\n");
3006 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
3007 fprintf(stderr, "\t\tRRSIG end time "
3008 "- absolute|from start|from now "
3009 "(now + 30 days)\n");
3010 fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
3011 fprintf(stderr, "\t\tDNSKEY RRSIG end "
3012 "- absolute|from start|from now "
3013 "(matches -e)\n");
3014 fprintf(stderr, "\t-i interval:\n");
3015 fprintf(stderr, "\t\tcycle interval - resign "
3016 "if < interval from end ( (end-start)/4 )\n");
3017 fprintf(stderr, "\t-j jitter:\n");
3018 fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
3019 fprintf(stderr, "\t-v debuglevel (0)\n");
3020 fprintf(stderr, "\t-V:\tprint version information\n");
3021 fprintf(stderr, "\t-o origin:\n");
3022 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
3023 fprintf(stderr, "\t-f outfile:\n");
3024 fprintf(stderr, "\t\tfile the signed zone is written in "
3025 "(zonefile + .signed)\n");
3026 fprintf(stderr, "\t-I format:\n");
3027 fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
3028 fprintf(stderr, "\t-O format:\n");
3029 fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
3030 fprintf(stderr, "\t-N format:\n");
3031 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
3032 fprintf(stderr, "\t-D:\n");
3033 fprintf(stderr, "\t\toutput only DNSSEC-related records\n");
3034 fprintf(stderr, "\t-r randomdev:\n");
3035 fprintf(stderr, "\t\ta file containing random data\n");
3036 fprintf(stderr, "\t-a:\t");
3037 fprintf(stderr, "verify generated signatures\n");
3038 fprintf(stderr, "\t-c class (IN)\n");
3039 fprintf(stderr, "\t-E engine:\n");
3040 #if defined(PKCS11CRYPTO)
3041 fprintf(stderr, "\t\tpath to PKCS#11 provider library "
3042 "(default is %s)\n", PK11_LIB_LOCATION);
3043 #elif defined(USE_PKCS11)
3044 fprintf(stderr, "\t\tname of an OpenSSL engine to use "
3045 "(default is \"pkcs11\")\n");
3046 #else
3047 fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
3048 #endif
3049 fprintf(stderr, "\t-p:\t");
3050 fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
3051 fprintf(stderr, "\t-P:\t");
3052 fprintf(stderr, "disable post-sign verification\n");
3053 fprintf(stderr, "\t-Q:\t");
3054 fprintf(stderr, "remove signatures from keys that are no "
3055 "longer active\n");
3056 fprintf(stderr, "\t-R:\t");
3057 fprintf(stderr, "remove signatures from keys that no longer exist\n");
3058 fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
3059 fprintf(stderr, "\t-t:\t");
3060 fprintf(stderr, "print statistics\n");
3061 fprintf(stderr, "\t-u:\t");
3062 fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
3063 fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
3064 fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
3065 fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
3066 "\t\twith older versions of dnssec-signzone -g\n");
3067 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
3068 fprintf(stderr, "\t-k key_signing_key\n");
3069 fprintf(stderr, "\t-l lookasidezone\n");
3070 fprintf(stderr, "\t-3 NSEC3 salt\n");
3071 fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
3072 fprintf(stderr, "\t-A NSEC3 optout\n");
3073
3074 fprintf(stderr, "\n");
3075
3076 fprintf(stderr, "Signing Keys: ");
3077 fprintf(stderr, "(default: all zone keys that have private keys)\n");
3078 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
3079
3080 exit(0);
3081 }
3082
3083 static void
removetempfile(void)3084 removetempfile(void) {
3085 if (removefile)
3086 isc_file_remove(tempfile);
3087 }
3088
3089 static void
print_stats(isc_time_t * timer_start,isc_time_t * timer_finish,isc_time_t * sign_start,isc_time_t * sign_finish)3090 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish,
3091 isc_time_t *sign_start, isc_time_t *sign_finish)
3092 {
3093 uint64_t time_us; /* Time in microseconds */
3094 uint64_t time_ms; /* Time in milliseconds */
3095 uint64_t sig_ms; /* Signatures per millisecond */
3096 FILE *out = output_stdout ? stderr : stdout;
3097
3098 fprintf(out, "Signatures generated: %10u\n", nsigned);
3099 fprintf(out, "Signatures retained: %10u\n", nretained);
3100 fprintf(out, "Signatures dropped: %10u\n", ndropped);
3101 fprintf(out, "Signatures successfully verified: %10u\n", nverified);
3102 fprintf(out, "Signatures unsuccessfully "
3103 "verified: %10u\n", nverifyfailed);
3104
3105 time_us = isc_time_microdiff(sign_finish, sign_start);
3106 time_ms = time_us / 1000;
3107 fprintf(out, "Signing time in seconds: %7u.%03u\n",
3108 (unsigned int) (time_ms / 1000),
3109 (unsigned int) (time_ms % 1000));
3110 if (time_us > 0) {
3111 sig_ms = ((uint64_t)nsigned * 1000000000) / time_us;
3112 fprintf(out, "Signatures per second: %7u.%03u\n",
3113 (unsigned int) sig_ms / 1000,
3114 (unsigned int) sig_ms % 1000);
3115 }
3116
3117 time_us = isc_time_microdiff(timer_finish, timer_start);
3118 time_ms = time_us / 1000;
3119 fprintf(out, "Runtime in seconds: %7u.%03u\n",
3120 (unsigned int) (time_ms / 1000),
3121 (unsigned int) (time_ms % 1000));
3122 }
3123
3124 int
main(int argc,char * argv[])3125 main(int argc, char *argv[]) {
3126 int i, ch;
3127 char *startstr = NULL, *endstr = NULL, *classname = NULL;
3128 char *dnskey_endstr = NULL;
3129 char *origin = NULL, *file = NULL, *output = NULL;
3130 char *inputformatstr = NULL, *outputformatstr = NULL;
3131 char *serialformatstr = NULL;
3132 char *dskeyfile[MAXDSKEYS];
3133 int ndskeys = 0;
3134 char *endp;
3135 isc_time_t timer_start, timer_finish;
3136 isc_time_t sign_start, sign_finish;
3137 dns_dnsseckey_t *key;
3138 isc_result_t result;
3139 isc_log_t *log = NULL;
3140 bool pseudorandom = false;
3141 #ifdef USE_PKCS11
3142 const char *engine = PKCS11_ENGINE;
3143 #else
3144 const char *engine = NULL;
3145 #endif
3146 unsigned int eflags;
3147 bool free_output = false;
3148 int tempfilelen = 0;
3149 dns_rdataclass_t rdclass;
3150 isc_task_t **tasks = NULL;
3151 isc_buffer_t b;
3152 int len;
3153 hashlist_t hashlist;
3154 bool make_keyset = false;
3155 bool set_salt = false;
3156 bool set_optout = false;
3157 bool set_iter = false;
3158 bool nonsecify = false;
3159
3160 /* Unused letters: Bb G J q Yy (and F is reserved). */
3161 #define CMDLINE_FLAGS \
3162 "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:M:n:N:o:O:PpQRr:s:ST:tuUv:VX:xzZ:"
3163
3164 /*
3165 * Process memory debugging argument first.
3166 */
3167 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3168 switch (ch) {
3169 case 'm':
3170 if (strcasecmp(isc_commandline_argument, "record") == 0)
3171 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
3172 if (strcasecmp(isc_commandline_argument, "trace") == 0)
3173 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
3174 if (strcasecmp(isc_commandline_argument, "usage") == 0)
3175 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
3176 if (strcasecmp(isc_commandline_argument, "size") == 0)
3177 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
3178 if (strcasecmp(isc_commandline_argument, "mctx") == 0)
3179 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
3180 break;
3181 default:
3182 break;
3183 }
3184 }
3185 isc_commandline_reset = true;
3186
3187 #ifdef _WIN32
3188 InitSockets();
3189 #endif
3190
3191 masterstyle = &dns_master_style_explicitttl;
3192
3193 check_result(isc_app_start(), "isc_app_start");
3194
3195 result = isc_mem_create(0, 0, &mctx);
3196 if (result != ISC_R_SUCCESS)
3197 fatal("out of memory");
3198
3199 #ifdef PKCS11CRYPTO
3200 pk11_result_register();
3201 #endif
3202 dns_result_register();
3203
3204 isc_commandline_errprint = false;
3205
3206 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3207 switch (ch) {
3208 case '3':
3209 set_salt = true;
3210 nsec_datatype = dns_rdatatype_nsec3;
3211 if (strcmp(isc_commandline_argument, "-") != 0) {
3212 isc_buffer_t target;
3213 char *sarg;
3214
3215 sarg = isc_commandline_argument;
3216 isc_buffer_init(&target, saltbuf,
3217 sizeof(saltbuf));
3218 result = isc_hex_decodestring(sarg, &target);
3219 check_result(result,
3220 "isc_hex_decodestring(salt)");
3221 salt_length = isc_buffer_usedlength(&target);
3222 }
3223 break;
3224
3225 case 'A':
3226 set_optout = true;
3227 if (OPTOUT(nsec3flags))
3228 nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
3229 else
3230 nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
3231 break;
3232
3233 case 'a':
3234 tryverify = true;
3235 break;
3236
3237 case 'C':
3238 make_keyset = true;
3239 break;
3240
3241 case 'c':
3242 classname = isc_commandline_argument;
3243 break;
3244
3245 case 'd':
3246 dsdir = isc_commandline_argument;
3247 if (strlen(dsdir) == 0U)
3248 fatal("DS directory must be non-empty string");
3249 result = try_dir(dsdir);
3250 if (result != ISC_R_SUCCESS)
3251 fatal("cannot open directory %s: %s",
3252 dsdir, isc_result_totext(result));
3253 break;
3254
3255 case 'D':
3256 output_dnssec_only = true;
3257 break;
3258
3259 case 'E':
3260 engine = isc_commandline_argument;
3261 break;
3262
3263 case 'e':
3264 endstr = isc_commandline_argument;
3265 break;
3266
3267 case 'f':
3268 output = isc_commandline_argument;
3269 if (strcmp(output, "-") == 0)
3270 output_stdout = true;
3271 break;
3272
3273 case 'g':
3274 generateds = true;
3275 break;
3276
3277 case 'H':
3278 set_iter = true;
3279 /* too-many is NOT DOCUMENTED */
3280 if (strcmp(isc_commandline_argument, "too-many") == 0) {
3281 nsec3iter = 151;
3282 no_max_check = true;
3283 break;
3284 }
3285 nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
3286 if (*endp != '\0')
3287 fatal("iterations must be numeric");
3288 if (nsec3iter > 0xffffU)
3289 fatal("iterations too big");
3290 break;
3291
3292 case 'I':
3293 inputformatstr = isc_commandline_argument;
3294 break;
3295
3296 case 'i':
3297 endp = NULL;
3298 cycle = strtol(isc_commandline_argument, &endp, 0);
3299 if (*endp != '\0' || cycle < 0)
3300 fatal("cycle period must be numeric and "
3301 "positive");
3302 break;
3303
3304 case 'j':
3305 endp = NULL;
3306 jitter = strtol(isc_commandline_argument, &endp, 0);
3307 if (*endp != '\0' || jitter < 0)
3308 fatal("jitter must be numeric and positive");
3309 break;
3310
3311 case 'K':
3312 directory = isc_commandline_argument;
3313 break;
3314
3315 case 'k':
3316 if (ndskeys == MAXDSKEYS)
3317 fatal("too many key-signing keys specified");
3318 dskeyfile[ndskeys++] = isc_commandline_argument;
3319 break;
3320
3321 case 'L':
3322 snset = true;
3323 endp = NULL;
3324 serialnum = strtol(isc_commandline_argument, &endp, 0);
3325 if (*endp != '\0') {
3326 fprintf(stderr, "source serial number "
3327 "must be numeric");
3328 exit(1);
3329 }
3330 break;
3331
3332 case 'l':
3333 len = strlen(isc_commandline_argument);
3334 isc_buffer_init(&b, isc_commandline_argument, len);
3335 isc_buffer_add(&b, len);
3336
3337 dlv = dns_fixedname_initname(&dlv_fixed);
3338 result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
3339 NULL);
3340 check_result(result, "dns_name_fromtext(dlv)");
3341 break;
3342
3343 case 'M':
3344 endp = NULL;
3345 set_maxttl = true;
3346 maxttl = strtol(isc_commandline_argument, &endp, 0);
3347 if (*endp != '\0') {
3348 fprintf(stderr, "maximum TTL "
3349 "must be numeric");
3350 exit(1);
3351 }
3352 break;
3353
3354 case 'm':
3355 break;
3356
3357 case 'N':
3358 serialformatstr = isc_commandline_argument;
3359 break;
3360
3361 case 'n':
3362 endp = NULL;
3363 ntasks = strtol(isc_commandline_argument, &endp, 0);
3364 if (*endp != '\0' || ntasks > INT32_MAX)
3365 fatal("number of cpus must be numeric");
3366 break;
3367
3368 case 'O':
3369 outputformatstr = isc_commandline_argument;
3370 break;
3371
3372 case 'o':
3373 origin = isc_commandline_argument;
3374 break;
3375
3376 case 'P':
3377 disable_zone_check = true;
3378 break;
3379
3380 case 'p':
3381 pseudorandom = true;
3382 break;
3383
3384 case 'Q':
3385 remove_inactkeysigs = true;
3386 break;
3387
3388 case 'R':
3389 remove_orphansigs = true;
3390 break;
3391
3392 case 'r':
3393 setup_entropy(mctx, isc_commandline_argument, &ectx);
3394 break;
3395
3396 case 'S':
3397 smartsign = true;
3398 break;
3399
3400 case 's':
3401 startstr = isc_commandline_argument;
3402 break;
3403
3404 case 'T':
3405 endp = NULL;
3406 set_keyttl = true;
3407 keyttl = strtottl(isc_commandline_argument);
3408 break;
3409
3410 case 't':
3411 printstats = true;
3412 break;
3413
3414 case 'U': /* Undocumented for testing only. */
3415 unknownalg = true;
3416 break;
3417
3418 case 'u':
3419 update_chain = true;
3420 break;
3421
3422 case 'v':
3423 endp = NULL;
3424 verbose = strtol(isc_commandline_argument, &endp, 0);
3425 if (*endp != '\0')
3426 fatal("verbose level must be numeric");
3427 break;
3428
3429 case 'X':
3430 dnskey_endstr = isc_commandline_argument;
3431 break;
3432
3433 case 'x':
3434 keyset_kskonly = true;
3435 break;
3436
3437 case 'z':
3438 ignore_kskflag = true;
3439 break;
3440
3441 case 'F':
3442 /* Reserved for FIPS mode */
3443 /* FALLTHROUGH */
3444 case '?':
3445 if (isc_commandline_option != '?')
3446 fprintf(stderr, "%s: invalid argument -%c\n",
3447 program, isc_commandline_option);
3448 /* FALLTHROUGH */
3449 case 'h':
3450 /* Does not return. */
3451 usage();
3452
3453 case 'V':
3454 /* Does not return. */
3455 version(program);
3456
3457 case 'Z': /* Undocumented test options */
3458 if (!strcmp(isc_commandline_argument, "nonsecify"))
3459 nonsecify = true;
3460 break;
3461
3462 default:
3463 fprintf(stderr, "%s: unhandled option -%c\n",
3464 program, isc_commandline_option);
3465 exit(1);
3466 }
3467 }
3468
3469 if (ectx == NULL)
3470 setup_entropy(mctx, NULL, &ectx);
3471 eflags = ISC_ENTROPY_BLOCKING;
3472 if (!pseudorandom)
3473 eflags |= ISC_ENTROPY_GOODONLY;
3474
3475 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
3476 if (result != ISC_R_SUCCESS)
3477 fatal("could not create hash context");
3478
3479 result = dst_lib_init2(mctx, ectx, engine, eflags);
3480 if (result != ISC_R_SUCCESS)
3481 fatal("could not initialize dst: %s",
3482 isc_result_totext(result));
3483 isc_stdtime_get(&now);
3484
3485 if (startstr != NULL) {
3486 starttime = strtotime(startstr, now, now, NULL);
3487 } else
3488 starttime = now - 3600; /* Allow for some clock skew. */
3489
3490 if (endstr != NULL)
3491 endtime = strtotime(endstr, now, starttime, NULL);
3492 else
3493 endtime = starttime + (30 * 24 * 60 * 60);
3494
3495 if (dnskey_endstr != NULL) {
3496 dnskey_endtime = strtotime(dnskey_endstr, now, starttime,
3497 NULL);
3498 if (endstr != NULL && dnskey_endtime == endtime)
3499 fprintf(stderr, "WARNING: -e and -X were both set, "
3500 "but have identical values.\n");
3501 } else
3502 dnskey_endtime = endtime;
3503
3504 if (cycle == -1)
3505 cycle = (endtime - starttime) / 4;
3506
3507 if (ntasks == 0)
3508 ntasks = isc_os_ncpus() * 2;
3509 vbprintf(4, "using %d cpus\n", ntasks);
3510
3511 rdclass = strtoclass(classname);
3512
3513 if (directory == NULL)
3514 directory = ".";
3515
3516 setup_logging(mctx, &log);
3517
3518 argc -= isc_commandline_index;
3519 argv += isc_commandline_index;
3520
3521 if (argc < 1)
3522 usage();
3523
3524 file = argv[0];
3525
3526 argc -= 1;
3527 argv += 1;
3528
3529 if (origin == NULL)
3530 origin = file;
3531
3532 if (output == NULL) {
3533 size_t size;
3534 free_output = true;
3535 size = strlen(file) + strlen(".signed") + 1;
3536 output = isc_mem_allocate(mctx, size);
3537 if (output == NULL)
3538 fatal("out of memory");
3539 snprintf(output, size, "%s.signed", file);
3540 }
3541
3542 if (inputformatstr != NULL) {
3543 if (strcasecmp(inputformatstr, "text") == 0)
3544 inputformat = dns_masterformat_text;
3545 else if (strcasecmp(inputformatstr, "map") == 0)
3546 inputformat = dns_masterformat_map;
3547 else if (strcasecmp(inputformatstr, "raw") == 0)
3548 inputformat = dns_masterformat_raw;
3549 else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
3550 inputformat = dns_masterformat_raw;
3551 fprintf(stderr,
3552 "WARNING: input format version ignored\n");
3553 } else
3554 fatal("unknown file format: %s", inputformatstr);
3555
3556 }
3557
3558 if (outputformatstr != NULL) {
3559 if (strcasecmp(outputformatstr, "text") == 0) {
3560 outputformat = dns_masterformat_text;
3561 } else if (strcasecmp(outputformatstr, "full") == 0) {
3562 outputformat = dns_masterformat_text;
3563 masterstyle = &dns_master_style_full;
3564 } else if (strcasecmp(outputformatstr, "map") == 0) {
3565 outputformat = dns_masterformat_map;
3566 } else if (strcasecmp(outputformatstr, "raw") == 0) {
3567 outputformat = dns_masterformat_raw;
3568 } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
3569 char *end;
3570 outputformat = dns_masterformat_raw;
3571
3572 outputformat = dns_masterformat_raw;
3573 rawversion = strtol(outputformatstr + 4, &end, 10);
3574 if (end == outputformatstr + 4 || *end != '\0' ||
3575 rawversion > 1U) {
3576 fprintf(stderr,
3577 "unknown raw format version\n");
3578 exit(1);
3579 }
3580 } else
3581 fatal("unknown file format: %s", outputformatstr);
3582 }
3583
3584 if (serialformatstr != NULL) {
3585 if (strcasecmp(serialformatstr, "keep") == 0)
3586 serialformat = SOA_SERIAL_KEEP;
3587 else if (strcasecmp(serialformatstr, "increment") == 0 ||
3588 strcasecmp(serialformatstr, "incr") == 0)
3589 serialformat = SOA_SERIAL_INCREMENT;
3590 else if (strcasecmp(serialformatstr, "unixtime") == 0)
3591 serialformat = SOA_SERIAL_UNIXTIME;
3592 else if (strcasecmp(serialformatstr, "date") == 0)
3593 serialformat = SOA_SERIAL_DATE;
3594 else
3595 fatal("unknown soa serial format: %s",
3596 serialformatstr);
3597 }
3598
3599 if (output_dnssec_only && outputformat != dns_masterformat_text)
3600 fatal("option -D can only be used with \"-O text\"");
3601
3602 if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP)
3603 fatal("option -D can only be used with \"-N keep\"");
3604
3605 if (output_dnssec_only && set_maxttl)
3606 fatal("option -D cannot be used with -M");
3607
3608 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
3609 0, 24, 0, 0, 0, 8, mctx);
3610 check_result(result, "dns_master_stylecreate");
3611
3612 gdb = NULL;
3613 TIME_NOW(&timer_start);
3614 loadzone(file, origin, rdclass, &gdb);
3615 gorigin = dns_db_origin(gdb);
3616 gclass = dns_db_class(gdb);
3617 get_soa_ttls();
3618
3619 if (set_maxttl && set_keyttl && keyttl > maxttl) {
3620 fprintf(stderr, "%s: warning: Specified key TTL %u "
3621 "exceeds maximum zone TTL; reducing to %u\n",
3622 program, keyttl, maxttl);
3623 keyttl = maxttl;
3624 }
3625
3626 if (!set_keyttl)
3627 keyttl = soa_ttl;
3628
3629 /*
3630 * Check for any existing NSEC3 parameters in the zone,
3631 * and use them as defaults if -u was not specified.
3632 */
3633 if (update_chain && !set_optout && !set_iter && !set_salt)
3634 nsec_datatype = dns_rdatatype_nsec;
3635 else
3636 set_nsec3params(update_chain, set_salt, set_optout, set_iter);
3637
3638 /*
3639 * We need to do this early on, as we start messing with the list
3640 * of keys rather early.
3641 */
3642 ISC_LIST_INIT(keylist);
3643 result = isc_rwlock_init(&keylist_lock, 0, 0);
3644 if (result != ISC_R_SUCCESS)
3645 fatal("could not initialize keylist_lock: %s",
3646 isc_result_totext(result));
3647
3648 /*
3649 * Fill keylist with:
3650 * 1) Keys listed in the DNSKEY set that have
3651 * private keys associated, *if* no keys were
3652 * set on the command line.
3653 * 2) ZSKs set on the command line
3654 * 3) KSKs set on the command line
3655 * 4) Any keys remaining in the DNSKEY set which
3656 * do not have private keys associated and were
3657 * not specified on the command line.
3658 */
3659 if (argc == 0 || smartsign)
3660 loadzonekeys(!smartsign, false);
3661 loadexplicitkeys(argv, argc, false);
3662 loadexplicitkeys(dskeyfile, ndskeys, true);
3663 loadzonekeys(!smartsign, true);
3664
3665 /*
3666 * If we're doing smart signing, look in the key repository for
3667 * key files with metadata, and merge them with the keylist
3668 * we have now.
3669 */
3670 if (smartsign)
3671 build_final_keylist();
3672
3673 /* Now enumerate the key list */
3674 for (key = ISC_LIST_HEAD(keylist);
3675 key != NULL;
3676 key = ISC_LIST_NEXT(key, link)) {
3677 key->index = keycount++;
3678 }
3679
3680 if (keycount == 0) {
3681 if (disable_zone_check)
3682 fprintf(stderr, "%s: warning: No keys specified "
3683 "or found\n", program);
3684 else
3685 fatal("No signing keys specified or found.");
3686 nokeys = true;
3687 }
3688
3689 warnifallksk(gdb);
3690
3691 if (IS_NSEC3) {
3692 bool answer;
3693
3694 hash_length = dns_nsec3_hashlength(dns_hash_sha1);
3695 hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
3696 hash_length);
3697 result = dns_nsec_nseconly(gdb, gversion, &answer);
3698 if (result == ISC_R_NOTFOUND)
3699 fprintf(stderr, "%s: warning: NSEC3 generation "
3700 "requested with no DNSKEY; ignoring\n",
3701 program);
3702 else if (result != ISC_R_SUCCESS)
3703 check_result(result, "dns_nsec_nseconly");
3704 else if (answer)
3705 fatal("NSEC3 generation requested with "
3706 "NSEC-only DNSKEY");
3707
3708 if (nsec3iter > dns_nsec3_maxiterations()) {
3709 if (no_max_check) {
3710 fprintf(stderr,
3711 "Ignoring max iterations check.\n");
3712 } else {
3713 fatal("NSEC3 iterations too big. Maximum "
3714 "iterations allowed %u.",
3715 dns_nsec3_maxiterations());
3716 }
3717 }
3718
3719 } else {
3720 hashlist_init(&hashlist, 0, 0); /* silence clang */
3721 }
3722
3723 gversion = NULL;
3724 result = dns_db_newversion(gdb, &gversion);
3725 check_result(result, "dns_db_newversion()");
3726
3727 switch (serialformat) {
3728 case SOA_SERIAL_INCREMENT:
3729 setsoaserial(0, dns_updatemethod_increment);
3730 break;
3731 case SOA_SERIAL_UNIXTIME:
3732 setsoaserial(now, dns_updatemethod_unixtime);
3733 break;
3734 case SOA_SERIAL_DATE:
3735 setsoaserial(now, dns_updatemethod_date);
3736 break;
3737 case SOA_SERIAL_KEEP:
3738 default:
3739 /* do nothing */
3740 break;
3741 }
3742
3743 /* Remove duplicates and cap TTLs at maxttl */
3744 cleanup_zone();
3745
3746 if (!nonsecify) {
3747 if (IS_NSEC3)
3748 nsec3ify(dns_hash_sha1, nsec3iter, gsalt, salt_length,
3749 &hashlist);
3750 else
3751 nsecify();
3752 }
3753
3754 if (!nokeys) {
3755 writeset("dsset-", dns_rdatatype_ds);
3756 if (make_keyset)
3757 writeset("keyset-", dns_rdatatype_dnskey);
3758 if (dlv != NULL) {
3759 writeset("dlvset-", dns_rdatatype_dlv);
3760 }
3761 }
3762
3763 if (output_stdout) {
3764 outfp = stdout;
3765 if (outputformatstr == NULL)
3766 masterstyle = &dns_master_style_full;
3767 } else {
3768 tempfilelen = strlen(output) + 20;
3769 tempfile = isc_mem_get(mctx, tempfilelen);
3770 if (tempfile == NULL)
3771 fatal("out of memory");
3772
3773 result = isc_file_mktemplate(output, tempfile, tempfilelen);
3774 check_result(result, "isc_file_mktemplate");
3775
3776 if (outputformat == dns_masterformat_text)
3777 result = isc_file_openunique(tempfile, &outfp);
3778 else
3779 result = isc_file_bopenunique(tempfile, &outfp);
3780 if (result != ISC_R_SUCCESS)
3781 fatal("failed to open temporary output file: %s",
3782 isc_result_totext(result));
3783 removefile = true;
3784 setfatalcallback(&removetempfile);
3785 }
3786
3787 print_time(outfp);
3788 print_version(outfp);
3789
3790 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
3791 if (result != ISC_R_SUCCESS)
3792 fatal("failed to create task manager: %s",
3793 isc_result_totext(result));
3794
3795 master = NULL;
3796 result = isc_task_create(taskmgr, 0, &master);
3797 if (result != ISC_R_SUCCESS)
3798 fatal("failed to create task: %s", isc_result_totext(result));
3799
3800 tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
3801 if (tasks == NULL)
3802 fatal("out of memory");
3803 for (i = 0; i < (int)ntasks; i++) {
3804 tasks[i] = NULL;
3805 result = isc_task_create(taskmgr, 0, &tasks[i]);
3806 if (result != ISC_R_SUCCESS)
3807 fatal("failed to create task: %s",
3808 isc_result_totext(result));
3809 }
3810
3811 RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
3812 if (printstats)
3813 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
3814
3815 presign();
3816 TIME_NOW(&sign_start);
3817 signapex();
3818 if (!finished) {
3819 /*
3820 * There is more work to do. Spread it out over multiple
3821 * processors if possible.
3822 */
3823 for (i = 0; i < (int)ntasks; i++) {
3824 result = isc_app_onrun(mctx, master, startworker,
3825 tasks[i]);
3826 if (result != ISC_R_SUCCESS)
3827 fatal("failed to start task: %s",
3828 isc_result_totext(result));
3829 }
3830 (void)isc_app_run();
3831 if (!finished)
3832 fatal("process aborted by user");
3833 } else
3834 isc_task_detach(&master);
3835 shuttingdown = true;
3836 for (i = 0; i < (int)ntasks; i++)
3837 isc_task_detach(&tasks[i]);
3838 isc_taskmgr_destroy(&taskmgr);
3839 isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
3840 postsign();
3841 TIME_NOW(&sign_finish);
3842
3843 if (!disable_zone_check)
3844 verifyzone(gdb, gversion, gorigin, mctx,
3845 ignore_kskflag, keyset_kskonly);
3846
3847 if (outputformat != dns_masterformat_text) {
3848 dns_masterrawheader_t header;
3849 dns_master_initrawheader(&header);
3850 if (rawversion == 0U)
3851 header.flags = DNS_MASTERRAW_COMPAT;
3852 else if (snset) {
3853 header.flags = DNS_MASTERRAW_SOURCESERIALSET;
3854 header.sourceserial = serialnum;
3855 }
3856 result = dns_master_dumptostream3(mctx, gdb, gversion,
3857 masterstyle, outputformat,
3858 &header, outfp);
3859 check_result(result, "dns_master_dumptostream3");
3860 }
3861
3862 DESTROYLOCK(&namelock);
3863 if (printstats)
3864 DESTROYLOCK(&statslock);
3865
3866 if (!output_stdout) {
3867 result = isc_stdio_close(outfp);
3868 check_result(result, "isc_stdio_close");
3869 removefile = false;
3870
3871 result = isc_file_rename(tempfile, output);
3872 if (result != ISC_R_SUCCESS)
3873 fatal("failed to rename temp file to %s: %s",
3874 output, isc_result_totext(result));
3875
3876 printf("%s\n", output);
3877 }
3878
3879 dns_db_closeversion(gdb, &gversion, false);
3880 dns_db_detach(&gdb);
3881
3882 hashlist_free(&hashlist);
3883
3884 while (!ISC_LIST_EMPTY(keylist)) {
3885 key = ISC_LIST_HEAD(keylist);
3886 ISC_LIST_UNLINK(keylist, key, link);
3887 dns_dnsseckey_destroy(mctx, &key);
3888 }
3889
3890 if (tempfilelen != 0)
3891 isc_mem_put(mctx, tempfile, tempfilelen);
3892
3893 if (free_output)
3894 isc_mem_free(mctx, output);
3895
3896 dns_master_styledestroy(&dsstyle, mctx);
3897
3898 cleanup_logging(&log);
3899 dst_lib_destroy();
3900 isc_hash_destroy();
3901 cleanup_entropy(&ectx);
3902 dns_name_destroy();
3903 if (verbose > 10)
3904 isc_mem_stats(mctx, stdout);
3905 isc_mem_destroy(&mctx);
3906
3907 (void) isc_app_finish();
3908
3909 if (printstats) {
3910 TIME_NOW(&timer_finish);
3911 print_stats(&timer_start, &timer_finish,
3912 &sign_start, &sign_finish);
3913 }
3914
3915 #ifdef _WIN32
3916 DestroySockets();
3917 #endif
3918 return (0);
3919 }
3920