Prevent Invalid MFA Reg States (#3194)

This commit is contained in:
Firstyear 2024-11-10 13:36:28 +10:00 committed by GitHub
parent ab4291e8d2
commit 1218abd8c6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -31,6 +31,8 @@ use compact_jwt::jwe::JweBuilder;
use super::accountpolicy::ResolvedAccountPolicy; use super::accountpolicy::ResolvedAccountPolicy;
// A user can take up to 15 minutes to update their credentials before we automatically
// cancel on them.
const MAXIMUM_CRED_UPDATE_TTL: Duration = Duration::from_secs(900); const MAXIMUM_CRED_UPDATE_TTL: Duration = Duration::from_secs(900);
// Minimum 5 minutes. // Minimum 5 minutes.
const MINIMUM_INTENT_TTL: Duration = Duration::from_secs(300); const MINIMUM_INTENT_TTL: Duration = Duration::from_secs(300);
@ -1126,27 +1128,24 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
}; };
(*max_ttl, *perms) (*max_ttl, *perms)
} }
Some(IntentTokenState::Valid { max_ttl, perms }) => { Some(IntentTokenState::Valid { max_ttl, perms }) => (*max_ttl, *perms),
// Check the TTL
if current_time >= *max_ttl {
trace!(?current_time, ?max_ttl);
security_info!(%account.uuid, "intent has expired");
return Err(OperationError::SessionExpired);
} else {
security_info!(
%entry,
%account.uuid,
"Initiating Credential Update Session",
);
(*max_ttl, *perms)
}
}
None => { None => {
admin_error!("Corruption may have occurred - index yielded an entry for intent_id, but the entry does not contain that intent_id"); admin_error!("Corruption may have occurred - index yielded an entry for intent_id, but the entry does not contain that intent_id");
return Err(OperationError::InvalidState); return Err(OperationError::InvalidState);
} }
}; };
if current_time >= max_ttl {
security_info!(?current_time, ?max_ttl, %account.uuid, "intent has expired");
return Err(OperationError::SessionExpired);
}
security_info!(
%entry,
%account.uuid,
"Initiating Credential Update Session",
);
// To prevent issues with repl, we need to associate this cred update session id, with // To prevent issues with repl, we need to associate this cred update session id, with
// this intent token id. // this intent token id.
@ -1848,11 +1847,9 @@ impl<'a> IdmServerCredUpdateTransaction<'a> {
return Err(OperationError::AccessDenied); return Err(OperationError::AccessDenied);
}; };
// Is there something else in progress? // Is there something else in progress? Cancel it if so.
// Or should this just cancel it ....
if !matches!(session.mfaregstate, MfaRegState::None) { if !matches!(session.mfaregstate, MfaRegState::None) {
admin_info!("Invalid TOTP state, another update is in progress"); debug!("Clearing incomplete mfareg");
return Err(OperationError::InvalidState);
} }
// Generate the TOTP. // Generate the TOTP.
@ -2017,7 +2014,7 @@ impl<'a> IdmServerCredUpdateTransaction<'a> {
) -> Result<CredentialUpdateSessionStatus, OperationError> { ) -> Result<CredentialUpdateSessionStatus, OperationError> {
let session_handle = self.get_current_session(cust, ct)?; let session_handle = self.get_current_session(cust, ct)?;
let mut session = session_handle.try_lock().map_err(|_| { let mut session = session_handle.try_lock().map_err(|_| {
admin_error!("Session already locked, unable to proceed."); error!("Session already locked, unable to proceed.");
OperationError::InvalidState OperationError::InvalidState
})?; })?;
trace!(?session); trace!(?session);
@ -2035,13 +2032,13 @@ impl<'a> IdmServerCredUpdateTransaction<'a> {
.primary .primary
.as_ref() .as_ref()
.ok_or_else(|| { .ok_or_else(|| {
admin_error!("Tried to add backup codes, but no primary credential stub exists"); error!("Tried to add backup codes, but no primary credential stub exists");
OperationError::InvalidState OperationError::InvalidState
}) })
.and_then(|cred| .and_then(|cred|
cred.update_backup_code(BackupCodes::new(codes.clone())) cred.update_backup_code(BackupCodes::new(codes.clone()))
.map_err(|_| { .map_err(|_| {
admin_error!("Tried to add backup codes, but MFA is not enabled on this credential yet"); error!("Tried to add backup codes, but MFA is not enabled on this credential yet");
OperationError::InvalidState OperationError::InvalidState
}) })
) )
@ -2134,8 +2131,7 @@ impl<'a> IdmServerCredUpdateTransaction<'a> {
}; };
if !matches!(session.mfaregstate, MfaRegState::None) { if !matches!(session.mfaregstate, MfaRegState::None) {
admin_info!("Invalid Passkey Init state, another update is in progress"); debug!("Clearing incomplete mfareg");
return Err(OperationError::InvalidState);
} }
let (ccr, pk_reg) = self let (ccr, pk_reg) = self
@ -2248,8 +2244,7 @@ impl<'a> IdmServerCredUpdateTransaction<'a> {
}; };
if !matches!(session.mfaregstate, MfaRegState::None) { if !matches!(session.mfaregstate, MfaRegState::None) {
info!("Invalid Attested Passkey Init state, another update is in progress"); debug!("Cancelling abandoned mfareg");
return Err(OperationError::InvalidState);
} }
let att_ca_list = session let att_ca_list = session