bssh_russh/lib.rs
1#![deny(
2 clippy::unwrap_used,
3 clippy::expect_used,
4 clippy::indexing_slicing,
5 clippy::panic
6)]
7#![allow(clippy::single_match, clippy::upper_case_acronyms)]
8#![allow(macro_expanded_macro_exports_accessed_by_absolute_paths)]
9// length checked
10// Copyright 2016 Pierre-Étienne Meunier
11//
12// Licensed under the Apache License, Version 2.0 (the "License");
13// you may not use this file except in compliance with the License.
14// You may obtain a copy of the License at
15//
16// http://www.apache.org/licenses/LICENSE-2.0
17//
18// Unless required by applicable law or agreed to in writing, software
19// distributed under the License is distributed on an "AS IS" BASIS,
20// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21// See the License for the specific language governing permissions and
22// limitations under the License.
23
24//! Server and client SSH asynchronous library, based on tokio/futures.
25//!
26//! The normal way to use this library, both for clients and for
27//! servers, is by creating *handlers*, i.e. types that implement
28//! `client::Handler` for clients and `server::Handler` for
29//! servers.
30//!
31//! * [Writing SSH clients - the `russh::client` module](client)
32//! * [Writing SSH servers - the `russh::server` module](server)
33//!
34//! # Using non-socket IO / writing tunnels
35//!
36//! The easy way to implement SSH tunnels, like `ProxyCommand` for
37//! OpenSSH, is to use the `russh-config` crate, and use the
38//! `Stream::tcp_connect` or `Stream::proxy_command` methods of that
39//! crate. That crate is a very lightweight layer above Russh, only
40//! implementing for external commands the traits used for sockets.
41//!
42//! # The SSH protocol
43//!
44//! If we exclude the key exchange and authentication phases, handled
45//! by Russh behind the scenes, the rest of the SSH protocol is
46//! relatively simple: clients and servers open *channels*, which are
47//! just integers used to handle multiple requests in parallel in a
48//! single connection. Once a client has obtained a `ChannelId` by
49//! calling one of the many `channel_open_…` methods of
50//! `client::Connection`, the client may send exec requests and data
51//! to the server.
52//!
53//! A simple client just asking the server to run one command will
54//! usually start by calling
55//! `client::Connection::channel_open_session`, then
56//! `client::Connection::exec`, then possibly
57//! `client::Connection::data` a number of times to send data to the
58//! command's standard input, and finally `Connection::channel_eof`
59//! and `Connection::channel_close`.
60//!
61//! # Design principles
62//!
63//! The main goal of this library is conciseness, and reduced size and
64//! readability of the library's code.
65//!
66//! One non-goal is to implement all possible cryptographic algorithms
67//! published since the initial release of SSH. Technical debt is
68//! easily acquired, and we would need a very strong reason to go
69//! against this principle. If you are designing a system from
70//! scratch, we urge you to consider recent cryptographic primitives
71//! such as Ed25519 for public key cryptography, and Chacha20-Poly1305
72//! for symmetric cryptography and MAC.
73//!
74//! # Internal details of the event loop
75//!
76//! It might seem a little odd that the read/write methods for server
77//! or client sessions often return neither `Result` nor
78//! `Future`. This is because the data sent to the remote side is
79//! buffered, because it needs to be encrypted first, and encryption
80//! works on buffers, and for many algorithms, not in place.
81//!
82//! Hence, the event loop keeps waiting for incoming packets, reacts
83//! to them by calling the provided `Handler`, which fills some
84//! buffers. If the buffers are non-empty, the event loop then sends
85//! them to the socket, flushes the socket, empties the buffers and
86//! starts again. In the special case of the server, unsolicited
87//! messages sent through a `server::Handle` are processed when there
88//! is no incoming packet to read.
89
90#[cfg(not(any(feature = "ring", feature = "aws-lc-rs")))]
91compile_error!(
92 "`russh` requires enabling either the `ring` or `aws-lc-rs` feature as a crypto backend."
93);
94
95#[cfg(any(feature = "ring", feature = "aws-lc-rs"))]
96include!("lib_inner.rs");