From: Matt Corallo Date: Tue, 6 Feb 2024 01:46:21 +0000 (+0000) Subject: Marginally resolve time rollovers, giving us until 2133 X-Git-Tag: v0.5.4~103 X-Git-Url: http://git.bitcoin.ninja/?a=commitdiff_plain;h=38fae046fd1ff66dd65826d95d58adf0c19a2faf;p=dnssec-prover Marginally resolve time rollovers, giving us until 2133 --- diff --git a/src/lib.rs b/src/lib.rs index 667624a..c60f704 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -240,13 +240,17 @@ pub struct VerifiedRRStream<'a> { /// /// Any records in [`Self::verified_rrs`] should not be considered valid unless this is before /// the current UNIX time. - pub valid_from: u32, + /// + /// While the field here is a u64, the algorithm used to identify rollovers will fail in 2133. + pub valid_from: u64, /// The earliest [`RRSig::expiration`] of all the [`RRSig`]s validated to verify /// [`Self::verified_rrs`]. /// /// Any records in [`Self::verified_rrs`] should not be considered valid unless this is after /// the current UNIX time. - pub expires: u32, + /// + /// While the field here is a u64, the algorithm used to identify rollovers will fail in 2133. + pub expires: u64, /// The minimum [`RRSig::orig_ttl`] of all the [`RRSig`]s validated to verify /// [`Self::verified_rrs`]. /// @@ -254,6 +258,17 @@ pub struct VerifiedRRStream<'a> { pub max_cache_ttl: u32, } +fn resolve_time(time: u32) -> u64 { + // RFC 2065 was published in January 1997, so we arbitrarily use that as a cutoff and assume + // any timestamps before then are actually past 2106 instead. + // We ignore leap years for simplicity. + if time < 60*60*24*365*27 { + (time as u64) + (u32::MAX as u64) + } else { + time.into() + } +} + /// Verifies the given set of resource records. /// /// Given a set of arbitrary records, this attempts to validate DNSSEC data from the [`root_hints`] @@ -269,7 +284,7 @@ pub fn verify_rr_stream<'a>(inp: &'a [RR]) -> Result, Valid let mut res = Vec::new(); let mut pending_ds_sets = Vec::with_capacity(1); let mut latest_inception = 0; - let mut earliest_expiry = u32::MAX; + let mut earliest_expiry = u64::MAX; let mut min_ttl = u32::MAX; 'next_zone: while zone == "." || !pending_ds_sets.is_empty() { let mut found_unsupported_alg = false; @@ -297,8 +312,8 @@ pub fn verify_rr_stream<'a>(inp: &'a [RR]) -> Result, Valid verify_dnskey_rrsig(rrsig, next_ds_set.clone().unwrap(), dnskeys.clone().collect()) }; if dnskeys_verified.is_ok() { - latest_inception = cmp::max(latest_inception, rrsig.inception); - earliest_expiry = cmp::min(earliest_expiry, rrsig.expiration); + latest_inception = cmp::max(latest_inception, resolve_time(rrsig.inception)); + earliest_expiry = cmp::min(earliest_expiry, resolve_time(rrsig.expiration)); min_ttl = cmp::min(min_ttl, rrsig.orig_ttl); for rrsig in inp.iter() .filter_map(|rr| if let RR::RRSig(sig) = rr { Some(sig) } else { None }) @@ -308,8 +323,8 @@ pub fn verify_rr_stream<'a>(inp: &'a [RR]) -> Result, Valid let signed_records = inp.iter() .filter(|rr| rr.name() == &rrsig.name && rr.ty() == rrsig.ty); verify_rrsig(rrsig, dnskeys.clone(), signed_records.clone().collect())?; - latest_inception = cmp::max(latest_inception, rrsig.inception); - earliest_expiry = cmp::min(earliest_expiry, rrsig.expiration); + latest_inception = cmp::max(latest_inception, resolve_time(rrsig.inception)); + earliest_expiry = cmp::min(earliest_expiry, resolve_time(rrsig.expiration)); min_ttl = cmp::min(min_ttl, rrsig.orig_ttl); match rrsig.ty { // RRSigs shouldn't cover child `DnsKey`s or other `RRSig`s diff --git a/src/query.rs b/src/query.rs index 7599afc..b82f0a6 100644 --- a/src/query.rs +++ b/src/query.rs @@ -211,6 +211,7 @@ mod tests { use rand::seq::SliceRandom; use std::net::ToSocketAddrs; + use std::time::SystemTime; #[test] fn test_txt_query() { @@ -222,6 +223,10 @@ mod tests { rrs.shuffle(&mut rand::rngs::OsRng); let verified_rrs = verify_rr_stream(&rrs).unwrap(); assert_eq!(verified_rrs.verified_rrs.len(), 1); + + let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + assert!(verified_rrs.valid_from < now); + assert!(verified_rrs.expires > now); } #[cfg(feature = "tokio")] @@ -238,5 +243,9 @@ mod tests { rrs.shuffle(&mut rand::rngs::OsRng); let verified_rrs = verify_rr_stream(&rrs).unwrap(); assert_eq!(verified_rrs.verified_rrs.len(), 1); + + let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + assert!(verified_rrs.valid_from < now); + assert!(verified_rrs.expires > now); } }