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:
Warren
2026-06-15 10:36:53 +08:00
parent 2187e78398
commit e5af2537b4
2 changed files with 116 additions and 7 deletions

View File

@@ -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_DATAPhase 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_EOFPhase 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 IDPhase 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
}
}
/// 移除channelPhase 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

View File

@@ -95,7 +95,7 @@ fn handle_connection_complete(stream: TcpStream) -> Result<()> {
let mut channel_manager = ChannelManager::new();
// Phase 6-7: SSH服务循环处理channel请求
handle_ssh_service_loop(&mut stream, &mut channel_manager)?;
handle_ssh_service_loop(&mut stream, &mut channel_manager, &mut encryption_ctx)?;
info!("SSH session completed successfully");
Ok(())
@@ -278,23 +278,54 @@ AuthResult::Failure(message) => {
fn handle_ssh_service_loop(
stream: &mut TcpStream,
channel_manager: &mut ChannelManager,
encryption_ctx: &mut EncryptionContext,
) -> Result<()> {
info!("Starting SSH service loop (channel management)");
loop {
let packet = SshPacket::read(stream)?;
// 使用EncryptedPacket读取加密packetPhase 6
let encrypted_packet = EncryptedPacket::read(stream, encryption_ctx, true)?;
let packet = SshPacket::new(encrypted_packet.payload().to_vec());
match packet.payload.first() {
Some(&pt) if pt == PacketType::SSH_MSG_CHANNEL_OPEN as u8 => {
info!("Received SSH_MSG_CHANNEL_OPEN");
let response = channel_manager.handle_channel_open(&packet)?;
response.write(stream)?;
let encrypted_response = EncryptedPacket::new(&response.payload, encryption_ctx, true)?;
encrypted_response.write(stream)?;
info!("Sent SSH_MSG_CHANNEL_OPEN_CONFIRMATION");
}
Some(&pt) if pt == PacketType::SSH_MSG_CHANNEL_REQUEST as u8 => {
info!("Received SSH_MSG_CHANNEL_REQUEST");
if let Some(response) = channel_manager.handle_channel_request(&packet)? {
response.write(stream)?;
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);
}
}
}
}
Some(&pt) if pt == PacketType::SSH_MSG_CHANNEL_DATA as u8 => {
@@ -303,7 +334,10 @@ fn handle_ssh_service_loop(
}
Some(&pt) if pt == PacketType::SSH_MSG_CHANNEL_CLOSE as u8 => {
info!("Received SSH_MSG_CHANNEL_CLOSE");
channel_manager.handle_channel_close(&packet)?;
if let Some(response) = channel_manager.handle_channel_close(&packet)? {
let encrypted_response = EncryptedPacket::new(&response.payload, encryption_ctx, true)?;
encrypted_response.write(stream)?;
}
break;
}
Some(&pt) if pt == PacketType::SSH_MSG_DISCONNECT as u8 => {