Purge legacy RustDesk configs before provisioning
This commit is contained in:
parent
ddcff6768d
commit
daca17a93d
2 changed files with 148 additions and 2 deletions
|
|
@ -34,6 +34,14 @@ const ACL_FLAG_FILENAME: &str = "rustdesk_acl_unlocked.flag";
|
|||
const RUSTDESK_ACL_STORE_KEY: &str = "rustdeskAclUnlockedAt";
|
||||
const SECURITY_VERIFICATION_VALUE: &str = "use-permanent-password";
|
||||
const SECURITY_APPROVE_MODE_VALUE: &str = "password";
|
||||
const RUSTDESK_CONFIG_FILES: [&str; 6] = [
|
||||
"RustDesk.toml",
|
||||
"RustDesk_local.toml",
|
||||
"RustDesk2.toml",
|
||||
"password",
|
||||
"passwd",
|
||||
"passwd.txt",
|
||||
];
|
||||
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||
|
||||
static PROVISION_MUTEX: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
|
||||
|
|
@ -93,6 +101,13 @@ pub fn ensure_rustdesk(
|
|||
)),
|
||||
}
|
||||
|
||||
match purge_existing_rustdesk_profiles() {
|
||||
Ok(_) => log_event("Configurações antigas do RustDesk limpas antes da reaplicação"),
|
||||
Err(error) => log_event(&format!(
|
||||
"Aviso: não foi possível limpar completamente os perfis existentes do RustDesk ({error})"
|
||||
)),
|
||||
}
|
||||
|
||||
if let Some(value) = config_string.and_then(|raw| {
|
||||
let trimmed = raw.trim();
|
||||
if trimmed.is_empty() { None } else { Some(trimmed) }
|
||||
|
|
@ -137,7 +152,10 @@ pub fn ensure_rustdesk(
|
|||
}
|
||||
|
||||
match ensure_password_files(&password) {
|
||||
Ok(_) => log_event("Senha e flags de segurança gravadas em todos os perfis do RustDesk"),
|
||||
Ok(_) => {
|
||||
log_event("Senha e flags de segurança gravadas em todos os perfis do RustDesk");
|
||||
log_password_replication(&password);
|
||||
}
|
||||
Err(error) => log_event(&format!("Falha ao persistir senha nos perfis: {error}")),
|
||||
}
|
||||
|
||||
|
|
@ -707,6 +725,57 @@ fn replicate_password_artifacts() -> io::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn purge_existing_rustdesk_profiles() -> Result<(), String> {
|
||||
let mut errors = Vec::new();
|
||||
let mut cleaned_any = false;
|
||||
|
||||
for dir in remote_id_directories() {
|
||||
match purge_config_dir(&dir) {
|
||||
Ok(true) => {
|
||||
cleaned_any = true;
|
||||
log_event(&format!(
|
||||
"Perfis antigos removidos em {}",
|
||||
dir.display()
|
||||
));
|
||||
}
|
||||
Ok(false) => {}
|
||||
Err(error) => errors.push(format!("{} -> {error}", dir.display())),
|
||||
}
|
||||
}
|
||||
|
||||
if cleaned_any {
|
||||
Ok(())
|
||||
} else if errors.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(errors.join(" | "))
|
||||
}
|
||||
}
|
||||
|
||||
fn purge_config_dir(dir: &Path) -> Result<bool, io::Error> {
|
||||
if !dir.exists() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let mut removed = false;
|
||||
fs::create_dir_all(dir)?;
|
||||
|
||||
for name in RUSTDESK_CONFIG_FILES {
|
||||
let path = dir.join(name);
|
||||
if path.is_dir() {
|
||||
fs::remove_dir_all(&path)?;
|
||||
removed = true;
|
||||
continue;
|
||||
}
|
||||
if path.exists() {
|
||||
fs::remove_file(&path)?;
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(removed)
|
||||
}
|
||||
|
||||
fn run_powershell_elevated(script: &str) -> Result<(), String> {
|
||||
let temp_dir = env::temp_dir();
|
||||
let payload = temp_dir.join("raven_payload.ps1");
|
||||
|
|
@ -991,6 +1060,65 @@ fn run_with_args(exe_path: &Path, args: &[&str]) -> Result<(), RustdeskError> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn log_password_replication(secret: &str) {
|
||||
for dir in remote_id_directories() {
|
||||
let local_path = dir.join("RustDesk_local.toml");
|
||||
match read_password_from_file(&local_path) {
|
||||
Some(value) if value == secret => {
|
||||
log_event(&format!(
|
||||
"Senha confirmada em {} ({})",
|
||||
local_path.display(),
|
||||
mask_secret(&value)
|
||||
));
|
||||
}
|
||||
Some(value) => {
|
||||
log_event(&format!(
|
||||
"Aviso: senha divergente ({}) em {}",
|
||||
mask_secret(&value),
|
||||
local_path.display()
|
||||
));
|
||||
}
|
||||
None => {
|
||||
log_event(&format!(
|
||||
"Aviso: chave 'password' não encontrada em {}",
|
||||
local_path.display()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_password_from_file(path: &Path) -> Option<String> {
|
||||
let content = fs::read_to_string(path).ok()?;
|
||||
for line in content.lines() {
|
||||
if let Some(value) = parse_assignment(line, "password") {
|
||||
return Some(value);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn mask_secret(secret: &str) -> String {
|
||||
if secret.is_empty() {
|
||||
return "<vazio>".to_string();
|
||||
}
|
||||
let chars: Vec<char> = secret.chars().collect();
|
||||
if chars.len() <= 4 {
|
||||
return "*".repeat(chars.len());
|
||||
}
|
||||
let prefix: String = chars.iter().take(2).copied().collect();
|
||||
let suffix: String = chars
|
||||
.iter()
|
||||
.rev()
|
||||
.take(2)
|
||||
.copied()
|
||||
.collect::<Vec<char>>()
|
||||
.into_iter()
|
||||
.rev()
|
||||
.collect();
|
||||
format!("{}***{}", prefix, suffix)
|
||||
}
|
||||
|
||||
fn hidden_command(program: impl AsRef<OsStr>) -> Command {
|
||||
let mut cmd = Command::new(program);
|
||||
cmd.creation_flags(CREATE_NO_WINDOW);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue