From de6e39d57ab7f1b871f02ad85a8e30f135ebd327 Mon Sep 17 00:00:00 2001 From: matejvelikonja Date: Mon, 25 Aug 2014 22:55:07 +0200 Subject: [PATCH 1/2] Nmap executable can now be passed via constructor. Checks if executable is really executable. --- src/Nmap/Nmap.php | 15 +++++++-- tests/Nmap/Tests/NmapTest.php | 60 +++++++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/Nmap/Nmap.php b/src/Nmap/Nmap.php index 9a531ff..30fc89f 100644 --- a/src/Nmap/Nmap.php +++ b/src/Nmap/Nmap.php @@ -35,6 +35,8 @@ class Nmap private $treatHostsAsOnline = false; + private $executable; + /** * @return Nmap */ @@ -46,11 +48,19 @@ public static function create() /** * @param ProcessExecutor $executor * @param string $outputFile + * @param string $executable + * + * @throws \InvalidArgumentException */ - public function __construct(ProcessExecutor $executor = null, $outputFile = null) + public function __construct(ProcessExecutor $executor = null, $outputFile = null, $executable = 'nmap') { $this->executor = $executor ?: new ProcessExecutor(); $this->outputFile = $outputFile ?: sys_get_temp_dir() . '/output.xml'; + $this->executable = $executable; + + if ($executor->execute($this->executable)) { + throw new \InvalidArgumentException(sprintf('`%s` is not executable.', $this->executable)); + } } /** @@ -93,7 +103,8 @@ public function scan(array $targets, array $ports = array()) } $options[] = '-oX'; - $command = sprintf('nmap %s %s %s', + $command = sprintf('%s %s %s %s', + $this->executable, implode(' ', $options), ProcessUtils::escapeArgument($this->outputFile), $targets diff --git a/tests/Nmap/Tests/NmapTest.php b/tests/Nmap/Tests/NmapTest.php index f8655c6..f4ea5d5 100644 --- a/tests/Nmap/Tests/NmapTest.php +++ b/tests/Nmap/Tests/NmapTest.php @@ -13,9 +13,9 @@ public function testScan() $outputFile = __DIR__ . '/Fixtures/test_scan.xml'; $expectedCommand = sprintf("nmap -oX '%s' 'williamdurand.fr'", $outputFile); - $executor = $this->getMock('Nmap\Util\ProcessExecutor'); + $executor = $this->getProcessExecutorMock(); $executor - ->expects($this->once()) + ->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnValue(0)); @@ -53,9 +53,9 @@ public function testScanSpecifyingPorts() $outputFile = __DIR__ . '/Fixtures/test_scan_specifying_ports.xml'; $expectedCommand = sprintf("nmap -p 21,22,80 -oX '%s' 'williamdurand.fr'", $outputFile); - $executor = $this->getMock('Nmap\Util\ProcessExecutor'); + $executor = $this->getProcessExecutorMock(); $executor - ->expects($this->once()) + ->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnValue(0)); @@ -92,9 +92,9 @@ public function testScanWithOsDetection() $outputFile = __DIR__ . '/Fixtures/test_scan_with_os_detection.xml'; $expectedCommand = sprintf("nmap -O -oX '%s' 'williamdurand.fr'", $outputFile); - $executor = $this->getMock('Nmap\Util\ProcessExecutor'); + $executor = $this->getProcessExecutorMock(); $executor - ->expects($this->once()) + ->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnValue(0)); @@ -110,9 +110,9 @@ public function testScanWithServiceInfo() $outputFile = __DIR__ . '/Fixtures/test_scan_with_service_info.xml'; $expectedCommand = sprintf("nmap -sV -oX '%s' 'williamdurand.fr'", $outputFile); - $executor = $this->getMock('Nmap\Util\ProcessExecutor'); + $executor = $this->getProcessExecutorMock(); $executor - ->expects($this->once()) + ->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnValue(0)); @@ -128,9 +128,9 @@ public function testScanWithVerbose() $outputFile = __DIR__ . '/Fixtures/test_scan_with_verbose.xml'; $expectedCommand = sprintf("nmap -v -oX '%s' 'williamdurand.fr'", $outputFile); - $executor = $this->getMock('Nmap\Util\ProcessExecutor'); + $executor = $this->getProcessExecutorMock(); $executor - ->expects($this->once()) + ->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnValue(0)); @@ -146,9 +146,9 @@ public function testPingScan() $outputFile = __DIR__ . '/Fixtures/test_ping_scan.xml'; $expectedCommand = sprintf("nmap -sn -oX '%s' 'williamdurand.fr'", $outputFile); - $executor = $this->getMock('Nmap\Util\ProcessExecutor'); + $executor = $this->getProcessExecutorMock(); $executor - ->expects($this->once()) + ->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnValue(0)); @@ -164,9 +164,9 @@ public function testScanWithoutReverseDNS() $outputFile = __DIR__ . '/Fixtures/test_ping_without_reverse_dns.xml'; $expectedCommand = sprintf("nmap -n -oX '%s' 'williamdurand.fr'", $outputFile); - $executor = $this->getMock('Nmap\Util\ProcessExecutor'); + $executor = $this->getProcessExecutorMock(); $executor - ->expects($this->once()) + ->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnValue(0)); @@ -182,9 +182,9 @@ public function testScanWithTreatHostsAsOnline() $outputFile = __DIR__ . '/Fixtures/test_scan_with_verbose.xml'; $expectedCommand = sprintf("nmap -Pn -oX '%s' 'williamdurand.fr'", $outputFile); - $executor = $this->getMock('Nmap\Util\ProcessExecutor'); + $executor = $this->getProcessExecutorMock(); $executor - ->expects($this->once()) + ->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedCommand)) ->will($this->returnValue(0)); @@ -192,4 +192,32 @@ public function testScanWithTreatHostsAsOnline() $nmap = new Nmap($executor, $outputFile); $hosts = $nmap->treatHostsAsOnline()->scan(array('williamdurand.fr')); } + + /** + * @expectedException \InvalidArgumentException + */ + public function testExecutableNotExecutable() + { + $executor = $this->getMock('Nmap\Util\ProcessExecutor'); + $executor + ->expects($this->once()) + ->method('execute') + ->will($this->returnValue(1)); + + new Nmap($executor); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject | \Nmap\Util\ProcessExecutor + */ + private function getProcessExecutorMock() + { + $executor = $this->getMock('Nmap\Util\ProcessExecutor'); + $executor + ->expects($this->at(0)) + ->method('execute') + ->will($this->returnValue(0)); + + return $executor; + } } From a7a7a04a797184bb8a4e4434bcee698556934c74 Mon Sep 17 00:00:00 2001 From: Matej Velikonja Date: Tue, 26 Aug 2014 10:31:12 +0200 Subject: [PATCH 2/2] A bit more explicit if statement --- src/Nmap/Nmap.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Nmap/Nmap.php b/src/Nmap/Nmap.php index 30fc89f..c804a17 100644 --- a/src/Nmap/Nmap.php +++ b/src/Nmap/Nmap.php @@ -58,7 +58,8 @@ public function __construct(ProcessExecutor $executor = null, $outputFile = null $this->outputFile = $outputFile ?: sys_get_temp_dir() . '/output.xml'; $this->executable = $executable; - if ($executor->execute($this->executable)) { + // If executor returns anything else than 0 (success exit code), throw an exeption since $executable is not executable. + if ($executor->execute($this->executable) !== 0) { throw new \InvalidArgumentException(sprintf('`%s` is not executable.', $this->executable)); } }