use nanorand::{Rng, WyRand}; use sha3::{Digest, Sha3_256}; use crate::{config_manager, error::PeachError, sbot_client}; /// Returns Ok(()) if the supplied password is correct, /// and returns Err if the supplied password is incorrect. pub fn verify_password(password: &str) -> Result<(), PeachError> { let real_admin_password_hash = config_manager::get_admin_password_hash()?; let password_hash = hash_password(&password.to_string()); if real_admin_password_hash == password_hash { Ok(()) } else { Err(PeachError::PasswordIncorrect) } } /// Checks if the given passwords are valid, and returns Ok() if they are and /// a PeachError otherwise. /// Currently this just checks that the passwords are the same, /// but could be extended to test if they are strong enough. pub fn validate_new_passwords(new_password1: &str, new_password2: &str) -> Result<(), PeachError> { if new_password1 == new_password2 { Ok(()) } else { Err(PeachError::PasswordMismatch) } } /// Sets a new password for the admin user pub fn set_new_password(new_password: &str) -> Result<(), PeachError> { let new_password_hash = hash_password(&new_password.to_string()); config_manager::set_admin_password_hash(&new_password_hash)?; Ok(()) } /// Creates a hash from a password string pub fn hash_password(password: &str) -> String { let mut hasher = Sha3_256::new(); // write input message hasher.update(password); // read hash digest let result = hasher.finalize(); // convert `u8` to `String` result[0].to_string() } /// Sets a new temporary password for the admin user /// which can be used to reset the permanent password pub fn set_new_temporary_password(new_password: &str) -> Result<(), PeachError> { let new_password_hash = hash_password(&new_password.to_string()); config_manager::set_temporary_password_hash(&new_password_hash)?; Ok(()) } /// Returns Ok(()) if the supplied temp_password is correct, /// and returns Err if the supplied temp_password is incorrect pub fn verify_temporary_password(password: &str) -> Result<(), PeachError> { let temporary_admin_password_hash = config_manager::get_temporary_password_hash()?; let password_hash = hash_password(&password.to_string()); if temporary_admin_password_hash == password_hash { Ok(()) } else { Err(PeachError::PasswordIncorrect) } } /// Generates a temporary password and sends it via ssb dm /// to the ssb id configured to be the admin of the peachcloud device pub fn send_password_reset() -> Result<(), PeachError> { // initialise random number generator let mut rng = WyRand::new(); // generate a new password of random numbers let temporary_password = rng.generate::().to_string(); // save this string as a new temporary password set_new_temporary_password(&temporary_password)?; let domain = config_manager::get_peachcloud_domain()?; // then send temporary password as a private ssb message to admin let mut msg = format!( "Your new temporary password is: {} If you are on the same WiFi network as your PeachCloud device you can reset your password \ using this link: http://peach.local/reset_password", temporary_password ); // if there is an external domain, then include remote link in message // otherwise dont include it let remote_link = match domain { Some(domain) => { format!( "\n\nOr if you are on a different WiFi network, you can reset your password \ using the the following link: {}/reset_password", domain ) } None => "".to_string(), }; msg += &remote_link; // finally send the message to the admins let peach_config = config_manager::load_peach_config()?; for ssb_admin_id in peach_config.ssb_admin_ids { sbot_client::private_message(&msg, &ssb_admin_id)?; } Ok(()) }