move existing test into RFC4035 section 3.2.2
This commit is contained in:
parent
8f414879b8
commit
b6e97bf3b6
|
@ -1,4 +1,5 @@
|
|||
//! DNSSEC functionality
|
||||
|
||||
mod fixtures;
|
||||
mod rfc4035;
|
||||
mod scenarios;
|
||||
|
|
50
packages/conformance-tests/src/resolver/dnssec/fixtures.rs
Normal file
50
packages/conformance-tests/src/resolver/dnssec/fixtures.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
use std::net::Ipv4Addr;
|
||||
|
||||
use base64::prelude::*;
|
||||
use dns_test::{
|
||||
name_server::{Graph, NameServer, Sign},
|
||||
record::Record,
|
||||
Network, Resolver, Result, FQDN,
|
||||
};
|
||||
|
||||
pub fn bad_signature_in_leaf_nameserver(
|
||||
leaf_fqdn: &FQDN,
|
||||
leaf_ipv4_addr: Ipv4Addr,
|
||||
) -> Result<(Resolver, Graph)> {
|
||||
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 = Graph::build(
|
||||
leaf_ns,
|
||||
Sign::AndAmend(&|zone, records| {
|
||||
if zone == &FQDN::NAMESERVERS {
|
||||
let mut modified = 0;
|
||||
for record in records {
|
||||
if let Record::RRSIG(rrsig) = record {
|
||||
if rrsig.fqdn == *leaf_fqdn {
|
||||
let mut signature = BASE64_STANDARD.decode(&rrsig.signature).unwrap();
|
||||
let last = signature.last_mut().expect("empty signature");
|
||||
*last = !*last;
|
||||
|
||||
rrsig.signature = BASE64_STANDARD.encode(&signature);
|
||||
modified += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(modified, 1, "sanity check");
|
||||
}
|
||||
}),
|
||||
)?;
|
||||
|
||||
let trust_anchor = graph.trust_anchor.as_ref().unwrap();
|
||||
let resolver = Resolver::new(&network, graph.root.clone())
|
||||
.trust_anchor(trust_anchor)
|
||||
.start(&dns_test::SUBJECT)?;
|
||||
|
||||
Ok((resolver, graph))
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
use std::net::Ipv4Addr;
|
||||
|
||||
use dns_test::{
|
||||
client::{Client, DigSettings},
|
||||
name_server::NameServer,
|
||||
|
@ -6,6 +8,8 @@ use dns_test::{
|
|||
Network, Resolver, Result, FQDN,
|
||||
};
|
||||
|
||||
use crate::resolver::dnssec::fixtures;
|
||||
|
||||
#[test]
|
||||
fn copies_cd_bit_from_query_to_response() -> Result<()> {
|
||||
let network = &Network::new()?;
|
||||
|
@ -21,3 +25,33 @@ fn copies_cd_bit_from_query_to_response() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn if_cd_bit_is_set_then_respond_with_data_that_fails_authentication() -> Result<()> {
|
||||
let needle_fqdn = FQDN("example.nameservers.com.")?;
|
||||
let needle_ipv4_addr = Ipv4Addr::new(1, 2, 3, 4);
|
||||
|
||||
let (resolver, _graph) =
|
||||
fixtures::bad_signature_in_leaf_nameserver(&needle_fqdn, needle_ipv4_addr)?;
|
||||
|
||||
let resolver_addr = resolver.ipv4_addr();
|
||||
|
||||
let client = Client::new(resolver.network())?;
|
||||
|
||||
let settings = *DigSettings::default()
|
||||
.recurse()
|
||||
.authentic_data()
|
||||
.checking_disabled();
|
||||
let output = client.dig(settings, resolver_addr, RecordType::A, &needle_fqdn)?;
|
||||
|
||||
assert!(output.status.is_noerror());
|
||||
assert!(!output.flags.authenticated_data);
|
||||
|
||||
let [record] = output.answer.try_into().unwrap();
|
||||
let record = record.try_into_a().unwrap();
|
||||
|
||||
assert_eq!(needle_fqdn, record.fqdn);
|
||||
assert_eq!(needle_ipv4_addr, record.ipv4_addr);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,73 +1,29 @@
|
|||
use std::net::Ipv4Addr;
|
||||
|
||||
use base64::prelude::*;
|
||||
use dns_test::client::{Client, DigSettings};
|
||||
use dns_test::name_server::{Graph, NameServer, Sign};
|
||||
use dns_test::record::{Record, RecordType};
|
||||
use dns_test::{Network, Resolver, Result, FQDN};
|
||||
use dns_test::record::RecordType;
|
||||
use dns_test::{Result, FQDN};
|
||||
|
||||
use crate::resolver::dnssec::fixtures;
|
||||
|
||||
// TODO find out which RFC section states this
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn bad_signature_in_leaf_nameserver() -> Result<()> {
|
||||
let expected_ipv4_addr = Ipv4Addr::new(1, 2, 3, 4);
|
||||
fn if_cd_bit_is_clear_and_data_is_not_authentic_then_respond_with_servfail() -> Result<()> {
|
||||
let needle_fqdn = FQDN("example.nameservers.com.")?;
|
||||
let needle_ipv4_addr = Ipv4Addr::new(1, 2, 3, 4);
|
||||
|
||||
let network = Network::new()?;
|
||||
let (resolver, _graph) =
|
||||
fixtures::bad_signature_in_leaf_nameserver(&needle_fqdn, needle_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::AndAmend(&|zone, records| {
|
||||
if zone == &FQDN::NAMESERVERS {
|
||||
let mut modified = 0;
|
||||
for record in records {
|
||||
if let Record::RRSIG(rrsig) = record {
|
||||
if rrsig.fqdn == needle_fqdn {
|
||||
let mut signature = BASE64_STANDARD.decode(&rrsig.signature).unwrap();
|
||||
let last = signature.last_mut().expect("empty signature");
|
||||
*last = !*last;
|
||||
|
||||
rrsig.signature = BASE64_STANDARD.encode(&signature);
|
||||
modified += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(modified, 1, "sanity check");
|
||||
}
|
||||
}),
|
||||
)?;
|
||||
|
||||
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 mut settings = *DigSettings::default().recurse().authentic_data();
|
||||
let settings = *DigSettings::default().recurse().authentic_data();
|
||||
let output = client.dig(settings, resolver_addr, RecordType::A, &needle_fqdn)?;
|
||||
|
||||
// the resolver will try to validate the chain of trust; the validation fails so it responds
|
||||
// with SERVFAIL
|
||||
assert!(output.status.is_servfail());
|
||||
|
||||
// avoids a SERVFAIL response
|
||||
settings.checking_disabled();
|
||||
|
||||
let output = client.dig(settings, resolver_addr, RecordType::A, &needle_fqdn)?;
|
||||
|
||||
// when the CD (Checking Disabled) bit is set the server won't respond with SERVFAIL on
|
||||
// validation errors. the outcome of the validation process is reported in the AD bit
|
||||
assert!(output.status.is_noerror());
|
||||
assert!(!output.flags.authenticated_data);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -31,6 +31,10 @@ impl Resolver {
|
|||
self.container.eavesdrop()
|
||||
}
|
||||
|
||||
pub fn network(&self) -> &Network {
|
||||
self.container.network()
|
||||
}
|
||||
|
||||
pub fn container_id(&self) -> &str {
|
||||
self.container.id()
|
||||
}
|
||||
|
|
|
@ -92,6 +92,7 @@ impl FromStr for ZoneFile {
|
|||
}
|
||||
|
||||
/// A root (server) hint
|
||||
#[derive(Clone)]
|
||||
pub struct Root {
|
||||
pub ipv4_addr: Ipv4Addr,
|
||||
pub ns: FQDN,
|
||||
|
|
Loading…
Reference in New Issue
Block a user