Skip to content

Commit 419291a

Browse files
committed
implement fixes by cyberkimchi in #2227
1 parent 607016a commit 419291a

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import socket
2+
import sys
3+
from collections import OrderedDict
4+
5+
import pytest
6+
7+
8+
class TestShodanEngine:
9+
@pytest.mark.asyncio
10+
async def test_shodan_engine_processes_without_work_item_error_and_yields_hostnames(self, monkeypatch, capsys):
11+
# Import inside the test so monkeypatching affects the already-imported module namespace.
12+
import theHarvester.__main__ as main_module
13+
14+
# Make DNS resolution deterministic and offline.
15+
monkeypatch.setattr(socket, "gethostbyname", lambda _domain: "1.2.3.4", raising=True)
16+
17+
# Avoid filesystem/sqlite side effects.
18+
class DummyStashManager:
19+
async def do_init(self) -> None:
20+
return None
21+
22+
async def store_all(self, domain, all, res_type, source) -> None: # noqa: A002
23+
return None
24+
25+
monkeypatch.setattr(main_module.stash, "StashManager", DummyStashManager, raising=True)
26+
27+
# Stub Shodan search to avoid network and API key requirements.
28+
class DummySearchShodan:
29+
async def search_ip(self, ip):
30+
return OrderedDict({ip: {"hostnames": ["a.example.com", "b.example.com"]}})
31+
32+
monkeypatch.setattr(main_module.shodansearch, "SearchShodan", DummySearchShodan, raising=True)
33+
34+
# Run the CLI path that uses the engine queue/worker (`-b shodan`).
35+
monkeypatch.setattr(sys, "argv", ["theHarvester", "-d", "example.com", "-b", "shodan"], raising=True)
36+
37+
with pytest.raises(SystemExit) as excinfo:
38+
await main_module.start()
39+
assert excinfo.value.code == 0
40+
41+
out = capsys.readouterr().out
42+
assert 'A error occurred while processing a "work item"' not in out
43+
assert "a.example.com" in out
44+
assert "b.example.com" in out

theHarvester/__main__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ def __init__(self, domain):
10161016
self.hosts = set()
10171017
self.shodan = shodan_search
10181018

1019-
async def do_search(self):
1019+
async def process(self, use_proxy: bool = False):
10201020
import socket
10211021

10221022
try:
@@ -1027,13 +1027,17 @@ async def do_search(self):
10271027
if ip in result and isinstance(result[ip], dict):
10281028
# Add the IP as a host for consistency with other modules
10291029
self.hosts.add(ip)
1030+
1031+
for host in result[ip].get('hostnames', []):
1032+
self.hosts.add(host)
1033+
10301034
print(f'Found Shodan data for {ip}')
10311035
elif ip in result and isinstance(result[ip], str):
10321036
print(f'{ip}: {result[ip]}')
10331037
except Exception as e:
10341038
print(f'Error in Shodan search: {e}')
10351039

1036-
def get_hostnames(self):
1040+
async def get_hostnames(self):
10371041
return list(self.hosts)
10381042

10391043
shodan_wrapper = ShodanWrapper(word)

0 commit comments

Comments
 (0)