mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2025-06-12 13:17:43 +02:00
Added option to force 2fa at logins and made some changes to two factor code.
Added newlines to config options to keep them a reasonable length.
This commit is contained in:
@ -102,6 +102,14 @@ fn recover(data: JsonUpcase<RecoverTwoFactor>, conn: DbConn) -> JsonResult {
|
||||
Ok(Json(json!({})))
|
||||
}
|
||||
|
||||
fn _generate_recover_code(user: &mut User, conn: &DbConn) {
|
||||
if user.totp_recover.is_none() {
|
||||
let totp_recover = BASE32.encode(&crypto::get_random(vec![0u8; 20]));
|
||||
user.totp_recover = Some(totp_recover);
|
||||
user.save(conn).ok();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[allow(non_snake_case)]
|
||||
struct DisableTwoFactorData {
|
||||
@ -196,9 +204,7 @@ fn activate_authenticator(data: JsonUpcase<EnableAuthenticatorData>, headers: He
|
||||
let twofactor = TwoFactor::new(user.uuid.clone(), type_, key.to_uppercase());
|
||||
|
||||
// Validate the token provided with the key
|
||||
if !twofactor.check_totp_code(token) {
|
||||
err!("Invalid totp code")
|
||||
}
|
||||
validate_totp_code(token, &twofactor.data)?;
|
||||
|
||||
_generate_recover_code(&mut user, &conn);
|
||||
twofactor.save(&conn)?;
|
||||
@ -215,12 +221,30 @@ fn activate_authenticator_put(data: JsonUpcase<EnableAuthenticatorData>, headers
|
||||
activate_authenticator(data, headers, conn)
|
||||
}
|
||||
|
||||
fn _generate_recover_code(user: &mut User, conn: &DbConn) {
|
||||
if user.totp_recover.is_none() {
|
||||
let totp_recover = BASE32.encode(&crypto::get_random(vec![0u8; 20]));
|
||||
user.totp_recover = Some(totp_recover);
|
||||
user.save(conn).ok();
|
||||
pub fn validate_totp_code_str(totp_code: &str, secret: &str) -> EmptyResult {
|
||||
let totp_code: u64 = match totp_code.parse() {
|
||||
Ok(code) => code,
|
||||
_ => err!("TOTP code is not a number"),
|
||||
};
|
||||
|
||||
validate_totp_code(totp_code, secret)
|
||||
}
|
||||
|
||||
pub fn validate_totp_code(totp_code: u64, secret: &str) -> EmptyResult {
|
||||
use data_encoding::BASE32;
|
||||
use oath::{totp_raw_now, HashType};
|
||||
|
||||
let decoded_secret = match BASE32.decode(secret.as_bytes()) {
|
||||
Ok(s) => s,
|
||||
Err(_) => err!("Invalid TOTP secret"),
|
||||
};
|
||||
|
||||
let generated = totp_raw_now(&decoded_secret, 6, 0, 30, &HashType::SHA1);
|
||||
if generated != totp_code {
|
||||
err!("Invalid TOTP code");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
use u2f::messages::{RegisterResponse, SignResponse, U2fSignRequest};
|
||||
@ -671,20 +695,12 @@ fn activate_yubikey_put(data: JsonUpcase<EnableYubikeyData>, headers: Headers, c
|
||||
activate_yubikey(data, headers, conn)
|
||||
}
|
||||
|
||||
pub fn validate_yubikey_login(user_uuid: &str, response: &str, conn: &DbConn) -> EmptyResult {
|
||||
pub fn validate_yubikey_login(response: &str, twofactor_data: &str) -> EmptyResult {
|
||||
if response.len() != 44 {
|
||||
err!("Invalid Yubikey OTP length");
|
||||
}
|
||||
|
||||
let yubikey_type = TwoFactorType::YubiKey as i32;
|
||||
|
||||
let twofactor = match TwoFactor::find_by_user_and_type(user_uuid, yubikey_type, &conn) {
|
||||
Some(tf) => tf,
|
||||
None => err!("No YubiKey devices registered"),
|
||||
};
|
||||
|
||||
let yubikey_metadata: YubikeyMetadata =
|
||||
serde_json::from_str(&twofactor.data).expect("Can't parse Yubikey Metadata");
|
||||
let yubikey_metadata: YubikeyMetadata = serde_json::from_str(twofactor_data).expect("Can't parse Yubikey Metadata");
|
||||
let response_id = &response[..12];
|
||||
|
||||
if !yubikey_metadata.Keys.contains(&response_id.to_owned()) {
|
||||
|
Reference in New Issue
Block a user