Complete Phase 15: Window Control + sshbuf zero-copy + SCP support
- Fix Window Control: decrease local_window on SSH_MSG_CHANNEL_DATA (critical fix) - Implement SSH_MSG_CHANNEL_WINDOW_ADJUST (OpenSSH channels.c style) - Add sshbuf.rs: zero-copy buffer management (339 lines, OpenSSH sshbuf.c reference) - Add SCP command detection (scp -t/-f support for legacy protocol) - Add handle_scp_exec() and handle_interactive_exec() for SCP/rsync - Verify: rsync 100MB transfer successful, SCP legacy protocol working - Security: All crypto using RustCrypto authoritative libraries (x25519-dalek, ed25519-dalek, aes, hmac)
This commit is contained in:
@@ -202,14 +202,16 @@ fn perform_complete_kex_exchange(
|
||||
kexdh_reply.write(stream)?;
|
||||
info!("Sent SSH_MSG_KEX_ECDH_REPLY");
|
||||
|
||||
// Strict KEX: Wait for client NEWKEYS first (OpenSSH 10.2 requirement)
|
||||
let client_newkeys = SshPacket::read(stream)?;
|
||||
kex_state.handle_newkeys(&client_newkeys)?;
|
||||
info!("Received SSH_MSG_NEWKEYS from client");
|
||||
|
||||
// Now send server NEWKEYS
|
||||
let newkeys_packet = KexState::send_newkeys()?;
|
||||
newkeys_packet.write(stream)?;
|
||||
kex_state.newkeys_sent = true;
|
||||
info!("Sent SSH_MSG_NEWKEYS");
|
||||
|
||||
let client_newkeys = SshPacket::read(stream)?;
|
||||
kex_state.handle_newkeys(&client_newkeys)?;
|
||||
info!("Received SSH_MSG_NEWKEYS");
|
||||
info!("Sent SSH_MSG_NEWKEYS from server");
|
||||
|
||||
if kex_state.is_encryption_ready() {
|
||||
info!("Encryption channel established successfully");
|
||||
@@ -454,29 +456,39 @@ fn handle_ssh_service_loop(
|
||||
let encrypted_response = EncryptedPacket::new(&response.payload, encryption_ctx, true)?;
|
||||
encrypted_response.write(stream)?;
|
||||
|
||||
// Phase 6: 检查是否有命令输出需要发送
|
||||
if let Some(channel_id) = channel_manager.get_channel_with_output() {
|
||||
if let Some(output) = channel_manager.get_channel_output(channel_id) {
|
||||
// 发送命令输出(SSH_MSG_CHANNEL_DATA)
|
||||
let data_packet = channel_manager.build_channel_data(channel_id, &output)?;
|
||||
let encrypted_data = EncryptedPacket::new(&data_packet.payload, encryption_ctx, true)?;
|
||||
encrypted_data.write(stream)?;
|
||||
info!("Sent command output ({} bytes)", output.len());
|
||||
|
||||
// 发送SSH_MSG_CHANNEL_EOF
|
||||
let eof_packet = channel_manager.build_channel_eof(channel_id)?;
|
||||
let encrypted_eof = EncryptedPacket::new(&eof_packet.payload, encryption_ctx, true)?;
|
||||
encrypted_eof.write(stream)?;
|
||||
info!("Sent SSH_MSG_CHANNEL_EOF");
|
||||
|
||||
// 发送SSH_MSG_CHANNEL_CLOSE
|
||||
let close_packet = channel_manager.build_channel_close(channel_id)?;
|
||||
let encrypted_close = EncryptedPacket::new(&close_packet.payload, encryption_ctx, true)?;
|
||||
encrypted_close.write(stream)?;
|
||||
info!("Sent SSH_MSG_CHANNEL_CLOSE");
|
||||
|
||||
// 移除channel
|
||||
channel_manager.remove_channel(channel_id);
|
||||
// ⭐⭐⭐⭐⭐ Phase 14.5修复:区分普通命令和交互式进程
|
||||
// 检查是否有 exec_process(交互式进程如 rsync)
|
||||
let has_exec_process = channel_manager.has_exec_process();
|
||||
|
||||
if has_exec_process {
|
||||
info!("⭐⭐⭐⭐⭐ [INTERACTIVE_PROCESS] Detected exec_process (rsync/SCP), skipping immediate EOF");
|
||||
// 对于交互式进程,只发送 SUCCESS,等待 poll 循环处理数据流
|
||||
// 不立即发送 EOF + CLOSE
|
||||
} else {
|
||||
// Phase 6: 普通命令执行,检查是否有命令输出需要发送
|
||||
if let Some(channel_id) = channel_manager.get_channel_with_output() {
|
||||
if let Some(output) = channel_manager.get_channel_output(channel_id) {
|
||||
// 发送命令输出(SSH_MSG_CHANNEL_DATA)
|
||||
let data_packet = channel_manager.build_channel_data(channel_id, &output)?;
|
||||
let encrypted_data = EncryptedPacket::new(&data_packet.payload, encryption_ctx, true)?;
|
||||
encrypted_data.write(stream)?;
|
||||
info!("Sent command output ({} bytes)", output.len());
|
||||
|
||||
// 发送SSH_MSG_CHANNEL_EOF
|
||||
let eof_packet = channel_manager.build_channel_eof(channel_id)?;
|
||||
let encrypted_eof = EncryptedPacket::new(&eof_packet.payload, encryption_ctx, true)?;
|
||||
encrypted_eof.write(stream)?;
|
||||
info!("Sent SSH_MSG_CHANNEL_EOF");
|
||||
|
||||
// 发送SSH_MSG_CHANNEL_CLOSE
|
||||
let close_packet = channel_manager.build_channel_close(channel_id)?;
|
||||
let encrypted_close = EncryptedPacket::new(&close_packet.payload, encryption_ctx, true)?;
|
||||
encrypted_close.write(stream)?;
|
||||
info!("Sent SSH_MSG_CHANNEL_CLOSE");
|
||||
|
||||
// 移除channel
|
||||
channel_manager.remove_channel(channel_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user