dnssec-signzone.c

Go to the documentation of this file.
00001 /*
00002  * Portions Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Portions Copyright (C) 1999-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
00010  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
00011  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
00012  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00013  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00014  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
00015  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00016  *
00017  * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
00018  *
00019  * Permission to use, copy, modify, and/or distribute this software for any
00020  * purpose with or without fee is hereby granted, provided that the above
00021  * copyright notice and this permission notice appear in all copies.
00022  *
00023  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
00024  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
00025  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
00026  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00027  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00028  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
00029  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00030  */
00031 
00032 /*! \file */
00033 
00034 #include <config.h>
00035 
00036 #include <stdlib.h>
00037 #include <time.h>
00038 #include <unistd.h>
00039 
00040 #include <isc/app.h>
00041 #include <isc/base32.h>
00042 #include <isc/commandline.h>
00043 #include <isc/entropy.h>
00044 #include <isc/event.h>
00045 #include <isc/file.h>
00046 #include <isc/hash.h>
00047 #include <isc/hex.h>
00048 #include <isc/mem.h>
00049 #include <isc/mutex.h>
00050 #include <isc/os.h>
00051 #include <isc/print.h>
00052 #include <isc/random.h>
00053 #include <isc/rwlock.h>
00054 #include <isc/serial.h>
00055 #include <isc/stdio.h>
00056 #include <isc/stdlib.h>
00057 #include <isc/string.h>
00058 #include <isc/task.h>
00059 #include <isc/time.h>
00060 #include <isc/util.h>
00061 
00062 #include <dns/db.h>
00063 #include <dns/dbiterator.h>
00064 #include <dns/diff.h>
00065 #include <dns/dnssec.h>
00066 #include <dns/ds.h>
00067 #include <dns/fixedname.h>
00068 #include <dns/keyvalues.h>
00069 #include <dns/log.h>
00070 #include <dns/master.h>
00071 #include <dns/masterdump.h>
00072 #include <dns/nsec.h>
00073 #include <dns/nsec3.h>
00074 #include <dns/rdata.h>
00075 #include <dns/rdatalist.h>
00076 #include <dns/rdataset.h>
00077 #include <dns/rdataclass.h>
00078 #include <dns/rdatasetiter.h>
00079 #include <dns/rdatastruct.h>
00080 #include <dns/rdatatype.h>
00081 #include <dns/result.h>
00082 #include <dns/soa.h>
00083 #include <dns/time.h>
00084 #include <dns/update.h>
00085 
00086 #include <dst/dst.h>
00087 
00088 #ifdef PKCS11CRYPTO
00089 #include <pk11/result.h>
00090 #endif
00091 
00092 #include "dnssectool.h"
00093 
00094 #ifndef PATH_MAX
00095 #define PATH_MAX 1024   /* AIX, WIN32, and others don't define this. */
00096 #endif
00097 
00098 const char *program = "dnssec-signzone";
00099 int verbose;
00100 
00101 typedef struct hashlist hashlist_t;
00102 
00103 static int nsec_datatype = dns_rdatatype_nsec;
00104 
00105 #define IS_NSEC3        (nsec_datatype == dns_rdatatype_nsec3)
00106 #define OPTOUT(x)       (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
00107 
00108 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
00109 
00110 #define BUFSIZE 2048
00111 #define MAXDSKEYS 8
00112 
00113 #define SIGNER_EVENTCLASS       ISC_EVENTCLASS(0x4453)
00114 #define SIGNER_EVENT_WRITE      (SIGNER_EVENTCLASS + 0)
00115 #define SIGNER_EVENT_WORK       (SIGNER_EVENTCLASS + 1)
00116 
00117 #define SOA_SERIAL_KEEP         0
00118 #define SOA_SERIAL_INCREMENT    1
00119 #define SOA_SERIAL_UNIXTIME     2
00120 #define SOA_SERIAL_DATE         3
00121 
00122 typedef struct signer_event sevent_t;
00123 struct signer_event {
00124         ISC_EVENT_COMMON(sevent_t);
00125         dns_fixedname_t *fname;
00126         dns_dbnode_t *node;
00127 };
00128 
00129 static dns_dnsseckeylist_t keylist;
00130 static unsigned int keycount = 0;
00131 isc_rwlock_t keylist_lock;
00132 static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now;
00133 static int cycle = -1;
00134 static int jitter = 0;
00135 static isc_boolean_t tryverify = ISC_FALSE;
00136 static isc_boolean_t printstats = ISC_FALSE;
00137 static isc_mem_t *mctx = NULL;
00138 static isc_entropy_t *ectx = NULL;
00139 static dns_ttl_t zone_soa_min_ttl;
00140 static dns_ttl_t soa_ttl;
00141 static FILE *outfp = NULL;
00142 static char *tempfile = NULL;
00143 static const dns_master_style_t *masterstyle;
00144 static dns_masterformat_t inputformat = dns_masterformat_text;
00145 static dns_masterformat_t outputformat = dns_masterformat_text;
00146 static isc_uint32_t rawversion = 1, serialnum = 0;
00147 static isc_boolean_t snset = ISC_FALSE;
00148 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
00149 static unsigned int nverified = 0, nverifyfailed = 0;
00150 static const char *directory = NULL, *dsdir = NULL;
00151 static isc_mutex_t namelock, statslock;
00152 static isc_taskmgr_t *taskmgr = NULL;
00153 static dns_db_t *gdb;                   /* The database */
00154 static dns_dbversion_t *gversion;       /* The database version */
00155 static dns_dbiterator_t *gdbiter;       /* The database iterator */
00156 static dns_rdataclass_t gclass;         /* The class */
00157 static dns_name_t *gorigin;             /* The database origin */
00158 static int nsec3flags = 0;
00159 static dns_iterations_t nsec3iter = 10U;
00160 static unsigned char saltbuf[255];
00161 static unsigned char *gsalt = saltbuf;
00162 static size_t salt_length = 0;
00163 static isc_task_t *master = NULL;
00164 static unsigned int ntasks = 0;
00165 static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
00166 static isc_boolean_t nokeys = ISC_FALSE;
00167 static isc_boolean_t removefile = ISC_FALSE;
00168 static isc_boolean_t generateds = ISC_FALSE;
00169 static isc_boolean_t ignore_kskflag = ISC_FALSE;
00170 static isc_boolean_t keyset_kskonly = ISC_FALSE;
00171 static dns_name_t *dlv = NULL;
00172 static dns_fixedname_t dlv_fixed;
00173 static dns_master_style_t *dsstyle = NULL;
00174 static unsigned int serialformat = SOA_SERIAL_KEEP;
00175 static unsigned int hash_length = 0;
00176 static isc_boolean_t unknownalg = ISC_FALSE;
00177 static isc_boolean_t disable_zone_check = ISC_FALSE;
00178 static isc_boolean_t update_chain = ISC_FALSE;
00179 static isc_boolean_t set_keyttl = ISC_FALSE;
00180 static dns_ttl_t keyttl;
00181 static isc_boolean_t smartsign = ISC_FALSE;
00182 static isc_boolean_t remove_orphansigs = ISC_FALSE;
00183 static isc_boolean_t remove_inactkeysigs = ISC_FALSE;
00184 static isc_boolean_t output_dnssec_only = ISC_FALSE;
00185 static isc_boolean_t output_stdout = ISC_FALSE;
00186 isc_boolean_t set_maxttl = ISC_FALSE;
00187 static dns_ttl_t maxttl = 0;
00188 
00189 #define INCSTAT(counter)                \
00190         if (printstats) {               \
00191                 LOCK(&statslock);       \
00192                 counter++;              \
00193                 UNLOCK(&statslock);     \
00194         }
00195 
00196 static void
00197 sign(isc_task_t *task, isc_event_t *event);
00198 
00199 static void
00200 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
00201         dns_rdataset_t rds;
00202         dns_rdatasetiter_t *iter = NULL;
00203         isc_buffer_t *buffer = NULL;
00204         isc_region_t r;
00205         isc_result_t result;
00206         unsigned bufsize = 4096;
00207 
00208         if (outputformat != dns_masterformat_text)
00209                 return;
00210 
00211         if (!output_dnssec_only) {
00212                 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node,
00213                                                      name, masterstyle, outfp);
00214                 check_result(result, "dns_master_dumpnodetostream");
00215                 return;
00216         }
00217 
00218         result = dns_db_allrdatasets(gdb, node, gversion, 0, &iter);
00219         check_result(result, "dns_db_allrdatasets");
00220 
00221         dns_rdataset_init(&rds);
00222 
00223         result = isc_buffer_allocate(mctx, &buffer, bufsize);
00224         check_result(result, "isc_buffer_allocate");
00225 
00226         for (result = dns_rdatasetiter_first(iter);
00227              result == ISC_R_SUCCESS;
00228              result = dns_rdatasetiter_next(iter)) {
00229 
00230                 dns_rdatasetiter_current(iter, &rds);
00231 
00232                 if (rds.type != dns_rdatatype_rrsig &&
00233                     rds.type != dns_rdatatype_nsec &&
00234                     rds.type != dns_rdatatype_nsec3 &&
00235                     rds.type != dns_rdatatype_nsec3param &&
00236                     (!smartsign || rds.type != dns_rdatatype_dnskey)) {
00237                         dns_rdataset_disassociate(&rds);
00238                         continue;
00239                 }
00240 
00241                 for (;;) {
00242                         result = dns_master_rdatasettotext(name, &rds,
00243                                                            masterstyle, buffer);
00244                         if (result != ISC_R_NOSPACE)
00245                                 break;
00246 
00247                         bufsize <<= 1;
00248                         isc_buffer_free(&buffer);
00249                         result = isc_buffer_allocate(mctx, &buffer, bufsize);
00250                         check_result(result, "isc_buffer_allocate");
00251                 }
00252                 check_result(result, "dns_master_rdatasettotext");
00253 
00254                 isc_buffer_usedregion(buffer, &r);
00255                 result = isc_stdio_write(r.base, 1, r.length, outfp, NULL);
00256                 check_result(result, "isc_stdio_write");
00257                 isc_buffer_clear(buffer);
00258 
00259                 dns_rdataset_disassociate(&rds);
00260         }
00261 
00262         isc_buffer_free(&buffer);
00263         dns_rdatasetiter_destroy(&iter);
00264 }
00265 
00266 /*%
00267  * Sign the given RRset with given key, and add the signature record to the
00268  * given tuple.
00269  */
00270 static void
00271 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
00272             dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
00273 {
00274         isc_result_t result;
00275         isc_stdtime_t jendtime, expiry;
00276         char keystr[DST_KEY_FORMATSIZE];
00277         dns_rdata_t trdata = DNS_RDATA_INIT;
00278         unsigned char array[BUFSIZE];
00279         isc_buffer_t b;
00280         dns_difftuple_t *tuple;
00281 
00282         dst_key_format(key, keystr, sizeof(keystr));
00283         vbprintf(1, "\t%s %s\n", logmsg, keystr);
00284 
00285         if (rdataset->type == dns_rdatatype_dnskey)
00286                 expiry = dnskey_endtime;
00287         else
00288                 expiry = endtime;
00289 
00290         jendtime = (jitter != 0) ? isc_random_jitter(expiry, jitter) : expiry;
00291         isc_buffer_init(&b, array, sizeof(array));
00292         result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
00293                                  mctx, &b, &trdata);
00294         isc_entropy_stopcallbacksources(ectx);
00295         if (result != ISC_R_SUCCESS) {
00296                 fatal("dnskey '%s' failed to sign data: %s",
00297                       keystr, isc_result_totext(result));
00298         }
00299         INCSTAT(nsigned);
00300 
00301         if (tryverify) {
00302                 result = dns_dnssec_verify(name, rdataset, key,
00303                                            ISC_TRUE, mctx, &trdata);
00304                 if (result == ISC_R_SUCCESS) {
00305                         vbprintf(3, "\tsignature verified\n");
00306                         INCSTAT(nverified);
00307                 } else {
00308                         vbprintf(3, "\tsignature failed to verify\n");
00309                         INCSTAT(nverifyfailed);
00310                 }
00311         }
00312 
00313         tuple = NULL;
00314         result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN,
00315                                       name, ttl, &trdata, &tuple);
00316         check_result(result, "dns_difftuple_create");
00317         dns_diff_append(add, &tuple);
00318 }
00319 
00320 static inline isc_boolean_t
00321 issigningkey(dns_dnsseckey_t *key) {
00322         return (key->force_sign || key->hint_sign);
00323 }
00324 
00325 static inline isc_boolean_t
00326 ispublishedkey(dns_dnsseckey_t *key) {
00327         return ((key->force_publish || key->hint_publish) &&
00328                 !key->hint_remove);
00329 }
00330 
00331 static inline isc_boolean_t
00332 iszonekey(dns_dnsseckey_t *key) {
00333         return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
00334                        dst_key_iszonekey(key->key)));
00335 }
00336 
00337 static inline isc_boolean_t
00338 isksk(dns_dnsseckey_t *key) {
00339         return (key->ksk);
00340 }
00341 
00342 static inline isc_boolean_t
00343 iszsk(dns_dnsseckey_t *key) {
00344         return (ignore_kskflag || !key->ksk);
00345 }
00346 
00347 /*%
00348  * Find the key that generated an RRSIG, if it is in the key list.  If
00349  * so, return a pointer to it, otherwise return NULL.
00350  *
00351  * No locking is performed here, this must be done by the caller.
00352  */
00353 static dns_dnsseckey_t *
00354 keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
00355         dns_dnsseckey_t *key;
00356 
00357         for (key = ISC_LIST_HEAD(keylist);
00358              key != NULL;
00359              key = ISC_LIST_NEXT(key, link)) {
00360                 if (rrsig->keyid == dst_key_id(key->key) &&
00361                     rrsig->algorithm == dst_key_alg(key->key) &&
00362                     dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
00363                         return (key);
00364         }
00365         return (NULL);
00366 }
00367 
00368 /*%
00369  * Finds the key that generated a RRSIG, if possible.  First look at the keys
00370  * that we've loaded already, and then see if there's a key on disk.
00371  */
00372 static dns_dnsseckey_t *
00373 keythatsigned(dns_rdata_rrsig_t *rrsig) {
00374         isc_result_t result;
00375         dst_key_t *pubkey = NULL, *privkey = NULL;
00376         dns_dnsseckey_t *key = NULL;
00377 
00378         isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
00379         key = keythatsigned_unlocked(rrsig);
00380         isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
00381         if (key != NULL)
00382                 return (key);
00383 
00384         /*
00385          * We did not find the key in our list.  Get a write lock now, since
00386          * we may be modifying the bits.  We could do the tryupgrade() dance,
00387          * but instead just get a write lock and check once again to see if
00388          * it is on our list.  It's possible someone else may have added it
00389          * after all.
00390          */
00391         isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
00392         key = keythatsigned_unlocked(rrsig);
00393         if (key != NULL) {
00394                 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
00395                 return (key);
00396         }
00397 
00398         result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
00399                                   rrsig->algorithm, DST_TYPE_PUBLIC,
00400                                   directory, mctx, &pubkey);
00401         if (result != ISC_R_SUCCESS) {
00402                 isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
00403                 return (NULL);
00404         }
00405 
00406         result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
00407                                   rrsig->algorithm,
00408                                   DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
00409                                   directory, mctx, &privkey);
00410         if (result == ISC_R_SUCCESS) {
00411                 dst_key_free(&pubkey);
00412                 result = dns_dnsseckey_create(mctx, &privkey, &key);
00413         } else
00414                 result = dns_dnsseckey_create(mctx, &pubkey, &key);
00415 
00416         if (result == ISC_R_SUCCESS) {
00417                 key->force_publish = ISC_FALSE;
00418                 key->force_sign = ISC_FALSE;
00419                 key->index = keycount++;
00420                 ISC_LIST_APPEND(keylist, key, link);
00421         }
00422 
00423         isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
00424         return (key);
00425 }
00426 
00427 /*%
00428  * Check to see if we expect to find a key at this name.  If we see a RRSIG
00429  * and can't find the signing key that we expect to find, we drop the rrsig.
00430  * I'm not sure if this is completely correct, but it seems to work.
00431  */
00432 static isc_boolean_t
00433 expecttofindkey(dns_name_t *name) {
00434         unsigned int options = DNS_DBFIND_NOWILD;
00435         dns_fixedname_t fname;
00436         isc_result_t result;
00437         char namestr[DNS_NAME_FORMATSIZE];
00438 
00439         dns_fixedname_init(&fname);
00440         result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
00441                              0, NULL, dns_fixedname_name(&fname), NULL, NULL);
00442         switch (result) {
00443         case ISC_R_SUCCESS:
00444         case DNS_R_NXDOMAIN:
00445         case DNS_R_NXRRSET:
00446                 return (ISC_TRUE);
00447         case DNS_R_DELEGATION:
00448         case DNS_R_CNAME:
00449         case DNS_R_DNAME:
00450                 return (ISC_FALSE);
00451         }
00452         dns_name_format(name, namestr, sizeof(namestr));
00453         fatal("failure looking for '%s DNSKEY' in database: %s",
00454               namestr, isc_result_totext(result));
00455         /* NOTREACHED */
00456         return (ISC_FALSE); /* removes a warning */
00457 }
00458 
00459 static inline isc_boolean_t
00460 setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
00461             dns_rdata_t *rrsig)
00462 {
00463         isc_result_t result;
00464         result = dns_dnssec_verify(name, set, key, ISC_FALSE, mctx, rrsig);
00465         if (result == ISC_R_SUCCESS) {
00466                 INCSTAT(nverified);
00467                 return (ISC_TRUE);
00468         } else {
00469                 INCSTAT(nverifyfailed);
00470                 return (ISC_FALSE);
00471         }
00472 }
00473 
00474 /*%
00475  * Signs a set.  Goes through contortions to decide if each RRSIG should
00476  * be dropped or retained, and then determines if any new SIGs need to
00477  * be generated.
00478  */
00479 static void
00480 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
00481         dns_rdataset_t *set)
00482 {
00483         dns_rdataset_t sigset;
00484         dns_rdata_t sigrdata = DNS_RDATA_INIT;
00485         dns_rdata_rrsig_t rrsig;
00486         dns_dnsseckey_t *key;
00487         isc_result_t result;
00488         isc_boolean_t nosigs = ISC_FALSE;
00489         isc_boolean_t *wassignedby, *nowsignedby;
00490         int arraysize;
00491         dns_difftuple_t *tuple;
00492         dns_ttl_t ttl;
00493         int i;
00494         char namestr[DNS_NAME_FORMATSIZE];
00495         char typestr[TYPE_FORMATSIZE];
00496         char sigstr[SIG_FORMATSIZE];
00497 
00498         dns_name_format(name, namestr, sizeof(namestr));
00499         type_format(set->type, typestr, sizeof(typestr));
00500 
00501         ttl = ISC_MIN(set->ttl, endtime - starttime);
00502 
00503         dns_rdataset_init(&sigset);
00504         result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
00505                                      set->type, 0, &sigset, NULL);
00506         if (result == ISC_R_NOTFOUND) {
00507                 vbprintf(2, "no existing signatures for %s/%s\n",
00508                          namestr, typestr);
00509                 result = ISC_R_SUCCESS;
00510                 nosigs = ISC_TRUE;
00511         }
00512         if (result != ISC_R_SUCCESS)
00513                 fatal("failed while looking for '%s RRSIG %s': %s",
00514                       namestr, typestr, isc_result_totext(result));
00515 
00516         vbprintf(1, "%s/%s:\n", namestr, typestr);
00517 
00518         arraysize = keycount;
00519         if (!nosigs)
00520                 arraysize += dns_rdataset_count(&sigset);
00521         wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
00522         nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
00523         if (wassignedby == NULL || nowsignedby == NULL)
00524                 fatal("out of memory");
00525 
00526         for (i = 0; i < arraysize; i++)
00527                 wassignedby[i] = nowsignedby[i] = ISC_FALSE;
00528 
00529         if (nosigs)
00530                 result = ISC_R_NOMORE;
00531         else
00532                 result = dns_rdataset_first(&sigset);
00533 
00534         while (result == ISC_R_SUCCESS) {
00535                 isc_boolean_t expired, future;
00536                 isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
00537 
00538                 dns_rdataset_current(&sigset, &sigrdata);
00539 
00540                 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
00541                 check_result(result, "dns_rdata_tostruct");
00542 
00543                 future = isc_serial_lt(now, rrsig.timesigned);
00544 
00545                 key = keythatsigned(&rrsig);
00546                 sig_format(&rrsig, sigstr, sizeof(sigstr));
00547                 if (key != NULL && issigningkey(key))
00548                         expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
00549                 else
00550                         expired = isc_serial_gt(now, rrsig.timeexpire);
00551 
00552                 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
00553                         /* rrsig is dropped and not replaced */
00554                         vbprintf(2, "\trrsig by %s dropped - "
00555                                  "invalid validity period\n",
00556                                  sigstr);
00557                 } else if (key == NULL && !future &&
00558                            expecttofindkey(&rrsig.signer)) {
00559                         /* rrsig is dropped and not replaced */
00560                         vbprintf(2, "\trrsig by %s dropped - "
00561                                  "private dnskey not found\n",
00562                                  sigstr);
00563                 } else if (key == NULL || future) {
00564                         keep = (!expired && !remove_orphansigs);
00565                         vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
00566                                  keep ? "retained" : "dropped", sigstr);
00567                 } else if (!dns_dnssec_keyactive(key->key, now) &&
00568                            remove_inactkeysigs) {
00569                         keep = ISC_FALSE;
00570                         vbprintf(2, "\trrsig by %s dropped - key inactive\n",
00571                                  sigstr);
00572                 } else if (issigningkey(key)) {
00573                         wassignedby[key->index] = ISC_TRUE;
00574 
00575                         if (!expired && rrsig.originalttl == set->ttl &&
00576                             setverifies(name, set, key->key, &sigrdata)) {
00577                                 vbprintf(2, "\trrsig by %s retained\n", sigstr);
00578                                 keep = ISC_TRUE;
00579                         } else {
00580                                 vbprintf(2, "\trrsig by %s dropped - %s\n",
00581                                          sigstr, expired ? "expired" :
00582                                          rrsig.originalttl != set->ttl ?
00583                                          "ttl change" : "failed to verify");
00584                                 resign = ISC_TRUE;
00585                         }
00586                 } else if (!ispublishedkey(key) && remove_orphansigs) {
00587                         vbprintf(2, "\trrsig by %s dropped - dnskey removed\n",
00588                                  sigstr);
00589                 } else if (iszonekey(key)) {
00590                         wassignedby[key->index] = ISC_TRUE;
00591 
00592                         if (!expired && rrsig.originalttl == set->ttl &&
00593                             setverifies(name, set, key->key, &sigrdata)) {
00594                                 vbprintf(2, "\trrsig by %s retained\n", sigstr);
00595                                 keep = ISC_TRUE;
00596                         } else {
00597                                 vbprintf(2, "\trrsig by %s dropped - %s\n",
00598                                          sigstr, expired ? "expired" :
00599                                          rrsig.originalttl != set->ttl ?
00600                                          "ttl change" : "failed to verify");
00601                         }
00602                 } else if (!expired) {
00603                         vbprintf(2, "\trrsig by %s retained\n", sigstr);
00604                         keep = ISC_TRUE;
00605                 } else {
00606                         vbprintf(2, "\trrsig by %s expired\n", sigstr);
00607                 }
00608 
00609                 if (keep) {
00610                         if (key != NULL)
00611                                 nowsignedby[key->index] = ISC_TRUE;
00612                         INCSTAT(nretained);
00613                         if (sigset.ttl != ttl) {
00614                                 vbprintf(2, "\tfixing ttl %s\n", sigstr);
00615                                 tuple = NULL;
00616                                 result = dns_difftuple_create(mctx,
00617                                                       DNS_DIFFOP_DELRESIGN,
00618                                                       name, sigset.ttl,
00619                                                       &sigrdata, &tuple);
00620                                 check_result(result, "dns_difftuple_create");
00621                                 dns_diff_append(del, &tuple);
00622                                 result = dns_difftuple_create(mctx,
00623                                                       DNS_DIFFOP_ADDRESIGN,
00624                                                       name, ttl,
00625                                                       &sigrdata, &tuple);
00626                                 check_result(result, "dns_difftuple_create");
00627                                 dns_diff_append(add, &tuple);
00628                         }
00629                 } else {
00630                         tuple = NULL;
00631                         vbprintf(2, "removing signature by %s\n", sigstr);
00632                         result = dns_difftuple_create(mctx,
00633                                                       DNS_DIFFOP_DELRESIGN,
00634                                                       name, sigset.ttl,
00635                                                       &sigrdata, &tuple);
00636                         check_result(result, "dns_difftuple_create");
00637                         dns_diff_append(del, &tuple);
00638                         INCSTAT(ndropped);
00639                 }
00640 
00641                 if (resign) {
00642                         INSIST(!keep);
00643 
00644                         signwithkey(name, set, key->key, ttl, add,
00645                                     "resigning with dnskey");
00646                         nowsignedby[key->index] = ISC_TRUE;
00647                 }
00648 
00649                 dns_rdata_reset(&sigrdata);
00650                 dns_rdata_freestruct(&rrsig);
00651                 result = dns_rdataset_next(&sigset);
00652         }
00653         if (result == ISC_R_NOMORE)
00654                 result = ISC_R_SUCCESS;
00655 
00656         check_result(result, "dns_rdataset_first/next");
00657         if (dns_rdataset_isassociated(&sigset))
00658                 dns_rdataset_disassociate(&sigset);
00659 
00660         for (key = ISC_LIST_HEAD(keylist);
00661              key != NULL;
00662              key = ISC_LIST_NEXT(key, link))
00663         {
00664                 if (nowsignedby[key->index])
00665                         continue;
00666 
00667                 if (!issigningkey(key))
00668                         continue;
00669 
00670                 if (set->type == dns_rdatatype_dnskey &&
00671                      dns_name_equal(name, gorigin)) {
00672                         isc_boolean_t have_ksk;
00673                         dns_dnsseckey_t *tmpkey;
00674 
00675                         have_ksk = isksk(key);
00676                         for (tmpkey = ISC_LIST_HEAD(keylist);
00677                              tmpkey != NULL;
00678                              tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
00679                                 if (dst_key_alg(key->key) !=
00680                                     dst_key_alg(tmpkey->key))
00681                                         continue;
00682                                 if (REVOKE(tmpkey->key))
00683                                         continue;
00684                                 if (isksk(tmpkey))
00685                                         have_ksk = ISC_TRUE;
00686                         }
00687                         if (isksk(key) || !have_ksk ||
00688                             (iszsk(key) && !keyset_kskonly))
00689                                 signwithkey(name, set, key->key, ttl, add,
00690                                             "signing with dnskey");
00691                 } else if (iszsk(key)) {
00692                         signwithkey(name, set, key->key, ttl, add,
00693                                     "signing with dnskey");
00694                 }
00695         }
00696 
00697         isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
00698         isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
00699 }
00700 
00701 struct hashlist {
00702         unsigned char *hashbuf;
00703         size_t entries;
00704         size_t size;
00705         size_t length;
00706 };
00707 
00708 static void
00709 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
00710 
00711         l->entries = 0;
00712         l->length = length + 1;
00713 
00714         if (nodes != 0) {
00715                 l->size = nodes;
00716                 l->hashbuf = malloc(l->size * l->length);
00717                 if (l->hashbuf == NULL)
00718                         l->size = 0;
00719         } else {
00720                 l->size = 0;
00721                 l->hashbuf = NULL;
00722         }
00723 }
00724 
00725 static void
00726 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
00727 {
00728 
00729         REQUIRE(len <= l->length);
00730 
00731         if (l->entries == l->size) {
00732                 l->size = l->size * 2 + 100;
00733                 l->hashbuf = realloc(l->hashbuf, l->size * l->length);
00734                 if (l->hashbuf == NULL)
00735                         fatal("unable to grow hashlist: out of memory");
00736         }
00737         memset(l->hashbuf + l->entries * l->length, 0, l->length);
00738         memmove(l->hashbuf + l->entries * l->length, hash, len);
00739         l->entries++;
00740 }
00741 
00742 static void
00743 hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
00744                       unsigned int hashalg, unsigned int iterations,
00745                       const unsigned char *salt, size_t salt_len,
00746                       isc_boolean_t speculative)
00747 {
00748         char nametext[DNS_NAME_FORMATSIZE];
00749         unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
00750         unsigned int len;
00751         size_t i;
00752 
00753         len = isc_iterated_hash(hash, hashalg, iterations,
00754                                 salt, (int)salt_len,
00755                                 name->ndata, name->length);
00756         if (verbose) {
00757                 dns_name_format(name, nametext, sizeof nametext);
00758                 for (i = 0 ; i < len; i++)
00759                         fprintf(stderr, "%02x", hash[i]);
00760                 fprintf(stderr, " %s\n", nametext);
00761         }
00762         hash[len++] = speculative ? 1 : 0;
00763         hashlist_add(l, hash, len);
00764 }
00765 
00766 static int
00767 hashlist_comp(const void *a, const void *b) {
00768         return (memcmp(a, b, hash_length + 1));
00769 }
00770 
00771 static void
00772 hashlist_sort(hashlist_t *l) {
00773         qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
00774 }
00775 
00776 static isc_boolean_t
00777 hashlist_hasdup(hashlist_t *l) {
00778         unsigned char *current;
00779         unsigned char *next = l->hashbuf;
00780         size_t entries = l->entries;
00781 
00782         /*
00783          * Skip initial speculative wild card hashs.
00784          */
00785         while (entries > 0U && next[l->length-1] != 0U) {
00786                 next += l->length;
00787                 entries--;
00788         }
00789 
00790         current = next;
00791         while (entries-- > 1U) {
00792                 next += l->length;
00793                 if (next[l->length-1] != 0)
00794                         continue;
00795                 if (memcmp(current, next, l->length - 1) == 0)
00796                         return (ISC_TRUE);
00797                 current = next;
00798         }
00799         return (ISC_FALSE);
00800 }
00801 
00802 static const unsigned char *
00803 hashlist_findnext(const hashlist_t *l,
00804                   const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
00805 {
00806         size_t entries = l->entries;
00807         const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
00808                                             l->length, hashlist_comp);
00809         INSIST(next != NULL);
00810 
00811         do {
00812                 if (next < l->hashbuf + (l->entries - 1) * l->length)
00813                         next += l->length;
00814                 else
00815                         next = l->hashbuf;
00816                 if (next[l->length - 1] == 0)
00817                         break;
00818         } while (entries-- > 1U);
00819         INSIST(entries != 0U);
00820         return (next);
00821 }
00822 
00823 static isc_boolean_t
00824 hashlist_exists(const hashlist_t *l,
00825                 const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
00826 {
00827         if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
00828                 return (ISC_TRUE);
00829         else
00830                 return (ISC_FALSE);
00831 }
00832 
00833 static void
00834 addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
00835                   unsigned int hashalg, unsigned int iterations,
00836                   const unsigned char *salt, size_t salt_len)
00837 {
00838         dns_fixedname_t fixed;
00839         dns_name_t *wild;
00840         dns_dbnode_t *node = NULL;
00841         isc_result_t result;
00842         char namestr[DNS_NAME_FORMATSIZE];
00843 
00844         dns_fixedname_init(&fixed);
00845         wild = dns_fixedname_name(&fixed);
00846 
00847         result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
00848         if (result == ISC_R_NOSPACE)
00849                 return;
00850         check_result(result,"addnowildcardhash: dns_name_concatenate()");
00851 
00852         result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
00853         if (result == ISC_R_SUCCESS) {
00854                 dns_db_detachnode(gdb, &node);
00855                 return;
00856         }
00857 
00858         if (verbose) {
00859                 dns_name_format(wild, namestr, sizeof(namestr));
00860                 fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
00861         }
00862 
00863         hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_len,
00864                               ISC_TRUE);
00865 }
00866 
00867 static void
00868 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
00869        dns_db_t **dbp)
00870 {
00871         char filename[PATH_MAX];
00872         isc_buffer_t b;
00873         isc_result_t result;
00874 
00875         isc_buffer_init(&b, filename, sizeof(filename));
00876         if (dsdir != NULL) {
00877                 /* allow room for a trailing slash */
00878                 if (strlen(dsdir) >= isc_buffer_availablelength(&b))
00879                         fatal("path '%s' is too long", dsdir);
00880                 isc_buffer_putstr(&b, dsdir);
00881                 if (dsdir[strlen(dsdir) - 1] != '/')
00882                         isc_buffer_putstr(&b, "/");
00883         }
00884         if (strlen(prefix) > isc_buffer_availablelength(&b))
00885                 fatal("path '%s' is too long", dsdir);
00886         isc_buffer_putstr(&b, prefix);
00887         result = dns_name_tofilenametext(name, ISC_FALSE, &b);
00888         check_result(result, "dns_name_tofilenametext()");
00889         if (isc_buffer_availablelength(&b) == 0) {
00890                 char namestr[DNS_NAME_FORMATSIZE];
00891                 dns_name_format(name, namestr, sizeof(namestr));
00892                 fatal("name '%s' is too long", namestr);
00893         }
00894         isc_buffer_putuint8(&b, 0);
00895 
00896         result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
00897                                rdclass, 0, NULL, dbp);
00898         check_result(result, "dns_db_create()");
00899 
00900         result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT);
00901         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
00902                 dns_db_detach(dbp);
00903 }
00904 
00905 /*%
00906  * Load the DS set for a child zone, if a dsset-* file can be found.
00907  * If not, try to find a keyset-* file from an earlier version of
00908  * dnssec-signzone, and build DS records from that.
00909  */
00910 static isc_result_t
00911 loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
00912         dns_db_t *db = NULL;
00913         dns_dbversion_t *ver = NULL;
00914         dns_dbnode_t *node = NULL;
00915         isc_result_t result;
00916         dns_rdataset_t keyset;
00917         dns_rdata_t key, ds;
00918         unsigned char dsbuf[DNS_DS_BUFFERSIZE];
00919         dns_diff_t diff;
00920         dns_difftuple_t *tuple = NULL;
00921 
00922         opendb("dsset-", name, gclass, &db);
00923         if (db != NULL) {
00924                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
00925                 if (result == ISC_R_SUCCESS) {
00926                         dns_rdataset_init(dsset);
00927                         result = dns_db_findrdataset(db, node, NULL,
00928                                                      dns_rdatatype_ds, 0, 0,
00929                                                      dsset, NULL);
00930                         dns_db_detachnode(db, &node);
00931                         if (result == ISC_R_SUCCESS) {
00932                                 vbprintf(2, "found DS records\n");
00933                                 dsset->ttl = ttl;
00934                                 dns_db_detach(&db);
00935                                 return (result);
00936                         }
00937                 }
00938                 dns_db_detach(&db);
00939         }
00940 
00941         /* No DS records found; try again, looking for DNSKEY records */
00942         opendb("keyset-", name, gclass, &db);
00943         if (db == NULL) {
00944                 return (ISC_R_NOTFOUND);
00945         }
00946 
00947         result = dns_db_findnode(db, name, ISC_FALSE, &node);
00948         if (result != ISC_R_SUCCESS) {
00949                 dns_db_detach(&db);
00950                 return (result);
00951         }
00952 
00953         dns_rdataset_init(&keyset);
00954         result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
00955                                      &keyset, NULL);
00956         if (result != ISC_R_SUCCESS) {
00957                 dns_db_detachnode(db, &node);
00958                 dns_db_detach(&db);
00959                 return (result);
00960         }
00961         vbprintf(2, "found DNSKEY records\n");
00962 
00963         result = dns_db_newversion(db, &ver);
00964         check_result(result, "dns_db_newversion");
00965         dns_diff_init(mctx, &diff);
00966 
00967         for (result = dns_rdataset_first(&keyset);
00968              result == ISC_R_SUCCESS;
00969              result = dns_rdataset_next(&keyset))
00970         {
00971                 dns_rdata_init(&key);
00972                 dns_rdata_init(&ds);
00973                 dns_rdataset_current(&keyset, &key);
00974                 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
00975                                            dsbuf, &ds);
00976                 check_result(result, "dns_ds_buildrdata");
00977 
00978                 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
00979                                               ttl, &ds, &tuple);
00980                 check_result(result, "dns_difftuple_create");
00981                 dns_diff_append(&diff, &tuple);
00982 
00983                 dns_rdata_reset(&ds);
00984                 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
00985                                            dsbuf, &ds);
00986                 check_result(result, "dns_ds_buildrdata");
00987 
00988                 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
00989                                               ttl, &ds, &tuple);
00990                 check_result(result, "dns_difftuple_create");
00991                 dns_diff_append(&diff, &tuple);
00992         }
00993 
00994         result = dns_diff_apply(&diff, db, ver);
00995         check_result(result, "dns_diff_apply");
00996         dns_diff_clear(&diff);
00997 
00998         dns_db_closeversion(db, &ver, ISC_TRUE);
00999 
01000         result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
01001                                      dsset, NULL);
01002         check_result(result, "dns_db_findrdataset");
01003 
01004         dns_rdataset_disassociate(&keyset);
01005         dns_db_detachnode(db, &node);
01006         dns_db_detach(&db);
01007         return (result);
01008 }
01009 
01010 static isc_boolean_t
01011 secure(dns_name_t *name, dns_dbnode_t *node) {
01012         dns_rdataset_t dsset;
01013         isc_result_t result;
01014 
01015         if (dns_name_equal(name, gorigin))
01016                 return (ISC_FALSE);
01017 
01018         dns_rdataset_init(&dsset);
01019         result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
01020                                      0, 0, &dsset, NULL);
01021         if (dns_rdataset_isassociated(&dsset))
01022                 dns_rdataset_disassociate(&dsset);
01023 
01024         return (ISC_TF(result == ISC_R_SUCCESS));
01025 }
01026 
01027 /*%
01028  * Signs all records at a name.
01029  */
01030 static void
01031 signname(dns_dbnode_t *node, dns_name_t *name) {
01032         isc_result_t result;
01033         dns_rdataset_t rdataset;
01034         dns_rdatasetiter_t *rdsiter;
01035         isc_boolean_t isdelegation = ISC_FALSE;
01036         dns_diff_t del, add;
01037         char namestr[DNS_NAME_FORMATSIZE];
01038 
01039         dns_rdataset_init(&rdataset);
01040         dns_name_format(name, namestr, sizeof(namestr));
01041 
01042         /*
01043          * Determine if this is a delegation point.
01044          */
01045         if (is_delegation(gdb, gversion, gorigin, name, node, NULL))
01046                 isdelegation = ISC_TRUE;
01047 
01048         /*
01049          * Now iterate through the rdatasets.
01050          */
01051         dns_diff_init(mctx, &del);
01052         dns_diff_init(mctx, &add);
01053         rdsiter = NULL;
01054         result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
01055         check_result(result, "dns_db_allrdatasets()");
01056         result = dns_rdatasetiter_first(rdsiter);
01057         while (result == ISC_R_SUCCESS) {
01058                 dns_rdatasetiter_current(rdsiter, &rdataset);
01059 
01060                 /* If this is a RRSIG set, skip it. */
01061                 if (rdataset.type == dns_rdatatype_rrsig)
01062                         goto skip;
01063 
01064                 /*
01065                  * If this name is a delegation point, skip all records
01066                  * except NSEC and DS sets.  Otherwise check that there
01067                  * isn't a DS record.
01068                  */
01069                 if (isdelegation) {
01070                         if (rdataset.type != nsec_datatype &&
01071                             rdataset.type != dns_rdatatype_ds)
01072                                 goto skip;
01073                 } else if (rdataset.type == dns_rdatatype_ds) {
01074                         char namebuf[DNS_NAME_FORMATSIZE];
01075                         dns_name_format(name, namebuf, sizeof(namebuf));
01076                         fatal("'%s': found DS RRset without NS RRset\n",
01077                               namebuf);
01078                 }
01079 
01080                 signset(&del, &add, node, name, &rdataset);
01081 
01082  skip:
01083                 dns_rdataset_disassociate(&rdataset);
01084                 result = dns_rdatasetiter_next(rdsiter);
01085         }
01086         if (result != ISC_R_NOMORE)
01087                 fatal("rdataset iteration for name '%s' failed: %s",
01088                       namestr, isc_result_totext(result));
01089 
01090         dns_rdatasetiter_destroy(&rdsiter);
01091 
01092         result = dns_diff_applysilently(&del, gdb, gversion);
01093         if (result != ISC_R_SUCCESS)
01094                 fatal("failed to delete SIGs at node '%s': %s",
01095                       namestr, isc_result_totext(result));
01096 
01097         result = dns_diff_applysilently(&add, gdb, gversion);
01098         if (result != ISC_R_SUCCESS)
01099                 fatal("failed to add SIGs at node '%s': %s",
01100                       namestr, isc_result_totext(result));
01101 
01102         dns_diff_clear(&del);
01103         dns_diff_clear(&add);
01104 }
01105 
01106 static inline isc_boolean_t
01107 active_node(dns_dbnode_t *node) {
01108         dns_rdatasetiter_t *rdsiter = NULL;
01109         dns_rdatasetiter_t *rdsiter2 = NULL;
01110         isc_boolean_t active = ISC_FALSE;
01111         isc_result_t result;
01112         dns_rdataset_t rdataset;
01113         dns_rdatatype_t type;
01114         dns_rdatatype_t covers;
01115         isc_boolean_t found;
01116 
01117         dns_rdataset_init(&rdataset);
01118         result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
01119         check_result(result, "dns_db_allrdatasets()");
01120         result = dns_rdatasetiter_first(rdsiter);
01121         while (result == ISC_R_SUCCESS) {
01122                 dns_rdatasetiter_current(rdsiter, &rdataset);
01123                 if (rdataset.type != dns_rdatatype_nsec &&
01124                     rdataset.type != dns_rdatatype_nsec3 &&
01125                     rdataset.type != dns_rdatatype_rrsig)
01126                         active = ISC_TRUE;
01127                 dns_rdataset_disassociate(&rdataset);
01128                 if (!active)
01129                         result = dns_rdatasetiter_next(rdsiter);
01130                 else
01131                         result = ISC_R_NOMORE;
01132         }
01133         if (result != ISC_R_NOMORE)
01134                 fatal("rdataset iteration failed: %s",
01135                       isc_result_totext(result));
01136 
01137         if (!active && nsec_datatype == dns_rdatatype_nsec) {
01138                 /*%
01139                  * The node is empty of everything but NSEC / RRSIG records.
01140                  */
01141                 for (result = dns_rdatasetiter_first(rdsiter);
01142                      result == ISC_R_SUCCESS;
01143                      result = dns_rdatasetiter_next(rdsiter)) {
01144                         dns_rdatasetiter_current(rdsiter, &rdataset);
01145                         result = dns_db_deleterdataset(gdb, node, gversion,
01146                                                        rdataset.type,
01147                                                        rdataset.covers);
01148                         check_result(result, "dns_db_deleterdataset()");
01149                         dns_rdataset_disassociate(&rdataset);
01150                 }
01151                 if (result != ISC_R_NOMORE)
01152                         fatal("rdataset iteration failed: %s",
01153                               isc_result_totext(result));
01154         } else {
01155                 /*
01156                  * Delete RRSIGs for types that no longer exist.
01157                  */
01158                 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
01159                 check_result(result, "dns_db_allrdatasets()");
01160                 for (result = dns_rdatasetiter_first(rdsiter);
01161                      result == ISC_R_SUCCESS;
01162                      result = dns_rdatasetiter_next(rdsiter)) {
01163                         dns_rdatasetiter_current(rdsiter, &rdataset);
01164                         type = rdataset.type;
01165                         covers = rdataset.covers;
01166                         dns_rdataset_disassociate(&rdataset);
01167                         /*
01168                          * Delete the NSEC chain if we are signing with
01169                          * NSEC3.
01170                          */
01171                         if (nsec_datatype == dns_rdatatype_nsec3 &&
01172                             (type == dns_rdatatype_nsec ||
01173                              covers == dns_rdatatype_nsec)) {
01174                                 result = dns_db_deleterdataset(gdb, node,
01175                                                                gversion, type,
01176                                                                covers);
01177                                 check_result(result,
01178                                            "dns_db_deleterdataset(nsec/rrsig)");
01179                                 continue;
01180                         }
01181                         if (type != dns_rdatatype_rrsig)
01182                                 continue;
01183                         found = ISC_FALSE;
01184                         for (result = dns_rdatasetiter_first(rdsiter2);
01185                              !found && result == ISC_R_SUCCESS;
01186                              result = dns_rdatasetiter_next(rdsiter2)) {
01187                                 dns_rdatasetiter_current(rdsiter2, &rdataset);
01188                                 if (rdataset.type == covers)
01189                                         found = ISC_TRUE;
01190                                 dns_rdataset_disassociate(&rdataset);
01191                         }
01192                         if (!found) {
01193                                 if (result != ISC_R_NOMORE)
01194                                         fatal("rdataset iteration failed: %s",
01195                                               isc_result_totext(result));
01196                                 result = dns_db_deleterdataset(gdb, node,
01197                                                                gversion, type,
01198                                                                covers);
01199                                 check_result(result,
01200                                              "dns_db_deleterdataset(rrsig)");
01201                         } else if (result != ISC_R_NOMORE &&
01202                                    result != ISC_R_SUCCESS)
01203                                 fatal("rdataset iteration failed: %s",
01204                                       isc_result_totext(result));
01205                 }
01206                 if (result != ISC_R_NOMORE)
01207                         fatal("rdataset iteration failed: %s",
01208                               isc_result_totext(result));
01209                 dns_rdatasetiter_destroy(&rdsiter2);
01210         }
01211         dns_rdatasetiter_destroy(&rdsiter);
01212 
01213         return (active);
01214 }
01215 
01216 /*%
01217  * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
01218  */
01219 static void
01220 get_soa_ttls(void) {
01221         dns_rdataset_t soaset;
01222         dns_fixedname_t fname;
01223         dns_name_t *name;
01224         isc_result_t result;
01225         dns_rdata_t rdata = DNS_RDATA_INIT;
01226 
01227         dns_fixedname_init(&fname);
01228         name = dns_fixedname_name(&fname);
01229         dns_rdataset_init(&soaset);
01230         result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
01231                              0, 0, NULL, name, &soaset, NULL);
01232         if (result != ISC_R_SUCCESS)
01233                 fatal("failed to find an SOA at the zone apex: %s",
01234                       isc_result_totext(result));
01235 
01236         result = dns_rdataset_first(&soaset);
01237         check_result(result, "dns_rdataset_first");
01238         dns_rdataset_current(&soaset, &rdata);
01239         zone_soa_min_ttl = dns_soa_getminimum(&rdata);
01240         soa_ttl = soaset.ttl;
01241         if (set_maxttl) {
01242                 zone_soa_min_ttl = ISC_MIN(zone_soa_min_ttl, maxttl);
01243                 soa_ttl = ISC_MIN(soa_ttl, maxttl);
01244         }
01245         dns_rdataset_disassociate(&soaset);
01246 }
01247 
01248 /*%
01249  * Increment (or set if nonzero) the SOA serial
01250  */
01251 static isc_result_t
01252 setsoaserial(isc_uint32_t serial, dns_updatemethod_t method) {
01253         isc_result_t result;
01254         dns_dbnode_t *node = NULL;
01255         dns_rdataset_t rdataset;
01256         dns_rdata_t rdata = DNS_RDATA_INIT;
01257         isc_uint32_t old_serial, new_serial;
01258 
01259         result = dns_db_getoriginnode(gdb, &node);
01260         if (result != ISC_R_SUCCESS)
01261                 return result;
01262 
01263         dns_rdataset_init(&rdataset);
01264 
01265         result = dns_db_findrdataset(gdb, node, gversion,
01266                                      dns_rdatatype_soa, 0,
01267                                      0, &rdataset, NULL);
01268         if (result != ISC_R_SUCCESS)
01269                 goto cleanup;
01270 
01271         result = dns_rdataset_first(&rdataset);
01272         RUNTIME_CHECK(result == ISC_R_SUCCESS);
01273 
01274         dns_rdataset_current(&rdataset, &rdata);
01275 
01276         old_serial = dns_soa_getserial(&rdata);
01277 
01278         if (method == dns_updatemethod_date ||
01279             method == dns_updatemethod_unixtime) {
01280                 new_serial = dns_update_soaserial(old_serial, method);
01281         } else if (serial != 0 || method == dns_updatemethod_none) {
01282                 /* Set SOA serial to the value provided. */
01283                 new_serial = serial;
01284         } else {
01285                 /* Increment SOA serial using RFC 1982 arithmetics */
01286                 new_serial = (old_serial + 1) & 0xFFFFFFFF;
01287                 if (new_serial == 0)
01288                         new_serial = 1;
01289         }
01290 
01291         /* If the new serial is not likely to cause a zone transfer
01292          * (a/ixfr) from servers having the old serial, warn the user.
01293          *
01294          * RFC1982 section 7 defines the maximum increment to be
01295          * (2^(32-1))-1.  Using u_int32_t arithmetic, we can do a single
01296          * comparison.  (5 - 6 == (2^32)-1, not negative-one)
01297          */
01298         if (new_serial == old_serial ||
01299             (new_serial - old_serial) > 0x7fffffffU)
01300                 fprintf(stderr, "%s: warning: Serial number not advanced, "
01301                         "zone may not transfer\n", program);
01302 
01303         dns_soa_setserial(new_serial, &rdata);
01304 
01305         result = dns_db_deleterdataset(gdb, node, gversion,
01306                                        dns_rdatatype_soa, 0);
01307         check_result(result, "dns_db_deleterdataset");
01308         if (result != ISC_R_SUCCESS)
01309                 goto cleanup;
01310 
01311         result = dns_db_addrdataset(gdb, node, gversion,
01312                                     0, &rdataset, 0, NULL);
01313         check_result(result, "dns_db_addrdataset");
01314         if (result != ISC_R_SUCCESS)
01315                 goto cleanup;
01316 
01317 cleanup:
01318         dns_rdataset_disassociate(&rdataset);
01319         if (node != NULL)
01320                 dns_db_detachnode(gdb, &node);
01321         dns_rdata_reset(&rdata);
01322 
01323         return (result);
01324 }
01325 
01326 /*%
01327  * Delete any RRSIG records at a node.
01328  */
01329 static void
01330 cleannode(dns_db_t *db, dns_dbversion_t *dbversion, dns_dbnode_t *node) {
01331         dns_rdatasetiter_t *rdsiter = NULL;
01332         dns_rdataset_t set;
01333         isc_result_t result, dresult;
01334 
01335         if (outputformat != dns_masterformat_text || !disable_zone_check)
01336                 return;
01337 
01338         dns_rdataset_init(&set);
01339         result = dns_db_allrdatasets(db, node, dbversion, 0, &rdsiter);
01340         check_result(result, "dns_db_allrdatasets");
01341         result = dns_rdatasetiter_first(rdsiter);
01342         while (result == ISC_R_SUCCESS) {
01343                 isc_boolean_t destroy = ISC_FALSE;
01344                 dns_rdatatype_t covers = 0;
01345                 dns_rdatasetiter_current(rdsiter, &set);
01346                 if (set.type == dns_rdatatype_rrsig) {
01347                         covers = set.covers;
01348                         destroy = ISC_TRUE;
01349                 }
01350                 dns_rdataset_disassociate(&set);
01351                 result = dns_rdatasetiter_next(rdsiter);
01352                 if (destroy) {
01353                         dresult = dns_db_deleterdataset(db, node, dbversion,
01354                                                         dns_rdatatype_rrsig,
01355                                                         covers);
01356                         check_result(dresult, "dns_db_deleterdataset");
01357                 }
01358         }
01359         if (result != ISC_R_NOMORE)
01360                 fatal("rdataset iteration failed: %s",
01361                       isc_result_totext(result));
01362         dns_rdatasetiter_destroy(&rdsiter);
01363 }
01364 
01365 /*%
01366  * Set up the iterator and global state before starting the tasks.
01367  */
01368 static void
01369 presign(void) {
01370         isc_result_t result;
01371 
01372         gdbiter = NULL;
01373         result = dns_db_createiterator(gdb, 0, &gdbiter);
01374         check_result(result, "dns_db_createiterator()");
01375 }
01376 
01377 /*%
01378  * Clean up the iterator and global state after the tasks complete.
01379  */
01380 static void
01381 postsign(void) {
01382         dns_dbiterator_destroy(&gdbiter);
01383 }
01384 
01385 /*%
01386  * Sign the apex of the zone.
01387  * Note the origin may not be the first node if there are out of zone
01388  * records.
01389  */
01390 static void
01391 signapex(void) {
01392         dns_dbnode_t *node = NULL;
01393         dns_fixedname_t fixed;
01394         dns_name_t *name;
01395         isc_result_t result;
01396 
01397         dns_fixedname_init(&fixed);
01398         name = dns_fixedname_name(&fixed);
01399         result = dns_dbiterator_seek(gdbiter, gorigin);
01400         check_result(result, "dns_dbiterator_seek()");
01401         result = dns_dbiterator_current(gdbiter, &node, name);
01402         check_dns_dbiterator_current(result);
01403         signname(node, name);
01404         dumpnode(name, node);
01405         cleannode(gdb, gversion, node);
01406         dns_db_detachnode(gdb, &node);
01407         result = dns_dbiterator_first(gdbiter);
01408         if (result == ISC_R_NOMORE)
01409                 finished = ISC_TRUE;
01410         else if (result != ISC_R_SUCCESS)
01411                 fatal("failure iterating database: %s",
01412                       isc_result_totext(result));
01413 }
01414 
01415 /*%
01416  * Assigns a node to a worker thread.  This is protected by the master task's
01417  * lock.
01418  */
01419 static void
01420 assignwork(isc_task_t *task, isc_task_t *worker) {
01421         dns_fixedname_t *fname;
01422         dns_name_t *name;
01423         dns_dbnode_t *node;
01424         sevent_t *sevent;
01425         dns_rdataset_t nsec;
01426         isc_boolean_t found;
01427         isc_result_t result;
01428         static dns_name_t *zonecut = NULL;      /* Protected by namelock. */
01429         static dns_fixedname_t fzonecut;        /* Protected by namelock. */
01430         static unsigned int ended = 0;          /* Protected by namelock. */
01431 
01432         if (shuttingdown)
01433                 return;
01434 
01435         LOCK(&namelock);
01436         if (finished) {
01437                 ended++;
01438                 if (ended == ntasks) {
01439                         isc_task_detach(&task);
01440                         isc_app_shutdown();
01441                 }
01442                 goto unlock;
01443         }
01444 
01445         fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
01446         if (fname == NULL)
01447                 fatal("out of memory");
01448         dns_fixedname_init(fname);
01449         name = dns_fixedname_name(fname);
01450         node = NULL;
01451         found = ISC_FALSE;
01452         while (!found) {
01453                 result = dns_dbiterator_current(gdbiter, &node, name);
01454                 check_dns_dbiterator_current(result);
01455                 /*
01456                  * The origin was handled by signapex().
01457                  */
01458                 if (dns_name_equal(name, gorigin)) {
01459                         dns_db_detachnode(gdb, &node);
01460                         goto next;
01461                 }
01462                 /*
01463                  * Sort the zone data from the glue and out-of-zone data.
01464                  * For NSEC zones nodes with zone data have NSEC records.
01465                  * For NSEC3 zones the NSEC3 nodes are zone data but
01466                  * outside of the zone name space.  For the rest we need
01467                  * to track the bottom of zone cuts.
01468                  * Nodes which don't need to be signed are dumped here.
01469                  */
01470                 dns_rdataset_init(&nsec);
01471                 result = dns_db_findrdataset(gdb, node, gversion,
01472                                              nsec_datatype, 0, 0,
01473                                              &nsec, NULL);
01474                 if (dns_rdataset_isassociated(&nsec))
01475                         dns_rdataset_disassociate(&nsec);
01476                 if (result == ISC_R_SUCCESS) {
01477                         found = ISC_TRUE;
01478                 } else if (nsec_datatype == dns_rdatatype_nsec3) {
01479                         if (dns_name_issubdomain(name, gorigin) &&
01480                             (zonecut == NULL ||
01481                              !dns_name_issubdomain(name, zonecut))) {
01482                                 if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) {
01483                                         dns_fixedname_init(&fzonecut);
01484                                         zonecut = dns_fixedname_name(&fzonecut);
01485                                         dns_name_copy(name, zonecut, NULL);
01486                                         if (!OPTOUT(nsec3flags) ||
01487                                             secure(name, node))
01488                                                 found = ISC_TRUE;
01489                                 } else
01490                                         found = ISC_TRUE;
01491                         }
01492                 }
01493 
01494                 if (!found) {
01495                         dumpnode(name, node);
01496                         dns_db_detachnode(gdb, &node);
01497                 }
01498 
01499  next:
01500                 result = dns_dbiterator_next(gdbiter);
01501                 if (result == ISC_R_NOMORE) {
01502                         finished = ISC_TRUE;
01503                         break;
01504                 } else if (result != ISC_R_SUCCESS)
01505                         fatal("failure iterating database: %s",
01506                               isc_result_totext(result));
01507         }
01508         if (!found) {
01509                 ended++;
01510                 if (ended == ntasks) {
01511                         isc_task_detach(&task);
01512                         isc_app_shutdown();
01513                 }
01514                 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
01515                 goto unlock;
01516         }
01517         sevent = (sevent_t *)
01518                  isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
01519                                     sign, NULL, sizeof(sevent_t));
01520         if (sevent == NULL)
01521                 fatal("failed to allocate event\n");
01522 
01523         sevent->node = node;
01524         sevent->fname = fname;
01525         isc_task_send(worker, ISC_EVENT_PTR(&sevent));
01526  unlock:
01527         UNLOCK(&namelock);
01528 }
01529 
01530 /*%
01531  * Start a worker task
01532  */
01533 static void
01534 startworker(isc_task_t *task, isc_event_t *event) {
01535         isc_task_t *worker;
01536 
01537         worker = (isc_task_t *)event->ev_arg;
01538         assignwork(task, worker);
01539         isc_event_free(&event);
01540 }
01541 
01542 /*%
01543  * Write a node to the output file, and restart the worker task.
01544  */
01545 static void
01546 writenode(isc_task_t *task, isc_event_t *event) {
01547         isc_task_t *worker;
01548         sevent_t *sevent = (sevent_t *)event;
01549 
01550         worker = (isc_task_t *)event->ev_sender;
01551         dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
01552         cleannode(gdb, gversion, sevent->node);
01553         dns_db_detachnode(gdb, &sevent->node);
01554         isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
01555         assignwork(task, worker);
01556         isc_event_free(&event);
01557 }
01558 
01559 /*%
01560  *  Sign a database node.
01561  */
01562 static void
01563 sign(isc_task_t *task, isc_event_t *event) {
01564         dns_fixedname_t *fname;
01565         dns_dbnode_t *node;
01566         sevent_t *sevent, *wevent;
01567 
01568         sevent = (sevent_t *)event;
01569         node = sevent->node;
01570         fname = sevent->fname;
01571         isc_event_free(&event);
01572 
01573         signname(node, dns_fixedname_name(fname));
01574         wevent = (sevent_t *)
01575                  isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
01576                                     writenode, NULL, sizeof(sevent_t));
01577         if (wevent == NULL)
01578                 fatal("failed to allocate event\n");
01579         wevent->node = node;
01580         wevent->fname = fname;
01581         isc_task_send(master, ISC_EVENT_PTR(&wevent));
01582 }
01583 
01584 /*%
01585  * Update / remove the DS RRset.  Preserve RRSIG(DS) if possible.
01586  */
01587 static void
01588 add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
01589         dns_rdataset_t dsset;
01590         dns_rdataset_t sigdsset;
01591         isc_result_t result;
01592 
01593         dns_rdataset_init(&dsset);
01594         dns_rdataset_init(&sigdsset);
01595         result = dns_db_findrdataset(gdb, node, gversion,
01596                                      dns_rdatatype_ds,
01597                                      0, 0, &dsset, &sigdsset);
01598         if (result == ISC_R_SUCCESS) {
01599                 dns_rdataset_disassociate(&dsset);
01600                 result = dns_db_deleterdataset(gdb, node, gversion,
01601                                                dns_rdatatype_ds, 0);
01602                 check_result(result, "dns_db_deleterdataset");
01603         }
01604 
01605         result = loadds(name, nsttl, &dsset);
01606         if (result == ISC_R_SUCCESS) {
01607                 result = dns_db_addrdataset(gdb, node, gversion, 0,
01608                                             &dsset, 0, NULL);
01609                 check_result(result, "dns_db_addrdataset");
01610                 dns_rdataset_disassociate(&dsset);
01611                 if (dns_rdataset_isassociated(&sigdsset))
01612                         dns_rdataset_disassociate(&sigdsset);
01613         } else if (dns_rdataset_isassociated(&sigdsset)) {
01614                 result = dns_db_deleterdataset(gdb, node, gversion,
01615                                                dns_rdatatype_rrsig,
01616                                                dns_rdatatype_ds);
01617                 check_result(result, "dns_db_deleterdataset");
01618                 dns_rdataset_disassociate(&sigdsset);
01619         }
01620 }
01621 
01622 /*
01623  * Remove records of the given type and their signatures.
01624  */
01625 static void
01626 remove_records(dns_dbnode_t *node, dns_rdatatype_t which,
01627                isc_boolean_t checknsec)
01628 {
01629         isc_result_t result;
01630         dns_rdatatype_t type, covers;
01631         dns_rdatasetiter_t *rdsiter = NULL;
01632         dns_rdataset_t rdataset;
01633 
01634         dns_rdataset_init(&rdataset);
01635 
01636         /*
01637          * Delete any records of the given type at the apex.
01638          */
01639         result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
01640         check_result(result, "dns_db_allrdatasets()");
01641         for (result = dns_rdatasetiter_first(rdsiter);
01642              result == ISC_R_SUCCESS;
01643              result = dns_rdatasetiter_next(rdsiter)) {
01644                 dns_rdatasetiter_current(rdsiter, &rdataset);
01645                 type = rdataset.type;
01646                 covers = rdataset.covers;
01647                 dns_rdataset_disassociate(&rdataset);
01648                 if (type == which || covers == which) {
01649                         if (which == dns_rdatatype_nsec &&
01650                             checknsec && !update_chain)
01651                                 fatal("Zone contains NSEC records.  Use -u "
01652                                       "to update to NSEC3.");
01653                         if (which == dns_rdatatype_nsec3param &&
01654                             checknsec && !update_chain)
01655                                 fatal("Zone contains NSEC3 chains.  Use -u "
01656                                       "to update to NSEC.");
01657                         result = dns_db_deleterdataset(gdb, node, gversion,
01658                                                        type, covers);
01659                         check_result(result, "dns_db_deleterdataset()");
01660                         continue;
01661                 }
01662         }
01663         dns_rdatasetiter_destroy(&rdsiter);
01664 }
01665 
01666 /*
01667  * Remove signatures covering the given type.  If type == 0,
01668  * then remove all signatures, unless this is a delegation, in
01669  * which case remove all signatures except for DS or nsec_datatype
01670  */
01671 static void
01672 remove_sigs(dns_dbnode_t *node, isc_boolean_t delegation,
01673             dns_rdatatype_t which)
01674 {
01675         isc_result_t result;
01676         dns_rdatatype_t type, covers;
01677         dns_rdatasetiter_t *rdsiter = NULL;
01678         dns_rdataset_t rdataset;
01679 
01680         dns_rdataset_init(&rdataset);
01681         result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
01682         check_result(result, "dns_db_allrdatasets()");
01683         for (result = dns_rdatasetiter_first(rdsiter);
01684              result == ISC_R_SUCCESS;
01685              result = dns_rdatasetiter_next(rdsiter)) {
01686                 dns_rdatasetiter_current(rdsiter, &rdataset);
01687                 type = rdataset.type;
01688                 covers = rdataset.covers;
01689                 dns_rdataset_disassociate(&rdataset);
01690 
01691                 if (type != dns_rdatatype_rrsig)
01692                         continue;
01693 
01694                 if (which == 0 && delegation &&
01695                     (dns_rdatatype_atparent(covers) ||
01696                      (nsec_datatype == dns_rdatatype_nsec &&
01697                       covers == nsec_datatype)))
01698                         continue;
01699 
01700                 if (which != 0 && covers != which)
01701                         continue;
01702 
01703                 result = dns_db_deleterdataset(gdb, node, gversion,
01704                                                type, covers);
01705                 check_result(result, "dns_db_deleterdataset()");
01706         }
01707         dns_rdatasetiter_destroy(&rdsiter);
01708 }
01709 
01710 /*%
01711  * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
01712  */
01713 static void
01714 nsecify(void) {
01715         dns_dbiterator_t *dbiter = NULL;
01716         dns_dbnode_t *node = NULL, *nextnode = NULL;
01717         dns_fixedname_t fname, fnextname, fzonecut;
01718         dns_name_t *name, *nextname, *zonecut;
01719         dns_rdataset_t rdataset;
01720         dns_rdatasetiter_t *rdsiter = NULL;
01721         dns_rdatatype_t type, covers;
01722         isc_boolean_t done = ISC_FALSE;
01723         isc_result_t result;
01724         isc_uint32_t nsttl = 0;
01725 
01726         dns_rdataset_init(&rdataset);
01727         dns_fixedname_init(&fname);
01728         name = dns_fixedname_name(&fname);
01729         dns_fixedname_init(&fnextname);
01730         nextname = dns_fixedname_name(&fnextname);
01731         dns_fixedname_init(&fzonecut);
01732         zonecut = NULL;
01733 
01734         /*
01735          * Remove any NSEC3 chains.
01736          */
01737         result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
01738         check_result(result, "dns_db_createiterator()");
01739         for (result = dns_dbiterator_first(dbiter);
01740              result == ISC_R_SUCCESS;
01741              result = dns_dbiterator_next(dbiter)) {
01742                 result = dns_dbiterator_current(dbiter, &node, name);
01743                 check_dns_dbiterator_current(result);
01744                 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
01745                 check_result(result, "dns_db_allrdatasets()");
01746                 for (result = dns_rdatasetiter_first(rdsiter);
01747                      result == ISC_R_SUCCESS;
01748                      result = dns_rdatasetiter_next(rdsiter)) {
01749                         dns_rdatasetiter_current(rdsiter, &rdataset);
01750                         type = rdataset.type;
01751                         covers = rdataset.covers;
01752                         dns_rdataset_disassociate(&rdataset);
01753                         result = dns_db_deleterdataset(gdb, node, gversion,
01754                                                        type, covers);
01755                         check_result(result,
01756                                      "dns_db_deleterdataset(nsec3param/rrsig)");
01757                 }
01758                 dns_rdatasetiter_destroy(&rdsiter);
01759                 dns_db_detachnode(gdb, &node);
01760         }
01761         dns_dbiterator_destroy(&dbiter);
01762 
01763         result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
01764         check_result(result, "dns_db_createiterator()");
01765 
01766         result = dns_dbiterator_first(dbiter);
01767         check_result(result, "dns_dbiterator_first()");
01768 
01769         while (!done) {
01770                 result = dns_dbiterator_current(dbiter, &node, name);
01771                 check_dns_dbiterator_current(result);
01772                 /*
01773                  * Skip out-of-zone records.
01774                  */
01775                 if (!dns_name_issubdomain(name, gorigin)) {
01776                         result = dns_dbiterator_next(dbiter);
01777                         if (result == ISC_R_NOMORE)
01778                                 done = ISC_TRUE;
01779                         else
01780                                 check_result(result, "dns_dbiterator_next()");
01781                         dns_db_detachnode(gdb, &node);
01782                         continue;
01783                 }
01784 
01785                 if (dns_name_equal(name, gorigin))
01786                         remove_records(node, dns_rdatatype_nsec3param,
01787                                        ISC_TRUE);
01788 
01789                 if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) {
01790                         zonecut = dns_fixedname_name(&fzonecut);
01791                         dns_name_copy(name, zonecut, NULL);
01792                         remove_sigs(node, ISC_TRUE, 0);
01793                         if (generateds)
01794                                 add_ds(name, node, nsttl);
01795                 }
01796 
01797                 result = dns_dbiterator_next(dbiter);
01798                 nextnode = NULL;
01799                 while (result == ISC_R_SUCCESS) {
01800                         isc_boolean_t active = ISC_FALSE;
01801                         result = dns_dbiterator_current(dbiter, &nextnode,
01802                                                         nextname);
01803                         check_dns_dbiterator_current(result);
01804                         active = active_node(nextnode);
01805                         if (!active) {
01806                                 dns_db_detachnode(gdb, &nextnode);
01807                                 result = dns_dbiterator_next(dbiter);
01808                                 continue;
01809                         }
01810                         if (!dns_name_issubdomain(nextname, gorigin) ||
01811                             (zonecut != NULL &&
01812                              dns_name_issubdomain(nextname, zonecut)))
01813                         {
01814                                 remove_sigs(nextnode, ISC_FALSE, 0);
01815                                 remove_records(nextnode, dns_rdatatype_nsec,
01816                                                ISC_FALSE);
01817                                 dns_db_detachnode(gdb, &nextnode);
01818                                 result = dns_dbiterator_next(dbiter);
01819                                 continue;
01820                         }
01821                         dns_db_detachnode(gdb, &nextnode);
01822                         break;
01823                 }
01824                 if (result == ISC_R_NOMORE) {
01825                         dns_name_clone(gorigin, nextname);
01826                         done = ISC_TRUE;
01827                 } else if (result != ISC_R_SUCCESS)
01828                         fatal("iterating through the database failed: %s",
01829                               isc_result_totext(result));
01830                 dns_dbiterator_pause(dbiter);
01831                 result = dns_nsec_build(gdb, gversion, node, nextname,
01832                                         zone_soa_min_ttl);
01833                 check_result(result, "dns_nsec_build()");
01834                 dns_db_detachnode(gdb, &node);
01835         }
01836 
01837         dns_dbiterator_destroy(&dbiter);
01838 }
01839 
01840 static void
01841 addnsec3param(const unsigned char *salt, size_t salt_len,
01842               dns_iterations_t iterations)
01843 {
01844         dns_dbnode_t *node = NULL;
01845         dns_rdata_nsec3param_t nsec3param;
01846         unsigned char nsec3parambuf[5 + 255];
01847         dns_rdatalist_t rdatalist;
01848         dns_rdataset_t rdataset;
01849         dns_rdata_t rdata = DNS_RDATA_INIT;
01850         isc_buffer_t b;
01851         isc_result_t result;
01852 
01853         dns_rdataset_init(&rdataset);
01854 
01855         nsec3param.common.rdclass = gclass;
01856         nsec3param.common.rdtype = dns_rdatatype_nsec3param;
01857         ISC_LINK_INIT(&nsec3param.common, link);
01858         nsec3param.mctx = NULL;
01859         nsec3param.flags = 0;
01860         nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
01861         nsec3param.iterations = iterations;
01862         nsec3param.salt_length = (unsigned char)salt_len;
01863         DE_CONST(salt, nsec3param.salt);
01864 
01865         isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
01866         result = dns_rdata_fromstruct(&rdata, gclass,
01867                                       dns_rdatatype_nsec3param,
01868                                       &nsec3param, &b);
01869         check_result(result, "dns_rdata_fromstruct()");
01870         dns_rdatalist_init(&rdatalist);
01871         rdatalist.rdclass = rdata.rdclass;
01872         rdatalist.type = rdata.type;
01873         ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
01874         result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
01875         check_result(result, "dns_rdatalist_tordataset()");
01876 
01877         result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node);
01878         check_result(result, "dns_db_find(gorigin)");
01879 
01880         /*
01881          * Delete any current NSEC3PARAM records.
01882          */
01883         result = dns_db_deleterdataset(gdb, node, gversion,
01884                                        dns_rdatatype_nsec3param, 0);
01885         if (result == DNS_R_UNCHANGED)
01886                 result = ISC_R_SUCCESS;
01887         check_result(result, "dddnsec3param: dns_db_deleterdataset()");
01888 
01889         result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
01890                                     DNS_DBADD_MERGE, NULL);
01891         if (result == DNS_R_UNCHANGED)
01892                 result = ISC_R_SUCCESS;
01893         check_result(result, "addnsec3param: dns_db_addrdataset()");
01894         dns_db_detachnode(gdb, &node);
01895 }
01896 
01897 static void
01898 addnsec3(dns_name_t *name, dns_dbnode_t *node,
01899          const unsigned char *salt, size_t salt_len,
01900          unsigned int iterations, hashlist_t *hashlist,
01901          dns_ttl_t ttl)
01902 {
01903         unsigned char hash[NSEC3_MAX_HASH_LENGTH];
01904         const unsigned char *nexthash;
01905         unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
01906         dns_fixedname_t hashname;
01907         dns_rdatalist_t rdatalist;
01908         dns_rdataset_t rdataset;
01909         dns_rdata_t rdata = DNS_RDATA_INIT;
01910         isc_result_t result;
01911         dns_dbnode_t *nsec3node = NULL;
01912         char namebuf[DNS_NAME_FORMATSIZE];
01913         size_t hash_len;
01914 
01915         dns_name_format(name, namebuf, sizeof(namebuf));
01916 
01917         dns_fixedname_init(&hashname);
01918         dns_rdataset_init(&rdataset);
01919 
01920         dns_name_downcase(name, name, NULL);
01921         result = dns_nsec3_hashname(&hashname, hash, &hash_len,
01922                                     name, gorigin, dns_hash_sha1, iterations,
01923                                     salt, salt_len);
01924         check_result(result, "addnsec3: dns_nsec3_hashname()");
01925         nexthash = hashlist_findnext(hashlist, hash);
01926         result = dns_nsec3_buildrdata(gdb, gversion, node,
01927                                       unknownalg ?
01928                                           DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
01929                                       nsec3flags, iterations,
01930                                       salt, salt_len,
01931                                       nexthash, ISC_SHA1_DIGESTLENGTH,
01932                                       nsec3buffer, &rdata);
01933         check_result(result, "addnsec3: dns_nsec3_buildrdata()");
01934         dns_rdatalist_init(&rdatalist);
01935         rdatalist.rdclass = rdata.rdclass;
01936         rdatalist.type = rdata.type;
01937         rdatalist.ttl = ttl;
01938         ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
01939         result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
01940         check_result(result, "dns_rdatalist_tordataset()");
01941         result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
01942                                       ISC_TRUE, &nsec3node);
01943         check_result(result, "addnsec3: dns_db_findnode()");
01944         result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
01945                                     0, NULL);
01946         if (result == DNS_R_UNCHANGED)
01947                 result = ISC_R_SUCCESS;
01948         check_result(result, "addnsec3: dns_db_addrdataset()");
01949         dns_db_detachnode(gdb, &nsec3node);
01950 }
01951 
01952 /*%
01953  * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
01954  *
01955  * Extract the hash from the first label of 'name' then see if it
01956  * is in hashlist.  If 'name' is not in the hashlist then delete the
01957  * any NSEC3 records which have the same parameters as the chain we
01958  * are building.
01959  *
01960  * XXXMPA Should we also check that it of the form <hash>.<origin>?
01961  */
01962 static void
01963 nsec3clean(dns_name_t *name, dns_dbnode_t *node,
01964            unsigned int hashalg, unsigned int iterations,
01965            const unsigned char *salt, size_t salt_len, hashlist_t *hashlist)
01966 {
01967         dns_label_t label;
01968         dns_rdata_nsec3_t nsec3;
01969         dns_rdata_t rdata, delrdata;
01970         dns_rdatalist_t rdatalist;
01971         dns_rdataset_t rdataset, delrdataset;
01972         isc_boolean_t delete_rrsigs = ISC_FALSE;
01973         isc_buffer_t target;
01974         isc_result_t result;
01975         unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
01976         isc_boolean_t exists;
01977 
01978         /*
01979          * Get the first label.
01980          */
01981         dns_name_getlabel(name, 0, &label);
01982 
01983         /*
01984          * We want just the label contents.
01985          */
01986         isc_region_consume(&label, 1);
01987 
01988         /*
01989          * Decode base32hex string.
01990          */
01991         isc_buffer_init(&target, hash, sizeof(hash) - 1);
01992         result = isc_base32hex_decoderegion(&label, &target);
01993         if (result != ISC_R_SUCCESS)
01994                 return;
01995 
01996         hash[isc_buffer_usedlength(&target)] = 0;
01997 
01998         exists = hashlist_exists(hashlist, hash);
01999 
02000         /*
02001          * Verify that the NSEC3 parameters match the current ones
02002          * otherwise we are dealing with a different NSEC3 chain.
02003          */
02004         dns_rdataset_init(&rdataset);
02005         dns_rdataset_init(&delrdataset);
02006 
02007         result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
02008                                      0, 0, &rdataset, NULL);
02009         if (result != ISC_R_SUCCESS)
02010                 return;
02011 
02012         /*
02013          * Delete any NSEC3 records which are not part of the current
02014          * NSEC3 chain.
02015          */
02016         for (result = dns_rdataset_first(&rdataset);
02017              result == ISC_R_SUCCESS;
02018              result = dns_rdataset_next(&rdataset)) {
02019                 dns_rdata_init(&rdata);
02020                 dns_rdataset_current(&rdataset, &rdata);
02021                 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
02022                 check_result(result, "dns_rdata_tostruct");
02023                 if (exists && nsec3.hash == hashalg &&
02024                     nsec3.iterations == iterations &&
02025                     nsec3.salt_length == salt_len &&
02026                     !memcmp(nsec3.salt, salt, salt_len))
02027                         continue;
02028                 dns_rdatalist_init(&rdatalist);
02029                 rdatalist.rdclass = rdata.rdclass;
02030                 rdatalist.type = rdata.type;
02031                 if (set_maxttl)
02032                         rdatalist.ttl = ISC_MIN(rdataset.ttl, maxttl);
02033                 dns_rdata_init(&delrdata);
02034                 dns_rdata_clone(&rdata, &delrdata);
02035                 ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
02036                 result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
02037                 check_result(result, "dns_rdatalist_tordataset()");
02038                 result = dns_db_subtractrdataset(gdb, node, gversion,
02039                                                  &delrdataset, 0, NULL);
02040                 dns_rdataset_disassociate(&delrdataset);
02041                 if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET)
02042                         check_result(result, "dns_db_subtractrdataset(NSEC3)");
02043                 delete_rrsigs = ISC_TRUE;
02044         }
02045         dns_rdataset_disassociate(&rdataset);
02046         if (result != ISC_R_NOMORE)
02047                 check_result(result, "dns_rdataset_first/next");
02048 
02049         if (!delete_rrsigs)
02050                 return;
02051         /*
02052          * Delete the NSEC3 RRSIGs
02053          */
02054         result = dns_db_deleterdataset(gdb, node, gversion,
02055                                        dns_rdatatype_rrsig,
02056                                        dns_rdatatype_nsec3);
02057         if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
02058                 check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
02059 }
02060 
02061 static void
02062 rrset_cleanup(dns_name_t *name, dns_rdataset_t *rdataset,
02063               dns_diff_t *add, dns_diff_t *del)
02064 {
02065         isc_result_t result;
02066         unsigned int count1 = 0;
02067         dns_rdataset_t tmprdataset;
02068         char namestr[DNS_NAME_FORMATSIZE];
02069         char typestr[TYPE_FORMATSIZE];
02070 
02071         dns_name_format(name, namestr, sizeof(namestr));
02072         type_format(rdataset->type, typestr, sizeof(typestr));
02073 
02074         dns_rdataset_init(&tmprdataset);
02075         for (result = dns_rdataset_first(rdataset);
02076              result == ISC_R_SUCCESS;
02077              result = dns_rdataset_next(rdataset)) {
02078                 dns_rdata_t rdata1 = DNS_RDATA_INIT;
02079                 unsigned int count2 = 0;
02080 
02081                 count1++;
02082                 dns_rdataset_current(rdataset, &rdata1);
02083                 dns_rdataset_clone(rdataset, &tmprdataset);
02084                 for (result = dns_rdataset_first(&tmprdataset);
02085                      result == ISC_R_SUCCESS;
02086                      result = dns_rdataset_next(&tmprdataset)) {
02087                         dns_rdata_t rdata2 = DNS_RDATA_INIT;
02088                         dns_difftuple_t *tuple = NULL;
02089                         count2++;
02090                         dns_rdataset_current(&tmprdataset, &rdata2);
02091                         if (count1 < count2 &&
02092                             dns_rdata_casecompare(&rdata1, &rdata2) == 0)
02093                         {
02094                                 vbprintf(2, "removing duplicate at %s/%s\n",
02095                                             namestr, typestr);
02096                                 result = dns_difftuple_create(mctx,
02097                                                       DNS_DIFFOP_DELRESIGN,
02098                                                       name, rdataset->ttl,
02099                                                       &rdata2, &tuple);
02100                                 check_result(result, "dns_difftuple_create");
02101                                 dns_diff_append(del, &tuple);
02102                         } else if (set_maxttl && rdataset->ttl > maxttl) {
02103                                 vbprintf(2, "reducing ttl of %s/%s "
02104                                             "from %d to %d\n",
02105                                             namestr, typestr,
02106                                             rdataset->ttl, maxttl);
02107                                 result = dns_difftuple_create(mctx,
02108                                                       DNS_DIFFOP_DELRESIGN,
02109                                                       name, rdataset->ttl,
02110                                                       &rdata2, &tuple);
02111                                 check_result(result, "dns_difftuple_create");
02112                                 dns_diff_append(del, &tuple);
02113                                 tuple = NULL;
02114                                 result = dns_difftuple_create(mctx,
02115                                                       DNS_DIFFOP_ADDRESIGN,
02116                                                       name, maxttl,
02117                                                       &rdata2, &tuple);
02118                                 check_result(result, "dns_difftuple_create");
02119                                 dns_diff_append(add, &tuple);
02120                         }
02121                 }
02122                 dns_rdataset_disassociate(&tmprdataset);
02123         }
02124 }
02125 
02126 static void
02127 cleanup_zone(void) {
02128         isc_result_t result;
02129         dns_dbiterator_t *dbiter = NULL;
02130         dns_rdatasetiter_t *rdsiter = NULL;
02131         dns_diff_t add, del;
02132         dns_dbnode_t *node = NULL;
02133         dns_rdataset_t rdataset;
02134         dns_fixedname_t fname;
02135         dns_name_t *name;
02136 
02137         dns_diff_init(mctx, &add);
02138         dns_diff_init(mctx, &del);
02139         dns_fixedname_init(&fname);
02140         name = dns_fixedname_name(&fname);
02141         dns_rdataset_init(&rdataset);
02142 
02143         result = dns_db_createiterator(gdb, 0, &dbiter);
02144         check_result(result, "dns_db_createiterator()");
02145 
02146         for (result = dns_dbiterator_first(dbiter);
02147              result == ISC_R_SUCCESS;
02148              result = dns_dbiterator_next(dbiter)) {
02149 
02150                 result = dns_dbiterator_current(dbiter, &node, name);
02151                 check_dns_dbiterator_current(result);
02152                 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
02153                 check_result(result, "dns_db_allrdatasets()");
02154                 for (result = dns_rdatasetiter_first(rdsiter);
02155                      result == ISC_R_SUCCESS;
02156                      result = dns_rdatasetiter_next(rdsiter)) {
02157                         dns_rdatasetiter_current(rdsiter, &rdataset);
02158                         rrset_cleanup(name, &rdataset, &add, &del);
02159                         dns_rdataset_disassociate(&rdataset);
02160                 }
02161                 if (result != ISC_R_NOMORE)
02162                         fatal("rdatasets iteration failed.");
02163                 dns_rdatasetiter_destroy(&rdsiter);
02164                 dns_db_detachnode(gdb, &node);
02165         }
02166         if (result != ISC_R_NOMORE)
02167                 fatal("zone iteration failed.");
02168 
02169         result = dns_diff_applysilently(&del, gdb, gversion);
02170         check_result(result, "dns_diff_applysilently");
02171 
02172         result = dns_diff_applysilently(&add, gdb, gversion);
02173         check_result(result, "dns_diff_applysilently");
02174 
02175         dns_diff_clear(&del);
02176         dns_diff_clear(&add);
02177         dns_dbiterator_destroy(&dbiter);
02178 }
02179 
02180 /*
02181  * Generate NSEC3 records for the zone.
02182  */
02183 static void
02184 nsec3ify(unsigned int hashalg, dns_iterations_t iterations,
02185          const unsigned char *salt, size_t salt_len, hashlist_t *hashlist)
02186 {
02187         dns_dbiterator_t *dbiter = NULL;
02188         dns_dbnode_t *node = NULL, *nextnode = NULL;
02189         dns_fixedname_t fname, fnextname, fzonecut;
02190         dns_name_t *name, *nextname, *zonecut;
02191         dns_rdataset_t rdataset;
02192         int order;
02193         isc_boolean_t active;
02194         isc_boolean_t done = ISC_FALSE;
02195         isc_result_t result;
02196         isc_uint32_t nsttl = 0;
02197         unsigned int count, nlabels;
02198 
02199         dns_rdataset_init(&rdataset);
02200         dns_fixedname_init(&fname);
02201         name = dns_fixedname_name(&fname);
02202         dns_fixedname_init(&fnextname);
02203         nextname = dns_fixedname_name(&fnextname);
02204         dns_fixedname_init(&fzonecut);
02205         zonecut = NULL;
02206 
02207         /*
02208          * Walk the zone generating the hash names.
02209          */
02210         result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
02211         check_result(result, "dns_db_createiterator()");
02212 
02213         result = dns_dbiterator_first(dbiter);
02214         check_result(result, "dns_dbiterator_first()");
02215 
02216         while (!done) {
02217                 result = dns_dbiterator_current(dbiter, &node, name);
02218                 check_dns_dbiterator_current(result);
02219                 /*
02220                  * Skip out-of-zone records.
02221                  */
02222                 if (!dns_name_issubdomain(name, gorigin)) {
02223                         result = dns_dbiterator_next(dbiter);
02224                         if (result == ISC_R_NOMORE)
02225                                 done = ISC_TRUE;
02226                         else
02227                                 check_result(result, "dns_dbiterator_next()");
02228                         dns_db_detachnode(gdb, &node);
02229                         continue;
02230                 }
02231 
02232                 if (dns_name_equal(name, gorigin))
02233                         remove_records(node, dns_rdatatype_nsec, ISC_TRUE);
02234 
02235                 result = dns_dbiterator_next(dbiter);
02236                 nextnode = NULL;
02237                 while (result == ISC_R_SUCCESS) {
02238                         result = dns_dbiterator_current(dbiter, &nextnode,
02239                                                         nextname);
02240                         check_dns_dbiterator_current(result);
02241                         active = active_node(nextnode);
02242                         if (!active) {
02243                                 dns_db_detachnode(gdb, &nextnode);
02244                                 result = dns_dbiterator_next(dbiter);
02245                                 continue;
02246                         }
02247                         if (!dns_name_issubdomain(nextname, gorigin) ||
02248                             (zonecut != NULL &&
02249                              dns_name_issubdomain(nextname, zonecut))) {
02250                                 remove_sigs(nextnode, ISC_FALSE, 0);
02251                                 dns_db_detachnode(gdb, &nextnode);
02252                                 result = dns_dbiterator_next(dbiter);
02253                                 continue;
02254                         }
02255                         if (is_delegation(gdb, gversion, gorigin,
02256                                           nextname, nextnode, &nsttl))
02257                         {
02258                                 zonecut = dns_fixedname_name(&fzonecut);
02259                                 dns_name_copy(nextname, zonecut, NULL);
02260                                 remove_sigs(nextnode, ISC_TRUE, 0);
02261                                 if (generateds)
02262                                         add_ds(nextname, nextnode, nsttl);
02263                                 if (OPTOUT(nsec3flags) &&
02264                                     !secure(nextname, nextnode)) {
02265                                         dns_db_detachnode(gdb, &nextnode);
02266                                         result = dns_dbiterator_next(dbiter);
02267                                         continue;
02268                                 }
02269                         }
02270                         dns_db_detachnode(gdb, &nextnode);
02271                         break;
02272                 }
02273                 if (result == ISC_R_NOMORE) {
02274                         dns_name_copy(gorigin, nextname, NULL);
02275                         done = ISC_TRUE;
02276                 } else if (result != ISC_R_SUCCESS)
02277                         fatal("iterating through the database failed: %s",
02278                               isc_result_totext(result));
02279                 dns_name_downcase(name, name, NULL);
02280                 hashlist_add_dns_name(hashlist, name, hashalg, iterations,
02281                                       salt, salt_len, ISC_FALSE);
02282                 dns_db_detachnode(gdb, &node);
02283                 /*
02284                  * Add hashs for empty nodes.  Use closest encloser logic.
02285                  * The closest encloser either has data or is a empty
02286                  * node for another <name,nextname> span so we don't add
02287                  * it here.  Empty labels on nextname are within the span.
02288                  */
02289                 dns_name_downcase(nextname, nextname, NULL);
02290                 dns_name_fullcompare(name, nextname, &order, &nlabels);
02291                 addnowildcardhash(hashlist, name, hashalg, iterations,
02292                                   salt, salt_len);
02293                 count = dns_name_countlabels(nextname);
02294                 while (count > nlabels + 1) {
02295                         count--;
02296                         dns_name_split(nextname, count, NULL, nextname);
02297                         hashlist_add_dns_name(hashlist, nextname, hashalg,
02298                                               iterations, salt, salt_len,
02299                                               ISC_FALSE);
02300                         addnowildcardhash(hashlist, nextname, hashalg,
02301                                           iterations, salt, salt_len);
02302                 }
02303         }
02304         dns_dbiterator_destroy(&dbiter);
02305 
02306         /*
02307          * We have all the hashes now so we can sort them.
02308          */
02309         hashlist_sort(hashlist);
02310 
02311         /*
02312          * Check for duplicate hashes.  If found the salt needs to
02313          * be changed.
02314          */
02315         if (hashlist_hasdup(hashlist))
02316                 fatal("Duplicate hash detected. Pick a different salt.");
02317 
02318         /*
02319          * Generate the nsec3 records.
02320          */
02321         zonecut = NULL;
02322         done = ISC_FALSE;
02323 
02324         addnsec3param(salt, salt_len, iterations);
02325 
02326         /*
02327          * Clean out NSEC3 records which don't match this chain.
02328          */
02329         result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
02330         check_result(result, "dns_db_createiterator()");
02331 
02332         for (result = dns_dbiterator_first(dbiter);
02333              result == ISC_R_SUCCESS;
02334              result = dns_dbiterator_next(dbiter)) {
02335                 result = dns_dbiterator_current(dbiter, &node, name);
02336                 check_dns_dbiterator_current(result);
02337                 nsec3clean(name, node, hashalg, iterations, salt, salt_len,
02338                            hashlist);
02339                 dns_db_detachnode(gdb, &node);
02340         }
02341         dns_dbiterator_destroy(&dbiter);
02342 
02343         /*
02344          * Generate / complete the new chain.
02345          */
02346         result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
02347         check_result(result, "dns_db_createiterator()");
02348 
02349         result = dns_dbiterator_first(dbiter);
02350         check_result(result, "dns_dbiterator_first()");
02351 
02352         while (!done) {
02353                 result = dns_dbiterator_current(dbiter, &node, name);
02354                 check_dns_dbiterator_current(result);
02355                 /*
02356                  * Skip out-of-zone records.
02357                  */
02358                 if (!dns_name_issubdomain(name, gorigin)) {
02359                         result = dns_dbiterator_next(dbiter);
02360                         if (result == ISC_R_NOMORE)
02361                                 done = ISC_TRUE;
02362                         else
02363                                 check_result(result, "dns_dbiterator_next()");
02364                         dns_db_detachnode(gdb, &node);
02365                         continue;
02366                 }
02367                 result = dns_dbiterator_next(dbiter);
02368                 nextnode = NULL;
02369                 while (result == ISC_R_SUCCESS) {
02370                         result = dns_dbiterator_current(dbiter, &nextnode,
02371                                                         nextname);
02372                         check_dns_dbiterator_current(result);
02373                         active = active_node(nextnode);
02374                         if (!active) {
02375                                 dns_db_detachnode(gdb, &nextnode);
02376                                 result = dns_dbiterator_next(dbiter);
02377                                 continue;
02378                         }
02379                         if (!dns_name_issubdomain(nextname, gorigin) ||
02380                             (zonecut != NULL &&
02381                              dns_name_issubdomain(nextname, zonecut))) {
02382                                 dns_db_detachnode(gdb, &nextnode);
02383                                 result = dns_dbiterator_next(dbiter);
02384                                 continue;
02385                         }
02386                         if (is_delegation(gdb, gversion, gorigin,
02387                                           nextname, nextnode, NULL))
02388                         {
02389                                 zonecut = dns_fixedname_name(&fzonecut);
02390                                 dns_name_copy(nextname, zonecut, NULL);
02391                                 if (OPTOUT(nsec3flags) &&
02392                                     !secure(nextname, nextnode)) {
02393                                         dns_db_detachnode(gdb, &nextnode);
02394                                         result = dns_dbiterator_next(dbiter);
02395                                         continue;
02396                                 }
02397                         }
02398                         dns_db_detachnode(gdb, &nextnode);
02399                         break;
02400                 }
02401                 if (result == ISC_R_NOMORE) {
02402                         dns_name_copy(gorigin, nextname, NULL);
02403                         done = ISC_TRUE;
02404                 } else if (result != ISC_R_SUCCESS)
02405                         fatal("iterating through the database failed: %s",
02406                               isc_result_totext(result));
02407                 /*
02408                  * We need to pause here to release the lock on the database.
02409                  */
02410                 dns_dbiterator_pause(dbiter);
02411                 addnsec3(name, node, salt, salt_len, iterations,
02412                          hashlist, zone_soa_min_ttl);
02413                 dns_db_detachnode(gdb, &node);
02414                 /*
02415                  * Add NSEC3's for empty nodes.  Use closest encloser logic.
02416                  */
02417                 dns_name_fullcompare(name, nextname, &order, &nlabels);
02418                 count = dns_name_countlabels(nextname);
02419                 while (count > nlabels + 1) {
02420                         count--;
02421                         dns_name_split(nextname, count, NULL, nextname);
02422                         addnsec3(nextname, NULL, salt, salt_len,
02423                                  iterations, hashlist, zone_soa_min_ttl);
02424                 }
02425         }
02426         dns_dbiterator_destroy(&dbiter);
02427 }
02428 
02429 /*%
02430  * Load the zone file from disk
02431  */
02432 static void
02433 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
02434         isc_buffer_t b;
02435         int len;
02436         dns_fixedname_t fname;
02437         dns_name_t *name;
02438         isc_result_t result;
02439 
02440         len = strlen(origin);
02441         isc_buffer_init(&b, origin, len);
02442         isc_buffer_add(&b, len);
02443 
02444         dns_fixedname_init(&fname);
02445         name = dns_fixedname_name(&fname);
02446         result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
02447         if (result != ISC_R_SUCCESS)
02448                 fatal("failed converting name '%s' to dns format: %s",
02449                       origin, isc_result_totext(result));
02450 
02451         result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
02452                                rdclass, 0, NULL, db);
02453         check_result(result, "dns_db_create()");
02454 
02455         result = dns_db_load2(*db, file, inputformat);
02456         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
02457                 fatal("failed loading zone from '%s': %s",
02458                       file, isc_result_totext(result));
02459 }
02460 
02461 /*%
02462  * Finds all public zone keys in the zone, and attempts to load the
02463  * private keys from disk.
02464  */
02465 static void
02466 loadzonekeys(isc_boolean_t preserve_keys, isc_boolean_t load_public) {
02467         dns_dbnode_t *node;
02468         dns_dbversion_t *currentversion = NULL;
02469         isc_result_t result;
02470         dns_rdataset_t rdataset, keysigs, soasigs;
02471 
02472         node = NULL;
02473         result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
02474         if (result != ISC_R_SUCCESS)
02475                 fatal("failed to find the zone's origin: %s",
02476                       isc_result_totext(result));
02477 
02478         dns_db_currentversion(gdb, &currentversion);
02479 
02480         dns_rdataset_init(&rdataset);
02481         dns_rdataset_init(&soasigs);
02482         dns_rdataset_init(&keysigs);
02483 
02484         /* Make note of the keys which signed the SOA, if any */
02485         result = dns_db_findrdataset(gdb, node, currentversion,
02486                                      dns_rdatatype_soa, 0, 0,
02487                                      &rdataset, &soasigs);
02488         if (result != ISC_R_SUCCESS)
02489                 goto cleanup;
02490 
02491         /* Preserve the TTL of the DNSKEY RRset, if any */
02492         dns_rdataset_disassociate(&rdataset);
02493         result = dns_db_findrdataset(gdb, node, currentversion,
02494                                      dns_rdatatype_dnskey, 0, 0,
02495                                      &rdataset, &keysigs);
02496 
02497         if (result != ISC_R_SUCCESS)
02498                 goto cleanup;
02499 
02500         if (set_keyttl && keyttl != rdataset.ttl) {
02501                 fprintf(stderr, "User-specified TTL %d conflicts "
02502                                 "with existing DNSKEY RRset TTL.\n",
02503                                 keyttl);
02504                 fprintf(stderr, "Imported keys will use the RRSet "
02505                                 "TTL %d instead.\n",
02506                                 rdataset.ttl);
02507         }
02508         keyttl = rdataset.ttl;
02509 
02510         /* Load keys corresponding to the existing DNSKEY RRset. */
02511         result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx,
02512                                                 &rdataset, &keysigs, &soasigs,
02513                                                 preserve_keys, load_public,
02514                                                 &keylist);
02515         if (result != ISC_R_SUCCESS)
02516                 fatal("failed to load the zone keys: %s",
02517                       isc_result_totext(result));
02518 
02519  cleanup:
02520         if (dns_rdataset_isassociated(&rdataset))
02521                 dns_rdataset_disassociate(&rdataset);
02522         if (dns_rdataset_isassociated(&keysigs))
02523                 dns_rdataset_disassociate(&keysigs);
02524         if (dns_rdataset_isassociated(&soasigs))
02525                 dns_rdataset_disassociate(&soasigs);
02526         dns_db_detachnode(gdb, &node);
02527         dns_db_closeversion(gdb, &currentversion, ISC_FALSE);
02528 }
02529 
02530 static void
02531 loadexplicitkeys(char *keyfiles[], int n, isc_boolean_t setksk) {
02532         isc_result_t result;
02533         int i;
02534 
02535         for (i = 0; i < n; i++) {
02536                 dns_dnsseckey_t *key = NULL;
02537                 dst_key_t *newkey = NULL;
02538 
02539                 result = dst_key_fromnamedfile(keyfiles[i], directory,
02540                                                DST_TYPE_PUBLIC |
02541                                                DST_TYPE_PRIVATE,
02542                                                mctx, &newkey);
02543                 if (result != ISC_R_SUCCESS)
02544                         fatal("cannot load dnskey %s: %s", keyfiles[i],
02545                               isc_result_totext(result));
02546 
02547                 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
02548                         fatal("key %s not at origin\n", keyfiles[i]);
02549 
02550                 if (!dst_key_isprivate(newkey))
02551                         fatal("cannot sign zone with non-private dnskey %s",
02552                               keyfiles[i]);
02553 
02554                 /* Skip any duplicates */
02555                 for (key = ISC_LIST_HEAD(keylist);
02556                      key != NULL;
02557                      key = ISC_LIST_NEXT(key, link)) {
02558                         if (dst_key_id(key->key) == dst_key_id(newkey) &&
02559                             dst_key_alg(key->key) == dst_key_alg(newkey))
02560                                 break;
02561                 }
02562 
02563                 if (key == NULL) {
02564                         /* We haven't seen this key before */
02565                         dns_dnsseckey_create(mctx, &newkey, &key);
02566                         ISC_LIST_APPEND(keylist, key, link);
02567                         key->source = dns_keysource_user;
02568                 } else {
02569                         dst_key_free(&key->key);
02570                         key->key = newkey;
02571                 }
02572 
02573                 key->force_publish = ISC_TRUE;
02574                 key->force_sign = ISC_TRUE;
02575 
02576                 if (setksk)
02577                         key->ksk = ISC_TRUE;
02578         }
02579 }
02580 
02581 static void
02582 report(const char *format, ...) {
02583         va_list args;
02584         va_start(args, format);
02585         vfprintf(stderr, format, args);
02586         va_end(args);
02587         putc('\n', stderr);
02588 }
02589 
02590 static void
02591 build_final_keylist(void) {
02592         isc_result_t result;
02593         dns_dbversion_t *ver = NULL;
02594         dns_diff_t diff;
02595         dns_dnsseckeylist_t matchkeys;
02596         char name[DNS_NAME_FORMATSIZE];
02597 
02598         /*
02599          * Find keys that match this zone in the key repository.
02600          */
02601         ISC_LIST_INIT(matchkeys);
02602         result = dns_dnssec_findmatchingkeys(gorigin, directory,
02603                                              mctx, &matchkeys);
02604         if (result == ISC_R_NOTFOUND)
02605                 result = ISC_R_SUCCESS;
02606         check_result(result, "dns_dnssec_findmatchingkeys");
02607 
02608         result = dns_db_newversion(gdb, &ver);
02609         check_result(result, "dns_db_newversion");
02610 
02611         dns_diff_init(mctx, &diff);
02612 
02613         /*
02614          * Update keylist with information from from the key repository.
02615          */
02616         dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
02617                               &diff, ignore_kskflag, mctx, report);
02618 
02619         dns_name_format(gorigin, name, sizeof(name));
02620 
02621         result = dns_diff_applysilently(&diff, gdb, ver);
02622         if (result != ISC_R_SUCCESS)
02623                 fatal("failed to update DNSKEY RRset at node '%s': %s",
02624                       name, isc_result_totext(result));
02625 
02626         dns_db_closeversion(gdb, &ver, ISC_TRUE);
02627 
02628         dns_diff_clear(&diff);
02629 }
02630 
02631 static void
02632 warnifallksk(dns_db_t *db) {
02633         dns_dbversion_t *currentversion = NULL;
02634         dns_dbnode_t *node = NULL;
02635         dns_rdataset_t rdataset;
02636         dns_rdata_t rdata = DNS_RDATA_INIT;
02637         isc_result_t result;
02638         dns_rdata_dnskey_t dnskey;
02639         isc_boolean_t have_non_ksk = ISC_FALSE;
02640 
02641         dns_db_currentversion(db, &currentversion);
02642 
02643         result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
02644         if (result != ISC_R_SUCCESS)
02645                 fatal("failed to find the zone's origin: %s",
02646                       isc_result_totext(result));
02647 
02648         dns_rdataset_init(&rdataset);
02649         result = dns_db_findrdataset(db, node, currentversion,
02650                                      dns_rdatatype_dnskey, 0, 0, &rdataset,
02651                                      NULL);
02652         if (result != ISC_R_SUCCESS)
02653                 fatal("failed to find keys at the zone apex: %s",
02654                       isc_result_totext(result));
02655         result = dns_rdataset_first(&rdataset);
02656         check_result(result, "dns_rdataset_first");
02657         while (result == ISC_R_SUCCESS) {
02658                 dns_rdata_reset(&rdata);
02659                 dns_rdataset_current(&rdataset, &rdata);
02660                 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
02661                 check_result(result, "dns_rdata_tostruct");
02662                 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
02663                         have_non_ksk = ISC_TRUE;
02664                         result = ISC_R_NOMORE;
02665                 } else
02666                         result = dns_rdataset_next(&rdataset);
02667                 dns_rdata_freestruct(&dnskey);
02668         }
02669         dns_rdataset_disassociate(&rdataset);
02670         dns_db_detachnode(db, &node);
02671         dns_db_closeversion(db, &currentversion, ISC_FALSE);
02672         if (!have_non_ksk && !ignore_kskflag) {
02673                 if (disable_zone_check)
02674                         fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
02675                                 "supply a ZSK or use '-z'.\n",
02676                                 program);
02677                 else
02678                         fatal("No non-KSK DNSKEY found; "
02679                               "supply a ZSK or use '-z'.");
02680         }
02681 }
02682 
02683 static void
02684 set_nsec3params(isc_boolean_t update, isc_boolean_t set_salt,
02685                 isc_boolean_t set_optout, isc_boolean_t set_iter)
02686 {
02687         isc_result_t result;
02688         dns_dbversion_t *ver = NULL;
02689         dns_dbnode_t *node = NULL;
02690         dns_rdataset_t rdataset;
02691         dns_rdata_t rdata = DNS_RDATA_INIT;
02692         dns_rdata_nsec3_t nsec3;
02693         dns_fixedname_t fname;
02694         dns_name_t *hashname;
02695         unsigned char orig_salt[255];
02696         size_t orig_saltlen;
02697         dns_hash_t orig_hash;
02698         isc_uint16_t orig_iter;
02699 
02700         dns_db_currentversion(gdb, &ver);
02701         dns_rdataset_init(&rdataset);
02702 
02703         orig_saltlen = sizeof(orig_salt);
02704         result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
02705                                            &orig_iter, orig_salt,
02706                                            &orig_saltlen);
02707         if (result != ISC_R_SUCCESS)
02708                 goto cleanup;
02709 
02710         nsec_datatype = dns_rdatatype_nsec3;
02711 
02712         if (!update && set_salt) {
02713                 if (salt_length != orig_saltlen ||
02714                     memcmp(saltbuf, orig_salt, salt_length) != 0)
02715                         fatal("An NSEC3 chain exists with a different salt. "
02716                               "Use -u to update it.");
02717         } else if (!set_salt) {
02718                 salt_length = orig_saltlen;
02719                 memmove(saltbuf, orig_salt, orig_saltlen);
02720                 gsalt = saltbuf;
02721         }
02722 
02723         if (!update && set_iter) {
02724                 if (nsec3iter != orig_iter)
02725                         fatal("An NSEC3 chain exists with different "
02726                               "iterations. Use -u to update it.");
02727         } else if (!set_iter)
02728                 nsec3iter = orig_iter;
02729 
02730         /*
02731          * Find an NSEC3 record to get the current OPTOUT value.
02732          * (This assumes all NSEC3 records agree.)
02733          */
02734 
02735         dns_fixedname_init(&fname);
02736         hashname = dns_fixedname_name(&fname);
02737         result = dns_nsec3_hashname(&fname, NULL, NULL,
02738                                     gorigin, gorigin, dns_hash_sha1,
02739                                     orig_iter, orig_salt, orig_saltlen);
02740         check_result(result, "dns_nsec3_hashname");
02741 
02742         result = dns_db_findnsec3node(gdb, hashname, ISC_FALSE, &node);
02743         if (result != ISC_R_SUCCESS)
02744                 goto cleanup;
02745 
02746         result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3,
02747                                      0, 0, &rdataset, NULL);
02748         if (result != ISC_R_SUCCESS)
02749                 goto cleanup;
02750 
02751         result = dns_rdataset_first(&rdataset);
02752         check_result(result, "dns_rdataset_first");
02753         dns_rdataset_current(&rdataset, &rdata);
02754         result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
02755         check_result(result, "dns_rdata_tostruct");
02756 
02757         if (!update && set_optout) {
02758                 if (nsec3flags != nsec3.flags)
02759                         fatal("An NSEC3 chain exists with%s OPTOUT. "
02760                               "Use -u -%s to %s it.",
02761                               OPTOUT(nsec3.flags) ? "" : "out",
02762                               OPTOUT(nsec3.flags) ? "AA" : "A",
02763                               OPTOUT(nsec3.flags) ? "clear" : "set");
02764         } else if (!set_optout)
02765                 nsec3flags = nsec3.flags;
02766 
02767         dns_rdata_freestruct(&nsec3);
02768 
02769  cleanup:
02770         if (dns_rdataset_isassociated(&rdataset))
02771                 dns_rdataset_disassociate(&rdataset);
02772         if (node != NULL)
02773                 dns_db_detachnode(gdb, &node);
02774         dns_db_closeversion(gdb, &ver, ISC_FALSE);
02775 }
02776 
02777 static void
02778 writeset(const char *prefix, dns_rdatatype_t type) {
02779         char *filename;
02780         char namestr[DNS_NAME_FORMATSIZE];
02781         dns_db_t *db = NULL;
02782         dns_dbversion_t *dbversion = NULL;
02783         dns_diff_t diff;
02784         dns_difftuple_t *tuple = NULL;
02785         dns_fixedname_t fixed;
02786         dns_name_t *name;
02787         dns_rdata_t rdata, ds;
02788         isc_boolean_t have_ksk = ISC_FALSE;
02789         isc_boolean_t have_non_ksk = ISC_FALSE;
02790         isc_buffer_t b;
02791         isc_buffer_t namebuf;
02792         isc_region_t r;
02793         isc_result_t result;
02794         dns_dnsseckey_t *key, *tmpkey;
02795         unsigned char dsbuf[DNS_DS_BUFFERSIZE];
02796         unsigned char keybuf[DST_KEY_MAXSIZE];
02797         unsigned int filenamelen;
02798         const dns_master_style_t *style =
02799                 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
02800 
02801         isc_buffer_init(&namebuf, namestr, sizeof(namestr));
02802         result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
02803         check_result(result, "dns_name_tofilenametext");
02804         isc_buffer_putuint8(&namebuf, 0);
02805         filenamelen = strlen(prefix) + strlen(namestr);
02806         if (dsdir != NULL)
02807                 filenamelen += strlen(dsdir) + 1;
02808         filename = isc_mem_get(mctx, filenamelen + 1);
02809         if (filename == NULL)
02810                 fatal("out of memory");
02811         if (dsdir != NULL)
02812                 sprintf(filename, "%s/", dsdir);
02813         else
02814                 filename[0] = 0;
02815         strcat(filename, prefix);
02816         strcat(filename, namestr);
02817 
02818         dns_diff_init(mctx, &diff);
02819 
02820         if (type == dns_rdatatype_dlv) {
02821                 dns_name_t tname;
02822                 unsigned int labels;
02823 
02824                 dns_name_init(&tname, NULL);
02825                 dns_fixedname_init(&fixed);
02826                 name = dns_fixedname_name(&fixed);
02827                 labels = dns_name_countlabels(gorigin);
02828                 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
02829                 result = dns_name_concatenate(&tname, dlv, name, NULL);
02830                 check_result(result, "dns_name_concatenate");
02831         } else
02832                 name = gorigin;
02833 
02834         for (key = ISC_LIST_HEAD(keylist);
02835              key != NULL;
02836              key = ISC_LIST_NEXT(key, link))
02837         {
02838                 if (REVOKE(key->key))
02839                         continue;
02840                 if (isksk(key)) {
02841                         have_ksk = ISC_TRUE;
02842                         have_non_ksk = ISC_FALSE;
02843                 } else {
02844                         have_ksk = ISC_FALSE;
02845                         have_non_ksk = ISC_TRUE;
02846                 }
02847                 for (tmpkey = ISC_LIST_HEAD(keylist);
02848                      tmpkey != NULL;
02849                      tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
02850                         if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
02851                                 continue;
02852                         if (REVOKE(tmpkey->key))
02853                                 continue;
02854                         if (isksk(tmpkey))
02855                                 have_ksk = ISC_TRUE;
02856                         else
02857                                 have_non_ksk = ISC_TRUE;
02858                 }
02859                 if (have_ksk && have_non_ksk && !isksk(key))
02860                         continue;
02861                 dns_rdata_init(&rdata);
02862                 dns_rdata_init(&ds);
02863                 isc_buffer_init(&b, keybuf, sizeof(keybuf));
02864                 result = dst_key_todns(key->key, &b);
02865                 check_result(result, "dst_key_todns");
02866                 isc_buffer_usedregion(&b, &r);
02867                 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
02868                 if (type != dns_rdatatype_dnskey) {
02869                         result = dns_ds_buildrdata(gorigin, &rdata,
02870                                                    DNS_DSDIGEST_SHA1,
02871                                                    dsbuf, &ds);
02872                         check_result(result, "dns_ds_buildrdata");
02873                         if (type == dns_rdatatype_dlv)
02874                                 ds.type = dns_rdatatype_dlv;
02875                         result = dns_difftuple_create(mctx,
02876                                                       DNS_DIFFOP_ADDRESIGN,
02877                                                       name, 0, &ds, &tuple);
02878                         check_result(result, "dns_difftuple_create");
02879                         dns_diff_append(&diff, &tuple);
02880 
02881                         dns_rdata_reset(&ds);
02882                         result = dns_ds_buildrdata(gorigin, &rdata,
02883                                                    DNS_DSDIGEST_SHA256,
02884                                                    dsbuf, &ds);
02885                         check_result(result, "dns_ds_buildrdata");
02886                         if (type == dns_rdatatype_dlv)
02887                                 ds.type = dns_rdatatype_dlv;
02888                         result = dns_difftuple_create(mctx,
02889                                                       DNS_DIFFOP_ADDRESIGN,
02890                                                       name, 0, &ds, &tuple);
02891 
02892                 } else
02893                         result = dns_difftuple_create(mctx,
02894                                                       DNS_DIFFOP_ADDRESIGN,
02895                                                       gorigin, zone_soa_min_ttl,
02896                                                       &rdata, &tuple);
02897                 check_result(result, "dns_difftuple_create");
02898                 dns_diff_append(&diff, &tuple);
02899         }
02900 
02901         result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
02902                                gclass, 0, NULL, &db);
02903         check_result(result, "dns_db_create");
02904 
02905         result = dns_db_newversion(db, &dbversion);
02906         check_result(result, "dns_db_newversion");
02907 
02908         result = dns_diff_apply(&diff, db, dbversion);
02909         check_result(result, "dns_diff_apply");
02910         dns_diff_clear(&diff);
02911 
02912         result = dns_master_dump(mctx, db, dbversion, style, filename);
02913         check_result(result, "dns_master_dump");
02914 
02915         isc_mem_put(mctx, filename, filenamelen + 1);
02916 
02917         dns_db_closeversion(db, &dbversion, ISC_FALSE);
02918         dns_db_detach(&db);
02919 }
02920 
02921 static void
02922 print_time(FILE *fp) {
02923         time_t currenttime;
02924 
02925         if (outputformat != dns_masterformat_text)
02926                 return;
02927 
02928         currenttime = time(NULL);
02929         fprintf(fp, "; File written on %s", ctime(&currenttime));
02930 }
02931 
02932 static void
02933 print_version(FILE *fp) {
02934         if (outputformat != dns_masterformat_text)
02935                 return;
02936 
02937         fprintf(fp, "; dnssec_signzone version " VERSION "\n");
02938 }
02939 
02940 ISC_PLATFORM_NORETURN_PRE static void
02941 usage(void) ISC_PLATFORM_NORETURN_POST;
02942 
02943 static void
02944 usage(void) {
02945         fprintf(stderr, "Usage:\n");
02946         fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
02947 
02948         fprintf(stderr, "\n");
02949 
02950         fprintf(stderr, "Version: %s\n", VERSION);
02951 
02952         fprintf(stderr, "Options: (default value in parenthesis) \n");
02953         fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
02954                         "\t\tfor the zone and determines how they are to "
02955                         "be used\n");
02956         fprintf(stderr, "\t-K directory:\n");
02957         fprintf(stderr, "\t\tdirectory to find key files (.)\n");
02958         fprintf(stderr, "\t-d directory:\n");
02959         fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
02960         fprintf(stderr, "\t-g:\t");
02961         fprintf(stderr, "update DS records based on child zones' "
02962                         "dsset-* files\n");
02963         fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
02964         fprintf(stderr, "\t\tRRSIG start time "
02965                                 "- absolute|offset (now - 1 hour)\n");
02966         fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
02967         fprintf(stderr, "\t\tRRSIG end time "
02968                                 "- absolute|from start|from now "
02969                                 "(now + 30 days)\n");
02970         fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
02971         fprintf(stderr, "\t\tDNSKEY RRSIG end "
02972                                 "- absolute|from start|from now "
02973                                 "(matches -e)\n");
02974         fprintf(stderr, "\t-i interval:\n");
02975         fprintf(stderr, "\t\tcycle interval - resign "
02976                                 "if < interval from end ( (end-start)/4 )\n");
02977         fprintf(stderr, "\t-j jitter:\n");
02978         fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
02979         fprintf(stderr, "\t-v debuglevel (0)\n");
02980         fprintf(stderr, "\t-V:\tprint version information\n");
02981         fprintf(stderr, "\t-o origin:\n");
02982         fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
02983         fprintf(stderr, "\t-f outfile:\n");
02984         fprintf(stderr, "\t\tfile the signed zone is written in "
02985                                 "(zonefile + .signed)\n");
02986         fprintf(stderr, "\t-I format:\n");
02987         fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
02988         fprintf(stderr, "\t-O format:\n");
02989         fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
02990         fprintf(stderr, "\t-N format:\n");
02991         fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
02992         fprintf(stderr, "\t-D:\n");
02993         fprintf(stderr, "\t\toutput only DNSSEC-related records\n");
02994         fprintf(stderr, "\t-r randomdev:\n");
02995         fprintf(stderr, "\t\ta file containing random data\n");
02996         fprintf(stderr, "\t-a:\t");
02997         fprintf(stderr, "verify generated signatures\n");
02998         fprintf(stderr, "\t-c class (IN)\n");
02999         fprintf(stderr, "\t-E engine:\n");
03000 #if defined(PKCS11CRYPTO)
03001         fprintf(stderr, "\t\tpath to PKCS#11 provider library "
03002                 "(default is %s)\n", PK11_LIB_LOCATION);
03003 #elif defined(USE_PKCS11)
03004         fprintf(stderr, "\t\tname of an OpenSSL engine to use "
03005                                 "(default is \"pkcs11\")\n");
03006 #else
03007         fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
03008 #endif
03009         fprintf(stderr, "\t-p:\t");
03010         fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
03011         fprintf(stderr, "\t-P:\t");
03012         fprintf(stderr, "disable post-sign verification\n");
03013         fprintf(stderr, "\t-Q:\t");
03014         fprintf(stderr, "remove signatures from keys that are no "
03015                                 "longer active\n");
03016         fprintf(stderr, "\t-R:\t");
03017         fprintf(stderr, "remove signatures from keys that no longer exist\n");
03018         fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
03019         fprintf(stderr, "\t-t:\t");
03020         fprintf(stderr, "print statistics\n");
03021         fprintf(stderr, "\t-u:\t");
03022         fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
03023         fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
03024         fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
03025         fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
03026                         "\t\twith older versions of dnssec-signzone -g\n");
03027         fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
03028         fprintf(stderr, "\t-k key_signing_key\n");
03029         fprintf(stderr, "\t-l lookasidezone\n");
03030         fprintf(stderr, "\t-3 NSEC3 salt\n");
03031         fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
03032         fprintf(stderr, "\t-A NSEC3 optout\n");
03033 
03034         fprintf(stderr, "\n");
03035 
03036         fprintf(stderr, "Signing Keys: ");
03037         fprintf(stderr, "(default: all zone keys that have private keys)\n");
03038         fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
03039 
03040         exit(0);
03041 }
03042 
03043 static void
03044 removetempfile(void) {
03045         if (removefile)
03046                 isc_file_remove(tempfile);
03047 }
03048 
03049 static void
03050 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish,
03051             isc_time_t *sign_start, isc_time_t *sign_finish)
03052 {
03053         isc_uint64_t time_us;      /* Time in microseconds */
03054         isc_uint64_t time_ms;      /* Time in milliseconds */
03055         isc_uint64_t sig_ms;       /* Signatures per millisecond */
03056         FILE *out = output_stdout ? stderr : stdout;
03057 
03058         fprintf(out, "Signatures generated:               %10d\n", nsigned);
03059         fprintf(out, "Signatures retained:                %10d\n", nretained);
03060         fprintf(out, "Signatures dropped:                 %10d\n", ndropped);
03061         fprintf(out, "Signatures successfully verified:   %10d\n", nverified);
03062         fprintf(out, "Signatures unsuccessfully "
03063                      "verified: %10d\n", nverifyfailed);
03064 
03065         time_us = isc_time_microdiff(sign_finish, sign_start);
03066         time_ms = time_us / 1000;
03067         fprintf(out, "Signing time in seconds:           %7u.%03u\n",
03068                 (unsigned int) (time_ms / 1000),
03069                 (unsigned int) (time_ms % 1000));
03070         if (time_us > 0) {
03071                 sig_ms = ((isc_uint64_t)nsigned * 1000000000) / time_us;
03072                 fprintf(out, "Signatures per second:             %7u.%03u\n",
03073                         (unsigned int) sig_ms / 1000,
03074                         (unsigned int) sig_ms % 1000);
03075         }
03076 
03077         time_us = isc_time_microdiff(timer_finish, timer_start);
03078         time_ms = time_us / 1000;
03079         fprintf(out, "Runtime in seconds:                %7u.%03u\n",
03080                 (unsigned int) (time_ms / 1000),
03081                 (unsigned int) (time_ms % 1000));
03082 }
03083 
03084 int
03085 main(int argc, char *argv[]) {
03086         int i, ch;
03087         char *startstr = NULL, *endstr = NULL, *classname = NULL;
03088         char *dnskey_endstr = NULL;
03089         char *origin = NULL, *file = NULL, *output = NULL;
03090         char *inputformatstr = NULL, *outputformatstr = NULL;
03091         char *serialformatstr = NULL;
03092         char *dskeyfile[MAXDSKEYS];
03093         int ndskeys = 0;
03094         char *endp;
03095         isc_time_t timer_start, timer_finish;
03096         isc_time_t sign_start, sign_finish;
03097         dns_dnsseckey_t *key;
03098         isc_result_t result;
03099         isc_log_t *log = NULL;
03100         isc_boolean_t pseudorandom = ISC_FALSE;
03101 #ifdef USE_PKCS11
03102         const char *engine = PKCS11_ENGINE;
03103 #else
03104         const char *engine = NULL;
03105 #endif
03106         unsigned int eflags;
03107         isc_boolean_t free_output = ISC_FALSE;
03108         int tempfilelen = 0;
03109         dns_rdataclass_t rdclass;
03110         isc_task_t **tasks = NULL;
03111         isc_buffer_t b;
03112         int len;
03113         hashlist_t hashlist;
03114         isc_boolean_t make_keyset = ISC_FALSE;
03115         isc_boolean_t set_salt = ISC_FALSE;
03116         isc_boolean_t set_optout = ISC_FALSE;
03117         isc_boolean_t set_iter = ISC_FALSE;
03118         isc_boolean_t nonsecify = ISC_FALSE;
03119 
03120         /* Unused letters: Bb G J q Yy (and F is reserved). */
03121 #define CMDLINE_FLAGS \
03122         "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:M:n:N:o:O:PpQRr:s:ST:tuUv:VX:xzZ:"
03123 
03124         /*
03125          * Process memory debugging argument first.
03126          */
03127         while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
03128                 switch (ch) {
03129                 case 'm':
03130                         if (strcasecmp(isc_commandline_argument, "record") == 0)
03131                                 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
03132                         if (strcasecmp(isc_commandline_argument, "trace") == 0)
03133                                 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
03134                         if (strcasecmp(isc_commandline_argument, "usage") == 0)
03135                                 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
03136                         if (strcasecmp(isc_commandline_argument, "size") == 0)
03137                                 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
03138                         if (strcasecmp(isc_commandline_argument, "mctx") == 0)
03139                                 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
03140                         break;
03141                 default:
03142                         break;
03143                 }
03144         }
03145         isc_commandline_reset = ISC_TRUE;
03146 
03147         masterstyle = &dns_master_style_explicitttl;
03148 
03149         check_result(isc_app_start(), "isc_app_start");
03150 
03151         result = isc_mem_create(0, 0, &mctx);
03152         if (result != ISC_R_SUCCESS)
03153                 fatal("out of memory");
03154 
03155 #ifdef PKCS11CRYPTO
03156         pk11_result_register();
03157 #endif
03158         dns_result_register();
03159 
03160         isc_commandline_errprint = ISC_FALSE;
03161 
03162         while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
03163                 switch (ch) {
03164                 case '3':
03165                         set_salt = ISC_TRUE;
03166                         nsec_datatype = dns_rdatatype_nsec3;
03167                         if (strcmp(isc_commandline_argument, "-") != 0) {
03168                                 isc_buffer_t target;
03169                                 char *sarg;
03170 
03171                                 sarg = isc_commandline_argument;
03172                                 isc_buffer_init(&target, saltbuf,
03173                                                 sizeof(saltbuf));
03174                                 result = isc_hex_decodestring(sarg, &target);
03175                                 check_result(result,
03176                                              "isc_hex_decodestring(salt)");
03177                                 salt_length = isc_buffer_usedlength(&target);
03178                         }
03179                         break;
03180 
03181                 case 'A':
03182                         set_optout = ISC_TRUE;
03183                         if (OPTOUT(nsec3flags))
03184                                 nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
03185                         else
03186                                 nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
03187                         break;
03188 
03189                 case 'a':
03190                         tryverify = ISC_TRUE;
03191                         break;
03192 
03193                 case 'C':
03194                         make_keyset = ISC_TRUE;
03195                         break;
03196 
03197                 case 'c':
03198                         classname = isc_commandline_argument;
03199                         break;
03200 
03201                 case 'd':
03202                         dsdir = isc_commandline_argument;
03203                         if (strlen(dsdir) == 0U)
03204                                 fatal("DS directory must be non-empty string");
03205                         result = try_dir(dsdir);
03206                         if (result != ISC_R_SUCCESS)
03207                                 fatal("cannot open directory %s: %s",
03208                                       dsdir, isc_result_totext(result));
03209                         break;
03210 
03211                 case 'D':
03212                         output_dnssec_only = ISC_TRUE;
03213                         break;
03214 
03215                 case 'E':
03216                         engine = isc_commandline_argument;
03217                         break;
03218 
03219                 case 'e':
03220                         endstr = isc_commandline_argument;
03221                         break;
03222 
03223                 case 'f':
03224                         output = isc_commandline_argument;
03225                         if (strcmp(output, "-") == 0)
03226                                 output_stdout = ISC_TRUE;
03227                         break;
03228 
03229                 case 'g':
03230                         generateds = ISC_TRUE;
03231                         break;
03232 
03233                 case 'H':
03234                         set_iter = ISC_TRUE;
03235                         nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
03236                         if (*endp != '\0')
03237                                 fatal("iterations must be numeric");
03238                         if (nsec3iter  > 0xffffU)
03239                                 fatal("iterations too big");
03240                         break;
03241 
03242                 case 'I':
03243                         inputformatstr = isc_commandline_argument;
03244                         break;
03245 
03246                 case 'i':
03247                         endp = NULL;
03248                         cycle = strtol(isc_commandline_argument, &endp, 0);
03249                         if (*endp != '\0' || cycle < 0)
03250                                 fatal("cycle period must be numeric and "
03251                                       "positive");
03252                         break;
03253 
03254                 case 'j':
03255                         endp = NULL;
03256                         jitter = strtol(isc_commandline_argument, &endp, 0);
03257                         if (*endp != '\0' || jitter < 0)
03258                                 fatal("jitter must be numeric and positive");
03259                         break;
03260 
03261                 case 'K':
03262                         directory = isc_commandline_argument;
03263                         break;
03264 
03265                 case 'k':
03266                         if (ndskeys == MAXDSKEYS)
03267                                 fatal("too many key-signing keys specified");
03268                         dskeyfile[ndskeys++] = isc_commandline_argument;
03269                         break;
03270 
03271                 case 'L':
03272                         snset = ISC_TRUE;
03273                         endp = NULL;
03274                         serialnum = strtol(isc_commandline_argument, &endp, 0);
03275                         if (*endp != '\0') {
03276                                 fprintf(stderr, "source serial number "
03277                                                 "must be numeric");
03278                                 exit(1);
03279                         }
03280                         break;
03281 
03282                 case 'l':
03283                         len = strlen(isc_commandline_argument);
03284                         isc_buffer_init(&b, isc_commandline_argument, len);
03285                         isc_buffer_add(&b, len);
03286 
03287                         dns_fixedname_init(&dlv_fixed);
03288                         dlv = dns_fixedname_name(&dlv_fixed);
03289                         result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
03290                                                    NULL);
03291                         check_result(result, "dns_name_fromtext(dlv)");
03292                         break;
03293 
03294                 case 'M':
03295                         endp = NULL;
03296                         set_maxttl = ISC_TRUE;
03297                         maxttl = strtol(isc_commandline_argument, &endp, 0);
03298                         if (*endp != '\0') {
03299                                 fprintf(stderr, "maximum TTL "
03300                                                 "must be numeric");
03301                                 exit(1);
03302                         }
03303                         break;
03304 
03305                 case 'm':
03306                         break;
03307 
03308                 case 'N':
03309                         serialformatstr = isc_commandline_argument;
03310                         break;
03311 
03312                 case 'n':
03313                         endp = NULL;
03314                         ntasks = strtol(isc_commandline_argument, &endp, 0);
03315                         if (*endp != '\0' || ntasks > ISC_INT32_MAX)
03316                                 fatal("number of cpus must be numeric");
03317                         break;
03318 
03319                 case 'O':
03320                         outputformatstr = isc_commandline_argument;
03321                         break;
03322 
03323                 case 'o':
03324                         origin = isc_commandline_argument;
03325                         break;
03326 
03327                 case 'P':
03328                         disable_zone_check = ISC_TRUE;
03329                         break;
03330 
03331                 case 'p':
03332                         pseudorandom = ISC_TRUE;
03333                         break;
03334 
03335                 case 'Q':
03336                         remove_inactkeysigs = ISC_TRUE;
03337                         break;
03338 
03339                 case 'R':
03340                         remove_orphansigs = ISC_TRUE;
03341                         break;
03342 
03343                 case 'r':
03344                         setup_entropy(mctx, isc_commandline_argument, &ectx);
03345                         break;
03346 
03347                 case 'S':
03348                         smartsign = ISC_TRUE;
03349                         break;
03350 
03351                 case 's':
03352                         startstr = isc_commandline_argument;
03353                         break;
03354 
03355                 case 'T':
03356                         endp = NULL;
03357                         set_keyttl = ISC_TRUE;
03358                         keyttl = strtottl(isc_commandline_argument);
03359                         break;
03360 
03361                 case 't':
03362                         printstats = ISC_TRUE;
03363                         break;
03364 
03365                 case 'U':       /* Undocumented for testing only. */
03366                         unknownalg = ISC_TRUE;
03367                         break;
03368 
03369                 case 'u':
03370                         update_chain = ISC_TRUE;
03371                         break;
03372 
03373                 case 'v':
03374                         endp = NULL;
03375                         verbose = strtol(isc_commandline_argument, &endp, 0);
03376                         if (*endp != '\0')
03377                                 fatal("verbose level must be numeric");
03378                         break;
03379 
03380                 case 'X':
03381                         dnskey_endstr = isc_commandline_argument;
03382                         break;
03383 
03384                 case 'x':
03385                         keyset_kskonly = ISC_TRUE;
03386                         break;
03387 
03388                 case 'z':
03389                         ignore_kskflag = ISC_TRUE;
03390                         break;
03391 
03392                 case 'F':
03393                         /* Reserved for FIPS mode */
03394                         /* FALLTHROUGH */
03395                 case '?':
03396                         if (isc_commandline_option != '?')
03397                                 fprintf(stderr, "%s: invalid argument -%c\n",
03398                                         program, isc_commandline_option);
03399                         /* FALLTHROUGH */
03400                 case 'h':
03401                         /* Does not return. */
03402                         usage();
03403 
03404                 case 'V':
03405                         /* Does not return. */
03406                         version(program);
03407 
03408                 case 'Z':       /* Undocumented test options */
03409                         if (!strcmp(isc_commandline_argument, "nonsecify"))
03410                                 nonsecify = ISC_TRUE;
03411                         break;
03412 
03413                 default:
03414                         fprintf(stderr, "%s: unhandled option -%c\n",
03415                                 program, isc_commandline_option);
03416                         exit(1);
03417                 }
03418         }
03419 
03420         if (ectx == NULL)
03421                 setup_entropy(mctx, NULL, &ectx);
03422         eflags = ISC_ENTROPY_BLOCKING;
03423         if (!pseudorandom)
03424                 eflags |= ISC_ENTROPY_GOODONLY;
03425 
03426         result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
03427         if (result != ISC_R_SUCCESS)
03428                 fatal("could not create hash context");
03429 
03430         result = dst_lib_init2(mctx, ectx, engine, eflags);
03431         if (result != ISC_R_SUCCESS)
03432                 fatal("could not initialize dst: %s",
03433                       isc_result_totext(result));
03434         isc_stdtime_get(&now);
03435 
03436         if (startstr != NULL) {
03437                 starttime = strtotime(startstr, now, now, NULL);
03438         } else
03439                 starttime = now - 3600;  /* Allow for some clock skew. */
03440 
03441         if (endstr != NULL)
03442                 endtime = strtotime(endstr, now, starttime, NULL);
03443         else
03444                 endtime = starttime + (30 * 24 * 60 * 60);
03445 
03446         if (dnskey_endstr != NULL) {
03447                 dnskey_endtime = strtotime(dnskey_endstr, now, starttime,
03448                                            NULL);
03449                 if (endstr != NULL && dnskey_endtime == endtime)
03450                         fprintf(stderr, "WARNING: -e and -X were both set, "
03451                                         "but have identical values.\n");
03452         } else
03453                 dnskey_endtime = endtime;
03454 
03455         if (cycle == -1)
03456                 cycle = (endtime - starttime) / 4;
03457 
03458         if (ntasks == 0)
03459                 ntasks = isc_os_ncpus() * 2;
03460         vbprintf(4, "using %d cpus\n", ntasks);
03461 
03462         rdclass = strtoclass(classname);
03463 
03464         if (directory == NULL)
03465                 directory = ".";
03466 
03467         setup_logging(mctx, &log);
03468 
03469         argc -= isc_commandline_index;
03470         argv += isc_commandline_index;
03471 
03472         if (argc < 1)
03473                 usage();
03474 
03475         file = argv[0];
03476 
03477         argc -= 1;
03478         argv += 1;
03479 
03480         if (origin == NULL)
03481                 origin = file;
03482 
03483         if (output == NULL) {
03484                 free_output = ISC_TRUE;
03485                 output = isc_mem_allocate(mctx,
03486                                           strlen(file) + strlen(".signed") + 1);
03487                 if (output == NULL)
03488                         fatal("out of memory");
03489                 sprintf(output, "%s.signed", file);
03490         }
03491 
03492         if (inputformatstr != NULL) {
03493                 if (strcasecmp(inputformatstr, "text") == 0)
03494                         inputformat = dns_masterformat_text;
03495                 else if (strcasecmp(inputformatstr, "map") == 0)
03496                         inputformat = dns_masterformat_map;
03497                 else if (strcasecmp(inputformatstr, "raw") == 0)
03498                         inputformat = dns_masterformat_raw;
03499                 else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
03500                         inputformat = dns_masterformat_raw;
03501                         fprintf(stderr,
03502                                 "WARNING: input format version ignored\n");
03503                 } else
03504                         fatal("unknown file format: %s", inputformatstr);
03505 
03506         }
03507 
03508         if (outputformatstr != NULL) {
03509                 if (strcasecmp(outputformatstr, "text") == 0) {
03510                         outputformat = dns_masterformat_text;
03511                 } else if (strcasecmp(outputformatstr, "full") == 0) {
03512                         outputformat = dns_masterformat_text;
03513                         masterstyle = &dns_master_style_full;
03514                 } else if (strcasecmp(outputformatstr, "map") == 0) {
03515                         outputformat = dns_masterformat_map;
03516                 } else if (strcasecmp(outputformatstr, "raw") == 0) {
03517                         outputformat = dns_masterformat_raw;
03518                 } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
03519                         char *end;
03520                         outputformat = dns_masterformat_raw;
03521 
03522                         outputformat = dns_masterformat_raw;
03523                         rawversion = strtol(outputformatstr + 4, &end, 10);
03524                         if (end == outputformatstr + 4 || *end != '\0' ||
03525                             rawversion > 1U) {
03526                                 fprintf(stderr,
03527                                         "unknown raw format version\n");
03528                                 exit(1);
03529                         }
03530                 } else
03531                         fatal("unknown file format: %s", outputformatstr);
03532         }
03533 
03534         if (serialformatstr != NULL) {
03535                 if (strcasecmp(serialformatstr, "keep") == 0)
03536                         serialformat = SOA_SERIAL_KEEP;
03537                 else if (strcasecmp(serialformatstr, "increment") == 0 ||
03538                          strcasecmp(serialformatstr, "incr") == 0)
03539                         serialformat = SOA_SERIAL_INCREMENT;
03540                 else if (strcasecmp(serialformatstr, "unixtime") == 0)
03541                         serialformat = SOA_SERIAL_UNIXTIME;
03542                 else if (strcasecmp(serialformatstr, "date") == 0)
03543                         serialformat = SOA_SERIAL_DATE;
03544                 else
03545                         fatal("unknown soa serial format: %s",
03546                               serialformatstr);
03547         }
03548 
03549         if (output_dnssec_only && outputformat != dns_masterformat_text)
03550                 fatal("option -D can only be used with \"-O text\"");
03551 
03552         if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP)
03553                 fatal("option -D can only be used with \"-N keep\"");
03554 
03555         if (output_dnssec_only && set_maxttl)
03556                 fatal("option -D cannot be used with -M");
03557 
03558         result = dns_master_stylecreate(&dsstyle,  DNS_STYLEFLAG_NO_TTL,
03559                                         0, 24, 0, 0, 0, 8, mctx);
03560         check_result(result, "dns_master_stylecreate");
03561 
03562         gdb = NULL;
03563         TIME_NOW(&timer_start);
03564         loadzone(file, origin, rdclass, &gdb);
03565         gorigin = dns_db_origin(gdb);
03566         gclass = dns_db_class(gdb);
03567         get_soa_ttls();
03568 
03569         if (set_maxttl && set_keyttl && keyttl > maxttl) {
03570                 fprintf(stderr, "%s: warning: Specified key TTL %d "
03571                         "exceeds maximum zone TTL; reducing to %d\n",
03572                         program, keyttl, maxttl);
03573                 keyttl = maxttl;
03574         }
03575 
03576         if (!set_keyttl)
03577                 keyttl = soa_ttl;
03578 
03579         /*
03580          * Check for any existing NSEC3 parameters in the zone,
03581          * and use them as defaults if -u was not specified.
03582          */
03583         if (update_chain && !set_optout && !set_iter && !set_salt)
03584                 nsec_datatype = dns_rdatatype_nsec;
03585         else
03586                 set_nsec3params(update_chain, set_salt, set_optout, set_iter);
03587 
03588         /*
03589          * We need to do this early on, as we start messing with the list
03590          * of keys rather early.
03591          */
03592         ISC_LIST_INIT(keylist);
03593         isc_rwlock_init(&keylist_lock, 0, 0);
03594 
03595         /*
03596          * Fill keylist with:
03597          * 1) Keys listed in the DNSKEY set that have
03598          *    private keys associated, *if* no keys were
03599          *    set on the command line.
03600          * 2) ZSKs set on the command line
03601          * 3) KSKs set on the command line
03602          * 4) Any keys remaining in the DNSKEY set which
03603          *    do not have private keys associated and were
03604          *    not specified on the command line.
03605          */
03606         if (argc == 0 || smartsign)
03607                 loadzonekeys(!smartsign, ISC_FALSE);
03608         loadexplicitkeys(argv, argc, ISC_FALSE);
03609         loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE);
03610         loadzonekeys(!smartsign, ISC_TRUE);
03611 
03612         /*
03613          * If we're doing smart signing, look in the key repository for
03614          * key files with metadata, and merge them with the keylist
03615          * we have now.
03616          */
03617         if (smartsign)
03618                 build_final_keylist();
03619 
03620         /* Now enumerate the key list */
03621         for (key = ISC_LIST_HEAD(keylist);
03622              key != NULL;
03623              key = ISC_LIST_NEXT(key, link)) {
03624                 key->index = keycount++;
03625         }
03626 
03627         if (keycount == 0) {
03628                 if (disable_zone_check)
03629                         fprintf(stderr, "%s: warning: No keys specified "
03630                                         "or found\n", program);
03631                 else
03632                         fatal("No signing keys specified or found.");
03633                 nokeys = ISC_TRUE;
03634         }
03635 
03636         warnifallksk(gdb);
03637 
03638         if (IS_NSEC3) {
03639                 unsigned int max;
03640                 isc_boolean_t answer;
03641 
03642                 hash_length = dns_nsec3_hashlength(dns_hash_sha1);
03643                 hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
03644                               hash_length);
03645                 result = dns_nsec_nseconly(gdb, gversion, &answer);
03646                 if (result == ISC_R_NOTFOUND)
03647                         fprintf(stderr, "%s: warning: NSEC3 generation "
03648                                 "requested with no DNSKEY; ignoring\n",
03649                                 program);
03650                 else if (result != ISC_R_SUCCESS)
03651                         check_result(result, "dns_nsec_nseconly");
03652                 else if (answer)
03653                         fatal("NSEC3 generation requested with "
03654                               "NSEC-only DNSKEY");
03655 
03656                 result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
03657                 check_result(result, "dns_nsec3_maxiterations()");
03658                 if (nsec3iter > max)
03659                         fatal("NSEC3 iterations too big for weakest DNSKEY "
03660                               "strength. Maximum iterations allowed %u.", max);
03661         }
03662 
03663         gversion = NULL;
03664         result = dns_db_newversion(gdb, &gversion);
03665         check_result(result, "dns_db_newversion()");
03666 
03667         switch (serialformat) {
03668                 case SOA_SERIAL_INCREMENT:
03669                         setsoaserial(0, dns_updatemethod_increment);
03670                         break;
03671                 case SOA_SERIAL_UNIXTIME:
03672                         setsoaserial(now, dns_updatemethod_unixtime);
03673                         break;
03674                 case SOA_SERIAL_DATE:
03675                         setsoaserial(now, dns_updatemethod_date);
03676                         break;
03677                 case SOA_SERIAL_KEEP:
03678                 default:
03679                         /* do nothing */
03680                         break;
03681         }
03682 
03683         /* Remove duplicates and cap TTLs at maxttl */
03684         cleanup_zone();
03685 
03686         if (!nonsecify) {
03687                 if (IS_NSEC3)
03688                         nsec3ify(dns_hash_sha1, nsec3iter, gsalt, salt_length,
03689                                  &hashlist);
03690                 else
03691                         nsecify();
03692         }
03693 
03694         if (!nokeys) {
03695                 writeset("dsset-", dns_rdatatype_ds);
03696                 if (make_keyset)
03697                         writeset("keyset-", dns_rdatatype_dnskey);
03698                 if (dlv != NULL) {
03699                         writeset("dlvset-", dns_rdatatype_dlv);
03700                 }
03701         }
03702 
03703         if (output_stdout) {
03704                 outfp = stdout;
03705                 if (outputformatstr == NULL)
03706                         masterstyle = &dns_master_style_full;
03707         } else {
03708                 tempfilelen = strlen(output) + 20;
03709                 tempfile = isc_mem_get(mctx, tempfilelen);
03710                 if (tempfile == NULL)
03711                         fatal("out of memory");
03712 
03713                 result = isc_file_mktemplate(output, tempfile, tempfilelen);
03714                 check_result(result, "isc_file_mktemplate");
03715 
03716                 if (outputformat == dns_masterformat_text)
03717                         result = isc_file_openunique(tempfile, &outfp);
03718                 else
03719                         result = isc_file_bopenunique(tempfile, &outfp);
03720                 if (result != ISC_R_SUCCESS)
03721                         fatal("failed to open temporary output file: %s",
03722                               isc_result_totext(result));
03723                 removefile = ISC_TRUE;
03724                 setfatalcallback(&removetempfile);
03725         }
03726 
03727         print_time(outfp);
03728         print_version(outfp);
03729 
03730         result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
03731         if (result != ISC_R_SUCCESS)
03732                 fatal("failed to create task manager: %s",
03733                       isc_result_totext(result));
03734 
03735         master = NULL;
03736         result = isc_task_create(taskmgr, 0, &master);
03737         if (result != ISC_R_SUCCESS)
03738                 fatal("failed to create task: %s", isc_result_totext(result));
03739 
03740         tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
03741         if (tasks == NULL)
03742                 fatal("out of memory");
03743         for (i = 0; i < (int)ntasks; i++) {
03744                 tasks[i] = NULL;
03745                 result = isc_task_create(taskmgr, 0, &tasks[i]);
03746                 if (result != ISC_R_SUCCESS)
03747                         fatal("failed to create task: %s",
03748                               isc_result_totext(result));
03749         }
03750 
03751         RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
03752         if (printstats)
03753                 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
03754 
03755         presign();
03756         TIME_NOW(&sign_start);
03757         signapex();
03758         if (!finished) {
03759                 /*
03760                  * There is more work to do.  Spread it out over multiple
03761                  * processors if possible.
03762                  */
03763                 for (i = 0; i < (int)ntasks; i++) {
03764                         result = isc_app_onrun(mctx, master, startworker,
03765                                                tasks[i]);
03766                         if (result != ISC_R_SUCCESS)
03767                                 fatal("failed to start task: %s",
03768                                       isc_result_totext(result));
03769                 }
03770                 (void)isc_app_run();
03771                 if (!finished)
03772                         fatal("process aborted by user");
03773         } else
03774                 isc_task_detach(&master);
03775         shuttingdown = ISC_TRUE;
03776         for (i = 0; i < (int)ntasks; i++)
03777                 isc_task_detach(&tasks[i]);
03778         isc_taskmgr_destroy(&taskmgr);
03779         isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
03780         postsign();
03781         TIME_NOW(&sign_finish);
03782 
03783         if (!disable_zone_check)
03784                 verifyzone(gdb, gversion, gorigin, mctx,
03785                            ignore_kskflag, keyset_kskonly);
03786 
03787         if (outputformat != dns_masterformat_text) {
03788                 dns_masterrawheader_t header;
03789                 dns_master_initrawheader(&header);
03790                 if (rawversion == 0U)
03791                         header.flags = DNS_MASTERRAW_COMPAT;
03792                 else if (snset) {
03793                         header.flags = DNS_MASTERRAW_SOURCESERIALSET;
03794                         header.sourceserial = serialnum;
03795                 }
03796                 result = dns_master_dumptostream3(mctx, gdb, gversion,
03797                                                   masterstyle, outputformat,
03798                                                   &header, outfp);
03799                 check_result(result, "dns_master_dumptostream3");
03800         }
03801 
03802         DESTROYLOCK(&namelock);
03803         if (printstats)
03804                 DESTROYLOCK(&statslock);
03805 
03806         if (!output_stdout) {
03807                 result = isc_stdio_close(outfp);
03808                 check_result(result, "isc_stdio_close");
03809                 removefile = ISC_FALSE;
03810 
03811                 result = isc_file_rename(tempfile, output);
03812                 if (result != ISC_R_SUCCESS)
03813                         fatal("failed to rename temp file to %s: %s",
03814                               output, isc_result_totext(result));
03815 
03816                 printf("%s\n", output);
03817         }
03818 
03819         dns_db_closeversion(gdb, &gversion, ISC_FALSE);
03820         dns_db_detach(&gdb);
03821 
03822         while (!ISC_LIST_EMPTY(keylist)) {
03823                 key = ISC_LIST_HEAD(keylist);
03824                 ISC_LIST_UNLINK(keylist, key, link);
03825                 dns_dnsseckey_destroy(mctx, &key);
03826         }
03827 
03828         if (tempfilelen != 0)
03829                 isc_mem_put(mctx, tempfile, tempfilelen);
03830 
03831         if (free_output)
03832                 isc_mem_free(mctx, output);
03833 
03834         dns_master_styledestroy(&dsstyle, mctx);
03835 
03836         cleanup_logging(&log);
03837         dst_lib_destroy();
03838         isc_hash_destroy();
03839         cleanup_entropy(&ectx);
03840         dns_name_destroy();
03841         if (verbose > 10)
03842                 isc_mem_stats(mctx, stdout);
03843         isc_mem_destroy(&mctx);
03844 
03845         (void) isc_app_finish();
03846 
03847         if (printstats) {
03848                 TIME_NOW(&timer_finish);
03849                 print_stats(&timer_start, &timer_finish,
03850                             &sign_start, &sign_finish);
03851         }
03852 
03853         return (0);
03854 }

Generated on Tue Apr 28 17:40:53 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha