Files
NLnetLabs-dnst/src/parse.rs
T
6f0e27d3e1 Implement ldns-update and dnst update (#10)
* implement ldns-update and dnst update

* implement TSIG support for dnst update

* update: imports compliant with domain's CONTRIBUTING.md

* Use RequestMessage instead of RequestMessageMulti as we're expecting to receive multiple responses because we don't expect to send XFR requests.

* Clippy.

* update: fix parsing of optional IP addr

* WIP

* update: make it compile after rebase

* start testing update

* update: stelline test

* update: fix some comments and strings

* update: improve TSIG error message

* update: use lookup_host instead of manual A query

* notify & update: merge the separate TSigInfo instances

* update: look in both answer and authority sections

* fix duplicate clippy attribute

---------

Co-authored-by: Ximon Eighteen <3304436+ximon18@users.noreply.github.com>
2024-12-02 14:33:03 +01:00

70 lines
2.2 KiB
Rust

use core::str::FromStr;
use domain::base::Name;
use domain::tsig::{Algorithm, KeyName};
use domain::utils::base64;
use crate::error::Error;
pub fn parse_name(arg: &str) -> Result<Name<Vec<u8>>, Error> {
Name::from_str(&arg.to_lowercase()).map_err(|e| Error::from(e.to_string()))
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TSigInfo {
pub name: KeyName,
pub key: Vec<u8>,
pub algorithm: Algorithm,
}
impl FromStr for TSigInfo {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
// TODO: better error messages
let Some((mut name, rest)) = s.split_once(':') else {
return Err("should contain at least one `:`".into());
};
let mut key;
let mut algorithm;
if let Some((k, a)) = rest.split_once(':') {
key = k;
algorithm = a;
} else {
key = rest;
// This is different from the default algorithm that ldns-notify uses, which is MD5,
// but we don't support that. So we use the default that is also used by dig when MD5
// is disabled.
algorithm = "hmac-sha256";
};
// With dig TSIG keys are also specified with -y,
// but our format is: <name:key[:algo]>
// and dig's is: [hmac:]name:key
//
// When we detect an unknown TSIG algorithm in algo,
// but a known algorithm in name, we can assume dig
// order was used.
//
// We can correct this by checking whether the name contains a valid
// algorithm while the algorithm doesn't.
if Algorithm::from_str(algorithm).is_err() && Algorithm::from_str(name).is_ok() {
(name, key, algorithm) = (key, algorithm, name);
}
let algorithm = Algorithm::from_str(algorithm)
.map_err(|_| format!("Unsupported TSIG algorithm: {algorithm}"))?;
let key = base64::decode(key).map_err(|e| format!("TSIG key is invalid base64: {e}"))?;
let name = KeyName::from_str(name).map_err(|e| format!("TSIG name is invalid: {e}"))?;
Ok(TSigInfo {
name,
key,
algorithm,
})
}
}