From ea431f4190fe11449b1bbb8dc77eb415054d1f59 Mon Sep 17 00:00:00 2001 From: Avril Date: Tue, 17 Nov 2020 15:17:24 +0000 Subject: [PATCH] skel+ --- Cargo.lock | 19 ++++++++++++++++--- Cargo.toml | 2 ++ src/ext.rs | 32 ++++++++++++++++++++++++++++++++ src/main.rs | 5 +++++ src/server/web/auth.rs | 29 +++++++++++++++++++++++++++-- src/server/web/mod.rs | 2 +- src/server/web/settings.rs | 12 ++++++++---- src/server/web/state.rs | 2 ++ src/util.rs | 14 ++++++++++++++ 9 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 src/ext.rs create mode 100644 src/util.rs diff --git a/Cargo.lock b/Cargo.lock index 28cfe90..3c54edd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -209,7 +209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cfc491baaffd7cbd6acc02ebd23564760d83a2c17e1a47e6a04a8d5a86e7fb5" dependencies = [ "crc", - "getrandom", + "getrandom 0.1.15", "hex-literal", "hmac", "libc", @@ -228,9 +228,11 @@ dependencies = [ "color-eyre", "cryptohelpers", "futures", + "getrandom 0.2.0", "lazy_static", "log", "pretty_env_logger", + "rand 0.7.3", "serde", "tokio", "uuid", @@ -468,6 +470,17 @@ dependencies = [ "wasi 0.9.0+wasi-snapshot-preview1", ] +[[package]] +name = "getrandom" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "gimli" version = "0.23.0" @@ -1052,7 +1065,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom", + "getrandom 0.1.15", "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", @@ -1100,7 +1113,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom", + "getrandom 0.1.15", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b255fc5..77edefb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,9 +23,11 @@ client = [] color-eyre = {version = "0.5", default-features=false} cryptohelpers = {version = "1.5.1", features= ["sha256", "rsa", "serde"]} futures = "0.3.8" +getrandom = "0.2.0" lazy_static = "1.4.0" log = "0.4.11" pretty_env_logger = "0.4.0" +rand = "0.7.3" serde = {version = "1.0", features = ["derive"]} tokio = {version = "0.2", features = ["full"]} uuid = {version = "0.8.1", features = ["v4","serde"]} diff --git a/src/ext.rs b/src/ext.rs new file mode 100644 index 0000000..83c2e3d --- /dev/null +++ b/src/ext.rs @@ -0,0 +1,32 @@ +//! Extensions +use super::*; + +pub trait Tuple2MapExt +{ + fn map(self, fun: F) -> (U, U) + where F: FnMut(T) -> U; +} + +impl Tuple2MapExt for (T,T) +{ + fn map(self, mut fun: F) -> (U, U) + where F: FnMut(T) -> U + { + (fun(self.0), fun(self.1)) + } +} + +pub trait JitterExt +{ + /// Produce a random value between `self.0` and `self.1` inclusive + fn jitter(self) -> T; +} + +impl JitterExt for (T, T) +where T: rand::distributions::uniform::SampleUniform +{ + fn jitter(self) -> T + { + util::jitter(self.0, self.1) + } +} diff --git a/src/main.rs b/src/main.rs index a05d275..6e70aeb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ use futures::{ prelude::*, }; use lazy_static::lazy_static; +use getrandom::getrandom; use serde::{ Serialize, Deserialize, @@ -30,6 +31,10 @@ fn install() -> eyre::Result<()> Ok(()) } +mod ext; +use ext::*; +mod util; + mod args; #[cfg(feature="server")] mod server; diff --git a/src/server/web/auth.rs b/src/server/web/auth.rs index 35e3ffa..a93dd09 100644 --- a/src/server/web/auth.rs +++ b/src/server/web/auth.rs @@ -12,29 +12,54 @@ impl str::FromStr for Sha256Hash } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] pub struct AuthRequest { id: uuid::Uuid, sign_this: [u8; 32], salt: [u8; 16], passwd_is_allowed: bool, + ttl_ms: u64 +} + +impl AuthRequest +{ + /// Create a new auth request + pub fn new(cfg: &settings::Settings) -> Self + { + let mut empty = Self { + id: uuid::Uuid::new_v4(), + sign_this: [0; 32], + salt: [0;16], + passwd_is_allowed: cfg.allow_passwd_auth, + ttl_ms: cfg.auth_req_ttl_millis.jitter(), + }; + getrandom(&mut empty.sign_this[..]).expect("fatal rng"); + getrandom(&mut empty.salt[..]).expect("fatal rng"); + empty + } } pub async fn auth_req(who: source::IpAddr, state: Arc) -> Result { + let req = AuthRequest::new(state.cfg()); + trace!("{:?} auth req", who); - todo!() + // TODO: Add `req` into `state` somehow for later. + // TODO: Use `DelayQueue` to remove `req.id` from the hashmap after `ttl` expires. + Ok(req) } pub async fn auth_key(who: source::IpAddr, state: Arc, req_id: uuid::Uuid, num: usize, body: Bytes) -> Result<(), Infallible> { + trace!("{:?} auth resp key <{}>:{}", who, req_id, num); Ok(()) } pub async fn auth_pass(who: source::IpAddr, state: Arc, req_id: uuid::Uuid, passhash: sha256::Sha256Hash) -> Result<(), Infallible> { + trace!("{:?} auth resp pass <{}>: \"{}\"", who, req_id, passhash); Ok(()) } diff --git a/src/server/web/mod.rs b/src/server/web/mod.rs index 6e2ddf9..d9d4bfa 100644 --- a/src/server/web/mod.rs +++ b/src/server/web/mod.rs @@ -74,7 +74,7 @@ pub async fn main(state: server::state::ServerState, cfg: settings::Settings) -> .and(warp::path::end()) .and_then(auth::auth_pass).boxed() } else { - pw_path.and_then(|_addr, _state, _hash| async move {Err(warp::reject::reject())}).boxed() + pw_path.and_then(|_addr, _state, _hash| async move {Err(warp::reject::not_found())}).boxed() } }; diff --git a/src/server/web/settings.rs b/src/server/web/settings.rs index fdef351..df664d2 100644 --- a/src/server/web/settings.rs +++ b/src/server/web/settings.rs @@ -17,9 +17,13 @@ pub struct Settings pub max_key_sigs_per_auth_response: usize, /// How long is an auth request ID is valid. - pub auth_req_ttl_millis: u64, + /// + /// A random value between these two bounds is selected + pub auth_req_ttl_millis: (u64, u64), /// How long is an authentication token valid for an action. - pub auth_token_ttl_millis: u64, + /// + /// A random value between these two bounds is selected + pub auth_token_ttl_millis: (u64, u64), } impl Default for Settings @@ -34,8 +38,8 @@ impl Default for Settings allow_passwd_auth: true, max_key_sigs_per_auth_response: 16, - auth_req_ttl_millis: 5000, //5 s - auth_token_ttl_millis: 60 * 2000, //2 m + auth_req_ttl_millis: (4000, 6000), //4s - 6s + auth_token_ttl_millis: (1500, 2500).map(|x| x * 60), // 1.5m - 2.5m } } } diff --git a/src/server/web/state.rs b/src/server/web/state.rs index 2325ec4..023265a 100644 --- a/src/server/web/state.rs +++ b/src/server/web/state.rs @@ -15,6 +15,7 @@ pub struct State impl State { + /// Create state from a backend state and server settings pub fn new(backend: server::state::ServerState, settings: settings::Settings) -> Self { Self { @@ -23,6 +24,7 @@ impl State } } + /// The web server settings pub fn cfg(&self) -> &settings::Settings { &self.settings diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..c72c54b --- /dev/null +++ b/src/util.rs @@ -0,0 +1,14 @@ +//! Utils + +/// Get a random value between these two inclusive +pub fn jitter(min: T, max: T) -> T + where T: rand::distributions::uniform::SampleUniform +{ + use rand::Rng; + + let mut thread = rand::thread_rng(); + let dist = rand::distributions::Uniform::new_inclusive(min, max); + + thread.sample(dist) +} +