Project

General

Profile

Download (53.7 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	/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
	if ($g['platform'] == 'jail')
86
		return;
87

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

    
92
	vpn_ipsec_configure_preferoldsa();
93

    
94
	$syscfg = $config['system'];
95
	$ipseccfg = $config['ipsec'];
96
	$a_phase1 = $config['ipsec']['phase1'];
97
	$a_phase2 = $config['ipsec']['phase2'];
98
	$a_client = $config['ipsec']['client'];
99

    
100
	if (!isset($ipseccfg['enable'])) {
101
		/* try to stop racoon*/
102
		killbypid("{$g['varrun_path']}/racoon.pid");
103
		/* Stop dynamic monitoring */
104
		killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
105

    
106
		/* kill racoon forcefully */
107
		if (is_process_running("racoon"))
108
			mwexec("/usr/bin/killall -9 racoon", true);
109

    
110
		/* wait for racoon process to die */
111
		sleep(2);
112

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

    
117
		/* disallow IPSEC, it is off */
118
		mwexec("/sbin/ifconfig enc0 down");
119
		exec("/sbin/sysctl net.inet.ip.ipsec_in_use=0");
120

    
121
		return true;
122
	} else {
123
		mwexec("/sbin/ifconfig enc0 up");
124
		mwexec("/sbin/sysctl net.inet.ip.ipsec_in_use=1");
125
		/* needed for racoonctl admin socket */
126
		if (!is_dir("/var/db/racoon"))
127
			mkdir("/var/db/racoon/");
128
		/* needed for config files */
129
		if (!is_dir("{$g['varetc_path']}/ipsec"))
130
			mkdir("{$g['varetc_path']}/ipsec");
131
		
132

    
133
		if ($g['booting'])
134
			echo gettext("Configuring IPsec VPN... ");
135

    
136
		/* fastforwarding is not compatible with ipsec tunnels */
137
		mwexec("/sbin/sysctl net.inet.ip.fastforwarding=0");
138

    
139
		/* resolve all local, peer addresses and setup pings */
140
		$ipmap = array();
141
		$rgmap = array();
142
		$filterdns_list = array();
143
		unset($iflist);
144
		if (is_array($a_phase1) && count($a_phase1)) {
145

    
146
			$ipsecpinghosts = "";
147
			/* step through each phase1 entry */
148
			$ipsecpinghosts = "";
149
			foreach ($a_phase1 as $ph1ent) {
150
				if (isset($ph1ent['disabled']))
151
					continue;
152

    
153
				$ep = ipsec_get_phase1_src($ph1ent);
154
				if (!is_ipaddr($ep))
155
					continue;
156

    
157
				if(!in_array($ep,$ipmap))
158
					$ipmap[] = $ep;
159

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

    
163
				if (isset ($ph1ent['mobile']))
164
					continue;
165

    
166
				$rg = $ph1ent['remote-gateway'];
167

    
168
				if (!is_ipaddr($rg)) {
169
					$filterdns_list[] = "{$rg}";
170
					add_hostname_to_watch($rg);
171
					if(! $g['booting'])
172
						$rg = resolve_retry($rg);
173
					if (!is_ipaddr($rg))
174
						continue;
175
				}
176
				if(array_search($rg, $rgmap)) {
177
					log_error("The remote gateway {$rg} already exists on another phase 1 entry");
178
					continue;
179
				}
180
				$rgmap[$ph1ent['remote-gateway']] = $rg;
181

    
182
				if (is_array($a_phase2)) {
183
					/* step through each phase2 entry */
184
					foreach ($a_phase2 as $ph2ent) {
185
						$ikeid = $ph2ent['ikeid'];
186

    
187
						if (isset($ph2ent['disabled']))
188
							continue;
189

    
190
						if ($ikeid != $ph1ent['ikeid'])
191
							continue;
192

    
193
						$ph2ent['localid']['mode'] = $ph2ent['mode'];
194
						/* add an ipsec pinghosts entry */
195
						if ($ph2ent['pinghost']) {
196
							if (!is_array($iflist))
197
								$iflist = get_configured_interface_list();
198
							foreach ($iflist as $ifent => $ifname) {
199
								if(is_ipaddrv6($ph2ent['pinghost'])) {
200
									$interface_ip = get_interface_ipv6($ifent);
201
									if(!is_ipaddrv6($interface_ip))
202
										continue;
203
									$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
204
									if (ip_in_subnet($interface_ip, $local_subnet)) {
205
										$srcip = $interface_ip;
206
										break;
207
									}
208
								} else {
209
									$interface_ip = get_interface_ip($ifent);
210
									if(!is_ipaddrv4($interface_ip))
211
										continue;
212
									$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
213
									if ($local_subnet == "0.0.0.0/0" || ip_in_subnet($interface_ip, $local_subnet)) {
214
										$srcip = $interface_ip;
215
										break;
216
									}
217
								}
218
							}
219
							$dstip = $ph2ent['pinghost'];
220
							if(is_ipaddrv6($dstip)) {
221
								$family = "inet6";
222
							} else {
223
								$family = "inet";
224
							}
225
							if (is_ipaddr($srcip))
226
								$ipsecpinghosts[] = "{$srcip}|{$dstip}|3|||||{$family}|\n";
227
						}
228
					}
229
					@file_put_contents("{$g['vardb_path']}/ipsecpinghosts", $ipsecpinghosts);
230
				}
231
			}
232
		}
233

    
234
		/* generate CA certificates files */
235
		if (is_array($config['ca']) && count($config['ca'])) {
236
			foreach ($config['ca'] as $ca) {
237
				if (!isset($ca['crt'])) {
238
					log_error(sprintf(gettext("Error: Invalid certificate info for %s"), $ca['descr']));
239
					continue;
240
				}
241
				$cert = base64_decode($ca['crt']);
242
				$x509cert = openssl_x509_parse(openssl_x509_read($cert));
243
				if (!is_array($x509cert) || !isset($x509cert['hash'])) {
244
					log_error(sprintf(gettext("Error: Invalid certificate hash info for %s"), $ca['descr']));
245
					continue;
246
				}
247
				$fname = "{$g['varetc_path']}/ipsec/{$x509cert['hash']}.0";
248
				if (!@file_put_contents($fname, $cert)) {
249
					log_error(sprintf(gettext("Error: Cannot write IPsec CA file for %s"), $ca['descr']));
250
					continue;
251
				}
252
			}
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
		@file_put_contents("{$g['varetc_path']}/ipsec/psk.txt", $pskconf);
305
		chmod("{$g['varetc_path']}/ipsec/psk.txt", 0600);
306
			
307
		/* begin racoon.conf */
308
		$racoonconf = "";
309
		if ((is_array($a_phase1) && count($a_phase1)) || (is_array($a_phase2) && count($a_phase2))) {
310

    
311
			$racoonconf .= "# This file is automatically generated. Do not edit\n";			
312
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
313
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
314

    
315
			/* begin listen section */
316
			if (count($ipmap)) {
317
				$racoonconf .= "\nlisten\n";
318
				$racoonconf .= "{\n";
319
				$racoonconf .= "	adminsock \"/var/db/racoon/racoon.sock\" \"root\" \"wheel\" 0660;\n";
320
				foreach ($ipmap as $addr) {
321
					$racoonconf .= "\tisakmp {$addr} [500];\n";
322
					$racoonconf .= "\tisakmp_natt {$addr} [4500];\n";
323
				}
324
				$racoonconf .= "}\n\n";
325
			}
326

    
327
			/* begin mode_cfg section */
328
			if (is_array($a_client) && isset($a_client['enable'])) {
329

    
330
				$racoonconf .= "\nmode_cfg\n";
331
				$racoonconf .= "{\n";
332

    
333
				if (!empty($a_client['user_source']))
334
					$racoonconf .= "\tauth_source external;\n";
335
				if (!empty($a_client['group_source']) && $a_client['group_source'] != "none")
336
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
337

    
338
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
339
					$pool_address = $a_client['pool_address'];
340
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
341

    
342
					$pool_address = long2ip32(ip2long($pool_address)+1);
343
					$pool_size = (~ip2long($pool_netmask) & 0xFFFFFFFF) - 2;
344

    
345
					$racoonconf .= "\tpool_size {$pool_size};\n";
346
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
347
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
348
				}
349

    
350
				if (isset($a_client['net_list'])) {
351

    
352
					$net_list = '';
353

    
354
					foreach ($a_phase2 as $ph2ent) {
355

    
356
						if (isset($ph2ent['disabled']))
357
							continue;
358

    
359
						if (!isset($ph2ent['mobile']))
360
							continue;
361

    
362
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
363

    
364
						if ($net_list)
365
							$net_list .= ", ";
366
						$net_list .= $localid;
367
					}
368

    
369
					if ($net_list)
370
						$racoonconf .= "\tsplit_network include {$net_list};\n";
371
				}
372

    
373
				if ($a_client['dns_server1'])
374
					$racoonconf .= "\tdns4 {$a_client['dns_server1']};\n";
375
				if ($a_client['dns_server2'])
376
					$racoonconf .= "\tdns4 {$a_client['dns_server2']};\n";
377
				if ($a_client['dns_server3'])
378
					$racoonconf .= "\tdns4 {$a_client['dns_server3']};\n";
379
				if ($a_client['dns_server4'])
380
					$racoonconf .= "\tdns4 {$a_client['dns_server4']};\n";
381

    
382
				if ($a_client['wins_server1'])
383
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
384
				if ($a_client['wins_server2'])
385
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
386

    
387
				if ($a_client['dns_domain']) {
388
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
389
					if (empty($a_client['dns_split']))
390
						$racoonconf .= "\tsplit_dns \"{$a_client['dns_domain']}\";\n";
391
				}
392

    
393
				if ($a_client['dns_split']) {
394
					$domain_array = preg_split("/[ ,]+/",$a_client['dns_split']);
395
					$domain_string = implode('", "', $domain_array);
396
					$racoonconf .= "\tsplit_dns \"{$domain_string}\";\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
					@file_put_contents("{$g['varetc_path']}/ipsec/racoon.motd", $a_client['login_banner']);
404
					$racoonconf .= "\tbanner \"{$fn}\";\n";
405
				}
406

    
407
				if (isset($a_client['save_passwd']))
408
					$racoonconf .= "\tsave_passwd on;\n";
409

    
410
				$racoonconf .= "}\n\n";
411
			}
412
			/* end mode_cfg section */
413
			
414
			if ($a_client['user_source'] != "none") {
415
				$authcfgs = explode(",", $a_client['user_source']);
416
				$sed = "\$authmodes=array(";
417
				$firstsed = 0;
418
				foreach ($authcfgs as $authcfg) {
419
					if ($firstsed > 0)
420
						$sed .= ",";
421
					$firstsed = 1;
422
					$sed .= "\"{$authcfg}\"";
423
				}
424
				$sed .= ");\\\n";
425
				if ($a_client['strictusercn'])
426
					$sed .= "\$strictusercn = true;";
427
				mwexec("/bin/cat /etc/inc/ipsec.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/ipsec/ipsec.php");
428
				mwexec("/bin/chmod a+x {$g['varetc_path']}/ipsec/ipsec.php");
429
				$racoonconf .= "extcfg { script \"{$g['varetc_path']}/ipsec/ipsec.php\" }\n";
430
			}
431

    
432
			/* begin remote sections */
433
			if (is_array($a_phase1) && count($a_phase1)) {
434
				/* begin remote */
435
				foreach ($a_phase1 as $ph1ent) {
436

    
437
					if (isset($ph1ent['disabled']))
438
						continue;
439

    
440
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
441
						continue;
442

    
443
					$ikeid = $ph1ent['ikeid'];
444

    
445
					$ep = ipsec_get_phase1_src($ph1ent);
446
					if (!$ep)
447
						continue;
448

    
449
					if (!isset($ph1ent['mobile'])) {
450
						$rgip = $rgmap[$ph1ent['remote-gateway']];
451
						if (!$rgip)
452
							continue;
453
					}
454

    
455
					$myid_type = $ph1ent['myid_type'];
456

    
457
					switch ($myid_type) {
458

    
459
						case "myaddress":
460
							$myid_type = "address";
461
							$myid_data = $ep;
462
							break;
463

    
464
						case "dyn_dns":
465
							$myid_type = "address";
466
							$myid_data = resolve_retry($ph1ent['myid_data']);
467
							break;
468

    
469
						case "address";
470
							$myid_data = $ph1ent['myid_data'];
471
							break;
472

    
473
						case "fqdn";
474
						case "keyid tag";
475
						case "user_fqdn";
476
						case "asn1dn";
477
							$myid_data = $ph1ent['myid_data'];
478
							if( $myid_data )
479
								$myid_data = "\"".$myid_data."\"";
480
							break;
481
					}
482

    
483
					$peerid_type = $ph1ent['peerid_type'];
484

    
485
					switch ($peerid_type) {
486
						case "peeraddress":
487
							$peerid_type = "address";
488
							$peerid_data = $rgip;
489
							break;
490

    
491
						case "address";
492
							$peerid_data = $ph1ent['peerid_data'];
493
							break;
494

    
495
						case "fqdn";
496
						case "keyid tag";
497
						case "user_fqdn";
498
						case "asn1dn";
499
							$peerid_data = $ph1ent['peerid_data'];
500
							if( $peerid_data )
501
								$peerid_data = "\"".$peerid_data."\"";
502
							break;
503
					}
504

    
505
					$natt = "off";
506
					if (isset($ph1ent['nat_traversal']))
507
						$natt = $ph1ent['nat_traversal'];
508

    
509
					$init = "on";
510
					$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "off";
511
					$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "claim";
512
					$passive = "";
513
					if (isset($ph1ent['mobile'])) {
514
						$rgip = "anonymous";
515
						$passive = "passive on;";
516
						$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "obey";
517
						/* Mimic 1.2.3's behavior for pure-psk mobile tunnels */
518
						if ($ph1ent['authentication_method'] == "pre_shared_key") {
519
							$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "on";
520
						} else {
521
							$init = "off";
522
							$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "unique";
523
						}
524
					}
525

    
526
					$dpdline1 = '';
527
					$dpdline2 = '';
528
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
529
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
530
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
531
					}
532

    
533
					if (isset ($ph1ent['authentication_method']))
534
						$authmethod = $ph1ent['authentication_method'];
535
					else
536
						$authmethod = 'pre_shared_key';
537

    
538
					$certline = '';
539

    
540
					if (strstr($authmethod,'rsa')) {
541

    
542
						$cert = lookup_cert($ph1ent['certref']);
543

    
544
						if (!$cert)
545
						{
546
							log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
547
							continue;
548
						}
549

    
550
						$certfile = "cert-".$ikeid.".crt";
551
						$certpath = $g['varetc_path']."/".$certfile;
552

    
553
						if (!file_put_contents($certpath, base64_decode($cert['crt'])))
554
						{
555
							log_error(sprintf(gettext("Error: Cannot write phase1 certificate file for %s"), $ph1ent['name']));
556
							continue;
557
						}
558

    
559
						chmod($certpath, 0600);
560

    
561
						$keyfile = "cert-".$ikeid.".key";
562
						$keypath = $g['varetc_path']."/".$keyfile;
563

    
564
						if (!file_put_contents($keypath, base64_decode($cert['prv'])))
565
						{
566
							log_error(sprintf(gettext("Error: Cannot write phase1 key file for %s"), $ph1ent['name']));
567
							continue;
568
						}
569

    
570
						chmod($keypath, 0600);
571

    
572
						$ca = lookup_ca($ph1ent['caref']);
573
						if ($ca) {
574
							$cafile = "ca-".$ikeid.".crt";
575
							$capath = $g['varetc_path']."/".$cafile;
576

    
577
							if (!file_put_contents($capath, base64_decode($ca['crt'])))
578
							{
579
								log_error(sprintf(gettext("Error: Cannot write phase1 CA certificate file for %s"), $ph1ent['name']));
580
								continue;
581
							}
582

    
583
							chmod($capath, 0600);
584
							$caline = "ca_type x509 \"".basename($capath)."\";";
585
						}
586

    
587
						$certline = "certificate_type x509 \"".basename($certpath)."\" \"".basename($keypath)."\";";
588

    
589
					}
590

    
591
					$ealgos = '';
592
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
593
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
594
					if ($ealg_kl)
595
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
596
					else
597
						$ealgos = $ealgos.$ealg_id;
598

    
599
					$lifeline = '';
600
					if ($ph1ent['lifetime'])
601
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
602

    
603
					/* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */
604
					if (!(($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))) {
605
						$peerid_spec = "peers_identifier {$peerid_type} {$peerid_data};";
606
					}
607

    
608
					/* add remote section to configuration */
609

    
610
					$racoonconf .=<<<EOD
611

    
612
remote {$rgip}
613
{
614
	ph1id {$ikeid};
615
	exchange_mode {$ph1ent['mode']};
616
	my_identifier {$myid_type} {$myid_data};
617
	{$peerid_spec}
618
	ike_frag on;
619
	generate_policy = {$genp};
620
	initial_contact = {$init};
621
	nat_traversal = {$natt};
622
	{$certline}
623
	{$caline}
624
	{$dpdline1}
625
	{$dpdline2}
626
	support_proxy on;
627
	proposal_check {$pcheck};
628
	{$passive}
629

    
630
	proposal
631
	{
632
		authentication_method {$authmethod};
633
		encryption_algorithm ${ealgos};
634
		hash_algorithm {$ph1ent['hash-algorithm']};
635
		dh_group {$ph1ent['dhgroup']};
636
		${lifeline}
637
	}
638
}
639

    
640
EOD;
641
				}
642
				/* end remote */
643
			}
644
			/* end remote sections */
645
		
646
			/* begin sainfo sections */
647
			if (is_array($a_phase2) && count($a_phase2)) {
648

    
649
				/* begin sainfo */
650
				foreach ($a_phase2 as $ph2ent) {
651

    
652
					$ikeid = $ph2ent['ikeid'];
653

    
654
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
655
						continue;
656

    
657
					if (isset($ph1ent['disabled']))
658
						continue;
659

    
660
					if (isset($ph2ent['disabled']))
661
						continue;
662

    
663
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
664
						continue;
665

    
666
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
667

    
668
						$localid_type = $ph2ent['localid']['type'];
669
						$ph2ent['localid']['mode'] = $ph2ent['mode'];
670
						$localid_data = ipsec_idinfo_to_cidr($ph2ent['localid']);
671
						/* Do not print localid in some cases, such as a pure-psk or psk/xauth single phase2 mobile tunnel */
672
						if (($localid_type == "none") ||
673
							(($ph1ent['authentication_method'] == "xauth_psk_server") ||
674
							($ph1ent['authentication_method'] == "pre_shared_key"))
675
							&& isset($ph1ent['mobile'])
676
							&& (ipsec_get_number_of_phase2($ikeid)==1))
677
							$localid_spec = " ";
678
						else {
679
							if ($localid_type != "address") {
680
								$localid_type = "subnet";
681
							}
682
							// Don't let an empty subnet into racoon.conf, it can cause parse errors. Ticket #2201.
683
							if (!is_ipaddr($localid_data) && !is_subnet($localid_data)) {
684
								log_error("Invalid IPsec Phase 2 \"{$ph2ent['descr']}\" - {$ph2ent['localid']['type']} has no subnet.");
685
								continue;
686
							}
687
							$localid_spec = "{$localid_type} {$localid_data} any";
688
							if (!empty($ph2ent['natlocalid'])) {
689
								$natlocalid_data =  ipsec_idinfo_to_cidr($ph2ent['natlocalid']);
690
								if ($ph2ent['natlocalid']['type'] != "address") {
691
									if (is_subnet($natlocalid_data))
692
										$localid_spec .= " nat subnet {$natlocalid_data} any";
693
								} else {
694
									if (is_ipaddr($natlocalid_data))
695
										$localid_spec .= " nat address {$natlocalid_data} any";
696
								}
697
							}
698
						}
699

    
700
						if (!isset($ph2ent['mobile'])) {
701
							$remoteid_type = $ph2ent['remoteid']['type'];
702
							if ($remoteid_type != "address")
703
								$remoteid_type = "subnet";
704

    
705
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
706
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
707
						} else
708
							$remoteid_spec = "anonymous";
709

    
710
					} else {
711
						$rgip = $rgmap[$ph1ent['remote-gateway']];
712

    
713
						if ((($ph1ent['authentication_method'] == "xauth_psk_server") ||
714
							($ph1ent['authentication_method'] == "pre_shared_key"))
715
							&& isset($ph1ent['mobile']))
716
							$localid_spec = " ";
717
						else {
718
							$localid_data = ipsec_get_phase1_src($ph1ent);
719
							if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
720
							$localid_spec = "address {$localid_data}";
721
						}
722
						if (!isset($ph2ent['mobile'])) {
723
							$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
724
							if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
725
							$remoteid_spec = "address {$remoteid_data}";
726
						} else
727
							$remoteid_spec = "anonymous";
728
					}
729

    
730
					if($ph2ent['protocol'] == 'esp') {
731

    
732
						$ealgos = '';
733

    
734
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
735

    
736
							$ealg_id = $ealg['name'];
737
							$ealg_kl = $ealg['keylen'];
738

    
739
							if ($ealg_kl) {
740
								if( $ealg_kl == "auto" ) {
741
									/*   This seems to be required on my system and was not reproducable
742
									 *   on other systems.   For some reason $p2_ealgos is not defined
743
									 *   and needs to be read back in!?  -sullrich Aug 26, 2009 
744
									 */
745
									if(!$p2_ealgos)
746
										require("ipsec.inc");
747
									$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
748
									$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
749
									$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
750
									/* in some cases where include ordering is suspect these variables
751
									   are somehow 0 and we enter this loop forever and timeout after 900
752
									   seconds wrecking bootup */
753
									if($key_hi != 0 and $key_lo !=0 and $key_step !=0) {
754
										for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
755
//											Uncomment the next line if you want to test the comment 5 lines up.											
756
//											echo "$keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step \n";
757
											if ($ealgos)
758
												$ealgos = $ealgos.", ";
759
											$ealgos = $ealgos.$ealg_id." ".$keylen;
760
										}
761
									}
762
								} else {
763
									if ($ealgos)
764
										$ealgos = $ealgos.", ";
765
									$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
766
								}
767
							} else {
768
								if ($ealgos)
769
									$ealgos = $ealgos.", ";
770
								$ealgos = $ealgos.$ealg_id;
771
							}
772
						}
773

    
774
						$ealgosline = "encryption_algorithm {$ealgos};";
775

    
776
					} else {
777

    
778
						$ealgosline = "encryption_algorithm null_enc;";
779
					}
780

    
781
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
782
					$halgosline = "authentication_algorithm {$halgos};";
783

    
784
					$pfsline = '';
785
					if ($ph2ent['pfsgroup'])
786
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
787
					if (isset($a_client['pfs_group'])) {
788
						$pfsline = '';
789
						if ($a_client['pfs_group'])
790
							$pfsline = "pfs_group {$a_client['pfs_group']};";
791
					}
792

    
793
					$lifeline = '';
794
					if ($ph2ent['lifetime'])
795
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
796

    
797
					/* add sainfo section to configuration */
798
					
799
					$racoonconf .=<<<EOD
800
					
801
sainfo {$localid_spec} {$remoteid_spec}
802
{
803
	remoteid {$ikeid};
804
	{$ealgosline}
805
	{$halgosline}
806
	{$pfsline}
807
	{$lifeline}
808
	compression_algorithm deflate;
809
}
810

    
811
EOD;
812
				}
813
				/* end sainfo */
814
			}
815
			/* end sainfo sections */
816
		}
817
		@file_put_contents("{$g['varetc_path']}/ipsec/racoon.conf", $racoonconf);
818
		/* end racoon.conf */
819

    
820
		/* generate IPsec policies */
821
		/* generate spd.conf */
822
		$spdconf = "";
823
		$natfilterrules = false;
824
		if (is_array($a_phase2) && count($a_phase2)) {
825
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
826
			if ($config['interfaces']['lan']) {
827
				$lanip = get_interface_ip("lan");
828
				if (!empty($lanip) && is_ipaddrv4($lanip)) {
829
					$lansn = get_interface_subnet("lan");
830
					$lansa = gen_subnet($lanip, $lansn);
831
					$spdconf .= "spdadd -4 {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
832
					$spdconf .= "spdadd -4 {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
833
				}
834
				$lanipv6 = get_interface_ipv6("lan");
835
				if (!empty($lanipv6) && is_ipaddrv6($lanipv6)) {
836
					$lansnv6 = get_interface_subnetv6("lan");
837
					$lansav6 = gen_subnetv6($lanipv6, $lansnv6);
838
					$spdconf .= "spdadd -6 {$lanipv6}/128 {$lansav6}/{$lansnv6} any -P out none;\n";
839
					$spdconf .= "spdadd -6 {$lansav6}/{$lansnv6} {$lanipv6}/128 any -P in none;\n";
840
				}
841
			}
842

    
843
			foreach ($a_phase2 as $ph2ent) {
844

    
845
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
846
					continue;
847

    
848
				if (isset($ph1ent['mobile']))
849
					continue;
850

    
851
				if (isset($ph1ent['disabled']))
852
					continue;
853

    
854
				if (isset($ph2ent['disabled']))
855
					continue;
856

    
857
				$ep = ipsec_get_phase1_src($ph1ent);
858
				if (!$ep)
859
					continue;
860

    
861
				$rgip = $rgmap[$ph1ent['remote-gateway']];
862
				if(!is_ipaddr($rgip))
863
					continue;
864

    
865
				$ph2ent['localid']['mode'] = $ph2ent['mode'];
866
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
867
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
868

    
869
				if(($ph2ent['mode'] == "tunnel") or ($ph2ent['mode'] == 'tunnel6')) {
870
					// Error will be logged above, no need to log this twice. #2201
871
					if (!is_subnet($localid))
872
						continue;
873

    
874
					if($ph2ent['mode'] == "tunnel6")
875
						$family = "-6";
876
					else
877
						$family = "-4";
878

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

    
882
					if (!empty($ph2ent['natlocalid'])) {
883
						$natlocalid = ipsec_idinfo_to_cidr($ph2ent['natlocalid'],true);
884
						$spdconf .= "spdadd {$family} {$remoteid} {$natlocalid} any -P in ipsec " .
885
							"{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
886
						$natfilterrules = true;
887
					} else
888
						$spdconf .= "spdadd {$family} {$remoteid} {$localid} any -P in ipsec " .
889
							"{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
890

    
891
				} else {
892

    
893
					$localid_data = ipsec_get_phase1_src($ph1ent);
894
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
895

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

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

    
902
				}
903

    
904
				/* static route needed? */
905
				if (is_ipaddr($ph1ent['interface'])) {
906
					$vip = find_virtual_ip_alias($ph1ent['interface']);
907
					if (preg_match("/^carp|^[a-z0-9]+_vip/i", $vip['interface']))
908
						$parentinterface = link_carp_interface_to_parent($vip['interface']);
909
					else
910
						$parentinterface = $vip['interface'];
911
				} else if (preg_match("/^carp|^[a-z0-9]+_vip/i", $ph1ent['interface']))
912
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
913
				else
914
					$parentinterface = $ph1ent['interface'];
915

    
916
				if (is_ipaddr($rgip)) {
917
					/* add endpoint routes to correct gateway on interface */
918
					if (interface_has_gateway($parentinterface)) {
919
						$gatewayip = get_interface_gateway("$parentinterface");
920
						$interfaceip = get_interface_ip($parentinterface);
921
						$subnet_bits = get_interface_subnet($parentinterface);
922
						$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
923
						/* if the remote gateway is in the local subnet, then don't add a route */
924
						if (! ip_in_subnet($rgip, "{$subnet_ip}/{$subnet_bits}")) {
925
							if(is_ipaddr($gatewayip)) {
926
								/* FIXME: does adding route-to and reply-to on the in/outbound
927
								 * rules fix this? smos@ 13-01-2009 */
928
								// log_error("IPSEC interface is not WAN but {$parentinterface}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
929
								mwexec("/sbin/route change -host {$rgip} {$gatewayip}", true);
930
							}
931
						}
932
					}
933
				} 
934
			}
935
		}
936
		@file_put_contents("{$g['varetc_path']}/ipsec/spd.conf", $spdconf);
937

    
938
		/* mange racoon process */
939
		if (is_process_running("racoon")) {
940
			sleep("0.1");
941
			mwexec("/usr/local/sbin/racoonctl -s /var/db/racoon/racoon.sock reload-config", false);
942
			/* load SPD without flushing to be safe on config additions or changes. */
943
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/ipsec/spd.conf", false);
944
		} else {
945
			/* flush SA + SPD entries */
946
			mwexec("/usr/local/sbin/setkey -FP", false);
947
 			sleep("0.1");
948
			mwexec("/usr/local/sbin/setkey -F", false);
949
 			sleep("0.1");
950
 			/* start racoon */
951
			$ipsecdebug = isset($config['ipsec']['racoondebug']) ? "-d -v" : "";
952
			mwexec("/usr/local/sbin/racoon {$ipsecdebug} -f {$g['varetc_path']}/ipsec/racoon.conf", false);
953
 			sleep("0.1");
954
 			/* load SPD */
955
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/ipsec/spd.conf", false);
956

    
957
		}
958
		if ($natfilterrules == true)
959
			filter_configure();
960
		/* start filterdns, if necessary */
961
		if (count($filterdns_list) > 0) {
962
			$interval = 60;
963
			if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval']))
964
				$interval = $ipseccfg['dns-interval'];
965

    
966
			$hostnames = "";
967
			array_unique($filterdns_list);
968
			foreach ($filterdns_list as $hostname)
969
				$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n";
970
			file_put_contents("{$g['varetc_path']}/ipsec/filterdns-ipsec.hosts", $hostnames);
971

    
972
			killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
973
			sleep(1);
974
			mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/ipsec/filterdns-ipsec.hosts -d 1");
975
		}
976
	
977
		vpn_ipsec_failover_configure();
978

    
979
		if ($g['booting'])
980
			echo "done\n";
981
	}
982

    
983
	return 0;
984
}
985

    
986
/* 
987
 * Forcefully restart IPsec
988
 * This is required for when dynamic interfaces reload
989
 * For all other occasions the normal vpn_ipsec_configure()
990
 * will gracefully reload the settings without restarting
991
 */
992
function vpn_ipsec_force_reload() {
993
	global $config;
994
	global $g;
995

    
996
	$ipseccfg = $config['ipsec'];
997

    
998
	/* send a SIGKILL to be sure */
999
	killbypid("{$g['varrun_path']}/racoon.pid");
1000

    
1001
	/* wait for process to die */
1002
	sleep(4);
1003

    
1004
	/* kill racoon forcefully */
1005
	if (is_process_running("racoon"))
1006
		mwexec("/usr/bin/killall -9 racoon", true);
1007

    
1008
	/* wait for flushing to finish */
1009
	sleep(1);
1010

    
1011
	/* if ipsec is enabled, start up again */
1012
	if (isset($ipseccfg['enable'])) {
1013
		log_error(gettext("Forcefully reloading IPsec racoon daemon"));
1014
		vpn_ipsec_configure();
1015
	}
1016
}
1017

    
1018
/* master setup for vpn (mpd) */
1019
function vpn_setup() {
1020
	global $g;
1021

    
1022
	if ($g['platform'] == 'jail')
1023
		return;
1024

    
1025
	/* start pptpd */
1026
	vpn_pptpd_configure();
1027

    
1028
	/* start pppoe server */
1029
	vpn_pppoes_configure();
1030

    
1031
	/* setup l2tp */
1032
	vpn_l2tp_configure();
1033
}
1034

    
1035
function vpn_netgraph_support() {
1036
	$iflist = get_configured_interface_list();
1037
	foreach ($iflist as $iface) {
1038
		$realif = get_real_interface($iface);
1039
		/* Get support for netgraph(4) from the nic */
1040
		$ifinfo = pfSense_get_interface_addresses($realif);
1041
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge")))
1042
                	pfSense_ngctl_attach(".", $realif);
1043
	}
1044
}
1045

    
1046
function vpn_pptpd_configure() {
1047
	global $config, $g;
1048

    
1049
	$syscfg = $config['system'];
1050
	$pptpdcfg = $config['pptpd'];
1051

    
1052
	if ($g['booting']) {
1053
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
1054
			return 0;
1055

    
1056
		echo gettext("Configuring PPTP VPN service... ");
1057
	} else {
1058
		/* kill mpd */
1059
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1060

    
1061
		/* wait for process to die */
1062
		sleep(3);
1063

    
1064
		if (is_process_running("mpd -b")) {
1065
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1066
			log_error(gettext("Could not kill mpd within 3 seconds.   Trying again."));
1067
		}
1068

    
1069
		/* remove mpd.conf, if it exists */
1070
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
1071
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
1072
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
1073
	}
1074

    
1075
	if (empty($pptpdcfg['n_pptp_units'])) {
1076
		log_error("Something wrong in the PPTPd configuration. Preventing starting the daemon because issues would arise.");
1077
		return; 
1078
	}
1079

    
1080
	/* make sure pptp-vpn directory exists */
1081
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
1082
		mkdir("{$g['varetc_path']}/pptp-vpn");
1083

    
1084
	switch ($pptpdcfg['mode']) {
1085
		case 'server' :
1086
			/* write mpd.conf */
1087
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
1088
			if (!$fd) {
1089
				printf(gettext("Error: cannot open mpd.conf in vpn_pptpd_configure().") . "\n");
1090
				return 1;
1091
			}
1092

    
1093
			$mpdconf = <<<EOD
1094
pptps:
1095

    
1096
EOD;
1097

    
1098
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1099
				$mpdconf .= "	load pt{$i}\n";
1100
			}
1101

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

    
1104
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1105

    
1106
				$mpdconf .= <<<EOD
1107

    
1108
pt{$i}:
1109
	new -i pptpd{$i} pt{$i} pt{$i}
1110
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1111
	load pts
1112

    
1113
EOD;
1114
			}
1115

    
1116
			$mpdconf .=<<<EOD
1117

    
1118
pts:
1119
	set iface disable on-demand
1120
	set iface enable proxy-arp
1121
	set iface enable tcpmssfix
1122
	set iface idle 1800
1123
	set iface up-script /usr/local/sbin/vpn-linkup
1124
	set iface down-script /usr/local/sbin/vpn-linkdown
1125
	set bundle enable multilink
1126
	set bundle enable crypt-reqd
1127
	set link yes acfcomp protocomp
1128
	set link no pap chap
1129
	set link enable chap-msv2
1130
	set link mtu 1460
1131
	set link keep-alive 10 60
1132
	set ipcp yes vjcomp
1133
	set bundle enable compression
1134
	set ccp yes mppc
1135
	set ccp yes mpp-e128
1136
	set ccp yes mpp-stateless
1137

    
1138
EOD;
1139

    
1140
			if (!isset ($pptpdcfg['req128'])) {
1141
				$mpdconf .=<<<EOD
1142
	set ccp yes mpp-e40
1143
	set ccp yes mpp-e56
1144

    
1145
EOD;
1146
			}
1147

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

    
1151
			if (!empty($pptpdcfg['dns1'])) {
1152
				$mpdconf .= "	set ipcp dns " . $pptpdcfg['dns1'];
1153
				if (!empty($pptpdcfg['dns2']))
1154
					$mpdconf .= " " . $pptpdcfg['dns2'];
1155
				$mpdconf .= "\n";
1156
			} elseif (isset ($config['dnsmasq']['enable'])) {
1157
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1158
				if ($syscfg['dnsserver'][0])
1159
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1160
				$mpdconf .= "\n";
1161
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1162
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1163
			}
1164

    
1165
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1166
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1167
				$acctport = $authport + 1;
1168
				$mpdconf .=<<<EOD
1169
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1170

    
1171
EOD;
1172
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1173
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1174
				$acctport = $authport + 1;
1175
				$mpdconf .=<<<EOD
1176
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret2']}" {$authport} {$acctport}
1177

    
1178
EOD;
1179
			}
1180
			$mpdconf .=<<<EOD
1181
	set radius retries 3
1182
	set radius timeout 10
1183
	set auth enable radius-auth
1184

    
1185
EOD;
1186

    
1187
				if (isset ($pptpdcfg['radius']['accounting'])) {
1188
					$mpdconf .=<<<EOD
1189
	set auth enable radius-acct
1190
	set radius acct-update 300
1191

    
1192
EOD;
1193
				}
1194
			}
1195

    
1196
			fwrite($fd, $mpdconf);
1197
			fclose($fd);
1198

    
1199
			/* write mpd.links */
1200
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.links", "w");
1201
			if (!$fd) {
1202
				printf(gettext("Error: cannot open mpd.links in vpn_pptpd_configure().") . "\n");
1203
				return 1;
1204
			}
1205

    
1206
			$mpdlinks = "";
1207

    
1208
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1209
				$mpdlinks .=<<<EOD
1210

    
1211
pt{$i}:
1212
	set link type pptp
1213
	set pptp enable incoming
1214
	set pptp disable originate
1215
	set pptp disable windowing
1216

    
1217
EOD;
1218
			}
1219

    
1220
			fwrite($fd, $mpdlinks);
1221
			fclose($fd);
1222

    
1223
			/* write mpd.secret */
1224
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1225
			if (!$fd) {
1226
				printf(gettext("Error: cannot open mpd.secret in vpn_pptpd_configure().") . "\n");
1227
				return 1;
1228
			}
1229

    
1230
			$mpdsecret = "";
1231

    
1232
			if (is_array($pptpdcfg['user'])) {
1233
				foreach ($pptpdcfg['user'] as $user) {
1234
					$pass = str_replace('\\', '\\\\', $user['password']);
1235
					$pass = str_replace('"', '\"', $pass);
1236
					$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
1237
				}
1238
			}
1239

    
1240
			fwrite($fd, $mpdsecret);
1241
			fclose($fd);
1242
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1243

    
1244
			vpn_netgraph_support();
1245

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

    
1249
			break;
1250

    
1251
		case 'redir' :
1252
			break;
1253
	}
1254

    
1255
	if ($g['booting'])
1256
		echo "done\n";
1257

    
1258
	return 0;
1259
}
1260

    
1261
function vpn_pppoes_configure() {
1262
	global $config;
1263

    
1264
	if (is_array($config['pppoes']['pppoe'])) {
1265
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1266
			vpn_pppoe_configure($pppoe);
1267
	}
1268
}
1269

    
1270
function vpn_pppoe_configure(&$pppoecfg) {
1271
	global $config, $g;
1272

    
1273
	$syscfg = $config['system'];
1274

    
1275
	/* create directory if it does not exist */
1276
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1277
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1278

    
1279
	if ($g['booting']) {
1280
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1281
			return 0;
1282

    
1283
		echo gettext("Configuring PPPoE VPN service... ");
1284
	} else {
1285
		/* kill mpd */
1286
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1287

    
1288
		/* wait for process to die */
1289
		sleep(2);
1290

    
1291
	}
1292

    
1293
	switch ($pppoecfg['mode']) {
1294

    
1295
		case 'server' :
1296

    
1297
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1298

    
1299
			if ($pppoecfg['paporchap'] == "chap")
1300
				$paporchap = "set link enable chap";
1301
			else
1302
				$paporchap = "set link enable pap";
1303

    
1304
			/* write mpd.conf */
1305
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1306
			if (!$fd) {
1307
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
1308
				return 1;
1309
			}
1310
			$mpdconf = "\n\n";
1311
			$mpdconf .= "poes:\n";
1312

    
1313
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1314
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1315
			}
1316

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

    
1319
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1320

    
1321
				if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
1322
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1323
				} else {
1324
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1325
				}
1326

    
1327
				$mpdconf .=<<<EOD
1328

    
1329
poes{$pppoecfg['pppoeid']}{$i}:
1330
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1331
	{$isssue_ip_type}
1332
	load pppoe_standard
1333

    
1334
EOD;
1335
			}
1336

    
1337
			$mpdconf .=<<<EOD
1338

    
1339
pppoe_standard:
1340
	set bundle no multilink
1341
	set bundle enable compression
1342
	set auth max-logins 1
1343
	set iface up-script /usr/local/sbin/vpn-linkup
1344
	set iface down-script /usr/local/sbin/vpn-linkdown
1345
	set iface idle 0
1346
	set iface disable on-demand
1347
	set iface disable proxy-arp
1348
	set iface enable tcpmssfix
1349
	set iface mtu 1500
1350
	set link no pap chap
1351
	{$paporchap}
1352
	set link keep-alive 60 180
1353
	set ipcp yes vjcomp
1354
	set ipcp no vjcomp
1355
	set link max-redial -1
1356
	set link mtu 1492
1357
	set link mru 1492
1358
	set ccp yes mpp-e40
1359
	set ccp yes mpp-e128
1360
	set ccp yes mpp-stateless
1361
	set link latency 1
1362
	#set ipcp dns 10.10.1.3
1363
	#set bundle accept encryption
1364

    
1365
EOD;
1366

    
1367
			if (!empty($pppoecfg['dns1'])) {
1368
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1369
				if (!empty($pppoecfg['dns2']))
1370
					$mpdconf .= " " . $pppoecfg['dns2'];
1371
				$mpdconf .= "\n";
1372
			} elseif (isset ($config['dnsmasq']['enable'])) {
1373
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1374
				if ($syscfg['dnsserver'][0])
1375
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1376
				$mpdconf .= "\n";
1377
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1378
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1379
			}
1380

    
1381
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1382
				$radiusport = "";
1383
				$radiusacctport = "";
1384
				if (isset($pppoecfg['radius']['server']['port']))
1385
					$radiusport = $pppoecfg['radius']['server']['port'];
1386
				if (isset($pppoecfg['radius']['server']['acctport']))
1387
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1388
				$mpdconf .=<<<EOD
1389
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
1390
	set radius retries 3
1391
	set radius timeout 10
1392
	set auth enable radius-auth
1393

    
1394
EOD;
1395

    
1396
				if (isset ($pppoecfg['radius']['accounting'])) {
1397
					$mpdconf .=<<<EOD
1398
	set auth enable radius-acct
1399

    
1400
EOD;
1401
				}
1402
			}
1403

    
1404
			fwrite($fd, $mpdconf);
1405
			fclose($fd);
1406

    
1407
			/* write mpd.links */
1408
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.links", "w");
1409
			if (!$fd) {
1410
				printf(gettext("Error: cannot open mpd.links in vpn_pppoe_configure().") . "\n");
1411
				return 1;
1412
			}
1413

    
1414
			$mpdlinks = "";
1415

    
1416
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1417
				$mpdlinks .=<<<EOD
1418
			
1419
poes{$pppoecfg['pppoeid']}{$i}:
1420
	set phys type pppoe
1421
        set pppoe iface {$pppoe_interface}
1422
        set pppoe service "*"
1423
        set pppoe disable originate
1424
        set pppoe enable incoming
1425

    
1426
EOD;
1427
			}
1428

    
1429
			fwrite($fd, $mpdlinks);
1430
			fclose($fd);
1431

    
1432
			if ($pppoecfg['username']) {
1433
				/* write mpd.secret */
1434
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1435
				if (!$fd) {
1436
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1437
					return 1;
1438
				}
1439

    
1440
				$mpdsecret = "\n\n";
1441

    
1442
				if (!empty($pppoecfg['username'])) {
1443
					$item = explode(" ", $pppoecfg['username']);
1444
					foreach($item as $userdata) {
1445
						$data = explode(":", $userdata);
1446
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1447
					}
1448
				}
1449

    
1450
				fwrite($fd, $mpdsecret);
1451
				fclose($fd);
1452
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1453
			}
1454

    
1455
			/* Check if previous instance is still up */
1456
			while (file_exists("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid") && isvalidpid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid"))
1457
				killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1458

    
1459
			/* Get support for netgraph(4) from the nic */
1460
			pfSense_ngctl_attach(".", $pppoe_interface);
1461
			/* fire up mpd */
1462
			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");
1463

    
1464
			break;
1465
	}
1466

    
1467
	if ($g['booting'])
1468
		echo gettext("done") . "\n";
1469

    
1470
	return 0;
1471
}
1472

    
1473
function vpn_l2tp_configure() {
1474
	global $config, $g;
1475

    
1476
	$syscfg = $config['system'];
1477
	$l2tpcfg = $config['l2tp'];
1478

    
1479
	/* create directory if it does not exist */
1480
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1481
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1482

    
1483
	if ($g['booting']) {
1484
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1485
			return 0;
1486

    
1487
		echo gettext("Configuring l2tp VPN service... ");
1488
	} else {
1489
		/* kill mpd */
1490
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1491

    
1492
		/* wait for process to die */
1493
		sleep(8);
1494

    
1495
	}
1496

    
1497
	/* make sure l2tp-vpn directory exists */
1498
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1499
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1500

    
1501
	switch ($l2tpcfg['mode']) {
1502

    
1503
		case 'server' :
1504
			if ($l2tpcfg['paporchap'] == "chap")
1505
				$paporchap = "set link enable chap";
1506
			else
1507
				$paporchap = "set link enable pap";
1508

    
1509
			/* write mpd.conf */
1510
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1511
			if (!$fd) {
1512
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
1513
				return 1;
1514
			}
1515
			$mpdconf = "\n\n";
1516
			$mpdconf .=<<<EOD
1517
l2tps:
1518

    
1519
EOD;
1520

    
1521
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1522
				$mpdconf .= "	load l2tp{$i}\n";
1523
			}
1524

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

    
1527
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1528

    
1529
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1530
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1531
				} else {
1532
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1533
				}
1534

    
1535
				$mpdconf .=<<<EOD
1536

    
1537
l2tp{$i}:
1538
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1539
	{$isssue_ip_type}
1540
	load l2tp_standard
1541

    
1542
EOD;
1543
			}
1544

    
1545
			$mpdconf .=<<<EOD
1546

    
1547
l2tp_standard:
1548
        set bundle disable multilink
1549
        set bundle enable compression
1550
        set bundle yes crypt-reqd
1551
        set ipcp yes vjcomp
1552
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1553
        set ccp yes mppc
1554
        set iface disable on-demand
1555
        set iface enable proxy-arp
1556
	set iface up-script /usr/local/sbin/vpn-linkup
1557
	set iface down-script /usr/local/sbin/vpn-linkdown
1558
        set link yes acfcomp protocomp
1559
        set link no pap chap
1560
        set link enable chap
1561
        set link keep-alive 10 180
1562

    
1563
EOD;
1564

    
1565
			if (is_ipaddr($l2tpcfg['wins'])) {
1566
				$mpdconf .= "	set ipcp nbns {$l2tpcfg['wins']}\n";
1567
			}
1568
			if (is_ipaddr($l2tpcfg['dns1'])) {
1569
				$mpdconf .= "	set ipcp dns " . $l2tpcfg['dns1'];
1570
				if (is_ipaddr($l2tpcfg['dns2']))
1571
					$mpdconf .= " " . $l2tpcfg['dns2'];
1572
				$mpdconf .= "\n";
1573
			} elseif (isset ($config['dnsmasq']['enable'])) {
1574
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1575
				if ($syscfg['dnsserver'][0])
1576
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1577
				$mpdconf .= "\n";
1578
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1579
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1580
			}
1581

    
1582
			if (isset ($l2tpcfg['radius']['enable'])) {
1583
				$mpdconf .=<<<EOD
1584
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1585
	set radius retries 3
1586
	set radius timeout 10
1587
	set auth enable radius-auth
1588

    
1589
EOD;
1590

    
1591
				if (isset ($l2tpcfg['radius']['accounting'])) {
1592
					$mpdconf .=<<<EOD
1593
	set auth enable radius-acct
1594

    
1595
EOD;
1596
				}
1597
			}
1598

    
1599
			fwrite($fd, $mpdconf);
1600
			fclose($fd);
1601

    
1602
			/* write mpd.links */
1603
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.links", "w");
1604
			if (!$fd) {
1605
				printf(gettext("Error: cannot open mpd.links in vpn_l2tp_configure().") . "\n");
1606
				return 1;
1607
			}
1608

    
1609
			$mpdlinks = "";
1610

    
1611
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1612
				$mpdlinks .=<<<EOD
1613

    
1614
l2tp{$i}:
1615
	set link type l2tp
1616
        set l2tp enable incoming
1617
        set l2tp disable originate
1618

    
1619
EOD;
1620
			if (!empty($l2tpcfg['secret']))
1621
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1622
			}
1623

    
1624
			fwrite($fd, $mpdlinks);
1625
			fclose($fd);
1626

    
1627
			/* write mpd.secret */
1628
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1629
			if (!$fd) {
1630
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
1631
				return 1;
1632
			}
1633

    
1634
			$mpdsecret = "\n\n";
1635

    
1636
			if (is_array($l2tpcfg['user'])) {
1637
				foreach ($l2tpcfg['user'] as $user)
1638
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1639
			}
1640

    
1641
			fwrite($fd, $mpdsecret);
1642
			fclose($fd);
1643
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1644

    
1645
			vpn_netgraph_support();
1646

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

    
1650
			break;
1651

    
1652
		case 'redir' :
1653
			break;
1654
	}
1655

    
1656
	if ($g['booting'])
1657
		echo "done\n";
1658

    
1659
	return 0;
1660
}
1661

    
1662
/* Walk the tunnels for hostname endpoints. If the hostnames 
1663
 * resolve to a different IP now compared to the DNS cache
1664
 * we reload the policies if the endpoint has changed */
1665
function vpn_ipsec_refresh_policies() {
1666
	global $config;
1667
	global $g;
1668

    
1669
	$ipseccfg = $config['ipsec'];
1670
	$a_phase1 = $config['ipsec']['phase1'];
1671
	$a_phase2 = $config['ipsec']['phase2'];
1672

    
1673
	if (isset($ipseccfg['disable'])) {
1674
		return true;
1675
	}
1676

    
1677
	/* Walk the Ipsec tunnel array */
1678
	if (!is_array($a_phase1) || (!count($a_phase1)))
1679
		return;
1680

    
1681
	foreach ($a_phase1 as $phase1) {
1682
		if (isset($phase1['disabled']))
1683
			continue;
1684
		if (is_ipaddr($phase1['remote-gateway']))
1685
			continue;
1686
		if (!is_ipaddr($phase1['remote-gateway'])) {
1687
			$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1688
			$dnscache = trim($dnscache);
1689
			/* we should have the old IP addresses in the dnscache now */
1690
			if(!empty($dnscache)) {
1691
				$oldphase1 = $phase1;
1692
				$oldphase1['remote-gateway'] = $dnscache;
1693
				/* now we need to find all tunnels for this host */
1694
				if (!is_array($a_phase2) || (!count($a_phase2)))
1695
					continue;
1696
				foreach ($a_phase2 as $phase2) {
1697
					if ($phase2['ikeid'] == $phase1['ikeid'])
1698
						reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1699
				}
1700
			}
1701
		}
1702
	}
1703

    
1704
	/* process all generated temporary spd.conf files */
1705
	$tmpfiles = glob("{$g['tmp_path']}/spd.conf.reload.*");
1706
	foreach($tmpfiles as $tmpfile) {
1707
		$ret = mwexec("/usr/local/sbin/setkey -f {$tmpfile} 2>&1", false);
1708
		if ($ret == 0)
1709
			unlink_if_exists($tmpfile);
1710
		else {
1711
			$tmpfile = basename($tmpfile);
1712
			@rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1713
		}
1714
	}
1715
}
1716

    
1717
/* reloads the tunnel configuration for a tunnel item
1718
 * Will remove and add SPD polices */
1719
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1720
	global $config;
1721
	global $g;
1722

    
1723
	/* if we are not passed a old tunnel array we create one */
1724
	if(empty($old_phase1)) {
1725
		$old_phase1 = $phase1;
1726
	}
1727
	if(empty($old_phase2)) {
1728
		$old_phase2 = $phase2;
1729
	}
1730

    
1731
	$sad_arr = ipsec_dump_sad();
1732

    
1733
	$ep = ipsec_get_phase1_src($phase1);
1734
	$phase2['localid']['mode'] = $phase2['mode'];
1735
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1736
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1737

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

    
1741
	$old_ep = ipsec_get_phase1_src($old_phase1);
1742
	$old_phase2['localid']['mode'] = $old_phase2['mode'];
1743
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1744
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1745

    
1746
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1747
	 * try to resolve it now and add it to the list for filterdns */
1748
	$rgip = "";
1749
	if (!is_ipaddr($phase1['remote-gateway'])) {
1750
		if(! $g['booting']) {
1751
			$rgip = resolve_retry($phase1['remote-gateway']);
1752
			add_hostname_to_watch($phase1['remote-gateway']);
1753
		} else {
1754
			add_hostname_to_watch($phase1['remote-gateway']);
1755
		}
1756
		if (!is_ipaddr($rgip)) {
1757
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1758
			return false;
1759
		}
1760
	} else {
1761
		$rgip = $phase1['remote-gateway'];
1762
	}
1763
	if (!$ep) {
1764
		log_error(sprintf(gettext("Could not determine VPN endpoint for '%s'"), $phase1['descr']));
1765
		return false;
1766
	}
1767

    
1768
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1769
		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));
1770
	}
1771
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1772
		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));
1773
	}
1774

    
1775
	$spdconf = "";
1776
	/* Delete old SPD policies if there are changes between the old and new */
1777
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1778
		if($old_phase2['mode'] == "tunnel6")
1779
			$family = "-6";
1780
		else
1781
			$family = "-4";
1782

    
1783
		$spdconf .= "spddelete {$family} {$old_local_subnet} " .
1784
			"{$old_remote_subnet} any -P out ipsec " .
1785
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1786
			"{$old_gw}/unique;\n";
1787
		if (!empty($old_phase2['natlocalid']))
1788
			$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['natlocalid']);
1789
		$spdconf .= "spddelete {$family} {$old_remote_subnet} " .
1790
			"{$old_local_subnet} any -P in ipsec " .
1791
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1792
			"{$old_ep}/unique;\n";
1793

    
1794
		/* zap any existing SA entries */
1795
		foreach($sad_arr as $sad) {
1796
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1797
				$spdconf .= "delete {$family} {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1798
			}
1799
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1800
				$spdconf .= "delete {$family} {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1801
			}
1802
		}
1803
	}
1804

    
1805
	if($phase2['mode'] == "tunnel6")
1806
		$family = "-6";
1807
	else
1808
		$family = "-4";
1809

    
1810
	/* Create new SPD entries for the new configuration */
1811
	/* zap any existing SA entries beforehand */
1812
	foreach($sad_arr as $sad) {
1813
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1814
			$spdconf .= "delete {$family} {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1815
		}
1816
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1817
			$spdconf .= "delete {$family} {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1818
		}
1819
	}
1820
	/* add new SPD policies to replace them */
1821
	if (!isset($phase1['disabled'])) {
1822
		$spdconf .= "spdadd {$family} {$local_subnet} " .
1823
			"{$remote_subnet} any -P out ipsec " .
1824
			"{$phase2['protocol']}/tunnel/{$ep}-" .
1825
			"{$rgip}/unique;\n";
1826

    
1827
		if (!empty($phase2['natlocalid']))
1828
			$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid']);
1829
		$spdconf .= "spdadd {$family} {$remote_subnet} " .
1830
			"{$local_subnet} any -P in ipsec " .
1831
			"{$phase2['protocol']}/tunnel/{$rgip}-" .
1832
			"{$ep}/unique;\n";
1833
	}
1834

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

    
1837
	$now = time();
1838
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1839
	/* generate temporary spd.conf */
1840
	@file_put_contents($spdfile, $spdconf);
1841
	return true;
1842
}
1843

    
1844
function vpn_ipsec_configure_preferoldsa() {
1845
	global $config;
1846
	if(isset($config['ipsec']['preferoldsa']))
1847
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1848
	else
1849
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1850
}
1851

    
1852
?>
(59-59/68)