summaryrefslogtreecommitdiff
path: root/src/request_handler/handler_login.rs
diff options
context:
space:
mode:
authorYves Fischer <yvesf-git@xapek.org>2018-12-02 13:52:23 +0100
committerYves Fischer <yvesf-git@xapek.org>2018-12-02 13:52:23 +0100
commitf098fdc99de724f53f7f129b6a5bde50b73fd797 (patch)
treedab4645ee420a7d6373818c44c6a5f7439dc7726 /src/request_handler/handler_login.rs
parentcf40041946626b105102e3dab2515d2ef2fb0506 (diff)
downloadnginx-auth-totp-master.tar.gz
nginx-auth-totp-master.zip
request slowdown on login failureHEADmaster
Diffstat (limited to 'src/request_handler/handler_login.rs')
-rw-r--r--src/request_handler/handler_login.rs25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/request_handler/handler_login.rs b/src/request_handler/handler_login.rs
index aa93e96..ac0c37e 100644
--- a/src/request_handler/handler_login.rs
+++ b/src/request_handler/handler_login.rs
@@ -1,5 +1,9 @@
+use std::ops::Add;
use std::io;
use std::borrow::Cow;
+use std::time;
+use std::thread;
+use std::sync::atomic;
use tokio::prelude::*;
@@ -36,6 +40,18 @@ fn test_secrets(secrets: &Vec<&str>, token: &String) -> bool {
pub(in super) fn POST<'a>(header_infos: &HeaderExtract, state: &ApplicationState, req: &Request<Bytes>)
-> Response<String> {
+let wait_until = state.request_slowdown.load(atomic::Ordering::Acquire);
+ let now = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap().as_secs();
+
+ let slept = if wait_until > now {
+ let time = wait_until - now;
+ warn!("Sleep {}s", time);
+ thread::sleep(time::Duration::from_secs(time));
+ time
+ } else {
+ 0
+ };
+
let mut token = None;
let mut redirect = None;
for (key, val) in form_urlencoded::parse(req.body()) {
@@ -67,6 +83,15 @@ pub(in super) fn POST<'a>(header_infos: &HeaderExtract, state: &ApplicationState
.header(SET_COOKIE, cookie.to_string())
.body(views::login_auth_success(&redirect)).unwrap()
} else {
+ let current_wait = state.request_slowdown.load(atomic::Ordering::Acquire);
+ let wait_until = time::SystemTime::now()
+ .add(time::Duration::from_secs(8))
+ .duration_since(time::UNIX_EPOCH).unwrap()
+ .as_secs();
+ // if this request was already delayed then we double-delay
+ let wait_until = wait_until.max(current_wait + 8 + slept);
+ state.request_slowdown.store(wait_until, atomic::Ordering::Release);
+
Response::builder()
.set_defaults()
.body(views::login_auth_fail()).unwrap()