Project

General

Profile

Download (11.5 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
 * Licensed under the Apache License, Version 2.0 (the "License");
11
 * you may not use this file except in compliance with the License.
12
 * You may obtain a copy of the License at
13
 *
14
 * http://www.apache.org/licenses/LICENSE-2.0
15
 *
16
 * Unless required by applicable law or agreed to in writing, software
17
 * distributed under the License is distributed on an "AS IS" BASIS,
18
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
 * See the License for the specific language governing permissions and
20
 * limitations under the License.
21
 */
22

    
23
require_once("globals.inc");
24
require_once("functions.inc");
25
require_once("led.inc");
26

    
27
$notice_path = $g['tmp_path'] . '/notices';
28
$smtp_authentication_mechanisms = array(
29
	'PLAIN' => 'PLAIN',
30
	'LOGIN' => 'LOGIN');
31
/* Other SMTP Authentication Mechanisms that could be supported.
32
 * Note that MD5 is no longer considered secure.
33
 *	'GSSAPI' => 'GSSAPI ' . gettext("Generic Security Services Application Program Interface")
34
 *	'DIGEST-MD5' => 'DIGEST-MD5 ' . gettext("Digest access authentication")
35
 *	'MD5' => 'MD5'
36
 *	'CRAM-MD5' => 'CRAM-MD5'
37
*/
38

    
39
/****f* notices/file_notice
40
 * NAME
41
 *   file_notice
42
 * INPUTS
43
 *	 $id, $notice, $category, $url, $priority, $local_only
44
 * RESULT
45
 *   Files a notice and kicks off the various alerts, smtp, growl, system log, LED's, etc.
46
 *   If $local_only is true then the notice is not sent to external places (smtp, growl)
47
 ******/
48
function file_notice($id, $notice, $category = "General", $url = "", $priority = 1, $local_only = false) {
49
	/*
50
	 * $category - Category that this notice should be displayed under. This can be arbitrary,
51
	 * 	       but a page must be set to receive this messages for it to be displayed.
52
	 *
53
	 * $priority - A notice's priority. Higher numbers indicate greater severity.
54
	 *	       0 = informational, 1 = warning, 2 = error, etc. This may also be arbitrary,
55
	 */
56
	global $notice_path;
57
	if (!$queue = get_notices()) {
58
		$queue = array();
59
	}
60
	$queuekey = time();
61
	$toqueue = array(
62
				'id'		=> htmlentities($id),
63
				'notice'	=> htmlentities($notice),
64
				'url'		=> htmlentities($url),
65
				'category'	=> htmlentities($category),
66
				'priority'	=> htmlentities($priority),
67
			);
68
	while (isset($queue[$queuekey])) {
69
		$queuekey++;
70
	}
71
	$queue[$queuekey] = $toqueue;
72
	$queueout = fopen($notice_path, "w");
73
	if (!$queueout) {
74
		log_error(sprintf(gettext("Could not open %s for writing"), $notice_path));
75
		return;
76
	}
77
	fwrite($queueout, serialize($queue));
78
	fclose($queueout);
79
	log_error(sprintf(gettext("New alert found: %s"), $notice));
80
	/* soekris */
81
	if (file_exists("/dev/led/error")) {
82
		exec("/bin/echo 1 > /dev/led/error");
83
	}
84
	/* wrap & alix */
85
	led_normalize();
86
	led_morse(1, 'sos');
87
	if (!$local_only) {
88
		notify_all_remote($notice);
89
	}
90
	return $queuekey;
91
}
92

    
93
/****f* notices/get_notices
94
 * NAME
95
 *   get_notices
96
 * INPUTS
97
 *	 $category
98
 * RESULT
99
 *   Returns a specific notices text
100
 ******/
101
function get_notices($category = "all") {
102
	global $g;
103

    
104
	if (file_exists("{$g['tmp_path']}/notices")) {
105
		$queue = unserialize(file_get_contents("{$g['tmp_path']}/notices"));
106
		if (!$queue) {
107
			return false;
108
		}
109
		if ($category != 'all') {
110
			foreach ($queue as $time => $notice) {
111
				if (strtolower($notice['category']) == strtolower($category)) {
112
					$toreturn[$time] = $notice;
113
				}
114
			}
115
			return $toreturn;
116
		} else {
117
			return $queue;
118
		}
119
	} else {
120
		return false;
121
	}
122
}
123

    
124
/****f* notices/close_notice
125
 * NAME
126
 *   close_notice
127
 * INPUTS
128
 *	 $id
129
 * RESULT
130
 *   Removes a notice from the list
131
 ******/
132
function close_notice($id) {
133
	global $notice_path;
134
	require_once("util.inc");
135
	/* soekris */
136
	if (file_exists("/dev/led/error")) {
137
		exec("/bin/echo 0 > /dev/led/error");
138
	}
139
	/* wrap & alix */
140
	led_normalize();
141
	$ids = array();
142
	if (!$notices = get_notices()) {
143
		return;
144
	}
145
	if ($id == "all") {
146
		unlink_if_exists($notice_path);
147
		return;
148
	}
149
	foreach (array_keys($notices) as $time) {
150
		if ($id == $time) {
151
			unset($notices[$id]);
152
			break;
153
		}
154
	}
155
	foreach ($notices as $key => $notice) {
156
		$ids[$key] = $notice['id'];
157
	}
158
	foreach ($ids as $time => $tocheck) {
159
		if ($id == $tocheck) {
160
			unset($notices[$time]);
161
			break;
162
		}
163
	}
164
	if (count($notices) != 0) {
165
		$queueout = fopen($notice_path, "w");
166
		fwrite($queueout, serialize($notices));
167
		fclose($queueout);
168
	} else {
169
		unlink_if_exists($notice_path);
170
	}
171

    
172
	return;
173
}
174

    
175
/****f* notices/dump_xml_notices
176
 * NAME
177
 *   dump_xml_notices
178
 * INPUTS
179
 *	 NONE
180
 * RESULT
181
 *   Outputs notices in XML formatted text
182
 ******/
183
function dump_xml_notices() {
184
	if (file_exists("/cf/conf/use_xmlreader")) {
185
		require_once("xmlreader.inc");
186
	} else {
187
		require_once("xmlparse.inc");
188
	}
189
	global $notice_path, $listtags;
190
	$listtags[] = 'notice';
191
	if (!$notices = get_notices()) {
192
		return;
193
	}
194
	foreach ($notices as $time => $notice) {
195
		$notice['time'] = $time;
196
		$toput['notice'][] = $notice;
197
	}
198
	$xml = dump_xml_config($toput, 'notices');
199
	return $xml;
200
}
201

    
202
/****f* notices/are_notices_pending
203
 * NAME
204
 *   are_notices_pending
205
 * INPUTS
206
 *	 $category to check
207
 * RESULT
208
 *   returns true if notices are pending, false if they are not
209
 ******/
210
function are_notices_pending($category = "all") {
211
	global $notice_path;
212
	if (file_exists($notice_path)) {
213
		return true;
214
	}
215
	return false;
216
}
217

    
218
/****f* notices/notify_via_smtp
219
 * NAME
220
 *   notify_via_smtp
221
 * INPUTS
222
 *	 notification string to send as an email
223
 * RESULT
224
 *   returns true if message was sent
225
 ******/
226
function notify_via_smtp($message, $force = false) {
227
	global $config, $g;
228
	if (platform_booting()) {
229
		return;
230
	}
231

    
232
	if (isset($config['notifications']['smtp']['disable']) && !$force) {
233
		return;
234
	}
235

    
236
	/* Do NOT send the same message twice, except if $force is true */
237
	if (!$force && file_exists("/var/db/notices_lastmsg.txt")) {
238
		$lastmsg = trim(file_get_contents("/var/db/notices_lastmsg.txt"));
239
		if ($lastmsg == $message) {
240
			return;
241
		}
242
	}
243

    
244
	/* Store last message sent to avoid spamming */
245
	$fd = fopen("/var/db/notices_lastmsg.txt", "w");
246
	fwrite($fd, $message);
247
	fclose($fd);
248

    
249
	return send_smtp_message($message, "{$config['system']['hostname']}.{$config['system']['domain']} - Notification", $force);
250
}
251

    
252
function send_smtp_message($message, $subject = "(no subject)", $force = false) {
253
	global $config, $g;
254
	require_once("Mail.php");
255

    
256
	if (isset($config['notifications']['smtp']['disable']) && !$force) {
257
		return;
258
	}
259

    
260
	if (!$config['notifications']['smtp']['ipaddress']) {
261
		return;
262
	}
263

    
264
	if (!$config['notifications']['smtp']['notifyemailaddress']) {
265
		return;
266
	}
267

    
268
	$to = $config['notifications']['smtp']['notifyemailaddress'];
269

    
270
	if (empty($config['notifications']['smtp']['username']) ||
271
	    empty($config['notifications']['smtp']['password'])) {
272
		$auth = false;
273
		$username = '';
274
		$password = '';
275
	} else {
276
		$auth = isset($config['notifications']['smtp']['authentication_mechanism'])
277
		    ? $config['notifications']['smtp']['authentication_mechanism']
278
		    : 'PLAIN';
279
		$username = $config['notifications']['smtp']['username'];
280
		$password = $config['notifications']['smtp']['password'];
281
	}
282

    
283
	$params = array(
284
		'host' => (isset($config['notifications']['smtp']['ssl'])
285
		    ? 'ssl://'
286
		    : '')
287
		    . $config['notifications']['smtp']['ipaddress'],
288
		'port' => empty($config['notifications']['smtp']['port'])
289
		    ? 25
290
		    : $config['notifications']['smtp']['port'],
291
		'auth' => $auth,
292
		'username' => $username,
293
		'password' => $password,
294
		'localhost' => $config['system']['hostname'] . "." .
295
		    $config['system']['domain'],
296
		'timeout' => !empty($config['notifications']['smtp']['timeout'])
297
		    ? $config['notifications']['smtp']['timeout']
298
		    : 20,
299
		'debug' => false,
300
		'persist' => false
301
	);
302

    
303
	if ($config['notifications']['smtp']['fromaddress']) {
304
		$from = $config['notifications']['smtp']['fromaddress'];
305
	} else {
306
		$from = "pfsense@{$config['system']['hostname']}.{$config['system']['domain']}";
307
	}
308

    
309
	$headers = array(
310
		"From"    => $from,
311
		"To"      => $to,
312
		"Subject" => $subject,
313
		"Date"    => date("r")
314
	);
315

    
316
	$smtp =& Mail::factory('smtp', $params);
317
	$mail = $smtp->send($to, $headers, $message);
318

    
319
	if (PEAR::isError($mail)) {
320
		$err_msg = sprintf(gettext(
321
		    'Could not send the message to %1$s -- Error: %2$s'),
322
		    $to, $mail->getMessage());
323
		log_error($err_msg);
324
		return($err_msg);
325
	}
326

    
327
	log_error(sprintf(gettext("Message sent to %s OK"), $to));
328
	return;
329
}
330

    
331
/****f* notices/notify_via_growl
332
 * NAME
333
 *   notify_via_growl
334
 * INPUTS
335
 *	 notification string to send
336
 * RESULT
337
 *   returns true if message was sent
338
 ******/
339
function notify_via_growl($message, $force=false) {
340
	require_once("Net/Growl/Autoload.php");
341

    
342
	global $config, $g;
343

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

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

    
352
	/* Do NOT send the same message twice */
353
	if (file_exists("/var/db/growlnotices_lastmsg.txt")) {
354
		$lastmsg = trim(file_get_contents("/var/db/growlnotices_lastmsg.txt"));
355
		if ($lastmsg == $message) {
356
			return;
357
		}
358
	}
359

    
360
	$ip = $config['notifications']['growl']['ipaddress'];
361

    
362
	if (!is_ipaddr($ip) && !(dns_check_record($ip, A) || dns_check_record($ip, AAAA))) {
363
		$err_msg = gettext(
364
		    "Growl IP Address is invalid. Check the setting in System Advanced Notifications.");
365
		log_error($err_msg);
366
		return($err_msg);
367
	}
368

    
369
	$hostname = $config['system']['hostname'] . "." . $config['system']['domain'];
370
	$password = $config['notifications']['growl']['password'];
371
	$name = $config['notifications']['growl']['name'];
372
	$notification = $config['notifications']['growl']['notification_name'];
373

    
374
	$options  = array(
375
		'host' => $ip,
376
		'protocol' => 'gntp',
377
		'timeout' => 20
378
	);
379

    
380
	try {
381
		$growl = Net_Growl::singleton($name, null, $password, $options);
382
		//$name = 'GROWL_NOTIFY_STATUS';
383
		$title = sprintf(gettext('%1$s (%2$s) - Notification'), $g['product_name'], $hostname);
384
		$growl->publish($name, $title, $message);
385
	} catch (Net_Growl_Exception $e) {
386
		$err_msg = sprintf(gettext(
387
		    'Could not send Growl notification to %1$s -- Error: %2$s'),
388
		    $ip, $e->getMessage());
389
		log_error($err_msg);
390
		return($err_msg);
391
	}
392

    
393
	/* Store last message sent to avoid spamming */
394
	@file_put_contents("/var/db/growlnotices_lastmsg.txt", $message);
395

    
396
	return;
397
}
398

    
399
/****f* notices/register_via_growl
400
 * NAME
401
 *   register_via_growl
402
 * INPUTS
403
 *	 none
404
 * RESULT
405
 *   none
406
 ******/
407
function register_via_growl() {
408
	require_once("Net/Growl/Autoload.php");
409

    
410
	global $config;
411

    
412
	if (empty($config['notifications']['growl']['ipaddress'])) {
413
		return;
414
	}
415

    
416
	$ip = $config['notifications']['growl']['ipaddress'];
417

    
418
	if (!is_ipaddr($ip) && !(dns_check_record($ip, A) || dns_check_record($ip, AAAA))) {
419
		$err_msg = gettext(
420
		    "Growl IP Address is invalid. Check the setting in System Advanced Notifications.");
421
		log_error($err_msg);
422
		return($err_msg);
423
	}
424

    
425
	$name = $config['notifications']['growl']['name'];
426
	$password = $config['notifications']['growl']['password'];
427

    
428
	$app = new Net_Growl_Application(
429
		$name,
430
		null,
431
		$password
432
	);
433

    
434
	$options = array(
435
		'host' => $ip,
436
		'protocol' => 'gntp',
437
		'timeout' => 20
438
	);
439

    
440
	try {
441
		$growl = Net_Growl::singleton($app, null, null, $options);
442
		$growl->register();
443
	} catch (Net_Growl_Exception $e) {
444
		$err_msg = sprintf(gettext(
445
		    'Could not send register Growl on %1$s -- Error: %2$s'),
446
		    $ip, $e->getMessage());
447
		log_error($err_msg);
448
		return($err_msg);
449
	}
450

    
451
	return;
452
}
453

    
454
/* Notify via remote methods only - not via GUI. */
455
function notify_all_remote($msg) {
456
	notify_via_smtp($msg);
457
	notify_via_growl($msg);
458
}
459

    
460
?>
(27-27/54)