1 /* $NetBSD: dnssec-signzone.c,v 1.1.1.4 2009/12/26 22:19:04 christos Exp $ */
4 * Portions Copyright (C) 2004-2009 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.
34 /* Id: dnssec-signzone.c,v 1.258 2009/12/04 22:06:37 tbox Exp */
44 #include <isc/base32.h>
45 #include <isc/commandline.h>
46 #include <isc/entropy.h>
47 #include <isc/event.h>
52 #include <isc/mutex.h>
54 #include <isc/print.h>
55 #include <isc/random.h>
56 #include <isc/rwlock.h>
57 #include <isc/serial.h>
58 #include <isc/stdio.h>
59 #include <isc/stdlib.h>
60 #include <isc/string.h>
66 #include <dns/dbiterator.h>
68 #include <dns/dnssec.h>
70 #include <dns/fixedname.h>
71 #include <dns/keyvalues.h>
73 #include <dns/master.h>
74 #include <dns/masterdump.h>
76 #include <dns/nsec3.h>
77 #include <dns/rdata.h>
78 #include <dns/rdatalist.h>
79 #include <dns/rdataset.h>
80 #include <dns/rdataclass.h>
81 #include <dns/rdatasetiter.h>
82 #include <dns/rdatastruct.h>
83 #include <dns/rdatatype.h>
84 #include <dns/result.h>
90 #include "dnssectool.h"
93 #define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */
96 const char *program
= "dnssec-signzone";
99 typedef struct hashlist hashlist_t
;
101 static int nsec_datatype
= dns_rdatatype_nsec
;
103 #define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
104 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
106 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
111 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
112 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
113 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
115 #define SOA_SERIAL_KEEP 0
116 #define SOA_SERIAL_INCREMENT 1
117 #define SOA_SERIAL_UNIXTIME 2
119 typedef struct signer_event sevent_t
;
120 struct signer_event
{
121 ISC_EVENT_COMMON(sevent_t
);
122 dns_fixedname_t
*fname
;
126 static dns_dnsseckeylist_t keylist
;
127 static unsigned int keycount
= 0;
128 isc_rwlock_t keylist_lock
;
129 static isc_stdtime_t starttime
= 0, endtime
= 0, now
;
130 static int cycle
= -1;
131 static int jitter
= 0;
132 static isc_boolean_t tryverify
= ISC_FALSE
;
133 static isc_boolean_t printstats
= ISC_FALSE
;
134 static isc_mem_t
*mctx
= NULL
;
135 static isc_entropy_t
*ectx
= NULL
;
136 static dns_ttl_t zone_soa_min_ttl
;
137 static dns_ttl_t soa_ttl
;
139 static char *tempfile
= NULL
;
140 static const dns_master_style_t
*masterstyle
;
141 static dns_masterformat_t inputformat
= dns_masterformat_text
;
142 static dns_masterformat_t outputformat
= dns_masterformat_text
;
143 static unsigned int nsigned
= 0, nretained
= 0, ndropped
= 0;
144 static unsigned int nverified
= 0, nverifyfailed
= 0;
145 static const char *directory
= NULL
, *dsdir
= NULL
;
146 static isc_mutex_t namelock
, statslock
;
147 static isc_taskmgr_t
*taskmgr
= NULL
;
148 static dns_db_t
*gdb
; /* The database */
149 static dns_dbversion_t
*gversion
; /* The database version */
150 static dns_dbiterator_t
*gdbiter
; /* The database iterator */
151 static dns_rdataclass_t gclass
; /* The class */
152 static dns_name_t
*gorigin
; /* The database origin */
153 static int nsec3flags
= 0;
154 static dns_iterations_t nsec3iter
= 10U;
155 static unsigned char saltbuf
[255];
156 static unsigned char *salt
= saltbuf
;
157 static size_t salt_length
= 0;
158 static isc_task_t
*master
= NULL
;
159 static unsigned int ntasks
= 0;
160 static isc_boolean_t shuttingdown
= ISC_FALSE
, finished
= ISC_FALSE
;
161 static isc_boolean_t nokeys
= ISC_FALSE
;
162 static isc_boolean_t removefile
= ISC_FALSE
;
163 static isc_boolean_t generateds
= ISC_FALSE
;
164 static isc_boolean_t ignore_kskflag
= ISC_FALSE
;
165 static isc_boolean_t keyset_kskonly
= ISC_FALSE
;
166 static dns_name_t
*dlv
= NULL
;
167 static dns_fixedname_t dlv_fixed
;
168 static dns_master_style_t
*dsstyle
= NULL
;
169 static unsigned int serialformat
= SOA_SERIAL_KEEP
;
170 static unsigned int hash_length
= 0;
171 static isc_boolean_t unknownalg
= ISC_FALSE
;
172 static isc_boolean_t disable_zone_check
= ISC_FALSE
;
173 static isc_boolean_t update_chain
= ISC_FALSE
;
174 static isc_boolean_t set_keyttl
= ISC_FALSE
;
175 static dns_ttl_t keyttl
;
177 #define INCSTAT(counter) \
181 UNLOCK(&statslock); \
185 sign(isc_task_t
*task
, isc_event_t
*event
);
187 #define check_dns_dbiterator_current(result) \
188 check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \
189 "dns_dbiterator_current()")
192 dumpnode(dns_name_t
*name
, dns_dbnode_t
*node
) {
195 if (outputformat
!= dns_masterformat_text
)
197 result
= dns_master_dumpnodetostream(mctx
, gdb
, gversion
, node
, name
,
199 check_result(result
, "dns_master_dumpnodetostream");
203 * Sign the given RRset with given key, and add the signature record to the
207 signwithkey(dns_name_t
*name
, dns_rdataset_t
*rdataset
, dst_key_t
*key
,
208 dns_ttl_t ttl
, dns_diff_t
*add
, const char *logmsg
)
211 isc_stdtime_t jendtime
;
212 char keystr
[DST_KEY_FORMATSIZE
];
213 dns_rdata_t trdata
= DNS_RDATA_INIT
;
214 unsigned char array
[BUFSIZE
];
216 dns_difftuple_t
*tuple
;
218 dst_key_format(key
, keystr
, sizeof(keystr
));
219 vbprintf(1, "\t%s %s\n", logmsg
, keystr
);
221 jendtime
= (jitter
!= 0) ? isc_random_jitter(endtime
, jitter
) : endtime
;
222 isc_buffer_init(&b
, array
, sizeof(array
));
223 result
= dns_dnssec_sign(name
, rdataset
, key
, &starttime
, &jendtime
,
225 isc_entropy_stopcallbacksources(ectx
);
226 if (result
!= ISC_R_SUCCESS
) {
227 char keystr
[DST_KEY_FORMATSIZE
];
228 dst_key_format(key
, keystr
, sizeof(keystr
));
229 fatal("dnskey '%s' failed to sign data: %s",
230 keystr
, isc_result_totext(result
));
235 result
= dns_dnssec_verify(name
, rdataset
, key
,
236 ISC_TRUE
, mctx
, &trdata
);
237 if (result
== ISC_R_SUCCESS
) {
238 vbprintf(3, "\tsignature verified\n");
241 vbprintf(3, "\tsignature failed to verify\n");
242 INCSTAT(nverifyfailed
);
247 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
, name
, ttl
, &trdata
,
249 check_result(result
, "dns_difftuple_create");
250 dns_diff_append(add
, &tuple
);
253 static inline isc_boolean_t
254 issigningkey(dns_dnsseckey_t
*key
) {
255 return (key
->force_sign
|| key
->hint_sign
);
258 static inline isc_boolean_t
259 iszonekey(dns_dnsseckey_t
*key
) {
260 return (ISC_TF(dns_name_equal(dst_key_name(key
->key
), gorigin
) &&
261 dst_key_iszonekey(key
->key
)));
264 static inline isc_boolean_t
265 isksk(dns_dnsseckey_t
*key
) {
269 static inline isc_boolean_t
270 iszsk(dns_dnsseckey_t
*key
) {
271 return (ignore_kskflag
|| !key
->ksk
);
275 * Find the key that generated an RRSIG, if it is in the key list. If
276 * so, return a pointer to it, otherwise return NULL.
278 * No locking is performed here, this must be done by the caller.
280 static dns_dnsseckey_t
*
281 keythatsigned_unlocked(dns_rdata_rrsig_t
*rrsig
) {
282 dns_dnsseckey_t
*key
;
284 for (key
= ISC_LIST_HEAD(keylist
);
286 key
= ISC_LIST_NEXT(key
, link
)) {
287 if (rrsig
->keyid
== dst_key_id(key
->key
) &&
288 rrsig
->algorithm
== dst_key_alg(key
->key
) &&
289 dns_name_equal(&rrsig
->signer
, dst_key_name(key
->key
)))
296 * Finds the key that generated a RRSIG, if possible. First look at the keys
297 * that we've loaded already, and then see if there's a key on disk.
299 static dns_dnsseckey_t
*
300 keythatsigned(dns_rdata_rrsig_t
*rrsig
) {
302 dst_key_t
*pubkey
= NULL
, *privkey
= NULL
;
303 dns_dnsseckey_t
*key
= NULL
;
305 isc_rwlock_lock(&keylist_lock
, isc_rwlocktype_read
);
306 key
= keythatsigned_unlocked(rrsig
);
307 isc_rwlock_unlock(&keylist_lock
, isc_rwlocktype_read
);
312 * We did not find the key in our list. Get a write lock now, since
313 * we may be modifying the bits. We could do the tryupgrade() dance,
314 * but instead just get a write lock and check once again to see if
315 * it is on our list. It's possible someone else may have added it
318 isc_rwlock_lock(&keylist_lock
, isc_rwlocktype_write
);
319 key
= keythatsigned_unlocked(rrsig
);
321 isc_rwlock_unlock(&keylist_lock
, isc_rwlocktype_write
);
325 result
= dst_key_fromfile(&rrsig
->signer
, rrsig
->keyid
,
326 rrsig
->algorithm
, DST_TYPE_PUBLIC
,
327 directory
, mctx
, &pubkey
);
328 if (result
!= ISC_R_SUCCESS
) {
329 isc_rwlock_unlock(&keylist_lock
, isc_rwlocktype_write
);
333 result
= dst_key_fromfile(&rrsig
->signer
, rrsig
->keyid
,
335 DST_TYPE_PUBLIC
| DST_TYPE_PRIVATE
,
336 directory
, mctx
, &privkey
);
337 if (result
== ISC_R_SUCCESS
) {
338 dst_key_free(&pubkey
);
339 dns_dnsseckey_create(mctx
, &privkey
, &key
);
341 dns_dnsseckey_create(mctx
, &pubkey
, &key
);
343 key
->force_publish
= ISC_TRUE
;
344 key
->force_sign
= ISC_FALSE
;
345 ISC_LIST_APPEND(keylist
, key
, link
);
347 isc_rwlock_unlock(&keylist_lock
, isc_rwlocktype_write
);
352 * Check to see if we expect to find a key at this name. If we see a RRSIG
353 * and can't find the signing key that we expect to find, we drop the rrsig.
354 * I'm not sure if this is completely correct, but it seems to work.
357 expecttofindkey(dns_name_t
*name
) {
358 unsigned int options
= DNS_DBFIND_NOWILD
;
359 dns_fixedname_t fname
;
361 char namestr
[DNS_NAME_FORMATSIZE
];
363 dns_fixedname_init(&fname
);
364 result
= dns_db_find(gdb
, name
, gversion
, dns_rdatatype_dnskey
, options
,
365 0, NULL
, dns_fixedname_name(&fname
), NULL
, NULL
);
371 case DNS_R_DELEGATION
:
376 dns_name_format(name
, namestr
, sizeof(namestr
));
377 fatal("failure looking for '%s DNSKEY' in database: %s",
378 namestr
, isc_result_totext(result
));
380 return (ISC_FALSE
); /* removes a warning */
383 static inline isc_boolean_t
384 setverifies(dns_name_t
*name
, dns_rdataset_t
*set
, dst_key_t
*key
,
388 result
= dns_dnssec_verify(name
, set
, key
, ISC_FALSE
, mctx
, rrsig
);
389 if (result
== ISC_R_SUCCESS
) {
393 INCSTAT(nverifyfailed
);
399 * Signs a set. Goes through contortions to decide if each RRSIG should
400 * be dropped or retained, and then determines if any new SIGs need to
404 signset(dns_diff_t
*del
, dns_diff_t
*add
, dns_dbnode_t
*node
, dns_name_t
*name
,
407 dns_rdataset_t sigset
;
408 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
409 dns_rdata_rrsig_t rrsig
;
410 dns_dnsseckey_t
*key
;
412 isc_boolean_t nosigs
= ISC_FALSE
;
413 isc_boolean_t
*wassignedby
, *nowsignedby
;
415 dns_difftuple_t
*tuple
;
418 char namestr
[DNS_NAME_FORMATSIZE
];
419 char typestr
[TYPE_FORMATSIZE
];
420 char sigstr
[SIG_FORMATSIZE
];
422 dns_name_format(name
, namestr
, sizeof(namestr
));
423 type_format(set
->type
, typestr
, sizeof(typestr
));
425 ttl
= ISC_MIN(set
->ttl
, endtime
- starttime
);
427 dns_rdataset_init(&sigset
);
428 result
= dns_db_findrdataset(gdb
, node
, gversion
, dns_rdatatype_rrsig
,
429 set
->type
, 0, &sigset
, NULL
);
430 if (result
== ISC_R_NOTFOUND
) {
431 result
= ISC_R_SUCCESS
;
434 if (result
!= ISC_R_SUCCESS
)
435 fatal("failed while looking for '%s RRSIG %s': %s",
436 namestr
, typestr
, isc_result_totext(result
));
438 vbprintf(1, "%s/%s:\n", namestr
, typestr
);
440 arraysize
= keycount
;
442 arraysize
+= dns_rdataset_count(&sigset
);
443 wassignedby
= isc_mem_get(mctx
, arraysize
* sizeof(isc_boolean_t
));
444 nowsignedby
= isc_mem_get(mctx
, arraysize
* sizeof(isc_boolean_t
));
445 if (wassignedby
== NULL
|| nowsignedby
== NULL
)
446 fatal("out of memory");
448 for (i
= 0; i
< arraysize
; i
++)
449 wassignedby
[i
] = nowsignedby
[i
] = ISC_FALSE
;
452 result
= ISC_R_NOMORE
;
454 result
= dns_rdataset_first(&sigset
);
456 while (result
== ISC_R_SUCCESS
) {
457 isc_boolean_t expired
, future
;
458 isc_boolean_t keep
= ISC_FALSE
, resign
= ISC_FALSE
;
460 dns_rdataset_current(&sigset
, &sigrdata
);
462 result
= dns_rdata_tostruct(&sigrdata
, &rrsig
, NULL
);
463 check_result(result
, "dns_rdata_tostruct");
465 future
= isc_serial_lt(now
, rrsig
.timesigned
);
467 key
= keythatsigned(&rrsig
);
468 sig_format(&rrsig
, sigstr
, sizeof(sigstr
));
469 if (key
!= NULL
&& issigningkey(key
))
470 expired
= isc_serial_gt(now
+ cycle
, rrsig
.timeexpire
);
472 expired
= isc_serial_gt(now
, rrsig
.timeexpire
);
474 if (isc_serial_gt(rrsig
.timesigned
, rrsig
.timeexpire
)) {
475 /* rrsig is dropped and not replaced */
476 vbprintf(2, "\trrsig by %s dropped - "
477 "invalid validity period\n",
479 } else if (key
== NULL
&& !future
&&
480 expecttofindkey(&rrsig
.signer
)) {
481 /* rrsig is dropped and not replaced */
482 vbprintf(2, "\trrsig by %s dropped - "
483 "private dnskey not found\n",
485 } else if (key
== NULL
|| future
) {
486 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
487 expired
? "retained" : "dropped", sigstr
);
490 } else if (issigningkey(key
)) {
491 if (!expired
&& setverifies(name
, set
, key
->key
,
493 vbprintf(2, "\trrsig by %s retained\n", sigstr
);
495 wassignedby
[key
->index
] = ISC_TRUE
;
496 nowsignedby
[key
->index
] = ISC_TRUE
;
498 vbprintf(2, "\trrsig by %s dropped - %s\n",
500 expired
? "expired" :
502 wassignedby
[key
->index
] = ISC_TRUE
;
505 } else if (iszonekey(key
)) {
506 if (!expired
&& setverifies(name
, set
, key
->key
,
508 vbprintf(2, "\trrsig by %s retained\n", sigstr
);
510 wassignedby
[key
->index
] = ISC_TRUE
;
511 nowsignedby
[key
->index
] = ISC_TRUE
;
513 vbprintf(2, "\trrsig by %s dropped - %s\n",
515 expired
? "expired" :
517 wassignedby
[key
->index
] = ISC_TRUE
;
519 } else if (!expired
) {
520 vbprintf(2, "\trrsig by %s retained\n", sigstr
);
523 vbprintf(2, "\trrsig by %s expired\n", sigstr
);
527 nowsignedby
[key
->index
] = ISC_TRUE
;
529 if (sigset
.ttl
!= ttl
) {
530 vbprintf(2, "\tfixing ttl %s\n", sigstr
);
532 result
= dns_difftuple_create(mctx
,
537 check_result(result
, "dns_difftuple_create");
538 dns_diff_append(del
, &tuple
);
539 result
= dns_difftuple_create(mctx
,
544 check_result(result
, "dns_difftuple_create");
545 dns_diff_append(add
, &tuple
);
549 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_DEL
,
552 check_result(result
, "dns_difftuple_create");
553 dns_diff_append(del
, &tuple
);
560 signwithkey(name
, set
, key
->key
, ttl
, add
,
561 "resigning with dnskey");
562 nowsignedby
[key
->index
] = ISC_TRUE
;
565 dns_rdata_reset(&sigrdata
);
566 dns_rdata_freestruct(&rrsig
);
567 result
= dns_rdataset_next(&sigset
);
569 if (result
== ISC_R_NOMORE
)
570 result
= ISC_R_SUCCESS
;
572 check_result(result
, "dns_rdataset_first/next");
573 if (dns_rdataset_isassociated(&sigset
))
574 dns_rdataset_disassociate(&sigset
);
576 for (key
= ISC_LIST_HEAD(keylist
);
578 key
= ISC_LIST_NEXT(key
, link
))
580 if (nowsignedby
[key
->index
])
583 if (!issigningkey(key
))
586 if (set
->type
== dns_rdatatype_dnskey
&&
587 dns_name_equal(name
, gorigin
)) {
588 isc_boolean_t have_ksk
;
589 dns_dnsseckey_t
*tmpkey
;
591 have_ksk
= isksk(key
);
592 for (tmpkey
= ISC_LIST_HEAD(keylist
);
594 tmpkey
= ISC_LIST_NEXT(tmpkey
, link
)) {
595 if (dst_key_alg(key
->key
) !=
596 dst_key_alg(tmpkey
->key
))
598 if (REVOKE(tmpkey
->key
))
603 if (isksk(key
) || !have_ksk
||
604 (iszsk(key
) && !keyset_kskonly
))
605 signwithkey(name
, set
, key
->key
, ttl
, add
,
606 "signing with dnskey");
607 } else if (iszsk(key
)) {
608 signwithkey(name
, set
, key
->key
, ttl
, add
,
609 "signing with dnskey");
613 isc_mem_put(mctx
, wassignedby
, arraysize
* sizeof(isc_boolean_t
));
614 isc_mem_put(mctx
, nowsignedby
, arraysize
* sizeof(isc_boolean_t
));
618 unsigned char *hashbuf
;
625 hashlist_init(hashlist_t
*l
, unsigned int nodes
, unsigned int length
) {
628 l
->length
= length
+ 1;
632 l
->hashbuf
= malloc(l
->size
* l
->length
);
633 if (l
->hashbuf
== NULL
)
642 hashlist_add(hashlist_t
*l
, const unsigned char *hash
, size_t len
)
645 REQUIRE(len
<= l
->length
);
647 if (l
->entries
== l
->size
) {
648 l
->size
= l
->size
* 2 + 100;
649 l
->hashbuf
= realloc(l
->hashbuf
, l
->size
* l
->length
);
651 memset(l
->hashbuf
+ l
->entries
* l
->length
, 0, l
->length
);
652 memcpy(l
->hashbuf
+ l
->entries
* l
->length
, hash
, len
);
657 hashlist_add_dns_name(hashlist_t
*l
, /*const*/ dns_name_t
*name
,
658 unsigned int hashalg
, unsigned int iterations
,
659 const unsigned char *salt
, size_t salt_length
,
660 isc_boolean_t speculative
)
662 char nametext
[DNS_NAME_FORMATSIZE
];
663 unsigned char hash
[NSEC3_MAX_HASH_LENGTH
+ 1];
667 len
= isc_iterated_hash(hash
, hashalg
, iterations
, salt
, salt_length
,
668 name
->ndata
, name
->length
);
670 dns_name_format(name
, nametext
, sizeof nametext
);
671 for (i
= 0 ; i
< len
; i
++)
672 fprintf(stderr
, "%02x", hash
[i
]);
673 fprintf(stderr
, " %s\n", nametext
);
675 hash
[len
++] = speculative
? 1 : 0;
676 hashlist_add(l
, hash
, len
);
680 hashlist_comp(const void *a
, const void *b
) {
681 return (memcmp(a
, b
, hash_length
+ 1));
685 hashlist_sort(hashlist_t
*l
) {
686 qsort(l
->hashbuf
, l
->entries
, l
->length
, hashlist_comp
);
690 hashlist_hasdup(hashlist_t
*l
) {
691 unsigned char *current
;
692 unsigned char *next
= l
->hashbuf
;
693 size_t entries
= l
->entries
;
696 * Skip initial speculative wild card hashs.
698 while (entries
> 0U && next
[l
->length
-1] != 0U) {
704 while (entries
-- > 1U) {
706 if (next
[l
->length
-1] != 0)
708 if (memcmp(current
, next
, l
->length
- 1) == 0)
715 static const unsigned char *
716 hashlist_findnext(const hashlist_t
*l
,
717 const unsigned char hash
[NSEC3_MAX_HASH_LENGTH
])
719 unsigned int entries
= l
->entries
;
720 const unsigned char *next
= bsearch(hash
, l
->hashbuf
, l
->entries
,
721 l
->length
, hashlist_comp
);
722 INSIST(next
!= NULL
);
725 if (next
< l
->hashbuf
+ (l
->entries
- 1) * l
->length
)
729 if (next
[l
->length
- 1] == 0)
731 } while (entries
-- > 1);
732 INSIST(entries
!= 0);
737 hashlist_exists(const hashlist_t
*l
,
738 const unsigned char hash
[NSEC3_MAX_HASH_LENGTH
])
740 if (bsearch(hash
, l
->hashbuf
, l
->entries
, l
->length
, hashlist_comp
))
747 addnowildcardhash(hashlist_t
*l
, /*const*/ dns_name_t
*name
,
748 unsigned int hashalg
, unsigned int iterations
,
749 const unsigned char *salt
, size_t salt_length
)
751 dns_fixedname_t fixed
;
753 dns_dbnode_t
*node
= NULL
;
755 char namestr
[DNS_NAME_FORMATSIZE
];
757 dns_fixedname_init(&fixed
);
758 wild
= dns_fixedname_name(&fixed
);
760 result
= dns_name_concatenate(dns_wildcardname
, name
, wild
, NULL
);
761 if (result
== ISC_R_NOSPACE
)
763 check_result(result
,"addnowildcardhash: dns_name_concatenate()");
765 result
= dns_db_findnode(gdb
, wild
, ISC_FALSE
, &node
);
766 if (result
== ISC_R_SUCCESS
) {
767 dns_db_detachnode(gdb
, &node
);
772 dns_name_format(wild
, namestr
, sizeof(namestr
));
773 fprintf(stderr
, "adding no-wildcardhash for %s\n", namestr
);
776 hashlist_add_dns_name(l
, wild
, hashalg
, iterations
, salt
, salt_length
,
781 opendb(const char *prefix
, dns_name_t
*name
, dns_rdataclass_t rdclass
,
784 char filename
[PATH_MAX
];
788 isc_buffer_init(&b
, filename
, sizeof(filename
));
790 /* allow room for a trailing slash */
791 if (strlen(dsdir
) >= isc_buffer_availablelength(&b
))
792 fatal("path '%s' is too long", dsdir
);
793 isc_buffer_putstr(&b
, dsdir
);
794 if (dsdir
[strlen(dsdir
) - 1] != '/')
795 isc_buffer_putstr(&b
, "/");
797 if (strlen(prefix
) > isc_buffer_availablelength(&b
))
798 fatal("path '%s' is too long", dsdir
);
799 isc_buffer_putstr(&b
, prefix
);
800 result
= dns_name_tofilenametext(name
, ISC_FALSE
, &b
);
801 check_result(result
, "dns_name_tofilenametext()");
802 if (isc_buffer_availablelength(&b
) == 0) {
803 char namestr
[DNS_NAME_FORMATSIZE
];
804 dns_name_format(name
, namestr
, sizeof(namestr
));
805 fatal("name '%s' is too long", namestr
);
807 isc_buffer_putuint8(&b
, 0);
809 result
= dns_db_create(mctx
, "rbt", dns_rootname
, dns_dbtype_zone
,
810 rdclass
, 0, NULL
, dbp
);
811 check_result(result
, "dns_db_create()");
813 result
= dns_db_load3(*dbp
, filename
, inputformat
, DNS_MASTER_HINT
);
814 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_SEENINCLUDE
)
819 * Load the DS set for a child zone, if a dsset-* file can be found.
820 * If not, try to find a keyset-* file from an earlier version of
821 * dnssec-signzone, and build DS records from that.
824 loadds(dns_name_t
*name
, isc_uint32_t ttl
, dns_rdataset_t
*dsset
) {
826 dns_dbversion_t
*ver
= NULL
;
827 dns_dbnode_t
*node
= NULL
;
829 dns_rdataset_t keyset
;
831 unsigned char dsbuf
[DNS_DS_BUFFERSIZE
];
833 dns_difftuple_t
*tuple
= NULL
;
835 opendb("dsset-", name
, gclass
, &db
);
837 result
= dns_db_findnode(db
, name
, ISC_FALSE
, &node
);
838 if (result
== ISC_R_SUCCESS
) {
839 dns_rdataset_init(dsset
);
840 result
= dns_db_findrdataset(db
, node
, NULL
,
841 dns_rdatatype_ds
, 0, 0,
843 dns_db_detachnode(db
, &node
);
844 if (result
== ISC_R_SUCCESS
) {
845 vbprintf(2, "found DS records\n");
854 /* No DS records found; try again, looking for DNSKEY records */
855 opendb("keyset-", name
, gclass
, &db
);
857 return (ISC_R_NOTFOUND
);
860 result
= dns_db_findnode(db
, name
, ISC_FALSE
, &node
);
861 if (result
!= ISC_R_SUCCESS
) {
866 dns_rdataset_init(&keyset
);
867 result
= dns_db_findrdataset(db
, node
, NULL
, dns_rdatatype_dnskey
, 0, 0,
869 if (result
!= ISC_R_SUCCESS
) {
870 dns_db_detachnode(db
, &node
);
874 vbprintf(2, "found DNSKEY records\n");
876 result
= dns_db_newversion(db
, &ver
);
877 check_result(result
, "dns_db_newversion");
878 dns_diff_init(mctx
, &diff
);
880 for (result
= dns_rdataset_first(&keyset
);
881 result
== ISC_R_SUCCESS
;
882 result
= dns_rdataset_next(&keyset
))
884 dns_rdata_init(&key
);
886 dns_rdataset_current(&keyset
, &key
);
887 result
= dns_ds_buildrdata(name
, &key
, DNS_DSDIGEST_SHA1
,
889 check_result(result
, "dns_ds_buildrdata");
891 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
, name
,
893 check_result(result
, "dns_difftuple_create");
894 dns_diff_append(&diff
, &tuple
);
896 dns_rdata_reset(&ds
);
897 result
= dns_ds_buildrdata(name
, &key
, DNS_DSDIGEST_SHA256
,
899 check_result(result
, "dns_ds_buildrdata");
901 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
, name
,
903 check_result(result
, "dns_difftuple_create");
904 dns_diff_append(&diff
, &tuple
);
907 result
= dns_diff_apply(&diff
, db
, ver
);
908 check_result(result
, "dns_diff_apply");
909 dns_diff_clear(&diff
);
911 dns_db_closeversion(db
, &ver
, ISC_TRUE
);
913 result
= dns_db_findrdataset(db
, node
, NULL
, dns_rdatatype_ds
, 0, 0,
915 check_result(result
, "dns_db_findrdataset");
917 dns_rdataset_disassociate(&keyset
);
918 dns_db_detachnode(db
, &node
);
924 delegation(dns_name_t
*name
, dns_dbnode_t
*node
, isc_uint32_t
*ttlp
) {
925 dns_rdataset_t nsset
;
928 if (dns_name_equal(name
, gorigin
))
931 dns_rdataset_init(&nsset
);
932 result
= dns_db_findrdataset(gdb
, node
, gversion
, dns_rdatatype_ns
,
934 if (dns_rdataset_isassociated(&nsset
)) {
937 dns_rdataset_disassociate(&nsset
);
940 return (ISC_TF(result
== ISC_R_SUCCESS
));
944 secure(dns_name_t
*name
, dns_dbnode_t
*node
) {
945 dns_rdataset_t dsset
;
948 if (dns_name_equal(name
, gorigin
))
951 dns_rdataset_init(&dsset
);
952 result
= dns_db_findrdataset(gdb
, node
, gversion
, dns_rdatatype_ds
,
954 if (dns_rdataset_isassociated(&dsset
))
955 dns_rdataset_disassociate(&dsset
);
957 return (ISC_TF(result
== ISC_R_SUCCESS
));
961 * Signs all records at a name.
964 signname(dns_dbnode_t
*node
, dns_name_t
*name
) {
966 dns_rdataset_t rdataset
;
967 dns_rdatasetiter_t
*rdsiter
;
968 isc_boolean_t isdelegation
= ISC_FALSE
;
970 char namestr
[DNS_NAME_FORMATSIZE
];
972 dns_rdataset_init(&rdataset
);
973 dns_name_format(name
, namestr
, sizeof(namestr
));
976 * Determine if this is a delegation point.
978 if (delegation(name
, node
, NULL
))
979 isdelegation
= ISC_TRUE
;
982 * Now iterate through the rdatasets.
984 dns_diff_init(mctx
, &del
);
985 dns_diff_init(mctx
, &add
);
987 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
988 check_result(result
, "dns_db_allrdatasets()");
989 result
= dns_rdatasetiter_first(rdsiter
);
990 while (result
== ISC_R_SUCCESS
) {
991 dns_rdatasetiter_current(rdsiter
, &rdataset
);
993 /* If this is a RRSIG set, skip it. */
994 if (rdataset
.type
== dns_rdatatype_rrsig
)
998 * If this name is a delegation point, skip all records
999 * except NSEC and DS sets. Otherwise check that there
1000 * isn't a DS record.
1003 if (rdataset
.type
!= nsec_datatype
&&
1004 rdataset
.type
!= dns_rdatatype_ds
)
1006 } else if (rdataset
.type
== dns_rdatatype_ds
) {
1007 char namebuf
[DNS_NAME_FORMATSIZE
];
1008 dns_name_format(name
, namebuf
, sizeof(namebuf
));
1009 fatal("'%s': found DS RRset without NS RRset\n",
1013 signset(&del
, &add
, node
, name
, &rdataset
);
1016 dns_rdataset_disassociate(&rdataset
);
1017 result
= dns_rdatasetiter_next(rdsiter
);
1019 if (result
!= ISC_R_NOMORE
)
1020 fatal("rdataset iteration for name '%s' failed: %s",
1021 namestr
, isc_result_totext(result
));
1023 dns_rdatasetiter_destroy(&rdsiter
);
1025 result
= dns_diff_applysilently(&del
, gdb
, gversion
);
1026 if (result
!= ISC_R_SUCCESS
)
1027 fatal("failed to delete SIGs at node '%s': %s",
1028 namestr
, isc_result_totext(result
));
1030 result
= dns_diff_applysilently(&add
, gdb
, gversion
);
1031 if (result
!= ISC_R_SUCCESS
)
1032 fatal("failed to add SIGs at node '%s': %s",
1033 namestr
, isc_result_totext(result
));
1035 dns_diff_clear(&del
);
1036 dns_diff_clear(&add
);
1039 static inline isc_boolean_t
1040 active_node(dns_dbnode_t
*node
) {
1041 dns_rdatasetiter_t
*rdsiter
= NULL
;
1042 dns_rdatasetiter_t
*rdsiter2
= NULL
;
1043 isc_boolean_t active
= ISC_FALSE
;
1044 isc_result_t result
;
1045 dns_rdataset_t rdataset
;
1046 dns_rdatatype_t type
;
1047 dns_rdatatype_t covers
;
1048 isc_boolean_t found
;
1050 dns_rdataset_init(&rdataset
);
1051 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
1052 check_result(result
, "dns_db_allrdatasets()");
1053 result
= dns_rdatasetiter_first(rdsiter
);
1054 while (result
== ISC_R_SUCCESS
) {
1055 dns_rdatasetiter_current(rdsiter
, &rdataset
);
1056 if (rdataset
.type
!= dns_rdatatype_nsec
&&
1057 rdataset
.type
!= dns_rdatatype_nsec3
&&
1058 rdataset
.type
!= dns_rdatatype_rrsig
)
1060 dns_rdataset_disassociate(&rdataset
);
1062 result
= dns_rdatasetiter_next(rdsiter
);
1064 result
= ISC_R_NOMORE
;
1066 if (result
!= ISC_R_NOMORE
)
1067 fatal("rdataset iteration failed: %s",
1068 isc_result_totext(result
));
1070 if (!active
&& nsec_datatype
== dns_rdatatype_nsec
) {
1072 * The node is empty of everything but NSEC / RRSIG records.
1074 for (result
= dns_rdatasetiter_first(rdsiter
);
1075 result
== ISC_R_SUCCESS
;
1076 result
= dns_rdatasetiter_next(rdsiter
)) {
1077 dns_rdatasetiter_current(rdsiter
, &rdataset
);
1078 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1081 check_result(result
, "dns_db_deleterdataset()");
1082 dns_rdataset_disassociate(&rdataset
);
1084 if (result
!= ISC_R_NOMORE
)
1085 fatal("rdataset iteration failed: %s",
1086 isc_result_totext(result
));
1089 * Delete RRSIGs for types that no longer exist.
1091 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter2
);
1092 check_result(result
, "dns_db_allrdatasets()");
1093 for (result
= dns_rdatasetiter_first(rdsiter
);
1094 result
== ISC_R_SUCCESS
;
1095 result
= dns_rdatasetiter_next(rdsiter
)) {
1096 dns_rdatasetiter_current(rdsiter
, &rdataset
);
1097 type
= rdataset
.type
;
1098 covers
= rdataset
.covers
;
1099 dns_rdataset_disassociate(&rdataset
);
1101 * Delete the NSEC chain if we are signing with
1104 if (nsec_datatype
== dns_rdatatype_nsec3
&&
1105 (type
== dns_rdatatype_nsec
||
1106 covers
== dns_rdatatype_nsec
)) {
1107 result
= dns_db_deleterdataset(gdb
, node
,
1110 check_result(result
,
1111 "dns_db_deleterdataset(nsec/rrsig)");
1114 if (type
!= dns_rdatatype_rrsig
)
1117 for (result
= dns_rdatasetiter_first(rdsiter2
);
1118 !found
&& result
== ISC_R_SUCCESS
;
1119 result
= dns_rdatasetiter_next(rdsiter2
)) {
1120 dns_rdatasetiter_current(rdsiter2
, &rdataset
);
1121 if (rdataset
.type
== covers
)
1123 dns_rdataset_disassociate(&rdataset
);
1126 if (result
!= ISC_R_NOMORE
)
1127 fatal("rdataset iteration failed: %s",
1128 isc_result_totext(result
));
1129 result
= dns_db_deleterdataset(gdb
, node
,
1132 check_result(result
,
1133 "dns_db_deleterdataset(rrsig)");
1134 } else if (result
!= ISC_R_NOMORE
&&
1135 result
!= ISC_R_SUCCESS
)
1136 fatal("rdataset iteration failed: %s",
1137 isc_result_totext(result
));
1139 if (result
!= ISC_R_NOMORE
)
1140 fatal("rdataset iteration failed: %s",
1141 isc_result_totext(result
));
1142 dns_rdatasetiter_destroy(&rdsiter2
);
1144 dns_rdatasetiter_destroy(&rdsiter
);
1150 * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
1153 get_soa_ttls(void) {
1154 dns_rdataset_t soaset
;
1155 dns_fixedname_t fname
;
1157 isc_result_t result
;
1158 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1160 dns_fixedname_init(&fname
);
1161 name
= dns_fixedname_name(&fname
);
1162 dns_rdataset_init(&soaset
);
1163 result
= dns_db_find(gdb
, gorigin
, gversion
, dns_rdatatype_soa
,
1164 0, 0, NULL
, name
, &soaset
, NULL
);
1165 if (result
!= ISC_R_SUCCESS
)
1166 fatal("failed to find an SOA at the zone apex: %s",
1167 isc_result_totext(result
));
1169 result
= dns_rdataset_first(&soaset
);
1170 check_result(result
, "dns_rdataset_first");
1171 dns_rdataset_current(&soaset
, &rdata
);
1172 zone_soa_min_ttl
= dns_soa_getminimum(&rdata
);
1173 soa_ttl
= soaset
.ttl
;
1174 dns_rdataset_disassociate(&soaset
);
1178 * Increment (or set if nonzero) the SOA serial
1181 setsoaserial(isc_uint32_t serial
) {
1182 isc_result_t result
;
1183 dns_dbnode_t
*node
= NULL
;
1184 dns_rdataset_t rdataset
;
1185 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1186 isc_uint32_t old_serial
, new_serial
;
1188 result
= dns_db_getoriginnode(gdb
, &node
);
1189 if (result
!= ISC_R_SUCCESS
)
1192 dns_rdataset_init(&rdataset
);
1194 result
= dns_db_findrdataset(gdb
, node
, gversion
,
1195 dns_rdatatype_soa
, 0,
1196 0, &rdataset
, NULL
);
1197 if (result
!= ISC_R_SUCCESS
)
1200 result
= dns_rdataset_first(&rdataset
);
1201 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1203 dns_rdataset_current(&rdataset
, &rdata
);
1205 old_serial
= dns_soa_getserial(&rdata
);
1208 /* Set SOA serial to the value provided. */
1209 new_serial
= serial
;
1211 /* Increment SOA serial using RFC 1982 arithmetics */
1212 new_serial
= (old_serial
+ 1) & 0xFFFFFFFF;
1213 if (new_serial
== 0)
1217 /* If the new serial is not likely to cause a zone transfer
1218 * (a/ixfr) from servers having the old serial, warn the user.
1220 * RFC1982 section 7 defines the maximum increment to be
1221 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1222 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1224 if (new_serial
== old_serial
||
1225 (new_serial
- old_serial
) > 0x7fffffffU
)
1226 fprintf(stderr
, "%s: warning: Serial number not advanced, "
1227 "zone may not transfer\n", program
);
1229 dns_soa_setserial(new_serial
, &rdata
);
1231 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1232 dns_rdatatype_soa
, 0);
1233 check_result(result
, "dns_db_deleterdataset");
1234 if (result
!= ISC_R_SUCCESS
)
1237 result
= dns_db_addrdataset(gdb
, node
, gversion
,
1238 0, &rdataset
, 0, NULL
);
1239 check_result(result
, "dns_db_addrdataset");
1240 if (result
!= ISC_R_SUCCESS
)
1244 dns_rdataset_disassociate(&rdataset
);
1246 dns_db_detachnode(gdb
, &node
);
1247 dns_rdata_reset(&rdata
);
1253 * Delete any RRSIG records at a node.
1256 cleannode(dns_db_t
*db
, dns_dbversion_t
*version
, dns_dbnode_t
*node
) {
1257 dns_rdatasetiter_t
*rdsiter
= NULL
;
1259 isc_result_t result
, dresult
;
1261 if (outputformat
!= dns_masterformat_text
|| !disable_zone_check
)
1264 dns_rdataset_init(&set
);
1265 result
= dns_db_allrdatasets(db
, node
, version
, 0, &rdsiter
);
1266 check_result(result
, "dns_db_allrdatasets");
1267 result
= dns_rdatasetiter_first(rdsiter
);
1268 while (result
== ISC_R_SUCCESS
) {
1269 isc_boolean_t destroy
= ISC_FALSE
;
1270 dns_rdatatype_t covers
= 0;
1271 dns_rdatasetiter_current(rdsiter
, &set
);
1272 if (set
.type
== dns_rdatatype_rrsig
) {
1273 covers
= set
.covers
;
1276 dns_rdataset_disassociate(&set
);
1277 result
= dns_rdatasetiter_next(rdsiter
);
1279 dresult
= dns_db_deleterdataset(db
, node
, version
,
1280 dns_rdatatype_rrsig
,
1282 check_result(dresult
, "dns_db_deleterdataset");
1285 if (result
!= ISC_R_NOMORE
)
1286 fatal("rdataset iteration failed: %s",
1287 isc_result_totext(result
));
1288 dns_rdatasetiter_destroy(&rdsiter
);
1292 * Set up the iterator and global state before starting the tasks.
1296 isc_result_t result
;
1299 result
= dns_db_createiterator(gdb
, 0, &gdbiter
);
1300 check_result(result
, "dns_db_createiterator()");
1304 * Clean up the iterator and global state after the tasks complete.
1308 dns_dbiterator_destroy(&gdbiter
);
1311 static isc_boolean_t
1312 goodsig(dns_rdata_t
*sigrdata
, dns_name_t
*name
, dns_rdataset_t
*keyrdataset
,
1313 dns_rdataset_t
*rdataset
)
1315 dns_rdata_dnskey_t key
;
1316 dns_rdata_rrsig_t sig
;
1317 dst_key_t
*dstkey
= NULL
;
1318 isc_result_t result
;
1320 dns_rdata_tostruct(sigrdata
, &sig
, NULL
);
1322 for (result
= dns_rdataset_first(keyrdataset
);
1323 result
== ISC_R_SUCCESS
;
1324 result
= dns_rdataset_next(keyrdataset
)) {
1325 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1326 dns_rdataset_current(keyrdataset
, &rdata
);
1327 dns_rdata_tostruct(&rdata
, &key
, NULL
);
1328 result
= dns_dnssec_keyfromrdata(gorigin
, &rdata
, mctx
,
1330 if (result
!= ISC_R_SUCCESS
)
1332 if (sig
.algorithm
!= key
.algorithm
||
1333 sig
.keyid
!= dst_key_id(dstkey
) ||
1334 !dns_name_equal(&sig
.signer
, gorigin
)) {
1335 dst_key_free(&dstkey
);
1338 result
= dns_dnssec_verify(name
, rdataset
, dstkey
, ISC_FALSE
,
1340 dst_key_free(&dstkey
);
1341 if (result
== ISC_R_SUCCESS
)
1348 verifyset(dns_rdataset_t
*rdataset
, dns_name_t
*name
, dns_dbnode_t
*node
,
1349 dns_rdataset_t
*keyrdataset
, unsigned char *ksk_algorithms
,
1350 unsigned char *bad_algorithms
)
1352 unsigned char set_algorithms
[256];
1353 char namebuf
[DNS_NAME_FORMATSIZE
];
1356 dns_rdataset_t sigrdataset
;
1357 dns_rdatasetiter_t
*rdsiter
= NULL
;
1358 isc_result_t result
;
1361 dns_rdataset_init(&sigrdataset
);
1362 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
1363 check_result(result
, "dns_db_allrdatasets()");
1364 for (result
= dns_rdatasetiter_first(rdsiter
);
1365 result
== ISC_R_SUCCESS
;
1366 result
= dns_rdatasetiter_next(rdsiter
)) {
1367 dns_rdatasetiter_current(rdsiter
, &sigrdataset
);
1368 if (sigrdataset
.type
== dns_rdatatype_rrsig
&&
1369 sigrdataset
.covers
== rdataset
->type
)
1371 dns_rdataset_disassociate(&sigrdataset
);
1373 if (result
!= ISC_R_SUCCESS
) {
1374 dns_name_format(name
, namebuf
, sizeof(namebuf
));
1375 type_format(rdataset
->type
, typebuf
, sizeof(typebuf
));
1376 fprintf(stderr
, "no signatures for %s/%s\n", namebuf
, typebuf
);
1377 for (i
= 0; i
< 256; i
++)
1378 if (ksk_algorithms
[i
] != 0)
1379 bad_algorithms
[i
] = 1;
1383 memset(set_algorithms
, 0, sizeof(set_algorithms
));
1384 for (result
= dns_rdataset_first(&sigrdataset
);
1385 result
== ISC_R_SUCCESS
;
1386 result
= dns_rdataset_next(&sigrdataset
)) {
1387 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1388 dns_rdata_rrsig_t sig
;
1390 dns_rdataset_current(&sigrdataset
, &rdata
);
1391 dns_rdata_tostruct(&rdata
, &sig
, NULL
);
1392 if ((set_algorithms
[sig
.algorithm
] != 0) ||
1393 (ksk_algorithms
[sig
.algorithm
] == 0))
1395 if (goodsig(&rdata
, name
, keyrdataset
, rdataset
))
1396 set_algorithms
[sig
.algorithm
] = 1;
1398 dns_rdatasetiter_destroy(&rdsiter
);
1399 if (memcmp(set_algorithms
, ksk_algorithms
, sizeof(set_algorithms
))) {
1400 dns_name_format(name
, namebuf
, sizeof(namebuf
));
1401 type_format(rdataset
->type
, typebuf
, sizeof(typebuf
));
1402 for (i
= 0; i
< 256; i
++)
1403 if ((ksk_algorithms
[i
] != 0) &&
1404 (set_algorithms
[i
] == 0)) {
1405 dns_secalg_format(i
, algbuf
, sizeof(algbuf
));
1406 fprintf(stderr
, "Missing %s signature for "
1407 "%s %s\n", algbuf
, namebuf
, typebuf
);
1408 bad_algorithms
[i
] = 1;
1411 dns_rdataset_disassociate(&sigrdataset
);
1415 verifynode(dns_name_t
*name
, dns_dbnode_t
*node
, isc_boolean_t delegation
,
1416 dns_rdataset_t
*keyrdataset
, unsigned char *ksk_algorithms
,
1417 unsigned char *bad_algorithms
)
1419 dns_rdataset_t rdataset
;
1420 dns_rdatasetiter_t
*rdsiter
= NULL
;
1421 isc_result_t result
;
1423 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
1424 check_result(result
, "dns_db_allrdatasets()");
1425 result
= dns_rdatasetiter_first(rdsiter
);
1426 dns_rdataset_init(&rdataset
);
1427 while (result
== ISC_R_SUCCESS
) {
1428 dns_rdatasetiter_current(rdsiter
, &rdataset
);
1429 if (rdataset
.type
!= dns_rdatatype_rrsig
&&
1430 rdataset
.type
!= dns_rdatatype_dnskey
&&
1431 (!delegation
|| rdataset
.type
== dns_rdatatype_ds
||
1432 rdataset
.type
== dns_rdatatype_nsec
)) {
1433 verifyset(&rdataset
, name
, node
, keyrdataset
,
1434 ksk_algorithms
, bad_algorithms
);
1436 dns_rdataset_disassociate(&rdataset
);
1437 result
= dns_rdatasetiter_next(rdsiter
);
1439 if (result
!= ISC_R_NOMORE
)
1440 fatal("rdataset iteration failed: %s",
1441 isc_result_totext(result
));
1442 dns_rdatasetiter_destroy(&rdsiter
);
1446 * Verify that certain things are sane:
1448 * The apex has a DNSKEY record with at least one KSK, and at least
1449 * one ZSK if the -x flag was not used.
1451 * The DNSKEY record was signed with at least one of the KSKs in this
1454 * The rest of the zone was signed with at least one of the ZSKs
1455 * present in the DNSKEY RRSET.
1460 dns_dbiterator_t
*dbiter
= NULL
;
1461 dns_dbnode_t
*node
= NULL
, *nextnode
= NULL
;
1462 dns_fixedname_t fname
, fnextname
, fzonecut
;
1463 dns_name_t
*name
, *nextname
, *zonecut
;
1464 dns_rdata_dnskey_t dnskey
;
1465 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1466 dns_rdataset_t rdataset
;
1467 dns_rdataset_t sigrdataset
;
1469 isc_boolean_t done
= ISC_FALSE
;
1470 isc_boolean_t first
= ISC_TRUE
;
1471 isc_boolean_t goodksk
= ISC_FALSE
;
1472 isc_boolean_t goodzsk
= ISC_FALSE
;
1473 isc_result_t result
;
1474 unsigned char revoked_ksk
[256];
1475 unsigned char revoked_zsk
[256];
1476 unsigned char standby_ksk
[256];
1477 unsigned char standby_zsk
[256];
1478 unsigned char ksk_algorithms
[256];
1479 unsigned char zsk_algorithms
[256];
1480 unsigned char bad_algorithms
[256];
1481 #ifdef ALLOW_KSKLESS_ZONES
1482 isc_boolean_t allzsksigned
= ISC_TRUE
;
1483 unsigned char self_algorithms
[256];
1486 if (disable_zone_check
)
1489 result
= dns_db_findnode(gdb
, gorigin
, ISC_FALSE
, &node
);
1490 if (result
!= ISC_R_SUCCESS
)
1491 fatal("failed to find the zone's origin: %s",
1492 isc_result_totext(result
));
1494 dns_rdataset_init(&rdataset
);
1495 dns_rdataset_init(&sigrdataset
);
1496 result
= dns_db_findrdataset(gdb
, node
, gversion
,
1497 dns_rdatatype_dnskey
,
1498 0, 0, &rdataset
, &sigrdataset
);
1499 dns_db_detachnode(gdb
, &node
);
1500 if (result
!= ISC_R_SUCCESS
)
1501 fatal("cannot find DNSKEY rrset\n");
1503 if (!dns_rdataset_isassociated(&sigrdataset
))
1504 fatal("cannot find DNSKEY RRSIGs\n");
1506 memset(revoked_ksk
, 0, sizeof(revoked_ksk
));
1507 memset(revoked_zsk
, 0, sizeof(revoked_zsk
));
1508 memset(standby_ksk
, 0, sizeof(standby_ksk
));
1509 memset(standby_zsk
, 0, sizeof(standby_zsk
));
1510 memset(ksk_algorithms
, 0, sizeof(ksk_algorithms
));
1511 memset(zsk_algorithms
, 0, sizeof(zsk_algorithms
));
1512 memset(bad_algorithms
, 0, sizeof(bad_algorithms
));
1513 #ifdef ALLOW_KSKLESS_ZONES
1514 memset(self_algorithms
, 0, sizeof(self_algorithms
));
1518 * Check that the DNSKEY RR has at least one self signing KSK
1519 * and one ZSK per algorithm in it (or, if -x was used, one
1520 * self-signing KSK).
1522 for (result
= dns_rdataset_first(&rdataset
);
1523 result
== ISC_R_SUCCESS
;
1524 result
= dns_rdataset_next(&rdataset
)) {
1525 dns_rdataset_current(&rdataset
, &rdata
);
1526 result
= dns_rdata_tostruct(&rdata
, &dnskey
, NULL
);
1527 check_result(result
, "dns_rdata_tostruct");
1529 if ((dnskey
.flags
& DNS_KEYOWNER_ZONE
) == 0)
1531 else if ((dnskey
.flags
& DNS_KEYFLAG_REVOKE
) != 0) {
1532 if ((dnskey
.flags
& DNS_KEYFLAG_KSK
) != 0 &&
1533 !dns_dnssec_selfsigns(&rdata
, gorigin
, &rdataset
,
1534 &sigrdataset
, ISC_FALSE
,
1536 char namebuf
[DNS_NAME_FORMATSIZE
];
1540 dns_name_format(gorigin
, namebuf
,
1542 isc_buffer_init(&buf
, buffer
, sizeof(buffer
));
1543 result
= dns_rdata_totext(&rdata
, NULL
, &buf
);
1544 check_result(result
, "dns_rdata_totext");
1545 fatal("revoked KSK is not self signed:\n"
1546 "%s DNSKEY %.*s", namebuf
,
1547 (int)isc_buffer_usedlength(&buf
), buffer
);
1549 if ((dnskey
.flags
& DNS_KEYFLAG_KSK
) != 0 &&
1550 revoked_ksk
[dnskey
.algorithm
] != 255)
1551 revoked_ksk
[dnskey
.algorithm
]++;
1552 else if ((dnskey
.flags
& DNS_KEYFLAG_KSK
) == 0 &&
1553 revoked_zsk
[dnskey
.algorithm
] != 255)
1554 revoked_zsk
[dnskey
.algorithm
]++;
1555 } else if ((dnskey
.flags
& DNS_KEYFLAG_KSK
) != 0) {
1556 if (dns_dnssec_selfsigns(&rdata
, gorigin
, &rdataset
,
1557 &sigrdataset
, ISC_FALSE
, mctx
)) {
1558 if (ksk_algorithms
[dnskey
.algorithm
] != 255)
1559 ksk_algorithms
[dnskey
.algorithm
]++;
1562 if (standby_ksk
[dnskey
.algorithm
] != 255)
1563 standby_ksk
[dnskey
.algorithm
]++;
1565 } else if (dns_dnssec_selfsigns(&rdata
, gorigin
, &rdataset
,
1566 &sigrdataset
, ISC_FALSE
,
1568 #ifdef ALLOW_KSKLESS_ZONES
1569 if (self_algorithms
[dnskey
.algorithm
] != 255)
1570 self_algorithms
[dnskey
.algorithm
]++;
1572 if (zsk_algorithms
[dnskey
.algorithm
] != 255)
1573 zsk_algorithms
[dnskey
.algorithm
]++;
1576 if (standby_zsk
[dnskey
.algorithm
] != 255)
1577 standby_zsk
[dnskey
.algorithm
]++;
1578 #ifdef ALLOW_KSKLESS_ZONES
1579 allzsksigned
= ISC_FALSE
;
1582 dns_rdata_freestruct(&dnskey
);
1583 dns_rdata_reset(&rdata
);
1585 dns_rdataset_disassociate(&sigrdataset
);
1587 #ifdef ALLOW_KSKLESS_ZONES
1589 if (!ignore_kskflag
)
1590 fprintf(stderr
, "No self signing KSK found. Using "
1591 "self signed ZSK's for active "
1592 "algorithm list.\n");
1593 memcpy(ksk_algorithms
, self_algorithms
, sizeof(ksk_algorithms
));
1595 fprintf(stderr
, "warning: not all ZSK's are self "
1600 fatal("no self signed KSK's found");
1604 fprintf(stderr
, "Verifying the zone using the following algorithms:");
1605 for (i
= 0; i
< 256; i
++) {
1606 #ifdef ALLOW_KSKLESS_ZONES
1607 if (ksk_algorithms
[i
] != 0 || zsk_algorithms
[i
] != 0)
1609 if (ksk_algorithms
[i
] != 0)
1612 dns_secalg_format(i
, algbuf
, sizeof(algbuf
));
1613 fprintf(stderr
, " %s", algbuf
);
1616 fprintf(stderr
, ".\n");
1618 if (!ignore_kskflag
&& !keyset_kskonly
) {
1619 for (i
= 0; i
< 256; i
++) {
1621 * The counts should both be zero or both be non-zero.
1622 * Mark the algorithm as bad if this is not met.
1624 if ((ksk_algorithms
[i
] != 0) ==
1625 (zsk_algorithms
[i
] != 0))
1627 dns_secalg_format(i
, algbuf
, sizeof(algbuf
));
1628 fprintf(stderr
, "Missing %s for algorithm %s\n",
1629 (ksk_algorithms
[i
] != 0)
1631 : "self signing KSK",
1633 bad_algorithms
[i
] = 1;
1638 * Check that all the other records were signed by keys that are
1639 * present in the DNSKEY RRSET.
1642 dns_fixedname_init(&fname
);
1643 name
= dns_fixedname_name(&fname
);
1644 dns_fixedname_init(&fnextname
);
1645 nextname
= dns_fixedname_name(&fnextname
);
1646 dns_fixedname_init(&fzonecut
);
1649 result
= dns_db_createiterator(gdb
, DNS_DB_NONSEC3
, &dbiter
);
1650 check_result(result
, "dns_db_createiterator()");
1652 result
= dns_dbiterator_first(dbiter
);
1653 check_result(result
, "dns_dbiterator_first()");
1656 isc_boolean_t isdelegation
= ISC_FALSE
;
1658 result
= dns_dbiterator_current(dbiter
, &node
, name
);
1659 check_dns_dbiterator_current(result
);
1660 if (delegation(name
, node
, NULL
)) {
1661 zonecut
= dns_fixedname_name(&fzonecut
);
1662 dns_name_copy(name
, zonecut
, NULL
);
1663 isdelegation
= ISC_TRUE
;
1665 verifynode(name
, node
, isdelegation
, &rdataset
,
1666 ksk_algorithms
, bad_algorithms
);
1667 result
= dns_dbiterator_next(dbiter
);
1669 while (result
== ISC_R_SUCCESS
) {
1670 result
= dns_dbiterator_current(dbiter
, &nextnode
,
1672 check_dns_dbiterator_current(result
);
1673 if (!dns_name_issubdomain(nextname
, gorigin
) ||
1675 dns_name_issubdomain(nextname
, zonecut
)))
1677 dns_db_detachnode(gdb
, &nextnode
);
1678 result
= dns_dbiterator_next(dbiter
);
1681 dns_db_detachnode(gdb
, &nextnode
);
1684 if (result
== ISC_R_NOMORE
) {
1686 } else if (result
!= ISC_R_SUCCESS
)
1687 fatal("iterating through the database failed: %s",
1688 isc_result_totext(result
));
1689 dns_db_detachnode(gdb
, &node
);
1692 dns_dbiterator_destroy(&dbiter
);
1694 result
= dns_db_createiterator(gdb
, DNS_DB_NSEC3ONLY
, &dbiter
);
1695 check_result(result
, "dns_db_createiterator()");
1697 for (result
= dns_dbiterator_first(dbiter
);
1698 result
== ISC_R_SUCCESS
;
1699 result
= dns_dbiterator_next(dbiter
) ) {
1700 result
= dns_dbiterator_current(dbiter
, &node
, name
);
1701 check_dns_dbiterator_current(result
);
1702 verifynode(name
, node
, ISC_FALSE
, &rdataset
,
1703 ksk_algorithms
, bad_algorithms
);
1704 dns_db_detachnode(gdb
, &node
);
1706 dns_dbiterator_destroy(&dbiter
);
1708 dns_rdataset_disassociate(&rdataset
);
1711 * If we made it this far, we have what we consider a properly signed
1712 * zone. Set the good flag.
1714 for (i
= 0; i
< 256; i
++) {
1715 if (bad_algorithms
[i
] != 0) {
1717 fprintf(stderr
, "The zone is not fully signed "
1718 "for the following algorithms:");
1719 dns_secalg_format(i
, algbuf
, sizeof(algbuf
));
1720 fprintf(stderr
, " %s", algbuf
);
1725 fprintf(stderr
, ".\n");
1726 fatal("DNSSEC completeness test failed.");
1729 if (goodksk
|| ignore_kskflag
) {
1731 * Print the success summary.
1733 fprintf(stderr
, "Zone signing complete:\n");
1734 for (i
= 0; i
< 256; i
++) {
1735 if ((ksk_algorithms
[i
] != 0) ||
1736 (standby_ksk
[i
] != 0) ||
1737 (revoked_zsk
[i
] != 0) ||
1738 (zsk_algorithms
[i
] != 0) ||
1739 (standby_zsk
[i
] != 0) ||
1740 (revoked_zsk
[i
] != 0)) {
1741 dns_secalg_format(i
, algbuf
, sizeof(algbuf
));
1742 fprintf(stderr
, "Algorithm: %s: KSKs: "
1743 "%u active, %u stand-by, %u revoked\n",
1744 algbuf
, ksk_algorithms
[i
],
1745 standby_ksk
[i
], revoked_ksk
[i
]);
1746 fprintf(stderr
, "%*sZSKs: "
1747 "%u active, %u %s, %u revoked\n",
1748 (int) strlen(algbuf
) + 13, "",
1751 keyset_kskonly
? "present" : "stand-by",
1759 * Sign the apex of the zone.
1760 * Note the origin may not be the first node if there are out of zone
1765 dns_dbnode_t
*node
= NULL
;
1766 dns_fixedname_t fixed
;
1768 isc_result_t result
;
1770 dns_fixedname_init(&fixed
);
1771 name
= dns_fixedname_name(&fixed
);
1772 result
= dns_dbiterator_seek(gdbiter
, gorigin
);
1773 check_result(result
, "dns_dbiterator_seek()");
1774 result
= dns_dbiterator_current(gdbiter
, &node
, name
);
1775 check_dns_dbiterator_current(result
);
1776 signname(node
, name
);
1777 dumpnode(name
, node
);
1778 cleannode(gdb
, gversion
, node
);
1779 dns_db_detachnode(gdb
, &node
);
1780 result
= dns_dbiterator_first(gdbiter
);
1781 if (result
== ISC_R_NOMORE
)
1782 finished
= ISC_TRUE
;
1783 else if (result
!= ISC_R_SUCCESS
)
1784 fatal("failure iterating database: %s",
1785 isc_result_totext(result
));
1789 * Assigns a node to a worker thread. This is protected by the master task's
1793 assignwork(isc_task_t
*task
, isc_task_t
*worker
) {
1794 dns_fixedname_t
*fname
;
1798 dns_rdataset_t nsec
;
1799 isc_boolean_t found
;
1800 isc_result_t result
;
1801 static dns_name_t
*zonecut
= NULL
; /* Protected by namelock. */
1802 static dns_fixedname_t fzonecut
; /* Protected by namelock. */
1803 static unsigned int ended
= 0; /* Protected by namelock. */
1811 if (ended
== ntasks
) {
1812 isc_task_detach(&task
);
1818 fname
= isc_mem_get(mctx
, sizeof(dns_fixedname_t
));
1820 fatal("out of memory");
1821 dns_fixedname_init(fname
);
1822 name
= dns_fixedname_name(fname
);
1826 result
= dns_dbiterator_current(gdbiter
, &node
, name
);
1827 check_dns_dbiterator_current(result
);
1829 * The origin was handled by signapex().
1831 if (dns_name_equal(name
, gorigin
)) {
1832 dns_db_detachnode(gdb
, &node
);
1836 * Sort the zone data from the glue and out-of-zone data.
1837 * For NSEC zones nodes with zone data have NSEC records.
1838 * For NSEC3 zones the NSEC3 nodes are zone data but
1839 * outside of the zone name space. For the rest we need
1840 * to track the bottom of zone cuts.
1841 * Nodes which don't need to be signed are dumped here.
1843 dns_rdataset_init(&nsec
);
1844 result
= dns_db_findrdataset(gdb
, node
, gversion
,
1845 nsec_datatype
, 0, 0,
1847 if (dns_rdataset_isassociated(&nsec
))
1848 dns_rdataset_disassociate(&nsec
);
1849 if (result
== ISC_R_SUCCESS
) {
1851 } else if (nsec_datatype
== dns_rdatatype_nsec3
) {
1852 if (dns_name_issubdomain(name
, gorigin
) &&
1854 !dns_name_issubdomain(name
, zonecut
))) {
1855 if (delegation(name
, node
, NULL
)) {
1856 dns_fixedname_init(&fzonecut
);
1857 zonecut
= dns_fixedname_name(&fzonecut
);
1858 dns_name_copy(name
, zonecut
, NULL
);
1859 if (!OPTOUT(nsec3flags
) ||
1868 dumpnode(name
, node
);
1869 dns_db_detachnode(gdb
, &node
);
1873 result
= dns_dbiterator_next(gdbiter
);
1874 if (result
== ISC_R_NOMORE
) {
1875 finished
= ISC_TRUE
;
1877 } else if (result
!= ISC_R_SUCCESS
)
1878 fatal("failure iterating database: %s",
1879 isc_result_totext(result
));
1883 if (ended
== ntasks
) {
1884 isc_task_detach(&task
);
1887 isc_mem_put(mctx
, fname
, sizeof(dns_fixedname_t
));
1890 sevent
= (sevent_t
*)
1891 isc_event_allocate(mctx
, task
, SIGNER_EVENT_WORK
,
1892 sign
, NULL
, sizeof(sevent_t
));
1894 fatal("failed to allocate event\n");
1896 sevent
->node
= node
;
1897 sevent
->fname
= fname
;
1898 isc_task_send(worker
, ISC_EVENT_PTR(&sevent
));
1904 * Start a worker task
1907 startworker(isc_task_t
*task
, isc_event_t
*event
) {
1910 worker
= (isc_task_t
*)event
->ev_arg
;
1911 assignwork(task
, worker
);
1912 isc_event_free(&event
);
1916 * Write a node to the output file, and restart the worker task.
1919 writenode(isc_task_t
*task
, isc_event_t
*event
) {
1921 sevent_t
*sevent
= (sevent_t
*)event
;
1923 worker
= (isc_task_t
*)event
->ev_sender
;
1924 dumpnode(dns_fixedname_name(sevent
->fname
), sevent
->node
);
1925 cleannode(gdb
, gversion
, sevent
->node
);
1926 dns_db_detachnode(gdb
, &sevent
->node
);
1927 isc_mem_put(mctx
, sevent
->fname
, sizeof(dns_fixedname_t
));
1928 assignwork(task
, worker
);
1929 isc_event_free(&event
);
1933 * Sign a database node.
1936 sign(isc_task_t
*task
, isc_event_t
*event
) {
1937 dns_fixedname_t
*fname
;
1939 sevent_t
*sevent
, *wevent
;
1941 sevent
= (sevent_t
*)event
;
1942 node
= sevent
->node
;
1943 fname
= sevent
->fname
;
1944 isc_event_free(&event
);
1946 signname(node
, dns_fixedname_name(fname
));
1947 wevent
= (sevent_t
*)
1948 isc_event_allocate(mctx
, task
, SIGNER_EVENT_WRITE
,
1949 writenode
, NULL
, sizeof(sevent_t
));
1951 fatal("failed to allocate event\n");
1952 wevent
->node
= node
;
1953 wevent
->fname
= fname
;
1954 isc_task_send(master
, ISC_EVENT_PTR(&wevent
));
1958 * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
1961 add_ds(dns_name_t
*name
, dns_dbnode_t
*node
, isc_uint32_t nsttl
) {
1962 dns_rdataset_t dsset
;
1963 dns_rdataset_t sigdsset
;
1964 isc_result_t result
;
1966 dns_rdataset_init(&dsset
);
1967 dns_rdataset_init(&sigdsset
);
1968 result
= dns_db_findrdataset(gdb
, node
, gversion
,
1970 0, 0, &dsset
, &sigdsset
);
1971 if (result
== ISC_R_SUCCESS
) {
1972 dns_rdataset_disassociate(&dsset
);
1973 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1974 dns_rdatatype_ds
, 0);
1975 check_result(result
, "dns_db_deleterdataset");
1978 result
= loadds(name
, nsttl
, &dsset
);
1979 if (result
== ISC_R_SUCCESS
) {
1980 result
= dns_db_addrdataset(gdb
, node
, gversion
, 0,
1982 check_result(result
, "dns_db_addrdataset");
1983 dns_rdataset_disassociate(&dsset
);
1984 if (dns_rdataset_isassociated(&sigdsset
))
1985 dns_rdataset_disassociate(&sigdsset
);
1986 } else if (dns_rdataset_isassociated(&sigdsset
)) {
1987 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1988 dns_rdatatype_rrsig
,
1990 check_result(result
, "dns_db_deleterdataset");
1991 dns_rdataset_disassociate(&sigdsset
);
1996 * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
2000 dns_dbiterator_t
*dbiter
= NULL
;
2001 dns_dbnode_t
*node
= NULL
, *nextnode
= NULL
;
2002 dns_fixedname_t fname
, fnextname
, fzonecut
;
2003 dns_name_t
*name
, *nextname
, *zonecut
;
2004 dns_rdataset_t rdataset
;
2005 dns_rdatasetiter_t
*rdsiter
= NULL
;
2006 dns_rdatatype_t type
, covers
;
2007 isc_boolean_t done
= ISC_FALSE
;
2008 isc_result_t result
;
2009 isc_uint32_t nsttl
= 0;
2011 dns_rdataset_init(&rdataset
);
2012 dns_fixedname_init(&fname
);
2013 name
= dns_fixedname_name(&fname
);
2014 dns_fixedname_init(&fnextname
);
2015 nextname
= dns_fixedname_name(&fnextname
);
2016 dns_fixedname_init(&fzonecut
);
2020 * Remove any NSEC3 chains.
2022 result
= dns_db_createiterator(gdb
, DNS_DB_NSEC3ONLY
, &dbiter
);
2023 check_result(result
, "dns_db_createiterator()");
2024 for (result
= dns_dbiterator_first(dbiter
);
2025 result
== ISC_R_SUCCESS
;
2026 result
= dns_dbiterator_next(dbiter
)) {
2027 result
= dns_dbiterator_current(dbiter
, &node
, name
);
2028 check_dns_dbiterator_current(result
);
2029 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
2030 check_result(result
, "dns_db_allrdatasets()");
2031 for (result
= dns_rdatasetiter_first(rdsiter
);
2032 result
== ISC_R_SUCCESS
;
2033 result
= dns_rdatasetiter_next(rdsiter
)) {
2034 dns_rdatasetiter_current(rdsiter
, &rdataset
);
2035 type
= rdataset
.type
;
2036 covers
= rdataset
.covers
;
2037 dns_rdataset_disassociate(&rdataset
);
2038 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
2040 check_result(result
,
2041 "dns_db_deleterdataset(nsec3param/rrsig)");
2043 dns_rdatasetiter_destroy(&rdsiter
);
2044 dns_db_detachnode(gdb
, &node
);
2046 dns_dbiterator_destroy(&dbiter
);
2048 result
= dns_db_createiterator(gdb
, DNS_DB_NONSEC3
, &dbiter
);
2049 check_result(result
, "dns_db_createiterator()");
2051 result
= dns_dbiterator_first(dbiter
);
2052 check_result(result
, "dns_dbiterator_first()");
2054 result
= dns_dbiterator_current(dbiter
, &node
, name
);
2055 check_dns_dbiterator_current(result
);
2058 * Delete any NSEC3PARAM records at the apex.
2060 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
2061 check_result(result
, "dns_db_allrdatasets()");
2062 for (result
= dns_rdatasetiter_first(rdsiter
);
2063 result
== ISC_R_SUCCESS
;
2064 result
= dns_rdatasetiter_next(rdsiter
)) {
2065 dns_rdatasetiter_current(rdsiter
, &rdataset
);
2066 type
= rdataset
.type
;
2067 covers
= rdataset
.covers
;
2068 dns_rdataset_disassociate(&rdataset
);
2069 if (type
== dns_rdatatype_nsec3param
||
2070 covers
== dns_rdatatype_nsec3param
) {
2071 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
2073 check_result(result
,
2074 "dns_db_deleterdataset(nsec3param/rrsig)");
2078 dns_rdatasetiter_destroy(&rdsiter
);
2079 dns_db_detachnode(gdb
, &node
);
2082 result
= dns_dbiterator_current(dbiter
, &node
, name
);
2083 check_dns_dbiterator_current(result
);
2084 if (delegation(name
, node
, &nsttl
)) {
2085 zonecut
= dns_fixedname_name(&fzonecut
);
2086 dns_name_copy(name
, zonecut
, NULL
);
2088 add_ds(name
, node
, nsttl
);
2090 result
= dns_dbiterator_next(dbiter
);
2092 while (result
== ISC_R_SUCCESS
) {
2093 isc_boolean_t active
= ISC_FALSE
;
2094 result
= dns_dbiterator_current(dbiter
, &nextnode
,
2096 check_dns_dbiterator_current(result
);
2097 active
= active_node(nextnode
);
2099 dns_db_detachnode(gdb
, &nextnode
);
2100 result
= dns_dbiterator_next(dbiter
);
2103 if (!dns_name_issubdomain(nextname
, gorigin
) ||
2105 dns_name_issubdomain(nextname
, zonecut
)))
2107 dns_db_detachnode(gdb
, &nextnode
);
2108 result
= dns_dbiterator_next(dbiter
);
2111 dns_db_detachnode(gdb
, &nextnode
);
2114 if (result
== ISC_R_NOMORE
) {
2115 dns_name_clone(gorigin
, nextname
);
2117 } else if (result
!= ISC_R_SUCCESS
)
2118 fatal("iterating through the database failed: %s",
2119 isc_result_totext(result
));
2120 dns_dbiterator_pause(dbiter
);
2121 result
= dns_nsec_build(gdb
, gversion
, node
, nextname
,
2123 check_result(result
, "dns_nsec_build()");
2124 dns_db_detachnode(gdb
, &node
);
2127 dns_dbiterator_destroy(&dbiter
);
2131 addnsec3param(const unsigned char *salt
, size_t salt_length
,
2132 unsigned int iterations
)
2134 dns_dbnode_t
*node
= NULL
;
2135 dns_rdata_nsec3param_t nsec3param
;
2136 unsigned char nsec3parambuf
[5 + 255];
2137 dns_rdatalist_t rdatalist
;
2138 dns_rdataset_t rdataset
;
2139 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2141 isc_result_t result
;
2143 dns_rdataset_init(&rdataset
);
2145 nsec3param
.common
.rdclass
= gclass
;
2146 nsec3param
.common
.rdtype
= dns_rdatatype_nsec3param
;
2147 ISC_LINK_INIT(&nsec3param
.common
, link
);
2148 nsec3param
.mctx
= NULL
;
2149 nsec3param
.flags
= 0;
2150 nsec3param
.hash
= unknownalg
? DNS_NSEC3_UNKNOWNALG
: dns_hash_sha1
;
2151 nsec3param
.iterations
= iterations
;
2152 nsec3param
.salt_length
= salt_length
;
2153 DE_CONST(salt
, nsec3param
.salt
);
2155 isc_buffer_init(&b
, nsec3parambuf
, sizeof(nsec3parambuf
));
2156 result
= dns_rdata_fromstruct(&rdata
, gclass
,
2157 dns_rdatatype_nsec3param
,
2159 rdatalist
.rdclass
= rdata
.rdclass
;
2160 rdatalist
.type
= rdata
.type
;
2161 rdatalist
.covers
= 0;
2163 ISC_LIST_INIT(rdatalist
.rdata
);
2164 ISC_LIST_APPEND(rdatalist
.rdata
, &rdata
, link
);
2165 result
= dns_rdatalist_tordataset(&rdatalist
, &rdataset
);
2166 check_result(result
, "dns_rdatalist_tordataset()");
2168 result
= dns_db_findnode(gdb
, gorigin
, ISC_TRUE
, &node
);
2169 check_result(result
, "dns_db_find(gorigin)");
2172 * Delete any current NSEC3PARAM records.
2174 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
2175 dns_rdatatype_nsec3param
, 0);
2176 if (result
== DNS_R_UNCHANGED
)
2177 result
= ISC_R_SUCCESS
;
2178 check_result(result
, "dddnsec3param: dns_db_deleterdataset()");
2180 result
= dns_db_addrdataset(gdb
, node
, gversion
, 0, &rdataset
,
2181 DNS_DBADD_MERGE
, NULL
);
2182 if (result
== DNS_R_UNCHANGED
)
2183 result
= ISC_R_SUCCESS
;
2184 check_result(result
, "addnsec3param: dns_db_addrdataset()");
2185 dns_db_detachnode(gdb
, &node
);
2189 addnsec3(dns_name_t
*name
, dns_dbnode_t
*node
,
2190 const unsigned char *salt
, size_t salt_length
,
2191 unsigned int iterations
, hashlist_t
*hashlist
,
2194 unsigned char hash
[NSEC3_MAX_HASH_LENGTH
];
2195 const unsigned char *nexthash
;
2196 unsigned char nsec3buffer
[DNS_NSEC3_BUFFERSIZE
];
2197 dns_fixedname_t hashname
;
2198 dns_rdatalist_t rdatalist
;
2199 dns_rdataset_t rdataset
;
2200 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2201 isc_result_t result
;
2202 dns_dbnode_t
*nsec3node
= NULL
;
2203 char namebuf
[DNS_NAME_FORMATSIZE
];
2206 dns_name_format(name
, namebuf
, sizeof(namebuf
));
2208 dns_fixedname_init(&hashname
);
2209 dns_rdataset_init(&rdataset
);
2211 dns_name_downcase(name
, name
, NULL
);
2212 result
= dns_nsec3_hashname(&hashname
, hash
, &hash_length
,
2213 name
, gorigin
, dns_hash_sha1
, iterations
,
2215 check_result(result
, "addnsec3: dns_nsec3_hashname()");
2216 nexthash
= hashlist_findnext(hashlist
, hash
);
2217 result
= dns_nsec3_buildrdata(gdb
, gversion
, node
,
2219 DNS_NSEC3_UNKNOWNALG
: dns_hash_sha1
,
2220 nsec3flags
, iterations
,
2222 nexthash
, ISC_SHA1_DIGESTLENGTH
,
2223 nsec3buffer
, &rdata
);
2224 check_result(result
, "addnsec3: dns_nsec3_buildrdata()");
2225 rdatalist
.rdclass
= rdata
.rdclass
;
2226 rdatalist
.type
= rdata
.type
;
2227 rdatalist
.covers
= 0;
2228 rdatalist
.ttl
= ttl
;
2229 ISC_LIST_INIT(rdatalist
.rdata
);
2230 ISC_LIST_APPEND(rdatalist
.rdata
, &rdata
, link
);
2231 result
= dns_rdatalist_tordataset(&rdatalist
, &rdataset
);
2232 check_result(result
, "dns_rdatalist_tordataset()");
2233 result
= dns_db_findnsec3node(gdb
, dns_fixedname_name(&hashname
),
2234 ISC_TRUE
, &nsec3node
);
2235 check_result(result
, "addnsec3: dns_db_findnode()");
2236 result
= dns_db_addrdataset(gdb
, nsec3node
, gversion
, 0, &rdataset
,
2238 if (result
== DNS_R_UNCHANGED
)
2239 result
= ISC_R_SUCCESS
;
2240 check_result(result
, "addnsec3: dns_db_addrdataset()");
2241 dns_db_detachnode(gdb
, &nsec3node
);
2245 * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
2247 * Extract the hash from the first label of 'name' then see if it
2248 * is in hashlist. If 'name' is not in the hashlist then delete the
2249 * any NSEC3 records which have the same parameters as the chain we
2252 * XXXMPA Should we also check that it of the form <hash>.<origin>?
2255 nsec3clean(dns_name_t
*name
, dns_dbnode_t
*node
,
2256 unsigned int hashalg
, unsigned int iterations
,
2257 const unsigned char *salt
, size_t salt_length
, hashlist_t
*hashlist
)
2260 dns_rdata_nsec3_t nsec3
;
2261 dns_rdata_t rdata
, delrdata
;
2262 dns_rdatalist_t rdatalist
;
2263 dns_rdataset_t rdataset
, delrdataset
;
2264 isc_boolean_t delete_rrsigs
= ISC_FALSE
;
2265 isc_buffer_t target
;
2266 isc_result_t result
;
2267 unsigned char hash
[NSEC3_MAX_HASH_LENGTH
+ 1];
2268 isc_boolean_t exists
;
2271 * Get the first label.
2273 dns_name_getlabel(name
, 0, &label
);
2276 * We want just the label contents.
2278 isc_region_consume(&label
, 1);
2281 * Decode base32hex string.
2283 isc_buffer_init(&target
, hash
, sizeof(hash
) - 1);
2284 result
= isc_base32hex_decoderegion(&label
, &target
);
2285 if (result
!= ISC_R_SUCCESS
)
2288 hash
[isc_buffer_usedlength(&target
)] = 0;
2290 exists
= hashlist_exists(hashlist
, hash
);
2293 * Verify that the NSEC3 parameters match the current ones
2294 * otherwise we are dealing with a different NSEC3 chain.
2296 dns_rdataset_init(&rdataset
);
2297 dns_rdataset_init(&delrdataset
);
2299 result
= dns_db_findrdataset(gdb
, node
, gversion
, dns_rdatatype_nsec3
,
2300 0, 0, &rdataset
, NULL
);
2301 if (result
!= ISC_R_SUCCESS
)
2305 * Delete any NSEC3 records which are not part of the current
2308 for (result
= dns_rdataset_first(&rdataset
);
2309 result
== ISC_R_SUCCESS
;
2310 result
= dns_rdataset_next(&rdataset
)) {
2311 dns_rdata_init(&rdata
);
2312 dns_rdataset_current(&rdataset
, &rdata
);
2313 result
= dns_rdata_tostruct(&rdata
, &nsec3
, NULL
);
2314 check_result(result
, "dns_rdata_tostruct");
2315 if (exists
&& nsec3
.hash
== hashalg
&&
2316 nsec3
.iterations
== iterations
&&
2317 nsec3
.salt_length
== salt_length
&&
2318 !memcmp(nsec3
.salt
, salt
, salt_length
))
2320 rdatalist
.rdclass
= rdata
.rdclass
;
2321 rdatalist
.type
= rdata
.type
;
2322 rdatalist
.covers
= 0;
2323 rdatalist
.ttl
= rdataset
.ttl
;
2324 ISC_LIST_INIT(rdatalist
.rdata
);
2325 dns_rdata_init(&delrdata
);
2326 dns_rdata_clone(&rdata
, &delrdata
);
2327 ISC_LIST_APPEND(rdatalist
.rdata
, &delrdata
, link
);
2328 result
= dns_rdatalist_tordataset(&rdatalist
, &delrdataset
);
2329 check_result(result
, "dns_rdatalist_tordataset()");
2330 result
= dns_db_subtractrdataset(gdb
, node
, gversion
,
2331 &delrdataset
, 0, NULL
);
2332 dns_rdataset_disassociate(&delrdataset
);
2333 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_NXRRSET
)
2334 check_result(result
, "dns_db_subtractrdataset(NSEC3)");
2335 delete_rrsigs
= ISC_TRUE
;
2337 dns_rdataset_disassociate(&rdataset
);
2338 if (result
!= ISC_R_NOMORE
)
2339 check_result(result
, "dns_rdataset_first/next");
2344 * Delete the NSEC3 RRSIGs
2346 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
2347 dns_rdatatype_rrsig
,
2348 dns_rdatatype_nsec3
);
2349 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_UNCHANGED
)
2350 check_result(result
, "dns_db_deleterdataset(RRSIG(NSEC3))");
2354 rrset_remove_duplicates(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
2357 dns_difftuple_t
*tuple
= NULL
;
2358 isc_result_t result
;
2359 unsigned int count1
= 0;
2360 dns_rdataset_t tmprdataset
;
2362 dns_rdataset_init(&tmprdataset
);
2363 for (result
= dns_rdataset_first(rdataset
);
2364 result
== ISC_R_SUCCESS
;
2365 result
= dns_rdataset_next(rdataset
)) {
2366 dns_rdata_t rdata1
= DNS_RDATA_INIT
;
2367 unsigned int count2
= 0;
2370 dns_rdataset_current(rdataset
, &rdata1
);
2371 dns_rdataset_clone(rdataset
, &tmprdataset
);
2372 for (result
= dns_rdataset_first(&tmprdataset
);
2373 result
== ISC_R_SUCCESS
;
2374 result
= dns_rdataset_next(&tmprdataset
)) {
2375 dns_rdata_t rdata2
= DNS_RDATA_INIT
;
2377 if (count1
>= count2
)
2379 dns_rdataset_current(&tmprdataset
, &rdata2
);
2380 if (dns_rdata_casecompare(&rdata1
, &rdata2
) == 0) {
2381 result
= dns_difftuple_create(mctx
,
2386 check_result(result
, "dns_difftuple_create");
2387 dns_diff_append(diff
, &tuple
);
2390 dns_rdataset_disassociate(&tmprdataset
);
2395 remove_duplicates(void) {
2396 isc_result_t result
;
2397 dns_dbiterator_t
*dbiter
= NULL
;
2398 dns_rdatasetiter_t
*rdsiter
= NULL
;
2400 dns_dbnode_t
*node
= NULL
;
2401 dns_rdataset_t rdataset
;
2402 dns_fixedname_t fname
;
2405 dns_diff_init(mctx
, &diff
);
2406 dns_fixedname_init(&fname
);
2407 name
= dns_fixedname_name(&fname
);
2408 dns_rdataset_init(&rdataset
);
2410 result
= dns_db_createiterator(gdb
, 0, &dbiter
);
2411 check_result(result
, "dns_db_createiterator()");
2413 for (result
= dns_dbiterator_first(dbiter
);
2414 result
== ISC_R_SUCCESS
;
2415 result
= dns_dbiterator_next(dbiter
)) {
2417 result
= dns_dbiterator_current(dbiter
, &node
, name
);
2418 check_dns_dbiterator_current(result
);
2419 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
2420 check_result(result
, "dns_db_allrdatasets()");
2421 for (result
= dns_rdatasetiter_first(rdsiter
);
2422 result
== ISC_R_SUCCESS
;
2423 result
= dns_rdatasetiter_next(rdsiter
)) {
2424 dns_rdatasetiter_current(rdsiter
, &rdataset
);
2425 rrset_remove_duplicates(name
, &rdataset
, &diff
);
2426 dns_rdataset_disassociate(&rdataset
);
2428 if (result
!= ISC_R_NOMORE
)
2429 fatal("rdatasets iteration failed.");
2430 dns_rdatasetiter_destroy(&rdsiter
);
2431 dns_db_detachnode(gdb
, &node
);
2433 if (result
!= ISC_R_NOMORE
)
2434 fatal("zone iteration failed.");
2436 if (!ISC_LIST_EMPTY(diff
.tuples
)) {
2437 result
= dns_diff_applysilently(&diff
, gdb
, gversion
);
2438 check_result(result
, "dns_diff_applysilently");
2440 dns_diff_clear(&diff
);
2441 dns_dbiterator_destroy(&dbiter
);
2445 * Generate NSEC3 records for the zone.
2448 nsec3ify(unsigned int hashalg
, unsigned int iterations
,
2449 const unsigned char *salt
, size_t salt_length
, hashlist_t
*hashlist
)
2451 dns_dbiterator_t
*dbiter
= NULL
;
2452 dns_dbnode_t
*node
= NULL
, *nextnode
= NULL
;
2453 dns_fixedname_t fname
, fnextname
, fzonecut
;
2454 dns_name_t
*name
, *nextname
, *zonecut
;
2455 dns_rdataset_t rdataset
;
2456 dns_rdatasetiter_t
*rdsiter
= NULL
;
2457 dns_rdatatype_t type
, covers
;
2459 isc_boolean_t active
;
2460 isc_boolean_t done
= ISC_FALSE
;
2461 isc_result_t result
;
2462 isc_uint32_t nsttl
= 0;
2463 unsigned int count
, nlabels
;
2465 dns_rdataset_init(&rdataset
);
2466 dns_fixedname_init(&fname
);
2467 name
= dns_fixedname_name(&fname
);
2468 dns_fixedname_init(&fnextname
);
2469 nextname
= dns_fixedname_name(&fnextname
);
2470 dns_fixedname_init(&fzonecut
);
2474 * Walk the zone generating the hash names.
2476 result
= dns_db_createiterator(gdb
, DNS_DB_NONSEC3
, &dbiter
);
2477 check_result(result
, "dns_db_createiterator()");
2479 result
= dns_dbiterator_first(dbiter
);
2480 check_result(result
, "dns_dbiterator_first()");
2482 result
= dns_dbiterator_current(dbiter
, &node
, name
);
2483 check_dns_dbiterator_current(result
);
2486 * Delete any NSEC records at the apex.
2488 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
2489 check_result(result
, "dns_db_allrdatasets()");
2490 for (result
= dns_rdatasetiter_first(rdsiter
);
2491 result
== ISC_R_SUCCESS
;
2492 result
= dns_rdatasetiter_next(rdsiter
)) {
2493 dns_rdatasetiter_current(rdsiter
, &rdataset
);
2494 type
= rdataset
.type
;
2495 covers
= rdataset
.covers
;
2496 dns_rdataset_disassociate(&rdataset
);
2497 if (type
== dns_rdatatype_nsec
||
2498 covers
== dns_rdatatype_nsec
) {
2500 fatal("Zone contains NSEC records. Use -u "
2501 "to update to NSEC3.");
2503 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
2505 check_result(result
,
2506 "dns_db_deleterdataset(nsec3param/rrsig)");
2510 dns_rdatasetiter_destroy(&rdsiter
);
2511 dns_db_detachnode(gdb
, &node
);
2514 result
= dns_dbiterator_current(dbiter
, &node
, name
);
2515 check_dns_dbiterator_current(result
);
2516 result
= dns_dbiterator_next(dbiter
);
2518 while (result
== ISC_R_SUCCESS
) {
2519 result
= dns_dbiterator_current(dbiter
, &nextnode
,
2521 check_dns_dbiterator_current(result
);
2522 active
= active_node(nextnode
);
2524 dns_db_detachnode(gdb
, &nextnode
);
2525 result
= dns_dbiterator_next(dbiter
);
2528 if (!dns_name_issubdomain(nextname
, gorigin
) ||
2530 dns_name_issubdomain(nextname
, zonecut
))) {
2531 dns_db_detachnode(gdb
, &nextnode
);
2532 result
= dns_dbiterator_next(dbiter
);
2535 if (delegation(nextname
, nextnode
, &nsttl
)) {
2536 zonecut
= dns_fixedname_name(&fzonecut
);
2537 dns_name_copy(nextname
, zonecut
, NULL
);
2539 add_ds(nextname
, nextnode
, nsttl
);
2540 if (OPTOUT(nsec3flags
) &&
2541 !secure(nextname
, nextnode
)) {
2542 dns_db_detachnode(gdb
, &nextnode
);
2543 result
= dns_dbiterator_next(dbiter
);
2547 dns_db_detachnode(gdb
, &nextnode
);
2550 if (result
== ISC_R_NOMORE
) {
2551 dns_name_copy(gorigin
, nextname
, NULL
);
2553 } else if (result
!= ISC_R_SUCCESS
)
2554 fatal("iterating through the database failed: %s",
2555 isc_result_totext(result
));
2556 dns_name_downcase(name
, name
, NULL
);
2557 hashlist_add_dns_name(hashlist
, name
, hashalg
, iterations
,
2558 salt
, salt_length
, ISC_FALSE
);
2559 dns_db_detachnode(gdb
, &node
);
2561 * Add hashs for empty nodes. Use closest encloser logic.
2562 * The closest encloser either has data or is a empty
2563 * node for another <name,nextname> span so we don't add
2564 * it here. Empty labels on nextname are within the span.
2566 dns_name_downcase(nextname
, nextname
, NULL
);
2567 dns_name_fullcompare(name
, nextname
, &order
, &nlabels
);
2568 addnowildcardhash(hashlist
, name
, hashalg
, iterations
,
2570 count
= dns_name_countlabels(nextname
);
2571 while (count
> nlabels
+ 1) {
2573 dns_name_split(nextname
, count
, NULL
, nextname
);
2574 hashlist_add_dns_name(hashlist
, nextname
, hashalg
,
2575 iterations
, salt
, salt_length
,
2577 addnowildcardhash(hashlist
, nextname
, hashalg
,
2578 iterations
, salt
, salt_length
);
2581 dns_dbiterator_destroy(&dbiter
);
2584 * We have all the hashes now so we can sort them.
2586 hashlist_sort(hashlist
);
2589 * Check for duplicate hashes. If found the salt needs to
2592 if (hashlist_hasdup(hashlist
))
2593 fatal("Duplicate hash detected. Pick a different salt.");
2596 * Generate the nsec3 records.
2601 addnsec3param(salt
, salt_length
, iterations
);
2604 * Clean out NSEC3 records which don't match this chain.
2606 result
= dns_db_createiterator(gdb
, DNS_DB_NSEC3ONLY
, &dbiter
);
2607 check_result(result
, "dns_db_createiterator()");
2609 for (result
= dns_dbiterator_first(dbiter
);
2610 result
== ISC_R_SUCCESS
;
2611 result
= dns_dbiterator_next(dbiter
)) {
2612 result
= dns_dbiterator_current(dbiter
, &node
, name
);
2613 check_dns_dbiterator_current(result
);
2614 nsec3clean(name
, node
, hashalg
, iterations
, salt
, salt_length
,
2616 dns_db_detachnode(gdb
, &node
);
2618 dns_dbiterator_destroy(&dbiter
);
2621 * Generate / complete the new chain.
2623 result
= dns_db_createiterator(gdb
, DNS_DB_NONSEC3
, &dbiter
);
2624 check_result(result
, "dns_db_createiterator()");
2626 result
= dns_dbiterator_first(dbiter
);
2627 check_result(result
, "dns_dbiterator_first()");
2630 result
= dns_dbiterator_current(dbiter
, &node
, name
);
2631 check_dns_dbiterator_current(result
);
2632 result
= dns_dbiterator_next(dbiter
);
2634 while (result
== ISC_R_SUCCESS
) {
2635 result
= dns_dbiterator_current(dbiter
, &nextnode
,
2637 check_dns_dbiterator_current(result
);
2638 active
= active_node(nextnode
);
2640 dns_db_detachnode(gdb
, &nextnode
);
2641 result
= dns_dbiterator_next(dbiter
);
2644 if (!dns_name_issubdomain(nextname
, gorigin
) ||
2646 dns_name_issubdomain(nextname
, zonecut
))) {
2647 dns_db_detachnode(gdb
, &nextnode
);
2648 result
= dns_dbiterator_next(dbiter
);
2651 if (delegation(nextname
, nextnode
, NULL
)) {
2652 zonecut
= dns_fixedname_name(&fzonecut
);
2653 dns_name_copy(nextname
, zonecut
, NULL
);
2654 if (OPTOUT(nsec3flags
) &&
2655 !secure(nextname
, nextnode
)) {
2656 dns_db_detachnode(gdb
, &nextnode
);
2657 result
= dns_dbiterator_next(dbiter
);
2661 dns_db_detachnode(gdb
, &nextnode
);
2664 if (result
== ISC_R_NOMORE
) {
2665 dns_name_copy(gorigin
, nextname
, NULL
);
2667 } else if (result
!= ISC_R_SUCCESS
)
2668 fatal("iterating through the database failed: %s",
2669 isc_result_totext(result
));
2671 * We need to pause here to release the lock on the database.
2673 dns_dbiterator_pause(dbiter
);
2674 addnsec3(name
, node
, salt
, salt_length
, iterations
,
2675 hashlist
, zone_soa_min_ttl
);
2676 dns_db_detachnode(gdb
, &node
);
2678 * Add NSEC3's for empty nodes. Use closest encloser logic.
2680 dns_name_fullcompare(name
, nextname
, &order
, &nlabels
);
2681 count
= dns_name_countlabels(nextname
);
2682 while (count
> nlabels
+ 1) {
2684 dns_name_split(nextname
, count
, NULL
, nextname
);
2685 addnsec3(nextname
, NULL
, salt
, salt_length
,
2686 iterations
, hashlist
, zone_soa_min_ttl
);
2689 dns_dbiterator_destroy(&dbiter
);
2693 * Load the zone file from disk
2696 loadzone(char *file
, char *origin
, dns_rdataclass_t rdclass
, dns_db_t
**db
) {
2699 dns_fixedname_t fname
;
2701 isc_result_t result
;
2703 len
= strlen(origin
);
2704 isc_buffer_init(&b
, origin
, len
);
2705 isc_buffer_add(&b
, len
);
2707 dns_fixedname_init(&fname
);
2708 name
= dns_fixedname_name(&fname
);
2709 result
= dns_name_fromtext(name
, &b
, dns_rootname
, 0, NULL
);
2710 if (result
!= ISC_R_SUCCESS
)
2711 fatal("failed converting name '%s' to dns format: %s",
2712 origin
, isc_result_totext(result
));
2714 result
= dns_db_create(mctx
, "rbt", name
, dns_dbtype_zone
,
2715 rdclass
, 0, NULL
, db
);
2716 check_result(result
, "dns_db_create()");
2718 result
= dns_db_load2(*db
, file
, inputformat
);
2719 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_SEENINCLUDE
)
2720 fatal("failed loading zone from '%s': %s",
2721 file
, isc_result_totext(result
));
2725 * Finds all public zone keys in the zone, and attempts to load the
2726 * private keys from disk.
2729 loadzonekeys(isc_boolean_t preserve_keys
, isc_boolean_t load_public
) {
2731 dns_dbversion_t
*currentversion
= NULL
;
2732 isc_result_t result
;
2733 dns_rdataset_t rdataset
, keysigs
, soasigs
;
2736 result
= dns_db_findnode(gdb
, gorigin
, ISC_FALSE
, &node
);
2737 if (result
!= ISC_R_SUCCESS
)
2738 fatal("failed to find the zone's origin: %s",
2739 isc_result_totext(result
));
2741 dns_db_currentversion(gdb
, ¤tversion
);
2743 dns_rdataset_init(&rdataset
);
2744 dns_rdataset_init(&soasigs
);
2745 dns_rdataset_init(&keysigs
);
2747 /* Make note of the keys which signed the SOA, if any */
2748 result
= dns_db_findrdataset(gdb
, node
, currentversion
,
2749 dns_rdatatype_soa
, 0, 0,
2750 &rdataset
, &soasigs
);
2751 if (result
!= ISC_R_SUCCESS
)
2754 /* Preserve the TTL of the DNSKEY RRset, if any */
2755 dns_rdataset_disassociate(&rdataset
);
2756 result
= dns_db_findrdataset(gdb
, node
, currentversion
,
2757 dns_rdatatype_dnskey
, 0, 0,
2758 &rdataset
, &keysigs
);
2760 if (result
!= ISC_R_SUCCESS
)
2763 if (set_keyttl
&& keyttl
!= rdataset
.ttl
) {
2764 fprintf(stderr
, "User-specified TTL (%d) conflicts "
2765 "with existing DNSKEY RRset TTL.\n",
2767 fprintf(stderr
, "Imported keys will use the RRSet "
2768 "TTL (%d) instead.\n",
2771 keyttl
= rdataset
.ttl
;
2773 /* Load keys corresponding to the existing DNSKEY RRset */
2774 result
= dns_dnssec_keylistfromrdataset(gorigin
, directory
, mctx
,
2775 &rdataset
, &keysigs
, &soasigs
,
2776 preserve_keys
, load_public
,
2778 if (result
!= ISC_R_SUCCESS
)
2779 fatal("failed to load the zone keys: %s",
2780 isc_result_totext(result
));
2783 if (dns_rdataset_isassociated(&rdataset
))
2784 dns_rdataset_disassociate(&rdataset
);
2785 if (dns_rdataset_isassociated(&keysigs
))
2786 dns_rdataset_disassociate(&keysigs
);
2787 if (dns_rdataset_isassociated(&soasigs
))
2788 dns_rdataset_disassociate(&soasigs
);
2789 dns_db_detachnode(gdb
, &node
);
2790 dns_db_closeversion(gdb
, ¤tversion
, ISC_FALSE
);
2794 loadexplicitkeys(char *keyfiles
[], int n
, isc_boolean_t setksk
) {
2795 isc_result_t result
;
2798 for (i
= 0; i
< n
; i
++) {
2799 dns_dnsseckey_t
*key
= NULL
;
2800 dst_key_t
*newkey
= NULL
;
2802 result
= dst_key_fromnamedfile(keyfiles
[i
], directory
,
2806 if (result
!= ISC_R_SUCCESS
)
2807 fatal("cannot load dnskey %s: %s", keyfiles
[i
],
2808 isc_result_totext(result
));
2810 if (!dns_name_equal(gorigin
, dst_key_name(newkey
)))
2811 fatal("key %s not at origin\n", keyfiles
[i
]);
2813 if (!dst_key_isprivate(newkey
))
2814 fatal("cannot sign zone with non-private dnskey %s",
2817 /* Skip any duplicates */
2818 for (key
= ISC_LIST_HEAD(keylist
);
2820 key
= ISC_LIST_NEXT(key
, link
)) {
2821 if (dst_key_id(key
->key
) == dst_key_id(newkey
) &&
2822 dst_key_alg(key
->key
) == dst_key_alg(newkey
))
2827 /* We haven't seen this key before */
2828 dns_dnsseckey_create(mctx
, &newkey
, &key
);
2829 ISC_LIST_APPEND(keylist
, key
, link
);
2830 key
->source
= dns_keysource_user
;
2832 dst_key_free(&key
->key
);
2836 key
->force_publish
= ISC_TRUE
;
2837 key
->force_sign
= ISC_TRUE
;
2840 key
->ksk
= ISC_TRUE
;
2845 report(const char *format
, ...) {
2847 va_start(args
, format
);
2848 vfprintf(stderr
, format
, args
);
2854 build_final_keylist(void) {
2855 isc_result_t result
;
2856 dns_dbversion_t
*ver
= NULL
;
2858 dns_dnsseckeylist_t matchkeys
;
2859 char name
[DNS_NAME_FORMATSIZE
];
2862 * Find keys that match this zone in the key repository.
2864 ISC_LIST_INIT(matchkeys
);
2865 result
= dns_dnssec_findmatchingkeys(gorigin
, directory
,
2867 if (result
== ISC_R_NOTFOUND
)
2868 result
= ISC_R_SUCCESS
;
2869 check_result(result
, "dns_dnssec_findmatchingkeys");
2871 result
= dns_db_newversion(gdb
, &ver
);
2872 check_result(result
, "dns_db_newversion");
2874 dns_diff_init(mctx
, &diff
);
2877 * Update keylist with information from from the key repository.
2879 dns_dnssec_updatekeys(&keylist
, &matchkeys
, NULL
, gorigin
, keyttl
,
2880 &diff
, ignore_kskflag
, mctx
, report
);
2882 dns_name_format(gorigin
, name
, sizeof(name
));
2884 result
= dns_diff_applysilently(&diff
, gdb
, ver
);
2885 if (result
!= ISC_R_SUCCESS
)
2886 fatal("failed to update DNSKEY RRset at node '%s': %s",
2887 name
, isc_result_totext(result
));
2889 dns_db_closeversion(gdb
, &ver
, ISC_TRUE
);
2891 dns_diff_clear(&diff
);
2895 warnifallksk(dns_db_t
*db
) {
2896 dns_dbversion_t
*currentversion
= NULL
;
2897 dns_dbnode_t
*node
= NULL
;
2898 dns_rdataset_t rdataset
;
2899 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2900 isc_result_t result
;
2901 dns_rdata_dnskey_t dnskey
;
2902 isc_boolean_t have_non_ksk
= ISC_FALSE
;
2904 dns_db_currentversion(db
, ¤tversion
);
2906 result
= dns_db_findnode(db
, gorigin
, ISC_FALSE
, &node
);
2907 if (result
!= ISC_R_SUCCESS
)
2908 fatal("failed to find the zone's origin: %s",
2909 isc_result_totext(result
));
2911 dns_rdataset_init(&rdataset
);
2912 result
= dns_db_findrdataset(db
, node
, currentversion
,
2913 dns_rdatatype_dnskey
, 0, 0, &rdataset
,
2915 if (result
!= ISC_R_SUCCESS
)
2916 fatal("failed to find keys at the zone apex: %s",
2917 isc_result_totext(result
));
2918 result
= dns_rdataset_first(&rdataset
);
2919 check_result(result
, "dns_rdataset_first");
2920 while (result
== ISC_R_SUCCESS
) {
2921 dns_rdata_reset(&rdata
);
2922 dns_rdataset_current(&rdataset
, &rdata
);
2923 result
= dns_rdata_tostruct(&rdata
, &dnskey
, NULL
);
2924 check_result(result
, "dns_rdata_tostruct");
2925 if ((dnskey
.flags
& DNS_KEYFLAG_KSK
) == 0) {
2926 have_non_ksk
= ISC_TRUE
;
2927 result
= ISC_R_NOMORE
;
2929 result
= dns_rdataset_next(&rdataset
);
2930 dns_rdata_freestruct(&dnskey
);
2932 dns_rdataset_disassociate(&rdataset
);
2933 dns_db_detachnode(db
, &node
);
2934 dns_db_closeversion(db
, ¤tversion
, ISC_FALSE
);
2935 if (!have_non_ksk
&& !ignore_kskflag
) {
2936 if (disable_zone_check
)
2937 fprintf(stderr
, "%s: warning: No non-KSK DNSKEY found; "
2938 "supply a ZSK or use '-z'.\n",
2941 fatal("No non-KSK DNSKEY found; "
2942 "supply a ZSK or use '-z'.");
2947 set_nsec3params(isc_boolean_t update_chain
, isc_boolean_t set_salt
,
2948 isc_boolean_t set_optout
, isc_boolean_t set_iter
)
2950 isc_result_t result
;
2951 dns_dbversion_t
*ver
= NULL
;
2952 dns_dbnode_t
*node
= NULL
;
2953 dns_rdataset_t rdataset
;
2954 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2955 dns_rdata_nsec3_t nsec3
;
2956 dns_fixedname_t fname
;
2957 dns_name_t
*hashname
;
2958 unsigned char orig_salt
[256];
2959 size_t orig_saltlen
;
2960 dns_hash_t orig_hash
;
2961 isc_uint16_t orig_iter
;
2963 dns_db_currentversion(gdb
, &ver
);
2964 dns_rdataset_init(&rdataset
);
2966 orig_saltlen
= sizeof(orig_salt
);
2967 result
= dns_db_getnsec3parameters(gdb
, ver
, &orig_hash
, NULL
,
2968 &orig_iter
, orig_salt
,
2970 if (result
!= ISC_R_SUCCESS
)
2973 nsec_datatype
= dns_rdatatype_nsec3
;
2975 if (!update_chain
&& set_salt
) {
2976 if (salt_length
!= orig_saltlen
||
2977 memcmp(saltbuf
, orig_salt
, salt_length
) != 0)
2978 fatal("An NSEC3 chain exists with a different salt. "
2979 "Use -u to update it.");
2980 } else if (!set_salt
) {
2981 salt_length
= orig_saltlen
;
2982 memcpy(saltbuf
, orig_salt
, orig_saltlen
);
2986 if (!update_chain
&& set_iter
) {
2987 if (nsec3iter
!= orig_iter
)
2988 fatal("An NSEC3 chain exists with different "
2989 "iterations. Use -u to update it.");
2990 } else if (!set_iter
)
2991 nsec3iter
= orig_iter
;
2994 * Find an NSEC3 record to get the current OPTOUT value.
2995 * (This assumes all NSEC3 records agree.)
2998 dns_fixedname_init(&fname
);
2999 hashname
= dns_fixedname_name(&fname
);
3000 result
= dns_nsec3_hashname(&fname
, NULL
, NULL
,
3001 gorigin
, gorigin
, dns_hash_sha1
,
3002 orig_iter
, orig_salt
, orig_saltlen
);
3003 check_result(result
, "dns_nsec3_hashname");
3005 result
= dns_db_findnsec3node(gdb
, hashname
, ISC_FALSE
, &node
);
3006 if (result
!= ISC_R_SUCCESS
)
3009 result
= dns_db_findrdataset(gdb
, node
, ver
, dns_rdatatype_nsec3
,
3010 0, 0, &rdataset
, NULL
);
3011 if (result
!= ISC_R_SUCCESS
)
3014 result
= dns_rdataset_first(&rdataset
);
3015 check_result(result
, "dns_rdataset_first");
3016 dns_rdataset_current(&rdataset
, &rdata
);
3017 result
= dns_rdata_tostruct(&rdata
, &nsec3
, NULL
);
3018 check_result(result
, "dns_rdata_tostruct");
3020 if (!update_chain
&& set_optout
) {
3021 if (nsec3flags
!= nsec3
.flags
)
3022 fatal("An NSEC3 chain exists with%s OPTOUT. "
3023 "Use -u -%s to %s it.",
3024 OPTOUT(nsec3
.flags
) ? "" : "out",
3025 OPTOUT(nsec3
.flags
) ? "AA" : "A",
3026 OPTOUT(nsec3
.flags
) ? "clear" : "set");
3027 } else if (!set_optout
)
3028 nsec3flags
= nsec3
.flags
;
3030 dns_rdata_freestruct(&nsec3
);
3033 if (dns_rdataset_isassociated(&rdataset
))
3034 dns_rdataset_disassociate(&rdataset
);
3036 dns_db_detachnode(gdb
, &node
);
3037 dns_db_closeversion(gdb
, &ver
, ISC_FALSE
);
3041 writeset(const char *prefix
, dns_rdatatype_t type
) {
3043 char namestr
[DNS_NAME_FORMATSIZE
];
3044 dns_db_t
*db
= NULL
;
3045 dns_dbversion_t
*version
= NULL
;
3047 dns_difftuple_t
*tuple
= NULL
;
3048 dns_fixedname_t fixed
;
3050 dns_rdata_t rdata
, ds
;
3051 isc_boolean_t have_ksk
= ISC_FALSE
;
3052 isc_boolean_t have_non_ksk
= ISC_FALSE
;
3054 isc_buffer_t namebuf
;
3056 isc_result_t result
;
3057 dns_dnsseckey_t
*key
, *tmpkey
;
3058 unsigned char dsbuf
[DNS_DS_BUFFERSIZE
];
3059 unsigned char keybuf
[DST_KEY_MAXSIZE
];
3060 unsigned int filenamelen
;
3061 const dns_master_style_t
*style
=
3062 (type
== dns_rdatatype_dnskey
) ? masterstyle
: dsstyle
;
3064 isc_buffer_init(&namebuf
, namestr
, sizeof(namestr
));
3065 result
= dns_name_tofilenametext(gorigin
, ISC_FALSE
, &namebuf
);
3066 check_result(result
, "dns_name_tofilenametext");
3067 isc_buffer_putuint8(&namebuf
, 0);
3068 filenamelen
= strlen(prefix
) + strlen(namestr
);
3070 filenamelen
+= strlen(dsdir
) + 1;
3071 filename
= isc_mem_get(mctx
, filenamelen
+ 1);
3072 if (filename
== NULL
)
3073 fatal("out of memory");
3075 sprintf(filename
, "%s/", dsdir
);
3078 strcat(filename
, prefix
);
3079 strcat(filename
, namestr
);
3081 dns_diff_init(mctx
, &diff
);
3083 if (type
== dns_rdatatype_dlv
) {
3085 unsigned int labels
;
3087 dns_name_init(&tname
, NULL
);
3088 dns_fixedname_init(&fixed
);
3089 name
= dns_fixedname_name(&fixed
);
3090 labels
= dns_name_countlabels(gorigin
);
3091 dns_name_getlabelsequence(gorigin
, 0, labels
- 1, &tname
);
3092 result
= dns_name_concatenate(&tname
, dlv
, name
, NULL
);
3093 check_result(result
, "dns_name_concatenate");
3097 for (key
= ISC_LIST_HEAD(keylist
);
3099 key
= ISC_LIST_NEXT(key
, link
))
3101 if (REVOKE(key
->key
))
3104 have_ksk
= ISC_TRUE
;
3105 have_non_ksk
= ISC_FALSE
;
3107 have_ksk
= ISC_FALSE
;
3108 have_non_ksk
= ISC_TRUE
;
3110 for (tmpkey
= ISC_LIST_HEAD(keylist
);
3112 tmpkey
= ISC_LIST_NEXT(tmpkey
, link
)) {
3113 if (dst_key_alg(key
->key
) != dst_key_alg(tmpkey
->key
))
3115 if (REVOKE(tmpkey
->key
))
3118 have_ksk
= ISC_TRUE
;
3120 have_non_ksk
= ISC_TRUE
;
3122 if (have_ksk
&& have_non_ksk
&& !isksk(key
))
3124 dns_rdata_init(&rdata
);
3125 dns_rdata_init(&ds
);
3126 isc_buffer_init(&b
, keybuf
, sizeof(keybuf
));
3127 result
= dst_key_todns(key
->key
, &b
);
3128 check_result(result
, "dst_key_todns");
3129 isc_buffer_usedregion(&b
, &r
);
3130 dns_rdata_fromregion(&rdata
, gclass
, dns_rdatatype_dnskey
, &r
);
3131 if (type
!= dns_rdatatype_dnskey
) {
3132 result
= dns_ds_buildrdata(gorigin
, &rdata
,
3135 check_result(result
, "dns_ds_buildrdata");
3136 if (type
== dns_rdatatype_dlv
)
3137 ds
.type
= dns_rdatatype_dlv
;
3138 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
,
3139 name
, 0, &ds
, &tuple
);
3140 check_result(result
, "dns_difftuple_create");
3141 dns_diff_append(&diff
, &tuple
);
3143 dns_rdata_reset(&ds
);
3144 result
= dns_ds_buildrdata(gorigin
, &rdata
,
3145 DNS_DSDIGEST_SHA256
,
3147 check_result(result
, "dns_ds_buildrdata");
3148 if (type
== dns_rdatatype_dlv
)
3149 ds
.type
= dns_rdatatype_dlv
;
3150 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
,
3151 name
, 0, &ds
, &tuple
);
3154 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
,
3155 gorigin
, zone_soa_min_ttl
,
3157 check_result(result
, "dns_difftuple_create");
3158 dns_diff_append(&diff
, &tuple
);
3161 result
= dns_db_create(mctx
, "rbt", dns_rootname
, dns_dbtype_zone
,
3162 gclass
, 0, NULL
, &db
);
3163 check_result(result
, "dns_db_create");
3165 result
= dns_db_newversion(db
, &version
);
3166 check_result(result
, "dns_db_newversion");
3168 result
= dns_diff_apply(&diff
, db
, version
);
3169 check_result(result
, "dns_diff_apply");
3170 dns_diff_clear(&diff
);
3172 result
= dns_master_dump(mctx
, db
, version
, style
, filename
);
3173 check_result(result
, "dns_master_dump");
3175 isc_mem_put(mctx
, filename
, filenamelen
+ 1);
3177 dns_db_closeversion(db
, &version
, ISC_FALSE
);
3182 print_time(FILE *fp
) {
3185 if (outputformat
!= dns_masterformat_text
)
3188 currenttime
= time(NULL
);
3189 fprintf(fp
, "; File written on %s", ctime(¤ttime
));
3193 print_version(FILE *fp
) {
3194 if (outputformat
!= dns_masterformat_text
)
3197 fprintf(fp
, "; dnssec_signzone version " VERSION
"\n");
3200 ISC_PLATFORM_NORETURN_PRE
static void
3201 usage(void) ISC_PLATFORM_NORETURN_POST
;
3205 fprintf(stderr
, "Usage:\n");
3206 fprintf(stderr
, "\t%s [options] zonefile [keys]\n", program
);
3208 fprintf(stderr
, "\n");
3210 fprintf(stderr
, "Version: %s\n", VERSION
);
3212 fprintf(stderr
, "Options: (default value in parenthesis) \n");
3213 fprintf(stderr
, "\t-S:\tsmart signing: automatically finds key files\n"
3214 "\t\tfor the zone and determines how they are to "
3216 fprintf(stderr
, "\t-K directory:\n");
3217 fprintf(stderr
, "\t\tdirectory to find key files (.)\n");
3218 fprintf(stderr
, "\t-d directory:\n");
3219 fprintf(stderr
, "\t\tdirectory to find dsset-* files (.)\n");
3220 fprintf(stderr
, "\t-g:\t");
3221 fprintf(stderr
, "update DS records based on child zones' "
3223 fprintf(stderr
, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
3224 fprintf(stderr
, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n");
3225 fprintf(stderr
, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
3226 fprintf(stderr
, "\t\tRRSIG end time - absolute|from start|from now "
3227 "(now + 30 days)\n");
3228 fprintf(stderr
, "\t-i interval:\n");
3229 fprintf(stderr
, "\t\tcycle interval - resign "
3230 "if < interval from end ( (end-start)/4 )\n");
3231 fprintf(stderr
, "\t-j jitter:\n");
3232 fprintf(stderr
, "\t\trandomize signature end time up to jitter seconds\n");
3233 fprintf(stderr
, "\t-v debuglevel (0)\n");
3234 fprintf(stderr
, "\t-o origin:\n");
3235 fprintf(stderr
, "\t\tzone origin (name of zonefile)\n");
3236 fprintf(stderr
, "\t-f outfile:\n");
3237 fprintf(stderr
, "\t\tfile the signed zone is written in "
3238 "(zonefile + .signed)\n");
3239 fprintf(stderr
, "\t-I format:\n");
3240 fprintf(stderr
, "\t\tfile format of input zonefile (text)\n");
3241 fprintf(stderr
, "\t-O format:\n");
3242 fprintf(stderr
, "\t\tfile format of signed zone file (text)\n");
3243 fprintf(stderr
, "\t-N format:\n");
3244 fprintf(stderr
, "\t\tsoa serial format of signed zone file (keep)\n");
3245 fprintf(stderr
, "\t-r randomdev:\n");
3246 fprintf(stderr
, "\t\ta file containing random data\n");
3247 fprintf(stderr
, "\t-a:\t");
3248 fprintf(stderr
, "verify generated signatures\n");
3249 fprintf(stderr
, "\t-c class (IN)\n");
3250 fprintf(stderr
, "\t-E engine:\n");
3252 fprintf(stderr
, "\t\tname of an OpenSSL engine to use "
3253 "(default is \"pkcs11\")\n");
3255 fprintf(stderr
, "\t\tname of an OpenSSL engine to use\n");
3257 fprintf(stderr
, "\t-p:\t");
3258 fprintf(stderr
, "use pseudorandom data (faster but less secure)\n");
3259 fprintf(stderr
, "\t-P:\t");
3260 fprintf(stderr
, "disable post-sign verification\n");
3261 fprintf(stderr
, "\t-T TTL:\tTTL for newly added DNSKEYs");
3262 fprintf(stderr
, "\t-t:\t");
3263 fprintf(stderr
, "print statistics\n");
3264 fprintf(stderr
, "\t-u:\t");
3265 fprintf(stderr
, "update or replace an existing NSEC/NSEC3 chain\n");
3266 fprintf(stderr
, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
3267 fprintf(stderr
, "\t-z:\tsign all records with KSKs\n");
3268 fprintf(stderr
, "\t-C:\tgenerate a keyset file, for compatibility\n"
3269 "\t\twith older versions of dnssec-signzone -g\n");
3270 fprintf(stderr
, "\t-n ncpus (number of cpus present)\n");
3271 fprintf(stderr
, "\t-k key_signing_key\n");
3272 fprintf(stderr
, "\t-l lookasidezone\n");
3273 fprintf(stderr
, "\t-3 NSEC3 salt\n");
3274 fprintf(stderr
, "\t-H NSEC3 iterations (10)\n");
3275 fprintf(stderr
, "\t-A NSEC3 optout\n");
3277 fprintf(stderr
, "\n");
3279 fprintf(stderr
, "Signing Keys: ");
3280 fprintf(stderr
, "(default: all zone keys that have private keys)\n");
3281 fprintf(stderr
, "\tkeyfile (Kname+alg+tag)\n");
3286 removetempfile(void) {
3288 isc_file_remove(tempfile
);
3292 print_stats(isc_time_t
*timer_start
, isc_time_t
*timer_finish
) {
3293 isc_uint64_t runtime_us
; /* Runtime in microseconds */
3294 isc_uint64_t runtime_ms
; /* Runtime in milliseconds */
3295 isc_uint64_t sig_ms
; /* Signatures per millisecond */
3297 runtime_us
= isc_time_microdiff(timer_finish
, timer_start
);
3299 printf("Signatures generated: %10d\n", nsigned
);
3300 printf("Signatures retained: %10d\n", nretained
);
3301 printf("Signatures dropped: %10d\n", ndropped
);
3302 printf("Signatures successfully verified: %10d\n", nverified
);
3303 printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed
);
3304 runtime_ms
= runtime_us
/ 1000;
3305 printf("Runtime in seconds: %7u.%03u\n",
3306 (unsigned int) (runtime_ms
/ 1000),
3307 (unsigned int) (runtime_ms
% 1000));
3308 if (runtime_us
> 0) {
3309 sig_ms
= ((isc_uint64_t
)nsigned
* 1000000000) / runtime_us
;
3310 printf("Signatures per second: %7u.%03u\n",
3311 (unsigned int) sig_ms
/ 1000,
3312 (unsigned int) sig_ms
% 1000);
3317 main(int argc
, char *argv
[]) {
3319 char *startstr
= NULL
, *endstr
= NULL
, *classname
= NULL
;
3320 char *origin
= NULL
, *file
= NULL
, *output
= NULL
;
3321 char *inputformatstr
= NULL
, *outputformatstr
= NULL
;
3322 char *serialformatstr
= NULL
;
3323 char *dskeyfile
[MAXDSKEYS
];
3326 isc_time_t timer_start
, timer_finish
;
3327 dns_dnsseckey_t
*key
;
3328 isc_result_t result
;
3329 isc_log_t
*log
= NULL
;
3330 isc_boolean_t pseudorandom
= ISC_FALSE
;
3332 const char *engine
= "pkcs11";
3334 const char *engine
= NULL
;
3336 unsigned int eflags
;
3337 isc_boolean_t free_output
= ISC_FALSE
;
3339 dns_rdataclass_t rdclass
;
3340 isc_task_t
**tasks
= NULL
;
3343 hashlist_t hashlist
;
3344 isc_boolean_t smartsign
= ISC_FALSE
;
3345 isc_boolean_t make_keyset
= ISC_FALSE
;
3346 isc_boolean_t set_salt
= ISC_FALSE
;
3347 isc_boolean_t set_optout
= ISC_FALSE
;
3348 isc_boolean_t set_iter
= ISC_FALSE
;
3350 #define CMDLINE_FLAGS \
3351 "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:l:m:n:N:o:O:pPr:s:ST:tuUv:xz"
3354 * Process memory debugging argument first.
3356 while ((ch
= isc_commandline_parse(argc
, argv
, CMDLINE_FLAGS
)) != -1) {
3359 if (strcasecmp(isc_commandline_argument
, "record") == 0)
3360 isc_mem_debugging
|= ISC_MEM_DEBUGRECORD
;
3361 if (strcasecmp(isc_commandline_argument
, "trace") == 0)
3362 isc_mem_debugging
|= ISC_MEM_DEBUGTRACE
;
3363 if (strcasecmp(isc_commandline_argument
, "usage") == 0)
3364 isc_mem_debugging
|= ISC_MEM_DEBUGUSAGE
;
3365 if (strcasecmp(isc_commandline_argument
, "size") == 0)
3366 isc_mem_debugging
|= ISC_MEM_DEBUGSIZE
;
3367 if (strcasecmp(isc_commandline_argument
, "mctx") == 0)
3368 isc_mem_debugging
|= ISC_MEM_DEBUGCTX
;
3374 isc_commandline_reset
= ISC_TRUE
;
3376 masterstyle
= &dns_master_style_explicitttl
;
3378 check_result(isc_app_start(), "isc_app_start");
3380 result
= isc_mem_create(0, 0, &mctx
);
3381 if (result
!= ISC_R_SUCCESS
)
3382 fatal("out of memory");
3384 dns_result_register();
3386 isc_commandline_errprint
= ISC_FALSE
;
3388 while ((ch
= isc_commandline_parse(argc
, argv
, CMDLINE_FLAGS
)) != -1) {
3391 set_salt
= ISC_TRUE
;
3392 nsec_datatype
= dns_rdatatype_nsec3
;
3393 if (strcmp(isc_commandline_argument
, "-") != 0) {
3394 isc_buffer_t target
;
3397 sarg
= isc_commandline_argument
;
3398 isc_buffer_init(&target
, saltbuf
,
3400 result
= isc_hex_decodestring(sarg
, &target
);
3401 check_result(result
,
3402 "isc_hex_decodestring(salt)");
3403 salt_length
= isc_buffer_usedlength(&target
);
3408 set_optout
= ISC_TRUE
;
3409 if (OPTOUT(nsec3flags
))
3410 nsec3flags
&= ~DNS_NSEC3FLAG_OPTOUT
;
3412 nsec3flags
|= DNS_NSEC3FLAG_OPTOUT
;
3416 tryverify
= ISC_TRUE
;
3420 make_keyset
= ISC_TRUE
;
3424 classname
= isc_commandline_argument
;
3428 dsdir
= isc_commandline_argument
;
3429 if (strlen(dsdir
) == 0U)
3430 fatal("DS directory must be non-empty string");
3431 result
= try_dir(dsdir
);
3432 if (result
!= ISC_R_SUCCESS
)
3433 fatal("cannot open directory %s: %s",
3434 dsdir
, isc_result_totext(result
));
3438 engine
= isc_commandline_argument
;
3442 endstr
= isc_commandline_argument
;
3446 output
= isc_commandline_argument
;
3450 generateds
= ISC_TRUE
;
3454 set_iter
= ISC_TRUE
;
3455 nsec3iter
= strtoul(isc_commandline_argument
, &endp
, 0);
3457 fatal("iterations must be numeric");
3458 if (nsec3iter
> 0xffffU
)
3459 fatal("iterations too big");
3467 inputformatstr
= isc_commandline_argument
;
3472 cycle
= strtol(isc_commandline_argument
, &endp
, 0);
3473 if (*endp
!= '\0' || cycle
< 0)
3474 fatal("cycle period must be numeric and "
3480 jitter
= strtol(isc_commandline_argument
, &endp
, 0);
3481 if (*endp
!= '\0' || jitter
< 0)
3482 fatal("jitter must be numeric and positive");
3486 directory
= isc_commandline_argument
;
3490 if (ndskeys
== MAXDSKEYS
)
3491 fatal("too many key-signing keys specified");
3492 dskeyfile
[ndskeys
++] = isc_commandline_argument
;
3496 len
= strlen(isc_commandline_argument
);
3497 isc_buffer_init(&b
, isc_commandline_argument
, len
);
3498 isc_buffer_add(&b
, len
);
3500 dns_fixedname_init(&dlv_fixed
);
3501 dlv
= dns_fixedname_name(&dlv_fixed
);
3502 result
= dns_name_fromtext(dlv
, &b
, dns_rootname
, 0,
3504 check_result(result
, "dns_name_fromtext(dlv)");
3511 serialformatstr
= isc_commandline_argument
;
3516 ntasks
= strtol(isc_commandline_argument
, &endp
, 0);
3517 if (*endp
!= '\0' || ntasks
> ISC_INT32_MAX
)
3518 fatal("number of cpus must be numeric");
3522 outputformatstr
= isc_commandline_argument
;
3526 origin
= isc_commandline_argument
;
3530 disable_zone_check
= ISC_TRUE
;
3534 pseudorandom
= ISC_TRUE
;
3538 setup_entropy(mctx
, isc_commandline_argument
, &ectx
);
3542 smartsign
= ISC_TRUE
;
3546 startstr
= isc_commandline_argument
;
3551 set_keyttl
= ISC_TRUE
;
3552 keyttl
= strtottl(isc_commandline_argument
);
3556 printstats
= ISC_TRUE
;
3559 case 'U': /* Undocumented for testing only. */
3560 unknownalg
= ISC_TRUE
;
3564 update_chain
= ISC_TRUE
;
3569 verbose
= strtol(isc_commandline_argument
, &endp
, 0);
3571 fatal("verbose level must be numeric");
3575 keyset_kskonly
= ISC_TRUE
;
3579 ignore_kskflag
= ISC_TRUE
;
3583 /* Reserved for FIPS mode */
3586 if (isc_commandline_option
!= '?')
3587 fprintf(stderr
, "%s: invalid argument -%c\n",
3588 program
, isc_commandline_option
);
3593 fprintf(stderr
, "%s: unhandled option -%c\n",
3594 program
, isc_commandline_option
);
3600 setup_entropy(mctx
, NULL
, &ectx
);
3601 eflags
= ISC_ENTROPY_BLOCKING
;
3603 eflags
|= ISC_ENTROPY_GOODONLY
;
3605 result
= isc_hash_create(mctx
, ectx
, DNS_NAME_MAXWIRE
);
3606 if (result
!= ISC_R_SUCCESS
)
3607 fatal("could not create hash context");
3609 result
= dst_lib_init2(mctx
, ectx
, engine
, eflags
);
3610 if (result
!= ISC_R_SUCCESS
)
3611 fatal("could not initialize dst: %s",
3612 isc_result_totext(result
));
3614 isc_stdtime_get(&now
);
3616 if (startstr
!= NULL
) {
3617 starttime
= strtotime(startstr
, now
, now
);
3619 starttime
= now
- 3600; /* Allow for some clock skew. */
3621 if (endstr
!= NULL
) {
3622 endtime
= strtotime(endstr
, now
, starttime
);
3624 endtime
= starttime
+ (30 * 24 * 60 * 60);
3627 cycle
= (endtime
- starttime
) / 4;
3630 ntasks
= isc_os_ncpus() * 2;
3631 vbprintf(4, "using %d cpus\n", ntasks
);
3633 rdclass
= strtoclass(classname
);
3635 if (directory
== NULL
)
3638 setup_logging(verbose
, mctx
, &log
);
3640 argc
-= isc_commandline_index
;
3641 argv
+= isc_commandline_index
;
3654 if (output
== NULL
) {
3655 free_output
= ISC_TRUE
;
3656 output
= isc_mem_allocate(mctx
,
3657 strlen(file
) + strlen(".signed") + 1);
3659 fatal("out of memory");
3660 sprintf(output
, "%s.signed", file
);
3663 if (inputformatstr
!= NULL
) {
3664 if (strcasecmp(inputformatstr
, "text") == 0)
3665 inputformat
= dns_masterformat_text
;
3666 else if (strcasecmp(inputformatstr
, "raw") == 0)
3667 inputformat
= dns_masterformat_raw
;
3669 fatal("unknown file format: %s\n", inputformatstr
);
3672 if (outputformatstr
!= NULL
) {
3673 if (strcasecmp(outputformatstr
, "text") == 0)
3674 outputformat
= dns_masterformat_text
;
3675 else if (strcasecmp(outputformatstr
, "raw") == 0)
3676 outputformat
= dns_masterformat_raw
;
3678 fatal("unknown file format: %s\n", outputformatstr
);
3681 if (serialformatstr
!= NULL
) {
3682 if (strcasecmp(serialformatstr
, "keep") == 0)
3683 serialformat
= SOA_SERIAL_KEEP
;
3684 else if (strcasecmp(serialformatstr
, "increment") == 0 ||
3685 strcasecmp(serialformatstr
, "incr") == 0)
3686 serialformat
= SOA_SERIAL_INCREMENT
;
3687 else if (strcasecmp(serialformatstr
, "unixtime") == 0)
3688 serialformat
= SOA_SERIAL_UNIXTIME
;
3690 fatal("unknown soa serial format: %s\n",
3694 result
= dns_master_stylecreate(&dsstyle
, DNS_STYLEFLAG_NO_TTL
,
3695 0, 24, 0, 0, 0, 8, mctx
);
3696 check_result(result
, "dns_master_stylecreate");
3699 TIME_NOW(&timer_start
);
3700 loadzone(file
, origin
, rdclass
, &gdb
);
3701 gorigin
= dns_db_origin(gdb
);
3702 gclass
= dns_db_class(gdb
);
3709 * Check for any existing NSEC3 parameters in the zone,
3710 * and use them as defaults if -u was not specified.
3712 if (update_chain
&& !set_optout
&& !set_iter
&& !set_salt
)
3713 nsec_datatype
= dns_rdatatype_nsec
;
3715 set_nsec3params(update_chain
, set_salt
, set_optout
, set_iter
);
3718 isc_boolean_t answer
;
3719 hash_length
= dns_nsec3_hashlength(dns_hash_sha1
);
3720 hashlist_init(&hashlist
, dns_db_nodecount(gdb
) * 2,
3722 result
= dns_nsec_nseconly(gdb
, gversion
, &answer
);
3723 check_result(result
, "dns_nsec_nseconly");
3725 fatal("NSEC3 generation requested with "
3726 "NSEC only DNSKEY");
3730 * We need to do this early on, as we start messing with the list
3731 * of keys rather early.
3733 ISC_LIST_INIT(keylist
);
3734 isc_rwlock_init(&keylist_lock
, 0, 0);
3737 * Fill keylist with:
3738 * 1) Keys listed in the DNSKEY set that have
3739 * private keys associated, *if* no keys were
3740 * set on the command line.
3741 * 2) ZSKs set on the command line
3742 * 3) KSKs set on the command line
3743 * 4) Any keys remaining in the DNSKEY set which
3744 * do not have private keys associated and were
3745 * not specified on the command line.
3747 if (argc
== 0 || smartsign
)
3748 loadzonekeys(!smartsign
, ISC_FALSE
);
3749 loadexplicitkeys(argv
, argc
, ISC_FALSE
);
3750 loadexplicitkeys(dskeyfile
, ndskeys
, ISC_TRUE
);
3751 loadzonekeys(!smartsign
, ISC_TRUE
);
3754 * If we're doing smart signing, look in the key repository for
3755 * key files with metadata, and merge them with the keylist
3759 build_final_keylist();
3761 /* Now enumerate the key list */
3762 for (key
= ISC_LIST_HEAD(keylist
);
3764 key
= ISC_LIST_NEXT(key
, link
)) {
3765 key
->index
= keycount
++;
3768 if (keycount
== 0) {
3769 if (disable_zone_check
)
3770 fprintf(stderr
, "%s: warning: No keys specified "
3771 "or found\n", program
);
3773 fatal("No signing keys specified or found.");
3779 result
= dns_nsec3_maxiterations(gdb
, NULL
, mctx
, &max
);
3780 check_result(result
, "dns_nsec3_maxiterations()");
3781 if (nsec3iter
> max
)
3782 fatal("NSEC3 iterations too big for weakest DNSKEY "
3783 "strength. Maximum iterations allowed %u.", max
);
3789 result
= dns_db_newversion(gdb
, &gversion
);
3790 check_result(result
, "dns_db_newversion()");
3792 switch (serialformat
) {
3793 case SOA_SERIAL_INCREMENT
:
3796 case SOA_SERIAL_UNIXTIME
:
3799 case SOA_SERIAL_KEEP
:
3805 remove_duplicates();
3808 nsec3ify(dns_hash_sha1
, nsec3iter
, salt
, salt_length
,
3814 writeset("dsset-", dns_rdatatype_ds
);
3816 writeset("keyset-", dns_rdatatype_dnskey
);
3818 writeset("dlvset-", dns_rdatatype_dlv
);
3822 tempfilelen
= strlen(output
) + 20;
3823 tempfile
= isc_mem_get(mctx
, tempfilelen
);
3824 if (tempfile
== NULL
)
3825 fatal("out of memory");
3827 result
= isc_file_mktemplate(output
, tempfile
, tempfilelen
);
3828 check_result(result
, "isc_file_mktemplate");
3831 result
= isc_file_openunique(tempfile
, &fp
);
3832 if (result
!= ISC_R_SUCCESS
)
3833 fatal("failed to open temporary output file: %s",
3834 isc_result_totext(result
));
3835 removefile
= ISC_TRUE
;
3836 setfatalcallback(&removetempfile
);
3841 result
= isc_taskmgr_create(mctx
, ntasks
, 0, &taskmgr
);
3842 if (result
!= ISC_R_SUCCESS
)
3843 fatal("failed to create task manager: %s",
3844 isc_result_totext(result
));
3847 result
= isc_task_create(taskmgr
, 0, &master
);
3848 if (result
!= ISC_R_SUCCESS
)
3849 fatal("failed to create task: %s", isc_result_totext(result
));
3851 tasks
= isc_mem_get(mctx
, ntasks
* sizeof(isc_task_t
*));
3853 fatal("out of memory");
3854 for (i
= 0; i
< (int)ntasks
; i
++) {
3856 result
= isc_task_create(taskmgr
, 0, &tasks
[i
]);
3857 if (result
!= ISC_R_SUCCESS
)
3858 fatal("failed to create task: %s",
3859 isc_result_totext(result
));
3862 RUNTIME_CHECK(isc_mutex_init(&namelock
) == ISC_R_SUCCESS
);
3864 RUNTIME_CHECK(isc_mutex_init(&statslock
) == ISC_R_SUCCESS
);
3870 * There is more work to do. Spread it out over multiple
3871 * processors if possible.
3873 for (i
= 0; i
< (int)ntasks
; i
++) {
3874 result
= isc_app_onrun(mctx
, master
, startworker
,
3876 if (result
!= ISC_R_SUCCESS
)
3877 fatal("failed to start task: %s",
3878 isc_result_totext(result
));
3880 (void)isc_app_run();
3882 fatal("process aborted by user");
3884 isc_task_detach(&master
);
3885 shuttingdown
= ISC_TRUE
;
3886 for (i
= 0; i
< (int)ntasks
; i
++)
3887 isc_task_detach(&tasks
[i
]);
3888 isc_taskmgr_destroy(&taskmgr
);
3889 isc_mem_put(mctx
, tasks
, ntasks
* sizeof(isc_task_t
*));
3893 if (outputformat
!= dns_masterformat_text
) {
3894 result
= dns_master_dumptostream2(mctx
, gdb
, gversion
,
3895 masterstyle
, outputformat
,
3897 check_result(result
, "dns_master_dumptostream2");
3900 result
= isc_stdio_close(fp
);
3901 check_result(result
, "isc_stdio_close");
3902 removefile
= ISC_FALSE
;
3904 result
= isc_file_rename(tempfile
, output
);
3905 if (result
!= ISC_R_SUCCESS
)
3906 fatal("failed to rename temp file to %s: %s\n",
3907 output
, isc_result_totext(result
));
3909 DESTROYLOCK(&namelock
);
3911 DESTROYLOCK(&statslock
);
3913 printf("%s\n", output
);
3915 dns_db_closeversion(gdb
, &gversion
, ISC_FALSE
);
3916 dns_db_detach(&gdb
);
3918 while (!ISC_LIST_EMPTY(keylist
)) {
3919 key
= ISC_LIST_HEAD(keylist
);
3920 ISC_LIST_UNLINK(keylist
, key
, link
);
3921 dns_dnsseckey_destroy(mctx
, &key
);
3924 isc_mem_put(mctx
, tempfile
, tempfilelen
);
3927 isc_mem_free(mctx
, output
);
3929 dns_master_styledestroy(&dsstyle
, mctx
);
3931 cleanup_logging(&log
);
3934 cleanup_entropy(&ectx
);
3937 isc_mem_stats(mctx
, stdout
);
3938 isc_mem_destroy(&mctx
);
3940 (void) isc_app_finish();
3943 TIME_NOW(&timer_finish
);
3944 print_stats(&timer_start
, &timer_finish
);