From 3ab2da1595da8b1b596f256a26c9e65ab35bc24c Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 28 May 2020 03:12:09 -0400 Subject: display the server's error message for incorrect password --- src/actions.rs | 6 ++++- src/api.rs | 41 ++++++++++++++++--------------- src/bin/rbw-agent/actions.rs | 57 ++++++++++++++++++++++++++++++++------------ src/error.rs | 4 ++-- 4 files changed, 71 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/actions.rs b/src/actions.rs index c63191f..f77378e 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -52,7 +52,11 @@ pub async fn unlock( crate::cipherstring::CipherString::new(protected_key)?; let key = match protected_key.decrypt_locked_symmetric(&identity.keys) { Ok(master_keys) => crate::locked::Keys::new(master_keys), - Err(Error::InvalidMac) => return Err(Error::IncorrectPassword), + Err(Error::InvalidMac) => { + return Err(Error::IncorrectPassword { + message: "Password is incorrect. Try again.".to_string(), + }) + } Err(e) => return Err(e), }; diff --git a/src/api.rs b/src/api.rs index 813043a..aec1398 100644 --- a/src/api.rs +++ b/src/api.rs @@ -901,24 +901,26 @@ fn classify_login_error(error_res: &ConnectErrorRes, code: u16) -> Error { match error_res.error.as_str() { "invalid_grant" => match error_res.error_description.as_str() { "invalid_username_or_password" => { - return Error::IncorrectPassword; + if let Some(error_model) = error_res.error_model.as_ref() { + let message = error_model.message.as_str().to_string(); + return Error::IncorrectPassword { message }; + } } "Two factor required." => { - match error_res.two_factor_providers.as_ref() { - Some(providers) => { - let providers: Result<_> = providers - .iter() - .copied() - .map(std::convert::TryInto::try_into) - .collect(); - return match providers { - Ok(providers) => { - Error::TwoFactorRequired { providers } - } - Err(e) => e, - }; - } - _ => {} + if let Some(providers) = + error_res.two_factor_providers.as_ref() + { + let providers: Result<_> = providers + .iter() + .copied() + .map(std::convert::TryInto::try_into) + .collect(); + return match providers { + Ok(providers) => { + Error::TwoFactorRequired { providers } + } + Err(e) => e, + }; } } _ => {} @@ -928,16 +930,17 @@ fn classify_login_error(error_res: &ConnectErrorRes, code: u16) -> Error { // this case, for some reason if error_res.error_description == "" { if let Some(error_model) = error_res.error_model.as_ref() { - match error_model.message.as_str() { + let message = error_model.message.as_str().to_string(); + match message.as_str() { "Username or password is incorrect. Try again" | "TOTP code is not a number" => { - return Error::IncorrectPassword; + return Error::IncorrectPassword { message }; } s => { if s.starts_with( "Invalid TOTP code! Server time: ", ) { - return Error::IncorrectPassword; + return Error::IncorrectPassword { message }; } } } diff --git a/src/bin/rbw-agent/actions.rs b/src/bin/rbw-agent/actions.rs index 0062067..a01f510 100644 --- a/src/bin/rbw-agent/actions.rs +++ b/src/bin/rbw-agent/actions.rs @@ -22,9 +22,12 @@ pub async fn login( let email = config_email().await?; + let mut err_msg = None; for i in 1_u8..=3 { let err = if i > 1 { - Some(format!("Incorrect password (attempt {}/3)", i)) + // this unwrap is safe because we only ever continue the loop + // if we have set err_msg + Some(format!("{} (attempt {}/3)", err_msg.unwrap(), i)) } else { None }; @@ -91,13 +94,14 @@ pub async fn login( return Err(anyhow::anyhow!("TODO")); } } - Err(rbw::error::Error::IncorrectPassword) => { + Err(rbw::error::Error::IncorrectPassword { message }) => { if i == 3 { - return Err(rbw::error::Error::IncorrectPassword) - .context( - "failed to log in to bitwarden instance", - ); + return Err(rbw::error::Error::IncorrectPassword { + message, + }) + .context("failed to log in to bitwarden instance"); } else { + err_msg = Some(message); continue; } } @@ -120,9 +124,12 @@ async fn two_factor( password: &rbw::locked::Password, provider: rbw::api::TwoFactorProviderType, ) -> anyhow::Result<(String, String, u32, String)> { + let mut err_msg = None; for i in 1_u8..=3 { let err = if i > 1 { - Some(format!("Incorrect code (attempt {}/3)", i)) + // this unwrap is safe because we only ever continue the loop if + // we have set err_msg + Some(format!("{} (attempt {}/3)", err_msg.unwrap(), i)) } else { None }; @@ -158,13 +165,27 @@ async fn two_factor( protected_key, )) } - Err(rbw::error::Error::IncorrectPassword) + Err(rbw::error::Error::IncorrectPassword { message }) => { + if i == 3 { + return Err(rbw::error::Error::IncorrectPassword { + message, + }) + .context("failed to log in to bitwarden instance"); + } else { + err_msg = Some(message); + continue; + } + } // can get this if the user passes an empty string - | Err(rbw::error::Error::TwoFactorRequired { .. }) => { + Err(rbw::error::Error::TwoFactorRequired { .. }) => { + let message = "TOTP code is not a number".to_string(); if i == 3 { - return Err(rbw::error::Error::IncorrectPassword) - .context("failed to log in to bitwarden instance"); + return Err(rbw::error::Error::IncorrectPassword { + message, + }) + .context("failed to log in to bitwarden instance"); } else { + err_msg = Some(message); continue; } } @@ -262,9 +283,12 @@ pub async fn unlock( let email = config_email().await?; + let mut err_msg = None; for i in 1u8..=3 { let err = if i > 1 { - Some(format!("Incorrect password (attempt {}/3)", i)) + // this unwrap is safe because we only ever continue the loop + // if we have set err_msg + Some(format!("{} (attempt {}/3)", err_msg.unwrap(), i)) } else { None }; @@ -290,11 +314,14 @@ pub async fn unlock( unlock_success(state, keys, org_keys).await?; break; } - Err(rbw::error::Error::IncorrectPassword) => { + Err(rbw::error::Error::IncorrectPassword { message }) => { if i == 3 { - return Err(rbw::error::Error::IncorrectPassword) - .context("failed to unlock database"); + return Err(rbw::error::Error::IncorrectPassword { + message, + }) + .context("failed to unlock database"); } else { + err_msg = Some(message); continue; } } diff --git a/src/error.rs b/src/error.rs index 5a6eef4..5a95fec 100644 --- a/src/error.rs +++ b/src/error.rs @@ -34,8 +34,8 @@ pub enum Error { #[snafu(display("failed to expand with hkdf"))] HkdfExpand, - #[snafu(display("username or password incorrect"))] - IncorrectPassword, + #[snafu(display("{}", message))] + IncorrectPassword { message: String }, #[snafu(display("invalid base64"))] InvalidBase64 { source: base64::DecodeError }, -- cgit v1.2.3-54-g00ecf