diff --git a/russh/src/client/mod.rs b/russh/src/client/mod.rs index 8bb9e9c9..b2111d1a 100644 --- a/russh/src/client/mod.rs +++ b/russh/src/client/mod.rs @@ -697,6 +697,7 @@ where strict_kex: false, alive_timeouts: 0, received_data: false, + remote_sshid: sshid.into(), }, session_receiver, session_sender, diff --git a/russh/src/client/session.rs b/russh/src/client/session.rs index de387642..4c93d1ad 100644 --- a/russh/src/client/session.rs +++ b/russh/src/client/session.rs @@ -268,7 +268,7 @@ impl Session { /// Requests a TCP/IP forwarding from the server /// /// If `reply_channel` is not None, sets want_reply and returns the server's response via the channel, - /// Some for a success message with port, or None for failure + /// [`Some`] for a success message with port, or [`None`] for failure pub fn tcpip_forward( &mut self, reply_channel: Option>>, @@ -395,4 +395,17 @@ impl Session { 0 } } + + /// Returns the SSH ID (Protocol Version + Software Version) the server sent when connecting + /// + /// This should contain only ASCII characters for implementations conforming to RFC4253, Section 4.2: + /// + /// > Both the 'protoversion' and 'softwareversion' strings MUST consist of + /// > printable US-ASCII characters, with the exception of whitespace + /// > characters and the minus sign (-). + /// + /// So it usually is fine to convert it to a `String` using `String::from_utf8_lossy` + pub fn remote_sshid(&self) -> &[u8] { + &self.common.remote_sshid + } } diff --git a/russh/src/server/mod.rs b/russh/src/server/mod.rs index 4ae560fb..bc10d00c 100644 --- a/russh/src/server/mod.rs +++ b/russh/src/server/mod.rs @@ -16,7 +16,7 @@ //! # Writing servers //! //! There are two ways of accepting connections: -//! * implement the [Server](server::Server) trait and let [run](server::run) handle everything +//! * implement the [Server](server::Server) trait and let [run_on_socket](server::Server::run_on_socket)/[run_on_address](server::Server::run_on_address) handle everything //! * accept connections yourself and pass them to [run_stream](server::run_stream) //! //! In both cases, you'll first need to implement the [Handler](server::Handler) trait - @@ -731,6 +731,7 @@ async fn read_ssh_id( strict_kex: false, alive_timeouts: 0, received_data: false, + remote_sshid: sshid.into(), }) } diff --git a/russh/src/server/session.rs b/russh/src/server/session.rs index 0a333c5e..02fd4638 100644 --- a/russh/src/server/session.rs +++ b/russh/src/server/session.rs @@ -1028,6 +1028,19 @@ impl Session { } } + /// Returns the SSH ID (Protocol Version + Software Version) the client sent when connecting + /// + /// This should contain only ASCII characters for implementations conforming to RFC4253, Section 4.2: + /// + /// > Both the 'protoversion' and 'softwareversion' strings MUST consist of + /// > printable US-ASCII characters, with the exception of whitespace + /// > characters and the minus sign (-). + /// + /// So it usually is fine to convert it to a [`String`] using [`String::from_utf8_lossy`] + pub fn remote_sshid(&self) -> &[u8] { + &self.common.remote_sshid + } + pub(crate) fn maybe_send_ext_info(&mut self) { if let Some(ref mut enc) = self.common.encrypted { // If client sent a ext-info-c message in the kex list, it supports RFC 8308 extension negotiation. diff --git a/russh/src/session.rs b/russh/src/session.rs index b2ed54d4..c1958227 100644 --- a/russh/src/session.rs +++ b/russh/src/session.rs @@ -54,6 +54,7 @@ pub(crate) struct Encrypted { pub(crate) struct CommonSession { pub auth_user: String, + pub remote_sshid: Vec, pub config: Config, pub encrypted: Option, pub auth_method: Option,