Split resolving and decoding
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
2c00e57bc6
commit
fd76ec9983
|
@ -86,51 +86,58 @@ impl Dnssec {
|
|||
|
||||
Ok(Self { resolver })
|
||||
}
|
||||
const TXT_RECORD_START: &str = "v=Fenrir1 ";
|
||||
/// 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;
|
||||
|
||||
let fqdn_str = "_fenrir.".to_owned() + domain;
|
||||
::tracing::debug!("Resolving: {}", fqdn_str);
|
||||
let fqdn = Name::from_utf8(&fqdn_str)?;
|
||||
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() {
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
::tracing::trace!("Found fenrir record: {}", txt);
|
||||
let base85 = txt[TXT_RECORD_START.len()..].trim();
|
||||
return Ok(txt);
|
||||
}
|
||||
Err(::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,
|
||||
"Self::TXT record does not start with \"v=Fenrir1\"",
|
||||
));
|
||||
}
|
||||
|
||||
let base85 = txt[Self::TXT_RECORD_START.len()..].trim();
|
||||
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 {
|
||||
::std::io::Error::new(
|
||||
return Err(::std::io::Error::new(
|
||||
::std::io::ErrorKind::InvalidData,
|
||||
"record found but not parsable",
|
||||
)
|
||||
} else {
|
||||
::std::io::Error::new(
|
||||
::std::io::ErrorKind::NotFound,
|
||||
"record not found",
|
||||
)
|
||||
});
|
||||
"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",
|
||||
))
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ impl PublicKeyType {
|
|||
/// Get the size of a public key of this kind
|
||||
pub fn key_len(&self) -> usize {
|
||||
match &self {
|
||||
PublicKeyType::Ed25519 => 42,
|
||||
PublicKeyType::Ed25519 => 32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ impl Address {
|
|||
|
||||
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 {
|
||||
None
|
||||
} else {
|
||||
|
|
16
src/lib.rs
16
src/lib.rs
|
@ -80,10 +80,11 @@ impl Fenrir {
|
|||
/// Stop all workers, listeners
|
||||
/// asyncronous version for Drop
|
||||
fn stop_sync(&mut self) {
|
||||
let _ = self.stop_working.send(true);
|
||||
let mut toempty_socket = Vec::new();
|
||||
::std::mem::swap(&mut self.sockets, &mut toempty_socket);
|
||||
let task = ::tokio::task::spawn(Self::real_stop(toempty_socket));
|
||||
let _ = futures::executor::block_on(task);
|
||||
let task = ::tokio::task::spawn(Self::stop_sockets(toempty_socket));
|
||||
let _ = ::futures::executor::block_on(task);
|
||||
self.dnssec = None;
|
||||
}
|
||||
/// Stop all workers, listeners
|
||||
|
@ -91,11 +92,11 @@ impl Fenrir {
|
|||
let _ = self.stop_working.send(true);
|
||||
let mut toempty_socket = Vec::new();
|
||||
::std::mem::swap(&mut self.sockets, &mut toempty_socket);
|
||||
Self::real_stop(toempty_socket).await;
|
||||
Self::stop_sockets(toempty_socket).await;
|
||||
self.dnssec = None;
|
||||
}
|
||||
/// 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<()>>)>,
|
||||
) {
|
||||
for s in sockets.into_iter() {
|
||||
|
@ -126,12 +127,17 @@ impl Fenrir {
|
|||
Ok(())
|
||||
}
|
||||
/// 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 {
|
||||
Some(dnssec) => Ok(dnssec.resolv(domain).await?),
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue