Skip to content

Commit 5e91396

Browse files
authored
fixed #515 - unexpected pre-kex message causing panic (#516)
1 parent a404ae3 commit 5e91396

File tree

4 files changed

+60
-4
lines changed

4 files changed

+60
-4
lines changed

russh/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ tokio = { workspace = true, features = [
110110
"net",
111111
"sync",
112112
"macros",
113+
"process",
113114
] }
114115
rand = "0.8.5"
115116
shell-escape = "0.1"

russh/src/client/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ use std::convert::TryInto;
3939
use std::num::Wrapping;
4040
use std::pin::Pin;
4141
use std::sync::Arc;
42+
#[cfg(not(target_arch = "wasm32"))]
43+
use std::time::Duration;
4244

4345
use futures::task::{Context, Poll};
4446
use futures::Future;
@@ -47,8 +49,6 @@ use log::{debug, error, trace};
4749
use russh_util::time::Instant;
4850
use ssh_encoding::Decode;
4951
use ssh_key::{Algorithm, Certificate, HashAlg, PrivateKey, PublicKey};
50-
#[cfg(not(target_arch = "wasm32"))]
51-
use std::time::Duration;
5252
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt, ReadHalf, WriteHalf};
5353
use tokio::pin;
5454
use tokio::sync::mpsc::{

russh/src/server/encrypted.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,10 @@ impl Session {
6262
rejection_wait_until
6363
};
6464

65-
#[allow(clippy::unwrap_used)]
66-
let enc = self.common.encrypted.as_mut().unwrap();
65+
let Some(enc) = self.common.encrypted.as_mut() else {
66+
return Err(Error::Inconsistent.into());
67+
};
68+
6769
// If we've successfully read a packet.
6870
match (&mut enc.state, buf.split_first()) {
6971
(

russh/src/tests.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,3 +564,56 @@ mod channels {
564564
.await;
565565
}
566566
}
567+
568+
mod server_kex_junk {
569+
use std::sync::Arc;
570+
571+
use tokio::io::AsyncWriteExt;
572+
573+
use super::server::Server as _;
574+
use super::*;
575+
576+
#[tokio::test]
577+
async fn server_kex_junk_test() {
578+
let _ = env_logger::try_init();
579+
580+
let config = server::Config::default();
581+
let config = Arc::new(config);
582+
let mut sh = Server {};
583+
584+
let socket = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
585+
let addr = socket.local_addr().unwrap();
586+
587+
tokio::spawn(async move {
588+
let mut client_stream = tokio::net::TcpStream::connect(addr).await.unwrap();
589+
client_stream
590+
.write_all(b"SSH-2.0-Client_1.0\r\n")
591+
.await
592+
.unwrap();
593+
// Unexpected message pre-kex
594+
client_stream.write_all(&[0, 0, 0, 2, 0, 99]).await.unwrap();
595+
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
596+
});
597+
598+
let (socket, _) = socket.accept().await.unwrap();
599+
let server = sh.new_client(socket.peer_addr().ok());
600+
let rs = server::run_stream(config, socket, server).await.unwrap();
601+
602+
// May not panic
603+
assert!(rs.await.is_err());
604+
}
605+
606+
#[derive(Clone)]
607+
struct Server {}
608+
609+
impl server::Server for Server {
610+
type Handler = Self;
611+
fn new_client(&mut self, _: Option<std::net::SocketAddr>) -> Self {
612+
self.clone()
613+
}
614+
}
615+
616+
impl server::Handler for Server {
617+
type Error = super::Error;
618+
}
619+
}

0 commit comments

Comments
 (0)