mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-11 13:20:00 -04:00
4082. [bug] Incrementally sign large inline zone deltas.
[RT #37927]
(cherry picked from commit 1b05d22789)
This commit is contained in:
parent
8d47120f7d
commit
263413c7a7
10 changed files with 858 additions and 570 deletions
3
CHANGES
3
CHANGES
|
|
@ -1,3 +1,6 @@
|
|||
4082. [bug] Incrementally sign large inline zone deltas.
|
||||
[RT #37927]
|
||||
|
||||
4081. [cleanup] Use dns_rdatalist_init consistently. [RT #38759]
|
||||
|
||||
4077. [test] Add static-stub regression test for DS NXDOMAIN
|
||||
|
|
|
|||
|
|
@ -2191,6 +2191,7 @@ update_completed(isc_task_t *task, isc_event_t *event) {
|
|||
dns_request_destroy(&request);
|
||||
dns_message_renderreset(updatemsg);
|
||||
dns_message_settsigkey(updatemsg, NULL);
|
||||
/* XXX MPA fix zonename is freed already */
|
||||
send_update(zname, &master_servers[master_inuse]);
|
||||
isc_event_free(&event);
|
||||
return;
|
||||
|
|
@ -2493,6 +2494,9 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
|
|||
dns_name_init(&master, NULL);
|
||||
dns_name_clone(&soa.origin, &master);
|
||||
|
||||
/*
|
||||
* XXXMPA
|
||||
*/
|
||||
if (userzone != NULL)
|
||||
zname = userzone;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -88,3 +88,4 @@ rm -f ns3/test-?.bk.signed.jnl
|
|||
rm -f import.key Kimport*
|
||||
rm -f checkgost checkdsa checkecdsa
|
||||
rm -f ns3/a-file
|
||||
rm -f dig.out.*
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ zone "bits" {
|
|||
auto-dnssec maintain;
|
||||
allow-update-forwarding { any; };
|
||||
file "bits.bk";
|
||||
sig-signing-signatures 1; // force incremental processing
|
||||
};
|
||||
|
||||
server 10.53.0.4 { request-ixfr no; };
|
||||
|
|
|
|||
|
|
@ -66,6 +66,15 @@
|
|||
<listitem>
|
||||
<para>None</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Large inline-signing changes should be less disruptive.
|
||||
Signature generation is now done incrementally; the number
|
||||
of signatures to be generated in each quantum is controlled
|
||||
by "sig-signing-signatures <replaceable>number</replaceable>;".
|
||||
[RT #37927]
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</sect2>
|
||||
<sect2 id="relnotes_bugs">
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ typedef struct dns_tsec dns_tsec_t;
|
|||
typedef struct dns_tsig_keyring dns_tsig_keyring_t;
|
||||
typedef struct dns_tsigkey dns_tsigkey_t;
|
||||
typedef isc_uint32_t dns_ttl_t;
|
||||
typedef struct dns_update_state dns_update_state_t;
|
||||
typedef struct dns_validator dns_validator_t;
|
||||
typedef struct dns_view dns_view_t;
|
||||
typedef ISC_LIST(dns_view_t) dns_viewlist_t;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,12 @@ dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
|||
dns_dbversion_t *oldver, dns_dbversion_t *newver,
|
||||
dns_diff_t *diff, isc_uint32_t sigvalidityinterval);
|
||||
|
||||
isc_result_t
|
||||
dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
||||
dns_dbversion_t *oldver, dns_dbversion_t *newver,
|
||||
dns_diff_t *diff, isc_uint32_t sigvalidityinterval,
|
||||
dns_update_state_t **state);
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_UPDATE_H */
|
||||
|
|
|
|||
|
|
@ -1903,6 +1903,12 @@ dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures);
|
|||
* Set the number of signatures that will be generated per quantum.
|
||||
*/
|
||||
|
||||
isc_uint32_t
|
||||
dns_zone_getsignatures(dns_zone_t *zone);
|
||||
/*%<
|
||||
* Get the number of signatures that will be generated per quantum.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
|
||||
isc_uint16_t keyid, isc_boolean_t deleteit);
|
||||
|
|
|
|||
1118
lib/dns/update.c
1118
lib/dns/update.c
File diff suppressed because it is too large
Load diff
279
lib/dns/zone.c
279
lib/dns/zone.c
|
|
@ -379,6 +379,23 @@ struct dns_zone {
|
|||
|
||||
isc_boolean_t sourceserialset;
|
||||
isc_uint32_t sourceserial;
|
||||
|
||||
/*%
|
||||
* maximum zone ttl
|
||||
*/
|
||||
dns_ttl_t maxttl;
|
||||
|
||||
/*
|
||||
* Inline zone signing state.
|
||||
*/
|
||||
dns_diff_t rss_diff;
|
||||
isc_eventlist_t rss_events;
|
||||
dns_dbversion_t *rss_newver;
|
||||
dns_dbversion_t *rss_oldver;
|
||||
dns_db_t *rss_db;
|
||||
dns_zone_t *rss_raw;
|
||||
isc_event_t *rss_event;
|
||||
dns_update_state_t *rss_state;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -967,6 +984,13 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
|
|||
zone->secure = NULL;
|
||||
zone->sourceserial = 0;
|
||||
zone->sourceserialset = ISC_FALSE;
|
||||
ISC_LIST_INIT(zone->rss_events);
|
||||
zone->rss_db = NULL;
|
||||
zone->rss_raw = NULL;
|
||||
zone->rss_newver = NULL;
|
||||
zone->rss_oldver = NULL;
|
||||
zone->rss_event = NULL;
|
||||
zone->rss_state = NULL;
|
||||
|
||||
zone->magic = ZONE_MAGIC;
|
||||
|
||||
|
|
@ -9015,7 +9039,8 @@ zone_maintenance(dns_zone_t *zone) {
|
|||
break;
|
||||
case dns_zone_master:
|
||||
if (!isc_time_isepoch(&zone->refreshkeytime) &&
|
||||
isc_time_compare(&now, &zone->refreshkeytime) >= 0)
|
||||
isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
|
||||
zone->rss_event == NULL)
|
||||
zone_rekey(zone);
|
||||
default:
|
||||
break;
|
||||
|
|
@ -9028,6 +9053,8 @@ zone_maintenance(dns_zone_t *zone) {
|
|||
/*
|
||||
* Do we need to sign/resign some RRsets?
|
||||
*/
|
||||
if (zone->rss_event != NULL)
|
||||
break;
|
||||
if (!isc_time_isepoch(&zone->signingtime) &&
|
||||
isc_time_compare(&now, &zone->signingtime) >= 0)
|
||||
zone_sign(zone);
|
||||
|
|
@ -12935,61 +12962,74 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
|
|||
static void
|
||||
receive_secure_serial(isc_task_t *task, isc_event_t *event) {
|
||||
static char me[] = "receive_secure_serial";
|
||||
isc_result_t result;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
dns_journal_t *rjournal = NULL;
|
||||
dns_journal_t *sjournal = NULL;
|
||||
isc_uint32_t start, end;
|
||||
dns_zone_t *zone, *raw = NULL;
|
||||
dns_db_t *db = NULL;
|
||||
dns_dbversion_t *newver = NULL, *oldver = NULL;
|
||||
dns_diff_t diff;
|
||||
dns_zone_t *zone;
|
||||
dns_difftuple_t *tuple = NULL, *soatuple = NULL;
|
||||
dns_update_log_t log = { update_log_cb, NULL };
|
||||
isc_time_t timenow;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
zone = event->ev_arg;
|
||||
end = ((struct secure_event *)event)->serial;
|
||||
isc_event_free(&event);
|
||||
|
||||
ENTER;
|
||||
|
||||
LOCK_ZONE(zone);
|
||||
|
||||
dns_diff_init(zone->mctx, &diff);
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
|
||||
if (zone->db != NULL)
|
||||
dns_db_attach(zone->db, &db);
|
||||
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
|
||||
|
||||
if (zone->raw != NULL)
|
||||
dns_zone_attach(zone->raw, &raw);
|
||||
UNLOCK_ZONE(zone);
|
||||
|
||||
/*
|
||||
* zone->db may be NULL if the load from disk failed.
|
||||
* If we are already processing a receive secure serial event
|
||||
* for the zone, just queue the new one and exit.
|
||||
*/
|
||||
if (db == NULL || raw == NULL) {
|
||||
result = ISC_R_FAILURE;
|
||||
goto failure;
|
||||
if (zone->rss_event != NULL && zone->rss_event != event) {
|
||||
ISC_LIST_APPEND(zone->rss_events, event, ev_link);
|
||||
UNLOCK_ZONE(zone);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We first attempt to sync the raw zone to the secure zone
|
||||
* by using the raw zone's journal, applying all the deltas
|
||||
* from the latest source-serial of the secure zone up to
|
||||
* the current serial number of the raw zone.
|
||||
*
|
||||
* If that fails, then we'll fall back to a direct comparison
|
||||
* between raw and secure zones.
|
||||
*/
|
||||
result = dns_journal_open(raw->mctx, raw->journal,
|
||||
DNS_JOURNAL_WRITE, &rjournal);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto failure;
|
||||
else {
|
||||
dns_journal_t *sjournal = NULL;
|
||||
nextevent:
|
||||
if (zone->rss_event != NULL) {
|
||||
INSIST(zone->rss_event == event);
|
||||
UNLOCK_ZONE(zone);
|
||||
} else {
|
||||
zone->rss_event = event;
|
||||
dns_diff_init(zone->mctx, &zone->rss_diff);
|
||||
|
||||
/*
|
||||
* zone->db may be NULL, if the load from disk failed.
|
||||
*/
|
||||
result = ISC_R_SUCCESS;
|
||||
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
|
||||
if (zone->db != NULL)
|
||||
dns_db_attach(zone->db, &zone->rss_db);
|
||||
else
|
||||
result = ISC_R_FAILURE;
|
||||
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
|
||||
|
||||
if (result == ISC_R_SUCCESS && zone->raw != NULL)
|
||||
dns_zone_attach(zone->raw, &zone->rss_raw);
|
||||
else
|
||||
result = ISC_R_FAILURE;
|
||||
|
||||
UNLOCK_ZONE(zone);
|
||||
|
||||
CHECK(result);
|
||||
|
||||
/*
|
||||
* We first attempt to sync the raw zone to the secure zone
|
||||
* by using the raw zone's journal, applying all the deltas
|
||||
* from the latest source-serial of the secure zone up to
|
||||
* the current serial number of the raw zone.
|
||||
*
|
||||
* If that fails, then we'll fall back to a direct comparison
|
||||
* between raw and secure zones.
|
||||
*/
|
||||
CHECK(dns_journal_open(zone->rss_raw->mctx,
|
||||
zone->rss_raw->journal,
|
||||
DNS_JOURNAL_WRITE, &rjournal));
|
||||
|
||||
result = dns_journal_open(zone->mctx, zone->journal,
|
||||
DNS_JOURNAL_READ, &sjournal);
|
||||
|
|
@ -13003,9 +13043,9 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) {
|
|||
if (sjournal != NULL) {
|
||||
isc_uint32_t serial;
|
||||
/*
|
||||
* We read the secure journal first, if that exists
|
||||
* use its value provided it is greater that from the
|
||||
* raw journal.
|
||||
* We read the secure journal first, if that
|
||||
* exists use its value provided it is greater
|
||||
* that from the raw journal.
|
||||
*/
|
||||
if (dns_journal_get_sourceserial(sjournal, &serial)) {
|
||||
if (isc_serial_gt(serial, start))
|
||||
|
|
@ -13013,50 +13053,78 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
dns_journal_destroy(&sjournal);
|
||||
}
|
||||
|
||||
dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
|
||||
CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
|
||||
|
||||
/*
|
||||
* Try to apply diffs from the raw zone's journal to the secure
|
||||
* zone. If that fails, we recover by syncing up the databases
|
||||
* directly.
|
||||
*/
|
||||
result = sync_secure_journal(zone, zone->rss_raw, rjournal,
|
||||
start, end, &soatuple,
|
||||
&zone->rss_diff);
|
||||
if (result == DNS_R_UNCHANGED)
|
||||
goto failure;
|
||||
else if (result != ISC_R_SUCCESS)
|
||||
CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
|
||||
zone->rss_oldver, &soatuple,
|
||||
&zone->rss_diff));
|
||||
|
||||
CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
|
||||
zone->rss_newver));
|
||||
|
||||
if (soatuple != NULL) {
|
||||
isc_uint32_t oldserial, newserial, desired;
|
||||
|
||||
CHECK(dns_db_createsoatuple(zone->rss_db,
|
||||
zone->rss_oldver,
|
||||
zone->rss_diff.mctx,
|
||||
DNS_DIFFOP_DEL, &tuple));
|
||||
oldserial = dns_soa_getserial(&tuple->rdata);
|
||||
newserial = desired =
|
||||
dns_soa_getserial(&soatuple->rdata);
|
||||
if (!isc_serial_gt(newserial, oldserial)) {
|
||||
newserial = oldserial + 1;
|
||||
if (newserial == 0)
|
||||
newserial++;
|
||||
dns_soa_setserial(newserial, &soatuple->rdata);
|
||||
}
|
||||
CHECK(do_one_tuple(&tuple, zone->rss_db,
|
||||
zone->rss_newver, &zone->rss_diff));
|
||||
CHECK(do_one_tuple(&soatuple, zone->rss_db,
|
||||
zone->rss_newver, &zone->rss_diff));
|
||||
dns_zone_log(zone, ISC_LOG_INFO,
|
||||
"serial %u (unsigned %u)",
|
||||
newserial, desired);
|
||||
} else
|
||||
CHECK(update_soa_serial(zone->rss_db, zone->rss_newver,
|
||||
&zone->rss_diff, zone->mctx,
|
||||
zone->updatemethod));
|
||||
|
||||
}
|
||||
|
||||
dns_db_currentversion(db, &oldver);
|
||||
CHECK(dns_db_newversion(db, &newver));
|
||||
|
||||
/*
|
||||
* Try to apply diffs from the raw zone's journal to the secure
|
||||
* zone. If that fails, we recover by syncing up the databases
|
||||
* directly.
|
||||
*/
|
||||
result = sync_secure_journal(zone, raw, rjournal, start, end,
|
||||
&soatuple, &diff);
|
||||
if (result == DNS_R_UNCHANGED)
|
||||
result = dns_update_signaturesinc(&log, zone, zone->rss_db,
|
||||
zone->rss_oldver, zone->rss_newver,
|
||||
&zone->rss_diff,
|
||||
zone->sigvalidityinterval,
|
||||
&zone->rss_state);
|
||||
if (result == DNS_R_CONTINUE) {
|
||||
if (rjournal != NULL)
|
||||
dns_journal_destroy(&rjournal);
|
||||
isc_task_send(task, &event);
|
||||
fprintf(stderr, "looping on dns_update_signaturesinc\n");
|
||||
return;
|
||||
}
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto failure;
|
||||
else if (result != ISC_R_SUCCESS)
|
||||
CHECK(sync_secure_db(zone, raw, db, oldver, &soatuple, &diff));
|
||||
|
||||
CHECK(dns_diff_apply(&diff, db, newver));
|
||||
|
||||
if (soatuple != NULL) {
|
||||
isc_uint32_t oldserial, newserial, desired;
|
||||
|
||||
CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
|
||||
DNS_DIFFOP_DEL, &tuple));
|
||||
oldserial = dns_soa_getserial(&tuple->rdata);
|
||||
newserial = desired = dns_soa_getserial(&soatuple->rdata);
|
||||
if (!isc_serial_gt(newserial, oldserial)) {
|
||||
newserial = oldserial + 1;
|
||||
if (newserial == 0)
|
||||
newserial++;
|
||||
dns_soa_setserial(newserial, &soatuple->rdata);
|
||||
}
|
||||
CHECK(do_one_tuple(&tuple, db, newver, &diff));
|
||||
CHECK(do_one_tuple(&soatuple, db, newver, &diff));
|
||||
dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
|
||||
newserial, desired);
|
||||
} else
|
||||
CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
|
||||
zone->updatemethod));
|
||||
|
||||
CHECK(dns_update_signatures(&log, zone, db, oldver, newver,
|
||||
&diff, zone->sigvalidityinterval));
|
||||
|
||||
CHECK(zone_journal(zone, &diff, &end, "receive_secure_serial"));
|
||||
if (rjournal == NULL)
|
||||
CHECK(dns_journal_open(zone->rss_raw->mctx,
|
||||
zone->rss_raw->journal,
|
||||
DNS_JOURNAL_WRITE, &rjournal));
|
||||
CHECK(zone_journal(zone, &zone->rss_diff, &end,
|
||||
"receive_secure_serial"));
|
||||
|
||||
dns_journal_set_sourceserial(rjournal, end);
|
||||
dns_journal_commit(rjournal);
|
||||
|
|
@ -13072,12 +13140,15 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) {
|
|||
zone_settimer(zone, &timenow);
|
||||
UNLOCK_ZONE(zone);
|
||||
|
||||
dns_db_closeversion(db, &oldver, ISC_FALSE);
|
||||
dns_db_closeversion(db, &newver, ISC_TRUE);
|
||||
dns_db_closeversion(zone->rss_db, &zone->rss_oldver, ISC_FALSE);
|
||||
dns_db_closeversion(zone->rss_db, &zone->rss_newver, ISC_TRUE);
|
||||
|
||||
failure:
|
||||
if (raw != NULL)
|
||||
dns_zone_detach(&raw);
|
||||
isc_event_free(&zone->rss_event);
|
||||
event = ISC_LIST_HEAD(zone->rss_events);
|
||||
|
||||
if (zone->rss_raw != NULL)
|
||||
dns_zone_detach(&zone->rss_raw);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
|
||||
dns_result_totext(result));
|
||||
|
|
@ -13085,20 +13156,28 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) {
|
|||
dns_difftuple_free(&tuple);
|
||||
if (soatuple != NULL)
|
||||
dns_difftuple_free(&soatuple);
|
||||
if (db != NULL) {
|
||||
if (oldver != NULL)
|
||||
dns_db_closeversion(db, &oldver, ISC_FALSE);
|
||||
if (newver != NULL)
|
||||
dns_db_closeversion(db, &newver, ISC_FALSE);
|
||||
dns_db_detach(&db);
|
||||
if (zone->rss_db != NULL) {
|
||||
if (zone->rss_oldver != NULL)
|
||||
dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
|
||||
ISC_FALSE);
|
||||
if (zone->rss_newver != NULL)
|
||||
dns_db_closeversion(zone->rss_db, &zone->rss_newver,
|
||||
ISC_FALSE);
|
||||
dns_db_detach(&zone->rss_db);
|
||||
}
|
||||
INSIST(zone->rss_oldver == NULL);
|
||||
INSIST(zone->rss_newver == NULL);
|
||||
if (rjournal != NULL)
|
||||
dns_journal_destroy(&rjournal);
|
||||
dns_diff_clear(&diff);
|
||||
dns_zone_idetach(&zone);
|
||||
dns_diff_clear(&zone->rss_diff);
|
||||
|
||||
INSIST(oldver == NULL);
|
||||
INSIST(newver == NULL);
|
||||
if (event != NULL) {
|
||||
LOCK_ZONE(zone);
|
||||
INSIST(zone->irefs > 1);
|
||||
zone->irefs--;
|
||||
goto nextevent;
|
||||
}
|
||||
dns_zone_idetach(&zone);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
|
|
@ -16029,6 +16108,12 @@ dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
|
|||
zone->signatures = signatures;
|
||||
}
|
||||
|
||||
isc_uint32_t
|
||||
dns_zone_getsignatures(dns_zone_t *zone) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
return (zone->signatures);
|
||||
}
|
||||
|
||||
void
|
||||
dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
|
|
|||
Loading…
Reference in a new issue