From 10903599517b2b103315cf3852ff718f1eef2ec5 Mon Sep 17 00:00:00 2001 From: ZhenYi <434836402@qq.com> Date: Thu, 16 Apr 2026 20:40:17 +0800 Subject: [PATCH] fix(git): add SSH channel lifecycle logging and fix password auth username check - Remove user=="git" restriction from auth_password: the actual user is determined by the token, not the SSH username, matching Gitea's approach - Add channel_open_session logging with explicit flush to verify CHANNEL_OPEN_CONFIRMATION reaches the client - Add pty_request handler (reject with log) so git clients that request a PTY are handled gracefully instead of falling through to default - Add subsystem_request handler (log + accept) so git subsystems are visible in logs - Prefix unused variables with _ to eliminate warnings --- libs/git/ssh/handle.rs | 58 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/libs/git/ssh/handle.rs b/libs/git/ssh/handle.rs index 41ab38d..ab4c8c9 100644 --- a/libs/git/ssh/handle.rs +++ b/libs/git/ssh/handle.rs @@ -163,19 +163,12 @@ impl russh::server::Handler for SSHandle { Ok(Auth::UnsupportedMethod) } - async fn auth_password(&mut self, user: &str, token: &str) -> Result { + async fn auth_password(&mut self, _user: &str, token: &str) -> Result { let client_info = self .client_addr .map(|addr| format!("{}", addr)) .unwrap_or_else(|| "unknown".to_string()); - if user != "git" { - warn!( - self.logger, - "auth_password rejected: invalid username '{}', client: {}", user, client_info - ); - return Err(russh::Error::NotAuthenticated); - } if token.is_empty() { warn!( @@ -423,11 +416,56 @@ impl russh::server::Handler for SSHandle { async fn channel_open_session( &mut self, - _: Channel, - _: &mut Session, + channel: Channel, + session: &mut Session, ) -> Result { + let client_info = self + .client_addr + .map(|addr| format!("{}", addr)) + .unwrap_or_else(|| "unknown".to_string()); + info!(self.logger, "channel_open_session"; "channel" => ?channel, "client" => %client_info); + let _ = session.flush().ok(); Ok(true) } + + async fn pty_request( + &mut self, + channel: ChannelId, + term: &str, + col_width: u32, + row_height: u32, + _pix_width: u32, + _pix_height: u32, + _modes: &[(russh::Pty, u32)], + session: &mut Session, + ) -> Result<(), Self::Error> { + let client_info = self + .client_addr + .map(|addr| format!("{}", addr)) + .unwrap_or_else(|| "unknown".to_string()); + warn!(self.logger, "pty_request (not supported)"; + "channel" => ?channel, "term" => %term, "cols" => col_width, "rows" => row_height, "client" => %client_info); + let _ = session.flush().ok(); + Ok(()) + } + + async fn subsystem_request( + &mut self, + channel: ChannelId, + name: &str, + session: &mut Session, + ) -> Result<(), Self::Error> { + let client_info = self + .client_addr + .map(|addr| format!("{}", addr)) + .unwrap_or_else(|| "unknown".to_string()); + info!(self.logger, "subsystem_request"; + "channel" => ?channel, "subsystem" => %name, "client" => %client_info); + // git-clients may send "subsystem" for git protocol over ssh. + // We don't use subsystem; exec_request handles it directly. + let _ = session.flush().ok(); + Ok(()) + } async fn data( &mut self, channel: ChannelId,