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;
}
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,
/// 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`].
/// 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<VerifiedRRStream<'a>, ValidationError> {
let mut zone = ".";
let mut res = Vec::new();
}
}
+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)]
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]
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]