Projet

Général

Profil

Télécharger (15,5 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / rc.filter_synchronize @ master

1
#!/usr/local/bin/php -f
2
<?php
3
/*
4
        filter.inc
5
        Copyright (C) 2004-2006 Scott Ullrich
6
        Copyright (C) 2005              Bill Marquette
7
        Copyright (C) 2006              Peter Allgeyer
8
        Copyright (C) 2008              Ermal Luci
9
        All rights reserved.
10

    
11
        originally part of m0n0wall (http://m0n0.ch/wall)
12
        Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
13
        All rights reserved.
14

    
15
        Redistribution and use in source and binary forms, with or without
16
        modification, are permitted provided that the following conditions are met:
17

    
18
        1. Redistributions of source code must retain the above copyright notice,
19
           this list of conditions and the following disclaimer.
20

    
21
        2. Redistributions in binary form must reproduce the above copyright
22
           notice, this list of conditions and the following disclaimer in the
23
           documentation and/or other materials provided with the distribution.
24

    
25
        THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
26
        INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
        AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28
        AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
29
        OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
        INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
        CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
        ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
        POSSIBILITY OF SUCH DAMAGE.
35

    
36
*/
37

    
38
require_once("globals.inc");
39
require_once("config.inc");
40
require_once("functions.inc");
41
require_once("filter.inc");
42
require_once("shaper.inc");
43
require_once("xmlrpc.inc");
44
require_once("interfaces.inc");
45

    
46
/*
47
 *  backup_vip_config_section($section): returns as an xml file string of
48
 *                                   the configuration section
49
 */
50
function backup_vip_config_section() {
51
	global $config;
52

    
53
	if (!is_array($config['virtualip']['vip']))
54
		return;
55
	$temp = array();
56
	$temp['vip'] = array();
57
	foreach($config['virtualip']['vip'] as $section) {
58
		if (($section['mode'] == 'proxyarp' || $section['mode'] == 'ipalias') && !(strpos($section['interface'], '_vip') || strpos($section['interface'], 'lo0')))
59
			continue;
60
		if ($section['advskew'] <> "") {
61
			$section_val = intval($section['advskew']);
62
			$section_val=$section_val+100;
63
			if ($section_val > 254)
64
				$section_val = 254;
65
			$section['advskew'] = $section_val;
66
		}
67
		if ($section['advbase'] <> "") {
68
			$section_val = intval($section['advbase']);
69
			if ($section_val > 254)
70
				$section_val = 254;
71
			$section['advbase'] = $section_val;
72
		}
73
		$temp['vip'][] = $section;
74
	}
75
	return $temp;
76
}
77

    
78
function remove_special_characters($string) {
79
	$match_array = "";
80
	preg_match_all("/[a-zA-Z0-9\_\-]+/",$string,$match_array);
81
	$string = "";
82
	foreach ($match_array[0] as $ma) {
83
		if ($string <> "")
84
			$string .= " ";
85
		$string .= $ma;
86
	}
87
	return $string;
88
}
89

    
90
function carp_check_version($url, $username, $password, $port = 80, $method = 'pfsense.host_firmware_version') {
91
	global $config, $g;
92

    
93
	if(file_exists("{$g['varrun_path']}/booting") || $g['booting'])
94
		return;
95

    
96
	$params = array(
97
		XML_RPC_encode($password)
98
	);
99

    
100
	$numberofruns = 0;
101
	while ($numberofruns < 2) {
102
		$msg = new XML_RPC_Message($method, $params);
103
		$cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
104
		$cli->setCredentials($username, $password);
105
		if($numberofruns > 0)
106
			$cli->setDebug(1);
107
		/* send our XMLRPC message and timeout after 240 seconds */
108
		$resp = $cli->send($msg, "240");
109
		if(!is_object($resp)) {
110
			$error = "A communications error occurred while attempting XMLRPC sync with username {$username} {$url}:{$port}.";
111
		} elseif($resp->faultCode()) {
112
			$error = "An error code was received while attempting XMLRPC sync with username {$username} {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
113
		} else {
114
			$parsed_response =  XML_RPC_decode($resp->value());
115
			if(!is_array($parsed_response)) {
116
				if (trim($parsed_response) == "Authentication failed") {
117
					$error = "An authentication failure occurred while trying to access {$url}:{$port} ({$method}).";
118
					log_error($error);
119
					file_notice("sync_settings", $error, "Settings Sync", "");
120
					exit;
121
				}
122
			} else {
123
				if (!isset($parsed_response['config_version']) ||
124
				  $parsed_response['config_version'] < $config['version']) {
125
					update_filter_reload_status("The other member is on older configuration version of {$g['product_name']}. Sync will not be done to prevent problems!");
126
					log_error("The other member is on older configuration version of {$g['product_name']}. Sync will not be done to prevent problems!");
127
					return false;
128
				} else
129
					return true;
130
			}
131
		}
132
		log_error($error);
133
		file_notice("sync_settings", $error, "Settings Sync", "");
134
		$numberofruns++;
135
	}
136

    
137
	return false;
138
}
139

    
140
function carp_sync_xml($url, $username, $password, $sections, $port = 80, $method = 'pfsense.restore_config_section') {
141
	global $config, $g;
142

    
143
	if(file_exists("{$g['varrun_path']}/booting") || $g['booting'])
144
		return;
145

    
146
	update_filter_reload_status("Syncing CARP data to {$url}");
147

    
148
	/* make a copy of config */
149
	$config_copy = $config;
150

    
151
	/* strip out nosync items */
152
	if (is_array($config_copy['nat']['outbound']['rule'])) {
153
		$rulescnt = count($config_copy['nat']['outbound']['rule']);
154
		for ($x = 0; $x < $rulescnt; $x++) {
155
			$config_copy['nat']['outbound']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['outbound']['rule'][$x]['descr']);
156
			if (isset ($config_copy['nat']['outbound']['rule'][$x]['nosync']))
157
				unset ($config_copy['nat']['outbound']['rule'][$x]);
158
		}
159
	}
160
	if (is_array($config_copy['nat']['rule'])) {
161
		$natcnt = count($config_copy['nat']['rule']);
162
		for ($x = 0; $x < $natcnt; $x++) {
163
			$config_copy['nat']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['rule'][$x]['descr']);
164
			if (isset ($config_copy['nat']['rule'][$x]['nosync']))
165
				unset ($config_copy['nat']['rule'][$x]);
166
		}
167
	}
168
	if (is_array($config_copy['filter']['rule'])) {
169
		$filtercnt = count($config_copy['filter']['rule']);
170
		for ($x = 0; $x < $filtercnt; $x++) {
171
			$config_copy['filter']['rule'][$x]['descr'] = remove_special_characters($config_copy['filter']['rule'][$x]['descr']);
172
			if (isset ($config_copy['filter']['rule'][$x]['nosync']))
173
				unset ($config_copy['filter']['rule'][$x]);
174
		}
175
	}
176
	if (is_array($config_copy['aliases']['alias'])) {
177
		$aliascnt = count($config_copy['aliases']['alias']);
178
		for ($x = 0; $x < $aliascnt; $x++) {
179
			$config_copy['aliases']['alias'][$x]['descr'] = remove_special_characters($config_copy['aliases']['alias'][$x]['descr']);
180
			if (isset ($config_copy['aliases']['alias'][$x]['nosync']))
181
				unset ($config_copy['aliases']['alias'][$x]);
182
		}
183
	}
184
	if (is_array($config_copy['dnsmasq']['hosts'])) {
185
		$dnscnt = count($config_copy['dnsmasq']['hosts']);
186
		for ($x = 0; $x < $dnscnt; $x++) {
187
			$config_copy['dnsmasq']['hosts'][$x]['descr'] = remove_special_characters($config_copy['dnsmasq']['hosts'][$x]['descr']);
188
			if (isset ($config_copy['dnsmasq']['hosts'][$x]['nosync']))
189
				unset ($config_copy['dnsmasq']['hosts'][$x]);
190
		}
191
	}
192
	if (is_array($config_copy['ipsec']['tunnel'])) {
193
		$ipseccnt = count($config_copy['ipsec']['tunnel']);
194
		for ($x = 0; $x < $ipseccnt; $x++) {
195
			$config_copy['ipsec']['tunnel'][$x]['descr'] = remove_special_characters($config_copy['ipsec']['tunnel'][$x]['descr']);
196
			if (isset ($config_copy['ipsec']['tunnel'][$x]['nosync']))
197
				unset ($config_copy['ipsec']['tunnel'][$x]);
198
		}
199
	}
200

    
201
	if (is_array($config_copy['dhcpd'])) {
202
		foreach($config_copy['dhcpd'] as $dhcpif => $dhcpifconf) {
203
			if($dhcpifconf['failover_peerip'] <> "") {
204
				$int = guess_interface_from_ip($dhcpifconf['failover_peerip']);
205
				$intip = find_interface_ip($int);
206
				$config_copy['dhcpd'][$dhcpif]['failover_peerip'] = $intip;
207
			}
208
		}
209
	}
210

    
211
	foreach ($sections as $section) {
212
	   /*  we can't use array_intersect_key()
213
		*  due to the vip 'special case'
214
		*/
215
		switch ($section) {
216
			case 'virtualip':
217
				$xml[$section] = backup_vip_config_section();
218
				break;
219
			case 'user':
220
				$xml['system'][$section] = $config_copy['system'][$section];
221
				$xml['system']['nextuid'] = $config_copy['system']['nextuid'];
222
				break;
223
			case 'group':
224
				$xml['system'][$section] = $config_copy['system'][$section];
225
				$xml['system']['nextgid'] = $config_copy['system']['nextgid'];
226
				break;
227
			case 'authserver':
228
				$xml['system'][$section] = $config_copy['system'][$section];
229
			default:
230
				$xml[$section] = $config_copy[$section];
231
		}
232
	}
233

    
234
	$params = array(
235
		XML_RPC_encode($password),
236
		XML_RPC_encode($xml)
237
	);
238

    
239
	$numberofruns = 0;
240
	while ($numberofruns < 2) {
241
		log_error("Beginning XMLRPC sync to {$url}:{$port}.");
242
		$msg = new XML_RPC_Message($method, $params);
243
		$cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
244
		$cli->setCredentials($username, $password);
245
		if($numberofruns > 0)
246
			$cli->setDebug(1);
247
		/* send our XMLRPC message and timeout after 240 seconds */
248
		$resp = $cli->send($msg, "240");
249
		if(!is_object($resp)) {
250
			$error = "A communications error occurred while attempting XMLRPC sync with username {$username} {$url}:{$port}.";
251
			log_error($error);
252
			file_notice("sync_settings", $error, "Settings Sync", "");
253
		} elseif($resp->faultCode()) {
254
			$error = "An error code was received while attempting XMLRPC sync with username {$username} {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
255
			log_error($error);
256
			file_notice("sync_settings", $error, "Settings Sync", "");
257
		} else {
258
			$parsed_response =  XML_RPC_decode($resp->value());
259
			if(!is_array($parsed_response) && trim($parsed_response) == "Authentication failed") {
260
				$error = "An authentication failure occurred while trying to access {$url}:{$port} ($method).";
261
				log_error($error);
262
				file_notice("sync_settings", $error, "Settings Sync", "");
263
				exit;
264
			} else {
265
				log_error("XMLRPC sync successfully completed with {$url}:{$port}.");
266
				update_filter_reload_status("XMLRPC sync successfully completed with {$url}:{$port}.");
267
			}
268
			$numberofruns = 3;
269
		}
270
		$numberofruns++;
271
	}
272
}
273

    
274
global $g;
275
if (file_exists("{$g['varrun_path']}/booting") || $g['booting'])
276
	return;
277

    
278
if (is_array($config['hasync'])) {
279
	update_filter_reload_status("Building high availability sync information");
280
	$hasync = $config['hasync'];
281

    
282
	if (empty($hasync['synchronizetoip'])) {
283
		/* this gets hit on every filter sync on the secondary, a log here creates a lot of log spam and I never saw it actually log anything useful */
284
		exit;
285
	}
286

    
287
	/*
288
	* XXX: The way we're finding the port right now is really suboptimal -
289
	*     we can't assume that the other machine is setup identically.
290
	*/
291
	if (!empty($config['system']['webgui']['protocol'])) {
292
		$synchronizetoip = $config['system']['webgui']['protocol'];
293
		$synchronizetoip .= "://";
294
	}
295

    
296
	/* if port is empty lets rely on the protocol selection */
297
	$port = $config['system']['webgui']['port'];
298
	if (empty($port)) {
299
		if ($config['system']['webgui']['protocol'] == "http")
300
			$port = "80";
301
		else
302
			$port = "443";
303
	}
304

    
305
	if(is_ipaddrv6($hasync['synchronizetoip']))
306
		$hasync['synchronizetoip'] = "[{$hasync['synchronizetoip']}]";
307
	$synchronizetoip .= $hasync['synchronizetoip'];
308
	if ($hasync['synchronizerules'] != "") {
309
		if (!is_array($config['filter']))
310
			$config['filter'] = array();
311
		$sections[] = 'filter';
312
	}
313
	if ($hasync['synchronizenat'] != "") {
314
		if (!is_array($config['nat']))
315
			$config['nat'] = array();
316
		$sections[] = 'nat';
317
	}
318
	if ($hasync['synchronizealiases'] != "") {
319
		if (!is_array($config['aliases']))
320
			$config['aliases'] = array();
321
		$sections[] = 'aliases';
322
	}
323
	if ($hasync['synchronizedhcpd'] != "" and is_array($config['dhcpd']))
324
		$sections[] = 'dhcpd';
325
	if ($hasync['synchronizewol'] != "") {
326
		if (!is_array($config['wol']))
327
			$config['wol'] = array();
328
		$sections[] = 'wol';
329
	}
330
	if ($hasync['synchronizetrafficshaper'] != "" and is_array($config['shaper']))
331
		$sections[] = 'shaper';
332
	if ($hasync['synchronizetrafficshaperlimiter'] != "" and is_array($config['dnshaper']))
333
		$sections[] = 'dnshaper';
334
	if ($hasync['synchronizetrafficshaperlayer7'] != "" and is_array($config['l7shaper']))
335
		$sections[] = 'l7shaper';
336
	if ($hasync['synchronizestaticroutes'] != "") {
337
		if (!is_array($config['staticroutes']))
338
			$config['staticroutes'] = array();
339
		if (!is_array($config['staticroutes']['route']))
340
			$config['staticroutes']['route'] = array();
341
		$sections[] = 'staticroutes';
342
		if (!is_array($config['gateways']))
343
			$config['gateways'] = array();
344
		$sections[] = 'gateways';
345
	}
346
	if ($hasync['synchronizevirtualip'] != "") {
347
		if (!is_array($config['virtualip']))
348
			$config['virtualip'] = array();
349
		$sections[] = 'virtualip';
350
	}
351
	if ($hasync['synchronizelb'] != "") {
352
		if (!is_array($config['load_balancer']))
353
			$config['load_balancer'] = array();
354
		$sections[] = 'load_balancer';
355
	}
356
	if ($hasync['synchronizeipsec'] != "") {
357
		if (!is_array($config['ipsec']))
358
			$config['ipsec'] = array();
359
		$sections[] = 'ipsec';
360
	}
361
	if ($hasync['synchronizeopenvpn'] != "") {
362
		if (!is_array($config['openvpn']))
363
			$config['openvpn'] = array();
364
		$sections[] = 'openvpn';
365
	}
366
	if ($hasync['synchronizecerts'] != "" || $hasync['synchronizeopenvpn'] != "") {
367
		if (!is_array($config['cert']))
368
			$config['cert'] = array();
369
		$sections[] = 'cert';
370

    
371
		if (!is_array($config['ca']))
372
			$config['ca'] = array();
373
		$sections[] = 'ca';
374

    
375
		if (!is_array($config['crl']))
376
			$config['crl'] = array();
377
		$sections[] = 'crl';
378
	}
379
	if ($hasync['synchronizeusers'] != "") {
380
		$sections[] = 'user';
381
		$sections[] = 'group';
382
	} 
383
	if ($hasync['synchronizeauthservers'] != "") {
384
		$sections[] = 'authserver';
385
	}
386
	if ($hasync['synchronizednsforwarder'] != "" and is_array($config['dnsmasq']))
387
		$sections[] = 'dnsmasq';
388
	if ($hasync['synchronizeschedules'] != "" || $hasync['synchronizerules'] != "") {
389
		if (!is_array($config['schedules']))
390
			$config['schedules'] = array();
391
		$sections[] = 'schedules';
392
	}
393
	if ($hasync['synchronizecaptiveportal'] != "" and is_array($config['captiveportal']))
394
		$sections[] = 'captiveportal';
395
	if ($hasync['synchronizecaptiveportal'] != "" and is_array($config['vouchers']))
396
		$sections[] = 'vouchers';
397

    
398
	if (count($sections) <= 0) {
399
		log_error("Nothing has been configured to be synched. Skipping....");
400
		exit;
401
	}
402

    
403
	if (empty($hasync['username']))
404
		$username = "admin";
405
	else
406
		$username = $hasync['username'];
407

    
408
	if (!carp_check_version($synchronizetoip, $username, $hasync['password'], $port))
409
		exit;
410

    
411
	update_filter_reload_status("Signaling CARP reload signal...");
412
	carp_sync_xml($synchronizetoip, $username, $hasync['password'], $sections, $port);
413
	$cli = new XML_RPC_Client('/xmlrpc.php', $synchronizetoip, $port);
414
	$params = array(
415
	  XML_RPC_encode($hasync['password'])
416
	);
417

    
418
	$msg = new XML_RPC_Message('pfsense.filter_configure', $params);
419
	$cli->setCredentials($username, $hasync['password']);
420
	$resp = $cli->send($msg, "900");
421

    
422
	if (!is_object($resp)) {
423
		$error = "A communications error occurred while attempting Filter sync with username {$username} {$synchronizetoip}:{$port}.";
424
		log_error($error);
425
		file_notice("sync_settings", $error, "Settings Sync", "");
426
	} elseif($resp->faultCode()) {
427
		$error = "An error code was received while attempting Filter sync with username {$username} {$synchronizetoip}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
428
		log_error($error);
429
		file_notice("sync_settings", $error, "Settings Sync", "");
430
	} else {
431
		log_error("Filter sync successfully completed with {$synchronizetoip}:{$port}.");
432
		$numberofruns = 3;
433
	}
434
}
435

    
436
?>
(50-50/103)