diff --git a/src/commands/decrypt.rs b/src/commands/decrypt.rs index 7dc3b30..a6a2489 100644 --- a/src/commands/decrypt.rs +++ b/src/commands/decrypt.rs @@ -45,8 +45,7 @@ fn load_accounts_with_prompts(manager: &mut AccountManager) -> anyhow::Result<() if manager.has_passkey() { error!("Incorrect passkey"); } - let passkey = rpassword::prompt_password_stdout("Enter encryption passkey: ").ok(); - let passkey = passkey.map(SecretString::new); + let passkey = Some(crate::tui::prompt_passkey()?); manager.submit_passkey(passkey); } Err(e) => { diff --git a/src/commands/encrypt.rs b/src/commands/encrypt.rs index f4def57..ca28e4d 100644 --- a/src/commands/encrypt.rs +++ b/src/commands/encrypt.rs @@ -1,4 +1,5 @@ use log::*; +use secrecy::ExposeSecret; use crate::{ encryption::{EncryptionScheme, EntryEncryptor}, @@ -17,23 +18,22 @@ where { fn execute(&self, _transport: T, manager: &mut AccountManager) -> anyhow::Result<()> { if !manager.has_passkey() { - let mut passkey; + let passkey: Option; loop { - passkey = rpassword::prompt_password_stdout("Enter encryption passkey: ").ok(); - if let Some(p) = passkey.as_ref() { - if p.is_empty() { - error!("Passkey cannot be empty, try again."); - continue; - } + let passkey1 = tui::prompt_passkey()?; + if passkey1.expose_secret().is_empty() { + error!("Passkey cannot be empty, try again."); + continue; } let passkey_confirm = - rpassword::prompt_password_stdout("Confirm encryption passkey: ").ok(); - if passkey == passkey_confirm { + rpassword::prompt_password_stdout("Confirm encryption passkey: ") + .map(SecretString::new)?; + if passkey1.expose_secret() == passkey_confirm.expose_secret() { + passkey = Some(passkey1); break; } error!("Passkeys do not match, try again."); } - let passkey = passkey.map(SecretString::new); #[cfg(feature = "keyring")] { diff --git a/src/login.rs b/src/login.rs index f3e0eb9..641e6c6 100644 --- a/src/login.rs +++ b/src/login.rs @@ -1,6 +1,7 @@ use std::io::Write; use log::*; +use secrecy::{ExposeSecret, SecretString}; use steamguard::{ protobufs::steammessages_auth_steamclient::{EAuthSessionGuardType, EAuthTokenPlatformType}, refresher::TokenRefresher, @@ -42,8 +43,8 @@ pub fn do_login( account.account_name = tui::prompt(); } let _ = std::io::stdout().flush(); - let password = rpassword::prompt_password_stdout("Password: ").unwrap(); - if !password.is_empty() { + let password = tui::prompt_password()?; + if !password.expose_secret().is_empty() { debug!("password is present"); } else { debug!("password is empty"); @@ -65,8 +66,8 @@ pub fn do_login_raw( username: String, ) -> anyhow::Result { let _ = std::io::stdout().flush(); - let password = rpassword::prompt_password_stdout("Password: ").unwrap(); - if !password.is_empty() { + let password = tui::prompt_password()?; + if !password.expose_secret().is_empty() { debug!("password is present"); } else { debug!("password is empty"); @@ -77,7 +78,7 @@ pub fn do_login_raw( fn do_login_impl( transport: T, username: String, - password: String, + password: SecretString, account: Option<&SteamGuardAccount>, ) -> anyhow::Result { let mut login = UserLogin::new(transport.clone(), build_device_details()); @@ -85,7 +86,7 @@ fn do_login_impl( let mut password = password; let confirmation_methods; loop { - match login.begin_auth_via_credentials(&username, &password) { + match login.begin_auth_via_credentials(&username, password.expose_secret()) { Ok(methods) => { confirmation_methods = methods; break; @@ -95,11 +96,8 @@ fn do_login_impl( return Err(LoginError::TooManyAttempts.into()); } Err(LoginError::BadCredentials) => { - error!("Incorrect password."); - password = rpassword::prompt_password_stdout("Password: ") - .unwrap() - .trim() - .to_owned(); + error!("Incorrect password for {username}"); + password = tui::prompt_password()?; continue; } Err(err) => { diff --git a/src/main.rs b/src/main.rs index aaf8b57..3afc492 100644 --- a/src/main.rs +++ b/src/main.rs @@ -152,9 +152,7 @@ fn run(args: commands::Args) -> anyhow::Result<()> { } } - let raw = - rpassword::prompt_password_stdout("Enter encryption passkey: ")?; - passkey = Some(SecretString::new(raw)); + passkey = Some(tui::prompt_passkey()?); } Err(e) => { error!("Failed to migrate manifest: {}", e); @@ -208,8 +206,7 @@ fn run(args: commands::Args) -> anyhow::Result<()> { if manager.has_passkey() { error!("Incorrect passkey"); } - let raw = rpassword::prompt_password_stdout("Enter encryption passkey: ")?; - passkey = Some(SecretString::new(raw)); + passkey = Some(tui::prompt_passkey()?); manager.submit_passkey(passkey); } Err(e) => { @@ -253,8 +250,7 @@ fn run(args: commands::Args) -> anyhow::Result<()> { if manager.has_passkey() { error!("Incorrect passkey"); } - let raw = rpassword::prompt_password_stdout("Enter encryption passkey: ")?; - passkey = Some(SecretString::new(raw)); + passkey = Some(tui::prompt_passkey()?); manager.submit_passkey(passkey); } Err(e) => { diff --git a/src/tui.rs b/src/tui.rs index 2d8b0b0..d45cde6 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -6,6 +6,7 @@ use crossterm::{ terminal::{Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen}, QueueableCommand, }; +use secrecy::SecretString; use std::collections::HashSet; use std::io::{stderr, stdout, Write}; use steamguard::Confirmation; @@ -244,6 +245,24 @@ pub(crate) fn pause() { } } +pub(crate) fn prompt_passkey() -> std::io::Result { + loop { + let raw = rpassword::prompt_password_stdout("Enter encryption passkey: ")?; + if !raw.is_empty() { + return Ok(SecretString::new(raw)); + } + } +} + +pub(crate) fn prompt_password() -> std::io::Result { + loop { + let raw = rpassword::prompt_password_stdout("Password: ")?; + if !raw.is_empty() { + return Ok(SecretString::new(raw)); + } + } +} + #[cfg(test)] mod prompt_char_tests { use super::*;