diff --git a/conduit-example.toml b/conduit-example.toml index 260517ae..f35a3d63 100644 --- a/conduit-example.toml +++ b/conduit-example.toml @@ -66,12 +66,7 @@ trusted_servers = ["matrix.org"] address = "127.0.0.1" # This makes sure Conduit can only be reached using the reverse proxy #address = "0.0.0.0" # If Conduit is running in a container, make sure the reverse proxy (ie. Traefik) can reach it. -# possible URL preview modes: -# None: previews disabled -# All: previews for any URL allowed -# Allowlist: only domains in `url_preview_allowlist` are allowed -url_preview_mode = "None" -url_preview_allowlist = ["google.com", "youtube.com", "www.youtube.com"] +url_preview_allowlist = [] [global.well_known] # Conduit handles the /.well-known/matrix/* endpoints, making both clients and servers try to access conduit with the host diff --git a/debian/postinst b/debian/postinst index 27afc03b..cf8937ff 100644 --- a/debian/postinst +++ b/debian/postinst @@ -97,12 +97,7 @@ trusted_servers = ["matrix.org"] # [0]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives #log = "..." -# possible URL preview modes: -# None: previews disabled -# All: previews for any URL allowed -# Allowlist: only domains in \`url_preview_allowlist\` are allowed -url_preview_mode = "None" -url_preview_allowlist = ["google.com", "youtube.com", "www.youtube.com"] +url_preview_allowlist = [] EOF fi ;; diff --git a/src/api/client_server/media.rs b/src/api/client_server/media.rs index 16f0d90a..41d6b9be 100644 --- a/src/api/client_server/media.rs +++ b/src/api/client_server/media.rs @@ -11,7 +11,6 @@ use ruma::api::client::{ #[cfg(feature = "url_preview")] use { - crate::config::UrlPreviewMode, crate::service::media::UrlPreviewData, webpage::HTML, reqwest::Url, @@ -190,7 +189,7 @@ async fn get_url_preview(url: &str) -> Result { .url_preview_requests .write() .unwrap() - .insert(url.to_string(), notifier.clone()); + .insert(url.to_owned(), notifier.clone()); } let data = request_url_preview(url).await; @@ -222,6 +221,13 @@ async fn get_url_preview(url: &str) -> Result { #[cfg(feature = "url_preview")] fn url_preview_allowed(url_str: &str) -> bool { + const DEFAULT_ALLOWLIST: &[&str] = &[ + "matrix.org", + "mastodon.social", + "youtube.com", + "wikipedia.org", + ]; + let url = match Url::parse(url_str) { Ok(u) => u, Err(_) => return false, @@ -229,18 +235,29 @@ fn url_preview_allowed(url_str: &str) -> bool { if ["http", "https"].iter().all(|&scheme| scheme != url.scheme().to_lowercase()) { return false; } - match services().globals.url_preview_mode() { - UrlPreviewMode::All => true, - UrlPreviewMode::None => false, - UrlPreviewMode::Allowlist => { - match url.host_str() { - None => false, - Some(host) => { - services().globals.url_preview_allowlist().contains(&host.to_string()) - } - } + let mut host = match url.host_str() { + None => return false, + Some(h) => h.to_lowercase(), + }; + + let allowlist = services().globals.url_preview_allowlist(); + if allowlist.contains(&"*".to_owned()) { + return true; + } + while !host.is_empty() { + if allowlist.contains(&host) { + return true; + } + if allowlist.contains(&"default".to_owned()) && DEFAULT_ALLOWLIST.contains(&host.as_str()) { + return true; + } + /* also check higher level domains, so that e.g. `en.m.wikipedia.org` is matched by `wikipedia.org` on allowlist. */ + host = match host.split_once('.') { + None => return false, + Some((_, domain)) => domain.to_owned(), } } + false } /// # `GET /_matrix/media/r0/preview_url` diff --git a/src/config/mod.rs b/src/config/mod.rs index cd19d38f..b8eef648 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -13,23 +13,6 @@ mod proxy; use self::proxy::ProxyConfig; -#[derive(Clone, Copy, Debug, Deserialize)] -pub enum UrlPreviewMode { - All, - None, - Allowlist, -} - -impl ToString for UrlPreviewMode { - fn to_string(&self) -> String { - match *self { - UrlPreviewMode::All => "All".to_string(), - UrlPreviewMode::None => "None".to_string(), - UrlPreviewMode::Allowlist => "Allowlist".to_string(), - } - } -} - #[derive(Clone, Debug, Deserialize)] pub struct Config { #[serde(default = "default_address")] @@ -102,8 +85,6 @@ pub struct Config { pub emergency_password: Option, - #[serde(default = "default_url_preview_mode")] - pub url_preview_mode: UrlPreviewMode, #[serde(default = "Vec::new")] pub url_preview_allowlist: Vec, @@ -254,7 +235,6 @@ impl fmt::Display for Config { }), ("Well-known server name", well_known_server.as_str()), ("Well-known client URL", &self.well_known_client()), - ("URL preview mode", &self.url_preview_mode.to_string()), ("URL preview allowlist", &self.url_preview_allowlist.join(", ")), ]; @@ -336,7 +316,3 @@ fn default_openid_token_ttl() -> u64 { pub fn default_default_room_version() -> RoomVersionId { RoomVersionId::V10 } - -pub fn default_url_preview_mode() -> UrlPreviewMode { - UrlPreviewMode::None -} diff --git a/src/service/globals/mod.rs b/src/service/globals/mod.rs index 38962aae..e1762054 100644 --- a/src/service/globals/mod.rs +++ b/src/service/globals/mod.rs @@ -12,7 +12,6 @@ use futures_util::FutureExt; use hickory_resolver::TokioAsyncResolver; use hyper_util::client::legacy::connect::dns::{GaiResolver, Name as HyperName}; use reqwest::dns::{Addrs, Name, Resolve, Resolving}; -use crate::config::UrlPreviewMode; use ruma::{ api::{client::sync::sync_events, federation::discovery::ServerSigningKeys}, DeviceId, RoomVersionId, ServerName, UserId, @@ -325,10 +324,6 @@ impl Service { self.config.allow_federation } - pub fn url_preview_mode(&self) -> UrlPreviewMode { - self.config.url_preview_mode - } - pub fn url_preview_allowlist(&self) -> &Vec { &self.config.url_preview_allowlist }