feat: added a basic interactivity to the client
This commit is contained in:
parent
7876e00dc8
commit
7f1f43a601
134
Cargo.lock
generated
134
Cargo.lock
generated
@ -263,6 +263,18 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d944ac6003ed268757ef1ee686753b57efc5fcf0ebe7b64c9fc81e7e32ff839"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"rustc_version",
|
||||
"syn 0.15.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.9.0"
|
||||
@ -443,8 +455,8 @@ version = "0.3.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.33",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
@ -700,8 +712,8 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f35583365be5d148e959284f42526841917b7bfa09e2d1a7ad5dde2cf0eaa39"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.33",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
@ -760,8 +772,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.33",
|
||||
"syn 1.0.109",
|
||||
"version_check",
|
||||
]
|
||||
@ -772,11 +784,20 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.33",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.66"
|
||||
@ -786,13 +807,22 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2 1.0.66",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -836,6 +866,16 @@ dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw_tty"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51f512d7504049ef0d3f5d48d8aa5129beaea4fccfaf5c500c9b60101394f8b1"
|
||||
dependencies = [
|
||||
"derive_more",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rmp"
|
||||
version = "0.8.12"
|
||||
@ -864,6 +904,30 @@ version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.188"
|
||||
@ -888,8 +952,8 @@ version = "1.0.188"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.33",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
@ -899,8 +963,8 @@ version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.33",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
@ -968,10 +1032,13 @@ dependencies = [
|
||||
name = "sparse-05-client"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"anyhow",
|
||||
"ecies-ed25519",
|
||||
"ed25519-dalek",
|
||||
"libc",
|
||||
"rand",
|
||||
"raw_tty",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
"sparse-05-common",
|
||||
@ -1044,8 +1111,8 @@ checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.33",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
@ -1055,14 +1122,25 @@ version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.33",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
@ -1072,8 +1150,8 @@ version = "2.0.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.33",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
@ -1101,8 +1179,8 @@ version = "1.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.33",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
@ -1159,8 +1237,8 @@ version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.33",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
@ -1199,6 +1277,12 @@ version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
|
||||
[[package]]
|
||||
name = "universal-hash"
|
||||
version = "0.4.1"
|
||||
@ -1417,7 +1501,7 @@ version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 1.0.66",
|
||||
"quote 1.0.33",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
@ -4,10 +4,13 @@ version = "0.5.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
ansi_term = "0.12.1"
|
||||
anyhow = "1.0.75"
|
||||
ecies-ed25519 = { version = "0.5.1", features = ["serde"] }
|
||||
ed25519-dalek = "1.0.1"
|
||||
libc = "0.2.147"
|
||||
rand = "0.7"
|
||||
raw_tty = "0.1.0"
|
||||
rmp-serde = "1.1.2"
|
||||
serde = { version = "1.0.188", features = ["derive"] }
|
||||
sparse-05-common = { version = "0.1.0", path = "../sparse-05-common" }
|
||||
|
||||
@ -0,0 +1 @@
|
||||
pub mod sysinfo;
|
||||
@ -0,0 +1,71 @@
|
||||
use sparse_05_common::messages::{Capabilities, OperatingSystem};
|
||||
|
||||
pub fn print_capabilities(capabilities: &Capabilities) {
|
||||
use ansi_term::Colour as Color;
|
||||
|
||||
println!("Capabilities of remote host:");
|
||||
println!(
|
||||
"\tOperating system: \t{}",
|
||||
match &capabilities.operating_system {
|
||||
OperatingSystem::Linux => "Linux",
|
||||
OperatingSystem::Windows => "Windows",
|
||||
}
|
||||
);
|
||||
println!(
|
||||
"\tInside a container: \t{}",
|
||||
if capabilities.docker_container {
|
||||
"yes"
|
||||
} else {
|
||||
"no"
|
||||
}
|
||||
);
|
||||
if capabilities.docker_container {
|
||||
println!(
|
||||
"\tContainer breakout: \t{}",
|
||||
if capabilities.docker_breakout {
|
||||
Color::Green.paint("successful")
|
||||
} else {
|
||||
Color::Red.paint("unsuccessful")
|
||||
}
|
||||
);
|
||||
}
|
||||
println!(
|
||||
"\tRemote user: \t\t{}",
|
||||
match &capabilities.userent {
|
||||
Some(user) => Color::White.paint(user),
|
||||
None => Color::Red.paint("unknown"),
|
||||
}
|
||||
);
|
||||
match capabilities.operating_system {
|
||||
OperatingSystem::Linux => {
|
||||
println!(
|
||||
"\tAdmin user: \t\t{}",
|
||||
match (capabilities.root, capabilities.setuid) {
|
||||
(false, false) => Color::Red.paint("no"),
|
||||
(_, _) => Color::Green.paint("yes"),
|
||||
}
|
||||
);
|
||||
println!(
|
||||
"\tsetuid capability: \t{}",
|
||||
match capabilities.setuid {
|
||||
true => Color::Green.paint("yes"),
|
||||
false => Color::Red.paint("no"),
|
||||
}
|
||||
);
|
||||
}
|
||||
OperatingSystem::Windows => {
|
||||
println!(
|
||||
"\tAdmin user: \t\t{}",
|
||||
match capabilities.root {
|
||||
true => Color::Green.paint("yes"),
|
||||
false => Color::Red.paint("no"),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
println!("\tTransport type: \t{:?}", capabilities.transport);
|
||||
println!(
|
||||
"\tHost name: \t\t{}",
|
||||
capabilities.hostname.as_deref().unwrap_or("<unknown>")
|
||||
);
|
||||
}
|
||||
@ -1,24 +1,28 @@
|
||||
use std::{net::SocketAddr, path::PathBuf, sync::Arc};
|
||||
use std::{
|
||||
io::{self, Write},
|
||||
net::SocketAddr,
|
||||
path::PathBuf,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use anyhow::{bail, Context};
|
||||
use ed25519_dalek::{Keypair, Signature, Signer, Verifier};
|
||||
use rmp_serde::decode::ReadSlice;
|
||||
use sparse_05_common::messages::{Capabilities, Response, CONNECTED_MESSAGE, CONNECT_MESSAGE};
|
||||
use sparse_05_common::messages::{
|
||||
Capabilities, Command, OperatingSystem, Response, CONNECTED_MESSAGE, CONNECT_MESSAGE,
|
||||
};
|
||||
use tokio::{fs, net::UdpSocket};
|
||||
|
||||
use crate::configs::ClientConfig;
|
||||
|
||||
enum State {
|
||||
Authenticating,
|
||||
Ready,
|
||||
UploadingFile,
|
||||
DownloadingFile,
|
||||
}
|
||||
mod commands;
|
||||
mod shell;
|
||||
|
||||
struct Connection {
|
||||
config: ClientConfig,
|
||||
foreign_sign_pubkey: ed25519_dalek::PublicKey,
|
||||
foreign_enc_pubkey: ecies_ed25519::PublicKey,
|
||||
socket: Arc<UdpSocket>,
|
||||
ip: SocketAddr,
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
@ -44,6 +48,27 @@ impl Connection {
|
||||
|
||||
Ok([&signature.to_bytes(), &*data].concat())
|
||||
}
|
||||
|
||||
async fn send_command(&self, command: Command) -> anyhow::Result<()> {
|
||||
let cmd = rmp_serde::to_vec(&command)?;
|
||||
|
||||
self.socket
|
||||
.send_to(&self.encrypt_and_sign(&cmd)?, self.ip)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_response(&self) -> anyhow::Result<Response> {
|
||||
let mut buffer = [0u8; 2000];
|
||||
let (read, from) = self.socket.recv_from(&mut buffer).await?;
|
||||
|
||||
if from != self.ip {
|
||||
bail!("received packet from wrong computer");
|
||||
}
|
||||
|
||||
self.decrypt_and_verify(&buffer[..read])
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn connect(config: PathBuf, ip: SocketAddr) -> anyhow::Result<()> {
|
||||
@ -58,10 +83,20 @@ pub async fn connect(config: PathBuf, ip: SocketAddr) -> anyhow::Result<()> {
|
||||
let mut counter = 0;
|
||||
|
||||
let (foreign_sign_pubkey, foreign_enc_pubkey, capabilities) = loop {
|
||||
if counter > 5 {
|
||||
if counter > 25 {
|
||||
bail!("could not connect to server");
|
||||
}
|
||||
|
||||
print!(
|
||||
"\rConnecting{}",
|
||||
match counter % 3 {
|
||||
2 => ".. ",
|
||||
1 => ". ",
|
||||
_ => "...",
|
||||
}
|
||||
);
|
||||
io::stdout().flush().unwrap();
|
||||
|
||||
remote.send_to(connect_msg, ip).await?;
|
||||
|
||||
let mut buf = [0u8; 2000];
|
||||
@ -122,17 +157,21 @@ pub async fn connect(config: PathBuf, ip: SocketAddr) -> anyhow::Result<()> {
|
||||
}
|
||||
};
|
||||
|
||||
let connection = Connection {
|
||||
let connection = Arc::new(Connection {
|
||||
config,
|
||||
foreign_enc_pubkey,
|
||||
foreign_sign_pubkey,
|
||||
};
|
||||
socket: Arc::clone(&remote),
|
||||
ip,
|
||||
});
|
||||
|
||||
remote
|
||||
.send_to(&connection.encrypt_and_sign(CONNECTED_MESSAGE)?, ip)
|
||||
.await?;
|
||||
|
||||
println!("connected! {:?}", capabilities);
|
||||
println!("\rConnected! ");
|
||||
|
||||
shell::shell(Arc::clone(&connection), capabilities).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
102
sparse-05/sparse-05-client/src/commands/connect/shell.rs
Normal file
102
sparse-05/sparse-05-client/src/commands/connect/shell.rs
Normal file
@ -0,0 +1,102 @@
|
||||
use std::{
|
||||
io::{self, Read, Write},
|
||||
os::fd::AsRawFd,
|
||||
path::PathBuf,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use sparse_05_common::messages::Capabilities;
|
||||
use tokio::net::UdpSocket;
|
||||
|
||||
use super::{commands, Connection};
|
||||
|
||||
macro_rules! libc_try {
|
||||
($expr:expr) => {
|
||||
if unsafe { $expr } == -1 {
|
||||
return Err(std::io::Error::last_os_error())?;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn get_term_attrs<F: AsRawFd>(fd: &F) -> anyhow::Result<libc::termios> {
|
||||
let mut termios = unsafe { std::mem::zeroed() };
|
||||
libc_try!(libc::tcgetattr(fd.as_raw_fd(), &mut termios));
|
||||
Ok(termios)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn set_term_attrs<F: AsRawFd>(fd: &mut F, attrs: &libc::termios) -> anyhow::Result<()> {
|
||||
libc_try!(libc::tcsetattr(fd.as_raw_fd(), 0, attrs));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn convert_termios_raw(attrs: &mut libc::termios) -> anyhow::Result<()> {
|
||||
unsafe { libc::cfmakeraw(attrs) };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) async fn shell(
|
||||
connection: Arc<Connection>,
|
||||
mut capabilities: Capabilities,
|
||||
) -> anyhow::Result<()> {
|
||||
println!("Type #help to view a list of sparse commands\n");
|
||||
|
||||
let mut stdin = io::stdin();
|
||||
let mut stdout = io::stdout();
|
||||
let backup_term_attrs = get_term_attrs(&stdin)?;
|
||||
let mut raw_term_attrs = get_term_attrs(&stdin)?;
|
||||
convert_termios_raw(&mut raw_term_attrs)?;
|
||||
|
||||
macro_rules! cmd_matcher {
|
||||
($input:expr, $(($check:ident, $matcher:expr) => {$($body:tt)*}),+, _ => {$($ebody:tt)*}) => {
|
||||
match &$input[..] {
|
||||
$($check if $check.len() >= $matcher.len() && $check[..$matcher.len()] == $matcher[..] => {
|
||||
let $check = &$check[$matcher.len()..];
|
||||
$($body)*
|
||||
}),+
|
||||
_ => {
|
||||
$($ebody)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut cwd = "/".to_string();
|
||||
|
||||
loop {
|
||||
print!(
|
||||
"{}@{}:{} {} ",
|
||||
capabilities.userent.as_deref().unwrap_or("unknown user!"),
|
||||
match &capabilities.hostname {
|
||||
Some(n) => n.clone(),
|
||||
None => format!("{}", connection.ip.ip()),
|
||||
},
|
||||
cwd,
|
||||
if capabilities.root { "#" } else { "$" }
|
||||
);
|
||||
stdout.flush().unwrap();
|
||||
|
||||
let mut cmd = [0u8; 256];
|
||||
let amount = stdin.read(&mut cmd)?;
|
||||
|
||||
if amount == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
cmd_matcher!(
|
||||
cmd[..amount],
|
||||
(_sysinfo, b"#sysinfo") => {
|
||||
commands::sysinfo::print_capabilities(&capabilities)
|
||||
},
|
||||
(_help, b"#help") => {},
|
||||
(_exit, b"#exit") => {
|
||||
break;
|
||||
},
|
||||
_ => {}
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -12,19 +12,23 @@ pub mod messages {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum Command {
|
||||
SendData(Vec<u8>),
|
||||
RunCommand(OsString),
|
||||
SendStdin(Vec<u8>, u64),
|
||||
|
||||
Cd(PathBuf),
|
||||
Ls(PathBuf),
|
||||
|
||||
OpenTTY,
|
||||
CloseTTY,
|
||||
CloseTTY(u64),
|
||||
SendRawData(Vec<u64>, u64),
|
||||
|
||||
StartUploadFile(PathBuf, u64),
|
||||
SendFileSegment(u64, u64, Vec<u8>),
|
||||
SendFileSegment(u64, u64, Vec<u64>),
|
||||
|
||||
StartDownloadFile(PathBuf, u64),
|
||||
DownloadFileStatus(Result<(), Vec<u8>>),
|
||||
StartDownloadFile(PathBuf),
|
||||
DownloadFileStatus(Result<(), Vec<u64>>),
|
||||
|
||||
Disconnect,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -56,19 +60,22 @@ pub mod messages {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum Response {
|
||||
// Connected(Capabilities, ed25519_dalek::PublicKey, ecies_ed25519::PublicKey),
|
||||
SendData(Vec<u8>),
|
||||
AckRunCommand(u64),
|
||||
SendStdout(Vec<u8>, u64, u64),
|
||||
CommandDone(u64),
|
||||
|
||||
CdDone,
|
||||
LsResults(Vec<DirEntry>),
|
||||
|
||||
OpenedTTY,
|
||||
ClosedTTY,
|
||||
OpenedTTY(u64),
|
||||
ClosedTTY(u64),
|
||||
SendRawData(Vec<u64>, u64),
|
||||
|
||||
UploadFileID(u64),
|
||||
UploadFileStatus(Result<(), Vec<u8>>),
|
||||
UploadFileStatus(u64, Result<(), Vec<u64>>),
|
||||
|
||||
DownloadFileSegment(u64, u64, Vec<u8>),
|
||||
StartDownloadFile(u64),
|
||||
DownloadFileSegment(u64, u64, Vec<u64>),
|
||||
}
|
||||
|
||||
#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Copy)]
|
||||
@ -94,5 +101,6 @@ pub mod messages {
|
||||
pub root: bool,
|
||||
pub userent: Option<String>,
|
||||
pub transport: TransportType,
|
||||
pub hostname: Option<String>,
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ fn get_current_capabilities() -> anyhow::Result<Capabilities> {
|
||||
return Err(std::io::Error::last_os_error())?;
|
||||
}
|
||||
|
||||
let docker_container = false;
|
||||
let docker_container = std::fs::read_to_string("/proc/1/cgroup")? != "0::/\n";
|
||||
let docker_breakout = false;
|
||||
let uid = unsafe { libc::getuid() };
|
||||
let root = uid == 0;
|
||||
@ -76,6 +76,9 @@ fn get_current_capabilities() -> anyhow::Result<Capabilities> {
|
||||
TransportType::Udp
|
||||
};
|
||||
let userent = get_username(uid)?;
|
||||
let hostname = std::fs::read_to_string("/etc/hostname")
|
||||
.map(|s| s.trim().to_string())
|
||||
.ok();
|
||||
|
||||
Ok(Capabilities {
|
||||
operating_system: if cfg!(target_os = "linux") {
|
||||
@ -89,6 +92,7 @@ fn get_current_capabilities() -> anyhow::Result<Capabilities> {
|
||||
root,
|
||||
userent,
|
||||
transport,
|
||||
hostname,
|
||||
})
|
||||
}
|
||||
|
||||
@ -104,6 +108,7 @@ fn get_current_capabilities() -> anyhow::Result<Capabilities> {
|
||||
root: userent.as_deref() == Some("Administrator"),
|
||||
userent,
|
||||
transport: TransportType::Udp,
|
||||
hostname: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ struct ConnectionInformation {
|
||||
srcip: Ipv4Addr,
|
||||
dstip: Ipv4Addr,
|
||||
srcport: u16,
|
||||
packet_sender: Sender<EthernetPacket>,
|
||||
}
|
||||
|
||||
impl ConnectionInformation {
|
||||
@ -79,6 +80,11 @@ impl ConnectionInformation {
|
||||
|
||||
Ok(rmp_serde::from_slice(&data)?)
|
||||
}
|
||||
|
||||
fn send(&self, packet: EthernetPacket) -> anyhow::Result<()> {
|
||||
self.packet_sender.send(packet)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_connection_handler(
|
||||
@ -132,6 +138,7 @@ pub fn spawn_connection_handler(
|
||||
srcip: ip_pkt.source_ip(),
|
||||
dstip: ip_pkt.dest_ip(),
|
||||
srcport: udp_pkt.srcport(),
|
||||
packet_sender,
|
||||
}
|
||||
};
|
||||
let close = {
|
||||
@ -145,7 +152,7 @@ pub fn spawn_connection_handler(
|
||||
let (packet_handler_sender, packet_handler) = channel();
|
||||
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = authenticate(capabilities, packet_handler, conninfo, packet_sender, close) {
|
||||
if let Err(e) = authenticate(capabilities, packet_handler, conninfo, close) {
|
||||
eprintln!("connection thread died: {e:?}");
|
||||
}
|
||||
});
|
||||
@ -159,7 +166,6 @@ fn authenticate<F: Fn()>(
|
||||
capabilities: Arc<Capabilities>,
|
||||
packet_handler: Receiver<EthernetPacket>,
|
||||
conninfo: ConnectionInformation,
|
||||
packet_sender: Sender<EthernetPacket>,
|
||||
close: F,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut counter = 0;
|
||||
@ -169,15 +175,16 @@ fn authenticate<F: Fn()>(
|
||||
close();
|
||||
}
|
||||
|
||||
let next_pkt = conninfo.encrypt_and_sign(
|
||||
&[
|
||||
&conninfo.local_sign_keypair.public.to_bytes(),
|
||||
&conninfo.local_enc_pubkey.to_bytes(),
|
||||
&*(rmp_serde::to_vec(&*capabilities)?),
|
||||
]
|
||||
.concat(),
|
||||
conninfo.send(
|
||||
conninfo.encrypt_and_sign(
|
||||
&[
|
||||
&conninfo.local_sign_keypair.public.to_bytes(),
|
||||
&conninfo.local_enc_pubkey.to_bytes(),
|
||||
&*(rmp_serde::to_vec(&*capabilities)?),
|
||||
]
|
||||
.concat(),
|
||||
)?,
|
||||
)?;
|
||||
packet_sender.send(next_pkt)?;
|
||||
|
||||
match packet_handler.recv_timeout(std::time::Duration::from_millis(250)) {
|
||||
Ok(p) => {
|
||||
@ -204,14 +211,13 @@ fn authenticate<F: Fn()>(
|
||||
}
|
||||
}
|
||||
|
||||
handle_full_connection(capabilities, packet_handler, conninfo, packet_sender, close)
|
||||
handle_full_connection(capabilities, packet_handler, conninfo, close)
|
||||
}
|
||||
|
||||
fn handle_full_connection<F>(
|
||||
capabilities: Arc<Capabilities>,
|
||||
packet_handler: Receiver<EthernetPacket>,
|
||||
conninfo: ConnectionInformation,
|
||||
packet_sender: Sender<EthernetPacket>,
|
||||
close: F,
|
||||
) -> anyhow::Result<()>
|
||||
where
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user