resolver: check that out queries don't have the AD bit
This commit is contained in:
parent
a58fb71eeb
commit
2de7139bc6
|
@ -2,9 +2,9 @@ use std::net::Ipv4Addr;
|
|||
|
||||
use base64::prelude::*;
|
||||
use dns_test::{
|
||||
name_server::{Graph, NameServer, Sign},
|
||||
name_server::{Graph, NameServer, Running, Sign},
|
||||
record::Record,
|
||||
Network, Resolver, Result, FQDN,
|
||||
Network, Resolver, Result, TrustAnchor, FQDN,
|
||||
};
|
||||
|
||||
pub fn bad_signature_in_leaf_nameserver(
|
||||
|
@ -48,3 +48,28 @@ pub fn bad_signature_in_leaf_nameserver(
|
|||
|
||||
Ok((resolver, graph))
|
||||
}
|
||||
|
||||
pub fn minimally_secure(
|
||||
leaf_fqdn: FQDN,
|
||||
leaf_ipv4_addr: Ipv4Addr,
|
||||
) -> Result<(Resolver, Vec<NameServer<Running>>, TrustAnchor)> {
|
||||
assert_eq!(Some(FQDN::NAMESERVERS), leaf_fqdn.parent());
|
||||
|
||||
let network = Network::new()?;
|
||||
|
||||
let mut leaf_ns = NameServer::new(&dns_test::PEER, FQDN::NAMESERVERS, &network)?;
|
||||
leaf_ns.add(Record::a(leaf_fqdn.clone(), leaf_ipv4_addr));
|
||||
|
||||
let Graph {
|
||||
nameservers,
|
||||
root,
|
||||
trust_anchor,
|
||||
} = Graph::build(leaf_ns, Sign::Yes)?;
|
||||
|
||||
let trust_anchor = trust_anchor.unwrap();
|
||||
let resolver = Resolver::new(&network, root)
|
||||
.trust_anchor(&trust_anchor)
|
||||
.start(&dns_test::SUBJECT)?;
|
||||
|
||||
Ok((resolver, nameservers, trust_anchor))
|
||||
}
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
mod section_4_1;
|
||||
mod section_4_6;
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
use std::net::Ipv4Addr;
|
||||
|
||||
use dns_test::{
|
||||
client::{Client, DigSettings},
|
||||
record::RecordType,
|
||||
tshark::{Capture, Direction},
|
||||
Result, FQDN,
|
||||
};
|
||||
|
||||
use crate::resolver::dnssec::fixtures;
|
||||
|
||||
#[test]
|
||||
fn clears_ad_bit_in_outgoing_queries() -> Result<()> {
|
||||
let leaf_ipv4_addr = Ipv4Addr::new(1, 2, 3, 4);
|
||||
let leaf_fqdn = FQDN("example.nameservers.com.")?;
|
||||
|
||||
let (resolver, nameservers, _trust_anchor) =
|
||||
fixtures::minimally_secure(leaf_fqdn.clone(), leaf_ipv4_addr)?;
|
||||
|
||||
let mut tshark = resolver.eavesdrop()?;
|
||||
|
||||
let resolver_addr = resolver.ipv4_addr();
|
||||
|
||||
let client = Client::new(resolver.network())?;
|
||||
let settings = *DigSettings::default().recurse().authentic_data();
|
||||
let _output = client.dig(settings, resolver_addr, RecordType::A, &leaf_fqdn)?;
|
||||
|
||||
tshark.wait_for_capture()?;
|
||||
let captures = tshark.terminate()?;
|
||||
|
||||
let client_addr = client.ipv4_addr();
|
||||
let mut ns_checks_count = 0;
|
||||
let mut client_checks_count = 0;
|
||||
let ns_addrs = nameservers
|
||||
.iter()
|
||||
.map(|ns| ns.ipv4_addr())
|
||||
.collect::<Vec<_>>();
|
||||
for Capture { message, direction } in captures {
|
||||
match direction {
|
||||
Direction::Incoming { source } => {
|
||||
if source == client_addr {
|
||||
// sanity check
|
||||
assert!(message.is_ad_flag_set());
|
||||
|
||||
client_checks_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Direction::Outgoing { destination } => {
|
||||
if destination == client_addr {
|
||||
// skip response to client
|
||||
continue;
|
||||
}
|
||||
|
||||
// sanity check
|
||||
assert!(ns_addrs.contains(&destination));
|
||||
|
||||
assert!(!message.is_ad_flag_set());
|
||||
|
||||
ns_checks_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sanity checks
|
||||
assert_eq!(1, client_checks_count);
|
||||
assert_ne!(0, dbg!(ns_checks_count));
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
use std::net::Ipv4Addr;
|
||||
|
||||
use dns_test::client::{Client, DigSettings};
|
||||
use dns_test::name_server::{Graph, NameServer, Sign};
|
||||
use dns_test::name_server::NameServer;
|
||||
use dns_test::record::{Record, RecordType};
|
||||
use dns_test::zone_file::Root;
|
||||
use dns_test::{Network, Resolver, Result, TrustAnchor, FQDN};
|
||||
|
||||
use crate::resolver::dnssec::fixtures;
|
||||
|
||||
// no DS records are involved; this is a single-link chain of trust
|
||||
#[ignore]
|
||||
#[test]
|
||||
|
@ -49,24 +51,12 @@ fn can_validate_with_delegation() -> Result<()> {
|
|||
let expected_ipv4_addr = Ipv4Addr::new(1, 2, 3, 4);
|
||||
let needle_fqdn = FQDN("example.nameservers.com.")?;
|
||||
|
||||
let network = Network::new()?;
|
||||
let (resolver, _nameservers, trust_anchor) =
|
||||
fixtures::minimally_secure(needle_fqdn.clone(), expected_ipv4_addr)?;
|
||||
|
||||
let mut leaf_ns = NameServer::new(&dns_test::PEER, FQDN::NAMESERVERS, &network)?;
|
||||
leaf_ns.add(Record::a(needle_fqdn.clone(), expected_ipv4_addr));
|
||||
|
||||
let Graph {
|
||||
nameservers: _nameservers,
|
||||
root,
|
||||
trust_anchor,
|
||||
} = Graph::build(leaf_ns, Sign::Yes)?;
|
||||
|
||||
let trust_anchor = &trust_anchor.unwrap();
|
||||
let resolver = Resolver::new(&network, root)
|
||||
.trust_anchor(trust_anchor)
|
||||
.start(&dns_test::SUBJECT)?;
|
||||
let resolver_addr = resolver.ipv4_addr();
|
||||
|
||||
let client = Client::new(&network)?;
|
||||
let client = Client::new(resolver.network())?;
|
||||
let settings = *DigSettings::default().recurse().authentic_data();
|
||||
let output = client.dig(settings, resolver_addr, RecordType::A, &needle_fqdn)?;
|
||||
|
||||
|
@ -80,7 +70,7 @@ fn can_validate_with_delegation() -> Result<()> {
|
|||
assert_eq!(needle_fqdn, a.fqdn);
|
||||
assert_eq!(expected_ipv4_addr, a.ipv4_addr);
|
||||
|
||||
let output = client.delv(resolver_addr, RecordType::A, &needle_fqdn, trust_anchor)?;
|
||||
let output = client.delv(resolver_addr, RecordType::A, &needle_fqdn, &trust_anchor)?;
|
||||
assert!(output.starts_with("; fully validated"));
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -183,6 +183,20 @@ impl Message {
|
|||
&self.inner
|
||||
}
|
||||
|
||||
pub fn is_ad_flag_set(&self) -> bool {
|
||||
let Some(authenticated) = self.inner["dns.flags_tree"]
|
||||
.as_object()
|
||||
.unwrap()
|
||||
.get("dns.flags.authenticated")
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let authenticated = authenticated.as_str().unwrap();
|
||||
assert_eq!("1", authenticated);
|
||||
true
|
||||
}
|
||||
|
||||
fn opt_record(&self) -> Option<&serde_json::Value> {
|
||||
for (key, value) in self.inner.get("Additional records")?.as_object()? {
|
||||
if key.ends_with(": type OPT") {
|
||||
|
|
Loading…
Reference in New Issue
Block a user