feat(opsec): implement inactivity auto-lock, session lock detection, and anti-leak shield

This commit is contained in:
2026-09-08 10:14:31 +02:00
parent 38df3d3845
commit 2cb065c8c0
5 changed files with 727 additions and 7 deletions
+64 -3
View File
@@ -2,6 +2,8 @@ use std::convert::Infallible;
use std::net::SocketAddr;
use std::path::Path;
use std::process::Command;
use std::sync::atomic::Ordering;
use std::time::{SystemTime, UNIX_EPOCH};
use anyhow::{bail, Context, Result};
use dav_server::{fakels::FakeLs, DavHandler};
@@ -83,6 +85,9 @@ pub async fn mount_container(
auth: ContainerAuth,
open_explorer: bool,
enable_tray: bool,
idle_timeout: Option<u64>,
lock_on_screen_lock: bool,
anti_leak: bool,
) -> Result<()> {
let drive_str = format_drive(drive_letter);
@@ -127,8 +132,9 @@ pub async fn mount_container(
}
};
// WebDAV Filesystem und Handler konfigurieren
let fs = SanctumFs::new(db.clone(), dek, version);
// WebDAV Filesystem und Handler konfigurieren (mit Anti-Leak Shield)
let fs = SanctumFs::with_options(db.clone(), dek, version, anti_leak);
let last_activity = fs.last_activity();
let dav_server = DavHandler::builder()
.filesystem(Box::new(fs))
.locksystem(FakeLs::new())
@@ -248,6 +254,44 @@ pub async fn mount_container(
None
};
// Inaktivitäts-Timer (Auto-Lock)
let (idle_shutdown_tx, mut idle_shutdown_rx) = tokio::sync::mpsc::channel::<()>(1);
if let Some(timeout_secs) = idle_timeout {
if timeout_secs > 0 {
let last_act = last_activity.clone();
let idle_tx = idle_shutdown_tx.clone();
tokio::spawn(async move {
let mut interval = tokio::time::interval(std::time::Duration::from_secs(1));
loop {
interval.tick().await;
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0);
let last = last_act.load(Ordering::Relaxed);
if now.saturating_sub(last) >= timeout_secs {
let _ = idle_tx.send(()).await;
break;
}
}
});
}
}
// Windows-Sitzungssperre (Win + L Auto-Lock)
let (session_lock_tx, mut session_lock_rx) = tokio::sync::mpsc::channel::<()>(1);
let _session_monitor = if lock_on_screen_lock {
match crate::windows::start_session_lock_monitor(session_lock_tx) {
Ok(guard) => Some(guard),
Err(e) => {
warn!("Konnte Windows Session-Lock Monitor nicht aktivieren: {e}");
None
}
}
} else {
None
};
println!();
println!("┌─────────────────────────────────────────────────────────────┐");
println!("│ ✔ Sanctum Container erfolgreich gemountet │");
@@ -256,6 +300,15 @@ pub async fn mount_container(
println!(" • Container: {}", container_path.display());
println!(" • Netzlaufwerk: {} (im Windows Explorer bereit)", ui::cyan(&drive_str));
println!(" • WebDAV-URL: http://127.0.0.1:{}/", bound_port);
if let Some(secs) = idle_timeout {
println!(" • Auto-Lock: Inaktivität nach {}s", secs);
}
if lock_on_screen_lock {
println!(" • Sitzung: Automatisches Sperren bei Win + L aktiv");
}
if anti_leak {
println!(" • Anti-Leak: Explorer-Metadatenfilter aktiv (Thumbs.db, desktop.ini blockiert)");
}
if enable_tray {
println!(" • System-Tray: Icon aktiv (Rechtsklick für Explorer/Trennen)");
}
@@ -263,7 +316,7 @@ pub async fn mount_container(
println!(" [{}] Drücke [Ctrl+C] oder nutze das Tray-Icon zum Beenden.", ui::yellow("Tipp"));
println!();
// Warten auf Strg+C ODER Signal aus dem System-Tray
// Warten auf Beendigungssignal (Ctrl+C, Tray-Klick, Inaktivität, Win+L)
tokio::select! {
res = tokio::signal::ctrl_c() => {
let _ = res;
@@ -274,6 +327,14 @@ pub async fn mount_container(
println!();
println!(" {} Beendigungssignal aus System-Tray empfangen.", ui::yellow("[!]"));
}
_ = session_lock_rx.recv() => {
println!();
println!(" {} Windows-Sitzung gesperrt (Win + L) — Auto-Lock ausgelöst!", ui::yellow("[!]"));
}
_ = idle_shutdown_rx.recv() => {
println!();
println!(" {} Inaktivitäts-Timeout erreicht — Auto-Lock ausgelöst!", ui::yellow("[!]"));
}
}
print!(" {} Trenne Windows-Netzlaufwerk {} ... ", ui::dim("[-]"), drive_str);
let _ = std::io::Write::flush(&mut std::io::stdout());