From 660dc3eba75b2d0ba21e5a697387acb615293140 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 25 Feb 2020 12:09:13 +1100 Subject: [PATCH 1/3] use the full sig-validity-interval for RRSIG(SOA) --- lib/dns/update.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/dns/update.c b/lib/dns/update.c index e3477acb1b..6ba2fbd53a 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -1467,7 +1467,7 @@ struct dns_update_state { dns_diff_t work; dst_key_t *zone_keys[DNS_MAXZONEKEYS]; unsigned int nkeys; - isc_stdtime_t inception, expire, keyexpire; + isc_stdtime_t inception, expire, soaexpire, keyexpire; dns_ttl_t nsecttl; bool check_ksk, keyset_kskonly, build_nsec3; enum { sign_updates, @@ -1552,6 +1552,7 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, state->inception = now - 3600; /* Allow for some clock skew. */ state->expire = now + dns__jitter_expire(zone, sigvalidityinterval); + state->soaexpire = now + sigvalidityinterval; state->keyexpire = dns_zone_getkeyvalidityinterval(zone); if (state->keyexpire == 0) { state->keyexpire = state->expire; @@ -1661,6 +1662,8 @@ next_state: type == dns_rdatatype_cds) { exp = state->keyexpire; + } else if (type == dns_rdatatype_soa) { + exp = state->soaexpire; } else { exp = state->expire; } From a24fd55836775a717efaedd3c0e080a991dc6b73 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 25 Feb 2020 12:11:27 +1100 Subject: [PATCH 2/3] sort RRSIG(SOA) to be last of RRSIGs with a common re-resign time --- bin/tests/system/statschannel/tests.sh | 18 +++++++----------- lib/dns/rbtdb.c | 14 +++++++++++--- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/bin/tests/system/statschannel/tests.sh b/bin/tests/system/statschannel/tests.sh index 39d12a5697..333018a03a 100644 --- a/bin/tests/system/statschannel/tests.sh +++ b/bin/tests/system/statschannel/tests.sh @@ -282,14 +282,10 @@ ret=0 # almost right away, this should trigger 10 zsk and 1 ksk sign operations. # However, the DNSSEC maintenance assumes when we see the SOA record we have # walked the whole zone, since the SOA record should always have the most -# recent signature. This however is not always the case, for example when -# the signature expiration is the same, `dns_db_getsigningtime could return -# the SOA RRset before a competing RRset. This happens here and so the -# SOA RRset is updated and resigned twice at startup, that explains the -# additional zsk sign operation (11 instead of 10). -echo "${refresh_prefix} ${zsk_id}: 11" > zones.expect +# recent signature. +echo "${refresh_prefix} ${zsk_id}: 10" > zones.expect echo "${refresh_prefix} ${ksk_id}: 1" >> zones.expect -echo "${sign_prefix} ${zsk_id}: 11" >> zones.expect +echo "${sign_prefix} ${zsk_id}: 10" >> zones.expect echo "${sign_prefix} ${ksk_id}: 1" >> zones.expect cat zones.expect | sort > zones.expect.$n rm -f zones.expect @@ -317,9 +313,9 @@ echo update add $zone. 300 in txt "nsupdate added me" echo send ) | $NSUPDATE # This should trigger the resign of SOA, TXT and NSEC (+3 zsk). -echo "${refresh_prefix} ${zsk_id}: 11" > zones.expect +echo "${refresh_prefix} ${zsk_id}: 10" > zones.expect echo "${refresh_prefix} ${ksk_id}: 1" >> zones.expect -echo "${sign_prefix} ${zsk_id}: 14" >> zones.expect +echo "${sign_prefix} ${zsk_id}: 13" >> zones.expect echo "${sign_prefix} ${ksk_id}: 1" >> zones.expect cat zones.expect | sort > zones.expect.$n rm -f zones.expect @@ -345,9 +341,9 @@ zsk=$("$KEYGEN" -K ns2 -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") $SETTIME -K ns2 -P now -A never $zsk.key > /dev/null loadkeys_on 2 $zone || ret=1 # This should trigger the resign of SOA (+1 zsk) and DNSKEY (+1 ksk). -echo "${refresh_prefix} ${zsk_id}: 12" > zones.expect +echo "${refresh_prefix} ${zsk_id}: 11" > zones.expect echo "${refresh_prefix} ${ksk_id}: 2" >> zones.expect -echo "${sign_prefix} ${zsk_id}: 15" >> zones.expect +echo "${sign_prefix} ${zsk_id}: 14" >> zones.expect echo "${sign_prefix} ${ksk_id}: 2" >> zones.expect cat zones.expect | sort > zones.expect.$n rm -f zones.expect diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index bd35ae3b97..e7554b0f24 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -131,8 +131,10 @@ typedef uint32_t rbtdb_rdatatype_t; RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_cname) #define RBTDB_RDATATYPE_SIGDNAME \ RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_dname) -#define RBTDB_RDATATYPE_SIGDDS \ +#define RBTDB_RDATATYPE_SIGDS \ RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ds) +#define RBTDB_RDATATYPE_SIGSOA \ + RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_soa) #define RBTDB_RDATATYPE_NCACHEANY RBTDB_RDATATYPE_VALUE(0, dns_rdatatype_any) #define RBTDB_INITLOCK(l) isc_rwlock_init((l), 0, 0) @@ -903,13 +905,19 @@ ttl_sooner(void *v1, void *v2) { return (h1->rdh_ttl < h2->rdh_ttl); } +/*% + * Return which RRset should be resigned sooner. If the RRsets have the + * same signing time, prefer the other RRset over the SOA RRset. + */ static bool resign_sooner(void *v1, void *v2) { rdatasetheader_t *h1 = v1; rdatasetheader_t *h2 = v2; return (h1->resign < h2->resign || - (h1->resign == h2->resign && h1->resign_lsb < h2->resign_lsb)); + (h1->resign == h2->resign && h1->resign_lsb < h2->resign_lsb) || + (h1->resign == h2->resign && h1->resign_lsb == h2->resign_lsb && + h2->type == RBTDB_RDATATYPE_SIGSOA)); } /*% @@ -6250,7 +6258,7 @@ find_header: (header->type == dns_rdatatype_a || header->type == dns_rdatatype_aaaa || header->type == dns_rdatatype_ds || - header->type == RBTDB_RDATATYPE_SIGDDS) && + header->type == RBTDB_RDATATYPE_SIGDS) && !header_nx && !newheader_nx && header->trust >= newheader->trust && dns_rdataslab_equal((unsigned char *)header, From 88c828cb9ff876319f01ce37d26ad4a052201ec5 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 25 Feb 2020 12:17:11 +1100 Subject: [PATCH 3/3] capture named-journalprint output --- bin/tests/system/inline/tests.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/tests/system/inline/tests.sh b/bin/tests/system/inline/tests.sh index a5ed9c679a..059840aa82 100755 --- a/bin/tests/system/inline/tests.sh +++ b/bin/tests/system/inline/tests.sh @@ -417,7 +417,8 @@ status=`expr $status + $ret` n=`expr $n + 1` echo_i "checking master zone that was updated while offline is correct ($n)" ret=0 -serial=`$DIG $DIGOPTS +nodnssec +short @10.53.0.3 updated SOA | awk '{print $3}'` +$DIG $DIGOPTS +nodnssec +short @10.53.0.3 updated SOA >dig.out.ns2.soa.test$n +serial=`awk '{print $3}' dig.out.ns2.soa.test$n` # serial should have changed [ "$serial" = "2000042407" ] && ret=1 # e.updated should exist and should be signed @@ -428,9 +429,10 @@ grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1 # of master2.db, and should show a minimal diff: no more than 8 added # records (SOA/RRSIG, 2 x NSEC/RRSIG, A/RRSIG), and 4 removed records # (SOA/RRSIG, NSEC/RRSIG). -serial=`$JOURNALPRINT ns3/updated.db.signed.jnl | head -1 | awk '{print $4}'` +$JOURNALPRINT ns3/updated.db.signed.jnl >journalprint.out.test$n +serial=`awk '/Source serial =/ {print $4}' journalprint.out.test$n` [ "$serial" = "2000042408" ] || ret=1 -diffsize=`$JOURNALPRINT ns3/updated.db.signed.jnl | wc -l` +diffsize=`wc -l < journalprint.out.test$n` [ "$diffsize" -le 13 ] || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret`