diff --git a/src/main.rs b/src/main.rs index e4ca9d3..8f47202 100644 --- a/src/main.rs +++ b/src/main.rs @@ -220,6 +220,10 @@ fn execute_command(command: &[u8]) -> ProcessOutput { status: 0, stdout: CPUINFO_UNAME_A.to_vec(), }, + "true" => ProcessOutput { + status: 0, + stdout: b"".to_vec(), + }, _ => { let argv0 = command.split_ascii_whitespace().next().unwrap_or(""); diff --git a/ssh-transport/src/keys.rs b/ssh-transport/src/keys.rs index 3dce8d8..5dd85d4 100644 --- a/ssh-transport/src/keys.rs +++ b/ssh-transport/src/keys.rs @@ -3,10 +3,38 @@ use sha2::Digest; use subtle::ConstantTimeEq; use crate::{ + client_error, packet::{EncryptedPacket, MsgKind, Packet, RawPacket}, Msg, Result, }; +#[derive(Clone, Copy)] +pub struct KexAlgorithm { + pub name: &'static str, +} + +pub const KEX_CURVE_25519_SHA256: KexAlgorithm = KexAlgorithm { + name: "curve25519-sha256", +}; + +pub struct AlgorithmNegotiation { + pub supported: Vec<(&'static str, T)>, +} + +impl AlgorithmNegotiation { + pub fn find<'a>(&self, client_supports: &str) -> Result { + for client_alg in client_supports.split(',') { + if let Some(alg) = self.supported.iter().find(|alg| alg.0 == client_alg) { + return Ok(alg.1); + } + } + + Err(client_error!( + "client does not support any matching algorithm: supported: {client_supports:?}" + )) + } +} + pub(crate) struct Session { session_id: [u8; 32], encryption_key_client_to_server: SshChaCha20Poly1305, diff --git a/ssh-transport/src/lib.rs b/ssh-transport/src/lib.rs index e09a2b1..d31638e 100644 --- a/ssh-transport/src/lib.rs +++ b/ssh-transport/src/lib.rs @@ -6,6 +6,7 @@ use core::str; use std::{collections::VecDeque, mem::take}; use ed25519_dalek::ed25519::signature::Signer; +use keys::AlgorithmNegotiation; use packet::{ DhKeyExchangeInitPacket, DhKeyExchangeInitReplyPacket, KeyExchangeInitPacket, Packet, PacketTransport, SshPublicKey, SshSignature, @@ -169,14 +170,24 @@ impl ServerConnection { Ok(expected) } else { Err(client_error!( - "client does not supported algorithm {expected}. supported: {list:?}", + "client does not supporte algorithm {expected}. supported: {list:?}", )) } }; - let key_algorithm = require_algorithm("curve25519-sha256", kex.kex_algorithms)?; + // TODO: support ecdh-sha2-nistp256 + let kex_algorithms = AlgorithmNegotiation { + supported: vec![( + keys::KEX_CURVE_25519_SHA256.name, + keys::KEX_CURVE_25519_SHA256, + )], + }; + let kex_algorithm = kex_algorithms.find(kex.kex_algorithms.0)?; + let server_host_key_algorithm = require_algorithm("ssh-ed25519", kex.server_host_key_algorithms)?; + + // TODO: support aes128-ctr (aes-gcm is not supported by everyone) let encryption_algorithm_client_to_server = require_algorithm( "chacha20-poly1305@openssh.com", kex.encryption_algorithms_client_to_server, @@ -205,7 +216,7 @@ impl ServerConnection { let server_kexinit = KeyExchangeInitPacket { cookie: [0; 16], - kex_algorithms: NameList::one(key_algorithm), + kex_algorithms: NameList::one(kex_algorithm.name), server_host_key_algorithms: NameList::one(server_host_key_algorithm), encryption_algorithms_client_to_server: NameList::one( encryption_algorithm_client_to_server, diff --git a/ssh-transport/src/parse.rs b/ssh-transport/src/parse.rs index 5f723fb..5d06e07 100644 --- a/ssh-transport/src/parse.rs +++ b/ssh-transport/src/parse.rs @@ -120,7 +120,7 @@ impl Writer { } #[derive(Clone, Copy)] -pub struct NameList<'a>(&'a str); +pub struct NameList<'a>(pub &'a str); impl<'a> NameList<'a> { pub fn one(item: &'a str) -> Self { @@ -132,7 +132,7 @@ impl<'a> NameList<'a> { pub fn none() -> NameList<'static> { NameList("") } - pub fn iter(&self) -> std::str::Split { + pub fn iter(&self) -> std::str::Split<'a, char> { self.0.split(',') } }