diff --git a/protos/message.proto b/protos/message.proto index 2e4a84bdb..815bcc715 100644 --- a/protos/message.proto +++ b/protos/message.proto @@ -87,6 +87,8 @@ message LoginRequest { OSLogin os_login = 12; string my_platform = 13; bytes hwid = 14; + string email = 17; + string salt = 18; } message Terminal { diff --git a/src/config.rs b/src/config.rs index e99a90c95..e0c321240 100644 --- a/src/config.rs +++ b/src/config.rs @@ -21,7 +21,7 @@ use sodiumoxide::crypto::sign; use crate::{ compress::{compress, decompress}, - log, + is_client, is_host, is_sos, is_standard, log, password_security::{ decrypt_str_or_original, decrypt_vec_or_original, encrypt_str_or_original, encrypt_vec_or_original, symmetric_crypt, @@ -70,6 +70,10 @@ lazy_static::lazy_static! { pub static ref OVERWRITE_LOCAL_SETTINGS: RwLock> = Default::default(); pub static ref HARD_SETTINGS: RwLock> = Default::default(); pub static ref BUILTIN_SETTINGS: RwLock> = Default::default(); + pub static ref STRATEGY_OVERRIDE_SETTINGS: RwLock> = Default::default(); + pub static ref STRATEGY_HARD_SETTINGS: RwLock> = Default::default(); + pub static ref STRATEGY_OVERRIDE_SETTINGS: RwLock> = Default::default(); + pub static ref STRATEGY_HARD_SETTINGS: RwLock> = Default::default(); } #[cfg(target_os = "android")] @@ -1001,13 +1005,22 @@ impl Config { pub fn get_options() -> HashMap { let mut res = DEFAULT_SETTINGS.read().unwrap().clone(); res.extend(CONFIG2.read().unwrap().options.clone()); + res.extend(STRATEGY_OVERRIDE_SETTINGS.read().unwrap().clone()); res.extend(OVERWRITE_SETTINGS.read().unwrap().clone()); res } #[inline] fn purify_options(v: &mut HashMap) { - v.retain(|k, v| is_option_can_save(&OVERWRITE_SETTINGS, k, &DEFAULT_SETTINGS, v)); + v.retain(|k, v| { + is_option_can_save( + &OVERWRITE_SETTINGS, + &STRATEGY_OVERRIDE_SETTINGS, + k, + &DEFAULT_SETTINGS, + v, + ) + }); } pub fn set_options(mut v: HashMap) { @@ -1023,6 +1036,7 @@ impl Config { pub fn get_option(k: &str) -> String { get_or( &OVERWRITE_SETTINGS, + &STRATEGY_OVERRIDE_SETTINGS, &CONFIG2.read().unwrap().options, &DEFAULT_SETTINGS, k, @@ -1035,7 +1049,13 @@ impl Config { } pub fn set_option(k: String, v: String) { - if !is_option_can_save(&OVERWRITE_SETTINGS, &k, &DEFAULT_SETTINGS, &v) { + if !is_option_can_save( + &OVERWRITE_SETTINGS, + &STRATEGY_OVERRIDE_SETTINGS, + &k, + &DEFAULT_SETTINGS, + &v, + ) { let mut config = CONFIG2.write().unwrap(); if config.options.remove(&k).is_some() { config.store(); @@ -1117,6 +1137,13 @@ impl Config { { return; } + if STRATEGY_OVERRIDE_SETTINGS + .read() + .unwrap() + .contains_key(keys::OPTION_PROXY_URL) + { + return; + } let mut config = CONFIG2.write().unwrap(); if config.socks == socks { @@ -1175,6 +1202,9 @@ impl Config { pub fn get_socks() -> Option { Self::get_socks_from_custom_client_advanced_settings(&OVERWRITE_SETTINGS.read().unwrap()) + .or(Self::get_socks_from_custom_client_advanced_settings( + &STRATEGY_OVERRIDE_SETTINGS.read().unwrap(), + )) .or(CONFIG2.read().unwrap().socks.clone()) .or(Self::get_socks_from_custom_client_advanced_settings( &DEFAULT_SETTINGS.read().unwrap(), @@ -1195,6 +1225,14 @@ impl Config { { return NetworkType::ProxySocks; } + if STRATEGY_OVERRIDE_SETTINGS + .read() + .unwrap() + .get(keys::OPTION_PROXY_URL) + .is_some() + { + return NetworkType::ProxySocks; + } if CONFIG2.read().unwrap().socks.is_some() { return NetworkType::ProxySocks; } @@ -1809,6 +1847,7 @@ impl LocalConfig { pub fn get_option(k: &str) -> String { get_or( &OVERWRITE_LOCAL_SETTINGS, + &STRATEGY_OVERRIDE_SETTINGS, &LOCAL_CONFIG.read().unwrap().options, &DEFAULT_LOCAL_SETTINGS, k, @@ -1820,6 +1859,7 @@ impl LocalConfig { pub fn get_option_from_file(k: &str) -> String { get_or( &OVERWRITE_LOCAL_SETTINGS, + &STRATEGY_OVERRIDE_SETTINGS, &Self::load().options, &DEFAULT_LOCAL_SETTINGS, k, @@ -1832,7 +1872,13 @@ impl LocalConfig { } pub fn set_option(k: String, v: String) { - if !is_option_can_save(&OVERWRITE_LOCAL_SETTINGS, &k, &DEFAULT_LOCAL_SETTINGS, &v) { + if !is_option_can_save( + &OVERWRITE_LOCAL_SETTINGS, + &STRATEGY_OVERRIDE_SETTINGS, + &k, + &DEFAULT_LOCAL_SETTINGS, + &v, + ) { let mut config = LOCAL_CONFIG.write().unwrap(); if config.options.remove(&k).is_some() { config.store(); @@ -1861,6 +1907,7 @@ impl LocalConfig { pub fn get_flutter_option(k: &str) -> String { get_or( &OVERWRITE_LOCAL_SETTINGS, + &STRATEGY_OVERRIDE_SETTINGS, &LOCAL_CONFIG.read().unwrap().ui_flutter, &DEFAULT_LOCAL_SETTINGS, k, @@ -1996,6 +2043,7 @@ impl UserDefaultConfig { pub fn set(&mut self, key: String, value: String) { if !is_option_can_save( &OVERWRITE_DISPLAY_SETTINGS, + &STRATEGY_OVERRIDE_SETTINGS, &key, &DEFAULT_DISPLAY_SETTINGS, &value, @@ -2048,6 +2096,7 @@ impl UserDefaultConfig { fn get_after(&self, k: &str) -> Option { get_or( &OVERWRITE_DISPLAY_SETTINGS, + &STRATEGY_OVERRIDE_SETTINGS, &self.options, &DEFAULT_DISPLAY_SETTINGS, k, @@ -2227,6 +2276,12 @@ pub struct GroupPeer { skip_serializing_if = "String::is_empty" )] pub login_name: String, + #[serde( + default, + deserialize_with = "deserialize_string", + skip_serializing_if = "String::is_empty" + )] + pub user: String, } #[derive(Debug, Default, Serialize, Deserialize, Clone)] @@ -2237,6 +2292,12 @@ pub struct GroupUser { skip_serializing_if = "String::is_empty" )] pub name: String, + #[serde( + default, + deserialize_with = "deserialize_string", + skip_serializing_if = "String::is_empty" + )] + pub user: String, } #[derive(Debug, Default, Serialize, Deserialize, Clone)] @@ -2344,26 +2405,30 @@ deserialize_default!(deserialize_hashmap_resolutions, HashMap>, - b: &HashMap, - c: &RwLock>, + b: &RwLock>, + c: &HashMap, + d: &RwLock>, k: &str, ) -> Option { a.read() .unwrap() .get(k) - .or(b.get(k)) - .or(c.read().unwrap().get(k)) + .or(b.read().unwrap().get(k)) + .or(c.get(k)) + .or(d.read().unwrap().get(k)) .cloned() } #[inline] fn is_option_can_save( overwrite: &RwLock>, + strategy_override: &RwLock>, k: &str, defaults: &RwLock>, v: &str, ) -> bool { if overwrite.read().unwrap().contains_key(k) + || strategy_override.read().unwrap().contains_key(k) || defaults.read().unwrap().get(k).map_or(false, |x| x == v) { return false; @@ -2373,29 +2438,36 @@ fn is_option_can_save( #[inline] pub fn is_incoming_only() -> bool { - HARD_SETTINGS - .read() - .unwrap() - .get("conn-type") - .map_or(false, |x| x == ("incoming")) + is_host() + || is_sos() + || (is_standard() + && HARD_SETTINGS + .read() + .unwrap() + .get("conn-type") + .map_or(false, |x| x == ("incoming"))) } #[inline] pub fn is_outgoing_only() -> bool { - HARD_SETTINGS - .read() - .unwrap() - .get("conn-type") - .map_or(false, |x| x == ("outgoing")) + is_client() + || (is_standard() + && HARD_SETTINGS + .read() + .unwrap() + .get("conn-type") + .map_or(false, |x| x == ("outgoing"))) } #[inline] fn is_some_hard_opton(name: &str) -> bool { - HARD_SETTINGS - .read() - .unwrap() - .get(name) - .map_or(false, |x| x == ("Y")) + if let Some(value) = HARD_SETTINGS.read().unwrap().get(name) { + return value == "Y"; + } + if let Some(value) = STRATEGY_HARD_SETTINGS.read().unwrap().get(name) { + return value == "Y"; + } + false } #[inline] @@ -2415,12 +2487,12 @@ pub fn is_disable_ab() -> bool { #[inline] pub fn is_disable_account() -> bool { - is_some_hard_opton("disable-account") + is_sos() || is_host() || (is_standard() && is_some_hard_opton("disable-account")) } #[inline] pub fn is_disable_installation() -> bool { - is_some_hard_opton("disable-installation") + is_sos() || is_some_hard_opton("disable-installation") } // This function must be kept the same as the one in flutter and sciter code. @@ -2692,6 +2764,7 @@ pub mod keys { OPTION_SHOW_VIRTUAL_JOYSTICK, OPTION_ENABLE_FLUTTER_HTTP_ON_RUST, OPTION_ALLOW_ASK_FOR_NOTE, + OPTION_ENABLE_CHECK_UPDATE, ]; // DEFAULT_SETTINGS, OVERWRITE_SETTINGS pub const KEYS_SETTINGS: &[&str] = &[ @@ -2747,6 +2820,7 @@ pub mod keys { OPTION_ICE_SERVERS, OPTION_DISABLE_UDP, OPTION_ALLOW_INSECURE_TLS_FALLBACK, + OPTION_ALLOW_AUTO_UPDATE, ]; // BUILDIN_SETTINGS diff --git a/src/lib.rs b/src/lib.rs index 675a8331a..c65934fce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,9 +58,9 @@ pub use uuid; pub mod fingerprint; pub use flexi_logger; pub mod stream; -pub mod websocket; #[cfg(feature = "webrtc")] pub mod webrtc; +pub mod websocket; #[cfg(any(target_os = "android", target_os = "ios"))] pub use rustls_platform_verifier; pub use stream::Stream; @@ -69,6 +69,30 @@ pub mod tls; pub mod verifier; pub use async_recursion; +const HOST_APP_NAME: &str = "RustDesk-Host"; +const CLIENT_APP_NAME: &str = "RustDesk-Client"; +const SOS_APP_NAME: &str = "RustDesk-SOS"; + +pub fn is_standard() -> bool { + let app_name = config::APP_NAME.read().unwrap().clone(); + app_name != HOST_APP_NAME && app_name != SOS_APP_NAME && app_name != CLIENT_APP_NAME +} + +pub fn is_host() -> bool { + let app_name = config::APP_NAME.read().unwrap().clone(); + app_name == HOST_APP_NAME +} + +pub fn is_client() -> bool { + let app_name = config::APP_NAME.read().unwrap().clone(); + app_name == CLIENT_APP_NAME +} + +pub fn is_sos() -> bool { + let app_name = config::APP_NAME.read().unwrap().clone(); + app_name == SOS_APP_NAME +} + pub type SessionID = uuid::Uuid; #[inline] @@ -372,7 +396,10 @@ pub fn init_log(_is_async: bool, _name: &str) -> Option Option (Vec, boo (v.to_owned(), false, !v.is_empty()) } -fn encrypt(v: &[u8]) -> Result { +pub fn encrypt(v: &[u8]) -> Result { if !v.is_empty() { symmetric_crypt(v, true).map(|v| base64::encode(v, base64::Variant::Original)) } else { @@ -172,7 +172,7 @@ fn encrypt(v: &[u8]) -> Result { } } -fn decrypt(v: &[u8]) -> Result, ()> { +pub fn decrypt(v: &[u8]) -> Result, ()> { if !v.is_empty() { base64::decode(v, base64::Variant::Original).and_then(|v| symmetric_crypt(&v, false)) } else {