diff --git a/examples/local_federation/instance.rs b/examples/local_federation/instance.rs index ad1fd12..2ea3e40 100644 --- a/examples/local_federation/instance.rs +++ b/examples/local_federation/instance.rs @@ -29,7 +29,7 @@ pub async fn new_instance( .signed_fetch_actor(&system_user) .app_data(database) .url_verifier(Box::new(MyUrlVerifier())) - .debug(true) + .debug(false) .build() .await?; Ok(config) diff --git a/src/config.rs b/src/config.rs index 73f7688..1702626 100644 --- a/src/config.rs +++ b/src/config.rs @@ -26,8 +26,6 @@ use bytes::Bytes; use derive_builder::Builder; use dyn_clone::{clone_trait_object, DynClone}; use moka::future::Cache; -use once_cell::sync::Lazy; -use regex::Regex; use reqwest::Request; use reqwest_middleware::{ClientWithMiddleware, RequestBuilder}; use rsa::{pkcs8::DecodePrivateKey, RsaPrivateKey}; @@ -167,12 +165,6 @@ impl FederationConfig { return Err(Error::UrlVerificationError("Url must have a domain")); }; - static DOMAIN_REGEX: Lazy = - Lazy::new(|| Regex::new(r"^[a-zA-Z0-9.-]*$").expect("compile regex")); - if !DOMAIN_REGEX.is_match(domain) { - return Err(Error::UrlVerificationError("Invalid characters in domain")); - } - // Extra checks only for production mode if !self.debug { if url.port().is_some() { @@ -182,20 +174,23 @@ impl FederationConfig { // Resolve domain and see if it points to private IP // TODO: Use is_global() once stabilized // https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_global - let invalid_ip = lookup_host(domain).await?.any(|addr| match addr.ip() { - IpAddr::V4(addr) => { - addr.is_private() - || addr.is_link_local() - || addr.is_loopback() - || addr.is_multicast() - } - IpAddr::V6(addr) => { - addr.is_loopback() + let invalid_ip = + lookup_host((domain.to_owned(), 80)) + .await? + .any(|addr| match addr.ip() { + IpAddr::V4(addr) => { + addr.is_private() + || addr.is_link_local() + || addr.is_loopback() + || addr.is_multicast() + } + IpAddr::V6(addr) => { + addr.is_loopback() || addr.is_multicast() || ((addr.segments()[0] & 0xfe00) == 0xfc00) // is_unique_local || ((addr.segments()[0] & 0xffc0) == 0xfe80) // is_unicast_link_local - } - }); + } + }); if invalid_ip { return Err(Error::UrlVerificationError( "Localhost is only allowed in debug mode", diff --git a/src/fetch/webfinger.rs b/src/fetch/webfinger.rs index 8460245..a804a34 100644 --- a/src/fetch/webfinger.rs +++ b/src/fetch/webfinger.rs @@ -50,10 +50,16 @@ where for<'de2> ::Kind: serde::Deserialize<'de2>, ::Error: From + Send + Sync + Display, { + static DOMAIN_REGEX: Lazy = + Lazy::new(|| Regex::new(r"^[a-zA-Z0-9.-]*$").expect("compile regex")); + let (_, domain) = identifier .splitn(2, '@') .collect_tuple() .ok_or(WebFingerError::WrongFormat.into_crate_error())?; + if !DOMAIN_REGEX.is_match(domain) { + return Err(Error::UrlVerificationError("Invalid characters in domain").into()); + } let protocol = if data.config.debug { "http" } else { "https" }; let fetch_url = format!("{protocol}://{domain}/.well-known/webfinger?resource=acct:{identifier}");