use std::path::PathBuf; use sanctum::crypto::{ derive_kek, generate_dek, generate_salt, wrap_dek, KdfParams, MIN_MEMORY_COST_KIB, MIN_TIME_COST, }; use sanctum::mount::is_loopback_host; use sanctum::storage::Database; #[test] fn test_is_loopback_host_comprehensive() { // Gültige IPv4 Loopback Varianten assert!(is_loopback_host("127.0.0.1")); assert!(is_loopback_host("127.0.0.1:80")); assert!(is_loopback_host("127.0.0.1:8080")); assert!(is_loopback_host("127.0.0.1:65535")); // Gültige Hostname Loopback Varianten assert!(is_loopback_host("localhost")); assert!(is_loopback_host("localhost:80")); assert!(is_loopback_host("localhost:8443")); assert!(is_loopback_host("LOCALHOST")); assert!(is_loopback_host("LocalHost:9000")); // Gültige IPv6 Loopback Varianten assert!(is_loopback_host("[::1]")); assert!(is_loopback_host("[::1]:80")); assert!(is_loopback_host("[::1]:8443")); assert!(is_loopback_host("::1")); // DNS-Rebinding & Spoofing Angriffe (MÜSSEN abgewiesen werden) assert!(!is_loopback_host("127.0.0.1.attacker.com")); assert!(!is_loopback_host("localhost.attacker.com")); assert!(!is_loopback_host("localhost.evil.org:8080")); assert!(!is_loopback_host("notlocalhost")); assert!(!is_loopback_host("attacker.com")); assert!(!is_loopback_host("attacker.com:127001")); assert!(!is_loopback_host("192.168.1.1")); assert!(!is_loopback_host("10.0.0.1")); assert!(!is_loopback_host("0.0.0.0")); assert!(!is_loopback_host("")); assert!(!is_loopback_host(" ")); assert!(!is_loopback_host("foo:bar:baz")); } #[test] fn test_wal_and_shm_cleanup_on_close() { let temp_dir = std::env::temp_dir(); let container_path: PathBuf = temp_dir.join(format!("test_wal_cleanup_{}.sanctum", std::process::id())); if container_path.exists() { let _ = std::fs::remove_file(&container_path); } let salt = generate_salt(); let kdf_params = KdfParams { memory_cost: MIN_MEMORY_COST_KIB, time_cost: MIN_TIME_COST, parallelism: 1, }; let kek = derive_kek("WalCleanupPassword2026!", &salt, &kdf_params).unwrap(); let dek = generate_dek(); let (wrapped_dek, nonce, tag) = wrap_dek(&kek, &dek).unwrap(); let db = Database::open(&container_path).unwrap(); db.init_schema(&salt, &kdf_params, &wrapped_dek, &nonce, &tag).unwrap(); // Erstelle Knoten, um Schreibaktivität im WAL zu erzeugen let _ = db.create_node(1, "test_file.txt", false).unwrap(); db.checkpoint().unwrap(); drop(db); // Bereinigungslogik (wie in mount.rs unmount) ausführen let base_os = container_path.as_os_str().to_os_string(); let mut wal = base_os.clone(); wal.push("-wal"); let _ = std::fs::remove_file(&wal); let mut shm = base_os; shm.push("-shm"); let _ = std::fs::remove_file(&shm); assert!(!PathBuf::from(wal).exists(), "WAL-Datei darf nach sauberem Unmount nicht zurückbleiben"); assert!(!PathBuf::from(shm).exists(), "SHM-Datei darf nach sauberem Unmount nicht zurückbleiben"); let _ = std::fs::remove_file(&container_path); }