diff --git a/yazi-shared/src/url/buf.rs b/yazi-shared/src/url/buf.rs index ef9b2e05..cfdb80de 100644 --- a/yazi-shared/src/url/buf.rs +++ b/yazi-shared/src/url/buf.rs @@ -167,8 +167,8 @@ impl UrlBuf { Self::Archive { loc: loc.rebase(base), domain: domain.clone() } } Self::Sftp { loc, domain } => { - todo!(); - // Self::Sftp { loc: loc.rebase(base), domain: domain.clone() } + let base = typed_path::UnixPath::new(base.as_os_str().as_encoded_bytes()); + Self::Sftp { loc: loc.rebase(base), domain: domain.clone() } } } } diff --git a/yazi-vfs/src/provider/sftp/conn.rs b/yazi-vfs/src/provider/sftp/conn.rs index 413f41db..7f95fbf0 100644 --- a/yazi-vfs/src/provider/sftp/conn.rs +++ b/yazi-vfs/src/provider/sftp/conn.rs @@ -1,8 +1,8 @@ use std::{io, sync::Arc, time::{Duration, SystemTime}}; use chrono::DateTime; -use russh::keys::{PrivateKeyWithHashAlg, agent::AgentIdentity}; -use yazi_fs::provider::local::Local; +use russh::keys::{PrivateKeyWithHashAlg, agent::AgentIdentity, known_hosts}; +use yazi_fs::{Xdg, provider::local::Local}; use crate::config::ServiceSftp; @@ -23,9 +23,41 @@ impl russh::client::Handler for Conn { async fn check_server_key( &mut self, - _server_public_key: &russh::keys::PublicKey, + server_public_key: &russh::keys::PublicKey, ) -> Result { - Ok(true) + let path = Xdg::config_dir().join("known_hosts"); + + match known_hosts::check_known_hosts_path( + &self.config.host, + self.config.port, + server_public_key, + &path, + ) { + Ok(true) => Ok(true), + Ok(false) => { + if let Err(e) = known_hosts::learn_known_hosts_path( + &self.config.host, + self.config.port, + server_public_key, + &path, + ) { + tracing::warn!("Failed to record host key in known_hosts: {e}"); + } + Ok(true) + } + Err(russh::keys::Error::KeyChanged { line }) => { + tracing::error!( + "Host key for `{}` has changed (known_hosts:{}). Possible MITM attack!", + self.config.host, + line + ); + Ok(false) + } + Err(e) => { + tracing::error!("Could not verify host key for `{}`: {e}", self.config.host); + Ok(false) + } + } } }