diff --git a/Cargo.lock b/Cargo.lock index ea1b659..a6fcda1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -449,11 +449,13 @@ dependencies = [ "crypto-bigint", "ctr", "ed25519-dalek", + "hex", "hex-literal", "p256", "poly1305", "rand_core", "secrecy", + "serde", "sha2", "subtle", "tracing", diff --git a/bin/cluelessh-faked/src/main.rs b/bin/cluelessh-faked/src/main.rs index 6c6520e..a10d351 100644 --- a/bin/cluelessh-faked/src/main.rs +++ b/bin/cluelessh-faked/src/main.rs @@ -102,6 +102,8 @@ async fn main() -> eyre::Result<()> { let transport_config = cluelessh_protocol::transport::server::ServerConfig { host_keys: pub_host_keys, + // This is definitely who we are. + server_identification: b"SSH-2.0-OpenSSH_9.7\r\n".to_vec(), }; let mut listener = diff --git a/bin/cluelessh/src/main.rs b/bin/cluelessh/src/main.rs index c0fc8b5..c0e59e8 100644 --- a/bin/cluelessh/src/main.rs +++ b/bin/cluelessh/src/main.rs @@ -69,7 +69,7 @@ async fn main() -> eyre::Result<()> { result.wrap_err("failed to prompt password") }) }), - sign_pubkey: Arc::new(move |session_identifier| { + sign_pubkey: Arc::new(move |session_id| { let mut attempted_public_keys = HashSet::new(); let username = username.clone(); Box::pin(async move { @@ -93,11 +93,8 @@ async fn main() -> eyre::Result<()> { } let pubkey = PublicKey::from_wire_encoding(&identity.key_blob)?; - let sign_data = cluelessh_keys::signature::signature_data( - session_identifier, - &username, - &pubkey, - ); + let sign_data = + cluelessh_keys::signature::signature_data(session_id.0, &username, &pubkey); let signature = agent .sign(&identity.key_blob, &sign_data, 0) .await diff --git a/bin/cluelesshd/src/auth.rs b/bin/cluelesshd/src/auth.rs index 273db92..c62db3c 100644 --- a/bin/cluelesshd/src/auth.rs +++ b/bin/cluelesshd/src/auth.rs @@ -74,7 +74,7 @@ pub async fn verify_signature(auth: VerifySignature) -> eyre::Result bool { false } - fn addr_default() -> IpAddr { IpAddr::V4(Ipv4Addr::UNSPECIFIED) } diff --git a/bin/cluelesshd/src/connection.rs b/bin/cluelesshd/src/connection.rs index 85b456d..07a1296 100644 --- a/bin/cluelesshd/src/connection.rs +++ b/bin/cluelesshd/src/connection.rs @@ -52,7 +52,10 @@ async fn connection_inner(state: SerializedConnectionState) -> Result<()> { let stream = TcpStream::from_std(stream)?; let host_keys = state.pub_host_keys; - let transport_config = cluelessh_transport::server::ServerConfig { host_keys }; + let transport_config = cluelessh_transport::server::ServerConfig { + host_keys, + server_identification: b"SSH-2.0-ClueleSSH_0.1\r\n".to_vec(), + }; let rpc_client = unsafe { OwnedFd::from_raw_fd(PRIVSEP_CONNECTION_RPC_CLIENT_FD) }; let rpc_client1 = Arc::new(rpc::Client::from_fd(rpc_client)?); @@ -66,25 +69,13 @@ async fn connection_inner(state: SerializedConnectionState) -> Result<()> { let rpc_client = rpc_client1.clone(); Box::pin(async move { rpc_client - .verify_signature( - msg.user, - msg.session_identifier, - msg.public_key, - msg.signature, - ) + .verify_signature(msg.user, msg.session_id, msg.public_key, msg.signature) .await }) })), check_pubkey: Some(Arc::new(move |msg| { let rpc_client = rpc_client2.clone(); - Box::pin(async move { - rpc_client - .check_public_key( - msg.user, - msg.public_key, - ) - .await - }) + Box::pin(async move { rpc_client.check_public_key(msg.user, msg.public_key).await }) })), auth_banner: config.auth.banner, do_key_exchange: Arc::new(move |msg| { diff --git a/bin/cluelesshd/src/rpc.rs b/bin/cluelesshd/src/rpc.rs index 77a632a..982605b 100644 --- a/bin/cluelesshd/src/rpc.rs +++ b/bin/cluelesshd/src/rpc.rs @@ -14,6 +14,7 @@ use cluelessh_keys::public::PublicKey; use cluelessh_keys::signature::Signature; use cluelessh_protocol::auth::VerifySignature; use cluelessh_transport::crypto::AlgorithmName; +use cluelessh_transport::SessionId; use eyre::bail; use eyre::ensure; use eyre::eyre; @@ -56,7 +57,7 @@ enum Request { /// If it is okay, store the user so we can later spawn a process as them. VerifySignature { user: String, - session_identifier: [u8; 32], + session_id: SessionId, public_key: PublicKey, signature: Signature, }, @@ -115,7 +116,7 @@ impl secrecy::DebugSecret for SerializableSharedSecret {} #[derive(Debug, Serialize, Deserialize)] pub struct KeyExchangeResponse { - pub hash: [u8; 32], + pub hash: SessionId, pub server_ephemeral_public_key: Vec, pub shared_secret: secrecy::Secret, pub signature: Signature, @@ -259,7 +260,7 @@ impl Server { } Request::VerifySignature { user, - session_identifier, + session_id, public_key, signature, } => { @@ -269,7 +270,7 @@ impl Server { } let is_ok = crate::auth::verify_signature(VerifySignature { user, - session_identifier, + session_id, public_key, signature, }) @@ -487,13 +488,13 @@ impl Client { pub async fn verify_signature( &self, user: String, - session_identifier: [u8; 32], + session_id: SessionId, public_key: PublicKey, signature: Signature, ) -> Result { self.request_response::(&Request::VerifySignature { user, - session_identifier, + session_id, public_key, signature, }) diff --git a/bin/cluelesshd/src/sandbox.rs b/bin/cluelesshd/src/sandbox.rs index 7d90065..e7e7535 100644 --- a/bin/cluelesshd/src/sandbox.rs +++ b/bin/cluelesshd/src/sandbox.rs @@ -14,7 +14,9 @@ use rustix::{ use seccompiler::{BpfProgram, SeccompAction, SeccompFilter, SeccompRule, TargetArch}; use tracing::{debug, trace, warn}; -use crate::{SerializedConnectionState, PRIVSEP_CONNECTION_RPC_CLIENT_FD, PRIVSEP_CONNECTION_STREAM_FD}; +use crate::{ + SerializedConnectionState, PRIVSEP_CONNECTION_RPC_CLIENT_FD, PRIVSEP_CONNECTION_STREAM_FD, +}; #[tracing::instrument(skip(state), ret)] pub fn drop_privileges(state: &SerializedConnectionState) -> Result<()> { @@ -228,12 +230,24 @@ fn seccomp() -> Result<()> { (libc::SYS_eventfd2, vec![]), (libc::SYS_epoll_wait, vec![]), (libc::SYS_epoll_ctl, vec![]), - (libc::SYS_fcntl, vec![]), // todo: restrict (72) + (libc::SYS_fcntl, vec![]), // todo: restrict this (libc::SYS_socketpair, vec![]), - (libc::SYS_sendmsg, vec![limit_fd(PRIVSEP_CONNECTION_RPC_CLIENT_FD)],), - (libc::SYS_recvmsg, vec![limit_fd(PRIVSEP_CONNECTION_RPC_CLIENT_FD)]), - (libc::SYS_sendto, vec![limit_fd(PRIVSEP_CONNECTION_STREAM_FD)]), - (libc::SYS_recvfrom, vec![limit_fd(PRIVSEP_CONNECTION_STREAM_FD)]), + ( + libc::SYS_sendmsg, + vec![limit_fd(PRIVSEP_CONNECTION_RPC_CLIENT_FD)], + ), + ( + libc::SYS_recvmsg, + vec![limit_fd(PRIVSEP_CONNECTION_RPC_CLIENT_FD)], + ), + ( + libc::SYS_sendto, + vec![limit_fd(PRIVSEP_CONNECTION_STREAM_FD)], + ), + ( + libc::SYS_recvfrom, + vec![limit_fd(PRIVSEP_CONNECTION_STREAM_FD)], + ), (libc::SYS_getrandom, vec![]), (libc::SYS_rt_sigaction, vec![]), (libc::SYS_rt_sigprocmask, vec![]), diff --git a/lib/cluelessh-connection/src/lib.rs b/lib/cluelessh-connection/src/lib.rs index 34c6438..0d7fa3f 100644 --- a/lib/cluelessh-connection/src/lib.rs +++ b/lib/cluelessh-connection/src/lib.rs @@ -153,8 +153,8 @@ impl ChannelsState { } pub fn recv_packet(&mut self, packet: Packet) -> Result<()> { - // TODO: window - + // TODO: what if we mostly ignored window and just always increased it again? + // there's an excention to ignore it entirely that we could also support... let mut p = packet.payload_parser(); let packet_type = p.u8()?; match packet_type { diff --git a/lib/cluelessh-keys/src/signature.rs b/lib/cluelessh-keys/src/signature.rs index b334958..669ac73 100644 --- a/lib/cluelessh-keys/src/signature.rs +++ b/lib/cluelessh-keys/src/signature.rs @@ -2,7 +2,6 @@ use cluelessh_format::{ParseError, Reader, Writer}; use crate::{private::PrivateKey, public::PublicKey}; -// TODO SessionId newtype pub fn signature_data(session_id: [u8; 32], username: &str, pubkey: &PublicKey) -> Vec { let mut s = Writer::new(); diff --git a/lib/cluelessh-protocol/src/lib.rs b/lib/cluelessh-protocol/src/lib.rs index 936cba3..0cedd5c 100644 --- a/lib/cluelessh-protocol/src/lib.rs +++ b/lib/cluelessh-protocol/src/lib.rs @@ -47,11 +47,11 @@ impl ServerConnection { self.transport.recv_bytes(bytes)?; if let ServerConnectionState::Setup(options, auth_banner) = &mut self.state { - if let Some(session_ident) = self.transport.is_open() { + if let Some(session_id) = self.transport.is_open() { self.state = ServerConnectionState::Auth(auth::ServerAuth::new( mem::take(options), auth_banner.take(), - session_ident, + session_id, )); } } @@ -177,9 +177,9 @@ impl ClientConnection { self.transport.recv_bytes(bytes)?; if let ClientConnectionState::Setup(auth) = &mut self.state { - if let Some(session_ident) = self.transport.is_open() { + if let Some(session_id) = self.transport.is_open() { let mut auth = mem::take(auth).unwrap(); - auth.set_session_identifier(session_ident); + auth.set_session_id(session_id); debug!("Connection has been opened"); self.state = ClientConnectionState::Auth(auth); @@ -278,7 +278,7 @@ pub mod auth { use cluelessh_format::{numbers, NameList}; use cluelessh_keys::{public::PublicKey, signature::Signature}; - use cluelessh_transport::{packet::Packet, peer_error, Result}; + use cluelessh_transport::{packet::Packet, peer_error, Result, SessionId}; use tracing::debug; pub struct ServerAuth { @@ -288,7 +288,7 @@ pub mod auth { options: HashSet, banner: Option, server_requests: VecDeque, - session_ident: [u8; 32], + session_id: SessionId, } pub enum ServerRequest { @@ -314,7 +314,7 @@ pub mod auth { #[derive(Debug, Clone)] pub struct VerifySignature { pub user: String, - pub session_identifier: [u8; 32], + pub session_id: SessionId, pub public_key: PublicKey, /// The signature. Guaranteed to match the algorithm of `public_key`. pub signature: Signature, @@ -330,14 +330,14 @@ pub mod auth { pub fn new( options: HashSet, banner: Option, - session_ident: [u8; 32], + session_id: SessionId, ) -> Self { Self { has_failed: false, packets_to_send: VecDeque::new(), options, is_authenticated: None, - session_ident, + session_id, banner, server_requests: VecDeque::new(), } @@ -426,7 +426,7 @@ pub mod auth { self.server_requests .push_back(ServerRequest::VerifySignature(VerifySignature { user: username.to_owned(), - session_identifier: self.session_ident, + session_id: self.session_id, public_key, signature, })); @@ -512,12 +512,12 @@ pub mod auth { packets_to_send: VecDeque, user_requests: VecDeque, is_authenticated: bool, - session_identifier: Option<[u8; 32]>, + session_id: Option, } pub enum ClientUserRequest { Password, - PrivateKeySign { session_identifier: [u8; 32] }, + PrivateKeySign { session_id: SessionId }, Banner(Vec), } @@ -533,13 +533,13 @@ pub mod auth { username, user_requests: VecDeque::new(), is_authenticated: false, - session_identifier: None, + session_id: None, } } - pub fn set_session_identifier(&mut self, ident: [u8; 32]) { - assert!(self.session_identifier.is_none()); - self.session_identifier = Some(ident); + pub fn set_session_id(&mut self, session_id: SessionId) { + assert!(self.session_id.is_none()); + self.session_id = Some(session_id); } pub fn is_authenticated(&self) -> bool { @@ -605,9 +605,9 @@ pub mod auth { // TODO: Ask the server whether there are any keys we can use instead of just yoloing the signature. self.user_requests .push_back(ClientUserRequest::PrivateKeySign { - session_identifier: self - .session_identifier - .expect("set_session_identifier has not been called"), + session_id: self + .session_id + .expect("set_session_id has not been called"), }); } else { return Err(peer_error!( diff --git a/lib/cluelessh-tokio/src/client.rs b/lib/cluelessh-tokio/src/client.rs index 48c7787..e73b3ca 100644 --- a/lib/cluelessh-tokio/src/client.rs +++ b/lib/cluelessh-tokio/src/client.rs @@ -1,4 +1,5 @@ use cluelessh_connection::{ChannelKind, ChannelNumber, ChannelOperation}; +use cluelessh_transport::SessionId; use std::{collections::HashMap, pin::Pin, sync::Arc}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; @@ -31,7 +32,7 @@ pub struct ClientAuth { pub username: String, pub prompt_password: Arc BoxFuture<'static, Result> + Send + Sync>, pub sign_pubkey: - Arc BoxFuture<'static, Result> + Send + Sync>, + Arc BoxFuture<'static, Result> + Send + Sync>, } enum Operation { @@ -59,9 +60,7 @@ impl ClientConnection { channel_ops_recv, channels: HashMap::new(), proto: cluelessh_protocol::ClientConnection::new( - cluelessh_transport::client::ClientConnection::new( - cluelessh_protocol::OsRng, - ), + cluelessh_transport::client::ClientConnection::new(cluelessh_protocol::OsRng), cluelessh_protocol::auth::ClientAuth::new(auth.username.as_bytes().to_vec()), ), auth, @@ -88,13 +87,11 @@ impl ClientConnection { let _ = send.send(Operation::PasswordEntered(password)).await; }); } - cluelessh_protocol::auth::ClientUserRequest::PrivateKeySign { - session_identifier, - } => { + cluelessh_protocol::auth::ClientUserRequest::PrivateKeySign { session_id } => { let send = self.operations_send.clone(); let sign_pubkey = self.auth.sign_pubkey.clone(); tokio::spawn(async move { - let signature_result = sign_pubkey(session_identifier).await; + let signature_result = sign_pubkey(session_id).await; let _ = send.send(Operation::Signature(signature_result)).await; }); } diff --git a/lib/cluelessh-tokio/src/server.rs b/lib/cluelessh-tokio/src/server.rs index fca6d57..97e541d 100644 --- a/lib/cluelessh-tokio/src/server.rs +++ b/lib/cluelessh-tokio/src/server.rs @@ -213,10 +213,7 @@ impl ServerConnection { tokio::spawn(async move { let result = check(check_pubkey.clone()).await; let _ = send - .send(Operation::CheckPubkey( - result, - check_pubkey.public_key, - )) + .send(Operation::CheckPubkey(result, check_pubkey.public_key)) .await; }); } diff --git a/lib/cluelessh-transport/Cargo.toml b/lib/cluelessh-transport/Cargo.toml index 7a31c05..585e097 100644 --- a/lib/cluelessh-transport/Cargo.toml +++ b/lib/cluelessh-transport/Cargo.toml @@ -22,6 +22,8 @@ x25519-dalek = "2.0.1" tracing.workspace = true base64 = "0.22.1" secrecy = "0.8.0" +hex = "0.4.3" +serde = { version = "1.0.209", features = ["derive"] } [dev-dependencies] hex-literal = "0.4.1" diff --git a/lib/cluelessh-transport/src/client.rs b/lib/cluelessh-transport/src/client.rs index 9ff9bf4..7013cc8 100644 --- a/lib/cluelessh-transport/src/client.rs +++ b/lib/cluelessh-transport/src/client.rs @@ -4,10 +4,11 @@ use tracing::{debug, info, trace}; use crate::{ crypto::{ - self, AlgorithmName, EncodedSshSignature, EncryptionAlgorithm, HostKeyVerifyAlgorithm, KeyExchangeSecret, SharedSecret, SupportedAlgorithms + self, AlgorithmName, EncodedSshSignature, EncryptionAlgorithm, HostKeyVerifyAlgorithm, + KeyExchangeSecret, SharedSecret, SupportedAlgorithms, }, packet::{Packet, PacketTransport, ProtocolIdentParser}, - peer_error, Msg, Result, SshRng, SshStatus, + peer_error, Msg, Result, SessionId, SshRng, SshStatus, }; use cluelessh_format::{numbers, NameList, Reader, Writer}; @@ -50,10 +51,10 @@ enum ClientState { encryption_server_to_client: EncryptionAlgorithm, }, ServiceRequest { - session_identifier: [u8; 32], + session_id: SessionId, }, Open { - session_identifier: [u8; 32], + session_id: SessionId, }, } @@ -310,10 +311,10 @@ impl ClientConnection { .queue_packet(Packet::new_msg_service_request(b"ssh-userauth")); self.state = ClientState::ServiceRequest { - session_identifier: *h, + session_id: SessionId(*h), }; } - ClientState::ServiceRequest { session_identifier } => { + ClientState::ServiceRequest { session_id } => { let mut accept = packet.payload_parser(); let packet_type = accept.u8()?; if packet_type != numbers::SSH_MSG_SERVICE_ACCEPT { @@ -326,7 +327,7 @@ impl ClientConnection { debug!("Connection has been opened successfully"); self.state = ClientState::Open { - session_identifier: *session_identifier, + session_id: *session_id, }; } ClientState::Open { .. } => { @@ -349,9 +350,9 @@ impl ClientConnection { self.packet_transport.queue_packet(packet); } - pub fn is_open(&self) -> Option<[u8; 32]> { + pub fn is_open(&self) -> Option { match self.state { - ClientState::Open { session_identifier } => Some(session_identifier), + ClientState::Open { session_id } => Some(session_id), _ => None, } } diff --git a/lib/cluelessh-transport/src/crypto.rs b/lib/cluelessh-transport/src/crypto.rs index 36d08d9..c50b450 100644 --- a/lib/cluelessh-transport/src/crypto.rs +++ b/lib/cluelessh-transport/src/crypto.rs @@ -7,7 +7,7 @@ use sha2::Digest; use crate::{ packet::{EncryptedPacket, MsgKind, Packet, RawPacket}, - peer_error, Msg, Result, SshRng, + peer_error, Msg, Result, SessionId, SshRng, }; pub type SharedSecret = secrecy::Secret; @@ -308,7 +308,7 @@ impl SupportedAlgorithms { } pub(crate) struct Session { - session_id: [u8; 32], + session_id: SessionId, from_peer: Tunnel, to_peer: Tunnel, } @@ -326,6 +326,7 @@ pub(crate) trait Keys: Send + Sync + 'static { fn encrypt_packet_to_msg(&mut self, packet: Packet, packet_number: u64) -> Msg; fn additional_mac_len(&self) -> usize; + // TODO: actually rekey... fn rekey( &mut self, h: [u8; 32], @@ -362,7 +363,7 @@ impl Keys for Plaintext { impl Session { pub(crate) fn new( - h: [u8; 32], + h: SessionId, k: &SharedSecret, encryption_client_to_server: EncryptionAlgorithm, encryption_server_to_client: EncryptionAlgorithm, @@ -370,7 +371,7 @@ impl Session { ) -> Self { Self::from_keys( h, - h, + h.0, k, encryption_client_to_server, encryption_server_to_client, @@ -380,7 +381,7 @@ impl Session { /// fn from_keys( - session_id: [u8; 32], + session_id: SessionId, h: [u8; 32], k: &SharedSecret, alg_c2s: EncryptionAlgorithm, @@ -462,7 +463,7 @@ fn derive_key( k: &SharedSecret, h: [u8; 32], letter: &str, - session_id: [u8; 32], + session_id: SessionId, key_size: usize, ) -> Vec { let sha2len = sha2::Sha256::output_size(); @@ -476,7 +477,7 @@ fn derive_key( if i == 0 { hash.update(letter.as_bytes()); - hash.update(session_id); + hash.update(session_id.0); } else { hash.update(&output[..(i * sha2len)]); } diff --git a/lib/cluelessh-transport/src/lib.rs b/lib/cluelessh-transport/src/lib.rs index fb7617e..c7db756 100644 --- a/lib/cluelessh-transport/src/lib.rs +++ b/lib/cluelessh-transport/src/lib.rs @@ -3,8 +3,13 @@ pub mod crypto; pub mod packet; pub mod server; +use std::fmt::Debug; + use cluelessh_format::ParseError; pub use packet::Msg; +use serde::{Deserialize, Serialize}; + +// TODO: extensions #[derive(Debug)] pub enum SshStatus { @@ -17,6 +22,17 @@ pub enum SshStatus { PeerError(String), } +#[derive(Clone, Copy, Serialize, Deserialize)] +pub struct SessionId(pub [u8; 32]); + +impl Debug for SessionId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("SessionId") + .field(&hex::encode(self.0)) + .finish() + } +} + pub type Result = std::result::Result; impl From for SshStatus { diff --git a/lib/cluelessh-transport/src/packet.rs b/lib/cluelessh-transport/src/packet.rs index a9280a5..a22761a 100644 --- a/lib/cluelessh-transport/src/packet.rs +++ b/lib/cluelessh-transport/src/packet.rs @@ -6,8 +6,8 @@ use std::mem; use tracing::{debug, trace}; use crate::crypto::{self, EncryptionAlgorithm, Keys, Plaintext, Session, SharedSecret}; -use crate::peer_error; use crate::Result; +use crate::{peer_error, SessionId}; use cluelessh_format::numbers; use cluelessh_format::{NameList, Reader, Writer}; @@ -67,7 +67,8 @@ impl PacketTransport { } fn recv_bytes_step(&mut self, bytes: &[u8]) -> Result> { - // TODO: This might not work if we buffer two packets where one changes keys in between? + // This would not work if we buffer two packets where one changes keys in between, + // but SSH_MSG_NEWKEYS messages guarantee that this cannot happen. let result = self.recv_next_packet @@ -125,7 +126,7 @@ impl PacketTransport { is_server, ) { self.keys = Box::new(Session::new( - h, + SessionId(h), k, encryption_client_to_server, encryption_server_to_client, diff --git a/lib/cluelessh-transport/src/server.rs b/lib/cluelessh-transport/src/server.rs index 8c30277..d96e05c 100644 --- a/lib/cluelessh-transport/src/server.rs +++ b/lib/cluelessh-transport/src/server.rs @@ -7,18 +7,14 @@ use crate::crypto::{ use crate::packet::{ KeyExchangeEcDhInitPacket, KeyExchangeInitPacket, Packet, PacketTransport, ProtocolIdentParser, }; -use crate::Result; use crate::{peer_error, Msg, SshRng, SshStatus}; +use crate::{Result, SessionId}; use cluelessh_format::numbers; use cluelessh_format::{NameList, Reader, Writer}; use cluelessh_keys::private::PlaintextPrivateKey; use cluelessh_keys::signature::Signature; use tracing::{debug, info, trace}; -// This is definitely who we are. -// TODO: dont make cluelesshd do this -pub const SERVER_IDENTIFICATION: &[u8] = b"SSH-2.0-OpenSSH_9.7\r\n"; - pub struct ServerConnection { state: ServerState, packet_transport: PacketTransport, @@ -31,6 +27,7 @@ pub struct ServerConnection { #[derive(Debug, Clone, Default)] pub struct ServerConfig { + pub server_identification: Vec, pub host_keys: Vec, } @@ -69,10 +66,10 @@ enum ServerState { encryption_server_to_client: EncryptionAlgorithm, }, ServiceRequest { - session_ident: [u8; 32], + session_id: SessionId, }, Open { - session_ident: [u8; 32], + session_id: SessionId, }, } @@ -87,7 +84,7 @@ pub struct KeyExchangeParameters { } pub struct KeyExchangeResponse { - pub hash: [u8; 32], + pub hash: SessionId, pub server_ephemeral_public_key: Vec, pub shared_secret: SharedSecret, pub signature: Signature, @@ -111,7 +108,7 @@ impl ServerConnection { ident_parser.recv_bytes(bytes); if let Some(client_identification) = ident_parser.get_peer_ident() { self.packet_transport - .queue_send_protocol_info(SERVER_IDENTIFICATION.to_vec()); + .queue_send_protocol_info(self.config.server_identification.clone()); self.state = ServerState::KeyExchangeInit { client_identification, }; @@ -311,10 +308,11 @@ impl ServerConnection { *encryption_server_to_client, true, ); - self.state = ServerState::ServiceRequest { session_ident: *h }; + self.state = ServerState::ServiceRequest { + session_id: SessionId(*h), + }; } - ServerState::ServiceRequest { session_ident } => { - // TODO: this should probably move out of here? unsure. + ServerState::ServiceRequest { session_id } => { if packet.payload.first() != Some(&numbers::SSH_MSG_SERVICE_REQUEST) { return Err(peer_error!("did not send SSH_MSG_SERVICE_REQUEST")); } @@ -335,7 +333,7 @@ impl ServerConnection { }, }); self.state = ServerState::Open { - session_ident: *session_ident, + session_id: *session_id, }; } ServerState::Open { .. } => { @@ -346,9 +344,9 @@ impl ServerConnection { Ok(()) } - pub fn is_open(&self) -> Option<[u8; 32]> { + pub fn is_open(&self) -> Option { match self.state { - ServerState::Open { session_ident } => Some(session_ident), + ServerState::Open { session_id } => Some(session_id), _ => None, } } @@ -365,7 +363,7 @@ impl ServerConnection { .. } => Some(KeyExchangeParameters { client_ident: client_identification.clone(), - server_ident: SERVER_IDENTIFICATION.to_vec(), + server_ident: self.config.server_identification.to_vec(), client_kexinit: client_kexinit.clone(), server_kexinit: server_kexinit.clone(), eph_client_public_key: client_ephemeral_public_key.clone(), @@ -392,7 +390,7 @@ impl ServerConnection { self.packet_transport.queue_packet(packet); self.state = ServerState::NewKeys { - hash: response.hash, + hash: response.hash.0, shared_secret: response.shared_secret.clone(), encryption_client_to_server: *encryption_client_to_server, encryption_server_to_client: *encryption_server_to_client, @@ -437,7 +435,7 @@ pub fn do_key_exchange( ); Ok(KeyExchangeResponse { - hash, + hash: SessionId(hash), server_ephemeral_public_key, shared_secret, signature: private.private_key.sign(&hash),