Project

General

Profile

Download (10.8 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-2013 BSD Perimeter
8
 * Copyright (c) 2013-2016 Electric Sheep Fencing
9
 * Copyright (c) 2014-2020 Rubicon Communications, LLC (Netgate)
10
 * All rights reserved.
11
 *
12
 * Licensed under the Apache License, Version 2.0 (the "License");
13
 * you may not use this file except in compliance with the License.
14
 * You may obtain a copy of the License at
15
 *
16
 * http://www.apache.org/licenses/LICENSE-2.0
17
 *
18
 * Unless required by applicable law or agreed to in writing, software
19
 * distributed under the License is distributed on an "AS IS" BASIS,
20
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
 * See the License for the specific language governing permissions and
22
 * limitations under the License.
23
 */
24

    
25
require_once("globals.inc");
26
require_once("functions.inc");
27
require_once("led.inc");
28

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

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

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

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

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

    
174
	return;
175
}
176

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

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

    
220
function notices_sendqueue() {
221
	global $g;
222
	$nothing_done_count = 0;
223
	$messagequeue = array();
224

    
225
	while(true) {
226
		$notifyqueue_lck = lock("notifyqueue", LOCK_EX);
227
		$nothing_done_count++;
228
		$smptcount = 0;
229
		$messages = array();
230
		if (file_exists("{$g['vardb_path']}/notifyqueue.messages")) {
231
			$messages = unserialize(file_get_contents("{$g['vardb_path']}/notifyqueue.messages"));
232
			$messagequeue = $messages;
233
			$messages['mails']['item'] = array(); // clear all items to be send
234
			file_put_contents("{$g['vardb_path']}/notifyqueue.messages", serialize($messages));
235
			unset($messages);
236
		}
237
		// clear lock before trying to send messages, so new one's can be added
238
		unlock($notifyqueue_lck);
239

    
240
		if (is_array($messagequeue['mails']['item'])) {
241
			$smtpmessage = "";
242
			foreach($messagequeue['mails']['item'] as $mail) {
243
				switch ($mail['type']) {
244
					case 'mail':
245
						$smptcount++;
246
						$smtpmessage .= "\r\n" . date("G:i:s",$mail['time']) . " " . $mail['msg'];
247
						break;
248
					default:
249
						break;
250
				}
251
			}
252
			if (!empty($smtpmessage)) {
253
				$smtpmessageheader = sprintf(gettext("Notifications in this message: %s"), $smptcount);
254
				$smtpmessageheader .= "\n" . str_repeat('=', strlen($smtpmessageheader)) . "\n";
255
				$nothing_done_count = 0;
256
				notify_via_smtp($smtpmessageheader . $smtpmessage, true);
257
			}
258
		}
259
		if ($nothing_done_count > 6) {
260
			break;
261
		} else {
262
			sleep(10);
263
		}
264
	}
265
}
266

    
267
function notify_via_queue_add($message, $type='mail') {
268
	global $g;
269
	$mail = array();
270
	$mail['time'] = time();
271
	$mail['type'] = $type;
272
	$mail['msg'] = $message;
273
	$notifyqueue_lck = lock("notifyqueue", LOCK_EX);
274
	$messages = array();
275
	if (file_exists("{$g['vardb_path']}/notifyqueue.messages")) {
276
		$messages = unserialize(file_get_contents("{$g['vardb_path']}/notifyqueue.messages"));
277
	}
278
	if(is_array($messages)) {
279
		$messages['mails']['item'][] = $mail;
280
		file_put_contents("{$g['vardb_path']}/notifyqueue.messages", serialize($messages));
281
	}
282
	unset($messages);
283

    
284
	mwexec_bg('/usr/local/bin/notify_monitor.php');
285
	unlock($notifyqueue_lck);
286
}
287

    
288
/****f* notices/notify_via_smtp
289
 * NAME
290
 *   notify_via_smtp
291
 * INPUTS
292
 *	 notification string to send as an email
293
 * RESULT
294
 *   returns true if message was sent
295
 ******/
296
function notify_via_smtp($message, $force = false) {
297
	global $config, $g;
298
	if (platform_booting()) {
299
		return;
300
	}
301

    
302
	if (isset($config['notifications']['smtp']['disable']) && !$force) {
303
		return;
304
	}
305

    
306
	/* Do NOT send the same message twice, except if $force is true */
307
	if (!$force && file_exists("/var/db/notices_lastmsg.txt")) {
308
		$lastmsg = trim(file_get_contents("/var/db/notices_lastmsg.txt"));
309
		if ($lastmsg == $message) {
310
			return;
311
		}
312
	}
313

    
314
	/* Store last message sent to avoid spamming */
315
	@file_put_contents("/var/db/notices_lastmsg.txt", $message);
316
	if (!$force) {
317
		notify_via_queue_add($message, 'mail');
318
		$ret = true;
319
	} else {
320
		$ret = send_smtp_message($message, "{$config['system']['hostname']}.{$config['system']['domain']} - Notification", $force);
321
	}
322

    
323
	return $ret;
324
}
325

    
326
function send_smtp_message($message, $subject = "(no subject)", $force = false) {
327
	global $config, $g;
328
	require_once("Mail.php");
329

    
330
	if (isset($config['notifications']['smtp']['disable']) && !$force) {
331
		return;
332
	}
333

    
334
	if (!$config['notifications']['smtp']['ipaddress']) {
335
		return;
336
	}
337

    
338
	if (!$config['notifications']['smtp']['notifyemailaddress']) {
339
		return;
340
	}
341

    
342
	$to = $config['notifications']['smtp']['notifyemailaddress'];
343

    
344
	if (empty($config['notifications']['smtp']['username']) ||
345
	    empty($config['notifications']['smtp']['password'])) {
346
		$auth = false;
347
		$username = '';
348
		$password = '';
349
	} else {
350
		$auth = isset($config['notifications']['smtp']['authentication_mechanism'])
351
		    ? $config['notifications']['smtp']['authentication_mechanism']
352
		    : 'PLAIN';
353
		$username = $config['notifications']['smtp']['username'];
354
		$password = $config['notifications']['smtp']['password'];
355
	}
356

    
357
	$params = array(
358
		'host' => (isset($config['notifications']['smtp']['ssl'])
359
		    ? 'ssl://'
360
		    : '')
361
		    . $config['notifications']['smtp']['ipaddress'],
362
		'port' => empty($config['notifications']['smtp']['port'])
363
		    ? 25
364
		    : $config['notifications']['smtp']['port'],
365
		'auth' => $auth,
366
		'username' => $username,
367
		'password' => $password,
368
		'localhost' => $config['system']['hostname'] . "." .
369
		    $config['system']['domain'],
370
		'timeout' => !empty($config['notifications']['smtp']['timeout'])
371
		    ? $config['notifications']['smtp']['timeout']
372
		    : 20,
373
		'debug' => false,
374
		'persist' => false
375
	);
376

    
377
	if ($config['notifications']['smtp']['sslvalidate'] == "disabled") {
378
		$params['socket_options'] = array('ssl' => array('verify_peer_name' => false));
379
	}
380

    
381
	if ($config['notifications']['smtp']['fromaddress']) {
382
		$from = $config['notifications']['smtp']['fromaddress'];
383
	} else {
384
		$from = "pfsense@{$config['system']['hostname']}.{$config['system']['domain']}";
385
	}
386

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

    
394
	$smtp =& Mail::factory('smtp', $params);
395
	$mail = $smtp->send($to, $headers, $message);
396

    
397
	if (PEAR::isError($mail)) {
398
		$err_msg = sprintf(gettext(
399
		    'Could not send the message to %1$s -- Error: %2$s'),
400
		    $to, $mail->getMessage());
401
		log_error($err_msg);
402
		return($err_msg);
403
	}
404

    
405
	log_error(sprintf(gettext("Message sent to %s OK"), $to));
406
	return;
407
}
408

    
409
/* Notify via remote methods only - not via GUI. */
410
function notify_all_remote($msg) {
411
	notify_via_smtp($msg);
412
}
413

    
414
?>
(30-30/60)