Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions src/seeyoucm_thief/thief.py
Original file line number Diff line number Diff line change
Expand Up @@ -2835,7 +2835,13 @@ def main():
)
quit(0)

if CUCM_host:
# The version probe only informs the UDS-based features; it queries the UDS
# port (8443) and has nothing to say for --brute-mac or plain config/phone
# scans. Running it unconditionally made those runs pay a full UDS read
# timeout and print a misleading "could not retrieve version" error against
# hosts where UDS is firewalled or not listening.
uds_feature = args.servers or args.directory or args.userenum or args.spray
if CUCM_host and uds_feature:
version_info = get_version(CUCM_host, port=args.uds_port)
if version_info:
v = version_info.get('version', 'unknown')
Expand Down Expand Up @@ -3014,9 +3020,17 @@ def main():
else:
db_prefixes = all_prefixes
if not db_prefixes:
print('You must specify at least one phone with -p (or a CUCM server with -H) when using --brute-mac')
if not no_db:
print(' (and no previously discovered phones were found in the database)')
if CUCM_host:
# -H was given, but --brute-mac does not itself query the
# server: it replays MAC prefixes already harvested into the
# database by --userenum/--spray or an earlier phone scan.
print(f'--brute-mac found no MAC prefixes for {CUCM_host} in the database.')
print(' Run --userenum or --spray against it first, scan a phone with -p,')
print(' or pass a phone IP directly with -p to seed prefixes.')
else:
print('You must specify at least one phone with -p (or a CUCM server with -H) when using --brute-mac')
if not no_db:
print(' (and no previously discovered phones were found in the database)')
quit(1)
prefix_len = 12 - brute_mac_len
if prefix_len < 0:
Expand Down
49 changes: 49 additions & 0 deletions tests/test_brute_host_prefixes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import sqlite3

import pytest

import thief


Expand Down Expand Up @@ -48,3 +50,50 @@ def test_brute_mac_accepts_host_without_phone(tmp_path):
)
assert 'You must specify at least one phone' not in result.stdout
assert 'MAC brute force mode enabled using 1 MAC prefix' in result.stdout


def test_brute_mac_does_not_probe_uds_version(monkeypatch, tmp_path, capsys):
"""--brute-mac must not run the UDS version probe: it never touches UDS, so
a firewalled 8443 would otherwise cost a full read timeout and a misleading
'could not retrieve version' error."""
calls = []
monkeypatch.setattr(thief, 'get_version', lambda *a, **kw: calls.append(kw) or None)
db_file = str(tmp_path / 'thief.db')
thief.init_database(db_file)
monkeypatch.setattr('sys.argv',
['thief', '-b', '1', '-H', 'cucm1', '--db', db_file])
with pytest.raises(SystemExit):
thief.main()
out = capsys.readouterr().out
assert calls == []
assert 'Could not retrieve CUCM version' not in out


def test_brute_mac_empty_db_message_names_host(monkeypatch, tmp_path, capsys):
"""With -H but no seeded prefixes, the error should point at seeding steps,
not claim -H was missing."""
monkeypatch.setattr(thief, 'get_version', lambda *a, **kw: None)
db_file = str(tmp_path / 'thief.db')
thief.init_database(db_file)
monkeypatch.setattr('sys.argv',
['thief', '-b', '1', '-H', 'cucm-empty', '--db', db_file])
with pytest.raises(SystemExit):
thief.main()
out = capsys.readouterr().out
assert 'no MAC prefixes for cucm-empty' in out
assert 'You must specify at least one phone' not in out


def test_servers_feature_still_probes_uds_version(monkeypatch, tmp_path):
"""UDS features must keep running the version probe."""
calls = []
monkeypatch.setattr(thief, 'get_version',
lambda *a, **kw: calls.append(kw) or {'version': '14.0', 'prefix': None})
monkeypatch.setattr(thief, 'get_servers_api', lambda *a, **kw: [])
db_file = str(tmp_path / 'thief.db')
thief.init_database(db_file)
monkeypatch.setattr('sys.argv',
['thief', '--servers', '-H', 'cucm1', '--db', db_file])
with pytest.raises(SystemExit):
thief.main()
assert len(calls) == 1
Loading