]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Print warning when falling back to increment soa serial method
authorOndřej Surý <ondrej@sury.org>
Thu, 10 Dec 2020 09:31:31 +0000 (10:31 +0100)
committerOndřej Surý <ondrej@isc.org>
Sat, 12 Dec 2020 06:55:29 +0000 (07:55 +0100)
When using the `unixtime` or `date` method to update the SOA serial,
`named` and `dnssec-signzone` would silently fallback to `increment`
method to prevent the new serial number to be smaller than the old
serial number (using the serial number arithmetics).  Add a warning
message when such fallback happens.

(cherry picked from commit ef685bab5c0ce68e98328dd19dfb1fb8f9d0fdee)

bin/dnssec/dnssec-signzone.c
lib/dns/include/dns/update.h
lib/dns/tests/update_test.c
lib/dns/update.c
lib/dns/zone.c
lib/ns/update.c

index c319693a2ed0b8231aafb1d5f4377ff911eccf00..e6c36ac6991c383f69644a066a933569cf017f79 100644 (file)
@@ -1351,7 +1351,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) {
@@ -1375,16 +1376,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
index 7a816e2292927506e508faf20c2d702649f819be..f566488e3ec24518fb1dcc0367122b0f1e1a512e 100644 (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
index e97c750f266f8f20c06b8fb41803bd4e92b7d82f..bc789b2be29d5ffd97bba8f780d4e0c9026529b3 100644 (file)
@@ -111,7 +111,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);
@@ -125,7 +125,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);
@@ -142,7 +142,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);
@@ -159,7 +159,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);
@@ -176,7 +176,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);
@@ -194,7 +194,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);
@@ -212,7 +212,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);
@@ -229,7 +229,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);
@@ -246,7 +246,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);
@@ -260,10 +260,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);
@@ -279,9 +279,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);
@@ -296,10 +296,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);
index 4a8a03c0c179378b8ba45837de3dd216227cf422..43dad7035a331bab00f4e4ba937f92c57e9fd877 100644 (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);
 }
index b536ae3b7a38afed89875b304cc6afde60d1f1a1..7b7d1f36c324005488b057cd10230856819badb3 100644 (file)
@@ -4305,12 +4305,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);
 
@@ -4319,7 +4321,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));
@@ -4576,7 +4583,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"));
 
@@ -7123,7 +7130,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,
@@ -8831,7 +8838,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,
@@ -9574,7 +9581,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,
@@ -10581,7 +10588,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;
@@ -10812,7 +10819,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;
@@ -15961,7 +15968,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));
                }
@@ -19856,7 +19864,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));
@@ -20653,7 +20661,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,
@@ -20938,7 +20946,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,
index cb0ff5cd84b424913d810117138b24ed9c4ccfd7..277bc1b6ebba6e3eb04e6486d84c401402df7463 100644 (file)
@@ -1473,7 +1473,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));