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