aboutsummaryrefslogtreecommitdiff
path: root/contrib/bind9/bin/dnssec/dnssec-signzone.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/bin/dnssec/dnssec-signzone.c')
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-signzone.c3746
1 files changed, 0 insertions, 3746 deletions
diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.c b/contrib/bind9/bin/dnssec/dnssec-signzone.c
deleted file mode 100644
index 83456a7db7d7..000000000000
--- a/contrib/bind9/bin/dnssec/dnssec-signzone.c
+++ /dev/null
@@ -1,3746 +0,0 @@
-/*
- * Portions Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
- * Portions Copyright (C) 1999-2003 Internet Software Consortium.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
- * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
- * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
- * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
- * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* $Id: dnssec-signzone.c,v 1.285 2011/12/22 07:32:39 each Exp $ */
-
-/*! \file */
-
-#include <config.h>
-
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <isc/app.h>
-#include <isc/base32.h>
-#include <isc/commandline.h>
-#include <isc/entropy.h>
-#include <isc/event.h>
-#include <isc/file.h>
-#include <isc/hash.h>
-#include <isc/hex.h>
-#include <isc/mem.h>
-#include <isc/mutex.h>
-#include <isc/os.h>
-#include <isc/print.h>
-#include <isc/random.h>
-#include <isc/rwlock.h>
-#include <isc/serial.h>
-#include <isc/stdio.h>
-#include <isc/stdlib.h>
-#include <isc/string.h>
-#include <isc/task.h>
-#include <isc/time.h>
-#include <isc/util.h>
-
-#include <dns/db.h>
-#include <dns/dbiterator.h>
-#include <dns/diff.h>
-#include <dns/dnssec.h>
-#include <dns/ds.h>
-#include <dns/fixedname.h>
-#include <dns/keyvalues.h>
-#include <dns/log.h>
-#include <dns/master.h>
-#include <dns/masterdump.h>
-#include <dns/nsec.h>
-#include <dns/nsec3.h>
-#include <dns/rdata.h>
-#include <dns/rdatalist.h>
-#include <dns/rdataset.h>
-#include <dns/rdataclass.h>
-#include <dns/rdatasetiter.h>
-#include <dns/rdatastruct.h>
-#include <dns/rdatatype.h>
-#include <dns/result.h>
-#include <dns/soa.h>
-#include <dns/time.h>
-
-#include <dst/dst.h>
-
-#include "dnssectool.h"
-
-#ifndef PATH_MAX
-#define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */
-#endif
-
-const char *program = "dnssec-signzone";
-int verbose;
-
-typedef struct hashlist hashlist_t;
-
-static int nsec_datatype = dns_rdatatype_nsec;
-
-#define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
-#define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
-
-#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
-
-#define BUFSIZE 2048
-#define MAXDSKEYS 8
-
-#define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
-#define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
-#define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
-
-#define SOA_SERIAL_KEEP 0
-#define SOA_SERIAL_INCREMENT 1
-#define SOA_SERIAL_UNIXTIME 2
-
-typedef struct signer_event sevent_t;
-struct signer_event {
- ISC_EVENT_COMMON(sevent_t);
- dns_fixedname_t *fname;
- dns_dbnode_t *node;
-};
-
-static dns_dnsseckeylist_t keylist;
-static unsigned int keycount = 0;
-isc_rwlock_t keylist_lock;
-static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now;
-static int cycle = -1;
-static int jitter = 0;
-static isc_boolean_t tryverify = ISC_FALSE;
-static isc_boolean_t printstats = ISC_FALSE;
-static isc_mem_t *mctx = NULL;
-static isc_entropy_t *ectx = NULL;
-static dns_ttl_t zone_soa_min_ttl;
-static dns_ttl_t soa_ttl;
-static FILE *fp = NULL;
-static char *tempfile = NULL;
-static const dns_master_style_t *masterstyle;
-static dns_masterformat_t inputformat = dns_masterformat_text;
-static dns_masterformat_t outputformat = dns_masterformat_text;
-static isc_uint32_t rawversion = 1, serialnum = 0;
-static isc_boolean_t snset = ISC_FALSE;
-static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
-static unsigned int nverified = 0, nverifyfailed = 0;
-static const char *directory = NULL, *dsdir = NULL;
-static isc_mutex_t namelock, statslock;
-static isc_taskmgr_t *taskmgr = NULL;
-static dns_db_t *gdb; /* The database */
-static dns_dbversion_t *gversion; /* The database version */
-static dns_dbiterator_t *gdbiter; /* The database iterator */
-static dns_rdataclass_t gclass; /* The class */
-static dns_name_t *gorigin; /* The database origin */
-static int nsec3flags = 0;
-static dns_iterations_t nsec3iter = 10U;
-static unsigned char saltbuf[255];
-static unsigned char *salt = saltbuf;
-static size_t salt_length = 0;
-static isc_task_t *master = NULL;
-static unsigned int ntasks = 0;
-static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
-static isc_boolean_t nokeys = ISC_FALSE;
-static isc_boolean_t removefile = ISC_FALSE;
-static isc_boolean_t generateds = ISC_FALSE;
-static isc_boolean_t ignore_kskflag = ISC_FALSE;
-static isc_boolean_t keyset_kskonly = ISC_FALSE;
-static dns_name_t *dlv = NULL;
-static dns_fixedname_t dlv_fixed;
-static dns_master_style_t *dsstyle = NULL;
-static unsigned int serialformat = SOA_SERIAL_KEEP;
-static unsigned int hash_length = 0;
-static isc_boolean_t unknownalg = ISC_FALSE;
-static isc_boolean_t disable_zone_check = ISC_FALSE;
-static isc_boolean_t update_chain = ISC_FALSE;
-static isc_boolean_t set_keyttl = ISC_FALSE;
-static dns_ttl_t keyttl;
-static isc_boolean_t smartsign = ISC_FALSE;
-static isc_boolean_t remove_orphans = ISC_FALSE;
-static isc_boolean_t output_dnssec_only = ISC_FALSE;
-static isc_boolean_t output_stdout = ISC_FALSE;
-
-#define INCSTAT(counter) \
- if (printstats) { \
- LOCK(&statslock); \
- counter++; \
- UNLOCK(&statslock); \
- }
-
-static void
-sign(isc_task_t *task, isc_event_t *event);
-
-static void
-dumpnode(dns_name_t *name, dns_dbnode_t *node) {
- dns_rdataset_t rds;
- dns_rdatasetiter_t *iter = NULL;
- isc_buffer_t *buffer = NULL;
- isc_region_t r;
- isc_result_t result;
- unsigned bufsize = 4096;
-
- if (outputformat != dns_masterformat_text)
- return;
-
- if (!output_dnssec_only) {
- result = dns_master_dumpnodetostream(mctx, gdb, gversion, node,
- name, masterstyle, fp);
- check_result(result, "dns_master_dumpnodetostream");
- return;
- }
-
- result = dns_db_allrdatasets(gdb, node, gversion, 0, &iter);
- check_result(result, "dns_db_allrdatasets");
-
- dns_rdataset_init(&rds);
-
- result = isc_buffer_allocate(mctx, &buffer, bufsize);
- check_result(result, "isc_buffer_allocate");
-
- for (result = dns_rdatasetiter_first(iter);
- result == ISC_R_SUCCESS;
- result = dns_rdatasetiter_next(iter)) {
-
- dns_rdatasetiter_current(iter, &rds);
-
- if (rds.type != dns_rdatatype_rrsig &&
- rds.type != dns_rdatatype_nsec &&
- rds.type != dns_rdatatype_nsec3 &&
- rds.type != dns_rdatatype_nsec3param &&
- (!smartsign || rds.type != dns_rdatatype_dnskey)) {
- dns_rdataset_disassociate(&rds);
- continue;
- }
-
- for (;;) {
- result = dns_master_rdatasettotext(name, &rds,
- masterstyle, buffer);
- if (result != ISC_R_NOSPACE)
- break;
-
- bufsize <<= 1;
- isc_buffer_free(&buffer);
- result = isc_buffer_allocate(mctx, &buffer, bufsize);
- check_result(result, "isc_buffer_allocate");
- }
- check_result(result, "dns_master_rdatasettotext");
-
- isc_buffer_usedregion(buffer, &r);
- result = isc_stdio_write(r.base, 1, r.length, fp, NULL);
- check_result(result, "isc_stdio_write");
- isc_buffer_clear(buffer);
-
- dns_rdataset_disassociate(&rds);
- }
-
- isc_buffer_free(&buffer);
- dns_rdatasetiter_destroy(&iter);
-}
-
-/*%
- * Sign the given RRset with given key, and add the signature record to the
- * given tuple.
- */
-static void
-signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
- dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
-{
- isc_result_t result;
- isc_stdtime_t jendtime, expiry;
- char keystr[DST_KEY_FORMATSIZE];
- dns_rdata_t trdata = DNS_RDATA_INIT;
- unsigned char array[BUFSIZE];
- isc_buffer_t b;
- dns_difftuple_t *tuple;
-
- dst_key_format(key, keystr, sizeof(keystr));
- vbprintf(1, "\t%s %s\n", logmsg, keystr);
-
- if (rdataset->type == dns_rdatatype_dnskey)
- expiry = dnskey_endtime;
- else
- expiry = endtime;
-
- jendtime = (jitter != 0) ? isc_random_jitter(expiry, jitter) : expiry;
- isc_buffer_init(&b, array, sizeof(array));
- result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
- mctx, &b, &trdata);
- isc_entropy_stopcallbacksources(ectx);
- if (result != ISC_R_SUCCESS) {
- char keystr[DST_KEY_FORMATSIZE];
- dst_key_format(key, keystr, sizeof(keystr));
- fatal("dnskey '%s' failed to sign data: %s",
- keystr, isc_result_totext(result));
- }
- INCSTAT(nsigned);
-
- if (tryverify) {
- result = dns_dnssec_verify(name, rdataset, key,
- ISC_TRUE, mctx, &trdata);
- if (result == ISC_R_SUCCESS) {
- vbprintf(3, "\tsignature verified\n");
- INCSTAT(nverified);
- } else {
- vbprintf(3, "\tsignature failed to verify\n");
- INCSTAT(nverifyfailed);
- }
- }
-
- tuple = NULL;
- result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name, ttl, &trdata,
- &tuple);
- check_result(result, "dns_difftuple_create");
- dns_diff_append(add, &tuple);
-}
-
-static inline isc_boolean_t
-issigningkey(dns_dnsseckey_t *key) {
- return (key->force_sign || key->hint_sign);
-}
-
-static inline isc_boolean_t
-ispublishedkey(dns_dnsseckey_t *key) {
- return ((key->force_publish || key->hint_publish) &&
- !key->hint_remove);
-}
-
-static inline isc_boolean_t
-iszonekey(dns_dnsseckey_t *key) {
- return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
- dst_key_iszonekey(key->key)));
-}
-
-static inline isc_boolean_t
-isksk(dns_dnsseckey_t *key) {
- return (key->ksk);
-}
-
-static inline isc_boolean_t
-iszsk(dns_dnsseckey_t *key) {
- return (ignore_kskflag || !key->ksk);
-}
-
-/*%
- * Find the key that generated an RRSIG, if it is in the key list. If
- * so, return a pointer to it, otherwise return NULL.
- *
- * No locking is performed here, this must be done by the caller.
- */
-static dns_dnsseckey_t *
-keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
- dns_dnsseckey_t *key;
-
- for (key = ISC_LIST_HEAD(keylist);
- key != NULL;
- key = ISC_LIST_NEXT(key, link)) {
- if (rrsig->keyid == dst_key_id(key->key) &&
- rrsig->algorithm == dst_key_alg(key->key) &&
- dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
- return (key);
- }
- return (NULL);
-}
-
-/*%
- * Finds the key that generated a RRSIG, if possible. First look at the keys
- * that we've loaded already, and then see if there's a key on disk.
- */
-static dns_dnsseckey_t *
-keythatsigned(dns_rdata_rrsig_t *rrsig) {
- isc_result_t result;
- dst_key_t *pubkey = NULL, *privkey = NULL;
- dns_dnsseckey_t *key = NULL;
-
- isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
- key = keythatsigned_unlocked(rrsig);
- isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
- if (key != NULL)
- return (key);
-
- /*
- * We did not find the key in our list. Get a write lock now, since
- * we may be modifying the bits. We could do the tryupgrade() dance,
- * but instead just get a write lock and check once again to see if
- * it is on our list. It's possible someone else may have added it
- * after all.
- */
- isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
- key = keythatsigned_unlocked(rrsig);
- if (key != NULL) {
- isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
- return (key);
- }
-
- result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
- rrsig->algorithm, DST_TYPE_PUBLIC,
- directory, mctx, &pubkey);
- if (result != ISC_R_SUCCESS) {
- isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
- return (NULL);
- }
-
- result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
- rrsig->algorithm,
- DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
- directory, mctx, &privkey);
- if (result == ISC_R_SUCCESS) {
- dst_key_free(&pubkey);
- result = dns_dnsseckey_create(mctx, &privkey, &key);
- } else
- result = dns_dnsseckey_create(mctx, &pubkey, &key);
-
- if (result == ISC_R_SUCCESS) {
- key->force_publish = ISC_FALSE;
- key->force_sign = ISC_FALSE;
- key->index = keycount++;
- ISC_LIST_APPEND(keylist, key, link);
- }
-
- isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
- return (key);
-}
-
-/*%
- * Check to see if we expect to find a key at this name. If we see a RRSIG
- * and can't find the signing key that we expect to find, we drop the rrsig.
- * I'm not sure if this is completely correct, but it seems to work.
- */
-static isc_boolean_t
-expecttofindkey(dns_name_t *name) {
- unsigned int options = DNS_DBFIND_NOWILD;
- dns_fixedname_t fname;
- isc_result_t result;
- char namestr[DNS_NAME_FORMATSIZE];
-
- dns_fixedname_init(&fname);
- result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
- 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
- switch (result) {
- case ISC_R_SUCCESS:
- case DNS_R_NXDOMAIN:
- case DNS_R_NXRRSET:
- return (ISC_TRUE);
- case DNS_R_DELEGATION:
- case DNS_R_CNAME:
- case DNS_R_DNAME:
- return (ISC_FALSE);
- }
- dns_name_format(name, namestr, sizeof(namestr));
- fatal("failure looking for '%s DNSKEY' in database: %s",
- namestr, isc_result_totext(result));
- /* NOTREACHED */
- return (ISC_FALSE); /* removes a warning */
-}
-
-static inline isc_boolean_t
-setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
- dns_rdata_t *rrsig)
-{
- isc_result_t result;
- result = dns_dnssec_verify(name, set, key, ISC_FALSE, mctx, rrsig);
- if (result == ISC_R_SUCCESS) {
- INCSTAT(nverified);
- return (ISC_TRUE);
- } else {
- INCSTAT(nverifyfailed);
- return (ISC_FALSE);
- }
-}
-
-/*%
- * Signs a set. Goes through contortions to decide if each RRSIG should
- * be dropped or retained, and then determines if any new SIGs need to
- * be generated.
- */
-static void
-signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
- dns_rdataset_t *set)
-{
- dns_rdataset_t sigset;
- dns_rdata_t sigrdata = DNS_RDATA_INIT;
- dns_rdata_rrsig_t rrsig;
- dns_dnsseckey_t *key;
- isc_result_t result;
- isc_boolean_t nosigs = ISC_FALSE;
- isc_boolean_t *wassignedby, *nowsignedby;
- int arraysize;
- dns_difftuple_t *tuple;
- dns_ttl_t ttl;
- int i;
- char namestr[DNS_NAME_FORMATSIZE];
- char typestr[TYPE_FORMATSIZE];
- char sigstr[SIG_FORMATSIZE];
-
- dns_name_format(name, namestr, sizeof(namestr));
- type_format(set->type, typestr, sizeof(typestr));
-
- ttl = ISC_MIN(set->ttl, endtime - starttime);
-
- dns_rdataset_init(&sigset);
- result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
- set->type, 0, &sigset, NULL);
- if (result == ISC_R_NOTFOUND) {
- result = ISC_R_SUCCESS;
- nosigs = ISC_TRUE;
- }
- if (result != ISC_R_SUCCESS)
- fatal("failed while looking for '%s RRSIG %s': %s",
- namestr, typestr, isc_result_totext(result));
-
- vbprintf(1, "%s/%s:\n", namestr, typestr);
-
- arraysize = keycount;
- if (!nosigs)
- arraysize += dns_rdataset_count(&sigset);
- wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
- nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
- if (wassignedby == NULL || nowsignedby == NULL)
- fatal("out of memory");
-
- for (i = 0; i < arraysize; i++)
- wassignedby[i] = nowsignedby[i] = ISC_FALSE;
-
- if (nosigs)
- result = ISC_R_NOMORE;
- else
- result = dns_rdataset_first(&sigset);
-
- while (result == ISC_R_SUCCESS) {
- isc_boolean_t expired, future;
- isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
-
- dns_rdataset_current(&sigset, &sigrdata);
-
- result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
- check_result(result, "dns_rdata_tostruct");
-
- future = isc_serial_lt(now, rrsig.timesigned);
-
- key = keythatsigned(&rrsig);
- sig_format(&rrsig, sigstr, sizeof(sigstr));
- if (key != NULL && issigningkey(key))
- expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
- else
- expired = isc_serial_gt(now, rrsig.timeexpire);
-
- if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
- /* rrsig is dropped and not replaced */
- vbprintf(2, "\trrsig by %s dropped - "
- "invalid validity period\n",
- sigstr);
- } else if (key == NULL && !future &&
- expecttofindkey(&rrsig.signer)) {
- /* rrsig is dropped and not replaced */
- vbprintf(2, "\trrsig by %s dropped - "
- "private dnskey not found\n",
- sigstr);
- } else if (key == NULL || future) {
- keep = (!expired && !remove_orphans);
- vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
- keep ? "retained" : "dropped", sigstr);
- } else if (issigningkey(key)) {
- wassignedby[key->index] = ISC_TRUE;
-
- if (!expired && rrsig.originalttl == set->ttl &&
- setverifies(name, set, key->key, &sigrdata)) {
- vbprintf(2, "\trrsig by %s retained\n", sigstr);
- keep = ISC_TRUE;
- } else {
- vbprintf(2, "\trrsig by %s dropped - %s\n",
- sigstr, expired ? "expired" :
- rrsig.originalttl != set->ttl ?
- "ttl change" : "failed to verify");
- resign = ISC_TRUE;
- }
- } else if (!ispublishedkey(key) && remove_orphans) {
- vbprintf(2, "\trrsig by %s dropped - dnskey removed\n",
- sigstr);
- } else if (iszonekey(key)) {
- wassignedby[key->index] = ISC_TRUE;
-
- if (!expired && rrsig.originalttl == set->ttl &&
- setverifies(name, set, key->key, &sigrdata)) {
- vbprintf(2, "\trrsig by %s retained\n", sigstr);
- keep = ISC_TRUE;
- } else {
- vbprintf(2, "\trrsig by %s dropped - %s\n",
- sigstr, expired ? "expired" :
- rrsig.originalttl != set->ttl ?
- "ttl change" : "failed to verify");
- }
- } else if (!expired) {
- vbprintf(2, "\trrsig by %s retained\n", sigstr);
- keep = ISC_TRUE;
- } else {
- vbprintf(2, "\trrsig by %s expired\n", sigstr);
- }
-
- if (keep) {
- if (key != NULL)
- nowsignedby[key->index] = ISC_TRUE;
- INCSTAT(nretained);
- if (sigset.ttl != ttl) {
- vbprintf(2, "\tfixing ttl %s\n", sigstr);
- tuple = NULL;
- result = dns_difftuple_create(mctx,
- DNS_DIFFOP_DEL,
- name, sigset.ttl,
- &sigrdata,
- &tuple);
- check_result(result, "dns_difftuple_create");
- dns_diff_append(del, &tuple);
- result = dns_difftuple_create(mctx,
- DNS_DIFFOP_ADD,
- name, ttl,
- &sigrdata,
- &tuple);
- check_result(result, "dns_difftuple_create");
- dns_diff_append(add, &tuple);
- }
- } else {
- tuple = NULL;
- vbprintf(2, "removing signature by %s\n", sigstr);
- result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
- name, sigset.ttl,
- &sigrdata, &tuple);
- check_result(result, "dns_difftuple_create");
- dns_diff_append(del, &tuple);
- INCSTAT(ndropped);
- }
-
- if (resign) {
- INSIST(!keep);
-
- signwithkey(name, set, key->key, ttl, add,
- "resigning with dnskey");
- nowsignedby[key->index] = ISC_TRUE;
- }
-
- dns_rdata_reset(&sigrdata);
- dns_rdata_freestruct(&rrsig);
- result = dns_rdataset_next(&sigset);
- }
- if (result == ISC_R_NOMORE)
- result = ISC_R_SUCCESS;
-
- check_result(result, "dns_rdataset_first/next");
- if (dns_rdataset_isassociated(&sigset))
- dns_rdataset_disassociate(&sigset);
-
- for (key = ISC_LIST_HEAD(keylist);
- key != NULL;
- key = ISC_LIST_NEXT(key, link))
- {
- if (nowsignedby[key->index])
- continue;
-
- if (!issigningkey(key))
- continue;
-
- if (set->type == dns_rdatatype_dnskey &&
- dns_name_equal(name, gorigin)) {
- isc_boolean_t have_ksk;
- dns_dnsseckey_t *tmpkey;
-
- have_ksk = isksk(key);
- for (tmpkey = ISC_LIST_HEAD(keylist);
- tmpkey != NULL;
- tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
- if (dst_key_alg(key->key) !=
- dst_key_alg(tmpkey->key))
- continue;
- if (REVOKE(tmpkey->key))
- continue;
- if (isksk(tmpkey))
- have_ksk = ISC_TRUE;
- }
- if (isksk(key) || !have_ksk ||
- (iszsk(key) && !keyset_kskonly))
- signwithkey(name, set, key->key, ttl, add,
- "signing with dnskey");
- } else if (iszsk(key)) {
- signwithkey(name, set, key->key, ttl, add,
- "signing with dnskey");
- }
- }
-
- isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
- isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
-}
-
-struct hashlist {
- unsigned char *hashbuf;
- size_t entries;
- size_t size;
- size_t length;
-};
-
-static void
-hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
-
- l->entries = 0;
- l->length = length + 1;
-
- if (nodes != 0) {
- l->size = nodes;
- l->hashbuf = malloc(l->size * l->length);
- if (l->hashbuf == NULL)
- l->size = 0;
- } else {
- l->size = 0;
- l->hashbuf = NULL;
- }
-}
-
-static void
-hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
-{
-
- REQUIRE(len <= l->length);
-
- if (l->entries == l->size) {
- l->size = l->size * 2 + 100;
- l->hashbuf = realloc(l->hashbuf, l->size * l->length);
- if (l->hashbuf == NULL)
- fatal("unable to grow hashlist: out of memory");
- }
- memset(l->hashbuf + l->entries * l->length, 0, l->length);
- memcpy(l->hashbuf + l->entries * l->length, hash, len);
- l->entries++;
-}
-
-static void
-hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
- unsigned int hashalg, unsigned int iterations,
- const unsigned char *salt, size_t salt_length,
- isc_boolean_t speculative)
-{
- char nametext[DNS_NAME_FORMATSIZE];
- unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
- unsigned int len;
- size_t i;
-
- len = isc_iterated_hash(hash, hashalg, iterations, salt, salt_length,
- name->ndata, name->length);
- if (verbose) {
- dns_name_format(name, nametext, sizeof nametext);
- for (i = 0 ; i < len; i++)
- fprintf(stderr, "%02x", hash[i]);
- fprintf(stderr, " %s\n", nametext);
- }
- hash[len++] = speculative ? 1 : 0;
- hashlist_add(l, hash, len);
-}
-
-static int
-hashlist_comp(const void *a, const void *b) {
- return (memcmp(a, b, hash_length + 1));
-}
-
-static void
-hashlist_sort(hashlist_t *l) {
- qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
-}
-
-static isc_boolean_t
-hashlist_hasdup(hashlist_t *l) {
- unsigned char *current;
- unsigned char *next = l->hashbuf;
- size_t entries = l->entries;
-
- /*
- * Skip initial speculative wild card hashs.
- */
- while (entries > 0U && next[l->length-1] != 0U) {
- next += l->length;
- entries--;
- }
-
- current = next;
- while (entries-- > 1U) {
- next += l->length;
- if (next[l->length-1] != 0)
- continue;
- if (memcmp(current, next, l->length - 1) == 0)
- return (ISC_TRUE);
- current = next;
- }
- return (ISC_FALSE);
-}
-
-static const unsigned char *
-hashlist_findnext(const hashlist_t *l,
- const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
-{
- unsigned int entries = l->entries;
- const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
- l->length, hashlist_comp);
- INSIST(next != NULL);
-
- do {
- if (next < l->hashbuf + (l->entries - 1) * l->length)
- next += l->length;
- else
- next = l->hashbuf;
- if (next[l->length - 1] == 0)
- break;
- } while (entries-- > 1);
- INSIST(entries != 0);
- return (next);
-}
-
-static isc_boolean_t
-hashlist_exists(const hashlist_t *l,
- const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
-{
- if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
- return (ISC_TRUE);
- else
- return (ISC_FALSE);
-}
-
-static void
-addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
- unsigned int hashalg, unsigned int iterations,
- const unsigned char *salt, size_t salt_length)
-{
- dns_fixedname_t fixed;
- dns_name_t *wild;
- dns_dbnode_t *node = NULL;
- isc_result_t result;
- char namestr[DNS_NAME_FORMATSIZE];
-
- dns_fixedname_init(&fixed);
- wild = dns_fixedname_name(&fixed);
-
- result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
- if (result == ISC_R_NOSPACE)
- return;
- check_result(result,"addnowildcardhash: dns_name_concatenate()");
-
- result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
- if (result == ISC_R_SUCCESS) {
- dns_db_detachnode(gdb, &node);
- return;
- }
-
- if (verbose) {
- dns_name_format(wild, namestr, sizeof(namestr));
- fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
- }
-
- hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_length,
- ISC_TRUE);
-}
-
-static void
-opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
- dns_db_t **dbp)
-{
- char filename[PATH_MAX];
- isc_buffer_t b;
- isc_result_t result;
-
- isc_buffer_init(&b, filename, sizeof(filename));
- if (dsdir != NULL) {
- /* allow room for a trailing slash */
- if (strlen(dsdir) >= isc_buffer_availablelength(&b))
- fatal("path '%s' is too long", dsdir);
- isc_buffer_putstr(&b, dsdir);
- if (dsdir[strlen(dsdir) - 1] != '/')
- isc_buffer_putstr(&b, "/");
- }
- if (strlen(prefix) > isc_buffer_availablelength(&b))
- fatal("path '%s' is too long", dsdir);
- isc_buffer_putstr(&b, prefix);
- result = dns_name_tofilenametext(name, ISC_FALSE, &b);
- check_result(result, "dns_name_tofilenametext()");
- if (isc_buffer_availablelength(&b) == 0) {
- char namestr[DNS_NAME_FORMATSIZE];
- dns_name_format(name, namestr, sizeof(namestr));
- fatal("name '%s' is too long", namestr);
- }
- isc_buffer_putuint8(&b, 0);
-
- result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
- rdclass, 0, NULL, dbp);
- check_result(result, "dns_db_create()");
-
- result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT);
- if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
- dns_db_detach(dbp);
-}
-
-/*%
- * Load the DS set for a child zone, if a dsset-* file can be found.
- * If not, try to find a keyset-* file from an earlier version of
- * dnssec-signzone, and build DS records from that.
- */
-static isc_result_t
-loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
- dns_db_t *db = NULL;
- dns_dbversion_t *ver = NULL;
- dns_dbnode_t *node = NULL;
- isc_result_t result;
- dns_rdataset_t keyset;
- dns_rdata_t key, ds;
- unsigned char dsbuf[DNS_DS_BUFFERSIZE];
- dns_diff_t diff;
- dns_difftuple_t *tuple = NULL;
-
- opendb("dsset-", name, gclass, &db);
- if (db != NULL) {
- result = dns_db_findnode(db, name, ISC_FALSE, &node);
- if (result == ISC_R_SUCCESS) {
- dns_rdataset_init(dsset);
- result = dns_db_findrdataset(db, node, NULL,
- dns_rdatatype_ds, 0, 0,
- dsset, NULL);
- dns_db_detachnode(db, &node);
- if (result == ISC_R_SUCCESS) {
- vbprintf(2, "found DS records\n");
- dsset->ttl = ttl;
- dns_db_detach(&db);
- return (result);
- }
- }
- dns_db_detach(&db);
- }
-
- /* No DS records found; try again, looking for DNSKEY records */
- opendb("keyset-", name, gclass, &db);
- if (db == NULL) {
- return (ISC_R_NOTFOUND);
- }
-
- result = dns_db_findnode(db, name, ISC_FALSE, &node);
- if (result != ISC_R_SUCCESS) {
- dns_db_detach(&db);
- return (result);
- }
-
- dns_rdataset_init(&keyset);
- result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
- &keyset, NULL);
- if (result != ISC_R_SUCCESS) {
- dns_db_detachnode(db, &node);
- dns_db_detach(&db);
- return (result);
- }
- vbprintf(2, "found DNSKEY records\n");
-
- result = dns_db_newversion(db, &ver);
- check_result(result, "dns_db_newversion");
- dns_diff_init(mctx, &diff);
-
- for (result = dns_rdataset_first(&keyset);
- result == ISC_R_SUCCESS;
- result = dns_rdataset_next(&keyset))
- {
- dns_rdata_init(&key);
- dns_rdata_init(&ds);
- dns_rdataset_current(&keyset, &key);
- result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
- dsbuf, &ds);
- check_result(result, "dns_ds_buildrdata");
-
- result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
- ttl, &ds, &tuple);
- check_result(result, "dns_difftuple_create");
- dns_diff_append(&diff, &tuple);
-
- dns_rdata_reset(&ds);
- result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
- dsbuf, &ds);
- check_result(result, "dns_ds_buildrdata");
-
- result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
- ttl, &ds, &tuple);
- check_result(result, "dns_difftuple_create");
- dns_diff_append(&diff, &tuple);
- }
-
- result = dns_diff_apply(&diff, db, ver);
- check_result(result, "dns_diff_apply");
- dns_diff_clear(&diff);
-
- dns_db_closeversion(db, &ver, ISC_TRUE);
-
- result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
- dsset, NULL);
- check_result(result, "dns_db_findrdataset");
-
- dns_rdataset_disassociate(&keyset);
- dns_db_detachnode(db, &node);
- dns_db_detach(&db);
- return (result);
-}
-
-static isc_boolean_t
-secure(dns_name_t *name, dns_dbnode_t *node) {
- dns_rdataset_t dsset;
- isc_result_t result;
-
- if (dns_name_equal(name, gorigin))
- return (ISC_FALSE);
-
- dns_rdataset_init(&dsset);
- result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
- 0, 0, &dsset, NULL);
- if (dns_rdataset_isassociated(&dsset))
- dns_rdataset_disassociate(&dsset);
-
- return (ISC_TF(result == ISC_R_SUCCESS));
-}
-
-/*%
- * Signs all records at a name.
- */
-static void
-signname(dns_dbnode_t *node, dns_name_t *name) {
- isc_result_t result;
- dns_rdataset_t rdataset;
- dns_rdatasetiter_t *rdsiter;
- isc_boolean_t isdelegation = ISC_FALSE;
- dns_diff_t del, add;
- char namestr[DNS_NAME_FORMATSIZE];
-
- dns_rdataset_init(&rdataset);
- dns_name_format(name, namestr, sizeof(namestr));
-
- /*
- * Determine if this is a delegation point.
- */
- if (is_delegation(gdb, gversion, gorigin, name, node, NULL))
- isdelegation = ISC_TRUE;
-
- /*
- * Now iterate through the rdatasets.
- */
- dns_diff_init(mctx, &del);
- dns_diff_init(mctx, &add);
- rdsiter = NULL;
- result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
- check_result(result, "dns_db_allrdatasets()");
- result = dns_rdatasetiter_first(rdsiter);
- while (result == ISC_R_SUCCESS) {
- dns_rdatasetiter_current(rdsiter, &rdataset);
-
- /* If this is a RRSIG set, skip it. */
- if (rdataset.type == dns_rdatatype_rrsig)
- goto skip;
-
- /*
- * If this name is a delegation point, skip all records
- * except NSEC and DS sets. Otherwise check that there
- * isn't a DS record.
- */
- if (isdelegation) {
- if (rdataset.type != nsec_datatype &&
- rdataset.type != dns_rdatatype_ds)
- goto skip;
- } else if (rdataset.type == dns_rdatatype_ds) {
- char namebuf[DNS_NAME_FORMATSIZE];
- dns_name_format(name, namebuf, sizeof(namebuf));
- fatal("'%s': found DS RRset without NS RRset\n",
- namebuf);
- }
-
- signset(&del, &add, node, name, &rdataset);
-
- skip:
- dns_rdataset_disassociate(&rdataset);
- result = dns_rdatasetiter_next(rdsiter);
- }
- if (result != ISC_R_NOMORE)
- fatal("rdataset iteration for name '%s' failed: %s",
- namestr, isc_result_totext(result));
-
- dns_rdatasetiter_destroy(&rdsiter);
-
- result = dns_diff_applysilently(&del, gdb, gversion);
- if (result != ISC_R_SUCCESS)
- fatal("failed to delete SIGs at node '%s': %s",
- namestr, isc_result_totext(result));
-
- result = dns_diff_applysilently(&add, gdb, gversion);
- if (result != ISC_R_SUCCESS)
- fatal("failed to add SIGs at node '%s': %s",
- namestr, isc_result_totext(result));
-
- dns_diff_clear(&del);
- dns_diff_clear(&add);
-}
-
-static inline isc_boolean_t
-active_node(dns_dbnode_t *node) {
- dns_rdatasetiter_t *rdsiter = NULL;
- dns_rdatasetiter_t *rdsiter2 = NULL;
- isc_boolean_t active = ISC_FALSE;
- isc_result_t result;
- dns_rdataset_t rdataset;
- dns_rdatatype_t type;
- dns_rdatatype_t covers;
- isc_boolean_t found;
-
- dns_rdataset_init(&rdataset);
- result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
- check_result(result, "dns_db_allrdatasets()");
- result = dns_rdatasetiter_first(rdsiter);
- while (result == ISC_R_SUCCESS) {
- dns_rdatasetiter_current(rdsiter, &rdataset);
- if (rdataset.type != dns_rdatatype_nsec &&
- rdataset.type != dns_rdatatype_nsec3 &&
- rdataset.type != dns_rdatatype_rrsig)
- active = ISC_TRUE;
- dns_rdataset_disassociate(&rdataset);
- if (!active)
- result = dns_rdatasetiter_next(rdsiter);
- else
- result = ISC_R_NOMORE;
- }
- if (result != ISC_R_NOMORE)
- fatal("rdataset iteration failed: %s",
- isc_result_totext(result));
-
- if (!active && nsec_datatype == dns_rdatatype_nsec) {
- /*%
- * The node is empty of everything but NSEC / RRSIG records.
- */
- for (result = dns_rdatasetiter_first(rdsiter);
- result == ISC_R_SUCCESS;
- result = dns_rdatasetiter_next(rdsiter)) {
- dns_rdatasetiter_current(rdsiter, &rdataset);
- result = dns_db_deleterdataset(gdb, node, gversion,
- rdataset.type,
- rdataset.covers);
- check_result(result, "dns_db_deleterdataset()");
- dns_rdataset_disassociate(&rdataset);
- }
- if (result != ISC_R_NOMORE)
- fatal("rdataset iteration failed: %s",
- isc_result_totext(result));
- } else {
- /*
- * Delete RRSIGs for types that no longer exist.
- */
- result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
- check_result(result, "dns_db_allrdatasets()");
- for (result = dns_rdatasetiter_first(rdsiter);
- result == ISC_R_SUCCESS;
- result = dns_rdatasetiter_next(rdsiter)) {
- dns_rdatasetiter_current(rdsiter, &rdataset);
- type = rdataset.type;
- covers = rdataset.covers;
- dns_rdataset_disassociate(&rdataset);
- /*
- * Delete the NSEC chain if we are signing with
- * NSEC3.
- */
- if (nsec_datatype == dns_rdatatype_nsec3 &&
- (type == dns_rdatatype_nsec ||
- covers == dns_rdatatype_nsec)) {
- result = dns_db_deleterdataset(gdb, node,
- gversion, type,
- covers);
- check_result(result,
- "dns_db_deleterdataset(nsec/rrsig)");
- continue;
- }
- if (type != dns_rdatatype_rrsig)
- continue;
- found = ISC_FALSE;
- for (result = dns_rdatasetiter_first(rdsiter2);
- !found && result == ISC_R_SUCCESS;
- result = dns_rdatasetiter_next(rdsiter2)) {
- dns_rdatasetiter_current(rdsiter2, &rdataset);
- if (rdataset.type == covers)
- found = ISC_TRUE;
- dns_rdataset_disassociate(&rdataset);
- }
- if (!found) {
- if (result != ISC_R_NOMORE)
- fatal("rdataset iteration failed: %s",
- isc_result_totext(result));
- result = dns_db_deleterdataset(gdb, node,
- gversion, type,
- covers);
- check_result(result,
- "dns_db_deleterdataset(rrsig)");
- } else if (result != ISC_R_NOMORE &&
- result != ISC_R_SUCCESS)
- fatal("rdataset iteration failed: %s",
- isc_result_totext(result));
- }
- if (result != ISC_R_NOMORE)
- fatal("rdataset iteration failed: %s",
- isc_result_totext(result));
- dns_rdatasetiter_destroy(&rdsiter2);
- }
- dns_rdatasetiter_destroy(&rdsiter);
-
- return (active);
-}
-
-/*%
- * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
- */
-static void
-get_soa_ttls(void) {
- dns_rdataset_t soaset;
- dns_fixedname_t fname;
- dns_name_t *name;
- isc_result_t result;
- dns_rdata_t rdata = DNS_RDATA_INIT;
-
- dns_fixedname_init(&fname);
- name = dns_fixedname_name(&fname);
- dns_rdataset_init(&soaset);
- result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
- 0, 0, NULL, name, &soaset, NULL);
- if (result != ISC_R_SUCCESS)
- fatal("failed to find an SOA at the zone apex: %s",
- isc_result_totext(result));
-
- result = dns_rdataset_first(&soaset);
- check_result(result, "dns_rdataset_first");
- dns_rdataset_current(&soaset, &rdata);
- zone_soa_min_ttl = dns_soa_getminimum(&rdata);
- soa_ttl = soaset.ttl;
- dns_rdataset_disassociate(&soaset);
-}
-
-/*%
- * Increment (or set if nonzero) the SOA serial
- */
-static isc_result_t
-setsoaserial(isc_uint32_t serial) {
- isc_result_t result;
- dns_dbnode_t *node = NULL;
- dns_rdataset_t rdataset;
- dns_rdata_t rdata = DNS_RDATA_INIT;
- isc_uint32_t old_serial, new_serial;
-
- result = dns_db_getoriginnode(gdb, &node);
- if (result != ISC_R_SUCCESS)
- return result;
-
- dns_rdataset_init(&rdataset);
-
- result = dns_db_findrdataset(gdb, node, gversion,
- dns_rdatatype_soa, 0,
- 0, &rdataset, NULL);
- if (result != ISC_R_SUCCESS)
- goto cleanup;
-
- result = dns_rdataset_first(&rdataset);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
-
- dns_rdataset_current(&rdataset, &rdata);
-
- old_serial = dns_soa_getserial(&rdata);
-
- if (serial) {
- /* Set SOA serial to the value provided. */
- new_serial = serial;
- } else {
- /* Increment SOA serial using RFC 1982 arithmetics */
- new_serial = (old_serial + 1) & 0xFFFFFFFF;
- if (new_serial == 0)
- new_serial = 1;
- }
-
- /* If the new serial is not likely to cause a zone transfer
- * (a/ixfr) from servers having the old serial, warn the user.
- *
- * RFC1982 section 7 defines the maximum increment to be
- * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
- * comparison. (5 - 6 == (2^32)-1, not negative-one)
- */
- if (new_serial == old_serial ||
- (new_serial - old_serial) > 0x7fffffffU)
- fprintf(stderr, "%s: warning: Serial number not advanced, "
- "zone may not transfer\n", program);
-
- dns_soa_setserial(new_serial, &rdata);
-
- result = dns_db_deleterdataset(gdb, node, gversion,
- dns_rdatatype_soa, 0);
- check_result(result, "dns_db_deleterdataset");
- if (result != ISC_R_SUCCESS)
- goto cleanup;
-
- result = dns_db_addrdataset(gdb, node, gversion,
- 0, &rdataset, 0, NULL);
- check_result(result, "dns_db_addrdataset");
- if (result != ISC_R_SUCCESS)
- goto cleanup;
-
-cleanup:
- dns_rdataset_disassociate(&rdataset);
- if (node != NULL)
- dns_db_detachnode(gdb, &node);
- dns_rdata_reset(&rdata);
-
- return (result);
-}
-
-/*%
- * Delete any RRSIG records at a node.
- */
-static void
-cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
- dns_rdatasetiter_t *rdsiter = NULL;
- dns_rdataset_t set;
- isc_result_t result, dresult;
-
- if (outputformat != dns_masterformat_text || !disable_zone_check)
- return;
-
- dns_rdataset_init(&set);
- result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
- check_result(result, "dns_db_allrdatasets");
- result = dns_rdatasetiter_first(rdsiter);
- while (result == ISC_R_SUCCESS) {
- isc_boolean_t destroy = ISC_FALSE;
- dns_rdatatype_t covers = 0;
- dns_rdatasetiter_current(rdsiter, &set);
- if (set.type == dns_rdatatype_rrsig) {
- covers = set.covers;
- destroy = ISC_TRUE;
- }
- dns_rdataset_disassociate(&set);
- result = dns_rdatasetiter_next(rdsiter);
- if (destroy) {
- dresult = dns_db_deleterdataset(db, node, version,
- dns_rdatatype_rrsig,
- covers);
- check_result(dresult, "dns_db_deleterdataset");
- }
- }
- if (result != ISC_R_NOMORE)
- fatal("rdataset iteration failed: %s",
- isc_result_totext(result));
- dns_rdatasetiter_destroy(&rdsiter);
-}
-
-/*%
- * Set up the iterator and global state before starting the tasks.
- */
-static void
-presign(void) {
- isc_result_t result;
-
- gdbiter = NULL;
- result = dns_db_createiterator(gdb, 0, &gdbiter);
- check_result(result, "dns_db_createiterator()");
-}
-
-/*%
- * Clean up the iterator and global state after the tasks complete.
- */
-static void
-postsign(void) {
- dns_dbiterator_destroy(&gdbiter);
-}
-
-/*%
- * Sign the apex of the zone.
- * Note the origin may not be the first node if there are out of zone
- * records.
- */
-static void
-signapex(void) {
- dns_dbnode_t *node = NULL;
- dns_fixedname_t fixed;
- dns_name_t *name;
- isc_result_t result;
-
- dns_fixedname_init(&fixed);
- name = dns_fixedname_name(&fixed);
- result = dns_dbiterator_seek(gdbiter, gorigin);
- check_result(result, "dns_dbiterator_seek()");
- result = dns_dbiterator_current(gdbiter, &node, name);
- check_dns_dbiterator_current(result);
- signname(node, name);
- dumpnode(name, node);
- cleannode(gdb, gversion, node);
- dns_db_detachnode(gdb, &node);
- result = dns_dbiterator_first(gdbiter);
- if (result == ISC_R_NOMORE)
- finished = ISC_TRUE;
- else if (result != ISC_R_SUCCESS)
- fatal("failure iterating database: %s",
- isc_result_totext(result));
-}
-
-/*%
- * Assigns a node to a worker thread. This is protected by the master task's
- * lock.
- */
-static void
-assignwork(isc_task_t *task, isc_task_t *worker) {
- dns_fixedname_t *fname;
- dns_name_t *name;
- dns_dbnode_t *node;
- sevent_t *sevent;
- dns_rdataset_t nsec;
- isc_boolean_t found;
- isc_result_t result;
- static dns_name_t *zonecut = NULL; /* Protected by namelock. */
- static dns_fixedname_t fzonecut; /* Protected by namelock. */
- static unsigned int ended = 0; /* Protected by namelock. */
-
- if (shuttingdown)
- return;
-
- LOCK(&namelock);
- if (finished) {
- ended++;
- if (ended == ntasks) {
- isc_task_detach(&task);
- isc_app_shutdown();
- }
- goto unlock;
- }
-
- fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
- if (fname == NULL)
- fatal("out of memory");
- dns_fixedname_init(fname);
- name = dns_fixedname_name(fname);
- node = NULL;
- found = ISC_FALSE;
- while (!found) {
- result = dns_dbiterator_current(gdbiter, &node, name);
- check_dns_dbiterator_current(result);
- /*
- * The origin was handled by signapex().
- */
- if (dns_name_equal(name, gorigin)) {
- dns_db_detachnode(gdb, &node);
- goto next;
- }
- /*
- * Sort the zone data from the glue and out-of-zone data.
- * For NSEC zones nodes with zone data have NSEC records.
- * For NSEC3 zones the NSEC3 nodes are zone data but
- * outside of the zone name space. For the rest we need
- * to track the bottom of zone cuts.
- * Nodes which don't need to be signed are dumped here.
- */
- dns_rdataset_init(&nsec);
- result = dns_db_findrdataset(gdb, node, gversion,
- nsec_datatype, 0, 0,
- &nsec, NULL);
- if (dns_rdataset_isassociated(&nsec))
- dns_rdataset_disassociate(&nsec);
- if (result == ISC_R_SUCCESS) {
- found = ISC_TRUE;
- } else if (nsec_datatype == dns_rdatatype_nsec3) {
- if (dns_name_issubdomain(name, gorigin) &&
- (zonecut == NULL ||
- !dns_name_issubdomain(name, zonecut))) {
- if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) {
- dns_fixedname_init(&fzonecut);
- zonecut = dns_fixedname_name(&fzonecut);
- dns_name_copy(name, zonecut, NULL);
- if (!OPTOUT(nsec3flags) ||
- secure(name, node))
- found = ISC_TRUE;
- } else
- found = ISC_TRUE;
- }
- }
-
- if (!found) {
- dumpnode(name, node);
- dns_db_detachnode(gdb, &node);
- }
-
- next:
- result = dns_dbiterator_next(gdbiter);
- if (result == ISC_R_NOMORE) {
- finished = ISC_TRUE;
- break;
- } else if (result != ISC_R_SUCCESS)
- fatal("failure iterating database: %s",
- isc_result_totext(result));
- }
- if (!found) {
- ended++;
- if (ended == ntasks) {
- isc_task_detach(&task);
- isc_app_shutdown();
- }
- isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
- goto unlock;
- }
- sevent = (sevent_t *)
- isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
- sign, NULL, sizeof(sevent_t));
- if (sevent == NULL)
- fatal("failed to allocate event\n");
-
- sevent->node = node;
- sevent->fname = fname;
- isc_task_send(worker, ISC_EVENT_PTR(&sevent));
- unlock:
- UNLOCK(&namelock);
-}
-
-/*%
- * Start a worker task
- */
-static void
-startworker(isc_task_t *task, isc_event_t *event) {
- isc_task_t *worker;
-
- worker = (isc_task_t *)event->ev_arg;
- assignwork(task, worker);
- isc_event_free(&event);
-}
-
-/*%
- * Write a node to the output file, and restart the worker task.
- */
-static void
-writenode(isc_task_t *task, isc_event_t *event) {
- isc_task_t *worker;
- sevent_t *sevent = (sevent_t *)event;
-
- worker = (isc_task_t *)event->ev_sender;
- dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
- cleannode(gdb, gversion, sevent->node);
- dns_db_detachnode(gdb, &sevent->node);
- isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
- assignwork(task, worker);
- isc_event_free(&event);
-}
-
-/*%
- * Sign a database node.
- */
-static void
-sign(isc_task_t *task, isc_event_t *event) {
- dns_fixedname_t *fname;
- dns_dbnode_t *node;
- sevent_t *sevent, *wevent;
-
- sevent = (sevent_t *)event;
- node = sevent->node;
- fname = sevent->fname;
- isc_event_free(&event);
-
- signname(node, dns_fixedname_name(fname));
- wevent = (sevent_t *)
- isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
- writenode, NULL, sizeof(sevent_t));
- if (wevent == NULL)
- fatal("failed to allocate event\n");
- wevent->node = node;
- wevent->fname = fname;
- isc_task_send(master, ISC_EVENT_PTR(&wevent));
-}
-
-/*%
- * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
- */
-static void
-add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
- dns_rdataset_t dsset;
- dns_rdataset_t sigdsset;
- isc_result_t result;
-
- dns_rdataset_init(&dsset);
- dns_rdataset_init(&sigdsset);
- result = dns_db_findrdataset(gdb, node, gversion,
- dns_rdatatype_ds,
- 0, 0, &dsset, &sigdsset);
- if (result == ISC_R_SUCCESS) {
- dns_rdataset_disassociate(&dsset);
- result = dns_db_deleterdataset(gdb, node, gversion,
- dns_rdatatype_ds, 0);
- check_result(result, "dns_db_deleterdataset");
- }
-
- result = loadds(name, nsttl, &dsset);
- if (result == ISC_R_SUCCESS) {
- result = dns_db_addrdataset(gdb, node, gversion, 0,
- &dsset, 0, NULL);
- check_result(result, "dns_db_addrdataset");
- dns_rdataset_disassociate(&dsset);
- if (dns_rdataset_isassociated(&sigdsset))
- dns_rdataset_disassociate(&sigdsset);
- } else if (dns_rdataset_isassociated(&sigdsset)) {
- result = dns_db_deleterdataset(gdb, node, gversion,
- dns_rdatatype_rrsig,
- dns_rdatatype_ds);
- check_result(result, "dns_db_deleterdataset");
- dns_rdataset_disassociate(&sigdsset);
- }
-}
-
-/*
- * Remove records of the given type and their signatures.
- */
-static void
-remove_records(dns_dbnode_t *node, dns_rdatatype_t which,
- isc_boolean_t checknsec)
-{
- isc_result_t result;
- dns_rdatatype_t type, covers;
- dns_rdatasetiter_t *rdsiter = NULL;
- dns_rdataset_t rdataset;
-
- dns_rdataset_init(&rdataset);
-
- /*
- * Delete any records of the given type at the apex.
- */
- result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
- check_result(result, "dns_db_allrdatasets()");
- for (result = dns_rdatasetiter_first(rdsiter);
- result == ISC_R_SUCCESS;
- result = dns_rdatasetiter_next(rdsiter)) {
- dns_rdatasetiter_current(rdsiter, &rdataset);
- type = rdataset.type;
- covers = rdataset.covers;
- dns_rdataset_disassociate(&rdataset);
- if (type == which || covers == which) {
- if (which == dns_rdatatype_nsec &&
- checknsec && !update_chain)
- fatal("Zone contains NSEC records. Use -u "
- "to update to NSEC3.");
- if (which == dns_rdatatype_nsec3param &&
- checknsec && !update_chain)
- fatal("Zone contains NSEC3 chains. Use -u "
- "to update to NSEC.");
- result = dns_db_deleterdataset(gdb, node, gversion,
- type, covers);
- check_result(result, "dns_db_deleterdataset()");
- continue;
- }
- }
- dns_rdatasetiter_destroy(&rdsiter);
-}
-
-/*
- * Remove signatures covering the given type (0 == all signatures).
- */
-static void
-remove_sigs(dns_dbnode_t *node, dns_rdatatype_t which) {
- isc_result_t result;
- dns_rdatatype_t type, covers;
- dns_rdatasetiter_t *rdsiter = NULL;
- dns_rdataset_t rdataset;
-
- dns_rdataset_init(&rdataset);
- result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
- check_result(result, "dns_db_allrdatasets()");
- for (result = dns_rdatasetiter_first(rdsiter);
- result == ISC_R_SUCCESS;
- result = dns_rdatasetiter_next(rdsiter)) {
- dns_rdatasetiter_current(rdsiter, &rdataset);
- type = rdataset.type;
- covers = rdataset.covers;
- dns_rdataset_disassociate(&rdataset);
-
- if (type == dns_rdatatype_rrsig &&
- (covers == which || which == 0))
- {
- result = dns_db_deleterdataset(gdb, node, gversion,
- type, covers);
- check_result(result, "dns_db_deleterdataset()");
- continue;
- }
- }
- dns_rdatasetiter_destroy(&rdsiter);
-}
-
-/*%
- * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
- */
-static void
-nsecify(void) {
- dns_dbiterator_t *dbiter = NULL;
- dns_dbnode_t *node = NULL, *nextnode = NULL;
- dns_fixedname_t fname, fnextname, fzonecut;
- dns_name_t *name, *nextname, *zonecut;
- dns_rdataset_t rdataset;
- dns_rdatasetiter_t *rdsiter = NULL;
- dns_rdatatype_t type, covers;
- isc_boolean_t done = ISC_FALSE;
- isc_result_t result;
- isc_uint32_t nsttl = 0;
-
- dns_rdataset_init(&rdataset);
- dns_fixedname_init(&fname);
- name = dns_fixedname_name(&fname);
- dns_fixedname_init(&fnextname);
- nextname = dns_fixedname_name(&fnextname);
- dns_fixedname_init(&fzonecut);
- zonecut = NULL;
-
- /*
- * Remove any NSEC3 chains.
- */
- result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
- check_result(result, "dns_db_createiterator()");
- for (result = dns_dbiterator_first(dbiter);
- result == ISC_R_SUCCESS;
- result = dns_dbiterator_next(dbiter)) {
- result = dns_dbiterator_current(dbiter, &node, name);
- check_dns_dbiterator_current(result);
- result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
- check_result(result, "dns_db_allrdatasets()");
- for (result = dns_rdatasetiter_first(rdsiter);
- result == ISC_R_SUCCESS;
- result = dns_rdatasetiter_next(rdsiter)) {
- dns_rdatasetiter_current(rdsiter, &rdataset);
- type = rdataset.type;
- covers = rdataset.covers;
- dns_rdataset_disassociate(&rdataset);
- result = dns_db_deleterdataset(gdb, node, gversion,
- type, covers);
- check_result(result,
- "dns_db_deleterdataset(nsec3param/rrsig)");
- }
- dns_rdatasetiter_destroy(&rdsiter);
- dns_db_detachnode(gdb, &node);
- }
- dns_dbiterator_destroy(&dbiter);
-
- result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
- check_result(result, "dns_db_createiterator()");
-
- result = dns_dbiterator_first(dbiter);
- check_result(result, "dns_dbiterator_first()");
-
- while (!done) {
- result = dns_dbiterator_current(dbiter, &node, name);
- check_dns_dbiterator_current(result);
- /*
- * Skip out-of-zone records.
- */
- if (!dns_name_issubdomain(name, gorigin)) {
- result = dns_dbiterator_next(dbiter);
- if (result == ISC_R_NOMORE)
- done = ISC_TRUE;
- else
- check_result(result, "dns_dbiterator_next()");
- dns_db_detachnode(gdb, &node);
- continue;
- }
-
- if (dns_name_equal(name, gorigin))
- remove_records(node, dns_rdatatype_nsec3param,
- ISC_TRUE);
-
- if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) {
- zonecut = dns_fixedname_name(&fzonecut);
- dns_name_copy(name, zonecut, NULL);
- remove_sigs(node, 0);
- if (generateds)
- add_ds(name, node, nsttl);
- }
-
- result = dns_dbiterator_next(dbiter);
- nextnode = NULL;
- while (result == ISC_R_SUCCESS) {
- isc_boolean_t active = ISC_FALSE;
- result = dns_dbiterator_current(dbiter, &nextnode,
- nextname);
- check_dns_dbiterator_current(result);
- active = active_node(nextnode);
- if (!active) {
- dns_db_detachnode(gdb, &nextnode);
- result = dns_dbiterator_next(dbiter);
- continue;
- }
- if (!dns_name_issubdomain(nextname, gorigin) ||
- (zonecut != NULL &&
- dns_name_issubdomain(nextname, zonecut)))
- {
- remove_sigs(nextnode, 0);
- remove_records(nextnode, dns_rdatatype_nsec,
- ISC_FALSE);
- dns_db_detachnode(gdb, &nextnode);
- result = dns_dbiterator_next(dbiter);
- continue;
- }
- dns_db_detachnode(gdb, &nextnode);
- break;
- }
- if (result == ISC_R_NOMORE) {
- dns_name_clone(gorigin, nextname);
- done = ISC_TRUE;
- } else if (result != ISC_R_SUCCESS)
- fatal("iterating through the database failed: %s",
- isc_result_totext(result));
- dns_dbiterator_pause(dbiter);
- result = dns_nsec_build(gdb, gversion, node, nextname,
- zone_soa_min_ttl);
- check_result(result, "dns_nsec_build()");
- dns_db_detachnode(gdb, &node);
- }
-
- dns_dbiterator_destroy(&dbiter);
-}
-
-static void
-addnsec3param(const unsigned char *salt, size_t salt_length,
- unsigned int iterations)
-{
- dns_dbnode_t *node = NULL;
- dns_rdata_nsec3param_t nsec3param;
- unsigned char nsec3parambuf[5 + 255];
- dns_rdatalist_t rdatalist;
- dns_rdataset_t rdataset;
- dns_rdata_t rdata = DNS_RDATA_INIT;
- isc_buffer_t b;
- isc_result_t result;
-
- dns_rdataset_init(&rdataset);
-
- nsec3param.common.rdclass = gclass;
- nsec3param.common.rdtype = dns_rdatatype_nsec3param;
- ISC_LINK_INIT(&nsec3param.common, link);
- nsec3param.mctx = NULL;
- nsec3param.flags = 0;
- nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
- nsec3param.iterations = iterations;
- nsec3param.salt_length = salt_length;
- DE_CONST(salt, nsec3param.salt);
-
- isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
- result = dns_rdata_fromstruct(&rdata, gclass,
- dns_rdatatype_nsec3param,
- &nsec3param, &b);
- check_result(result, "dns_rdata_fromstruct()");
- rdatalist.rdclass = rdata.rdclass;
- rdatalist.type = rdata.type;
- rdatalist.covers = 0;
- rdatalist.ttl = 0;
- ISC_LIST_INIT(rdatalist.rdata);
- ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
- result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
- check_result(result, "dns_rdatalist_tordataset()");
-
- result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node);
- check_result(result, "dns_db_find(gorigin)");
-
- /*
- * Delete any current NSEC3PARAM records.
- */
- result = dns_db_deleterdataset(gdb, node, gversion,
- dns_rdatatype_nsec3param, 0);
- if (result == DNS_R_UNCHANGED)
- result = ISC_R_SUCCESS;
- check_result(result, "dddnsec3param: dns_db_deleterdataset()");
-
- result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
- DNS_DBADD_MERGE, NULL);
- if (result == DNS_R_UNCHANGED)
- result = ISC_R_SUCCESS;
- check_result(result, "addnsec3param: dns_db_addrdataset()");
- dns_db_detachnode(gdb, &node);
-}
-
-static void
-addnsec3(dns_name_t *name, dns_dbnode_t *node,
- const unsigned char *salt, size_t salt_length,
- unsigned int iterations, hashlist_t *hashlist,
- dns_ttl_t ttl)
-{
- unsigned char hash[NSEC3_MAX_HASH_LENGTH];
- const unsigned char *nexthash;
- unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
- dns_fixedname_t hashname;
- dns_rdatalist_t rdatalist;
- dns_rdataset_t rdataset;
- dns_rdata_t rdata = DNS_RDATA_INIT;
- isc_result_t result;
- dns_dbnode_t *nsec3node = NULL;
- char namebuf[DNS_NAME_FORMATSIZE];
- size_t hash_length;
-
- dns_name_format(name, namebuf, sizeof(namebuf));
-
- dns_fixedname_init(&hashname);
- dns_rdataset_init(&rdataset);
-
- dns_name_downcase(name, name, NULL);
- result = dns_nsec3_hashname(&hashname, hash, &hash_length,
- name, gorigin, dns_hash_sha1, iterations,
- salt, salt_length);
- check_result(result, "addnsec3: dns_nsec3_hashname()");
- nexthash = hashlist_findnext(hashlist, hash);
- result = dns_nsec3_buildrdata(gdb, gversion, node,
- unknownalg ?
- DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
- nsec3flags, iterations,
- salt, salt_length,
- nexthash, ISC_SHA1_DIGESTLENGTH,
- nsec3buffer, &rdata);
- check_result(result, "addnsec3: dns_nsec3_buildrdata()");
- rdatalist.rdclass = rdata.rdclass;
- rdatalist.type = rdata.type;
- rdatalist.covers = 0;
- rdatalist.ttl = ttl;
- ISC_LIST_INIT(rdatalist.rdata);
- ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
- result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
- check_result(result, "dns_rdatalist_tordataset()");
- result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
- ISC_TRUE, &nsec3node);
- check_result(result, "addnsec3: dns_db_findnode()");
- result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
- 0, NULL);
- if (result == DNS_R_UNCHANGED)
- result = ISC_R_SUCCESS;
- check_result(result, "addnsec3: dns_db_addrdataset()");
- dns_db_detachnode(gdb, &nsec3node);
-}
-
-/*%
- * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
- *
- * Extract the hash from the first label of 'name' then see if it
- * is in hashlist. If 'name' is not in the hashlist then delete the
- * any NSEC3 records which have the same parameters as the chain we
- * are building.
- *
- * XXXMPA Should we also check that it of the form <hash>.<origin>?
- */
-static void
-nsec3clean(dns_name_t *name, dns_dbnode_t *node,
- unsigned int hashalg, unsigned int iterations,
- const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
-{
- dns_label_t label;
- dns_rdata_nsec3_t nsec3;
- dns_rdata_t rdata, delrdata;
- dns_rdatalist_t rdatalist;
- dns_rdataset_t rdataset, delrdataset;
- isc_boolean_t delete_rrsigs = ISC_FALSE;
- isc_buffer_t target;
- isc_result_t result;
- unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
- isc_boolean_t exists;
-
- /*
- * Get the first label.
- */
- dns_name_getlabel(name, 0, &label);
-
- /*
- * We want just the label contents.
- */
- isc_region_consume(&label, 1);
-
- /*
- * Decode base32hex string.
- */
- isc_buffer_init(&target, hash, sizeof(hash) - 1);
- result = isc_base32hex_decoderegion(&label, &target);
- if (result != ISC_R_SUCCESS)
- return;
-
- hash[isc_buffer_usedlength(&target)] = 0;
-
- exists = hashlist_exists(hashlist, hash);
-
- /*
- * Verify that the NSEC3 parameters match the current ones
- * otherwise we are dealing with a different NSEC3 chain.
- */
- dns_rdataset_init(&rdataset);
- dns_rdataset_init(&delrdataset);
-
- result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
- 0, 0, &rdataset, NULL);
- if (result != ISC_R_SUCCESS)
- return;
-
- /*
- * Delete any NSEC3 records which are not part of the current
- * NSEC3 chain.
- */
- for (result = dns_rdataset_first(&rdataset);
- result == ISC_R_SUCCESS;
- result = dns_rdataset_next(&rdataset)) {
- dns_rdata_init(&rdata);
- dns_rdataset_current(&rdataset, &rdata);
- result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
- check_result(result, "dns_rdata_tostruct");
- if (exists && nsec3.hash == hashalg &&
- nsec3.iterations == iterations &&
- nsec3.salt_length == salt_length &&
- !memcmp(nsec3.salt, salt, salt_length))
- continue;
- rdatalist.rdclass = rdata.rdclass;
- rdatalist.type = rdata.type;
- rdatalist.covers = 0;
- rdatalist.ttl = rdataset.ttl;
- ISC_LIST_INIT(rdatalist.rdata);
- dns_rdata_init(&delrdata);
- dns_rdata_clone(&rdata, &delrdata);
- ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
- result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
- check_result(result, "dns_rdatalist_tordataset()");
- result = dns_db_subtractrdataset(gdb, node, gversion,
- &delrdataset, 0, NULL);
- dns_rdataset_disassociate(&delrdataset);
- if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET)
- check_result(result, "dns_db_subtractrdataset(NSEC3)");
- delete_rrsigs = ISC_TRUE;
- }
- dns_rdataset_disassociate(&rdataset);
- if (result != ISC_R_NOMORE)
- check_result(result, "dns_rdataset_first/next");
-
- if (!delete_rrsigs)
- return;
- /*
- * Delete the NSEC3 RRSIGs
- */
- result = dns_db_deleterdataset(gdb, node, gversion,
- dns_rdatatype_rrsig,
- dns_rdatatype_nsec3);
- if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
- check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
-}
-
-static void
-rrset_remove_duplicates(dns_name_t *name, dns_rdataset_t *rdataset,
- dns_diff_t *diff)
-{
- dns_difftuple_t *tuple = NULL;
- isc_result_t result;
- unsigned int count1 = 0;
- dns_rdataset_t tmprdataset;
-
- dns_rdataset_init(&tmprdataset);
- for (result = dns_rdataset_first(rdataset);
- result == ISC_R_SUCCESS;
- result = dns_rdataset_next(rdataset)) {
- dns_rdata_t rdata1 = DNS_RDATA_INIT;
- unsigned int count2 = 0;
-
- count1++;
- dns_rdataset_current(rdataset, &rdata1);
- dns_rdataset_clone(rdataset, &tmprdataset);
- for (result = dns_rdataset_first(&tmprdataset);
- result == ISC_R_SUCCESS;
- result = dns_rdataset_next(&tmprdataset)) {
- dns_rdata_t rdata2 = DNS_RDATA_INIT;
- count2++;
- if (count1 >= count2)
- continue;
- dns_rdataset_current(&tmprdataset, &rdata2);
- if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
- result = dns_difftuple_create(mctx,
- DNS_DIFFOP_DEL,
- name,
- rdataset->ttl,
- &rdata2, &tuple);
- check_result(result, "dns_difftuple_create");
- dns_diff_append(diff, &tuple);
- }
- }
- dns_rdataset_disassociate(&tmprdataset);
- }
-}
-
-static void
-remove_duplicates(void) {
- isc_result_t result;
- dns_dbiterator_t *dbiter = NULL;
- dns_rdatasetiter_t *rdsiter = NULL;
- dns_diff_t diff;
- dns_dbnode_t *node = NULL;
- dns_rdataset_t rdataset;
- dns_fixedname_t fname;
- dns_name_t *name;
-
- dns_diff_init(mctx, &diff);
- dns_fixedname_init(&fname);
- name = dns_fixedname_name(&fname);
- dns_rdataset_init(&rdataset);
-
- result = dns_db_createiterator(gdb, 0, &dbiter);
- check_result(result, "dns_db_createiterator()");
-
- for (result = dns_dbiterator_first(dbiter);
- result == ISC_R_SUCCESS;
- result = dns_dbiterator_next(dbiter)) {
-
- result = dns_dbiterator_current(dbiter, &node, name);
- check_dns_dbiterator_current(result);
- result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
- check_result(result, "dns_db_allrdatasets()");
- for (result = dns_rdatasetiter_first(rdsiter);
- result == ISC_R_SUCCESS;
- result = dns_rdatasetiter_next(rdsiter)) {
- dns_rdatasetiter_current(rdsiter, &rdataset);
- rrset_remove_duplicates(name, &rdataset, &diff);
- dns_rdataset_disassociate(&rdataset);
- }
- if (result != ISC_R_NOMORE)
- fatal("rdatasets iteration failed.");
- dns_rdatasetiter_destroy(&rdsiter);
- dns_db_detachnode(gdb, &node);
- }
- if (result != ISC_R_NOMORE)
- fatal("zone iteration failed.");
-
- if (!ISC_LIST_EMPTY(diff.tuples)) {
- result = dns_diff_applysilently(&diff, gdb, gversion);
- check_result(result, "dns_diff_applysilently");
- }
- dns_diff_clear(&diff);
- dns_dbiterator_destroy(&dbiter);
-}
-
-/*
- * Generate NSEC3 records for the zone.
- */
-static void
-nsec3ify(unsigned int hashalg, unsigned int iterations,
- const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
-{
- dns_dbiterator_t *dbiter = NULL;
- dns_dbnode_t *node = NULL, *nextnode = NULL;
- dns_fixedname_t fname, fnextname, fzonecut;
- dns_name_t *name, *nextname, *zonecut;
- dns_rdataset_t rdataset;
- int order;
- isc_boolean_t active;
- isc_boolean_t done = ISC_FALSE;
- isc_result_t result;
- isc_uint32_t nsttl = 0;
- unsigned int count, nlabels;
-
- dns_rdataset_init(&rdataset);
- dns_fixedname_init(&fname);
- name = dns_fixedname_name(&fname);
- dns_fixedname_init(&fnextname);
- nextname = dns_fixedname_name(&fnextname);
- dns_fixedname_init(&fzonecut);
- zonecut = NULL;
-
- /*
- * Walk the zone generating the hash names.
- */
- result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
- check_result(result, "dns_db_createiterator()");
-
- result = dns_dbiterator_first(dbiter);
- check_result(result, "dns_dbiterator_first()");
-
- while (!done) {
- result = dns_dbiterator_current(dbiter, &node, name);
- check_dns_dbiterator_current(result);
- /*
- * Skip out-of-zone records.
- */
- if (!dns_name_issubdomain(name, gorigin)) {
- result = dns_dbiterator_next(dbiter);
- if (result == ISC_R_NOMORE)
- done = ISC_TRUE;
- else
- check_result(result, "dns_dbiterator_next()");
- dns_db_detachnode(gdb, &node);
- continue;
- }
-
- if (dns_name_equal(name, gorigin))
- remove_records(node, dns_rdatatype_nsec, ISC_TRUE);
-
- result = dns_dbiterator_next(dbiter);
- nextnode = NULL;
- while (result == ISC_R_SUCCESS) {
- result = dns_dbiterator_current(dbiter, &nextnode,
- nextname);
- check_dns_dbiterator_current(result);
- active = active_node(nextnode);
- if (!active) {
- dns_db_detachnode(gdb, &nextnode);
- result = dns_dbiterator_next(dbiter);
- continue;
- }
- if (!dns_name_issubdomain(nextname, gorigin) ||
- (zonecut != NULL &&
- dns_name_issubdomain(nextname, zonecut))) {
- remove_sigs(nextnode, 0);
- dns_db_detachnode(gdb, &nextnode);
- result = dns_dbiterator_next(dbiter);
- continue;
- }
- if (is_delegation(gdb, gversion, gorigin,
- nextname, nextnode, &nsttl))
- {
- zonecut = dns_fixedname_name(&fzonecut);
- dns_name_copy(nextname, zonecut, NULL);
- remove_sigs(nextnode, 0);
- if (generateds)
- add_ds(nextname, nextnode, nsttl);
- if (OPTOUT(nsec3flags) &&
- !secure(nextname, nextnode)) {
- dns_db_detachnode(gdb, &nextnode);
- result = dns_dbiterator_next(dbiter);
- continue;
- }
- }
- dns_db_detachnode(gdb, &nextnode);
- break;
- }
- if (result == ISC_R_NOMORE) {
- dns_name_copy(gorigin, nextname, NULL);
- done = ISC_TRUE;
- } else if (result != ISC_R_SUCCESS)
- fatal("iterating through the database failed: %s",
- isc_result_totext(result));
- dns_name_downcase(name, name, NULL);
- hashlist_add_dns_name(hashlist, name, hashalg, iterations,
- salt, salt_length, ISC_FALSE);
- dns_db_detachnode(gdb, &node);
- /*
- * Add hashs for empty nodes. Use closest encloser logic.
- * The closest encloser either has data or is a empty
- * node for another <name,nextname> span so we don't add
- * it here. Empty labels on nextname are within the span.
- */
- dns_name_downcase(nextname, nextname, NULL);
- dns_name_fullcompare(name, nextname, &order, &nlabels);
- addnowildcardhash(hashlist, name, hashalg, iterations,
- salt, salt_length);
- count = dns_name_countlabels(nextname);
- while (count > nlabels + 1) {
- count--;
- dns_name_split(nextname, count, NULL, nextname);
- hashlist_add_dns_name(hashlist, nextname, hashalg,
- iterations, salt, salt_length,
- ISC_FALSE);
- addnowildcardhash(hashlist, nextname, hashalg,
- iterations, salt, salt_length);
- }
- }
- dns_dbiterator_destroy(&dbiter);
-
- /*
- * We have all the hashes now so we can sort them.
- */
- hashlist_sort(hashlist);
-
- /*
- * Check for duplicate hashes. If found the salt needs to
- * be changed.
- */
- if (hashlist_hasdup(hashlist))
- fatal("Duplicate hash detected. Pick a different salt.");
-
- /*
- * Generate the nsec3 records.
- */
- zonecut = NULL;
- done = ISC_FALSE;
-
- addnsec3param(salt, salt_length, iterations);
-
- /*
- * Clean out NSEC3 records which don't match this chain.
- */
- result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
- check_result(result, "dns_db_createiterator()");
-
- for (result = dns_dbiterator_first(dbiter);
- result == ISC_R_SUCCESS;
- result = dns_dbiterator_next(dbiter)) {
- result = dns_dbiterator_current(dbiter, &node, name);
- check_dns_dbiterator_current(result);
- nsec3clean(name, node, hashalg, iterations, salt, salt_length,
- hashlist);
- dns_db_detachnode(gdb, &node);
- }
- dns_dbiterator_destroy(&dbiter);
-
- /*
- * Generate / complete the new chain.
- */
- result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
- check_result(result, "dns_db_createiterator()");
-
- result = dns_dbiterator_first(dbiter);
- check_result(result, "dns_dbiterator_first()");
-
- while (!done) {
- result = dns_dbiterator_current(dbiter, &node, name);
- check_dns_dbiterator_current(result);
- /*
- * Skip out-of-zone records.
- */
- if (!dns_name_issubdomain(name, gorigin)) {
- result = dns_dbiterator_next(dbiter);
- if (result == ISC_R_NOMORE)
- done = ISC_TRUE;
- else
- check_result(result, "dns_dbiterator_next()");
- dns_db_detachnode(gdb, &node);
- continue;
- }
- result = dns_dbiterator_next(dbiter);
- nextnode = NULL;
- while (result == ISC_R_SUCCESS) {
- result = dns_dbiterator_current(dbiter, &nextnode,
- nextname);
- check_dns_dbiterator_current(result);
- active = active_node(nextnode);
- if (!active) {
- dns_db_detachnode(gdb, &nextnode);
- result = dns_dbiterator_next(dbiter);
- continue;
- }
- if (!dns_name_issubdomain(nextname, gorigin) ||
- (zonecut != NULL &&
- dns_name_issubdomain(nextname, zonecut))) {
- dns_db_detachnode(gdb, &nextnode);
- result = dns_dbiterator_next(dbiter);
- continue;
- }
- if (is_delegation(gdb, gversion, gorigin,
- nextname, nextnode, NULL))
- {
- zonecut = dns_fixedname_name(&fzonecut);
- dns_name_copy(nextname, zonecut, NULL);
- if (OPTOUT(nsec3flags) &&
- !secure(nextname, nextnode)) {
- dns_db_detachnode(gdb, &nextnode);
- result = dns_dbiterator_next(dbiter);
- continue;
- }
- }
- dns_db_detachnode(gdb, &nextnode);
- break;
- }
- if (result == ISC_R_NOMORE) {
- dns_name_copy(gorigin, nextname, NULL);
- done = ISC_TRUE;
- } else if (result != ISC_R_SUCCESS)
- fatal("iterating through the database failed: %s",
- isc_result_totext(result));
- /*
- * We need to pause here to release the lock on the database.
- */
- dns_dbiterator_pause(dbiter);
- addnsec3(name, node, salt, salt_length, iterations,
- hashlist, zone_soa_min_ttl);
- dns_db_detachnode(gdb, &node);
- /*
- * Add NSEC3's for empty nodes. Use closest encloser logic.
- */
- dns_name_fullcompare(name, nextname, &order, &nlabels);
- count = dns_name_countlabels(nextname);
- while (count > nlabels + 1) {
- count--;
- dns_name_split(nextname, count, NULL, nextname);
- addnsec3(nextname, NULL, salt, salt_length,
- iterations, hashlist, zone_soa_min_ttl);
- }
- }
- dns_dbiterator_destroy(&dbiter);
-}
-
-/*%
- * Load the zone file from disk
- */
-static void
-loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
- isc_buffer_t b;
- int len;
- dns_fixedname_t fname;
- dns_name_t *name;
- isc_result_t result;
-
- len = strlen(origin);
- isc_buffer_init(&b, origin, len);
- isc_buffer_add(&b, len);
-
- dns_fixedname_init(&fname);
- name = dns_fixedname_name(&fname);
- result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
- if (result != ISC_R_SUCCESS)
- fatal("failed converting name '%s' to dns format: %s",
- origin, isc_result_totext(result));
-
- result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
- rdclass, 0, NULL, db);
- check_result(result, "dns_db_create()");
-
- result = dns_db_load2(*db, file, inputformat);
- if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
- fatal("failed loading zone from '%s': %s",
- file, isc_result_totext(result));
-}
-
-/*%
- * Finds all public zone keys in the zone, and attempts to load the
- * private keys from disk.
- */
-static void
-loadzonekeys(isc_boolean_t preserve_keys, isc_boolean_t load_public) {
- dns_dbnode_t *node;
- dns_dbversion_t *currentversion = NULL;
- isc_result_t result;
- dns_rdataset_t rdataset, keysigs, soasigs;
-
- node = NULL;
- result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
- if (result != ISC_R_SUCCESS)
- fatal("failed to find the zone's origin: %s",
- isc_result_totext(result));
-
- dns_db_currentversion(gdb, &currentversion);
-
- dns_rdataset_init(&rdataset);
- dns_rdataset_init(&soasigs);
- dns_rdataset_init(&keysigs);
-
- /* Make note of the keys which signed the SOA, if any */
- result = dns_db_findrdataset(gdb, node, currentversion,
- dns_rdatatype_soa, 0, 0,
- &rdataset, &soasigs);
- if (result != ISC_R_SUCCESS)
- goto cleanup;
-
- /* Preserve the TTL of the DNSKEY RRset, if any */
- dns_rdataset_disassociate(&rdataset);
- result = dns_db_findrdataset(gdb, node, currentversion,
- dns_rdatatype_dnskey, 0, 0,
- &rdataset, &keysigs);
-
- if (result != ISC_R_SUCCESS)
- goto cleanup;
-
- if (set_keyttl && keyttl != rdataset.ttl) {
- fprintf(stderr, "User-specified TTL (%d) conflicts "
- "with existing DNSKEY RRset TTL.\n",
- keyttl);
- fprintf(stderr, "Imported keys will use the RRSet "
- "TTL (%d) instead.\n",
- rdataset.ttl);
- }
- keyttl = rdataset.ttl;
-
- /* Load keys corresponding to the existing DNSKEY RRset. */
- result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx,
- &rdataset, &keysigs, &soasigs,
- preserve_keys, load_public,
- &keylist);
- if (result != ISC_R_SUCCESS)
- fatal("failed to load the zone keys: %s",
- isc_result_totext(result));
-
- cleanup:
- if (dns_rdataset_isassociated(&rdataset))
- dns_rdataset_disassociate(&rdataset);
- if (dns_rdataset_isassociated(&keysigs))
- dns_rdataset_disassociate(&keysigs);
- if (dns_rdataset_isassociated(&soasigs))
- dns_rdataset_disassociate(&soasigs);
- dns_db_detachnode(gdb, &node);
- dns_db_closeversion(gdb, &currentversion, ISC_FALSE);
-}
-
-static void
-loadexplicitkeys(char *keyfiles[], int n, isc_boolean_t setksk) {
- isc_result_t result;
- int i;
-
- for (i = 0; i < n; i++) {
- dns_dnsseckey_t *key = NULL;
- dst_key_t *newkey = NULL;
-
- result = dst_key_fromnamedfile(keyfiles[i], directory,
- DST_TYPE_PUBLIC |
- DST_TYPE_PRIVATE,
- mctx, &newkey);
- if (result != ISC_R_SUCCESS)
- fatal("cannot load dnskey %s: %s", keyfiles[i],
- isc_result_totext(result));
-
- if (!dns_name_equal(gorigin, dst_key_name(newkey)))
- fatal("key %s not at origin\n", keyfiles[i]);
-
- if (!dst_key_isprivate(newkey))
- fatal("cannot sign zone with non-private dnskey %s",
- keyfiles[i]);
-
- /* Skip any duplicates */
- for (key = ISC_LIST_HEAD(keylist);
- key != NULL;
- key = ISC_LIST_NEXT(key, link)) {
- if (dst_key_id(key->key) == dst_key_id(newkey) &&
- dst_key_alg(key->key) == dst_key_alg(newkey))
- break;
- }
-
- if (key == NULL) {
- /* We haven't seen this key before */
- dns_dnsseckey_create(mctx, &newkey, &key);
- ISC_LIST_APPEND(keylist, key, link);
- key->source = dns_keysource_user;
- } else {
- dst_key_free(&key->key);
- key->key = newkey;
- }
-
- key->force_publish = ISC_TRUE;
- key->force_sign = ISC_TRUE;
-
- if (setksk)
- key->ksk = ISC_TRUE;
- }
-}
-
-static void
-report(const char *format, ...) {
- va_list args;
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
- putc('\n', stderr);
-}
-
-static void
-build_final_keylist() {
- isc_result_t result;
- dns_dbversion_t *ver = NULL;
- dns_diff_t diff;
- dns_dnsseckeylist_t matchkeys;
- char name[DNS_NAME_FORMATSIZE];
-
- /*
- * Find keys that match this zone in the key repository.
- */
- ISC_LIST_INIT(matchkeys);
- result = dns_dnssec_findmatchingkeys(gorigin, directory,
- mctx, &matchkeys);
- if (result == ISC_R_NOTFOUND)
- result = ISC_R_SUCCESS;
- check_result(result, "dns_dnssec_findmatchingkeys");
-
- result = dns_db_newversion(gdb, &ver);
- check_result(result, "dns_db_newversion");
-
- dns_diff_init(mctx, &diff);
-
- /*
- * Update keylist with information from from the key repository.
- */
- dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
- &diff, ignore_kskflag, mctx, report);
-
- dns_name_format(gorigin, name, sizeof(name));
-
- result = dns_diff_applysilently(&diff, gdb, ver);
- if (result != ISC_R_SUCCESS)
- fatal("failed to update DNSKEY RRset at node '%s': %s",
- name, isc_result_totext(result));
-
- dns_db_closeversion(gdb, &ver, ISC_TRUE);
-
- dns_diff_clear(&diff);
-}
-
-static void
-warnifallksk(dns_db_t *db) {
- dns_dbversion_t *currentversion = NULL;
- dns_dbnode_t *node = NULL;
- dns_rdataset_t rdataset;
- dns_rdata_t rdata = DNS_RDATA_INIT;
- isc_result_t result;
- dns_rdata_dnskey_t dnskey;
- isc_boolean_t have_non_ksk = ISC_FALSE;
-
- dns_db_currentversion(db, &currentversion);
-
- result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
- if (result != ISC_R_SUCCESS)
- fatal("failed to find the zone's origin: %s",
- isc_result_totext(result));
-
- dns_rdataset_init(&rdataset);
- result = dns_db_findrdataset(db, node, currentversion,
- dns_rdatatype_dnskey, 0, 0, &rdataset,
- NULL);
- if (result != ISC_R_SUCCESS)
- fatal("failed to find keys at the zone apex: %s",
- isc_result_totext(result));
- result = dns_rdataset_first(&rdataset);
- check_result(result, "dns_rdataset_first");
- while (result == ISC_R_SUCCESS) {
- dns_rdata_reset(&rdata);
- dns_rdataset_current(&rdataset, &rdata);
- result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
- check_result(result, "dns_rdata_tostruct");
- if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
- have_non_ksk = ISC_TRUE;
- result = ISC_R_NOMORE;
- } else
- result = dns_rdataset_next(&rdataset);
- dns_rdata_freestruct(&dnskey);
- }
- dns_rdataset_disassociate(&rdataset);
- dns_db_detachnode(db, &node);
- dns_db_closeversion(db, &currentversion, ISC_FALSE);
- if (!have_non_ksk && !ignore_kskflag) {
- if (disable_zone_check)
- fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
- "supply a ZSK or use '-z'.\n",
- program);
- else
- fatal("No non-KSK DNSKEY found; "
- "supply a ZSK or use '-z'.");
- }
-}
-
-static void
-set_nsec3params(isc_boolean_t update_chain, isc_boolean_t set_salt,
- isc_boolean_t set_optout, isc_boolean_t set_iter)
-{
- isc_result_t result;
- dns_dbversion_t *ver = NULL;
- dns_dbnode_t *node = NULL;
- dns_rdataset_t rdataset;
- dns_rdata_t rdata = DNS_RDATA_INIT;
- dns_rdata_nsec3_t nsec3;
- dns_fixedname_t fname;
- dns_name_t *hashname;
- unsigned char orig_salt[255];
- size_t orig_saltlen;
- dns_hash_t orig_hash;
- isc_uint16_t orig_iter;
-
- dns_db_currentversion(gdb, &ver);
- dns_rdataset_init(&rdataset);
-
- orig_saltlen = sizeof(orig_salt);
- result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
- &orig_iter, orig_salt,
- &orig_saltlen);
- if (result != ISC_R_SUCCESS)
- goto cleanup;
-
- nsec_datatype = dns_rdatatype_nsec3;
-
- if (!update_chain && set_salt) {
- if (salt_length != orig_saltlen ||
- memcmp(saltbuf, orig_salt, salt_length) != 0)
- fatal("An NSEC3 chain exists with a different salt. "
- "Use -u to update it.");
- } else if (!set_salt) {
- salt_length = orig_saltlen;
- memcpy(saltbuf, orig_salt, orig_saltlen);
- salt = saltbuf;
- }
-
- if (!update_chain && set_iter) {
- if (nsec3iter != orig_iter)
- fatal("An NSEC3 chain exists with different "
- "iterations. Use -u to update it.");
- } else if (!set_iter)
- nsec3iter = orig_iter;
-
- /*
- * Find an NSEC3 record to get the current OPTOUT value.
- * (This assumes all NSEC3 records agree.)
- */
-
- dns_fixedname_init(&fname);
- hashname = dns_fixedname_name(&fname);
- result = dns_nsec3_hashname(&fname, NULL, NULL,
- gorigin, gorigin, dns_hash_sha1,
- orig_iter, orig_salt, orig_saltlen);
- check_result(result, "dns_nsec3_hashname");
-
- result = dns_db_findnsec3node(gdb, hashname, ISC_FALSE, &node);
- if (result != ISC_R_SUCCESS)
- goto cleanup;
-
- result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3,
- 0, 0, &rdataset, NULL);
- if (result != ISC_R_SUCCESS)
- goto cleanup;
-
- result = dns_rdataset_first(&rdataset);
- check_result(result, "dns_rdataset_first");
- dns_rdataset_current(&rdataset, &rdata);
- result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
- check_result(result, "dns_rdata_tostruct");
-
- if (!update_chain && set_optout) {
- if (nsec3flags != nsec3.flags)
- fatal("An NSEC3 chain exists with%s OPTOUT. "
- "Use -u -%s to %s it.",
- OPTOUT(nsec3.flags) ? "" : "out",
- OPTOUT(nsec3.flags) ? "AA" : "A",
- OPTOUT(nsec3.flags) ? "clear" : "set");
- } else if (!set_optout)
- nsec3flags = nsec3.flags;
-
- dns_rdata_freestruct(&nsec3);
-
- cleanup:
- if (dns_rdataset_isassociated(&rdataset))
- dns_rdataset_disassociate(&rdataset);
- if (node != NULL)
- dns_db_detachnode(gdb, &node);
- dns_db_closeversion(gdb, &ver, ISC_FALSE);
-}
-
-static void
-writeset(const char *prefix, dns_rdatatype_t type) {
- char *filename;
- char namestr[DNS_NAME_FORMATSIZE];
- dns_db_t *db = NULL;
- dns_dbversion_t *version = NULL;
- dns_diff_t diff;
- dns_difftuple_t *tuple = NULL;
- dns_fixedname_t fixed;
- dns_name_t *name;
- dns_rdata_t rdata, ds;
- isc_boolean_t have_ksk = ISC_FALSE;
- isc_boolean_t have_non_ksk = ISC_FALSE;
- isc_buffer_t b;
- isc_buffer_t namebuf;
- isc_region_t r;
- isc_result_t result;
- dns_dnsseckey_t *key, *tmpkey;
- unsigned char dsbuf[DNS_DS_BUFFERSIZE];
- unsigned char keybuf[DST_KEY_MAXSIZE];
- unsigned int filenamelen;
- const dns_master_style_t *style =
- (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
-
- isc_buffer_init(&namebuf, namestr, sizeof(namestr));
- result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
- check_result(result, "dns_name_tofilenametext");
- isc_buffer_putuint8(&namebuf, 0);
- filenamelen = strlen(prefix) + strlen(namestr);
- if (dsdir != NULL)
- filenamelen += strlen(dsdir) + 1;
- filename = isc_mem_get(mctx, filenamelen + 1);
- if (filename == NULL)
- fatal("out of memory");
- if (dsdir != NULL)
- sprintf(filename, "%s/", dsdir);
- else
- filename[0] = 0;
- strcat(filename, prefix);
- strcat(filename, namestr);
-
- dns_diff_init(mctx, &diff);
-
- if (type == dns_rdatatype_dlv) {
- dns_name_t tname;
- unsigned int labels;
-
- dns_name_init(&tname, NULL);
- dns_fixedname_init(&fixed);
- name = dns_fixedname_name(&fixed);
- labels = dns_name_countlabels(gorigin);
- dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
- result = dns_name_concatenate(&tname, dlv, name, NULL);
- check_result(result, "dns_name_concatenate");
- } else
- name = gorigin;
-
- for (key = ISC_LIST_HEAD(keylist);
- key != NULL;
- key = ISC_LIST_NEXT(key, link))
- {
- if (REVOKE(key->key))
- continue;
- if (isksk(key)) {
- have_ksk = ISC_TRUE;
- have_non_ksk = ISC_FALSE;
- } else {
- have_ksk = ISC_FALSE;
- have_non_ksk = ISC_TRUE;
- }
- for (tmpkey = ISC_LIST_HEAD(keylist);
- tmpkey != NULL;
- tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
- if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
- continue;
- if (REVOKE(tmpkey->key))
- continue;
- if (isksk(tmpkey))
- have_ksk = ISC_TRUE;
- else
- have_non_ksk = ISC_TRUE;
- }
- if (have_ksk && have_non_ksk && !isksk(key))
- continue;
- dns_rdata_init(&rdata);
- dns_rdata_init(&ds);
- isc_buffer_init(&b, keybuf, sizeof(keybuf));
- result = dst_key_todns(key->key, &b);
- check_result(result, "dst_key_todns");
- isc_buffer_usedregion(&b, &r);
- dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
- if (type != dns_rdatatype_dnskey) {
- result = dns_ds_buildrdata(gorigin, &rdata,
- DNS_DSDIGEST_SHA1,
- dsbuf, &ds);
- check_result(result, "dns_ds_buildrdata");
- if (type == dns_rdatatype_dlv)
- ds.type = dns_rdatatype_dlv;
- result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
- name, 0, &ds, &tuple);
- check_result(result, "dns_difftuple_create");
- dns_diff_append(&diff, &tuple);
-
- dns_rdata_reset(&ds);
- result = dns_ds_buildrdata(gorigin, &rdata,
- DNS_DSDIGEST_SHA256,
- dsbuf, &ds);
- check_result(result, "dns_ds_buildrdata");
- if (type == dns_rdatatype_dlv)
- ds.type = dns_rdatatype_dlv;
- result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
- name, 0, &ds, &tuple);
-
- } else
- result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
- gorigin, zone_soa_min_ttl,
- &rdata, &tuple);
- check_result(result, "dns_difftuple_create");
- dns_diff_append(&diff, &tuple);
- }
-
- result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
- gclass, 0, NULL, &db);
- check_result(result, "dns_db_create");
-
- result = dns_db_newversion(db, &version);
- check_result(result, "dns_db_newversion");
-
- result = dns_diff_apply(&diff, db, version);
- check_result(result, "dns_diff_apply");
- dns_diff_clear(&diff);
-
- result = dns_master_dump(mctx, db, version, style, filename);
- check_result(result, "dns_master_dump");
-
- isc_mem_put(mctx, filename, filenamelen + 1);
-
- dns_db_closeversion(db, &version, ISC_FALSE);
- dns_db_detach(&db);
-}
-
-static void
-print_time(FILE *fp) {
- time_t currenttime;
-
- if (outputformat != dns_masterformat_text)
- return;
-
- currenttime = time(NULL);
- fprintf(fp, "; File written on %s", ctime(&currenttime));
-}
-
-static void
-print_version(FILE *fp) {
- if (outputformat != dns_masterformat_text)
- return;
-
- fprintf(fp, "; dnssec_signzone version " VERSION "\n");
-}
-
-ISC_PLATFORM_NORETURN_PRE static void
-usage(void) ISC_PLATFORM_NORETURN_POST;
-
-static void
-usage(void) {
- fprintf(stderr, "Usage:\n");
- fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
-
- fprintf(stderr, "\n");
-
- fprintf(stderr, "Version: %s\n", VERSION);
-
- fprintf(stderr, "Options: (default value in parenthesis) \n");
- fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
- "\t\tfor the zone and determines how they are to "
- "be used\n");
- fprintf(stderr, "\t-K directory:\n");
- fprintf(stderr, "\t\tdirectory to find key files (.)\n");
- fprintf(stderr, "\t-d directory:\n");
- fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
- fprintf(stderr, "\t-g:\t");
- fprintf(stderr, "update DS records based on child zones' "
- "dsset-* files\n");
- fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
- fprintf(stderr, "\t\tRRSIG start time "
- "- absolute|offset (now - 1 hour)\n");
- fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
- fprintf(stderr, "\t\tRRSIG end time "
- "- absolute|from start|from now "
- "(now + 30 days)\n");
- fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
- fprintf(stderr, "\t\tDNSKEY RRSIG end "
- "- absolute|from start|from now "
- "(matches -e)\n");
- fprintf(stderr, "\t-i interval:\n");
- fprintf(stderr, "\t\tcycle interval - resign "
- "if < interval from end ( (end-start)/4 )\n");
- fprintf(stderr, "\t-j jitter:\n");
- fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
- fprintf(stderr, "\t-v debuglevel (0)\n");
- fprintf(stderr, "\t-o origin:\n");
- fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
- fprintf(stderr, "\t-f outfile:\n");
- fprintf(stderr, "\t\tfile the signed zone is written in "
- "(zonefile + .signed)\n");
- fprintf(stderr, "\t-I format:\n");
- fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
- fprintf(stderr, "\t-O format:\n");
- fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
- fprintf(stderr, "\t-N format:\n");
- fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
- fprintf(stderr, "\t-D:\n");
- fprintf(stderr, "\t\toutput only DNSSEC-related records\n");
- fprintf(stderr, "\t-r randomdev:\n");
- fprintf(stderr, "\t\ta file containing random data\n");
- fprintf(stderr, "\t-a:\t");
- fprintf(stderr, "verify generated signatures\n");
- fprintf(stderr, "\t-c class (IN)\n");
- fprintf(stderr, "\t-E engine:\n");
-#ifdef USE_PKCS11
- fprintf(stderr, "\t\tname of an OpenSSL engine to use "
- "(default is \"pkcs11\")\n");
-#else
- fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
-#endif
- fprintf(stderr, "\t-p:\t");
- fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
- fprintf(stderr, "\t-P:\t");
- fprintf(stderr, "disable post-sign verification\n");
- fprintf(stderr, "\t-R:\t");
- fprintf(stderr, "remove signatures from keys that no longer exist\n");
- fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
- fprintf(stderr, "\t-t:\t");
- fprintf(stderr, "print statistics\n");
- fprintf(stderr, "\t-u:\t");
- fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
- fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
- fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
- fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
- "\t\twith older versions of dnssec-signzone -g\n");
- fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
- fprintf(stderr, "\t-k key_signing_key\n");
- fprintf(stderr, "\t-l lookasidezone\n");
- fprintf(stderr, "\t-3 NSEC3 salt\n");
- fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
- fprintf(stderr, "\t-A NSEC3 optout\n");
-
- fprintf(stderr, "\n");
-
- fprintf(stderr, "Signing Keys: ");
- fprintf(stderr, "(default: all zone keys that have private keys)\n");
- fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
- exit(0);
-}
-
-static void
-removetempfile(void) {
- if (removefile)
- isc_file_remove(tempfile);
-}
-
-static void
-print_stats(isc_time_t *timer_start, isc_time_t *timer_finish,
- isc_time_t *sign_start, isc_time_t *sign_finish)
-{
- isc_uint64_t time_us; /* Time in microseconds */
- isc_uint64_t time_ms; /* Time in milliseconds */
- isc_uint64_t sig_ms; /* Signatures per millisecond */
- FILE *out = output_stdout ? stderr : stdout;
-
- fprintf(out, "Signatures generated: %10d\n", nsigned);
- fprintf(out, "Signatures retained: %10d\n", nretained);
- fprintf(out, "Signatures dropped: %10d\n", ndropped);
- fprintf(out, "Signatures successfully verified: %10d\n", nverified);
- fprintf(out, "Signatures unsuccessfully "
- "verified: %10d\n", nverifyfailed);
-
- time_us = isc_time_microdiff(sign_finish, sign_start);
- time_ms = time_us / 1000;
- fprintf(out, "Signing time in seconds: %7u.%03u\n",
- (unsigned int) (time_ms / 1000),
- (unsigned int) (time_ms % 1000));
- if (time_us > 0) {
- sig_ms = ((isc_uint64_t)nsigned * 1000000000) / time_us;
- fprintf(out, "Signatures per second: %7u.%03u\n",
- (unsigned int) sig_ms / 1000,
- (unsigned int) sig_ms % 1000);
- }
-
- time_us = isc_time_microdiff(timer_finish, timer_start);
- time_ms = time_us / 1000;
- fprintf(out, "Runtime in seconds: %7u.%03u\n",
- (unsigned int) (time_ms / 1000),
- (unsigned int) (time_ms % 1000));
-}
-
-int
-main(int argc, char *argv[]) {
- int i, ch;
- char *startstr = NULL, *endstr = NULL, *classname = NULL;
- char *dnskey_endstr = NULL;
- char *origin = NULL, *file = NULL, *output = NULL;
- char *inputformatstr = NULL, *outputformatstr = NULL;
- char *serialformatstr = NULL;
- char *dskeyfile[MAXDSKEYS];
- int ndskeys = 0;
- char *endp;
- isc_time_t timer_start, timer_finish;
- isc_time_t sign_start, sign_finish;
- dns_dnsseckey_t *key;
- isc_result_t result;
- isc_log_t *log = NULL;
- isc_boolean_t pseudorandom = ISC_FALSE;
-#ifdef USE_PKCS11
- const char *engine = "pkcs11";
-#else
- const char *engine = NULL;
-#endif
- unsigned int eflags;
- isc_boolean_t free_output = ISC_FALSE;
- int tempfilelen = 0;
- dns_rdataclass_t rdclass;
- isc_task_t **tasks = NULL;
- isc_buffer_t b;
- int len;
- hashlist_t hashlist;
- isc_boolean_t make_keyset = ISC_FALSE;
- isc_boolean_t set_salt = ISC_FALSE;
- isc_boolean_t set_optout = ISC_FALSE;
- isc_boolean_t set_iter = ISC_FALSE;
- isc_boolean_t nonsecify = ISC_FALSE;
-
-#define CMDLINE_FLAGS \
- "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:n:N:o:O:PpRr:s:ST:tuUv:X:xzZ:"
-
- /*
- * Process memory debugging argument first.
- */
- while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
- switch (ch) {
- case 'm':
- if (strcasecmp(isc_commandline_argument, "record") == 0)
- isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
- if (strcasecmp(isc_commandline_argument, "trace") == 0)
- isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
- if (strcasecmp(isc_commandline_argument, "usage") == 0)
- isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
- if (strcasecmp(isc_commandline_argument, "size") == 0)
- isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
- if (strcasecmp(isc_commandline_argument, "mctx") == 0)
- isc_mem_debugging |= ISC_MEM_DEBUGCTX;
- break;
- default:
- break;
- }
- }
- isc_commandline_reset = ISC_TRUE;
-
- masterstyle = &dns_master_style_explicitttl;
-
- check_result(isc_app_start(), "isc_app_start");
-
- result = isc_mem_create(0, 0, &mctx);
- if (result != ISC_R_SUCCESS)
- fatal("out of memory");
-
- dns_result_register();
-
- isc_commandline_errprint = ISC_FALSE;
-
- while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
- switch (ch) {
- case '3':
- set_salt = ISC_TRUE;
- nsec_datatype = dns_rdatatype_nsec3;
- if (strcmp(isc_commandline_argument, "-") != 0) {
- isc_buffer_t target;
- char *sarg;
-
- sarg = isc_commandline_argument;
- isc_buffer_init(&target, saltbuf,
- sizeof(saltbuf));
- result = isc_hex_decodestring(sarg, &target);
- check_result(result,
- "isc_hex_decodestring(salt)");
- salt_length = isc_buffer_usedlength(&target);
- }
- break;
-
- case 'A':
- set_optout = ISC_TRUE;
- if (OPTOUT(nsec3flags))
- nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
- else
- nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
- break;
-
- case 'a':
- tryverify = ISC_TRUE;
- break;
-
- case 'C':
- make_keyset = ISC_TRUE;
- break;
-
- case 'c':
- classname = isc_commandline_argument;
- break;
-
- case 'd':
- dsdir = isc_commandline_argument;
- if (strlen(dsdir) == 0U)
- fatal("DS directory must be non-empty string");
- result = try_dir(dsdir);
- if (result != ISC_R_SUCCESS)
- fatal("cannot open directory %s: %s",
- dsdir, isc_result_totext(result));
- break;
-
- case 'D':
- output_dnssec_only = ISC_TRUE;
- break;
-
- case 'E':
- engine = isc_commandline_argument;
- break;
-
- case 'e':
- endstr = isc_commandline_argument;
- break;
-
- case 'f':
- output = isc_commandline_argument;
- if (strcmp(output, "-") == 0)
- output_stdout = ISC_TRUE;
- break;
-
- case 'g':
- generateds = ISC_TRUE;
- break;
-
- case 'H':
- set_iter = ISC_TRUE;
- nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
- if (*endp != '\0')
- fatal("iterations must be numeric");
- if (nsec3iter > 0xffffU)
- fatal("iterations too big");
- break;
-
- case 'h':
- usage();
- break;
-
- case 'I':
- inputformatstr = isc_commandline_argument;
- break;
-
- case 'i':
- endp = NULL;
- cycle = strtol(isc_commandline_argument, &endp, 0);
- if (*endp != '\0' || cycle < 0)
- fatal("cycle period must be numeric and "
- "positive");
- break;
-
- case 'j':
- endp = NULL;
- jitter = strtol(isc_commandline_argument, &endp, 0);
- if (*endp != '\0' || jitter < 0)
- fatal("jitter must be numeric and positive");
- break;
-
- case 'K':
- directory = isc_commandline_argument;
- break;
-
- case 'k':
- if (ndskeys == MAXDSKEYS)
- fatal("too many key-signing keys specified");
- dskeyfile[ndskeys++] = isc_commandline_argument;
- break;
-
- case 'L':
- snset = ISC_TRUE;
- endp = NULL;
- serialnum = strtol(isc_commandline_argument, &endp, 0);
- if (*endp != '\0') {
- fprintf(stderr, "source serial number "
- "must be numeric");
- exit(1);
- }
- break;
-
- case 'l':
- len = strlen(isc_commandline_argument);
- isc_buffer_init(&b, isc_commandline_argument, len);
- isc_buffer_add(&b, len);
-
- dns_fixedname_init(&dlv_fixed);
- dlv = dns_fixedname_name(&dlv_fixed);
- result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
- NULL);
- check_result(result, "dns_name_fromtext(dlv)");
- break;
-
- case 'm':
- break;
-
- case 'N':
- serialformatstr = isc_commandline_argument;
- break;
-
- case 'n':
- endp = NULL;
- ntasks = strtol(isc_commandline_argument, &endp, 0);
- if (*endp != '\0' || ntasks > ISC_INT32_MAX)
- fatal("number of cpus must be numeric");
- break;
-
- case 'O':
- outputformatstr = isc_commandline_argument;
- break;
-
- case 'o':
- origin = isc_commandline_argument;
- break;
-
- case 'P':
- disable_zone_check = ISC_TRUE;
- break;
-
- case 'p':
- pseudorandom = ISC_TRUE;
- break;
-
- case 'R':
- remove_orphans = ISC_TRUE;
- break;
-
- case 'r':
- setup_entropy(mctx, isc_commandline_argument, &ectx);
- break;
-
- case 'S':
- smartsign = ISC_TRUE;
- break;
-
- case 's':
- startstr = isc_commandline_argument;
- break;
-
- case 'T':
- endp = NULL;
- set_keyttl = ISC_TRUE;
- keyttl = strtottl(isc_commandline_argument);
- break;
-
- case 't':
- printstats = ISC_TRUE;
- break;
-
- case 'U': /* Undocumented for testing only. */
- unknownalg = ISC_TRUE;
- break;
-
- case 'u':
- update_chain = ISC_TRUE;
- break;
-
- case 'v':
- endp = NULL;
- verbose = strtol(isc_commandline_argument, &endp, 0);
- if (*endp != '\0')
- fatal("verbose level must be numeric");
- break;
-
- case 'X':
- dnskey_endstr = isc_commandline_argument;
- break;
-
- case 'x':
- keyset_kskonly = ISC_TRUE;
- break;
-
- case 'z':
- ignore_kskflag = ISC_TRUE;
- break;
-
- case 'F':
- /* Reserved for FIPS mode */
- /* FALLTHROUGH */
- case '?':
- if (isc_commandline_option != '?')
- fprintf(stderr, "%s: invalid argument -%c\n",
- program, isc_commandline_option);
- usage();
- break;
-
- default:
- fprintf(stderr, "%s: unhandled option -%c\n",
- program, isc_commandline_option);
- exit(1);
- case 'Z': /* Undocumented test options */
- if (!strcmp(isc_commandline_argument, "nonsecify"))
- nonsecify = ISC_TRUE;
- break;
- }
- }
-
- if (ectx == NULL)
- setup_entropy(mctx, NULL, &ectx);
- eflags = ISC_ENTROPY_BLOCKING;
- if (!pseudorandom)
- eflags |= ISC_ENTROPY_GOODONLY;
-
- result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
- if (result != ISC_R_SUCCESS)
- fatal("could not create hash context");
-
- result = dst_lib_init2(mctx, ectx, engine, eflags);
- if (result != ISC_R_SUCCESS)
- fatal("could not initialize dst: %s",
- isc_result_totext(result));
-
- isc_stdtime_get(&now);
-
- if (startstr != NULL) {
- starttime = strtotime(startstr, now, now);
- } else
- starttime = now - 3600; /* Allow for some clock skew. */
-
- if (endstr != NULL)
- endtime = strtotime(endstr, now, starttime);
- else
- endtime = starttime + (30 * 24 * 60 * 60);
-
- if (dnskey_endstr != NULL) {
- dnskey_endtime = strtotime(dnskey_endstr, now, starttime);
- if (endstr != NULL && dnskey_endtime == endtime)
- fprintf(stderr, "WARNING: -e and -X were both set, "
- "but have identical values.\n");
- } else
- dnskey_endtime = endtime;
-
- if (cycle == -1)
- cycle = (endtime - starttime) / 4;
-
- if (ntasks == 0)
- ntasks = isc_os_ncpus() * 2;
- vbprintf(4, "using %d cpus\n", ntasks);
-
- rdclass = strtoclass(classname);
-
- if (directory == NULL)
- directory = ".";
-
- setup_logging(verbose, mctx, &log);
-
- argc -= isc_commandline_index;
- argv += isc_commandline_index;
-
- if (argc < 1)
- usage();
-
- file = argv[0];
-
- argc -= 1;
- argv += 1;
-
- if (origin == NULL)
- origin = file;
-
- if (output == NULL) {
- free_output = ISC_TRUE;
- output = isc_mem_allocate(mctx,
- strlen(file) + strlen(".signed") + 1);
- if (output == NULL)
- fatal("out of memory");
- sprintf(output, "%s.signed", file);
- }
-
- if (inputformatstr != NULL) {
- if (strcasecmp(inputformatstr, "text") == 0)
- inputformat = dns_masterformat_text;
- else if (strcasecmp(inputformatstr, "raw") == 0)
- inputformat = dns_masterformat_raw;
- else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
- inputformat = dns_masterformat_raw;
- fprintf(stderr,
- "WARNING: input format version ignored\n");
- } else
- fatal("unknown file format: %s", inputformatstr);
-
- }
-
- if (outputformatstr != NULL) {
- if (strcasecmp(outputformatstr, "text") == 0) {
- outputformat = dns_masterformat_text;
- } else if (strcasecmp(outputformatstr, "full") == 0) {
- outputformat = dns_masterformat_text;
- masterstyle = &dns_master_style_full;
- } else if (strcasecmp(outputformatstr, "raw") == 0) {
- outputformat = dns_masterformat_raw;
- } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
- char *end;
- outputformat = dns_masterformat_raw;
-
- outputformat = dns_masterformat_raw;
- rawversion = strtol(outputformatstr + 4, &end, 10);
- if (end == outputformatstr + 4 || *end != '\0' ||
- rawversion > 1U) {
- fprintf(stderr,
- "unknown raw format version\n");
- exit(1);
- }
- } else
- fatal("unknown file format: %s\n", outputformatstr);
- }
-
- if (serialformatstr != NULL) {
- if (strcasecmp(serialformatstr, "keep") == 0)
- serialformat = SOA_SERIAL_KEEP;
- else if (strcasecmp(serialformatstr, "increment") == 0 ||
- strcasecmp(serialformatstr, "incr") == 0)
- serialformat = SOA_SERIAL_INCREMENT;
- else if (strcasecmp(serialformatstr, "unixtime") == 0)
- serialformat = SOA_SERIAL_UNIXTIME;
- else
- fatal("unknown soa serial format: %s\n",
- serialformatstr);
- }
-
- if (output_dnssec_only && outputformat != dns_masterformat_text)
- fatal("option -D can only be used with \"-O text\"\n");
-
- if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP)
- fatal("option -D can only be used with \"-N keep\"\n");
-
- result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
- 0, 24, 0, 0, 0, 8, mctx);
- check_result(result, "dns_master_stylecreate");
-
- gdb = NULL;
- TIME_NOW(&timer_start);
- loadzone(file, origin, rdclass, &gdb);
- gorigin = dns_db_origin(gdb);
- gclass = dns_db_class(gdb);
- get_soa_ttls();
-
- if (!set_keyttl)
- keyttl = soa_ttl;
-
- /*
- * Check for any existing NSEC3 parameters in the zone,
- * and use them as defaults if -u was not specified.
- */
- if (update_chain && !set_optout && !set_iter && !set_salt)
- nsec_datatype = dns_rdatatype_nsec;
- else
- set_nsec3params(update_chain, set_salt, set_optout, set_iter);
-
- /*
- * We need to do this early on, as we start messing with the list
- * of keys rather early.
- */
- ISC_LIST_INIT(keylist);
- isc_rwlock_init(&keylist_lock, 0, 0);
-
- /*
- * Fill keylist with:
- * 1) Keys listed in the DNSKEY set that have
- * private keys associated, *if* no keys were
- * set on the command line.
- * 2) ZSKs set on the command line
- * 3) KSKs set on the command line
- * 4) Any keys remaining in the DNSKEY set which
- * do not have private keys associated and were
- * not specified on the command line.
- */
- if (argc == 0 || smartsign)
- loadzonekeys(!smartsign, ISC_FALSE);
- loadexplicitkeys(argv, argc, ISC_FALSE);
- loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE);
- loadzonekeys(!smartsign, ISC_TRUE);
-
- /*
- * If we're doing smart signing, look in the key repository for
- * key files with metadata, and merge them with the keylist
- * we have now.
- */
- if (smartsign)
- build_final_keylist();
-
- /* Now enumerate the key list */
- for (key = ISC_LIST_HEAD(keylist);
- key != NULL;
- key = ISC_LIST_NEXT(key, link)) {
- key->index = keycount++;
- }
-
- if (keycount == 0) {
- if (disable_zone_check)
- fprintf(stderr, "%s: warning: No keys specified "
- "or found\n", program);
- else
- fatal("No signing keys specified or found.");
- nokeys = ISC_TRUE;
- }
-
- warnifallksk(gdb);
-
- if (IS_NSEC3) {
- unsigned int max;
- isc_boolean_t answer;
-
- hash_length = dns_nsec3_hashlength(dns_hash_sha1);
- hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
- hash_length);
- result = dns_nsec_nseconly(gdb, gversion, &answer);
- if (result == ISC_R_NOTFOUND)
- fprintf(stderr, "%s: warning: NSEC3 generation "
- "requested with no DNSKEY; ignoring\n",
- program);
- else if (result != ISC_R_SUCCESS)
- check_result(result, "dns_nsec_nseconly");
- else if (answer)
- fatal("NSEC3 generation requested with "
- "NSEC-only DNSKEY");
-
- result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
- check_result(result, "dns_nsec3_maxiterations()");
- if (nsec3iter > max)
- fatal("NSEC3 iterations too big for weakest DNSKEY "
- "strength. Maximum iterations allowed %u.", max);
- }
-
- gversion = NULL;
- result = dns_db_newversion(gdb, &gversion);
- check_result(result, "dns_db_newversion()");
-
- switch (serialformat) {
- case SOA_SERIAL_INCREMENT:
- setsoaserial(0);
- break;
- case SOA_SERIAL_UNIXTIME:
- setsoaserial(now);
- break;
- case SOA_SERIAL_KEEP:
- default:
- /* do nothing */
- break;
- }
-
- remove_duplicates();
-
- if (!nonsecify) {
- if (IS_NSEC3)
- nsec3ify(dns_hash_sha1, nsec3iter, salt, salt_length,
- &hashlist);
- else
- nsecify();
- }
-
- if (!nokeys) {
- writeset("dsset-", dns_rdatatype_ds);
- if (make_keyset)
- writeset("keyset-", dns_rdatatype_dnskey);
- if (dlv != NULL) {
- writeset("dlvset-", dns_rdatatype_dlv);
- }
- }
-
- if (output_stdout) {
- fp = stdout;
- if (outputformatstr == NULL)
- masterstyle = &dns_master_style_full;
- } else {
- tempfilelen = strlen(output) + 20;
- tempfile = isc_mem_get(mctx, tempfilelen);
- if (tempfile == NULL)
- fatal("out of memory");
-
- result = isc_file_mktemplate(output, tempfile, tempfilelen);
- check_result(result, "isc_file_mktemplate");
-
- if (outputformat == dns_masterformat_text)
- result = isc_file_openunique(tempfile, &fp);
- else
- result = isc_file_bopenunique(tempfile, &fp);
- if (result != ISC_R_SUCCESS)
- fatal("failed to open temporary output file: %s",
- isc_result_totext(result));
- removefile = ISC_TRUE;
- setfatalcallback(&removetempfile);
- }
-
- print_time(fp);
- print_version(fp);
-
- result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
- if (result != ISC_R_SUCCESS)
- fatal("failed to create task manager: %s",
- isc_result_totext(result));
-
- master = NULL;
- result = isc_task_create(taskmgr, 0, &master);
- if (result != ISC_R_SUCCESS)
- fatal("failed to create task: %s", isc_result_totext(result));
-
- tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
- if (tasks == NULL)
- fatal("out of memory");
- for (i = 0; i < (int)ntasks; i++) {
- tasks[i] = NULL;
- result = isc_task_create(taskmgr, 0, &tasks[i]);
- if (result != ISC_R_SUCCESS)
- fatal("failed to create task: %s",
- isc_result_totext(result));
- }
-
- RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
- if (printstats)
- RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
-
- presign();
- TIME_NOW(&sign_start);
- signapex();
- if (!finished) {
- /*
- * There is more work to do. Spread it out over multiple
- * processors if possible.
- */
- for (i = 0; i < (int)ntasks; i++) {
- result = isc_app_onrun(mctx, master, startworker,
- tasks[i]);
- if (result != ISC_R_SUCCESS)
- fatal("failed to start task: %s",
- isc_result_totext(result));
- }
- (void)isc_app_run();
- if (!finished)
- fatal("process aborted by user");
- } else
- isc_task_detach(&master);
- shuttingdown = ISC_TRUE;
- for (i = 0; i < (int)ntasks; i++)
- isc_task_detach(&tasks[i]);
- isc_taskmgr_destroy(&taskmgr);
- isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
- postsign();
- TIME_NOW(&sign_finish);
-
- if (!disable_zone_check)
- verifyzone(gdb, gversion, gorigin, mctx,
- ignore_kskflag, keyset_kskonly);
-
- if (outputformat != dns_masterformat_text) {
- dns_masterrawheader_t header;
- dns_master_initrawheader(&header);
- if (rawversion == 0U)
- header.flags = DNS_MASTERRAW_COMPAT;
- else if (snset) {
- header.flags = DNS_MASTERRAW_SOURCESERIALSET;
- header.sourceserial = serialnum;
- }
- result = dns_master_dumptostream3(mctx, gdb, gversion,
- masterstyle, outputformat,
- &header, fp);
- check_result(result, "dns_master_dumptostream3");
- }
-
- DESTROYLOCK(&namelock);
- if (printstats)
- DESTROYLOCK(&statslock);
-
- if (!output_stdout) {
- result = isc_stdio_close(fp);
- check_result(result, "isc_stdio_close");
- removefile = ISC_FALSE;
-
- result = isc_file_rename(tempfile, output);
- if (result != ISC_R_SUCCESS)
- fatal("failed to rename temp file to %s: %s\n",
- output, isc_result_totext(result));
-
- printf("%s\n", output);
- }
-
- dns_db_closeversion(gdb, &gversion, ISC_FALSE);
- dns_db_detach(&gdb);
-
- while (!ISC_LIST_EMPTY(keylist)) {
- key = ISC_LIST_HEAD(keylist);
- ISC_LIST_UNLINK(keylist, key, link);
- dns_dnsseckey_destroy(mctx, &key);
- }
-
- if (tempfilelen != 0)
- isc_mem_put(mctx, tempfile, tempfilelen);
-
- if (free_output)
- isc_mem_free(mctx, output);
-
- dns_master_styledestroy(&dsstyle, mctx);
-
- cleanup_logging(&log);
- dst_lib_destroy();
- isc_hash_destroy();
- cleanup_entropy(&ectx);
- dns_name_destroy();
- if (verbose > 10)
- isc_mem_stats(mctx, stdout);
- isc_mem_destroy(&mctx);
-
- (void) isc_app_finish();
-
- if (printstats) {
- TIME_NOW(&timer_finish);
- print_stats(&timer_start, &timer_finish,
- &sign_start, &sign_finish);
- }
-
- return (0);
-}