import os import sys import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'payload', 'user', 'remote_access', 'pager-webui')) import server def setUpModule(): __import__('importlib').reload(server) _orig_device_run = server.device_run _orig_assoc_clients = server.assoc_clients _orig_iface_ap_info = server._iface_ap_info _orig_pineap = server._pineap class NormalizeTest(unittest.TestCase): def test_normalize(self): self.assertEqual(server.normalize_mac(' 00:11:22:33:44:55 '), '00:11:22:33:44:55') self.assertEqual(server.normalize_mac('aa:bb:cc:dd:ee:ff'), 'AA:BB:CC:DD:EE:FF') def test_invalid_returns_none(self): self.assertIsNone(server.normalize_mac('nope')) class ClientsTest(unittest.TestCase): def tearDown(self): server.device_run = _orig_device_run server.assoc_clients = _orig_assoc_clients server._iface_ap_info = _orig_iface_ap_info server._pineap = _orig_pineap def test_clients_handler(self): server.assoc_clients = lambda: [{'mac': 'AA:BB:CC:DD:EE:FF', 'iface': 'wlan0open', 'rssi': -55}] class Ctx: args = () status, payload = server.h_clients(Ctx()) self.assertEqual(status, 200) self.assertEqual(payload['count'], 1) def _kick_env(self): calls = [] def fake_run(argv, timeout=30): calls.append(argv) return 0, '', '' server.device_run = fake_run server.assoc_clients = lambda: [{'mac': '00:11:22:33:44:55', 'iface': 'wlan0open', 'rssi': -55}] server._iface_ap_info = lambda iface: ('AA:BB:CC:DD:EE:FF', 6) server._pineap = lambda *a, **k: (0, '', '') return calls def test_kick_validates_and_deny_adds(self): calls = self._kick_env() server.h_client_kick(type('C', (), {'args': (), 'body': {'mac': '00:11:22:33:44:55'}})()) self.assertIn([server.HAK5CMD, 'PINEAPPLE_DEVICE_FILTER_ADD', 'deny', '00:11:22:33:44:55'], calls) # The immediate deauth must use the full bssid/target/channel form. self.assertTrue(any(c[:4] == [server.HAK5CMD, 'PINEAPPLE_DEAUTH_CLIENT', 'AA:BB:CC:DD:EE:FF', '00:11:22:33:44:55'] and c[4] == '6' for c in calls)) def test_kick_not_associated_still_filters(self): calls = [] def fake_run(argv, timeout=30): calls.append(argv) return 0, '', '' server.device_run = fake_run server.assoc_clients = lambda: [] status, payload = server.h_client_kick(type('C', (), {'args': (), 'body': {'mac': '00:11:22:33:44:55'}})()) self.assertEqual(status, 200) self.assertIs(payload['deauth'], False) self.assertTrue(any(c == [server.HAK5CMD, 'PINEAPPLE_DEVICE_FILTER_ADD', 'deny', '00:11:22:33:44:55'] for c in calls)) def test_kick_bad_mac_400(self): status, payload = server.h_client_kick(type('C', (), {'args': (), 'body': {'mac': 'x'}})()) self.assertEqual(status, 400) def test_deauth_client(self): calls = [] def fake_run(argv, timeout=30): calls.append(argv) return 0, '', '' server.device_run = fake_run server.assoc_clients = lambda: [{'mac': '00:11:22:33:44:55', 'iface': 'wlan1wpa', 'rssi': -60}] server._iface_ap_info = lambda iface: ('AA:BB:CC:DD:EE:FF', 149) status, payload = server.h_deauth_client(type('C', (), {'args': (), 'body': {'mac': '00:11:22:33:44:55'}})()) self.assertEqual(status, 200) # 5 GHz client -> wlan1mon inject, no _pineap pin needed. self.assertTrue(any(c[:4] == [server.HAK5CMD, 'PINEAPPLE_DEAUTH_CLIENT', 'AA:BB:CC:DD:EE:FF', '00:11:22:33:44:55'] and c[4] == '149' for c in calls)) def test_deauth_client_not_associated_502(self): server.assoc_clients = lambda: [] status, payload = server.h_deauth_client(type('C', (), {'args': (), 'body': {'mac': '00:11:22:33:44:55'}})()) self.assertEqual(status, 502) if __name__ == '__main__': unittest.main()