Merge branch '2058-print-warning-when-fallback-to-soaserial-increment' into 'main'

Resolve "`dnssec-signzone -N unixtime` behaves like `increment`"

Closes #2058

See merge request isc-projects/bind9!4487
This commit is contained in:
Ondřej Surý 2020-12-12 06:52:50 +00:00
commit 27f0988b52
10 changed files with 121 additions and 58 deletions

View file

@ -1,3 +1,6 @@
5550. [func] Print a warning when falling back to the "increment" SOA
serial method. [GL #2058]
5549. [protocol] Serve ipv4only.arpa when dns64 is configured. [GL #385]
5548. [placeholder]

View file

@ -1352,7 +1352,8 @@ setsoaserial(uint32_t serial, dns_updatemethod_t method) {
dns_dbnode_t *node = NULL;
dns_rdataset_t rdataset;
dns_rdata_t rdata = DNS_RDATA_INIT;
uint32_t old_serial, new_serial;
uint32_t old_serial, new_serial = 0;
dns_updatemethod_t used = dns_updatemethod_none;
result = dns_db_getoriginnode(gdb, &node);
if (result != ISC_R_SUCCESS) {
@ -1376,16 +1377,20 @@ setsoaserial(uint32_t serial, dns_updatemethod_t method) {
if (method == dns_updatemethod_date ||
method == dns_updatemethod_unixtime) {
new_serial = dns_update_soaserial(old_serial, method);
new_serial = dns_update_soaserial(old_serial, method, &used);
} else if (serial != 0 || method == dns_updatemethod_none) {
/* Set SOA serial to the value provided. */
new_serial = serial;
used = method;
} else {
/* Increment SOA serial using RFC 1982 arithmetic */
new_serial = (old_serial + 1) & 0xFFFFFFFF;
if (new_serial == 0) {
new_serial = 1;
}
new_serial = dns_update_soaserial(old_serial, method, &used);
}
if (method != used) {
fprintf(stderr,
"%s: warning: Serial number would not advance, "
"using increment method instead\n",
program);
}
/* If the new serial is not likely to cause a zone transfer

View file

@ -202,10 +202,16 @@ Options
This format increments the SOA serial number using :rfc:`1982` arithmetic.
**unixtime**
This format sets the SOA serial number to the number of seconds since the beginning of the Unix epoch.
This format sets the SOA serial number to the number of seconds
since the beginning of the Unix epoch, unless the serial
number is already greater than or equal to that value, in
which case it is simply incremented by one.
**date**
This format sets the SOA serial number to today's date, in YYYYMMDDNN format.
This format sets the SOA serial number to today's date, in
YYYYMMDDNN format, unless the serial number is already greater
than or equal to that value, in which case it is simply
incremented by one.
``-o origin``
This option sets the zone origin. If not specified, the name of the zone file is

View file

@ -203,10 +203,16 @@ This format indicates that the SOA serial number should not be modified.
This format increments the SOA serial number using \fI\%RFC 1982\fP arithmetic.
.TP
\fBunixtime\fP
This format sets the SOA serial number to the number of seconds since the beginning of the Unix epoch.
This format sets the SOA serial number to the number of seconds
since the beginning of the Unix epoch, unless the serial
number is already greater than or equal to that value, in
which case it is simply incremented by one.
.TP
\fBdate\fP
This format sets the SOA serial number to today\(aqs date, in YYYYMMDDNN format.
This format sets the SOA serial number to today\(aqs date, in
YYYYMMDDNN format, unless the serial number is already greater
than or equal to that value, in which case it is simply
incremented by one.
.UNINDENT
.TP
.B \fB\-o origin\fP

View file

@ -57,6 +57,13 @@ Feature Changes
- ``ipv4only.arpa`` is now served when ``dns64`` is configured. [GL #385]
- When using the ``unixtime`` or ``date`` method to update the SOA
serial number, ``named`` and ``dnssec-signzone`` silently fell back to
the ``increment`` method to prevent the new serial number from being
smaller than the old serial number (using serial number arithmetics).
``dnsssec-signzone`` now prints a warning message, and ``named`` logs
a warning, when such a fallback happens. [GL #2058]
Bug Fixes
~~~~~~~~~

View file

@ -38,15 +38,23 @@ ISC_LANG_BEGINDECLS
***/
uint32_t
dns_update_soaserial(uint32_t serial, dns_updatemethod_t method);
dns_update_soaserial(uint32_t serial, dns_updatemethod_t method,
dns_updatemethod_t *used);
/*%<
* Return the next serial number after 'serial', depending on the
* update method 'method':
*
*\li * dns_updatemethod_increment increments the serial number by one
*\li * dns_updatemethod_date sets the serial number to YYYYMMDD00
*\li * dns_updatemethod_unixtime sets the serial number to the current
* time (seconds since UNIX epoch) if possible, or increments by one
* if not.
* time (seconds since UNIX epoch)
*\li * dns_updatemethod_none just returns the given serial
*
* NOTE: The dns_updatemethod_increment will be used if dns_updatemethod_date or
* dns_updatemethod_unixtime is used and the new serial number would be lower
* than current serial number.
*
* Sets *used to the method that was used.
*/
isc_result_t

View file

@ -88,7 +88,7 @@ increment_test(void **state) {
UNUSED(state);
serial = dns_update_soaserial(old, dns_updatemethod_increment);
serial = dns_update_soaserial(old, dns_updatemethod_increment, NULL);
assert_true(isc_serial_lt(old, serial));
assert_int_not_equal(serial, 0);
assert_int_equal(serial, 51);
@ -102,7 +102,7 @@ increment_past_zero_test(void **state) {
UNUSED(state);
serial = dns_update_soaserial(old, dns_updatemethod_increment);
serial = dns_update_soaserial(old, dns_updatemethod_increment, NULL);
assert_true(isc_serial_lt(old, serial));
assert_int_not_equal(serial, 0);
assert_int_equal(serial, 1u);
@ -119,7 +119,7 @@ past_to_unix_test(void **state) {
set_mystdtime(2011, 6, 22);
old = mystdtime - 1;
serial = dns_update_soaserial(old, dns_updatemethod_unixtime);
serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
assert_true(isc_serial_lt(old, serial));
assert_int_not_equal(serial, 0);
assert_int_equal(serial, mystdtime);
@ -136,7 +136,7 @@ now_to_unix_test(void **state) {
set_mystdtime(2011, 6, 22);
old = mystdtime;
serial = dns_update_soaserial(old, dns_updatemethod_unixtime);
serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
assert_true(isc_serial_lt(old, serial));
assert_int_not_equal(serial, 0);
assert_int_equal(serial, old + 1);
@ -153,7 +153,7 @@ future_to_unix_test(void **state) {
set_mystdtime(2011, 6, 22);
old = mystdtime + 1;
serial = dns_update_soaserial(old, dns_updatemethod_unixtime);
serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
assert_true(isc_serial_lt(old, serial));
assert_int_not_equal(serial, 0);
assert_int_equal(serial, old + 1);
@ -171,7 +171,7 @@ undefined_plus1_to_unix_test(void **state) {
old = mystdtime ^ 0x80000000u;
old += 1;
serial = dns_update_soaserial(old, dns_updatemethod_unixtime);
serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
assert_true(isc_serial_lt(old, serial));
assert_int_not_equal(serial, 0);
assert_int_equal(serial, mystdtime);
@ -189,7 +189,7 @@ undefined_minus1_to_unix_test(void **state) {
old = mystdtime ^ 0x80000000u;
old -= 1;
serial = dns_update_soaserial(old, dns_updatemethod_unixtime);
serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
assert_true(isc_serial_lt(old, serial));
assert_int_not_equal(serial, 0);
assert_int_equal(serial, old + 1);
@ -206,7 +206,7 @@ undefined_to_unix_test(void **state) {
set_mystdtime(2011, 6, 22);
old = mystdtime ^ 0x80000000u;
serial = dns_update_soaserial(old, dns_updatemethod_unixtime);
serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
assert_true(isc_serial_lt(old, serial));
assert_int_not_equal(serial, 0);
assert_int_equal(serial, old + 1);
@ -223,7 +223,7 @@ unixtime_zero_test(void **state) {
mystdtime = 0;
old = 0xfffffff0;
serial = dns_update_soaserial(old, dns_updatemethod_unixtime);
serial = dns_update_soaserial(old, dns_updatemethod_unixtime, NULL);
assert_true(isc_serial_lt(old, serial));
assert_int_not_equal(serial, 0);
assert_int_equal(serial, old + 1);
@ -237,10 +237,10 @@ past_to_date_test(void **state) {
UNUSED(state);
set_mystdtime(2014, 3, 31);
old = dns_update_soaserial(0, dns_updatemethod_date);
old = dns_update_soaserial(0, dns_updatemethod_date, NULL);
set_mystdtime(2014, 4, 1);
serial = dns_update_soaserial(old, dns_updatemethod_date);
serial = dns_update_soaserial(old, dns_updatemethod_date, NULL);
assert_true(isc_serial_lt(old, serial));
assert_int_not_equal(serial, 0);
@ -256,9 +256,9 @@ now_to_date_test(void **state) {
UNUSED(state);
set_mystdtime(2014, 4, 1);
old = dns_update_soaserial(0, dns_updatemethod_date);
old = dns_update_soaserial(0, dns_updatemethod_date, NULL);
serial = dns_update_soaserial(old, dns_updatemethod_date);
serial = dns_update_soaserial(old, dns_updatemethod_date, NULL);
assert_true(isc_serial_lt(old, serial));
assert_int_not_equal(serial, 0);
assert_int_equal(serial, 2014040101);
@ -273,10 +273,10 @@ future_to_date_test(void **state) {
UNUSED(state);
set_mystdtime(2014, 4, 1);
old = dns_update_soaserial(0, dns_updatemethod_date);
old = dns_update_soaserial(0, dns_updatemethod_date, NULL);
set_mystdtime(2014, 3, 31);
serial = dns_update_soaserial(old, dns_updatemethod_date);
serial = dns_update_soaserial(old, dns_updatemethod_date, NULL);
assert_true(isc_serial_lt(old, serial));
assert_int_not_equal(serial, 0);
assert_int_equal(serial, 2014040101);

View file

@ -2204,35 +2204,55 @@ epoch_to_yyyymmdd(time_t when) {
tm->tm_mday);
}
uint32_t
dns_update_soaserial(uint32_t serial, dns_updatemethod_t method) {
static uint32_t
dns__update_soaserial(uint32_t serial, dns_updatemethod_t method) {
isc_stdtime_t now;
uint32_t new_serial;
switch (method) {
case dns_updatemethod_none:
return (serial);
case dns_updatemethod_unixtime:
isc_stdtime_get(&now);
if (now != 0 && isc_serial_gt(now, serial)) {
return (now);
}
break;
return (now);
case dns_updatemethod_date:
isc_stdtime_get(&now);
new_serial = epoch_to_yyyymmdd((time_t)now) * 100;
if (new_serial != 0 && isc_serial_gt(new_serial, serial)) {
return (new_serial);
return (epoch_to_yyyymmdd((time_t)now) * 100);
case dns_updatemethod_increment:
/* RFC1982 */
serial = (serial + 1) & 0xFFFFFFFF;
if (serial == 0) {
return (1);
}
return (serial);
default:
INSIST(0);
ISC_UNREACHABLE();
}
}
uint32_t
dns_update_soaserial(uint32_t serial, dns_updatemethod_t method,
dns_updatemethod_t *used) {
uint32_t new_serial = dns__update_soaserial(serial, method);
switch (method) {
case dns_updatemethod_none:
case dns_updatemethod_increment:
break;
case dns_updatemethod_unixtime:
case dns_updatemethod_date:
if (!(new_serial != 0 && isc_serial_gt(new_serial, serial))) {
method = dns_updatemethod_increment;
new_serial = dns__update_soaserial(serial, method);
}
break;
default:
INSIST(0);
ISC_UNREACHABLE();
}
/* RFC1982 */
serial = (serial + 1) & 0xFFFFFFFF;
if (serial == 0) {
serial = 1;
if (used != NULL) {
*used = method;
}
return (serial);
return (new_serial);
}

View file

@ -4346,12 +4346,14 @@ update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
}
static isc_result_t
update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
isc_mem_t *mctx, dns_updatemethod_t method) {
update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
dns_diff_t *diff, isc_mem_t *mctx,
dns_updatemethod_t method) {
dns_difftuple_t *deltuple = NULL;
dns_difftuple_t *addtuple = NULL;
uint32_t serial;
isc_result_t result;
dns_updatemethod_t used = dns_updatemethod_none;
INSIST(method != dns_updatemethod_none);
@ -4360,7 +4362,12 @@ update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
addtuple->op = DNS_DIFFOP_ADD;
serial = dns_soa_getserial(&addtuple->rdata);
serial = dns_update_soaserial(serial, method);
serial = dns_update_soaserial(serial, method, &used);
if (method != used) {
dns_zone_log(zone, ISC_LOG_WARNING,
"update_soa_serial:new serial would be lower than "
"old serial, using increment method instead");
}
dns_soa_setserial(serial, &addtuple->rdata);
CHECK(do_one_tuple(&deltuple, db, ver, diff));
CHECK(do_one_tuple(&addtuple, db, ver, diff));
@ -4617,7 +4624,7 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
result = arg.result;
if (changed) {
/* Write changes to journal file. */
CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
zone->updatemethod));
CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
@ -7164,7 +7171,7 @@ zone_resigninc(dns_zone_t *zone) {
}
/* Increment SOA serial if we have made changes */
result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
zone->updatemethod);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
@ -8872,7 +8879,7 @@ skip_removals:
goto failure;
}
result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
zone->updatemethod);
if (result != ISC_R_SUCCESS) {
dnssec_log(zone, ISC_LOG_ERROR,
@ -9615,7 +9622,7 @@ zone_sign(dns_zone_t *zone) {
goto cleanup;
}
result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
zone->updatemethod);
if (result != ISC_R_SUCCESS) {
dnssec_log(zone, ISC_LOG_ERROR,
@ -10624,7 +10631,7 @@ anchors_done:
done:
if (!ISC_LIST_EMPTY(diff.tuples)) {
/* Write changes to journal file. */
CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
CHECK(update_soa_serial(zone, kfetch->db, ver, &diff, mctx,
zone->updatemethod));
CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
commit = true;
@ -10855,7 +10862,7 @@ zone_refreshkeys(dns_zone_t *zone) {
}
}
if (!ISC_LIST_EMPTY(diff.tuples)) {
CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
zone->updatemethod));
CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
commit = true;
@ -16013,7 +16020,8 @@ nextevent:
CHECK(do_one_tuple(&soatuple, zone->rss_db,
zone->rss_newver, &zone->rss_diff));
} else {
CHECK(update_soa_serial(zone->rss_db, zone->rss_newver,
CHECK(update_soa_serial(zone, zone->rss_db,
zone->rss_newver,
&zone->rss_diff, zone->mctx,
zone->updatemethod));
}
@ -19910,7 +19918,7 @@ zone_rekey(dns_zone_t *zone) {
CHECK(clean_nsec3param(zone, db, ver, &diff));
CHECK(add_signing_records(db, zone->privatetype, ver,
&diff, (newalg || fullsign)));
CHECK(update_soa_serial(db, ver, &diff, mctx,
CHECK(update_soa_serial(zone, db, ver, &diff, mctx,
zone->updatemethod));
CHECK(add_chains(zone, db, ver, &diff));
CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
@ -20719,7 +20727,7 @@ keydone(isc_task_t *task, isc_event_t *event) {
if (!ISC_LIST_EMPTY(diff.tuples)) {
/* Write changes to journal file. */
CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
zone->updatemethod));
result = dns_update_signatures(&log, zone, db, oldver, newver,
@ -21004,7 +21012,7 @@ rss_post(dns_zone_t *zone, isc_event_t *event) {
* records.
*/
if (!ISC_LIST_EMPTY(diff.tuples)) {
CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
zone->updatemethod));
result = dns_update_signatures(&log, zone, db, oldver, newver,
&diff,

View file

@ -1486,7 +1486,7 @@ update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
addtuple->op = DNS_DIFFOP_ADD;
serial = dns_soa_getserial(&addtuple->rdata);
serial = dns_update_soaserial(serial, method);
serial = dns_update_soaserial(serial, method, NULL);
dns_soa_setserial(serial, &addtuple->rdata);
CHECK(do_one_tuple(&deltuple, db, ver, diff));
CHECK(do_one_tuple(&addtuple, db, ver, diff));