Skip to content
This repository has been archived by the owner on Jun 7, 2024. It is now read-only.

Commit

Permalink
move existing test into RFC4035 section 3.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
japaric committed May 22, 2024
1 parent 8f41487 commit b6e97bf
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 55 deletions.
1 change: 1 addition & 0 deletions packages/conformance-tests/src/resolver/dnssec.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! DNSSEC functionality
mod fixtures;
mod rfc4035;
mod scenarios;
50 changes: 50 additions & 0 deletions packages/conformance-tests/src/resolver/dnssec/fixtures.rs
Original file line number Diff line number Diff line change
@@ -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))
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::net::Ipv4Addr;

use dns_test::{
client::{Client, DigSettings},
name_server::NameServer,
Expand All @@ -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()?;
Expand All @@ -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(())
}
66 changes: 11 additions & 55 deletions packages/conformance-tests/src/resolver/dnssec/scenarios/bogus.rs
Original file line number Diff line number Diff line change
@@ -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 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 (resolver, _graph) =
fixtures::bad_signature_in_leaf_nameserver(&needle_fqdn, needle_ipv4_addr)?;

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(())
}
4 changes: 4 additions & 0 deletions packages/dns-test/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
1 change: 1 addition & 0 deletions packages/dns-test/src/zone_file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ impl FromStr for ZoneFile {
}

/// A root (server) hint
#[derive(Clone)]
pub struct Root {
pub ipv4_addr: Ipv4Addr,
pub ns: FQDN,
Expand Down

0 comments on commit b6e97bf

Please sign in to comment.