use super::trust_anchor::ValidationStatus;
use crate::protocol::message::Message;
use crate::protocol::record::RecordType;
#[derive(Clone)]
pub struct DnssecValidator {
enabled: bool,
}
impl DnssecValidator {
pub fn new(enabled: bool) -> Self {
Self { enabled }
}
pub fn validate(&self, response: &Message) -> ValidationStatus {
if !self.enabled {
return ValidationStatus::Insecure;
}
let has_rrsig = response
.answers
.iter()
.any(|rr| rr.rtype == RecordType::RRSIG);
if !has_rrsig {
return ValidationStatus::Insecure;
}
tracing::debug!("DNSSEC validation not implemented — treating signed response as Indeterminate");
ValidationStatus::Indeterminate
}
pub fn set_ad_bit(response: &mut Message, status: ValidationStatus) {
response.header.ad = status == ValidationStatus::Secure;
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::protocol::header::Header;
use crate::protocol::name::DnsName;
use crate::protocol::opcode::Opcode;
use crate::protocol::rcode::Rcode;
use crate::protocol::rdata::RData;
use crate::protocol::record::{RecordClass, ResourceRecord};
fn empty_response() -> Message {
Message {
header: Header {
id: 1,
qr: true,
opcode: Opcode::Query,
aa: false,
tc: false,
rd: true,
ra: true,
ad: false,
cd: false,
rcode: Rcode::NoError,
qd_count: 0,
an_count: 0,
ns_count: 0,
ar_count: 0,
},
questions: vec![],
answers: vec![],
authority: vec![],
additional: vec![],
edns: None,
}
}
#[test]
fn test_disabled_validator() {
let validator = DnssecValidator::new(false);
let response = empty_response();
assert_eq!(validator.validate(&response), ValidationStatus::Insecure);
}
#[test]
fn test_no_rrsig_insecure() {
let validator = DnssecValidator::new(true);
let mut response = empty_response();
response.answers.push(ResourceRecord {
name: DnsName::from_str("example.com").unwrap(),
rtype: RecordType::A,
rclass: RecordClass::IN,
ttl: 300,
rdata: RData::A(std::net::Ipv4Addr::new(1, 2, 3, 4)),
});
assert_eq!(validator.validate(&response), ValidationStatus::Insecure);
}
#[test]
fn test_ad_bit_setting() {
let mut response = empty_response();
DnssecValidator::set_ad_bit(&mut response, ValidationStatus::Secure);
assert!(response.header.ad);
DnssecValidator::set_ad_bit(&mut response, ValidationStatus::Insecure);
assert!(!response.header.ad);
}
}