From 8a627949a30d3573b254b5f37e3da577eedd0fde Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sun, 25 Aug 2024 23:26:57 +0200 Subject: [PATCH] moves --- Cargo.lock | 12 ++++++ bin/cluelessh-agentctl/Cargo.toml | 1 + bin/cluelessh-agentctl/src/main.rs | 5 ++- bin/cluelesshd/src/main.rs | 1 - lib/cluelessh-agent-client/Cargo.toml | 1 + lib/cluelessh-agent-client/src/lib.rs | 9 ++--- lib/cluelessh-format/Cargo.toml | 10 +++++ lib/cluelessh-format/README.md | 3 ++ .../parse.rs => cluelessh-format/src/lib.rs} | 13 +------ lib/cluelessh-keys/Cargo.toml | 1 + lib/cluelessh-keys/src/crypto.rs | 20 +++++----- lib/cluelessh-keys/src/lib.rs | 38 +++++++++---------- lib/cluelessh-keys/src/signature.rs | 3 +- lib/cluelessh-protocol/Cargo.toml | 1 + lib/cluelessh-protocol/src/lib.rs | 3 +- lib/cluelessh-transport/Cargo.toml | 1 + lib/cluelessh-transport/src/client.rs | 8 ++-- lib/cluelessh-transport/src/crypto.rs | 8 ++-- lib/cluelessh-transport/src/key.rs | 8 ++-- lib/cluelessh-transport/src/lib.rs | 9 ++++- lib/cluelessh-transport/src/packet.rs | 10 ++--- lib/cluelessh-transport/src/packet/ctors.rs | 4 +- lib/cluelessh-transport/src/server.rs | 10 ++--- 23 files changed, 102 insertions(+), 77 deletions(-) create mode 100644 lib/cluelessh-format/Cargo.toml create mode 100644 lib/cluelessh-format/README.md rename lib/{cluelessh-transport/src/parse.rs => cluelessh-format/src/lib.rs} (94%) diff --git a/Cargo.lock b/Cargo.lock index 5ca60ed..e51ed5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -296,6 +296,7 @@ dependencies = [ name = "cluelessh-agent-client" version = "0.1.0" dependencies = [ + "cluelessh-format", "cluelessh-transport", "eyre", "tokio", @@ -308,6 +309,7 @@ version = "0.1.0" dependencies = [ "clap", "cluelessh-agent-client", + "cluelessh-format", "cluelessh-transport", "eyre", "hex", @@ -357,6 +359,13 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "cluelessh-format" +version = "0.1.0" +dependencies = [ + "crypto-bigint", +] + [[package]] name = "cluelessh-key" version = "0.1.0" @@ -377,6 +386,7 @@ dependencies = [ "aes", "base64", "bcrypt-pbkdf", + "cluelessh-format", "cluelessh-transport", "ctr", "ed25519-dalek", @@ -390,6 +400,7 @@ name = "cluelessh-protocol" version = "0.1.0" dependencies = [ "cluelessh-connection", + "cluelessh-format", "cluelessh-transport", "rand", "tracing", @@ -416,6 +427,7 @@ dependencies = [ "aes-gcm", "base64", "chacha20", + "cluelessh-format", "crypto-bigint", "ctr", "ed25519-dalek", diff --git a/bin/cluelessh-agentctl/Cargo.toml b/bin/cluelessh-agentctl/Cargo.toml index 30e8025..e64e0b6 100644 --- a/bin/cluelessh-agentctl/Cargo.toml +++ b/bin/cluelessh-agentctl/Cargo.toml @@ -15,6 +15,7 @@ rpassword = "7.3.1" sha2 = "0.10.8" hex = "0.4.3" pem = "3.0.4" +cluelessh-format = { version = "0.1.0", path = "../../lib/cluelessh-format" } [lints] workspace = true diff --git a/bin/cluelessh-agentctl/src/main.rs b/bin/cluelessh-agentctl/src/main.rs index 416e4b1..6e98d71 100644 --- a/bin/cluelessh-agentctl/src/main.rs +++ b/bin/cluelessh-agentctl/src/main.rs @@ -1,10 +1,11 @@ use std::{io::Write, path::PathBuf}; use clap::Parser; +use cluelessh_agent_client::{IdentityAnswer, SocketAgentConnection}; +use cluelessh_format::Writer; +use cluelessh_transport::key::PublicKey; use eyre::{bail, Context}; use sha2::Digest; -use cluelessh_agent_client::{IdentityAnswer, SocketAgentConnection}; -use cluelessh_transport::{key::PublicKey, parse::Writer}; #[derive(clap::Parser, Debug)] struct Args { diff --git a/bin/cluelesshd/src/main.rs b/bin/cluelesshd/src/main.rs index 6e670a2..9a9c097 100644 --- a/bin/cluelesshd/src/main.rs +++ b/bin/cluelesshd/src/main.rs @@ -158,7 +158,6 @@ async fn handle_connection( }, }, result = futures::future::try_join_all(&mut channel_tasks), if channel_tasks.len() > 0 => { - debug!(?result, "error!"); match result { Ok(_) => channel_tasks.clear(), Err(err) => return Err((err as eyre::Report).wrap_err("channel task failed")), diff --git a/lib/cluelessh-agent-client/Cargo.toml b/lib/cluelessh-agent-client/Cargo.toml index 8f9bc1f..3a0781c 100644 --- a/lib/cluelessh-agent-client/Cargo.toml +++ b/lib/cluelessh-agent-client/Cargo.toml @@ -8,6 +8,7 @@ eyre.workspace = true cluelessh-transport = { path = "../cluelessh-transport" } tokio = { version = "1.39.3", features = ["net"] } tracing.workspace = true +cluelessh-format = { version = "0.1.0", path = "../cluelessh-format" } [lints] workspace = true diff --git a/lib/cluelessh-agent-client/src/lib.rs b/lib/cluelessh-agent-client/src/lib.rs index 6be4574..afc3ce9 100644 --- a/lib/cluelessh-agent-client/src/lib.rs +++ b/lib/cluelessh-agent-client/src/lib.rs @@ -1,9 +1,6 @@ +use cluelessh_format::{Reader, Writer}; +use cluelessh_transport::{packet::PacketParser, SshStatus}; use eyre::{bail, eyre, Context}; -use cluelessh_transport::{ - packet::PacketParser, - parse::{Parser, Writer}, - SshStatus, -}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tracing::{debug, trace}; @@ -121,7 +118,7 @@ pub struct IdentityAnswer { impl ServerResponse { pub fn parse(bytes: &[u8]) -> eyre::Result { let bytes = &bytes[4..]; - let mut p = Parser::new(bytes); + let mut p = Reader::new(bytes); let msg_type = p.u8()?; trace!(%msg_type, msg_type_str = %numbers::server_response_type_to_string(msg_type), "Received message"); let resp = match msg_type { diff --git a/lib/cluelessh-format/Cargo.toml b/lib/cluelessh-format/Cargo.toml new file mode 100644 index 0000000..c345069 --- /dev/null +++ b/lib/cluelessh-format/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "cluelessh-format" +version = "0.1.0" +edition = "2021" + +[dependencies] +crypto-bigint = "0.5.5" + +[lints] +workspace = true diff --git a/lib/cluelessh-format/README.md b/lib/cluelessh-format/README.md new file mode 100644 index 0000000..921da62 --- /dev/null +++ b/lib/cluelessh-format/README.md @@ -0,0 +1,3 @@ +# cluelessh-format + +Helpers for SSH encoded data (). diff --git a/lib/cluelessh-transport/src/parse.rs b/lib/cluelessh-format/src/lib.rs similarity index 94% rename from lib/cluelessh-transport/src/parse.rs rename to lib/cluelessh-format/src/lib.rs index 3077f78..c86cc8a 100644 --- a/lib/cluelessh-transport/src/parse.rs +++ b/lib/cluelessh-format/src/lib.rs @@ -1,8 +1,6 @@ use core::str; use std::fmt::{Debug, Display}; -use crate::SshStatus; - #[derive(Debug)] pub struct ParseError(pub String); impl Display for ParseError { @@ -12,18 +10,11 @@ impl Display for ParseError { } impl std::error::Error for ParseError {} -impl From for SshStatus { - fn from(err: ParseError) -> Self { - Self::PeerError(err.0) - } -} - pub type Result = std::result::Result; -/// A simplified `byteorder` clone that emits client errors when the data is too short. -pub struct Parser<'a>(&'a [u8]); +pub struct Reader<'a>(&'a [u8]); -impl<'a> Parser<'a> { +impl<'a> Reader<'a> { pub fn new(data: &'a [u8]) -> Self { Self(data) } diff --git a/lib/cluelessh-keys/Cargo.toml b/lib/cluelessh-keys/Cargo.toml index 262e9d7..c10297b 100644 --- a/lib/cluelessh-keys/Cargo.toml +++ b/lib/cluelessh-keys/Cargo.toml @@ -13,6 +13,7 @@ rand = "0.8.5" cluelessh-transport = { path = "../cluelessh-transport" } thiserror = "1.0.63" base64 = "0.22.1" +cluelessh-format = { version = "0.1.0", path = "../cluelessh-format" } [lints] workspace = true diff --git a/lib/cluelessh-keys/src/crypto.rs b/lib/cluelessh-keys/src/crypto.rs index a77d3ad..43a307f 100644 --- a/lib/cluelessh-keys/src/crypto.rs +++ b/lib/cluelessh-keys/src/crypto.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use aes::cipher::{KeySizeUser, StreamCipher}; -use cluelessh_transport::parse::{self, Parser, Writer}; +use cluelessh_format::{Reader, Writer}; use crate::PrivateKeyType; @@ -12,14 +12,14 @@ pub enum Cipher { } impl FromStr for Cipher { - type Err = parse::ParseError; + type Err = cluelessh_format::ParseError; fn from_str(ciphername: &str) -> Result { let cipher = match ciphername { "none" => Cipher::None, "aes256-ctr" => Cipher::Aes256Ctr, _ => { - return Err(parse::ParseError(format!( + return Err(cluelessh_format::ParseError(format!( "unsupported cipher: {ciphername}" ))); } @@ -66,29 +66,29 @@ impl Kdf { pub(crate) fn from_str_and_options( kdfname: &str, kdfoptions: &[u8], - ) -> Result { + ) -> Result { let kdf = match kdfname { "none" => { if !kdfoptions.is_empty() { - return Err(parse::ParseError(format!( + return Err(cluelessh_format::ParseError(format!( "KDF options must be empty for none KDF" ))); } Kdf::None } "bcrypt" => { - let mut opts = Parser::new(kdfoptions); + let mut opts = Reader::new(kdfoptions); let salt = opts.string()?; let rounds = opts.u32()?; Kdf::BCrypt { salt: salt .try_into() - .map_err(|_| parse::ParseError(format!("incorrect bcrypt salt len")))?, + .map_err(|_| cluelessh_format::ParseError(format!("incorrect bcrypt salt len")))?, rounds, } } _ => { - return Err(parse::ParseError(format!("unsupported KDF: {kdfname}"))); + return Err(cluelessh_format::ParseError(format!("unsupported KDF: {kdfname}"))); } }; Ok(kdf) @@ -113,12 +113,12 @@ impl Kdf { } } - pub(crate) fn derive(&self, passphrase: &str, output: &mut [u8]) -> parse::Result<()> { + pub(crate) fn derive(&self, passphrase: &str, output: &mut [u8]) -> cluelessh_format::Result<()> { match self { Self::None => unreachable!("should not attempt to derive passphrase from none"), Self::BCrypt { salt, rounds } => { bcrypt_pbkdf::bcrypt_pbkdf(passphrase, salt, *rounds, output).map_err(|err| { - parse::ParseError(format!("error when performing key derivation: {err}")) + cluelessh_format::ParseError(format!("error when performing key derivation: {err}")) }) } } diff --git a/lib/cluelessh-keys/src/lib.rs b/lib/cluelessh-keys/src/lib.rs index f93b34a..3c2c4a7 100644 --- a/lib/cluelessh-keys/src/lib.rs +++ b/lib/cluelessh-keys/src/lib.rs @@ -2,10 +2,8 @@ pub mod authorized_keys; mod crypto; pub mod signature; -use cluelessh_transport::{ - key::PublicKey, - parse::{self, Parser, Writer}, -}; +use cluelessh_format::{Reader, Writer}; +use cluelessh_transport::key::PublicKey; use crypto::{Cipher, Kdf}; // TODO: good typed error messages so the user knows what's going on @@ -42,24 +40,24 @@ const MAGIC: &[u8; 15] = b"openssh-key-v1\0"; impl EncryptedPrivateKeys { /// Parse OpenSSH private keys, either armored or not. - pub fn parse(content: &[u8]) -> parse::Result { + pub fn parse(content: &[u8]) -> cluelessh_format::Result { // https://github.com/openssh/openssh-portable/blob/a76a6b85108e3032c8175611ecc5746e7131f876/PROTOCOL.key let pem: pem::Pem; // lifetime extension let content = if content.starts_with(b"openssh-key-v1") { content } else if content.starts_with(b"-----BEGIN OPENSSH PRIVATE KEY-----") { pem = pem::parse(content) - .map_err(|err| parse::ParseError(format!("invalid PEM format: {err}")))?; + .map_err(|err| cluelessh_format::ParseError(format!("invalid PEM format: {err}")))?; pem.contents() } else { - return Err(parse::ParseError("invalid SSH key".to_owned())); + return Err(cluelessh_format::ParseError("invalid SSH key".to_owned())); }; - let mut p = Parser::new(content); + let mut p = Reader::new(content); let magic = p.array::<{ MAGIC.len() }>()?; if magic != *MAGIC { - return Err(parse::ParseError( + return Err(cluelessh_format::ParseError( "invalid magic, not an SSH key?".to_owned(), )); } @@ -117,14 +115,14 @@ impl EncryptedPrivateKeys { (!matches!(self.kdf, Kdf::None)) && (!matches!(self.cipher, Cipher::None)) } - pub fn decrypt_encrypted_part(&self, passphrase: Option<&str>) -> parse::Result> { + pub fn decrypt_encrypted_part(&self, passphrase: Option<&str>) -> cluelessh_format::Result> { let mut data = self.encrypted_private_keys.clone(); if self.requires_passphrase() { let Some(passphrase) = passphrase else { panic!("missing passphrase for encrypted key"); }; if passphrase.is_empty() { - return Err(parse::ParseError(format!("empty passphrase"))); + return Err(cluelessh_format::ParseError(format!("empty passphrase"))); } let (key_size, iv_size) = self.cipher.key_iv_size(); @@ -140,14 +138,14 @@ impl EncryptedPrivateKeys { pub fn parse_private( &self, passphrase: Option<&str>, - ) -> parse::Result> { + ) -> cluelessh_format::Result> { let data = self.decrypt_encrypted_part(passphrase)?; - let mut p = Parser::new(&data); + let mut p = Reader::new(&data); let checkint1 = p.u32()?; let checkint2 = p.u32()?; if checkint1 != checkint2 { - return Err(parse::ParseError(format!("invalid key or password"))); + return Err(cluelessh_format::ParseError(format!("invalid key or password"))); } let mut result_keys = Vec::new(); @@ -158,17 +156,17 @@ impl EncryptedPrivateKeys { // let alg = p.utf8_string()?; if alg != "ssh-ed25519" { - return Err(parse::ParseError(format!( + return Err(cluelessh_format::ParseError(format!( "algorithm mismatch. pubkey: ssh-ed25519, privkey: {alg}" ))); } let enc_a = p.string()?; // ENC(A) if enc_a != public_key { - return Err(parse::ParseError(format!("public key mismatch"))); + return Err(cluelessh_format::ParseError(format!("public key mismatch"))); } let k_enc_a = p.string()?; // k || ENC(A) if k_enc_a.len() != 64 { - return Err(parse::ParseError(format!( + return Err(cluelessh_format::ParseError(format!( "invalid len for ed25519 keypair: {}, expected 64", k_enc_a.len() ))); @@ -176,7 +174,7 @@ impl EncryptedPrivateKeys { let (k, enc_a) = k_enc_a.split_at(32); if enc_a != public_key { // Yes, ed25519 SSH keys seriously store the public key THREE TIMES. - return Err(parse::ParseError(format!("public key mismatch"))); + return Err(cluelessh_format::ParseError(format!("public key mismatch"))); } let private_key = k.try_into().unwrap(); PrivateKeyType::Ed25519 { @@ -200,7 +198,7 @@ impl EncryptedPrivateKeys { if p.has_data() { let b = p.u8()?; if b != i { - return Err(parse::ParseError(format!( + return Err(cluelessh_format::ParseError(format!( "private key padding is incorrect: {b} != {i}" ))); } @@ -248,7 +246,7 @@ impl PlaintextPrivateKey { } } - pub fn encrypt(&self, params: KeyEncryptionParams) -> parse::Result { + pub fn encrypt(&self, params: KeyEncryptionParams) -> cluelessh_format::Result { let public_keys = vec![self.private_key.public_key()]; let mut enc = Writer::new(); diff --git a/lib/cluelessh-keys/src/signature.rs b/lib/cluelessh-keys/src/signature.rs index 5639c41..243f9d6 100644 --- a/lib/cluelessh-keys/src/signature.rs +++ b/lib/cluelessh-keys/src/signature.rs @@ -1,4 +1,5 @@ -use cluelessh_transport::{key::PublicKey, parse::Writer}; +use cluelessh_format::Writer; +use cluelessh_transport::key::PublicKey; // TODO SessionId newtype pub fn signature_data(session_id: [u8; 32], username: &str, pubkey: &PublicKey) -> Vec { diff --git a/lib/cluelessh-protocol/Cargo.toml b/lib/cluelessh-protocol/Cargo.toml index ffd1240..5614c61 100644 --- a/lib/cluelessh-protocol/Cargo.toml +++ b/lib/cluelessh-protocol/Cargo.toml @@ -8,6 +8,7 @@ rand = "0.8.5" cluelessh-connection = { path = "../cluelessh-connection" } cluelessh-transport = { path = "../cluelessh-transport" } tracing.workspace = true +cluelessh-format = { version = "0.1.0", path = "../cluelessh-format" } [lints] workspace = true diff --git a/lib/cluelessh-protocol/src/lib.rs b/lib/cluelessh-protocol/src/lib.rs index 9d6611e..1686ec6 100644 --- a/lib/cluelessh-protocol/src/lib.rs +++ b/lib/cluelessh-protocol/src/lib.rs @@ -266,7 +266,8 @@ impl ClientConnection { pub mod auth { use std::collections::{HashSet, VecDeque}; - use cluelessh_transport::{numbers, packet::Packet, parse::NameList, peer_error, Result}; + use cluelessh_format::NameList; + use cluelessh_transport::{numbers, packet::Packet, peer_error, Result}; use tracing::{debug, info}; pub struct ServerAuth { diff --git a/lib/cluelessh-transport/Cargo.toml b/lib/cluelessh-transport/Cargo.toml index 738714d..302e32d 100644 --- a/lib/cluelessh-transport/Cargo.toml +++ b/lib/cluelessh-transport/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +cluelessh-format = { path = "../cluelessh-format" } aes = "0.8.4" aes-gcm = "0.10.3" chacha20 = "0.9.1" diff --git a/lib/cluelessh-transport/src/client.rs b/lib/cluelessh-transport/src/client.rs index 780140d..a49e5c3 100644 --- a/lib/cluelessh-transport/src/client.rs +++ b/lib/cluelessh-transport/src/client.rs @@ -9,9 +9,9 @@ use crate::{ }, numbers, packet::{Packet, PacketTransport, ProtocolIdentParser}, - parse::{NameList, Parser, Writer}, peer_error, Msg, Result, SshRng, SshStatus, }; +use cluelessh_format::{NameList, Reader, Writer}; pub struct ClientConnection { state: ClientState, @@ -106,7 +106,7 @@ impl ClientConnection { match packet.payload.first().copied() { Some(numbers::SSH_MSG_DISCONNECT) => { // - let mut p = Parser::new(&packet.payload[1..]); + let mut p = Reader::new(&packet.payload[1..]); let reason = p.u32()?; let description = p.utf8_string()?; let _language_tag = p.utf8_string()?; @@ -120,13 +120,13 @@ impl ClientConnection { } Some(numbers::SSH_MSG_IGNORE) => { // - let mut p = Parser::new(&packet.payload[1..]); + let mut p = Reader::new(&packet.payload[1..]); let _ = p.string()?; continue; } Some(numbers::SSH_MSG_DEBUG) => { // - let mut p = Parser::new(&packet.payload[1..]); + let mut p = Reader::new(&packet.payload[1..]); let always_display = p.bool()?; let msg = p.utf8_string()?; let _language_tag = p.utf8_string()?; diff --git a/lib/cluelessh-transport/src/crypto.rs b/lib/cluelessh-transport/src/crypto.rs index 56d1032..0816474 100644 --- a/lib/cluelessh-transport/src/crypto.rs +++ b/lib/cluelessh-transport/src/crypto.rs @@ -1,11 +1,11 @@ pub mod encrypt; +use cluelessh_format::{Reader, Writer}; use p256::ecdsa::signature::Signer; use sha2::Digest; use crate::{ packet::{EncryptedPacket, MsgKind, Packet, RawPacket}, - parse::{self, Parser, Writer}, peer_error, Msg, Result, SshRng, }; @@ -157,7 +157,7 @@ pub fn hostkey_ed25519(hostkey_private: Vec) -> HostKeySigningAlgorithm { }, verify: |public_key, message, signature| { // Parse out public key - let mut public_key = Parser::new(public_key); + let mut public_key = Reader::new(public_key); let public_key_alg = public_key.string()?; if public_key_alg != b"ssh-ed25519" { return Err(peer_error!("incorrect algorithm public host key")); @@ -170,7 +170,7 @@ pub fn hostkey_ed25519(hostkey_private: Vec) -> HostKeySigningAlgorithm { .map_err(|err| peer_error!("incorrect public host key: {err}"))?; // Parse out signature - let mut signature = Parser::new(&signature.0); + let mut signature = Reader::new(&signature.0); let alg = signature.string()?; if alg != b"ssh-ed25519" { return Err(peer_error!("incorrect algorithm for signature")); @@ -473,7 +473,7 @@ fn derive_key( } pub(crate) fn encode_mpint_for_hash(key: &[u8], mut add_to_hash: impl FnMut(&[u8])) { - let (key, pad_zero) = parse::fixup_mpint(key); + let (key, pad_zero) = cluelessh_format::fixup_mpint(key); add_to_hash(&u32::to_be_bytes((key.len() + (pad_zero as usize)) as u32)); if pad_zero { add_to_hash(&[0]); diff --git a/lib/cluelessh-transport/src/key.rs b/lib/cluelessh-transport/src/key.rs index ef6d34a..f4c3530 100644 --- a/lib/cluelessh-transport/src/key.rs +++ b/lib/cluelessh-transport/src/key.rs @@ -7,7 +7,7 @@ use std::fmt::Display; use base64::Engine; use tracing::debug; -use crate::parse::{self, ParseError, Parser, Writer}; +use cluelessh_format::{ParseError, Reader, Writer}; #[derive(Debug, Clone, PartialEq, Eq)] pub enum PublicKey { @@ -17,8 +17,8 @@ pub enum PublicKey { impl PublicKey { /// Parses an SSH public key from its wire encoding as specified in /// RFC4253, RFC5656, and RFC8709. - pub fn from_wire_encoding(bytes: &[u8]) -> parse::Result { - let mut p = Parser::new(bytes); + pub fn from_wire_encoding(bytes: &[u8]) -> cluelessh_format::Result { + let mut p = Reader::new(bytes); let alg = p.utf8_string()?; let k = match alg { @@ -55,7 +55,7 @@ impl PublicKey { pub fn verify_signature(&self, data: &[u8], signature: &[u8]) -> bool { match self { PublicKey::Ed25519 { public_key } => { - let mut s = Parser::new(signature); + let mut s = Reader::new(signature); let Ok(alg) = s.utf8_string() else { return false; }; diff --git a/lib/cluelessh-transport/src/lib.rs b/lib/cluelessh-transport/src/lib.rs index 8a189b0..56324ef 100644 --- a/lib/cluelessh-transport/src/lib.rs +++ b/lib/cluelessh-transport/src/lib.rs @@ -3,9 +3,9 @@ mod crypto; pub mod key; pub mod numbers; pub mod packet; -pub mod parse; pub mod server; +use cluelessh_format::ParseError; pub use packet::Msg; #[derive(Debug)] @@ -21,6 +21,13 @@ pub enum SshStatus { pub type Result = std::result::Result; +impl From for SshStatus { + fn from(err: ParseError) -> Self { + Self::PeerError(err.0) + } +} + + pub trait SshRng { fn fill_bytes(&mut self, dest: &mut [u8]); } diff --git a/lib/cluelessh-transport/src/packet.rs b/lib/cluelessh-transport/src/packet.rs index b462e98..83b8296 100644 --- a/lib/cluelessh-transport/src/packet.rs +++ b/lib/cluelessh-transport/src/packet.rs @@ -6,7 +6,7 @@ use std::mem; use tracing::{debug, trace}; use crate::crypto::{self, EncryptionAlgorithm, Keys, Plaintext, Session}; -use crate::parse::{NameList, Parser, Writer}; +use cluelessh_format::{NameList, Reader, Writer}; use crate::Result; use crate::{numbers, peer_error}; @@ -214,8 +214,8 @@ impl Packet { new } - pub fn payload_parser(&self) -> Parser<'_> { - Parser::new(&self.payload) + pub fn payload_parser(&self) -> Reader<'_> { + Reader::new(&self.payload) } } @@ -250,7 +250,7 @@ pub(crate) struct KeyExchangeInitPacket<'a> { impl<'a> KeyExchangeInitPacket<'a> { pub(crate) fn parse(payload: &'a [u8]) -> Result> { - let mut c = Parser::new(payload); + let mut c = Reader::new(payload); let kind = c.u8()?; if kind != numbers::SSH_MSG_KEXINIT { @@ -317,7 +317,7 @@ pub(crate) struct KeyExchangeEcDhInitPacket<'a> { } impl<'a> KeyExchangeEcDhInitPacket<'a> { pub(crate) fn parse(payload: &'a [u8]) -> Result> { - let mut c = Parser::new(payload); + let mut c = Reader::new(payload); let kind = c.u8()?; if kind != numbers::SSH_MSG_KEX_ECDH_INIT { diff --git a/lib/cluelessh-transport/src/packet/ctors.rs b/lib/cluelessh-transport/src/packet/ctors.rs index d3ddb97..6002ad0 100644 --- a/lib/cluelessh-transport/src/packet/ctors.rs +++ b/lib/cluelessh-transport/src/packet/ctors.rs @@ -1,11 +1,11 @@ use crate::packet::Packet; -use crate::parse::Writer; +use cluelessh_format::Writer; #[allow(non_camel_case_types)] mod ssh_type_to_rust { pub(super) use {bool, u32, u8}; pub(super) type string<'a> = &'a [u8]; - pub(super) type name_list<'a> = crate::parse::NameList<'a>; + pub(super) type name_list<'a> = cluelessh_format::NameList<'a>; } macro_rules! ctors { diff --git a/lib/cluelessh-transport/src/server.rs b/lib/cluelessh-transport/src/server.rs index b1370cc..13d5f28 100644 --- a/lib/cluelessh-transport/src/server.rs +++ b/lib/cluelessh-transport/src/server.rs @@ -6,7 +6,7 @@ use crate::crypto::{ use crate::packet::{ KeyExchangeEcDhInitPacket, KeyExchangeInitPacket, Packet, PacketTransport, ProtocolIdentParser, }; -use crate::parse::{NameList, Parser, Writer}; +use cluelessh_format::{NameList, Reader, Writer}; use crate::{numbers, Result}; use crate::{peer_error, Msg, SshRng, SshStatus}; use tracing::{debug, info, trace}; @@ -91,7 +91,7 @@ impl ServerConnection { match packet.payload.first().copied() { Some(numbers::SSH_MSG_DISCONNECT) => { // - let mut disconnect = Parser::new(&packet.payload[1..]); + let mut disconnect = Reader::new(&packet.payload[1..]); let reason = disconnect.u32()?; let description = disconnect.utf8_string()?; let _language_tag = disconnect.utf8_string()?; @@ -105,13 +105,13 @@ impl ServerConnection { } Some(numbers::SSH_MSG_IGNORE) => { // - let mut p = Parser::new(&packet.payload[1..]); + let mut p = Reader::new(&packet.payload[1..]); let _ = p.string()?; continue; } Some(numbers::SSH_MSG_DEBUG) => { // - let mut p = Parser::new(&packet.payload[1..]); + let mut p = Reader::new(&packet.payload[1..]); let always_display = p.bool()?; let msg = p.utf8_string()?; let _language_tag = p.utf8_string()?; @@ -300,7 +300,7 @@ impl ServerConnection { if packet.payload.first() != Some(&numbers::SSH_MSG_SERVICE_REQUEST) { return Err(peer_error!("did not send SSH_MSG_SERVICE_REQUEST")); } - let mut p = Parser::new(&packet.payload[1..]); + let mut p = Reader::new(&packet.payload[1..]); let service = p.utf8_string()?; debug!(%service, "Client requesting service");