diff --git a/src/api/core/two_factor/authenticator.rs b/src/api/core/two_factor/authenticator.rs index 02eff3b..5ea2308 100644 --- a/src/api/core/two_factor/authenticator.rs +++ b/src/api/core/two_factor/authenticator.rs @@ -1,18 +1,15 @@ -use data_encoding::{BASE32, BASE64}; +use data_encoding::{BASE32}; use rocket::Route; use rocket_contrib::json::Json; -use serde_json; -use serde_json::Value; -use crate::api::{ApiResult, EmptyResult, JsonResult, JsonUpcase, NumberOrString, PasswordData}; +use crate::api::{JsonResult, JsonUpcase, NumberOrString, PasswordData}; use crate::api::core::two_factor::{_generate_recover_code, totp}; use crate::auth::Headers; use crate::crypto; use crate::db::{ DbConn, - models::{TwoFactor, TwoFactorType, User}, + models::{TwoFactor, TwoFactorType}, }; -use crate::error::{Error, MapResult}; const TOTP_TIME_STEP: u64 = 30; diff --git a/src/api/core/two_factor/duo.rs b/src/api/core/two_factor/duo.rs index 647cb25..80d1411 100644 --- a/src/api/core/two_factor/duo.rs +++ b/src/api/core/two_factor/duo.rs @@ -1,12 +1,10 @@ use chrono::Utc; -use data_encoding::{BASE32, BASE64}; -use oath::{HashType, totp_raw_now}; +use data_encoding::{BASE64}; use rocket::Route; use rocket_contrib::json::Json; use serde_json; -use serde_json::Value; -use crate::api::{ApiResult, EmptyResult, JsonResult, JsonUpcase, NumberOrString, PasswordData}; +use crate::api::{ApiResult, EmptyResult, JsonResult, JsonUpcase, PasswordData}; use crate::auth::Headers; use crate::CONFIG; use crate::crypto; @@ -14,7 +12,7 @@ use crate::db::{ DbConn, models::{TwoFactor, TwoFactorType, User}, }; -use crate::error::{Error, MapResult}; +use crate::error::{MapResult}; pub fn routes() -> Vec { routes![ diff --git a/src/api/core/two_factor/email.rs b/src/api/core/two_factor/email.rs index afdf09d..16d6183 100644 --- a/src/api/core/two_factor/email.rs +++ b/src/api/core/two_factor/email.rs @@ -1,20 +1,17 @@ -use data_encoding::{BASE32, BASE64}; -use lettre_email::Email; +use data_encoding::{BASE32}; use oath::{totp_raw_now, HashType}; use rocket::Route; use rocket_contrib::json::Json; use serde_json; -use serde_json::Value; use crate::api::core::two_factor::totp; -use crate::api::core::two_factor::totp::validate_totp_code_with_time_step; -use crate::api::{ApiResult, EmptyResult, JsonResult, JsonUpcase, NumberOrString, PasswordData}; +use crate::api::{EmptyResult, JsonResult, JsonUpcase, PasswordData}; use crate::auth::Headers; use crate::db::{ - models::{TwoFactor, TwoFactorType, User}, + models::{TwoFactor, TwoFactorType}, DbConn, }; -use crate::error::{Error, MapResult}; +use crate::error::{Error}; use crate::{crypto, mail}; const TOTP_TIME_STEP: u64 = 120; @@ -38,7 +35,7 @@ fn send_email_login(data: JsonUpcase, conn: DbConn) -> Empty use crate::db::models::User; // Get the user - let mut user = match User::find_by_mail(&data.Email, &conn) { + let user = match User::find_by_mail(&data.Email, &conn) { Some(user) => user, None => err!("Username or password is incorrect. Try again."), }; @@ -49,16 +46,16 @@ fn send_email_login(data: JsonUpcase, conn: DbConn) -> Empty } let type_ = TwoFactorType::Email as i32; - let mut twofactor = TwoFactor::find_by_user_and_type(&user.uuid, type_, &conn)?; + let twofactor = TwoFactor::find_by_user_and_type(&user.uuid, type_, &conn)?; let twofactor_data = EmailTokenData::from_json(&twofactor.data)?; - let decoded_key = totp::validate_decode_key(&twofactor_data.TotpSecret)?; + let decoded_key = totp::validate_decode_key(&twofactor_data.totp_secret)?; let generated_token = totp_raw_now(&decoded_key, 6, 0, TOTP_TIME_STEP, &HashType::SHA1); let token_string = generated_token.to_string(); - mail::send_token(&twofactor_data.Email, &token_string)?; + mail::send_token(&twofactor_data.email, &token_string)?; Ok(()) } @@ -119,7 +116,7 @@ fn send_email(data: JsonUpcase, headers: Headers, conn: DbConn) - let twofactor_data = EmailTokenData::new(data.Email, base32_secret); // Uses EmailVerificationChallenge as type to show that it's not verified yet. - let mut twofactor = TwoFactor::new( + let twofactor = TwoFactor::new( user.uuid, TwoFactorType::EmailVerificationChallenge, twofactor_data.to_json(), @@ -129,7 +126,7 @@ fn send_email(data: JsonUpcase, headers: Headers, conn: DbConn) - let generated_token = totp_raw_now(&secret, 6, 0, TOTP_TIME_STEP, &HashType::SHA1); let token_string = generated_token.to_string(); - mail::send_token(&twofactor_data.Email, &token_string)?; + mail::send_token(&twofactor_data.email, &token_string)?; Ok(()) } @@ -162,13 +159,13 @@ fn email(data: JsonUpcase, headers: Headers, conn: DbConn) -> JsonRes let email_data = EmailTokenData::from_json(&twofactor.data)?; - totp::validate_totp_code_with_time_step(token_u64, &email_data.TotpSecret, TOTP_TIME_STEP)?; + totp::validate_totp_code_with_time_step(token_u64, &email_data.totp_secret, TOTP_TIME_STEP)?; twofactor.atype = TwoFactorType::Email as i32; twofactor.save(&conn)?; Ok(Json(json!({ - "Email": email_data.Email, + "Email": email_data.email, "Enabled": "true", "Object": "twoFactorEmail" }))) @@ -186,7 +183,7 @@ pub fn validate_email_code_str(code: &str, data: &str) -> EmptyResult { pub fn validate_email_code(code: u64, data: &str) -> EmptyResult { let email_data = EmailTokenData::from_json(&data)?; - let decoded_secret = match BASE32.decode(email_data.TotpSecret.as_bytes()) { + let decoded_secret = match BASE32.decode(email_data.totp_secret.as_bytes()) { Ok(s) => s, Err(_) => err!("Invalid email secret"), }; @@ -201,15 +198,15 @@ pub fn validate_email_code(code: u64, data: &str) -> EmptyResult { #[derive(Serialize, Deserialize)] pub struct EmailTokenData { - pub Email: String, - pub TotpSecret: String, + pub email: String, + pub totp_secret: String, } impl EmailTokenData { - pub fn new(email: String, secret: String) -> EmailTokenData { + pub fn new(email: String, totp_secret: String) -> EmailTokenData { EmailTokenData { - Email: email, - TotpSecret: secret, + email, + totp_secret, } } @@ -226,6 +223,7 @@ impl EmailTokenData { } } +/// Takes an email address and obscures it by replacing it with asterisks except two characters. pub fn obscure_email(email: &str) -> String { let split: Vec<&str> = email.split("@").collect(); @@ -235,7 +233,7 @@ pub fn obscure_email(email: &str) -> String { let name_size = name.chars().count(); let new_name = match name_size { - 1..=2 => "*".repeat(name_size), + 1..=3 => "*".repeat(name_size), _ => { let stars = "*".repeat(name_size-2); name.truncate(2); @@ -262,11 +260,11 @@ mod tests { #[test] fn test_obscure_email_short() { - let email = "by@example.ext"; + let email = "byt@example.ext"; let result = obscure_email(&email); // If it's smaller than 3 characters it should only show asterisks. - assert_eq!(result, "**@example.ext"); + assert_eq!(result, "***@example.ext"); } } diff --git a/src/api/core/two_factor/mod.rs b/src/api/core/two_factor/mod.rs index 85d44f8..6190fc2 100644 --- a/src/api/core/two_factor/mod.rs +++ b/src/api/core/two_factor/mod.rs @@ -1,19 +1,16 @@ -use chrono::Utc; -use data_encoding::{BASE32, BASE64}; -use oath::{HashType, totp_raw_now}; +use data_encoding::{BASE32}; use rocket::Route; use rocket_contrib::json::Json; use serde_json; use serde_json::Value; -use crate::api::{ApiResult, EmptyResult, JsonResult, JsonUpcase, NumberOrString, PasswordData}; +use crate::api::{JsonResult, JsonUpcase, NumberOrString, PasswordData}; use crate::auth::Headers; use crate::crypto; use crate::db::{ DbConn, - models::{TwoFactor, TwoFactorType, User}, + models::{TwoFactor, User}, }; -use crate::error::{Error, MapResult}; pub(crate) mod authenticator; pub(crate) mod duo; diff --git a/src/api/core/two_factor/u2f.rs b/src/api/core/two_factor/u2f.rs index 1d1d495..0bf9cfb 100644 --- a/src/api/core/two_factor/u2f.rs +++ b/src/api/core/two_factor/u2f.rs @@ -1,4 +1,3 @@ -use data_encoding::{BASE32, BASE64}; use rocket::Route; use rocket_contrib::json::Json; use serde_json; @@ -11,12 +10,11 @@ use crate::api::{ApiResult, EmptyResult, JsonResult, JsonUpcase, NumberOrString, use crate::api::core::two_factor::_generate_recover_code; use crate::auth::Headers; use crate::CONFIG; -use crate::crypto; use crate::db::{ DbConn, - models::{TwoFactor, TwoFactorType, User}, + models::{TwoFactor, TwoFactorType}, }; -use crate::error::{Error, MapResult}; +use crate::error::{Error}; const U2F_VERSION: &str = "U2F_V2"; diff --git a/src/api/core/two_factor/yubikey.rs b/src/api/core/two_factor/yubikey.rs index fc2c422..a7b91de 100644 --- a/src/api/core/two_factor/yubikey.rs +++ b/src/api/core/two_factor/yubikey.rs @@ -1,4 +1,3 @@ -use data_encoding::{BASE32, BASE64}; use rocket::Route; use rocket_contrib::json::Json; use serde_json; @@ -6,23 +5,18 @@ use serde_json::Value; use yubico::config::Config; use yubico::verify; -use crate::api::{ApiResult, EmptyResult, JsonResult, JsonUpcase, NumberOrString, PasswordData}; use crate::api::core::two_factor::_generate_recover_code; +use crate::api::{EmptyResult, JsonResult, JsonUpcase, PasswordData}; use crate::auth::Headers; -use crate::CONFIG; -use crate::crypto; use crate::db::{ + models::{TwoFactor, TwoFactorType}, DbConn, - models::{TwoFactor, TwoFactorType, User}, }; use crate::error::{Error, MapResult}; +use crate::CONFIG; pub fn routes() -> Vec { - routes![ - generate_yubikey, - activate_yubikey, - activate_yubikey_put, - ] + routes![generate_yubikey, activate_yubikey, activate_yubikey_put,] } #[derive(Deserialize, Debug)] @@ -76,8 +70,8 @@ fn verify_yubikey_otp(otp: String) -> EmptyResult { Some(server) => verify(otp, config.set_api_hosts(vec![server])), None => verify(otp, config), } - .map_res("Failed to verify OTP") - .and(Ok(())) + .map_res("Failed to verify OTP") + .and(Ok(())) } #[post("/two-factor/get-yubikey", data = "")] diff --git a/src/api/identity.rs b/src/api/identity.rs index d343747..b616362 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -292,7 +292,7 @@ fn _json_err_twofactor(providers: &[i32], user_uuid: &str, conn: &DbConn) -> Api let email_data = EmailTokenData::from_json(&twofactor.data)?; result["TwoFactorProviders2"][provider.to_string()] = json!({ - "Email": email::obscure_email(&email_data.Email), + "Email": email::obscure_email(&email_data.email), }) }