Add ip on totp miss

This commit is contained in:
Daniel García
2020-05-14 00:19:50 +02:00
parent 80d4061d14
commit 0807783388
2 changed files with 43 additions and 15 deletions

View File

@@ -4,7 +4,7 @@ use rocket_contrib::json::Json;
use crate::api::core::two_factor::_generate_recover_code;
use crate::api::{EmptyResult, JsonResult, JsonUpcase, NumberOrString, PasswordData};
use crate::auth::Headers;
use crate::auth::{ClientIp, Headers};
use crate::crypto;
use crate::db::{
models::{TwoFactor, TwoFactorType},
@@ -54,7 +54,12 @@ struct EnableAuthenticatorData {
}
#[post("/two-factor/authenticator", data = "<data>")]
fn activate_authenticator(data: JsonUpcase<EnableAuthenticatorData>, headers: Headers, conn: DbConn) -> JsonResult {
fn activate_authenticator(
data: JsonUpcase<EnableAuthenticatorData>,
headers: Headers,
ip: ClientIp,
conn: DbConn,
) -> JsonResult {
let data: EnableAuthenticatorData = data.into_inner().data;
let password_hash = data.MasterPasswordHash;
let key = data.Key;
@@ -77,7 +82,7 @@ fn activate_authenticator(data: JsonUpcase<EnableAuthenticatorData>, headers: He
}
// Validate the token provided with the key, and save new twofactor
validate_totp_code(&user.uuid, token, &key.to_uppercase(), &conn)?;
validate_totp_code(&user.uuid, token, &key.to_uppercase(), &ip, &conn)?;
_generate_recover_code(&mut user, &conn);
@@ -89,20 +94,31 @@ fn activate_authenticator(data: JsonUpcase<EnableAuthenticatorData>, headers: He
}
#[put("/two-factor/authenticator", data = "<data>")]
fn activate_authenticator_put(data: JsonUpcase<EnableAuthenticatorData>, headers: Headers, conn: DbConn) -> JsonResult {
activate_authenticator(data, headers, conn)
fn activate_authenticator_put(
data: JsonUpcase<EnableAuthenticatorData>,
headers: Headers,
ip: ClientIp,
conn: DbConn,
) -> JsonResult {
activate_authenticator(data, headers, ip, conn)
}
pub fn validate_totp_code_str(user_uuid: &str, totp_code: &str, secret: &str, conn: &DbConn) -> EmptyResult {
pub fn validate_totp_code_str(
user_uuid: &str,
totp_code: &str,
secret: &str,
ip: &ClientIp,
conn: &DbConn,
) -> EmptyResult {
let totp_code: u64 = match totp_code.parse() {
Ok(code) => code,
_ => err!("TOTP code is not a number"),
};
validate_totp_code(user_uuid, totp_code, secret, &conn)
validate_totp_code(user_uuid, totp_code, secret, ip, &conn)
}
pub fn validate_totp_code(user_uuid: &str, totp_code: u64, secret: &str, conn: &DbConn) -> EmptyResult {
pub fn validate_totp_code(user_uuid: &str, totp_code: u64, secret: &str, ip: &ClientIp, conn: &DbConn) -> EmptyResult {
use oath::{totp_raw_custom_time, HashType};
let decoded_secret = match BASE32.decode(secret.as_bytes()) {
@@ -144,11 +160,22 @@ pub fn validate_totp_code(user_uuid: &str, totp_code: u64, secret: &str, conn: &
twofactor.save(&conn)?;
return Ok(());
} else if generated == totp_code && time_step <= twofactor.last_used as i64 {
warn!("This or a TOTP code within {} steps back and forward has already been used!", steps);
err!(format!("Invalid TOTP code! Server time: {}", current_time.format("%F %T UTC")));
warn!(
"This or a TOTP code within {} steps back and forward has already been used!",
steps
);
err!(format!(
"Invalid TOTP code! Server time: {} IP: {}",
current_time.format("%F %T UTC"),
ip.ip
));
}
}
// Else no valide code received, deny access
err!(format!("Invalid TOTP code! Server time: {}", current_time.format("%F %T UTC")));
err!(format!(
"Invalid TOTP code! Server time: {} IP: {}",
current_time.format("%F %T UTC"),
ip.ip
));
}