X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fvalidation.rs;h=ae0bb58f15de418ecc7305695374d4d8fcd89abd;hb=3d98f4ce7f1c8d824aa411bd5c08e2734bd98b91;hp=999f7878cf9109d98e6ffb771980693067e33516;hpb=dc8996dd008fbf0ec3123c58c1a7024f5003dfc6;p=dnssec-prover diff --git a/src/validation.rs b/src/validation.rs index 999f787..ae0bb58 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -162,7 +162,7 @@ where T: IntoIterator, I: Iterator + Clone { let mut had_ds = false; for ds in dses.clone() { had_ds = true; - if ds.digest_type == 2 || ds.digest_type == 4 { + if ds.digest_type == 1 || ds.digest_type == 2 || ds.digest_type == 4 { had_known_digest_type = true; break; } @@ -171,11 +171,13 @@ where T: IntoIterator, I: Iterator + Clone { if !had_known_digest_type { return Err(ValidationError::UnsupportedAlgorithm); } for dnskey in records.iter() { + // Only use SHA1 DS records if we don't have any SHA256/SHA384 DS RRs. + let trust_sha1 = dses.clone().all(|ds| ds.digest_type != 2 && ds.digest_type != 4); for ds in dses.clone() { - if ds.digest_type != 2 && ds.digest_type != 4 { continue; } if ds.alg != dnskey.alg { continue; } if dnskey.key_tag() == ds.key_tag { let alg = match ds.digest_type { + 1 if trust_sha1 => &ring::digest::SHA1_FOR_LEGACY_USE_ONLY, 2 => &ring::digest::SHA256, 4 => &ring::digest::SHA384, _ => continue, @@ -207,7 +209,7 @@ pub struct VerifiedRRStream<'a> { /// The set of verified [`RR`]s. /// /// These are not valid unless the current UNIX time is between [`Self::valid_from`] and - /// [`Self::expiration`]. + /// [`Self::expires`]. pub verified_rrs: Vec<&'a RR>, /// The latest [`RRSig::inception`] of all the [`RRSig`]s validated to verify /// [`Self::verified_rrs`]. @@ -251,8 +253,8 @@ fn resolve_time(time: u32) -> u64 { /// All records which could be validated are returned, though if an error is found validating any /// contained record, only `Err` will be returned. /// -/// You MUST check that the current UNIX time is between [`VerifiedRRStream::latest_inception`] and -/// [`VerifiedRRStream::earliest_expiry`]. +/// You MUST check that the current UNIX time is between [`VerifiedRRStream::valid_from`] and +/// [`VerifiedRRStream::expires`]. pub fn verify_rr_stream<'a>(inp: &'a [RR]) -> Result, ValidationError> { let mut zone = "."; let mut res = Vec::new(); @@ -348,6 +350,29 @@ pub fn verify_rr_stream<'a>(inp: &'a [RR]) -> Result, Valid } } +impl<'a> VerifiedRRStream<'a> { + /// Given a name, resolve any [`CName`] records and return any verified records which were + /// pointed to by the original name. + /// + /// Note that because of [`CName`]s, the [`RR::name`] in the returned records may or may not be + /// equal to `name`. + /// + /// You MUST still check that the current UNIX time is between + /// [`VerifiedRRStream::valid_from`] and [`VerifiedRRStream::expires`] before + /// using any records returned here. + pub fn resolve_name<'b>(&self, mut name: &'b Name) -> Vec<&'a RR> where 'a: 'b { + loop { + let mut cname_search = self.verified_rrs.iter() + .filter(|rr| rr.name() == name) + .filter_map(|rr| if let RR::CName(cn) = rr { Some(cn) } else { None }); + if let Some(cname) = cname_search.next() { + name = &cname.canonical_name; + } + return self.verified_rrs.iter().filter(|rr| rr.name() == name).map(|rr| *rr).collect(); + } + } +} + #[cfg(test)] mod tests { #![allow(deprecated)] @@ -662,6 +687,14 @@ mod tests { assert_eq!(cname.name.as_str(), "cname_test.matcorallo.com."); assert_eq!(cname.canonical_name.as_str(), "txt_test.matcorallo.com."); } else { panic!(); } + + let filtered_rrs = + verified_rrs.resolve_name(&"cname_test.matcorallo.com.".try_into().unwrap()); + assert_eq!(filtered_rrs.len(), 1); + if let RR::Txt(txt) = &filtered_rrs[0] { + assert_eq!(txt.name.as_str(), "txt_test.matcorallo.com."); + assert_eq!(txt.data, b"dnssec_prover_test"); + } else { panic!(); } } #[test] @@ -695,6 +728,14 @@ mod tests { assert_eq!(cname.name.as_str(), "test.cname_wildcard_test.matcorallo.com."); assert_eq!(cname.canonical_name.as_str(), "cname.wildcard_test.matcorallo.com."); } else { panic!(); } + + let filtered_rrs = + verified_rrs.resolve_name(&"test.cname_wildcard_test.matcorallo.com.".try_into().unwrap()); + assert_eq!(filtered_rrs.len(), 1); + if let RR::Txt(txt) = &filtered_rrs[0] { + assert_eq!(txt.name.as_str(), "cname.wildcard_test.matcorallo.com."); + assert_eq!(txt.data, b"wildcard_test"); + } else { panic!(); } } #[test]