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 futures;
extern crate tokio_core;
extern crate env_logger;
use std::sync::Arc;
use thrussh::*;

#[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 auth_publickey(mut self, _: &str, _: &key::PublicKey) -> Self::FutureAuth {
        futures::finished((self, server::Auth::Accept))
    }
    fn data(mut 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 std::net::ToSocketAddrs;
use futures::Future;
use tokio_core::net::TcpStream;
use tokio_core::reactor::Core;


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(mut self, server_public_key: &key::PublicKey) -> Self::FutureBool {
        println!("check_server_key: {:?}", server_public_key);
        futures::finished((self, true))
    }
    fn channel_open_confirmation(mut self, channel: ChannelId, session: client::Session) -> Self::SessionUnit {
        println!("channel_open_confirmation: {:?}", channel);
        futures::finished((self, session))
    }
    fn data(mut 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: Arc<client::Config>, addr: &str) {

        let addr = addr.to_socket_addrs().unwrap().next().unwrap();
        let mut l = Core::new().unwrap();
        let handle = l.handle();
        let done =
            TcpStream::connect(&addr, &handle).map_err(|err| HandlerError::Error(thrussh::Error::IO(err))).and_then(|socket| {

                println!("connected");
                let mut connection = client::Connection::new(
                    config.clone(),
                    socket,
                    self,
                    None
                ).unwrap();

                let key = thrussh::load_secret_key("/home/pe/.ssh/id_ed25519").unwrap();
                connection.authenticate_key("pe", key).and_then(|connection| {

                    connection.channel_open_session().and_then(move |(mut connection, chan)| {

                        connection.data(chan, None, b"First test").and_then(move |(connection, _)| {
                           connection.data(chan, None, b"Second test").and_then(move |(mut connection, _)| {
                              connection.disconnect(Disconnect::ByApplication, "Ciao", "");
                              connection
                           })
                        })
                    })
                })
            });
        l.run(done).unwrap();
    }

}

fn main() {
    env_logger::init().unwrap();
    // Starting the server thread.
    let t = std::thread::spawn(|| {
        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).unwrap());
        let config = Arc::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 = Arc::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.

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).

Functions

check_known_hosts_path

Check that a server key matches the one recorded in file path.

learn_known_hosts_path

Record a host's public key into a nonstandard location.

load_public_key

Load a public key from a file. Only ed25519 keys are currently supported.

load_secret_key

Load a secret key from a file. Only ed25519 keys are currently supported.

parse_public_key_base64

Reads a public key from the standard encoding. In some cases, the encoding is prefixed with a key type identifier and a space (such as ssh-ed25519 AAAAC3N...).

write_public_key_base64

Write a public key onto the provided Write, encoded in base-64.