-
-
Notifications
You must be signed in to change notification settings - Fork 289
Expand file tree
/
Copy pathtest.rs
More file actions
168 lines (140 loc) · 5.23 KB
/
Copy pathtest.rs
File metadata and controls
168 lines (140 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use log::debug;
use ssh_key::PrivateKey;
use tokio::net::TcpListener;
use crate::cert::PublicKeyOrCertificate;
// Import client types directly since we're in the client module
use crate::Error;
use crate::client::{Config, Handler, connect};
use crate::keys::PrivateKeyWithHashAlg;
use crate::server::{self, Auth, Handler as ServerHandler, Server, Session};
use crate::{ChannelId, SshId}; // Import directly from crate root
use rand::rng;
#[derive(Clone)]
struct TestServer {
clients: Arc<Mutex<HashMap<(usize, ChannelId), server::Handle>>>,
id: usize,
}
impl server::Server for TestServer {
type Handler = Self;
fn new_client(&mut self, _: Option<std::net::SocketAddr>) -> Self {
let s = self.clone();
self.id += 1;
s
}
}
impl ServerHandler for TestServer {
type Error = Error;
type Data = ();
async fn channel_open_session(
&mut self,
channel: crate::channels::Channel<server::Msg>,
reply: server::ChannelOpenHandle,
session: &mut Session,
) -> Result<(), Self::Error> {
{
let mut clients = self.clients.lock().unwrap();
clients.insert((self.id, channel.id()), session.handle());
}
reply.accept().await;
Ok(())
}
async fn auth_publickey(
&mut self,
_: &str,
_: &ssh_key::PublicKey,
) -> Result<Auth, Self::Error> {
debug!("auth_publickey");
Ok(Auth::Accept)
}
async fn data(
&mut self,
channel: ChannelId,
data: &[u8],
session: &mut Session,
) -> Result<(), Self::Error> {
debug!("server received data: {:?}", std::str::from_utf8(data));
session.data(channel, data.to_vec())?;
Ok(())
}
}
struct Client {}
impl Handler for Client {
type Error = Error;
async fn check_server_key(
&mut self,
_: &PublicKeyOrCertificate,
) -> Result<bool, Self::Error> {
Ok(true)
}
}
#[tokio::test]
async fn test_client_connects_to_protocol_1_99() {
let _ = env_logger::try_init();
// Create a client key
let client_key = PrivateKey::random(&mut rng(), ssh_key::Algorithm::Ed25519).unwrap();
// Configure the server
let mut config = server::Config::default();
config.auth_rejection_time = std::time::Duration::from_secs(1);
config.server_id = SshId::Standard("SSH-1.99-CustomServer_1.0".into());
config.inactivity_timeout = None;
config
.keys
.push(PrivateKey::random(&mut rng(), ssh_key::Algorithm::Ed25519).unwrap());
let config = Arc::new(config);
// Create server struct
let mut server = TestServer {
clients: Arc::new(Mutex::new(HashMap::new())),
id: 0,
};
// Start the TCP listener for our mock server
let socket = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = socket.local_addr().unwrap();
// Spawn a separate task that will handle the server connection
tokio::spawn(async move {
// Accept a connection
let (socket, _) = socket.accept().await.unwrap();
// Handle the connection with the server
let server_handler = server.new_client(None);
server::run_stream(config, socket, server_handler)
.await
.unwrap();
});
println!("Server listening on {addr}");
// Configure the client
let client_config = Arc::new(Config::default());
// Connect to the server
let mut session = connect(client_config, addr, Client {}).await.unwrap();
// Unfortunately, we can't directly verify the protocol version from the client API
// The Protocol199Stream wrapper ensures the server sends SSH-1.99-CustomServer_1.0
// The test passing means the client accepted this protocol version
// Try to authenticate
let auth_result = session
.authenticate_publickey(
std::env::var("USER").unwrap_or("user".to_string()),
PrivateKeyWithHashAlg::new(
Arc::new(client_key),
session.best_supported_rsa_hash().await.unwrap().flatten(),
),
)
.await
.unwrap();
assert!(auth_result.success());
// Try opening a session channel
let mut channel = session.channel_open_session().await.unwrap();
// Send some data
let test_data = b"Hello, 1.99 protocol server!";
channel.data(&test_data[..]).await.unwrap();
// Wait for response
let msg = channel.wait().await.unwrap();
match msg {
crate::channels::ChannelMsg::Data { data: msg_data } => {
assert_eq!(test_data.as_slice(), &msg_data[..]);
}
msg => panic!("Unexpected message {msg:?}"),
}
}
}