diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index cf657c8dc..3f5330d10 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -534,9 +534,9 @@ impl Config { } } - pub fn get_auto_password() -> String { + pub fn get_auto_password(length: usize) -> String { let mut rng = rand::thread_rng(); - (0..6) + (0..length) .map(|_| CHARS[rng.gen::() % CHARS.len()]) .collect() } @@ -657,7 +657,7 @@ impl Config { log::info!("id updated from {} to {}", id, new_id); } - pub fn set_security_password(password: &str) { + pub fn set_permanent_password(password: &str) { let mut config = CONFIG.write().unwrap(); if password == config.password { return; @@ -666,7 +666,7 @@ impl Config { config.store(); } - pub fn get_security_password() -> String { + pub fn get_permanent_password() -> String { CONFIG.read().unwrap().password.clone() } @@ -682,7 +682,7 @@ impl Config { pub fn get_salt() -> String { let mut salt = CONFIG.read().unwrap().salt.clone(); if salt.is_empty() { - salt = Config::get_auto_password(); + salt = Config::get_auto_password(6); Config::set_salt(&salt); } salt diff --git a/libs/hbb_common/src/password_security.rs b/libs/hbb_common/src/password_security.rs index ed6376ff9..7be014574 100644 --- a/libs/hbb_common/src/password_security.rs +++ b/libs/hbb_common/src/password_security.rs @@ -1,182 +1,62 @@ pub mod password { use crate::config::Config; - use std::{ - fmt::Display, - str::FromStr, - sync::{Arc, RwLock}, - }; + use std::sync::{Arc, RwLock}; lazy_static::lazy_static! { - pub static ref RANDOM_PASSWORD:Arc> = Arc::new(RwLock::new(Config::get_auto_password())); + pub static ref TEMPORARY_PASSWORD:Arc> = Arc::new(RwLock::new(Config::get_auto_password(temporary_password_length()))); } - const SECURITY_ENABLED: &'static str = "security-password-enabled"; - const RANDOM_ENABLED: &'static str = "random-password-enabled"; - const ONETIME_ENABLED: &'static str = "onetime-password-enabled"; - const ONETIME_ACTIVATED: &'static str = "onetime-password-activated"; - const UPDATE_METHOD: &'static str = "random-password-update-method"; - - #[derive(Debug, Clone, PartialEq, Eq)] - pub enum UpdateMethod { - KEEP, - UPDATE, - DISABLE, + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + enum VerificationMethod { + OnlyUseTemporaryPassword, + OnlyUsePermanentPassword, + UseBothPasswords, } - impl FromStr for UpdateMethod { - type Err = (); - - fn from_str(s: &str) -> Result { - if s == "KEEP" { - Ok(Self::KEEP) - } else if s == "UPDATE" { - Ok(Self::UPDATE) - } else if s == "DISABLE" { - Ok(Self::DISABLE) - } else { - Err(()) - } - } + // Should only be called in server + pub fn update_temporary_password() { + *TEMPORARY_PASSWORD.write().unwrap() = + Config::get_auto_password(temporary_password_length()); } - impl Display for UpdateMethod { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - UpdateMethod::KEEP => write!(f, "KEEP"), - UpdateMethod::UPDATE => write!(f, "UPDATE"), - UpdateMethod::DISABLE => write!(f, "DISABLE"), - } - } + // Should only be called in server + pub fn temporary_password() -> String { + TEMPORARY_PASSWORD.read().unwrap().clone() } - pub fn set_random_password(password: &str) { - *RANDOM_PASSWORD.write().unwrap() = password.to_owned(); - } - - pub fn random_password() -> String { - let mut password = RANDOM_PASSWORD.read().unwrap().clone(); - if password.is_empty() { - password = Config::get_auto_password(); - set_random_password(&password); - } - password - } - - pub fn random_password_valid() -> bool { - if random_enabled() { - onetime_password_activated() || !onetime_password_enabled() + fn verification_method() -> VerificationMethod { + let method = Config::get_option("verification-method"); + if method == "use-temporary-password" { + VerificationMethod::OnlyUseTemporaryPassword + } else if method == "use-permanent-password" { + VerificationMethod::OnlyUsePermanentPassword } else { - false + VerificationMethod::UseBothPasswords // default } } - pub fn passwords() -> Vec { - let mut v = vec![]; - if random_password_valid() { - v.push(random_password()); - } - if security_enabled() { - v.push(Config::get_security_password()); - } - v - } - - pub fn after_session(authorized: bool) { - if authorized && random_enabled() { - UpdateMethod::from_str(&update_method()) - .map(|method| match method { - UpdateMethod::KEEP => {} - UpdateMethod::UPDATE => set_random_password(&Config::get_auto_password()), - UpdateMethod::DISABLE => set_random_enabled(false), - }) - .ok(); - } - } - - pub fn update_method() -> String { - let mut method = Config::get_option(UPDATE_METHOD); - if UpdateMethod::from_str(&method).is_err() { - method = UpdateMethod::KEEP.to_string(); // default is keep - set_update_method(&method); - } - method - } - - pub fn set_update_method(method: &str) { - Config::set_option(UPDATE_METHOD.to_owned(), method.to_owned()); - } - - pub fn random_enabled() -> bool { - str2bool(RANDOM_ENABLED, true, || { - set_onetime_password_activated(false); - set_random_password(&Config::get_auto_password()); - }) - } - - pub fn set_random_enabled(enabled: bool) { - if enabled != random_enabled() { - Config::set_option(RANDOM_ENABLED.to_owned(), bool2str(enabled)); - set_onetime_password_activated(false); - if enabled { - set_random_password(&Config::get_auto_password()); - } - } - } - - pub fn security_enabled() -> bool { - str2bool(SECURITY_ENABLED, true, || {}) - } - - pub fn set_security_enabled(enabled: bool) { - if enabled != security_enabled() { - Config::set_option(SECURITY_ENABLED.to_owned(), bool2str(enabled)); - } - } - - pub fn onetime_password_enabled() -> bool { - str2bool(ONETIME_ENABLED, false, || { - set_onetime_password_activated(false); - set_random_password(&Config::get_auto_password()); - }) - } - - pub fn set_onetime_password_enabled(enabled: bool) { - if enabled != onetime_password_enabled() { - Config::set_option(ONETIME_ENABLED.to_owned(), bool2str(enabled)); - set_onetime_password_activated(false); - set_random_password(&Config::get_auto_password()); - } - } - - pub fn onetime_password_activated() -> bool { - str2bool(ONETIME_ACTIVATED, false, || {}) - } - - pub fn set_onetime_password_activated(activated: bool) { - if activated != onetime_password_activated() { - Config::set_option(ONETIME_ACTIVATED.to_owned(), bool2str(activated)); - if activated { - set_random_password(&Config::get_auto_password()); - } - } - } - - // notice: Function nesting - fn str2bool(key: &str, default: bool, default_set: impl Fn()) -> bool { - let option = Config::get_option(key); - if option == "Y" { - true - } else if option == "N" { - false + pub fn temporary_password_length() -> usize { + let length = Config::get_option("temporary-password-length"); + if length == "8" { + 8 + } else if length == "10" { + 10 } else { - Config::set_option(key.to_owned(), bool2str(default)); - default_set(); - default + 6 // default } } - fn bool2str(option: bool) -> String { - if option { "Y" } else { "N" }.to_owned() + pub fn temporary_enabled() -> bool { + verification_method() != VerificationMethod::OnlyUsePermanentPassword + } + + pub fn permanent_enabled() -> bool { + verification_method() != VerificationMethod::OnlyUseTemporaryPassword + } + + pub fn has_valid_password() -> bool { + temporary_enabled() && !temporary_password().is_empty() + || permanent_enabled() && !Config::get_permanent_password().is_empty() } } diff --git a/src/ipc.rs b/src/ipc.rs index 7cef1fc03..9ada67dbd 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -1,4 +1,5 @@ use crate::rendezvous_mediator::RendezvousMediator; +use bytes::Bytes; #[cfg(not(any(target_os = "android", target_os = "ios")))] pub use clipboard::ClipbaordFile; use hbb_common::{ @@ -19,20 +20,9 @@ use parity_tokio_ipc::{ }; use serde_derive::{Deserialize, Serialize}; use std::{collections::HashMap, sync::atomic::Ordering}; -use bytes::Bytes; #[cfg(not(windows))] use std::{fs::File, io::prelude::*}; -const STR_RANDOM_PASSWORD: &'static str = "random-password"; -const STR_SECURITY_PASSWORD: &'static str = "security-password"; -const STR_RANDOM_PASSWORD_UPDATE_METHOD: &'static str = "random-password-update-method"; -const STR_RANDOM_PASSWORD_ENABLED: &'static str = "random-password-enabled"; -const STR_SECURITY_PASSWORD_ENABLED: &'static str = "security-password-enabled"; -const STR_ONETIME_PASSWORD_ENABLED: &'static str = "onetime-password-enabled"; -const STR_ONETIME_PASSWORD_ACTIVATED: &'static str = "onetime-password-activated"; -const STR_RANDOM_PASSWORD_VALID: &'static str = "random-password-valid"; -pub const STR_PASSWORD_DESCRIPTION: &'static str = "password-description"; - // State with timestamp, because std::time::Instant cannot be serialized #[derive(Debug, Serialize, Deserialize, Copy, Clone)] #[serde(tag = "t", content = "c")] @@ -340,20 +330,10 @@ async fn handle(data: Data, stream: &mut Connection) { let value; if name == "id" { value = Some(Config::get_id()); - } else if name == STR_RANDOM_PASSWORD { - value = Some(password::random_password()); - } else if name == STR_SECURITY_PASSWORD { - value = Some(Config::get_security_password()); - } else if name == STR_RANDOM_PASSWORD_UPDATE_METHOD { - value = Some(password::update_method().to_string()); - } else if name == STR_PASSWORD_DESCRIPTION { - value = Some( - password::random_password() - + &password::security_enabled().to_string() - + &password::random_enabled().to_string() - + &password::onetime_password_enabled().to_string() - + &password::onetime_password_activated().to_string(), - ); + } else if name == "temporary-password" { + value = Some(password::temporary_password()); + } else if name == "permanent-password" { + value = Some(Config::get_permanent_password()); } else if name == "salt" { value = Some(Config::get_salt()); } else if name == "rendezvous_server" { @@ -373,12 +353,10 @@ async fn handle(data: Data, stream: &mut Connection) { if name == "id" { Config::set_key_confirmed(false); Config::set_id(&value); - } else if name == STR_RANDOM_PASSWORD { - password::set_random_password(&value); - } else if name == STR_SECURITY_PASSWORD { - Config::set_security_password(&value); - } else if name == STR_RANDOM_PASSWORD_UPDATE_METHOD { - password::set_update_method(&value); + } else if name == "temporary-password" { + password::update_temporary_password(); + } else if name == "permanent-password" { + Config::set_permanent_password(&value); } else if name == "salt" { Config::set_salt(&value); } else { @@ -418,36 +396,6 @@ async fn handle(data: Data, stream: &mut Connection) { Data::TestRendezvousServer => { crate::test_rendezvous_server(); } - Data::Bool((name, value)) => match value { - None => { - let value; - if name == STR_SECURITY_PASSWORD_ENABLED { - value = Some(password::security_enabled()); - } else if name == STR_RANDOM_PASSWORD_ENABLED { - value = Some(password::random_enabled()); - } else if name == STR_ONETIME_PASSWORD_ENABLED { - value = Some(password::onetime_password_enabled()); - } else if name == STR_ONETIME_PASSWORD_ACTIVATED { - value = Some(password::onetime_password_activated()); - } else if name == STR_RANDOM_PASSWORD_VALID { - value = Some(password::random_password_valid()); - } else { - return; - } - allow_err!(stream.send(&Data::Bool((name, value))).await); - } - Some(value) => { - if name == STR_SECURITY_PASSWORD_ENABLED { - password::set_security_enabled(value); - } else if name == STR_RANDOM_PASSWORD_ENABLED { - password::set_random_enabled(value); - } else if name == STR_ONETIME_PASSWORD_ENABLED { - password::set_onetime_password_enabled(value); - } else if name == STR_ONETIME_PASSWORD_ACTIVATED { - password::set_onetime_password_activated(value); - } - } - }, _ => {} } } @@ -530,10 +478,6 @@ where .await } - async fn send_bool(&mut self, name: &str, value: bool) -> ResultType<()> { - self.send(&Data::Bool((name.to_owned(), Some(value)))).await - } - pub async fn next_timeout(&mut self, ms_timeout: u64) -> ResultType> { Ok(timeout(ms_timeout, self.next()).await??) } @@ -605,128 +549,22 @@ pub async fn set_config(name: &str, value: String) -> ResultType<()> { set_config_async(name, value).await } -#[tokio::main(flavor = "current_thread")] -async fn get_bool(name: &str) -> ResultType> { - get_bool_async(name, 1_000).await +pub fn update_temporary_password() -> ResultType<()> { + set_config("temporary-password", "".to_owned()) } -async fn get_bool_async(name: &str, ms_timeout: u64) -> ResultType> { - let mut c = connect(ms_timeout, "").await?; - c.send(&Data::Bool((name.to_owned(), None))).await?; - if let Some(Data::Bool((name2, value))) = c.next_timeout(ms_timeout).await? { - if name == name2 { - return Ok(value); - } - } - return Ok(None); -} - -pub async fn set_bool_async(name: &str, value: bool) -> ResultType<()> { - let mut c = connect(1000, "").await?; - c.send_bool(name, value).await?; - Ok(()) -} - -#[tokio::main(flavor = "current_thread")] -pub async fn set_bool(name: &str, value: bool) -> ResultType<()> { - set_bool_async(name, value).await -} - -pub fn get_random_password() -> String { - if let Ok(Some(password)) = get_config(STR_RANDOM_PASSWORD) { - password::set_random_password(&password); - password +pub fn get_permanent_password() -> String { + if let Ok(Some(v)) = get_config("permanent-password") { + Config::set_permanent_password(&v); + v } else { - password::random_password() + Config::get_permanent_password() } } -pub fn set_random_password(v: String) -> ResultType<()> { - password::set_random_password(&v); - set_config(STR_RANDOM_PASSWORD, v) -} - -pub fn set_security_password(v: String) -> ResultType<()> { - Config::set_security_password(&v); - set_config(STR_SECURITY_PASSWORD, v) -} - -pub fn random_password_update_method() -> String { - if let Ok(Some(method)) = get_config(STR_RANDOM_PASSWORD_UPDATE_METHOD) { - password::set_update_method(&method); - method - } else { - password::update_method() - } -} - -pub fn set_random_password_update_method(method: String) -> ResultType<()> { - password::set_update_method(&method); - set_config(STR_RANDOM_PASSWORD_UPDATE_METHOD, method) -} - -pub fn is_random_password_enabled() -> bool { - if let Ok(Some(enabled)) = get_bool(STR_RANDOM_PASSWORD_ENABLED) { - password::set_random_enabled(enabled); - enabled - } else { - password::random_enabled() - } -} - -pub fn set_random_password_enabled(enabled: bool) -> ResultType<()> { - password::set_random_enabled(enabled); - set_bool(STR_RANDOM_PASSWORD_ENABLED, enabled) -} - -pub fn is_security_password_enabled() -> bool { - if let Ok(Some(enabled)) = get_bool(STR_SECURITY_PASSWORD_ENABLED) { - password::set_security_enabled(enabled); - enabled - } else { - password::security_enabled() - } -} - -pub fn set_security_password_enabled(enabled: bool) -> ResultType<()> { - password::set_security_enabled(enabled); - set_bool(STR_SECURITY_PASSWORD_ENABLED, enabled) -} - -pub fn is_onetime_password_enabled() -> bool { - if let Ok(Some(enabled)) = get_bool(STR_ONETIME_PASSWORD_ENABLED) { - password::set_onetime_password_enabled(enabled); - enabled - } else { - password::onetime_password_enabled() - } -} - -pub fn set_onetime_password_enabled(enabled: bool) -> ResultType<()> { - password::set_onetime_password_enabled(enabled); - set_bool(STR_ONETIME_PASSWORD_ENABLED, enabled) -} - -pub fn is_onetime_password_activated() -> bool { - if let Ok(Some(activated)) = get_bool(STR_ONETIME_PASSWORD_ACTIVATED) { - password::set_onetime_password_activated(activated); - activated - } else { - password::onetime_password_activated() - } -} - -pub fn set_onetime_password_activated(activated: bool) -> ResultType<()> { - password::set_onetime_password_activated(activated); - set_bool(STR_ONETIME_PASSWORD_ACTIVATED, activated) -} - -pub fn is_random_password_valid() -> bool { - if let Ok(Some(valid)) = get_bool(STR_RANDOM_PASSWORD_VALID) { - valid - } else { - password::random_password_valid() - } +pub fn set_permanent_password(v: String) -> ResultType<()> { + Config::set_permanent_password(&v); + set_config("permanent-password", v) } pub fn get_id() -> String { diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 6e3d4d067..9c23de91f 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "保持RustDesk后台服务"), ("Ignore Battery Optimizations", "忽略电池优化"), ("android_open_battery_optimizations_tip", "如需关闭此功能,请在接下来的RustDesk应用设置页面中,找到并进入 [电源] 页面,取消勾选 [不受限制]"), - ("Random Password After Session", "会话结束更新随机密码"), - ("Keep", "保持"), - ("Update", "更新"), - ("Disable", "禁用"), - ("Onetime Password", "一次性口令"), - ("Verification Method", "密码验证方式"), - ("Enable security password", "启用安全密码"), - ("Enable random password", "启用随机密码"), - ("Enable onetime password", "启用一次性访问功能"), - ("Disable onetime password", "禁用一次性访问功能"), - ("Activate onetime password", "激活一次性访问功能"), - ("Set security password", "设置安全密码"), ("Connection not allowed", "对方不允许连接"), + ("Use temporary password", "使用临时密码"), + ("Use permanent password", "使用固定密码"), + ("Use both passwords", "同时使用两种密码"), + ("Set permanent password", "设置固定密码"), + ("Set temporary password length", "设置临时密码长度"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index d9ff10416..510a50c45 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), ("Connection not allowed", ""), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index f9776e687..5489a6b74 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), ("Connection not allowed", ""), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 671bcae98..e54377195 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "RustDesk im Hintergrund ausführen"), ("Ignore Battery Optimizations", "Batterieoptimierung ignorieren"), ("android_open_battery_optimizations_tip", "Möchten Sie die Batterieopimierungs-Einstellungen öffnen?"), - ("Random Password After Session", "Neues zufälliges Passwort nach jeder Sitzung"), - ("Keep", "Behalten"), - ("Update", "Aktualisieren"), - ("Disable", "Deaktivieren"), - ("Onetime Password", "Einmal-Passwort"), - ("Verification Method", "Überprüfungsmethode"), - ("Enable security password", "Sicheres Passwort aktivieren"), - ("Enable random password", "Zufälliges Passwort aktivieren"), - ("Enable onetime password", "Einmal-Passwort aktivieren"), - ("Disable onetime password", "Einmal-Passwort deaktivieren"), - ("Activate onetime password", "Einmal-Passwort aktivieren"), - ("Set security password", "Sicheres Passwort setzen"), ("Connection not allowed", "Verbindung abgelehnt"), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index a21833559..d0c6511a6 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), ("Connection not allowed", ""), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 14ba0ab57..24b1122ef 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), ("Connection not allowed", ""), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index f387b550b..e928b6939 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), ("Connection not allowed", ""), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index e35ab8195..8f182cdda 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), ("Connection not allowed", ""), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 6bf69e476..d26706f87 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), ("Connection not allowed", ""), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 778313d5b..dffeb4773 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), ("Connection not allowed", ""), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 176833501..390bbf968 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), ("Connection not allowed", ""), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 55d33c7b3..1c5a79cb3 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "Сохранить фоновый службу RustDesk"), ("Ignore Battery Optimizations", "Игнорировать оптимизацию батареи"), ("android_open_battery_optimizations_tip", "Перейдите на следующую страницу настроек "), - ("Random Password After Session", "Случайный пароль после сеанса"), - ("Keep", "Оставить"), - ("Update", "Обновить"), - ("Disable", "Отключить"), - ("Onetime Password", "Одноразовый пароль"), - ("Verification Method", "Метод верификации"), - ("Enable security password", "Включить пароль безопасности"), - ("Enable random password", "Включить случайный пароль"), - ("Enable onetime password", "Включить одноразовый пароль"), - ("Disable onetime password", "Отключить одноразовый пароль"), - ("Activate onetime password", "Активировать одноразовый пароль"), - ("Set security password", "Задать пароль безопасности"), ("Connection not allowed", "Подключение не разрешено"), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 332336007..dc255dd2b 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), ("Connection not allowed", ""), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 7b39a2876..fa8ef8cfb 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), ("Connection not allowed", ""), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 02468201e..a54cc7099 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", ""), ("Ignore Battery Optimizations", ""), ("android_open_battery_optimizations_tip", ""), - ("Random Password After Session", ""), - ("Keep", ""), - ("Update", ""), - ("Disable", ""), - ("Onetime Password", ""), - ("Verification Method", ""), - ("Enable security password", ""), - ("Enable random password", ""), - ("Enable onetime password", ""), - ("Disable onetime password", ""), - ("Activate onetime password", ""), - ("Set security password", ""), ("Connection not allowed", ""), + ("Use temporary password", ""), + ("Use permanent password", ""), + ("Use both passwords", ""), + ("Set permanent password", ""), + ("Set temporary password length", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index ea94d159c..6eeeb8e72 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -287,18 +287,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Keep RustDesk background service", "保持RustDesk後台服務"), ("Ignore Battery Optimizations", "忽略電池優化"), ("android_open_battery_optimizations_tip", "如需關閉此功能,請在接下來的RustDesk應用設置頁面中,找到並進入 [電源] 頁面,取消勾選 [不受限制]"), - ("Random Password After Session", "會話結束更新隨機密碼"), - ("Keep", "保持"), - ("Update", "更新"), - ("Disable", "禁用"), - ("Onetime Password", "一次性口令"), - ("Verification Method", "密碼驗證方式"), - ("Enable security password", "啟用安全密碼"), - ("Enable random password", "啟用隨機密碼"), - ("Enable onetime password", "啟用一次性訪問功能"), - ("Disable onetime password", "禁用一次性訪問功能"), - ("Activate onetime password", "激活一次性訪問功能"), - ("Set security password", "設置安全密碼"), ("Connection not allowed", "對方不允許連接"), + ("Use temporary password", "使用臨時密碼"), + ("Use permanent password", "使用固定密碼"), + ("Use both passwords", "同時使用兩種密碼"), + ("Set permanent password", "設定固定密碼"), + ("Set temporary password length", "設定臨時密碼長度"), ].iter().cloned().collect(); } diff --git a/src/main.rs b/src/main.rs index c8f76cbd7..be1e046a1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -152,7 +152,7 @@ fn main() { return; } else if args[0] == "--password" { if args.len() == 2 { - ipc::set_security_password(args[1].to_owned()).unwrap(); + ipc::set_permanent_password(args[1].to_owned()).unwrap(); } return; } else if args[0] == "--check-hwcodec-config" { diff --git a/src/server/connection.rs b/src/server/connection.rs index 8cbc952bc..590dc198b 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -134,7 +134,7 @@ impl Connection { ) { let hash = Hash { salt: Config::get_salt(), - challenge: Config::get_auto_password(), + challenge: Config::get_auto_password(6), ..Default::default() }; let (tx_from_cm_holder, mut rx_from_cm) = mpsc::unbounded_channel::(); @@ -415,7 +415,9 @@ impl Connection { video_service::notify_video_frame_feched(id, None); scrap::codec::Encoder::update_video_encoder(id, scrap::codec::EncoderUpdate::Remove); video_service::VIDEO_QOS.lock().unwrap().reset(); - password::after_session(conn.authorized); + if conn.authorized { + password::update_temporary_password(); + } if let Err(err) = conn.try_port_forward_loop(&mut rx_from_cm).await { conn.on_close(&err.to_string(), false).await; } @@ -820,17 +822,9 @@ impl Connection { } fn validate_password(&mut self) -> bool { - if password::security_enabled() { - if self.validate_one_password(Config::get_security_password()) { - return true; - } - } - if password::random_password_valid() { - let password = password::random_password(); + if password::temporary_enabled() { + let password = password::temporary_password(); if self.validate_one_password(password.clone()) { - if password::onetime_password_activated() { - password::set_onetime_password_activated(false); - } SESSIONS.lock().unwrap().insert( self.lr.my_id.clone(), Session { @@ -843,6 +837,11 @@ impl Connection { return true; } } + if password::permanent_enabled() { + if self.validate_one_password(Config::get_permanent_password()) { + return true; + } + } false } @@ -956,7 +955,7 @@ impl Connection { } else if lr.password.is_empty() { self.try_start_cm(lr.my_id, lr.my_name, false); } else { - if password::passwords().len() == 0 { + if !password::has_valid_password() { self.send_login_error("Connection not allowed").await; return false; } diff --git a/src/ui.rs b/src/ui.rs index 3fecc33cd..b51fd0d11 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -187,16 +187,20 @@ impl UI { ipc::get_id() } - fn get_random_password(&self) -> String { - ipc::get_random_password() + fn temporary_password(&mut self) -> String { + self.5.lock().unwrap().clone() } - fn update_random_password(&self) { - allow_err!(ipc::set_random_password(Config::get_auto_password())); + fn update_temporary_password(&self) { + allow_err!(ipc::update_temporary_password()); } - fn set_security_password(&self, password: String) { - allow_err!(ipc::set_security_password(password)); + fn permanent_password(&self) -> String { + ipc::get_permanent_password() + } + + fn set_permanent_password(&self, password: String) { + allow_err!(ipc::set_permanent_password(password)); } fn get_remote_id(&mut self) -> String { @@ -775,54 +779,6 @@ impl UI { fn get_langs(&self) -> String { crate::lang::LANGS.to_string() } - - fn random_password_update_method(&self) -> String { - ipc::random_password_update_method() - } - - fn set_random_password_update_method(&self, method: String) { - allow_err!(ipc::set_random_password_update_method(method)); - } - - fn is_random_password_enabled(&self) -> bool { - ipc::is_random_password_enabled() - } - - fn set_random_password_enabled(&self, enabled: bool) { - allow_err!(ipc::set_random_password_enabled(enabled)); - } - - fn is_security_password_enabled(&self) -> bool { - ipc::is_security_password_enabled() - } - - fn set_security_password_enabled(&self, enabled: bool) { - allow_err!(ipc::set_security_password_enabled(enabled)); - } - - fn is_onetime_password_enabled(&self) -> bool { - ipc::is_onetime_password_enabled() - } - - fn set_onetime_password_enabled(&self, enabled: bool) { - allow_err!(ipc::set_onetime_password_enabled(enabled)); - } - - fn is_onetime_password_activated(&self) -> bool { - ipc::is_onetime_password_activated() - } - - fn set_onetime_password_activated(&self, activated: bool) { - allow_err!(ipc::set_onetime_password_activated(activated)); - } - - fn is_random_password_valid(&self) -> bool { - ipc::is_random_password_valid() - } - - fn password_description(&mut self) -> String { - self.5.lock().unwrap().clone() - } } impl sciter::EventHandler for UI { @@ -832,9 +788,10 @@ impl sciter::EventHandler for UI { fn is_xfce(); fn using_public_server(); fn get_id(); - fn get_random_password(); - fn update_random_password(); - fn set_security_password(String); + fn temporary_password(); + fn update_temporary_password(); + fn permanent_password(); + fn set_permanent_password(String); fn get_remote_id(); fn set_remote_id(String); fn closing(i32, i32, i32, i32); @@ -904,18 +861,6 @@ impl sciter::EventHandler for UI { fn get_uuid(); fn has_hwcodec(); fn get_langs(); - fn random_password_update_method(); - fn set_random_password_update_method(String); - fn is_random_password_enabled(); - fn set_random_password_enabled(bool); - fn is_security_password_enabled(); - fn set_security_password_enabled(bool); - fn is_onetime_password_enabled(); - fn set_onetime_password_enabled(bool); - fn is_onetime_password_activated(); - fn set_onetime_password_activated(bool); - fn is_random_password_valid(); - fn password_description(); } } @@ -982,7 +927,7 @@ async fn check_connect_status_( Ok(Some(ipc::Data::Config((name, Some(value))))) => { if name == "id" { id = value; - } else if name == ipc::STR_PASSWORD_DESCRIPTION { + } else if name == "temporary-password" { *password.lock().unwrap() = value; } } @@ -1003,7 +948,7 @@ async fn check_connect_status_( c.send(&ipc::Data::OnlineStatus(None)).await.ok(); c.send(&ipc::Data::Options(None)).await.ok(); c.send(&ipc::Data::Config(("id".to_owned(), None))).await.ok(); - c.send(&ipc::Data::Config((ipc::STR_PASSWORD_DESCRIPTION.to_owned(), None))).await.ok(); + c.send(&ipc::Data::Config(("temporary-password".to_owned(), None))).await.ok(); } } } diff --git a/src/ui/index.tis b/src/ui/index.tis index 4a6004135..296527681 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -529,9 +529,7 @@ class App: Reactor.Component {key_confirmed ? : translate("Generating ...")} -
- -
+ {!is_win || handler.is_installed() ? "": } {software_update_url ? : ""} @@ -802,8 +800,8 @@ function watch_screen_recording() { class PasswordEyeArea : Reactor.Component { render() { - var show = handler.is_random_password_valid(); - var value = show ? handler.get_random_password() : "-"; + var method = handler.get_option('verification-method'); + var value = method != 'use-permanent-password' ? password_cache[0] : "-"; return
@@ -812,95 +810,49 @@ class PasswordEyeArea : Reactor.Component { } event click $(svg#refresh-password) (_, me) { - if (handler.is_random_password_valid()) handler.update_random_password(); + handler.update_temporary_password(); this.update(); } } -var verificationMethodMenu; -class VerificationMethodMenu: Reactor.Component { +var temporaryPasswordLengthMenu; +class TemporaryPasswordLengthMenu: Reactor.Component { function this() { - verificationMethodMenu = this; + temporaryPasswordLengthMenu = this; } function render() { if (!this.show) return
  • ; var me = this; + var method = handler.get_option('verification-method'); self.timer(1ms, function() { me.toggleMenuState() }); - return
  • {translate('Verification Method')} - -
  • {svg_checkmark}{translate('Enable security password')}
  • -
  • {svg_checkmark}{translate('Enable random password')}
  • + return
  • {translate("Set temporary password length")} + +
  • {svg_checkmark}6
  • +
  • {svg_checkmark}8
  • +
  • {svg_checkmark}10
  • ; } function toggleMenuState() { - var security_enabled = handler.is_security_password_enabled(); - var random_enabled = handler.is_random_password_enabled(); - var onetime_enabled = handler.is_onetime_password_enabled(); - for (var (index, el) in this.$$(menu#verification-method>li)) { - if (index == 0) el.attributes.toggleClass("selected", security_enabled); - if (index == 1) el.attributes.toggleClass("selected", random_enabled); + var length = handler.get_option("temporary-password-length"); + var index = ['6', '8', '10'].indexOf(length); + if (index < 0) index = 0; + for (var (i, el) in this.$$(menu#temporary-password-length>li)) { + el.attributes.toggleClass("selected", i == index); } } - event click $(menu#verification-method>li) (_, me) { - switch (me.id.substring('verification-method-'.length)) { - case 'security': - { - var security_enabled = handler.is_security_password_enabled(); - handler.set_security_password_enabled(!security_enabled); - } - break; - case 'random': - { - var random_enabled = handler.is_random_password_enabled(); - handler.set_random_password_enabled(!random_enabled); - } - break; + event click $(menu#temporary-password-length>li) (_, me) { + var length = me.id.substring('temporary-password-length-'.length); + var old_length = handler.get_option('temporary-password-length'); + if (length != old_length) { + handler.set_option('temporary-password-length', length); + handler.update_temporary_password(); + this.toggleMenuState(); + passwordArea.update(); } - - this.toggleMenuState(); - passwordArea.update(); - } -} - -var randomPasswordUpdateMethodMenu; -class RandomPasswordUpdateMethodMenu: Reactor.Component { - function this() { - randomPasswordUpdateMethodMenu = this; - } - - function render() { - if (!this.show) return
  • ; - var me = this; - var random_enabled = handler.is_random_password_enabled(); - self.timer(1ms, function() { me.toggleMenuState() }); - return
  • {translate('Random Password After Session')} - -
  • {svg_checkmark}{translate('Keep')}
  • -
  • {svg_checkmark}{translate('Update')}
  • -
  • {svg_checkmark}{translate('Disable')}
  • -
    -
  • ; - } - - function toggleMenuState() { - var method = handler.random_password_update_method(); - for (var (index, el) in this.$$(menu#random-password-update-method>li)) { - if (index == 0) el.attributes.toggleClass("selected", method == "KEEP"); - if (index == 1) el.attributes.toggleClass("selected", method == "UPDATE"); - if (index == 2) el.attributes.toggleClass("selected", method == "DISABLE"); - } - } - - event click $(menu#random-password-update-method>li) (_, me) { - if (me.id === 'random-password-update-method-keep') handler.set_random_password_update_method("KEEP"); - if (me.id === 'random-password-update-method-update') handler.set_random_password_update_method("UPDATE"); - if (me.id === 'random-password-update-method-disable') handler.set_random_password_update_method("DISABLE"); - this.toggleMenuState(); - passwordArea.update(); } } @@ -911,11 +863,11 @@ class PasswordArea: Reactor.Component { } function render() { - var onetime_enabled = handler.is_onetime_password_enabled(); - + var me = this; + self.timer(1ms, function() { me.toggleMenuState() }); return -
    -
    {translate(onetime_enabled ? 'Onetime Password' : 'Password')}
    +
    +
    {translate('Password')}
    {this.renderPop()} @@ -925,35 +877,39 @@ class PasswordArea: Reactor.Component { } function renderPop() { - var security_enabled = handler.is_security_password_enabled(); - var random_enabled = handler.is_random_password_enabled(); - var onetime_enabled = handler.is_onetime_password_enabled(); - var onetime_activated = handler.is_onetime_password_activated(); - + var method = handler.get_option('verification-method'); return -
  • {translate(onetime_enabled ? "Disable onetime password" : "Enable onetime password")}
  • -
  • {translate('Activate onetime password')}
  • +
  • {svg_checkmark}{translate('Use temporary password')}
  • +
  • {svg_checkmark}{translate('Use permanent password')}
  • +
  • {svg_checkmark}{translate('Use both passwords')}
  • - -
    -
  • {translate('Set security password')}
  • -
    - +
  • {translate('Set permanent password')}
  • +
    ; } + function toggleMenuState() { + var id = handler.get_option('verification-method'); + if (id != 'use-temporary-password' && id != 'use-permanent-password') + id = 'use-both-passwords'; + for (var el in [this.$(li#use-temporary-password), this.$(li#use-permanent-password), this.$(li#use-both-passwords)]) { + el.attributes.toggleClass("selected", el.id == id); + } + } + event click $(svg#edit) (_, me) { - randomPasswordUpdateMethodMenu.update({show: true }); - verificationMethodMenu.update({show: true }); + temporaryPasswordLengthMenu.update({show: true }); var menu = $(menu#edit-password-context); me.popup(menu); } event click $(li#set-password) { var me = this; + var password = handler.permanent_password(); + var value_field = password.length == 0 ? "" : "value=" + password; msgbox("custom-password", translate("Set Password"), "
    \ -
    " + translate('Password') + ":
    \ -
    " + translate('Confirmation') + ":
    \ +
    " + translate('Password') + ":
    \ +
    " + translate('Confirmation') + ":
    \
    \ ", function(res=null) { if (!res) return; @@ -965,31 +921,40 @@ class PasswordArea: Reactor.Component { if (p0 != p1) { return translate("The confirmation is not identical."); } - handler.set_security_password(p0); + handler.set_permanent_password(p0); me.update(); }); } - event click $(li#enable-onetime-password) { - var onetime_enabled = handler.is_onetime_password_enabled(); - handler.set_onetime_password_enabled(!onetime_enabled); - passwordArea.update(); - } - - event click $(li#activate-onetime-password) { - handler.set_onetime_password_activated(true); - passwordArea.update(); + event click $(menu#edit-password-context>li) (_, me) { + if (me.id.indexOf('use-') == 0) { + handler.set_option('verification-method', me.id); + this.toggleMenuState(); + passwordArea.update(); + } } } -var last_password_description = ""; +var password_cache = ["","",""]; function updatePasswordArea() { self.timer(1s, function() { - var description = handler.password_description(); - if (last_password_description != description) { - last_password_description = description - passwordArea.update(); + var temporary_password = handler.temporary_password(); + var verification_method = handler.get_option('verification-method'); + var temporary_password_length = handler.get_option('temporary-password-length'); + var update = false; + if (password_cache[0] != temporary_password) { + password_cache[0] = temporary_password; + update = true; } + if (password_cache[1] != verification_method) { + password_cache[1] = verification_method; + update = true; + } + if (password_cache[2] != temporary_password_length) { + password_cache[2] = temporary_password_length; + update = true; + } + if (update) passwordArea.update(); updatePasswordArea(); }); }