Split resolving and decoding

Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
Luca Fulchir 2023-02-09 12:12:09 +01:00
parent 2c00e57bc6
commit fd76ec9983
Signed by: luca.fulchir
GPG Key ID: 8F6440603D13A78E
3 changed files with 51 additions and 38 deletions

View File

@ -86,51 +86,58 @@ impl Dnssec {
Ok(Self { resolver }) Ok(Self { resolver })
} }
const TXT_RECORD_START: &str = "v=Fenrir1 ";
/// Get the fenrir data for a domain /// Get the fenrir data for a domain
pub async fn resolv(&self, domain: &str) -> ::std::io::Result<Record> { pub async fn resolv(&self, domain: &str) -> ::std::io::Result<String> {
use ::trust_dns_client::rr::Name; use ::trust_dns_client::rr::Name;
let fqdn_str = "_fenrir.".to_owned() + domain; let fqdn_str = "_fenrir.".to_owned() + domain;
::tracing::debug!("Resolving: {}", fqdn_str); ::tracing::debug!("Resolving: {}", fqdn_str);
let fqdn = Name::from_utf8(&fqdn_str)?; let fqdn = Name::from_utf8(&fqdn_str)?;
let answers = self.resolver.txt_lookup(fqdn).await?; let answers = self.resolver.txt_lookup(fqdn).await?;
const TXT_RECORD_START: &str = "v=Fenrir1 ";
let mut found_but_wrong: bool = false;
for txt_raw in answers.into_iter() { for txt_raw in answers.into_iter() {
let txt = ::std::format!("{}", txt_raw); let txt = ::std::format!("{}", txt_raw);
if !txt.starts_with(TXT_RECORD_START) { if !txt.starts_with(Self::TXT_RECORD_START) {
::tracing::trace!("Found NON-fenrir record: {}", txt); ::tracing::trace!("Found NON-fenrir record: {}", txt);
continue; continue;
} }
::tracing::trace!("Found fenrir record: {}", txt); ::tracing::trace!("Found fenrir record: {}", txt);
let base85 = txt[TXT_RECORD_START.len()..].trim(); return Ok(txt);
let bytes = match ::base85::decode(base85) {
Ok(bytes) => bytes,
Err(e) => {
::tracing::error!("Invalid DNSSEC base85: {}", e);
continue;
}
};
let record = match Record::decode(&bytes) {
Ok(record) => record,
Err(e) => {
found_but_wrong = true;
::tracing::error!("{}: {}", fqdn_str, e);
continue;
}
};
return Ok(record);
} }
return Err(if found_but_wrong { Err(::std::io::Error::new(
::std::io::Error::new( ::std::io::ErrorKind::NotFound,
"record not found",
))
}
/// Parse the dns TXT record and output a `Record` struct
pub fn parse_txt_record(txt: &str) -> ::std::io::Result<Record> {
if !txt.starts_with(Self::TXT_RECORD_START) {
return Err(::std::io::Error::new(
::std::io::ErrorKind::InvalidData, ::std::io::ErrorKind::InvalidData,
"record found but not parsable", "Self::TXT record does not start with \"v=Fenrir1\"",
) ));
} else { }
::std::io::Error::new(
::std::io::ErrorKind::NotFound, let base85 = txt[Self::TXT_RECORD_START.len()..].trim();
"record not found", let bytes = match ::base85::decode(base85) {
) Ok(bytes) => bytes,
}); Err(e) => {
::tracing::error!("Invalid DNSSEC base85: {}", e);
return Err(::std::io::Error::new(
::std::io::ErrorKind::InvalidData,
"record is not base85, RFC1924",
));
}
};
return match Record::decode(&bytes) {
Ok(record) => Ok(record),
Err(e) => {
::tracing::error!("Can't parse record: {}", e);
Err(::std::io::Error::new(
::std::io::ErrorKind::InvalidData,
"Can't parse the record",
))
}
};
} }
} }

View File

@ -63,7 +63,7 @@ impl PublicKeyType {
/// Get the size of a public key of this kind /// Get the size of a public key of this kind
pub fn key_len(&self) -> usize { pub fn key_len(&self) -> usize {
match &self { match &self {
PublicKeyType::Ed25519 => 42, PublicKeyType::Ed25519 => 32,
} }
} }
} }
@ -314,7 +314,7 @@ impl Address {
let public_key_id = PublicKeyId(raw[1]); let public_key_id = PublicKeyId(raw[1]);
let raw_port = u16::from_le_bytes(raw[2..3].try_into().unwrap()); let raw_port = u16::from_le_bytes([raw[2], raw[3]]);
let port = if raw_port == 0 { let port = if raw_port == 0 {
None None
} else { } else {

View File

@ -80,10 +80,11 @@ impl Fenrir {
/// Stop all workers, listeners /// Stop all workers, listeners
/// asyncronous version for Drop /// asyncronous version for Drop
fn stop_sync(&mut self) { fn stop_sync(&mut self) {
let _ = self.stop_working.send(true);
let mut toempty_socket = Vec::new(); let mut toempty_socket = Vec::new();
::std::mem::swap(&mut self.sockets, &mut toempty_socket); ::std::mem::swap(&mut self.sockets, &mut toempty_socket);
let task = ::tokio::task::spawn(Self::real_stop(toempty_socket)); let task = ::tokio::task::spawn(Self::stop_sockets(toempty_socket));
let _ = futures::executor::block_on(task); let _ = ::futures::executor::block_on(task);
self.dnssec = None; self.dnssec = None;
} }
/// Stop all workers, listeners /// Stop all workers, listeners
@ -91,11 +92,11 @@ impl Fenrir {
let _ = self.stop_working.send(true); let _ = self.stop_working.send(true);
let mut toempty_socket = Vec::new(); let mut toempty_socket = Vec::new();
::std::mem::swap(&mut self.sockets, &mut toempty_socket); ::std::mem::swap(&mut self.sockets, &mut toempty_socket);
Self::real_stop(toempty_socket).await; Self::stop_sockets(toempty_socket).await;
self.dnssec = None; self.dnssec = None;
} }
/// actually do the work of stopping resolvers and listeners /// actually do the work of stopping resolvers and listeners
async fn real_stop( async fn stop_sockets(
sockets: Vec<(Arc<UdpSocket>, JoinHandle<::std::io::Result<()>>)>, sockets: Vec<(Arc<UdpSocket>, JoinHandle<::std::io::Result<()>>)>,
) { ) {
for s in sockets.into_iter() { for s in sockets.into_iter() {
@ -126,12 +127,17 @@ impl Fenrir {
Ok(()) Ok(())
} }
/// Get the raw TXT record of a Fenrir domain /// Get the raw TXT record of a Fenrir domain
pub async fn resolv(&self, domain: &str) -> Result<dnssec::Record, Error> { pub async fn resolv_str(&self, domain: &str) -> Result<String, Error> {
match &self.dnssec { match &self.dnssec {
Some(dnssec) => Ok(dnssec.resolv(domain).await?), Some(dnssec) => Ok(dnssec.resolv(domain).await?),
None => Err(Error::NotInitialized), None => Err(Error::NotInitialized),
} }
} }
/// Get the raw TXT record of a Fenrir domain
pub async fn resolv(&self, domain: &str) -> Result<dnssec::Record, Error> {
let record_str = self.resolv_str(domain).await?;
Ok(dnssec::Dnssec::parse_txt_record(&record_str)?)
}
} }
/// Add an async udp listener /// Add an async udp listener