Project

General

Profile

Download (51.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2

    
3
/*
4
	vpn.inc
5
	Copyright (C) 2004 Scott Ullrich
6
	Copyright (C) 2008 Shrew Soft Inc
7
	Copyright (C) 2008 Ermal Lu?i
8
	All rights reserved.
9

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

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

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

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

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

    
36
/*
37
	pfSense_BUILDER_BINARIES:	/usr/bin/killall	/usr/local/sbin/sasyncd	/sbin/ifconfig	/sbin/sysctl
38
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/setkey	/usr/bin/netstat	/sbin/route	/bin/mkdir
39
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/racoonctl	/usr/local/sbin/racoon
40
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/filterdns	/usr/local/sbin/mpd4	
41
	pfSense_MODULE:	vpn
42
*/
43

    
44
/* include all configuration functions */
45

    
46
function vpn_ipsec_failover_configure() {
47
	global $config, $g;
48

    
49

    
50
	if (is_array($config['installedpackages']['sasyncd'])) {
51
		$sasyncd_text = "";
52
		foreach ($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
53
			$enabled = isset ($sasyncd['enable']);
54
			if (!$enabled)
55
				return;
56
			if ($sasyncd['peerip'] <> "")
57
				$sasyncd_text .= "peer {$sasyncd['peerip']}\n";
58
			if ($sasyncd['interface'])
59
				$sasyncd_text .= "carp interface {$sasyncd['interface']}\n";
60
			if ($sasyncd['sharedkey'] <> "")
61
				$sasyncd_text .= "sharedkey {$sasyncd['sharedkey']}\n";
62
			if ($sasyncd['mode'] <> "")
63
				$sasyncd_text .= "mode {$sasyncd['mode']}\n";
64
			if ($sasyncd['listenon'] <> "")
65
				$sasyncd_text .= "listen on {$sasyncd['listenon']}\n";
66
			if ($sasyncd['flushmodesync'] <> "")
67
				$sasyncd_text .= "flushmode sync {$sasyncd['flushmodesync']}\n";
68
		}
69

    
70
		file_put_contents("{$g['varetc_path']}/sasyncd.conf", $sasyncd_text);
71
		chmod("{$g['varetc_path']}/sasyncd.conf", 0600);
72

    
73
		if(is_process_running("sasyncd"))
74
			mwexec("killall sasyncd", true);
75

    
76
		/* launch sasyncd, oh wise one */
77
		mwexec_bg("/usr/local/sbin/sasyncd -d -v -v -v");
78
	}
79
}
80

    
81
function vpn_ipsec_configure($ipchg = false)
82
{
83
	global $config, $g, $sa, $sn, $p1_ealgos, $p2_ealgos;
84

    
85
	/* get the automatic ping_hosts.sh ready */
86
	unlink_if_exists("{$g['vardb_path']}/ipsecpinghosts");
87
	touch("{$g['vardb_path']}/ipsecpinghosts");
88

    
89
	vpn_ipsec_configure_preferoldsa();
90

    
91
	$syscfg = $config['system'];
92
	$ipseccfg = $config['ipsec'];
93
	$a_phase1 = $config['ipsec']['phase1'];
94
	$a_phase2 = $config['ipsec']['phase2'];
95
	$a_client = $config['ipsec']['client'];
96

    
97
	if (!isset($ipseccfg['enable'])) {
98
		mwexec("/sbin/ifconfig enc0 down");
99

    
100
		/* send a SIGKILL to be sure */
101
		sigkillbypid("{$g['varrun_path']}/racoon.pid", "KILL");
102

    
103
		/* kill racoon */
104
		if(is_process_running("racoon"))
105
			mwexec("/usr/bin/killall racoon", true);
106
		killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
107

    
108
		/* wait for racoon process to die */
109
		sleep(2);
110

    
111
		/* flush SPD and SAD */
112
		mwexec("/usr/local/sbin/setkey -F");
113
		mwexec("/usr/local/sbin/setkey -FP");
114

    
115
		/* disallow IPSEC, it is off */
116
		exec("/sbin/sysctl net.inet.ip.ipsec_in_use=0");
117

    
118
		return true;
119
	} else {
120
		mwexec("/sbin/ifconfig enc0 up");
121
		mwexec("/sbin/sysctl net.inet.ip.ipsec_in_use=1");
122

    
123
		if ($g['booting'])
124
			echo gettext("Configuring IPsec VPN... ");
125

    
126
		/* fastforwarding is not compatible with ipsec tunnels */
127
		mwexec("/sbin/sysctl net.inet.ip.fastforwarding=0");
128

    
129
		/* this loads a route table which is used to determine if a route needs to be removed. */
130
		exec("/usr/bin/netstat -rnf inet", $route_arr, $retval);
131
		$route_str = implode("\n", $route_arr);
132

    
133
		/* resolve all local, peer addresses and setup pings */
134
		$ipmap = array();
135
		$rgmap = array();
136
		$filterdns_list = array();
137
		if (is_array($a_phase1) && count($a_phase1)) {
138

    
139
			$ipsecpinghosts = "";
140
			/* step through each phase1 entry */
141
			$ipsecpinghosts = "";
142
			foreach ($a_phase1 as $ph1ent) {
143
				if (isset($ph1ent['disabled']))
144
					continue;
145

    
146
				$ep = ipsec_get_phase1_src($ph1ent);
147
				if (!is_ipaddr($ep))
148
					continue;
149

    
150
				if(!in_array($ep,$ipmap))
151
					$ipmap[] = $ep;
152

    
153
				/* see if this tunnel has a hostname for the remote-gateway. If so,
154
				   try to resolve it now and add it to the list for filterdns */
155

    
156
				if (isset ($ph1ent['mobile']))
157
					continue;
158

    
159
				$rg = $ph1ent['remote-gateway'];
160

    
161
				if (!is_ipaddr($rg)) {
162
					$filterdns_list[] = "{$rg}";
163
					add_hostname_to_watch($rg);
164
					if(! $g['booting'])
165
						$rg = resolve_retry($rg);
166
					if (!is_ipaddr($rg))
167
						continue;
168
				}
169
				if(array_search($rg, $rgmap)) {
170
					log_error("The remote gateway {$rg} already exists on another phase 1 entry");
171
					continue;
172
				}
173
				$rgmap[$ph1ent['remote-gateway']] = $rg;
174

    
175
				/* step through each phase2 entry */
176
				foreach ($a_phase2 as $ph2ent) {
177

    
178
					$ikeid = $ph2ent['ikeid'];
179

    
180
					if (isset($ph2ent['disabled']))
181
						continue;
182

    
183
					if ($ikeid != $ph1ent['ikeid'])
184
						continue;
185

    
186
					$ph2ent['localid']['mode'] = $ph2ent['mode'];
187
					/* add an ipsec pinghosts entry */
188
					if ($ph2ent['pinghost']) {
189
						$iflist = get_configured_interface_list();
190
						foreach ($iflist as $ifent => $ifname) {
191
							if(is_ipaddrv6($ph2ent['pinghost'])) {
192
								$interface_ip = get_interface_ipv6($ifent);
193
								if(!is_ipaddrv6($interface_ip))
194
									continue;
195
								$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
196
								if (ip_in_subnet($interface_ip, $local_subnet)) {
197
									$srcip = $interface_ip;
198
									break;
199
								}
200
							} else {
201
								$interface_ip = get_interface_ip($ifent);
202
								if(!is_ipaddrv4($interface_ip))
203
									continue;
204
								$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
205
								if (ip_in_subnet($interface_ip, $local_subnet)) {
206
									$srcip = $interface_ip;
207
									break;
208
								}
209
							}
210
						}
211
						$dstip = $ph2ent['pinghost'];
212
						if(is_ipaddrv6($dstip)) {
213
							$family = "inet6";
214
						} else {
215
							$family = "inet";
216
						}
217
						if (is_ipaddr($srcip))
218
							$ipsecpinghosts[] = "{$srcip}|{$dstip}|3|||||{$family}|\n";
219

    
220
					}
221
				}
222
				file_put_contents("{$g['vardb_path']}/ipsecpinghosts", $ipsecpinghosts);
223
				
224
			}
225
		}
226

    
227
		/* generate CA certificates files */
228
		if (is_array($config['ca']) && count($config['ca'])) {
229
			foreach ($config['ca'] as $ca) {
230
				if (!isset($ca['crt'])) {
231
					log_error(sprintf(gettext("Error: Invalid certificate info for %s"), $ca['descr']));
232
					continue;
233
				}
234
				$cert = base64_decode($ca['crt']);
235
				$x509cert = openssl_x509_parse(openssl_x509_read($cert));
236
				if (!is_array($x509cert) || !isset($x509cert['hash'])) {
237
					log_error(sprintf(gettext("Error: Invalid certificate hash info for %s"), $ca['descr']));
238
					continue;
239
				}
240
				$fname = $g['varetc_path']."/".$x509cert['hash'].".0";
241
				if (!file_put_contents($fname, $cert)) {
242
					log_error(sprintf(gettext("Error: Cannot write IPsec CA file for %s"), $ca['descr']));
243
					continue;
244
				}
245
			}
246
		}
247
		
248
		/* generate psk.txt */
249
		$fd = fopen("{$g['varetc_path']}/psk.txt", "w");
250
		if (!$fd) {
251
			printf(gettext("Error: cannot open psk.txt in vpn_ipsec_configure().") . "\n");
252
			return 1;
253
		}
254

    
255
		$pskconf = "";
256

    
257
		if (is_array($a_phase1) && count($a_phase1)) {
258
			foreach ($a_phase1 as $ph1ent) {
259

    
260
				if (isset($ph1ent['disabled']))
261
					continue;
262

    
263
				if (strstr($ph1ent['authentication_method'],'rsa'))
264
					continue;
265

    
266
				$peerid_type = $ph1ent['peerid_type'];
267

    
268
				switch ($peerid_type) {
269
					case "peeraddress":
270
						$peerid_type = "address";
271
						$peerid_data = $rgmap[$ph1ent['remote-gateway']];
272
						break;
273

    
274
					case "address";
275
						$peerid_data = $ph1ent['peerid_data'];
276
						break;
277

    
278
					case "fqdn";
279
					case "keyid tag";
280
					case "user_fqdn";
281
						$peerid_data = $ph1ent['peerid_data'];
282
						break;
283
				}
284

    
285
				if (!empty($peerid_data) && !empty($ph1ent['pre-shared-key']))
286
					$pskconf .= trim($peerid_data) . "\t" . trim($ph1ent['pre-shared-key']) . "\n";
287
			}
288
		}
289

    
290
		/* Add user PSKs */
291
		foreach ($config['system']['user'] as $user) {
292
			if (!empty($user['ipsecpsk'])) {
293
				$pskconf .= "{$user['name']}\t{$user['ipsecpsk']}\n";
294
			}
295
		}
296

    
297
		/* add PSKs for mobile clients */
298
		if (is_array($ipseccfg['mobilekey'])) {
299
			foreach ($ipseccfg['mobilekey'] as $key) {
300
				$pskconf .= "{$key['ident']}\t{$key['pre-shared-key']}\n";
301
			}
302
		}
303

    
304
		fwrite($fd, $pskconf);
305
		fclose($fd);
306
		chmod("{$g['varetc_path']}/psk.txt", 0600);
307
			
308
		/* begin racoon.conf */
309
		if ((is_array($a_phase1) && count($a_phase1)) ||
310
			(is_array($a_phase2) && count($a_phase2))) {
311

    
312
			$fd = fopen("{$g['varetc_path']}/racoon.conf", "w");
313
			if (!$fd) {
314
				printf(gettext("Error: cannot open racoon.conf in vpn_ipsec_configure().") . "\n");
315
				return 1;
316
			}
317

    
318
			$racoonconf = "# This file is automatically generated. Do not edit\n";			
319
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
320
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
321

    
322
			/* begin listen section */
323
			if (count($ipmap)) {
324
				$racoonconf .= "\nlisten\n";
325
				$racoonconf .= "{\n";
326
				$racoonconf .= "	adminsock \"/var/db/racoon/racoon.sock\" \"root\" \"wheel\" 0660;\n";
327
				foreach ($ipmap as $addr) {
328
					$racoonconf .= "\tisakmp {$addr} [500];\n";
329
					$racoonconf .= "\tisakmp_natt {$addr} [4500];\n";
330
				}
331
				$racoonconf .= "}\n\n";
332
			}
333

    
334
			/* begin mode_cfg section */
335
			if (is_array($a_client) && isset($a_client['enable'])) {
336

    
337
				$racoonconf .= "\nmode_cfg\n";
338
				$racoonconf .= "{\n";
339

    
340
				if ($a_client['user_source'])
341
					$racoonconf .= "\tauth_source {$a_client['user_source']};\n";
342
				if ($a_client['group_source'])
343
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
344

    
345
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
346
					$pool_address = $a_client['pool_address'];
347
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
348

    
349
					$pool_address = long2ip32(ip2long($pool_address)+1);
350
					$pool_size = (~ip2long($pool_netmask) & 0xFFFFFFFF) - 2;
351

    
352
					$racoonconf .= "\tpool_size {$pool_size};\n";
353
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
354
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
355
				}
356

    
357
				if (isset($a_client['net_list'])) {
358

    
359
					$net_list = '';
360

    
361
					foreach ($a_phase2 as $ph2ent) {
362

    
363
						if (isset($ph2ent['disabled']))
364
							continue;
365

    
366
						if (!isset($ph2ent['mobile']))
367
							continue;
368

    
369
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
370

    
371
						if ($net_list)
372
							$net_list .= ", ";
373
						$net_list .= $localid;
374
					}
375

    
376
					if ($net_list)
377
						$racoonconf .= "\tsplit_network include {$net_list};\n";
378
				}
379

    
380
				if ($a_client['dns_server1'])
381
					$racoonconf .= "\tdns4 {$a_client['dns_server1']};\n";
382
				if ($a_client['dns_server2'])
383
					$racoonconf .= "\tdns4 {$a_client['dns_server2']};\n";
384
				if ($a_client['dns_server3'])
385
					$racoonconf .= "\tdns4 {$a_client['dns_server3']};\n";
386
				if ($a_client['dns_server4'])
387
					$racoonconf .= "\tdns4 {$a_client['dns_server4']};\n";
388

    
389
				if ($a_client['wins_server1'])
390
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
391
				if ($a_client['wins_server2'])
392
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
393

    
394
				if ($a_client['dns_domain']) {
395
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
396
					$racoonconf .= "\tsplit_dns \"{$a_client['dns_domain']}\";\n";
397
				}
398

    
399
				if ($a_client['pfs_group'])
400
					$racoonconf .= "\tpfs_group {$a_client['pfs_group']};\n";
401

    
402
				if ($a_client['login_banner']) {
403
					$fn = "{$g['varetc_path']}/racoon.motd";
404
					$fd1 = fopen($fn, "w");
405
					if (!$fd1) {
406
						printf(gettext("Error: cannot open server %s in vpn.\n"), $fn);
407
						return 1;
408
					}
409

    
410
					fwrite($fd1, $a_client['login_banner']);
411
					fclose($fd1);
412

    
413
					$racoonconf .= "\tbanner \"{$fn}\";\n";
414
				}
415

    
416
				if (isset($a_client['save_passwd']))
417
					$racoonconf .= "\tsave_passwd on;\n";
418

    
419
				$racoonconf .= "}\n\n";
420
			}
421
			/* end mode_cfg section */
422

    
423
			/* begin remote sections */
424
			if (is_array($a_phase1) && count($a_phase1)) {
425
				/* begin remote */
426
				foreach ($a_phase1 as $ph1ent) {
427

    
428
					if (isset($ph1ent['disabled']))
429
						continue;
430

    
431
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
432
						continue;
433

    
434
					$ikeid = $ph1ent['ikeid'];
435

    
436
					$ep = ipsec_get_phase1_src($ph1ent);
437
					if (!$ep)
438
						continue;
439

    
440
					if (!isset($ph1ent['mobile'])) {
441
						$rgip = $rgmap[$ph1ent['remote-gateway']];
442
						if (!$rgip)
443
							continue;
444
					}
445

    
446
					$myid_type = $ph1ent['myid_type'];
447

    
448
					switch ($myid_type) {
449

    
450
						case "myaddress":
451
							$myid_type = "address";
452
							$myid_data = $ep;
453
							break;
454

    
455
						case "dyn_dns":
456
							$myid_type = "address";
457
							$myid_data = resolve_retry($ph1ent['myid_data']);
458
							break;
459

    
460
						case "address";
461
							$myid_data = $ph1ent['myid_data'];
462
							break;
463

    
464
						case "fqdn";
465
						case "keyid tag";
466
						case "user_fqdn";
467
						case "asn1dn";
468
							$myid_data = $ph1ent['myid_data'];
469
							if( $myid_data )
470
								$myid_data = "\"".$myid_data."\"";
471
							break;
472
					}
473

    
474
					$peerid_type = $ph1ent['peerid_type'];
475

    
476
					switch ($peerid_type) {
477
						case "peeraddress":
478
							$peerid_type = "address";
479
							$peerid_data = $rgip;
480
							break;
481

    
482
						case "address";
483
							$peerid_data = $ph1ent['peerid_data'];
484
							break;
485

    
486
						case "fqdn";
487
						case "keyid tag";
488
						case "user_fqdn";
489
						case "asn1dn";
490
							$peerid_data = $ph1ent['peerid_data'];
491
							if( $peerid_data )
492
								$peerid_data = "\"".$peerid_data."\"";
493
							break;
494
					}
495

    
496
					$natt = "off";
497
					if (isset($ph1ent['nat_traversal']))
498
						$natt = $ph1ent['nat_traversal'];
499

    
500
					$init = "on";
501
					$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "off";
502
					$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "claim";
503
					$passive = "";
504
					if (isset($ph1ent['mobile'])) {
505
						$rgip = "anonymous";
506
						$passive = "passive on;";
507
						/* Mimic 1.2.3's behavior for pure-psk mobile tunnels */
508
						if ($ph1ent['authentication_method'] == "pre_shared_key") {
509
							$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "obey";
510
							$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "on";
511
						} else {
512
							$init = "off";
513
							$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "unique";
514
						}
515
					}
516

    
517
					$dpdline1 = '';
518
					$dpdline2 = '';
519
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
520
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
521
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
522
					}
523

    
524
					if (isset ($ph1ent['authentication_method']))
525
						$authmethod = $ph1ent['authentication_method'];
526
					else
527
						$authmethod = 'pre_shared_key';
528

    
529
					$certline = '';
530

    
531
					if (strstr($authmethod,'rsa')) {
532

    
533
						$cert = lookup_cert($ph1ent['certref']);
534

    
535
						if (!$cert)
536
						{
537
							log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
538
							continue;
539
						}
540

    
541
						$certfile = "cert-".$ikeid.".crt";
542
						$certpath = $g['varetc_path']."/".$certfile;
543

    
544
						if (!file_put_contents($certpath, base64_decode($cert['crt'])))
545
						{
546
							log_error(sprintf(gettext("Error: Cannot write phase1 certificate file for %s"), $ph1ent['name']));
547
							continue;
548
						}
549

    
550
						chmod($certpath, 0600);
551

    
552
						$keyfile = "cert-".$ikeid.".key";
553
						$keypath = $g['varetc_path']."/".$keyfile;
554

    
555
						if (!file_put_contents($keypath, base64_decode($cert['prv'])))
556
						{
557
							log_error(sprintf(gettext("Error: Cannot write phase1 key file for %s"), $ph1ent['name']));
558
							continue;
559
						}
560

    
561
						chmod($keypath, 0600);
562

    
563
						$ca = lookup_ca($ph1ent['caref']);
564
						if ($ca) {
565
							$cafile = "ca-".$ikeid.".crt";
566
							$capath = $g['varetc_path']."/".$cafile;
567

    
568
							if (!file_put_contents($capath, base64_decode($ca['crt'])))
569
							{
570
								log_error(sprintf(gettext("Error: Cannot write phase1 CA certificate file for %s"), $ph1ent['name']));
571
								continue;
572
							}
573

    
574
							chmod($capath, 0600);
575
							$caline = "ca_type x509 \"".basename($capath)."\";";
576
						}
577

    
578
						$certline = "certificate_type x509 \"".basename($certpath)."\" \"".basename($keypath)."\";";
579

    
580
					}
581

    
582
					$ealgos = '';
583
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
584
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
585
					if ($ealg_kl)
586
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
587
					else
588
						$ealgos = $ealgos.$ealg_id;
589

    
590
					$lifeline = '';
591
					if ($ph1ent['lifetime'])
592
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
593

    
594
					/* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */
595
					if (!(($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))) {
596
						$peerid_spec = "peers_identifier {$peerid_type} {$peerid_data};";
597
					}
598

    
599
					/* add remote section to configuration */
600

    
601
					$racoonconf .=<<<EOD
602

    
603
remote {$rgip}
604
{
605
	ph1id {$ikeid};
606
	exchange_mode {$ph1ent['mode']};
607
	my_identifier {$myid_type} {$myid_data};
608
	{$peerid_spec}
609
	ike_frag on;
610
	generate_policy = {$genp};
611
	initial_contact = {$init};
612
	nat_traversal = {$natt};
613
	{$certline}
614
	{$caline}
615
	{$dpdline1}
616
	{$dpdline2}
617
	support_proxy on;
618
	proposal_check {$pcheck};
619
	{$passive}
620

    
621
	proposal
622
	{
623
		authentication_method {$authmethod};
624
		encryption_algorithm ${ealgos};
625
		hash_algorithm {$ph1ent['hash-algorithm']};
626
		dh_group {$ph1ent['dhgroup']};
627
		${lifeline}
628
	}
629
}
630

    
631
EOD;
632
				}
633
				/* end remote */
634
			}
635
			/* end remote sections */
636
		
637
			/* begin sainfo sections */
638
			if (is_array($a_phase2) && count($a_phase2)) {
639

    
640
				/* begin sainfo */
641
				foreach ($a_phase2 as $ph2ent) {
642

    
643
					$ikeid = $ph2ent['ikeid'];
644

    
645
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
646
						continue;
647

    
648
					if (isset($ph1ent['disabled']))
649
						continue;
650

    
651
					if (isset($ph2ent['disabled']))
652
						continue;
653

    
654
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
655
						continue;
656

    
657
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
658

    
659
						$localid_type = $ph2ent['localid']['type'];
660
						$ph2ent['localid']['mode'] = $ph2ent['mode'];
661
						$localid_data = ipsec_idinfo_to_cidr($ph2ent['localid']);
662
						/* Do not print localid in some cases, such as a pure-psk or psk/xauth single phase2 mobile tunnel */
663
						if (($localid_type == "none") ||
664
							(($ph1ent['authentication_method'] == "xauth_psk_server") ||
665
							($ph1ent['authentication_method'] == "pre_shared_key"))
666
							&& isset($ph1ent['mobile'])
667
							&& (ipsec_get_number_of_phase2($ikeid)==1))
668
							$localid_spec = " ";
669
						else {
670
							if ($localid_type != "address") {
671
								$localid_type = "subnet";
672
							}
673
							$localid_spec = $localid_type." ".$localid_data." any";
674
						}
675

    
676
						if (!isset($ph2ent['mobile'])) {
677
							$remoteid_type = $ph2ent['remoteid']['type'];
678
							if ($remoteid_type != "address")
679
								$remoteid_type = "subnet";
680

    
681
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
682
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
683
						} else
684
							$remoteid_spec = "anonymous";
685

    
686
					} else {
687
						$rgip = $rgmap[$ph1ent['remote-gateway']];
688

    
689
						if ((($ph1ent['authentication_method'] == "xauth_psk_server") ||
690
							($ph1ent['authentication_method'] == "pre_shared_key"))
691
							&& isset($ph1ent['mobile']))
692
							$localid_spec = " ";
693
						else {
694
							$localid_data = ipsec_get_phase1_src($ph1ent);
695
							if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
696
							$localid_spec = "address {$localid_data}";
697
						}
698
						if (!isset($ph2ent['mobile'])) {
699
							$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
700
							if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
701
							$remoteid_spec = "address {$remoteid_data}";
702
						} else
703
							$remoteid_spec = "anonymous";
704
					}
705

    
706
					if($ph2ent['protocol'] == 'esp') {
707

    
708
						$ealgos = '';
709

    
710
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
711

    
712
							$ealg_id = $ealg['name'];
713
							$ealg_kl = $ealg['keylen'];
714

    
715
							if ($ealg_kl) {
716
								if( $ealg_kl == "auto" ) {
717
									/*   This seems to be required on my system and was not reproducable
718
									 *   on other systems.   For some reason $p2_ealgos is not defined
719
									 *   and needs to be read back in!?  -sullrich Aug 26, 2009 
720
									 */
721
									if(!$p2_ealgos)
722
										require("ipsec.inc");
723
									$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
724
									$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
725
									$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
726
									/* in some cases where include ordering is suspect these variables
727
									   are somehow 0 and we enter this loop forever and timeout after 900
728
									   seconds wrecking bootup */
729
									if($key_hi != 0 and $key_lo !=0 and $key_step !=0) {
730
										for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
731
//											Uncomment the next line if you want to test the comment 5 lines up.											
732
//											echo "$keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step \n";
733
											if ($ealgos)
734
												$ealgos = $ealgos.", ";
735
											$ealgos = $ealgos.$ealg_id." ".$keylen;
736
										}
737
									}
738
								} else {
739
									if ($ealgos)
740
										$ealgos = $ealgos.", ";
741
									$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
742
								}
743
							} else {
744
								if ($ealgos)
745
									$ealgos = $ealgos.", ";
746
								$ealgos = $ealgos.$ealg_id;
747
							}
748
						}
749

    
750
						$ealgosline = "encryption_algorithm {$ealgos};";
751

    
752
					} else {
753

    
754
						$ealgosline = "encryption_algorithm null_enc;";
755
					}
756

    
757
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
758
					$halgosline = "authentication_algorithm {$halgos};";
759

    
760
					$pfsline = '';
761
					if ($ph2ent['pfsgroup'])
762
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
763
					if (isset($a_client['pfs_group'])) {
764
						$pfsline = '';
765
						if ($a_client['pfs_group'])
766
							$pfsline = "pfs_group {$a_client['pfs_group']};";
767
					}
768

    
769
					$lifeline = '';
770
					if ($ph2ent['lifetime'])
771
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
772

    
773
					/* add sainfo section to configuration */
774
					
775
					$racoonconf .=<<<EOD
776
					
777
sainfo {$localid_spec} {$remoteid_spec}
778
{
779
	remoteid {$ikeid};
780
	{$ealgosline}
781
	{$halgosline}
782
	{$pfsline}
783
	{$lifeline}
784
	compression_algorithm deflate;
785
}
786

    
787
EOD;
788
				}
789
				/* end sainfo */
790
			}
791
			/* end sainfo sections */
792

    
793
			fwrite($fd, $racoonconf);
794
			fclose($fd);
795
		}
796
		/* end racoon.conf */
797

    
798
		/* generate IPsec policies */
799
		if (is_array($a_phase2) && count($a_phase2)) {
800
			/* generate spd.conf */
801
			$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
802
			if (!$fd) {
803
				printf(gettext("Error: cannot open spd.conf in vpn_ipsec_configure().") . "\n");
804
				return 1;
805
			}
806

    
807
			$spdconf = "";
808

    
809
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
810
			if ($config['interfaces']['lan']) {
811
				$lanip = get_interface_ip("lan");
812
				if (!empty($lanip) && is_ipaddrv4($lanip)) {
813
					$lansn = get_interface_subnet("lan");
814
					$lansa = gen_subnet($lanip, $lansn);
815
					$spdconf .= "spdadd -4 {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
816
					$spdconf .= "spdadd -4 {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
817
				}
818
				$lanipv6 = get_interface_ipv6("lan");
819
				if (!empty($lanipv6) && is_ipaddrv6($lanipv6)) {
820
					$lansnv6 = get_interface_subnetv6("lan");
821
					$lansav6 = gen_subnetv6($lanipv6, $lansnv6);
822
					$spdconf .= "spdadd -6 {$lanipv6}/128 {$lansav6}/{$lansnv6} any -P out none;\n";
823
					$spdconf .= "spdadd -6 {$lansav6}/{$lansnv6} {$lanipv6}/128 any -P in none;\n";
824
				}
825
			}
826

    
827
			foreach ($a_phase2 as $ph2ent) {
828

    
829
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
830
					continue;
831

    
832
				if (isset($ph1ent['mobile']))
833
					continue;
834

    
835
				if (isset($ph1ent['disabled']))
836
					continue;
837

    
838
				if (isset($ph2ent['disabled']))
839
					continue;
840

    
841
				$ep = ipsec_get_phase1_src($ph1ent);
842
				if (!$ep)
843
					continue;
844

    
845
				$rgip = $rgmap[$ph1ent['remote-gateway']];
846
				if(!is_ipaddr($rgip))
847
					continue;
848

    
849
				$ph2ent['localid']['mode'] = $ph2ent['mode'];
850
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
851
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
852

    
853
				if(($ph2ent['mode'] == "tunnel") or ($ph2ent['mode'] == 'tunnel6')) {
854
					if($ph2ent['mode'] == "tunnel6")
855
						$family = "-6";
856
					else
857
						$family = "-4";
858

    
859
					$spdconf .= "spdadd {$family} {$localid} {$remoteid} any -P out ipsec " .
860
						"{$ph2ent['protocol']}/tunnel/{$ep}-{$rgip}/unique;\n";
861

    
862
					$spdconf .= "spdadd {$family} {$remoteid} {$localid} any -P in ipsec " .
863
						"{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
864

    
865
				} else {
866

    
867
					$localid_data = ipsec_get_phase1_src($ph1ent);
868
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
869

    
870
					$spdconf .= "spdadd {$localid_data} {$remoteid_data} any -P out ipsec " .
871
						"{$ph2ent['protocol']}/transport//require;\n";
872

    
873
					$spdconf .= "spdadd {$remoteid_data} {$localid_data} any -P in ipsec " .
874
						"{$ph2ent['protocol']}/transport//require;\n";
875

    
876
				}
877

    
878
				/* static route needed? */
879
				if (preg_match("/^carp|^vip/i", $ph1ent['interface']))
880
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
881
				else
882
					$parentinterface = $ph1ent['interface'];
883

    
884
				if (($parentinterface <> "wan") && (is_ipaddr($rgip))) {
885
					/* add endpoint routes to correct gateway on interface */
886
					if (interface_has_gateway($parentinterface)) {
887
						$gatewayip = get_interface_gateway("$parentinterface");
888
						$interfaceip = get_interface_ip($parentinterface);
889
						$subnet_bits = get_interface_subnet($parentinterface);
890
						$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
891
						/* if the remote gateway is in the local subnet, then don't add a route */
892
						if (! ip_in_subnet($rgip, "{$subnet_ip}/{$subnet_bits}")) {
893
							if(is_ipaddr($gatewayip)) {
894
								/* FIXME: does adding route-to and reply-to on the in/outbound
895
								 * rules fix this? smos@ 13-01-2009 */
896
								// log_error("IPSEC interface is not WAN but {$parentinterface}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
897
								mwexec("/sbin/route delete -host {$rgip}; /sbin/route add -host {$rgip} {$gatewayip}", true);
898
							}
899
						}
900
					}
901
				} elseif(is_ipaddr($rgip)) {
902
					if(stristr($route_str, "{$rgip}")) {
903
						mwexec("/sbin/route delete -host {$rgip}", true);
904
					}
905
				}
906
			}
907

    
908
			fwrite($fd, $spdconf);
909
			fclose($fd);
910
		}
911

    
912
		/* needed for racoonctl admin socket */
913
		if (!is_dir("/var/db/racoon"))
914
			mkdir("/var/db/racoon/");
915
		
916
		/* mange racoon process */
917
		if (is_process_running("racoon")) {
918
			sleep("0.1");
919
			mwexec("/usr/local/sbin/racoonctl -s /var/db/racoon/racoon.sock reload-config", false);
920
			/* load SPD without flushing to be safe on config additions or changes. */
921
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
922
		} else {
923
			/* flush SA + SPD entries */
924
			mwexec("/usr/local/sbin/setkey -FP", false);
925
 			sleep("0.1");
926
			mwexec("/usr/local/sbin/setkey -F", false);
927
 			sleep("0.1");
928
 			/* start racoon */
929
			$ipsecdebug = isset($config['ipsec']['racoondebug']) ? "-d -v" : "";
930
			mwexec("/usr/local/sbin/racoon {$ipsecdebug} -f {$g['varetc_path']}/racoon.conf", false);
931
 			sleep("0.1");
932
 			/* load SPD */
933
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
934

    
935
		}
936
		/* start filterdns, if necessary */
937
		if (count($filterdns_list) > 0) {
938
			$interval = 60;
939
			if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval']))
940
				$interval = $ipseccfg['dns-interval'];
941

    
942
			$hostnames = "";
943
			array_unique($filterdns_list);
944
			foreach ($filterdns_list as $hostname)
945
				$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n";
946
			file_put_contents("{$g['varetc_path']}/filterdns-ipsec.hosts", $hostnames);
947

    
948
			killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
949
			sleep(1);
950
			mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/filterdns-ipsec.hosts -d 1");
951
		}
952
	
953
		vpn_ipsec_failover_configure();
954

    
955
		if ($g['booting'])
956
			echo "done\n";
957
	}
958

    
959
	return 0;
960
}
961

    
962
/* Forcefully restart IPsec
963
 * This is required for when dynamic interfaces reload
964
 * For all other occasions the normal vpn_ipsec_configure()
965
 * will gracefully reload the settings without restarting
966
 */
967
function vpn_ipsec_force_reload() {
968
	global $config;
969
	global $g;
970

    
971
	$ipseccfg = $config['ipsec'];
972

    
973
	/* kill racoon */
974
	if(is_process_running("racoon"))
975
		mwexec("/usr/bin/killall racoon", true);
976

    
977
	/* wait for process to die */
978
	sleep(4);
979

    
980
	/* send a SIGKILL to be sure */
981
	sigkillbypid("{$g['varrun_path']}/racoon.pid", "KILL");
982

    
983
	/* wait for flushing to finish */
984
	sleep(1);
985

    
986
	/* if ipsec is enabled, start up again */
987
	if (isset($ipseccfg['enable'])) {
988
		log_error(gettext("Forcefully reloading IPsec racoon daemon"));
989
		vpn_ipsec_configure();
990
	}
991

    
992
}
993

    
994
/* master setup for vpn (mpd) */
995
function vpn_setup() {
996
	/* start pptpd */
997
	vpn_pptpd_configure();
998

    
999
	/* start pppoe server */
1000
	vpn_pppoes_configure();
1001

    
1002
	/* setup l2tp */
1003
	vpn_l2tp_configure();
1004
}
1005

    
1006
function vpn_netgraph_support() {
1007
	$iflist = get_configured_interface_list();
1008
	foreach ($iflist as $iface) {
1009
		$realif = get_real_interface($iface);
1010
		/* Get support for netgraph(4) from the nic */
1011
		$ifinfo = pfSense_get_interface_addresses($realif);
1012
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge")))
1013
                	pfSense_ngctl_attach(".", $realif);
1014
	}
1015
}
1016

    
1017
function vpn_pptpd_configure() {
1018
	global $config, $g;
1019

    
1020
	$syscfg = $config['system'];
1021
	$pptpdcfg = $config['pptpd'];
1022

    
1023
	if ($g['booting']) {
1024
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
1025
			return 0;
1026

    
1027
		echo gettext("Configuring PPTP VPN service... ");
1028
	} else {
1029
		/* kill mpd */
1030
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1031

    
1032
		/* wait for process to die */
1033
		sleep(3);
1034

    
1035
		if (is_process_running("mpd -b")) {
1036
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1037
			log_error(gettext("Could not kill mpd within 3 seconds.   Trying again."));
1038
		}
1039

    
1040
		/* remove mpd.conf, if it exists */
1041
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
1042
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
1043
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
1044
	}
1045

    
1046
	/* make sure pptp-vpn directory exists */
1047
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
1048
		mkdir("{$g['varetc_path']}/pptp-vpn");
1049

    
1050
	switch ($pptpdcfg['mode']) {
1051
		case 'server' :
1052
			/* write mpd.conf */
1053
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
1054
			if (!$fd) {
1055
				printf(gettext("Error: cannot open mpd.conf in vpn_pptpd_configure().") . "\n");
1056
				return 1;
1057
			}
1058

    
1059
			$mpdconf = <<<EOD
1060
pptps:
1061

    
1062
EOD;
1063

    
1064
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1065
				$mpdconf .= "	load pt{$i}\n";
1066
			}
1067

    
1068
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1069

    
1070
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1071

    
1072
				$mpdconf .= <<<EOD
1073

    
1074
pt{$i}:
1075
	new -i pptpd{$i} pt{$i} pt{$i}
1076
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1077
	load pts
1078

    
1079
EOD;
1080
			}
1081

    
1082
			$mpdconf .=<<<EOD
1083

    
1084
pts:
1085
	set iface disable on-demand
1086
	set iface enable proxy-arp
1087
	set iface enable tcpmssfix
1088
	set iface idle 1800
1089
	set iface up-script /usr/local/sbin/vpn-linkup
1090
	set iface down-script /usr/local/sbin/vpn-linkdown
1091
	set bundle enable multilink
1092
	set bundle enable crypt-reqd
1093
	set link yes acfcomp protocomp
1094
	set link no pap chap
1095
	set link enable chap-msv2
1096
	set link mtu 1460
1097
	set link keep-alive 10 60
1098
	set ipcp yes vjcomp
1099
	set bundle enable compression
1100
	set ccp yes mppc
1101
	set ccp yes mpp-e128
1102
	set ccp yes mpp-stateless
1103

    
1104
EOD;
1105

    
1106
			if (!isset ($pptpdcfg['req128'])) {
1107
				$mpdconf .=<<<EOD
1108
	set ccp yes mpp-e40
1109
	set ccp yes mpp-e56
1110

    
1111
EOD;
1112
			}
1113

    
1114
			if  (isset($pptpdcfg["wins"]) && $pptpdcfg['wins'] != "")
1115
				$mpdconf  .=  "	set ipcp nbns {$pptpdcfg['wins']}\n";
1116

    
1117
			if (!empty($pptpdcfg['dns1'])) {
1118
				$mpdconf .= "	set ipcp dns " . $pptpdcfg['dns1'];
1119
				if (!empty($pptpdcfg['dns2']))
1120
					$mpdconf .= " " . $pptpdcfg['dns2'];
1121
				$mpdconf .= "\n";
1122
			} elseif (isset ($config['dnsmasq']['enable'])) {
1123
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1124
				if ($syscfg['dnsserver'][0])
1125
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1126
				$mpdconf .= "\n";
1127
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1128
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1129
			}
1130

    
1131
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1132
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1133
				$acctport = $authport + 1;
1134
				$mpdconf .=<<<EOD
1135
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1136

    
1137
EOD;
1138
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1139
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1140
				$acctport = $authport + 1;
1141
				$mpdconf .=<<<EOD
1142
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret']}" {$authport} {$acctport}
1143

    
1144
EOD;
1145
			}
1146
			$mpdconf .=<<<EOD
1147
	set radius retries 3
1148
	set radius timeout 10
1149
	set auth enable radius-auth
1150

    
1151
EOD;
1152

    
1153
				if (isset ($pptpdcfg['radius']['accounting'])) {
1154
					$mpdconf .=<<<EOD
1155
	set auth enable radius-acct
1156
	set radius acct-update 300
1157

    
1158
EOD;
1159
				}
1160
			}
1161

    
1162
			fwrite($fd, $mpdconf);
1163
			fclose($fd);
1164

    
1165
			/* write mpd.links */
1166
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.links", "w");
1167
			if (!$fd) {
1168
				printf(gettext("Error: cannot open mpd.links in vpn_pptpd_configure().") . "\n");
1169
				return 1;
1170
			}
1171

    
1172
			$mpdlinks = "";
1173

    
1174
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1175
				$mpdlinks .=<<<EOD
1176

    
1177
pt{$i}:
1178
	set link type pptp
1179
	set pptp enable incoming
1180
	set pptp disable originate
1181
	set pptp disable windowing
1182

    
1183
EOD;
1184
			}
1185

    
1186
			fwrite($fd, $mpdlinks);
1187
			fclose($fd);
1188

    
1189
			/* write mpd.secret */
1190
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1191
			if (!$fd) {
1192
				printf(gettext("Error: cannot open mpd.secret in vpn_pptpd_configure().") . "\n");
1193
				return 1;
1194
			}
1195

    
1196
			$mpdsecret = "";
1197

    
1198
			if (is_array($pptpdcfg['user'])) {
1199
				foreach ($pptpdcfg['user'] as $user)
1200
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1201
			}
1202

    
1203
			fwrite($fd, $mpdsecret);
1204
			fclose($fd);
1205
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1206

    
1207
			vpn_netgraph_support();
1208

    
1209
			/* fire up mpd */
1210
			mwexec("/usr/local/sbin/mpd4 -b -d {$g['varetc_path']}/pptp-vpn -p {$g['varrun_path']}/pptp-vpn.pid -s pptps pptps");
1211

    
1212
			break;
1213

    
1214
		case 'redir' :
1215
			break;
1216
	}
1217

    
1218
	if ($g['booting'])
1219
		echo "done\n";
1220

    
1221
	return 0;
1222
}
1223

    
1224
function vpn_pppoes_configure() {
1225
	global $config;
1226

    
1227
	if (is_array($config['pppoes']['pppoe'])) {
1228
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1229
			vpn_pppoe_configure($pppoe);
1230
	}
1231
}
1232

    
1233
function vpn_pppoe_configure(&$pppoecfg) {
1234
	global $config, $g;
1235

    
1236
	$syscfg = $config['system'];
1237

    
1238
	/* create directory if it does not exist */
1239
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1240
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1241

    
1242
	if ($g['booting']) {
1243
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1244
			return 0;
1245

    
1246
		echo gettext("Configuring PPPoE VPN service... ");
1247
	} else {
1248
		/* kill mpd */
1249
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1250

    
1251
		/* wait for process to die */
1252
		sleep(2);
1253

    
1254
	}
1255

    
1256
	switch ($pppoecfg['mode']) {
1257

    
1258
		case 'server' :
1259

    
1260
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1261

    
1262
			if ($pppoecfg['paporchap'] == "chap")
1263
				$paporchap = "set link enable chap";
1264
			else
1265
				$paporchap = "set link enable pap";
1266

    
1267
			/* write mpd.conf */
1268
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1269
			if (!$fd) {
1270
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
1271
				return 1;
1272
			}
1273
			$mpdconf = "\n\n";
1274
			$mpdconf .= "poes:\n";
1275

    
1276
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1277
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1278
			}
1279

    
1280
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1281

    
1282
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1283

    
1284
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['server']['enable'])) {
1285
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1286
				} else {
1287
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1288
				}
1289

    
1290
				$mpdconf .=<<<EOD
1291

    
1292
poes{$pppoecfg['pppoeid']}{$i}:
1293
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1294
	{$isssue_ip_type}
1295
	load pppoe_standard
1296

    
1297
EOD;
1298
			}
1299

    
1300
			$mpdconf .=<<<EOD
1301

    
1302
pppoe_standard:
1303
	set bundle no multilink
1304
	set bundle enable compression
1305
	set auth max-logins 1
1306
	set iface up-script /usr/local/sbin/vpn-linkup
1307
	set iface down-script /usr/local/sbin/vpn-linkdown
1308
	set iface idle 0
1309
	set iface disable on-demand
1310
	set iface disable proxy-arp
1311
	set iface enable tcpmssfix
1312
	set iface mtu 1500
1313
	set link no pap chap
1314
	{$paporchap}
1315
	set link keep-alive 60 180
1316
	set ipcp yes vjcomp
1317
	set ipcp no vjcomp
1318
	set link max-redial -1
1319
	set link mtu 1492
1320
	set link mru 1492
1321
	set ccp yes mpp-e40
1322
	set ccp yes mpp-e128
1323
	set ccp yes mpp-stateless
1324
	set link latency 1
1325
	#set ipcp dns 10.10.1.3
1326
	#set bundle accept encryption
1327

    
1328
EOD;
1329

    
1330
			if (!empty($pppoecfg['dns1'])) {
1331
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1332
				if (!empty($pppoecfg['dns2']))
1333
					$mpdconf .= " " . $pppoecfg['dns2'];
1334
				$mpdconf .= "\n";
1335
			} elseif (isset ($config['dnsmasq']['enable'])) {
1336
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1337
				if ($syscfg['dnsserver'][0])
1338
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1339
				$mpdconf .= "\n";
1340
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1341
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1342
			}
1343

    
1344
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1345
				$radiusport = "";
1346
				$radiusacctport = "";
1347
				if (isset($pppoecfg['radius']['server']['port']))
1348
					$radiusport = $pppoecfg['radius']['server']['port'];
1349
				if (isset($pppoecfg['radius']['server']['acctport']))
1350
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1351
				$mpdconf .=<<<EOD
1352
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']} {$radiusport} {$radiusacctport}" 
1353
	set radius retries 3
1354
	set radius timeout 10
1355
	set auth enable radius-auth
1356

    
1357
EOD;
1358

    
1359
				if (isset ($pppoecfg['radius']['accounting'])) {
1360
					$mpdconf .=<<<EOD
1361
	set auth enable radius-acct
1362

    
1363
EOD;
1364
				}
1365
			}
1366

    
1367
			fwrite($fd, $mpdconf);
1368
			fclose($fd);
1369

    
1370
			/* write mpd.links */
1371
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.links", "w");
1372
			if (!$fd) {
1373
				printf(gettext("Error: cannot open mpd.links in vpn_pppoe_configure().") . "\n");
1374
				return 1;
1375
			}
1376

    
1377
			$mpdlinks = "";
1378

    
1379
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1380
				$mpdlinks .=<<<EOD
1381
			
1382
poes{$pppoecfg['pppoeid']}{$i}:
1383
	set phys type pppoe
1384
        set pppoe iface {$pppoe_interface}
1385
        set pppoe service "*"
1386
        set pppoe disable originate
1387
        set pppoe enable incoming
1388

    
1389
EOD;
1390
			}
1391

    
1392
			fwrite($fd, $mpdlinks);
1393
			fclose($fd);
1394

    
1395
			if ($pppoecfg['username']) {
1396
				/* write mpd.secret */
1397
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1398
				if (!$fd) {
1399
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1400
					return 1;
1401
				}
1402

    
1403
				$mpdsecret = "\n\n";
1404

    
1405
				if (!empty($pppoecfg['username'])) {
1406
					$item = explode(" ", $pppoecfg['username']);
1407
					foreach($item as $userdata) {
1408
						$data = explode(":", $userdata);
1409
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1410
					}
1411
				}
1412

    
1413
				fwrite($fd, $mpdsecret);
1414
				fclose($fd);
1415
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1416
			}
1417

    
1418
			/* Get support for netgraph(4) from the nic */
1419
			pfSense_ngctl_attach(".", $pppoe_interface);
1420
			/* fire up mpd */
1421
			mwexec("/usr/local/sbin/mpd4 -b -d {$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn -p {$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid -s poes poes");
1422

    
1423
			break;
1424
	}
1425

    
1426
	if ($g['booting'])
1427
		echo gettext("done") . "\n";
1428

    
1429
	return 0;
1430
}
1431

    
1432
function vpn_l2tp_configure() {
1433
	global $config, $g;
1434

    
1435
	$syscfg = $config['system'];
1436
	$l2tpcfg = $config['l2tp'];
1437

    
1438
	/* create directory if it does not exist */
1439
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1440
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1441

    
1442
	if ($g['booting']) {
1443
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1444
			return 0;
1445

    
1446
		echo gettext("Configuring l2tp VPN service... ");
1447
	} else {
1448
		/* kill mpd */
1449
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1450

    
1451
		/* wait for process to die */
1452
		sleep(8);
1453

    
1454
	}
1455

    
1456
	/* make sure l2tp-vpn directory exists */
1457
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1458
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1459

    
1460
	switch ($l2tpcfg['mode']) {
1461

    
1462
		case 'server' :
1463
			if ($l2tpcfg['paporchap'] == "chap")
1464
				$paporchap = "set link enable chap";
1465
			else
1466
				$paporchap = "set link enable pap";
1467

    
1468
			/* write mpd.conf */
1469
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1470
			if (!$fd) {
1471
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
1472
				return 1;
1473
			}
1474
			$mpdconf = "\n\n";
1475
			$mpdconf .=<<<EOD
1476
l2tps:
1477

    
1478
EOD;
1479

    
1480
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1481
				$mpdconf .= "	load l2tp{$i}\n";
1482
			}
1483

    
1484
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1485

    
1486
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1487

    
1488
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1489
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1490
				} else {
1491
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1492
				}
1493

    
1494
				$mpdconf .=<<<EOD
1495

    
1496
l2tp{$i}:
1497
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1498
	{$isssue_ip_type}
1499
	load l2tp_standard
1500

    
1501
EOD;
1502
			}
1503

    
1504
			$mpdconf .=<<<EOD
1505

    
1506
l2tp_standard:
1507
        set bundle disable multilink
1508
        set bundle enable compression
1509
        set bundle yes crypt-reqd
1510
        set ipcp yes vjcomp
1511
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1512
        set ccp yes mppc
1513
        set iface disable on-demand
1514
        set iface enable proxy-arp
1515
	set iface up-script /usr/local/sbin/vpn-linkup
1516
	set iface down-script /usr/local/sbin/vpn-linkdown
1517
        set link yes acfcomp protocomp
1518
        set link no pap chap
1519
        set link enable chap
1520
        set link keep-alive 10 180
1521

    
1522
EOD;
1523

    
1524
			if (is_ipaddr($l2tpcfg['wins'])) {
1525
				$mpdconf .= "	set ipcp nbns {$l2tpcfg['wins']}\n";
1526
			}
1527
			if (is_ipaddr($l2tpcfg['dns1'])) {
1528
				$mpdconf .= "	set ipcp dns " . $l2tpcfg['dns1'];
1529
				if (is_ipaddr($l2tpcfg['dns2']))
1530
					$mpdconf .= " " . $l2tpcfg['dns2'];
1531
				$mpdconf .= "\n";
1532
			} elseif (isset ($config['dnsmasq']['enable'])) {
1533
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1534
				if ($syscfg['dnsserver'][0])
1535
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1536
				$mpdconf .= "\n";
1537
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1538
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1539
			}
1540

    
1541
			if (isset ($l2tpcfg['radius']['enable'])) {
1542
				$mpdconf .=<<<EOD
1543
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1544
	set radius retries 3
1545
	set radius timeout 10
1546
	set auth enable radius-auth
1547

    
1548
EOD;
1549

    
1550
				if (isset ($l2tpcfg['radius']['accounting'])) {
1551
					$mpdconf .=<<<EOD
1552
	set auth enable radius-acct
1553

    
1554
EOD;
1555
				}
1556
			}
1557

    
1558
			fwrite($fd, $mpdconf);
1559
			fclose($fd);
1560

    
1561
			/* write mpd.links */
1562
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.links", "w");
1563
			if (!$fd) {
1564
				printf(gettext("Error: cannot open mpd.links in vpn_l2tp_configure().") . "\n");
1565
				return 1;
1566
			}
1567

    
1568
			$mpdlinks = "";
1569

    
1570
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1571
				$mpdlinks .=<<<EOD
1572

    
1573
l2tp{$i}:
1574
	set link type l2tp
1575
        set l2tp enable incoming
1576
        set l2tp disable originate
1577

    
1578
EOD;
1579
			if (!empty($l2tpcfg['secret']))
1580
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1581
			}
1582

    
1583
			fwrite($fd, $mpdlinks);
1584
			fclose($fd);
1585

    
1586
			/* write mpd.secret */
1587
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1588
			if (!$fd) {
1589
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
1590
				return 1;
1591
			}
1592

    
1593
			$mpdsecret = "\n\n";
1594

    
1595
			if (is_array($l2tpcfg['user'])) {
1596
				foreach ($l2tpcfg['user'] as $user)
1597
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1598
			}
1599

    
1600
			fwrite($fd, $mpdsecret);
1601
			fclose($fd);
1602
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1603

    
1604
			vpn_netgraph_support();
1605

    
1606
			/* fire up mpd */
1607
			mwexec("/usr/local/sbin/mpd4 -b -d {$g['varetc_path']}/l2tp-vpn -p {$g['varrun_path']}/l2tp-vpn.pid -s l2tps l2tps");
1608

    
1609
			break;
1610

    
1611
		case 'redir' :
1612
			break;
1613
	}
1614

    
1615
	if ($g['booting'])
1616
		echo "done\n";
1617

    
1618
	return 0;
1619
}
1620

    
1621
/* Walk the tunnels for hostname endpoints. If the hostnames 
1622
 * resolve to a different IP now compared to the DNS cache
1623
 * we reload the policies if the endpoint has changed */
1624
function vpn_ipsec_refresh_policies() {
1625
	global $config;
1626
	global $g;
1627

    
1628
	$ipseccfg = $config['ipsec'];
1629
	$a_phase1 = $config['ipsec']['phase1'];
1630
	$a_phase2 = $config['ipsec']['phase2'];
1631

    
1632
	if (isset($ipseccfg['disable'])) {
1633
		return true;
1634
	}
1635

    
1636
	/* Walk the Ipsec tunnel array */
1637
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1638
		return;
1639
	}
1640

    
1641
	foreach ($a_phase1 as $phase1) {
1642
		if (isset($phase1['disabled'])) {
1643
			continue;
1644
		}
1645
		if (is_ipaddr($phase1['remote-gateway'])) {
1646
			continue;
1647
		}
1648
		if (!is_ipaddr($phase1['remote-gateway'])) {
1649
			$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1650
			$dnscache = trim($dnscache);
1651
			/* we should have the old IP addresses in the dnscache now */
1652
			if($dnscache <> "") {
1653
				$oldphase1 = $phase1;
1654
				$oldphase1['remote-gateway'] = trim($dnscache);
1655
				/* now we need to find all tunnels for this host */
1656
				if (!is_array($a_phase2) || (!count($a_phase2))) {
1657
					continue;
1658
				}
1659
				foreach ($a_phase2 as $phase2) {
1660
					if($phase2['ikeid'] == $phase1['ikeid']) {
1661
						reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1662
					}
1663
				}
1664
			}
1665
		}
1666
	}
1667

    
1668
	/* process all generated spd.conf files from tmp which are left behind
1669
	 * behind by either changes of dynamic tunnels or manual edits
1670
	 * scandir() is only available in PHP5 */
1671
	$tmpfiles = array();
1672
	$dh  = opendir($g['tmp_path']);
1673
	while (false !== ($filename = readdir($dh))) {
1674
		if(preg_match("/^spd.conf.reload./", $filename)) {
1675
			$tmpfiles[] = $filename;
1676
		}
1677
	}
1678
	sort($tmpfiles);
1679
	foreach($tmpfiles as $tmpfile) {
1680
		$ret = mwexec("/usr/local/sbin/setkey -f {$g['tmp_path']}/{$tmpfile} 2>&1", false);
1681
		if($ret == 0) {
1682
			unlink_if_exists("{$g['tmp_path']}/{$tmpfile}");
1683
		} else {
1684
			rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1685
		}
1686
	}
1687
}
1688

    
1689
/* reloads the tunnel configuration for a tunnel item
1690
 * Will remove and add SPD polices */
1691
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1692
	global $config;
1693
	global $g;
1694

    
1695
	/* if we are not passed a old tunnel array we create one */
1696
	if(empty($old_phase1)) {
1697
		$old_phase1 = $phase1;
1698
	}
1699
	if(empty($old_phase2)) {
1700
		$old_phase2 = $phase2;
1701
	}
1702

    
1703
	$sad_arr = ipsec_dump_sad();
1704

    
1705
	$ep = ipsec_get_phase1_src($phase1);
1706
	$phase2['localid']['mode'] = $phase2['mode'];
1707
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1708
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1709

    
1710
	/* make sure we pass the oldtunnel array with a IP for the remote gw */
1711
	$old_gw = trim($old_phase1['remote-gateway']);
1712

    
1713
	$old_ep = ipsec_get_phase1_src($old_phase1);
1714
	$old_phase2['localid']['mode'] = $old_phase2['mode'];
1715
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1716
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1717

    
1718
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1719
	 * try to resolve it now and add it to the list for filterdns */
1720
	$rgip = "";
1721
	if (!is_ipaddr($phase1['remote-gateway'])) {
1722
		if(! $g['booting']) {
1723
			$rgip = resolve_retry($phase1['remote-gateway']);
1724
			add_hostname_to_watch($phase1['remote-gateway']);
1725
		} else {
1726
			add_hostname_to_watch($phase1['remote-gateway']);
1727
		}
1728
		if (!is_ipaddr($rgip)) {
1729
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1730
			return false;
1731
		}
1732
	} else {
1733
		$rgip = $phase1['remote-gateway'];
1734
	}
1735
	if (!$ep) {
1736
		log_error(sprintf(gettext("Could not determine VPN endpoint for '%s'"), $phase1['descr']));
1737
		return false;
1738
	}
1739

    
1740
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1741
		log_error(sprintf(gettext("IPSEC: ERROR: One of the endpoints is not a IP address. Old EP '%1\$s' new EP '%2\$s'"), $old_ep, $ep));
1742
	}
1743
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1744
		log_error(sprintf(gettext("IPSEC: ERROR: One of the remote endpoints is not a IP address. Old RG '%1\$s' new RG '%2\$s'"), $old_gw, $rgip));
1745
	}
1746

    
1747
	$spdconf = "";
1748
	/* Delete old SPD policies if there are changes between the old and new */
1749
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1750
		if($old_phase2['mode'] == "tunnel6")
1751
			$family = "-6";
1752
		else
1753
			$family = "-4";
1754

    
1755
		$spdconf .= "spddelete {$family} {$old_local_subnet} " .
1756
			"{$old_remote_subnet} any -P out ipsec " .
1757
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1758
			"{$old_gw}/unique;\n";
1759
		$spdconf .= "spddelete {$family} {$old_remote_subnet} " .
1760
			"{$old_local_subnet} any -P in ipsec " .
1761
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1762
			"{$old_ep}/unique;\n";
1763

    
1764
		/* zap any existing SA entries */
1765
		foreach($sad_arr as $sad) {
1766
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1767
				$spdconf .= "delete {$family} {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1768
			}
1769
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1770
				$spdconf .= "delete {$family} {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1771
			}
1772
		}
1773
	}
1774

    
1775
	if($phase2['mode'] == "tunnel6")
1776
		$family = "-6";
1777
	else
1778
		$family = "-4";
1779

    
1780
	/* Create new SPD entries for the new configuration */
1781
	/* zap any existing SA entries beforehand */
1782
	foreach($sad_arr as $sad) {
1783
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1784
			$spdconf .= "delete {$family} {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1785
		}
1786
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1787
			$spdconf .= "delete {$family} {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1788
		}
1789
	}
1790
	/* add new SPD policies to replace them */
1791
	$spdconf .= "spdadd {$family} {$local_subnet} " .
1792
		"{$remote_subnet} any -P out ipsec " .
1793
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1794
		"{$rgip}/unique;\n";
1795
	$spdconf .= "spdadd {$family} {$remote_subnet} " .
1796
		"{$local_subnet} any -P in ipsec " .
1797
		"{$phase2['protocol']}/tunnel/{$rgip}-" .
1798
		"{$ep}/unique;\n";
1799

    
1800
	log_error(sprintf(gettext("Reloading IPsec tunnel '%1\$s'. Previous IP '%2\$s', current IP '%3\$s'. Reloading policy"), $phase1['descr'], $old_gw, $rgip));
1801

    
1802
	$now = time();
1803
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1804
	/* generate temporary spd.conf */
1805
	file_put_contents($spdfile, $spdconf);
1806
	return true;
1807
}
1808

    
1809
function vpn_ipsec_configure_preferoldsa() {
1810
	global $config;
1811
	if(isset($config['ipsec']['preferoldsa']))
1812
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1813
	else
1814
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1815
}
1816

    
1817
?>
(52-52/61)