change results of validation to always return records
This commit is contained in:
@@ -225,8 +225,8 @@ pub enum ProofErrorKind {
|
||||
/// The error type for dnssec errors that get returned in the crate
|
||||
#[derive(Debug, Clone, Error)]
|
||||
pub struct ProofError {
|
||||
proof: Proof,
|
||||
kind: ProofErrorKind,
|
||||
pub proof: Proof,
|
||||
pub kind: ProofErrorKind,
|
||||
}
|
||||
|
||||
impl ProofError {
|
||||
|
@@ -193,11 +193,15 @@ where
|
||||
message_response,
|
||||
options,
|
||||
)
|
||||
.map(Result::<DnsResponse, ProtoError>::Ok)
|
||||
})
|
||||
.and_then(move |verified_message| {
|
||||
// Query should be unowned at this point
|
||||
let query = Arc::clone(&query2);
|
||||
|
||||
// TODO: I've noticed upstream resolvers don't always return NSEC responses
|
||||
// this causes bottom up evaluation to fail
|
||||
|
||||
// at this point all of the message is verified.
|
||||
// This is where NSEC (and possibly NSEC3) validation occurs
|
||||
// As of now, only NSEC is supported.
|
||||
@@ -249,7 +253,7 @@ async fn verify_response<H>(
|
||||
query: Arc<Query>,
|
||||
mut message: DnsResponse,
|
||||
options: DnsRequestOptions,
|
||||
) -> Result<DnsResponse, ProtoError>
|
||||
) -> DnsResponse
|
||||
where
|
||||
H: DnsHandle + Sync + Unpin,
|
||||
{
|
||||
@@ -257,15 +261,15 @@ where
|
||||
let nameservers = message.take_name_servers();
|
||||
let additionals = message.take_additionals();
|
||||
|
||||
let answers = verify_rrsets(handle.clone(), &query, answers, options).await?;
|
||||
let nameservers = verify_rrsets(handle.clone(), &query, nameservers, options).await?;
|
||||
let additionals = verify_rrsets(handle.clone(), &query, additionals, options).await?;
|
||||
let answers = verify_rrsets(handle.clone(), &query, answers, options).await;
|
||||
let nameservers = verify_rrsets(handle.clone(), &query, nameservers, options).await;
|
||||
let additionals = verify_rrsets(handle.clone(), &query, additionals, options).await;
|
||||
|
||||
message.insert_answers(answers);
|
||||
message.insert_name_servers(nameservers);
|
||||
message.insert_additionals(additionals);
|
||||
|
||||
Ok(message)
|
||||
message
|
||||
}
|
||||
|
||||
/// This pulls all answers returned in a Message response and returns a future which will
|
||||
@@ -276,7 +280,7 @@ async fn verify_rrsets<H>(
|
||||
query: &Query,
|
||||
records: Vec<Record>,
|
||||
options: DnsRequestOptions,
|
||||
) -> Result<Vec<Record>, ProtoError>
|
||||
) -> Vec<Record>
|
||||
where
|
||||
H: DnsHandle + Sync + Unpin,
|
||||
{
|
||||
@@ -302,7 +306,7 @@ where
|
||||
|
||||
// there were no records to verify
|
||||
if rrset_types.is_empty() {
|
||||
return Ok(records);
|
||||
return records;
|
||||
}
|
||||
|
||||
// collect all the rrsets to verify
|
||||
@@ -333,14 +337,24 @@ where
|
||||
|
||||
// TODO: support non-IN classes?
|
||||
debug!(
|
||||
"verifying: {}, record_type: {:?}, rrsigs: {}",
|
||||
rrset.name,
|
||||
record_type,
|
||||
rrsigs.len()
|
||||
"verifying: {name} record_type: {record_type}, rrsigs: {rrsig_len}",
|
||||
rrsig_len = rrsigs.len()
|
||||
);
|
||||
|
||||
// verify this rrset
|
||||
let proof = verify_rrset(handle.clone_with_context(), rrset, rrsigs, options).await?;
|
||||
let proof = verify_rrset(handle.clone_with_context(), rrset, rrsigs, options).await;
|
||||
|
||||
let proof = match proof {
|
||||
Ok(proof) => {
|
||||
debug!("verified: {name} record_type: {record_type}",);
|
||||
proof
|
||||
}
|
||||
Err(ProofError { proof, kind }) => {
|
||||
debug!("failed to verify: {name} record_type: {record_type}: {kind}",);
|
||||
proof
|
||||
}
|
||||
};
|
||||
|
||||
rrset_proofs.insert((name, record_type), proof);
|
||||
}
|
||||
|
||||
@@ -352,7 +366,7 @@ where
|
||||
.map(|proof| record.set_proof(*proof));
|
||||
}
|
||||
|
||||
Ok(records)
|
||||
records
|
||||
}
|
||||
|
||||
// TODO: is this method useful/necessary?
|
||||
@@ -373,7 +387,7 @@ async fn verify_rrset<H>(
|
||||
rrset: Rrset<'_>,
|
||||
rrsigs: Vec<&RRSIG>,
|
||||
options: DnsRequestOptions,
|
||||
) -> Result<Proof, ProtoError>
|
||||
) -> Result<Proof, ProofError>
|
||||
where
|
||||
H: DnsHandle + Sync + Unpin,
|
||||
{
|
||||
@@ -382,13 +396,9 @@ where
|
||||
match rrset.record_type {
|
||||
// validation of DNSKEY records require different logic as they search for DS record coverage as well
|
||||
RecordType::DNSKEY => {
|
||||
verify_dnskey_rrset(handle.clone_with_context(), rrset, options)
|
||||
.map_err(|e| ProtoError::from(format!("failed to validate DNSKEYs: {e}")))
|
||||
.await
|
||||
verify_dnskey_rrset(handle.clone_with_context(), rrset, options).await
|
||||
}
|
||||
_ => verify_default_rrset(&handle.clone_with_context(), rrset, rrsigs, options)
|
||||
.await
|
||||
.map_err(|e| ProtoError::from(format!("failed to validate RRSIGs: {e}"))),
|
||||
_ => verify_default_rrset(&handle.clone_with_context(), rrset, rrsigs, options).await,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -612,6 +612,10 @@ pub mod testing {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for record in response.as_lookup().record_iter() {
|
||||
assert!(record.proof().is_secure())
|
||||
}
|
||||
}
|
||||
|
||||
/// Test IP lookup from domains that exist but unsigned with DNSSEC validation.
|
||||
@@ -622,7 +626,7 @@ pub mod testing {
|
||||
mut exec: E,
|
||||
handle: R,
|
||||
) {
|
||||
use crate::error::*;
|
||||
use crate::{error::*, lookup};
|
||||
use proto::rr::RecordType;
|
||||
let resolver = AsyncResolver::new(
|
||||
ResolverConfig::default(),
|
||||
@@ -637,18 +641,9 @@ pub mod testing {
|
||||
// needs to be a domain that exists, but is not signed (eventually this will be)
|
||||
let response = exec.block_on(resolver.lookup_ip("hickory-dns.org."));
|
||||
|
||||
assert!(response.is_err());
|
||||
let error = response.unwrap_err();
|
||||
|
||||
let error_str = format!("{error}");
|
||||
let name = Name::from_str("hickory-dns.org.").unwrap();
|
||||
let expected_str = format!(
|
||||
"proto error: failed to validate RRSIGs: Bogus: ds record should exist: {name}"
|
||||
);
|
||||
assert_eq!(error_str, expected_str);
|
||||
if let ResolveErrorKind::Proto(_) = *error.kind() {
|
||||
} else {
|
||||
panic!("wrong error")
|
||||
let lookup_ip = response.unwrap();
|
||||
for record in lookup_ip.as_lookup().record_iter() {
|
||||
assert!(record.proof().is_bogus())
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user