From a154a8e8a46dc8cd33a5fa3a91e75dff4ff1d699 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Thu, 31 Jan 2019 14:34:21 +0100 Subject: [PATCH] delay unauthorized request (rate limit) --- src/api2/access.rs | 4 +++- src/server/rest.rs | 21 +++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/api2/access.rs b/src/api2/access.rs index 3ffc4dcd..6e52d24f 100644 --- a/src/api2/access.rs +++ b/src/api2/access.rs @@ -6,6 +6,8 @@ use crate::api::router::*; use crate::tools::ticket::*; use crate::auth_helpers::*; +use hyper::StatusCode; + use serde_json::{json, Value}; fn authenticate_user(username: &str, password: &str) -> Result<(), Error> { @@ -44,7 +46,7 @@ fn create_ticket( Err(err) => { let client_ip = "unknown"; // $rpcenv->get_client_ip() || ''; log::error!("authentication failure; rhost={} user={} msg={}", client_ip, username, err.to_string()); - bail!("authentication failure"); + return Err(http_err!(UNAUTHORIZED, "permission check failed.".into())); } } } diff --git a/src/server/rest.rs b/src/server/rest.rs index 12010e46..49fc0280 100644 --- a/src/server/rest.rs +++ b/src/server/rest.rs @@ -168,13 +168,30 @@ fn handle_sync_api_request( { let params = get_request_parameters_async(info, parts, req_body, uri_param); + let delay_unauth_time = std::time::Instant::now() + std::time::Duration::from_millis(3000); + let resp = params .and_then(move |params| { + let mut delay = false; let resp = match (info.handler)(params, info, &mut rpcenv) { Ok(data) => (formatter.format_result)(data, &rpcenv), - Err(err) => (formatter.format_error)(err), + Err(err) => { + if let Some(httperr) = err.downcast_ref::() { + if httperr.code == StatusCode::UNAUTHORIZED { delay = true; } + } + (formatter.format_error)(err) + } }; - Ok(resp) + + if delay { + let delayed_response = tokio::timer::Delay::new(delay_unauth_time) + .map_err(|err| http_err!(INTERNAL_SERVER_ERROR, format!("tokio timer delay error: {}", err))) + .and_then(|_| Ok(resp)); + + Either::A(delayed_response) + } else { + Either::B(future::ok(resp)) + } }); Box::new(resp)