From cacf106b804b62f8ab1dca8df3b0dc44f715a4b4 Mon Sep 17 00:00:00 2001 From: Warren Date: Wed, 17 Jun 2026 20:18:21 +0800 Subject: [PATCH] Phase 4: Implement SSH packet size limit (maxpack - 1024) - Add maxpack field to SftpHandler structure - Modify SftpHandler::new() to accept maxpack parameter - Limit SSH_FXP_READ data size to maxpack - 1024 bytes (OpenSSH style) - Get maxpack from Channel.remote_maxpacket Changes: - sftp_handler.rs: SftpHandler struct + new() + handle_read() - channel.rs: Pass remote_maxpacket to SftpHandler::new() Reference: OpenSSH sftp-server.c: process_read() - Limit: maxpacket - 1024 bytes - Prevent packet size violation Test status: 5MB upload still incomplete (2.0MB) - Issue may require additional debugging - Upload direction may also need maxpack limit --- markbase-core/src/ssh_server/channel.rs | 10 +++++++++- markbase-core/src/ssh_server/sftp_handler.rs | 16 ++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/markbase-core/src/ssh_server/channel.rs b/markbase-core/src/ssh_server/channel.rs index c631391..2be1513 100644 --- a/markbase-core/src/ssh_server/channel.rs +++ b/markbase-core/src/ssh_server/channel.rs @@ -460,7 +460,15 @@ impl ChannelManager { // Phase 7: 初始化SFTP handler let root_dir = PathBuf::from("/Users/accusys/markbase"); // 默认root目录 - let sftp_handler = SftpHandler::new(root_dir); + + // ⭐⭐⭐⭐⭐ Phase 4: 获取 client maxpack 限制(从 Channel 中获取) + let maxpacket = if let Some(ch) = self.channels.get(&channel) { + ch.remote_maxpacket // 来自 SSH_MSG_CHANNEL_OPEN 的 maximum_packet_size + } else { + 32768 // OpenSSH 默认值(32KB) + }; + + let sftp_handler = SftpHandler::new(root_dir, maxpacket); // ⭐⭐⭐⭐⭐ Phase 4: 传入 maxpack // 存储到channel if let Some(ch) = self.channels.get_mut(&channel) { diff --git a/markbase-core/src/ssh_server/sftp_handler.rs b/markbase-core/src/ssh_server/sftp_handler.rs index 1a9a023..69aeffb 100644 --- a/markbase-core/src/ssh_server/sftp_handler.rs +++ b/markbase-core/src/ssh_server/sftp_handler.rs @@ -256,15 +256,19 @@ pub struct SftpHandler { root_dir: PathBuf, next_handle_id: u32, handles: std::collections::HashMap, + // ⭐⭐⭐⭐⭐ Phase 4: 添加 client maxpack 限制(参考OpenSSH sftp-server.c) + maxpacket: u32, // 来自 SSH_MSG_CHANNEL_OPEN_CONFIRMATION 的 maximum_packet_size } impl SftpHandler { - pub fn new(root_dir: PathBuf) -> Self { + // ⭐⭐⭐⭐⭐ Phase 4: 修改 new() 方法,接受 maxpack 参数 + pub fn new(root_dir: PathBuf, maxpacket: u32) -> Self { let canonical_root = root_dir.canonicalize().unwrap_or(root_dir); Self { root_dir: canonical_root, next_handle_id: 0, handles: std::collections::HashMap::new(), + maxpacket, // ⭐⭐⭐⭐⭐ Phase 4: client maxpack 限制 } } @@ -420,7 +424,15 @@ impl SftpHandler { if let Some(ref mut file) = handle.file { file.seek(SeekFrom::Start(offset))?; - let mut buffer = vec![0u8; length as usize]; + // ⭐⭐⭐⭐⭐ Phase 4: 限制数据大小,不超过 maxpacket - 1024(参考OpenSSH sftp-server.c) + // OpenSSH sftp-server.c: process_read() 中限制数据大小为 maxpacket - 1024 bytes + // SSH packet overhead: ~1024 bytes (SSH header + SSH_FXP_DATA header) + let max_data_size = self.maxpacket - 1024; + let actual_length = std::cmp::min(length, max_data_size); + + info!("SSH_FXP_READ limited: requested={}, actual={}", length, actual_length); + + let mut buffer = vec![0u8; actual_length as usize]; match file.read(&mut buffer) { Ok(0) => { self.build_status_response(id, SftpStatus::SSH_FX_EOF, "End of file")