mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 12:37:00 +01:00
Prevent Invalid MFA Reg States (#3194)
This commit is contained in:
parent
ab4291e8d2
commit
1218abd8c6
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue