Project

General

Profile

Download (13.9 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * notices.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2005 Colin Smith (ethethlay@gmail.com)
7
 * Copyright (c) 2005-2016 Rubicon Communications, LLC (Netgate)
8
 * All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions are met:
12
 *
13
 * 1. Redistributions of source code must retain the above copyright notice,
14
 *    this list of conditions and the following disclaimer.
15
 *
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in
18
 *    the documentation and/or other materials provided with the
19
 *    distribution.
20
 *
21
 * 3. All advertising materials mentioning features or use of this software
22
 *    must display the following acknowledgment:
23
 *    "This product includes software developed by the pfSense Project
24
 *    for use in the pfSense® software distribution. (http://www.pfsense.org/).
25
 *
26
 * 4. The names "pfSense" and "pfSense Project" must not be used to
27
 *    endorse or promote products derived from this software without
28
 *    prior written permission. For written permission, please contact
29
 *    coreteam@pfsense.org.
30
 *
31
 * 5. Products derived from this software may not be called "pfSense"
32
 *    nor may "pfSense" appear in their names without prior written
33
 *    permission of the Electric Sheep Fencing, LLC.
34
 *
35
 * 6. Redistributions of any form whatsoever must retain the following
36
 *    acknowledgment:
37
 *
38
 * "This product includes software developed by the pfSense Project
39
 * for use in the pfSense software distribution (http://www.pfsense.org/).
40
 *
41
 * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
42
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
44
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
45
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
48
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
50
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
52
 * OF THE POSSIBILITY OF SUCH DAMAGE.
53
 */
54

    
55
require_once("globals.inc");
56
require_once("functions.inc");
57
require_once("led.inc");
58

    
59
$notice_path = $g['tmp_path'] . '/notices';
60
$smtp_authentication_mechanisms = array(
61
	'PLAIN' => 'PLAIN',
62
	'LOGIN' => 'LOGIN');
63
/* Other SMTP Authentication Mechanisms that could be supported.
64
 * Note that MD5 is no longer considered secure.
65
 *	'GSSAPI' => 'GSSAPI ' . gettext("Generic Security Services Application Program Interface")
66
 *	'DIGEST-MD5' => 'DIGEST-MD5 ' . gettext("Digest access authentication")
67
 *	'MD5' => 'MD5'
68
 *	'CRAM-MD5' => 'CRAM-MD5'
69
*/
70

    
71
/****f* notices/file_notice
72
 * NAME
73
 *   file_notice
74
 * INPUTS
75
 *	 $id, $notice, $category, $url, $priority, $local_only
76
 * RESULT
77
 *   Files a notice and kicks off the various alerts, smtp, growl, system log, LED's, etc.
78
 *   If $local_only is true then the notice is not sent to external places (smtp, growl)
79
 ******/
80
function file_notice($id, $notice, $category = "General", $url = "", $priority = 1, $local_only = false) {
81
	/*
82
	 * $category - Category that this notice should be displayed under. This can be arbitrary,
83
	 * 	       but a page must be set to receive this messages for it to be displayed.
84
	 *
85
	 * $priority - A notice's priority. Higher numbers indicate greater severity.
86
	 *	       0 = informational, 1 = warning, 2 = error, etc. This may also be arbitrary,
87
	 */
88
	global $notice_path;
89
	if (!$queue = get_notices()) {
90
		$queue = array();
91
	}
92
	$queuekey = time();
93
	$toqueue = array(
94
				'id'		=> htmlentities($id),
95
				'notice'	=> htmlentities($notice),
96
				'url'		=> htmlentities($url),
97
				'category'	=> htmlentities($category),
98
				'priority'	=> htmlentities($priority),
99
			);
100
	while (isset($queue[$queuekey])) {
101
		$queuekey++;
102
	}
103
	$queue[$queuekey] = $toqueue;
104
	$queueout = fopen($notice_path, "w");
105
	if (!$queueout) {
106
		log_error(sprintf(gettext("Could not open %s for writing"), $notice_path));
107
		return;
108
	}
109
	fwrite($queueout, serialize($queue));
110
	fclose($queueout);
111
	log_error(sprintf(gettext("New alert found: %s"), $notice));
112
	/* soekris */
113
	if (file_exists("/dev/led/error")) {
114
		exec("/bin/echo 1 > /dev/led/error");
115
	}
116
	/* wrap & alix */
117
	led_normalize();
118
	led_morse(1, 'sos');
119
	if (!$local_only) {
120
		notify_all_remote($notice);
121
	}
122
	return $queuekey;
123
}
124

    
125
/****f* notices/get_notices
126
 * NAME
127
 *   get_notices
128
 * INPUTS
129
 *	 $category
130
 * RESULT
131
 *   Returns a specific notices text
132
 ******/
133
function get_notices($category = "all") {
134
	global $g;
135

    
136
	if (file_exists("{$g['tmp_path']}/notices")) {
137
		$queue = unserialize(file_get_contents("{$g['tmp_path']}/notices"));
138
		if (!$queue) {
139
			return false;
140
		}
141
		if ($category != 'all') {
142
			foreach ($queue as $time => $notice) {
143
				if (strtolower($notice['category']) == strtolower($category)) {
144
					$toreturn[$time] = $notice;
145
				}
146
			}
147
			return $toreturn;
148
		} else {
149
			return $queue;
150
		}
151
	} else {
152
		return false;
153
	}
154
}
155

    
156
/****f* notices/close_notice
157
 * NAME
158
 *   close_notice
159
 * INPUTS
160
 *	 $id
161
 * RESULT
162
 *   Removes a notice from the list
163
 ******/
164
function close_notice($id) {
165
	global $notice_path;
166
	require_once("util.inc");
167
	/* soekris */
168
	if (file_exists("/dev/led/error")) {
169
		exec("/bin/echo 0 > /dev/led/error");
170
	}
171
	/* wrap & alix */
172
	led_normalize();
173
	$ids = array();
174
	if (!$notices = get_notices()) {
175
		return;
176
	}
177
	if ($id == "all") {
178
		unlink_if_exists($notice_path);
179
		return;
180
	}
181
	foreach (array_keys($notices) as $time) {
182
		if ($id == $time) {
183
			unset($notices[$id]);
184
			break;
185
		}
186
	}
187
	foreach ($notices as $key => $notice) {
188
		$ids[$key] = $notice['id'];
189
	}
190
	foreach ($ids as $time => $tocheck) {
191
		if ($id == $tocheck) {
192
			unset($notices[$time]);
193
			break;
194
		}
195
	}
196
	if (count($notices) != 0) {
197
		$queueout = fopen($notice_path, "w");
198
		fwrite($queueout, serialize($notices));
199
		fclose($queueout);
200
	} else {
201
		unlink_if_exists($notice_path);
202
	}
203

    
204
	return;
205
}
206

    
207
/****f* notices/dump_xml_notices
208
 * NAME
209
 *   dump_xml_notices
210
 * INPUTS
211
 *	 NONE
212
 * RESULT
213
 *   Outputs notices in XML formatted text
214
 ******/
215
function dump_xml_notices() {
216
	if (file_exists("/cf/conf/use_xmlreader")) {
217
		require_once("xmlreader.inc");
218
	} else {
219
		require_once("xmlparse.inc");
220
	}
221
	global $notice_path, $listtags;
222
	$listtags[] = 'notice';
223
	if (!$notices = get_notices()) {
224
		return;
225
	}
226
	foreach ($notices as $time => $notice) {
227
		$notice['time'] = $time;
228
		$toput['notice'][] = $notice;
229
	}
230
	$xml = dump_xml_config($toput, 'notices');
231
	return $xml;
232
}
233

    
234
/****f* notices/print_notices
235
 * NAME
236
 *   print_notices
237
 * INPUTS
238
 *	 $notices, $category
239
 * RESULT
240
 *   prints notices to the GUI
241
 ******/
242
function print_notices($notices, $category = "all") {
243
	foreach ($notices as $notice) {
244
		if ($category != "all") {
245
			if (in_array($notice['category'], $category)) {
246
				$categories[] = $notice['category'];
247
			}
248
		} else {
249
			$categories[] = $notice['category'];
250
		}
251
	}
252
	$categories = array_unique($categories);
253
	sort($categories);
254
	foreach ($categories as $category) {
255
		$toreturn .= "<ul><li>{$category}<ul>";
256
		foreach ($notices as $notice) {
257
			if (strtolower($notice['category']) == strtolower($category)) {
258
				if ($notice['id'] != "") {
259
					if ($notice['url'] != "") {
260
						$toreturn .= "<li><a href={$notice['url']}>{$notice['id']}</a> - {$notice['notice']}</li>";
261
					} else {
262
						$toreturn .= "<li>{$notice['id']} - {$notice['notice']}</li>";
263
					}
264
				}
265
			}
266
		}
267
		$toreturn .= "</ul></li></ul>";
268
	}
269
	return $toreturn;
270
}
271

    
272
/****f* notices/print_notice_box
273
 * NAME
274
 *   print_notice_box
275
 * INPUTS
276
 *	 $category
277
 * RESULT
278
 *   prints an info box to the GUI
279
 ******/
280
function print_notice_box($category = "all") {
281
	$notices = get_notices();
282
	if (!$notices) {
283
		return;
284
	}
285
	print_info_box(print_notices($notices, $category));
286
	return;
287
}
288

    
289
/****f* notices/are_notices_pending
290
 * NAME
291
 *   are_notices_pending
292
 * INPUTS
293
 *	 $category to check
294
 * RESULT
295
 *   returns true if notices are pending, false if they are not
296
 ******/
297
function are_notices_pending($category = "all") {
298
	global $notice_path;
299
	if (file_exists($notice_path)) {
300
		return true;
301
	}
302
	return false;
303
}
304

    
305
/****f* notices/notify_via_smtp
306
 * NAME
307
 *   notify_via_smtp
308
 * INPUTS
309
 *	 notification string to send as an email
310
 * RESULT
311
 *   returns true if message was sent
312
 ******/
313
function notify_via_smtp($message, $force = false) {
314
	global $config, $g;
315
	if (platform_booting()) {
316
		return;
317
	}
318

    
319
	if (isset($config['notifications']['smtp']['disable']) && !$force) {
320
		return;
321
	}
322

    
323
	/* Do NOT send the same message twice, except if $force is true */
324
	if (!$force && file_exists("/var/db/notices_lastmsg.txt")) {
325
		$lastmsg = trim(file_get_contents("/var/db/notices_lastmsg.txt"));
326
		if ($lastmsg == $message) {
327
			return;
328
		}
329
	}
330

    
331
	/* Store last message sent to avoid spamming */
332
	$fd = fopen("/var/db/notices_lastmsg.txt", "w");
333
	fwrite($fd, $message);
334
	fclose($fd);
335

    
336
	return send_smtp_message($message, "{$config['system']['hostname']}.{$config['system']['domain']} - Notification", $force);
337
}
338

    
339
function send_smtp_message($message, $subject = "(no subject)", $force = false) {
340
	global $config, $g;
341
	require_once("sasl.inc");
342
	require_once("smtp.inc");
343

    
344
	if (isset($config['notifications']['smtp']['disable']) && !$force) {
345
		return;
346
	}
347

    
348
	if (!$config['notifications']['smtp']['ipaddress']) {
349
		return;
350
	}
351

    
352
	if (!$config['notifications']['smtp']['notifyemailaddress']) {
353
		return;
354
	}
355

    
356
	$smtp = new smtp_class;
357

    
358
	$from = "pfsense@{$config['system']['hostname']}.{$config['system']['domain']}";
359
	$to = $config['notifications']['smtp']['notifyemailaddress'];
360

    
361
	$smtp->host_name = $config['notifications']['smtp']['ipaddress'];
362
	$smtp->host_port = empty($config['notifications']['smtp']['port']) ? 25 : $config['notifications']['smtp']['port'];
363

    
364
	$smtp->direct_delivery = 0;
365
	$smtp->ssl = (isset($config['notifications']['smtp']['ssl'])) ? 1 : 0;
366
	$smtp->start_tls = (isset($config['notifications']['smtp']['tls'])) ? 1 : 0;
367
	$smtp->debug = 0;
368
	$smtp->html_debug = 0;
369
	$smtp->localhost = $config['system']['hostname'] . "." . $config['system']['domain'];
370

    
371
	if ($config['notifications']['smtp']['fromaddress']) {
372
		$from = $config['notifications']['smtp']['fromaddress'];
373
	}
374

    
375
	// Use SMTP Auth if fields are filled out
376
	if ($config['notifications']['smtp']['username'] &&
377
	    $config['notifications']['smtp']['password']) {
378
		if (isset($config['notifications']['smtp']['authentication_mechanism'])) {
379
			$smtp->authentication_mechanism = $config['notifications']['smtp']['authentication_mechanism'];
380
		} else {
381
			$smtp->authentication_mechanism = "PLAIN";
382
		}
383
		$smtp->user = $config['notifications']['smtp']['username'];
384
		$smtp->password = $config['notifications']['smtp']['password'];
385
	}
386

    
387
	$headers = array(
388
		"From: {$from}",
389
		"To: {$to}",
390
		"Subject: {$subject}",
391
		"Date: " . date("r")
392
	);
393

    
394
	if ($smtp->SendMessage($from, preg_split('/\s*,\s*/', trim($to)), $headers, $message)) {
395
		log_error(sprintf(gettext("Message sent to %s OK"), $to));
396
		return;
397
	} else {
398
		log_error(sprintf(gettext('Could not send the message to %1$s -- Error: %2$s'), $to, $smtp->error));
399
		return(sprintf(gettext('Could not send the message to %1$s -- Error: %2$s'), $to, $smtp->error));
400
	}
401
}
402

    
403
/****f* notices/notify_via_growl
404
 * NAME
405
 *   notify_via_growl
406
 * INPUTS
407
 *	 notification string to send
408
 * RESULT
409
 *   returns true if message was sent
410
 ******/
411
function notify_via_growl($message, $force=false) {
412
	require_once("growl.class");
413
	global $config, $g;
414

    
415
	if (isset($config['notifications']['growl']['disable']) && !$force) {
416
		return;
417
	}
418

    
419
	/* Do NOT send the same message twice */
420
	if (file_exists("/var/db/growlnotices_lastmsg.txt")) {
421
		$lastmsg = trim(file_get_contents("/var/db/growlnotices_lastmsg.txt"));
422
		if ($lastmsg == $message) {
423
			return;
424
		}
425
	}
426

    
427
	$hostname = $config['system']['hostname'] . "." . $config['system']['domain'];
428
	$growl_ip = $config['notifications']['growl']['ipaddress'];
429
	$growl_password = $config['notifications']['growl']['password'];
430
	$growl_name = $config['notifications']['growl']['name'];
431
	$growl_notification = $config['notifications']['growl']['notification_name'];
432

    
433
	if (!empty($growl_ip)) {
434
		if (is_ipaddr($growl_ip) || dns_check_record($growl_ip, A) || dns_check_record($growl_ip, AAAA)) {
435
			$growl = new Growl($growl_ip, $growl_password, $growl_name);
436
			$growl->notify("{$growl_notification}", gettext(sprintf("%s (%s) - Notification", $g['product_name'], $hostname)), "{$message}");
437
		} else {
438
			// file_notice to local only to prevent file_notice from calling back to growl in a loop
439
			file_notice("growl", gettext("Growl IP Address is invalid. Check the setting in System Advanced Notifications."), "General", "", 1, true);
440
		}
441
	}
442

    
443
	/* Store last message sent to avoid spamming */
444
	$fd = fopen("/var/db/growlnotices_lastmsg.txt", "w");
445
	fwrite($fd, $message);
446
	fclose($fd);
447
}
448

    
449
/****f* notices/register_via_growl
450
 * NAME
451
 *   register_via_growl
452
 * INPUTS
453
 *	 none
454
 * RESULT
455
 *   none
456
 ******/
457
function register_via_growl() {
458
	require_once("growl.class");
459
	global $config;
460
	$growl_ip = $config['notifications']['growl']['ipaddress'];
461
	$growl_password = $config['notifications']['growl']['password'];
462
	$growl_name = $config['notifications']['growl']['name'];
463
	$growl_notification = $config['notifications']['growl']['notification_name'];
464

    
465
	if (!empty($growl_ip)) {
466
		if (is_ipaddr($growl_ip) || dns_check_record($growl_ip, A) || dns_check_record($growl_ip, AAAA)) {
467
			$growl = new Growl($growl_ip, $growl_password, $growl_name);
468
			$growl->addNotification($growl_notification);
469
			$growl->register();
470
		} else {
471
			// file_notice to local only to prevent file_notice from calling back to growl in a loop
472
			file_notice("growl", gettext("Growl IP Address is invalid. Check the setting in System Advanced Notifications."), "General", "", 1, true);
473
		}
474
	}
475
}
476

    
477
/* Notify via remote methods only - not via GUI. */
478
function notify_all_remote($msg) {
479
	notify_via_smtp($msg);
480
	notify_via_growl($msg);
481
}
482

    
483
?>
(35-35/67)