1 /* $NetBSD: dnssec-signzone.c,v 1.15 2015/07/08 17:28:55 christos Exp $ */
4 * Portions Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC")
5 * Portions Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
12 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
14 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
21 * Permission to use, copy, modify, and/or distribute this software for any
22 * purpose with or without fee is hereby granted, provided that the above
23 * copyright notice and this permission notice appear in all copies.
25 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
26 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
27 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
28 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
31 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
43 #include <isc/base32.h>
44 #include <isc/commandline.h>
45 #include <isc/entropy.h>
46 #include <isc/event.h>
51 #include <isc/mutex.h>
53 #include <isc/print.h>
54 #include <isc/random.h>
55 #include <isc/rwlock.h>
56 #include <isc/serial.h>
57 #include <isc/stdio.h>
58 #include <isc/stdlib.h>
59 #include <isc/string.h>
65 #include <dns/dbiterator.h>
67 #include <dns/dnssec.h>
69 #include <dns/fixedname.h>
70 #include <dns/keyvalues.h>
72 #include <dns/master.h>
73 #include <dns/masterdump.h>
75 #include <dns/nsec3.h>
76 #include <dns/rdata.h>
77 #include <dns/rdatalist.h>
78 #include <dns/rdataset.h>
79 #include <dns/rdataclass.h>
80 #include <dns/rdatasetiter.h>
81 #include <dns/rdatastruct.h>
82 #include <dns/rdatatype.h>
83 #include <dns/result.h>
90 #include <pk11/result.h>
93 #include "dnssectool.h"
96 #define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */
99 const char *program
= "dnssec-signzone";
102 typedef struct hashlist hashlist_t
;
104 static int nsec_datatype
= dns_rdatatype_nsec
;
106 #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
107 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
109 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
114 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
115 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
116 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
118 #define SOA_SERIAL_KEEP 0
119 #define SOA_SERIAL_INCREMENT 1
120 #define SOA_SERIAL_UNIXTIME 2
122 typedef struct signer_event sevent_t
;
123 struct signer_event
{
124 ISC_EVENT_COMMON(sevent_t
);
125 dns_fixedname_t
*fname
;
129 static dns_dnsseckeylist_t keylist
;
130 static unsigned int keycount
= 0;
131 isc_rwlock_t keylist_lock
;
132 static isc_stdtime_t starttime
= 0, endtime
= 0, dnskey_endtime
= 0, now
;
133 static int cycle
= -1;
134 static int jitter
= 0;
135 static isc_boolean_t tryverify
= ISC_FALSE
;
136 static isc_boolean_t printstats
= ISC_FALSE
;
137 static isc_mem_t
*mctx
= NULL
;
138 static isc_entropy_t
*ectx
= NULL
;
139 static dns_ttl_t zone_soa_min_ttl
;
140 static dns_ttl_t soa_ttl
;
141 static FILE *outfp
= NULL
;
142 static char *tempfile
= NULL
;
143 static const dns_master_style_t
*masterstyle
;
144 static dns_masterformat_t inputformat
= dns_masterformat_text
;
145 static dns_masterformat_t outputformat
= dns_masterformat_text
;
146 static isc_uint32_t rawversion
= 1, serialnum
= 0;
147 static isc_boolean_t snset
= ISC_FALSE
;
148 static unsigned int nsigned
= 0, nretained
= 0, ndropped
= 0;
149 static unsigned int nverified
= 0, nverifyfailed
= 0;
150 static const char *directory
= NULL
, *dsdir
= NULL
;
151 static isc_mutex_t namelock
, statslock
;
152 static isc_taskmgr_t
*taskmgr
= NULL
;
153 static dns_db_t
*gdb
; /* The database */
154 static dns_dbversion_t
*gversion
; /* The database version */
155 static dns_dbiterator_t
*gdbiter
; /* The database iterator */
156 static dns_rdataclass_t gclass
; /* The class */
157 static dns_name_t
*gorigin
; /* The database origin */
158 static int nsec3flags
= 0;
159 static dns_iterations_t nsec3iter
= 10U;
160 static unsigned char saltbuf
[255];
161 static unsigned char *gsalt
= saltbuf
;
162 static size_t salt_length
= 0;
163 static isc_task_t
*master
= NULL
;
164 static unsigned int ntasks
= 0;
165 static isc_boolean_t shuttingdown
= ISC_FALSE
, finished
= ISC_FALSE
;
166 static isc_boolean_t nokeys
= ISC_FALSE
;
167 static isc_boolean_t removefile
= ISC_FALSE
;
168 static isc_boolean_t generateds
= ISC_FALSE
;
169 static isc_boolean_t ignore_kskflag
= ISC_FALSE
;
170 static isc_boolean_t keyset_kskonly
= ISC_FALSE
;
171 static dns_name_t
*dlv
= NULL
;
172 static dns_fixedname_t dlv_fixed
;
173 static dns_master_style_t
*dsstyle
= NULL
;
174 static unsigned int serialformat
= SOA_SERIAL_KEEP
;
175 static unsigned int hash_length
= 0;
176 static isc_boolean_t unknownalg
= ISC_FALSE
;
177 static isc_boolean_t disable_zone_check
= ISC_FALSE
;
178 static isc_boolean_t update_chain
= ISC_FALSE
;
179 static isc_boolean_t set_keyttl
= ISC_FALSE
;
180 static dns_ttl_t keyttl
;
181 static isc_boolean_t smartsign
= ISC_FALSE
;
182 static isc_boolean_t remove_orphansigs
= ISC_FALSE
;
183 static isc_boolean_t remove_inactkeysigs
= ISC_FALSE
;
184 static isc_boolean_t output_dnssec_only
= ISC_FALSE
;
185 static isc_boolean_t output_stdout
= ISC_FALSE
;
186 isc_boolean_t set_maxttl
= ISC_FALSE
;
187 static dns_ttl_t maxttl
= 0;
189 #define INCSTAT(counter) \
193 UNLOCK(&statslock); \
197 sign(isc_task_t
*task
, isc_event_t
*event
);
200 dumpnode(dns_name_t
*name
, dns_dbnode_t
*node
) {
202 dns_rdatasetiter_t
*iter
= NULL
;
203 isc_buffer_t
*buffer
= NULL
;
206 unsigned bufsize
= 4096;
208 if (outputformat
!= dns_masterformat_text
)
211 if (!output_dnssec_only
) {
212 result
= dns_master_dumpnodetostream(mctx
, gdb
, gversion
, node
,
213 name
, masterstyle
, outfp
);
214 check_result(result
, "dns_master_dumpnodetostream");
218 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &iter
);
219 check_result(result
, "dns_db_allrdatasets");
221 dns_rdataset_init(&rds
);
223 result
= isc_buffer_allocate(mctx
, &buffer
, bufsize
);
224 check_result(result
, "isc_buffer_allocate");
226 for (result
= dns_rdatasetiter_first(iter
);
227 result
== ISC_R_SUCCESS
;
228 result
= dns_rdatasetiter_next(iter
)) {
230 dns_rdatasetiter_current(iter
, &rds
);
232 if (rds
.type
!= dns_rdatatype_rrsig
&&
233 rds
.type
!= dns_rdatatype_nsec
&&
234 rds
.type
!= dns_rdatatype_nsec3
&&
235 rds
.type
!= dns_rdatatype_nsec3param
&&
236 (!smartsign
|| rds
.type
!= dns_rdatatype_dnskey
)) {
237 dns_rdataset_disassociate(&rds
);
242 result
= dns_master_rdatasettotext(name
, &rds
,
243 masterstyle
, buffer
);
244 if (result
!= ISC_R_NOSPACE
)
248 isc_buffer_free(&buffer
);
249 result
= isc_buffer_allocate(mctx
, &buffer
, bufsize
);
250 check_result(result
, "isc_buffer_allocate");
252 check_result(result
, "dns_master_rdatasettotext");
254 isc_buffer_usedregion(buffer
, &r
);
255 result
= isc_stdio_write(r
.base
, 1, r
.length
, outfp
, NULL
);
256 check_result(result
, "isc_stdio_write");
257 isc_buffer_clear(buffer
);
259 dns_rdataset_disassociate(&rds
);
262 isc_buffer_free(&buffer
);
263 dns_rdatasetiter_destroy(&iter
);
267 * Sign the given RRset with given key, and add the signature record to the
271 signwithkey(dns_name_t
*name
, dns_rdataset_t
*rdataset
, dst_key_t
*key
,
272 dns_ttl_t ttl
, dns_diff_t
*add
, const char *logmsg
)
275 isc_stdtime_t jendtime
, expiry
;
276 char keystr
[DST_KEY_FORMATSIZE
];
277 dns_rdata_t trdata
= DNS_RDATA_INIT
;
278 unsigned char array
[BUFSIZE
];
280 dns_difftuple_t
*tuple
;
282 dst_key_format(key
, keystr
, sizeof(keystr
));
283 vbprintf(1, "\t%s %s\n", logmsg
, keystr
);
285 if (rdataset
->type
== dns_rdatatype_dnskey
)
286 expiry
= dnskey_endtime
;
290 jendtime
= (jitter
!= 0) ? isc_random_jitter(expiry
, jitter
) : expiry
;
291 isc_buffer_init(&b
, array
, sizeof(array
));
292 result
= dns_dnssec_sign(name
, rdataset
, key
, &starttime
, &jendtime
,
294 isc_entropy_stopcallbacksources(ectx
);
295 if (result
!= ISC_R_SUCCESS
) {
296 fatal("dnskey '%s' failed to sign data: %s",
297 keystr
, isc_result_totext(result
));
302 result
= dns_dnssec_verify(name
, rdataset
, key
,
303 ISC_TRUE
, mctx
, &trdata
);
304 if (result
== ISC_R_SUCCESS
) {
305 vbprintf(3, "\tsignature verified\n");
308 vbprintf(3, "\tsignature failed to verify\n");
309 INCSTAT(nverifyfailed
);
314 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADDRESIGN
,
315 name
, ttl
, &trdata
, &tuple
);
316 check_result(result
, "dns_difftuple_create");
317 dns_diff_append(add
, &tuple
);
320 static inline isc_boolean_t
321 issigningkey(dns_dnsseckey_t
*key
) {
322 return (key
->force_sign
|| key
->hint_sign
);
325 static inline isc_boolean_t
326 ispublishedkey(dns_dnsseckey_t
*key
) {
327 return ((key
->force_publish
|| key
->hint_publish
) &&
331 static inline isc_boolean_t
332 iszonekey(dns_dnsseckey_t
*key
) {
333 return (ISC_TF(dns_name_equal(dst_key_name(key
->key
), gorigin
) &&
334 dst_key_iszonekey(key
->key
)));
337 static inline isc_boolean_t
338 isksk(dns_dnsseckey_t
*key
) {
342 static inline isc_boolean_t
343 iszsk(dns_dnsseckey_t
*key
) {
344 return (ignore_kskflag
|| !key
->ksk
);
348 * Find the key that generated an RRSIG, if it is in the key list. If
349 * so, return a pointer to it, otherwise return NULL.
351 * No locking is performed here, this must be done by the caller.
353 static dns_dnsseckey_t
*
354 keythatsigned_unlocked(dns_rdata_rrsig_t
*rrsig
) {
355 dns_dnsseckey_t
*key
;
357 for (key
= ISC_LIST_HEAD(keylist
);
359 key
= ISC_LIST_NEXT(key
, link
)) {
360 if (rrsig
->keyid
== dst_key_id(key
->key
) &&
361 rrsig
->algorithm
== dst_key_alg(key
->key
) &&
362 dns_name_equal(&rrsig
->signer
, dst_key_name(key
->key
)))
369 * Finds the key that generated a RRSIG, if possible. First look at the keys
370 * that we've loaded already, and then see if there's a key on disk.
372 static dns_dnsseckey_t
*
373 keythatsigned(dns_rdata_rrsig_t
*rrsig
) {
375 dst_key_t
*pubkey
= NULL
, *privkey
= NULL
;
376 dns_dnsseckey_t
*key
= NULL
;
378 isc_rwlock_lock(&keylist_lock
, isc_rwlocktype_read
);
379 key
= keythatsigned_unlocked(rrsig
);
380 isc_rwlock_unlock(&keylist_lock
, isc_rwlocktype_read
);
385 * We did not find the key in our list. Get a write lock now, since
386 * we may be modifying the bits. We could do the tryupgrade() dance,
387 * but instead just get a write lock and check once again to see if
388 * it is on our list. It's possible someone else may have added it
391 isc_rwlock_lock(&keylist_lock
, isc_rwlocktype_write
);
392 key
= keythatsigned_unlocked(rrsig
);
394 isc_rwlock_unlock(&keylist_lock
, isc_rwlocktype_write
);
398 result
= dst_key_fromfile(&rrsig
->signer
, rrsig
->keyid
,
399 rrsig
->algorithm
, DST_TYPE_PUBLIC
,
400 directory
, mctx
, &pubkey
);
401 if (result
!= ISC_R_SUCCESS
) {
402 isc_rwlock_unlock(&keylist_lock
, isc_rwlocktype_write
);
406 result
= dst_key_fromfile(&rrsig
->signer
, rrsig
->keyid
,
408 DST_TYPE_PUBLIC
| DST_TYPE_PRIVATE
,
409 directory
, mctx
, &privkey
);
410 if (result
== ISC_R_SUCCESS
) {
411 dst_key_free(&pubkey
);
412 result
= dns_dnsseckey_create(mctx
, &privkey
, &key
);
414 result
= dns_dnsseckey_create(mctx
, &pubkey
, &key
);
416 if (result
== ISC_R_SUCCESS
) {
417 key
->force_publish
= ISC_FALSE
;
418 key
->force_sign
= ISC_FALSE
;
419 key
->index
= keycount
++;
420 ISC_LIST_APPEND(keylist
, key
, link
);
423 isc_rwlock_unlock(&keylist_lock
, isc_rwlocktype_write
);
428 * Check to see if we expect to find a key at this name. If we see a RRSIG
429 * and can't find the signing key that we expect to find, we drop the rrsig.
430 * I'm not sure if this is completely correct, but it seems to work.
433 expecttofindkey(dns_name_t
*name
) {
434 unsigned int options
= DNS_DBFIND_NOWILD
;
435 dns_fixedname_t fname
;
437 char namestr
[DNS_NAME_FORMATSIZE
];
439 dns_fixedname_init(&fname
);
440 result
= dns_db_find(gdb
, name
, gversion
, dns_rdatatype_dnskey
, options
,
441 0, NULL
, dns_fixedname_name(&fname
), NULL
, NULL
);
447 case DNS_R_DELEGATION
:
452 dns_name_format(name
, namestr
, sizeof(namestr
));
453 fatal("failure looking for '%s DNSKEY' in database: %s",
454 namestr
, isc_result_totext(result
));
456 return (ISC_FALSE
); /* removes a warning */
459 static inline isc_boolean_t
460 setverifies(dns_name_t
*name
, dns_rdataset_t
*set
, dst_key_t
*key
,
464 result
= dns_dnssec_verify(name
, set
, key
, ISC_FALSE
, mctx
, rrsig
);
465 if (result
== ISC_R_SUCCESS
) {
469 INCSTAT(nverifyfailed
);
475 * Signs a set. Goes through contortions to decide if each RRSIG should
476 * be dropped or retained, and then determines if any new SIGs need to
480 signset(dns_diff_t
*del
, dns_diff_t
*add
, dns_dbnode_t
*node
, dns_name_t
*name
,
483 dns_rdataset_t sigset
;
484 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
485 dns_rdata_rrsig_t rrsig
;
486 dns_dnsseckey_t
*key
;
488 isc_boolean_t nosigs
= ISC_FALSE
;
489 isc_boolean_t
*wassignedby
, *nowsignedby
;
491 dns_difftuple_t
*tuple
;
494 char namestr
[DNS_NAME_FORMATSIZE
];
495 char typestr
[TYPE_FORMATSIZE
];
496 char sigstr
[SIG_FORMATSIZE
];
498 dns_name_format(name
, namestr
, sizeof(namestr
));
499 type_format(set
->type
, typestr
, sizeof(typestr
));
501 ttl
= ISC_MIN(set
->ttl
, endtime
- starttime
);
503 dns_rdataset_init(&sigset
);
504 result
= dns_db_findrdataset(gdb
, node
, gversion
, dns_rdatatype_rrsig
,
505 set
->type
, 0, &sigset
, NULL
);
506 if (result
== ISC_R_NOTFOUND
) {
507 vbprintf(2, "no existing signatures for %s/%s\n",
509 result
= ISC_R_SUCCESS
;
512 if (result
!= ISC_R_SUCCESS
)
513 fatal("failed while looking for '%s RRSIG %s': %s",
514 namestr
, typestr
, isc_result_totext(result
));
516 vbprintf(1, "%s/%s:\n", namestr
, typestr
);
518 arraysize
= keycount
;
520 arraysize
+= dns_rdataset_count(&sigset
);
521 wassignedby
= isc_mem_get(mctx
, arraysize
* sizeof(isc_boolean_t
));
522 nowsignedby
= isc_mem_get(mctx
, arraysize
* sizeof(isc_boolean_t
));
523 if (wassignedby
== NULL
|| nowsignedby
== NULL
)
524 fatal("out of memory");
526 for (i
= 0; i
< arraysize
; i
++)
527 wassignedby
[i
] = nowsignedby
[i
] = ISC_FALSE
;
530 result
= ISC_R_NOMORE
;
532 result
= dns_rdataset_first(&sigset
);
534 while (result
== ISC_R_SUCCESS
) {
535 isc_boolean_t expired
, future
;
536 isc_boolean_t keep
= ISC_FALSE
, resign
= ISC_FALSE
;
538 dns_rdataset_current(&sigset
, &sigrdata
);
540 result
= dns_rdata_tostruct(&sigrdata
, &rrsig
, NULL
);
541 check_result(result
, "dns_rdata_tostruct");
543 future
= isc_serial_lt(now
, rrsig
.timesigned
);
545 key
= keythatsigned(&rrsig
);
546 sig_format(&rrsig
, sigstr
, sizeof(sigstr
));
547 if (key
!= NULL
&& issigningkey(key
))
548 expired
= isc_serial_gt(now
+ cycle
, rrsig
.timeexpire
);
550 expired
= isc_serial_gt(now
, rrsig
.timeexpire
);
552 if (isc_serial_gt(rrsig
.timesigned
, rrsig
.timeexpire
)) {
553 /* rrsig is dropped and not replaced */
554 vbprintf(2, "\trrsig by %s dropped - "
555 "invalid validity period\n",
557 } else if (key
== NULL
&& !future
&&
558 expecttofindkey(&rrsig
.signer
)) {
559 /* rrsig is dropped and not replaced */
560 vbprintf(2, "\trrsig by %s dropped - "
561 "private dnskey not found\n",
563 } else if (key
== NULL
|| future
) {
564 keep
= (!expired
&& !remove_orphansigs
);
565 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
566 keep
? "retained" : "dropped", sigstr
);
567 } else if (!dns_dnssec_keyactive(key
->key
, now
) &&
568 remove_inactkeysigs
) {
570 vbprintf(2, "\trrsig by %s dropped - key inactive\n",
572 } else if (issigningkey(key
)) {
573 wassignedby
[key
->index
] = ISC_TRUE
;
575 if (!expired
&& rrsig
.originalttl
== set
->ttl
&&
576 setverifies(name
, set
, key
->key
, &sigrdata
)) {
577 vbprintf(2, "\trrsig by %s retained\n", sigstr
);
580 vbprintf(2, "\trrsig by %s dropped - %s\n",
581 sigstr
, expired
? "expired" :
582 rrsig
.originalttl
!= set
->ttl
?
583 "ttl change" : "failed to verify");
586 } else if (!ispublishedkey(key
) && remove_orphansigs
) {
587 vbprintf(2, "\trrsig by %s dropped - dnskey removed\n",
589 } else if (iszonekey(key
)) {
590 wassignedby
[key
->index
] = ISC_TRUE
;
592 if (!expired
&& rrsig
.originalttl
== set
->ttl
&&
593 setverifies(name
, set
, key
->key
, &sigrdata
)) {
594 vbprintf(2, "\trrsig by %s retained\n", sigstr
);
597 vbprintf(2, "\trrsig by %s dropped - %s\n",
598 sigstr
, expired
? "expired" :
599 rrsig
.originalttl
!= set
->ttl
?
600 "ttl change" : "failed to verify");
602 } else if (!expired
) {
603 vbprintf(2, "\trrsig by %s retained\n", sigstr
);
606 vbprintf(2, "\trrsig by %s expired\n", sigstr
);
611 nowsignedby
[key
->index
] = ISC_TRUE
;
613 if (sigset
.ttl
!= ttl
) {
614 vbprintf(2, "\tfixing ttl %s\n", sigstr
);
616 result
= dns_difftuple_create(mctx
,
617 DNS_DIFFOP_DELRESIGN
,
620 check_result(result
, "dns_difftuple_create");
621 dns_diff_append(del
, &tuple
);
622 result
= dns_difftuple_create(mctx
,
623 DNS_DIFFOP_ADDRESIGN
,
626 check_result(result
, "dns_difftuple_create");
627 dns_diff_append(add
, &tuple
);
631 vbprintf(2, "removing signature by %s\n", sigstr
);
632 result
= dns_difftuple_create(mctx
,
633 DNS_DIFFOP_DELRESIGN
,
636 check_result(result
, "dns_difftuple_create");
637 dns_diff_append(del
, &tuple
);
644 signwithkey(name
, set
, key
->key
, ttl
, add
,
645 "resigning with dnskey");
646 nowsignedby
[key
->index
] = ISC_TRUE
;
649 dns_rdata_reset(&sigrdata
);
650 dns_rdata_freestruct(&rrsig
);
651 result
= dns_rdataset_next(&sigset
);
653 if (result
== ISC_R_NOMORE
)
654 result
= ISC_R_SUCCESS
;
656 check_result(result
, "dns_rdataset_first/next");
657 if (dns_rdataset_isassociated(&sigset
))
658 dns_rdataset_disassociate(&sigset
);
660 for (key
= ISC_LIST_HEAD(keylist
);
662 key
= ISC_LIST_NEXT(key
, link
))
664 if (nowsignedby
[key
->index
])
667 if (!issigningkey(key
))
670 if (set
->type
== dns_rdatatype_dnskey
&&
671 dns_name_equal(name
, gorigin
)) {
672 isc_boolean_t have_ksk
;
673 dns_dnsseckey_t
*tmpkey
;
675 have_ksk
= isksk(key
);
676 for (tmpkey
= ISC_LIST_HEAD(keylist
);
678 tmpkey
= ISC_LIST_NEXT(tmpkey
, link
)) {
679 if (dst_key_alg(key
->key
) !=
680 dst_key_alg(tmpkey
->key
))
682 if (REVOKE(tmpkey
->key
))
687 if (isksk(key
) || !have_ksk
||
688 (iszsk(key
) && !keyset_kskonly
))
689 signwithkey(name
, set
, key
->key
, ttl
, add
,
690 "signing with dnskey");
691 } else if (iszsk(key
)) {
692 signwithkey(name
, set
, key
->key
, ttl
, add
,
693 "signing with dnskey");
697 isc_mem_put(mctx
, wassignedby
, arraysize
* sizeof(isc_boolean_t
));
698 isc_mem_put(mctx
, nowsignedby
, arraysize
* sizeof(isc_boolean_t
));
702 unsigned char *hashbuf
;
709 hashlist_init(hashlist_t
*l
, unsigned int nodes
, unsigned int length
) {
712 l
->length
= length
+ 1;
716 l
->hashbuf
= malloc(l
->size
* l
->length
);
717 if (l
->hashbuf
== NULL
)
726 hashlist_add(hashlist_t
*l
, const unsigned char *hash
, size_t len
)
729 REQUIRE(len
<= l
->length
);
731 if (l
->entries
== l
->size
) {
732 l
->size
= l
->size
* 2 + 100;
733 l
->hashbuf
= realloc(l
->hashbuf
, l
->size
* l
->length
);
734 if (l
->hashbuf
== NULL
)
735 fatal("unable to grow hashlist: out of memory");
737 memset(l
->hashbuf
+ l
->entries
* l
->length
, 0, l
->length
);
738 memmove(l
->hashbuf
+ l
->entries
* l
->length
, hash
, len
);
743 hashlist_add_dns_name(hashlist_t
*l
, /*const*/ dns_name_t
*name
,
744 unsigned int hashalg
, unsigned int iterations
,
745 const unsigned char *salt
, size_t salt_len
,
746 isc_boolean_t speculative
)
748 char nametext
[DNS_NAME_FORMATSIZE
];
749 unsigned char hash
[NSEC3_MAX_HASH_LENGTH
+ 1];
753 len
= isc_iterated_hash(hash
, hashalg
, iterations
,
755 name
->ndata
, name
->length
);
757 dns_name_format(name
, nametext
, sizeof nametext
);
758 for (i
= 0 ; i
< len
; i
++)
759 fprintf(stderr
, "%02x", hash
[i
]);
760 fprintf(stderr
, " %s\n", nametext
);
762 hash
[len
++] = speculative
? 1 : 0;
763 hashlist_add(l
, hash
, len
);
767 hashlist_comp(const void *a
, const void *b
) {
768 return (memcmp(a
, b
, hash_length
+ 1));
772 hashlist_sort(hashlist_t
*l
) {
773 qsort(l
->hashbuf
, l
->entries
, l
->length
, hashlist_comp
);
777 hashlist_hasdup(hashlist_t
*l
) {
778 unsigned char *current
;
779 unsigned char *next
= l
->hashbuf
;
780 size_t entries
= l
->entries
;
783 * Skip initial speculative wild card hashs.
785 while (entries
> 0U && next
[l
->length
-1] != 0U) {
791 while (entries
-- > 1U) {
793 if (next
[l
->length
-1] != 0)
795 if (memcmp(current
, next
, l
->length
- 1) == 0)
802 static const unsigned char *
803 hashlist_findnext(const hashlist_t
*l
,
804 const unsigned char hash
[NSEC3_MAX_HASH_LENGTH
])
806 size_t entries
= l
->entries
;
807 const unsigned char *next
= bsearch(hash
, l
->hashbuf
, l
->entries
,
808 l
->length
, hashlist_comp
);
809 INSIST(next
!= NULL
);
812 if (next
< l
->hashbuf
+ (l
->entries
- 1) * l
->length
)
816 if (next
[l
->length
- 1] == 0)
818 } while (entries
-- > 1U);
819 INSIST(entries
!= 0U);
824 hashlist_exists(const hashlist_t
*l
,
825 const unsigned char hash
[NSEC3_MAX_HASH_LENGTH
])
827 if (bsearch(hash
, l
->hashbuf
, l
->entries
, l
->length
, hashlist_comp
))
834 addnowildcardhash(hashlist_t
*l
, /*const*/ dns_name_t
*name
,
835 unsigned int hashalg
, unsigned int iterations
,
836 const unsigned char *salt
, size_t salt_len
)
838 dns_fixedname_t fixed
;
840 dns_dbnode_t
*node
= NULL
;
842 char namestr
[DNS_NAME_FORMATSIZE
];
844 dns_fixedname_init(&fixed
);
845 wild
= dns_fixedname_name(&fixed
);
847 result
= dns_name_concatenate(dns_wildcardname
, name
, wild
, NULL
);
848 if (result
== ISC_R_NOSPACE
)
850 check_result(result
,"addnowildcardhash: dns_name_concatenate()");
852 result
= dns_db_findnode(gdb
, wild
, ISC_FALSE
, &node
);
853 if (result
== ISC_R_SUCCESS
) {
854 dns_db_detachnode(gdb
, &node
);
859 dns_name_format(wild
, namestr
, sizeof(namestr
));
860 fprintf(stderr
, "adding no-wildcardhash for %s\n", namestr
);
863 hashlist_add_dns_name(l
, wild
, hashalg
, iterations
, salt
, salt_len
,
868 opendb(const char *prefix
, dns_name_t
*name
, dns_rdataclass_t rdclass
,
871 char filename
[PATH_MAX
];
875 isc_buffer_init(&b
, filename
, sizeof(filename
));
877 /* allow room for a trailing slash */
878 if (strlen(dsdir
) >= isc_buffer_availablelength(&b
))
879 fatal("path '%s' is too long", dsdir
);
880 isc_buffer_putstr(&b
, dsdir
);
881 if (dsdir
[strlen(dsdir
) - 1] != '/')
882 isc_buffer_putstr(&b
, "/");
884 if (strlen(prefix
) > isc_buffer_availablelength(&b
))
885 fatal("path '%s' is too long", dsdir
);
886 isc_buffer_putstr(&b
, prefix
);
887 result
= dns_name_tofilenametext(name
, ISC_FALSE
, &b
);
888 check_result(result
, "dns_name_tofilenametext()");
889 if (isc_buffer_availablelength(&b
) == 0) {
890 char namestr
[DNS_NAME_FORMATSIZE
];
891 dns_name_format(name
, namestr
, sizeof(namestr
));
892 fatal("name '%s' is too long", namestr
);
894 isc_buffer_putuint8(&b
, 0);
896 result
= dns_db_create(mctx
, "rbt", dns_rootname
, dns_dbtype_zone
,
897 rdclass
, 0, NULL
, dbp
);
898 check_result(result
, "dns_db_create()");
900 result
= dns_db_load3(*dbp
, filename
, inputformat
, DNS_MASTER_HINT
);
901 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_SEENINCLUDE
)
906 * Load the DS set for a child zone, if a dsset-* file can be found.
907 * If not, try to find a keyset-* file from an earlier version of
908 * dnssec-signzone, and build DS records from that.
911 loadds(dns_name_t
*name
, isc_uint32_t ttl
, dns_rdataset_t
*dsset
) {
913 dns_dbversion_t
*ver
= NULL
;
914 dns_dbnode_t
*node
= NULL
;
916 dns_rdataset_t keyset
;
918 unsigned char dsbuf
[DNS_DS_BUFFERSIZE
];
920 dns_difftuple_t
*tuple
= NULL
;
922 opendb("dsset-", name
, gclass
, &db
);
924 result
= dns_db_findnode(db
, name
, ISC_FALSE
, &node
);
925 if (result
== ISC_R_SUCCESS
) {
926 dns_rdataset_init(dsset
);
927 result
= dns_db_findrdataset(db
, node
, NULL
,
928 dns_rdatatype_ds
, 0, 0,
930 dns_db_detachnode(db
, &node
);
931 if (result
== ISC_R_SUCCESS
) {
932 vbprintf(2, "found DS records\n");
941 /* No DS records found; try again, looking for DNSKEY records */
942 opendb("keyset-", name
, gclass
, &db
);
944 return (ISC_R_NOTFOUND
);
947 result
= dns_db_findnode(db
, name
, ISC_FALSE
, &node
);
948 if (result
!= ISC_R_SUCCESS
) {
953 dns_rdataset_init(&keyset
);
954 result
= dns_db_findrdataset(db
, node
, NULL
, dns_rdatatype_dnskey
, 0, 0,
956 if (result
!= ISC_R_SUCCESS
) {
957 dns_db_detachnode(db
, &node
);
961 vbprintf(2, "found DNSKEY records\n");
963 result
= dns_db_newversion(db
, &ver
);
964 check_result(result
, "dns_db_newversion");
965 dns_diff_init(mctx
, &diff
);
967 for (result
= dns_rdataset_first(&keyset
);
968 result
== ISC_R_SUCCESS
;
969 result
= dns_rdataset_next(&keyset
))
971 dns_rdata_init(&key
);
973 dns_rdataset_current(&keyset
, &key
);
974 result
= dns_ds_buildrdata(name
, &key
, DNS_DSDIGEST_SHA1
,
976 check_result(result
, "dns_ds_buildrdata");
978 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADDRESIGN
, name
,
980 check_result(result
, "dns_difftuple_create");
981 dns_diff_append(&diff
, &tuple
);
983 dns_rdata_reset(&ds
);
984 result
= dns_ds_buildrdata(name
, &key
, DNS_DSDIGEST_SHA256
,
986 check_result(result
, "dns_ds_buildrdata");
988 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADDRESIGN
, name
,
990 check_result(result
, "dns_difftuple_create");
991 dns_diff_append(&diff
, &tuple
);
994 result
= dns_diff_apply(&diff
, db
, ver
);
995 check_result(result
, "dns_diff_apply");
996 dns_diff_clear(&diff
);
998 dns_db_closeversion(db
, &ver
, ISC_TRUE
);
1000 result
= dns_db_findrdataset(db
, node
, NULL
, dns_rdatatype_ds
, 0, 0,
1002 check_result(result
, "dns_db_findrdataset");
1004 dns_rdataset_disassociate(&keyset
);
1005 dns_db_detachnode(db
, &node
);
1010 static isc_boolean_t
1011 secure(dns_name_t
*name
, dns_dbnode_t
*node
) {
1012 dns_rdataset_t dsset
;
1013 isc_result_t result
;
1015 if (dns_name_equal(name
, gorigin
))
1018 dns_rdataset_init(&dsset
);
1019 result
= dns_db_findrdataset(gdb
, node
, gversion
, dns_rdatatype_ds
,
1020 0, 0, &dsset
, NULL
);
1021 if (dns_rdataset_isassociated(&dsset
))
1022 dns_rdataset_disassociate(&dsset
);
1024 return (ISC_TF(result
== ISC_R_SUCCESS
));
1028 * Signs all records at a name.
1031 signname(dns_dbnode_t
*node
, dns_name_t
*name
) {
1032 isc_result_t result
;
1033 dns_rdataset_t rdataset
;
1034 dns_rdatasetiter_t
*rdsiter
;
1035 isc_boolean_t isdelegation
= ISC_FALSE
;
1036 dns_diff_t del
, add
;
1037 char namestr
[DNS_NAME_FORMATSIZE
];
1039 dns_rdataset_init(&rdataset
);
1040 dns_name_format(name
, namestr
, sizeof(namestr
));
1043 * Determine if this is a delegation point.
1045 if (is_delegation(gdb
, gversion
, gorigin
, name
, node
, NULL
))
1046 isdelegation
= ISC_TRUE
;
1049 * Now iterate through the rdatasets.
1051 dns_diff_init(mctx
, &del
);
1052 dns_diff_init(mctx
, &add
);
1054 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
1055 check_result(result
, "dns_db_allrdatasets()");
1056 result
= dns_rdatasetiter_first(rdsiter
);
1057 while (result
== ISC_R_SUCCESS
) {
1058 dns_rdatasetiter_current(rdsiter
, &rdataset
);
1060 /* If this is a RRSIG set, skip it. */
1061 if (rdataset
.type
== dns_rdatatype_rrsig
)
1065 * If this name is a delegation point, skip all records
1066 * except NSEC and DS sets. Otherwise check that there
1067 * isn't a DS record.
1070 if (rdataset
.type
!= nsec_datatype
&&
1071 rdataset
.type
!= dns_rdatatype_ds
)
1073 } else if (rdataset
.type
== dns_rdatatype_ds
) {
1074 char namebuf
[DNS_NAME_FORMATSIZE
];
1075 dns_name_format(name
, namebuf
, sizeof(namebuf
));
1076 fatal("'%s': found DS RRset without NS RRset\n",
1080 signset(&del
, &add
, node
, name
, &rdataset
);
1083 dns_rdataset_disassociate(&rdataset
);
1084 result
= dns_rdatasetiter_next(rdsiter
);
1086 if (result
!= ISC_R_NOMORE
)
1087 fatal("rdataset iteration for name '%s' failed: %s",
1088 namestr
, isc_result_totext(result
));
1090 dns_rdatasetiter_destroy(&rdsiter
);
1092 result
= dns_diff_applysilently(&del
, gdb
, gversion
);
1093 if (result
!= ISC_R_SUCCESS
)
1094 fatal("failed to delete SIGs at node '%s': %s",
1095 namestr
, isc_result_totext(result
));
1097 result
= dns_diff_applysilently(&add
, gdb
, gversion
);
1098 if (result
!= ISC_R_SUCCESS
)
1099 fatal("failed to add SIGs at node '%s': %s",
1100 namestr
, isc_result_totext(result
));
1102 dns_diff_clear(&del
);
1103 dns_diff_clear(&add
);
1106 static inline isc_boolean_t
1107 active_node(dns_dbnode_t
*node
) {
1108 dns_rdatasetiter_t
*rdsiter
= NULL
;
1109 dns_rdatasetiter_t
*rdsiter2
= NULL
;
1110 isc_boolean_t active
= ISC_FALSE
;
1111 isc_result_t result
;
1112 dns_rdataset_t rdataset
;
1113 dns_rdatatype_t type
;
1114 dns_rdatatype_t covers
;
1115 isc_boolean_t found
;
1117 dns_rdataset_init(&rdataset
);
1118 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
1119 check_result(result
, "dns_db_allrdatasets()");
1120 result
= dns_rdatasetiter_first(rdsiter
);
1121 while (result
== ISC_R_SUCCESS
) {
1122 dns_rdatasetiter_current(rdsiter
, &rdataset
);
1123 if (rdataset
.type
!= dns_rdatatype_nsec
&&
1124 rdataset
.type
!= dns_rdatatype_nsec3
&&
1125 rdataset
.type
!= dns_rdatatype_rrsig
)
1127 dns_rdataset_disassociate(&rdataset
);
1129 result
= dns_rdatasetiter_next(rdsiter
);
1131 result
= ISC_R_NOMORE
;
1133 if (result
!= ISC_R_NOMORE
)
1134 fatal("rdataset iteration failed: %s",
1135 isc_result_totext(result
));
1137 if (!active
&& nsec_datatype
== dns_rdatatype_nsec
) {
1139 * The node is empty of everything but NSEC / RRSIG records.
1141 for (result
= dns_rdatasetiter_first(rdsiter
);
1142 result
== ISC_R_SUCCESS
;
1143 result
= dns_rdatasetiter_next(rdsiter
)) {
1144 dns_rdatasetiter_current(rdsiter
, &rdataset
);
1145 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1148 check_result(result
, "dns_db_deleterdataset()");
1149 dns_rdataset_disassociate(&rdataset
);
1151 if (result
!= ISC_R_NOMORE
)
1152 fatal("rdataset iteration failed: %s",
1153 isc_result_totext(result
));
1156 * Delete RRSIGs for types that no longer exist.
1158 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter2
);
1159 check_result(result
, "dns_db_allrdatasets()");
1160 for (result
= dns_rdatasetiter_first(rdsiter
);
1161 result
== ISC_R_SUCCESS
;
1162 result
= dns_rdatasetiter_next(rdsiter
)) {
1163 dns_rdatasetiter_current(rdsiter
, &rdataset
);
1164 type
= rdataset
.type
;
1165 covers
= rdataset
.covers
;
1166 dns_rdataset_disassociate(&rdataset
);
1168 * Delete the NSEC chain if we are signing with
1171 if (nsec_datatype
== dns_rdatatype_nsec3
&&
1172 (type
== dns_rdatatype_nsec
||
1173 covers
== dns_rdatatype_nsec
)) {
1174 result
= dns_db_deleterdataset(gdb
, node
,
1177 check_result(result
,
1178 "dns_db_deleterdataset(nsec/rrsig)");
1181 if (type
!= dns_rdatatype_rrsig
)
1184 for (result
= dns_rdatasetiter_first(rdsiter2
);
1185 !found
&& result
== ISC_R_SUCCESS
;
1186 result
= dns_rdatasetiter_next(rdsiter2
)) {
1187 dns_rdatasetiter_current(rdsiter2
, &rdataset
);
1188 if (rdataset
.type
== covers
)
1190 dns_rdataset_disassociate(&rdataset
);
1193 if (result
!= ISC_R_NOMORE
)
1194 fatal("rdataset iteration failed: %s",
1195 isc_result_totext(result
));
1196 result
= dns_db_deleterdataset(gdb
, node
,
1199 check_result(result
,
1200 "dns_db_deleterdataset(rrsig)");
1201 } else if (result
!= ISC_R_NOMORE
&&
1202 result
!= ISC_R_SUCCESS
)
1203 fatal("rdataset iteration failed: %s",
1204 isc_result_totext(result
));
1206 if (result
!= ISC_R_NOMORE
)
1207 fatal("rdataset iteration failed: %s",
1208 isc_result_totext(result
));
1209 dns_rdatasetiter_destroy(&rdsiter2
);
1211 dns_rdatasetiter_destroy(&rdsiter
);
1217 * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
1220 get_soa_ttls(void) {
1221 dns_rdataset_t soaset
;
1222 dns_fixedname_t fname
;
1224 isc_result_t result
;
1225 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1227 dns_fixedname_init(&fname
);
1228 name
= dns_fixedname_name(&fname
);
1229 dns_rdataset_init(&soaset
);
1230 result
= dns_db_find(gdb
, gorigin
, gversion
, dns_rdatatype_soa
,
1231 0, 0, NULL
, name
, &soaset
, NULL
);
1232 if (result
!= ISC_R_SUCCESS
)
1233 fatal("failed to find an SOA at the zone apex: %s",
1234 isc_result_totext(result
));
1236 result
= dns_rdataset_first(&soaset
);
1237 check_result(result
, "dns_rdataset_first");
1238 dns_rdataset_current(&soaset
, &rdata
);
1239 zone_soa_min_ttl
= dns_soa_getminimum(&rdata
);
1240 soa_ttl
= soaset
.ttl
;
1242 zone_soa_min_ttl
= ISC_MIN(zone_soa_min_ttl
, maxttl
);
1243 soa_ttl
= ISC_MIN(soa_ttl
, maxttl
);
1245 dns_rdataset_disassociate(&soaset
);
1249 * Increment (or set if nonzero) the SOA serial
1252 setsoaserial(isc_uint32_t serial
) {
1253 isc_result_t result
;
1254 dns_dbnode_t
*node
= NULL
;
1255 dns_rdataset_t rdataset
;
1256 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1257 isc_uint32_t old_serial
, new_serial
;
1259 result
= dns_db_getoriginnode(gdb
, &node
);
1260 if (result
!= ISC_R_SUCCESS
)
1263 dns_rdataset_init(&rdataset
);
1265 result
= dns_db_findrdataset(gdb
, node
, gversion
,
1266 dns_rdatatype_soa
, 0,
1267 0, &rdataset
, NULL
);
1268 if (result
!= ISC_R_SUCCESS
)
1271 result
= dns_rdataset_first(&rdataset
);
1272 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1274 dns_rdataset_current(&rdataset
, &rdata
);
1276 old_serial
= dns_soa_getserial(&rdata
);
1279 /* Set SOA serial to the value provided. */
1280 new_serial
= serial
;
1282 /* Increment SOA serial using RFC 1982 arithmetics */
1283 new_serial
= (old_serial
+ 1) & 0xFFFFFFFF;
1284 if (new_serial
== 0)
1288 /* If the new serial is not likely to cause a zone transfer
1289 * (a/ixfr) from servers having the old serial, warn the user.
1291 * RFC1982 section 7 defines the maximum increment to be
1292 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1293 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1295 if (new_serial
== old_serial
||
1296 (new_serial
- old_serial
) > 0x7fffffffU
)
1297 fprintf(stderr
, "%s: warning: Serial number not advanced, "
1298 "zone may not transfer\n", program
);
1300 dns_soa_setserial(new_serial
, &rdata
);
1302 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1303 dns_rdatatype_soa
, 0);
1304 check_result(result
, "dns_db_deleterdataset");
1305 if (result
!= ISC_R_SUCCESS
)
1308 result
= dns_db_addrdataset(gdb
, node
, gversion
,
1309 0, &rdataset
, 0, NULL
);
1310 check_result(result
, "dns_db_addrdataset");
1311 if (result
!= ISC_R_SUCCESS
)
1315 dns_rdataset_disassociate(&rdataset
);
1317 dns_db_detachnode(gdb
, &node
);
1318 dns_rdata_reset(&rdata
);
1324 * Delete any RRSIG records at a node.
1327 cleannode(dns_db_t
*db
, dns_dbversion_t
*version
, dns_dbnode_t
*node
) {
1328 dns_rdatasetiter_t
*rdsiter
= NULL
;
1330 isc_result_t result
, dresult
;
1332 if (outputformat
!= dns_masterformat_text
|| !disable_zone_check
)
1335 dns_rdataset_init(&set
);
1336 result
= dns_db_allrdatasets(db
, node
, version
, 0, &rdsiter
);
1337 check_result(result
, "dns_db_allrdatasets");
1338 result
= dns_rdatasetiter_first(rdsiter
);
1339 while (result
== ISC_R_SUCCESS
) {
1340 isc_boolean_t destroy
= ISC_FALSE
;
1341 dns_rdatatype_t covers
= 0;
1342 dns_rdatasetiter_current(rdsiter
, &set
);
1343 if (set
.type
== dns_rdatatype_rrsig
) {
1344 covers
= set
.covers
;
1347 dns_rdataset_disassociate(&set
);
1348 result
= dns_rdatasetiter_next(rdsiter
);
1350 dresult
= dns_db_deleterdataset(db
, node
, version
,
1351 dns_rdatatype_rrsig
,
1353 check_result(dresult
, "dns_db_deleterdataset");
1356 if (result
!= ISC_R_NOMORE
)
1357 fatal("rdataset iteration failed: %s",
1358 isc_result_totext(result
));
1359 dns_rdatasetiter_destroy(&rdsiter
);
1363 * Set up the iterator and global state before starting the tasks.
1367 isc_result_t result
;
1370 result
= dns_db_createiterator(gdb
, 0, &gdbiter
);
1371 check_result(result
, "dns_db_createiterator()");
1375 * Clean up the iterator and global state after the tasks complete.
1379 dns_dbiterator_destroy(&gdbiter
);
1383 * Sign the apex of the zone.
1384 * Note the origin may not be the first node if there are out of zone
1389 dns_dbnode_t
*node
= NULL
;
1390 dns_fixedname_t fixed
;
1392 isc_result_t result
;
1394 dns_fixedname_init(&fixed
);
1395 name
= dns_fixedname_name(&fixed
);
1396 result
= dns_dbiterator_seek(gdbiter
, gorigin
);
1397 check_result(result
, "dns_dbiterator_seek()");
1398 result
= dns_dbiterator_current(gdbiter
, &node
, name
);
1399 check_dns_dbiterator_current(result
);
1400 signname(node
, name
);
1401 dumpnode(name
, node
);
1402 cleannode(gdb
, gversion
, node
);
1403 dns_db_detachnode(gdb
, &node
);
1404 result
= dns_dbiterator_first(gdbiter
);
1405 if (result
== ISC_R_NOMORE
)
1406 finished
= ISC_TRUE
;
1407 else if (result
!= ISC_R_SUCCESS
)
1408 fatal("failure iterating database: %s",
1409 isc_result_totext(result
));
1413 * Assigns a node to a worker thread. This is protected by the master task's
1417 assignwork(isc_task_t
*task
, isc_task_t
*worker
) {
1418 dns_fixedname_t
*fname
;
1422 dns_rdataset_t nsec
;
1423 isc_boolean_t found
;
1424 isc_result_t result
;
1425 static dns_name_t
*zonecut
= NULL
; /* Protected by namelock. */
1426 static dns_fixedname_t fzonecut
; /* Protected by namelock. */
1427 static unsigned int ended
= 0; /* Protected by namelock. */
1435 if (ended
== ntasks
) {
1436 isc_task_detach(&task
);
1442 fname
= isc_mem_get(mctx
, sizeof(dns_fixedname_t
));
1444 fatal("out of memory");
1445 dns_fixedname_init(fname
);
1446 name
= dns_fixedname_name(fname
);
1450 result
= dns_dbiterator_current(gdbiter
, &node
, name
);
1451 check_dns_dbiterator_current(result
);
1453 * The origin was handled by signapex().
1455 if (dns_name_equal(name
, gorigin
)) {
1456 dns_db_detachnode(gdb
, &node
);
1460 * Sort the zone data from the glue and out-of-zone data.
1461 * For NSEC zones nodes with zone data have NSEC records.
1462 * For NSEC3 zones the NSEC3 nodes are zone data but
1463 * outside of the zone name space. For the rest we need
1464 * to track the bottom of zone cuts.
1465 * Nodes which don't need to be signed are dumped here.
1467 dns_rdataset_init(&nsec
);
1468 result
= dns_db_findrdataset(gdb
, node
, gversion
,
1469 nsec_datatype
, 0, 0,
1471 if (dns_rdataset_isassociated(&nsec
))
1472 dns_rdataset_disassociate(&nsec
);
1473 if (result
== ISC_R_SUCCESS
) {
1475 } else if (nsec_datatype
== dns_rdatatype_nsec3
) {
1476 if (dns_name_issubdomain(name
, gorigin
) &&
1478 !dns_name_issubdomain(name
, zonecut
))) {
1479 if (is_delegation(gdb
, gversion
, gorigin
, name
, node
, NULL
)) {
1480 dns_fixedname_init(&fzonecut
);
1481 zonecut
= dns_fixedname_name(&fzonecut
);
1482 dns_name_copy(name
, zonecut
, NULL
);
1483 if (!OPTOUT(nsec3flags
) ||
1492 dumpnode(name
, node
);
1493 dns_db_detachnode(gdb
, &node
);
1497 result
= dns_dbiterator_next(gdbiter
);
1498 if (result
== ISC_R_NOMORE
) {
1499 finished
= ISC_TRUE
;
1501 } else if (result
!= ISC_R_SUCCESS
)
1502 fatal("failure iterating database: %s",
1503 isc_result_totext(result
));
1507 if (ended
== ntasks
) {
1508 isc_task_detach(&task
);
1511 isc_mem_put(mctx
, fname
, sizeof(dns_fixedname_t
));
1514 sevent
= (sevent_t
*)
1515 isc_event_allocate(mctx
, task
, SIGNER_EVENT_WORK
,
1516 sign
, NULL
, sizeof(sevent_t
));
1518 fatal("failed to allocate event\n");
1520 sevent
->node
= node
;
1521 sevent
->fname
= fname
;
1522 isc_task_send(worker
, ISC_EVENT_PTR(&sevent
));
1528 * Start a worker task
1531 startworker(isc_task_t
*task
, isc_event_t
*event
) {
1534 worker
= (isc_task_t
*)event
->ev_arg
;
1535 assignwork(task
, worker
);
1536 isc_event_free(&event
);
1540 * Write a node to the output file, and restart the worker task.
1543 writenode(isc_task_t
*task
, isc_event_t
*event
) {
1545 sevent_t
*sevent
= (sevent_t
*)event
;
1547 worker
= (isc_task_t
*)event
->ev_sender
;
1548 dumpnode(dns_fixedname_name(sevent
->fname
), sevent
->node
);
1549 cleannode(gdb
, gversion
, sevent
->node
);
1550 dns_db_detachnode(gdb
, &sevent
->node
);
1551 isc_mem_put(mctx
, sevent
->fname
, sizeof(dns_fixedname_t
));
1552 assignwork(task
, worker
);
1553 isc_event_free(&event
);
1557 * Sign a database node.
1560 sign(isc_task_t
*task
, isc_event_t
*event
) {
1561 dns_fixedname_t
*fname
;
1563 sevent_t
*sevent
, *wevent
;
1565 sevent
= (sevent_t
*)event
;
1566 node
= sevent
->node
;
1567 fname
= sevent
->fname
;
1568 isc_event_free(&event
);
1570 signname(node
, dns_fixedname_name(fname
));
1571 wevent
= (sevent_t
*)
1572 isc_event_allocate(mctx
, task
, SIGNER_EVENT_WRITE
,
1573 writenode
, NULL
, sizeof(sevent_t
));
1575 fatal("failed to allocate event\n");
1576 wevent
->node
= node
;
1577 wevent
->fname
= fname
;
1578 isc_task_send(master
, ISC_EVENT_PTR(&wevent
));
1582 * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
1585 add_ds(dns_name_t
*name
, dns_dbnode_t
*node
, isc_uint32_t nsttl
) {
1586 dns_rdataset_t dsset
;
1587 dns_rdataset_t sigdsset
;
1588 isc_result_t result
;
1590 dns_rdataset_init(&dsset
);
1591 dns_rdataset_init(&sigdsset
);
1592 result
= dns_db_findrdataset(gdb
, node
, gversion
,
1594 0, 0, &dsset
, &sigdsset
);
1595 if (result
== ISC_R_SUCCESS
) {
1596 dns_rdataset_disassociate(&dsset
);
1597 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1598 dns_rdatatype_ds
, 0);
1599 check_result(result
, "dns_db_deleterdataset");
1602 result
= loadds(name
, nsttl
, &dsset
);
1603 if (result
== ISC_R_SUCCESS
) {
1604 result
= dns_db_addrdataset(gdb
, node
, gversion
, 0,
1606 check_result(result
, "dns_db_addrdataset");
1607 dns_rdataset_disassociate(&dsset
);
1608 if (dns_rdataset_isassociated(&sigdsset
))
1609 dns_rdataset_disassociate(&sigdsset
);
1610 } else if (dns_rdataset_isassociated(&sigdsset
)) {
1611 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1612 dns_rdatatype_rrsig
,
1614 check_result(result
, "dns_db_deleterdataset");
1615 dns_rdataset_disassociate(&sigdsset
);
1620 * Remove records of the given type and their signatures.
1623 remove_records(dns_dbnode_t
*node
, dns_rdatatype_t which
,
1624 isc_boolean_t checknsec
)
1626 isc_result_t result
;
1627 dns_rdatatype_t type
, covers
;
1628 dns_rdatasetiter_t
*rdsiter
= NULL
;
1629 dns_rdataset_t rdataset
;
1631 dns_rdataset_init(&rdataset
);
1634 * Delete any records of the given type at the apex.
1636 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
1637 check_result(result
, "dns_db_allrdatasets()");
1638 for (result
= dns_rdatasetiter_first(rdsiter
);
1639 result
== ISC_R_SUCCESS
;
1640 result
= dns_rdatasetiter_next(rdsiter
)) {
1641 dns_rdatasetiter_current(rdsiter
, &rdataset
);
1642 type
= rdataset
.type
;
1643 covers
= rdataset
.covers
;
1644 dns_rdataset_disassociate(&rdataset
);
1645 if (type
== which
|| covers
== which
) {
1646 if (which
== dns_rdatatype_nsec
&&
1647 checknsec
&& !update_chain
)
1648 fatal("Zone contains NSEC records. Use -u "
1649 "to update to NSEC3.");
1650 if (which
== dns_rdatatype_nsec3param
&&
1651 checknsec
&& !update_chain
)
1652 fatal("Zone contains NSEC3 chains. Use -u "
1653 "to update to NSEC.");
1654 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1656 check_result(result
, "dns_db_deleterdataset()");
1660 dns_rdatasetiter_destroy(&rdsiter
);
1664 * Remove signatures covering the given type. If type == 0,
1665 * then remove all signatures, unless this is a delegation, in
1666 * which case remove all signatures except for DS or nsec_datatype
1669 remove_sigs(dns_dbnode_t
*node
, isc_boolean_t delegation
,
1670 dns_rdatatype_t which
)
1672 isc_result_t result
;
1673 dns_rdatatype_t type
, covers
;
1674 dns_rdatasetiter_t
*rdsiter
= NULL
;
1675 dns_rdataset_t rdataset
;
1677 dns_rdataset_init(&rdataset
);
1678 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
1679 check_result(result
, "dns_db_allrdatasets()");
1680 for (result
= dns_rdatasetiter_first(rdsiter
);
1681 result
== ISC_R_SUCCESS
;
1682 result
= dns_rdatasetiter_next(rdsiter
)) {
1683 dns_rdatasetiter_current(rdsiter
, &rdataset
);
1684 type
= rdataset
.type
;
1685 covers
= rdataset
.covers
;
1686 dns_rdataset_disassociate(&rdataset
);
1688 if (type
!= dns_rdatatype_rrsig
)
1691 if (which
== 0 && delegation
&&
1692 (dns_rdatatype_atparent(covers
) ||
1693 (nsec_datatype
== dns_rdatatype_nsec
&&
1694 covers
== nsec_datatype
)))
1697 if (which
!= 0 && covers
!= which
)
1700 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1702 check_result(result
, "dns_db_deleterdataset()");
1704 dns_rdatasetiter_destroy(&rdsiter
);
1708 * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
1712 dns_dbiterator_t
*dbiter
= NULL
;
1713 dns_dbnode_t
*node
= NULL
, *nextnode
= NULL
;
1714 dns_fixedname_t fname
, fnextname
, fzonecut
;
1715 dns_name_t
*name
, *nextname
, *zonecut
;
1716 dns_rdataset_t rdataset
;
1717 dns_rdatasetiter_t
*rdsiter
= NULL
;
1718 dns_rdatatype_t type
, covers
;
1719 isc_boolean_t done
= ISC_FALSE
;
1720 isc_result_t result
;
1721 isc_uint32_t nsttl
= 0;
1723 dns_rdataset_init(&rdataset
);
1724 dns_fixedname_init(&fname
);
1725 name
= dns_fixedname_name(&fname
);
1726 dns_fixedname_init(&fnextname
);
1727 nextname
= dns_fixedname_name(&fnextname
);
1728 dns_fixedname_init(&fzonecut
);
1732 * Remove any NSEC3 chains.
1734 result
= dns_db_createiterator(gdb
, DNS_DB_NSEC3ONLY
, &dbiter
);
1735 check_result(result
, "dns_db_createiterator()");
1736 for (result
= dns_dbiterator_first(dbiter
);
1737 result
== ISC_R_SUCCESS
;
1738 result
= dns_dbiterator_next(dbiter
)) {
1739 result
= dns_dbiterator_current(dbiter
, &node
, name
);
1740 check_dns_dbiterator_current(result
);
1741 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
1742 check_result(result
, "dns_db_allrdatasets()");
1743 for (result
= dns_rdatasetiter_first(rdsiter
);
1744 result
== ISC_R_SUCCESS
;
1745 result
= dns_rdatasetiter_next(rdsiter
)) {
1746 dns_rdatasetiter_current(rdsiter
, &rdataset
);
1747 type
= rdataset
.type
;
1748 covers
= rdataset
.covers
;
1749 dns_rdataset_disassociate(&rdataset
);
1750 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1752 check_result(result
,
1753 "dns_db_deleterdataset(nsec3param/rrsig)");
1755 dns_rdatasetiter_destroy(&rdsiter
);
1756 dns_db_detachnode(gdb
, &node
);
1758 dns_dbiterator_destroy(&dbiter
);
1760 result
= dns_db_createiterator(gdb
, DNS_DB_NONSEC3
, &dbiter
);
1761 check_result(result
, "dns_db_createiterator()");
1763 result
= dns_dbiterator_first(dbiter
);
1764 check_result(result
, "dns_dbiterator_first()");
1767 result
= dns_dbiterator_current(dbiter
, &node
, name
);
1768 check_dns_dbiterator_current(result
);
1770 * Skip out-of-zone records.
1772 if (!dns_name_issubdomain(name
, gorigin
)) {
1773 result
= dns_dbiterator_next(dbiter
);
1774 if (result
== ISC_R_NOMORE
)
1777 check_result(result
, "dns_dbiterator_next()");
1778 dns_db_detachnode(gdb
, &node
);
1782 if (dns_name_equal(name
, gorigin
))
1783 remove_records(node
, dns_rdatatype_nsec3param
,
1786 if (is_delegation(gdb
, gversion
, gorigin
, name
, node
, &nsttl
)) {
1787 zonecut
= dns_fixedname_name(&fzonecut
);
1788 dns_name_copy(name
, zonecut
, NULL
);
1789 remove_sigs(node
, ISC_TRUE
, 0);
1791 add_ds(name
, node
, nsttl
);
1794 result
= dns_dbiterator_next(dbiter
);
1796 while (result
== ISC_R_SUCCESS
) {
1797 isc_boolean_t active
= ISC_FALSE
;
1798 result
= dns_dbiterator_current(dbiter
, &nextnode
,
1800 check_dns_dbiterator_current(result
);
1801 active
= active_node(nextnode
);
1803 dns_db_detachnode(gdb
, &nextnode
);
1804 result
= dns_dbiterator_next(dbiter
);
1807 if (!dns_name_issubdomain(nextname
, gorigin
) ||
1809 dns_name_issubdomain(nextname
, zonecut
)))
1811 remove_sigs(nextnode
, ISC_FALSE
, 0);
1812 remove_records(nextnode
, dns_rdatatype_nsec
,
1814 dns_db_detachnode(gdb
, &nextnode
);
1815 result
= dns_dbiterator_next(dbiter
);
1818 dns_db_detachnode(gdb
, &nextnode
);
1821 if (result
== ISC_R_NOMORE
) {
1822 dns_name_clone(gorigin
, nextname
);
1824 } else if (result
!= ISC_R_SUCCESS
)
1825 fatal("iterating through the database failed: %s",
1826 isc_result_totext(result
));
1827 dns_dbiterator_pause(dbiter
);
1828 result
= dns_nsec_build(gdb
, gversion
, node
, nextname
,
1830 check_result(result
, "dns_nsec_build()");
1831 dns_db_detachnode(gdb
, &node
);
1834 dns_dbiterator_destroy(&dbiter
);
1838 addnsec3param(const unsigned char *salt
, size_t salt_len
,
1839 dns_iterations_t iterations
)
1841 dns_dbnode_t
*node
= NULL
;
1842 dns_rdata_nsec3param_t nsec3param
;
1843 unsigned char nsec3parambuf
[5 + 255];
1844 dns_rdatalist_t rdatalist
;
1845 dns_rdataset_t rdataset
;
1846 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1848 isc_result_t result
;
1850 dns_rdataset_init(&rdataset
);
1852 nsec3param
.common
.rdclass
= gclass
;
1853 nsec3param
.common
.rdtype
= dns_rdatatype_nsec3param
;
1854 ISC_LINK_INIT(&nsec3param
.common
, link
);
1855 nsec3param
.mctx
= NULL
;
1856 nsec3param
.flags
= 0;
1857 nsec3param
.hash
= unknownalg
? DNS_NSEC3_UNKNOWNALG
: dns_hash_sha1
;
1858 nsec3param
.iterations
= iterations
;
1859 nsec3param
.salt_length
= (unsigned char)salt_len
;
1860 DE_CONST(salt
, nsec3param
.salt
);
1862 isc_buffer_init(&b
, nsec3parambuf
, sizeof(nsec3parambuf
));
1863 result
= dns_rdata_fromstruct(&rdata
, gclass
,
1864 dns_rdatatype_nsec3param
,
1866 check_result(result
, "dns_rdata_fromstruct()");
1867 rdatalist
.rdclass
= rdata
.rdclass
;
1868 rdatalist
.type
= rdata
.type
;
1869 rdatalist
.covers
= 0;
1871 ISC_LIST_INIT(rdatalist
.rdata
);
1872 ISC_LIST_APPEND(rdatalist
.rdata
, &rdata
, link
);
1873 result
= dns_rdatalist_tordataset(&rdatalist
, &rdataset
);
1874 check_result(result
, "dns_rdatalist_tordataset()");
1876 result
= dns_db_findnode(gdb
, gorigin
, ISC_TRUE
, &node
);
1877 check_result(result
, "dns_db_find(gorigin)");
1880 * Delete any current NSEC3PARAM records.
1882 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1883 dns_rdatatype_nsec3param
, 0);
1884 if (result
== DNS_R_UNCHANGED
)
1885 result
= ISC_R_SUCCESS
;
1886 check_result(result
, "dddnsec3param: dns_db_deleterdataset()");
1888 result
= dns_db_addrdataset(gdb
, node
, gversion
, 0, &rdataset
,
1889 DNS_DBADD_MERGE
, NULL
);
1890 if (result
== DNS_R_UNCHANGED
)
1891 result
= ISC_R_SUCCESS
;
1892 check_result(result
, "addnsec3param: dns_db_addrdataset()");
1893 dns_db_detachnode(gdb
, &node
);
1897 addnsec3(dns_name_t
*name
, dns_dbnode_t
*node
,
1898 const unsigned char *salt
, size_t salt_len
,
1899 unsigned int iterations
, hashlist_t
*hashlist
,
1902 unsigned char hash
[NSEC3_MAX_HASH_LENGTH
];
1903 const unsigned char *nexthash
;
1904 unsigned char nsec3buffer
[DNS_NSEC3_BUFFERSIZE
];
1905 dns_fixedname_t hashname
;
1906 dns_rdatalist_t rdatalist
;
1907 dns_rdataset_t rdataset
;
1908 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1909 isc_result_t result
;
1910 dns_dbnode_t
*nsec3node
= NULL
;
1911 char namebuf
[DNS_NAME_FORMATSIZE
];
1914 dns_name_format(name
, namebuf
, sizeof(namebuf
));
1916 dns_fixedname_init(&hashname
);
1917 dns_rdataset_init(&rdataset
);
1919 dns_name_downcase(name
, name
, NULL
);
1920 result
= dns_nsec3_hashname(&hashname
, hash
, &hash_len
,
1921 name
, gorigin
, dns_hash_sha1
, iterations
,
1923 check_result(result
, "addnsec3: dns_nsec3_hashname()");
1924 nexthash
= hashlist_findnext(hashlist
, hash
);
1925 result
= dns_nsec3_buildrdata(gdb
, gversion
, node
,
1927 DNS_NSEC3_UNKNOWNALG
: dns_hash_sha1
,
1928 nsec3flags
, iterations
,
1930 nexthash
, ISC_SHA1_DIGESTLENGTH
,
1931 nsec3buffer
, &rdata
);
1932 check_result(result
, "addnsec3: dns_nsec3_buildrdata()");
1933 rdatalist
.rdclass
= rdata
.rdclass
;
1934 rdatalist
.type
= rdata
.type
;
1935 rdatalist
.covers
= 0;
1936 rdatalist
.ttl
= ttl
;
1937 ISC_LIST_INIT(rdatalist
.rdata
);
1938 ISC_LIST_APPEND(rdatalist
.rdata
, &rdata
, link
);
1939 result
= dns_rdatalist_tordataset(&rdatalist
, &rdataset
);
1940 check_result(result
, "dns_rdatalist_tordataset()");
1941 result
= dns_db_findnsec3node(gdb
, dns_fixedname_name(&hashname
),
1942 ISC_TRUE
, &nsec3node
);
1943 check_result(result
, "addnsec3: dns_db_findnode()");
1944 result
= dns_db_addrdataset(gdb
, nsec3node
, gversion
, 0, &rdataset
,
1946 if (result
== DNS_R_UNCHANGED
)
1947 result
= ISC_R_SUCCESS
;
1948 check_result(result
, "addnsec3: dns_db_addrdataset()");
1949 dns_db_detachnode(gdb
, &nsec3node
);
1953 * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
1955 * Extract the hash from the first label of 'name' then see if it
1956 * is in hashlist. If 'name' is not in the hashlist then delete the
1957 * any NSEC3 records which have the same parameters as the chain we
1960 * XXXMPA Should we also check that it of the form <hash>.<origin>?
1963 nsec3clean(dns_name_t
*name
, dns_dbnode_t
*node
,
1964 unsigned int hashalg
, unsigned int iterations
,
1965 const unsigned char *salt
, size_t salt_len
, hashlist_t
*hashlist
)
1968 dns_rdata_nsec3_t nsec3
;
1969 dns_rdata_t rdata
, delrdata
;
1970 dns_rdatalist_t rdatalist
;
1971 dns_rdataset_t rdataset
, delrdataset
;
1972 isc_boolean_t delete_rrsigs
= ISC_FALSE
;
1973 isc_buffer_t target
;
1974 isc_result_t result
;
1975 unsigned char hash
[NSEC3_MAX_HASH_LENGTH
+ 1];
1976 isc_boolean_t exists
;
1979 * Get the first label.
1981 dns_name_getlabel(name
, 0, &label
);
1984 * We want just the label contents.
1986 isc_region_consume(&label
, 1);
1989 * Decode base32hex string.
1991 isc_buffer_init(&target
, hash
, sizeof(hash
) - 1);
1992 result
= isc_base32hex_decoderegion(&label
, &target
);
1993 if (result
!= ISC_R_SUCCESS
)
1996 hash
[isc_buffer_usedlength(&target
)] = 0;
1998 exists
= hashlist_exists(hashlist
, hash
);
2001 * Verify that the NSEC3 parameters match the current ones
2002 * otherwise we are dealing with a different NSEC3 chain.
2004 dns_rdataset_init(&rdataset
);
2005 dns_rdataset_init(&delrdataset
);
2007 result
= dns_db_findrdataset(gdb
, node
, gversion
, dns_rdatatype_nsec3
,
2008 0, 0, &rdataset
, NULL
);
2009 if (result
!= ISC_R_SUCCESS
)
2013 * Delete any NSEC3 records which are not part of the current
2016 for (result
= dns_rdataset_first(&rdataset
);
2017 result
== ISC_R_SUCCESS
;
2018 result
= dns_rdataset_next(&rdataset
)) {
2019 dns_rdata_init(&rdata
);
2020 dns_rdataset_current(&rdataset
, &rdata
);
2021 result
= dns_rdata_tostruct(&rdata
, &nsec3
, NULL
);
2022 check_result(result
, "dns_rdata_tostruct");
2023 if (exists
&& nsec3
.hash
== hashalg
&&
2024 nsec3
.iterations
== iterations
&&
2025 nsec3
.salt_length
== salt_len
&&
2026 !memcmp(nsec3
.salt
, salt
, salt_len
))
2028 rdatalist
.rdclass
= rdata
.rdclass
;
2029 rdatalist
.type
= rdata
.type
;
2030 rdatalist
.covers
= 0;
2032 rdatalist
.ttl
= ISC_MIN(rdataset
.ttl
, maxttl
);
2033 ISC_LIST_INIT(rdatalist
.rdata
);
2034 dns_rdata_init(&delrdata
);
2035 dns_rdata_clone(&rdata
, &delrdata
);
2036 ISC_LIST_APPEND(rdatalist
.rdata
, &delrdata
, link
);
2037 result
= dns_rdatalist_tordataset(&rdatalist
, &delrdataset
);
2038 check_result(result
, "dns_rdatalist_tordataset()");
2039 result
= dns_db_subtractrdataset(gdb
, node
, gversion
,
2040 &delrdataset
, 0, NULL
);
2041 dns_rdataset_disassociate(&delrdataset
);
2042 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_NXRRSET
)
2043 check_result(result
, "dns_db_subtractrdataset(NSEC3)");
2044 delete_rrsigs
= ISC_TRUE
;
2046 dns_rdataset_disassociate(&rdataset
);
2047 if (result
!= ISC_R_NOMORE
)
2048 check_result(result
, "dns_rdataset_first/next");
2053 * Delete the NSEC3 RRSIGs
2055 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
2056 dns_rdatatype_rrsig
,
2057 dns_rdatatype_nsec3
);
2058 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_UNCHANGED
)
2059 check_result(result
, "dns_db_deleterdataset(RRSIG(NSEC3))");
2063 rrset_cleanup(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
2064 dns_diff_t
*add
, dns_diff_t
*del
)
2066 isc_result_t result
;
2067 unsigned int count1
= 0;
2068 dns_rdataset_t tmprdataset
;
2069 char namestr
[DNS_NAME_FORMATSIZE
];
2070 char typestr
[TYPE_FORMATSIZE
];
2072 dns_name_format(name
, namestr
, sizeof(namestr
));
2073 type_format(rdataset
->type
, typestr
, sizeof(typestr
));
2075 dns_rdataset_init(&tmprdataset
);
2076 for (result
= dns_rdataset_first(rdataset
);
2077 result
== ISC_R_SUCCESS
;
2078 result
= dns_rdataset_next(rdataset
)) {
2079 dns_rdata_t rdata1
= DNS_RDATA_INIT
;
2080 unsigned int count2
= 0;
2083 dns_rdataset_current(rdataset
, &rdata1
);
2084 dns_rdataset_clone(rdataset
, &tmprdataset
);
2085 for (result
= dns_rdataset_first(&tmprdataset
);
2086 result
== ISC_R_SUCCESS
;
2087 result
= dns_rdataset_next(&tmprdataset
)) {
2088 dns_rdata_t rdata2
= DNS_RDATA_INIT
;
2089 dns_difftuple_t
*tuple
= NULL
;
2091 dns_rdataset_current(&tmprdataset
, &rdata2
);
2092 if (count1
< count2
&&
2093 dns_rdata_casecompare(&rdata1
, &rdata2
) == 0)
2095 vbprintf(2, "removing duplicate at %s/%s\n",
2097 result
= dns_difftuple_create(mctx
,
2098 DNS_DIFFOP_DELRESIGN
,
2099 name
, rdataset
->ttl
,
2101 check_result(result
, "dns_difftuple_create");
2102 dns_diff_append(del
, &tuple
);
2103 } else if (set_maxttl
&& rdataset
->ttl
> maxttl
) {
2104 vbprintf(2, "reducing ttl of %s/%s "
2107 rdataset
->ttl
, maxttl
);
2108 result
= dns_difftuple_create(mctx
,
2109 DNS_DIFFOP_DELRESIGN
,
2110 name
, rdataset
->ttl
,
2112 check_result(result
, "dns_difftuple_create");
2113 dns_diff_append(del
, &tuple
);
2115 result
= dns_difftuple_create(mctx
,
2116 DNS_DIFFOP_ADDRESIGN
,
2119 check_result(result
, "dns_difftuple_create");
2120 dns_diff_append(add
, &tuple
);
2123 dns_rdataset_disassociate(&tmprdataset
);
2128 cleanup_zone(void) {
2129 isc_result_t result
;
2130 dns_dbiterator_t
*dbiter
= NULL
;
2131 dns_rdatasetiter_t
*rdsiter
= NULL
;
2132 dns_diff_t add
, del
;
2133 dns_dbnode_t
*node
= NULL
;
2134 dns_rdataset_t rdataset
;
2135 dns_fixedname_t fname
;
2138 dns_diff_init(mctx
, &add
);
2139 dns_diff_init(mctx
, &del
);
2140 dns_fixedname_init(&fname
);
2141 name
= dns_fixedname_name(&fname
);
2142 dns_rdataset_init(&rdataset
);
2144 result
= dns_db_createiterator(gdb
, 0, &dbiter
);
2145 check_result(result
, "dns_db_createiterator()");
2147 for (result
= dns_dbiterator_first(dbiter
);
2148 result
== ISC_R_SUCCESS
;
2149 result
= dns_dbiterator_next(dbiter
)) {
2151 result
= dns_dbiterator_current(dbiter
, &node
, name
);
2152 check_dns_dbiterator_current(result
);
2153 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
2154 check_result(result
, "dns_db_allrdatasets()");
2155 for (result
= dns_rdatasetiter_first(rdsiter
);
2156 result
== ISC_R_SUCCESS
;
2157 result
= dns_rdatasetiter_next(rdsiter
)) {
2158 dns_rdatasetiter_current(rdsiter
, &rdataset
);
2159 rrset_cleanup(name
, &rdataset
, &add
, &del
);
2160 dns_rdataset_disassociate(&rdataset
);
2162 if (result
!= ISC_R_NOMORE
)
2163 fatal("rdatasets iteration failed.");
2164 dns_rdatasetiter_destroy(&rdsiter
);
2165 dns_db_detachnode(gdb
, &node
);
2167 if (result
!= ISC_R_NOMORE
)
2168 fatal("zone iteration failed.");
2170 result
= dns_diff_applysilently(&del
, gdb
, gversion
);
2171 check_result(result
, "dns_diff_applysilently");
2173 result
= dns_diff_applysilently(&add
, gdb
, gversion
);
2174 check_result(result
, "dns_diff_applysilently");
2176 dns_diff_clear(&del
);
2177 dns_diff_clear(&add
);
2178 dns_dbiterator_destroy(&dbiter
);
2182 * Generate NSEC3 records for the zone.
2185 nsec3ify(unsigned int hashalg
, dns_iterations_t iterations
,
2186 const unsigned char *salt
, size_t salt_len
, hashlist_t
*hashlist
)
2188 dns_dbiterator_t
*dbiter
= NULL
;
2189 dns_dbnode_t
*node
= NULL
, *nextnode
= NULL
;
2190 dns_fixedname_t fname
, fnextname
, fzonecut
;
2191 dns_name_t
*name
, *nextname
, *zonecut
;
2192 dns_rdataset_t rdataset
;
2194 isc_boolean_t active
;
2195 isc_boolean_t done
= ISC_FALSE
;
2196 isc_result_t result
;
2197 isc_uint32_t nsttl
= 0;
2198 unsigned int count
, nlabels
;
2200 dns_rdataset_init(&rdataset
);
2201 dns_fixedname_init(&fname
);
2202 name
= dns_fixedname_name(&fname
);
2203 dns_fixedname_init(&fnextname
);
2204 nextname
= dns_fixedname_name(&fnextname
);
2205 dns_fixedname_init(&fzonecut
);
2209 * Walk the zone generating the hash names.
2211 result
= dns_db_createiterator(gdb
, DNS_DB_NONSEC3
, &dbiter
);
2212 check_result(result
, "dns_db_createiterator()");
2214 result
= dns_dbiterator_first(dbiter
);
2215 check_result(result
, "dns_dbiterator_first()");
2218 result
= dns_dbiterator_current(dbiter
, &node
, name
);
2219 check_dns_dbiterator_current(result
);
2221 * Skip out-of-zone records.
2223 if (!dns_name_issubdomain(name
, gorigin
)) {
2224 result
= dns_dbiterator_next(dbiter
);
2225 if (result
== ISC_R_NOMORE
)
2228 check_result(result
, "dns_dbiterator_next()");
2229 dns_db_detachnode(gdb
, &node
);
2233 if (dns_name_equal(name
, gorigin
))
2234 remove_records(node
, dns_rdatatype_nsec
, ISC_TRUE
);
2236 result
= dns_dbiterator_next(dbiter
);
2238 while (result
== ISC_R_SUCCESS
) {
2239 result
= dns_dbiterator_current(dbiter
, &nextnode
,
2241 check_dns_dbiterator_current(result
);
2242 active
= active_node(nextnode
);
2244 dns_db_detachnode(gdb
, &nextnode
);
2245 result
= dns_dbiterator_next(dbiter
);
2248 if (!dns_name_issubdomain(nextname
, gorigin
) ||
2250 dns_name_issubdomain(nextname
, zonecut
))) {
2251 remove_sigs(nextnode
, ISC_FALSE
, 0);
2252 dns_db_detachnode(gdb
, &nextnode
);
2253 result
= dns_dbiterator_next(dbiter
);
2256 if (is_delegation(gdb
, gversion
, gorigin
,
2257 nextname
, nextnode
, &nsttl
))
2259 zonecut
= dns_fixedname_name(&fzonecut
);
2260 dns_name_copy(nextname
, zonecut
, NULL
);
2261 remove_sigs(nextnode
, ISC_TRUE
, 0);
2263 add_ds(nextname
, nextnode
, nsttl
);
2264 if (OPTOUT(nsec3flags
) &&
2265 !secure(nextname
, nextnode
)) {
2266 dns_db_detachnode(gdb
, &nextnode
);
2267 result
= dns_dbiterator_next(dbiter
);
2271 dns_db_detachnode(gdb
, &nextnode
);
2274 if (result
== ISC_R_NOMORE
) {
2275 dns_name_copy(gorigin
, nextname
, NULL
);
2277 } else if (result
!= ISC_R_SUCCESS
)
2278 fatal("iterating through the database failed: %s",
2279 isc_result_totext(result
));
2280 dns_name_downcase(name
, name
, NULL
);
2281 hashlist_add_dns_name(hashlist
, name
, hashalg
, iterations
,
2282 salt
, salt_len
, ISC_FALSE
);
2283 dns_db_detachnode(gdb
, &node
);
2285 * Add hashs for empty nodes. Use closest encloser logic.
2286 * The closest encloser either has data or is a empty
2287 * node for another <name,nextname> span so we don't add
2288 * it here. Empty labels on nextname are within the span.
2290 dns_name_downcase(nextname
, nextname
, NULL
);
2291 dns_name_fullcompare(name
, nextname
, &order
, &nlabels
);
2292 addnowildcardhash(hashlist
, name
, hashalg
, iterations
,
2294 count
= dns_name_countlabels(nextname
);
2295 while (count
> nlabels
+ 1) {
2297 dns_name_split(nextname
, count
, NULL
, nextname
);
2298 hashlist_add_dns_name(hashlist
, nextname
, hashalg
,
2299 iterations
, salt
, salt_len
,
2301 addnowildcardhash(hashlist
, nextname
, hashalg
,
2302 iterations
, salt
, salt_len
);
2305 dns_dbiterator_destroy(&dbiter
);
2308 * We have all the hashes now so we can sort them.
2310 hashlist_sort(hashlist
);
2313 * Check for duplicate hashes. If found the salt needs to
2316 if (hashlist_hasdup(hashlist
))
2317 fatal("Duplicate hash detected. Pick a different salt.");
2320 * Generate the nsec3 records.
2325 addnsec3param(salt
, salt_len
, iterations
);
2328 * Clean out NSEC3 records which don't match this chain.
2330 result
= dns_db_createiterator(gdb
, DNS_DB_NSEC3ONLY
, &dbiter
);
2331 check_result(result
, "dns_db_createiterator()");
2333 for (result
= dns_dbiterator_first(dbiter
);
2334 result
== ISC_R_SUCCESS
;
2335 result
= dns_dbiterator_next(dbiter
)) {
2336 result
= dns_dbiterator_current(dbiter
, &node
, name
);
2337 check_dns_dbiterator_current(result
);
2338 nsec3clean(name
, node
, hashalg
, iterations
, salt
, salt_len
,
2340 dns_db_detachnode(gdb
, &node
);
2342 dns_dbiterator_destroy(&dbiter
);
2345 * Generate / complete the new chain.
2347 result
= dns_db_createiterator(gdb
, DNS_DB_NONSEC3
, &dbiter
);
2348 check_result(result
, "dns_db_createiterator()");
2350 result
= dns_dbiterator_first(dbiter
);
2351 check_result(result
, "dns_dbiterator_first()");
2354 result
= dns_dbiterator_current(dbiter
, &node
, name
);
2355 check_dns_dbiterator_current(result
);
2357 * Skip out-of-zone records.
2359 if (!dns_name_issubdomain(name
, gorigin
)) {
2360 result
= dns_dbiterator_next(dbiter
);
2361 if (result
== ISC_R_NOMORE
)
2364 check_result(result
, "dns_dbiterator_next()");
2365 dns_db_detachnode(gdb
, &node
);
2368 result
= dns_dbiterator_next(dbiter
);
2370 while (result
== ISC_R_SUCCESS
) {
2371 result
= dns_dbiterator_current(dbiter
, &nextnode
,
2373 check_dns_dbiterator_current(result
);
2374 active
= active_node(nextnode
);
2376 dns_db_detachnode(gdb
, &nextnode
);
2377 result
= dns_dbiterator_next(dbiter
);
2380 if (!dns_name_issubdomain(nextname
, gorigin
) ||
2382 dns_name_issubdomain(nextname
, zonecut
))) {
2383 dns_db_detachnode(gdb
, &nextnode
);
2384 result
= dns_dbiterator_next(dbiter
);
2387 if (is_delegation(gdb
, gversion
, gorigin
,
2388 nextname
, nextnode
, NULL
))
2390 zonecut
= dns_fixedname_name(&fzonecut
);
2391 dns_name_copy(nextname
, zonecut
, NULL
);
2392 if (OPTOUT(nsec3flags
) &&
2393 !secure(nextname
, nextnode
)) {
2394 dns_db_detachnode(gdb
, &nextnode
);
2395 result
= dns_dbiterator_next(dbiter
);
2399 dns_db_detachnode(gdb
, &nextnode
);
2402 if (result
== ISC_R_NOMORE
) {
2403 dns_name_copy(gorigin
, nextname
, NULL
);
2405 } else if (result
!= ISC_R_SUCCESS
)
2406 fatal("iterating through the database failed: %s",
2407 isc_result_totext(result
));
2409 * We need to pause here to release the lock on the database.
2411 dns_dbiterator_pause(dbiter
);
2412 addnsec3(name
, node
, salt
, salt_len
, iterations
,
2413 hashlist
, zone_soa_min_ttl
);
2414 dns_db_detachnode(gdb
, &node
);
2416 * Add NSEC3's for empty nodes. Use closest encloser logic.
2418 dns_name_fullcompare(name
, nextname
, &order
, &nlabels
);
2419 count
= dns_name_countlabels(nextname
);
2420 while (count
> nlabels
+ 1) {
2422 dns_name_split(nextname
, count
, NULL
, nextname
);
2423 addnsec3(nextname
, NULL
, salt
, salt_len
,
2424 iterations
, hashlist
, zone_soa_min_ttl
);
2427 dns_dbiterator_destroy(&dbiter
);
2431 * Load the zone file from disk
2434 loadzone(char *file
, char *origin
, dns_rdataclass_t rdclass
, dns_db_t
**db
) {
2437 dns_fixedname_t fname
;
2439 isc_result_t result
;
2441 len
= strlen(origin
);
2442 isc_buffer_init(&b
, origin
, len
);
2443 isc_buffer_add(&b
, len
);
2445 dns_fixedname_init(&fname
);
2446 name
= dns_fixedname_name(&fname
);
2447 result
= dns_name_fromtext(name
, &b
, dns_rootname
, 0, NULL
);
2448 if (result
!= ISC_R_SUCCESS
)
2449 fatal("failed converting name '%s' to dns format: %s",
2450 origin
, isc_result_totext(result
));
2452 result
= dns_db_create(mctx
, "rbt", name
, dns_dbtype_zone
,
2453 rdclass
, 0, NULL
, db
);
2454 check_result(result
, "dns_db_create()");
2456 result
= dns_db_load2(*db
, file
, inputformat
);
2457 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_SEENINCLUDE
)
2458 fatal("failed loading zone from '%s': %s",
2459 file
, isc_result_totext(result
));
2463 * Finds all public zone keys in the zone, and attempts to load the
2464 * private keys from disk.
2467 loadzonekeys(isc_boolean_t preserve_keys
, isc_boolean_t load_public
) {
2469 dns_dbversion_t
*currentversion
= NULL
;
2470 isc_result_t result
;
2471 dns_rdataset_t rdataset
, keysigs
, soasigs
;
2474 result
= dns_db_findnode(gdb
, gorigin
, ISC_FALSE
, &node
);
2475 if (result
!= ISC_R_SUCCESS
)
2476 fatal("failed to find the zone's origin: %s",
2477 isc_result_totext(result
));
2479 dns_db_currentversion(gdb
, ¤tversion
);
2481 dns_rdataset_init(&rdataset
);
2482 dns_rdataset_init(&soasigs
);
2483 dns_rdataset_init(&keysigs
);
2485 /* Make note of the keys which signed the SOA, if any */
2486 result
= dns_db_findrdataset(gdb
, node
, currentversion
,
2487 dns_rdatatype_soa
, 0, 0,
2488 &rdataset
, &soasigs
);
2489 if (result
!= ISC_R_SUCCESS
)
2492 /* Preserve the TTL of the DNSKEY RRset, if any */
2493 dns_rdataset_disassociate(&rdataset
);
2494 result
= dns_db_findrdataset(gdb
, node
, currentversion
,
2495 dns_rdatatype_dnskey
, 0, 0,
2496 &rdataset
, &keysigs
);
2498 if (result
!= ISC_R_SUCCESS
)
2501 if (set_keyttl
&& keyttl
!= rdataset
.ttl
) {
2502 fprintf(stderr
, "User-specified TTL %d conflicts "
2503 "with existing DNSKEY RRset TTL.\n",
2505 fprintf(stderr
, "Imported keys will use the RRSet "
2506 "TTL %d instead.\n",
2509 keyttl
= rdataset
.ttl
;
2511 /* Load keys corresponding to the existing DNSKEY RRset. */
2512 result
= dns_dnssec_keylistfromrdataset(gorigin
, directory
, mctx
,
2513 &rdataset
, &keysigs
, &soasigs
,
2514 preserve_keys
, load_public
,
2516 if (result
!= ISC_R_SUCCESS
)
2517 fatal("failed to load the zone keys: %s",
2518 isc_result_totext(result
));
2521 if (dns_rdataset_isassociated(&rdataset
))
2522 dns_rdataset_disassociate(&rdataset
);
2523 if (dns_rdataset_isassociated(&keysigs
))
2524 dns_rdataset_disassociate(&keysigs
);
2525 if (dns_rdataset_isassociated(&soasigs
))
2526 dns_rdataset_disassociate(&soasigs
);
2527 dns_db_detachnode(gdb
, &node
);
2528 dns_db_closeversion(gdb
, ¤tversion
, ISC_FALSE
);
2532 loadexplicitkeys(char *keyfiles
[], int n
, isc_boolean_t setksk
) {
2533 isc_result_t result
;
2536 for (i
= 0; i
< n
; i
++) {
2537 dns_dnsseckey_t
*key
= NULL
;
2538 dst_key_t
*newkey
= NULL
;
2540 result
= dst_key_fromnamedfile(keyfiles
[i
], directory
,
2544 if (result
!= ISC_R_SUCCESS
)
2545 fatal("cannot load dnskey %s: %s", keyfiles
[i
],
2546 isc_result_totext(result
));
2548 if (!dns_name_equal(gorigin
, dst_key_name(newkey
)))
2549 fatal("key %s not at origin\n", keyfiles
[i
]);
2551 if (!dst_key_isprivate(newkey
))
2552 fatal("cannot sign zone with non-private dnskey %s",
2555 /* Skip any duplicates */
2556 for (key
= ISC_LIST_HEAD(keylist
);
2558 key
= ISC_LIST_NEXT(key
, link
)) {
2559 if (dst_key_id(key
->key
) == dst_key_id(newkey
) &&
2560 dst_key_alg(key
->key
) == dst_key_alg(newkey
))
2565 /* We haven't seen this key before */
2566 dns_dnsseckey_create(mctx
, &newkey
, &key
);
2567 ISC_LIST_APPEND(keylist
, key
, link
);
2568 key
->source
= dns_keysource_user
;
2570 dst_key_free(&key
->key
);
2574 key
->force_publish
= ISC_TRUE
;
2575 key
->force_sign
= ISC_TRUE
;
2578 key
->ksk
= ISC_TRUE
;
2583 report(const char *format
, ...) {
2585 va_start(args
, format
);
2586 vfprintf(stderr
, format
, args
);
2592 build_final_keylist(void) {
2593 isc_result_t result
;
2594 dns_dbversion_t
*ver
= NULL
;
2596 dns_dnsseckeylist_t matchkeys
;
2597 char name
[DNS_NAME_FORMATSIZE
];
2600 * Find keys that match this zone in the key repository.
2602 ISC_LIST_INIT(matchkeys
);
2603 result
= dns_dnssec_findmatchingkeys(gorigin
, directory
,
2605 if (result
== ISC_R_NOTFOUND
)
2606 result
= ISC_R_SUCCESS
;
2607 check_result(result
, "dns_dnssec_findmatchingkeys");
2609 result
= dns_db_newversion(gdb
, &ver
);
2610 check_result(result
, "dns_db_newversion");
2612 dns_diff_init(mctx
, &diff
);
2615 * Update keylist with information from from the key repository.
2617 dns_dnssec_updatekeys(&keylist
, &matchkeys
, NULL
, gorigin
, keyttl
,
2618 &diff
, ignore_kskflag
, mctx
, report
);
2620 dns_name_format(gorigin
, name
, sizeof(name
));
2622 result
= dns_diff_applysilently(&diff
, gdb
, ver
);
2623 if (result
!= ISC_R_SUCCESS
)
2624 fatal("failed to update DNSKEY RRset at node '%s': %s",
2625 name
, isc_result_totext(result
));
2627 dns_db_closeversion(gdb
, &ver
, ISC_TRUE
);
2629 dns_diff_clear(&diff
);
2633 warnifallksk(dns_db_t
*db
) {
2634 dns_dbversion_t
*currentversion
= NULL
;
2635 dns_dbnode_t
*node
= NULL
;
2636 dns_rdataset_t rdataset
;
2637 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2638 isc_result_t result
;
2639 dns_rdata_dnskey_t dnskey
;
2640 isc_boolean_t have_non_ksk
= ISC_FALSE
;
2642 dns_db_currentversion(db
, ¤tversion
);
2644 result
= dns_db_findnode(db
, gorigin
, ISC_FALSE
, &node
);
2645 if (result
!= ISC_R_SUCCESS
)
2646 fatal("failed to find the zone's origin: %s",
2647 isc_result_totext(result
));
2649 dns_rdataset_init(&rdataset
);
2650 result
= dns_db_findrdataset(db
, node
, currentversion
,
2651 dns_rdatatype_dnskey
, 0, 0, &rdataset
,
2653 if (result
!= ISC_R_SUCCESS
)
2654 fatal("failed to find keys at the zone apex: %s",
2655 isc_result_totext(result
));
2656 result
= dns_rdataset_first(&rdataset
);
2657 check_result(result
, "dns_rdataset_first");
2658 while (result
== ISC_R_SUCCESS
) {
2659 dns_rdata_reset(&rdata
);
2660 dns_rdataset_current(&rdataset
, &rdata
);
2661 result
= dns_rdata_tostruct(&rdata
, &dnskey
, NULL
);
2662 check_result(result
, "dns_rdata_tostruct");
2663 if ((dnskey
.flags
& DNS_KEYFLAG_KSK
) == 0) {
2664 have_non_ksk
= ISC_TRUE
;
2665 result
= ISC_R_NOMORE
;
2667 result
= dns_rdataset_next(&rdataset
);
2668 dns_rdata_freestruct(&dnskey
);
2670 dns_rdataset_disassociate(&rdataset
);
2671 dns_db_detachnode(db
, &node
);
2672 dns_db_closeversion(db
, ¤tversion
, ISC_FALSE
);
2673 if (!have_non_ksk
&& !ignore_kskflag
) {
2674 if (disable_zone_check
)
2675 fprintf(stderr
, "%s: warning: No non-KSK DNSKEY found; "
2676 "supply a ZSK or use '-z'.\n",
2679 fatal("No non-KSK DNSKEY found; "
2680 "supply a ZSK or use '-z'.");
2685 set_nsec3params(isc_boolean_t update
, isc_boolean_t set_salt
,
2686 isc_boolean_t set_optout
, isc_boolean_t set_iter
)
2688 isc_result_t result
;
2689 dns_dbversion_t
*ver
= NULL
;
2690 dns_dbnode_t
*node
= NULL
;
2691 dns_rdataset_t rdataset
;
2692 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2693 dns_rdata_nsec3_t nsec3
;
2694 dns_fixedname_t fname
;
2695 dns_name_t
*hashname
;
2696 unsigned char orig_salt
[255];
2697 size_t orig_saltlen
;
2698 dns_hash_t orig_hash
;
2699 isc_uint16_t orig_iter
;
2701 dns_db_currentversion(gdb
, &ver
);
2702 dns_rdataset_init(&rdataset
);
2704 orig_saltlen
= sizeof(orig_salt
);
2705 result
= dns_db_getnsec3parameters(gdb
, ver
, &orig_hash
, NULL
,
2706 &orig_iter
, orig_salt
,
2708 if (result
!= ISC_R_SUCCESS
)
2711 nsec_datatype
= dns_rdatatype_nsec3
;
2713 if (!update
&& set_salt
) {
2714 if (salt_length
!= orig_saltlen
||
2715 memcmp(saltbuf
, orig_salt
, salt_length
) != 0)
2716 fatal("An NSEC3 chain exists with a different salt. "
2717 "Use -u to update it.");
2718 } else if (!set_salt
) {
2719 salt_length
= orig_saltlen
;
2720 memmove(saltbuf
, orig_salt
, orig_saltlen
);
2724 if (!update
&& set_iter
) {
2725 if (nsec3iter
!= orig_iter
)
2726 fatal("An NSEC3 chain exists with different "
2727 "iterations. Use -u to update it.");
2728 } else if (!set_iter
)
2729 nsec3iter
= orig_iter
;
2732 * Find an NSEC3 record to get the current OPTOUT value.
2733 * (This assumes all NSEC3 records agree.)
2736 dns_fixedname_init(&fname
);
2737 hashname
= dns_fixedname_name(&fname
);
2738 result
= dns_nsec3_hashname(&fname
, NULL
, NULL
,
2739 gorigin
, gorigin
, dns_hash_sha1
,
2740 orig_iter
, orig_salt
, orig_saltlen
);
2741 check_result(result
, "dns_nsec3_hashname");
2743 result
= dns_db_findnsec3node(gdb
, hashname
, ISC_FALSE
, &node
);
2744 if (result
!= ISC_R_SUCCESS
)
2747 result
= dns_db_findrdataset(gdb
, node
, ver
, dns_rdatatype_nsec3
,
2748 0, 0, &rdataset
, NULL
);
2749 if (result
!= ISC_R_SUCCESS
)
2752 result
= dns_rdataset_first(&rdataset
);
2753 check_result(result
, "dns_rdataset_first");
2754 dns_rdataset_current(&rdataset
, &rdata
);
2755 result
= dns_rdata_tostruct(&rdata
, &nsec3
, NULL
);
2756 check_result(result
, "dns_rdata_tostruct");
2758 if (!update
&& set_optout
) {
2759 if (nsec3flags
!= nsec3
.flags
)
2760 fatal("An NSEC3 chain exists with%s OPTOUT. "
2761 "Use -u -%s to %s it.",
2762 OPTOUT(nsec3
.flags
) ? "" : "out",
2763 OPTOUT(nsec3
.flags
) ? "AA" : "A",
2764 OPTOUT(nsec3
.flags
) ? "clear" : "set");
2765 } else if (!set_optout
)
2766 nsec3flags
= nsec3
.flags
;
2768 dns_rdata_freestruct(&nsec3
);
2771 if (dns_rdataset_isassociated(&rdataset
))
2772 dns_rdataset_disassociate(&rdataset
);
2774 dns_db_detachnode(gdb
, &node
);
2775 dns_db_closeversion(gdb
, &ver
, ISC_FALSE
);
2779 writeset(const char *prefix
, dns_rdatatype_t type
) {
2781 char namestr
[DNS_NAME_FORMATSIZE
];
2782 dns_db_t
*db
= NULL
;
2783 dns_dbversion_t
*version
= NULL
;
2785 dns_difftuple_t
*tuple
= NULL
;
2786 dns_fixedname_t fixed
;
2788 dns_rdata_t rdata
, ds
;
2789 isc_boolean_t have_ksk
= ISC_FALSE
;
2790 isc_boolean_t have_non_ksk
= ISC_FALSE
;
2792 isc_buffer_t namebuf
;
2794 isc_result_t result
;
2795 dns_dnsseckey_t
*key
, *tmpkey
;
2796 unsigned char dsbuf
[DNS_DS_BUFFERSIZE
];
2797 unsigned char keybuf
[DST_KEY_MAXSIZE
];
2798 unsigned int filenamelen
;
2799 const dns_master_style_t
*style
=
2800 (type
== dns_rdatatype_dnskey
) ? masterstyle
: dsstyle
;
2802 isc_buffer_init(&namebuf
, namestr
, sizeof(namestr
));
2803 result
= dns_name_tofilenametext(gorigin
, ISC_FALSE
, &namebuf
);
2804 check_result(result
, "dns_name_tofilenametext");
2805 isc_buffer_putuint8(&namebuf
, 0);
2806 filenamelen
= strlen(prefix
) + strlen(namestr
);
2808 filenamelen
+= strlen(dsdir
) + 1;
2809 filename
= isc_mem_get(mctx
, filenamelen
+ 1);
2810 if (filename
== NULL
)
2811 fatal("out of memory");
2813 sprintf(filename
, "%s/", dsdir
);
2816 strcat(filename
, prefix
);
2817 strcat(filename
, namestr
);
2819 dns_diff_init(mctx
, &diff
);
2821 if (type
== dns_rdatatype_dlv
) {
2823 unsigned int labels
;
2825 dns_name_init(&tname
, NULL
);
2826 dns_fixedname_init(&fixed
);
2827 name
= dns_fixedname_name(&fixed
);
2828 labels
= dns_name_countlabels(gorigin
);
2829 dns_name_getlabelsequence(gorigin
, 0, labels
- 1, &tname
);
2830 result
= dns_name_concatenate(&tname
, dlv
, name
, NULL
);
2831 check_result(result
, "dns_name_concatenate");
2835 for (key
= ISC_LIST_HEAD(keylist
);
2837 key
= ISC_LIST_NEXT(key
, link
))
2839 if (REVOKE(key
->key
))
2842 have_ksk
= ISC_TRUE
;
2843 have_non_ksk
= ISC_FALSE
;
2845 have_ksk
= ISC_FALSE
;
2846 have_non_ksk
= ISC_TRUE
;
2848 for (tmpkey
= ISC_LIST_HEAD(keylist
);
2850 tmpkey
= ISC_LIST_NEXT(tmpkey
, link
)) {
2851 if (dst_key_alg(key
->key
) != dst_key_alg(tmpkey
->key
))
2853 if (REVOKE(tmpkey
->key
))
2856 have_ksk
= ISC_TRUE
;
2858 have_non_ksk
= ISC_TRUE
;
2860 if (have_ksk
&& have_non_ksk
&& !isksk(key
))
2862 dns_rdata_init(&rdata
);
2863 dns_rdata_init(&ds
);
2864 isc_buffer_init(&b
, keybuf
, sizeof(keybuf
));
2865 result
= dst_key_todns(key
->key
, &b
);
2866 check_result(result
, "dst_key_todns");
2867 isc_buffer_usedregion(&b
, &r
);
2868 dns_rdata_fromregion(&rdata
, gclass
, dns_rdatatype_dnskey
, &r
);
2869 if (type
!= dns_rdatatype_dnskey
) {
2870 result
= dns_ds_buildrdata(gorigin
, &rdata
,
2873 check_result(result
, "dns_ds_buildrdata");
2874 if (type
== dns_rdatatype_dlv
)
2875 ds
.type
= dns_rdatatype_dlv
;
2876 result
= dns_difftuple_create(mctx
,
2877 DNS_DIFFOP_ADDRESIGN
,
2878 name
, 0, &ds
, &tuple
);
2879 check_result(result
, "dns_difftuple_create");
2880 dns_diff_append(&diff
, &tuple
);
2882 dns_rdata_reset(&ds
);
2883 result
= dns_ds_buildrdata(gorigin
, &rdata
,
2884 DNS_DSDIGEST_SHA256
,
2886 check_result(result
, "dns_ds_buildrdata");
2887 if (type
== dns_rdatatype_dlv
)
2888 ds
.type
= dns_rdatatype_dlv
;
2889 result
= dns_difftuple_create(mctx
,
2890 DNS_DIFFOP_ADDRESIGN
,
2891 name
, 0, &ds
, &tuple
);
2894 result
= dns_difftuple_create(mctx
,
2895 DNS_DIFFOP_ADDRESIGN
,
2896 gorigin
, zone_soa_min_ttl
,
2898 check_result(result
, "dns_difftuple_create");
2899 dns_diff_append(&diff
, &tuple
);
2902 result
= dns_db_create(mctx
, "rbt", dns_rootname
, dns_dbtype_zone
,
2903 gclass
, 0, NULL
, &db
);
2904 check_result(result
, "dns_db_create");
2906 result
= dns_db_newversion(db
, &version
);
2907 check_result(result
, "dns_db_newversion");
2909 result
= dns_diff_apply(&diff
, db
, version
);
2910 check_result(result
, "dns_diff_apply");
2911 dns_diff_clear(&diff
);
2913 result
= dns_master_dump(mctx
, db
, version
, style
, filename
);
2914 check_result(result
, "dns_master_dump");
2916 isc_mem_put(mctx
, filename
, filenamelen
+ 1);
2918 dns_db_closeversion(db
, &version
, ISC_FALSE
);
2923 print_time(FILE *fp
) {
2926 if (outputformat
!= dns_masterformat_text
)
2929 currenttime
= time(NULL
);
2930 fprintf(fp
, "; File written on %s", ctime(¤ttime
));
2934 print_version(FILE *fp
) {
2935 if (outputformat
!= dns_masterformat_text
)
2938 fprintf(fp
, "; dnssec_signzone version " VERSION
"\n");
2941 ISC_PLATFORM_NORETURN_PRE
static void
2942 usage(void) ISC_PLATFORM_NORETURN_POST
;
2946 fprintf(stderr
, "Usage:\n");
2947 fprintf(stderr
, "\t%s [options] zonefile [keys]\n", program
);
2949 fprintf(stderr
, "\n");
2951 fprintf(stderr
, "Version: %s\n", VERSION
);
2953 fprintf(stderr
, "Options: (default value in parenthesis) \n");
2954 fprintf(stderr
, "\t-S:\tsmart signing: automatically finds key files\n"
2955 "\t\tfor the zone and determines how they are to "
2957 fprintf(stderr
, "\t-K directory:\n");
2958 fprintf(stderr
, "\t\tdirectory to find key files (.)\n");
2959 fprintf(stderr
, "\t-d directory:\n");
2960 fprintf(stderr
, "\t\tdirectory to find dsset-* files (.)\n");
2961 fprintf(stderr
, "\t-g:\t");
2962 fprintf(stderr
, "update DS records based on child zones' "
2964 fprintf(stderr
, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
2965 fprintf(stderr
, "\t\tRRSIG start time "
2966 "- absolute|offset (now - 1 hour)\n");
2967 fprintf(stderr
, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
2968 fprintf(stderr
, "\t\tRRSIG end time "
2969 "- absolute|from start|from now "
2970 "(now + 30 days)\n");
2971 fprintf(stderr
, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
2972 fprintf(stderr
, "\t\tDNSKEY RRSIG end "
2973 "- absolute|from start|from now "
2975 fprintf(stderr
, "\t-i interval:\n");
2976 fprintf(stderr
, "\t\tcycle interval - resign "
2977 "if < interval from end ( (end-start)/4 )\n");
2978 fprintf(stderr
, "\t-j jitter:\n");
2979 fprintf(stderr
, "\t\trandomize signature end time up to jitter seconds\n");
2980 fprintf(stderr
, "\t-v debuglevel (0)\n");
2981 fprintf(stderr
, "\t-V:\tprint version information\n");
2982 fprintf(stderr
, "\t-o origin:\n");
2983 fprintf(stderr
, "\t\tzone origin (name of zonefile)\n");
2984 fprintf(stderr
, "\t-f outfile:\n");
2985 fprintf(stderr
, "\t\tfile the signed zone is written in "
2986 "(zonefile + .signed)\n");
2987 fprintf(stderr
, "\t-I format:\n");
2988 fprintf(stderr
, "\t\tfile format of input zonefile (text)\n");
2989 fprintf(stderr
, "\t-O format:\n");
2990 fprintf(stderr
, "\t\tfile format of signed zone file (text)\n");
2991 fprintf(stderr
, "\t-N format:\n");
2992 fprintf(stderr
, "\t\tsoa serial format of signed zone file (keep)\n");
2993 fprintf(stderr
, "\t-D:\n");
2994 fprintf(stderr
, "\t\toutput only DNSSEC-related records\n");
2995 fprintf(stderr
, "\t-r randomdev:\n");
2996 fprintf(stderr
, "\t\ta file containing random data\n");
2997 fprintf(stderr
, "\t-a:\t");
2998 fprintf(stderr
, "verify generated signatures\n");
2999 fprintf(stderr
, "\t-c class (IN)\n");
3000 fprintf(stderr
, "\t-E engine:\n");
3001 #if defined(PKCS11CRYPTO)
3002 fprintf(stderr
, "\t\tpath to PKCS#11 provider library "
3003 "(default is %s)\n", PK11_LIB_LOCATION
);
3004 #elif defined(USE_PKCS11)
3005 fprintf(stderr
, "\t\tname of an OpenSSL engine to use "
3006 "(default is \"pkcs11\")\n");
3008 fprintf(stderr
, "\t\tname of an OpenSSL engine to use\n");
3010 fprintf(stderr
, "\t-p:\t");
3011 fprintf(stderr
, "use pseudorandom data (faster but less secure)\n");
3012 fprintf(stderr
, "\t-P:\t");
3013 fprintf(stderr
, "disable post-sign verification\n");
3014 fprintf(stderr
, "\t-Q:\t");
3015 fprintf(stderr
, "remove signatures from keys that are no "
3017 fprintf(stderr
, "\t-R:\t");
3018 fprintf(stderr
, "remove signatures from keys that no longer exist\n");
3019 fprintf(stderr
, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
3020 fprintf(stderr
, "\t-t:\t");
3021 fprintf(stderr
, "print statistics\n");
3022 fprintf(stderr
, "\t-u:\t");
3023 fprintf(stderr
, "update or replace an existing NSEC/NSEC3 chain\n");
3024 fprintf(stderr
, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
3025 fprintf(stderr
, "\t-z:\tsign all records with KSKs\n");
3026 fprintf(stderr
, "\t-C:\tgenerate a keyset file, for compatibility\n"
3027 "\t\twith older versions of dnssec-signzone -g\n");
3028 fprintf(stderr
, "\t-n ncpus (number of cpus present)\n");
3029 fprintf(stderr
, "\t-k key_signing_key\n");
3030 fprintf(stderr
, "\t-l lookasidezone\n");
3031 fprintf(stderr
, "\t-3 NSEC3 salt\n");
3032 fprintf(stderr
, "\t-H NSEC3 iterations (10)\n");
3033 fprintf(stderr
, "\t-A NSEC3 optout\n");
3035 fprintf(stderr
, "\n");
3037 fprintf(stderr
, "Signing Keys: ");
3038 fprintf(stderr
, "(default: all zone keys that have private keys)\n");
3039 fprintf(stderr
, "\tkeyfile (Kname+alg+tag)\n");
3045 removetempfile(void) {
3047 isc_file_remove(tempfile
);
3051 print_stats(isc_time_t
*timer_start
, isc_time_t
*timer_finish
,
3052 isc_time_t
*sign_start
, isc_time_t
*sign_finish
)
3054 isc_uint64_t time_us
; /* Time in microseconds */
3055 isc_uint64_t time_ms
; /* Time in milliseconds */
3056 isc_uint64_t sig_ms
; /* Signatures per millisecond */
3057 FILE *out
= output_stdout
? stderr
: stdout
;
3059 fprintf(out
, "Signatures generated: %10d\n", nsigned
);
3060 fprintf(out
, "Signatures retained: %10d\n", nretained
);
3061 fprintf(out
, "Signatures dropped: %10d\n", ndropped
);
3062 fprintf(out
, "Signatures successfully verified: %10d\n", nverified
);
3063 fprintf(out
, "Signatures unsuccessfully "
3064 "verified: %10d\n", nverifyfailed
);
3066 time_us
= isc_time_microdiff(sign_finish
, sign_start
);
3067 time_ms
= time_us
/ 1000;
3068 fprintf(out
, "Signing time in seconds: %7u.%03u\n",
3069 (unsigned int) (time_ms
/ 1000),
3070 (unsigned int) (time_ms
% 1000));
3072 sig_ms
= ((isc_uint64_t
)nsigned
* 1000000000) / time_us
;
3073 fprintf(out
, "Signatures per second: %7u.%03u\n",
3074 (unsigned int) sig_ms
/ 1000,
3075 (unsigned int) sig_ms
% 1000);
3078 time_us
= isc_time_microdiff(timer_finish
, timer_start
);
3079 time_ms
= time_us
/ 1000;
3080 fprintf(out
, "Runtime in seconds: %7u.%03u\n",
3081 (unsigned int) (time_ms
/ 1000),
3082 (unsigned int) (time_ms
% 1000));
3086 main(int argc
, char *argv
[]) {
3088 char *startstr
= NULL
, *endstr
= NULL
, *classname
= NULL
;
3089 char *dnskey_endstr
= NULL
;
3090 char *origin
= NULL
, *file
= NULL
, *output
= NULL
;
3091 char *inputformatstr
= NULL
, *outputformatstr
= NULL
;
3092 char *serialformatstr
= NULL
;
3093 char *dskeyfile
[MAXDSKEYS
];
3096 isc_time_t timer_start
, timer_finish
;
3097 isc_time_t sign_start
, sign_finish
;
3098 dns_dnsseckey_t
*key
;
3099 isc_result_t result
;
3100 isc_log_t
*log
= NULL
;
3101 isc_boolean_t pseudorandom
= ISC_FALSE
;
3103 const char *engine
= PKCS11_ENGINE
;
3105 const char *engine
= NULL
;
3107 unsigned int eflags
;
3108 isc_boolean_t free_output
= ISC_FALSE
;
3109 int tempfilelen
= 0;
3110 dns_rdataclass_t rdclass
;
3111 isc_task_t
**tasks
= NULL
;
3114 hashlist_t hashlist
;
3115 isc_boolean_t make_keyset
= ISC_FALSE
;
3116 isc_boolean_t set_salt
= ISC_FALSE
;
3117 isc_boolean_t set_optout
= ISC_FALSE
;
3118 isc_boolean_t set_iter
= ISC_FALSE
;
3119 isc_boolean_t nonsecify
= ISC_FALSE
;
3121 /* Unused letters: Bb G J q Yy (and F is reserved). */
3122 #define CMDLINE_FLAGS \
3123 "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:"
3126 * Process memory debugging argument first.
3128 while ((ch
= isc_commandline_parse(argc
, argv
, CMDLINE_FLAGS
)) != -1) {
3131 if (strcasecmp(isc_commandline_argument
, "record") == 0)
3132 isc_mem_debugging
|= ISC_MEM_DEBUGRECORD
;
3133 if (strcasecmp(isc_commandline_argument
, "trace") == 0)
3134 isc_mem_debugging
|= ISC_MEM_DEBUGTRACE
;
3135 if (strcasecmp(isc_commandline_argument
, "usage") == 0)
3136 isc_mem_debugging
|= ISC_MEM_DEBUGUSAGE
;
3137 if (strcasecmp(isc_commandline_argument
, "size") == 0)
3138 isc_mem_debugging
|= ISC_MEM_DEBUGSIZE
;
3139 if (strcasecmp(isc_commandline_argument
, "mctx") == 0)
3140 isc_mem_debugging
|= ISC_MEM_DEBUGCTX
;
3146 isc_commandline_reset
= ISC_TRUE
;
3148 masterstyle
= &dns_master_style_explicitttl
;
3150 check_result(isc_app_start(), "isc_app_start");
3152 result
= isc_mem_create(0, 0, &mctx
);
3153 if (result
!= ISC_R_SUCCESS
)
3154 fatal("out of memory");
3157 pk11_result_register();
3159 dns_result_register();
3161 isc_commandline_errprint
= ISC_FALSE
;
3163 while ((ch
= isc_commandline_parse(argc
, argv
, CMDLINE_FLAGS
)) != -1) {
3166 set_salt
= ISC_TRUE
;
3167 nsec_datatype
= dns_rdatatype_nsec3
;
3168 if (strcmp(isc_commandline_argument
, "-") != 0) {
3169 isc_buffer_t target
;
3172 sarg
= isc_commandline_argument
;
3173 isc_buffer_init(&target
, saltbuf
,
3175 result
= isc_hex_decodestring(sarg
, &target
);
3176 check_result(result
,
3177 "isc_hex_decodestring(salt)");
3178 salt_length
= isc_buffer_usedlength(&target
);
3183 set_optout
= ISC_TRUE
;
3184 if (OPTOUT(nsec3flags
))
3185 nsec3flags
&= ~DNS_NSEC3FLAG_OPTOUT
;
3187 nsec3flags
|= DNS_NSEC3FLAG_OPTOUT
;
3191 tryverify
= ISC_TRUE
;
3195 make_keyset
= ISC_TRUE
;
3199 classname
= isc_commandline_argument
;
3203 dsdir
= isc_commandline_argument
;
3204 if (strlen(dsdir
) == 0U)
3205 fatal("DS directory must be non-empty string");
3206 result
= try_dir(dsdir
);
3207 if (result
!= ISC_R_SUCCESS
)
3208 fatal("cannot open directory %s: %s",
3209 dsdir
, isc_result_totext(result
));
3213 output_dnssec_only
= ISC_TRUE
;
3217 engine
= isc_commandline_argument
;
3221 endstr
= isc_commandline_argument
;
3225 output
= isc_commandline_argument
;
3226 if (strcmp(output
, "-") == 0)
3227 output_stdout
= ISC_TRUE
;
3231 generateds
= ISC_TRUE
;
3235 set_iter
= ISC_TRUE
;
3236 nsec3iter
= strtoul(isc_commandline_argument
, &endp
, 0);
3238 fatal("iterations must be numeric");
3239 if (nsec3iter
> 0xffffU
)
3240 fatal("iterations too big");
3244 inputformatstr
= isc_commandline_argument
;
3249 cycle
= strtol(isc_commandline_argument
, &endp
, 0);
3250 if (*endp
!= '\0' || cycle
< 0)
3251 fatal("cycle period must be numeric and "
3257 jitter
= strtol(isc_commandline_argument
, &endp
, 0);
3258 if (*endp
!= '\0' || jitter
< 0)
3259 fatal("jitter must be numeric and positive");
3263 directory
= isc_commandline_argument
;
3267 if (ndskeys
== MAXDSKEYS
)
3268 fatal("too many key-signing keys specified");
3269 dskeyfile
[ndskeys
++] = isc_commandline_argument
;
3275 serialnum
= strtol(isc_commandline_argument
, &endp
, 0);
3276 if (*endp
!= '\0') {
3277 fprintf(stderr
, "source serial number "
3284 len
= strlen(isc_commandline_argument
);
3285 isc_buffer_init(&b
, isc_commandline_argument
, len
);
3286 isc_buffer_add(&b
, len
);
3288 dns_fixedname_init(&dlv_fixed
);
3289 dlv
= dns_fixedname_name(&dlv_fixed
);
3290 result
= dns_name_fromtext(dlv
, &b
, dns_rootname
, 0,
3292 check_result(result
, "dns_name_fromtext(dlv)");
3297 set_maxttl
= ISC_TRUE
;
3298 maxttl
= strtol(isc_commandline_argument
, &endp
, 0);
3299 if (*endp
!= '\0') {
3300 fprintf(stderr
, "maximum TTL "
3310 serialformatstr
= isc_commandline_argument
;
3315 ntasks
= strtol(isc_commandline_argument
, &endp
, 0);
3316 if (*endp
!= '\0' || ntasks
> ISC_INT32_MAX
)
3317 fatal("number of cpus must be numeric");
3321 outputformatstr
= isc_commandline_argument
;
3325 origin
= isc_commandline_argument
;
3329 disable_zone_check
= ISC_TRUE
;
3333 pseudorandom
= ISC_TRUE
;
3337 remove_inactkeysigs
= ISC_TRUE
;
3341 remove_orphansigs
= ISC_TRUE
;
3345 setup_entropy(mctx
, isc_commandline_argument
, &ectx
);
3349 smartsign
= ISC_TRUE
;
3353 startstr
= isc_commandline_argument
;
3358 set_keyttl
= ISC_TRUE
;
3359 keyttl
= strtottl(isc_commandline_argument
);
3363 printstats
= ISC_TRUE
;
3366 case 'U': /* Undocumented for testing only. */
3367 unknownalg
= ISC_TRUE
;
3371 update_chain
= ISC_TRUE
;
3376 verbose
= strtol(isc_commandline_argument
, &endp
, 0);
3378 fatal("verbose level must be numeric");
3382 dnskey_endstr
= isc_commandline_argument
;
3386 keyset_kskonly
= ISC_TRUE
;
3390 ignore_kskflag
= ISC_TRUE
;
3394 /* Reserved for FIPS mode */
3397 if (isc_commandline_option
!= '?')
3398 fprintf(stderr
, "%s: invalid argument -%c\n",
3399 program
, isc_commandline_option
);
3402 /* Does not return. */
3406 /* Does not return. */
3409 case 'Z': /* Undocumented test options */
3410 if (!strcmp(isc_commandline_argument
, "nonsecify"))
3411 nonsecify
= ISC_TRUE
;
3415 fprintf(stderr
, "%s: unhandled option -%c\n",
3416 program
, isc_commandline_option
);
3422 setup_entropy(mctx
, NULL
, &ectx
);
3423 eflags
= ISC_ENTROPY_BLOCKING
;
3425 eflags
|= ISC_ENTROPY_GOODONLY
;
3427 result
= isc_hash_create(mctx
, ectx
, DNS_NAME_MAXWIRE
);
3428 if (result
!= ISC_R_SUCCESS
)
3429 fatal("could not create hash context");
3431 result
= dst_lib_init2(mctx
, ectx
, engine
, eflags
);
3432 if (result
!= ISC_R_SUCCESS
)
3433 fatal("could not initialize dst: %s",
3434 isc_result_totext(result
));
3435 isc_stdtime_get(&now
);
3437 if (startstr
!= NULL
) {
3438 starttime
= strtotime(startstr
, now
, now
, NULL
);
3440 starttime
= now
- 3600; /* Allow for some clock skew. */
3443 endtime
= strtotime(endstr
, now
, starttime
, NULL
);
3445 endtime
= starttime
+ (30 * 24 * 60 * 60);
3447 if (dnskey_endstr
!= NULL
) {
3448 dnskey_endtime
= strtotime(dnskey_endstr
, now
, starttime
,
3450 if (endstr
!= NULL
&& dnskey_endtime
== endtime
)
3451 fprintf(stderr
, "WARNING: -e and -X were both set, "
3452 "but have identical values.\n");
3454 dnskey_endtime
= endtime
;
3457 cycle
= (endtime
- starttime
) / 4;
3460 ntasks
= isc_os_ncpus() * 2;
3461 vbprintf(4, "using %d cpus\n", ntasks
);
3463 rdclass
= strtoclass(classname
);
3465 if (directory
== NULL
)
3468 setup_logging(mctx
, &log
);
3470 argc
-= isc_commandline_index
;
3471 argv
+= isc_commandline_index
;
3484 if (output
== NULL
) {
3485 free_output
= ISC_TRUE
;
3486 output
= isc_mem_allocate(mctx
,
3487 strlen(file
) + strlen(".signed") + 1);
3489 fatal("out of memory");
3490 sprintf(output
, "%s.signed", file
);
3493 if (inputformatstr
!= NULL
) {
3494 if (strcasecmp(inputformatstr
, "text") == 0)
3495 inputformat
= dns_masterformat_text
;
3496 else if (strcasecmp(inputformatstr
, "map") == 0)
3497 inputformat
= dns_masterformat_map
;
3498 else if (strcasecmp(inputformatstr
, "raw") == 0)
3499 inputformat
= dns_masterformat_raw
;
3500 else if (strncasecmp(inputformatstr
, "raw=", 4) == 0) {
3501 inputformat
= dns_masterformat_raw
;
3503 "WARNING: input format version ignored\n");
3505 fatal("unknown file format: %s", inputformatstr
);
3509 if (outputformatstr
!= NULL
) {
3510 if (strcasecmp(outputformatstr
, "text") == 0) {
3511 outputformat
= dns_masterformat_text
;
3512 } else if (strcasecmp(outputformatstr
, "full") == 0) {
3513 outputformat
= dns_masterformat_text
;
3514 masterstyle
= &dns_master_style_full
;
3515 } else if (strcasecmp(outputformatstr
, "map") == 0) {
3516 outputformat
= dns_masterformat_map
;
3517 } else if (strcasecmp(outputformatstr
, "raw") == 0) {
3518 outputformat
= dns_masterformat_raw
;
3519 } else if (strncasecmp(outputformatstr
, "raw=", 4) == 0) {
3521 outputformat
= dns_masterformat_raw
;
3523 outputformat
= dns_masterformat_raw
;
3524 rawversion
= strtol(outputformatstr
+ 4, &end
, 10);
3525 if (end
== outputformatstr
+ 4 || *end
!= '\0' ||
3528 "unknown raw format version\n");
3532 fatal("unknown file format: %s", outputformatstr
);
3535 if (serialformatstr
!= NULL
) {
3536 if (strcasecmp(serialformatstr
, "keep") == 0)
3537 serialformat
= SOA_SERIAL_KEEP
;
3538 else if (strcasecmp(serialformatstr
, "increment") == 0 ||
3539 strcasecmp(serialformatstr
, "incr") == 0)
3540 serialformat
= SOA_SERIAL_INCREMENT
;
3541 else if (strcasecmp(serialformatstr
, "unixtime") == 0)
3542 serialformat
= SOA_SERIAL_UNIXTIME
;
3544 fatal("unknown soa serial format: %s",
3548 if (output_dnssec_only
&& outputformat
!= dns_masterformat_text
)
3549 fatal("option -D can only be used with \"-O text\"");
3551 if (output_dnssec_only
&& serialformat
!= SOA_SERIAL_KEEP
)
3552 fatal("option -D can only be used with \"-N keep\"");
3554 if (output_dnssec_only
&& set_maxttl
)
3555 fatal("option -D cannot be used with -M");
3557 result
= dns_master_stylecreate(&dsstyle
, DNS_STYLEFLAG_NO_TTL
,
3558 0, 24, 0, 0, 0, 8, mctx
);
3559 check_result(result
, "dns_master_stylecreate");
3562 TIME_NOW(&timer_start
);
3563 loadzone(file
, origin
, rdclass
, &gdb
);
3564 gorigin
= dns_db_origin(gdb
);
3565 gclass
= dns_db_class(gdb
);
3568 if (set_maxttl
&& set_keyttl
&& keyttl
> maxttl
) {
3569 fprintf(stderr
, "%s: warning: Specified key TTL %d "
3570 "exceeds maximum zone TTL; reducing to %d\n",
3571 program
, keyttl
, maxttl
);
3579 * Check for any existing NSEC3 parameters in the zone,
3580 * and use them as defaults if -u was not specified.
3582 if (update_chain
&& !set_optout
&& !set_iter
&& !set_salt
)
3583 nsec_datatype
= dns_rdatatype_nsec
;
3585 set_nsec3params(update_chain
, set_salt
, set_optout
, set_iter
);
3588 * We need to do this early on, as we start messing with the list
3589 * of keys rather early.
3591 ISC_LIST_INIT(keylist
);
3592 isc_rwlock_init(&keylist_lock
, 0, 0);
3595 * Fill keylist with:
3596 * 1) Keys listed in the DNSKEY set that have
3597 * private keys associated, *if* no keys were
3598 * set on the command line.
3599 * 2) ZSKs set on the command line
3600 * 3) KSKs set on the command line
3601 * 4) Any keys remaining in the DNSKEY set which
3602 * do not have private keys associated and were
3603 * not specified on the command line.
3605 if (argc
== 0 || smartsign
)
3606 loadzonekeys(!smartsign
, ISC_FALSE
);
3607 loadexplicitkeys(argv
, argc
, ISC_FALSE
);
3608 loadexplicitkeys(dskeyfile
, ndskeys
, ISC_TRUE
);
3609 loadzonekeys(!smartsign
, ISC_TRUE
);
3612 * If we're doing smart signing, look in the key repository for
3613 * key files with metadata, and merge them with the keylist
3617 build_final_keylist();
3619 /* Now enumerate the key list */
3620 for (key
= ISC_LIST_HEAD(keylist
);
3622 key
= ISC_LIST_NEXT(key
, link
)) {
3623 key
->index
= keycount
++;
3626 if (keycount
== 0) {
3627 if (disable_zone_check
)
3628 fprintf(stderr
, "%s: warning: No keys specified "
3629 "or found\n", program
);
3631 fatal("No signing keys specified or found.");
3639 isc_boolean_t answer
;
3641 hash_length
= dns_nsec3_hashlength(dns_hash_sha1
);
3642 hashlist_init(&hashlist
, dns_db_nodecount(gdb
) * 2,
3644 result
= dns_nsec_nseconly(gdb
, gversion
, &answer
);
3645 if (result
== ISC_R_NOTFOUND
)
3646 fprintf(stderr
, "%s: warning: NSEC3 generation "
3647 "requested with no DNSKEY; ignoring\n",
3649 else if (result
!= ISC_R_SUCCESS
)
3650 check_result(result
, "dns_nsec_nseconly");
3652 fatal("NSEC3 generation requested with "
3653 "NSEC-only DNSKEY");
3655 result
= dns_nsec3_maxiterations(gdb
, NULL
, mctx
, &max
);
3656 check_result(result
, "dns_nsec3_maxiterations()");
3657 if (nsec3iter
> max
)
3658 fatal("NSEC3 iterations too big for weakest DNSKEY "
3659 "strength. Maximum iterations allowed %u.", max
);
3663 result
= dns_db_newversion(gdb
, &gversion
);
3664 check_result(result
, "dns_db_newversion()");
3666 switch (serialformat
) {
3667 case SOA_SERIAL_INCREMENT
:
3670 case SOA_SERIAL_UNIXTIME
:
3673 case SOA_SERIAL_KEEP
:
3679 /* Remove duplicates and cap TTLs at maxttl */
3684 nsec3ify(dns_hash_sha1
, nsec3iter
, gsalt
, salt_length
,
3691 writeset("dsset-", dns_rdatatype_ds
);
3693 writeset("keyset-", dns_rdatatype_dnskey
);
3695 writeset("dlvset-", dns_rdatatype_dlv
);
3699 if (output_stdout
) {
3701 if (outputformatstr
== NULL
)
3702 masterstyle
= &dns_master_style_full
;
3704 tempfilelen
= strlen(output
) + 20;
3705 tempfile
= isc_mem_get(mctx
, tempfilelen
);
3706 if (tempfile
== NULL
)
3707 fatal("out of memory");
3709 result
= isc_file_mktemplate(output
, tempfile
, tempfilelen
);
3710 check_result(result
, "isc_file_mktemplate");
3712 if (outputformat
== dns_masterformat_text
)
3713 result
= isc_file_openunique(tempfile
, &outfp
);
3715 result
= isc_file_bopenunique(tempfile
, &outfp
);
3716 if (result
!= ISC_R_SUCCESS
)
3717 fatal("failed to open temporary output file: %s",
3718 isc_result_totext(result
));
3719 removefile
= ISC_TRUE
;
3720 setfatalcallback(&removetempfile
);
3724 print_version(outfp
);
3726 result
= isc_taskmgr_create(mctx
, ntasks
, 0, &taskmgr
);
3727 if (result
!= ISC_R_SUCCESS
)
3728 fatal("failed to create task manager: %s",
3729 isc_result_totext(result
));
3732 result
= isc_task_create(taskmgr
, 0, &master
);
3733 if (result
!= ISC_R_SUCCESS
)
3734 fatal("failed to create task: %s", isc_result_totext(result
));
3736 tasks
= isc_mem_get(mctx
, ntasks
* sizeof(isc_task_t
*));
3738 fatal("out of memory");
3739 for (i
= 0; i
< (int)ntasks
; i
++) {
3741 result
= isc_task_create(taskmgr
, 0, &tasks
[i
]);
3742 if (result
!= ISC_R_SUCCESS
)
3743 fatal("failed to create task: %s",
3744 isc_result_totext(result
));
3747 RUNTIME_CHECK(isc_mutex_init(&namelock
) == ISC_R_SUCCESS
);
3749 RUNTIME_CHECK(isc_mutex_init(&statslock
) == ISC_R_SUCCESS
);
3752 TIME_NOW(&sign_start
);
3756 * There is more work to do. Spread it out over multiple
3757 * processors if possible.
3759 for (i
= 0; i
< (int)ntasks
; i
++) {
3760 result
= isc_app_onrun(mctx
, master
, startworker
,
3762 if (result
!= ISC_R_SUCCESS
)
3763 fatal("failed to start task: %s",
3764 isc_result_totext(result
));
3766 (void)isc_app_run();
3768 fatal("process aborted by user");
3770 isc_task_detach(&master
);
3771 shuttingdown
= ISC_TRUE
;
3772 for (i
= 0; i
< (int)ntasks
; i
++)
3773 isc_task_detach(&tasks
[i
]);
3774 isc_taskmgr_destroy(&taskmgr
);
3775 isc_mem_put(mctx
, tasks
, ntasks
* sizeof(isc_task_t
*));
3777 TIME_NOW(&sign_finish
);
3779 if (!disable_zone_check
)
3780 verifyzone(gdb
, gversion
, gorigin
, mctx
,
3781 ignore_kskflag
, keyset_kskonly
);
3783 if (outputformat
!= dns_masterformat_text
) {
3784 dns_masterrawheader_t header
;
3785 dns_master_initrawheader(&header
);
3786 if (rawversion
== 0U)
3787 header
.flags
= DNS_MASTERRAW_COMPAT
;
3789 header
.flags
= DNS_MASTERRAW_SOURCESERIALSET
;
3790 header
.sourceserial
= serialnum
;
3792 result
= dns_master_dumptostream3(mctx
, gdb
, gversion
,
3793 masterstyle
, outputformat
,
3795 check_result(result
, "dns_master_dumptostream3");
3798 DESTROYLOCK(&namelock
);
3800 DESTROYLOCK(&statslock
);
3802 if (!output_stdout
) {
3803 result
= isc_stdio_close(outfp
);
3804 check_result(result
, "isc_stdio_close");
3805 removefile
= ISC_FALSE
;
3807 result
= isc_file_rename(tempfile
, output
);
3808 if (result
!= ISC_R_SUCCESS
)
3809 fatal("failed to rename temp file to %s: %s",
3810 output
, isc_result_totext(result
));
3812 printf("%s\n", output
);
3815 dns_db_closeversion(gdb
, &gversion
, ISC_FALSE
);
3816 dns_db_detach(&gdb
);
3818 while (!ISC_LIST_EMPTY(keylist
)) {
3819 key
= ISC_LIST_HEAD(keylist
);
3820 ISC_LIST_UNLINK(keylist
, key
, link
);
3821 dns_dnsseckey_destroy(mctx
, &key
);
3824 if (tempfilelen
!= 0)
3825 isc_mem_put(mctx
, tempfile
, tempfilelen
);
3828 isc_mem_free(mctx
, output
);
3830 dns_master_styledestroy(&dsstyle
, mctx
);
3832 cleanup_logging(&log
);
3835 cleanup_entropy(&ectx
);
3838 isc_mem_stats(mctx
, stdout
);
3839 isc_mem_destroy(&mctx
);
3841 (void) isc_app_finish();
3844 TIME_NOW(&timer_finish
);
3845 print_stats(&timer_start
, &timer_finish
,
3846 &sign_start
, &sign_finish
);