feat: support LocalSystem RustDesk profile auto-fix
This commit is contained in:
parent
2339d5010f
commit
a535a6625b
1 changed files with 56 additions and 19 deletions
|
|
@ -26,6 +26,7 @@ const DEFAULT_PASSWORD: &str = "FMQ9MA>e73r.FI<b*34Vmx_8P";
|
||||||
const SERVICE_NAME: &str = "RustDesk";
|
const SERVICE_NAME: &str = "RustDesk";
|
||||||
const CACHE_DIR_NAME: &str = "Rever\\RustDeskCache";
|
const CACHE_DIR_NAME: &str = "Rever\\RustDeskCache";
|
||||||
const LOCAL_SERVICE_CONFIG: &str = r"C:\\Windows\\ServiceProfiles\\LocalService\\AppData\\Roaming\\RustDesk\\config";
|
const LOCAL_SERVICE_CONFIG: &str = r"C:\\Windows\\ServiceProfiles\\LocalService\\AppData\\Roaming\\RustDesk\\config";
|
||||||
|
const LOCAL_SYSTEM_CONFIG: &str = r"C:\\Windows\\System32\\config\\systemprofile\\AppData\\Roaming\\RustDesk\\config";
|
||||||
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||||
|
|
||||||
static PROVISION_MUTEX: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
|
static PROVISION_MUTEX: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
|
||||||
|
|
@ -64,9 +65,9 @@ pub fn ensure_rustdesk(
|
||||||
let _guard = PROVISION_MUTEX.lock();
|
let _guard = PROVISION_MUTEX.lock();
|
||||||
log_event("Iniciando preparo do RustDesk");
|
log_event("Iniciando preparo do RustDesk");
|
||||||
|
|
||||||
if let Err(error) = ensure_localservice_writable_preflight() {
|
if let Err(error) = ensure_service_profiles_writable_preflight() {
|
||||||
log_event(&format!(
|
log_event(&format!(
|
||||||
"Aviso: não foi possível preparar ACL do LocalService ({error}). Continuando mesmo assim; o serviço pode não aplicar a senha."
|
"Aviso: não foi possível preparar ACL dos perfis do serviço ({error}). Continuando mesmo assim; o serviço pode não aplicar a senha."
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -381,8 +382,8 @@ fn ensure_service_running() -> Result<(), RustdeskError> {
|
||||||
match start_sequence() {
|
match start_sequence() {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(RustdeskError::CommandFailed { command: _, status: Some(5), .. }) => {
|
Err(RustdeskError::CommandFailed { command: _, status: Some(5), .. }) => {
|
||||||
log_event("SC retornou acesso negado; tentando ajustar ACL do LocalService...");
|
log_event("SC retornou acesso negado; tentando ajustar ACL dos perfis do serviço...");
|
||||||
fix_localservice_acl().map_err(|error| RustdeskError::CommandFailed {
|
ensure_service_profiles_writable_preflight().map_err(|error| RustdeskError::CommandFailed {
|
||||||
command: format!("fix_acl ({error})"),
|
command: format!("fix_acl ({error})"),
|
||||||
status: Some(5),
|
status: Some(5),
|
||||||
})?;
|
})?;
|
||||||
|
|
@ -476,13 +477,22 @@ fn ensure_remote_id_files(id: &str) {
|
||||||
fn remote_id_directories() -> Vec<PathBuf> {
|
fn remote_id_directories() -> Vec<PathBuf> {
|
||||||
let mut dirs = Vec::new();
|
let mut dirs = Vec::new();
|
||||||
dirs.push(program_data_config_dir());
|
dirs.push(program_data_config_dir());
|
||||||
dirs.push(PathBuf::from(LOCAL_SERVICE_CONFIG));
|
for profile in service_profile_dirs() {
|
||||||
|
dirs.push(profile);
|
||||||
|
}
|
||||||
if let Some(appdir) = user_appdata_config_dir() {
|
if let Some(appdir) = user_appdata_config_dir() {
|
||||||
dirs.push(appdir);
|
dirs.push(appdir);
|
||||||
}
|
}
|
||||||
dirs
|
dirs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn service_profile_dirs() -> Vec<PathBuf> {
|
||||||
|
vec![
|
||||||
|
PathBuf::from(LOCAL_SERVICE_CONFIG),
|
||||||
|
PathBuf::from(LOCAL_SYSTEM_CONFIG),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
fn ensure_password_files(secret: &str) -> Result<(), String> {
|
fn ensure_password_files(secret: &str) -> Result<(), String> {
|
||||||
let mut errors = Vec::new();
|
let mut errors = Vec::new();
|
||||||
|
|
||||||
|
|
@ -630,9 +640,10 @@ exit $process.ExitCode
|
||||||
Err(format!("elevated ps exit {:?}", status.code()))
|
Err(format!("elevated ps exit {:?}", status.code()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fix_localservice_acl() -> Result<(), String> {
|
fn fix_profile_acl(target: &Path) -> Result<(), String> {
|
||||||
let target = r"C:\\Windows\\ServiceProfiles\\LocalService\\AppData\\Roaming\\RustDesk\\config";
|
let target_str = target.display().to_string().replace('\', "\\");
|
||||||
let transcript = env::temp_dir().join("raven_acl_ps.log");
|
let transcript = env::temp_dir().join("raven_acl_ps.log");
|
||||||
|
let log_str = transcript.display().to_string().replace('\', "\\");
|
||||||
let script = format!(
|
let script = format!(
|
||||||
r#"
|
r#"
|
||||||
$ErrorActionPreference='Stop'
|
$ErrorActionPreference='Stop'
|
||||||
|
|
@ -656,32 +667,58 @@ try {{
|
||||||
try {{ Stop-Transcript | Out-Null }} catch {{ }}
|
try {{ Stop-Transcript | Out-Null }} catch {{ }}
|
||||||
}}
|
}}
|
||||||
"#,
|
"#,
|
||||||
target = target,
|
target = target_str,
|
||||||
log = transcript.display()
|
log = log_str
|
||||||
);
|
);
|
||||||
|
|
||||||
let result = run_powershell_elevated(&script);
|
let result = run_powershell_elevated(&script);
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
if let Ok(content) = fs::read_to_string(&transcript) {
|
if let Ok(content) = fs::read_to_string(&transcript) {
|
||||||
log_event(&format!("ACL transcript:\n{content}"));
|
log_event(&format!(
|
||||||
|
"ACL transcript para {}:\n{}",
|
||||||
|
target.display(), content
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let _ = fs::remove_file(&transcript);
|
let _ = fs::remove_file(&transcript);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_localservice_writable_preflight() -> Result<(), String> {
|
fn ensure_service_profiles_writable_preflight() -> Result<(), String> {
|
||||||
let dir = PathBuf::from(LOCAL_SERVICE_CONFIG);
|
let mut success = false;
|
||||||
|
let mut last_error: Option<String> = None;
|
||||||
|
|
||||||
|
for dir in service_profile_dirs() {
|
||||||
if can_write_dir(&dir) {
|
if can_write_dir(&dir) {
|
||||||
return Ok(());
|
success = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
log_event(&format!(
|
||||||
|
"Tentando corrigir ACL via UAC (preflight) em {}...",
|
||||||
|
dir.display()
|
||||||
|
));
|
||||||
|
if let Err(error) = fix_profile_acl(&dir) {
|
||||||
|
last_error = Some(error);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
log_event("Tentando corrigir ACL do perfil LocalService via UAC (preflight)...");
|
|
||||||
fix_localservice_acl()?;
|
|
||||||
if can_write_dir(&dir) {
|
if can_write_dir(&dir) {
|
||||||
log_event("ACL do LocalService ajustada com sucesso.");
|
log_event(&format!(
|
||||||
|
"ACL ajustada com sucesso em {}",
|
||||||
|
dir.display()
|
||||||
|
));
|
||||||
|
success = true;
|
||||||
|
} else {
|
||||||
|
last_error = Some(format!(
|
||||||
|
"continua sem permissão para {} mesmo após preflight",
|
||||||
|
dir.display()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if success {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err("continua sem permissão para LocalService (após preflight)".into())
|
Err(last_error.unwrap_or_else(|| "nenhum perfil de serviço acessível".into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue