Crate thrussh [] [src]

Server and client SSH library, based on ring for its crypto, and tokio/futures for its network management. More information at pijul.org/thrussh.

Here is an example client and server:

extern crate thrussh;
extern crate thrussh_keys;
extern crate futures;
extern crate tokio_core;
extern crate env_logger;
extern crate ring;
use std::rc::Rc;
use thrussh::*;
use thrussh::server::{Auth, Session};
use thrussh_keys::*;

#[derive(Clone)]
struct H{}

impl server::Server for H {
   type Handler = Self;
   fn new(&self, _: SocketAddr) -> Self {
       H{}
   }
}

impl server::Handler for H {
   type Error = ();
   type FutureAuth = futures::Finished<(Self, server::Auth), Self::Error>;
   type FutureUnit = futures::Finished<(Self, server::Session), Self::Error>;
   type FutureBool = futures::Finished<(Self, server::Session, bool), Self::Error>;

   fn finished_auth(self, auth: Auth) -> Self::FutureAuth {
       futures::finished((self, auth))
   }
   fn finished_bool(self, session: Session, b: bool) -> Self::FutureBool {
       futures::finished((self, session, b))
   }
   fn finished(self, session: Session) -> Self::FutureUnit {
       futures::finished((self, session))
   }

   fn auth_publickey(self, _: &str, _: &key::PublicKey) -> Self::FutureAuth {
       futures::finished((self, server::Auth::Accept))
   }
   fn data(self, channel: ChannelId, data: &[u8], mut session: server::Session) -> Self::FutureUnit {
       println!("data on channel {:?}: {:?}", channel, std::str::from_utf8(data));
       session.data(channel, None, data).unwrap();
       futures::finished((self, session))
   }
}


use futures::Future;
use std::io::Read;


struct Client { }

impl client::Handler for Client {
   type Error = ();
   type FutureBool = futures::Finished<(Self, bool), Self::Error>;
   type FutureUnit = futures::Finished<Self, Self::Error>;
   type SessionUnit = futures::Finished<(Self, client::Session), Self::Error>;
   fn check_server_key(self, server_public_key: &key::PublicKey) -> Self::FutureBool {
       println!("check_server_key: {:?}", server_public_key);
       futures::finished((self, true))
   }
   fn channel_open_confirmation(self, channel: ChannelId, session: client::Session) -> Self::SessionUnit {
       println!("channel_open_confirmation: {:?}", channel);
       futures::finished((self, session))
   }
   fn data(self, channel: ChannelId, ext: Option<u32>, data: &[u8], session: client::Session) -> Self::SessionUnit {
       println!("data on channel {:?} {:?}: {:?}", ext, channel, std::str::from_utf8(data));
       futures::finished((self, session))
   }
}

impl Client {

 fn run(self, config: Rc<client::Config>, _: &str) {

    client::connect(
        "127.0.0.1:2222", config, None, self,

        |connection| {

            let mut key_file = std::fs::File::open("/home/pe/.ssh/id_ed25519_pkcs8").unwrap();
            let mut key = String::new();
            key_file.read_to_string(&mut key).unwrap();
            let key = load_secret_key(&key, None, None).unwrap();

            connection.authenticate_key("pe", key)
                .and_then(|session| {

                    session.channel_open_session().and_then(|(session, channelid)| {

                        session.data(channelid, None, "Hello, world!").and_then(|(mut session, _)| {
                            session.disconnect(Disconnect::ByApplication, "Ciao", "");
                            session
                        })
                    })
                })
        }).unwrap();

}

}

fn main() {
   env_logger::init().unwrap();
   // Starting the server thread.
   let t = std::thread::spawn(|| {
       let rand = ring::rand::SystemRandom::new();
       let mut config = thrussh::server::Config::default();
       config.connection_timeout = Some(std::time::Duration::from_secs(600));
       config.auth_rejection_time = std::time::Duration::from_secs(3);
       config.keys.push(thrussh::key::Algorithm::generate_keypair(thrussh::key::ED25519, &rand).unwrap());
       let config = Rc::new(config);
       let sh = H{};
       thrussh::server::run(config, "0.0.0.0:2222", sh);
   });

   std::thread::sleep(std::time::Duration::from_secs(1));
   let mut config = thrussh::client::Config::default();
   config.connection_timeout = Some(std::time::Duration::from_secs(600));
   let config = Rc::new(config);
   let sh = Client {};
   sh.run(config, "127.0.0.1:2222");

   // Kill the server thread after the client has ended.
   std::mem::forget(t)
}

Modules

client

Client side of this library.

server

Server side of this library.

Structs

Channel

The parameters of a channel.

ChannelId

The identifier of a channel.

CryptoVec

A buffer which zeroes its memory on .clear(), .resize() and reallocations, to avoid copying secrets around.

Limits

The number of bytes read/written, and the number of seconds before a key re-exchange is requested.

MethodSet

Set of methods, represented by bit flags.

Preferred

Lists of preferred algorithms. This is normally hard-coded into implementations.

Enums

ChannelOpenFailure

Reason for not being able to open a channel.

Disconnect

A reason for disconnection.

Error

Errors.

HandlerError

Errors including those coming from handler. These are not included in this crate's "main" error type to allow for a simpler API (the "handler error" type cannot be inferred by the compiler in some functions).

Pty

Standard pseudo-terminal codes.

Sig

The type of signals that can be sent to a remote process. If you plan to use custom signals, read the RFC to understand the encoding.

Traits

FromFinished

Since handlers are large, their associated future types must implement this trait to provide reasonable default implementations (basically, rejecting all requests).

Named

Named algorithms.

Tcp

Types that have a "TCP shutdown" operation.