feat: added connection and authentication
client can now generate a server binary, and try to connect to it and get capabilities
This commit is contained in:
parent
cda6388596
commit
4449a771e2
199
Cargo.lock
generated
199
Cargo.lock
generated
@ -17,6 +17,60 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aead"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561"
|
||||||
|
dependencies = [
|
||||||
|
"aes-soft",
|
||||||
|
"aesni",
|
||||||
|
"cipher",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes-gcm"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da"
|
||||||
|
dependencies = [
|
||||||
|
"aead",
|
||||||
|
"aes",
|
||||||
|
"cipher",
|
||||||
|
"ctr",
|
||||||
|
"ghash",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes-soft"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
|
||||||
|
dependencies = [
|
||||||
|
"cipher",
|
||||||
|
"opaque-debug",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aesni"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
|
||||||
|
dependencies = [
|
||||||
|
"cipher",
|
||||||
|
"opaque-debug",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -118,6 +172,15 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.34.0"
|
version = "2.34.0"
|
||||||
@ -162,6 +225,31 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpuid-bool"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-mac"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctr"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f"
|
||||||
|
dependencies = [
|
||||||
|
"cipher",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "curve25519-dalek"
|
name = "curve25519-dalek"
|
||||||
version = "3.2.0"
|
version = "3.2.0"
|
||||||
@ -184,6 +272,24 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ecies-ed25519"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0a882353828f086290bedd0b598e18863a4d2135f8e632c4325ed89a4e5535db"
|
||||||
|
dependencies = [
|
||||||
|
"aes-gcm",
|
||||||
|
"curve25519-dalek",
|
||||||
|
"digest",
|
||||||
|
"hex",
|
||||||
|
"hkdf",
|
||||||
|
"rand",
|
||||||
|
"serde",
|
||||||
|
"sha2",
|
||||||
|
"thiserror",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ed25519"
|
name = "ed25519"
|
||||||
version = "1.5.3"
|
version = "1.5.3"
|
||||||
@ -393,6 +499,16 @@ dependencies = [
|
|||||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ghash"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375"
|
||||||
|
dependencies = [
|
||||||
|
"opaque-debug",
|
||||||
|
"polyval",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
@ -426,6 +542,32 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hkdf"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
"hmac",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hmac"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-mac",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
@ -589,6 +731,17 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "polyval"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd"
|
||||||
|
dependencies = [
|
||||||
|
"cpuid-bool",
|
||||||
|
"opaque-debug",
|
||||||
|
"universal-hash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
@ -735,6 +888,17 @@ dependencies = [
|
|||||||
"syn 2.0.29",
|
"syn 2.0.29",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_repr"
|
||||||
|
version = "0.1.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.29",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.9.9"
|
version = "0.9.9"
|
||||||
@ -800,6 +964,7 @@ name = "sparse-05-client"
|
|||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"ecies-ed25519",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"rand",
|
"rand",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
@ -814,9 +979,11 @@ dependencies = [
|
|||||||
name = "sparse-05-common"
|
name = "sparse-05-common"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ecies-ed25519",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"rand",
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_repr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -826,10 +993,12 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"catconf",
|
"catconf",
|
||||||
"cc",
|
"cc",
|
||||||
|
"ecies-ed25519",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"pcap-sys",
|
"pcap-sys",
|
||||||
|
"rand",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
"serde",
|
"serde",
|
||||||
"simple_logger",
|
"simple_logger",
|
||||||
@ -911,6 +1080,26 @@ dependencies = [
|
|||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.48"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.48"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.29",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.20"
|
version = "0.3.20"
|
||||||
@ -1004,6 +1193,16 @@ version = "0.1.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "universal-hash"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vec_map"
|
name = "vec_map"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
|
|||||||
@ -19,6 +19,13 @@ workspace = false
|
|||||||
command = "docker-compose"
|
command = "docker-compose"
|
||||||
args = ["run", "build", "build", "${@}"]
|
args = ["run", "build", "build", "${@}"]
|
||||||
|
|
||||||
|
[tasks.sparse-05]
|
||||||
|
workspace = false
|
||||||
|
script = [
|
||||||
|
"docker-compose run build build --bin sparse-05-server ${@}",
|
||||||
|
"docker-compose run build build --bin sparse-05-client ${@}",
|
||||||
|
]
|
||||||
|
|
||||||
[tasks.fmt]
|
[tasks.fmt]
|
||||||
command = "cargo"
|
command = "cargo"
|
||||||
args = ["fmt"]
|
args = ["fmt"]
|
||||||
|
|||||||
@ -5,6 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.75"
|
anyhow = "1.0.75"
|
||||||
|
ecies-ed25519 = { version = "0.5.1", features = ["serde"] }
|
||||||
ed25519-dalek = "1.0.1"
|
ed25519-dalek = "1.0.1"
|
||||||
rand = "0.7"
|
rand = "0.7"
|
||||||
rmp-serde = "1.1.2"
|
rmp-serde = "1.1.2"
|
||||||
|
|||||||
@ -1,17 +1,51 @@
|
|||||||
use std::{net::SocketAddr, path::PathBuf, sync::Arc};
|
use std::{net::SocketAddr, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use ed25519_dalek::{Keypair, Signer};
|
use anyhow::{bail, Context};
|
||||||
use sparse_05_common::messages::CONNECT_MESSAGE;
|
use ed25519_dalek::{Keypair, Signature, Signer, Verifier};
|
||||||
|
use rmp_serde::decode::ReadSlice;
|
||||||
|
use sparse_05_common::messages::{Capabilities, Response, CONNECTED_MESSAGE, CONNECT_MESSAGE};
|
||||||
use tokio::{fs, net::UdpSocket};
|
use tokio::{fs, net::UdpSocket};
|
||||||
|
|
||||||
use crate::configs::ClientConfig;
|
use crate::configs::ClientConfig;
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
|
Authenticating,
|
||||||
Ready,
|
Ready,
|
||||||
UploadingFile,
|
UploadingFile,
|
||||||
DownloadingFile,
|
DownloadingFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Connection {
|
||||||
|
config: ClientConfig,
|
||||||
|
foreign_sign_pubkey: ed25519_dalek::PublicKey,
|
||||||
|
foreign_enc_pubkey: ecies_ed25519::PublicKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Connection {
|
||||||
|
fn decrypt_and_verify(&self, data: &[u8]) -> anyhow::Result<Response> {
|
||||||
|
if data.len() < 65 {
|
||||||
|
bail!("unable to parse out signature from message");
|
||||||
|
}
|
||||||
|
|
||||||
|
let signature: [u8; 64] = data[..64].try_into().unwrap();
|
||||||
|
self.foreign_sign_pubkey
|
||||||
|
.verify(data, &Signature::from(signature))?;
|
||||||
|
|
||||||
|
let data = ecies_ed25519::decrypt(&self.config.enc_privkey, &data[64..])?;
|
||||||
|
|
||||||
|
Ok(rmp_serde::from_slice(&data)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encrypt_and_sign(&self, data: &[u8]) -> anyhow::Result<Vec<u8>> {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let data = ecies_ed25519::encrypt(&self.foreign_enc_pubkey, data, &mut rng)?;
|
||||||
|
|
||||||
|
let signature = self.config.keypair.sign(&data);
|
||||||
|
|
||||||
|
Ok([&signature.to_bytes(), &*data].concat())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn connect(config: PathBuf, ip: SocketAddr) -> anyhow::Result<()> {
|
pub async fn connect(config: PathBuf, ip: SocketAddr) -> anyhow::Result<()> {
|
||||||
let config = fs::read(&config).await?;
|
let config = fs::read(&config).await?;
|
||||||
let config: ClientConfig = rmp_serde::from_slice(&config)?;
|
let config: ClientConfig = rmp_serde::from_slice(&config)?;
|
||||||
@ -21,7 +55,84 @@ pub async fn connect(config: PathBuf, ip: SocketAddr) -> anyhow::Result<()> {
|
|||||||
let connect_signature = config.keypair.sign(CONNECT_MESSAGE).to_bytes();
|
let connect_signature = config.keypair.sign(CONNECT_MESSAGE).to_bytes();
|
||||||
let connect_msg = &[&connect_signature, CONNECT_MESSAGE].concat();
|
let connect_msg = &[&connect_signature, CONNECT_MESSAGE].concat();
|
||||||
|
|
||||||
remote.send_to(connect_msg, ip).await?;
|
let mut counter = 0;
|
||||||
|
|
||||||
|
let (foreign_sign_pubkey, foreign_enc_pubkey, capabilities) = loop {
|
||||||
|
if counter > 5 {
|
||||||
|
bail!("could not connect to server");
|
||||||
|
}
|
||||||
|
|
||||||
|
remote.send_to(connect_msg, ip).await?;
|
||||||
|
|
||||||
|
let mut buf = [0u8; 2000];
|
||||||
|
|
||||||
|
match tokio::time::timeout(
|
||||||
|
std::time::Duration::from_millis(250),
|
||||||
|
remote.recv_from(&mut buf),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(packet) => {
|
||||||
|
let (count, addr) = packet?;
|
||||||
|
|
||||||
|
if addr != ip {
|
||||||
|
bail!("received response from wrong source");
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = &buf[..count];
|
||||||
|
|
||||||
|
if data.len() < 65 {
|
||||||
|
bail!("could not get signature from server");
|
||||||
|
}
|
||||||
|
|
||||||
|
let signature: [u8; 64] = data[..64].try_into().unwrap();
|
||||||
|
let data = &data[64..];
|
||||||
|
|
||||||
|
let Ok(foreign_keys) = ecies_ed25519::decrypt(&config.enc_privkey, data) else {
|
||||||
|
counter += 1;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
if foreign_keys.len()
|
||||||
|
< ed25519_dalek::PUBLIC_KEY_LENGTH + ecies_ed25519::PUBLIC_KEY_LENGTH
|
||||||
|
{
|
||||||
|
bail!("could not get public keys from the server");
|
||||||
|
}
|
||||||
|
|
||||||
|
let foreign_sign_pubkey = ed25519_dalek::PublicKey::from_bytes(
|
||||||
|
&foreign_keys[..ed25519_dalek::PUBLIC_KEY_LENGTH],
|
||||||
|
)?;
|
||||||
|
let foreign_enc_pubkey = ecies_ed25519::PublicKey::from_bytes(
|
||||||
|
&foreign_keys[ed25519_dalek::PUBLIC_KEY_LENGTH
|
||||||
|
..(ed25519_dalek::PUBLIC_KEY_LENGTH + ecies_ed25519::PUBLIC_KEY_LENGTH)],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let capabilities: Capabilities = rmp_serde::from_slice(
|
||||||
|
&foreign_keys
|
||||||
|
[(ed25519_dalek::PUBLIC_KEY_LENGTH + ecies_ed25519::PUBLIC_KEY_LENGTH)..],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
foreign_sign_pubkey.verify(data, &Signature::from(signature))?;
|
||||||
|
|
||||||
|
break (foreign_sign_pubkey, foreign_enc_pubkey, capabilities);
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let connection = Connection {
|
||||||
|
config,
|
||||||
|
foreign_enc_pubkey,
|
||||||
|
foreign_sign_pubkey,
|
||||||
|
};
|
||||||
|
|
||||||
|
remote
|
||||||
|
.send_to(&connection.encrypt_and_sign(CONNECTED_MESSAGE)?, ip)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
println!("connected! {:?}", capabilities);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ pub const SPARSE_SERVER_BINARY: &'static [u8] =
|
|||||||
pub async fn generate(mut name: PathBuf, port: u16) -> anyhow::Result<()> {
|
pub async fn generate(mut name: PathBuf, port: u16) -> anyhow::Result<()> {
|
||||||
let mut csprng = rand::thread_rng();
|
let mut csprng = rand::thread_rng();
|
||||||
let keypair = Keypair::generate(&mut csprng);
|
let keypair = Keypair::generate(&mut csprng);
|
||||||
|
let (enc_privkey, enc_pubkey) = ecies_ed25519::generate_keypair(&mut csprng);
|
||||||
|
|
||||||
let mut file = fs::OpenOptions::new()
|
let mut file = fs::OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
@ -28,11 +29,17 @@ pub async fn generate(mut name: PathBuf, port: u16) -> anyhow::Result<()> {
|
|||||||
file.write_all(CONFIG_SEPARATOR).await?;
|
file.write_all(CONFIG_SEPARATOR).await?;
|
||||||
file.write_all(&port.to_be_bytes()[..]).await?;
|
file.write_all(&port.to_be_bytes()[..]).await?;
|
||||||
file.write_all(keypair.public.as_bytes()).await?;
|
file.write_all(keypair.public.as_bytes()).await?;
|
||||||
|
file.write_all(enc_pubkey.as_bytes()).await?;
|
||||||
|
|
||||||
let config = ClientConfig { keypair, port };
|
let config = ClientConfig {
|
||||||
|
keypair,
|
||||||
|
enc_privkey,
|
||||||
|
enc_pubkey,
|
||||||
|
port,
|
||||||
|
};
|
||||||
|
|
||||||
let mut file_part = name.file_name().unwrap().to_owned();
|
let mut file_part = name.file_name().unwrap().to_owned();
|
||||||
file_part.push(OsString::from(".conf"));
|
file_part.push(OsString::from(".scon"));
|
||||||
name.pop();
|
name.pop();
|
||||||
name.push(file_part);
|
name.push(file_part);
|
||||||
let mut file = fs::OpenOptions::new()
|
let mut file = fs::OpenOptions::new()
|
||||||
|
|||||||
@ -4,5 +4,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct ClientConfig {
|
pub struct ClientConfig {
|
||||||
pub keypair: Keypair,
|
pub keypair: Keypair,
|
||||||
|
pub enc_pubkey: ecies_ed25519::PublicKey,
|
||||||
|
pub enc_privkey: ecies_ed25519::SecretKey,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,8 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
ecies-ed25519 = { version = "0.5.1", features = ["serde"] }
|
||||||
ed25519-dalek = { version = "1.0.1", features = ["serde"] }
|
ed25519-dalek = { version = "1.0.1", features = ["serde"] }
|
||||||
rand = "0.7"
|
rand = "0.7"
|
||||||
serde = { version = "1.0.188", features = ["derive"] }
|
serde = { version = "1.0.188", features = ["derive"] }
|
||||||
|
serde_repr = "0.1"
|
||||||
|
|||||||
@ -3,17 +3,12 @@ pub const CONFIG_SEPARATOR: &'static [u8] =
|
|||||||
|
|
||||||
pub mod messages {
|
pub mod messages {
|
||||||
pub const CONNECT_MESSAGE: &'static [u8] = b"CONNECT";
|
pub const CONNECT_MESSAGE: &'static [u8] = b"CONNECT";
|
||||||
|
pub const CONNECTED_MESSAGE: &'static [u8] = b"CONNECTED";
|
||||||
|
|
||||||
use std::{ffi::OsString, path::PathBuf};
|
use std::{ffi::OsString, path::PathBuf};
|
||||||
|
|
||||||
use ed25519_dalek::Signature;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
pub struct CommandWrapper {
|
|
||||||
sig: Signature,
|
|
||||||
command: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
@ -61,7 +56,7 @@ pub mod messages {
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub enum Response {
|
pub enum Response {
|
||||||
Connected(Capabilities),
|
// Connected(Capabilities, ed25519_dalek::PublicKey, ecies_ed25519::PublicKey),
|
||||||
SendData(Vec<u8>),
|
SendData(Vec<u8>),
|
||||||
|
|
||||||
CdDone,
|
CdDone,
|
||||||
@ -76,14 +71,23 @@ pub mod messages {
|
|||||||
DownloadFileSegment(u64, u64, Vec<u8>),
|
DownloadFileSegment(u64, u64, Vec<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Copy)]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum TransportType {
|
pub enum TransportType {
|
||||||
RawUdp,
|
RawUdp,
|
||||||
Udp,
|
Udp,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize_repr, Deserialize_repr, Debug, Clone, Copy)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum OperatingSystem {
|
||||||
|
Windows,
|
||||||
|
Linux,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct Capabilities {
|
pub struct Capabilities {
|
||||||
|
pub operating_system: OperatingSystem,
|
||||||
pub docker_container: bool,
|
pub docker_container: bool,
|
||||||
pub docker_breakout: bool,
|
pub docker_breakout: bool,
|
||||||
pub setuid: bool,
|
pub setuid: bool,
|
||||||
|
|||||||
@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
pcap-sys = { path = "../../pcap-sys" }
|
pcap-sys = { path = "../../pcap-sys" }
|
||||||
anyhow = "1.0.70"
|
anyhow = "1.0.70"
|
||||||
ed25519-dalek = "1.0.1"
|
ed25519-dalek = "1.0.1"
|
||||||
|
rand = "0.7"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
simple_logger = "4.1.0"
|
simple_logger = "4.1.0"
|
||||||
libc = { version = "0.2.147" }
|
libc = { version = "0.2.147" }
|
||||||
@ -14,6 +15,7 @@ serde = { version = "1.0.188", features = ["derive"] }
|
|||||||
rmp-serde = "1.1.2"
|
rmp-serde = "1.1.2"
|
||||||
catconf = "0.1.2"
|
catconf = "0.1.2"
|
||||||
sparse-05-common = { version = "0.1.0", path = "../sparse-05-common" }
|
sparse-05-common = { version = "0.1.0", path = "../sparse-05-common" }
|
||||||
|
ecies-ed25519 = { version = "0.5.1", features = ["serde"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cc = "1.0"
|
cc = "1.0"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use std::ffi::c_int;
|
use std::ffi::c_int;
|
||||||
|
|
||||||
use sparse_05_common::messages::{Capabilities, TransportType};
|
use sparse_05_common::messages::{Capabilities, OperatingSystem, TransportType};
|
||||||
|
|
||||||
const CAP_SETUID: u32 = 1 << 7;
|
const CAP_SETUID: u32 = 1 << 7;
|
||||||
const CAP_NET_RAW: u32 = 1 << 13;
|
const CAP_NET_RAW: u32 = 1 << 13;
|
||||||
@ -71,6 +71,11 @@ fn get_current_capabilities() -> anyhow::Result<Capabilities> {
|
|||||||
let userent = get_username(uid)?;
|
let userent = get_username(uid)?;
|
||||||
|
|
||||||
Ok(Capabilities {
|
Ok(Capabilities {
|
||||||
|
operating_system: if cfg!(target_os = "linux") {
|
||||||
|
OperatingSystem::Linux
|
||||||
|
} else {
|
||||||
|
OperatingSystem::Windows
|
||||||
|
},
|
||||||
docker_container,
|
docker_container,
|
||||||
docker_breakout,
|
docker_breakout,
|
||||||
setuid,
|
setuid,
|
||||||
|
|||||||
@ -1,22 +1,214 @@
|
|||||||
use std::{net::Ipv4Addr, sync::mpsc::Sender};
|
use std::{
|
||||||
|
net::{Ipv4Addr, UdpSocket},
|
||||||
|
sync::{
|
||||||
|
mpsc::{channel, Receiver, Sender},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
|
thread,
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::{anyhow, bail, Context};
|
||||||
|
use ed25519_dalek::{Keypair, Signature, Signer, Verifier};
|
||||||
use pcap_sys::packets::EthernetPacket;
|
use pcap_sys::packets::EthernetPacket;
|
||||||
|
use sparse_05_common::messages::{Capabilities, Command, Response, CONNECTED_MESSAGE};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ConnectionHandle {}
|
pub struct ConnectionHandle {
|
||||||
|
packet_handler_sender: Sender<EthernetPacket>,
|
||||||
|
}
|
||||||
|
|
||||||
impl ConnectionHandle {
|
impl ConnectionHandle {
|
||||||
pub fn handle_packet(&self, packet: EthernetPacket) -> anyhow::Result<()> {
|
pub fn handle_packet(&self, packet: EthernetPacket) -> anyhow::Result<()> {
|
||||||
|
self.packet_handler_sender.send(packet)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum State {}
|
struct ConnectionInformation {
|
||||||
|
remote_sign_pubkey: ed25519_dalek::PublicKey,
|
||||||
|
remote_enc_pubkey: ecies_ed25519::PublicKey,
|
||||||
|
local_sign_keypair: Keypair,
|
||||||
|
local_enc_pubkey: ecies_ed25519::PublicKey,
|
||||||
|
local_enc_privkey: ecies_ed25519::SecretKey,
|
||||||
|
srcmac: [u8; 6],
|
||||||
|
dstmac: [u8; 6],
|
||||||
|
srcip: Ipv4Addr,
|
||||||
|
dstip: Ipv4Addr,
|
||||||
|
srcport: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConnectionInformation {
|
||||||
|
fn format_udp_packet(&self, data: &[u8]) -> EthernetPacket {
|
||||||
|
use pcap_sys::packets::*;
|
||||||
|
|
||||||
|
let udp_packet = UDPPacket::construct(54248, self.srcport, data);
|
||||||
|
let ip_packet =
|
||||||
|
IPv4Packet::construct(self.dstip, self.srcip, &Layer4Packet::UDP(udp_packet));
|
||||||
|
EthernetPacket::construct(self.dstmac, self.srcmac, &Layer3Packet::IPv4(ip_packet))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encrypt_and_sign(&self, data: &[u8]) -> anyhow::Result<EthernetPacket> {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let enc_data = ecies_ed25519::encrypt(&self.remote_enc_pubkey, data, &mut rng)?;
|
||||||
|
let signature = self.local_sign_keypair.sign(&enc_data);
|
||||||
|
|
||||||
|
Ok(self.format_udp_packet(&[&signature.to_bytes(), &*enc_data].concat()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encrypt_and_sign_resp(&self, data: Response) -> anyhow::Result<EthernetPacket> {
|
||||||
|
let raw_data = rmp_serde::to_vec(&data)?;
|
||||||
|
self.encrypt_and_sign(&raw_data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_decrypt_and_verify(&self, data: &[u8]) -> anyhow::Result<Vec<u8>> {
|
||||||
|
if data.len() < 65 {
|
||||||
|
bail!("packet received is too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
let signature: [u8; 64] = data[..64].try_into()?;
|
||||||
|
let signature = Signature::from(signature);
|
||||||
|
let rest = &data[64..];
|
||||||
|
|
||||||
|
self.remote_sign_pubkey.verify(rest, &signature)?;
|
||||||
|
|
||||||
|
Ok(ecies_ed25519::decrypt(&self.local_enc_privkey, rest)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_decrypt_and_verify_comm(&self, data: &[u8]) -> anyhow::Result<Command> {
|
||||||
|
let data = self.try_decrypt_and_verify(data)?;
|
||||||
|
|
||||||
|
Ok(rmp_serde::from_slice(&data)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn spawn_connection_handler(
|
pub fn spawn_connection_handler(
|
||||||
|
capabilities: Arc<Capabilities>,
|
||||||
|
sign_pubkey: Arc<ed25519_dalek::PublicKey>,
|
||||||
|
enc_pubkey: Arc<ecies_ed25519::PublicKey>,
|
||||||
packet_sender: Sender<EthernetPacket>,
|
packet_sender: Sender<EthernetPacket>,
|
||||||
connection_packet: EthernetPacket,
|
connection_packet: EthernetPacket,
|
||||||
connection_killer: Sender<(Ipv4Addr, u16)>,
|
connection_killer: Sender<(Ipv4Addr, u16)>,
|
||||||
) -> ConnectionHandle {
|
) -> anyhow::Result<ConnectionHandle> {
|
||||||
ConnectionHandle {}
|
println!("received connection, starting to authenticate");
|
||||||
|
|
||||||
|
let conninfo = {
|
||||||
|
use pcap_sys::packets::*;
|
||||||
|
let packet = connection_packet.pkt();
|
||||||
|
|
||||||
|
let Layer3Pkt::IPv4Pkt(ip_pkt) = packet.get_layer3_pkt()?;
|
||||||
|
let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?;
|
||||||
|
|
||||||
|
let data = udp_pkt.get_data();
|
||||||
|
|
||||||
|
if data.len() < 71 {
|
||||||
|
bail!("connection packet was the wrong length");
|
||||||
|
}
|
||||||
|
|
||||||
|
let Ok(signature): Result<[u8; 64], _> = data[..64].try_into() else {
|
||||||
|
bail!("could not get signature from connection");
|
||||||
|
};
|
||||||
|
|
||||||
|
let signature = Signature::from(signature);
|
||||||
|
let connect = &data[64..];
|
||||||
|
|
||||||
|
if connect != b"CONNECT" {
|
||||||
|
bail!("connect magic bytes were wrong");
|
||||||
|
}
|
||||||
|
|
||||||
|
sign_pubkey
|
||||||
|
.verify(connect, &signature)
|
||||||
|
.context("could not verify the signature of the connection packet")?;
|
||||||
|
|
||||||
|
let mut csprng = rand::thread_rng();
|
||||||
|
let local_sign_keypair = Keypair::generate(&mut csprng);
|
||||||
|
let (local_enc_privkey, local_enc_pubkey) = ecies_ed25519::generate_keypair(&mut csprng);
|
||||||
|
|
||||||
|
ConnectionInformation {
|
||||||
|
remote_sign_pubkey: (*sign_pubkey).clone(),
|
||||||
|
remote_enc_pubkey: (*enc_pubkey).clone(),
|
||||||
|
local_sign_keypair,
|
||||||
|
local_enc_privkey,
|
||||||
|
local_enc_pubkey,
|
||||||
|
srcmac: *packet.source_address(),
|
||||||
|
dstmac: *packet.destination_address(),
|
||||||
|
srcip: ip_pkt.source_ip(),
|
||||||
|
dstip: ip_pkt.dest_ip(),
|
||||||
|
srcport: udp_pkt.srcport(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let close = {
|
||||||
|
let ip = conninfo.srcip.clone();
|
||||||
|
let port = conninfo.srcport;
|
||||||
|
move || {
|
||||||
|
let _ = connection_killer.send((ip, port));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let (packet_handler_sender, packet_handler) = channel();
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
if let Err(e) = authenticate(capabilities, packet_handler, conninfo, packet_sender, close) {
|
||||||
|
eprintln!("connection thread died: {e:?}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(ConnectionHandle {
|
||||||
|
packet_handler_sender,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if counter > 5 {
|
||||||
|
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(),
|
||||||
|
)?;
|
||||||
|
packet_sender.send(next_pkt)?;
|
||||||
|
|
||||||
|
match packet_handler.recv_timeout(std::time::Duration::from_millis(250)) {
|
||||||
|
Ok(p) => {
|
||||||
|
use pcap_sys::packets::*;
|
||||||
|
let p = p.pkt();
|
||||||
|
let Layer3Pkt::IPv4Pkt(ip_pkt) = p.get_layer3_pkt()?;
|
||||||
|
let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?;
|
||||||
|
|
||||||
|
let Ok(data) = conninfo.try_decrypt_and_verify(udp_pkt.get_data()) else {
|
||||||
|
counter += 1;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
if data == CONNECTED_MESSAGE {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
Err(e) => Err(e)?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Connection made!");
|
||||||
|
|
||||||
|
close();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,6 @@ use std::{
|
|||||||
|
|
||||||
use anyhow::{bail, Context};
|
use anyhow::{bail, Context};
|
||||||
use connection::ConnectionHandle;
|
use connection::ConnectionHandle;
|
||||||
use ed25519_dalek::PublicKey;
|
|
||||||
|
|
||||||
use pcap_sys::packets::EthernetPacket;
|
use pcap_sys::packets::EthernetPacket;
|
||||||
use sparse_05_common::CONFIG_SEPARATOR;
|
use sparse_05_common::CONFIG_SEPARATOR;
|
||||||
@ -24,26 +23,27 @@ fn main() -> anyhow::Result<()> {
|
|||||||
.with_module_level("sparse-05-server", log::LevelFilter::Info)
|
.with_module_level("sparse-05-server", log::LevelFilter::Info)
|
||||||
.init()?;
|
.init()?;
|
||||||
|
|
||||||
let capabilities = capabilities::get_capabilities()?;
|
let capabilities = Arc::new(capabilities::get_capabilities()?);
|
||||||
|
|
||||||
let config_bytes = catconf::read_from_exe(CONFIG_SEPARATOR, 512)?;
|
let config_bytes = catconf::read_from_exe(CONFIG_SEPARATOR, 512)?;
|
||||||
if config_bytes.len() != 34 {
|
if config_bytes.len() != 66 {
|
||||||
bail!("could not load configuration");
|
bail!("could not load configuration");
|
||||||
}
|
}
|
||||||
|
|
||||||
let (port, pubkey) = {
|
let (port, conn_pubkey, enc_pubkey) = {
|
||||||
let port = u16::from_be_bytes(config_bytes[..2].try_into().unwrap());
|
let port = u16::from_be_bytes(config_bytes[..2].try_into().unwrap());
|
||||||
let pubkey = PublicKey::from_bytes(&config_bytes[2..])
|
let conn_pubkey = ed25519_dalek::PublicKey::from_bytes(&config_bytes[2..34])
|
||||||
.context("could not parse public key from configuration")?;
|
.context("could not parse public signing key from configuration")?;
|
||||||
|
let enc_pubkey = ecies_ed25519::PublicKey::from_bytes(&config_bytes[34..66])
|
||||||
|
.context("could not parse public encryption key from configuration")?;
|
||||||
|
|
||||||
(port, Arc::new(pubkey))
|
(port, Arc::new(conn_pubkey), Arc::new(enc_pubkey))
|
||||||
};
|
};
|
||||||
|
|
||||||
let interface = interface::Interface::new(capabilities.transport, port)?;
|
let interface = interface::Interface::new(capabilities.transport, port)?;
|
||||||
let (interface_sender, interface_receiver) = interface.split()?;
|
let (interface_sender, interface_receiver) = interface.split()?;
|
||||||
|
|
||||||
let connections: Arc<Mutex<HashMap<(Ipv4Addr, u16), ConnectionHandle>>> =
|
let connections: Mutex<HashMap<(Ipv4Addr, u16), ConnectionHandle>> = Mutex::new(HashMap::new());
|
||||||
Arc::new(Mutex::new(HashMap::new()));
|
|
||||||
let (send_eth_packet, recv_eth_packet) = channel::<EthernetPacket>();
|
let (send_eth_packet, recv_eth_packet) = channel::<EthernetPacket>();
|
||||||
let (kill_connection, kill_connection_recv) = channel::<(Ipv4Addr, u16)>();
|
let (kill_connection, kill_connection_recv) = channel::<(Ipv4Addr, u16)>();
|
||||||
|
|
||||||
@ -52,46 +52,53 @@ fn main() -> anyhow::Result<()> {
|
|||||||
if let Err(_) = interface_sender.sendpacket(packet.pkt()) {}
|
if let Err(_) = interface_sender.sendpacket(packet.pkt()) {}
|
||||||
});
|
});
|
||||||
|
|
||||||
thread::spawn({
|
thread::scope(|s| {
|
||||||
let connections = Arc::clone(&connections);
|
s.spawn({
|
||||||
move || loop {
|
let connections = &connections;
|
||||||
let Ok(connection) = kill_connection_recv.recv() else { continue };
|
move || loop {
|
||||||
if let Ok(mut e) = connections.lock() {
|
let Ok(connection) = kill_connection_recv.recv() else { continue };
|
||||||
e.remove(&connection);
|
if let Ok(mut e) = connections.lock() {
|
||||||
|
e.remove(&connection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
interface_receiver
|
||||||
|
.listen(|pkt| {
|
||||||
|
use pcap_sys::packets::*;
|
||||||
|
|
||||||
|
let pkt = pkt.pkt();
|
||||||
|
|
||||||
|
let Layer3Pkt::IPv4Pkt(ip_pkt) = pkt.get_layer3_pkt()?;
|
||||||
|
let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?;
|
||||||
|
|
||||||
|
let connection_handle = &(ip_pkt.dest_ip(), udp_pkt.srcport());
|
||||||
|
|
||||||
|
if let Ok(mut connections) = connections.lock() {
|
||||||
|
let connection = connections.get(connection_handle);
|
||||||
|
|
||||||
|
match connection {
|
||||||
|
None => {
|
||||||
|
let new_connection = spawn_connection_handler(
|
||||||
|
Arc::clone(&capabilities),
|
||||||
|
Arc::clone(&conn_pubkey),
|
||||||
|
Arc::clone(&enc_pubkey),
|
||||||
|
send_eth_packet.clone(),
|
||||||
|
pkt.to_owned(),
|
||||||
|
kill_connection.clone(),
|
||||||
|
)?;
|
||||||
|
connections.insert(*connection_handle, new_connection);
|
||||||
|
}
|
||||||
|
Some(conn) => {
|
||||||
|
conn.handle_packet(pkt.to_owned())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.expect("packet capture loop failed");
|
||||||
});
|
});
|
||||||
|
|
||||||
interface_receiver.listen(|pkt| {
|
|
||||||
use pcap_sys::packets::*;
|
|
||||||
|
|
||||||
let pkt = pkt.pkt();
|
|
||||||
|
|
||||||
let Layer3Pkt::IPv4Pkt(ip_pkt) = pkt.get_layer3_pkt()?;
|
|
||||||
let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?;
|
|
||||||
|
|
||||||
let connection_handle = &(ip_pkt.dest_ip(), udp_pkt.srcport());
|
|
||||||
|
|
||||||
if let Ok(mut connections) = connections.lock() {
|
|
||||||
let connection = connections.get(connection_handle);
|
|
||||||
|
|
||||||
match connection {
|
|
||||||
None => {
|
|
||||||
let new_connection = spawn_connection_handler(
|
|
||||||
send_eth_packet.clone(),
|
|
||||||
pkt.to_owned(),
|
|
||||||
kill_connection.clone(),
|
|
||||||
);
|
|
||||||
connections.insert(*connection_handle, new_connection);
|
|
||||||
}
|
|
||||||
Some(conn) => {
|
|
||||||
conn.handle_packet(pkt.to_owned())?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user