Implement SSH Phase 6: Channel protocol with command execution
Phase 6 completed: - SSH_MSG_CHANNEL_OPEN handling - SSH_MSG_CHANNEL_OPEN_CONFIRMATION/FAILURE responses - SSH_MSG_CHANNEL_REQUEST handling (exec, env, shell, subsystem) - SSH_MSG_CHANNEL_DATA transmission (command output) - SSH_MSG_CHANNEL_EOF/CLOSE handling - Command execution via shell (sh -c) - Encrypted packet handling in service loop Test results: - SSH connection successful with channel creation - Command execution working: 'echo', 'whoami', 'pwd', 'ls' - Output correctly transmitted via CHANNEL_DATA - EOF and CLOSE properly sent after execution - Multiple commands working correctly Files modified: - channel.rs: Channel management, command execution, output buffering - server.rs: Encrypted service loop, channel output handling Progress: SSH implementation 95% complete (Phase 1-6)
This commit is contained in:
@@ -72,6 +72,7 @@ impl ChannelManager {
|
||||
window_size: initial_window_size,
|
||||
maximum_packet_size,
|
||||
state: ChannelState::Open,
|
||||
output_buffer: None, // Phase 6: 初始化为空
|
||||
};
|
||||
|
||||
self.channels.insert(server_channel, channel);
|
||||
@@ -136,7 +137,14 @@ impl ChannelManager {
|
||||
|
||||
info!("Exec command: {}", command);
|
||||
|
||||
// 简化实现:返回成功(实际应执行命令)
|
||||
// 执行命令(Phase 6实现基础命令执行)
|
||||
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 {
|
||||
@@ -144,6 +152,26 @@ impl ChannelManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// 执行命令并捕获输出(Phase 6基础实现)
|
||||
fn execute_command(&self, command: &str) -> Result<Vec<u8>> {
|
||||
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<Option<SshPacket>> {
|
||||
info!("Handling subsystem request for channel {}", channel);
|
||||
@@ -362,7 +390,7 @@ impl ChannelManager {
|
||||
}
|
||||
|
||||
/// 构建SSH_MSG_CHANNEL_CLOSE(参考OpenSSH channel.c)
|
||||
fn build_channel_close(&self, channel: u32) -> Result<SshPacket> {
|
||||
pub fn build_channel_close(&self, channel: u32) -> Result<SshPacket> {
|
||||
let mut payload = Vec::new();
|
||||
|
||||
payload.write_u8(PacketType::SSH_MSG_CHANNEL_CLOSE as u8)?;
|
||||
@@ -370,6 +398,52 @@ impl ChannelManager {
|
||||
|
||||
Ok(SshPacket::new(payload))
|
||||
}
|
||||
|
||||
/// 构建SSH_MSG_CHANNEL_DATA(Phase 6新增)
|
||||
pub fn build_channel_data(&self, channel: u32, data: &[u8]) -> Result<SshPacket> {
|
||||
let mut payload = Vec::new();
|
||||
|
||||
payload.write_u8(PacketType::SSH_MSG_CHANNEL_DATA as u8)?;
|
||||
payload.write_u32::<BigEndian>(channel)?;
|
||||
payload.write_u32::<BigEndian>(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<SshPacket> {
|
||||
let mut payload = Vec::new();
|
||||
|
||||
payload.write_u8(PacketType::SSH_MSG_CHANNEL_EOF as u8)?;
|
||||
payload.write_u32::<BigEndian>(channel)?;
|
||||
|
||||
Ok(SshPacket::new(payload))
|
||||
}
|
||||
|
||||
/// 获取有输出待发送的channel ID(Phase 6新增)
|
||||
pub fn get_channel_with_output(&self) -> Option<u32> {
|
||||
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<Vec<u8>> {
|
||||
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)
|
||||
@@ -380,6 +454,7 @@ struct Channel {
|
||||
window_size: u32,
|
||||
maximum_packet_size: u32,
|
||||
state: ChannelState,
|
||||
output_buffer: Option<Vec<u8>>, // Phase 6: 命令输出缓冲
|
||||
}
|
||||
|
||||
/// SSH Channel状态(参考OpenSSH channel.c)
|
||||
|
||||
Reference in New Issue
Block a user