clarity in 2fa skip code

This commit is contained in:
0x484558 2026-04-04 21:01:43 +02:00
parent 1bb32daaf9
commit bfe45e47f7
No known key found for this signature in database
2 changed files with 26 additions and 14 deletions

View File

@ -1,5 +1,6 @@
use chrono::{TimeDelta, Utc};
use data_encoding::BASE32;
use num_traits::FromPrimitive;
use rocket::serde::json::Json;
use rocket::Route;
use serde::Deserialize;
@ -36,7 +37,7 @@ fn has_global_duo_credentials() -> bool {
CONFIG._enable_duo() && CONFIG.duo_host().is_some() && CONFIG.duo_ikey().is_some() && CONFIG.duo_skey().is_some()
}
pub fn is_twofactor_provider_usable(provider_type: i32, provider_data: Option<&str>) -> bool {
pub fn is_twofactor_provider_usable(provider_type: TwoFactorType, provider_data: Option<&str>) -> bool {
#[derive(Deserialize)]
struct DuoProviderData {
host: String,
@ -45,21 +46,27 @@ pub fn is_twofactor_provider_usable(provider_type: i32, provider_data: Option<&s
}
match provider_type {
x if x == TwoFactorType::Authenticator as i32 => true,
x if x == TwoFactorType::Email as i32 => CONFIG._enable_email_2fa(),
x if x == TwoFactorType::Duo as i32 || x == TwoFactorType::OrganizationDuo as i32 => {
TwoFactorType::Authenticator => true,
TwoFactorType::Email => CONFIG._enable_email_2fa(),
TwoFactorType::Duo | TwoFactorType::OrganizationDuo => {
provider_data
.and_then(|raw| serde_json::from_str::<DuoProviderData>(raw).ok())
.is_some_and(|duo| !duo.host.is_empty() && !duo.ik.is_empty() && !duo.sk.is_empty())
|| has_global_duo_credentials()
}
x if x == TwoFactorType::YubiKey as i32 => {
TwoFactorType::YubiKey => {
CONFIG._enable_yubico() && CONFIG.yubico_client_id().is_some() && CONFIG.yubico_secret_key().is_some()
}
x if x == TwoFactorType::Webauthn as i32 => CONFIG.is_webauthn_2fa_supported(),
x if x == TwoFactorType::Remember as i32 => !CONFIG.disable_2fa_remember(),
x if x == TwoFactorType::RecoveryCode as i32 => true,
_ => false,
TwoFactorType::Webauthn => CONFIG.is_webauthn_2fa_supported(),
TwoFactorType::Remember => !CONFIG.disable_2fa_remember(),
TwoFactorType::RecoveryCode => true,
TwoFactorType::U2f
| TwoFactorType::U2fRegisterChallenge
| TwoFactorType::U2fLoginChallenge
| TwoFactorType::EmailVerificationChallenge
| TwoFactorType::WebauthnRegisterChallenge
| TwoFactorType::WebauthnLoginChallenge
| TwoFactorType::ProtectedActions => false,
}
}
@ -87,8 +94,10 @@ async fn get_twofactor(headers: Headers, conn: DbConn) -> Json<Value> {
let twofactors = TwoFactor::find_by_user(&headers.user.uuid, &conn).await;
let twofactors_json: Vec<Value> = twofactors
.iter()
.filter(|tf| is_twofactor_provider_usable(tf.atype, Some(&tf.data)))
.map(TwoFactor::to_json_provider)
.filter_map(|tf| {
let provider_type = TwoFactorType::from_i32(tf.atype)?;
is_twofactor_provider_usable(provider_type, Some(&tf.data)).then(|| TwoFactor::to_json_provider(tf))
})
.collect();
Json(json!({

View File

@ -15,7 +15,8 @@ use crate::{
accounts::{PreloginData, RegisterData, _prelogin, _register, kdf_upgrade},
log_user_event,
two_factor::{
authenticator, duo, duo_oidc, email, enforce_2fa_policy, is_twofactor_provider_usable, webauthn, yubikey,
authenticator, duo, duo_oidc, email, enforce_2fa_policy, is_twofactor_provider_usable, webauthn,
yubikey,
},
},
master_password_policy,
@ -743,8 +744,10 @@ async fn twofactor_auth(
let twofactor_ids: Vec<_> = twofactors
.iter()
.filter(|tf| tf.enabled && is_twofactor_provider_usable(tf.atype, Some(&tf.data)))
.map(|tf| tf.atype)
.filter_map(|tf| {
let provider_type = TwoFactorType::from_i32(tf.atype)?;
(tf.enabled && is_twofactor_provider_usable(provider_type, Some(&tf.data))).then_some(tf.atype)
})
.collect();
if twofactor_ids.is_empty() {
err!("No enabled and usable two factor providers are available for this account")