Project

General

Profile

Feature #2736 ยป snort.inc

Bill Meeks, 12/27/2012 05:27 PM

 
1
<?php
2
/*
3
 * snort.inc
4
 *
5
 * Copyright (C) 2006 Scott Ullrich
6
 * Copyright (C) 2009-2010 Robert Zelaya
7
 * Copyright (C) 2011-2012 Ermal Luci
8
 * part of pfSense
9
 * All rights reserved.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions are met:
13
 *
14
 * 1. Redistributions of source code must retain the above copyright notice,
15
 * this list of conditions and the following disclaimer.
16
 *
17
 * 2. Redistributions in binary form must reproduce the above copyright
18
 * notice, this list of conditions and the following disclaimer in the
19
 * documentation and/or other materials provided with the distribution.
20
 *
21
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
 * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
 * POSSIBILITY OF SUCH DAMAGE.
31
 */
32

    
33
require_once("pfsense-utils.inc");
34
require_once("config.inc");
35
require_once("functions.inc");
36

    
37
// Needed on 2.0 because of filter_get_vpns_list()
38
require_once("filter.inc");
39

    
40
/* package version */
41
$snort_version = "2.9.2.3";
42
$pfSense_snort_version = "2.5.2";
43
$snort_package_version = "Snort {$snort_version} pkg v. {$pfSense_snort_version}";
44
$snort_rules_file = "snortrules-snapshot-2923.tar.gz";
45
$emerging_threats_version = "2.9.3";
46
define("SNORTDIR", "/usr/local/etc/snort");
47
define("SNORTLOGDIR", "/var/log/snort");
48

    
49
if (!is_array($config['installedpackages']['snortglobal']))
50
	$config['installedpackages']['snortglobal'] = array();
51

    
52
function snort_get_blocked_ips() {
53
	$blocked_ips = "";
54
	exec('/sbin/pfctl -t snort2c -T show', $blocked_ips);
55
	$blocked_ips_array = array();
56
	if (!empty($blocked_ips)) {
57
		$blocked_ips_array = array();
58
		if (is_array($blocked_ips)) {
59
			foreach ($blocked_ips as $blocked_ip) {
60
				if (empty($blocked_ip))
61
					continue;
62
				$blocked_ips_array[] = trim($blocked_ip, " \n\t");
63
			}
64
		}
65
	}
66

    
67
	return $blocked_ips_array;
68
}
69

    
70
function snort_get_rule_part($source, $beginning, $ending, $start_pos) {
71

    
72
	$beginning_pos = strpos($source, $beginning, $start_pos);
73
	if (!$beginning_pos)
74
		return false;
75
	$middle_pos = $beginning_pos + strlen($beginning);
76
	$source = substr($source, $middle_pos);
77
	$ending_pos = strpos($source, $ending, 0);
78
	if (!$ending_pos)
79
		return false;
80
	return substr($source, 0, $ending_pos);
81
}
82

    
83
function snort_generate_id() {
84
	global $config;
85

    
86
	$snortglob = $config['installedpackages']['snortglobal']['rule'];
87
	while (true) {
88
		$snort_uuid = mt_rand(1, 65535);
89
		foreach ($snortglob as $value) {
90
			if ($value['uuid'] == $snort_uuid)
91
				continue 2;
92
		}
93
		break;
94
	}
95

    
96
	return $snort_uuid;
97
}
98

    
99
/* func builds custom white lists */
100
function snort_find_list($find_name, $type = 'whitelist') {
101
	global $config;
102

    
103
	$snortglob = $config['installedpackages']['snortglobal'];
104
	if (!is_array($snortglob[$type]))
105
		return "";
106
	if (!is_array($snortglob[$type]['item']))
107
		return "";
108

    
109
	foreach ($snortglob[$type]['item'] as $value) {
110
		if ($value['name'] == $find_name)
111
			return $value;
112
	}
113

    
114
	return array();
115
}
116

    
117
/* func builds custom whitelests */
118
function snort_build_list($snortcfg, $listname = "", $whitelist = false) {
119
	global $config, $g;
120

    
121
	/* Add loopback to whitelist (ftphelper) */
122
	$home_net = "127.0.0.1 ";
123

    
124
	if ($listname == 'default' || empty($listname)) {
125
		$wanip = 'yes'; $wangw = 'yes'; $wandns = 'yes'; $vips = 'yes'; $vpns = 'yes';
126
	} else {
127
                $whitelist = snort_find_list($listname);
128
                if (empty($whitelist))
129
                        return $whitelist;
130
		$wanip = $whitelist['wanips'];
131
		$wangw = $whitelist['wangateips'];
132
		$wandns = $whitelist['wandnsips'];
133
		$vips = $whitelist['vips'];
134
		$vpns = $whitelist['vpnips'];
135
		if (!empty($whitelist['address']) && is_alias($whitelist['address'])) {
136
			$home_net .= trim(filter_expand_alias($whitelist['address']));
137
			$home_net .= " ";
138
		}
139
	}
140

    
141
	/* build an interface array list */
142
	if (function_exists('get_configured_interface_list'))
143
		$int_array = get_configured_interface_list();
144
	else {
145
		$int_array = array('lan');
146
		for ($j = 1; isset ($config['interfaces']['opt' . $j]); $j++)
147
			if(isset($config['interfaces']['opt' . $j]['enable']))
148
				$int_array[] = "opt{$j}";
149
	}
150

    
151
	/*  iterate through interface list and write out whitelist items
152
	 *  and also compile a home_net list for snort.
153
	 */
154
	foreach ($int_array as $int) {
155
		/* calculate interface subnet information */
156
		if (function_exists('get_interface_ip')) {
157
			$subnet = get_interface_ip($int);
158
			if (is_ipaddr($subnet)) {
159
				if ($whitelist == false) {
160
					$sn = get_interface_subnet($int);
161
					$home_net .= "{$subnet}/{$sn} ";
162
				} else
163
					$home_net .= "{$subnet} ";
164
			}
165
			if (function_exists("get_interface_ipv6")) {
166
				$subnet = get_interface_ipv6($int);
167
				if (is_ipaddrv6($subnet)) {
168
					if ($whitelist == false) {
169
						$sn = get_interface_subnetv6($int);
170
						$home_net .= "{$subnet}/{$sn} ";
171
					} else
172
						$home_net .= "{$subnet} ";
173
				}
174
			}
175
		} else {
176
			$ifcfg = $config['interfaces'][$int];
177
			switch ($ifcfg['ipaddr']) {
178
			case "pppoe":
179
			case "pptp":
180
			case "l2tp":
181
				if (function_exists('get_interface_ip'))
182
					$subnet = get_interface_ip($int);
183
				else
184
					$subnet = find_interface_ip("ng0");
185

    
186
				if (is_ipaddr($subnet))
187
					$home_net .= "{$subnet} ";
188
				break;
189
			case "dhcp":
190
				$subnet = find_interface_ip(snort_get_real_interface($int));
191
				if (is_ipaddr($subnet))
192
					$home_net .= "{$subnet} ";
193
				break;
194
			default:
195
				if (is_ipaddr($ifcfg['ipaddr'])) {
196
					$home_net .= "{$ifcfg['ipaddr']} ";
197
				}
198
				break;
199
			}
200
		}
201
	}
202

    
203
	if ($wangw == 'yes') {
204
		$gw = get_interface_gateway($snortcfg['interface']);
205
		if (is_ipaddr($gw))
206
			$home_net .= "{$gw} ";
207
		if (function_exists("get_interface_gatewayv6")) {
208
			$gw = get_interface_gatewayv6($snortcfg['interface']);
209
			if (is_ipaddrv6($gw))
210
				$home_net .= "{$gw} ";
211
		}
212
	}
213

    
214
	if ($wandns == 'yes') {
215
		/* Add DNS server for WAN interface to whitelist */
216
		$dns_servers = get_dns_servers();
217
		foreach ($dns_servers as $dns) {
218
			if ($dns)
219
				$home_net .= "{$dns} ";
220
		}
221
	}
222

    
223
	if($vips == 'yes') {
224
		/* iterate all vips and add to whitelist */
225
		if (is_array($config['virtualip']) && is_array($config['virtualip']['vip'])) {
226
			foreach($config['virtualip']['vip'] as $vip) {
227
				if ($vip['subnet'] && $vip['mode'] != 'proxyarp') {
228
					if ($whitelist == false)
229
						$home_net .= "{$vip['subnet']}/{$vip['subnet_bits']} ";
230
					else
231
						$home_net .= "{$vip['subnet']} ";
232
				}
233
			}
234
		}
235
	}
236

    
237
	/* grab a list of vpns and whitelist if user desires added by nestorfish 954 */
238
	if ($vpns == 'yes') {
239
		if ($config['version'] <= 6) // chk what pfsense version were on
240
			$vpns_list = get_vpns_list();
241
		else
242
			$vpns_list = filter_get_vpns_list();
243

    
244
		if (!empty($vpns_list))
245
			$home_net .= "{$vpns_list} ";
246
	}
247

    
248
	$home_net = trim($home_net);
249
	$validator = explode(" ", $home_net);
250
	$valresult = array();
251
	foreach ($validator as $vald) { 
252
		if (empty($vald))
253
			continue;
254
		$vald = trim($vald);
255
		if (empty($valresult[$vald]))
256
			$valresult[$vald] = $vald;
257
	}
258

    
259
	return $valresult;
260
}
261

    
262
/* checks to see if service is running yes/no and stop/start */
263
function snort_is_running($snort_uuid, $if_real, $type = 'snort') {
264
	global $config, $g;
265

    
266
	if (file_exists("{$g['varrun_path']}/{$type}_{$if_real}{$snort_uuid}.pid") && isvalidpid("{$g['varrun_path']}/{$type}_{$if_real}{$snort_uuid}.pid"))
267
		return 'yes';
268

    
269
	return 'no';
270
}
271

    
272
function snort_barnyard_stop($snortcfg, $if_real) {
273
	global $config, $g;
274

    
275
	$snort_uuid = $snortcfg['uuid'];
276
	if (file_exists("{$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid") && isvalidpid("{$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid")) {
277
		killbypid("{$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid");
278
		@unlink("{$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid");
279
	}
280
}
281

    
282
function snort_stop($snortcfg, $if_real) {
283
	global $config, $g;
284

    
285
	$snort_uuid = $snortcfg['uuid'];
286
	if (file_exists("{$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid") && isvalidpid("{$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid")) {
287
		killbypid("{$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid");
288
		exec("/bin/rm {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid");
289
	}
290

    
291
	snort_barnyard_stop($snortcfg, $if_real);
292

    
293
	log_error("Interface Rule STOP for {$snortcfg['descr']}({$if_real})...");
294
}
295

    
296
function snort_barnyard_start($snortcfg, $if_real) {
297
	global $config, $g;
298

    
299
	$snortdir = SNORTDIR;
300
	$snort_uuid = $snortcfg['uuid'];
301

    
302
	/* define snortbarnyardlog_chk */
303
	if ($snortcfg['barnyard_enable'] == 'on' && !empty($snortcfg['barnyard_mysql']))
304
		exec("/usr/local/bin/barnyard2 -r {$snort_uuid} -f \"snort_{$snort_uuid}_{$if_real}.u2\" --pid-path {$g['varrun_path']} --nolock-pidfile -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -d /var/log/snort/snort_{$if_real}{$snort_uuid} -D -q");
305

    
306
}
307

    
308
function snort_start($snortcfg, $if_real) {
309
	global $config, $g;
310

    
311
	$snortdir = SNORTDIR;
312
	$snort_uuid = $snortcfg['uuid'];
313

    
314
	if ($snortcfg['enable'] == 'on')
315
		exec("/usr/local/bin/snort -R {$snort_uuid} -D -q -l /var/log/snort/snort_{$if_real}{$snort_uuid} --pid-path {$g['varrun_path']} --nolock-pidfile -G {$snort_uuid} -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf -i {$if_real}");
316
	else
317
		return;
318

    
319
	snort_barnyard_start($snortcfg, $if_real);
320

    
321
	log_error("Interface Rule START for {$snortcfg['descr']}({$if_real})...");
322
}
323

    
324
function snort_get_friendly_interface($interface) {
325

    
326
	if (function_exists('convert_friendly_interface_to_friendly_descr'))
327
		$iface = convert_friendly_interface_to_friendly_descr($interface);
328
	else {
329
		if (!$interface || ($interface == "wan"))
330
			$iface = "WAN";
331
		else if(strtolower($interface) == "lan")
332
			$iface = "LAN";
333
		else if(strtolower($interface) == "pppoe")
334
			$iface = "PPPoE";
335
		else if(strtolower($interface) == "pptp")
336
			$iface = "PPTP";
337
		else
338
			$iface = strtoupper($interface);
339
	}
340

    
341
	return $iface;
342
}
343

    
344
/* get the real iface name of wan */
345
function snort_get_real_interface($interface) {
346
	global $config;
347

    
348
	$lc_interface = strtolower($interface);
349
	if (function_exists('get_real_interface'))
350
		return get_real_interface($lc_interface);
351
	else {
352
		if ($lc_interface == "lan") {
353
			if ($config['inerfaces']['lan'])
354
				return $config['interfaces']['lan']['if'];
355
			return $interface;
356
		}
357
		if ($lc_interface == "wan")
358
			return $config['interfaces']['wan']['if'];
359
		$ifdescrs = array();
360
		for ($j = 1; isset($config['interfaces']['opt' . $j]); $j++) {
361
			$ifname = "opt{$j}";
362
			if(strtolower($ifname) == $lc_interface)
363
				return $config['interfaces'][$ifname]['if'];
364
			if(isset($config['interfaces'][$ifname]['descr']) && (strtolower($config['interfaces'][$ifname]['descr']) == $lc_interface))
365
				return $config['interfaces'][$ifname]['if'];
366
		}
367
	} 
368

    
369
	return $interface;
370
}
371

    
372
/*
373
 this code block is for deleteing logs while keeping the newest file,
374
 snort is linked to these files while running, do not take the easy way out
375
 by touch and rm, snort will lose sync and not log.
376

    
377
 */
378
function snort_post_delete_logs($snort_uuid = 0) {
379
	global $config, $g;
380

    
381
	/* do not start config build if rules is empty */
382
	if (!is_array($config['installedpackages']['snortglobal']['rule']))
383
		return;
384

    
385
	foreach ($config['installedpackages']['snortglobal']['rule'] as $value) {
386
		if ($value['uuid'] != $snort_uuid)
387
			continue;
388
		$if_real = snort_get_real_interface($value['interface']);
389
		$snort_log_dir = "/var/log/snort/snort_{$if_real}{$snort_uuid}";
390

    
391
		if ($if_real != '') {
392
			$filelist = glob("{$snort_log_dir}/*{$snort_uuid}_{$if_real}.u2.*");
393
			unset($filelist[count($filelist) - 1]);
394
			foreach ($filelist as $file)
395
				@unlink($file);
396

    
397
			if ($value['perform_stat'] == 'on') {
398
				$fd = fopen("{$snort_log_dir}/{$if_real}.stats", "w");
399
				if ($fd) {
400
					ftruncate($fd, 0);
401
					fclose($fd);
402
				}
403
			}
404
		}
405
	}
406
}
407

    
408
function snort_postinstall() {
409
	global $config, $g;
410

    
411
	$snortdir = SNORTDIR;
412

    
413
	/* cleanup default files */
414
	@rename("{$snortdir}/snort.conf-sample", "{$snortdir}/snort.conf");
415
	@rename("{$snortdir}/threshold.conf-sample", "{$snortdir}/threshold.conf");
416
	@rename("{$snortdir}/sid-msg.map-sample", "{$snortdir}/sid-msg.map");
417
	@rename("{$snortdir}/unicode.map-sample", "{$snortdir}/unicode.map");
418
	@rename("{$snortdir}/classification.config-sample", "{$snortdir}/classification.config");
419
	@rename("{$snortdir}/generators-sample", "{$snortdir}/generators");
420
	@rename("{$snortdir}/reference.config-sample", "{$snortdir}/reference.config");
421
	@rename("{$snortdir}/gen-msg.map-sample", "{$snortdir}/gen-msg.map");
422
	@unlink("{$snortdir}/sid");
423
	@unlink("/usr/local/etc/rc.d/snort");
424
	@unlink("/usr/local/etc/rc.d/barnyard2");
425

    
426
	/* remove example files */
427
	if (file_exists('/usr/local/lib/snort/dynamicrules/lib_sfdynamic_example_rule.so.0'))
428
		exec('rm /usr/local/lib/snort/dynamicrules/lib_sfdynamic_example*');
429

    
430
	if (file_exists('/usr/local/lib/snort/dynamicpreprocessor/lib_sfdynamic_preprocessor_example.so'))
431
		exec('/bin/rm /usr/local/lib/snort/dynamicpreprocessor/lib_sfdynamic_preprocessor_example*');
432

    
433
	/*
434
	mwexec("/usr/sbin/chown -R snort:snort /var/log/snort", true);
435
	mwexec("/usr/sbin/chown -R snort:snort {$snortdir}", true);
436
	mwexec('/usr/sbin/chown -R snort:snort /usr/local/lib/snort', true);
437
	mwexec('/usr/sbin/chown snort:snort /tmp/snort*', true);
438
	*/
439

    
440
	/* remake saved settings */
441
	if ($config['installedpackages']['snortglobal']['forcekeepsettings'] == 'on') {
442
		update_status(gettext("Saved settings detected..."));
443
		update_output_window(gettext("Please wait... rebuilding files..."));
444
		sync_snort_package_config();
445
		update_output_window(gettext("Finnished Rebuilding files..."));
446
	}
447
}
448

    
449
function snort_Getdirsize($node) {
450
	if(!is_readable($node))
451
		return false;
452

    
453
	$blah = exec( "/usr/bin/du -kd $node" );
454
	return substr( $blah, 0, strpos($blah, 9) );
455
}
456

    
457
/* func for log dir size limit cron */
458
function snort_snortloglimit_install_cron($should_install) {
459
	global $config, $g;
460

    
461
	if (!is_array($config['cron']['item']))
462
		$config['cron']['item'] = array();
463

    
464
	$x=0;
465
	$is_installed = false;
466
	foreach($config['cron']['item'] as $item) {
467
		if (strstr($item['command'], 'snort_check_cron_misc.inc')) {
468
			$is_installed = true;
469
			break;
470
		}
471
		$x++;
472
	}
473

    
474
	switch($should_install) {
475
		case true:
476
			if(!$is_installed)  {
477

    
478
				$cron_item = array();
479
				$cron_item['minute'] = "*/5";
480
				$cron_item['hour'] = "*";
481
				$cron_item['mday'] = "*";
482
				$cron_item['month'] = "*";
483
				$cron_item['wday'] = "*";
484
				$cron_item['who'] = "root";
485
				$cron_item['command'] = "/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/snort/snort_check_cron_misc.inc";
486
				$config['cron']['item'][] = $cron_item;
487
			}
488
			break;
489
		case false:
490
			if($is_installed == true)
491
				unset($config['cron']['item'][$x]);
492
			break;
493
	}
494
}
495

    
496
/* func for updating cron */
497
function snort_rm_blocked_install_cron($should_install) {
498
	global $config, $g;
499

    
500
	if (!is_array($config['cron']['item']))
501
		$config['cron']['item'] = array();
502

    
503
	$x=0;
504
	$is_installed = false;
505
	foreach($config['cron']['item'] as $item) {
506
		if (strstr($item['command'], "snort2c")) {
507
			$is_installed = true;
508
			break;
509
		}
510
		$x++;
511
	}
512

    
513
	$snort_rm_blocked_info_ck = $config['installedpackages']['snortglobal']['rm_blocked'];
514
	if ($snort_rm_blocked_info_ck == "1h_b") {
515
		$snort_rm_blocked_min = "*/5";
516
		$snort_rm_blocked_hr = "*";
517
		$snort_rm_blocked_mday = "*";
518
		$snort_rm_blocked_month = "*";
519
		$snort_rm_blocked_wday = "*";
520
		$snort_rm_blocked_expire = "3600";
521
	}
522
	if ($snort_rm_blocked_info_ck == "3h_b") {
523
		$snort_rm_blocked_min = "*/15";
524
		$snort_rm_blocked_hr = "*";
525
		$snort_rm_blocked_mday = "*";
526
		$snort_rm_blocked_month = "*";
527
		$snort_rm_blocked_wday = "*";
528
		$snort_rm_blocked_expire = "10800";
529
	}
530
	if ($snort_rm_blocked_info_ck == "6h_b") {
531
		$snort_rm_blocked_min = "*/30";
532
		$snort_rm_blocked_hr = "*";
533
		$snort_rm_blocked_mday = "*";
534
		$snort_rm_blocked_month = "*";
535
		$snort_rm_blocked_wday = "*";
536
		$snort_rm_blocked_expire = "21600";
537
	}
538
	if ($snort_rm_blocked_info_ck == "12h_b") {
539
		$snort_rm_blocked_min = "2";
540
		$snort_rm_blocked_hr = "*/1";
541
		$snort_rm_blocked_mday = "*";
542
		$snort_rm_blocked_month = "*";
543
		$snort_rm_blocked_wday = "*";
544
		$snort_rm_blocked_expire = "43200";
545
	}
546
	if ($snort_rm_blocked_info_ck == "1d_b") {
547
		$snort_rm_blocked_min = "2";
548
		$snort_rm_blocked_hr = "*/2";
549
		$snort_rm_blocked_mday = "*";
550
		$snort_rm_blocked_month = "*";
551
		$snort_rm_blocked_wday = "*";
552
		$snort_rm_blocked_expire = "86400";
553
	}
554
	if ($snort_rm_blocked_info_ck == "4d_b") {
555
		$snort_rm_blocked_min = "2";
556
		$snort_rm_blocked_hr = "*/8";
557
		$snort_rm_blocked_mday = "*";
558
		$snort_rm_blocked_month = "*";
559
		$snort_rm_blocked_wday = "*";
560
		$snort_rm_blocked_expire = "345600";
561
	}
562
	if ($snort_rm_blocked_info_ck == "7d_b") {
563
		$snort_rm_blocked_min = "2";
564
		$snort_rm_blocked_hr = "*/14";
565
		$snort_rm_blocked_mday = "*";
566
		$snort_rm_blocked_month = "*";
567
		$snort_rm_blocked_wday = "*";
568
		$snort_rm_blocked_expire = "604800";
569
	}
570
	if ($snort_rm_blocked_info_ck == "28d_b") {
571
		$snort_rm_blocked_min = "2";
572
		$snort_rm_blocked_hr = "0";
573
		$snort_rm_blocked_mday = "*/2";
574
		$snort_rm_blocked_month = "*";
575
		$snort_rm_blocked_wday = "*";
576
		$snort_rm_blocked_expire = "2419200";
577
	}
578
	switch($should_install) {
579
	case true:
580
		if(!$is_installed) {
581
			$cron_item = array();
582
			$cron_item['minute'] = "$snort_rm_blocked_min";
583
			$cron_item['hour'] = "$snort_rm_blocked_hr";
584
			$cron_item['mday'] = "$snort_rm_blocked_mday";
585
			$cron_item['month'] = "$snort_rm_blocked_month";
586
			$cron_item['wday'] = "$snort_rm_blocked_wday";
587
			$cron_item['who'] = "root";
588
			$cron_item['command'] = "/usr/bin/nice -n20 /usr/local/sbin/expiretable -t $snort_rm_blocked_expire snort2c";
589
			$config['cron']['item'][] = $cron_item;
590
		}
591
		break;
592
	case false:
593
		if ($is_installed == true)
594
			unset($config['cron']['item'][$x]);
595
		break;
596
	}
597
}
598

    
599
/* func to install snort update */
600
function snort_rules_up_install_cron($should_install) {
601
	global $config, $g;
602

    
603
	if(!$config['cron']['item'])
604
		$config['cron']['item'] = array();
605

    
606
	$x=0;
607
	$is_installed = false;
608
	foreach($config['cron']['item'] as $item) {
609
		if (strstr($item['command'], "snort_check_for_rule_updates.php")) {
610
			$is_installed = true;
611
			break;
612
		}
613
		$x++;
614
	}
615
	$snort_rules_up_info_ck = $config['installedpackages']['snortglobal']['autorulesupdate7'];
616
	if ($snort_rules_up_info_ck == "6h_up") {
617
		$snort_rules_up_min = "3";
618
		$snort_rules_up_hr = "*/6";
619
		$snort_rules_up_mday = "*";
620
		$snort_rules_up_month = "*";
621
		$snort_rules_up_wday = "*";
622
	}
623
	if ($snort_rules_up_info_ck == "12h_up") {
624
		$snort_rules_up_min = "3";
625
		$snort_rules_up_hr = "*/12";
626
		$snort_rules_up_mday = "*";
627
		$snort_rules_up_month = "*";
628
		$snort_rules_up_wday = "*";
629
	}
630
	if ($snort_rules_up_info_ck == "1d_up") {
631
		$snort_rules_up_min = "3";
632
		$snort_rules_up_hr = "0";
633
		$snort_rules_up_mday = "*/1";
634
		$snort_rules_up_month = "*";
635
		$snort_rules_up_wday = "*";
636
	}
637
	if ($snort_rules_up_info_ck == "4d_up") {
638
		$snort_rules_up_min = "3";
639
		$snort_rules_up_hr = "0";
640
		$snort_rules_up_mday = "*/4";
641
		$snort_rules_up_month = "*";
642
		$snort_rules_up_wday = "*";
643
	}
644
	if ($snort_rules_up_info_ck == "7d_up") {
645
		$snort_rules_up_min = "3";
646
		$snort_rules_up_hr = "0";
647
		$snort_rules_up_mday = "*/7";
648
		$snort_rules_up_month = "*";
649
		$snort_rules_up_wday = "*";
650
	}
651
	if ($snort_rules_up_info_ck == "28d_up") {
652
		$snort_rules_up_min = "3";
653
		$snort_rules_up_hr = "0";
654
		$snort_rules_up_mday = "*/28";
655
		$snort_rules_up_month = "*";
656
		$snort_rules_up_wday = "*";
657
	}
658
	switch($should_install) {
659
	case true:
660
		if(!$is_installed) {
661
			$cron_item = array();
662
			$cron_item['minute'] = "$snort_rules_up_min";
663
			$cron_item['hour'] = "$snort_rules_up_hr";
664
			$cron_item['mday'] = "$snort_rules_up_mday";
665
			$cron_item['month'] = "$snort_rules_up_month";
666
			$cron_item['wday'] = "$snort_rules_up_wday";
667
			$cron_item['who'] = "root";
668
			$cron_item['command'] = "/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/snort/snort_check_for_rule_updates.php >> /tmp/snort_update.log";
669
			$config['cron']['item'][] = $cron_item;
670
		}
671
		break;
672
	case false:
673
		if($is_installed == true)
674
			unset($config['cron']['item'][$x]);
675
		break;
676
	}
677
}
678

    
679
/* Only run when all ifaces needed to sync. Expects filesystem rw */
680
function sync_snort_package_config() {
681
	global $config, $g;
682

    
683
	conf_mount_rw();
684

    
685
	/* do not start config build if rules is empty */
686
	if (!is_array($config['installedpackages']['snortglobal']['rule'])) {
687
		exec('/bin/rm /usr/local/etc/rc.d/snort.sh');
688
		conf_mount_ro();
689
		return;
690
	}
691

    
692
	$snortconf = $config['installedpackages']['snortglobal']['rule'];
693
	foreach ($snortconf as $value) {
694
		$if_real = snort_get_real_interface($value['interface']);
695

    
696
		/* create snort configuration file */
697
		snort_generate_conf($value);
698

    
699
		/* create barnyard2 configuration file */
700
		if ($value['barnyard_enable'] == 'on')
701
			snort_create_barnyard2_conf($value, $if_real);
702
	}
703

    
704
	/* create snort bootup file snort.sh only create once */
705
	snort_create_rc();
706

    
707
	$snortglob = $config['installedpackages']['snortglobal'];
708

    
709
	snort_snortloglimit_install_cron($snortglob['snortloglimit'] == 'on' ? true : false);
710

    
711
	/* set the snort block hosts time IMPORTANT */
712
	snort_rm_blocked_install_cron($snortglob['rm_blocked'] != "never_b" ? true : false);
713

    
714
	/* set the snort rules update time */
715
	snort_rules_up_install_cron($snortglob['autorulesupdate7'] != "never_up" ? true : false);
716

    
717
	configure_cron();
718

    
719
	conf_mount_ro();
720
}
721

    
722
/* Start of main config files */
723
/* open snort.sh for writing" */
724
function snort_create_rc() {
725
	global $config, $g;
726

    
727
	$snortdir = SNORTDIR;
728

    
729
	if (!is_array($config['installedpackages']['snortglobal']['rule']))
730
		return;
731

    
732
	$snortconf =& $config['installedpackages']['snortglobal']['rule'];
733
	/* do not start config build if rules is empty */
734
	if (empty($snortconf))
735
		return;
736

    
737
	$start_snort_iface_start = array();
738
	$start_snort_iface_stop = array();
739
	foreach ($snortconf as $value) {
740
		$snort_uuid = $value['uuid'];
741
		$if_real = snort_get_real_interface($value['interface']);
742

    
743
		$start_barnyard = <<<EOE
744

    
745
	if [ ! -f {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid ]; then
746
		/bin/pgrep -xf '/usr/local/bin/barnyard2 -r {$snort_uuid} -f snort_{$snort_uuid}_{$if_real}.u2 --pid-path {$g['varrun_path']} --nolock-pidfile -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -d /var/log/snort/snort_{$if_real}{$snort_uuid} -D -q' > {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid
747
	fi
748
	/bin/pgrep -F {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid
749
	if [ $? = 0 ]; then
750
		/bin/pkill -HUP -F {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid -a
751
	else
752
		/usr/local/bin/barnyard2 -r {$snort_uuid} -f snort_{$snort_uuid}_{$if_real}.u2 --pid-path {$g['varrun_path']} --nolock-pidfile -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -d /var/log/snort/snort_{$if_real}{$snort_uuid} -D -q
753
	fi
754

    
755
EOE;
756
		$stop_barnyard2 = <<<EOE
757

    
758
	if [ -f {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid ]; then
759
                /bin/pkill -F {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid -a
760
		/bin/rm /var/run/barnyard2_{$if_real}{$snort_uuid}.pid
761
	else
762
		/bin/pkill -xf '/usr/local/bin/barnyard2 -r {$snort_uuid} -f snort_{$snort_uuid}_{$if_real}.u2 --pid-path {$g['varrun_path']} --nolock-pidfile -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -d /var/log/snort/snort_{$if_real}{$snort_uuid} -D -q'
763
        fi
764

    
765
EOE;
766
		if ($value['barnyard_enable'] == 'on' && !empty($value['barnyard_mysql']))
767
			$start_barnyard2 = $start_barnyard;
768
		else
769
			$start_barnyard2 = $stop_barnyard2;
770

    
771
		$start_snort_iface_start[] = <<<EOE
772

    
773
###### For Each Iface
774
#### Only try to restart if snort is running on Iface
775
	if [ ! -f {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid ]; then
776
		/bin/pgrep -xf '/usr/local/bin/snort -R {$snort_uuid} -D -q -l /var/log/snort/snort_{$if_real}{$snort_uuid} --pid-path {$g['varrun_path']} --nolock-pidfile -G {$snort_uuid} -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf -i {$if_real}' > {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid
777
	fi
778
	/bin/pgrep -nF {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid
779
	if [ $? = 0 ]; then
780
		/bin/pkill -HUP -F {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid -a
781
		/usr/bin/logger -p daemon.info -i -t SnortStartup "Snort SOFT START For {$value['descr']}({$snort_uuid}_{$if_real})..."
782
	else
783
		# Start snort and barnyard2
784
		/bin/rm {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid
785
		/usr/local/bin/snort -R {$snort_uuid} -D -q -l /var/log/snort/snort_{$if_real}{$snort_uuid} --pid-path {$g['varrun_path']} --nolock-pidfile -G {$snort_uuid} -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf -i {$if_real}
786
		/usr/bin/logger -p daemon.info -i -t SnortStartup "Snort START For {$value['descr']}({$snort_uuid}_{$if_real})..."
787
	fi
788

    
789
	sleep 2
790
	{$start_barnyard2}
791

    
792
EOE;
793

    
794
		$start_snort_iface_stop[] = <<<EOE
795

    
796
	/usr/bin/logger -p daemon.info -i -t SnortStartup "Snort STOP For {$value['descr']}({$snort_uuid}_{$if_real})..."
797
	if [ -f {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid ]; then
798
		/bin/pkill -F {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid -a
799
		/bin/rm /var/run/snort_{$if_real}{$snort_uuid}.pid
800
	else 
801
		/bin/pkill -xf '/usr/local/bin/snort -R {$snort_uuid} -D -q -l /var/log/snort/snort_{$if_real}{$snort_uuid} --pid-path {$g['varrun_path']} --nolock-pidfile -G {$snort_uuid} -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf -i {$if_real}'
802
	fi
803

    
804
	sleep 2
805
	{$stop_barnyard2}
806

    
807
EOE;
808
	}
809

    
810
	$rc_start = implode("\n", $start_snort_iface_start);
811
	$rc_stop = implode("\n", $start_snort_iface_stop);
812

    
813
	$snort_sh_text = <<<EOD
814
#!/bin/sh
815
########
816
# This file was automatically generated
817
# by the pfSense service handler.
818
# Code added to protect from double starts on pfSense bootup
819
######## Begining of Main snort.sh
820

    
821
rc_start() {
822
	{$rc_start}
823
}
824

    
825
rc_stop() {
826
	{$rc_stop}
827
}
828

    
829
case $1 in
830
	start)
831
		rc_start
832
		;;
833
	stop)
834
		rc_stop
835
		;;
836
	restart)
837
		rc_start
838
		;;
839
esac
840

    
841
EOD;
842

    
843
	/* write out snort.sh */
844
	if (!@file_put_contents("/usr/local/etc/rc.d/snort.sh", $snort_sh_text)) {
845
		log_error("Could not open /usr/local/etc/rc.d/snort.sh for writing.");
846
		return;
847
	}
848
	@chmod("/usr/local/etc/rc.d/snort.sh", 0755);
849
}
850

    
851
/* open barnyard2.conf for writing */
852
function snort_create_barnyard2_conf($snortcfg, $if_real) {
853
	global $config, $g;
854

    
855
	$snortdir = SNORTDIR;
856
	$snort_uuid = $snortcfg['uuid'];
857

    
858
	if (!file_exists("{$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf"))
859
		exec("/usr/bin/touch {$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf");
860

    
861
	if (!file_exists("/var/log/snort/snort_{$if_real}{$snort_uuid}/barnyard2/{$snort_uuid}_{$if_real}.waldo")) {
862
		@touch("/var/log/snort/snort_{$if_real}{$snort_uuid}/barnyard2/{$snort_uuid}_{$if_real}.waldo");
863
		mwexec("/bin/chmod 770 /var/log/snort/barnyard2/{$snort_uuid}_{$if_real}.waldo", true);
864
	}
865

    
866
	$barnyard2_conf_text = snort_generate_barnyard2_conf($snortcfg, $if_real);
867

    
868
	/* write out barnyard2_conf */
869
	@file_put_contents("{$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf", $barnyard2_conf_text);
870
}
871

    
872
/* open barnyard2.conf for writing" */
873
function snort_generate_barnyard2_conf($snortcfg, $if_real) {
874
	global $config, $g;
875

    
876
	$snortdir = SNORTDIR;
877
	$snort_uuid = $snortcfg['uuid'];
878

    
879
	/* TODO: add support for the other 5 output plugins */
880
	$snortbarnyardlog_database_info_chk = $snortcfg['barnyard_mysql'];
881
	$snortbarnyardlog_hostname_info_chk = php_uname("n");
882
	/* user add arguments */
883
	$snortbarnyardlog_config_pass_thru = str_replace("\r", "", base64_decode($snortcfg['barnconfigpassthru']));
884

    
885
	$barnyard2_conf_text = <<<EOD
886

    
887
#	barnyard2.conf
888
#   barnyard2 can be found at http://www.securixlive.com/barnyard2/index.php
889
#
890
# set the appropriate paths to the file(s) your Snort process is using
891

    
892
config reference_file:	    {$snortdir}/snort_{$snort_uuid}_{$if_real}/reference.config
893
config classification_file: {$snortdir}/snort_{$snort_uuid}_{$if_real}/classification.config
894
config gen_file:            {$snortdir}/snort_{$snort_uuid}_{$if_real}/gen-msg.map
895
config sid_file:	        {$snortdir}/snort_{$snort_uuid}_{$if_real}/sid-msg.map
896

    
897
config hostname:       $snortbarnyardlog_hostname_info_chk
898
config interface:      {$if_real}
899
config decode_data_link
900
config waldo_file: /var/log/snort/snort_{$if_real}{$snort_uuid}/barnyard2/{$snort_uuid}_{$if_real}.waldo
901

    
902
## START user pass through ##
903

    
904
	{$snortbarnyardlog_config_pass_thru}
905

    
906
## END user pass through ##
907

    
908
# Step 2: setup the input plugins
909
input unified2
910

    
911
config logdir: /var/log/snort/snort_{$if_real}{$snort_uuid}
912

    
913
# database: log to a variety of databases
914
# output database: log, mysql, user=xxxx password=xxxxxx dbname=xxxx host=xxx.xxx.xxx.xxxx
915

    
916
	$snortbarnyardlog_database_info_chk
917

    
918
EOD;
919

    
920
	return $barnyard2_conf_text;
921
}
922

    
923
function snort_deinstall() {
924
	global $config, $g;
925

    
926
	$snortdir = SNORTDIR;
927
	$snortlogdir = SNORTLOGDIR;
928

    
929
	/* decrease bpf buffers back to 4096, from 20480 */
930
	mwexec('/usr/bin/killall snort', true);
931
	sleep(2);
932
	mwexec('/usr/bin/killall -9 snort', true);
933
	sleep(2);
934
	mwexec('/usr/bin/killall barnyard2', true);
935
	sleep(2);
936
	mwexec('/usr/bin/killall -9 barnyard2', true);
937
	sleep(2);
938
	mwexec('/usr/sbin/pw userdel snort; /usr/sbin/pw groupdel snort', true);
939

    
940
	if (!function_exists("get_interface_ipv6")) {
941
		/* create a few directories and ensure the sample files are in place */
942
		$snort_dirs = array( $snortdir, $snortlogdir,
943
			"dynamicrules" => "/usr/local/lib/snort/dynamicrules",
944
			"dynamicengine" => "/usr/local/lib/snort/dynamicengine",
945
			"dynamicpreprocessor" => "/usr/local/lib/snort/dynamicpreprocessor"
946
		    );
947
		foreach ($snort_dirs as $dir) {
948
			if (is_dir($dir))
949
				mwexec("/bin/rm -rf {$dir}", true);
950
		}
951
	}
952

    
953
	/* Remove snort cron entries Ugly code needs smoothness*/
954
	if (!function_exists('snort_deinstall_cron')) {
955
		function snort_deinstall_cron($crontask) {
956
			global $config, $g;
957

    
958
			if(!is_array($config['cron']['item']))
959
				return;
960

    
961
			$x=0;
962
			$is_installed = false;
963
			foreach($config['cron']['item'] as $item) {
964
				if (strstr($item['command'], $crontask)) {
965
					$is_installed = true;
966
					break;
967
				}
968
				$x++;
969
			}
970
			if ($is_installed == true)
971
				unset($config['cron']['item'][$x]);
972
		}
973
	}
974

    
975
	snort_deinstall_cron("snort2c");
976
	snort_deinstall_cron("snort_check_for_rule_updates.php");
977
	snort_deinstall_cron("snort_check_cron_misc.inc");
978
	configure_cron();
979

    
980
	/* Keep this as a last step */
981
	if ($config['installedpackages']['snortglobal']['forcekeepsettings'] != 'on')
982
		unset($config['installedpackages']['snortglobal']);
983
}
984

    
985
function snort_generate_conf($snortcfg) {
986
	global $config, $g;
987

    
988
	$snortdir = SNORTDIR;
989
	$snortlogdir = SNORTLOGDIR;
990

    
991
	if (!is_array($config['installedpackages']['snortglobal']['rule']))
992
		return;
993

    
994
	$if_real = snort_get_real_interface($snortcfg['interface']);
995
	$snort_uuid = $snortcfg['uuid'];
996
	$snortcfgdir = "{$snortdir}/snort_{$snort_uuid}_{$if_real}";
997

    
998
	/* custom home nets */
999
	$home_net_list = snort_build_list($snortcfg, $snortcfg['homelistname']);
1000
	$home_net = implode(",", $home_net_list);
1001

    
1002
	$external_net = '!$HOME_NET';
1003
	if (!empty($snortcfg['externallistname']) && $snortcfg['externallistname'] != 'default') {
1004
		$external_net_list = snort_build_list($snortcfg, $snortcfg['externallistname']);
1005
		$external_net = implode(",", $external_net_list);
1006
	}
1007

    
1008
	/* user added arguments */
1009
	$snort_config_pass_thru = str_replace("\r", "", base64_decode($snortcfg['configpassthru']));
1010

    
1011
	/* create a few directories and ensure the sample files are in place */
1012
	$snort_dirs = array( $snortdir, $snortcfgdir, "{$snortcfgdir}/rules",
1013
		"{$snortlogdir}/snort_{$if_real}{$snort_uuid}",
1014
		"{$snortlogdir}/snort_{$if_real}{$snort_uuid}/barnyard2", 
1015
		"{$snortcfgdir}/preproc_rules", 
1016
		"dynamicrules" => "{$snortcfgdir}/dynamicrules",
1017
		"dynamicengine" => "/usr/local/lib/snort/dynamicengine",
1018
		"dynamicpreprocessor" => "{$snortcfgdir}/dynamicpreprocessor"
1019
	    );
1020
	foreach ($snort_dirs as $dir) {
1021
		if (!is_dir($dir))
1022
			safe_mkdir($dir);
1023
	}
1024

    
1025
	$snort_files = array("gen-msg.map", "classification.config", "reference.config",
1026
			"sid-msg.map", "unicode.map", "threshold.conf", "preproc_rules/preprocessor.rules",
1027
			"preproc_rules/decoder.rules", "preproc_rules/sensitive-data.rules"
1028
		);
1029
	foreach ($snort_files as $file) {
1030
		if (file_exists("{$snortdir}/{$file}"))
1031
			@copy("{$snortdir}/{$file}", "{$snortcfgdir}/{$file}");
1032
	}
1033

    
1034
	/* define alertsystemlog */
1035
	$alertsystemlog_type = "";
1036
	if ($snortcfg['alertsystemlog'] == "on")
1037
		$alertsystemlog_type = "output alert_syslog: log_alert";
1038

    
1039
	/* define snortunifiedlog */
1040
	$snortunifiedlog_type = "";
1041
	if ($snortcfg['snortunifiedlog'] == "on")
1042
		$snortunifiedlog_type = "output unified2: filename snort_{$snort_uuid}_{$if_real}.u2, limit 128";
1043

    
1044
	/* define spoink */
1045
	$spoink_type = "";
1046
	if ($snortcfg['blockoffenders7'] == "on") {
1047
		$pfkill = "";
1048
		if ($snortcfg['blockoffenderskill'] == "on")
1049
			$pfkill = "kill";
1050
		/* No subnets to default addresses */
1051
		$spoink_wlist = snort_build_list($snortcfg, $snortcfg['whitelistname'], true);
1052
		/* write whitelist */
1053
		@file_put_contents("{$snortcfgdir}/{$snortcfg['whitelistname']}", implode("\n", $spoink_wlist));
1054
		$spoink_type = "output alert_pf: {$snortcfgdir}/{$snortcfg['whitelistname']},snort2c,{$snortcfg['blockoffendersip']},{$pfkill}";
1055
	}
1056

    
1057
	/* define selected suppress file */
1058
	$suppress_file_name = "";
1059
	$suppress = snort_find_list($snortcfg['suppresslistname'], 'suppress');
1060
	if (!empty($suppress)) {
1061
		$suppress_data = str_replace("\r", "", base64_decode($suppress['suppresspassthru']));
1062
		@file_put_contents("{$snortcfgdir}/supp{$snortcfg['suppresslistname']}", $suppress_data);
1063
		$suppress_file_name = "include {$snortcfgdir}/supp{$snortcfg['suppresslistname']}";
1064
	}
1065

    
1066
	/* set the snort performance model */
1067
	$snort_performance = "ac-bnfa";
1068
	if(!empty($snortcfg['performance']))
1069
		$snort_performance = $snortcfg['performance'];
1070

    
1071
	/* if user has defined a custom ssh port, use it */
1072
	if(is_array($config['system']['ssh']) && isset($config['system']['ssh']['port']))
1073
		$ssh_port = $config['system']['ssh']['port'];
1074
	else
1075
		$ssh_port = "22";
1076
	$snort_ports = array(
1077
		"dns_ports" => "53", "smtp_ports" => "25", "mail_ports" => "25,143,465,691",
1078
		"http_ports" => "80", "oracle_ports" => "1521", "mssql_ports" => "1433",
1079
		"telnet_ports" => "23","snmp_ports" => "161", "ftp_ports" => "21",
1080
		"ssh_ports" => $ssh_port, "pop2_ports" => "109", "pop3_ports" => "110", 
1081
		"imap_ports" => "143", "sip_proxy_ports" => "5060:5090,16384:32768",
1082
		"sip_ports" => "5060:5090,16384:32768", "auth_ports" => "113", "finger_ports" => "79", 
1083
		"irc_ports" => "6665,6666,6667,6668,6669,7000", "smb_ports" => "139,445",
1084
		"nntp_ports" => "119", "rlogin_ports" => "513", "rsh_ports" => "514",
1085
		"ssl_ports" => "443,465,563,636,989,990,992,993,994,995",
1086
		"file_data_ports" => "\$HTTP_PORTS,110,143", "shellcode_ports" => "!80", 
1087
		"sun_rpc_ports" => "111,32770,32771,32772,32773,32774,32775,32776,32777,32778,32779",
1088
		"DCERPC_NCACN_IP_TCP" => "139,445", "DCERPC_NCADG_IP_UDP" => "138,1024:",
1089
		"DCERPC_NCACN_IP_LONG" => "135,139,445,593,1024:", "DCERPC_NCACN_UDP_LONG" => "135,1024:",
1090
		"DCERPC_NCACN_UDP_SHORT" => "135,593,1024:", "DCERPC_NCACN_TCP" => "2103,2105,2107",
1091
		"DCERPC_BRIGHTSTORE" => "6503,6504"
1092
	);
1093

    
1094
	$portvardef = "";
1095
	foreach ($snort_ports as $alias => $avalue) {
1096
		if (!empty($snortcfg["def_{$alias}"]) && is_alias($snortcfg["def_{$alias}"]))
1097
			$snort_ports[$alias] = filter_expand_alias($snortcfg["def_{$alias}"]);
1098
			$snort_ports[$alias] = str_replace(" ", ",", trim($snort_ports[$alias]));
1099
		$portvardef .= "portvar " . strtoupper($alias) . " [" . $snort_ports[$alias] . "]\n";
1100
	}
1101

    
1102

    
1103
	/////////////////////////////
1104
	/* preprocessor code */
1105
	/* def perform_stat */
1106
	$perform_stat = <<<EOD
1107
# Performance Statistics #
1108
preprocessor perfmonitor: time 300 file {$snortlogdir}/snort_{$if_real}{$snort_uuid}/{$if_real}.stats pktcnt 10000
1109
	
1110
EOD;
1111

    
1112
	$def_flow_depth_type = '0';
1113
	if (!empty($snortcfg['flow_depth']))
1114
		$def_flow_depth_type = $snortcfg['flow_depth'];
1115

    
1116
	$http_ports = str_replace(",", " ", $snort_ports['http_ports']);
1117
	/* def http_inspect */
1118
	$http_inspect = <<<EOD
1119
# HTTP Inspect  #
1120
preprocessor http_inspect: global iis_unicode_map unicode.map 1252 compress_depth 65535 decompress_depth 65535
1121

    
1122
preprocessor http_inspect_server: server default \
1123
                        ports  { {$http_ports} }  \
1124
                        non_strict \
1125
                        non_rfc_char  { 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 }  \
1126
                        flow_depth {$def_flow_depth_type}  \
1127
                        apache_whitespace no \
1128
                        directory no \
1129
                        iis_backslash no \
1130
                        u_encode yes \
1131
			extended_response_inspection \
1132
			inspect_gzip \
1133
			normalize_utf \
1134
			normalize_javascript \
1135
			unlimited_decompress \
1136
                        ascii no \
1137
                        chunk_length 500000 \
1138
                        bare_byte yes \
1139
                        double_decode yes \
1140
                        iis_unicode no \
1141
                        iis_delimiter no \
1142
                        multi_slash no
1143
	
1144
EOD;
1145

    
1146
	/* def ftp_preprocessor */
1147
	$ftp_preprocessor = <<<EOD
1148
# ftp preprocessor  #
1149
preprocessor ftp_telnet: global \
1150
inspection_type stateless
1151

    
1152
preprocessor ftp_telnet_protocol: telnet \
1153
   normalize \
1154
   ayt_attack_thresh 200
1155

    
1156
preprocessor ftp_telnet_protocol: \
1157
    ftp server default \
1158
    def_max_param_len 100 \
1159
    ports { 21 } \
1160
    ftp_cmds { USER PASS ACCT CWD SDUP SMNT QUIT REIN PORT PASV TYPE STRU MODE } \
1161
    ftp_cmds { RETR STOR STOU APPE ALLO REST RNFR RNTO ABOR DELE RMD MKD PWD } \
1162
    ftp_cmds { LIST NLST SITE SYST STAT HELP NOOP } \
1163
    ftp_cmds { AUTH ADAT PROT PBSZ CONF ENC } \
1164
    ftp_cmds { FEAT CEL CMD MACB } \
1165
    ftp_cmds { MDTM REST SIZE MLST MLSD } \
1166
    ftp_cmds { XPWD XCWD XCUP XMKD XRMD TEST CLNT } \
1167
    alt_max_param_len 0 { CDUP QUIT REIN PASV STOU ABOR PWD SYST NOOP } \
1168
    alt_max_param_len 100 { MDTM CEL XCWD SITE USER PASS REST DELE RMD SYST TEST STAT MACB EPSV CLNT LPRT } \
1169
    alt_max_param_len 200 { XMKD NLST ALLO STOU APPE RETR STOR CMD RNFR HELP } \
1170
    alt_max_param_len 256 { RNTO CWD } \
1171
    alt_max_param_len 400 { PORT } \
1172
    alt_max_param_len 512 { SIZE } \
1173
    chk_str_fmt { USER PASS ACCT CWD SDUP SMNT PORT TYPE STRU MODE } \
1174
    chk_str_fmt { RETR STOR STOU APPE ALLO REST RNFR RNTO DELE RMD MKD } \
1175
    chk_str_fmt { LIST NLST SITE SYST STAT HELP } \
1176
    chk_str_fmt { AUTH ADAT PROT PBSZ CONF ENC } \
1177
    chk_str_fmt { FEAT CEL CMD } \
1178
    chk_str_fmt { MDTM REST SIZE MLST MLSD } \
1179
    chk_str_fmt { XPWD XCWD XCUP XMKD XRMD TEST CLNT } \
1180
    cmd_validity MODE < char ASBCZ > \
1181
    cmd_validity STRU < char FRP > \
1182
    cmd_validity ALLO < int [ char R int ] > \
1183
    cmd_validity TYPE < { char AE [ char NTC ] | char I | char L [ number ] } > \
1184
    cmd_validity MDTM < [ date nnnnnnnnnnnnnn[.n[n[n]]] ] string > \
1185
    cmd_validity PORT < host_port >
1186

    
1187
preprocessor ftp_telnet_protocol: ftp client default \
1188
   max_resp_len 256 \
1189
   bounce yes \
1190
   telnet_cmds yes
1191
	
1192
EOD;
1193

    
1194
	$pop_ports = str_replace(",", " ", $snort_ports['pop3_ports']);
1195
	$pop_preproc = <<<EOD
1196
preprocessor pop: \
1197
	ports { {$pop_ports} } \
1198
        memcap 1310700 \
1199
	qp_decode_depth 0 \
1200
	b64_decode_depth 0 \
1201
	bitenc_decode_depth 0
1202
EOD;
1203

    
1204
	$imap_ports = str_replace(",", " ", $snort_ports['imap_ports']);
1205
	$imap_preproc = <<<EOD
1206
preprocessor imap: \
1207
	ports { {$imap_ports} } \
1208
        memcap 1310700 \
1209
	qp_decode_depth 0 \
1210
	b64_decode_depth 0 \
1211
	bitenc_decode_depth 0
1212
EOD;
1213

    
1214
	$smtp_ports = str_replace(",", " ", $snort_ports['mail_ports']);
1215
	/* def smtp_preprocessor */
1216
	$smtp_preprocessor = <<<EOD
1217
# SMTP preprocessor #
1218
preprocessor SMTP: \
1219
    ports { {$smtp_ports} } \
1220
    inspection_type stateful \
1221
    normalize cmds \
1222
    ignore_tls_data \
1223
    valid_cmds { MAIL RCPT HELP HELO ETRN EHLO EXPN VRFY ATRN SIZE BDAT DEBUG EMAL ESAM ESND ESOM EVFY IDENT NOOP RSET SEND SAML SOML AUTH TURN ETRN PIPELINING \
1224
CHUNKING DATA DSN RSET QUIT ONEX QUEU STARTTLS TICK TIME TURNME VERB X-EXPS X-LINK2STATE XADR XAUTH XCIR XEXCH50 XGEN XLICENSE XQUEU XSTA XTRN XUSR } \
1225
    normalize_cmds { MAIL RCPT HELP HELO ETRN EHLO EXPN VRFY ATRN SIZE BDAT DEBUG EMAL ESAM ESND ESOM EVFY IDENT NOOP RSET SEND SAML SOML AUTH TURN ETRN \
1226
PIPELINING CHUNKING DATA DSN RSET QUIT ONEX QUEU STARTTLS TICK TIME TURNME VERB X-EXPS X-LINK2STATE XADR XAUTH XCIR XEXCH50 XGEN XLICENSE XQUEU XSTA XTRN XUSR } \
1227
    max_header_line_len 1000 \ 
1228
    max_response_line_len 512 \
1229
    alt_max_command_line_len 260 { MAIL } \
1230
    alt_max_command_line_len 300 { RCPT } \
1231
    alt_max_command_line_len 500 { HELP HELO ETRN EHLO } \
1232
    alt_max_command_line_len 255 { EXPN VRFY ATRN SIZE BDAT DEBUG EMAL ESAM ESND ESOM EVFY IDENT NOOP RSET } \
1233
    alt_max_command_line_len 246 { SEND SAML SOML AUTH TURN ETRN PIPELINING CHUNKING DATA DSN RSET QUIT ONEX } \
1234
    alt_max_command_line_len 246 { QUEU STARTTLS TICK TIME TURNME VERB X-EXPS X-LINK2STATE XADR } \
1235
    alt_max_command_line_len 246 { XAUTH XCIR XEXCH50 XGEN XLICENSE XQUEU XSTA XTRN XUSR } \
1236
    xlink2state { enable } \
1237
    log_mailfrom \
1238
    log_rcptto \
1239
    log_email_hdrs \
1240
    email_hdrs_log_depth 1464 \
1241
    log_filename \
1242
    qp_decode_depth 0 \
1243
    b64_decode_depth 0 \
1244
    bitenc_decode_depth 0
1245

    
1246
EOD;
1247

    
1248
	/* def sf_portscan */
1249
	$sf_portscan = <<<EOD
1250
# sf Portscan  #
1251
preprocessor sfportscan: scan_type { all } \
1252
                         proto  { all } \
1253
                         memcap { 10000000 } \
1254
                         sense_level { medium } \
1255
                         ignore_scanners { \$HOME_NET }
1256
	
1257
EOD;
1258

    
1259
	$sun_rpc_ports = str_replace(",", " ", $snort_ports['sun_rpc_ports']);
1260
	/* def other_preprocs */
1261
	$other_preprocs = <<<EOD
1262

    
1263
# Other preprocs #
1264
preprocessor rpc_decode: {$sun_rpc_ports}
1265

    
1266
# Back Orifice
1267
preprocessor bo
1268
	
1269
EOD;
1270

    
1271
	/* def dce_rpc_2 */
1272
	$dce_rpc_2 = <<<EOD
1273
# DCE/RPC 2   #
1274
preprocessor dcerpc2: memcap 102400, events [smb, co, cl]
1275
preprocessor dcerpc2_server: default, policy WinXP, \
1276
    detect [smb [{$snort_ports['smb_ports']}], tcp 135, udp 135, rpc-over-http-server 593], \
1277
    autodetect [tcp 1025:, udp 1025:, rpc-over-http-server 1025:], \
1278
    smb_max_chain 3
1279
	
1280
EOD;
1281

    
1282
	$dns_ports = str_replace(",", " ", $snort_ports['dns_ports']);
1283
	/* def dns_preprocessor */
1284
	$dns_preprocessor = <<<EOD
1285
# DNS preprocessor #
1286
preprocessor dns: \
1287
    ports { {$dns_ports} } \
1288
    enable_rdata_overflow
1289
	
1290
EOD;
1291

    
1292
	$def_ssl_ports_ignore = str_replace(",", " ", $snort_ports['ssl_ports']);
1293
	$ssl_preproc = <<<EOD
1294
# Ignore SSL and Encryption  #
1295
preprocessor ssl: ports { {$def_ssl_ports_ignore} }, trustservers, noinspect_encrypted
1296

    
1297
EOD;
1298

    
1299
	$sensitive_data = "preprocessor sensitive_data:\n";
1300

    
1301
	/* stream5 queued settings */
1302
	$def_max_queued_bytes_type = '';
1303
	if (!empty($snortcfg['max_queued_bytes']))
1304
		$def_max_queued_bytes_type = ", max_queued_bytes {$snortcfg['max_queued_bytes']}";
1305

    
1306
	$def_max_queued_segs_type = '';
1307
	if (!empty($snortcfg['max_queued_segs']))
1308
		$def_max_queued_segs_type = ", max_queued_segs {$snortcfg['max_queued_segs']}";
1309

    
1310
	/* define servers and ports snortdefservers */
1311
	$snort_servers = array (
1312
		"dns_servers" => "\$HOME_NET", "smtp_servers" => "\$HOME_NET", "http_servers" => "\$HOME_NET",
1313
		"www_servers" => "\$HOME_NET", "sql_servers" => "\$HOME_NET", "telnet_servers" => "\$HOME_NET",
1314
		"snmp_servers" => "\$HOME_NET", "ftp_servers" => "\$HOME_NET", "ssh_servers" => "\$HOME_NET",
1315
		"pop_servers" => "\$HOME_NET", "imap_servers" => "\$HOME_NET", "sip_proxy_ip" => "\$HOME_NET",
1316
		"sip_servers" => "\$HOME_NET", "rpc_servers" => "\$HOME_NET",
1317
		"aim_servers" => "64.12.24.0/23,64.12.28.0/23,64.12.161.0/24,64.12.163.0/24,64.12.200.0/24,205.188.3.0/24,205.188.5.0/24,205.188.7.0/24,205.188.9.0/24,205.188.153.0/24,205.188.179.0/24,205.188.248.0/24"
1318
	    );
1319

    
1320
	$vardef = "";
1321
	foreach ($snort_servers as $alias => $avalue) {
1322
		if (!empty($snortcfg["def_{$alias}"]) && is_alias($snortcfg["def_{$alias}"])) {
1323
			$avalue = filter_expand_alias($snortcfg["def_{$alias}"]);
1324
			$avalue = str_replace(" ", ",", trim($avalue));
1325
		}
1326
		$vardef .= "var " . strtoupper($alias) . " [{$avalue}]\n";
1327
	}
1328

    
1329
	$snort_preproc_libs = array(
1330
		"dce_rpc_2" => "dce2_preproc", "dns_preprocessor" => "dns_preproc", "ftp_preprocessor" => "ftptelnet_preproc", "imap_preproc" => "imap_preproc",
1331
		"pop_preproc" => "pop_preproc", "reputation_preproc" => "reputation_preproc", "sensitive_data" => "sdf_preproc", 
1332
		"sip_preproc" => "sip_preproc", "smtp_preprocessor" => "smtp_preproc", "ssh_preproc" => "ssh_preproc", 
1333
		"ssl_preproc" => "ssl_preproc"
1334
	);
1335
	$snort_preproc = array (
1336
		"perform_stat", "http_inspect", "other_preprocs", "ftp_preprocessor", "smtp_preprocessor", "ssl_preproc",
1337
		"sf_portscan", "dce_rpc_2", "dns_preprocessor", "sensitive_data", "pop_preproc", "imap_preproc"
1338
	);
1339
	$snort_preprocessors = "";
1340
	foreach ($snort_preproc as $preproc) {
1341
		if ($snortcfg[$preproc] == 'on') {
1342
			/* NOTE: The $$ is not a bug. Its a advanced feature of php */
1343
			if (!empty($snort_preproc_libs[$preproc])) {
1344
				$preproclib = "libsf_" . $snort_preproc_libs[$preproc];
1345
				if (!file_exists($snort_dirs['dynamicpreprocessor'] . "{$preproclib}.so")) {
1346
					if (file_exists("/usr/local/lib/snort/dynamicpreprocessor/{$preproclib}.so")) {
1347
						@copy("/usr/local/lib/snort/dynamicpreprocessor/{$preproclib}.so", "{$snort_dirs['dynamicpreprocessor']}/{$preproclib}.so");
1348
						$snort_preprocessors .= $$preproc;
1349
						$snort_preprocessors .= "\n";
1350
					}
1351
				} else {
1352
					$snort_preprocessors .= $$preproc;
1353
					$snort_preprocessors .= "\n";
1354
				}
1355
			} else {
1356
				$snort_preprocessors .= $$preproc;
1357
				$snort_preprocessors .= "\n";
1358
			}
1359
		}
1360
	}
1361

    
1362
	$snort_misc_include_rules = "";
1363
	if (file_exists("{$snortcfgdir}/reference.config"))
1364
		$snort_misc_include_rules .= "include {$snortcfgdir}/reference.config\n";
1365
	if (file_exists("{$snortcfgdir}/classification.config"))
1366
		$snort_misc_include_rules .= "include {$snortcfgdir}/classification.config\n";
1367
	if (is_dir("{$snortcfgdir}/preproc_rules")) {
1368
		if ($snortcfg['sensitive_data'] == 'on') {
1369
			$sedcmd = '/^#alert.*classtype:sdf/s/^#//';
1370
			if (file_exists("{$snortcfgdir}/preproc_rules/sensitive-data.rules"))
1371
				$snort_misc_include_rules .= "include \$PREPROC_RULE_PATH/sensitive-data.rules\n";
1372
		} else
1373
			$sedcmd = '/^alert.*classtype:sdf/s/^/#/';
1374
		if (file_exists("{$snortcfgdir}/preproc_rules/decoder.rules") &&
1375
		    file_exists("{$snortcfgdir}/preproc_rules/preprocessor.rules")) {
1376
			@file_put_contents("{$g['tmp_path']}/sedcmd", $sedcmd);
1377
			mwexec("/usr/bin/sed -I '' -f {$g['tmp_path']}/sedcmd {$snortcfgdir}/preproc_rules/preprocessor.rules");
1378
			mwexec("/usr/bin/sed -I '' -f {$g['tmp_path']}/sedcmd {$snortcfgdir}/preproc_rules/decoder.rules");
1379
			@unlink("{$g['tmp_path']}/sedcmd");
1380

    
1381
			$snort_misc_include_rules .= "include \$PREPROC_RULE_PATH/decoder.rules\n";
1382
			$snort_misc_include_rules .= "include \$PREPROC_RULE_PATH/preprocessor.rules\n";
1383
		} else {
1384
			$snort_misc_include_rules .= "config autogenerate_preprocessor_decoder_rules\n";
1385
			log_error("Seems preprocessor/decoder rules are missing, enabling autogeneration of them");
1386
		}
1387
	} else {
1388
		$snort_misc_include_rules .= "config autogenerate_preprocessor_decoder_rules\n";
1389
		log_error("Seems preprocessor/decoder rules are missing, enabling autogeneration of them");
1390
	}
1391

    
1392
	/* generate rule sections to load */
1393
	$selected_rules_sections = "";
1394
	$dynamic_rules_sections = "";
1395
	if (!empty($snortcfg['rulesets'])) {
1396
		$enabled_rulesets_array = explode("||", $snortcfg['rulesets']);
1397
		foreach($enabled_rulesets_array as $enabled_item) {
1398
			if (file_exists("{$snortdir}/rules/{$enabled_item}") && !file_exists("{$snortcfgdir}/rules/{$enabled_item}"))
1399
				@copy("{$snortdir}/rules/{$enabled_item}", "{$snortcfgdir}/rules/{$enabled_item}");
1400
			if (substr($enabled_item, 0, 5) == "snort" && substr($enabled_item, -9) == ".so.rules") {
1401
				$slib = substr($enabled_item, 6, -6);
1402
				if (!file_exists("{$snort_dirs['dynamicrules']}/{$slib}"))
1403
					@copy("/usr/local/lib/snort/dynamicrules/{$slib}", "{$snort_dirs['dynamicrules']}/{$slib}");
1404
				if (file_exists("{$snort_dirs['dynamicrules']}/{$slib}") && 
1405
				    file_exists("{$snortcfgdir}/rules/{$enabled_item}"))
1406
					$selected_rules_sections  .= "include \$RULE_PATH/{$enabled_item}\n";
1407
			} else if (file_exists("{$snortcfgdir}/rules/{$enabled_item}"))
1408
				$selected_rules_sections  .= "include \$RULE_PATH/{$enabled_item}\n";
1409
		}
1410
	}
1411

    
1412
	if (!empty($snortcfg['customrules'])) {
1413
		@file_put_contents("{$snortcfgdir}/rules/custom.rules", base64_decode($snortcfg['customrules']));
1414
		$selected_rules_sections  .= "include \$RULE_PATH/custom.rules\n";
1415
	} else
1416
		@unlink("{$snortcfgdir}/rules/custom.rules");
1417

    
1418
	$cksumcheck = "all";
1419
	if ($snortcfg['cksumcheck'] == 'on')
1420
		$cksumcheck = "none";
1421

    
1422
	/* build snort configuration file */
1423
	$snort_conf_text = <<<EOD
1424

    
1425
# snort configuration file
1426
# generated automatically by the pfSense subsystems do not modify manually
1427

    
1428
# Define Local Network  #
1429
var HOME_NET [{$home_net}]
1430
var EXTERNAL_NET [{$external_net}]
1431

    
1432
# Define Rule Paths #
1433
var RULE_PATH {$snortcfgdir}/rules
1434
var PREPROC_RULE_PATH {$snortcfgdir}/preproc_rules
1435

    
1436
# Define Servers  #
1437
{$vardef}
1438

    
1439
# Define Server Ports  #
1440
{$portvardef}
1441

    
1442
# Configure the snort decoder  #
1443
config checksum_mode: {$cksumcheck}
1444
config disable_decode_alerts
1445
config disable_tcpopt_experimental_alerts
1446
config disable_tcpopt_obsolete_alerts
1447
config disable_ttcp_alerts
1448
config disable_tcpopt_alerts
1449
config disable_ipopt_alerts
1450
config disable_decode_drops
1451

    
1452
# Configure the detection engine  #
1453
config detection: search-method {$snort_performance} max_queue_events 5
1454
config event_queue: max_queue 8 log 3 order_events content_length
1455

    
1456
#Configure dynamic loaded libraries
1457
dynamicpreprocessor directory {$snort_dirs['dynamicpreprocessor']}
1458
dynamicengine directory {$snort_dirs['dynamicengine']}
1459
dynamicdetection directory {$snort_dirs['dynamicrules']}
1460

    
1461
# Flow and stream #
1462
preprocessor frag3_global: max_frags 8192
1463
preprocessor frag3_engine: policy bsd detect_anomalies
1464

    
1465
preprocessor stream5_global: track_tcp yes, track_udp yes, track_icmp yes
1466
preprocessor stream5_tcp: policy BSD, ports both all{$def_max_queued_bytes_type}{$def_max_queued_segs_type}
1467
preprocessor stream5_udp:
1468
preprocessor stream5_icmp:
1469

    
1470
{$snort_preprocessors}
1471

    
1472
# Snort Output Logs #
1473
output alert_csv: alert timestamp,sig_generator,sig_id,sig_rev,msg,proto,src,srcport,dst,dstport,id,classification,priority
1474
{$alertsystemlog_type}
1475
{$snortunifiedlog_type}
1476
{$spoink_type}
1477
						
1478
# Misc Includes #
1479
{$snort_misc_include_rules}
1480

    
1481
{$suppress_file_name}
1482

    
1483
# Snort user pass through configuration
1484
{$snort_config_pass_thru}
1485

    
1486
# Rules Selection #
1487
{$selected_rules_sections}
1488

    
1489
EOD;
1490

    
1491
	/* write out snort.conf */
1492
	$conf = fopen("{$snortcfgdir}/snort.conf", "w");
1493
	if(!$conf) {
1494
		log_error("Could not open {$snortcfgdir}/snort.conf for writing.");
1495
		return -1;
1496
	}
1497
	fwrite($conf, $snort_conf_text);
1498
	fclose($conf);
1499
}
1500

    
1501
?>
    (1-1/1)