feat: added the ability to run commands remotely
commands can now be sent and their outputs received
This commit is contained in:
parent
52538ac7d7
commit
9bb31ee6fa
@ -67,7 +67,7 @@ impl Connection {
|
|||||||
bail!("received packet from wrong computer");
|
bail!("received packet from wrong computer");
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg!(self.decrypt_and_verify(&buffer[..read]))
|
self.decrypt_and_verify(&buffer[..read])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,12 +25,13 @@ impl ConnectionHandle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct ConnectionInformation {
|
struct ConnectionInformation {
|
||||||
remote_sign_pubkey: ed25519_dalek::PublicKey,
|
remote_sign_pubkey: ed25519_dalek::PublicKey,
|
||||||
remote_enc_pubkey: ecies_ed25519::PublicKey,
|
remote_enc_pubkey: ecies_ed25519::PublicKey,
|
||||||
local_sign_keypair: Keypair,
|
local_sign_keypair: Arc<Keypair>,
|
||||||
local_enc_pubkey: ecies_ed25519::PublicKey,
|
local_enc_pubkey: ecies_ed25519::PublicKey,
|
||||||
local_enc_privkey: ecies_ed25519::SecretKey,
|
local_enc_privkey: Arc<ecies_ed25519::SecretKey>,
|
||||||
srcmac: [u8; 6],
|
srcmac: [u8; 6],
|
||||||
dstmac: [u8; 6],
|
dstmac: [u8; 6],
|
||||||
srcip: Ipv4Addr,
|
srcip: Ipv4Addr,
|
||||||
@ -131,8 +132,8 @@ pub fn spawn_connection_handler(
|
|||||||
ConnectionInformation {
|
ConnectionInformation {
|
||||||
remote_sign_pubkey: (*sign_pubkey).clone(),
|
remote_sign_pubkey: (*sign_pubkey).clone(),
|
||||||
remote_enc_pubkey: (*enc_pubkey).clone(),
|
remote_enc_pubkey: (*enc_pubkey).clone(),
|
||||||
local_sign_keypair,
|
local_sign_keypair: Arc::new(local_sign_keypair),
|
||||||
local_enc_privkey,
|
local_enc_privkey: Arc::new(local_enc_privkey),
|
||||||
local_enc_pubkey,
|
local_enc_pubkey,
|
||||||
srcmac: *packet.source_address(),
|
srcmac: *packet.source_address(),
|
||||||
dstmac: *packet.destination_address(),
|
dstmac: *packet.destination_address(),
|
||||||
@ -250,7 +251,7 @@ where
|
|||||||
|
|
||||||
match data {
|
match data {
|
||||||
Command::RunCommand(comm) => {
|
Command::RunCommand(comm) => {
|
||||||
let handler = match command::spawn_command(&s, comm, &conninfo) {
|
let handler = match command::spawn_command(&s, comm, conninfo.clone()) {
|
||||||
Ok(handler) => handler,
|
Ok(handler) => handler,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("error spawning command: {e:?}");
|
eprintln!("error spawning command: {e:?}");
|
||||||
|
|||||||
@ -2,10 +2,11 @@ use std::{
|
|||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
process::{Command, Stdio},
|
process::{Command, Stdio},
|
||||||
sync::{
|
sync::{
|
||||||
atomic::AtomicU64,
|
atomic::{AtomicBool, AtomicU64, Ordering},
|
||||||
mpsc::{channel, Sender},
|
mpsc::{channel, Sender},
|
||||||
|
Arc,
|
||||||
},
|
},
|
||||||
thread::Scope,
|
thread::{scope, Scope},
|
||||||
};
|
};
|
||||||
|
|
||||||
use sparse_05_common::messages::Response;
|
use sparse_05_common::messages::Response;
|
||||||
@ -22,7 +23,7 @@ pub(super) struct CommandHandler {
|
|||||||
pub(super) fn spawn_command<'a, 'b: 'a>(
|
pub(super) fn spawn_command<'a, 'b: 'a>(
|
||||||
s: &'a Scope<'a, 'b>,
|
s: &'a Scope<'a, 'b>,
|
||||||
command: String,
|
command: String,
|
||||||
conninfo: &'a ConnectionInformation,
|
conninfo: ConnectionInformation,
|
||||||
) -> anyhow::Result<CommandHandler> {
|
) -> anyhow::Result<CommandHandler> {
|
||||||
let (data_sender, data_receiver) = channel();
|
let (data_sender, data_receiver) = channel();
|
||||||
|
|
||||||
@ -41,10 +42,16 @@ pub(super) fn spawn_command<'a, 'b: 'a>(
|
|||||||
|
|
||||||
let resp = Response::AckRunCommand(id);
|
let resp = Response::AckRunCommand(id);
|
||||||
conninfo.send(conninfo.encrypt_and_sign_resp(resp)?)?;
|
conninfo.send(conninfo.encrypt_and_sign_resp(resp)?)?;
|
||||||
|
let data_sender_2 = data_sender.clone();
|
||||||
|
|
||||||
s.spawn(move || -> anyhow::Result<()> {
|
s.spawn(move || -> anyhow::Result<()> {
|
||||||
if let Some(mut stdout) = command.stdout.take() {
|
let should_die = AtomicBool::new(false);
|
||||||
s.spawn(move || {
|
scope(|s2| -> anyhow::Result<()> {
|
||||||
|
let stdout_thread = if let Some(mut stdout) = command.stdout.take() {
|
||||||
|
Some(s2.spawn({
|
||||||
|
let conninfo = conninfo.clone();
|
||||||
|
let should_die = &should_die;
|
||||||
|
move || {
|
||||||
let mut stdout_buffer = [0u8; 1024];
|
let mut stdout_buffer = [0u8; 1024];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@ -52,17 +59,31 @@ pub(super) fn spawn_command<'a, 'b: 'a>(
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if should_die.load(Ordering::Relaxed) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let resp = Response::SendStdout(stdout_buffer[..count].to_vec(), id);
|
let resp = Response::SendStdout(stdout_buffer[..count].to_vec(), id);
|
||||||
let Ok(packet) = conninfo.encrypt_and_sign_resp(resp) else {
|
let Ok(packet) = conninfo.encrypt_and_sign_resp(resp) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
_ = conninfo.send(packet);
|
_ = conninfo.send(packet);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(mut stderr) = command.stderr.take() {
|
let stderr_thread = if let Some(mut stderr) = command.stderr.take() {
|
||||||
s.spawn(move || {
|
Some(s2.spawn({
|
||||||
|
let conninfo = conninfo.clone();
|
||||||
|
let should_die = &should_die;
|
||||||
|
move || {
|
||||||
let mut stderr_buffer = [0u8; 1024];
|
let mut stderr_buffer = [0u8; 1024];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@ -70,33 +91,71 @@ pub(super) fn spawn_command<'a, 'b: 'a>(
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if should_die.load(Ordering::Relaxed) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let resp = Response::SendStderr(stderr_buffer[..count].to_vec(), id);
|
let resp = Response::SendStderr(stderr_buffer[..count].to_vec(), id);
|
||||||
let Ok(packet) = conninfo.encrypt_and_sign_resp(resp) else {
|
let Ok(packet) = conninfo.encrypt_and_sign_resp(resp) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
_ = conninfo.send(packet);
|
_ = conninfo.send(packet);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let stdin_thread = if let Some(mut stdin) = command.stdin.take() {
|
||||||
|
Some(s2.spawn({
|
||||||
|
let should_die = &should_die;
|
||||||
|
move || loop {
|
||||||
|
let Ok(input): Result<Vec<u8>, _> =
|
||||||
|
data_receiver.recv_timeout(std::time::Duration::from_millis(250))
|
||||||
|
else {
|
||||||
|
if should_die.load(Ordering::Relaxed) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut stdin) = command.stdin.take() {
|
|
||||||
s.spawn(move || loop {
|
|
||||||
let Ok(input): Result<Vec<u8>, _> = data_receiver.recv() else {
|
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
_ = stdin.write(&input);
|
if should_die.load(Ordering::Relaxed) {
|
||||||
});
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ = stdin.write(&input);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let code = match command.wait() {
|
let code = match command.wait() {
|
||||||
Ok(status) => status.code().unwrap_or(-1),
|
Ok(status) => status.code().unwrap_or(-1),
|
||||||
Err(_) => -1,
|
Err(_) => -1,
|
||||||
};
|
};
|
||||||
|
drop(data_sender_2);
|
||||||
|
should_die.store(true, Ordering::Relaxed);
|
||||||
|
if let Some(thread) = stdout_thread {
|
||||||
|
_ = thread.join();
|
||||||
|
}
|
||||||
|
if let Some(thread) = stderr_thread {
|
||||||
|
_ = thread.join();
|
||||||
|
}
|
||||||
let resp = Response::CommandDone(id, code);
|
let resp = Response::CommandDone(id, code);
|
||||||
let resp = conninfo.encrypt_and_sign_resp(resp)?;
|
let resp = conninfo.encrypt_and_sign_resp(resp)?;
|
||||||
conninfo.send(resp)?;
|
conninfo.send(resp)?;
|
||||||
|
if let Some(thread) = stdin_thread {
|
||||||
|
_ = thread.join();
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(CommandHandler { id, data_sender })
|
Ok(CommandHandler { id, data_sender })
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user