if questions != 1 { return Err(()); }
let answers = read_u16(&mut read)?;
if answers == 0 { return Err(()); }
- let _authorities = read_u16(&mut read)?;
+ let authorities = read_u16(&mut read)?;
let _additional = read_u16(&mut read)?;
for _ in 0..questions {
read_u16(&mut read)?; // class
}
- // Only read the answers (skip authorities and additional) as that's all we care about.
+ // Only read the answers and NSEC records in authorities, skipping additional entirely.
let mut min_ttl = u32::MAX;
for _ in 0..answers {
let (rr, ttl) = parse_wire_packet_rr(&mut read, &resp)?;
min_ttl = cmp::min(min_ttl, ttl);
if let RR::RRSig(rrsig) = rr { rrsig_key_names.push(rrsig.key_name); }
}
+
+ for _ in 0..authorities {
+ // Only include records from the authority section if they are NSEC/3 (or signatures
+ // thereover). We don't care about NS records here.
+ let (rr, ttl) = parse_wire_packet_rr(&mut read, &resp)?;
+ match &rr {
+ RR::RRSig(rrsig) => {
+ if rrsig.ty != NSec::TYPE && rrsig.ty != NSec3::TYPE {
+ continue;
+ }
+ },
+ RR::NSec(_)|RR::NSec3(_) => {},
+ _ => continue,
+ }
+ write_rr(&rr, ttl, proof);
+ min_ttl = cmp::min(min_ttl, ttl);
+ if let RR::RRSig(rrsig) = rr { rrsig_key_names.push(rrsig.key_name); }
+ }
+
Ok(min_ttl)
}
fn test_cname_query() {
for resolver in ["1.1.1.1:53", "8.8.8.8:53", "9.9.9.9:53"] {
let sockaddr = resolver.to_socket_addrs().unwrap().next().unwrap();
- let query_name = "cname_test.matcorallo.com.".try_into().unwrap();
+ let query_name = "cname_test.dnssec_proof_tests.bitcoin.ninja.".try_into().unwrap();
let (proof, _) = build_txt_proof(sockaddr, &query_name).unwrap();
let mut rrs = parse_rr_stream(&proof).unwrap();
let resolved_rrs = verified_rrs.resolve_name(&query_name);
assert_eq!(resolved_rrs.len(), 1);
if let RR::Txt(txt) = &resolved_rrs[0] {
- assert_eq!(txt.name.as_str(), "txt_test.matcorallo.com.");
+ assert_eq!(txt.name.as_str(), "txt_test.dnssec_proof_tests.bitcoin.ninja.");
assert_eq!(txt.data, b"dnssec_prover_test");
} else { panic!(); }
}
async fn test_cross_domain_cname_query_async() {
for resolver in ["1.1.1.1:53", "8.8.8.8:53", "9.9.9.9:53"] {
let sockaddr = resolver.to_socket_addrs().unwrap().next().unwrap();
- let query_name = "wildcard.x_domain_cname_wild.matcorallo.com.".try_into().unwrap();
+ let query_name = "wildcard.x_domain_cname_wild.dnssec_proof_tests.bitcoin.ninja.".try_into().unwrap();
let (proof, _) = build_txt_proof_async(sockaddr, &query_name).await.unwrap();
let mut rrs = parse_rr_stream(&proof).unwrap();
} else { panic!(); }
}
}
+
+ #[cfg(feature = "tokio")]
+ #[tokio::test]
+ async fn test_dname_wildcard_query_async() {
+ for resolver in ["1.1.1.1:53", "8.8.8.8:53", "9.9.9.9:53"] {
+ let sockaddr = resolver.to_socket_addrs().unwrap().next().unwrap();
+ let query_name = "wildcard_a.wildcard_b.dname_test.dnssec_proof_tests.bitcoin.ninja.".try_into().unwrap();
+ let (proof, _) = build_txt_proof_async(sockaddr, &query_name).await.unwrap();
+
+ let mut rrs = parse_rr_stream(&proof).unwrap();
+ rrs.shuffle(&mut rand::rngs::OsRng);
+ let verified_rrs = verify_rr_stream(&rrs).unwrap();
+ assert_eq!(verified_rrs.verified_rrs.len(), 3);
+
+ let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs();
+ assert!(verified_rrs.valid_from < now);
+ assert!(verified_rrs.expires > now);
+
+ let resolved_rrs = verified_rrs.resolve_name(&query_name);
+ assert_eq!(resolved_rrs.len(), 1);
+ if let RR::Txt(txt) = &resolved_rrs[0] {
+ assert_eq!(txt.name.as_str(), "cname.wildcard_test.dnssec_proof_tests.bitcoin.ninja.");
+ assert_eq!(txt.data, b"wildcard_test");
+ } else { panic!(); }
+ }
+ }
+
}