From bc5f721de8996b48550b5069f5592caf2968e822 Mon Sep 17 00:00:00 2001 From: fx Date: Mon, 9 Oct 2023 13:07:54 +0200 Subject: added wol func and bad auth --- Cargo.lock | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 4 +- src/auth.rs | 41 ++++++++- src/config.rs | 11 +++ src/main.rs | 3 +- src/routes/start.rs | 57 +++++++++++-- src/wol.rs | 29 +++++++ 7 files changed, 367 insertions(+), 14 deletions(-) create mode 100644 src/wol.rs diff --git a/Cargo.lock b/Cargo.lock index 47552e5..997a53e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "1.1.1" @@ -104,6 +115,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.4" @@ -146,6 +163,25 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "config" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7" +dependencies = [ + "async-trait", + "json5", + "lazy_static", + "nom", + "pathdiff", + "ron", + "rust-ini", + "serde", + "serde_json", + "toml", + "yaml-rust", +] + [[package]] name = "cpufeatures" version = "0.2.9" @@ -181,6 +217,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dlv-list" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" + [[package]] name = "fnv" version = "1.0.7" @@ -239,19 +281,39 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + [[package]] name = "headers" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64", + "base64 0.21.4", "bytes", "headers-core", "http", @@ -338,6 +400,17 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -350,6 +423,12 @@ version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "log" version = "0.4.20" @@ -383,6 +462,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -403,6 +488,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -447,18 +542,79 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "ordered-multimap" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" +dependencies = [ + "dlv-list", + "hashbrown", +] + [[package]] name = "overload" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "percent-encoding" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +[[package]] +name = "pest" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "pin-project" version = "1.1.3" @@ -553,6 +709,27 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +[[package]] +name = "ron" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" +dependencies = [ + "base64 0.13.1", + "bitflags", + "serde", +] + +[[package]] +name = "rust-ini" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -635,6 +812,17 @@ dependencies = [ "digest", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -687,6 +875,26 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "thiserror" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.7" @@ -754,6 +962,15 @@ dependencies = [ "syn", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "tower" version = "0.4.13" @@ -858,6 +1075,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "unicode-ident" version = "1.0.12" @@ -896,6 +1119,8 @@ name = "webol" version = "0.1.0" dependencies = [ "axum", + "config", + "once_cell", "serde", "serde_json", "time", @@ -991,3 +1216,12 @@ name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] diff --git a/Cargo.toml b/Cargo.toml index d0ba7b1..9eca09c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,10 +6,12 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -axum = { version = "0.6.20", features = ["tracing", "headers"] } +axum = { version = "0.6.20", features = ["headers"] } tokio = { version = "1.32.0", features = ["macros", "rt-multi-thread"] } tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter", "local-time", "time"] } time = { version = "0.3.29", features = ["macros"] } serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" +config = "0.13.3" +once_cell = "1.18.0" diff --git a/src/auth.rs b/src/auth.rs index b1ad76d..b7693a0 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,3 +1,40 @@ -pub fn auth(secret: &str) -> bool { - secret == "aaa" +use std::error::Error; +use axum::headers::HeaderValue; +use axum::http::StatusCode; +use tracing::error; +use crate::auth::AuthError::{MissingSecret, ServerError, WrongSecret}; +use crate::config::SETTINGS; + +pub fn auth(secret: Option<&HeaderValue>) -> Result { + if let Some(value) = secret { + let key = SETTINGS + .get_string("apikey") + .map_err(|err| ServerError(Box::new(err)))?; + if value.to_str().map_err(|err| ServerError(Box::new(err)))? == key.as_str() { + Ok(true) + } else { + Err(WrongSecret) + } + } else { + Err(MissingSecret) + } } + +pub enum AuthError { + WrongSecret, + MissingSecret, + ServerError(Box), +} + +impl AuthError { + pub fn get(self) -> (StatusCode, &'static str) { + match self { + AuthError::WrongSecret => (StatusCode::UNAUTHORIZED, "Wrong credentials"), + AuthError::MissingSecret => (StatusCode::BAD_REQUEST, "Missing credentials"), + AuthError::ServerError(err) => { + error!("server error: {}", err.to_string()); + (StatusCode::INTERNAL_SERVER_ERROR, "Server Error") + }, + } + } +} \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index e69de29..4c79810 100644 --- a/src/config.rs +++ b/src/config.rs @@ -0,0 +1,11 @@ +use config::Config; +use once_cell::sync::Lazy; + +pub static SETTINGS: Lazy = Lazy::new(setup); + +fn setup() -> Config { + Config::builder() + .add_source(config::Environment::with_prefix("WEBOL").separator("_")) + .build() + .unwrap() +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 60f2214..0fe170d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,11 +5,12 @@ use tracing_subscriber::{EnvFilter, fmt::{self, time::LocalTime}, prelude::*}; use crate::routes::start::start; mod auth; +mod config; mod routes; +mod wol; #[tokio::main] async fn main() { - unsafe { local_offset::set_soundness(local_offset::Soundness::Unsound); } let time_format = time::macros::format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"); diff --git a/src/routes/start.rs b/src/routes/start.rs index cda6352..e7d7e0e 100644 --- a/src/routes/start.rs +++ b/src/routes/start.rs @@ -1,18 +1,33 @@ use axum::headers::HeaderMap; +use axum::http::StatusCode; use axum::Json; +use axum::response::{IntoResponse, Response}; use serde::{Deserialize, Serialize}; +use std::error::Error; use serde_json::{json, Value}; -use crate::auth::auth; +use tracing::error; +use crate::auth::{auth, AuthError}; +use crate::config::SETTINGS; +use crate::wol::{create_buffer, send_packet}; -pub async fn start(headers: HeaderMap, Json(payload): Json) -> Json { - let mut res = StartResponse { id: payload.id, boot: false }; - if let Some(secret) = headers.get("authorization") { - if !auth(secret.to_str().unwrap()) { Json(json!(res)) } else { - res.boot = true; - Json(json!(res)) - } +pub async fn start(headers: HeaderMap, Json(payload): Json) -> Result, StartError> { + let secret = headers.get("authorization"); + if auth(secret).map_err(StartError::Auth)? { + let bind_addr = SETTINGS + .get_string("bindaddr") + .map_err(|err| StartError::Server(Box::new(err)))?; + let broadcast_addr = SETTINGS + .get_string("broadcastaddr") + .map_err(|err| StartError::Server(Box::new(err)))?; + let _ = send_packet( + &bind_addr.parse().map_err(|err| StartError::Server(Box::new(err)))?, + &broadcast_addr.parse().map_err(|err| StartError::Server(Box::new(err)))?, + // TODO: MAC saved in DB + create_buffer(std::env::var("MAC").unwrap().as_str()).map_err(|err| StartError::Server(Box::new(err)))? + ).map_err(|err| StartError::Server(Box::new(err))); + Ok(Json(json!(StartResponse { id: payload.id, boot: true }))) } else { - Json(json!(res)) + Err(StartError::Generic) } } @@ -27,3 +42,27 @@ struct StartResponse { id: String, boot: bool, } + +pub enum StartError { + Auth(AuthError), + Generic, + Server(Box), +} + +impl IntoResponse for StartError { + fn into_response(self) -> Response { + let (status, error_message) = match self { + StartError::Auth(err) => err.get(), + StartError::Generic => (StatusCode::INTERNAL_SERVER_ERROR, ""), + StartError::Server(err) => { + error!("server error: {}", err.to_string()); + (StatusCode::INTERNAL_SERVER_ERROR, "Server Error") + }, + + }; + let body = Json(json!({ + "error": error_message, + })); + (status, body).into_response() + } +} \ No newline at end of file diff --git a/src/wol.rs b/src/wol.rs new file mode 100644 index 0000000..80b66cd --- /dev/null +++ b/src/wol.rs @@ -0,0 +1,29 @@ +use std::net::{SocketAddr, UdpSocket}; +use std::num::ParseIntError; + +/// Creates the magic packet from a mac address +/// +/// # Panics +/// +/// Panics if `mac_addr` is an invalid mac +pub fn create_buffer(mac_addr: &str) -> Result, ParseIntError> { + let mut mac = Vec::new(); + let sp = mac_addr.split(':'); + for f in sp { + mac.push(u8::from_str_radix(f, 16)?); + }; + let mut buf = vec![255; 6]; + for _ in 0..16 { + for i in &mac { + buf.push(*i); + } + } + Ok(buf) +} + +/// Sends a buffer on UDP broadcast +pub fn send_packet(bind_addr: &SocketAddr, broadcast_addr: &SocketAddr, buffer: Vec) -> Result { + let socket = UdpSocket::bind(bind_addr)?; + socket.set_broadcast(true)?; + socket.send_to(&buffer, broadcast_addr) +} \ No newline at end of file -- cgit v1.2.3