mirror of
https://github.com/Noratrieb/cluelessh.git
synced 2026-01-16 09:25:04 +01:00
agent
This commit is contained in:
parent
9b49e09983
commit
a52b6b37d7
19 changed files with 770 additions and 92 deletions
|
|
@ -1,5 +1,4 @@
|
|||
use std::{
|
||||
io::Write,
|
||||
sync::{
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
Arc,
|
||||
|
|
@ -15,7 +14,7 @@ use tokio::{
|
|||
io::{AsyncReadExt, AsyncWriteExt},
|
||||
net::TcpStream,
|
||||
};
|
||||
use tracing::{debug, error, info};
|
||||
use tracing::{error, info};
|
||||
|
||||
use ssh_protocol::{
|
||||
transport::{self},
|
||||
|
|
@ -41,11 +40,6 @@ struct Args {
|
|||
#[arg(short = 'c', long)]
|
||||
chill: bool,
|
||||
destination: String,
|
||||
command: Vec<String>,
|
||||
}
|
||||
|
||||
enum Operation {
|
||||
PasswordEntered(std::io::Result<String>),
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
|
|
@ -86,7 +80,7 @@ async fn main() -> eyre::Result<()> {
|
|||
async fn execute_attempt(args: &Args) -> eyre::Result<()> {
|
||||
let conn = TcpStream::connect(&format!("{}:{}", args.destination, args.port)).await?;
|
||||
|
||||
let result = execute_attempt_inner(args, conn).await;
|
||||
let result = execute_attempt_inner(conn).await;
|
||||
|
||||
if args.chill {
|
||||
info!("Chilling, taking up space");
|
||||
|
|
@ -96,7 +90,7 @@ async fn execute_attempt(args: &Args) -> eyre::Result<()> {
|
|||
result
|
||||
}
|
||||
|
||||
async fn execute_attempt_inner(args: &Args, mut conn: TcpStream) -> eyre::Result<()> {
|
||||
async fn execute_attempt_inner(mut conn: TcpStream) -> eyre::Result<()> {
|
||||
let username = "dos";
|
||||
|
||||
let mut transport = transport::client::ClientConnection::new(ThreadRngRand);
|
||||
|
|
@ -107,8 +101,6 @@ async fn execute_attempt_inner(args: &Args, mut conn: TcpStream) -> eyre::Result
|
|||
ssh_protocol::auth::ClientAuth::new(username.as_bytes().to_vec()),
|
||||
);
|
||||
|
||||
let (send_op, mut recv_op) = tokio::sync::mpsc::channel::<Operation>(10);
|
||||
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
loop {
|
||||
|
|
@ -118,66 +110,33 @@ async fn execute_attempt_inner(args: &Args, mut conn: TcpStream) -> eyre::Result
|
|||
.wrap_err("writing response")?;
|
||||
}
|
||||
|
||||
if let Some(auth) = state.auth() {
|
||||
for req in auth.user_requests() {
|
||||
match req {
|
||||
ssh_protocol::auth::ClientUserRequest::Password => {
|
||||
let username = username.to_owned();
|
||||
let destination = args.destination.clone();
|
||||
let send_op = send_op.clone();
|
||||
std::thread::spawn(move || {
|
||||
let password = rpassword::prompt_password(format!(
|
||||
"{}@{}'s password: ",
|
||||
username, destination
|
||||
));
|
||||
let _ = send_op.blocking_send(Operation::PasswordEntered(password));
|
||||
});
|
||||
}
|
||||
ssh_protocol::auth::ClientUserRequest::Banner(banner) => {
|
||||
let banner = String::from_utf8_lossy(&banner);
|
||||
std::io::stdout().write(&banner.as_bytes())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(_) = state.auth() {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
tokio::select! {
|
||||
read = conn.read(&mut buf) => {
|
||||
let read = read.wrap_err("reading from connection")?;
|
||||
if read == 0 {
|
||||
info!("Did not read any bytes from TCP stream, EOF");
|
||||
let read = conn
|
||||
.read(&mut buf)
|
||||
.await
|
||||
.wrap_err("reading from connection")?;
|
||||
if read == 0 {
|
||||
info!("Did not read any bytes from TCP stream, EOF");
|
||||
return Ok(());
|
||||
}
|
||||
if let Err(err) = state.recv_bytes(&buf[..read]) {
|
||||
match err {
|
||||
SshStatus::PeerError(err) => {
|
||||
if err == "early abort" {
|
||||
// Expected.
|
||||
return Ok(());
|
||||
}
|
||||
error!(?err, "disconnecting client after invalid operation");
|
||||
return Ok(());
|
||||
}
|
||||
if let Err(err) = state.recv_bytes(&buf[..read]) {
|
||||
match err {
|
||||
SshStatus::PeerError(err) => {
|
||||
if err == "early abort" {
|
||||
// Expected.
|
||||
return Ok(());
|
||||
}
|
||||
error!(?err, "disconnecting client after invalid operation");
|
||||
return Ok(());
|
||||
}
|
||||
SshStatus::Disconnect => {
|
||||
error!("Received disconnect from server");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
SshStatus::Disconnect => {
|
||||
error!("Received disconnect from server");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
op = recv_op.recv() => {
|
||||
match op {
|
||||
Some(Operation::PasswordEntered(password)) => {
|
||||
if let Some(auth) = state.auth() {
|
||||
auth.send_password(&password?);
|
||||
} else {
|
||||
debug!("Ignoring entered password as the state has moved on");
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
state.progress();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue