From 3f6809bcdf88268543c0ee75ae6c3a3fbcf23df8 Mon Sep 17 00:00:00 2001 From: BlackDex Date: Thu, 7 Nov 2019 17:11:29 +0100 Subject: [PATCH] Fixed issue/request #705 Added a config option to disable time drifted totp codes. Default is false, since this is what the RFC recommends. --- .env.template | 12 ++++++++++++ src/api/core/two_factor/authenticator.rs | 8 ++++++-- src/config.rs | 4 ++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.env.template b/.env.template index 77be95e..dcb6f88 100644 --- a/.env.template +++ b/.env.template @@ -140,6 +140,18 @@ ## After that, you should be able to follow the rest of the guide linked above, ## ignoring the fields that ask for the values that you already configured beforehand. +## Authenticator Settings +## Disable authenticator time drifted codes to be valid. +## TOTP codes of the previous and next 30 seconds will be invalid +## +## According to the RFC6238 (https://tools.ietf.org/html/rfc6238), +## we allow by default the TOTP code which was valid one step back and one in the future. +## This can however allow attackers to be a bit more lucky with there attempts because there are 3 valid codes. +## You can disable this, so that only the current TOTP Code is allowed. +## Keep in mind that when a sever drifts out of time, valid codes could be marked as invalid. +## In any case, if a code has been used it can not be used again, also codes which predates it will be invalid. +# AUTHENTICATOR_DISABLE_TIME_DRIFT = false + ## Rocket specific settings, check Rocket documentation to learn more # ROCKET_ENV=staging # ROCKET_ADDRESS=0.0.0.0 # Enable this to test mobile app diff --git a/src/api/core/two_factor/authenticator.rs b/src/api/core/two_factor/authenticator.rs index 7dfb6c1..7981dd6 100644 --- a/src/api/core/two_factor/authenticator.rs +++ b/src/api/core/two_factor/authenticator.rs @@ -11,6 +11,8 @@ use crate::db::{ DbConn, }; +pub use crate::config::CONFIG; + pub fn routes() -> Vec { routes![ generate_authenticator, @@ -118,9 +120,11 @@ pub fn validate_totp_code(user_uuid: &str, totp_code: u64, secret: &str, conn: & .expect("Earlier than 1970-01-01 00:00:00 UTC").as_secs(); // The amount of steps back and forward in time - let steps = 1; - for step in -steps..=steps { + // Also check if we need to disable time drifted TOTP codes. + // If that is the case, we set the steps to 0 so only the current TOTP is valid. + let steps = if CONFIG.authenticator_disable_time_drift() { 0 } else { 1 }; + for step in -steps..=steps { let time_step = (current_time / 30) as i32 + step; // We need to calculate the time offsite and cast it as an i128. // Else we can't do math with it on a default u64 variable. diff --git a/src/config.rs b/src/config.rs index af36f82..1f18549 100644 --- a/src/config.rs +++ b/src/config.rs @@ -275,6 +275,10 @@ make_config! { /// Note that the checkbox would still be present, but ignored. disable_2fa_remember: bool, true, def, false; + /// Disable authenticator time drifted codes to be valid |> Enabling this only allows the current TOTP code to be valid + /// TOTP codes of the previous and next 30 seconds will be invalid. + authenticator_disable_time_drift: bool, true, def, false; + /// Require new device emails |> When a user logs in an email is required to be sent. /// If sending the email fails the login attempt will fail. require_device_email: bool, true, def, false;