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 })
|
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);
|
||||||
|
}
|
||||||
|
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) {
|
let bytes = match ::base85::decode(base85) {
|
||||||
Ok(bytes) => bytes,
|
Ok(bytes) => bytes,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
::tracing::error!("Invalid DNSSEC base85: {}", e);
|
::tracing::error!("Invalid DNSSEC base85: {}", e);
|
||||||
continue;
|
return Err(::std::io::Error::new(
|
||||||
}
|
|
||||||
};
|
|
||||||
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(
|
|
||||||
::std::io::ErrorKind::InvalidData,
|
::std::io::ErrorKind::InvalidData,
|
||||||
"record found but not parsable",
|
"record is not base85, RFC1924",
|
||||||
)
|
));
|
||||||
} else {
|
}
|
||||||
::std::io::Error::new(
|
};
|
||||||
::std::io::ErrorKind::NotFound,
|
return match Record::decode(&bytes) {
|
||||||
"record not found",
|
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
|
/// 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 {
|
||||||
|
|
16
src/lib.rs
16
src/lib.rs
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue