From 64210f7677ab6bd957da4ee5f000b0dfd26f3cc9 Mon Sep 17 00:00:00 2001 From: Mihir Samdarshi Date: Tue, 18 Apr 2023 10:42:16 -0700 Subject: [PATCH] chore: update dependencies, fix clippy lints --- Cargo.lock | 117 +++++++++++++++++++----------------- Cargo.toml | 3 +- README.md | 11 ++-- async-ssh2-lite/src/main.rs | 24 ++++---- common/src/lib.rs | 9 +++ russh/Cargo.toml | 16 ++--- russh/src/main.rs | 38 ++++++------ russh/src/scp.rs | 26 +++----- rustfmt.toml | 3 +- 9 files changed, 127 insertions(+), 120 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4a4e1a0..1193a9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,7 +25,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfe0133578c0986e1fe3dfcd4af1cc5b2dd6c3dbf534d69916ce16a2701d40ba" dependencies = [ "cfg-if", - "cipher 0.4.3", + "cipher", "cpufeatures", ] @@ -37,7 +37,7 @@ checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c" dependencies = [ "aead", "aes", - "cipher 0.4.3", + "cipher", "ctr", "ghash", "subtle", @@ -207,15 +207,13 @@ checksum = "ea2b2456fd614d856680dcd9fcc660a51a820fa09daef2e49772b56a193c8474" [[package]] name = "bcrypt-pbkdf" -version = "0.6.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c38c03b9506bd92bf1ef50665a81eda156f615438f7654bffba58907e6149d7" +checksum = "3806a8db60cf56efee531616a34a6aaa9a114d6da2add861b0fa4a188881b2c7" dependencies = [ "blowfish", - "crypto-mac", - "pbkdf2 0.8.0", - "sha2 0.9.9", - "zeroize", + "pbkdf2", + "sha2 0.10.6", ] [[package]] @@ -259,13 +257,12 @@ dependencies = [ [[package]] name = "blowfish" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe3ff3fc1de48c1ac2e3341c4df38b0d1bfb8fdf04632a187c8b75aaa319a7ab" +checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" dependencies = [ "byteorder", - "cipher 0.3.0", - "opaque-debug", + "cipher", ] [[package]] @@ -292,7 +289,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" dependencies = [ - "cipher 0.4.3", + "cipher", ] [[package]] @@ -314,19 +311,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7fc89c7c5b9e7a02dfe45cd2367bae382f9ed31c61ca8debe5f827c420a2f08" dependencies = [ "cfg-if", - "cipher 0.4.3", + "cipher", "cpufeatures", ] -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array", -] - [[package]] name = "cipher" version = "0.4.3" @@ -481,22 +469,22 @@ dependencies = [ ] [[package]] -name = "crypto-mac" -version = "0.11.1" +name = "ctr" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "generic-array", - "subtle", + "cipher", ] [[package]] -name = "ctr" -version = "0.9.2" +name = "ctrlc" +version = "3.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +checksum = "1d91974fbbe88ec1df0c24a4f00f99583667a7e2e6272b2b92d294d81e462173" dependencies = [ - "cipher 0.4.3", + "nix", + "winapi", ] [[package]] @@ -540,9 +528,9 @@ dependencies = [ [[package]] name = "dirs" -version = "3.0.2" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ "dirs-sys", ] @@ -993,9 +981,9 @@ checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" [[package]] name = "libssh2-sys" -version = "0.2.23" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b094a36eb4b8b8c8a7b4b8ae43b2944502be3e59cd87687595cf6b0a71b3f4ca" +checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" dependencies = [ "cc", "libc", @@ -1107,6 +1095,18 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags", + "cfg-if", + "libc", +] + [[package]] name = "nom" version = "7.1.1" @@ -1328,15 +1328,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "pbkdf2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" -dependencies = [ - "crypto-mac", -] - [[package]] name = "pbkdf2" version = "0.11.0" @@ -1684,10 +1675,13 @@ checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "russh" -version = "0.34.0-beta.16" +version = "0.37.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7894d12dc117ca07eb565bcf75aac708b6ed5e2fd6a47e54a2ce42b64b5eea0" dependencies = [ "aes", "aes-gcm", + "async-trait", "bitflags", "byteorder", "chacha20", @@ -1712,11 +1706,14 @@ dependencies = [ "subtle", "thiserror", "tokio", + "tokio-util", ] [[package]] name = "russh-cryptovec" -version = "0.7.0-beta.1" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fdf036c2216b554053d19d4af45c1722d13b00ac494ea19825daf4beac034e" dependencies = [ "libc", "winapi", @@ -1724,7 +1721,9 @@ dependencies = [ [[package]] name = "russh-keys" -version = "0.22.0-beta.7" +version = "0.37.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efecb132e085e1e7a3afdae40e19eec0dfd4d6159eb189de02f243c369e18b7" dependencies = [ "aes", "bcrypt-pbkdf", @@ -1744,12 +1743,11 @@ dependencies = [ "num-bigint", "num-integer", "openssl", - "pbkdf2 0.11.0", + "pbkdf2", "rand 0.7.3", "rand_core 0.5.1", "russh-cryptovec", "serde", - "serde_derive", "sha2 0.10.6", "thiserror", "tokio", @@ -1920,9 +1918,9 @@ dependencies = [ [[package]] name = "ssh2" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "269343e64430067a14937ae0e3c4ec604c178fb896dde0964b1acd22b3e2eeb1" +checksum = "e7fe461910559f6d5604c3731d00d2aafc4a83d1665922e280f42f9a168d5455" dependencies = [ "bitflags", "libc", @@ -1930,6 +1928,17 @@ dependencies = [ "parking_lot 0.11.2", ] +[[package]] +name = "ssh2-rs-port-forward" +version = "0.1.0" +dependencies = [ + "anyhow", + "common-port-forward", + "ctrlc", + "ssh2", + "tracing", +] + [[package]] name = "strsim" version = "0.10.0" @@ -2459,9 +2468,9 @@ checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" [[package]] name = "yasna" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e262a29d0e61ccf2b6190d7050d4b237535fc76ce4c1210d9caa316f71dffa75" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ "bit-vec", "num-bigint", diff --git a/Cargo.toml b/Cargo.toml index 5df3d7c..2b23545 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,5 +2,6 @@ members = [ "common", "async-ssh2-lite", - "russh" + "russh", + "ssh2-rs" ] diff --git a/README.md b/README.md index dcb1c46..944926a 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Specifically this repository contains experiments with two crates thus far: - [russh](https://github.com/warp-tech/russh) - An (updated) fork of Thrussh, which is a pure-Rust implementation of the SSH protocol. +- [ssh2-rs](https://github.com/alexcrichton/ssh2-rs) - A Rust wrapper around libssh2. - [async-ssh2-lite](https://github.com/bk-rs/ssh-rs) - An async wrapper around ssh2-rs, which is a Rust wrapper around libssh2. @@ -22,10 +23,6 @@ None of the binaries work as expected, and struggle to handle a full remote port debugged the issues in either library, and am working on fixing/upstreaming the fixes that I make to whichever library I get working. Therefore, this repository is a work in progress, and I will be updating it as I work further. -In addition, other libraries that I have tried (but that aren't in this library and plan to add are): - -- [async-ssh2](https://github.com/spebern/async-ssh2) - Another async wrapper around ssh2-rs - ## Example To run a demo web application on your local computer and connect to it via SSH, ensure that you have Docker and are @@ -33,7 +30,7 @@ running an SSH server on your local machine. Add your own SSH public key to `~/. following commands: ```bash -docker run docker run -d -p 8080:8080 --rm mihirstanford/gatsby-gitbook-starter +docker run -d -p 8080:8080 --rm mihirstanford/gatsby-gitbook-starter ``` Then, you may navigate into either the `async-ssh2-lite` or `russh` directories and run the following: @@ -55,7 +52,7 @@ locally ### To Enable SSH Login (On Mac) -First, go to System Preferences > Sharing and enable Remote Login. You may need to restart your computer. +First, go to Settings > General > Sharing and enable Remote Login. You may need to restart your computer. To create an SSH key and add it to your `authorized_keys` file, run the following commands: @@ -66,4 +63,4 @@ ssh-keygen -t ed25519 -C "" # add your SSH key to your authorized_keys file touch ~/.ssh/authorized_keys cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys -``` \ No newline at end of file +``` diff --git a/async-ssh2-lite/src/main.rs b/async-ssh2-lite/src/main.rs index 5f26f0b..ccd0c72 100644 --- a/async-ssh2-lite/src/main.rs +++ b/async-ssh2-lite/src/main.rs @@ -20,7 +20,7 @@ use tokio::{ net::{TcpListener, TcpStream}, select, }; -use tracing::{debug, debug_span, instrument, Instrument}; +use tracing::{debug, debug_span, error, instrument, Instrument}; use uuid::Uuid; const BUFFER_SIZE: usize = 8192; @@ -51,7 +51,7 @@ async fn read_stream(mut stream: R) -> (Vec, u } } Err(e) => { - println!("Error in reading request data: {:?}", e); + println!("Error in reading request data: {e:?}"); break; } } @@ -79,7 +79,7 @@ async fn read_async_channel(stream: &mut R) -> (Vec } } Err(e) => { - println!("Error in reading response data: {:?}", e); + error!("Error in reading response data: {e:?}"); break; } } @@ -93,7 +93,7 @@ async fn handle_req( remote_port: u16, session: Arc>, mut stream: TcpStream, - _unique_id: String, + unique_id: String, ) { let mut channel = session .channel_direct_tcpip("localhost", remote_port, None) @@ -138,13 +138,13 @@ async fn create_ssh_session( ) .await?; - if !session.authenticated() { - Err(session - .last_error() - .map(Error::from) - .unwrap_or_else(|| Error::new(ErrorKind::Other, "unknown user auth error"))) - } else { + if session.authenticated() { Ok(session) + } else { + Err(session.last_error().map_or_else( + || Error::new(ErrorKind::Other, "unknown user auth error"), + Error::from, + )) } } @@ -196,8 +196,8 @@ async fn main() -> std::io::Result<()> { .unwrap(); let key_pair = SSHKeyPair { - public_key: public_key.as_ref().map(|p| p.as_ref()), - private_key: private_key.as_ref().map(|p| p.as_ref()), + public_key: public_key.as_ref().map(AsRef::as_ref), + private_key: private_key.as_ref().map(AsRef::as_ref), }; let session = match create_ssh_session(&args.user, remote_address, key_pair).await { diff --git a/common/src/lib.rs b/common/src/lib.rs index 0a73a9a..a9b9b23 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -12,6 +12,11 @@ use tracing_subscriber::{fmt, prelude::*, EnvFilter}; const BUFFER_SIZE: usize = 16_384; +/// Expand a tilde to the full path of the user's home directory +/// +/// ## Errors +/// if the path does not start with a tilde or if the HOME environment variable +/// is not set pub fn expand_home_dir + ?Sized>(path: &P) -> Result, String> { let path = path.as_ref(); @@ -55,6 +60,7 @@ pub struct Arguments { } /// Get arguments from the command line. +#[must_use] pub fn get_args() -> Arguments { Arguments::parse() } @@ -85,6 +91,9 @@ pub fn read_buf_bytes( } /// Setup tracing for any program that uses this library. +/// +/// ## Panics +/// if the file `trace.json` cannot be opened pub fn setup_tracing() { let fmt_layer = fmt::layer() .pretty() diff --git a/russh/Cargo.toml b/russh/Cargo.toml index dda67f9..9203779 100644 --- a/russh/Cargo.toml +++ b/russh/Cargo.toml @@ -6,13 +6,13 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow = "1.0.58" -async-trait = "0.1.57" +anyhow = "1" +async-trait = "0.1" common-port-forward = { path = "../common" } -futures = "0.3.21" -russh = { path = "../../russh/russh", features = ["vendored-openssl"] } -russh-keys = { path = "../../russh/russh-keys", features = ["vendored-openssl"] } -tokio = { version = "1.20.1", features = ["full", "tracing"] } -tracing = "0.1.36" -uuid = { version = "1.1.2", features = ["v4", "fast-rng"] } +futures = "0.3" +russh = { version = "^0.37.1", features = ["vendored-openssl"] } +russh-keys = { version = "^0.37.1", features = ["vendored-openssl"] } +tokio = { version = "1", features = ["full", "tracing"] } +tracing = "0.1" +uuid = { version = "1", features = ["v4", "fast-rng"] } diff --git a/russh/src/main.rs b/russh/src/main.rs index 3c637eb..4b52231 100644 --- a/russh/src/main.rs +++ b/russh/src/main.rs @@ -8,7 +8,7 @@ use std::{ use anyhow::{anyhow, Result}; use common_port_forward::{expand_home_dir, get_args, read_buf_bytes, setup_tracing}; use russh::{client, client::Msg, Channel, ChannelMsg, Disconnect}; -use russh_keys::{key::PublicKey, load_secret_key}; +use russh_keys::load_secret_key; use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, net::{TcpListener, TcpStream}, @@ -26,18 +26,6 @@ struct Client {} impl client::Handler for Client { type Error = russh::Error; - type FutureBool = futures::future::Ready>; - type FutureUnit = futures::future::Ready>; - - fn finished_bool(self, b: bool) -> Self::FutureBool { - futures::future::ready(Ok((self, b))) - } - fn finished(self, session: client::Session) -> Self::FutureUnit { - futures::future::ready(Ok((self, session))) - } - fn check_server_key(self, _server_public_key: &PublicKey) -> Self::FutureBool { - self.finished_bool(true) - } } pub struct Session { @@ -65,7 +53,7 @@ async fn read_stream(mut stream: R) -> (Vec } } Err(e) => { - eprintln!("Error reading stream: {}", e); + eprintln!("Error reading stream: {e}"); break; } } @@ -108,7 +96,7 @@ impl Session { } #[instrument(skip(channel))] -async fn handle_req(mut channel: Channel, mut incoming_stream: TcpStream, _unique_id: String) { +async fn handle_req(mut channel: Channel, mut incoming_stream: TcpStream, unique_id: String) { debug!("Splitting stream"); let (mut read_half, mut write_half) = incoming_stream.split(); @@ -130,6 +118,8 @@ async fn handle_req(mut channel: Channel, mut incoming_stream: TcpStream, _ // error!("Error in sending EOF to server: {:?}", e); // } + let mut received_response = false; + debug!("Waiting for response"); let mut total_len = 0usize; @@ -148,10 +138,20 @@ async fn handle_req(mut channel: Channel, mut incoming_stream: TcpStream, _ error!("Error in writing response to client: {:?}", e); } }; + + if !received_response { + received_response = true; + debug!("Sending EOF to server"); + if let Err(e) = channel.eof().in_current_span().await { + error!("Error in sending EOF to server: {:?}", e); + } + } + debug!("Response written to client"); } ChannelMsg::Eof => { debug!("Received EOF from server"); + break; } ChannelMsg::Close => { debug!("End of data to be received"); @@ -171,7 +171,7 @@ async fn listen_on_forwarded_port( remote_port: u32, ) -> Result<()> { debug!("listening on forwarded port"); - let user_facing_socket = TcpListener::bind(format!("127.0.0.1:{}", local_port)) + let user_facing_socket = TcpListener::bind(format!("127.0.0.1:{local_port}")) .in_current_span() .await .unwrap(); @@ -184,7 +184,7 @@ async fn listen_on_forwarded_port( debug!("Accepted connection from {:?}", a); let channel = { - let mut session_guard = sess.lock().await; + let session_guard = sess.lock().await; session_guard .session .channel_open_direct_tcpip( @@ -221,8 +221,8 @@ async fn main() -> Result<()> { let t1 = tokio::spawn(listen_on_forwarded_port( cloned_e, - args.local_port as u32, - args.remote_port as u32, + u32::from(args.local_port), + u32::from(args.remote_port), )); let w = Wrapper(e); diff --git a/russh/src/scp.rs b/russh/src/scp.rs index 59eb7dc..c38b39e 100644 --- a/russh/src/scp.rs +++ b/russh/src/scp.rs @@ -41,18 +41,13 @@ impl Scp for client::Handle { let mut channel = self.channel_open_session().await?; eprintln!("channel open: {:?}", channel.id()); // Actually send the file. - channel - .exec(false, &(format!("scp -t {}", dirname))) - .await?; + channel.exec(false, &*(format!("scp -t {dirname}"))).await?; // SCP needs the contents to be prefixed with the permission, length and base // name. https://blogs.oracle.com/janp/entry/how_the_scp_protocol_works - let contents = Cursor::new(format!( - "C0{:o} {} {}\n", - permissions, contents_len, basename - )) - .chain(contents) - .chain(CONFIRM); + let contents = Cursor::new(format!("C0{permissions:o} {contents_len} {basename}\n")) + .chain(contents) + .chain(CONFIRM); let pinned = Box::pin(contents); @@ -70,7 +65,7 @@ impl Scp for client::Handle { let mut channel = self.channel_open_session().await?; eprintln!("channel open: {:?}", channel.id()); // Actually send the file. - channel.exec(false, &(format!("scp -f {}", source))).await?; + channel.exec(false, &*(format!("scp -f {source}"))).await?; // Run the event loop until the channel closes. loop { @@ -81,14 +76,11 @@ impl Scp for client::Handle { let mut file = File::create(target).unwrap(); file.write_all(&s).unwrap(); } - Some(ChannelMsg::Eof) => { - break; - } - Some(ChannelMsg::Close) => { + Some(ChannelMsg::Eof | ChannelMsg::Close) => { break; } Some(ChannelMsg::ExitStatus { exit_status }) => { - eprintln!("exit status: {}", exit_status); + eprintln!("exit status: {exit_status}"); break; } Some(ChannelMsg::ExitSignal { @@ -98,8 +90,8 @@ impl Scp for client::Handle { ref lang_tag, }) => { eprintln!( - "exit signal: {:?}, core dumped: {}, error: {:?}, lang tag: {:?}", - signal_name, core_dumped, error_message, lang_tag + "exit signal: {signal_name:?}, core dumped: {core_dumped}, error: \ + {error_message:?}, lang tag: {lang_tag:?}" ); break; } diff --git a/rustfmt.toml b/rustfmt.toml index 0df7eb6..09104f8 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -6,7 +6,6 @@ imports_granularity = "Crate" group_imports = "StdExternalCrate" use_small_heuristics = "Default" reorder_imports = true -merge_imports = true reorder_modules = true remove_nested_parens = true edition = "2021" @@ -15,4 +14,4 @@ use_field_init_shorthand = true wrap_comments = true format_strings = true use_try_shorthand = false -force_explicit_abi = true \ No newline at end of file +force_explicit_abi = true