diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2eacfee..912ad3e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -98,6 +98,6 @@ jobs: - name: run ssh run: mkdir /run/sshd && /usr/sbin/sshd -T &&/usr/sbin/sshd -D -p 8888 & - name: Test - run: cargo test --all-features + run: cargo test --all-features -- --test-threads 1 - name: Doc test run: cargo test --doc --all-features \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 5b85f07..abd9586 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,16 +22,17 @@ dangerous-dh-group1-sha1 = [] log = "0.4" rand = "0.8" num-bigint = { version = "0.4", features = ["rand"] } -strum = "0.24" -strum_macros = "0.24" +strum = "0.25" +strum_macros = "0.25" # the crate rsa has removed the internal hash implement from 0.7.0 sha1 = { version = "0.10.5", default-features = false, features = ["oid"], optional = true } sha2 = { version = "0.10.6", default-features = false, features = ["oid"]} -rsa = "^0.7" -aes = { version = "0.7", features = ["ctr"] } -ssh-key = { version = "0.5.1", features = ["rsa", "ed25519"]} -signature = "1.6.4" -ring = "0.16.20" +rsa = "0.9" +aes = "0.8" +ctr = "0.9" +ssh-key = { version = "0.6", features = ["rsa", "ed25519", "alloc"]} +signature = "2.1" +ring = "0.16" filetime = "0.2" # async diff --git a/build_check.sh b/build_check.sh index 30eb09a..e30e664 100644 --- a/build_check.sh +++ b/build_check.sh @@ -5,6 +5,14 @@ cargo fmt --all -- --check > /dev/null echo done echo echo +echo clippy check +cargo clippy -- -D warnings > /dev/null +echo +echo +echo clippy all check +cargo clippy --all-features -- -D warnings > /dev/null +echo +echo echo linux build check cargo build --target x86_64-unknown-linux-gnu > /dev/null echo done diff --git a/changelog b/changelog index 1813849..f25ec4c 100644 --- a/changelog +++ b/changelog @@ -1,9 +1,10 @@ -v0.3.3 (TBD) +v0.3.3 (2023-09-10) 1. fix hang when tcp connects to a non-existent host 2. refactor aes_ctr file 3. translate the changelogs 4. use std::time::Duration as timeout rather than u128 5. add the support for ssh message `SSH_MSG_CHANNEL_EXTENDED_DATA` + 6. bump dependencies v0.3.2 (2023-01-10) 1. fix some error with hmac2 diff --git a/src/algorithm/encryption/aes_ctr.rs b/src/algorithm/encryption/aes_ctr.rs index 9b163df..e2d9976 100644 --- a/src/algorithm/encryption/aes_ctr.rs +++ b/src/algorithm/encryption/aes_ctr.rs @@ -3,8 +3,12 @@ use crate::algorithm::hash::Hash; use crate::algorithm::mac::Mac; use crate::error::SshError; use crate::SshResult; -use aes::cipher::{NewCipher, StreamCipher, StreamCipherSeek}; -use aes::{Aes128Ctr, Aes192Ctr, Aes256Ctr}; +use aes::cipher::{KeyIvInit, StreamCipher, StreamCipherSeek}; +use ctr; + +type Aes128Ctr64BE = ctr::Ctr64BE; +type Aes192Ctr64BE = ctr::Ctr64BE; +type Aes256Ctr64BE = ctr::Ctr64BE; const CTR128_BLOCK_SIZE: usize = 16; const CTR192_BLOCK_SIZE: usize = 24; @@ -65,8 +69,8 @@ macro_rules! crate_aes { siv.clone_from_slice(&hash.iv_s_c[..$iv_size]); // TODO unwrap - let c = $alg::new_from_slices(&ckey, &civ).unwrap(); - let r = $alg::new_from_slices(&skey, &siv).unwrap(); + let c = $alg::new(&ckey.into(), &civ.into()); + let r = $alg::new(&skey.into(), &siv.into()); // hmac let (ik_c_s, ik_s_c) = hash.mix_ik(mac.bsize()); $name { @@ -133,8 +137,8 @@ macro_rules! crate_aes { } // aes-128-ctr -crate_aes!(Ctr128, Aes128Ctr, CTR128_BLOCK_SIZE, IV_SIZE); +crate_aes!(Ctr128, Aes128Ctr64BE, CTR128_BLOCK_SIZE, IV_SIZE); // aes-192-ctr -crate_aes!(Ctr192, Aes192Ctr, CTR192_BLOCK_SIZE, IV_SIZE); +crate_aes!(Ctr192, Aes192Ctr64BE, CTR192_BLOCK_SIZE, IV_SIZE); // aes-256-ctr -crate_aes!(Ctr256, Aes256Ctr, CTR256_BLOCK_SIZE, IV_SIZE); +crate_aes!(Ctr256, Aes256Ctr64BE, CTR256_BLOCK_SIZE, IV_SIZE); diff --git a/src/algorithm/public_key/rsa.rs b/src/algorithm/public_key/rsa.rs index 9f12305..5c901a1 100644 --- a/src/algorithm/public_key/rsa.rs +++ b/src/algorithm/public_key/rsa.rs @@ -1,7 +1,8 @@ use crate::algorithm::public_key::PublicKey as PubK; use crate::model::Data; use crate::SshError; -use rsa::PublicKey; +//use rsa::PublicKey; +use rsa::pkcs1v15::Pkcs1v15Sign; pub(super) struct RsaSha256; @@ -20,7 +21,7 @@ impl PubK for RsaSha256 { let e = rsa::BigUint::from_bytes_be(data.get_u8s().as_slice()); let n = rsa::BigUint::from_bytes_be(data.get_u8s().as_slice()); let public_key = rsa::RsaPublicKey::new(n, e).unwrap(); - let scheme = rsa::PaddingScheme::new_pkcs1v15_sign::(); + let scheme = Pkcs1v15Sign::new::(); let digest = ring::digest::digest(&ring::digest::SHA256, message); let msg = digest.as_ref(); @@ -46,7 +47,7 @@ impl PubK for RsaSha512 { let e = rsa::BigUint::from_bytes_be(data.get_u8s().as_slice()); let n = rsa::BigUint::from_bytes_be(data.get_u8s().as_slice()); let public_key = rsa::RsaPublicKey::new(n, e).unwrap(); - let scheme = rsa::PaddingScheme::new_pkcs1v15_sign::(); + let scheme = Pkcs1v15Sign::new::(); let digest = ring::digest::digest(&ring::digest::SHA512, message); let msg = digest.as_ref(); @@ -73,7 +74,7 @@ impl PubK for RsaSha1 { let e = rsa::BigUint::from_bytes_be(data.get_u8s().as_slice()); let n = rsa::BigUint::from_bytes_be(data.get_u8s().as_slice()); let public_key = rsa::RsaPublicKey::new(n, e).unwrap(); - let scheme = rsa::PaddingScheme::new_pkcs1v15_sign::(); + let scheme = Pkcs1v15Sign::new::(); let digest = ring::digest::digest(&ring::digest::SHA1_FOR_LEGACY_USE_ONLY, message); let msg = digest.as_ref(); diff --git a/src/channel/backend/channel_scp.rs b/src/channel/backend/channel_scp.rs index 93f5263..7b04fed 100644 --- a/src/channel/backend/channel_scp.rs +++ b/src/channel/backend/channel_scp.rs @@ -154,7 +154,7 @@ impl ScpBroker { Ok(()) } - fn send_file(&mut self, scp_file: &mut ScpFile) -> SshResult<()> { + fn send_file(&mut self, scp_file: &ScpFile) -> SshResult<()> { let mut file = match File::open(scp_file.local_path.as_path()) { Ok(f) => f, // 文件打开异常,不影响后续操作 @@ -394,7 +394,7 @@ impl ScpBroker { self.save_file(scp_file) } - fn save_file(&mut self, scp_file: &mut ScpFile) -> SshResult<()> { + fn save_file(&mut self, scp_file: &ScpFile) -> SshResult<()> { log::debug!( "name: [{}] size: [{}] type: [file] start download.", scp_file.name, @@ -449,7 +449,7 @@ impl ScpBroker { } #[cfg(windows)] - fn sync_permissions(&self, scp_file: &mut ScpFile) { + fn sync_permissions(&self, scp_file: &ScpFile) { let modify_time = filetime::FileTime::from_unix_time(scp_file.modify_time, 0); let access_time = filetime::FileTime::from_unix_time(scp_file.access_time, 0); if let Err(e) = @@ -466,7 +466,7 @@ impl ScpBroker { } #[cfg(any(target_os = "linux", target_os = "macos"))] - fn sync_permissions(&self, scp_file: &mut ScpFile, file: fs::File) { + fn sync_permissions(&self, scp_file: &ScpFile, file: fs::File) { let modify_time = filetime::FileTime::from_unix_time(scp_file.modify_time, 0); let access_time = filetime::FileTime::from_unix_time(scp_file.access_time, 0); if let Err(e) = diff --git a/src/channel/local/channel_scp.rs b/src/channel/local/channel_scp.rs index 2410e2e..7da2208 100644 --- a/src/channel/local/channel_scp.rs +++ b/src/channel/local/channel_scp.rs @@ -156,7 +156,7 @@ where Ok(()) } - fn send_file(&mut self, scp_file: &mut ScpFile) -> SshResult<()> { + fn send_file(&mut self, scp_file: &ScpFile) -> SshResult<()> { let mut file = match File::open(scp_file.local_path.as_path()) { Ok(f) => f, // 文件打开异常,不影响后续操作 @@ -460,7 +460,7 @@ where } #[cfg(any(target_os = "linux", target_os = "macos"))] - fn sync_permissions(&self, scp_file: &mut ScpFile, file: fs::File) { + fn sync_permissions(&self, scp_file: &ScpFile, file: fs::File) { let modify_time = filetime::FileTime::from_unix_time(scp_file.modify_time, 0); let access_time = filetime::FileTime::from_unix_time(scp_file.access_time, 0); if let Err(e) = diff --git a/src/client/client_auth.rs b/src/client/client_auth.rs index 52cbd33..86aeb18 100644 --- a/src/client/client_auth.rs +++ b/src/client/client_auth.rs @@ -10,7 +10,7 @@ use crate::{ use super::Client; impl Client { - pub fn do_auth(&mut self, stream: &mut S, digest: &mut Digest) -> SshResult<()> + pub fn do_auth(&mut self, stream: &mut S, digest: &Digest) -> SshResult<()> where S: Read + Write, { diff --git a/src/config/auth.rs b/src/config/auth.rs index 2cdf88e..8314258 100644 --- a/src/config/auth.rs +++ b/src/config/auth.rs @@ -5,7 +5,8 @@ use crate::algorithm::{ use crate::model::Data; use crate::{SshError, SshResult}; use rsa::pkcs1::DecodeRsaPrivateKey; -use rsa::PublicKeyParts; +use rsa::pkcs1v15::Pkcs1v15Sign; +use rsa::traits::PublicKeyParts; use std::fmt::Debug; use std::fs::File; use std::io::Read; @@ -93,16 +94,16 @@ impl KeyPair { KeyType::PemRsa | KeyType::SshRsa => { let (scheme, digest) = match alg { PubKey::RsaSha2_512 => ( - rsa::PaddingScheme::new_pkcs1v15_sign::(), + Pkcs1v15Sign::new::(), ring::digest::digest(&ring::digest::SHA512, sd), ), PubKey::RsaSha2_256 => ( - rsa::PaddingScheme::new_pkcs1v15_sign::(), + Pkcs1v15Sign::new::(), ring::digest::digest(&ring::digest::SHA256, sd), ), #[cfg(feature = "dangerous-rsa-sha1")] PubKey::SshRsa => ( - rsa::PaddingScheme::new_pkcs1v15_sign::(), + Pkcs1v15Sign::new::(), ring::digest::digest(&ring::digest::SHA1_FOR_LEGACY_USE_ONLY, sd), ), _ => unreachable!(), @@ -153,19 +154,14 @@ impl KeyPair { } } -#[derive(Clone)] +#[derive(Clone, Default)] pub(super) enum KeyType { + #[default] PemRsa, SshRsa, SshEd25519, } -impl Default for KeyType { - fn default() -> Self { - KeyType::PemRsa - } -} - #[derive(Clone, Default)] pub(crate) struct AuthInfo { pub username: String, diff --git a/src/config/version.rs b/src/config/version.rs index 7845142..0969f06 100644 --- a/src/config/version.rs +++ b/src/config/version.rs @@ -10,19 +10,14 @@ use crate::{ type OurVer = String; type ServerVer = String; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub(crate) enum SshVersion { V1, V2(OurVer, ServerVer), + #[default] Unknown, } -impl Default for SshVersion { - fn default() -> Self { - SshVersion::Unknown - } -} - fn read_version(stream: &mut S, tm: Option) -> SshResult> where S: Read, diff --git a/src/model/data.rs b/src/model/data.rs index 09e46f1..2fde405 100644 --- a/src/model/data.rs +++ b/src/model/data.rs @@ -122,14 +122,14 @@ impl Data { // 获取32位无符号整型 pub fn get_u32(&mut self) -> u32 { - let u32_buf = self.0.drain(..4).into_iter().collect::>(); + let u32_buf = self.0.drain(..4).collect::>(); u32::from_be_bytes(u32_buf.try_into().unwrap()) } // 获取字节数组 pub fn get_u8s(&mut self) -> Vec { let len = self.get_u32() as usize; - let bytes = self.0.drain(..len).into_iter().collect::>(); + let bytes = self.0.drain(..len).collect::>(); bytes } diff --git a/src/session/mod.rs b/src/session/mod.rs index b9a22fc..abf24f5 100644 --- a/src/session/mod.rs +++ b/src/session/mod.rs @@ -76,7 +76,7 @@ where digest.hash_ctx.set_i_s(server_algs.get_inner()); let server_algs = AlgList::unpack(server_algs)?; client.key_agreement(&mut stream, server_algs, &mut digest)?; - client.do_auth(&mut stream, &mut digest)?; + client.do_auth(&mut stream, &digest)?; Ok(Self { inner: SessionState::Connected(client, stream), })