132 lines
5.5 KiB
Python
132 lines
5.5 KiB
Python
import importlib
|
|
import sys
|
|
import types
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import Mock, patch
|
|
|
|
from librenet_scanner.fastscan import parse_naabu_host_json_line
|
|
from librenet_scanner.models import Host
|
|
from librenet_scanner.privileged_helper import command_for
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
if "PySide6.QtCore" not in sys.modules:
|
|
qtcore = types.ModuleType("PySide6.QtCore")
|
|
pyside = types.ModuleType("PySide6")
|
|
|
|
class DummySignal:
|
|
def __init__(self, *args, **kwargs):
|
|
self.calls = []
|
|
def emit(self, *args):
|
|
self.calls.append(args)
|
|
|
|
class DummyQThread:
|
|
def __init__(self, parent=None):
|
|
self._interrupted = False
|
|
def requestInterruption(self):
|
|
self._interrupted = True
|
|
def isInterruptionRequested(self):
|
|
return self._interrupted
|
|
|
|
qtcore.Signal = DummySignal
|
|
qtcore.QThread = DummyQThread
|
|
pyside.QtCore = qtcore
|
|
sys.modules["PySide6"] = pyside
|
|
sys.modules["PySide6.QtCore"] = qtcore
|
|
|
|
scanner = importlib.import_module("librenet_scanner.scanner")
|
|
|
|
|
|
class NaabuDiscovery0421Tests(unittest.TestCase):
|
|
def test_host_discovery_json_without_port_becomes_live_host(self):
|
|
host = parse_naabu_host_json_line('{"ip":"192.168.50.20"}')
|
|
self.assertIsNotNone(host)
|
|
self.assertEqual(host.ip, "192.168.50.20")
|
|
self.assertEqual(host.status, "up")
|
|
self.assertEqual(host.ports, [])
|
|
|
|
def test_legacy_admin_host_discovery_helper_remains_hardened(self):
|
|
with patch("librenet_scanner.privileged_helper._trusted_binary", return_value="/usr/local/bin/naabu"):
|
|
cmd = command_for("naabu-discover", ["192.168.50.10", "192.168.50.11"])
|
|
self.assertIn("-sn", cmd)
|
|
self.assertEqual(cmd[cmd.index("-config") + 1], "/dev/null")
|
|
self.assertIn("-auth=false", cmd)
|
|
|
|
|
|
class StandardBehavior0421Tests(unittest.TestCase):
|
|
def _worker(self, *, privileged=False):
|
|
req = scanner.ScanRequest(
|
|
target="192.168.50.0/30", profile="Standard", interface=None, privileged=privileged
|
|
)
|
|
return scanner.ScanWorker(req)
|
|
|
|
def test_standard_scan_uses_adaptive_baseline(self):
|
|
worker = self._worker()
|
|
worker._standard_baseline = Mock(return_value=({"192.168.50.1"}, "nmap"))
|
|
worker._set_progress = Mock()
|
|
worker._standard_scan()
|
|
worker._standard_baseline.assert_called_once()
|
|
self.assertIn("Nmap TCP (adaptatif)", worker._set_progress.call_args.args[1])
|
|
|
|
def test_small_active_set_uses_nmap_and_never_starts_naabu(self):
|
|
worker = self._worker()
|
|
worker._standard_discovery = Mock(return_value={"192.168.50.1"})
|
|
worker._naabu_ports = Mock(side_effect=AssertionError("Naabu ne doit pas démarrer pour un petit LAN"))
|
|
worker._nmap_standard_ports = Mock(return_value=[])
|
|
worker._neighbor_hosts = Mock(return_value=[])
|
|
worker._set_progress = Mock()
|
|
result, engine = worker._standard_baseline(start_percent=4, end_percent=96)
|
|
self.assertEqual(result, {"192.168.50.1"})
|
|
self.assertEqual(engine, "nmap")
|
|
worker._naabu_ports.assert_not_called()
|
|
self.assertFalse(worker._nmap_standard_ports.call_args.kwargs["fallback"])
|
|
|
|
def test_naabu_failure_falls_back_only_on_large_discovered_set(self):
|
|
worker = self._worker()
|
|
live = {f"192.168.50.{i}" for i in range(1, scanner.NAABU_ACTIVE_HOST_THRESHOLD + 1)}
|
|
worker._standard_discovery = Mock(return_value=live)
|
|
worker._naabu_ports = Mock(return_value=None)
|
|
worker._nmap_standard_ports = Mock(return_value=[])
|
|
worker._neighbor_hosts = Mock(return_value=[])
|
|
worker._set_progress = Mock()
|
|
result, engine = worker._standard_baseline(start_percent=4, end_percent=96)
|
|
self.assertEqual(engine, "nmap-fallback")
|
|
self.assertEqual(result, live)
|
|
fallback_ips = worker._nmap_standard_ports.call_args.args[0]
|
|
self.assertEqual(fallback_ips, sorted(live, key=scanner.ipaddress.ip_address))
|
|
self.assertTrue(worker._nmap_standard_ports.call_args.kwargs["fallback"])
|
|
|
|
def test_deep_reuses_adaptive_baseline_before_enrichment(self):
|
|
req = scanner.ScanRequest(
|
|
target="192.168.50.0/30", profile="Approfondi", interface=None, privileged=False
|
|
)
|
|
worker = scanner.ScanWorker(req)
|
|
worker._set_progress = Mock()
|
|
worker._standard_baseline = Mock(return_value=({"192.168.50.1"}, "nmap"))
|
|
worker._nmap = Mock(return_value=[])
|
|
worker._neighbor_hosts = Mock(return_value=[])
|
|
worker.run()
|
|
worker._standard_baseline.assert_called_once()
|
|
worker._nmap.assert_called_once()
|
|
args = worker._nmap.call_args.args[0]
|
|
self.assertIn("-sV", args)
|
|
self.assertIn("1000", args)
|
|
|
|
|
|
class Diagnostics0421Tests(unittest.TestCase):
|
|
def test_ui_distinguishes_user_and_admin_naabu(self):
|
|
source = (ROOT / "src/librenet_scanner/ui.py").read_text(encoding="utf-8")
|
|
self.assertIn("Naabu utilisateur", source)
|
|
self.assertIn("Naabu Admin SYN", source)
|
|
self.assertIn("naabu_diagnostic()", source)
|
|
|
|
def test_profile_signatures_identify_current_pipeline(self):
|
|
source = (ROOT / "src/librenet_scanner/scanner.py").read_text(encoding="utf-8")
|
|
self.assertIn("standard-v9:adaptive-nmap-small-naabu-large", source)
|
|
self.assertIn("deep-v10:adaptive-standard-baseline-nmap-enrichment", source)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|