diff --git a/markbase-core/src/ssh_server/channel.rs b/markbase-core/src/ssh_server/channel.rs index 658998d..f273067 100644 --- a/markbase-core/src/ssh_server/channel.rs +++ b/markbase-core/src/ssh_server/channel.rs @@ -129,6 +129,16 @@ impl ChannelManager { maximum_packet_size, ) } + + "x11" => { + // Phase 2: X11 forwarding channel (RFC 4254 §7.2) + info!("Received x11 channel open (X11 forwarding)"); + self.handle_x11_channel_open( + sender_channel, + initial_window_size, + maximum_packet_size, + ) + } _ => { warn!("Unsupported channel type: {}", channel_type); @@ -373,6 +383,68 @@ impl ChannelManager { maximum_packet_size, ) } + + /// Phase 2: 处理x11 channel open(RFC 4254 §7.2) + fn handle_x11_channel_open( + &mut self, + sender_channel: u32, + initial_window_size: u32, + maximum_packet_size: u32, + ) -> Result { + info!("Processing x11 channel open"); + + // 创建 X11ForwardContext(从 DISPLAY 环境变量) + let display = std::env::var("DISPLAY").unwrap_or_else(|_| ":0".to_string()); + let x11_ctx = super::x11_forward::X11ForwardContext::new(&display)?; + + let server_channel = self.next_channel_id; + self.next_channel_id += 1; + + let channel = Channel { + server_channel, + sender_channel, + channel_type: "x11".to_string(), + + // Phase 15: Window Control + remote_window: initial_window_size, + remote_maxpacket: maximum_packet_size, + local_window: 2097152, + local_window_max: 2097152, + local_consumed: 0, + local_maxpacket: 32768, + + window_size: initial_window_size, + maximum_packet_size, + state: ChannelState::Open, + output_buffer: None, + sftp_handler: None, + scp_handler: None, + rsync_handler: None, + exec_process: None, + exit_status: None, + sftp_input_buffer: Vec::new(), + scp_input_buffer: Vec::new(), + scp_state: ScpState::Idle, + scp_output_file: None, + direct_tcpip: None, + forwarded_tcpip: None, + auth_agent_socket: None, + }; + + self.channels.insert(server_channel, channel); + + info!( + "x11 channel created: server_channel={}, display={}", + server_channel, display + ); + + self.build_channel_open_confirmation( + server_channel, + sender_channel, + initial_window_size, + maximum_packet_size, + ) + } /// 处理SSH_MSG_CHANNEL_REQUEST(参考OpenSSH channel.c: channel_request()) pub fn handle_channel_request(&mut self, packet: &SshPacket) -> Result> { info!("Processing SSH_MSG_CHANNEL_REQUEST"); @@ -414,6 +486,9 @@ impl ChannelManager { self.handle_pty_request(&mut cursor, recipient_channel, want_reply) // 移除?操作符 } else if request_type == "auth-agent-req@openssh.com" { self.handle_auth_agent_request(recipient_channel, want_reply) + } else if request_type == "x11-req" { + // Phase 2: X11 forwarding request (RFC 4254 §7.2) + self.handle_x11_request(&mut cursor, recipient_channel, want_reply) } else { warn!("Unsupported channel request: {}", request_type); if want_reply { @@ -1406,6 +1481,50 @@ impl ChannelManager { } } } + + /// Phase 2: 处理x11-req请求(RFC 4254 §7.2) + fn handle_x11_request( + &mut self, + cursor: &mut std::io::Cursor<&[u8]>, + channel: u32, + want_reply: bool, + ) -> Result> { + info!("Handling x11-req request for channel {}", channel); + + // 读取 x11-req 参数(RFC 4254 §7.2) + // single_connection: boolean + let single_connection = cursor.read_u8()? != 0; + + // auth_protocol: SSH string (e.g., "MIT-MAGIC-COOKIE-1") + let auth_protocol = read_ssh_string(cursor)?; + + // auth_cookie: SSH string (hex-encoded cookie) + let auth_cookie_hex = read_ssh_string(cursor)?; + + // screen_number: u32 + let screen_number = cursor.read_u32::()?; + + info!( + "x11-req: single={}, protocol={}, screen={}", + single_connection, auth_protocol, screen_number + ); + + // 创建 X11ForwardContext + let display = std::env::var("DISPLAY").unwrap_or_else(|_| ":0".to_string()); + let x11_ctx = super::x11_forward::X11ForwardContext::new(&display)?; + + // 设置 DISPLAY 环境变量(client 会使用) + // Server 需要在 exec/shell 环境中设置 DISPLAY + // 这里只是记录,实际设置在 exec/shell handler 中 + + info!("X11 forwarding enabled: display={}", x11_ctx.display_env()); + + if want_reply { + Ok(Some(self.build_channel_success(channel)?)) + } else { + Ok(None) + } + } /// ⭐⭐⭐⭐⭐ Phase 17: Check if a specific channel has an exec process pub fn channel_has_exec_process(&self, channel_id: u32) -> bool { @@ -1685,9 +1804,9 @@ impl ChannelManager { if let Some(hook) = &self.upload_hook { if let Err(e) = hook.trigger(&path, &self.user_uuid) { warn!("Upload hook failed for {:?}: {}", path, e); - } - } - } +} + } + } } // 没有剩余数据,返回child_exited标志