// SSH Channel协议实现(Phase 6 + Phase 13端口转发) // 参考OpenSSH channel.c use crate::ssh_server::packet::{SshPacket, PacketType}; use crate::ssh_server::ssh_security_config::SshSecurityConfig; // Phase 13.3: 安全配置 use crate::ssh_server::port_forward::{PortForwardManager, DirectTcpipChannel, ForwardedTcpipChannel}; // Phase 13.3 use std::io::{Read, Write}; // 导入Write trait(OpenSSH标准) use anyhow::{Result, anyhow}; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use log::{info, warn, debug}; use std::collections::HashMap; use std::sync::{Arc, Mutex}; use crate::ssh_server::sftp_handler::SftpHandler; // Phase 7: SFTP handler use crate::ssh_server::scp_handler::ScpHandler; // Phase 8: SCP handler use crate::ssh_server::rsync_handler::RsyncHandler; // Phase 8: rsync handler use std::path::PathBuf; // Phase 7-8: Path for SFTP/SCP/rsync root directory /// SSH Channel管理器(参考OpenSSH channel.c: struct channel) pub struct ChannelManager { channels: HashMap, next_channel_id: u32, } impl ChannelManager { pub fn new() -> Self { Self { channels: HashMap::new(), next_channel_id: 0, } } /// 处理SSH_MSG_CHANNEL_OPEN(参考OpenSSH channel.c: channel_open()) /// Phase 13.3: 支持direct-tcpip和forwarded-tcpip channel pub fn handle_channel_open(&mut self, packet: &SshPacket, security_config: Option<&SshSecurityConfig>) -> Result { info!("Processing SSH_MSG_CHANNEL_OPEN"); let mut cursor = std::io::Cursor::new(packet.payload.as_slice()); // Packet type let packet_type = cursor.read_u8()?; if packet_type != PacketType::SSH_MSG_CHANNEL_OPEN as u8 { return Err(anyhow!("Invalid packet type for CHANNEL_OPEN")); } // 读取channel类型(SSH string) let channel_type = read_ssh_string(&mut cursor)?; // 读取sender channel ID(u32) let sender_channel = cursor.read_u32::()?; // 读取初始窗口大小(u32) let initial_window_size = cursor.read_u32::()?; // 读取最大packet大小(u32) let maximum_packet_size = cursor.read_u32::()?; info!("Channel open: type={}, sender_channel={}, window={}, max_packet={}", channel_type, sender_channel, initial_window_size, maximum_packet_size); // Phase 13.3: 检查channel类型(支持session、direct-tcpip、forwarded-tcpip) match channel_type.as_str() { "session" => { // 传统的session channel(Phase 6) self.handle_session_channel_open(sender_channel, initial_window_size, maximum_packet_size) } "direct-tcpip" => { // Phase 13.3: Remote port forwarding channel info!("Received direct-tcpip channel open (Remote port forwarding)"); self.handle_direct_tcpip_channel_open(packet, sender_channel, initial_window_size, maximum_packet_size, security_config) } "forwarded-tcpip" => { // Phase 13.3: Local port forwarding channel info!("Received forwarded-tcpip channel open (Local port forwarding)"); self.handle_forwarded_tcpip_channel_open(packet, sender_channel, initial_window_size, maximum_packet_size) } _ => { warn!("Unsupported channel type: {}", channel_type); self.build_channel_open_failure( sender_channel, 3, // SSH_OPEN_UNKNOWN_CHANNEL_TYPE "Unsupported channel type", "en" ) } } } /// 处理session channel open(Phase 6) fn handle_session_channel_open(&mut self, sender_channel: u32, initial_window_size: u32, maximum_packet_size: u32) -> Result { info!("Processing session channel open"); let server_channel = self.next_channel_id; self.next_channel_id += 1; let channel = Channel { server_channel, sender_channel, channel_type: "session".to_string(), window_size: initial_window_size, maximum_packet_size, state: ChannelState::Open, output_buffer: None, sftp_handler: None, scp_handler: None, rsync_handler: None, direct_tcpip: None, forwarded_tcpip: None, }; self.channels.insert(server_channel, channel); info!("Session channel created: server_channel={}, sender_channel={}", server_channel, sender_channel); self.build_channel_open_confirmation(server_channel, sender_channel, initial_window_size, maximum_packet_size) } /// 处理direct-tcpip channel open(Phase 13.3: Remote port forwarding) fn handle_direct_tcpip_channel_open( &mut self, packet: &SshPacket, sender_channel: u32, initial_window_size: u32, maximum_packet_size: u32, security_config: Option<&SshSecurityConfig>, ) -> Result { info!("Processing direct-tcpip channel open"); // 解析direct-tcpip参数 let mut port_forward_manager = PortForwardManager::new(); let direct_tcpip = port_forward_manager.handle_direct_tcpip_channel(&packet.payload)?; // Phase 13.3: 安全配置验证 if let Some(security) = security_config { if let Err(e) = security.validate_direct_tcpip_channel(&direct_tcpip.host_to_connect, direct_tcpip.port_to_connect) { warn!("direct-tcpip security validation failed: {}", e); return self.build_channel_open_failure( sender_channel, 2, // SSH_OPEN_CONNECT_FAILED "Security validation failed", "en" ); } info!("direct-tcpip security validation passed"); } let server_channel = self.next_channel_id; self.next_channel_id += 1; let channel = Channel { server_channel, sender_channel, channel_type: "direct-tcpip".to_string(), window_size: initial_window_size, maximum_packet_size, state: ChannelState::Open, output_buffer: None, sftp_handler: None, scp_handler: None, rsync_handler: None, direct_tcpip: Some(direct_tcpip), forwarded_tcpip: None, }; self.channels.insert(server_channel, channel); info!("direct-tcpip channel created: server_channel={}, host={}, port={}", server_channel, self.channels.get(&server_channel).unwrap().direct_tcpip.as_ref().unwrap().host_to_connect, self.channels.get(&server_channel).unwrap().direct_tcpip.as_ref().unwrap().port_to_connect); self.build_channel_open_confirmation(server_channel, sender_channel, initial_window_size, maximum_packet_size) } /// 处理forwarded-tcpip channel open(Phase 13.3: Local port forwarding) fn handle_forwarded_tcpip_channel_open( &mut self, packet: &SshPacket, sender_channel: u32, initial_window_size: u32, maximum_packet_size: u32, ) -> Result { info!("Processing forwarded-tcpip channel open"); // 解析forwarded-tcpip参数 let mut port_forward_manager = PortForwardManager::new(); let forwarded_tcpip = port_forward_manager.handle_forwarded_tcpip_channel(&packet.payload)?; let server_channel = self.next_channel_id; self.next_channel_id += 1; let channel = Channel { server_channel, sender_channel, channel_type: "forwarded-tcpip".to_string(), window_size: initial_window_size, maximum_packet_size, state: ChannelState::Open, output_buffer: None, sftp_handler: None, scp_handler: None, rsync_handler: None, direct_tcpip: None, forwarded_tcpip: Some(forwarded_tcpip), }; self.channels.insert(server_channel, channel); info!("forwarded-tcpip channel created: server_channel={}, bind={}, originator={}", server_channel, self.channels.get(&server_channel).unwrap().forwarded_tcpip.as_ref().unwrap().bind_port, self.channels.get(&server_channel).unwrap().forwarded_tcpip.as_ref().unwrap().originator_address); self.build_channel_open_confirmation(server_channel, sender_channel, initial_window_size, maximum_packet_size) } /// 处理SSH_MSG_CHANNEL_REQUEST(参考OpenSSH channel.c: channel_request()) pub fn handle_channel_request(&mut self, packet: &SshPacket) -> Result> { info!("Processing SSH_MSG_CHANNEL_REQUEST"); let mut cursor = std::io::Cursor::new(packet.payload.as_slice()); // 使用as_slice()(Rust标准) // Packet type let packet_type = cursor.read_u8()?; if packet_type != PacketType::SSH_MSG_CHANNEL_REQUEST as u8 { return Err(anyhow!("Invalid packet type for CHANNEL_REQUEST")); } // 读取recipient channel(u32) let recipient_channel = cursor.read_u32::()?; // 读取请求类型(SSH string) let request_type = read_ssh_string(&mut cursor)?; // 读取want reply标志(boolean) let want_reply = cursor.read_u8()? != 0; info!("Channel request: channel={}, type={}, want_reply={}", recipient_channel, request_type, want_reply); // 处理不同请求类型(参考OpenSSH channel.c) if request_type == "exec" { self.handle_exec_request(&mut cursor, recipient_channel, want_reply) // 移除?操作符(返回Option不是Result) } else if request_type == "subsystem" { self.handle_subsystem_request(&mut cursor, recipient_channel, want_reply) // 移除?操作符 } else if request_type == "shell" { self.handle_shell_request(recipient_channel, want_reply) // 移除?操作符 } else if request_type == "env" { self.handle_env_request(&mut cursor, recipient_channel, want_reply) // 移除?操作符 } else if request_type == "pty-req" { self.handle_pty_request(&mut cursor, recipient_channel, want_reply) // 移除?操作符 } else { warn!("Unsupported channel request: {}", request_type); if want_reply { Ok(Some(self.build_channel_failure(recipient_channel)?)) } else { Ok(None) } } } /// 处理exec请求(参考OpenSSH channel.c: channel_request_exec()) fn handle_exec_request(&mut self, cursor: &mut std::io::Cursor<&[u8]>, channel: u32, want_reply: bool) -> Result> { info!("Handling exec request for channel {}", channel); // 读取命令(SSH string) let command = read_ssh_string(cursor)?; info!("Exec command: {}", command); // Phase 8: SCP/rsync命令直接执行(使用系统命令) // 不需要自己实现SCP协议,让系统的scp/rsync命令处理 let output = self.execute_command(&command)?; // 存储输出,等待后续发送CHANNEL_DATA if let Some(ch) = self.channels.get_mut(&channel) { ch.output_buffer = Some(output); } if want_reply { Ok(Some(self.build_channel_success(channel)?)) } else { Ok(None) } } /// 执行命令并捕获输出(Phase 6基础实现) fn execute_command(&self, command: &str) -> Result> { use std::process::{Command, Stdio}; info!("Executing command: {}", command); // 使用shell执行命令(参考OpenSSH session.c) let output = Command::new("sh") .arg("-c") .arg(command) .output()?; // 返回stdout + stderr let mut result = output.stdout; result.extend_from_slice(&output.stderr); info!("Command output: {} bytes", result.len()); Ok(result) } /// 处理subsystem请求(参考OpenSSH channel.c: channel_request_subsystem()) fn handle_subsystem_request(&mut self, cursor: &mut std::io::Cursor<&[u8]>, channel: u32, want_reply: bool) -> Result> { info!("Handling subsystem request for channel {}", channel); // 读取subsystem名称(SSH string) let subsystem = read_ssh_string(cursor)?; info!("Subsystem: {}", subsystem); // 检查subsystem支持(OpenSSH支持:sftp) if subsystem == "sftp" { info!("SFTP subsystem requested"); // Phase 7: 初始化SFTP handler let root_dir = PathBuf::from("/Users/accusys/markbase"); // 默认root目录 let sftp_handler = SftpHandler::new(root_dir); // 存储到channel if let Some(ch) = self.channels.get_mut(&channel) { ch.sftp_handler = Some(sftp_handler); info!("SFTP handler initialized for channel {}", channel); } if want_reply { Ok(Some(self.build_channel_success(channel)?)) } else { Ok(None) } } else { warn!("Unsupported subsystem: {}", subsystem); if want_reply { Ok(Some(self.build_channel_failure(channel)?)) } else { Ok(None) } } } /// 处理shell请求(参考OpenSSH channel.c) fn handle_shell_request(&mut self, channel: u32, want_reply: bool) -> Result> { info!("Handling shell request for channel {}", channel); // Phase 9将实现shell warn!("Shell not implemented in Phase 6"); if want_reply { Ok(Some(self.build_channel_failure(channel)?)) } else { Ok(None) } } /// 处理env请求(参考OpenSSH channel.c) fn handle_env_request(&mut self, cursor: &mut std::io::Cursor<&[u8]>, channel: u32, want_reply: bool) -> Result> { info!("Handling env request for channel {}", channel); // 读取环境变量名和值 let name = read_ssh_string(cursor)?; let value = read_ssh_string(cursor)?; info!("Env: {}={}", name, value); if want_reply { Ok(Some(self.build_channel_success(channel)?)) } else { Ok(None) } } /// 处理pty请求(参考OpenSSH channel.c) fn handle_pty_request(&mut self, cursor: &mut std::io::Cursor<&[u8]>, channel: u32, want_reply: bool) -> Result> { info!("Handling pty request for channel {}", channel); // 读取terminal类型(SSH string) let term = read_ssh_string(cursor)?; // 读取窗口大小(4个uint32) let width = cursor.read_u32::()?; let height = cursor.read_u32::()?; let _pixel_width = cursor.read_u32::()?; let _pixel_height = cursor.read_u32::()?; // 读取terminal modes(SSH string格式) let modes_len = cursor.read_u32::()?; let mut modes = vec![0u8; modes_len as usize]; cursor.read_exact(&mut modes)?; info!("PTY: term={}, width={}, height={}, modes_len={}", term, width, height, modes_len); if want_reply { Ok(Some(self.build_channel_success(channel)?)) } else { Ok(None) } } /// 处理SSH_MSG_CHANNEL_DATA(参考OpenSSH channel.c: channel_input_data()) pub fn handle_channel_data(&mut self, packet: &SshPacket) -> Result> { info!("Processing SSH_MSG_CHANNEL_DATA"); let mut cursor = std::io::Cursor::new(packet.payload.as_slice()); // Packet type let packet_type = cursor.read_u8()?; if packet_type != PacketType::SSH_MSG_CHANNEL_DATA as u8 { return Err(anyhow!("Invalid packet type for CHANNEL_DATA")); } // 读取recipient channel let recipient_channel = cursor.read_u32::()?; // 读取数据(SSH string) let data_length = cursor.read_u32::()?; let mut data = vec![0u8; data_length as usize]; cursor.read_exact(&mut data)?; info!("Channel data: channel={}, length={}", recipient_channel, data.len()); info!("Channel data content (first 20 bytes): {:?}", &data[..std::cmp::min(20, data.len())]); // Phase 7: 检查是否是SFTP channel if let Some(channel) = self.channels.get_mut(&recipient_channel) { if let Some(sftp_handler) = &mut channel.sftp_handler { info!("Processing SFTP request ({} bytes)", data.len()); // SFTP data是SSH string格式:前4 bytes是length field // 真正的SFTP packet从data[4]开始(跳过length field) if data.len() < 4 { warn!("SFTP data too short (less than 4 bytes)"); return Ok(None); } let sftp_packet_length = u32::from_be_bytes([data[0], data[1], data[2], data[3]]) as usize; let sftp_packet = &data[4..4 + sftp_packet_length]; info!("SFTP packet: length={}, content={:?}", sftp_packet_length, &sftp_packet[..std::cmp::min(20, sftp_packet.len())]); // 处理SFTP请求 let response = sftp_handler.handle_request(sftp_packet)?; info!("SFTP response: {} bytes", response.len()); // 构建SSH_MSG_CHANNEL_DATA返回SFTP响应(需要SSH string格式) return Ok(Some(self.build_channel_data(recipient_channel, &response)?)); } } // 如果不是SFTP,返回None(Phase 6的普通channel data处理) Ok(None) } /// 处理SSH_MSG_CHANNEL_CLOSE(参考OpenSSH channel.c: channel_input_close()) pub fn handle_channel_close(&mut self, packet: &SshPacket) -> Result> { info!("Processing SSH_MSG_CHANNEL_CLOSE"); let mut cursor = std::io::Cursor::new(packet.payload.as_slice()); // 使用as_slice()(Rust标准) // Packet type let packet_type = cursor.read_u8()?; if packet_type != PacketType::SSH_MSG_CHANNEL_CLOSE as u8 { return Err(anyhow!("Invalid packet type for CHANNEL_CLOSE")); } // 读取recipient channel let recipient_channel = cursor.read_u32::()?; info!("Channel close: channel={}", recipient_channel); // 移除channel(参考OpenSSH channel.c) if let Some(channel) = self.channels.remove(&recipient_channel) { info!("Channel {} removed", recipient_channel); // 发送SSH_MSG_CHANNEL_CLOSE回应 Ok(Some(self.build_channel_close(channel.sender_channel)?)) } else { warn!("Channel {} not found", recipient_channel); Ok(None) } } /// 构建SSH_MSG_CHANNEL_OPEN_CONFIRMATION(参考OpenSSH channel.c) fn build_channel_open_confirmation( &self, server_channel: u32, sender_channel: u32, window_size: u32, packet_size: u32, ) -> Result { let mut payload = Vec::new(); // Packet type payload.write_u8(PacketType::SSH_MSG_CHANNEL_OPEN_CONFIRMATION as u8)?; // Server channel number payload.write_u32::(server_channel)?; // Sender channel number payload.write_u32::(sender_channel)?; // Initial window size payload.write_u32::(window_size)?; // Maximum packet size payload.write_u32::(packet_size)?; Ok(SshPacket::new(payload)) } /// 构建SSH_MSG_CHANNEL_OPEN_FAILURE(参考OpenSSH channel.c) fn build_channel_open_failure( &self, sender_channel: u32, reason_code: u32, description: &str, language: &str, ) -> Result { let mut payload = Vec::new(); // Packet type payload.write_u8(PacketType::SSH_MSG_CHANNEL_OPEN_FAILURE as u8)?; // Sender channel number payload.write_u32::(sender_channel)?; // Reason code payload.write_u32::(reason_code)?; // Description(SSH string) payload.write_u32::(description.len() as u32)?; payload.write_all(description.as_bytes())?; // Language(SSH string) payload.write_u32::(language.len() as u32)?; payload.write_all(language.as_bytes())?; Ok(SshPacket::new(payload)) } /// 构建SSH_MSG_CHANNEL_SUCCESS(参考OpenSSH channel.c) fn build_channel_success(&self, channel: u32) -> Result { let mut payload = Vec::new(); payload.write_u8(PacketType::SSH_MSG_CHANNEL_SUCCESS as u8)?; payload.write_u32::(channel)?; Ok(SshPacket::new(payload)) } /// 构建SSH_MSG_CHANNEL_FAILURE(参考OpenSSH channel.c) fn build_channel_failure(&self, channel: u32) -> Result { let mut payload = Vec::new(); payload.write_u8(PacketType::SSH_MSG_CHANNEL_FAILURE as u8)?; payload.write_u32::(channel)?; Ok(SshPacket::new(payload)) } /// 构建SSH_MSG_CHANNEL_CLOSE(参考OpenSSH channel.c) pub fn build_channel_close(&self, channel: u32) -> Result { let mut payload = Vec::new(); payload.write_u8(PacketType::SSH_MSG_CHANNEL_CLOSE as u8)?; payload.write_u32::(channel)?; Ok(SshPacket::new(payload)) } /// 构建SSH_MSG_CHANNEL_DATA(Phase 6新增) pub fn build_channel_data(&self, channel: u32, data: &[u8]) -> Result { let mut payload = Vec::new(); payload.write_u8(PacketType::SSH_MSG_CHANNEL_DATA as u8)?; payload.write_u32::(channel)?; payload.write_u32::(data.len() as u32)?; payload.write_all(data)?; Ok(SshPacket::new(payload)) } /// 构建SSH_MSG_CHANNEL_EOF(Phase 6新增) pub fn build_channel_eof(&self, channel: u32) -> Result { let mut payload = Vec::new(); payload.write_u8(PacketType::SSH_MSG_CHANNEL_EOF as u8)?; payload.write_u32::(channel)?; Ok(SshPacket::new(payload)) } /// 获取有输出待发送的channel ID(Phase 6新增) pub fn get_channel_with_output(&self) -> Option { for (&id, channel) in &self.channels { if channel.output_buffer.is_some() { return Some(id); } } None } /// 获取channel输出(Phase 6新增) pub fn get_channel_output(&mut self, channel_id: u32) -> Option> { if let Some(channel) = self.channels.get_mut(&channel_id) { channel.output_buffer.take() } else { None } } /// 移除channel(Phase 6新增) pub fn remove_channel(&mut self, channel_id: u32) { self.channels.remove(&channel_id); } } /// SSH Channel结构(参考OpenSSH channel.c: struct channel) struct Channel { server_channel: u32, sender_channel: u32, channel_type: String, window_size: u32, maximum_packet_size: u32, state: ChannelState, output_buffer: Option>, // Phase 6: 命令输出缓冲 sftp_handler: Option, // Phase 7: SFTP处理器 scp_handler: Option, // Phase 8: SCP处理器 rsync_handler: Option, // Phase 8: rsync处理器 // Phase 13.3: 端口转发相关字段 direct_tcpip: Option, // direct-tcpip channel(Remote forwarding) forwarded_tcpip: Option, // forwarded-tcpip channel(Local forwarding) } /// SSH Channel状态(参考OpenSSH channel.c) enum ChannelState { Open, Closing, Closed, } /// SSH string读取辅助函数 fn read_ssh_string(reader: &mut R) -> Result { let length = reader.read_u32::()?; let mut buffer = vec![0u8; length as usize]; reader.read_exact(&mut buffer)?; Ok(String::from_utf8(buffer)?) } #[cfg(test)] mod tests { use super::*; #[test] fn test_channel_manager_creation() { let manager = ChannelManager::new(); assert_eq!(manager.next_channel_id, 0); } #[test] fn test_channel_open_confirmation() { let manager = ChannelManager::new(); let packet = manager.build_channel_open_confirmation(0, 100, 2097152, 32768).unwrap(); assert_eq!(packet.payload[0], PacketType::SSH_MSG_CHANNEL_OPEN_CONFIRMATION as u8); } #[test] fn test_channel_success() { let manager = ChannelManager::new(); let packet = manager.build_channel_success(0).unwrap(); assert_eq!(packet.payload[0], PacketType::SSH_MSG_CHANNEL_SUCCESS as u8); } }