1 // Copyright 2016 Pierre-Étienne Meunier
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 
16 //! Server and client SSH asynchronous library, based on tokio/futures.
17 //!
18 //! The normal way to use this library, both for clients and for
19 //! servers, is by creating *handlers*, i.e. types that implement
20 //! `client::Handler` for clients and `server::Handler` for
21 //! servers.
22 //!
23 //! # Writing servers
24 //!
25 //! In the specific case of servers, a server must implement
26 //! `server::Server`, a trait for creating new `server::Handler`.  The
27 //! main type to look at in the `server` module is `Session` (and
28 //! `Config`, of course).
29 //!
30 //! Here is an example server, which forwards input from each client
31 //! to all other clients:
32 //!
33 //! ```
34 //! extern crate thrussh;
35 //! extern crate thrussh_keys;
36 //! extern crate futures;
37 //! extern crate tokio;
38 //! use std::sync::{Mutex, Arc};
39 //! use thrussh::*;
40 //! use thrussh::server::{Auth, Session};
41 //! use thrussh_keys::*;
42 //! use std::collections::HashMap;
43 //! use futures::Future;
44 //!
45 //! #[tokio::main]
46 //! async fn main() {
47 //!     let client_key = thrussh_keys::key::KeyPair::generate_ed25519().unwrap();
48 //!     let client_pubkey = Arc::new(client_key.clone_public_key());
49 //!     let mut config = thrussh::server::Config::default();
50 //!     config.connection_timeout = Some(std::time::Duration::from_secs(3));
51 //!     config.auth_rejection_time = std::time::Duration::from_secs(3);
52 //!     config.keys.push(thrussh_keys::key::KeyPair::generate_ed25519().unwrap());
53 //!     let config = Arc::new(config);
54 //!     let sh = Server{
55 //!         client_pubkey,
56 //!         clients: Arc::new(Mutex::new(HashMap::new())),
57 //!         id: 0
58 //!     };
59 //!     tokio::time::timeout(
60 //!        std::time::Duration::from_secs(1),
61 //!        thrussh::server::run(config, "0.0.0.0:2222", sh)
62 //!     ).await.unwrap_or(Ok(()));
63 //! }
64 //!
65 //! #[derive(Clone)]
66 //! struct Server {
67 //!     client_pubkey: Arc<thrussh_keys::key::PublicKey>,
68 //!     clients: Arc<Mutex<HashMap<(usize, ChannelId), thrussh::server::Handle>>>,
69 //!     id: usize,
70 //! }
71 //!
72 //! impl server::Server for Server {
73 //!     type Handler = Self;
74 //!     fn new(&mut self, _: Option<std::net::SocketAddr>) -> Self {
75 //!         let s = self.clone();
76 //!         self.id += 1;
77 //!         s
78 //!     }
79 //! }
80 //!
81 //! impl server::Handler for Server {
82 //!     type Error = anyhow::Error;
83 //!     type FutureAuth = futures::future::Ready<Result<(Self, server::Auth), anyhow::Error>>;
84 //!     type FutureUnit = futures::future::Ready<Result<(Self, Session), anyhow::Error>>;
85 //!     type FutureBool = futures::future::Ready<Result<(Self, Session, bool), anyhow::Error>>;
86 //!
87 //!     fn finished_auth(mut self, auth: Auth) -> Self::FutureAuth {
88 //!         futures::future::ready(Ok((self, auth)))
89 //!     }
90 //!     fn finished_bool(self, b: bool, s: Session) -> Self::FutureBool {
91 //!         futures::future::ready(Ok((self, s, b)))
92 //!     }
93 //!     fn finished(self, s: Session) -> Self::FutureUnit {
94 //!         futures::future::ready(Ok((self, s)))
95 //!     }
96 //!     fn channel_open_session(self, channel: ChannelId, session: Session) -> Self::FutureUnit {
97 //!         {
98 //!             let mut clients = self.clients.lock().unwrap();
99 //!             clients.insert((self.id, channel), session.handle());
100 //!         }
101 //!         self.finished(session)
102 //!     }
103 //!     fn auth_publickey(self, _: &str, _: &key::PublicKey) -> Self::FutureAuth {
104 //!         self.finished_auth(server::Auth::Accept)
105 //!     }
106 //!     fn data(self, channel: ChannelId, data: &[u8], mut session: Session) -> Self::FutureUnit {
107 //!         {
108 //!             let mut clients = self.clients.lock().unwrap();
109 //!             for ((id, channel), ref mut s) in clients.iter_mut() {
110 //!                 if *id != self.id {
111 //!                     s.data(*channel, CryptoVec::from_slice(data));
112 //!                 }
113 //!             }
114 //!         }
115 //!         session.data(channel, CryptoVec::from_slice(data));
116 //!         self.finished(session)
117 //!     }
118 //! }
119 //! ```
120 //!
121 //! Note the call to `session.handle()`, which allows to keep a handle
122 //! to a client outside the event loop. This feature is internally
123 //! implemented using `futures::sync::mpsc` channels.
124 //!
125 //! Note that this is just a toy server. In particular:
126 //!
127 //! - It doesn't handle errors when `s.data` returns an error,
128 //!   i.e. when the client has disappeared
129 //!
130 //! - Each new connection increments the `id` field. Even though we
131 //! would need a lot of connections per second for a very long time to
132 //! saturate it, there are probably better ways to handle this to
133 //! avoid collisions.
134 //!
135 //!
136 //! # Implementing clients
137 //!
138 //! Maybe surprisingly, the data types used by Thrussh to implement
139 //! clients are relatively more complicated than for servers. This is
140 //! mostly related to the fact that clients are generally used both in
141 //! a synchronous way (in the case of SSH, we can think of sending a
142 //! shell command), and asynchronously (because the server may send
143 //! unsollicited messages), and hence need to handle multiple
144 //! interfaces.
145 //!
146 //! The important types in the `client` module are `Session` and
147 //! `Connection`. A `Connection` is typically used to send commands to
148 //! the server and wait for responses, and contains a `Session`. The
149 //! `Session` is passed to the `Handler` when the client receives
150 //! data.
151 //!
152 //! ```
153 //!extern crate thrussh;
154 //!extern crate thrussh_keys;
155 //!extern crate futures;
156 //!extern crate tokio;
157 //!extern crate env_logger;
158 //!use std::sync::Arc;
159 //!use thrussh::*;
160 //!use thrussh::server::{Auth, Session};
161 //!use thrussh_keys::*;
162 //!use futures::Future;
163 //!use std::io::Read;
164 //!
165 //!
166 //!struct Client {
167 //!}
168 //!
169 //!impl client::Handler for Client {
170 //!    type Error = anyhow::Error;
171 //!    type FutureUnit = futures::future::Ready<Result<(Self, client::Session), anyhow::Error>>;
172 //!    type FutureBool = futures::future::Ready<Result<(Self, bool), anyhow::Error>>;
173 //!
174 //!    fn finished_bool(self, b: bool) -> Self::FutureBool {
175 //!        futures::future::ready(Ok((self, b)))
176 //!    }
177 //!    fn finished(self, session: client::Session) -> Self::FutureUnit {
178 //!        futures::future::ready(Ok((self, session)))
179 //!    }
180 //!    fn check_server_key(self, server_public_key: &key::PublicKey) -> Self::FutureBool {
181 //!        println!("check_server_key: {:?}", server_public_key);
182 //!        self.finished_bool(true)
183 //!    }
184 //!    fn channel_open_confirmation(self, channel: ChannelId, max_packet_size: u32, window_size: u32, session: client::Session) -> Self::FutureUnit {
185 //!        println!("channel_open_confirmation: {:?}", channel);
186 //!        self.finished(session)
187 //!    }
188 //!    fn data(self, channel: ChannelId, data: &[u8], session: client::Session) -> Self::FutureUnit {
189 //!        println!("data on channel {:?}: {:?}", channel, std::str::from_utf8(data));
190 //!        self.finished(session)
191 //!    }
192 //!}
193 //!
194 //! #[tokio::main]
195 //! async fn main() {
196 //!   let config = thrussh::client::Config::default();
197 //!   let config = Arc::new(config);
198 //!   let sh = Client{};
199 //!
200 //!   let key = thrussh_keys::key::KeyPair::generate_ed25519().unwrap();
201 //!   let mut agent = thrussh_keys::agent::client::AgentClient::connect_env().await.unwrap();
202 //!   agent.add_identity(&key, &[]).await.unwrap();
203 //!   let mut session = thrussh::client::connect(config, "localhost:22", sh).await.unwrap();
204 //!   if session.authenticate_future(std::env::var("USER").unwrap(), key.clone_public_key(), agent).await.1.unwrap() {
205 //!     let mut channel = session.channel_open_session().await.unwrap();
206 //!     channel.data(&b"Hello, world!"[..]).await.unwrap();
207 //!     if let Some(msg) = channel.wait().await {
208 //!         println!("{:?}", msg)
209 //!     }
210 //!   }
211 //! }
212 //! ```
213 //! # Using non-socket IO / writing tunnels
214 //!
215 //! The easy way to implement SSH tunnels, like `ProxyCommand` for
216 //! OpenSSH, is to use the `thrussh-config` crate, and use the
217 //! `Stream::tcp_connect` or `Stream::proxy_command` methods of that
218 //! crate. That crate is a very lightweight layer above Thrussh, only
219 //! implementing for external commands the traits used for sockets.
220 //!
221 //! # The SSH protocol
222 //!
223 //! If we exclude the key exchange and authentication phases, handled
224 //! by Thrussh behind the scenes, the rest of the SSH protocol is
225 //! relatively simple: clients and servers open *channels*, which are
226 //! just integers used to handle multiple requests in parallel in a
227 //! single connection. Once a client has obtained a `ChannelId` by
228 //! calling one the many `channel_open_…` methods of
229 //! `client::Connection`, the client may send exec requests and data
230 //! to the server.
231 //!
232 //! A simple client just asking the server to run one command will
233 //! usually start by calling
234 //! `client::Connection::channel_open_session`, then
235 //! `client::Connection::exec`, then possibly
236 //! `client::Connection::data` a number of times to send data to the
237 //! command's standard input, and finally `Connection::channel_eof`
238 //! and `Connection::channel_close`.
239 //!
240 //! # Design principles
241 //!
242 //! The main goal of this library is conciseness, and reduced size and
243 //! readability of the library's code. Moreover, this library is split
244 //! between Thrussh, which implements the main logic of SSH clients
245 //! and servers, and Thrussh-keys, which implements calls to
246 //! cryptographic primitives.
247 //!
248 //! One non-goal is to implement all possible cryptographic algorithms
249 //! published since the initial release of SSH. Technical debt is
250 //! easily acquired, and we would need a very strong reason to go
251 //! against this principle. If you are designing a system from
252 //! scratch, we urge you to consider recent cryptographic primitives
253 //! such as Ed25519 for public key cryptography, and Chacha20-Poly1305
254 //! for symmetric cryptography and MAC.
255 //!
256 //! # Internal details of the event loop
257 //!
258 //! It might seem a little odd that the read/write methods for server
259 //! or client sessions often return neither `Result` nor
260 //! `Future`. This is because the data sent to the remote side is
261 //! buffered, because it needs to be encrypted first, and encryption
262 //! works on buffers, and for many algorithms, not in place.
263 //!
264 //! Hence, the event loop keeps waiting for incoming packets, reacts
265 //! to them by calling the provided `Handler`, which fills some
266 //! buffers. If the buffers are non-empty, the event loop then sends
267 //! them to the socket, flushes the socket, empties the buffers and
268 //! starts again. In the special case of the server, unsollicited
269 //! messages sent through a `server::Handle` are processed when there
270 //! is no incoming packet to read.
271 //!
272 #[macro_use]
273 extern crate bitflags;
274 #[macro_use]
275 extern crate log;
276 extern crate thrussh_libsodium as sodium;
277 #[macro_use]
278 extern crate thiserror;
279 
280 pub use cryptovec::CryptoVec;
281 mod auth;
282 mod cipher;
283 mod compression;
284 mod kex;
285 mod key;
286 mod msg;
287 mod negotiation;
288 mod ssh_read;
289 mod sshbuffer;
290 
291 pub use negotiation::{Named, Preferred};
292 mod pty;
293 pub use pty::Pty;
294 
295 macro_rules! push_packet {
296     ( $buffer:expr, $x:expr ) => {{
297         use byteorder::{BigEndian, ByteOrder};
298         let i0 = $buffer.len();
299         $buffer.extend(b"\0\0\0\0");
300         let x = $x;
301         let i1 = $buffer.len();
302         use std::ops::DerefMut;
303         let buf = $buffer.deref_mut();
304         BigEndian::write_u32(&mut buf[i0..], (i1 - i0 - 4) as u32);
305         x
306     }};
307 }
308 
309 type Sha256Hash = generic_array::GenericArray<u8, <sha2::Sha256 as digest::FixedOutputDirty>::OutputSize>;
310 
311 mod session;
312 
313 /// Server side of this library.
314 pub mod server;
315 
316 /// Client side of this library.
317 pub mod client;
318 
319 #[derive(Debug, Error)]
320 pub enum Error {
321     /// The key file could not be parsed.
322     #[error("Could not read key")]
323     CouldNotReadKey,
324 
325     /// Unspecified problem with the beginning of key exchange.
326     #[error("Key exchange init failed")]
327     KexInit,
328 
329     /// No common key exchange algorithm.
330     #[error("No common key exchange algorithm")]
331     NoCommonKexAlgo,
332 
333     /// No common signature algorithm.
334     #[error("No common key algorithm")]
335     NoCommonKeyAlgo,
336 
337     /// No common cipher.
338     #[error("No common key cipher")]
339     NoCommonCipher,
340 
341     /// No common compression algorithm.
342     #[error("No common compression algorithm")]
343     NoCommonCompression,
344 
345     /// Invalid SSH version string.
346     #[error("invalid SSH version string")]
347     Version,
348 
349     /// Error during key exchange.
350     #[error("Key exchange failed")]
351     Kex,
352 
353     /// Invalid packet authentication code.
354     #[error("Wrong packet authentication code")]
355     PacketAuth,
356 
357     /// The protocol is in an inconsistent state.
358     #[error("Inconsistent state of the protocol")]
359     Inconsistent,
360 
361     /// The client is not yet authenticated.
362     #[error("Not yet authenticated")]
363     NotAuthenticated,
364 
365     /// Index out of bounds.
366     #[error("Index out of bounds")]
367     IndexOutOfBounds,
368 
369     /// Unknown server key.
370     #[error("Unknown server key")]
371     UnknownKey,
372 
373     /// The server provided a wrong signature.
374     #[error("Wrong server signature")]
375     WrongServerSig,
376 
377     /// Message received/sent on unopened channel.
378     #[error("Channel not open")]
379     WrongChannel,
380 
381     /// Disconnected
382     #[error("Disconnected")]
383     Disconnect,
384 
385     /// No home directory found when trying to learn new host key.
386     #[error("No home directory when saving host key")]
387     NoHomeDir,
388 
389     /// Remote key changed, this could mean a man-in-the-middle attack
390     /// is being performed on the connection.
391     #[error("Key changed, line {}", line)]
392     KeyChanged { line: usize },
393 
394     /// Connection closed by the remote side.
395     #[error("Connection closed by the remote side")]
396     HUP,
397 
398     /// Connection timeout.
399     #[error("Connection timeout")]
400     ConnectionTimeout,
401 
402     /// Missing authentication method.
403     #[error("No authentication method")]
404     NoAuthMethod,
405 
406     #[error("Channel send error")]
407     SendError,
408 
409     #[error("Pending buffer limit reached")]
410     Pending,
411 
412     #[error(transparent)]
413     Keys(#[from] thrussh_keys::Error),
414 
415     #[error(transparent)]
416     IO(#[from] std::io::Error),
417 
418     #[error(transparent)]
419     Utf8(#[from] std::str::Utf8Error),
420 
421     #[error(transparent)]
422     Compress(#[from] flate2::CompressError),
423 
424     #[error(transparent)]
425     Decompress(#[from] flate2::DecompressError),
426 
427     #[error(transparent)]
428     Join(#[from] tokio::task::JoinError),
429 
430     #[error(transparent)]
431     #[cfg(feature = "openssl")]
432     Openssl(#[from] openssl::error::ErrorStack),
433 
434     #[error(transparent)]
435     Elapsed(#[from] tokio::time::error::Elapsed),
436 }
437 
438 #[derive(Debug, Error)]
439 #[error("Could not reach the event loop")]
440 pub struct SendError {}
441 
442 /// Since handlers are large, their associated future types must implement this trait to provide reasonable default implementations (basically, rejecting all requests).
443 pub trait FromFinished<T>: futures::Future<Output = Result<T, Error>> {
444     /// Turns type `T` into `Self`, a future yielding `T`.
finished(t: T) -> Self445     fn finished(t: T) -> Self;
446 }
447 
448 impl<T> FromFinished<T> for futures::future::Ready<Result<T, Error>> {
finished(t: T) -> Self449     fn finished(t: T) -> Self {
450         futures::future::ready(Ok(t))
451     }
452 }
453 
454 impl<T: 'static> FromFinished<T> for Box<dyn futures::Future<Output = Result<T, Error>> + Unpin> {
finished(t: T) -> Self455     fn finished(t: T) -> Self {
456         Box::new(futures::future::ready(Ok(t)))
457     }
458 }
459 
460 // mod mac;
461 // use mac::*;
462 // mod compression;
463 
464 /// The number of bytes read/written, and the number of seconds before a key re-exchange is requested.
465 #[derive(Debug, Clone)]
466 pub struct Limits {
467     pub rekey_write_limit: usize,
468     pub rekey_read_limit: usize,
469     pub rekey_time_limit: std::time::Duration,
470 }
471 
472 impl Limits {
473     /// Create a new `Limits`, checking that the given bounds cannot lead to nonce reuse.
new(write_limit: usize, read_limit: usize, time_limit: std::time::Duration) -> Limits474     pub fn new(write_limit: usize, read_limit: usize, time_limit: std::time::Duration) -> Limits {
475         assert!(write_limit <= 1 << 30 && read_limit <= 1 << 30);
476         Limits {
477             rekey_write_limit: write_limit,
478             rekey_read_limit: read_limit,
479             rekey_time_limit: time_limit,
480         }
481     }
482 }
483 
484 impl Default for Limits {
default() -> Self485     fn default() -> Self {
486         // Following the recommendations of
487         // https://tools.ietf.org/html/rfc4253#section-9
488         Limits {
489             rekey_write_limit: 1 << 30, // 1 Gb
490             rekey_read_limit: 1 << 30,  // 1 Gb
491             rekey_time_limit: std::time::Duration::from_secs(3600),
492         }
493     }
494 }
495 
496 pub use auth::{AgentAuthError, MethodSet, Signer};
497 
498 /// A reason for disconnection.
499 #[allow(missing_docs)] // This should be relatively self-explanatory.
500 #[derive(Debug)]
501 pub enum Disconnect {
502     HostNotAllowedToConnect = 1,
503     ProtocolError = 2,
504     KeyExchangeFailed = 3,
505     #[doc(hidden)]
506     Reserved = 4,
507     MACError = 5,
508     CompressionError = 6,
509     ServiceNotAvailable = 7,
510     ProtocolVersionNotSupported = 8,
511     HostKeyNotVerifiable = 9,
512     ConnectionLost = 10,
513     ByApplication = 11,
514     TooManyConnections = 12,
515     AuthCancelledByUser = 13,
516     NoMoreAuthMethodsAvailable = 14,
517     IllegalUserName = 15,
518 }
519 
520 /// The type of signals that can be sent to a remote process. If you
521 /// plan to use custom signals, read [the
522 /// RFC](https://tools.ietf.org/html/rfc4254#section-6.10) to
523 /// understand the encoding.
524 #[allow(missing_docs)]
525 // This should be relatively self-explanatory.
526 #[derive(Debug, Clone)]
527 pub enum Sig {
528     ABRT,
529     ALRM,
530     FPE,
531     HUP,
532     ILL,
533     INT,
534     KILL,
535     PIPE,
536     QUIT,
537     SEGV,
538     TERM,
539     USR1,
540     Custom(String),
541 }
542 
543 impl Sig {
name(&self) -> &str544     fn name(&self) -> &str {
545         match *self {
546             Sig::ABRT => "ABRT",
547             Sig::ALRM => "ALRM",
548             Sig::FPE => "FPE",
549             Sig::HUP => "HUP",
550             Sig::ILL => "ILL",
551             Sig::INT => "INT",
552             Sig::KILL => "KILL",
553             Sig::PIPE => "PIPE",
554             Sig::QUIT => "QUIT",
555             Sig::SEGV => "SEGV",
556             Sig::TERM => "TERM",
557             Sig::USR1 => "USR1",
558             Sig::Custom(ref c) => c,
559         }
560     }
from_name(name: &[u8]) -> Result<Sig, Error>561     fn from_name(name: &[u8]) -> Result<Sig, Error> {
562         match name {
563             b"ABRT" => Ok(Sig::ABRT),
564             b"ALRM" => Ok(Sig::ALRM),
565             b"FPE" => Ok(Sig::FPE),
566             b"HUP" => Ok(Sig::HUP),
567             b"ILL" => Ok(Sig::ILL),
568             b"INT" => Ok(Sig::INT),
569             b"KILL" => Ok(Sig::KILL),
570             b"PIPE" => Ok(Sig::PIPE),
571             b"QUIT" => Ok(Sig::QUIT),
572             b"SEGV" => Ok(Sig::SEGV),
573             b"TERM" => Ok(Sig::TERM),
574             b"USR1" => Ok(Sig::USR1),
575             x => Ok(Sig::Custom(std::str::from_utf8(x)?.to_string())),
576         }
577     }
578 }
579 
580 /// Reason for not being able to open a channel.
581 #[derive(Debug, Copy, Clone, PartialEq)]
582 #[allow(missing_docs)]
583 pub enum ChannelOpenFailure {
584     AdministrativelyProhibited = 1,
585     ConnectFailed = 2,
586     UnknownChannelType = 3,
587     ResourceShortage = 4,
588 }
589 
590 impl ChannelOpenFailure {
from_u32(x: u32) -> Option<ChannelOpenFailure>591     fn from_u32(x: u32) -> Option<ChannelOpenFailure> {
592         match x {
593             1 => Some(ChannelOpenFailure::AdministrativelyProhibited),
594             2 => Some(ChannelOpenFailure::ConnectFailed),
595             3 => Some(ChannelOpenFailure::UnknownChannelType),
596             4 => Some(ChannelOpenFailure::ResourceShortage),
597             _ => None,
598         }
599     }
600 }
601 
602 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
603 /// The identifier of a channel.
604 pub struct ChannelId(u32);
605 
606 /// The parameters of a channel.
607 #[derive(Debug)]
608 pub(crate) struct Channel {
609     recipient_channel: u32,
610     sender_channel: ChannelId,
611     recipient_window_size: u32,
612     sender_window_size: u32,
613     recipient_maximum_packet_size: u32,
614     sender_maximum_packet_size: u32,
615     /// Has the other side confirmed the channel?
616     pub confirmed: bool,
617     wants_reply: bool,
618     pending_data: std::collections::VecDeque<(CryptoVec, Option<u32>, usize)>,
619 }
620 
621 #[derive(Debug)]
622 pub enum ChannelMsg {
623     Data {
624         data: CryptoVec,
625     },
626     ExtendedData {
627         data: CryptoVec,
628         ext: u32,
629     },
630     Eof,
631     Close,
632     XonXoff {
633         client_can_do: bool,
634     },
635     ExitStatus {
636         exit_status: u32,
637     },
638     ExitSignal {
639         signal_name: Sig,
640         core_dumped: bool,
641         error_message: String,
642         lang_tag: String,
643     },
644     WindowAdjusted {
645         new_size: u32,
646     },
647     Success,
648 }
649 
650 #[cfg(test)]
651 mod test_compress {
652     use super::server::{Auth, Server as _, Session};
653     use super::*;
654     use std::collections::HashMap;
655     use std::sync::{Arc, Mutex};
656 
657     #[tokio::test]
compress_local_test()658     async fn compress_local_test() {
659         let _ = env_logger::try_init();
660 
661         let client_key = thrussh_keys::key::KeyPair::generate_ed25519().unwrap();
662         let client_pubkey = Arc::new(client_key.clone_public_key());
663         let mut config = server::Config::default();
664         config.preferred = Preferred::COMPRESSED;
665         config.connection_timeout = None; // Some(std::time::Duration::from_secs(3));
666         config.auth_rejection_time = std::time::Duration::from_secs(3);
667         config
668             .keys
669             .push(thrussh_keys::key::KeyPair::generate_ed25519().unwrap());
670         let config = Arc::new(config);
671         let mut sh = Server {
672             client_pubkey,
673             clients: Arc::new(Mutex::new(HashMap::new())),
674             id: 0,
675         };
676 
677         let socket = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
678         let addr = socket.local_addr().unwrap();
679 
680         tokio::spawn(async move {
681             let (socket, _) = socket.accept().await.unwrap();
682             let server = sh.new(socket.peer_addr().ok());
683             server::run_stream(config, socket, server).await.unwrap();
684         });
685 
686         let mut config = client::Config::default();
687         config.preferred = Preferred::COMPRESSED;
688         let config = Arc::new(config);
689 
690         dbg!(&addr);
691         let mut session = client::connect(config, addr, Client {}).await.unwrap();
692         let authenticated = session
693             .authenticate_publickey(std::env::var("USER").unwrap(), Arc::new(client_key))
694             .await
695             .unwrap();
696         assert!(authenticated);
697         let mut channel = session.channel_open_session().await.unwrap();
698 
699         let data = &b"Hello, world!"[..];
700         channel.data(data).await.unwrap();
701         let msg = channel.wait().await.unwrap();
702         match msg {
703             ChannelMsg::Data { data: msg_data } => {
704                 assert_eq!(*data, *msg_data)
705             }
706             msg => panic!("Unexpected message {:?}", msg),
707         }
708     }
709 
710     #[derive(Clone)]
711     struct Server {
712         client_pubkey: Arc<thrussh_keys::key::PublicKey>,
713         clients: Arc<Mutex<HashMap<(usize, ChannelId), super::server::Handle>>>,
714         id: usize,
715     }
716 
717     impl server::Server for Server {
718         type Handler = Self;
new(&mut self, _: Option<std::net::SocketAddr>) -> Self719         fn new(&mut self, _: Option<std::net::SocketAddr>) -> Self {
720             let s = self.clone();
721             self.id += 1;
722             s
723         }
724     }
725 
726     impl server::Handler for Server {
727         type Error = super::Error;
728         type FutureAuth = futures::future::Ready<Result<(Self, server::Auth), Self::Error>>;
729         type FutureUnit = futures::future::Ready<Result<(Self, Session), Self::Error>>;
730         type FutureBool = futures::future::Ready<Result<(Self, Session, bool), Self::Error>>;
731 
finished_auth(self, auth: Auth) -> Self::FutureAuth732         fn finished_auth(self, auth: Auth) -> Self::FutureAuth {
733             futures::future::ready(Ok((self, auth)))
734         }
finished_bool(self, b: bool, s: Session) -> Self::FutureBool735         fn finished_bool(self, b: bool, s: Session) -> Self::FutureBool {
736             futures::future::ready(Ok((self, s, b)))
737         }
finished(self, s: Session) -> Self::FutureUnit738         fn finished(self, s: Session) -> Self::FutureUnit {
739             futures::future::ready(Ok((self, s)))
740         }
channel_open_session(self, channel: ChannelId, session: Session) -> Self::FutureUnit741         fn channel_open_session(self, channel: ChannelId, session: Session) -> Self::FutureUnit {
742             {
743                 let mut clients = self.clients.lock().unwrap();
744                 clients.insert((self.id, channel), session.handle());
745             }
746             self.finished(session)
747         }
auth_publickey(self, _: &str, _: &thrussh_keys::key::PublicKey) -> Self::FutureAuth748         fn auth_publickey(self, _: &str, _: &thrussh_keys::key::PublicKey) -> Self::FutureAuth {
749             debug!("auth_publickey");
750             self.finished_auth(server::Auth::Accept)
751         }
data(self, channel: ChannelId, data: &[u8], mut session: Session) -> Self::FutureUnit752         fn data(self, channel: ChannelId, data: &[u8], mut session: Session) -> Self::FutureUnit {
753             debug!("server data = {:?}", std::str::from_utf8(data));
754             session.data(channel, CryptoVec::from_slice(data));
755             self.finished(session)
756         }
757     }
758 
759     struct Client {}
760 
761     impl client::Handler for Client {
762         type Error = super::Error;
763         type FutureUnit = futures::future::Ready<Result<(Self, client::Session), Self::Error>>;
764         type FutureBool = futures::future::Ready<Result<(Self, bool), Self::Error>>;
765 
finished_bool(self, b: bool) -> Self::FutureBool766         fn finished_bool(self, b: bool) -> Self::FutureBool {
767             futures::future::ready(Ok((self, b)))
768         }
finished(self, session: client::Session) -> Self::FutureUnit769         fn finished(self, session: client::Session) -> Self::FutureUnit {
770             futures::future::ready(Ok((self, session)))
771         }
check_server_key( self, server_public_key: &thrussh_keys::key::PublicKey, ) -> Self::FutureBool772         fn check_server_key(
773             self,
774             server_public_key: &thrussh_keys::key::PublicKey,
775         ) -> Self::FutureBool {
776             println!("check_server_key: {:?}", server_public_key);
777             self.finished_bool(true)
778         }
779     }
780 }
781