feat: added beacon installer generation, download
This commit is contained in:
parent
b416f35b63
commit
0576c4fd3b
182
Cargo.lock
generated
182
Cargo.lock
generated
@ -95,6 +95,45 @@ version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
||||
|
||||
[[package]]
|
||||
name = "asn1-rs"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048"
|
||||
dependencies = [
|
||||
"asn1-rs-derive",
|
||||
"asn1-rs-impl",
|
||||
"displaydoc",
|
||||
"nom",
|
||||
"num-traits",
|
||||
"rusticata-macros",
|
||||
"thiserror 1.0.69",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asn1-rs-derive"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.96",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asn1-rs-impl"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.96",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-compression"
|
||||
version = "0.4.18"
|
||||
@ -797,6 +836,20 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der-parser"
|
||||
version = "9.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553"
|
||||
dependencies = [
|
||||
"asn1-rs",
|
||||
"displaydoc",
|
||||
"nom",
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
"rusticata-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
@ -1675,7 +1728,7 @@ dependencies = [
|
||||
"oco_ref",
|
||||
"or_poisoned",
|
||||
"paste",
|
||||
"rand",
|
||||
"rand 0.8.5",
|
||||
"reactive_graph",
|
||||
"rustc-hash 2.1.0",
|
||||
"send_wrapper",
|
||||
@ -2107,6 +2160,16 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint-dig"
|
||||
version = "0.8.4"
|
||||
@ -2119,7 +2182,7 @@ dependencies = [
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-traits",
|
||||
"rand",
|
||||
"rand 0.8.5",
|
||||
"smallvec",
|
||||
"zeroize",
|
||||
]
|
||||
@ -2189,6 +2252,15 @@ dependencies = [
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oid-registry"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9"
|
||||
dependencies = [
|
||||
"asn1-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.20.2"
|
||||
@ -2247,7 +2319,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
@ -2383,7 +2455,7 @@ version = "0.2.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
"zerocopy 0.7.35",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2513,8 +2585,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_chacha 0.3.1",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
|
||||
dependencies = [
|
||||
"rand_chacha 0.9.0",
|
||||
"rand_core 0.9.0",
|
||||
"zerocopy 0.8.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2524,7 +2607,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2536,6 +2629,16 @@ dependencies = [
|
||||
"getrandom 0.2.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff"
|
||||
dependencies = [
|
||||
"getrandom 0.3.1",
|
||||
"zerocopy 0.8.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rcgen"
|
||||
version = "0.13.2"
|
||||
@ -2546,6 +2649,7 @@ dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"time",
|
||||
"x509-parser",
|
||||
"yasna",
|
||||
]
|
||||
|
||||
@ -2690,7 +2794,7 @@ dependencies = [
|
||||
"num-traits",
|
||||
"pkcs1",
|
||||
"pkcs8",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
"signature",
|
||||
"spki",
|
||||
"subtle",
|
||||
@ -2740,6 +2844,15 @@ version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
|
||||
|
||||
[[package]]
|
||||
name = "rusticata-macros"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.44"
|
||||
@ -2760,6 +2873,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"log",
|
||||
"once_cell",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki",
|
||||
@ -3017,7 +3131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
|
||||
dependencies = [
|
||||
"digest",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3079,6 +3193,7 @@ dependencies = [
|
||||
"axum",
|
||||
"axum-server",
|
||||
"futures",
|
||||
"rustls",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
@ -3114,10 +3229,13 @@ dependencies = [
|
||||
"leptos_meta",
|
||||
"leptos_router",
|
||||
"pbkdf2",
|
||||
"rand 0.9.0",
|
||||
"rcgen",
|
||||
"rpassword",
|
||||
"rustls-pki-types",
|
||||
"serde",
|
||||
"sha2",
|
||||
"sparse-actions",
|
||||
"sparse-handler",
|
||||
"sqlx",
|
||||
"structopt",
|
||||
@ -3287,7 +3405,7 @@ dependencies = [
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"rand",
|
||||
"rand 0.8.5",
|
||||
"rsa",
|
||||
"serde",
|
||||
"sha1",
|
||||
@ -3326,7 +3444,7 @@ dependencies = [
|
||||
"md-5",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"rand",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
@ -3934,7 +4052,7 @@ dependencies = [
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand",
|
||||
"rand 0.8.5",
|
||||
"sha1",
|
||||
"thiserror 1.0.69",
|
||||
"utf-8",
|
||||
@ -4465,6 +4583,24 @@ version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
|
||||
|
||||
[[package]]
|
||||
name = "x509-parser"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69"
|
||||
dependencies = [
|
||||
"asn1-rs",
|
||||
"data-encoding",
|
||||
"der-parser",
|
||||
"lazy_static",
|
||||
"nom",
|
||||
"oid-registry",
|
||||
"ring",
|
||||
"rusticata-macros",
|
||||
"thiserror 1.0.69",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xxhash-rust"
|
||||
version = "0.8.15"
|
||||
@ -4517,7 +4653,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"zerocopy-derive",
|
||||
"zerocopy-derive 0.7.35",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468"
|
||||
dependencies = [
|
||||
"zerocopy-derive 0.8.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4531,6 +4676,17 @@ dependencies = [
|
||||
"syn 2.0.96",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.96",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom"
|
||||
version = "0.1.5"
|
||||
|
||||
@ -11,6 +11,9 @@ lto = true
|
||||
codegen-units = 1
|
||||
panic = "abort"
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.wasm-release]
|
||||
inherits = "release"
|
||||
strip = true
|
||||
|
||||
17
flake.nix
17
flake.nix
@ -99,6 +99,7 @@
|
||||
|
||||
craneLib = (crane.mkLib pkgs).overrideToolchain (p:
|
||||
p.rust-bin.nightly.latest.default.override {
|
||||
extensions = [ "rust-src" ];
|
||||
targets = [
|
||||
"x86_64-unknown-linux-gnu"
|
||||
"x86_64-unknown-linux-musl"
|
||||
@ -138,9 +139,10 @@
|
||||
set -eux
|
||||
|
||||
${setup-zig-freebsd}/bin/setup-zig-freebsd
|
||||
cargo build -p sparse-windows-beacon --target=x86_64-pc-windows-gnu
|
||||
cargo build -p sparse-unix-beacon --target=x86_64-unknown-freebsd
|
||||
cargo build -p sparse-unix-beacon --target=x86_64-unknown-linux-musl
|
||||
|
||||
mkdir -p target/x86_64-{unknown-{linux-musl,freebsd},pc-windows-gnu}/debug
|
||||
touch target/x86_64-unknown-{linux-musl,freebsd}/debug/sparse-unix-{beacon,installer}
|
||||
touch target/x86_64-pc-windows-gnu/debug/sparse-windows-{beacon.dll,installer.exe}
|
||||
'';
|
||||
in {
|
||||
packages = outputs.packages;
|
||||
@ -155,15 +157,18 @@
|
||||
|
||||
# Added to make development easier
|
||||
SPARSE_INSTALLER_LINUX =
|
||||
"../../target/x86_64-unknown-linux-musl/debug/sparse-unix-beacon";
|
||||
"../../target/x86_64-unknown-linux-musl/debug/sparse-unix-installer";
|
||||
SPARSE_INSTALLER_FREEBSD =
|
||||
"../../target/x86_64-unknown-freebsd/debug/sparse-unix-beacon";
|
||||
"../../target/x86_64-unknown-freebsd/debug/sparse-unix-installer";
|
||||
SPARSE_INSTALLER_WINDOWS =
|
||||
"../../target/x86_64-pc-windows-gnu/debug/sparse-windows-installer.exe";
|
||||
|
||||
SPARSE_BEACON_LINUX =
|
||||
"../../target/x86_64-unknown-linux-musl/debug/sparse-unix-beacon";
|
||||
SPARSE_BEACON_FREEBSD =
|
||||
"../../target/x86_64-unknown-freebsd/debug/sparse-unix-beacon";
|
||||
SPARSE_BEACON_WINDOWS =
|
||||
"../../target/x86_64-pc-windows-gnu/debug/sparse-windows-beacon.exe";
|
||||
"../../../target/x86_64-pc-windows-gnu/debug/sparse-windows-beacon.dll";
|
||||
|
||||
shellHook = ''
|
||||
export DATABASE_URL="sqlite://$(${pkgs.git}/bin/git rev-parse --show-toplevel)/sparse-server/db.sqlite"
|
||||
|
||||
@ -288,8 +288,9 @@ let
|
||||
|
||||
outputs = rec {
|
||||
packages = {
|
||||
inherit sparse-server sparse-installer-linux sparse-installer-freebsd
|
||||
sparse-installer-windows;
|
||||
inherit sparse-server sparse-beacon-linux sparse-beacon-freebsd
|
||||
sparse-beacon-windows linux-loader freebsd-loader sparse-installer-linux
|
||||
sparse-installer-freebsd sparse-installer-windows;
|
||||
|
||||
inherit freebsd-zig-libc;
|
||||
|
||||
|
||||
@ -14,3 +14,4 @@ sqlx = { version = "0.8", default-features = false, features = ["chrono", "macro
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
axum-server = { version = "^0.7", features = ["tokio-rustls", "tls-rustls"] }
|
||||
rustls = "0.23"
|
||||
|
||||
@ -4,6 +4,7 @@ pub enum Error {
|
||||
Sqlx(sqlx::Error),
|
||||
TokioJoin(tokio::task::JoinError),
|
||||
Io(std::io::Error),
|
||||
Rustls(rustls::Error),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
@ -21,6 +22,9 @@ impl std::fmt::Display for Error {
|
||||
Error::Io(err) => {
|
||||
write!(f, "io error: {err:?}")
|
||||
}
|
||||
Error::Rustls(err) => {
|
||||
write!(f, "rustls error: {err:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -31,6 +35,7 @@ impl std::error::Error for Error {
|
||||
Error::Sqlx(err) => Some(err),
|
||||
Error::TokioJoin(err) => Some(err),
|
||||
Error::Io(err) => Some(err),
|
||||
Error::Rustls(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -61,3 +66,9 @@ impl From<std::io::Error> for Error {
|
||||
Self::Io(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<rustls::Error> for Error {
|
||||
fn from(err: rustls::Error) -> Self {
|
||||
Self::Rustls(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ use std::{
|
||||
};
|
||||
|
||||
use axum::routing::{get, post, Router};
|
||||
use axum_server::tls_rustls::RustlsConfig;
|
||||
use sqlx::SqlitePool;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
@ -36,8 +35,6 @@ impl std::ops::Deref for BeaconListenerMap {
|
||||
}
|
||||
|
||||
pub async fn start_all_listeners(beacon_listener_map: BeaconListenerMap, db: SqlitePool) -> Result<(), crate::error::Error> {
|
||||
tracing::debug!("Typeid: {:?}", std::any::TypeId::of::<BeaconListenerMap>());
|
||||
|
||||
let listener_ids = sqlx::query!("SELECT listener_id FROM beacon_listener")
|
||||
.fetch_all(&db)
|
||||
.await?;
|
||||
@ -56,6 +53,15 @@ struct ListenerState {
|
||||
db: SqlitePool
|
||||
}
|
||||
|
||||
struct Listener {
|
||||
listener_id: i64,
|
||||
port: i64,
|
||||
public_ip: String,
|
||||
domain_name: String,
|
||||
certificate: Vec<u8>,
|
||||
privkey: Vec<u8>
|
||||
}
|
||||
|
||||
pub async fn start_listener(beacon_listener_map: BeaconListenerMap, listener_id: i64, db: SqlitePool) -> Result<(), crate::error::Error> {
|
||||
{
|
||||
let Ok(blm_handle) = beacon_listener_map.read() else {
|
||||
@ -66,7 +72,7 @@ pub async fn start_listener(beacon_listener_map: BeaconListenerMap, listener_id:
|
||||
return Err(crate::error::Error::Generic("Beacon listener already started".to_string()));
|
||||
}
|
||||
}
|
||||
let listener = sqlx::query!("SELECT * FROM beacon_listener WHERE listener_id = ?", listener_id)
|
||||
let listener = sqlx::query_as!(Listener, "SELECT * FROM beacon_listener WHERE listener_id = ?", listener_id)
|
||||
.fetch_one(&db)
|
||||
.await?;
|
||||
|
||||
@ -84,17 +90,30 @@ pub async fn start_listener(beacon_listener_map: BeaconListenerMap, listener_id:
|
||||
|
||||
let hidden_app = Router::new().nest("/hidden_sparse", app);
|
||||
|
||||
let tls_config = RustlsConfig::from_pem(
|
||||
listener.certificate.as_bytes().to_vec(),
|
||||
listener.privkey.as_bytes().to_vec()
|
||||
).await?;
|
||||
let keypair = match rustls::pki_types::PrivateKeyDer::try_from(listener.privkey.clone()) {
|
||||
Ok(pk) => pk,
|
||||
Err(e) => {
|
||||
return Err(crate::error::Error::Generic(format!("Could not parse private key: {e}")));
|
||||
}
|
||||
};
|
||||
let cert = rustls::pki_types::CertificateDer::from(listener.certificate.clone());
|
||||
|
||||
let mut tls_config = rustls::ServerConfig::builder()
|
||||
.with_no_client_auth()
|
||||
.with_single_cert(vec![cert], keypair)?;
|
||||
tls_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
|
||||
|
||||
let addr = std::net::SocketAddr::from(([0, 0, 0, 0], listener.port as u16));
|
||||
|
||||
tracing::debug!("Starting listener {}, {}, on port {}", listener_id, listener.domain_name, listener.port);
|
||||
|
||||
let join_handle = tokio::task::spawn(async move {
|
||||
let res = axum_server::tls_rustls::bind_rustls(addr, tls_config)
|
||||
let res = axum_server::tls_rustls::bind_rustls(
|
||||
addr,
|
||||
axum_server::tls_rustls::RustlsConfig::from_config(
|
||||
Arc::new(tls_config)
|
||||
)
|
||||
)
|
||||
.serve(hidden_app.into_make_service())
|
||||
.await;
|
||||
|
||||
|
||||
@ -9,12 +9,12 @@ crate-type = ["cdylib", "rlib"]
|
||||
[dependencies]
|
||||
leptos = { version = "^0.7", features = ["nightly"] }
|
||||
leptos_router = { version = "^0.7", features = ["nightly"] }
|
||||
axum = { version = "^0.7", features = ["ws", "macros"], optional = true }
|
||||
axum = { version = "^0.7", features = ["ws", "macros", "http2"], optional = true }
|
||||
axum-extra = { version = "^0.9", features = ["cookie"], optional = true }
|
||||
console_error_panic_hook = "0.1"
|
||||
leptos_axum = { version = "^0.7", optional = true }
|
||||
leptos_meta = { version = "^0.7" }
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "signal"], optional = true }
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "signal", "fs", "io-std", "io-util"], optional = true }
|
||||
tower = { version = "0.4", optional = true }
|
||||
tower-http = { version = "0.5", features = ["fs", "compression-br", "compression-deflate", "compression-gzip", "compression-zstd", "trace"], optional = true }
|
||||
wasm-bindgen = "0.2"
|
||||
@ -39,9 +39,12 @@ sha2 = { version = "0.10", optional = true }
|
||||
hex = { version = "0.4", optional = true }
|
||||
serde = "1.0"
|
||||
cfg-if = "1.0.0"
|
||||
rcgen = { version = "0.13.2", optional = true }
|
||||
rcgen = { version = "0.13.2", features = ["pem", "x509-parser", "crypto"], optional = true }
|
||||
cron = { version = "0.15.0", optional = true }
|
||||
rustls-pki-types = { version = "1.7", optional = true }
|
||||
rand = { version = "0.9", optional = true }
|
||||
|
||||
sparse-actions = { path = "../sparse-actions", optional = true }
|
||||
sparse-handler = { path = "../sparse-handler", optional = true }
|
||||
|
||||
[features]
|
||||
@ -67,6 +70,9 @@ ssr = [
|
||||
"dep:rcgen",
|
||||
"dep:cron",
|
||||
"dep:sparse-handler",
|
||||
"dep:rustls-pki-types",
|
||||
"dep:sparse-actions",
|
||||
"dep:rand",
|
||||
"leptos/ssr",
|
||||
"leptos_meta/ssr",
|
||||
"leptos_router/ssr",
|
||||
|
||||
14
sparse-server/migrations/20250202045114_mtls.sql
Normal file
14
sparse-server/migrations/20250202045114_mtls.sql
Normal file
@ -0,0 +1,14 @@
|
||||
-- Add migration script here
|
||||
ALTER TABLE beacon_template ADD COLUMN client_key blob NOT NULL DEFAULT '';
|
||||
ALTER TABLE beacon_template ADD COLUMN client_cert blob NOT NULL DEFAULT '';
|
||||
|
||||
DROP TABLE beacon_listener;
|
||||
CREATE TABLE beacon_listener (
|
||||
listener_id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
|
||||
port int NOT NULL,
|
||||
public_ip varchar NOT NULL,
|
||||
domain_name varchar NOT NULL,
|
||||
certificate blob NOT NULL,
|
||||
privkey blob NOT NULL
|
||||
);
|
||||
@ -112,6 +112,7 @@ pub fn provide_beacon_resources() {
|
||||
|
||||
#[component]
|
||||
pub fn BeaconView() -> impl IntoView {
|
||||
#[cfg(feature = "hydrate")]
|
||||
Effect::new(move || {
|
||||
let user = expect_context::<ReadSignal<Option<crate::users::User>>>();
|
||||
if user.get().is_none() {
|
||||
|
||||
@ -101,7 +101,6 @@ pub async fn rename_category(id: i64, name: String) -> Result<(), ServerFnError>
|
||||
pub fn CategoriesView() -> impl IntoView {
|
||||
let BeaconResources { add_category, categories, .. } = expect_context();
|
||||
|
||||
|
||||
view! {
|
||||
<div class="categories">
|
||||
<h2>"Categories"</h2>
|
||||
|
||||
@ -71,6 +71,17 @@ pub async fn get_listeners() -> Result<Vec<PubListener>, ServerFnError> {
|
||||
.collect())
|
||||
}
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
pub fn generate_cert_from_keypair(kp: &rcgen::KeyPair, names: Vec<String>) -> Result<rcgen::Certificate, rcgen::Error> {
|
||||
use rcgen::CertificateParams;
|
||||
|
||||
let mut params = CertificateParams::new(names)?;
|
||||
|
||||
params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained);
|
||||
|
||||
params.self_signed(&kp)
|
||||
}
|
||||
|
||||
#[server]
|
||||
pub async fn add_listener(public_ip: String, port: i16, domain_name: String) -> Result<(), ServerFnError> {
|
||||
let user = user::get_auth_session().await?;
|
||||
@ -84,15 +95,19 @@ pub async fn add_listener(public_ip: String, port: i16, domain_name: String) ->
|
||||
}
|
||||
|
||||
let subject_alt_names = vec![public_ip.to_string(), domain_name.clone()];
|
||||
let CertifiedKey { cert, key_pair } = tokio::task::spawn_blocking(|| {
|
||||
generate_simple_self_signed(subject_alt_names)
|
||||
|
||||
|
||||
let (key_pair, cert) = tokio::task::spawn_blocking(|| {
|
||||
rcgen::KeyPair::generate_for(&rcgen::PKCS_ECDSA_P256_SHA256)
|
||||
.and_then(|keypair|
|
||||
generate_cert_from_keypair(&keypair, subject_alt_names).map(|cert| (keypair, cert)))
|
||||
}).await??;
|
||||
|
||||
let db = expect_context::<SqlitePool>();
|
||||
|
||||
let public_ip = public_ip.to_string();
|
||||
let cert = cert.pem().to_string();
|
||||
let key_pair = key_pair.serialize_pem().to_string();
|
||||
let cert = cert.der().to_vec();
|
||||
let key_pair = key_pair.serialize_der();
|
||||
|
||||
sqlx::query!(
|
||||
"INSERT INTO beacon_listener (port, public_ip, domain_name, certificate, privkey) VALUES (?, ?, ?, ?, ?)",
|
||||
@ -116,23 +131,32 @@ pub async fn remove_listener(listener_id: i64) -> Result<(), ServerFnError> {
|
||||
return Err(ServerFnError::<NoCustomError>::ServerError("You are not signed in!".to_owned()));
|
||||
}
|
||||
|
||||
let pool = expect_context::<SqlitePool>();
|
||||
let blm = expect_context::<BeaconListenerMap>();
|
||||
{
|
||||
let blm = expect_context::<BeaconListenerMap>();
|
||||
|
||||
let Ok(mut blm_handle) = blm.write() else {
|
||||
return Err(ServerFnError::<NoCustomError>::ServerError("Failed to get write handle for beacon listener map".to_owned()));
|
||||
};
|
||||
let Ok(mut blm_handle) = blm.write() else {
|
||||
return Err(ServerFnError::<NoCustomError>::ServerError("Failed to get write handle for beacon listener map".to_owned()));
|
||||
};
|
||||
|
||||
if let Some(mut bl) = blm_handle.get_mut(&listener_id) {
|
||||
bl.abort();
|
||||
} else {
|
||||
return Err(ServerFnError::<NoCustomError>::ServerError("Failed to get write handle for beacon listener map".to_owned()));
|
||||
if let Some(bl) = blm_handle.get_mut(&listener_id) {
|
||||
bl.abort();
|
||||
} else {
|
||||
return Err(ServerFnError::<NoCustomError>::ServerError("Failed to get write handle for beacon listener map".to_owned()));
|
||||
}
|
||||
|
||||
blm_handle.remove(&listener_id);
|
||||
}
|
||||
|
||||
blm_handle.remove(&listener_id);
|
||||
drop(blm_handle);
|
||||
let pool = expect_context::<SqlitePool>();
|
||||
|
||||
unimplemented!()
|
||||
sqlx::query!(
|
||||
"DELETE FROM beacon_listener WHERE listener_id = ?",
|
||||
listener_id
|
||||
)
|
||||
.execute(&pool)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[server]
|
||||
|
||||
@ -103,6 +103,34 @@ pub async fn add_template(
|
||||
|
||||
let db = expect_context::<SqlitePool>();
|
||||
|
||||
let listener = sqlx::query!(
|
||||
"SELECT certificate, privkey FROM beacon_listener WHERE listener_id = ?",
|
||||
listener_id
|
||||
)
|
||||
.fetch_one(&db)
|
||||
.await?;
|
||||
|
||||
use rcgen::{Certificate, CertificateParams, KeyPair};
|
||||
|
||||
let keypair = KeyPair::from_der_and_sign_algo(
|
||||
match &rustls_pki_types::PrivateKeyDer::try_from(&*listener.privkey) {
|
||||
Ok(pk) => pk,
|
||||
Err(e) => {
|
||||
srverr!("Could not parse private key: {e}");
|
||||
}
|
||||
},
|
||||
&rcgen::PKCS_ECDSA_P256_SHA256
|
||||
)?;
|
||||
let ca_params = CertificateParams::from_ca_cert_der(&(*listener.certificate).into())?;
|
||||
let ca_cert = ca_params.self_signed(&keypair)?;
|
||||
|
||||
let client_key = KeyPair::generate()?;
|
||||
let client_params = CertificateParams::default();
|
||||
let client_cert = client_params.signed_by(&client_key, &ca_cert, &keypair)?;
|
||||
|
||||
let client_key_der = client_key.serialize_der();
|
||||
let client_cert_der = client_cert.der().to_vec();
|
||||
|
||||
match &*source_mode {
|
||||
"host" => {
|
||||
let source_mac = Some(source_mac).filter(|mac| mac != "00:00:00:00:00:00");
|
||||
@ -110,16 +138,18 @@ pub async fn add_template(
|
||||
|
||||
sqlx::query!(
|
||||
r"INSERT INTO beacon_template
|
||||
(template_name, operating_system, config_id, listener_id, source_ip, source_mac, source_mode, default_category)
|
||||
(template_name, operating_system, config_id, listener_id, source_ip, source_mac, source_mode, default_category, client_key, client_cert)
|
||||
VALUES
|
||||
(?, ?, ?, ?, ?, ?, 'host', ?)",
|
||||
(?, ?, ?, ?, ?, ?, 'host', ?, ?, ?)",
|
||||
template_name,
|
||||
operating_system,
|
||||
config_id,
|
||||
listener_id,
|
||||
source_ip,
|
||||
source_mac,
|
||||
default_category
|
||||
default_category,
|
||||
client_key_der,
|
||||
client_cert_der
|
||||
)
|
||||
.execute(&db)
|
||||
.await?;
|
||||
@ -132,9 +162,9 @@ pub async fn add_template(
|
||||
|
||||
sqlx::query!(
|
||||
r"INSERT INTO beacon_template
|
||||
(template_name, operating_system, config_id, listener_id, source_ip, source_mac, source_mode, source_netmask, source_gateway, default_category)
|
||||
(template_name, operating_system, config_id, listener_id, source_ip, source_mac, source_mode, source_netmask, source_gateway, default_category, client_key, client_cert)
|
||||
VALUES
|
||||
(?, ?, ?, ?, ?, ?, 'host', ?, ?, ?)",
|
||||
(?, ?, ?, ?, ?, ?, 'host', ?, ?, ?, ?, ?)",
|
||||
template_name,
|
||||
operating_system,
|
||||
config_id,
|
||||
@ -143,7 +173,9 @@ pub async fn add_template(
|
||||
source_mac,
|
||||
source_netmask,
|
||||
source_gateway,
|
||||
default_category
|
||||
default_category,
|
||||
client_key_der,
|
||||
client_cert_der
|
||||
)
|
||||
.execute(&db)
|
||||
.await?;
|
||||
@ -376,9 +408,13 @@ pub fn DisplayTemplates(
|
||||
")"
|
||||
</h4>
|
||||
<div>
|
||||
<button>
|
||||
<a
|
||||
class="button"
|
||||
download=""
|
||||
href=format!("/installer/{}", template.template_id)
|
||||
>
|
||||
"Download installer"
|
||||
</button>
|
||||
</a>
|
||||
<button
|
||||
on:click={
|
||||
let template_id = template.template_id;
|
||||
@ -386,6 +422,7 @@ pub fn DisplayTemplates(
|
||||
remove_template.dispatch(RemoveTemplate { template_id });
|
||||
}
|
||||
}
|
||||
class="warning"
|
||||
>
|
||||
"Delete template"
|
||||
</button>
|
||||
|
||||
@ -10,6 +10,7 @@ pub enum Error {
|
||||
Pbkdf2(pbkdf2::password_hash::errors::Error),
|
||||
#[cfg(feature = "ssr")]
|
||||
Io(std::io::Error),
|
||||
AddrParse(std::net::AddrParseError),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
@ -37,6 +38,9 @@ impl std::fmt::Display for Error {
|
||||
Error::Io(err) => {
|
||||
write!(f, "io error: {err:?}")
|
||||
}
|
||||
Error::AddrParse(err) => {
|
||||
write!(f, "ip address parse error: {err:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -50,11 +54,23 @@ impl std::error::Error for Error {
|
||||
Error::TokioJoin(err) => Some(err),
|
||||
#[cfg(feature = "ssr")]
|
||||
Error::Io(err) => Some(err),
|
||||
Error::AddrParse(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
impl axum::response::IntoResponse for Error {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
(
|
||||
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("{:?}", self),
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Error {
|
||||
type Err = Self;
|
||||
|
||||
@ -90,3 +106,9 @@ impl From<std::io::Error> for Error {
|
||||
Self::Io(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::net::AddrParseError> for Error {
|
||||
fn from(err: std::net::AddrParseError) -> Self {
|
||||
Self::AddrParse(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,19 +1,3 @@
|
||||
#[cfg(feature = "hydrate")]
|
||||
pub(crate) mod beacon_binaries {
|
||||
#[allow(dead_code)]
|
||||
pub const LINUX_BEACON: &'static [u8] = include_bytes!(std::env!("SPARSE_BEACON_LINUX"));
|
||||
#[allow(dead_code)]
|
||||
pub const FREEBSD_BEACON: &'static [u8] = include_bytes!(std::env!("SPARSE_BEACON_FREEBSD"));
|
||||
#[allow(dead_code)]
|
||||
pub const WINDOWS_BEACON: &'static [u8] = include_bytes!(std::env!("SPARSE_BEACON_WINDOWS"));
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const LINUX_INSTALLER: &'static [u8] = include_bytes!(std::env!("SPARSE_INSTALLER_LINUX"));
|
||||
#[allow(dead_code)]
|
||||
pub const FREEBSD_INSTALLER: &'static [u8] = include_bytes!(std::env!("SPARSE_INSTALLER_FREEBSD"));
|
||||
#[allow(dead_code)]
|
||||
pub const WINDOWS_INSTALLER: &'static [u8] = include_bytes!(std::env!("SPARSE_INSTALLER_WINDOWS"));
|
||||
}
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
mod cli;
|
||||
@ -29,6 +13,7 @@ pub mod db;
|
||||
#[cfg(feature = "ssr")]
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<std::process::ExitCode> {
|
||||
|
||||
use std::{path::PathBuf, process::ExitCode, str::FromStr};
|
||||
|
||||
use structopt::StructOpt;
|
||||
@ -38,7 +23,7 @@ async fn main() -> anyhow::Result<std::process::ExitCode> {
|
||||
tracing_subscriber::registry()
|
||||
.with(
|
||||
tracing_subscriber::EnvFilter::try_from_default_env()
|
||||
.unwrap_or_else(|_| format!("{}=debug,sparse_handler=debug,tower_http=trace", env!("CARGO_CRATE_NAME")).into()),
|
||||
.unwrap_or_else(|_| format!("{}=debug,sparse_handler=debug", env!("CARGO_CRATE_NAME")).into()),
|
||||
)
|
||||
.with(tracing_subscriber::fmt::layer())
|
||||
.init();
|
||||
|
||||
@ -1,13 +1,167 @@
|
||||
use std::{net::SocketAddrV4, process::ExitCode};
|
||||
|
||||
use sqlx::sqlite::SqlitePool;
|
||||
use axum::Router;
|
||||
use axum::{extract::{FromRef, Path, State}, response::IntoResponse, Router, routing::get};
|
||||
use leptos::prelude::*;
|
||||
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||
use tokio::signal;
|
||||
|
||||
use sparse_server::app::*;
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
pub(crate) mod beacon_binaries {
|
||||
pub const LINUX_INSTALLER: &'static [u8] = include_bytes!(std::env!("SPARSE_INSTALLER_LINUX"));
|
||||
pub const FREEBSD_INSTALLER: &'static [u8] = include_bytes!(std::env!("SPARSE_INSTALLER_FREEBSD"));
|
||||
pub const WINDOWS_INSTALLER: &'static [u8] = include_bytes!(std::env!("SPARSE_INSTALLER_WINDOWS"));
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
pub async fn get_installer(btype: &str) -> Result<Vec<u8>, crate::error::Error> {
|
||||
let path = match btype {
|
||||
"linux" => "target/x86_64-unknown-linux-musl/debug/sparse-unix-installer",
|
||||
"freebsd" => "target/x86_64-unknown-freebsd/debug/sparse-unix-installer",
|
||||
"windows" => "target/x86_64-pc-windows-gnu/debug/sparse-unix-installer",
|
||||
other => return Err(crate::error::Error::Generic(format!("unknown beacon type: {other}"))),
|
||||
};
|
||||
|
||||
Ok(tokio::fs::read(path).await?)
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
pub async fn get_installer(btype: &str) -> Result<Vec<u8>, crate::error::Error> {
|
||||
match btype {
|
||||
"linux" => Ok(beacon_binaries::LINUX_INSTALLER.to_owned()),
|
||||
"windows" => Ok(beacon_binaries::WINDOWS_INSTALLER.to_owned()),
|
||||
"freebsd" => Ok(beacon_binaries::FREEBSD_INSTALLER.to_owned()),
|
||||
other => Err(crate::error::Error::Generic(format!("unknown beacon type: {other}")))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromRef, Clone, Debug)]
|
||||
pub struct AppState {
|
||||
db: SqlitePool,
|
||||
leptos_options: leptos::config::LeptosOptions
|
||||
}
|
||||
|
||||
#[axum::debug_handler]
|
||||
pub async fn download_beacon_installer(
|
||||
Path(template_id): Path<i64>,
|
||||
State(db): State<AppState>
|
||||
) -> Result<impl IntoResponse, crate::error::Error> {
|
||||
use rand::{rngs::OsRng, TryRngCore};
|
||||
use sparse_actions::payload_types::Parameters_t;
|
||||
|
||||
let mut parameters_buffer = vec![0u8; std::mem::size_of::<Parameters_t>()];
|
||||
//let _ = OsRng.try_fill_bytes(&mut parameters_buffer);
|
||||
|
||||
let parameters: &mut Parameters_t = unsafe { std::mem::transmute(parameters_buffer.as_mut_ptr()) };
|
||||
|
||||
let template = sqlx::query!(
|
||||
r"SELECT operating_system, source_ip, source_mac, source_mode, source_netmask,
|
||||
source_gateway, port, public_ip, domain_name, certificate, client_cert, client_key
|
||||
FROM beacon_template JOIN beacon_listener"
|
||||
)
|
||||
.fetch_one(&db.db)
|
||||
.await?;
|
||||
|
||||
let dest_ip = template.public_ip.parse::<std::net::Ipv4Addr>()?;
|
||||
let src_ip = template.source_ip.parse::<std::net::Ipv4Addr>()?;
|
||||
|
||||
let dest_octets = dest_ip.octets();
|
||||
parameters.destination_ip.a = dest_octets[0];
|
||||
parameters.destination_ip.b = dest_octets[1];
|
||||
parameters.destination_ip.c = dest_octets[2];
|
||||
parameters.destination_ip.d = dest_octets[3];
|
||||
|
||||
let src_mac: [u8; 6] = template
|
||||
.source_mac
|
||||
.unwrap_or("00:00:00:00:00:00".to_string())
|
||||
.split(":")
|
||||
.map(|by| u8::from_str_radix(by, 16))
|
||||
.collect::<Result<Vec<u8>, _>>()
|
||||
.map_err(|_| crate::error::Error::Generic("Could not parse source MAC address".to_string()))
|
||||
.and_then(
|
||||
|bytes| bytes.try_into().map_err(|_| crate::error::Error::Generic("Could not parse source MAC address".to_string()))
|
||||
)?;
|
||||
|
||||
let src_octets = src_ip.octets();
|
||||
match (template.source_mode.as_deref(), template.source_netmask, template.source_gateway) {
|
||||
(Some("custom"), Some(nm), Some(ip)) => unsafe {
|
||||
let gateway = ip.parse::<std::net::Ipv4Addr>()?;
|
||||
let gw_octets = gateway.octets();
|
||||
|
||||
parameters.source_ip.custom_networking.mode = 0;
|
||||
parameters.source_ip.custom_networking.source_mac.copy_from_slice(&src_mac[..]);
|
||||
parameters.source_ip.custom_networking.netmask = nm as u16;
|
||||
parameters.source_ip.custom_networking.source_ip.a = src_octets[0];
|
||||
parameters.source_ip.custom_networking.source_ip.b = src_octets[1];
|
||||
parameters.source_ip.custom_networking.source_ip.c = src_octets[2];
|
||||
parameters.source_ip.custom_networking.source_ip.d = src_octets[3];
|
||||
parameters.source_ip.custom_networking.gateway.a = gw_octets[0];
|
||||
parameters.source_ip.custom_networking.gateway.b = gw_octets[1];
|
||||
parameters.source_ip.custom_networking.gateway.c = gw_octets[2];
|
||||
parameters.source_ip.custom_networking.gateway.d = gw_octets[3];
|
||||
}
|
||||
(Some("host"), _, _) => unsafe {
|
||||
parameters.source_ip.use_host_networking.mode = 1;
|
||||
parameters.source_ip.use_host_networking.source_mac.copy_from_slice(&src_mac[..]);
|
||||
parameters.source_ip.use_host_networking.source_ip.a = src_octets[0];
|
||||
parameters.source_ip.use_host_networking.source_ip.b = src_octets[1];
|
||||
parameters.source_ip.use_host_networking.source_ip.c = src_octets[2];
|
||||
parameters.source_ip.use_host_networking.source_ip.d = src_octets[3];
|
||||
}
|
||||
_ => {
|
||||
return Err(crate::error::Error::Generic("Could not parse host networking configuration".to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
parameters.destination_port = template.port as u16;
|
||||
parameters.template_id = template_id as u16;
|
||||
|
||||
let pubkey_cert = template.certificate;
|
||||
parameters.pubkey_cert[..pubkey_cert.len()].copy_from_slice(&pubkey_cert[..]);
|
||||
parameters.pubkey_cert_size = pubkey_cert.len() as u16;
|
||||
|
||||
let client_key = template.client_key;
|
||||
parameters.client_key[..client_key.len()].copy_from_slice(&client_key[..]);
|
||||
parameters.client_key_length = client_key.len() as u16;
|
||||
|
||||
let client_cert = template.client_cert;
|
||||
parameters.client_cert[..client_cert.len()].copy_from_slice(&client_cert[..]);
|
||||
parameters.client_cert_length = client_cert.len() as u16;
|
||||
|
||||
let domain_name = template.domain_name.as_bytes();
|
||||
parameters.domain_name[..domain_name.len()].copy_from_slice(&domain_name[..]);
|
||||
parameters.domain_name_length = domain_name.len() as u16;
|
||||
|
||||
let installer_bytes = get_installer(&template.operating_system).await?;
|
||||
|
||||
use axum::http::header;
|
||||
|
||||
Ok((
|
||||
[
|
||||
(
|
||||
header::CONTENT_TYPE,
|
||||
"application/octet-stream".to_string()
|
||||
),
|
||||
(
|
||||
header::CONTENT_DISPOSITION,
|
||||
format!(
|
||||
r#"attachement; filename="sparse-installer{}""#,
|
||||
if template.operating_system == "windows" {
|
||||
".exe"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
)
|
||||
)
|
||||
],
|
||||
[
|
||||
&installer_bytes[..],
|
||||
¶meters_buffer[..]
|
||||
].concat()
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn serve_web(management_address: SocketAddrV4, db: SqlitePool) -> anyhow::Result<ExitCode> {
|
||||
let conf = get_configuration(None).unwrap();
|
||||
let leptos_options = conf.leptos_options;
|
||||
@ -22,9 +176,15 @@ pub async fn serve_web(management_address: SocketAddrV4, db: SqlitePool) -> anyh
|
||||
|
||||
sparse_handler::start_all_listeners(beacon_listeners.clone(), db.clone()).await?;
|
||||
|
||||
let state = AppState {
|
||||
leptos_options: leptos_options.clone(),
|
||||
db: db.clone()
|
||||
};
|
||||
|
||||
let app = Router::new()
|
||||
.route("/installer/:template_id", get(download_beacon_installer))
|
||||
.leptos_routes_with_context(
|
||||
&leptos_options,
|
||||
&state,
|
||||
routes,
|
||||
move || {
|
||||
provide_context(beacon_listeners.clone());
|
||||
@ -36,7 +196,7 @@ pub async fn serve_web(management_address: SocketAddrV4, db: SqlitePool) -> anyh
|
||||
}
|
||||
)
|
||||
.fallback(leptos_axum::file_and_error_handler::<leptos::config::LeptosOptions, _>(shell))
|
||||
.with_state(leptos_options)
|
||||
.with_state(state)
|
||||
.layer(
|
||||
tower::ServiceBuilder::new()
|
||||
.layer(tower_http::trace::TraceLayer::new_for_http())
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
main.beacons div.categories {
|
||||
padding: 10px;
|
||||
overflow-y: scroll;
|
||||
|
||||
fieldset {
|
||||
display: grid;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
main.beacons div.config {
|
||||
padding: 10px;
|
||||
overflow-y: scroll;
|
||||
|
||||
fieldset {
|
||||
display: grid;
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
main.beacons div.listeners {
|
||||
overflow-y: scroll;
|
||||
|
||||
form, p, h2 {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
main.beacons div.templates {
|
||||
padding: 10px;
|
||||
overflow-y: scroll;
|
||||
|
||||
fieldset {
|
||||
display: grid;
|
||||
|
||||
@ -70,7 +70,11 @@ main {
|
||||
|
||||
input[type="submit"],
|
||||
input[type="button"],
|
||||
button {
|
||||
button,
|
||||
a.button {
|
||||
font-family: sans-serif;
|
||||
font-size: 0.9rem;
|
||||
color: black;
|
||||
background-color: #fff;
|
||||
border: 1px solid black;
|
||||
cursor: pointer;
|
||||
@ -82,4 +86,13 @@ button {
|
||||
&:hover {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
&.warning {
|
||||
background-color: #f00;
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
background-color: #c00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,12 +10,12 @@ typedef struct {
|
||||
typedef union SourceIp {
|
||||
struct {
|
||||
char mode; // set to 0
|
||||
char source_mac[6];
|
||||
unsigned char source_mac[6];
|
||||
ipaddr_t source_ip;
|
||||
} use_host_networking;
|
||||
struct {
|
||||
char mode; // set to 1
|
||||
char source_mac[6];
|
||||
unsigned char source_mac[6];
|
||||
unsigned short netmask;
|
||||
ipaddr_t source_ip;
|
||||
ipaddr_t gateway;
|
||||
@ -27,12 +27,17 @@ typedef struct Parameters {
|
||||
SourceIp_t source_ip;
|
||||
unsigned short destination_port;
|
||||
unsigned short pubkey_cert_size;
|
||||
unsigned short template_name_length;
|
||||
unsigned short domain_name_length;
|
||||
unsigned short beacon_name_length;
|
||||
char pubkey_cert[1024];
|
||||
char beacon_identifier[64];
|
||||
char template_name[128];
|
||||
char domain_name[128];
|
||||
char beacon_name[128];
|
||||
unsigned short client_key_length;
|
||||
unsigned short client_cert_length;
|
||||
unsigned short template_id;
|
||||
unsigned char delay_seconds_min;
|
||||
unsigned char delay_seconds_max;
|
||||
unsigned char pubkey_cert[512];
|
||||
unsigned char client_key[256];
|
||||
unsigned char client_cert[384];
|
||||
unsigned char beacon_identifier[64];
|
||||
unsigned char domain_name[64];
|
||||
unsigned char beacon_name[128];
|
||||
} Parameters_t;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user