use std::collections::HashMap; use std::net::SocketAddr; use std::sync::Arc; use russh::server::{Auth, Handler, Msg, Session}; use russh::{Channel, ChannelId}; use tokio::sync::OwnedSemaphorePermit; use uuid::Uuid; use models::users::user; use crate::ssh::handler::git_op::GitOperation; use crate::ssh::service::GitSshService; pub mod git_op; mod auth; mod channel; mod command; #[derive(Default)] pub struct ChannelState { pub buffer: Vec, pub git_op: Option, pub repo_id: Option, pub space_id: Option, pub actor_id: Option, pub buffer_overflow: bool, } pub struct GitSshHandler { pub service: Arc, pub client_addr: Option, pub session_permit: Option, pub operator: Option, pub channels: HashMap, pub over_capacity: bool, } impl GitSshHandler { pub fn new( service: Arc, client_addr: Option, session_permit: Option, ) -> Self { let over_capacity = session_permit.is_none(); Self { service, client_addr, session_permit, operator: None, channels: HashMap::new(), over_capacity, } } pub fn config(&self) -> &config::git::GitSshConfig { &self.service.config } } impl Handler for GitSshHandler { type Error = russh::Error; async fn auth_none(&mut self, _user: &str) -> Result { Ok(Auth::reject()) } async fn auth_password(&mut self, _user: &str, _password: &str) -> Result { Ok(Auth::reject()) } async fn auth_publickey_offered( &mut self, user: &str, public_key: &russh::keys::PublicKey, ) -> Result { self.auth_publickey_offered_impl(user, public_key).await } async fn auth_publickey( &mut self, user: &str, public_key: &russh::keys::PublicKey, ) -> Result { self.auth_publickey_impl(user, public_key).await } async fn auth_openssh_certificate( &mut self, _user: &str, _certificate: &russh::keys::Certificate, ) -> Result { Ok(Auth::reject()) } async fn authentication_banner(&mut self) -> Result, Self::Error> { Ok(self.config().banner.clone()) } async fn channel_open_session( &mut self, _channel: Channel, reply: russh::server::ChannelOpenHandle, _session: &mut Session, ) -> Result<(), Self::Error> { reply.accept().await; Ok(()) } async fn channel_close( &mut self, channel: ChannelId, _session: &mut Session, ) -> Result<(), Self::Error> { self.channel_close_impl(channel).await; Ok(()) } async fn channel_eof( &mut self, channel: ChannelId, session: &mut Session, ) -> Result<(), Self::Error> { self.channel_eof_impl(channel, session).await } async fn data( &mut self, channel: ChannelId, data: &[u8], session: &mut Session, ) -> Result<(), Self::Error> { self.data_impl(channel, data, session).await } async fn exec_request( &mut self, channel: ChannelId, data: &[u8], session: &mut Session, ) -> Result<(), Self::Error> { self.exec_request_impl(channel, data, session).await } 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 _ = session.flush(); Ok(()) } async fn shell_request( &mut self, channel: ChannelId, session: &mut Session, ) -> Result<(), Self::Error> { self.shell_request_impl(channel, session).await } async fn subsystem_request( &mut self, _channel: ChannelId, _name: &str, session: &mut Session, ) -> Result<(), Self::Error> { let _ = session.flush(); Ok(()) } async fn env_request( &mut self, _channel: ChannelId, _variable_name: &str, _variable_value: &str, session: &mut Session, ) -> Result<(), Self::Error> { let _ = session.flush(); Ok(()) } async fn window_change_request( &mut self, _channel: ChannelId, _col_width: u32, _row_height: u32, _pix_width: u32, _pix_height: u32, session: &mut Session, ) -> Result<(), Self::Error> { let _ = session.flush(); Ok(()) } }