From 484eb8fbe93fc7f43202b3e9a7b485f9c8a7cf2f Mon Sep 17 00:00:00 2001 From: Esdras Renan Date: Wed, 12 Nov 2025 10:39:36 -0300 Subject: [PATCH] fix: improve RustDesk ACL preflight and file writes --- apps/desktop/src-tauri/src/rustdesk.rs | 46 ++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/apps/desktop/src-tauri/src/rustdesk.rs b/apps/desktop/src-tauri/src/rustdesk.rs index 515600c..21b91fd 100644 --- a/apps/desktop/src-tauri/src/rustdesk.rs +++ b/apps/desktop/src-tauri/src/rustdesk.rs @@ -540,6 +540,9 @@ fn propagate_password_profile() -> io::Result { if let Some(parent) = target_path.parent() { fs::create_dir_all(parent)?; } + if target_path.is_dir() { + fs::remove_dir_all(&target_path)?; + } fs::write(&target_path, &contents)?; log_event(&format!( "RustDesk.toml propagado para {}", @@ -572,6 +575,9 @@ fn replicate_password_artifacts() -> io::Result<()> { } let target_path = dest.join(name); + if target_path.is_dir() { + fs::remove_dir_all(&target_path)?; + } fs::copy(&source_path, &target_path)?; log_event(&format!( "Artefato de senha {name} replicado para {}", @@ -636,7 +642,9 @@ if (-not (Test-Path '{target}')) {{ New-Item -ItemType Directory -Force -Path '{ $admins = (New-Object Security.Principal.SecurityIdentifier('S-1-5-32-544')).Translate([Security.Principal.NTAccount]).Value $localSvc = (New-Object Security.Principal.SecurityIdentifier('S-1-5-19')).Translate([Security.Principal.NTAccount]).Value takeown /F '{target}' /R /D Y | Out-Null +if ($LASTEXITCODE -ne 0) {{ exit $LASTEXITCODE }} icacls '{target}' /grant "${{admins}}":(OI)(CI)F "${{localSvc}}":(OI)(CI)F /T /C | Out-Null +exit $LASTEXITCODE "# ); run_powershell_elevated(&script) @@ -657,6 +665,41 @@ fn ensure_localservice_writable_preflight() -> Result<(), String> { } } +fn can_write_dir(dir: &Path) -> bool { + if fs::create_dir_all(dir).is_err() { + return false; + } + let probe = dir.join(".raven_acl_probe"); + match OpenOptions::new() + .create(true) + .write(true) + .truncate(true) + .open(&probe) + { + Ok(mut file) => { + let result = file.write_all(b"ok").is_ok(); + let _ = fs::remove_file(&probe); + result + } + Err(_) => false, + } +} + +fn ensure_localservice_writable_preflight() -> Result<(), String> { + let dir = PathBuf::from(LOCAL_SERVICE_CONFIG); + if can_write_dir(&dir) { + return Ok(()); + } + log_event("Tentando corrigir ACL do perfil LocalService via UAC (preflight)..."); + fix_localservice_acl()?; + if can_write_dir(&dir) { + log_event("ACL do LocalService ajustada com sucesso."); + Ok(()) + } else { + Err("continua sem permissão para LocalService (após preflight)".into()) + } +} + fn can_write_dir(dir: &Path) -> bool { if fs::create_dir_all(dir).is_err() { return false; @@ -720,6 +763,9 @@ fn write_toml_kv(path: &Path, key: &str, value: &str) -> io::Result<()> { if let Some(parent) = path.parent() { fs::create_dir_all(parent)?; } + if path.is_dir() { + fs::remove_dir_all(path)?; + } let sanitized = value.replace('\\', "\\\\").replace('"', "\\\""); let replacement = format!("{key} = \"{sanitized}\"\n"); let existing = fs::read_to_string(path).unwrap_or_default();