Passed
Push — master ( 37e6fd...667cd5 )
by Nils
02:43
created

PortsCollector::getTool()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Startwind\Inventorio\Collector\System\Ports;
4
5
use Startwind\Inventorio\Collector\BasicCollector;
6
7
class PortsCollector extends BasicCollector
8
{
9
    private array $portMap = [];
10
11
    protected string $identifier = 'SystemOpenPorts';
12
13
    public function __construct()
14
    {
15
        $this->loadPorts();
16
    }
17
18
    public function collect(): array
19
    {
20
        $ports = $this->parseListeningPorts();
21
22
        $enrichedPorts = [];
23
24
        foreach ($ports as $port) {
25
            $enrichedPorts[] = [
26
                'port' => $port['port'],
27
                'tool' => $this->getTool($port['port']),
28
                'external' => $port['external'],
29
                'protocol' => $port['protocol'],
30
            ];
31
        }
32
33
        return [
34
            'ports' => $enrichedPorts
35
        ];
36
    }
37
38
    private function loadPorts(): void
39
    {
40
        $csv = [];
41
        if (($handle = fopen(__DIR__ . '/ports.csv', "r")) !== false) {
42
            while (($data = fgetcsv($handle, 1000, ',', '"', '\\')) !== false) {
43
                $csv[$data[1]] = $data[2];
44
            }
45
            fclose($handle);
46
        }
47
        $this->portMap = $csv;
48
    }
49
50
    private function parseListeningPorts(): array
51
    {
52
        $output = [];
53
        exec("ss -tuln", $output);  // TCP und UDP, listening, numerisch
54
55
        $ports = [];
56
57
        foreach ($output as $line) {
58
            if (preg_match('/^(tcp|udp)\s+LISTEN\s+\S+\s+\S+\s+(\S+):(\d+)/', $line, $matches)) {
59
                $protocol = $matches[1];
60
                $ip = $matches[2];
61
                $port = $matches[3];
62
63
                // Normalize IP (e.g., [::] becomes ::)
64
                $ip = trim($ip, '[]');
65
66
                $isExternal = !in_array($ip, ['127.0.0.1', '::1', 'localhost']) || $ip === '*';
67
68
                $ports[] = [
69
                    'protocol' => strtoupper($protocol),
70
                    'ip' => $ip,
71
                    'port' => $port,
72
                    'external' => $isExternal
73
                ];
74
            }
75
        }
76
77
        return $ports;
78
    }
79
80
    private function getTool(int $port): string
81
    {
82
        return $this->portMap[$port] ?? $port;
83
    }
84
}
85