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