mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
@@ -24,6 +24,7 @@ directories-next = "2.0"
|
||||
rand = "0.8"
|
||||
serde_derive = "1.0"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
lazy_static = "1.4"
|
||||
confy = { git = "https://github.com/open-trade/confy" }
|
||||
dirs-next = "2.0"
|
||||
@@ -56,5 +57,3 @@ winapi = { version = "0.3", features = ["winuser"] }
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
osascript = "0.3"
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1.0"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
collections::{HashMap, HashSet},
|
||||
fs,
|
||||
io::{Read, Write},
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
|
||||
ops::{Deref, DerefMut},
|
||||
path::{Path, PathBuf},
|
||||
@@ -13,10 +14,12 @@ use rand::Rng;
|
||||
use regex::Regex;
|
||||
use serde as de;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde_json;
|
||||
use sodiumoxide::base64;
|
||||
use sodiumoxide::crypto::sign;
|
||||
|
||||
use crate::{
|
||||
compress::{compress, decompress},
|
||||
log,
|
||||
password_security::{
|
||||
decrypt_str_or_original, decrypt_vec_or_original, encrypt_str_or_original,
|
||||
@@ -31,6 +34,7 @@ pub const REG_INTERVAL: i64 = 12_000;
|
||||
pub const COMPRESS_LEVEL: i32 = 3;
|
||||
const SERIAL: i32 = 3;
|
||||
const PASSWORD_ENC_VERSION: &str = "00";
|
||||
const ENCRYPT_MAX_LEN: usize = 128;
|
||||
|
||||
// config2 options
|
||||
#[cfg(target_os = "linux")]
|
||||
@@ -57,6 +61,7 @@ lazy_static::lazy_static! {
|
||||
pub static ref APP_NAME: Arc<RwLock<String>> = Arc::new(RwLock::new("RustDesk".to_owned()));
|
||||
static ref KEY_PAIR: Arc<Mutex<Option<KeyPair>>> = Default::default();
|
||||
static ref USER_DEFAULT_CONFIG: Arc<RwLock<(UserDefaultConfig, Instant)>> = Arc::new(RwLock::new((UserDefaultConfig::load(), Instant::now())));
|
||||
pub static ref NEW_STORED_PEER_CONFIG: Arc<Mutex<HashSet<String>>> = Default::default();
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
@@ -376,7 +381,8 @@ impl Config2 {
|
||||
fn store(&self) {
|
||||
let mut config = self.clone();
|
||||
if let Some(mut socks) = config.socks {
|
||||
socks.password = encrypt_str_or_original(&socks.password, PASSWORD_ENC_VERSION);
|
||||
socks.password =
|
||||
encrypt_str_or_original(&socks.password, PASSWORD_ENC_VERSION, ENCRYPT_MAX_LEN);
|
||||
config.socks = Some(socks);
|
||||
}
|
||||
Config::store_(&config, "2");
|
||||
@@ -485,8 +491,9 @@ impl Config {
|
||||
|
||||
fn store(&self) {
|
||||
let mut config = self.clone();
|
||||
config.password = encrypt_str_or_original(&config.password, PASSWORD_ENC_VERSION);
|
||||
config.enc_id = encrypt_str_or_original(&config.id, PASSWORD_ENC_VERSION);
|
||||
config.password =
|
||||
encrypt_str_or_original(&config.password, PASSWORD_ENC_VERSION, ENCRYPT_MAX_LEN);
|
||||
config.enc_id = encrypt_str_or_original(&config.id, PASSWORD_ENC_VERSION, ENCRYPT_MAX_LEN);
|
||||
config.id = "".to_owned();
|
||||
Config::store_(&config, "");
|
||||
}
|
||||
@@ -980,15 +987,17 @@ impl PeerConfig {
|
||||
pub fn store(&self, id: &str) {
|
||||
let _lock = CONFIG.read().unwrap();
|
||||
let mut config = self.clone();
|
||||
config.password = encrypt_vec_or_original(&config.password, PASSWORD_ENC_VERSION);
|
||||
config.password =
|
||||
encrypt_vec_or_original(&config.password, PASSWORD_ENC_VERSION, ENCRYPT_MAX_LEN);
|
||||
for opt in ["rdp_password", "os-username", "os-password"] {
|
||||
if let Some(v) = config.options.get_mut(opt) {
|
||||
*v = encrypt_str_or_original(v, PASSWORD_ENC_VERSION)
|
||||
*v = encrypt_str_or_original(v, PASSWORD_ENC_VERSION, ENCRYPT_MAX_LEN)
|
||||
}
|
||||
}
|
||||
if let Err(err) = store_path(Self::path(id), config) {
|
||||
log::error!("Failed to store config: {}", err);
|
||||
}
|
||||
NEW_STORED_PEER_CONFIG.lock().unwrap().insert(id.to_owned());
|
||||
}
|
||||
|
||||
pub fn remove(id: &str) {
|
||||
@@ -1014,7 +1023,7 @@ impl PeerConfig {
|
||||
Config::with_extension(Config::path(path))
|
||||
}
|
||||
|
||||
pub fn peers() -> Vec<(String, SystemTime, PeerConfig)> {
|
||||
pub fn peers(id_filters: Option<Vec<String>>) -> Vec<(String, SystemTime, PeerConfig)> {
|
||||
if let Ok(peers) = Config::path(PEERS).read_dir() {
|
||||
if let Ok(peers) = peers
|
||||
.map(|res| res.map(|e| e.path()))
|
||||
@@ -1027,7 +1036,6 @@ impl PeerConfig {
|
||||
&& p.extension().map(|p| p.to_str().unwrap_or("")) == Some("toml")
|
||||
})
|
||||
.map(|p| {
|
||||
let t = crate::get_modified_time(p);
|
||||
let id = p
|
||||
.file_stem()
|
||||
.map(|p| p.to_str().unwrap_or(""))
|
||||
@@ -1041,12 +1049,21 @@ impl PeerConfig {
|
||||
} else {
|
||||
id
|
||||
};
|
||||
|
||||
let c = PeerConfig::load(&id_decoded_string);
|
||||
(id_decoded_string, p)
|
||||
})
|
||||
.filter(|(id, _)| {
|
||||
let Some(filters) = &id_filters else {
|
||||
return true;
|
||||
};
|
||||
filters.contains(id)
|
||||
})
|
||||
.map(|(id, p)| {
|
||||
let t = crate::get_modified_time(p);
|
||||
let c = PeerConfig::load(&id);
|
||||
if c.info.platform.is_empty() {
|
||||
fs::remove_file(p).ok();
|
||||
}
|
||||
(id_decoded_string, t, c)
|
||||
(id, t, c)
|
||||
})
|
||||
.filter(|p| !p.2.info.platform.is_empty())
|
||||
.collect();
|
||||
@@ -1445,6 +1462,74 @@ impl UserDefaultConfig {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||
pub struct AbPeer {
|
||||
#[serde(
|
||||
default,
|
||||
deserialize_with = "deserialize_string",
|
||||
skip_serializing_if = "String::is_empty"
|
||||
)]
|
||||
pub id: String,
|
||||
#[serde(
|
||||
default,
|
||||
deserialize_with = "deserialize_string",
|
||||
skip_serializing_if = "String::is_empty"
|
||||
)]
|
||||
pub hash: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||
pub struct Ab {
|
||||
#[serde(
|
||||
default,
|
||||
deserialize_with = "deserialize_string",
|
||||
skip_serializing_if = "String::is_empty"
|
||||
)]
|
||||
pub access_token: String,
|
||||
#[serde(default, deserialize_with = "deserialize_vec_abpeer")]
|
||||
pub peers: Vec<AbPeer>,
|
||||
}
|
||||
|
||||
impl Ab {
|
||||
fn path() -> PathBuf {
|
||||
let filename = format!("{}_ab", APP_NAME.read().unwrap().clone());
|
||||
Config::path(filename)
|
||||
}
|
||||
|
||||
pub fn store(json: String) {
|
||||
if let Ok(mut file) = std::fs::File::create(Self::path()) {
|
||||
let data = compress(json.as_bytes());
|
||||
let max_len = 32 * 1024 * 1024;
|
||||
if data.len() > max_len {
|
||||
// not store original
|
||||
return;
|
||||
}
|
||||
let data = encrypt_vec_or_original(&data, PASSWORD_ENC_VERSION, max_len);
|
||||
file.write_all(&data).ok();
|
||||
};
|
||||
}
|
||||
|
||||
pub fn load() -> Ab {
|
||||
if let Ok(mut file) = std::fs::File::open(Self::path()) {
|
||||
let mut data = vec![];
|
||||
if file.read_to_end(&mut data).is_ok() {
|
||||
let (data, succ, _) = decrypt_vec_or_original(&data, PASSWORD_ENC_VERSION);
|
||||
if succ {
|
||||
let data = decompress(&data);
|
||||
if let Ok(ab) = serde_json::from_str::<Ab>(&String::from_utf8_lossy(&data)) {
|
||||
return ab;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Ab::default()
|
||||
}
|
||||
|
||||
pub fn remove() {
|
||||
std::fs::remove_file(Self::path()).ok();
|
||||
}
|
||||
}
|
||||
|
||||
// use default value when field type is wrong
|
||||
macro_rules! deserialize_default {
|
||||
($func_name:ident, $return_type:ty) => {
|
||||
@@ -1464,6 +1549,7 @@ deserialize_default!(deserialize_vec_u8, Vec<u8>);
|
||||
deserialize_default!(deserialize_vec_string, Vec<String>);
|
||||
deserialize_default!(deserialize_vec_i32_string_i32, Vec<(i32, String, i32)>);
|
||||
deserialize_default!(deserialize_vec_discoverypeer, Vec<DiscoveryPeer>);
|
||||
deserialize_default!(deserialize_vec_abpeer, Vec<AbPeer>);
|
||||
deserialize_default!(deserialize_keypair, KeyPair);
|
||||
deserialize_default!(deserialize_size, Size);
|
||||
deserialize_default!(deserialize_hashmap_string_string, HashMap<String, String>);
|
||||
|
||||
@@ -84,13 +84,13 @@ pub fn hide_cm() -> bool {
|
||||
|
||||
const VERSION_LEN: usize = 2;
|
||||
|
||||
pub fn encrypt_str_or_original(s: &str, version: &str) -> String {
|
||||
pub fn encrypt_str_or_original(s: &str, version: &str, max_len: usize) -> String {
|
||||
if decrypt_str_or_original(s, version).1 {
|
||||
log::error!("Duplicate encryption!");
|
||||
return s.to_owned();
|
||||
}
|
||||
if version == "00" {
|
||||
if let Ok(s) = encrypt(s.as_bytes()) {
|
||||
if let Ok(s) = encrypt(s.as_bytes(), max_len) {
|
||||
return version.to_owned() + &s;
|
||||
}
|
||||
}
|
||||
@@ -117,13 +117,13 @@ pub fn decrypt_str_or_original(s: &str, current_version: &str) -> (String, bool,
|
||||
(s.to_owned(), false, !s.is_empty())
|
||||
}
|
||||
|
||||
pub fn encrypt_vec_or_original(v: &[u8], version: &str) -> Vec<u8> {
|
||||
pub fn encrypt_vec_or_original(v: &[u8], version: &str, max_len: usize) -> Vec<u8> {
|
||||
if decrypt_vec_or_original(v, version).1 {
|
||||
log::error!("Duplicate encryption!");
|
||||
return v.to_owned();
|
||||
}
|
||||
if version == "00" {
|
||||
if let Ok(s) = encrypt(v) {
|
||||
if let Ok(s) = encrypt(v, max_len) {
|
||||
let mut version = version.to_owned().into_bytes();
|
||||
version.append(&mut s.into_bytes());
|
||||
return version;
|
||||
@@ -148,8 +148,8 @@ 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, ()> {
|
||||
if !v.is_empty() && v.len() <= 128 {
|
||||
fn encrypt(v: &[u8], max_len: usize) -> Result<String, ()> {
|
||||
if !v.is_empty() && v.len() <= max_len {
|
||||
symmetric_crypt(v, true).map(|v| base64::encode(v, base64::Variant::Original))
|
||||
} else {
|
||||
Err(())
|
||||
@@ -185,12 +185,15 @@ mod test {
|
||||
#[test]
|
||||
fn test() {
|
||||
use super::*;
|
||||
use rand::{thread_rng, Rng};
|
||||
use std::time::Instant;
|
||||
|
||||
let version = "00";
|
||||
let max_len = 128;
|
||||
|
||||
println!("test str");
|
||||
let data = "Hello World";
|
||||
let encrypted = encrypt_str_or_original(data, version);
|
||||
let encrypted = encrypt_str_or_original(data, version, max_len);
|
||||
let (decrypted, succ, store) = decrypt_str_or_original(&encrypted, version);
|
||||
println!("data: {data}");
|
||||
println!("encrypted: {encrypted}");
|
||||
@@ -202,11 +205,14 @@ mod test {
|
||||
let (_, _, store) = decrypt_str_or_original(&encrypted, "99");
|
||||
assert!(store);
|
||||
assert!(!decrypt_str_or_original(&decrypted, version).1);
|
||||
assert_eq!(encrypt_str_or_original(&encrypted, version), encrypted);
|
||||
assert_eq!(
|
||||
encrypt_str_or_original(&encrypted, version, max_len),
|
||||
encrypted
|
||||
);
|
||||
|
||||
println!("test vec");
|
||||
let data: Vec<u8> = vec![1, 2, 3, 4, 5, 6];
|
||||
let encrypted = encrypt_vec_or_original(&data, version);
|
||||
let encrypted = encrypt_vec_or_original(&data, version, max_len);
|
||||
let (decrypted, succ, store) = decrypt_vec_or_original(&encrypted, version);
|
||||
println!("data: {data:?}");
|
||||
println!("encrypted: {encrypted:?}");
|
||||
@@ -218,7 +224,10 @@ mod test {
|
||||
let (_, _, store) = decrypt_vec_or_original(&encrypted, "99");
|
||||
assert!(store);
|
||||
assert!(!decrypt_vec_or_original(&decrypted, version).1);
|
||||
assert_eq!(encrypt_vec_or_original(&encrypted, version), encrypted);
|
||||
assert_eq!(
|
||||
encrypt_vec_or_original(&encrypted, version, max_len),
|
||||
encrypted
|
||||
);
|
||||
|
||||
println!("test original");
|
||||
let data = version.to_string() + "Hello World";
|
||||
@@ -238,5 +247,38 @@ mod test {
|
||||
let (_, succ, store) = decrypt_vec_or_original(&[], version);
|
||||
assert!(!store);
|
||||
assert!(!succ);
|
||||
|
||||
println!("test speed");
|
||||
let test_speed = |len: usize, name: &str| {
|
||||
let mut data: Vec<u8> = vec![];
|
||||
let mut rng = thread_rng();
|
||||
for _ in 0..len {
|
||||
data.push(rng.gen_range(0..255));
|
||||
}
|
||||
let start: Instant = Instant::now();
|
||||
let encrypted = encrypt_vec_or_original(&data, version, len);
|
||||
assert_ne!(data, decrypted);
|
||||
let t1 = start.elapsed();
|
||||
let start = Instant::now();
|
||||
let (decrypted, _, _) = decrypt_vec_or_original(&encrypted, version);
|
||||
let t2 = start.elapsed();
|
||||
assert_eq!(data, decrypted);
|
||||
println!("{name}");
|
||||
println!("encrypt:{:?}, decrypt:{:?}", t1, t2);
|
||||
|
||||
let start: Instant = Instant::now();
|
||||
let encrypted = base64::encode(&data, base64::Variant::Original);
|
||||
let t1 = start.elapsed();
|
||||
let start = Instant::now();
|
||||
let decrypted = base64::decode(&encrypted, base64::Variant::Original).unwrap();
|
||||
let t2 = start.elapsed();
|
||||
assert_eq!(data, decrypted);
|
||||
println!("base64, encrypt:{:?}, decrypt:{:?}", t1, t2,);
|
||||
};
|
||||
test_speed(128, "128");
|
||||
test_speed(1024, "1k");
|
||||
test_speed(1024 * 1024, "1M");
|
||||
test_speed(10 * 1024 * 1024, "10M");
|
||||
test_speed(100 * 1024 * 1024, "100M");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user