mirror of
https://github.com/Noratrieb/cluelessh.git
synced 2026-01-14 16:35:06 +01:00
cleanup
This commit is contained in:
parent
b6d0675976
commit
b0acf03502
22 changed files with 84 additions and 26 deletions
|
|
@ -5,5 +5,12 @@ members = [
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
|
[workspace.lints.clippy]
|
||||||
|
type_complexity = "allow"
|
||||||
|
too_many_arguments = "allow"
|
||||||
|
new_without_default = "allow"
|
||||||
|
useless_format = "allow"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
|
eyre = "0.6.12"
|
||||||
|
|
@ -8,10 +8,13 @@ cluelessh-agent-client = { path = "../../lib/cluelessh-agent-client" }
|
||||||
cluelessh-transport = { path = "../../lib/cluelessh-transport" }
|
cluelessh-transport = { path = "../../lib/cluelessh-transport" }
|
||||||
|
|
||||||
clap = { version = "4.5.16", features = ["derive"] }
|
clap = { version = "4.5.16", features = ["derive"] }
|
||||||
eyre = "0.6.12"
|
eyre.workspace = true
|
||||||
tokio = { version = "1.39.3", features = ["full"] }
|
tokio = { version = "1.39.3", features = ["full"] }
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||||
rpassword = "7.3.1"
|
rpassword = "7.3.1"
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.8"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
pem = "3.0.4"
|
pem = "3.0.4"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ edition = "2021"
|
||||||
cluelessh-protocol = { path = "../../lib/cluelessh-protocol" }
|
cluelessh-protocol = { path = "../../lib/cluelessh-protocol" }
|
||||||
cluelessh-transport = { path = "../../lib/cluelessh-transport" }
|
cluelessh-transport = { path = "../../lib/cluelessh-transport" }
|
||||||
clap = { version = "4.5.15", features = ["derive"] }
|
clap = { version = "4.5.15", features = ["derive"] }
|
||||||
eyre = "0.6.12"
|
eyre.workspace = true
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
tokio = { version = "1.39.2", features = ["full"] }
|
tokio = { version = "1.39.2", features = ["full"] }
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["json", "env-filter"] }
|
tracing-subscriber = { version = "0.3.18", features = ["json", "env-filter"] }
|
||||||
|
|
@ -15,3 +15,6 @@ tracing-subscriber = { version = "0.3.18", features = ["json", "env-filter"] }
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
rpassword = "7.3.1"
|
rpassword = "7.3.1"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ async fn execute_attempt_inner(mut conn: TcpStream) -> eyre::Result<()> {
|
||||||
.wrap_err("writing response")?;
|
.wrap_err("writing response")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(_) = state.auth() {
|
if state.auth().is_some() {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
eyre = "0.6.12"
|
eyre.workspace = true
|
||||||
hex-literal = "0.4.1"
|
hex-literal = "0.4.1"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
cluelessh-protocol = { path = "../../lib/cluelessh-protocol" }
|
cluelessh-protocol = { path = "../../lib/cluelessh-protocol" }
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,13 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.5.16", features = ["derive"] }
|
clap = { version = "4.5.16", features = ["derive"] }
|
||||||
eyre = "0.6.12"
|
eyre.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
|
|
||||||
cluelessh-keys = { path = "../../lib/cluelessh-keys" }
|
cluelessh-keys = { path = "../../lib/cluelessh-keys" }
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
rpassword = "7.3.1"
|
rpassword = "7.3.1"
|
||||||
pem = "3.0.4"
|
pem = "3.0.4"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ fn info(id_file: &Path, decrypt: bool, show_private: bool) -> eyre::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let file =
|
let file =
|
||||||
std::fs::read(&id_file).wrap_err_with(|| format!("reading file {}", id_file.display()))?;
|
std::fs::read(id_file).wrap_err_with(|| format!("reading file {}", id_file.display()))?;
|
||||||
|
|
||||||
let keys = cluelessh_keys::EncryptedPrivateKeys::parse(&file)?;
|
let keys = cluelessh_keys::EncryptedPrivateKeys::parse(&file)?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ cluelessh-agent-client = { path = "../../lib/cluelessh-agent-client" }
|
||||||
cluelessh-tokio = { path = "../../lib/cluelessh-tokio" }
|
cluelessh-tokio = { path = "../../lib/cluelessh-tokio" }
|
||||||
|
|
||||||
clap = { version = "4.5.15", features = ["derive"] }
|
clap = { version = "4.5.15", features = ["derive"] }
|
||||||
eyre = "0.6.12"
|
eyre.workspace = true
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
tokio = { version = "1.39.2", features = ["full"] }
|
tokio = { version = "1.39.2", features = ["full"] }
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["json", "env-filter"] }
|
tracing-subscriber = { version = "0.3.18", features = ["json", "env-filter"] }
|
||||||
|
|
@ -18,3 +18,6 @@ tracing-subscriber = { version = "0.3.18", features = ["json", "env-filter"] }
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
rpassword = "7.3.1"
|
rpassword = "7.3.1"
|
||||||
users = "0.11.0"
|
users = "0.11.0"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -59,11 +59,10 @@ async fn main() -> eyre::Result<()> {
|
||||||
let destination = args.destination.clone();
|
let destination = args.destination.clone();
|
||||||
Box::pin(async {
|
Box::pin(async {
|
||||||
let result = tokio::task::spawn_blocking(move || {
|
let result = tokio::task::spawn_blocking(move || {
|
||||||
let password = rpassword::prompt_password(format!(
|
rpassword::prompt_password(format!(
|
||||||
"{}@{}'s password: ",
|
"{}@{}'s password: ",
|
||||||
username, destination
|
username, destination
|
||||||
));
|
))
|
||||||
password
|
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
result.wrap_err("failed to prompt password")
|
result.wrap_err("failed to prompt password")
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,6 @@ edition = "2021"
|
||||||
cluelessh-protocol = { path = "../../lib/cluelessh-protocol" }
|
cluelessh-protocol = { path = "../../lib/cluelessh-protocol" }
|
||||||
cluelessh-tokio = { path = "../../lib/cluelessh-tokio" }
|
cluelessh-tokio = { path = "../../lib/cluelessh-tokio" }
|
||||||
cluelessh-transport = { path = "../../lib/cluelessh-transport" }
|
cluelessh-transport = { path = "../../lib/cluelessh-transport" }
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
eyre = "0.6.12"
|
eyre.workspace = true
|
||||||
cluelessh-transport = { path = "../cluelessh-transport" }
|
cluelessh-transport = { path = "../cluelessh-transport" }
|
||||||
tokio = { version = "1.39.3", features = ["net"] }
|
tokio = { version = "1.39.3", features = ["net"] }
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ impl Request {
|
||||||
} => {
|
} => {
|
||||||
p.u8(numbers::SSH_AGENTC_ADD_IDENTITY);
|
p.u8(numbers::SSH_AGENTC_ADD_IDENTITY);
|
||||||
p.string(key_type.as_bytes());
|
p.string(key_type.as_bytes());
|
||||||
p.raw(&key_contents);
|
p.raw(key_contents);
|
||||||
p.string(key_comment.as_bytes());
|
p.string(key_comment.as_bytes());
|
||||||
}
|
}
|
||||||
Self::RemoveAllIdentities => p.u8(numbers::SSH_AGENTC_REMOVE_ALL_IDENTITIES),
|
Self::RemoveAllIdentities => p.u8(numbers::SSH_AGENTC_REMOVE_ALL_IDENTITIES),
|
||||||
|
|
@ -56,8 +56,8 @@ impl Request {
|
||||||
flags,
|
flags,
|
||||||
} => {
|
} => {
|
||||||
p.u8(numbers::SSH_AGENTC_SIGN_REQUEST);
|
p.u8(numbers::SSH_AGENTC_SIGN_REQUEST);
|
||||||
p.string(&key_blob);
|
p.string(key_blob);
|
||||||
p.string(&data);
|
p.string(data);
|
||||||
p.u32(*flags);
|
p.u32(*flags);
|
||||||
}
|
}
|
||||||
Self::Lock { passphrase } => {
|
Self::Lock { passphrase } => {
|
||||||
|
|
@ -186,7 +186,7 @@ impl AgentConnection {
|
||||||
mut bytes: &'a [u8],
|
mut bytes: &'a [u8],
|
||||||
) -> impl Iterator<Item = eyre::Result<ServerResponse>> + 'a {
|
) -> impl Iterator<Item = eyre::Result<ServerResponse>> + 'a {
|
||||||
std::iter::from_fn(move || -> Option<eyre::Result<ServerResponse>> {
|
std::iter::from_fn(move || -> Option<eyre::Result<ServerResponse>> {
|
||||||
if bytes.len() == 0 {
|
if bytes.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
match self.packets.recv_plaintext_bytes(bytes) {
|
match self.packets.recv_plaintext_bytes(bytes) {
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,6 @@ tracing.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,6 @@ ed25519-dalek = { version = "2.1.1", features = ["rand_core"] }
|
||||||
pem = "3.0.4"
|
pem = "3.0.4"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
cluelessh-transport = { path = "../cluelessh-transport" }
|
cluelessh-transport = { path = "../cluelessh-transport" }
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -92,12 +92,12 @@ impl EncryptedPrivateKeys {
|
||||||
p.array(*MAGIC);
|
p.array(*MAGIC);
|
||||||
p.string(self.cipher.name().as_bytes());
|
p.string(self.cipher.name().as_bytes());
|
||||||
p.string(self.kdf.name().as_bytes());
|
p.string(self.kdf.name().as_bytes());
|
||||||
p.string(&self.kdf.options());
|
p.string(self.kdf.options());
|
||||||
|
|
||||||
p.u32(self.public_keys.len() as u32);
|
p.u32(self.public_keys.len() as u32);
|
||||||
|
|
||||||
for pubkey in &self.public_keys {
|
for pubkey in &self.public_keys {
|
||||||
p.string(&pubkey.to_wire_encoding());
|
p.string(pubkey.to_wire_encoding());
|
||||||
}
|
}
|
||||||
|
|
||||||
p.string(&self.encrypted_private_keys);
|
p.string(&self.encrypted_private_keys);
|
||||||
|
|
@ -124,7 +124,7 @@ impl EncryptedPrivateKeys {
|
||||||
let mut output = vec![0; key_size + iv_size];
|
let mut output = vec![0; key_size + iv_size];
|
||||||
self.kdf.derive(passphrase, &mut output)?;
|
self.kdf.derive(passphrase, &mut output)?;
|
||||||
let (key, iv) = output.split_at(key_size);
|
let (key, iv) = output.split_at(key_size);
|
||||||
self.cipher.crypt_in_place(&mut data, &key, &iv);
|
self.cipher.crypt_in_place(&mut data, key, iv);
|
||||||
}
|
}
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
@ -254,12 +254,12 @@ impl PlaintextPrivateKey {
|
||||||
} => {
|
} => {
|
||||||
// <https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent#section-3.2.3>
|
// <https://datatracker.ietf.org/doc/html/draft-miller-ssh-agent#section-3.2.3>
|
||||||
enc.string(b"ssh-ed25519");
|
enc.string(b"ssh-ed25519");
|
||||||
enc.string(&public_key);
|
enc.string(public_key);
|
||||||
let combined = private_key.len() + public_key.len();
|
let combined = private_key.len() + public_key.len();
|
||||||
enc.u32(combined as u32);
|
enc.u32(combined as u32);
|
||||||
enc.raw(&private_key);
|
enc.raw(&private_key);
|
||||||
enc.raw(&public_key);
|
enc.raw(&public_key);
|
||||||
enc.string(&self.comment.as_bytes());
|
enc.string(self.comment.as_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -282,7 +282,7 @@ impl PlaintextPrivateKey {
|
||||||
let (key, iv) = output.split_at(key_size);
|
let (key, iv) = output.split_at(key_size);
|
||||||
params
|
params
|
||||||
.cipher
|
.cipher
|
||||||
.crypt_in_place(&mut encrypted_private_keys, &key, &iv);
|
.crypt_in_place(&mut encrypted_private_keys, key, iv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,5 @@ cluelessh-connection = { path = "../cluelessh-connection" }
|
||||||
cluelessh-transport = { path = "../cluelessh-transport" }
|
cluelessh-transport = { path = "../cluelessh-transport" }
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,13 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
eyre = "0.6.12"
|
eyre.workspace = true
|
||||||
cluelessh-transport = { path = "../cluelessh-transport" }
|
cluelessh-transport = { path = "../cluelessh-transport" }
|
||||||
cluelessh-connection = { path = "../cluelessh-connection" }
|
cluelessh-connection = { path = "../cluelessh-connection" }
|
||||||
cluelessh-protocol = { path = "../cluelessh-protocol" }
|
cluelessh-protocol = { path = "../cluelessh-protocol" }
|
||||||
tokio = { version = "1.39.3", features = ["net"] }
|
tokio = { version = "1.39.3", features = ["net"] }
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::{collections::HashMap, pin::Pin, sync::Arc};
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
|
||||||
use cluelessh_protocol::{ChannelUpdateKind, SshStatus};
|
use cluelessh_protocol::{ChannelUpdateKind, SshStatus};
|
||||||
use eyre::{bail, ContextCompat, OptionExt, Result, WrapErr};
|
use eyre::{bail, ContextCompat, Result, WrapErr};
|
||||||
use futures::future::BoxFuture;
|
use futures::future::BoxFuture;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite};
|
use tokio::io::{AsyncRead, AsyncWrite};
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,6 @@ base64 = "0.22.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex-literal = "0.4.1"
|
hex-literal = "0.4.1"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ pub fn hostkey_ed25519(hostkey_private: Vec<u8>) -> HostKeySigningAlgorithm {
|
||||||
// <https://datatracker.ietf.org/doc/html/rfc8709#section-6>
|
// <https://datatracker.ietf.org/doc/html/rfc8709#section-6>
|
||||||
let mut data = Writer::new();
|
let mut data = Writer::new();
|
||||||
data.string(b"ssh-ed25519");
|
data.string(b"ssh-ed25519");
|
||||||
data.string(&signature.to_bytes());
|
data.string(signature.to_bytes());
|
||||||
EncodedSshSignature(data.finish())
|
EncodedSshSignature(data.finish())
|
||||||
},
|
},
|
||||||
verify: |public_key, message, signature| {
|
verify: |public_key, message, signature| {
|
||||||
|
|
@ -216,7 +216,7 @@ pub fn hostkey_ecdsa_sha2_p256(hostkey_private: Vec<u8>) -> HostKeySigningAlgori
|
||||||
let mut signature_blob = Writer::new();
|
let mut signature_blob = Writer::new();
|
||||||
signature_blob.mpint(p256::U256::from(r.as_ref()));
|
signature_blob.mpint(p256::U256::from(r.as_ref()));
|
||||||
signature_blob.mpint(p256::U256::from(s.as_ref()));
|
signature_blob.mpint(p256::U256::from(s.as_ref()));
|
||||||
data.string(&signature_blob.finish());
|
data.string(signature_blob.finish());
|
||||||
EncodedSshSignature(data.finish())
|
EncodedSshSignature(data.finish())
|
||||||
},
|
},
|
||||||
verify: |_public_key, _message, _signature| todo!("ecdsa p256 verification"),
|
verify: |_public_key, _message, _signature| todo!("ecdsa p256 verification"),
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remaining(&self) -> &[u8] {
|
pub fn remaining(&self) -> &[u8] {
|
||||||
&self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_data(&self) -> bool {
|
pub fn has_data(&self) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,26 @@ impl ServerConnection {
|
||||||
|
|
||||||
return Err(SshStatus::Disconnect);
|
return Err(SshStatus::Disconnect);
|
||||||
}
|
}
|
||||||
|
Some(numbers::SSH_MSG_IGNORE) => {
|
||||||
|
// <https://datatracker.ietf.org/doc/html/rfc4253#section-11.2>
|
||||||
|
let mut p = Parser::new(&packet.payload[1..]);
|
||||||
|
let _ = p.string()?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Some(numbers::SSH_MSG_DEBUG) => {
|
||||||
|
// <https://datatracker.ietf.org/doc/html/rfc4253#section-11.3>
|
||||||
|
let mut p = Parser::new(&packet.payload[1..]);
|
||||||
|
let always_display = p.bool()?;
|
||||||
|
let msg = p.utf8_string()?;
|
||||||
|
let _language_tag = p.utf8_string()?;
|
||||||
|
|
||||||
|
if always_display {
|
||||||
|
info!(%msg, "Received debug message (SSH_MSG_DEBUG)");
|
||||||
|
} else {
|
||||||
|
debug!(%msg, "Received debug message (SSH_MSG_DEBUG)")
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue