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