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::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)
}

Reexports

pub use key::parse_public_key;

Modules

client

Client side of this library.

encoding

SSH encoding of various types into buffers.

key

Key generation and use.

server

Server side of this library.

Structs

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.

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.