From 2339d5010fe9adc144bb670dd3909fbed07c5d2d Mon Sep 17 00:00:00 2001 From: Esdras Renan Date: Wed, 12 Nov 2025 11:25:24 -0300 Subject: [PATCH] fix: improve RustDesk ACL automation --- apps/desktop/src-tauri/src/rustdesk.rs | 79 +++++++++++++++++--------- 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/apps/desktop/src-tauri/src/rustdesk.rs b/apps/desktop/src-tauri/src/rustdesk.rs index 322739b..bffa15b 100644 --- a/apps/desktop/src-tauri/src/rustdesk.rs +++ b/apps/desktop/src-tauri/src/rustdesk.rs @@ -266,6 +266,7 @@ fn write_config_files() -> Result { )); let service_profile = PathBuf::from(LOCAL_SERVICE_CONFIG).join("RustDesk2.toml"); + let _ = ensure_localservice_writable_preflight(); if let Err(error) = write_file(&service_profile, &config_contents) { log_event(&format!( "Falha ao gravar config no perfil do serviço: {error}" @@ -534,22 +535,18 @@ fn propagate_password_profile() -> io::Result { "Copiando {} para ProgramData/LocalService", src_path.display() )); - let contents = fs::read(&src_path)?; + + let mut propagated = false; for dest_root in [program_data_config_dir(), PathBuf::from(LOCAL_SERVICE_CONFIG)] { let target_path = dest_root.join("RustDesk.toml"); - 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)?; + copy_overwrite(&src_path, &target_path)?; log_event(&format!( "RustDesk.toml propagado para {}", target_path.display() )); + propagated = true; } - Ok(true) + Ok(propagated) } fn replicate_password_artifacts() -> io::Result<()> { @@ -575,10 +572,7 @@ 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)?; + copy_overwrite(&source_path, &target_path)?; log_event(&format!( "Artefato de senha {name} replicado para {}", target_path.display() @@ -638,22 +632,42 @@ exit $process.ExitCode fn fix_localservice_acl() -> Result<(), String> { let target = r"C:\\Windows\\ServiceProfiles\\LocalService\\AppData\\Roaming\\RustDesk\\config"; + let transcript = env::temp_dir().join("raven_acl_ps.log"); let script = format!( r#" -$ErrorActionPreference = 'Stop' -if (-not (Test-Path '{target}')) {{ New-Item -ItemType Directory -Force -Path '{target}' | Out-Null }} -$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) {{ $take = $LASTEXITCODE }} else {{ $take = 0 }} -icacls '{target}' /grant "${{admins}}":(OI)(CI)F "${{localSvc}}":(OI)(CI)F /T /C | Out-Null -$ica = $LASTEXITCODE -if (($take -eq 0) -and ($ica -in 0,1)) {{ exit 0 }} -if ($ica -ne 0) {{ exit $ica }} -exit $take -"# +$ErrorActionPreference='Stop' +Start-Transcript -Path '{log}' -Force +try {{ + if (-not (Test-Path '{target}')) {{ New-Item -ItemType Directory -Force -Path '{target}' | Out-Null }} + + & takeown /F '{target}' /R /D Y + $takeCode = $LASTEXITCODE + + & icacls '{target}' /grant '*S-1-5-32-544:(OI)(CI)F' '*S-1-5-19:(OI)(CI)F' /T /C /Q + $icaCode = $LASTEXITCODE + + if (($takeCode -eq 0) -and ($icaCode -in 0,1)) {{ exit 0 }} + if ($icaCode -ne 0) {{ exit $icaCode }} + exit $takeCode +}} catch {{ + Write-Host ("exception: " + ($_.Exception.Message)) + exit 1 +}} finally {{ + try {{ Stop-Transcript | Out-Null }} catch {{ }} +}} +"#, + target = target, + log = transcript.display() ); - run_powershell_elevated(&script) + + let result = run_powershell_elevated(&script); + if result.is_err() { + if let Ok(content) = fs::read_to_string(&transcript) { + log_event(&format!("ACL transcript:\n{content}")); + } + } + let _ = fs::remove_file(&transcript); + result } fn ensure_localservice_writable_preflight() -> Result<(), String> { @@ -821,6 +835,19 @@ fn hidden_command(program: impl AsRef) -> Command { cmd } +fn copy_overwrite(src: &Path, dst: &Path) -> io::Result<()> { + if let Some(parent) = dst.parent() { + fs::create_dir_all(parent)?; + } + if dst.is_dir() { + fs::remove_dir_all(dst)?; + } else if dst.exists() { + fs::remove_file(dst)?; + } + fs::copy(src, dst)?; + Ok(()) +} + fn log_event(message: impl AsRef) { if let Some(dir) = logs_directory() { if let Err(error) = append_log(dir, message.as_ref()) {