Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions protos/message.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
124 changes: 99 additions & 25 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -70,6 +70,10 @@ lazy_static::lazy_static! {
pub static ref OVERWRITE_LOCAL_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
pub static ref HARD_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
pub static ref BUILTIN_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
pub static ref STRATEGY_OVERRIDE_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
pub static ref STRATEGY_HARD_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
pub static ref STRATEGY_OVERRIDE_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
pub static ref STRATEGY_HARD_SETTINGS: RwLock<HashMap<String, String>> = Default::default();
}

#[cfg(target_os = "android")]
Expand Down Expand Up @@ -1001,13 +1005,22 @@ impl Config {
pub fn get_options() -> HashMap<String, String> {
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<String, String>) {
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<String, String>) {
Expand All @@ -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,
Expand All @@ -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();
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -1175,6 +1202,9 @@ impl Config {

pub fn get_socks() -> Option<Socks5Server> {
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(),
Expand All @@ -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;
}
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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();
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -2048,6 +2096,7 @@ impl UserDefaultConfig {
fn get_after(&self, k: &str) -> Option<String> {
get_or(
&OVERWRITE_DISPLAY_SETTINGS,
&STRATEGY_OVERRIDE_SETTINGS,
&self.options,
&DEFAULT_DISPLAY_SETTINGS,
k,
Expand Down Expand Up @@ -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)]
Expand All @@ -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)]
Expand Down Expand Up @@ -2344,26 +2405,30 @@ deserialize_default!(deserialize_hashmap_resolutions, HashMap<String, Resolution
#[inline]
fn get_or(
a: &RwLock<HashMap<String, String>>,
b: &HashMap<String, String>,
c: &RwLock<HashMap<String, String>>,
b: &RwLock<HashMap<String, String>>,
c: &HashMap<String, String>,
d: &RwLock<HashMap<String, String>>,
k: &str,
) -> Option<String> {
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<HashMap<String, String>>,
strategy_override: &RwLock<HashMap<String, String>>,
k: &str,
defaults: &RwLock<HashMap<String, String>>,
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;
Expand All @@ -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]
Expand All @@ -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.
Expand Down Expand Up @@ -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] = &[
Expand Down Expand Up @@ -2747,6 +2820,7 @@ pub mod keys {
OPTION_ICE_SERVERS,
OPTION_DISABLE_UDP,
OPTION_ALLOW_INSECURE_TLS_FALLBACK,
OPTION_ALLOW_AUTO_UPDATE,
];

// BUILDIN_SETTINGS
Expand Down
35 changes: 32 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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]
Expand Down Expand Up @@ -372,7 +396,10 @@ pub fn init_log(_is_async: bool, _name: &str) -> Option<flexi_logger::LoggerHand
#[cfg(debug_assertions)]
{
use env_logger::*;
init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info,reqwest=warn,rustls=warn,webrtc-sctp=warn,webrtc=warn"));
init_from_env(Env::default().filter_or(
DEFAULT_FILTER_ENV,
"info,reqwest=warn,rustls=warn,webrtc-sctp=warn,webrtc=warn",
));
}
#[cfg(not(debug_assertions))]
{
Expand All @@ -387,7 +414,9 @@ pub fn init_log(_is_async: bool, _name: &str) -> Option<flexi_logger::LoggerHand
path.push(_name);
}
use flexi_logger::*;
if let Ok(x) = Logger::try_with_env_or_str("debug,reqwest=warn,rustls=warn,webrtc-sctp=warn,webrtc=warn") {
if let Ok(x) = Logger::try_with_env_or_str(
"debug,reqwest=warn,rustls=warn,webrtc-sctp=warn,webrtc=warn",
) {
logger_holder = x
.log_to_file(FileSpec::default().directory(path))
.write_mode(if _is_async {
Expand Down
4 changes: 2 additions & 2 deletions src/password_security.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,15 @@ pub fn decrypt_vec_or_original(v: &[u8], current_version: &str) -> (Vec<u8>, boo
(v.to_owned(), false, !v.is_empty())
}

fn encrypt(v: &[u8]) -> Result<String, ()> {
pub fn encrypt(v: &[u8]) -> Result<String, ()> {
if !v.is_empty() {
symmetric_crypt(v, true).map(|v| base64::encode(v, base64::Variant::Original))
} else {
Err(())
}
}

fn decrypt(v: &[u8]) -> Result<Vec<u8>, ()> {
pub fn decrypt(v: &[u8]) -> Result<Vec<u8>, ()> {
if !v.is_empty() {
base64::decode(v, base64::Variant::Original).and_then(|v| symmetric_crypt(&v, false))
} else {
Expand Down