Projet

Général

Profil

Télécharger (14,4 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / filter_log.inc @ 0b857543

1 af8ae7ce jim-p
<?php
2
/* $Id$ */
3
/*
4 c0b6fdde jim-p
	filter_log.inc
5 af8ae7ce jim-p
	part of pfSesne by Scott Ullrich
6
	originally based on m0n0wall (http://m0n0.ch/wall)
7
8
	Copyright (C) 2009 Jim Pingle <myfirstname>@<mylastname>.org
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 7ac5a4cb Scott Ullrich
/*
33 2a50fd8a Renato Botelho
	pfSense_BUILDER_BINARIES:	/usr/sbin/fifolog_reader	/usr/bin/tail	/usr/local/sbin/clog
34 7ac5a4cb Scott Ullrich
	pfSense_MODULE:	filter
35
*/
36 af8ae7ce jim-p
37 2c97c5d9 jim-p
require 'config.inc';
38
39 472455e8 jim-p
global $buffer_rules_rdr, $buffer_rules_normal;
40
$buffer_rules_rdr = array();
41
$buffer_rules_normal = array();
42
43 af8ae7ce jim-p
/* format filter logs */
44 90763c7f PiBa-NL
function conv_log_filter($logfile, $nentries, $tail = 50, $filtertext = "", $filterinterface = null) {
45 af8ae7ce jim-p
	global $config, $g;
46
47
	/* Make sure this is a number before using it in a system call */
48
	if (!(is_numeric($tail)))
49
		return;
50
51 c0b6fdde jim-p
	if ($filtertext)
52
		$tail = 5000;
53
54 af8ae7ce jim-p
	/* Always do a reverse tail, to be sure we're grabbing the 'end' of the log. */
55
	$logarr = "";
56
57 c0b6fdde jim-p
	if(isset($config['system']['usefifolog']))
58 115b7b81 Renato Botelho
		exec("/usr/sbin/fifolog_reader " . escapeshellarg($logfile) . " | /usr/bin/grep 'filterlog:' | /usr/bin/tail -r -n {$tail}", $logarr);
59 af8ae7ce jim-p
	else
60 2a50fd8a Renato Botelho
		exec("/usr/local/sbin/clog " . escapeshellarg($logfile) . " | grep -v \"CLOG\" | grep -v \"\033\" | /usr/bin/grep 'filterlog:' | /usr/bin/tail -r -n {$tail}", $logarr);
61 af8ae7ce jim-p
62
	$filterlog = array();
63
	$counter = 0;
64
65 90763c7f PiBa-NL
	$filterinterface = strtoupper($filterinterface);
66 af8ae7ce jim-p
	foreach ($logarr as $logent) {
67
		if($counter >= $nentries)
68
			break;
69
70
		$flent = parse_filter_line($logent);
71 90763c7f PiBa-NL
		if (!$filterinterface || ($filterinterface == $flent['interface']))
72
		{
73 cd8155b1 N0YB
			if ( ( ($flent != "") && (!is_array($filtertext)) && (match_filter_line ($flent, $filtertext))) || 
74
			     ( ($flent != "") && ( is_array($filtertext)) && (match_filter_field($flent, $filtertext)) ) ) {
75 90763c7f PiBa-NL
				$counter++;
76
				$filterlog[] = $flent;
77
			}
78 af8ae7ce jim-p
		}
79
	}
80
	/* Since the lines are in reverse order, flip them around if needed based on the user's preference */
81
	return isset($config['syslog']['reverse']) ? $filterlog : array_reverse($filterlog);
82
}
83
84 c4107752 Phil Davis
function escape_filter_regex($filtertext) {
85
	/* If the caller (user) has not already put a backslash before a slash, to escape it in the regex, */
86
	/* then this will do it. Take out any "\/" already there, then turn all ordinary "/" into "\/".  */
87
	return str_replace('/', '\/', str_replace('\/', '/', $filtertext));
88
}
89
90 c0b6fdde jim-p
function match_filter_line($flent, $filtertext = "") {
91
	if (!$filtertext)
92
		return true;
93 c4107752 Phil Davis
	$filtertext = escape_filter_regex(str_replace(' ', '\s+', $filtertext));
94
	return @preg_match("/{$filtertext}/i", implode(" ", array_values($flent)));
95 c0b6fdde jim-p
}
96
97 cd8155b1 N0YB
function match_filter_field($flent, $fields) {
98 939f4e39 Renato Botelho
	foreach ($fields as $key => $field) {
99
		if ($field == "All")
100
			continue;
101 0b857543 Phil Davis
		if ((strpos($field, '!') === 0)) {
102 939f4e39 Renato Botelho
			$field = substr($field, 1);
103
			if (strtolower($key) == 'act') {
104
				if (in_arrayi($flent[$key], explode(" ", $field)))
105
					return false;
106 c4107752 Phil Davis
			} else {
107 939f4e39 Renato Botelho
				$field_regex = escape_filter_regex($field);
108
				if (@preg_match("/{$field_regex}/i", $flent[$key]))
109 c4107752 Phil Davis
					return false;
110
			}
111 939f4e39 Renato Botelho
		} else {
112
			if (strtolower($key) == 'act') {
113
				if (!in_arrayi($flent[$key], explode(" ", $field)))
114
					return false;
115 c4107752 Phil Davis
			} else {
116 939f4e39 Renato Botelho
				$field_regex = escape_filter_regex($field);
117
				if (!@preg_match("/{$field_regex}/i", $flent[$key]))
118 c4107752 Phil Davis
					return false;
119
			}
120 74c6d36f N0YB
		}
121 939f4e39 Renato Botelho
	}
122 cd8155b1 N0YB
	return true;
123
}
124
125
// Case Insensitive in_array function
126
function in_arrayi($needle, $haystack) {
127 115b7b81 Renato Botelho
	return in_array(strtolower($needle), array_map('strtolower', $haystack));
128 ab046d5a jim-p
}
129
130 af8ae7ce jim-p
function parse_filter_line($line) {
131
	global $config, $g;
132
133 115b7b81 Renato Botelho
	$flent = array();
134
	$log_split = "";
135 af8ae7ce jim-p
136 115b7b81 Renato Botelho
	if (!preg_match("/(.*)\s(.*)\sfilterlog:\s(.*)$/", $line, $log_split))
137
		return "";
138 c0b6fdde jim-p
139 115b7b81 Renato Botelho
	list($all, $flent['time'], $host, $rule) = $log_split;
140 c0b6fdde jim-p
141 115b7b81 Renato Botelho
	$rule_data = explode(",", $rule);
142
	$field = 0;
143 c0b6fdde jim-p
144 115b7b81 Renato Botelho
	$flent['rulenum'] = $rule_data[$field++];
145
	$flent['subrulenum'] = $rule_data[$field++];
146
	$flent['anchor'] = $rule_data[$field++];
147
	$flent['tracker'] = $rule_data[$field++];
148
	$flent['realint'] = $rule_data[$field++];
149 eb0facb8 jim-p
	$flent['interface']  = convert_real_interface_to_friendly_descr($flent['realint']);
150 115b7b81 Renato Botelho
	$flent['reason'] = $rule_data[$field++];
151
	$flent['act'] = $rule_data[$field++];
152
	$flent['direction'] = $rule_data[$field++];
153
	$flent['version'] = $rule_data[$field++];
154
155
	if ($flent['version'] == '4' || $flent['version'] == '6') {
156
		if ($flent['version'] == '4') {
157
			$flent['tos'] = $rule_data[$field++];
158
			$flent['ecn'] = $rule_data[$field++];
159
			$flent['ttl'] = $rule_data[$field++];
160
			$flent['id'] = $rule_data[$field++];
161
			$flent['offset'] = $rule_data[$field++];
162
			$flent['flags'] = $rule_data[$field++];
163
			$flent['protoid'] = $rule_data[$field++];
164
			$flent['proto'] = strtoupper($rule_data[$field++]);
165
		} else {
166
			$flent['class'] = $rule_data[$field++];
167
			$flent['flowlabel'] = $rule_data[$field++];
168
			$flent['hlim'] = $rule_data[$field++];
169
			$flent['proto'] = $rule_data[$field++];
170
			$flent['protoid'] = $rule_data[$field++];
171
		}
172 af8ae7ce jim-p
173 115b7b81 Renato Botelho
		$flent['length'] = $rule_data[$field++];
174
		$flent['srcip'] = $rule_data[$field++];
175
		$flent['dstip'] = $rule_data[$field++];
176
177
		if ($flent['protoid'] == '6' || $flent['protoid'] == '17') { // TCP or UDP
178
			$flent['srcport'] = $rule_data[$field++];
179
			$flent['dstport'] = $rule_data[$field++];
180
181
			$flent['src'] = $flent['srcip'] . ':' . $flent['srcport'];
182
			$flent['dst'] = $flent['dstip'] . ':' . $flent['dstport'];
183
184
			$flent['datalen'] = $rule_data[$field++];
185
			if ($flent['protoid'] == '6') { // TCP
186
				$flent['tcpflags'] = $rule_data[$field++];
187
				$flent['seq'] = $rule_data[$field++];
188
				$flent['ack'] = $rule_data[$field++];
189
				$flent['window'] = $rule_data[$field++];
190
				$flent['urg'] = $rule_data[$field++];
191
				$flent['options'] = explode(";",$rule_data[$field++]);
192
			}
193 efa26483 Renato Botelho
		} else if ($flent['protoid'] == '1') { // ICMP
194
			$flent['src'] = $flent['srcip'];
195
			$flent['dst'] = $flent['dstip'];
196
197
			$flent['icmp_type'] = $rule_data[$field++];
198
199
			switch ($flent['icmp_type']) {
200
			case "request":
201
			case "reply":
202
				$flent['icmp_id'] = $rule_data[$field++];
203
				$flent['icmp_seq'] = $rule_data[$field++];
204
				break;
205
			case "unreachproto":
206
				$flent['icmp_dstip'] = $rule_data[$field++];
207
				$flent['icmp_protoid'] = $rule_data[$field++];
208
				break;
209
			case "unreachport":
210
				$flent['icmp_dstip'] = $rule_data[$field++];
211
				$flent['icmp_protoid'] = $rule_data[$field++];
212
				$flent['icmp_port'] = $rule_data[$field++];
213
				break;
214
			case "unreach":
215
			case "timexceed":
216
			case "paramprob":
217
			case "redirect":
218
			case "maskreply":
219
				$flent['icmp_descr'] = $rule_data[$field++];
220
				break;
221
			case "needfrag":
222
				$flent['icmp_dstip'] = $rule_data[$field++];
223
				$flent['icmp_mtu'] = $rule_data[$field++];
224
				break;
225
			case "tstamp":
226
				$flent['icmp_id'] = $rule_data[$field++];
227
				$flent['icmp_seq'] = $rule_data[$field++];
228
				break;
229
			case "tstampreply":
230
				$flent['icmp_id'] = $rule_data[$field++];
231
				$flent['icmp_seq'] = $rule_data[$field++];
232
				$flent['icmp_otime'] = $rule_data[$field++];
233
				$flent['icmp_rtime'] = $rule_data[$field++];
234
				$flent['icmp_ttime'] = $rule_data[$field++];
235
				break;
236
			default :
237
				$flent['icmp_descr'] = $rule_data[$field++];
238
				break;
239
			}
240
241 115b7b81 Renato Botelho
		} else if ($flent['protoid'] == '112') { // CARP
242
			$flent['type'] = $rule_data[$field++];
243
			$flent['ttl'] = $rule_data[$field++];
244
			$flent['vhid'] = $rule_data[$field++];
245
			$flent['version'] = $rule_data[$field++];
246
			$flent['advskew'] = $rule_data[$field++];
247
			$flent['advbase'] = $rule_data[$field++];
248 fb6079db jim-p
		}
249 115b7b81 Renato Botelho
	} else {
250
		if($g['debug'])
251
			log_error(sprintf(gettext("There was a error parsing rule number: %s.   Please report to mailing list or forum."), $flent['rulenum']));
252
		return "";
253 af8ae7ce jim-p
	}
254
255
	/* If there is a src, a dst, and a time, then the line should be usable/good */
256
	if (!((trim($flent['src']) == "") || (trim($flent['dst']) == "") || (trim($flent['time']) == ""))) {
257
		return $flent;
258
	} else {
259
		if($g['debug']) {
260 8abd095a Carlos Eduardo Ramos
			log_error(sprintf(gettext("There was a error parsing rule: %s.   Please report to mailing list or forum."), $errline));
261 af8ae7ce jim-p
		}
262
		return "";
263
	}
264
}
265
266 c0b6fdde jim-p
function get_port_with_service($port, $proto) {
267
	if (!$port)
268
		return '';
269
270
	$service = getservbyport($port, $proto);
271
	$portstr = "";
272
	if ($service) {
273 addc0439 Renato Botelho
		$portstr = sprintf('<span title="' . gettext('Service %1$s/%2$s: %3$s') . '">' . htmlspecialchars($port) . '</span>', $port, $proto, $service);
274 c0b6fdde jim-p
	} else {
275
		$portstr = htmlspecialchars($port);
276 af8ae7ce jim-p
	}
277 c0b6fdde jim-p
	return ':' . $portstr;
278 af8ae7ce jim-p
}
279
280 481b97b0 jim-p
function find_rule_by_number($rulenum, $trackernum, $type="block") {
281 b80e29e4 Ermal
	global $g;
282
283 af8ae7ce jim-p
	/* Passing arbitrary input to grep could be a Very Bad Thing(tm) */
284 481b97b0 jim-p
	if (!is_numeric($rulenum) || !is_numeric($trackernum) || !in_array($type, array('pass', 'block', 'match', 'rdr')))
285 af8ae7ce jim-p
		return;
286 481b97b0 jim-p
287
	if ($trackernum == "0")
288
		$lookup_pattern = "^@{$rulenum}\([0-9]+\)[[:space:]]{$type}[[:space:]].*[[:space:]]log[[:space:]]";
289
	else
290
		$lookup_pattern = "^@[0-9]+\({$trackernum}\)[[:space:]]{$type}[[:space:]].*[[:space:]]log[[:space:]]";
291
292 af8ae7ce jim-p
	/* At the moment, miniupnpd is the only thing I know of that
293
	   generates logging rdr rules */
294 b80e29e4 Ermal
	unset($buffer);
295 af8ae7ce jim-p
	if ($type == "rdr")
296 ec26979b jim-p
		$_gb = exec("/sbin/pfctl -vvPsn -a \"miniupnpd\" | /usr/bin/egrep " . escapeshellarg("^@{$rulenum}"), $buffer);
297 b80e29e4 Ermal
	else {
298
		if (file_exists("{$g['tmp_path']}/rules.debug"))
299 481b97b0 jim-p
			$_gb = exec("/sbin/pfctl -vvPnf {$g['tmp_path']}/rules.debug 2>/dev/null | /usr/bin/egrep " . escapeshellarg($lookup_pattern), $buffer);
300 b80e29e4 Ermal
		else
301 ec26979b jim-p
			$_gb = exec("/sbin/pfctl -vvPsr | /usr/bin/egrep " . escapeshellarg($lookup_pattern), $buffer);
302 b80e29e4 Ermal
	}
303
	if (is_array($buffer))
304
		return $buffer[0];
305
306
	return "";
307 af8ae7ce jim-p
}
308
309 a6d5e043 PiBa-NL
function buffer_rules_load() {
310 115b7b81 Renato Botelho
	global $g, $buffer_rules_rdr, $buffer_rules_normal;
311 b80e29e4 Ermal
	unset($buffer, $buffer_rules_rdr, $buffer_rules_normal);
312 472455e8 jim-p
	/* Redeclare globals after unset to work around PHP */
313
	global $buffer_rules_rdr, $buffer_rules_normal;
314 b80e29e4 Ermal
	$buffer_rules_rdr = array();
315
	$buffer_rules_normal = array();
316
317
	$_gb = exec("/sbin/pfctl -vvPsn -a \"miniupnpd\" | grep '^@'", $buffer);
318
	if (is_array($buffer)) {
319
		foreach ($buffer as $line) {
320
			list($key, $value) = explode (" ", $line, 2);
321
			$buffer_rules_rdr[$key] = $value;
322
		}
323
	}
324
	unset($buffer, $_gb);
325
	if (file_exists("{$g['tmp_path']}/rules.debug"))
326 481b97b0 jim-p
		$_gb = exec("/sbin/pfctl -vvPnf {$g['tmp_path']}/rules.debug 2>/dev/null | /usr/bin/egrep '^@[0-9]+\([0-9]+\)[[:space:]].*[[:space:]]log[[:space:]]' | /usr/bin/egrep -v '^@[0-9]+\([0-9]+\)[[:space:]](nat|rdr|binat|no|scrub)'", $buffer);
327 b80e29e4 Ermal
	else
328 481b97b0 jim-p
		$_gb = exec("/sbin/pfctl -vvPsr | /usr/bin/egrep '^@[0-9]+\([0-9]+\)[[:space:]].*[[:space:]]log[[:space:]]'", $buffer);
329
330 b80e29e4 Ermal
	if (is_array($buffer)) {
331
		foreach ($buffer as $line) {
332
			list($key, $value) = explode (" ", $line, 2);
333 481b97b0 jim-p
			# pfctl rule number output with tracker number: @dd(dddddddddd)
334
			$matches = array();
335
			if (preg_match('/\@(?P<rulenum>\d+)\((?<trackernum>\d+)\)/', $key, $matches) == 1) {
336
				if ($matches['trackernum'] > 0)
337
					$key = $matches['trackernum'];
338
				else
339
					$key = "@{$matches['rulenum']}";
340
			}
341 b80e29e4 Ermal
			$buffer_rules_normal[$key] = $value;
342
		}
343
	}
344
	unset($_gb, $buffer);
345 a6d5e043 PiBa-NL
}
346
347
function buffer_rules_clear() {
348
	unset($GLOBALS['buffer_rules_normal']);
349
	unset($GLOBALS['buffer_rules_rdr']);
350
}
351
352 481b97b0 jim-p
function find_rule_by_number_buffer($rulenum, $trackernum, $type){
353 115b7b81 Renato Botelho
	global $g, $buffer_rules_rdr, $buffer_rules_normal;
354 481b97b0 jim-p
355
	if ($trackernum == "0")
356
		$lookup_key = "@{$rulenum}";
357
	else
358
		$lookup_key = $trackernum;
359
360 52b27268 PiBa-NL
	if ($type == "rdr")	{
361 481b97b0 jim-p
		$ruleString = $buffer_rules_rdr[$lookup_key];
362 a6d5e043 PiBa-NL
		//TODO: get the correct 'description' part of a RDR log line. currently just first 30 characters..
363
		$rulename = substr($ruleString,0,30);
364
	} else {
365 481b97b0 jim-p
		$ruleString = $buffer_rules_normal[$lookup_key];
366 a6d5e043 PiBa-NL
		list(,$rulename,) = explode("\"",$ruleString);
367 52b27268 PiBa-NL
		$rulename = str_replace("USER_RULE: ",'<img src="/themes/'.$g['theme'].'/images/icons/icon_frmfld_user.png" width="11" height="12" title="USER_RULE" alt="USER_RULE"/> ',$rulename);
368 a6d5e043 PiBa-NL
	}
369 481b97b0 jim-p
	return "{$rulename} ({$lookup_key})";
370 a6d5e043 PiBa-NL
}
371
372 af8ae7ce jim-p
function find_action_image($action) {
373
	global $g;
374
	if ((strstr(strtolower($action), "p")) || (strtolower($action) == "rdr"))
375
		return "/themes/{$g['theme']}/images/icons/icon_pass.gif";
376
	else if(strstr(strtolower($action), "r"))
377
		return "/themes/{$g['theme']}/images/icons/icon_reject.gif";
378
	else
379
		return "/themes/{$g['theme']}/images/icons/icon_block.gif";
380
}
381
382
/* AJAX specific handlers */
383
function handle_ajax($nentries, $tail = 50) {
384
	global $config;
385
	if($_GET['lastsawtime'] or $_POST['lastsawtime']) {
386
		global $filter_logfile,$filterent;
387
		if($_GET['lastsawtime'])
388
			$lastsawtime = $_GET['lastsawtime'];
389
		if($_POST['lastsawtime'])
390
			$lastsawtime = $_POST['lastsawtime'];
391
		/*  compare lastsawrule's time stamp to filter logs.
392
		 *  afterwards return the newer records so that client
393 115b7b81 Renato Botelho
		 *  can update AJAX interface screen.
394 af8ae7ce jim-p
		 */
395
		$new_rules = "";
396
		$filterlog = conv_log_filter($filter_logfile, $nentries, $tail);
397
		/* We need this to always be in forward order for the AJAX update to work properly */
398
		$filterlog = isset($config['syslog']['reverse']) ? array_reverse($filterlog) : $filterlog;
399
		foreach($filterlog as $log_row) {
400 3b3170d0 jim-p
			$row_time = strtotime($log_row['time']);
401 af8ae7ce jim-p
			$img = "<img border='0' src='" . find_action_image($log_row['act']) . "' alt={$log_row['act']} title={$log_row['act']} />";
402
			if($row_time > $lastsawtime) {
403
				if ($log_row['proto'] == "TCP")
404
					$log_row['proto'] .= ":{$log_row['tcpflags']}";
405
406
				$img = "<a href=\"#\" onClick=\"javascript:getURL('diag_logs_filter.php?getrulenum={$log_row['rulenum']},{$log_row['rulenum']}', outputrule);\">{$img}</a>";
407 9486a580 N0YB
				$new_rules .= "{$img}||{$log_row['time']}||{$log_row['interface']}||{$log_row['srcip']}||{$log_row['dst']}||{$log_row['proto']}||" . time() . "||\n";
408 af8ae7ce jim-p
			}
409
		}
410
		echo $new_rules;
411
		exit;
412
	}
413
}
414
415 22599010 Seth Mos
?>