Project

General

Profile

Feature #12963 » nmap_scan-v19.patch

Phil Wardt, 04/01/2022 09:51 AM

View differences:

src/usr/local/www/nmap_scan.php
1
<?php
2
/*
3
 * nmap_scan.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2022-2022 Rubicon Communications, LLC (Netgate)
7
 * All rights reserved.
8
 *
9
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 * you may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 * http://www.apache.org/licenses/LICENSE-2.0
14
 *
15
 * Unless required by applicable law or agreed to in writing, software
16
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 * See the License for the specific language governing permissions and
19
 * limitations under the License.
20
 */
21

  
22
function nmap_get_running_process($f){
23
	$processcheck = trim(shell_exec("/bin/ps axw -O pid= | /usr/bin/grep '/usr/local/bin/[n]map.*{$f}'"));
24
	return $processcheck;
25
}
26

  
27
// Return a ports array from a nmap -p arg value format
28
// we strip ranges (-) and types (T:, U:, P:, S:)
29
// port names with '-' like 'netbios-ssn' are supported
30
function get_ports_array($port_post) {
31
	$ports_array = array();
32

  
33
	// get ports from the comma separated form input
34
	if (strpos($port_post, ',') === false) {
35
		$ports_array = array($port_post);
36
	} else {
37
		$ports_array = explode(',', $port_post);
38
	}
39

  
40
	$port_max_ranges = array();
41
	foreach ($ports_array as &$p) {
42
		if (preg_match('/^(T:|U:|P:|S:)/', $p) === 1) {
43
			$p = substr($p, 2);//if empty, we keep it as it is an illegal nmap syntax. On function return, empty ports will evaluate as invalid
44
		}
45

  
46
		// keep only inner and outer ports from a ports range
47
		// if the inner/outer port range limit is omitted, set corresponding port value to '*'
48
		if ($p === '-') {
49
			$p = '*';
50
		} elseif (strpos($p, '-') !== false && preg_match('/^[0-9\-]+$/', $p) === 1) {
51
			// port ranges must be in the format of 'numeric-numeric'
52
			$port_ranges = explode('-', $p, 2);
53
			$p = strlen($port_ranges[0]) ? $port_ranges[0] : '*';
54
			$port_max_ranges[] = strlen($port_ranges[1]) ? $port_ranges[1] : '*';
55
		}
56
	}
57
	unset($p);
58
	$ports_array = array_merge($ports_array, $port_max_ranges);
59

  
60
	return $ports_array;
61
}
62

  
63
if ($_POST['downloadbtn'] == gettext("Download Results")) {
64
	$nocsrf = true;
65
}
66

  
67
$pgtitle = array("Package", "Diagnostics: Nmap");
68
require_once("guiconfig.inc");
69
/* require_once("pfsense-utils.inc"); */
70
require_once("ipsec.inc");
71

  
72
$fp = "/root/";
73
$fn = "nmap.result";
74
$fe = "nmap.error"; // stderr
75
$max_display_size = 50*1024*1024; // 50MB limit on GUI results display. See https://redmine.pfsense.org/issues/9239
76

  
77
$interfaces = get_configured_interface_with_descr();
78
if (ipsec_enabled()) {
79
	$interfaces['enc0'] = "IPsec";
80
}
81
$interfaces['lo0'] = "Localhost";
82

  
83
foreach (array('server' => gettext('OpenVPN Server'), 'client' => gettext('OpenVPN Client')) as $mode => $mode_descr) {
84
	if (is_array($config['openvpn']["openvpn-{$mode}"])) {
85
		foreach ($config['openvpn']["openvpn-{$mode}"] as $id => $setting) {
86
			if (!isset($setting['disable'])) {
87
				$interfaces['ovpn' . substr($mode, 0, 1) . $setting['vpnid']] = $mode_descr . ": ".htmlspecialchars($setting['description']);
88
			}
89
		}
90
	}
91
}
92

  
93
$interfaces = array_merge($interfaces, interface_ipsec_vti_list_all());
94
$interfaces = array_merge(array('' => 'Auto detect (default)'), $interfaces);
95

  
96
$scan_types = array(
97
	'syn' => gettext('TCP SYN'),
98
	'connect' => gettext('TCP Connect()'),
99
	'ack' => gettext('TCP ACK'),
100
	'window' => gettext('TCP Window'),
101
	'udp' => gettext('UDP'),
102
	'icmp' => gettext('No Port Scan'),
103
	'arp' => gettext('ARP Ping'),
104
	'ipscan' => gettext('IP Protocol'),
105
	'sctpinit' => gettext('SCTP INIT'),
106
	'sctpecho' => gettext('SCTP COOKIE ECHO'),
107
	'listscan' => gettext('List Only')
108
);
109

  
110
$input_errors = array();
111
$do_nmapscan = false;
112
if ($_POST) {
113
	$hostnames = $_POST['hostnames'];
114
	$interface = $_POST['interface'];
115
	$scantype = $_POST['scantype'];
116
	$udpscan = isset($_POST['udpscan']);
117
	$noping = isset($_POST['noping']);
118
	$servicever = isset($_POST['servicever']);
119
	$osdetect = isset($_POST['osdetect']);
120
	$excludehosts = $_POST['excludehosts'];
121
	$ports = $_POST['ports'];
122
	$topports = $_POST['topports'];
123
	$traceroute = isset($_POST['traceroute']);
124

  
125
	if ($_POST['startbtn'] != "") {
126
		$action = gettext("Start");
127

  
128
		// check for input errors
129
		if (strlen($hostnames) === 0) {
130
			$input_errors[] = gettext("You must enter an IP address or host name to scan.");
131
		} else {
132
			$hostnames_array = explode(" ", $hostnames);
133
			foreach ($hostnames_array as $host_entry) {
134
				if (!(is_ipaddr($host_entry) || is_subnet($host_entry) || is_hostname($host_entry))) {
135
					$input_errors[] = gettext("Host: '") . escapeshellarg($host_entry) . gettext("' is not a valid IP address or host name.");
136
				} elseif (is_ipaddrv6($host_entry) || is_subnetv6($host_entry)) {
137
					$enable_ipv6 = true;
138
				}
139
			}
140
		}
141

  
142
		if(!empty($interface)) {
143
			if (!array_key_exists($interface, $interfaces)) {
144
				$input_errors[] = gettext("Invalid interface.");
145
			}
146
		}
147

  
148
		if ($udpscan) {
149
			if ($scantype !== 'syn' && $scantype !== 'connect' && $scantype !== 'ack' && $scantype !== 'window') {
150
				$input_errors[] = gettext("UDP Scan (-sU): This option cannot be used with '") . $scan_types[$scantype] . gettext("' scan type. UDP scan can only be combined with a TCP scan method");
151
			}
152
		}
153

  
154
		// Check advanced options
155
		if(strlen($excludehosts) > 0) {
156
			$excludehosts_array = explode(",", $excludehosts);
157
			foreach ($excludehosts_array as $host_entry) {
158
				if (strlen($host_entry) === 0) {
159
					$input_errors[] = gettext("Exclude Hosts: you cannot specify empty hosts in the list. Remove any extra or trailing commas !");
160
				} elseif (!(is_ipaddr($host_entry) || is_subnet($host_entry) || is_hostname($host_entry))) {
161
					$input_errors[] = gettext("Exclude Hosts: '") . escapeshellarg($host_entry) . gettext("' is not a valid IP address or host name.");
162
				}
163
			}
164
		}
165

  
166
		if(strlen($ports) > 0) {
167
			if (strpos($ports, '*') !== false) {
168
				$input_errors[] = gettext("Ports cannot contain an asterix '*'.");
169
			} else {
170
				$ports_arr = get_ports_array($ports);
171
				foreach ($ports_arr as $p) {
172
					if ($p === '*') {
173
						continue;
174
					} elseif (strlen($p) === 0) {
175
						$input_errors[] = gettext("Port: emtpy ports in list. Remove any extra or trailing commas. Also ensure that you type a port number/name after port specifiers (T:|U:|P:|S:)");
176
					} elseif (is_numericint($p) && intval($p) === 0) {
177
						continue;//nmap allows scanning of port 0 if explicitely specified
178
					} elseif (!is_port($p)) {
179
						$input_errors[] = gettext("Port: '") . escapeshellarg($p) . gettext("' is not a valid port.");
180
					} elseif ($scantype === 'ipscan' && is_numericint($p) && intval($p) > 255) {
181
						$input_errors[] = gettext("Port number must be an integer between 0 and 255 when using IP Protocol Scan method");
182
					}
183
				}
184
			}
185
		}
186

  
187
		if(strlen($topports) > 0) {
188
			if (!is_numericint($topports) || intval($topports) < 1 || intval($topports) > 65535) {
189
				$input_errors[] = gettext("--top-ports value must be an integer in the range 1-65535.");
190
			}
191
		}
192

  
193
		// process scan options only if no input errors
194
		if (!count($input_errors)) {
195
			$do_nmapscan = true;
196

  
197
			$nmap_options = "";
198

  
199
			// prevent use of any deprecated option
200
			//$nmap_options .= " -d";
201

  
202
			if ($enable_ipv6) {
203
				$nmap_options .= " -6";
204
			}
205

  
206
			// scan type
207
			switch($scantype) {
208
				case 'syn':
209
					$nmap_options .= " -sS";
210
					break;
211
				case 'connect':
212
					$nmap_options .= " -sT";
213
					break;
214
				case 'ack':
215
					$nmap_options .= " -sA";
216
					break;
217
				case 'window':
218
					$nmap_options .= " -sW";
219
					break;
220
				case 'udp':
221
					$nmap_options .= " -sU";
222
					break;
223
				case 'icmp':
224
					$nmap_options .= " -sn"; // previously -sP
225
					break;
226
				case 'arp':
227
					$nmap_options .= " -sn -PR";
228
					break;
229
				case 'ipscan':
230
					$nmap_options .= " -sO";
231
					break;
232
				case 'sctpinit':
233
					$nmap_options .= " -sY";
234
					break;
235
				case 'sctpecho':
236
					$nmap_options .= " -sZ";
237
					break;
238
				case 'listscan':
239
					$nmap_options .= " -sL";
240
					break;
241
			}
242

  
243
			// allow TCP + UDP combined scans
244
			if ($udpscan) {
245
				$nmap_options .= " -sU";
246
			}
247

  
248
			// scan options
249
			if ($noping) {
250
				$nmap_options .= " -Pn"; // previously -P0
251
			}
252
			if ($servicever) {
253
				$nmap_options .= " -sV";
254
			}
255
			if ($osdetect) {
256
				$nmap_options .= " -O";
257
			}
258

  
259
			if(strlen($ports) > 0) {
260
				$nmap_options .= " -p " . escapeshellarg($ports);
261
			}
262

  
263
			if(strlen($topports) > 0) {
264
				$nmap_options .= " --top-ports " . escapeshellarg($topports);
265
			}
266

  
267
			if ($traceroute) {
268
				$nmap_options .= " --traceroute";
269
			}
270

  
271
			// append summary output to results file (doesn't contain stderr)
272
			$nmap_options .= " -oN {$fp}{$fn} --append-output";
273

  
274
			if (!empty($interface)) {
275
				$nmap_options .= " -e " . get_real_interface($interface);
276
			}
277

  
278
			if(strlen($excludehosts) > 0) {
279
				$nmap_options .= " --exclude " . escapeshellarg($excludehosts);
280
			}
281

  
282
			foreach ($hostnames_array as $host_entry) {
283
				$nmap_options .= " " . escapeshellarg($host_entry);
284
			}
285
		}
286
	} elseif ($_POST['stopbtn'] != "") {
287
		$action = gettext("Stop");
288

  
289
		/* check if nmap scan is already running */
290
		$processes_running = nmap_get_running_process($fn);
291
		$processisrunning = ($processes_running != "");
292

  
293
		//explode processes into an array, (delimiter is new line)
294
		$processes_running_array = explode("\n", $processes_running);
295

  
296
		if ($processisrunning != true) {
297
			$input_errors[] = gettext("Process nmap already completed. Check results below.");
298
		} else {
299
			//kill each of the nmap processes
300
			foreach ($processes_running_array as $process) {
301
				$process_id_pos = strpos($process, ' ');
302
				$process_id = substr($process, 0, $process_id_pos);
303
				exec("kill $process_id");
304
			}				
305
		}
306
	} elseif ($_POST['viewbtn'] != "" || $_POST['refreshbtn'] != "") {
307
		$action = gettext("View");
308
	} elseif ($_POST['downloadbtn'] != "") {
309
		$action = gettext("Download");
310

  
311
		//download file
312
		send_user_download('file', $fp.$fn);
313
	} elseif ($_POST['clearbtn'] != "") {
314
		$action = gettext("Delete");
315

  
316
		//delete previous nmap results file if it exists
317
		unlink_if_exists($fp.$fn);
318
		unlink_if_exists($fp.$fe);
319
	}
320
}
321

  
322
include("head.inc");
323

  
324
/*
325
$tab_array = array();
326
$tab_array[] = array(gettext("Nmap Scan"), true, "/nmap_scan.php");
327
display_top_tabs($tab_array);
328
*/
329

  
330
if ($input_errors) {
331
	print_input_errors($input_errors);
332
}
333

  
334
$form = new Form(false); // No button yet. We add those later depending on the required action
335

  
336
$section = new Form_Section('General Options');
337

  
338
$section->addInput(new Form_Input(
339
	'hostnames',
340
	'*IP or Hostname',
341
	'text',
342
	$hostnames
343
))->setHelp('Enter the IP addresses or hostnames that you would like to scan.%1$s' .
344
			'%2$sCan pass space separated hostnames, IP addresses, ranges, networks, etc.%3$s' .
345
			'Ex: scanme.nmap.org; microsoft.com/24 192.168.0.1 10.10.1.1; 10.0.0-255.1-254%4$s',
346

  
347
			'<span class="infoblock" style="font-size:90%"><br />',
348
			'<p style="margin:0px;padding:0px">',
349
			'<br />',
350
			'</p></span>');
351

  
352
$section->addInput(new Form_Select(
353
	'interface',
354
	'Interface',
355
	$interface,
356
	$interfaces
357
))->setHelp('Select the source interface here.');
358

  
359
$section->addInput(new Form_Select(
360
	'scantype',
361
	'*Scan Type',
362
	$scantype,
363
	$scan_types
364
))->setHelp('Select the scan type.%1$s' .
365
			'%2$s%3$s%4$sTCP SYN (-sS):%5$s The default and most popular scan option.%6$s' .
366

  
367
			'%4$sTCP connect (-sT):%5$s The default TCP scan type when SYN scan is not an option. This is the case when a user does not have raw packet privileges. ' .
368
			'This is the same high-level system call that web browsers, P2P clients, and most other network-enabled applications use to establish a connection.%6$s' .
369

  
370
			'%4$sTCP ACK (-sA):%5$s This scan is different than the others discussed so far in that it never determines open (or even open|filtered) ports. ' .
371
			'It is used to map out firewall rulesets, determining whether they are stateful or not and which ports are filtered.%6$s' .
372

  
373
			'%4$sTCP Window (-sW):%5$s Window scan is exactly the same as ACK scan except that it exploits an implementation detail of certain systems to differentiate open ports from closed ones, ' .
374
			'rather than always printing unfiltered when a RST is returned.%6$s' .
375

  
376
			'%4$sUDP scan (-sU):%5$s UDP scan works by sending an UDP packet to every targeted port.%6$s' .
377

  
378
			'%4$sNo port scan (-sn):%5$s This option tells Nmap not to do a port scan after host discovery, and only print out the available hosts that responded to the host discovery probes. This is often known as a "ping scan". ' .
379
			'However, to skip host discovery and port scan, while still allowing NSE to run, you can use the two options -Pn -sn together.%6$s' .
380

  
381
			'%4$sARP Ping (-sn -PR):%5$s ARP is only for directly connected ethernet LAN. On local networks, ARP scan takes just over a tenth of the time taken by its IP equivalent. ' .
382
			'It also avoids filling source host ARP table space with invalid entries.%6$s' .
383

  
384
			'%4$sIP protocol scan (-sO):%5$s IP protocol scan allows you to determine which IP protocols (TCP, ICMP, IGMP, etc.) are supported by target machines. ' .
385
			'This is not technically a port scan, since it cycles through IP protocol numbers rather than TCP or UDP port numbers. Yet it still uses the -p option to select scanned protocol numbers, ' .
386
			'reports its results within the normal port table format, and even uses the same underlying scan engine as the true port scanning methods.%6$s' .
387

  
388
			'%4$sSCTP INIT scan (-sY):%5$s Scan for services implementing SCTP. SCTP INIT scan is the SCTP equivalent of a TCP SYN scan.%6$s' .
389

  
390
			'%4$sSCTP COOKIE ECHO (-sZ):%5$s A more advanced SCTP scan. It takes advantage of the fact that SCTP implementations should silently drop packets containing COOKIE ECHO chunks on open ports, ' .
391
			'but send an ABORT if the port is closed.%6$s' .
392

  
393
			'%4$sList scan (-sL):%5$s List scan simply lists each target host on the network(s) specified, without sending any packets to the target hosts. ' .
394
			'By default, Nmap still performs reverse-DNS resolution on the hosts to learn their names. Nmap also reports the total number of IP addresses at the end. ' .
395
			'List scan is a good sanity check to ensure that you have proper IP addresses for your targets. A preliminary list scan helps confirm exactly what targets are being scanned.%6$s%7$s',
396

  
397
			'<span class="infoblock" style="font-size:90%"><br />',
398
			'<p style="margin:0px;padding:0px">',
399
			'<ul>',
400
			'<li><b>',
401
			'</b>',
402
			'</li>',
403
			'</ul></p></span>');
404

  
405
$section->addInput(new Form_Checkbox(
406
	'udpscan',
407
	'UDP Scan',
408
	'Combines an UDP scan (-sU) with a TCP scan method',
409
	$_POST['udpscan']
410
))->setHelp('Only possible if a TCP scan method was selected.%1$s' .
411
			'%2$sUDP scan can be combined with a TCP scan type such as SYN scan (-sS) to check both protocols during the same run.%3$s' .
412
			'This option is valid only in combination with a TCP scan method (SYN, Connect(), ACK, Window).%3$s',
413

  
414
			'<span class="infoblock" style="font-size:90%"><br />',
415
			'<p style="margin:0px;padding:0px">',
416
			'<br />',
417
			'</p></span>');
418

  
419
$section->addInput(new Form_Checkbox(
420
	'noping',
421
	'-Pn',
422
	'Treat all hosts as online (No ping).',
423
	$_POST['noping']
424
))->setHelp('Allow scanning of networks that do not answer echo requests.%1$s' .
425
			'%2$sThis option skips the Nmap discovery stage altogether. So if a class B target address space (/16) is specified on the command line, all 65,536 IP addresses are scanned. ' .
426
			'Proper host discovery is skipped as with the list scan, but instead of stopping and printing the target list, Nmap continues to perform requested functions as if each target IP is active.%3$s' .
427
			'microsoft.com is an example of such a network, and thus you should always use -P0 or -PT80 when port scanning microsoft.com.%3$s' .
428
			'Note the "ping" in this context may involve more than the traditional ICMP echo request packet. Nmap supports many such probes, including arbitrary combinations of TCP, UDP, and ICMP probes.%3$s' .
429
			'By default, Nmap sends an ICMP echo request and a TCP ACK packet to port 80.%4$s',
430

  
431
			'<span class="infoblock" style="font-size:90%"><br />',
432
			'<p style="margin:0px;padding:0px">',
433
			'<br />',
434
			'</p></span>');
435

  
436
$section->addInput(new Form_Checkbox(
437
	'servicever',
438
	'-sV',
439
	'Attempt to identify service versions',
440
	$_POST['servicever']
441
))->setHelp('Try to detect services running on discoverd ports.%1$s' .
442
			'%2$sAfter TCP and/or UDP ports are discovered using one of the other scan types, version detection communicates with those ports to try and determine more about what is actually running.%3$s' .
443
			'A file called nmap-service-probes is used to determine the best probes for detecting various services and the match strings to expect.%3$s' .
444
			'Nmap tries to determine the service protocol (e.g. ftp, ssh, telnet, http), the application name (e.g. ISC Bind, Apache httpd, Solaris telnetd), ' .
445
			'the version number, and sometimes miscellaneous details like whether an X server is open to connections or the SSH protocol version).%4$s',
446

  
447
			'<span class="infoblock" style="font-size:90%"><br />',
448
			'<p style="margin:0px;padding:0px">',
449
			'<br />',
450
			'</p></span>');
451

  
452
$section->addInput(new Form_Checkbox(
453
	'osdetect',
454
	'-O',
455
	'Enable Operating System detection',
456
	$_POST['osdetect']
457
))->setHelp('Try to identify remote host via TCP/IP fingerprinting.%1$s' .
458
			'%2$sIn other words, it uses techniques to detect subtleties in the underlying operating system network stack of the computers being scanned.%3$s' .
459
			'It uses this information to create a "fingerprint" which it compares with its database of known OS fingerprints ' .
460
			'(the nmap-os-fingerprints file) to determine the operating system of the target host.%4$s',
461

  
462
			'<span class="infoblock" style="font-size:90%"><br />',
463
			'<p style="margin:0px;padding:0px">',
464
			'<br />',
465
			'</p></span>');
466

  
467
$form->add($section);
468

  
469
$section = new Form_Section('Advanced Options');
470

  
471
$section->addInput(new Form_Input(
472
	'excludehosts',
473
	'Exclude Hosts',
474
	'text',
475
	$excludehosts
476
))->setHelp('Enter the IP addresses or hostnames that you would like to exclude from scan.%1$s' .
477
			'%2$sCan pass comma separated hostnames, IP addresses, ranges, networks, etc.%3$s' .
478
			'Ex: scanme.nmap.org,microsoft.com/24,192.168.0.1,10.10.1.1,10.0.0-255.1-254%4$s',
479

  
480
			'<span class="infoblock" style="font-size:90%"><br />',
481
			'<p style="margin:0px;padding:0px">',
482
			'<br />',
483
			'</p></span>');
484

  
485
$section->addInput(new Form_Input(
486
	'ports',
487
	'Port',
488
	'text',
489
	$ports
490
))->setHelp('Only scan specified ports.%1$s' .
491
			'%2$sEx: 22; 1-65535; ssh; U:53,111,137,T:21-25,80,139,8080,P:9.%3$s' .
492
			'When scanning a combination of protocols (e.g. TCP and UDP), you can specify a particular protocol by preceding the port numbers by T: for TCP, U: for UDP, or P: for IP Protocol.%3$s' .
493
			'Individual port numbers are OK, as are ranges separated by a hyphen (e.g. 1-1023). The beginning and/or end values of a range may be omitted, causing Nmap to use 1 and 65535, respectively. ' .
494
			'So you can specify -p- to scan ports from 1 through 65535. Scanning port zero is allowed if you specify it explicitly.%3$s' .
495
			'For IP protocol scanning (-sO), this option specifies the protocol numbers you wish to scan for (0–255).%3$s' .
496
			'Note: SCTP (S:) specifier is not supported in GUI.%4$s',
497

  
498
			'<span class="infoblock" style="font-size:90%"><br />',
499
			'<p style="margin:0px;padding:0px">',
500
			'<br />',
501
			'</p></span>');
502

  
503
$section->addInput(new Form_Input(
504
	'topports',
505
	'--top-ports',
506
	'text',
507
	$topports
508
))->setHelp('Only scan specified most common ports (1-65535).%1$s' .
509
			'%2$sNormally Nmap scans the most common 1,000 ports for each scanned protocol.%3$s' .
510
			'With this option, nmap will only scan the specified most common ports number.%3$s' .
511
			'Value of 100 would be equivalent to the option "-F (Fast (limited port) scan)" which scans the first 100 most common ports.%4$s',
512

  
513
			'<span class="infoblock" style="font-size:90%"><br />',
514
			'<p style="margin:0px;padding:0px">',
515
			'<br />',
516
			'</p></span>');
517

  
518
$section->addInput(new Form_Checkbox(
519
	'traceroute',
520
	'--traceroute',
521
	'Trace hop path to each host',
522
	$_POST['traceroute']
523
));
524

  
525
$form->add($section);
526

  
527
/* check if nmap scan is already running */
528
$processes_running = nmap_get_running_process($fn);
529
$processisrunning = ($processes_running != "");
530

  
531
if ($processisrunning or $do_nmapscan) {
532
	$form->addGlobal(new Form_Button(
533
		'stopbtn',
534
		'Stop',
535
		null,
536
		'fa-stop-circle'
537
	))->addClass('btn-warning');
538

  
539
	$form->addGlobal(new Form_Button(
540
		'refreshbtn',
541
		'Refresh Results',
542
		null,
543
		'fa-retweet'
544
	))->addClass('btn-primary');
545
} else {
546
	$form->addGlobal(new Form_Button(
547
		'startbtn',
548
		'Start',
549
		null,
550
		'fa-play-circle'
551
	))->addClass('btn-success');
552

  
553
	if (file_exists($fp.$fn) or file_exists($fp.$fe)) {
554
		$form->addGlobal(new Form_Button(
555
			'viewbtn',
556
			'View Results',
557
			null,
558
			'fa-file-text-o'
559
		))->addClass('btn-primary');
560

  
561
		$form->addGlobal(new Form_Button(
562
			'downloadbtn',
563
			'Download Results',
564
			null,
565
			'fa-download'
566
		))->addClass('btn-primary');
567

  
568
		$form->addGlobal(new Form_Button(
569
			'clearbtn',
570
			'Clear Results',
571
			null,
572
			'fa-trash'
573
		))->addClass('btn-danger');
574
	}
575
}
576

  
577
if (file_exists($fp.$fn)) {
578
	$section->addInput(new Form_StaticText(
579
		'Last scan results',
580
		date("F jS, Y g:i:s a.", filemtime($fp.$fn))
581
	));
582
}
583

  
584
if (file_exists($fp.$fe) && filesize($fp.$fe) > 0) {
585
	$section->addInput(new Form_StaticText(
586
		'Last scan error',
587
		date("F jS, Y g:i:s a.", filemtime($fp.$fe))
588
	));
589
}
590

  
591
print($form);
592

  
593
if ($do_nmapscan) {
594
	$cmd = "/usr/local/bin/nmap {$nmap_options} >/dev/null 2>{$fp}{$fe} &";
595
	exec($cmd);
596
	print_info_box(gettext('Nmap scan is running' . '<br />' . 'Press info button to show command'), 'info');
597
	?>
598
	<div class="infoblock">
599
	<? print_info_box(gettext('Command line') . ': ' . htmlspecialchars($cmd), 'info', false); ?>
600
	</div>
601
	<?php
602

  
603
} elseif ($action == gettext("View") || $action == gettext("Stop")) {
604
		if (file_exists($fp.$fe) && filesize($fp.$fe) > 0) {
605
?>
606

  
607
<div class="panel panel-default">
608
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Scan Errors')?></h2></div>
609
	<div class="panel-body">
610
		<div class="form-group">
611
<?php
612

  
613
			print('<textarea class="form-control" rows="10" style="font-size: 13px; font-family: consolas,monaco,roboto mono,liberation mono,courier;">');
614
			if (filesize($fp.$fe) > $max_display_size) {
615
				print(gettext("Nmap scan error file is too large to display in the GUI.") .
616
					"\n" .
617
					gettext("Download the file, or view it in the console or ssh shell.") .
618
					"\n" .
619
					gettext("Error file: {$fp}{$fe}"));
620
			} else {
621
				print(file_get_contents($fp.$fe));
622
			}
623
			print('</textarea>');
624

  
625
?>
626
		</div>
627
	</div>
628
</div>
629
<?php
630
		}
631

  
632
?>
633

  
634
<div class="panel panel-default">
635
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('Scan Results')?></h2></div>
636
	<div class="panel-body">
637
		<div class="form-group">
638
<?php
639

  
640
		print('<textarea class="form-control" rows="20" style="font-size: 13px; font-family: consolas,monaco,roboto mono,liberation mono,courier;">');
641
		if (file_exists($fp.$fn) && (filesize($fp.$fn) > $max_display_size)) {
642
			print(gettext("Nmap scan results file is too large to display in the GUI.") .
643
				"\n" .
644
				gettext("Download the file, or view it in the console or ssh shell.") .
645
				"\n" .
646
				gettext("Results file: {$fp}{$fn}"));
647
		} elseif (!file_exists($fp.$fn) || (filesize($fp.$fn) === 0)) {
648
			print(gettext("No nmap scan results to display."));
649
		} else {
650
			print(file_get_contents($fp.$fn));
651
		}
652
		print('</textarea>');
653

  
654
?>
655
		</div>
656
	</div>
657
</div>
658
<?php
659
}
660

  
661
include("foot.inc");
(27-27/30)