diff --git a/apps/desktop/src-tauri/src/rustdesk.rs b/apps/desktop/src-tauri/src/rustdesk.rs index 21f7dba..d213c12 100644 --- a/apps/desktop/src-tauri/src/rustdesk.rs +++ b/apps/desktop/src-tauri/src/rustdesk.rs @@ -104,6 +104,14 @@ pub fn ensure_rustdesk( log_event(&format!("Falha ao definir senha padrão: {error}")); } else { log_event("Senha padrão definida com sucesso"); + match ensure_password_files(&password) { + Ok(_) => log_event("Senha persistida nos perfis do RustDesk"), + Err(error) => log_event(&format!("Falha ao persistir senha nos perfis: {error}")), + } + match replicate_password_artifacts() { + Ok(_) => log_event("Artefatos de senha replicados para o serviço do RustDesk"), + Err(error) => log_event(&format!("Falha ao replicar artefatos de senha: {error}")), + } } let custom_id = if let Some(value) = machine_id.and_then(|raw| { @@ -429,6 +437,60 @@ fn remote_id_directories() -> Vec { dirs } +fn ensure_password_files(secret: &str) -> Result<(), String> { + let mut errors = Vec::new(); + for dir in remote_id_directories() { + let password_path = dir.join("RustDesk.toml"); + if let Err(error) = write_toml_kv(&password_path, "password", secret) { + errors.push(format!("{} -> {}", password_path.display(), error)); + } + + let local_path = dir.join("RustDesk_local.toml"); + if let Err(error) = write_toml_kv(&local_path, "verification-method", "use-both-passwords") { + log_event(&format!( + "Falha ao ajustar verification-method em {}: {error}", + local_path.display() + )); + } + } + + if errors.is_empty() { + Ok(()) + } else { + Err(errors.join(" | ")) + } +} + +fn replicate_password_artifacts() -> io::Result<()> { + let Some(src) = user_appdata_config_dir() else { + return Ok(()); + }; + let destinations = [program_data_config_dir(), PathBuf::from(LOCAL_SERVICE_CONFIG)]; + let candidates = ["password", "passwd", "passwd.txt"]; + + for dest in destinations { + fs::create_dir_all(&dest)?; + for name in candidates { + let source_path = src.join(name); + if !source_path.exists() { + continue; + } + let metadata = match fs::metadata(&source_path) { + Ok(data) => data, + Err(_) => continue, + }; + if !metadata.is_file() || metadata.len() == 0 { + continue; + } + + let target_path = dest.join(name); + fs::copy(&source_path, &target_path)?; + } + } + + Ok(()) +} + fn write_remote_id_value(path: &Path, id: &str) -> io::Result<()> { if let Some(parent) = path.parent() { fs::create_dir_all(parent)?; @@ -465,6 +527,44 @@ fn write_remote_id_value(path: &Path, id: &str) -> io::Result<()> { } } +fn write_toml_kv(path: &Path, key: &str, value: &str) -> io::Result<()> { + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; + } + let sanitized = value.replace('\'', "''"); + let replacement = format!("{key} = '{}'\n", sanitized); + if let Ok(existing) = fs::read_to_string(path) { + let mut replaced = false; + let mut buffer = String::with_capacity(existing.len() + replacement.len()); + for line in existing.lines() { + let trimmed = line.trim_start(); + if trimmed.starts_with(&format!("{key} ")) || trimmed.starts_with(&format!("{key}=")) { + buffer.push_str(&replacement); + replaced = true; + } else { + buffer.push_str(line); + buffer.push('\n'); + } + } + if !replaced { + buffer.push_str(&replacement); + } + let mut file = OpenOptions::new() + .create(true) + .write(true) + .truncate(true) + .open(path)?; + file.write_all(buffer.as_bytes()) + } else { + let mut file = OpenOptions::new() + .create(true) + .write(true) + .truncate(true) + .open(path)?; + file.write_all(replacement.as_bytes()) + } +} + fn read_remote_id_from_profiles() -> Option { for dir in remote_id_directories() { for candidate in [dir.join("RustDesk_local.toml"), dir.join("RustDesk.toml")] {