diff --git a/.devcontainer/Dockerfile.alpine b/.devcontainer/Dockerfile.alpine
index 6504444..d63ebe5 100644
--- a/.devcontainer/Dockerfile.alpine
+++ b/.devcontainer/Dockerfile.alpine
@@ -17,3 +17,6 @@ FROM rust:1-alpine
RUN apk add cmake make automake musl-dev autoconf libtool \
flex bison linux-headers openssl-dev lldb build-base libcap-dev
+
+RUN apk add mingw-w64-gcc mingw-w64-winpthreads mingw-w64-headers && \
+ rustup target add x86_64-pc-windows-gnu
diff --git a/Cargo.lock b/Cargo.lock
index 39c5201..50003b6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -674,6 +674,10 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+[[package]]
+name = "packets"
+version = "0.1.0"
+
[[package]]
name = "paste"
version = "1.0.14"
@@ -715,6 +719,7 @@ dependencies = [
"errno",
"futures",
"libc",
+ "packets",
"tokio",
"tokio-stream",
]
@@ -997,6 +1002,7 @@ dependencies = [
"ed25519-dalek",
"libc",
"log",
+ "packets",
"pcap-sys",
"rand",
"rmp-serde",
diff --git a/Cargo.toml b/Cargo.toml
index 5aa7e72..4edf42f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,7 @@
[workspace]
members = [
"pcap-sys", "nl-sys",
+ "packets",
"examples/*/*",
"sparse-protocol",
"sparse-05/*",
diff --git a/Makefile.toml b/Makefile.toml
index cc9bd10..8aaaf47 100644
--- a/Makefile.toml
+++ b/Makefile.toml
@@ -23,6 +23,7 @@ args = ["run", "build", "build", "${@}"]
workspace = false
script = [
"docker-compose run build build --bin sparse-05-server ${@}",
+ "docker-compose run build build --bin sparse-05-server --target x86_64-pc-windows-gnu ${@}",
"docker-compose run build build --bin sparse-05-client ${@}",
]
diff --git a/packets/Cargo.toml b/packets/Cargo.toml
new file mode 100644
index 0000000..ff4201f
--- /dev/null
+++ b/packets/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "packets"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/packets/src/error.rs b/packets/src/error.rs
new file mode 100644
index 0000000..8413e5c
--- /dev/null
+++ b/packets/src/error.rs
@@ -0,0 +1,40 @@
+// Copyright (C) 2023 Andrew Rioux
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use std::{error, fmt::Display};
+
+#[derive(Debug)]
+pub enum Error {
+ StringParse,
+ UnknownPacketType(u16),
+ PacketLengthInvalid,
+}
+
+pub type Result = std::result::Result;
+
+impl Display for Error {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Error::StringParse => write!(f, "unable to parse a string from pcap"),
+ Error::UnknownPacketType(ptype) => write!(f, "unknown packet type ({ptype})"),
+ Error::PacketLengthInvalid => write!(
+ f,
+ "received a packet with a length that mismatched the header"
+ ),
+ }
+ }
+}
+
+impl error::Error for Error {}
diff --git a/pcap-sys/src/packets.rs b/packets/src/lib.rs
similarity index 99%
rename from pcap-sys/src/packets.rs
rename to packets/src/lib.rs
index b852316..c25e73d 100644
--- a/pcap-sys/src/packets.rs
+++ b/packets/src/lib.rs
@@ -13,14 +13,15 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use crate::error;
use std::{
net::Ipv4Addr,
sync::atomic::{AtomicU16, Ordering},
};
+pub mod error;
+
pub struct EthernetPkt<'a> {
- pub(crate) data: &'a [u8],
+ pub data: &'a [u8],
}
impl<'a> EthernetPkt<'a> {
diff --git a/packets/src/main.rs b/packets/src/main.rs
new file mode 100644
index 0000000..e7a11a9
--- /dev/null
+++ b/packets/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/pcap-sys/Cargo.toml b/pcap-sys/Cargo.toml
index 488d487..74e98e8 100644
--- a/pcap-sys/Cargo.toml
+++ b/pcap-sys/Cargo.toml
@@ -24,6 +24,7 @@ futures = "0.3.25"
libc = "0.2.142"
tokio = { version = "1.21.2", features = ["net", "rt", "macros", "rt-multi-thread" ] }
tokio-stream = "0.1.14"
+packets = { path = "../packets" }
[build-dependencies]
-cmake = "0.1"
\ No newline at end of file
+cmake = "0.1"
diff --git a/pcap-sys/src/error.rs b/pcap-sys/src/error.rs
index c978c9c..fad274f 100644
--- a/pcap-sys/src/error.rs
+++ b/pcap-sys/src/error.rs
@@ -122,3 +122,15 @@ impl From for Error {
Error::Libc(err)
}
}
+
+impl From for Error {
+ fn from(err: packets::error::Error) -> Error {
+ use packets::error::Error as ExtE;
+
+ match err {
+ ExtE::PacketLengthInvalid => Error::PacketLengthInvalid,
+ ExtE::UnknownPacketType(t) => Error::UnknownPacketType(t),
+ ExtE::StringParse => Error::StringParse,
+ }
+ }
+}
diff --git a/pcap-sys/src/lib.rs b/pcap-sys/src/lib.rs
index d1110d4..47bf615 100644
--- a/pcap-sys/src/lib.rs
+++ b/pcap-sys/src/lib.rs
@@ -24,7 +24,7 @@ use std::{
pub mod error;
mod ffi;
-pub mod packets;
+pub use packets;
pub mod consts {
pub use super::ffi::{
diff --git a/sparse-05/sparse-05-client/src/commands/generate.rs b/sparse-05/sparse-05-client/src/commands/generate.rs
index 4922c16..7a28404 100644
--- a/sparse-05/sparse-05-client/src/commands/generate.rs
+++ b/sparse-05/sparse-05-client/src/commands/generate.rs
@@ -4,28 +4,51 @@ use ed25519_dalek::Keypair;
use sparse_05_common::CONFIG_SEPARATOR;
use tokio::{fs, io::AsyncWriteExt};
-use crate::configs::ClientConfig;
+use crate::{configs::ClientConfig, options::TargetOs};
#[cfg(debug_assertions)]
-pub const SPARSE_SERVER_BINARY: &'static [u8] =
+pub const SPARSE_LINUX_SERVER_BINARY: &'static [u8] =
include_bytes!("../../../../target/debug/sparse-05-server");
#[cfg(not(debug_assertions))]
-pub const SPARSE_SERVER_BINARY: &'static [u8] =
+pub const SPARSE_LINUX_SERVER_BINARY: &'static [u8] =
include_bytes!("../../../../target/release/sparse-05-server");
+#[cfg(debug_assertions)]
+pub const SPARSE_WINDOWS_SERVER_BINARY: &'static [u8] =
+ include_bytes!("../../../../target/x86_64-pc-windows-gnu/debug/sparse-05-server.exe");
+#[cfg(not(debug_assertions))]
+pub const SPARSE_WINDOWS_SERVER_BINARY: &'static [u8] =
+ include_bytes!("../../../../target/x86_64-pc-windows-gnu/release/sparse-05-server.exe");
-pub async fn generate(mut name: PathBuf, port: u16) -> anyhow::Result<()> {
+pub async fn generate(mut name: PathBuf, port: u16, target: TargetOs) -> anyhow::Result<()> {
let mut csprng = rand::thread_rng();
let keypair = Keypair::generate(&mut csprng);
let (enc_privkey, enc_pubkey) = ecies_ed25519::generate_keypair(&mut csprng);
- let mut file = fs::OpenOptions::new()
- .write(true)
- .create(true)
- .mode(0o755)
- .open(&name)
- .await?;
+ let mut file = fs::OpenOptions::new();
+ file.write(true).create(true);
+ #[cfg(unix)]
+ file.mode(0o755);
- file.write_all(SPARSE_SERVER_BINARY).await?;
+ #[cfg(windows)]
+ let old_file_part = name.file_name().unwrap().to_owned();
+
+ #[cfg(windows)]
+ {
+ let mut file_part = name.file_name().unwrap().to_owned();
+ file_part.push(OsString::from(".exe"));
+ name.pop();
+ name.push(file_part);
+ }
+
+ let mut file = file.open(&name).await?;
+
+ #[cfg(windows)]
+ {
+ name.pop();
+ name.push(old_file_part);
+ }
+
+ file.write_all(SPARSE_LINUX_SERVER_BINARY).await?;
file.write_all(CONFIG_SEPARATOR).await?;
file.write_all(&port.to_be_bytes()[..]).await?;
file.write_all(keypair.public.as_bytes()).await?;
diff --git a/sparse-05/sparse-05-client/src/main.rs b/sparse-05/sparse-05-client/src/main.rs
index 6f5d2dc..361954d 100644
--- a/sparse-05/sparse-05-client/src/main.rs
+++ b/sparse-05/sparse-05-client/src/main.rs
@@ -11,7 +11,9 @@ async fn main() -> anyhow::Result<()> {
let options = Options::from_args();
match options.command {
- Command::Generate { name, port } => commands::generate::generate(name, port).await,
+ Command::Generate { name, port, target } => {
+ commands::generate::generate(name, port, target).await
+ }
Command::Connect { config, ip } => commands::connect::connect(config, ip).await,
}
}
diff --git a/sparse-05/sparse-05-client/src/options.rs b/sparse-05/sparse-05-client/src/options.rs
index 025257e..9d8564a 100644
--- a/sparse-05/sparse-05-client/src/options.rs
+++ b/sparse-05/sparse-05-client/src/options.rs
@@ -14,14 +14,33 @@ fn to_socket_addr(src: &str) -> Result {
))
}
+pub enum TargetOs {
+ Linux,
+ Windows,
+}
+
+impl std::str::FromStr for TargetOs {
+ type Err = &'static str;
+ fn from_str(input: &str) -> Result {
+ match input {
+ "linux" => Ok(Self::Linux),
+ "windows" => Ok(Self::Windows),
+ _ => Err("could not parse target operating system"),
+ }
+ }
+}
+
#[derive(StructOpt)]
pub enum Command {
Generate {
#[structopt(parse(from_os_str))]
name: PathBuf,
- #[structopt(default_value = "54248")]
+ #[structopt(long, short, default_value = "54248")]
port: u16,
+
+ #[structopt(long, short, default_value = "linux")]
+ target: TargetOs,
},
Connect {
#[structopt(parse(from_os_str))]
diff --git a/sparse-05/sparse-05-server/Cargo.toml b/sparse-05/sparse-05-server/Cargo.toml
index e3d090d..fd51161 100644
--- a/sparse-05/sparse-05-server/Cargo.toml
+++ b/sparse-05/sparse-05-server/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.5.0"
edition = "2021"
[dependencies]
-pcap-sys = { path = "../../pcap-sys" }
anyhow = "1.0.70"
ed25519-dalek = "1.0.1"
rand = "0.7"
@@ -16,6 +15,10 @@ rmp-serde = "1.1.2"
catconf = "0.1.2"
sparse-05-common = { version = "0.1.0", path = "../sparse-05-common" }
ecies-ed25519 = { version = "0.5.1", features = ["serde"] }
+packets = { path = "../../packets" }
+
+[target.'cfg(unix)'.dependencies]
+pcap-sys = { path = "../../pcap-sys" }
[build-dependencies]
cc = "1.0"
diff --git a/sparse-05/sparse-05-server/src/capabilities.rs b/sparse-05/sparse-05-server/src/capabilities.rs
index 7612d6e..7676d25 100644
--- a/sparse-05/sparse-05-server/src/capabilities.rs
+++ b/sparse-05/sparse-05-server/src/capabilities.rs
@@ -23,6 +23,7 @@ struct cap_user_data_t {
inheritable: u32,
}
+#[cfg(target_os = "linux")]
fn get_username(uid: u32) -> anyhow::Result