Update Phase 6: Fix SFTP subsystem initialization and data handling
Phase 6 updates: - Add SftpHandler integration in Channel structure - Initialize SFTP handler on subsystem request - Handle SFTP packets via CHANNEL_DATA - Fix CHANNEL_DATA response handling in server loop Phase 7 progress: - SFTP subsystem initialization working - SSH_FXP_INIT/VERSION handshake working - SFTP packet format partially implemented - Need further debugging for complete SFTP functionality Current status: - SSH command execution fully working (Phase 6 ✓) - SFTP connection initialization working - File transfer operations pending debug
This commit is contained in:
@@ -8,6 +8,8 @@ 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 std::path::PathBuf; // Phase 7: Path for SFTP root directory
|
||||
|
||||
/// SSH Channel管理器(参考OpenSSH channel.c: struct channel)
|
||||
pub struct ChannelManager {
|
||||
@@ -73,6 +75,7 @@ impl ChannelManager {
|
||||
maximum_packet_size,
|
||||
state: ChannelState::Open,
|
||||
output_buffer: None, // Phase 6: 初始化为空
|
||||
sftp_handler: None, // Phase 7: 初始化为空
|
||||
};
|
||||
|
||||
self.channels.insert(server_channel, channel);
|
||||
@@ -184,7 +187,17 @@ impl ChannelManager {
|
||||
// 检查subsystem支持(OpenSSH支持:sftp)
|
||||
if subsystem == "sftp" {
|
||||
info!("SFTP subsystem requested");
|
||||
// Phase 7将实现SFTP
|
||||
|
||||
// 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 {
|
||||
@@ -258,10 +271,10 @@ impl ChannelManager {
|
||||
}
|
||||
|
||||
/// 处理SSH_MSG_CHANNEL_DATA(参考OpenSSH channel.c: channel_input_data())
|
||||
pub fn handle_channel_data(&mut self, packet: &SshPacket) -> Result<()> {
|
||||
pub fn handle_channel_data(&mut self, packet: &SshPacket) -> Result<Option<SshPacket>> {
|
||||
info!("Processing SSH_MSG_CHANNEL_DATA");
|
||||
|
||||
let mut cursor = std::io::Cursor::new(packet.payload.as_slice()); // 使用as_slice()(Rust标准)
|
||||
let mut cursor = std::io::Cursor::new(packet.payload.as_slice());
|
||||
|
||||
// Packet type
|
||||
let packet_type = cursor.read_u8()?;
|
||||
@@ -273,13 +286,41 @@ impl ChannelManager {
|
||||
let recipient_channel = cursor.read_u32::<BigEndian>()?;
|
||||
|
||||
// 读取数据(SSH string)
|
||||
let data = read_ssh_string(&mut cursor)?;
|
||||
let data_length = cursor.read_u32::<BigEndian>()?;
|
||||
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)?));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
// 如果不是SFTP,返回None(Phase 6的普通channel data处理)
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// 处理SSH_MSG_CHANNEL_CLOSE(参考OpenSSH channel.c: channel_input_close())
|
||||
@@ -455,6 +496,7 @@ struct Channel {
|
||||
maximum_packet_size: u32,
|
||||
state: ChannelState,
|
||||
output_buffer: Option<Vec<u8>>, // Phase 6: 命令输出缓冲
|
||||
sftp_handler: Option<SftpHandler>, // Phase 7: SFTP处理器
|
||||
}
|
||||
|
||||
/// SSH Channel状态(参考OpenSSH channel.c)
|
||||
|
||||
@@ -330,7 +330,12 @@ fn handle_ssh_service_loop(
|
||||
}
|
||||
Some(&pt) if pt == PacketType::SSH_MSG_CHANNEL_DATA as u8 => {
|
||||
info!("Received SSH_MSG_CHANNEL_DATA");
|
||||
channel_manager.handle_channel_data(&packet)?;
|
||||
if let Some(response) = channel_manager.handle_channel_data(&packet)? {
|
||||
// Phase 7: SFTP响应通过CHANNEL_DATA返回
|
||||
let encrypted_response = EncryptedPacket::new(&response.payload, encryption_ctx, true)?;
|
||||
encrypted_response.write(stream)?;
|
||||
info!("Sent SSH_MSG_CHANNEL_DATA (SFTP response)");
|
||||
}
|
||||
}
|
||||
Some(&pt) if pt == PacketType::SSH_MSG_CHANNEL_CLOSE as u8 => {
|
||||
info!("Received SSH_MSG_CHANNEL_CLOSE");
|
||||
|
||||
Reference in New Issue
Block a user