Spiegel von
https://github.com/dani-garcia/vaultwarden.git
synchronisiert 2024-11-04 02:18:00 +01:00
Print current server time when failing TOTP, and use chrono as the rest of the server
Dieser Commit ist enthalten in:
Ursprung
a0ece3754b
Commit
e274af6e3d
1 geänderte Dateien mit 11 neuen und 13 gelöschten Zeilen
|
@ -103,7 +103,6 @@ pub fn validate_totp_code_str(user_uuid: &str, totp_code: &str, secret: &str, co
|
||||||
|
|
||||||
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, conn: &DbConn) -> EmptyResult {
|
||||||
use oath::{totp_raw_custom_time, HashType};
|
use oath::{totp_raw_custom_time, HashType};
|
||||||
use std::time::{UNIX_EPOCH, SystemTime};
|
|
||||||
|
|
||||||
let decoded_secret = match BASE32.decode(secret.as_bytes()) {
|
let decoded_secret = match BASE32.decode(secret.as_bytes()) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
|
@ -116,24 +115,23 @@ pub fn validate_totp_code(user_uuid: &str, totp_code: u64, secret: &str, conn: &
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the current system time in UNIX Epoch (UTC)
|
// Get the current system time in UNIX Epoch (UTC)
|
||||||
let current_time: u64 = SystemTime::now().duration_since(UNIX_EPOCH)
|
let current_time = chrono::Utc::now();
|
||||||
.expect("Earlier than 1970-01-01 00:00:00 UTC").as_secs();
|
let current_timestamp = current_time.timestamp();
|
||||||
|
|
||||||
// The amount of steps back and forward in time
|
// The amount of steps back and forward in time
|
||||||
// Also check if we need to disable time drifted TOTP codes.
|
// 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.
|
// 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 };
|
let steps: i64 = if CONFIG.authenticator_disable_time_drift() { 0 } else { 1 };
|
||||||
|
|
||||||
for step in -steps..=steps {
|
for step in -steps..=steps {
|
||||||
let time_step = (current_time / 30) as i32 + step;
|
let time_step = current_timestamp / 30i64 + step;
|
||||||
// We need to calculate the time offsite and cast it as an i128.
|
// 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.
|
// Else we can't do math with it on a default u64 variable.
|
||||||
let time_offset: i128 = (step * 30).into();
|
let time = (current_timestamp + step * 30i64) as u64;
|
||||||
let generated = totp_raw_custom_time(&decoded_secret, 6, 0, 30, (current_time as i128 + time_offset) as u64, &HashType::SHA1);
|
let generated = totp_raw_custom_time(&decoded_secret, 6, 0, 30, time, &HashType::SHA1);
|
||||||
|
|
||||||
// Check the the given code equals the generated and if the time_step is larger then the one last used.
|
// Check the the given code equals the generated and if the time_step is larger then the one last used.
|
||||||
if generated == totp_code && time_step > twofactor.last_used {
|
if generated == totp_code && time_step > twofactor.last_used as i64 {
|
||||||
|
|
||||||
// If the step does not equals 0 the time is drifted either server or client side.
|
// If the step does not equals 0 the time is drifted either server or client side.
|
||||||
if step != 0 {
|
if step != 0 {
|
||||||
info!("TOTP Time drift detected. The step offset is {}", step);
|
info!("TOTP Time drift detected. The step offset is {}", step);
|
||||||
|
@ -141,15 +139,15 @@ pub fn validate_totp_code(user_uuid: &str, totp_code: u64, secret: &str, conn: &
|
||||||
|
|
||||||
// Save the last used time step so only totp time steps higher then this one are allowed.
|
// Save the last used time step so only totp time steps higher then this one are allowed.
|
||||||
// This will also save a newly created twofactor if the code is correct.
|
// This will also save a newly created twofactor if the code is correct.
|
||||||
twofactor.last_used = time_step;
|
twofactor.last_used = time_step as i32;
|
||||||
twofactor.save(&conn)?;
|
twofactor.save(&conn)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else if generated == totp_code && time_step <= twofactor.last_used {
|
} 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);
|
warn!("This or a TOTP code within {} steps back and forward has already been used!", steps);
|
||||||
err!("Invalid TOTP Code!");
|
err!(format!("Invalid TOTP code! Server time: {}", current_time.format("%F %T UTC")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Else no valide code received, deny access
|
// Else no valide code received, deny access
|
||||||
err!("Invalid TOTP code!");
|
err!(format!("Invalid TOTP code! Server time: {}", current_time.format("%F %T UTC")));
|
||||||
}
|
}
|
||||||
|
|
Laden …
In neuem Issue referenzieren