summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib/dns/zone.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/lib/dns/zone.c')
-rw-r--r--contrib/bind9/lib/dns/zone.c696
1 files changed, 412 insertions, 284 deletions
diff --git a/contrib/bind9/lib/dns/zone.c b/contrib/bind9/lib/dns/zone.c
index c727c2e..9e05684 100644
--- a/contrib/bind9/lib/dns/zone.c
+++ b/contrib/bind9/lib/dns/zone.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.c,v 1.582.8.7 2011-02-18 23:23:08 each Exp $ */
+/* $Id: zone.c,v 1.582.8.26 2011-08-09 02:34:24 marka Exp $ */
/*! \file */
@@ -109,12 +109,20 @@
#define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
+/*%
+ * Key flags
+ */
+#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
+#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
+#define ALG(x) dst_key_alg(x)
+
/*
* Default values.
*/
#define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
#define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
#define MAX_XFER_TIME (2*3600) /*%< Documented default is 2 hours */
+#define RESIGN_DELAY 3600 /*%< 1 hour */
#ifndef DNS_MAX_EXPIRE
#define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
@@ -213,6 +221,7 @@ struct dns_zone {
isc_uint32_t expire;
isc_uint32_t minimum;
isc_stdtime_t key_expiry;
+ isc_stdtime_t log_key_expired_timer;
char *keydirectory;
isc_uint32_t maxrefresh;
@@ -660,6 +669,8 @@ static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
dns_dbnode_t *node, dns_name_t *name,
dns_diff_t *diff);
static void zone_rekey(dns_zone_t *zone);
+static isc_boolean_t delsig_ok(dns_rdata_rrsig_t *rrsig_ptr,
+ dst_key_t **keys, unsigned int nkeys);
#define ENTER zone_debuglog(zone, me, 1, "enter")
@@ -805,6 +816,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
zone->timer = NULL;
zone->idlein = DNS_DEFAULT_IDLEIN;
zone->idleout = DNS_DEFAULT_IDLEOUT;
+ zone->log_key_expired_timer = 0;
ISC_LIST_INIT(zone->notifies);
isc_sockaddr_any(&zone->notifysrc4);
isc_sockaddr_any6(&zone->notifysrc6);
@@ -1379,6 +1391,7 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
isc_time_t now;
isc_time_t loadtime, filetime;
dns_db_t *db = NULL;
+ isc_boolean_t rbt;
REQUIRE(DNS_ZONE_VALID(zone));
@@ -1394,14 +1407,15 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
goto cleanup;
}
- if (zone->db != NULL && zone->masterfile == NULL) {
+
+ INSIST(zone->db_argc >= 1);
+
+ rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
+ strcmp(zone->db_argv[0], "rbt64") == 0;
+
+ if (zone->db != NULL && zone->masterfile == NULL && rbt) {
/*
- * The zone has no master file configured, but it already
- * has a database. It could be the built-in
- * version.bind. CH zone, a zone with a persistent
- * database being reloaded, or maybe a zone that
- * used to have a master file but whose configuration
- * was changed so that it no longer has one. Do nothing.
+ * The zone has no master file configured.
*/
result = ISC_R_SUCCESS;
goto cleanup;
@@ -1420,7 +1434,6 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
goto cleanup;
}
-
/*
* Store the current time before the zone is loaded, so that if the
* file changes between the time of the load and the time that
@@ -1463,21 +1476,20 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
}
}
- INSIST(zone->db_argc >= 1);
-
/*
- * Built in zones don't need to be reloaded.
+ * Built in zones (with the exception of empty zones) don't need
+ * to be reloaded.
*/
if (zone->type == dns_zone_master &&
strcmp(zone->db_argv[0], "_builtin") == 0 &&
+ (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
result = ISC_R_SUCCESS;
goto cleanup;
}
if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
- (strcmp(zone->db_argv[0], "rbt") == 0 ||
- strcmp(zone->db_argv[0], "rbt64") == 0)) {
+ rbt) {
if (zone->masterfile == NULL ||
!isc_file_exists(zone->masterfile)) {
if (zone->masterfile != NULL) {
@@ -1993,8 +2005,7 @@ zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
dns_rdataset_disassociate(&aaaa);
return (answer);
}
- } else
- tresult = result;
+ }
dns_name_format(owner, ownerbuf, sizeof ownerbuf);
dns_name_format(name, namebuf, sizeof namebuf);
@@ -2840,16 +2851,15 @@ compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
}
/*
- * Add key to the security roots for all views.
+ * Add key to the security roots.
*/
static void
-trust_key(dns_viewlist_t *viewlist, dns_name_t *keyname,
+trust_key(dns_zone_t *zone, dns_name_t *keyname,
dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
isc_result_t result;
dns_rdata_t rdata = DNS_RDATA_INIT;
unsigned char data[4096];
isc_buffer_t buffer;
- dns_view_t *view;
dns_keytable_t *sr = NULL;
dst_key_t *dstkey = NULL;
@@ -2858,17 +2868,13 @@ trust_key(dns_viewlist_t *viewlist, dns_name_t *keyname,
dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
dns_rdatatype_dnskey, dnskey, &buffer);
- for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
- view = ISC_LIST_NEXT(view, link)) {
-
- result = dns_view_getsecroots(view, &sr);
- if (result != ISC_R_SUCCESS)
- continue;
+ result = dns_view_getsecroots(zone->view, &sr);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
- CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
- CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
- dns_keytable_detach(&sr);
- }
+ CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
+ CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
+ dns_keytable_detach(&sr);
failure:
if (dstkey != NULL)
@@ -2879,37 +2885,16 @@ trust_key(dns_viewlist_t *viewlist, dns_name_t *keyname,
}
/*
- * Remove key from the security roots for all views.
- */
-static void
-untrust_key(dns_viewlist_t *viewlist, dns_name_t *keyname, isc_mem_t *mctx,
- dns_rdata_dnskey_t *dnskey)
-{
- dns_view_t *view;
-
- for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
- view = ISC_LIST_NEXT(view, link))
- dns_view_untrust(view, keyname, dnskey, mctx);
-}
-
-/*
- * Add a null key to the security roots for all views, so that all queries
+ * Add a null key to the security roots for so that all queries
* to the zone will fail.
*/
static void
-fail_secure(dns_viewlist_t *viewlist, dns_name_t *keyname) {
+fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
isc_result_t result;
- dns_view_t *view;
-
- for (view = ISC_LIST_HEAD(*viewlist);
- view != NULL;
- view = ISC_LIST_NEXT(view, link)) {
- dns_keytable_t *sr = NULL;
-
- result = dns_view_getsecroots(view, &sr);
- if (result != ISC_R_SUCCESS)
- continue;
+ dns_keytable_t *sr = NULL;
+ result = dns_view_getsecroots(zone->view, &sr);
+ if (result == ISC_R_SUCCESS) {
dns_keytable_marksecure(sr, keyname);
dns_keytable_detach(&sr);
}
@@ -2917,8 +2902,7 @@ fail_secure(dns_viewlist_t *viewlist, dns_name_t *keyname) {
/*
* Scan a set of KEYDATA records from the key zone. The ones that are
- * valid (i.e., the add holddown timer has expired) become trusted keys for
- * all views.
+ * valid (i.e., the add holddown timer has expired) become trusted keys.
*/
static void
load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
@@ -2927,22 +2911,14 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
dns_rdata_keydata_t keydata;
dns_rdata_dnskey_t dnskey;
isc_mem_t *mctx = zone->mctx;
- dns_view_t *view = zone->view;
- dns_viewlist_t *viewlist = view->viewlist;
int trusted = 0, revoked = 0, pending = 0;
isc_stdtime_t now;
+ dns_keytable_t *sr = NULL;
isc_stdtime_get(&now);
- /* For each view, delete references to this key from secroots. */
- for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
- view = ISC_LIST_NEXT(view, link)) {
- dns_keytable_t *sr = NULL;
-
- result = dns_view_getsecroots(view, &sr);
- if (result != ISC_R_SUCCESS)
- continue;
-
+ result = dns_view_getsecroots(zone->view, &sr);
+ if (result == ISC_R_SUCCESS) {
dns_keytable_delete(sr, name);
dns_keytable_detach(&sr);
}
@@ -2980,7 +2956,7 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
/* Add to keytables. */
trusted++;
- trust_key(viewlist, name, &dnskey, mctx);
+ trust_key(zone, name, &dnskey, mctx);
}
if (trusted == 0 && pending != 0) {
@@ -2993,7 +2969,7 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
revoked, pending);
dns_zone_log(zone, ISC_LOG_ERROR,
"All queries to '%s' will fail", namebuf);
- fail_secure(viewlist, name);
+ fail_secure(zone, name);
}
}
@@ -3167,6 +3143,7 @@ static isc_result_t
sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
isc_result_t result = ISC_R_SUCCESS;
isc_boolean_t changed = ISC_FALSE;
+ isc_boolean_t commit = ISC_FALSE;
dns_rbtnodechain_t chain;
dns_fixedname_t fn;
dns_name_t foundname, *origin;
@@ -3288,12 +3265,12 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
if (changed) {
/* Write changes to journal file. */
- result = increment_soa_serial(db, ver, &diff, zone->mctx);
- if (result == ISC_R_SUCCESS)
- zone_journal(zone, &diff, "sync_keyzone");
+ CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
+ CHECK(zone_journal(zone, &diff, "sync_keyzone"));
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
zone_needdump(zone, 30);
+ commit = ISC_TRUE;
}
failure:
@@ -3302,7 +3279,7 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
if (sr != NULL)
dns_keytable_detach(&sr);
if (ver != NULL)
- dns_db_closeversion(db, &ver, changed);
+ dns_db_closeversion(db, &ver, commit);
dns_diff_clear(&diff);
return (result);
@@ -3500,7 +3477,8 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
dns_zone_log(zone, ISC_LOG_ERROR,
"zone serial (%u/%u) has gone "
"backwards", serial, oldserial);
- else if (serial == oldserial && !hasinclude)
+ else if (serial == oldserial && !hasinclude &&
+ strcmp(zone->db_argv[0], "_builtin") != 0)
dns_zone_log(zone, ISC_LOG_ERROR,
"zone serial (%u) unchanged. "
"zone may fail to transfer "
@@ -3617,6 +3595,39 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
resume_signingwithkey(zone);
resume_addnsec3chain(zone);
}
+
+ if (zone->type == dns_zone_master &&
+ zone_isdynamic(zone) &&
+ dns_db_issecure(db)) {
+ dns_name_t *name;
+ dns_fixedname_t fixed;
+ dns_rdataset_t next;
+
+ dns_rdataset_init(&next);
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+
+ result = dns_db_getsigningtime(db, &next, name);
+ if (result == ISC_R_SUCCESS) {
+ isc_stdtime_t timenow;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+
+ isc_stdtime_get(&timenow);
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(next.covers,
+ typebuf, sizeof(typebuf));
+ dns_zone_log(zone, ISC_LOG_DEBUG(3),
+ "next resign: %s/%s in %d seconds",
+ namebuf, typebuf,
+ next.resign - timenow);
+ dns_rdataset_disassociate(&next);
+ } else
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "signed dynamic zone has no "
+ "resign event scheduled");
+ }
+
zone_settimer(zone, &now);
}
@@ -4520,6 +4531,7 @@ static void
set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
{
unsigned int delta;
+ char timebuf[80];
zone->key_expiry = when;
if (when <= now) {
@@ -4527,20 +4539,57 @@ set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
"DNSKEY RRSIG(s) have expired");
isc_time_settoepoch(&zone->keywarntime);
} else if (when < now + 7 * 24 * 3600) {
+ isc_time_t t;
+ isc_time_set(&t, when, 0);
+ isc_time_formattimestamp(&t, timebuf, 80);
dns_zone_log(zone, ISC_LOG_WARNING,
- "DNSKEY RRSIG(s) will expire at %u",
- when); /* XXXMPA convert to date. */
+ "DNSKEY RRSIG(s) will expire within 7 days: %s",
+ timebuf);
delta = when - now;
delta--; /* loop prevention */
delta /= 24 * 3600; /* to whole days */
delta *= 24 * 3600; /* to seconds */
isc_time_set(&zone->keywarntime, when - delta, 0);
} else {
- dns_zone_log(zone, ISC_LOG_NOTICE, /* XXMPA ISC_LOG_DEBUG(1) */
- "setting keywarntime to %u - 7 days",
- when); /* XXXMPA convert to date. */
isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
+ isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
+ dns_zone_log(zone, ISC_LOG_NOTICE,
+ "setting keywarntime to %s", timebuf);
+ }
+}
+
+/*
+ * Helper function to del_sigs(). We don't want to delete RRSIGs that
+ * have no new key.
+ */
+static isc_boolean_t
+delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys) {
+ unsigned int i = 0;
+
+ /*
+ * It's okay to delete a signature if there is an active ZSK
+ * with the same algorithm
+ */
+ for (i = 0; i < nkeys; i++) {
+ if (rrsig_ptr->algorithm == dst_key_alg(keys[i]) &&
+ (dst_key_isprivate(keys[i])) && !KSK(keys[i]))
+ return (ISC_TRUE);
+ }
+
+ /*
+ * Failing that, it is *not* okay to delete a signature
+ * if the associated public key is still in the DNSKEY RRset
+ */
+ for (i = 0; i < nkeys; i++) {
+ if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
+ (rrsig_ptr->keyid == dst_key_id(keys[i])))
+ return (ISC_FALSE);
}
+
+ /*
+ * But if the key is gone, then go ahead.
+ */
+ return (ISC_TRUE);
}
/*
@@ -4550,7 +4599,7 @@ set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
static isc_result_t
del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
- unsigned int nkeys, isc_stdtime_t now)
+ unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
{
isc_result_t result;
dns_dbnode_t *node = NULL;
@@ -4558,7 +4607,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
dns_rdata_t rdata = DNS_RDATA_INIT;
unsigned int i;
dns_rdata_rrsig_t rrsig;
- isc_boolean_t found;
+ isc_boolean_t found, changed;
isc_stdtime_t warn = 0, maybe = 0;
dns_rdataset_init(&rdataset);
@@ -4584,6 +4633,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
goto failure;
}
+ changed = ISC_FALSE;
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset)) {
@@ -4592,12 +4642,56 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (type != dns_rdatatype_dnskey) {
- result = update_one_rr(db, ver, diff,
+ if (delsig_ok(&rrsig, keys, nkeys)) {
+ result = update_one_rr(db, ver, diff,
DNS_DIFFOP_DELRESIGN, name,
rdataset.ttl, &rdata);
- dns_rdata_reset(&rdata);
- if (result != ISC_R_SUCCESS)
- break;
+ if (incremental)
+ changed = ISC_TRUE;
+ dns_rdata_reset(&rdata);
+ if (result != ISC_R_SUCCESS)
+ break;
+ } else {
+ /*
+ * At this point, we've got an RRSIG,
+ * which is signed by an inactive key.
+ * An administrator needs to provide a new
+ * key/alg, but until that time, we want to
+ * keep the old RRSIG. Marking the key as
+ * offline will prevent us spinning waiting
+ * for the private part.
+ */
+ if (incremental) {
+ result = offline(db, ver, diff, name,
+ rdataset.ttl, &rdata);
+ changed = ISC_TRUE;
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+
+ /*
+ * Log the key id and algorithm of
+ * the inactive key with no replacement
+ */
+ if (zone->log_key_expired_timer <= now) {
+ char origin[DNS_NAME_FORMATSIZE];
+ char algbuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(&zone->origin, origin,
+ sizeof(origin));
+ dns_secalg_format(rrsig.algorithm,
+ algbuf,
+ sizeof(algbuf));
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "Key %s/%s/%d "
+ "missing or inactive "
+ "and has no replacement: "
+ "retaining signatures.",
+ origin, algbuf,
+ rrsig.keyid);
+ zone->log_key_expired_timer = now +
+ 3600;
+ }
+ }
continue;
}
@@ -4641,6 +4735,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
break;
}
}
+
/*
* If there is not a matching DNSKEY then
* delete the RRSIG.
@@ -4653,6 +4748,10 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
if (result != ISC_R_SUCCESS)
break;
}
+
+ if (changed && (rdataset.attributes & DNS_RDATASETATTR_RESIGN) != 0)
+ dns_db_resigned(db, &rdataset, ver);
+
dns_rdataset_disassociate(&rdataset);
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
@@ -4702,10 +4801,6 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
goto failure;
}
-#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
-#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
-#define ALG(x) dst_key_alg(x)
-
for (i = 0; i < nkeys; i++) {
isc_boolean_t both = ISC_FALSE;
@@ -4844,6 +4939,8 @@ zone_resigninc(dns_zone_t *zone) {
while (result == ISC_R_SUCCESS) {
resign = rdataset.resign;
covers = rdataset.covers;
+ dns_rdataset_disassociate(&rdataset);
+
/*
* Stop if we hit the SOA as that means we have walked the
* entire zone. The SOA record should always be the most
@@ -4851,27 +4948,18 @@ zone_resigninc(dns_zone_t *zone) {
*/
/* XXXMPA increase number of RRsets signed pre call */
if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
- resign > stop) {
- /*
- * Ensure that we don't loop resigning the SOA.
- */
- if (covers == dns_rdatatype_soa)
- dns_db_resigned(db, &rdataset, version);
- dns_rdataset_disassociate(&rdataset);
+ resign > stop)
break;
- }
-
- dns_db_resigned(db, &rdataset, version);
- dns_rdataset_disassociate(&rdataset);
result = del_sigs(zone, db, version, name, covers, &sig_diff,
- zone_keys, nkeys, now);
+ zone_keys, nkeys, now, ISC_TRUE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_resigninc:del_sigs -> %s\n",
dns_result_totext(result));
break;
}
+
result = add_sigs(db, version, name, covers, &sig_diff,
zone_keys, nkeys, zone->mctx, inception,
expire, check_ksk, keyset_kskonly);
@@ -4897,7 +4985,7 @@ zone_resigninc(dns_zone_t *zone) {
goto failure;
result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
- &sig_diff, zone_keys, nkeys, now);
+ &sig_diff, zone_keys, nkeys, now, ISC_TRUE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_resigninc:del_sigs -> %s\n",
@@ -4905,6 +4993,13 @@ zone_resigninc(dns_zone_t *zone) {
goto failure;
}
+ /*
+ * Did we change anything in the zone?
+ */
+ if (ISC_LIST_EMPTY(sig_diff.tuples))
+ goto failure;
+
+ /* Increment SOA serial if we have made changes */
result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
@@ -4928,7 +5023,7 @@ zone_resigninc(dns_zone_t *zone) {
}
/* Write changes to journal file. */
- zone_journal(zone, &sig_diff, "zone_resigninc");
+ CHECK(zone_journal(zone, &sig_diff, "zone_resigninc"));
/* Everything has succeeded. Commit the changes. */
dns_db_closeversion(db, &version, ISC_TRUE);
@@ -5614,7 +5709,7 @@ update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
tuple = ISC_LIST_HEAD(diff->tuples)) {
result = del_sigs(zone, db, version, &tuple->name,
tuple->rdata.type, sig_diff,
- zone_keys, nkeys, now);
+ zone_keys, nkeys, now, ISC_FALSE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"update_sigs:del_sigs -> %s\n",
@@ -5668,11 +5763,11 @@ zone_nsec3chain(dns_zone_t *zone) {
dns_nsec3chainlist_t cleanup;
dst_key_t *zone_keys[MAXZONEKEYS];
isc_int32_t signatures;
- isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
+ isc_boolean_t check_ksk, keyset_kskonly;
isc_boolean_t delegation;
isc_boolean_t first;
isc_result_t result;
- isc_stdtime_t now, inception, soaexpire, expire, stop;
+ isc_stdtime_t now, inception, soaexpire, expire;
isc_uint32_t jitter;
unsigned int i;
unsigned int nkeys = 0;
@@ -5737,7 +5832,6 @@ zone_nsec3chain(dns_zone_t *zone) {
*/
isc_random_get(&jitter);
expire = soaexpire - jitter % 3600;
- stop = now + 5;
check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
@@ -5783,8 +5877,6 @@ zone_nsec3chain(dns_zone_t *zone) {
if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
goto next_addchain;
- is_ksk = ISC_FALSE;
- delegation = ISC_FALSE;
dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
if (nsec3chain->delete_nsec) {
@@ -6170,6 +6262,12 @@ zone_nsec3chain(dns_zone_t *zone) {
result = dns_db_getoriginnode(db, &node);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = dns_db_allrdatasets(db, node, version, 0, &iterator);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
+ "dns_db_allrdatasets -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
for (result = dns_rdatasetiter_first(iterator);
result == ISC_R_SUCCESS;
result = dns_rdatasetiter_next(iterator)) {
@@ -6267,7 +6365,7 @@ zone_nsec3chain(dns_zone_t *zone) {
goto done;
result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
- &sig_diff, zone_keys, nkeys, now);
+ &sig_diff, zone_keys, nkeys, now, ISC_FALSE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
"del_sigs -> %s\n", dns_result_totext(result));
@@ -6292,10 +6390,11 @@ zone_nsec3chain(dns_zone_t *zone) {
}
/* Write changes to journal file. */
- zone_journal(zone, &sig_diff, "zone_nsec3chain");
+ CHECK(zone_journal(zone, &sig_diff, "zone_nsec3chain"));
LOCK_ZONE(zone);
zone_needdump(zone, DNS_DUMP_DELAY);
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
UNLOCK_ZONE(zone);
done:
@@ -6502,12 +6601,11 @@ zone_sign(dns_zone_t *zone) {
isc_boolean_t build_nsec3 = ISC_FALSE;
isc_boolean_t first;
isc_result_t result;
- isc_stdtime_t now, inception, soaexpire, expire, stop;
+ isc_stdtime_t now, inception, soaexpire, expire;
isc_uint32_t jitter;
unsigned int i, j;
unsigned int nkeys = 0;
isc_uint32_t nodes;
- isc_boolean_t was_ksk;
dns_rdataset_init(&rdataset);
dns_fixedname_init(&fixed);
@@ -6559,7 +6657,6 @@ zone_sign(dns_zone_t *zone) {
*/
isc_random_get(&jitter);
expire = soaexpire - jitter % 3600;
- stop = now + 5;
/*
* We keep pulling nodes off each iterator in turn until
@@ -6604,8 +6701,6 @@ zone_sign(dns_zone_t *zone) {
delegation = ISC_FALSE;
- was_ksk = ISC_FALSE;
-
if (first && signing->delete) {
/*
* Remove the key we are deleting from consideration.
@@ -6831,7 +6926,7 @@ zone_sign(dns_zone_t *zone) {
commit = ISC_TRUE;
result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
- &sig_diff, zone_keys, nkeys, now);
+ &sig_diff, zone_keys, nkeys, now, ISC_FALSE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_sign:del_sigs -> %s\n",
@@ -6864,9 +6959,7 @@ zone_sign(dns_zone_t *zone) {
/*
* Write changes to journal file.
*/
- result = zone_journal(zone, &sig_diff, "zone_sign");
- if (result != ISC_R_SUCCESS)
- goto failure;
+ CHECK(zone_journal(zone, &sig_diff, "zone_sign"));
pauseall:
/*
@@ -7048,6 +7141,7 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
dns_rdataset_current(rdset, &sigrr);
result = dns_rdata_tostruct(&sigrr, &sig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (!retry) {
t = sig.originalttl / 2;
@@ -7215,8 +7309,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
dns_keytable_t *secroots = NULL;
dns_dbversion_t *ver = NULL;
dns_diff_t diff;
- isc_boolean_t changed = ISC_FALSE;
isc_boolean_t alldone = ISC_FALSE;
+ isc_boolean_t commit = ISC_FALSE;
dns_name_t *keyname;
dns_rdata_t sigrr = DNS_RDATA_INIT;
dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
@@ -7232,6 +7326,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
isc_stdtime_t now;
int pending = 0;
isc_boolean_t secure;
+ isc_boolean_t free_needed;
UNUSED(task);
INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
@@ -7253,15 +7348,20 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
isc_event_free(&event);
dns_resolver_destroyfetch(&kfetch->fetch);
+ LOCK_ZONE(zone);
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
+ goto cleanup;
+
isc_stdtime_get(&now);
dns_name_format(keyname, namebuf, sizeof(namebuf));
result = dns_view_getsecroots(zone->view, &secroots);
INSIST(result == ISC_R_SUCCESS);
- LOCK_ZONE(zone);
- dns_db_newversion(kfetch->db, &ver);
dns_diff_init(mctx, &diff);
+ diff.resign = zone->sigresigninginterval;
+
+ CHECK(dns_db_newversion(kfetch->db, &ver));
zone->refreshkeycount--;
alldone = ISC_TF(zone->refreshkeycount == 0);
@@ -7276,8 +7376,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
"Unable to fetch DNSKEY set "
"'%s': %s", namebuf, dns_result_totext(eresult));
CHECK(minimal_update(kfetch, ver, &diff));
- changed = ISC_TRUE;
- goto failure;
+ goto done;
}
/* No RRSIGs found */
@@ -7286,8 +7385,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
"No DNSKEY RRSIGs found for "
"'%s': %s", namebuf, dns_result_totext(eresult));
CHECK(minimal_update(kfetch, ver, &diff));
- changed = ISC_TRUE;
- goto failure;
+ goto done;
}
/*
@@ -7415,7 +7513,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
CHECK(update_one_rr(kfetch->db, ver, &diff,
DNS_DIFFOP_DEL, keyname, 0,
&keydatarr));
- changed = ISC_TRUE;
}
if (!secure || deletekey)
@@ -7431,7 +7528,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
CHECK(update_one_rr(kfetch->db, ver, &diff,
DNS_DIFFOP_ADD, keyname, 0,
&keydatarr));
- changed = ISC_TRUE;
set_refreshkeytimer(zone, &keydata, now);
}
@@ -7486,8 +7582,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
deletekey = ISC_TRUE;
} else if (keydata.removehd == 0) {
/* Remove from secroots */
- untrust_key(zone->view->viewlist,
- keyname, mctx, &dnskey);
+ dns_view_untrust(zone->view, keyname,
+ &dnskey, mctx);
/* If initializing, delete now */
if (keydata.addhd == 0)
@@ -7555,12 +7651,10 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
}
/* Delete old version */
- if (deletekey || !newkey) {
+ if (deletekey || !newkey)
CHECK(update_one_rr(kfetch->db, ver, &diff,
DNS_DIFFOP_DEL, keyname, 0,
&keydatarr));
- changed = ISC_TRUE;
- }
if (updatekey) {
/* Set refresh timer */
@@ -7575,7 +7669,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
CHECK(update_one_rr(kfetch->db, ver, &diff,
DNS_DIFFOP_ADD, keyname, 0,
&keydatarr));
- changed = ISC_TRUE;
} else if (newkey) {
/* Convert DNSKEY to KEYDATA */
dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
@@ -7593,14 +7686,12 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
CHECK(update_one_rr(kfetch->db, ver, &diff,
DNS_DIFFOP_ADD, keyname, 0,
&keydatarr));
- changed = ISC_TRUE;
}
if (trustkey) {
- /* Trust this key in all views */
+ /* Trust this key. */
dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
- trust_key(zone->view->viewlist, keyname, &dnskey,
- mctx);
+ trust_key(zone, keyname, &dnskey, mctx);
}
if (!deletekey)
@@ -7617,27 +7708,32 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
* the security roots; then all queries to the zone will fail.
*/
if (pending != 0)
- fail_secure(zone->view->viewlist, keyname);
+ fail_secure(zone, keyname);
+
+ done:
+
+ if (!ISC_LIST_EMPTY(diff.tuples)) {
+ /* Write changes to journal file. */
+ CHECK(increment_soa_serial(kfetch->db, ver, &diff, mctx));
+ CHECK(zone_journal(zone, &diff, "keyfetch_done"));
+ commit = ISC_TRUE;
- failure:
- if (changed) {
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
zone_needdump(zone, 30);
}
- UNLOCK_ZONE(zone);
-
- /* Write changes to journal file. */
- if (alldone) {
- result = increment_soa_serial(kfetch->db, ver, &diff, mctx);
- if (result == ISC_R_SUCCESS)
- result = zone_journal(zone, &diff, "keyfetch_done");
- }
+ failure:
dns_diff_clear(&diff);
- dns_db_closeversion(kfetch->db, &ver, changed);
+ if (ver != NULL)
+ dns_db_closeversion(kfetch->db, &ver, commit);
+
+ cleanup:
dns_db_detach(&kfetch->db);
- dns_zone_detach(&kfetch->zone);
+
+ INSIST(zone->irefs > 0);
+ zone->irefs--;
+ kfetch->zone = NULL;
if (dns_rdataset_isassociated(&kfetch->keydataset))
dns_rdataset_disassociate(&kfetch->keydataset);
@@ -7652,6 +7748,11 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
if (secroots != NULL)
dns_keytable_detach(&secroots);
+
+ free_needed = exit_check(zone);
+ UNLOCK_ZONE(zone);
+ if (free_needed)
+ zone_free(zone);
}
/*
@@ -7676,14 +7777,21 @@ zone_refreshkeys(dns_zone_t *zone) {
isc_stdtime_get(&now);
+ LOCK_ZONE(zone);
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
+ isc_time_settoepoch(&zone->refreshkeytime);
+ UNLOCK_ZONE(zone);
+ return;
+ }
+
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
dns_db_attach(zone->db, &db);
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
- LOCK_ZONE(zone);
- dns_db_newversion(db, &ver);
dns_diff_init(zone->mctx, &diff);
+ CHECK(dns_db_newversion(db, &ver));
+
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
dns_rriterator_init(&rrit, db, ver, 0);
@@ -7738,8 +7846,9 @@ zone_refreshkeys(dns_zone_t *zone) {
zone->refreshkeycount++;
kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
- kfetch->zone = NULL;
- dns_zone_attach(zone, &kfetch->zone);
+ kfetch->zone = zone;
+ zone->irefs++;
+ INSIST(zone->irefs != 0);
dns_fixedname_init(&kfetch->name);
dns_name_dup(name, zone->mctx,
dns_fixedname_name(&kfetch->name));
@@ -7763,17 +7872,20 @@ zone_refreshkeys(dns_zone_t *zone) {
}
if (!ISC_LIST_EMPTY(diff.tuples)) {
CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
+ CHECK(zone_journal(zone, &diff, "sync_keyzone"));
commit = ISC_TRUE;
- zone_journal(zone, &diff, "sync_keyzone");
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
zone_needdump(zone, 30);
}
+
failure:
UNLOCK_ZONE(zone);
- dns_rriterator_destroy(&rrit);
dns_diff_clear(&diff);
- dns_db_closeversion(db, &ver, commit);
+ if (ver != NULL) {
+ dns_rriterator_destroy(&rrit);
+ dns_db_closeversion(db, &ver, commit);
+ }
dns_db_detach(&db);
}
@@ -7988,7 +8100,7 @@ dns_zone_refresh(dns_zone_t *zone) {
isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
0);
result = isc_time_nowplusinterval(&zone->refreshtime, &i);
- if (result |= ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS)
dns_zone_log(zone, ISC_LOG_WARNING,
"isc_time_nowplusinterval() failed: %s",
dns_result_totext(result));
@@ -9342,7 +9454,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
goto tcp_transfer;
}
dns_zone_log(zone, ISC_LOG_DEBUG(1),
- "refresh: skipped tcp fallback"
+ "refresh: skipped tcp fallback "
"as master %s (source %s) is "
"unreachable (cached)",
master, source);
@@ -9523,6 +9635,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
} else
zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
serial);
+
if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
isc_serial_gt(serial, oldserial)) {
@@ -10066,7 +10179,13 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
dns_db_settask(stub->db, zone->task);
}
- dns_db_newversion(stub->db, &stub->version);
+ result = dns_db_newversion(stub->db, &stub->version);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
+ "dns_db_newversion() failed: %s",
+ dns_result_totext(result));
+ goto cleanup;
+ }
/*
* Update SOA record.
@@ -10074,8 +10193,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
&node);
if (result != ISC_R_SUCCESS) {
- dns_zone_log(zone, ISC_LOG_INFO,
- "refreshing stub: "
+ dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
"dns_db_findnode() failed: %s",
dns_result_totext(result));
goto cleanup;
@@ -10097,6 +10215,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
* XXX Optimisation: Create message when zone is setup and reuse.
*/
result = create_query(zone, dns_rdatatype_ns, &message);
+ INSIST(result == ISC_R_SUCCESS);
INSIST(zone->masterscnt > 0);
INSIST(zone->curmaster < zone->masterscnt);
@@ -10170,6 +10289,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
break;
default:
result = ISC_R_NOTIMPLEMENTED;
+ POST(result);
goto cleanup;
}
timeout = 15;
@@ -12360,16 +12480,10 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
zmgr->transfersin = 10;
zmgr->transfersperns = 2;
- /* Create the zone task pool. */
- result = isc_taskpool_create(taskmgr, mctx,
- 8 /* XXX */, 2, &zmgr->zonetasks);
- if (result != ISC_R_SUCCESS)
- goto free_rwlock;
-
/* Create a single task for queueing of SOA queries. */
result = isc_task_create(taskmgr, 1, &zmgr->task);
if (result != ISC_R_SUCCESS)
- goto free_taskpool;
+ goto free_rwlock;
isc_task_setname(zmgr->task, "zmgr", zmgr);
result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
&zmgr->rl);
@@ -12403,8 +12517,6 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_ratelimiter_detach(&zmgr->rl);
free_task:
isc_task_detach(&zmgr->task);
- free_taskpool:
- isc_taskpool_destroy(&zmgr->zonetasks);
free_rwlock:
isc_rwlock_destroy(&zmgr->rwlock);
free_mem:
@@ -12420,16 +12532,16 @@ dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+ if (zmgr->zonetasks == NULL)
+ return (ISC_R_FAILURE);
+
RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
LOCK_ZONE(zone);
REQUIRE(zone->task == NULL);
REQUIRE(zone->timer == NULL);
REQUIRE(zone->zmgr == NULL);
- isc_taskpool_gettask(zmgr->zonetasks,
- dns_name_hash(dns_zone_getorigin(zone),
- ISC_FALSE),
- &zone->task);
+ isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
/*
* Set the task name. The tag will arbitrarily point to one
@@ -12522,6 +12634,7 @@ dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
if (free_now)
zonemgr_free(zmgr);
+ *zmgrp = NULL;
}
isc_result_t
@@ -12573,6 +12686,35 @@ dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
isc_taskpool_destroy(&zmgr->zonetasks);
}
+isc_result_t
+dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
+ isc_result_t result;
+ int ntasks = num_zones / 100;
+ isc_taskpool_t *pool = NULL;
+
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ /*
+ * For anything fewer than 1000 zones we use 10 tasks in
+ * the task pool. More than that, and we'll scale at one
+ * task per 100 zones.
+ */
+ if (ntasks < 10)
+ ntasks = 10;
+
+ /* Create or resize the zone task pool. */
+ if (zmgr->zonetasks == NULL)
+ result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
+ ntasks, 2, &pool);
+ else
+ result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
+
+ if (result == ISC_R_SUCCESS)
+ zmgr->zonetasks = pool;
+
+ return (result);
+}
+
static void
zonemgr_free(dns_zonemgr_t *zmgr) {
isc_mem_t *mctx;
@@ -13586,7 +13728,8 @@ rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
*/
static isc_result_t
add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
- dns_dbversion_t *ver, dns_diff_t *diff)
+ dns_dbversion_t *ver, dns_diff_t *diff,
+ isc_boolean_t sign_all)
{
dns_difftuple_t *tuple, *newtuple = NULL;
dns_rdata_dnskey_t dnskey;
@@ -13625,13 +13768,16 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
rdata.type = privatetype;
rdata.rdclass = tuple->rdata.rdclass;
- CHECK(rr_exists(db, ver, name, &rdata, &flag));
- if (flag)
- continue;
- CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
- name, 0, &rdata, &newtuple));
- CHECK(do_one_tuple(&newtuple, db, ver, diff));
- INSIST(newtuple == NULL);
+ if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+ if (flag)
+ continue;
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ name, 0, &rdata, &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ INSIST(newtuple == NULL);
+ }
+
/*
* Remove any record which says this operation has already
* completed.
@@ -13692,7 +13838,7 @@ sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
if (tuple == NULL) {
result = del_sigs(zone, db, ver, &zone->origin,
dns_rdatatype_dnskey, sig_diff,
- zone_keys, nkeys, now);
+ zone_keys, nkeys, now, ISC_FALSE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"sign_apex:del_sigs -> %s\n",
@@ -13868,6 +14014,7 @@ zone_rekey(dns_zone_t *zone) {
dns_dnsseckey_t *key;
dns_diff_t diff, sig_diff;
isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
+ isc_boolean_t newalg = ISC_FALSE;
isc_boolean_t fullsign;
dns_ttl_t ttl = 3600;
const char *dir;
@@ -13890,6 +14037,7 @@ zone_rekey(dns_zone_t *zone) {
mctx = zone->mctx;
dns_diff_init(mctx, &diff);
dns_diff_init(mctx, &sig_diff);
+ sig_diff.resign = zone->sigresigninginterval;
CHECK(dns_zone_getdb(zone, &db));
CHECK(dns_db_newversion(db, &ver));
@@ -13944,12 +14092,34 @@ zone_rekey(dns_zone_t *zone) {
goto trylater;
}
- /* See if any pre-existing keys have newly become active */
+ /* See if any pre-existing keys have newly become active;
+ * also, see if any new key is for a new algorithm, as in that
+ * event, we need to sign the zone fully. (If there's a new
+ * key, but it's for an already-existing algorithm, then
+ * the zone signing can be handled incrementally.)
+ */
for (key = ISC_LIST_HEAD(dnskeys);
key != NULL;
key = ISC_LIST_NEXT(key, link)) {
- if (key->first_sign) {
- newactive = ISC_TRUE;
+ if (!key->first_sign)
+ continue;
+
+ newactive = ISC_TRUE;
+
+ if (!dns_rdataset_isassociated(&keysigs)) {
+ newalg = ISC_TRUE;
+ break;
+ }
+
+ if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
+ /*
+ * This isn't a new algorithm; clear
+ * first_sign so we won't sign the
+ * whole zone with this key later
+ */
+ key->first_sign = ISC_FALSE;
+ } else {
+ newalg = ISC_TRUE;
break;
}
}
@@ -13958,8 +14128,9 @@ zone_rekey(dns_zone_t *zone) {
dnskey_sane(zone, db, ver, &diff)) {
CHECK(dns_diff_apply(&diff, db, ver));
CHECK(clean_nsec3param(zone, db, ver, &diff));
- CHECK(add_signing_records(db, zone->privatetype, ver,
- &diff));
+ CHECK(add_signing_records(db, zone->privatetype,
+ ver, &diff,
+ ISC_TF(newalg || fullsign)));
CHECK(increment_soa_serial(db, ver, &diff, mctx));
CHECK(add_chains(zone, db, ver, &diff));
CHECK(sign_apex(zone, db, ver, &diff, &sig_diff));
@@ -13973,8 +14144,6 @@ zone_rekey(dns_zone_t *zone) {
if (commit) {
isc_time_t timenow;
dns_difftuple_t *tuple;
- isc_boolean_t newkey = ISC_FALSE;
- isc_boolean_t newalg = ISC_FALSE;
LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
@@ -13984,43 +14153,6 @@ zone_rekey(dns_zone_t *zone) {
TIME_NOW(&timenow);
zone_settimer(zone, &timenow);
- /*
- * Has a new key become active? If so, is it for
- * a new algorithm?
- */
- for (tuple = ISC_LIST_HEAD(sig_diff.tuples);
- tuple != NULL;
- tuple = ISC_LIST_NEXT(tuple, link)) {
- dns_rdata_dnskey_t dnskey;
-
- if (tuple->rdata.type != dns_rdatatype_dnskey)
- continue;
-
- newkey = ISC_TRUE;
- if (!dns_rdataset_isassociated(&keysigs)) {
- newalg = ISC_TRUE;
- break;
- }
-
- result = dns_rdata_tostruct(&tuple->rdata,
- &dnskey, NULL);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- if (!signed_with_alg(&keysigs,
- dnskey.algorithm)) {
- newalg = ISC_TRUE;
- break;
- }
- }
-
- /*
- * If we found a new algorithm, we need to sign the
- * zone fully. If there's a new key, but it's for an
- * already-existing algorithm, then the zone signing
- * can be handled incrementally.
- */
- if (newkey && !newalg)
- set_resigntime(zone);
-
/* Remove any signatures from removed keys. */
if (!ISC_LIST_EMPTY(rmkeys)) {
for (key = ISC_LIST_HEAD(rmkeys);
@@ -14038,7 +14170,6 @@ zone_rekey(dns_zone_t *zone) {
}
}
-
if (fullsign) {
/*
* "rndc sign" was called, so we now sign the zone
@@ -14064,30 +14195,19 @@ zone_rekey(dns_zone_t *zone) {
/*
* We haven't been told to sign fully, but a new
* algorithm was added to the DNSKEY. We sign
- * the full zone, but only with the newly-added
+ * the full zone, but only with newly active
* keys.
*/
- for (tuple = ISC_LIST_HEAD(sig_diff.tuples);
- tuple != NULL;
- tuple = ISC_LIST_NEXT(tuple, link)) {
- dns_rdata_dnskey_t dnskey;
- dns_secalg_t algorithm;
- isc_region_t r;
- isc_uint16_t keyid;
-
- if (tuple->rdata.type != dns_rdatatype_dnskey ||
- tuple->op == DNS_DIFFOP_DEL)
+ for (key = ISC_LIST_HEAD(dnskeys);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
+ if (!key->first_sign)
continue;
- result = dns_rdata_tostruct(&tuple->rdata,
- &dnskey, NULL);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
- dns_rdata_toregion(&tuple->rdata, &r);
- algorithm = dnskey.algorithm;
- keyid = dst_region_computeid(&r, algorithm);
-
- result = zone_signwithkey(zone, algorithm,
- keyid, ISC_FALSE);
+ result = zone_signwithkey(zone,
+ dst_key_alg(key->key),
+ dst_key_id(key->key),
+ ISC_FALSE);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_signwithkey failed: %s",
@@ -14132,51 +14252,59 @@ zone_rekey(dns_zone_t *zone) {
dns_result_totext(result));
}
}
+
+ /*
+ * Schedule the next resigning event
+ */
+ set_resigntime(zone);
UNLOCK_ZONE(zone);
}
+ /*
+ * If we are doing automatic key maintenance and the key metadata
+ * indicates there is a key change event scheduled in the future,
+ * set the key refresh timer.
+ */
isc_stdtime_get(&now);
TIME_NOW(&timenow);
isc_time_settoepoch(&zone->refreshkeytime);
- for (key = ISC_LIST_HEAD(dnskeys);
- key != NULL;
- key = ISC_LIST_NEXT(key, link)) {
- isc_stdtime_t then;
+
+ /*
+ * If we're doing key maintenance, set the key refresh timer to
+ * the next scheduled key event or to one hour in the future,
+ * whichever is sooner.
+ */
+ if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
isc_time_t timethen;
+ isc_stdtime_t then;
- /*
- * If we are doing automatic key maintenance and the
- * key metadata indicates there is a key change event
- * scheduled in the future, set the key refresh timer.
- */
- if (!DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
- break;
+ LOCK_ZONE(zone);
+ DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
+ zone->refreshkeytime = timethen;
+ UNLOCK_ZONE(zone);
- then = now;
- result = next_keyevent(key->key, &then);
- if (result != ISC_R_SUCCESS)
- continue;
+ for (key = ISC_LIST_HEAD(dnskeys);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
+ then = now;
+ result = next_keyevent(key->key, &then);
+ if (result != ISC_R_SUCCESS)
+ continue;
- DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
- LOCK_ZONE(zone);
- if (isc_time_isepoch(&zone->refreshkeytime) ||
- isc_time_compare(&timethen, &zone->refreshkeytime) < 0) {
- zone->refreshkeytime = timethen;
- zone_settimer(zone, &timenow);
+ DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
+ LOCK_ZONE(zone);
+ if (isc_time_compare(&timethen,
+ &zone->refreshkeytime) < 0) {
+ zone->refreshkeytime = timethen;
+ }
+ UNLOCK_ZONE(zone);
}
- UNLOCK_ZONE(zone);
- }
- /*
- * If no key event is scheduled, we should still check the key
- * repository for updates every so often. (Currently this is
- * hard-coded to 12 hours, but it could be configurable.)
- */
- if (isc_time_isepoch(&zone->refreshkeytime))
- DNS_ZONE_TIME_ADD(&timenow, (3600 * 12), &zone->refreshkeytime);
+ zone_settimer(zone, &timenow);
- isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
- dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
+ isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
+ dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
+ }
failure:
dns_diff_clear(&diff);
OpenPOWER on IntegriCloud