Project

General

Profile

Download (14 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_via_growl($notice);
121
		notify_via_smtp($notice);
122
	}
123
	return $queuekey;
124
}
125

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

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

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

    
205
	return;
206
}
207

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

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

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

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

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

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

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

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

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

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

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

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

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

    
357
	$smtp = new smtp_class;
358

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
484
?>
(33-33/65)