resolver: check that out queries don't have the AD bit

This commit is contained in:
Jorge Aparicio 2024-05-10 15:56:47 +02:00
parent a58fb71eeb
commit 2de7139bc6
5 changed files with 119 additions and 19 deletions

View File

@ -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))
}

View File

@ -1 +1,2 @@
mod section_4_1;
mod section_4_6;

View File

@ -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(())
}

View File

@ -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(())

View File

@ -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") {