lanscape 1.2.9a1__tar.gz → 1.2.9a3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of lanscape might be problematic. Click here for more details.

Files changed (76) hide show
  1. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/MANIFEST.in +1 -0
  2. {lanscape-1.2.9a1/src/lanscape.egg-info → lanscape-1.2.9a3}/PKG-INFO +2 -2
  3. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/pyproject.toml +1 -1
  4. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/libraries/app_scope.py +12 -1
  5. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/libraries/ip_parser.py +1 -1
  6. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/libraries/mac_lookup.py +1 -2
  7. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/libraries/net_tools.py +9 -1
  8. lanscape-1.2.9a3/src/lanscape/libraries/service_scan.py +51 -0
  9. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/libraries/subnet_scan.py +47 -13
  10. lanscape-1.2.9a3/src/lanscape/resources/services/definitions.jsonc +456 -0
  11. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/blueprints/api/scan.py +2 -0
  12. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/js/main.js +5 -1
  13. {lanscape-1.2.9a1 → lanscape-1.2.9a3/src/lanscape.egg-info}/PKG-INFO +2 -2
  14. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape.egg-info/SOURCES.txt +2 -0
  15. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/LICENSE +0 -0
  16. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/README.md +0 -0
  17. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/setup.cfg +0 -0
  18. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/__init__.py +0 -0
  19. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/__main__.py +0 -0
  20. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/libraries/decorators.py +0 -0
  21. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/libraries/errors.py +0 -0
  22. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/libraries/logger.py +0 -0
  23. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/libraries/port_manager.py +0 -0
  24. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/libraries/runtime_args.py +0 -0
  25. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/libraries/version_manager.py +0 -0
  26. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/resources/mac_addresses/convert_csv.py +0 -0
  27. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/resources/mac_addresses/mac_db.json +0 -0
  28. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/resources/ports/convert_csv.py +0 -0
  29. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/resources/ports/full.json +0 -0
  30. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/resources/ports/large.json +0 -0
  31. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/resources/ports/medium.json +0 -0
  32. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/resources/ports/small.json +0 -0
  33. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/tests/__init__.py +0 -0
  34. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/tests/_helpers.py +0 -0
  35. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/tests/test_api.py +0 -0
  36. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/tests/test_env.py +0 -0
  37. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/tests/test_library.py +0 -0
  38. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/app.py +0 -0
  39. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/blueprints/__init__.py +0 -0
  40. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/blueprints/api/__init__.py +0 -0
  41. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/blueprints/api/port.py +0 -0
  42. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/blueprints/api/tools.py +0 -0
  43. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/blueprints/web/__init__.py +0 -0
  44. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/blueprints/web/routes.py +0 -0
  45. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/main.py +0 -0
  46. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/css/style.css +0 -0
  47. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/img/ico/android-chrome-192x192.png +0 -0
  48. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/img/ico/android-chrome-512x512.png +0 -0
  49. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/img/ico/apple-touch-icon.png +0 -0
  50. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/img/ico/favicon-16x16.png +0 -0
  51. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/img/ico/favicon-32x32.png +0 -0
  52. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/img/ico/favicon.ico +0 -0
  53. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/img/ico/site.webmanifest +0 -0
  54. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/js/core.js +0 -0
  55. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/js/layout-sizing.js +0 -0
  56. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/js/quietReload.js +0 -0
  57. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/js/shutdown-server.js +0 -0
  58. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/js/subnet-info.js +0 -0
  59. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/js/subnet-selector.js +0 -0
  60. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/static/lanscape.webmanifest +0 -0
  61. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/base.html +0 -0
  62. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/core/head.html +0 -0
  63. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/core/scripts.html +0 -0
  64. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/error.html +0 -0
  65. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/info.html +0 -0
  66. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/main.html +0 -0
  67. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/scan/export.html +0 -0
  68. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/scan/ip-table-row.html +0 -0
  69. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/scan/ip-table.html +0 -0
  70. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/scan/overview.html +0 -0
  71. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/scan/scan-error.html +0 -0
  72. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/scan.html +0 -0
  73. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape/ui/templates/shutdown.html +0 -0
  74. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape.egg-info/dependency_links.txt +0 -0
  75. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape.egg-info/requires.txt +0 -0
  76. {lanscape-1.2.9a1 → lanscape-1.2.9a3}/src/lanscape.egg-info/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
1
  recursive-include src/lanscape/resources *.json
2
+ recursive-include src/lanscape/resources *.jsonc
2
3
  recursive-include src/lanscape/ui/templates *.html
3
4
  recursive-include src/lanscape/ui/static *
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: lanscape
3
- Version: 1.2.9a1
3
+ Version: 1.2.9a3
4
4
  Summary: A python based local network scanner
5
5
  Author-email: Michael Dennis <michael@dipduo.com>
6
6
  Project-URL: Homepage, https://github.com/mdennis281/py-lanscape
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lanscape"
3
- version = "1.2.9a1"
3
+ version = "1.2.9a3"
4
4
  authors = [
5
5
  { name="Michael Dennis", email="michael@dipduo.com" },
6
6
  ]
@@ -1,6 +1,7 @@
1
1
  from pathlib import Path
2
- import importlib.util
2
+ import json
3
3
  import sys
4
+ import re
4
5
 
5
6
  class ResourceManager:
6
7
  """
@@ -17,6 +18,16 @@ class ResourceManager:
17
18
  with open(self.asset_dir / asset_name, 'r') as f:
18
19
  return f.read()
19
20
 
21
+ def get_json(self, asset_name: str):
22
+ return json.loads(self.get(asset_name))
23
+
24
+ def get_jsonc(self, asset_name: str):
25
+ " Get JSON content with comments removed "
26
+ content = self.get(asset_name)
27
+ cleaned_content = re.sub(r'//.*', '', content)
28
+ return json.loads(cleaned_content)
29
+
30
+
20
31
  def update(self, asset_name: str, content: str):
21
32
  with open(self.asset_dir / asset_name, 'w') as f:
22
33
  f.write(content)
@@ -28,7 +28,7 @@ def parse_ip_input(ip_input):
28
28
 
29
29
  # If no CIDR or range, assume a single IP
30
30
  else:
31
- ip_ranges.append(ipaddress.IPv4Address(entry,strict=False))
31
+ ip_ranges.append(ipaddress.IPv4Address(entry))
32
32
  if len(ip_ranges) > MAX_IPS_ALLOWED:
33
33
  raise SubnetTooLargeError(ip_input)
34
34
  return ip_ranges
@@ -1,5 +1,4 @@
1
1
  import re
2
- import json
3
2
  import logging
4
3
  import platform
5
4
  import subprocess
@@ -7,7 +6,7 @@ from typing import List
7
6
 
8
7
  from .app_scope import ResourceManager
9
8
 
10
- DB = json.loads(ResourceManager('mac_addresses').get('mac_db.json'))
9
+ DB = ResourceManager('mac_addresses').get_json('mac_db.json')
11
10
 
12
11
  log = logging.getLogger('MacLookup')
13
12
 
@@ -8,9 +8,10 @@ import ipaddress
8
8
  import traceback
9
9
  import subprocess
10
10
  from time import sleep
11
- from typing import List
11
+ from typing import List, Dict
12
12
  from scapy.all import ARP, Ether, srp
13
13
 
14
+ from .service_scan import scan_service
14
15
  from .mac_lookup import lookup_mac, get_macs
15
16
  from .ip_parser import get_address_count, MAX_IPS_ALLOWED
16
17
 
@@ -73,6 +74,7 @@ class Device(IPAlive):
73
74
  self.manufacturer: str = None
74
75
  self.ports: List[int] = []
75
76
  self.stage: str = 'found'
77
+ self.services: Dict[str,List[int]] = {}
76
78
  self.log = logging.getLogger('Device')
77
79
 
78
80
  def get_metadata(self):
@@ -100,6 +102,12 @@ class Device(IPAlive):
100
102
  return True
101
103
  return False
102
104
 
105
+ def scan_service(self,port:int):
106
+ service = scan_service(self.ip,port)
107
+ service_ports = self.services.get(service,[])
108
+ service_ports.append(port)
109
+ self.services[service] = service_ports
110
+
103
111
  def get_mac(self):
104
112
  if not self.macs:
105
113
  self.macs = self._get_mac_addresses()
@@ -0,0 +1,51 @@
1
+ import asyncio
2
+ import logging
3
+ import traceback
4
+ from .app_scope import ResourceManager
5
+
6
+ log = logging.getLogger('ServiceScan')
7
+ SERVICES = ResourceManager('services').get_jsonc('definitions.jsonc')
8
+
9
+ # skip printer ports because they cause blank pages to be printed
10
+ PRINTER_PORTS = [9100, 631]
11
+
12
+ def scan_service(ip: str, port: int, timeout=10) -> str:
13
+ """
14
+ Synchronous function that attempts to identify the service running on a given port.
15
+ """
16
+
17
+ async def _async_scan_service(ip: str, port: int, timeout) -> str:
18
+ if port in PRINTER_PORTS:
19
+ return "Printer"
20
+
21
+ try:
22
+ # Add a timeout to prevent hanging
23
+ reader, writer = await asyncio.wait_for(asyncio.open_connection(ip, port), timeout=5)
24
+
25
+ # Send a probe appropriate for common services
26
+ probe = "GET / HTTP/1.1\r\nHost: {}\r\n\r\n".format(ip).encode("utf-8")
27
+ writer.write(probe)
28
+ await writer.drain()
29
+
30
+ # Receive the response with a timeout
31
+ response = await asyncio.wait_for(reader.read(1024), timeout=timeout)
32
+ writer.close()
33
+ await writer.wait_closed()
34
+
35
+ # Analyze the response to identify the service
36
+ response_str = response.decode("utf-8", errors="ignore")
37
+ for service, hints in SERVICES.items():
38
+ if any(hint.lower() in response_str.lower() for hint in hints):
39
+ return service
40
+ except asyncio.TimeoutError:
41
+ log.warning(f"Timeout scanning {ip}:{port}")
42
+ except Exception as e:
43
+ log.error(f"Error scanning {ip}:{port}: {str(e)}")
44
+ log.debug(traceback.format_exc())
45
+ return "Unknown"
46
+
47
+ # Use asyncio.run to execute the asynchronous logic synchronously
48
+ return asyncio.run(_async_scan_service(ip, port,timeout=timeout))
49
+
50
+
51
+
@@ -32,8 +32,31 @@ class ScanConfig:
32
32
  t_cnt_port_test: int = 128
33
33
  t_cnt_isalive: int = 256
34
34
 
35
+ task_scan_ports: bool = True
36
+ # below wont run if above false
37
+ task_scan_port_services: bool = False # disabling until more stable
38
+
35
39
  def t_cnt(self, id: str) -> int:
36
40
  return int(int(getattr(self, f't_cnt_{id}')) * float(self.t_multiplier))
41
+
42
+ @staticmethod
43
+ def from_dict(data: dict) -> 'ScanConfig':
44
+ return ScanConfig(
45
+ subnet = data['subnet'],
46
+ port_list = data['port_list'],
47
+ t_multiplier = data.get('parallelism',1.0),
48
+ t_cnt_port_scan = data.get('t_cnt_port_scan',10),
49
+ t_cnt_port_test = data.get('t_cnt_port_test',128),
50
+ t_cnt_isalive = data.get('t_cnt_isalive',256),
51
+ task_scan_ports = data.get('task_scan_ports',True),
52
+ task_scan_port_services = data.get('task_scan_port_services',True)
53
+ )
54
+
55
+ def get_ports(self) -> List[int]:
56
+ return PortManager().get_port_list(self.port_list).keys()
57
+
58
+ def parse_subnet(self) -> List[ipaddress.IPv4Network]:
59
+ return parse_ip_input(self.subnet)
37
60
 
38
61
 
39
62
 
@@ -43,13 +66,13 @@ class SubnetScanner:
43
66
  self,
44
67
  config: ScanConfig
45
68
  ):
46
- self.subnet = parse_ip_input(config.subnet)
47
- self.port_list = config.port_list
48
- self.ports: list = PortManager().get_port_list(config.port_list).keys()
69
+ self.cfg = config
70
+ self.subnet = config.parse_subnet()
71
+ self.ports: List[int] = config.get_ports()
49
72
  self.running = False
50
73
  self.subnet_str = config.subnet
51
74
 
52
- self.cfg = config
75
+
53
76
  self.job_stats = JobStats()
54
77
  self.uid = str(uuid.uuid4())
55
78
  self.results = ScannerResults(self)
@@ -81,7 +104,8 @@ class SubnetScanner:
81
104
 
82
105
 
83
106
  self._set_stage('testing ports')
84
- self._scan_network_ports()
107
+ if self.cfg.task_scan_ports:
108
+ self._scan_network_ports()
85
109
  self.running = False
86
110
  self._set_stage('complete')
87
111
 
@@ -134,17 +158,23 @@ class SubnetScanner:
134
158
 
135
159
 
136
160
 
137
- def debug_active_scan(self):
161
+ def debug_active_scan(self,sleep_sec=1):
138
162
  """
139
163
  Run this after running scan_subnet_threaded
140
164
  to see the progress of the scan
141
165
  """
142
166
  while self.running:
167
+ percent = self.calc_percent_complete()
168
+ t_elapsed = time() - self.results.start_time
169
+ t_remain = int((100-percent) * (t_elapsed / percent)) if percent else '∞'
170
+ buffer = f'{self.uid} - {self.subnet_str}\n'
171
+ buffer += f'Elapsed: {int(t_elapsed)} sec - Remain: {t_remain} sec\n'
172
+ buffer += f'Scanned: {self.results.devices_scanned}/{self.results.devices_total}'
173
+ buffer += f' - {percent}%\n'
174
+ buffer += str(self.job_stats)
143
175
  os.system('cls' if os.name == 'nt' else 'clear')
144
- print(f'{self.uid} - {self.subnet_str}')
145
- print(f"Scanned: {self.results.devices_scanned}/{self.results.devices_total} - {self.calc_percent_complete()}%")
146
- print(self.job_stats)
147
- sleep(1)
176
+ print(buffer)
177
+ sleep(sleep_sec)
148
178
 
149
179
  @terminator
150
180
  @job_tracker
@@ -187,9 +217,13 @@ class SubnetScanner:
187
217
  def _test_port(self,host: Device, port: int):
188
218
  """
189
219
  Test if a port is open on a given host.
220
+ If port open, determine service.
190
221
  Device class handles tracking open ports.
191
222
  """
192
- return host.test_port(port)
223
+ is_alive = host.test_port(port)
224
+ if is_alive and self.cfg.task_scan_port_services:
225
+ host.scan_service(port)
226
+ return is_alive
193
227
 
194
228
 
195
229
  @terminator
@@ -209,7 +243,7 @@ class SubnetScanner:
209
243
  class ScannerResults:
210
244
  def __init__(self,scan: SubnetScanner):
211
245
  self.scan = scan
212
- self.port_list: str = scan.port_list
246
+ self.port_list: str = scan.cfg.port_list
213
247
  self.subnet: str = scan.subnet_str
214
248
  self.uid = scan.uid
215
249
 
@@ -263,7 +297,7 @@ class ScannerResults:
263
297
  def __str__(self):
264
298
  # Prepare data for tabulate
265
299
  data = [
266
- [device.ip, device.hostname, device.mac_addr, ", ".join(map(str, device.ports))]
300
+ [device.ip, device.hostname, device.get_mac(), ", ".join(map(str, device.ports))]
267
301
  for device in self.devices
268
302
  ]
269
303
 
@@ -0,0 +1,456 @@
1
+ {
2
+ // ----------------------- Web Services -----------------------
3
+ "HTTP": [
4
+ "HTTP",
5
+ "Apache",
6
+ "Nginx",
7
+ "IIS",
8
+ "lighttpd",
9
+ "Caddy",
10
+ "OpenResty",
11
+ "GWS", // Google Web Server
12
+ "LiteSpeed",
13
+ "Gunicorn", // Often in X-Powered-By
14
+ "OpenLiteSpeed",
15
+ "Cloudflare"
16
+ ],
17
+ "HTTPS": [
18
+ "HTTPS",
19
+ "SSL",
20
+ "TLS"
21
+ // Possibly you'd see "443" in a banner or SNI reference,
22
+ // but typically "SSL" or "TLS" coverage is sufficient
23
+ ],
24
+
25
+ // ------------------ Remote Shell / Admin --------------------
26
+ "SSH": [
27
+ "SSH",
28
+ "OpenSSH",
29
+ "Dropbear",
30
+ "libssh"
31
+ ],
32
+ "Telnet": [
33
+ "Telnet",
34
+ "BusyBox on telnetd"
35
+ ],
36
+
37
+ // ------------------ File Transfer Protocols -----------------
38
+ "FTP": [
39
+ "FTP",
40
+ "FileZilla",
41
+ "ProFTPD",
42
+ "vsftpd",
43
+ "Pure-FTPd",
44
+ "WS_FTP",
45
+ "Microsoft ftpd"
46
+ ],
47
+ "SFTP": [
48
+ "SFTP"
49
+ // SFTP typically is an SSH subsystem, so you'd often see an SSH banner anyway
50
+ ],
51
+ "TFTP": [
52
+ "TFTP"
53
+ ],
54
+
55
+ // -------------------- Email / Messaging ----------------------
56
+ "SMTP": [
57
+ "SMTP",
58
+ "Postfix",
59
+ "Exim",
60
+ "Sendmail",
61
+ "Qmail",
62
+ "Exchange"
63
+ ],
64
+ "SMTPS": [
65
+ "SMTPS",
66
+ "465 secure",
67
+ "587 secure"
68
+ // Some servers might mention "TLS wrapper" or similar
69
+ ],
70
+ "POP3": [
71
+ "POP3",
72
+ "Dovecot",
73
+ "Courier",
74
+ "POP3 (Internet Mail)"
75
+ ],
76
+ "POP3S": [
77
+ "POP3S",
78
+ "SSL POP3",
79
+ "Dovecot",
80
+ "Courier"
81
+ ],
82
+ "IMAP": [
83
+ "IMAP",
84
+ "Dovecot",
85
+ "Courier",
86
+ "Cyrus",
87
+ "IMAP4"
88
+ ],
89
+ "IMAPS": [
90
+ "IMAPS",
91
+ "SSL IMAP",
92
+ "Dovecot",
93
+ "Courier",
94
+ "Cyrus"
95
+ ],
96
+
97
+ // ---------------- Domain / Directory Services ---------------
98
+ "DNS": [
99
+ "DNS",
100
+ "Bind",
101
+ "DNSMasq",
102
+ "PowerDNS",
103
+ "Unbound",
104
+ "Microsoft DNS",
105
+ "Knot DNS"
106
+ ],
107
+ "LDAP": [
108
+ "LDAP"
109
+ ],
110
+ "Active Directory": [
111
+ "Active Directory",
112
+ "Kerberos",
113
+ "MSAD",
114
+ "LDAP for AD",
115
+ "LDAP Service (AD)"
116
+ ],
117
+
118
+ // -------------------- Database Services ----------------------
119
+ "MySQL": [
120
+ "MySQL",
121
+ "MariaDB",
122
+ "Percona"
123
+ ],
124
+ "PostgreSQL": [
125
+ "PostgreSQL",
126
+ "Postgres"
127
+ ],
128
+ "Microsoft SQL Server": [
129
+ "MSSQL",
130
+ "Microsoft SQL Server",
131
+ "TDS",
132
+ "SQL Server",
133
+ "MS-SQL"
134
+ ],
135
+ "Oracle Database": [
136
+ "Oracle",
137
+ "TNS",
138
+ "Oracle Net"
139
+ ],
140
+ "MongoDB": [
141
+ "MongoDB"
142
+ ],
143
+ "Redis": [
144
+ "Redis"
145
+ ],
146
+ "Cassandra": [
147
+ "Cassandra"
148
+ ],
149
+ "Memcached": [
150
+ "Memcached"
151
+ ],
152
+
153
+ // ----------------- Caching / Indexing / Logging -------------
154
+ "Elasticsearch": [
155
+ "Elasticsearch"
156
+ ],
157
+ "Logstash": [
158
+ "Logstash"
159
+ ],
160
+
161
+ // --------------- Message Brokers & Streaming ----------------
162
+ "Kafka": [
163
+ "Kafka"
164
+ ],
165
+ "RabbitMQ": [
166
+ "RabbitMQ",
167
+ "AMQP"
168
+ ],
169
+ "ActiveMQ": [
170
+ "ActiveMQ"
171
+ ],
172
+ "Mosquitto": [
173
+ "Mosquitto",
174
+ "MQTT"
175
+ ],
176
+
177
+ // -------------------- Microsoft Services ---------------------
178
+ "RDP": [
179
+ "RDP",
180
+ "Terminal Services",
181
+ "Remote Desktop",
182
+ "MSTerminal"
183
+ ],
184
+ "SMB": [
185
+ "SMB",
186
+ "NetBIOS",
187
+ "Samba"
188
+ ],
189
+ "WMI": [
190
+ "WMI"
191
+ ],
192
+ "WinRM": [
193
+ "WinRM"
194
+ ],
195
+
196
+ // ---------------- Collaboration / Chat -----------------------
197
+ "IRC": [
198
+ "IRC"
199
+ ],
200
+ "XMPP": [
201
+ "XMPP",
202
+ "Jabber"
203
+ ],
204
+ "Matrix": [
205
+ "Matrix"
206
+ ],
207
+
208
+ // ------------- Virtualization / Container Services ----------
209
+ "Docker API": [
210
+ "Docker"
211
+ ],
212
+ "Kubernetes API": [
213
+ "Kubernetes",
214
+ "K8s",
215
+ "kube-apiserver"
216
+ ],
217
+ "VMware ESXi": [
218
+ "VMware ESXi",
219
+ "ESX"
220
+ ],
221
+ "Proxmox": [
222
+ "Proxmox"
223
+ ],
224
+
225
+ // ----------------- Remote Desktop / Control -----------------
226
+ "VNC": [
227
+ "VNC",
228
+ "RFB"
229
+ ],
230
+ "TeamViewer": [
231
+ "TeamViewer"
232
+ ],
233
+ "AnyDesk": [
234
+ "AnyDesk"
235
+ ],
236
+
237
+ // --------------------- Voice over IP ------------------------
238
+ "SIP": [
239
+ "SIP",
240
+ "Asterisk",
241
+ "FreeSWITCH"
242
+ ],
243
+ "H.323": [
244
+ "H.323"
245
+ ],
246
+
247
+ // ----------- Time, Network Config, and Infrastructure -------
248
+ "NTP": [
249
+ "NTP"
250
+ ],
251
+ "DHCP": [
252
+ "DHCP"
253
+ ],
254
+
255
+ // ------------------ VPN / Tunneling / Security --------------
256
+ "OpenVPN": [
257
+ "OpenVPN"
258
+ ],
259
+ "IPSec": [
260
+ "IPSec",
261
+ "IKE"
262
+ ],
263
+ "WireGuard": [
264
+ "WireGuard"
265
+ ],
266
+
267
+ // ---------------------- Other Protocols ----------------------
268
+ "SNMP": [
269
+ "SNMP"
270
+ ],
271
+ "SNMP Trap": [
272
+ "Trap",
273
+ "SNMPTRAP"
274
+ ],
275
+ "Syslog": [
276
+ "Syslog"
277
+ ],
278
+
279
+ // -------------------- Cloud Services / APIs -----------------
280
+ "AWS S3": [
281
+ "AmazonS3",
282
+ "S3"
283
+ ],
284
+ "AWS RDS": [
285
+ "AWS RDS",
286
+ "amazon-rds"
287
+ ],
288
+ "Azure DevOps": [
289
+ "Azure DevOps",
290
+ "VSTS"
291
+ ],
292
+ "GCP Services": [
293
+ "GCP",
294
+ "googleapis.com"
295
+ ],
296
+
297
+ // -------------------- Repo / Code Hosting --------------------
298
+ "Git": [
299
+ "git-daemon"
300
+ ],
301
+ "SVN": [
302
+ "SVN",
303
+ "Subversion"
304
+ ],
305
+
306
+ // -------------- HPC / Cluster Management / HPC --------------
307
+ "Slurm": [
308
+ "Slurm"
309
+ ],
310
+
311
+ // --------------------- Misc / Exotic ------------------------
312
+ "Tor": [
313
+ "Tor",
314
+ "obfs"
315
+ ],
316
+ "ZeroTier": [
317
+ "ZeroTier"
318
+ ],
319
+ "Mumble": [
320
+ "Mumble",
321
+ "Murmur"
322
+ ],
323
+ "Spice": [
324
+ "SPICE protocol"
325
+ ],
326
+ "FusionDirectory": [
327
+ "FusionDirectory"
328
+ ],
329
+ "Jenkins": [
330
+ "Jenkins"
331
+ ],
332
+ "GitLab": [
333
+ "GitLab"
334
+ ],
335
+ "GitHub": [
336
+ "GitHub",
337
+ "github.com"
338
+ ],
339
+ "Bitbucket": [
340
+ "Bitbucket"
341
+ ],
342
+
343
+ // ------------------ Legacy or Older Protocols ---------------
344
+ "Gopher": [
345
+ "Gopher"
346
+ ],
347
+ "Finger": [
348
+ "Finger"
349
+ ],
350
+ "Ident": [
351
+ "Ident"
352
+ ],
353
+ "Rlogin": [
354
+ "rlogin"
355
+ ],
356
+ "Rsync": [
357
+ "rsync"
358
+ ],
359
+ "UUCP": [
360
+ "UUCP"
361
+ ],
362
+ "AFS": [
363
+ "AFS",
364
+ "OpenAFS"
365
+ ],
366
+ "NIS": [
367
+ "NIS",
368
+ "YPServ"
369
+ ],
370
+ "Telnet SSL": [
371
+ "telnet-ssl"
372
+ ],
373
+
374
+ // ----------------- Big Data / Hadoop Ecosystem --------------
375
+ "Hadoop": [
376
+ "Hadoop",
377
+ "MapReduce",
378
+ "YARN"
379
+ ],
380
+ "HDFS": [
381
+ "HDFS"
382
+ ],
383
+ "Hive": [
384
+ "Hive",
385
+ "HiveServer2"
386
+ ],
387
+ "HBase": [
388
+ "HBase",
389
+ "HMaster"
390
+ ],
391
+ "Zookeeper": [
392
+ "Zookeeper",
393
+ "ZooKeeper"
394
+ ],
395
+ "Spark": [
396
+ "Spark"
397
+ ],
398
+
399
+ // ------------ Web Frameworks / Application Servers ----------
400
+ "Tomcat": [
401
+ "Apache Tomcat",
402
+ "Apache-Coyote"
403
+ ],
404
+ "JBoss": [
405
+ "JBoss",
406
+ "JBoss EAP"
407
+ ],
408
+ "GlassFish": [
409
+ "GlassFish"
410
+ ],
411
+ "WebLogic": [
412
+ "WebLogic"
413
+ ],
414
+ "WebSphere": [
415
+ "WebSphere"
416
+ ],
417
+ "Jetty": [
418
+ "Jetty"
419
+ ],
420
+ // Gunicorn and uWSGI also appear under HTTP if they surface in the banner.
421
+
422
+ // ------- Additional Container / Orchestration Tools ---------
423
+ "Docker Swarm": [
424
+ "Swarm"
425
+ ],
426
+
427
+ // ---------- Reverse Proxies / Load Balancers / Gateways -----
428
+ "HAProxy": [
429
+ "HAProxy"
430
+ ],
431
+ "Traefik": [
432
+ "Traefik"
433
+ ],
434
+ "Envoy": [
435
+ "Envoy"
436
+ ],
437
+
438
+ // ------------------ CI/CD and DevOps Tools ------------------
439
+ "Bamboo": [
440
+ "Bamboo"
441
+ ],
442
+ "TeamCity": [
443
+ "TeamCity"
444
+ ],
445
+ "Drone CI": [
446
+ "Drone"
447
+ ],
448
+
449
+ // ------------------- Just for completeness ------------------
450
+ "COBOL-based service": [
451
+ "Mainframe",
452
+ "AS/400",
453
+ // Banner might mention "Enterprise COBOL" or "z/OS"
454
+ "z/OS"
455
+ ]
456
+ }
@@ -35,6 +35,8 @@ def get_scan(scan_id):
35
35
  @api_bp.route('/api/scan/<scan_id>/summary',methods=['GET'])
36
36
  def get_scan_summary(scan_id):
37
37
  scan = scan_manager.get_scan(scan_id)
38
+ if not scan:
39
+ return jsonify({'error':'scan not found'}), 404
38
40
  return jsonify({
39
41
  'running': scan.running,
40
42
  'percent_complete': scan.calc_percent_complete(),
@@ -164,7 +164,6 @@ function pollScanSummary(id) {
164
164
  if (summary.running || summary.stage == 'terminating') {
165
165
  progress.css('height','2px');
166
166
  progress.css('width',`${summary.percent_complete}vw`);
167
- // TODO: move overview here??
168
167
  setTimeout(() => {pollScanSummary(id)},500);
169
168
  } else {
170
169
  progress.css('width','100vw');
@@ -179,6 +178,11 @@ function pollScanSummary(id) {
179
178
  },1000);
180
179
  }
181
180
  updateOverviewUI(summary);
181
+ }).fail(function(req) {
182
+ if (req === 404) {
183
+ console.log('Scan not found, redirecting to home');
184
+ window.location.href = '/';
185
+ }
182
186
  });
183
187
  }
184
188
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: lanscape
3
- Version: 1.2.9a1
3
+ Version: 1.2.9a3
4
4
  Summary: A python based local network scanner
5
5
  Author-email: Michael Dennis <michael@dipduo.com>
6
6
  Project-URL: Homepage, https://github.com/mdennis281/py-lanscape
@@ -18,6 +18,7 @@ src/lanscape/libraries/mac_lookup.py
18
18
  src/lanscape/libraries/net_tools.py
19
19
  src/lanscape/libraries/port_manager.py
20
20
  src/lanscape/libraries/runtime_args.py
21
+ src/lanscape/libraries/service_scan.py
21
22
  src/lanscape/libraries/subnet_scan.py
22
23
  src/lanscape/libraries/version_manager.py
23
24
  src/lanscape/resources/mac_addresses/convert_csv.py
@@ -27,6 +28,7 @@ src/lanscape/resources/ports/full.json
27
28
  src/lanscape/resources/ports/large.json
28
29
  src/lanscape/resources/ports/medium.json
29
30
  src/lanscape/resources/ports/small.json
31
+ src/lanscape/resources/services/definitions.jsonc
30
32
  src/lanscape/tests/__init__.py
31
33
  src/lanscape/tests/_helpers.py
32
34
  src/lanscape/tests/test_api.py
File without changes
File without changes
File without changes