diff --git a/crates/dbx-core/src/db/ssh_tunnel.rs b/crates/dbx-core/src/db/ssh_tunnel.rs index a691ea189..2992904dc 100644 --- a/crates/dbx-core/src/db/ssh_tunnel.rs +++ b/crates/dbx-core/src/db/ssh_tunnel.rs @@ -10,7 +10,7 @@ use base64::Engine; use russh::client::{self, Config, Handle}; use russh::keys::agent::{client::AgentClient, AgentIdentity}; use russh::keys::{decode_secret_key, key::PrivateKeyWithHashAlg, PrivateKey}; -use russh::{kex, ChannelMsg, Preferred}; +use russh::{kex, mac, ChannelMsg, Preferred}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::TcpListener; use tokio::sync::Mutex; @@ -55,6 +55,13 @@ fn ssh_client_config() -> Config { } preferred.kex = Cow::Owned(kex); + let mut mac = preferred.mac.into_owned(); + // Keep SHA-1 MAC support as a last-resort fallback for legacy SSH proxies. + if !mac.contains(&mac::HMAC_SHA1) { + mac.push(mac::HMAC_SHA1); + } + preferred.mac = Cow::Owned(mac); + Config { nodelay: true, keepalive_interval: Some(Duration::from_secs(30)), preferred, ..Default::default() } } @@ -923,6 +930,16 @@ mod tests { assert!(ecdh_index < group14_sha1_index); } + #[test] + fn ssh_client_config_keeps_legacy_mac_after_safe_defaults() { + let config = ssh_client_config(); + let mac = config.preferred.mac; + let sha2_index = mac.iter().position(|algorithm| *algorithm == russh::mac::HMAC_SHA256).unwrap(); + let sha1_index = mac.iter().position(|algorithm| *algorithm == russh::mac::HMAC_SHA1).unwrap(); + + assert!(sha2_index < sha1_index); + } + #[test] fn sanitizes_invalid_openssh_private_key_comment() { let mut key = openssh_container(&padded_private_blob(&[0xff, 0xfe, b'a']));