Project

General

Profile

Download (52.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
	/* get the automatic ping_hosts.sh ready */
88
	unlink_if_exists("{$g['vardb_path']}/ipsecpinghosts");
89
	touch("{$g['vardb_path']}/ipsecpinghosts");
90

    
91
	vpn_ipsec_configure_preferoldsa();
92

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

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

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

    
105
		/* kill racoon */
106
		if(is_process_running("racoon"))
107
			mwexec("/usr/bin/killall racoon", true);
108
		killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
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
		exec("/sbin/sysctl net.inet.ip.ipsec_in_use=0");
119

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

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

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

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

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

    
144
				$ep = ipsec_get_phase1_src($ph1ent);
145
				if (!is_ipaddr($ep))
146
					continue;
147

    
148
				if(!in_array($ep,$ipmap))
149
					$ipmap[] = $ep;
150

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

    
154
				if (isset ($ph1ent['mobile']))
155
					continue;
156

    
157
				$rg = $ph1ent['remote-gateway'];
158

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

    
173
				if (is_array($a_phase2)) {
174
					/* step through each phase2 entry */
175
					foreach ($a_phase2 as $ph2ent) {
176
						$ikeid = $ph2ent['ikeid'];
177

    
178
						if (isset($ph2ent['disabled']))
179
							continue;
180

    
181
						if ($ikeid != $ph1ent['ikeid'])
182
							continue;
183

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

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

    
252
		$pskconf = "";
253

    
254
		if (is_array($a_phase1) && count($a_phase1)) {
255
			foreach ($a_phase1 as $ph1ent) {
256

    
257
				if (isset($ph1ent['disabled']))
258
					continue;
259

    
260
				if (strstr($ph1ent['authentication_method'],'rsa'))
261
					continue;
262

    
263
				$peerid_type = $ph1ent['peerid_type'];
264

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

    
271
					case "address";
272
						$peerid_data = $ph1ent['peerid_data'];
273
						break;
274

    
275
					case "fqdn";
276
					case "keyid tag";
277
					case "user_fqdn";
278
						$peerid_data = $ph1ent['peerid_data'];
279
						break;
280
				}
281

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

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

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

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

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

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

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

    
331
			/* begin mode_cfg section */
332
			if (is_array($a_client) && isset($a_client['enable'])) {
333

    
334
				$racoonconf .= "\nmode_cfg\n";
335
				$racoonconf .= "{\n";
336

    
337
				if ($a_client['user_source'])
338
					$racoonconf .= "\tauth_source {$a_client['user_source']};\n";
339
				if ($a_client['group_source'])
340
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
341

    
342
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
343
					$pool_address = $a_client['pool_address'];
344
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
345

    
346
					$pool_address = long2ip32(ip2long($pool_address)+1);
347
					$pool_size = (~ip2long($pool_netmask) & 0xFFFFFFFF) - 2;
348

    
349
					$racoonconf .= "\tpool_size {$pool_size};\n";
350
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
351
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
352
				}
353

    
354
				if (isset($a_client['net_list'])) {
355

    
356
					$net_list = '';
357

    
358
					foreach ($a_phase2 as $ph2ent) {
359

    
360
						if (isset($ph2ent['disabled']))
361
							continue;
362

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

    
366
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
367

    
368
						if ($net_list)
369
							$net_list .= ", ";
370
						$net_list .= $localid;
371
					}
372

    
373
					if ($net_list)
374
						$racoonconf .= "\tsplit_network include {$net_list};\n";
375
				}
376

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

    
386
				if ($a_client['wins_server1'])
387
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
388
				if ($a_client['wins_server2'])
389
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
390

    
391
				if ($a_client['dns_domain']) {
392
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
393
					$racoonconf .= "\tsplit_dns \"{$a_client['dns_domain']}\";\n";
394
				}
395

    
396
				if ($a_client['pfs_group'])
397
					$racoonconf .= "\tpfs_group {$a_client['pfs_group']};\n";
398

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

    
407
					fwrite($fd1, $a_client['login_banner']);
408
					fclose($fd1);
409

    
410
					$racoonconf .= "\tbanner \"{$fn}\";\n";
411
				}
412

    
413
				if (isset($a_client['save_passwd']))
414
					$racoonconf .= "\tsave_passwd on;\n";
415

    
416
				$racoonconf .= "}\n\n";
417
			}
418
			/* end mode_cfg section */
419
			
420
			if ($a_client['user_source'] != "system") {
421
				if (is_array($config['system']['authserver'])) {
422
					foreach ($config['system']['authserver'] as $authcfg) {
423
						if ($authcfg['type'] == 'ldap' and $authcfg['name'] == $a_client['user_source']) 
424
							$thisauthcfg = $authcfg;
425
					}
426

    
427
					/* begin ldapcfg */                        
428
					$racoonconf .= "ldapcfg {\n";
429
					$racoonconf .= "\tversion 3;\n";
430
					$racoonconf .= "\thost \"".$thisauthcfg['host']."\";\n";
431
					$lport = "389";
432
					if ($authcfg['port'] != "")
433
						$lport = $authcfg['port'];
434
					$racoonconf .= "\tport ".$lport.";\n";
435
					$racoonconf .= "\tbase \"".$thisauthcfg['ldap_basedn']."\";\n";
436
					$racoonconf .= "\tsubtree on;\n";
437
					$racoonconf .= "\tbind_dn \"".$thisauthcfg['ldap_binddn']."\";\n";
438
					$racoonconf .= "\tbind_pw \"".$thisauthcfg['ldap_bindpw']."\";\n";
439
					$racoonconf .= "\tattr_user \"".$thisauthcfg['ldap_attr_user']."\";\n";
440
					$racoonconf .= "}\n\n";
441
					/* end ldapcfg */
442
				}
443
			}
444

    
445
			/* begin remote sections */
446
			if (is_array($a_phase1) && count($a_phase1)) {
447
				/* begin remote */
448
				foreach ($a_phase1 as $ph1ent) {
449

    
450
					if (isset($ph1ent['disabled']))
451
						continue;
452

    
453
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
454
						continue;
455

    
456
					$ikeid = $ph1ent['ikeid'];
457

    
458
					$ep = ipsec_get_phase1_src($ph1ent);
459
					if (!$ep)
460
						continue;
461

    
462
					if (!isset($ph1ent['mobile'])) {
463
						$rgip = $rgmap[$ph1ent['remote-gateway']];
464
						if (!$rgip)
465
							continue;
466
					}
467

    
468
					$myid_type = $ph1ent['myid_type'];
469

    
470
					switch ($myid_type) {
471

    
472
						case "myaddress":
473
							$myid_type = "address";
474
							$myid_data = $ep;
475
							break;
476

    
477
						case "dyn_dns":
478
							$myid_type = "address";
479
							$myid_data = resolve_retry($ph1ent['myid_data']);
480
							break;
481

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

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

    
496
					$peerid_type = $ph1ent['peerid_type'];
497

    
498
					switch ($peerid_type) {
499
						case "peeraddress":
500
							$peerid_type = "address";
501
							$peerid_data = $rgip;
502
							break;
503

    
504
						case "address";
505
							$peerid_data = $ph1ent['peerid_data'];
506
							break;
507

    
508
						case "fqdn";
509
						case "keyid tag";
510
						case "user_fqdn";
511
						case "asn1dn";
512
							$peerid_data = $ph1ent['peerid_data'];
513
							if( $peerid_data )
514
								$peerid_data = "\"".$peerid_data."\"";
515
							break;
516
					}
517

    
518
					$natt = "off";
519
					if (isset($ph1ent['nat_traversal']))
520
						$natt = $ph1ent['nat_traversal'];
521

    
522
					$init = "on";
523
					$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "off";
524
					$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "claim";
525
					$passive = "";
526
					if (isset($ph1ent['mobile'])) {
527
						$rgip = "anonymous";
528
						$passive = "passive on;";
529
						/* Mimic 1.2.3's behavior for pure-psk mobile tunnels */
530
						if ($ph1ent['authentication_method'] == "pre_shared_key") {
531
							$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "obey";
532
							$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "on";
533
						} else {
534
							$init = "off";
535
							$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "unique";
536
						}
537
					}
538

    
539
					$dpdline1 = '';
540
					$dpdline2 = '';
541
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
542
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
543
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
544
					}
545

    
546
					if (isset ($ph1ent['authentication_method']))
547
						$authmethod = $ph1ent['authentication_method'];
548
					else
549
						$authmethod = 'pre_shared_key';
550

    
551
					$certline = '';
552

    
553
					if (strstr($authmethod,'rsa')) {
554

    
555
						$cert = lookup_cert($ph1ent['certref']);
556

    
557
						if (!$cert)
558
						{
559
							log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
560
							continue;
561
						}
562

    
563
						$certfile = "cert-".$ikeid.".crt";
564
						$certpath = $g['varetc_path']."/".$certfile;
565

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

    
572
						chmod($certpath, 0600);
573

    
574
						$keyfile = "cert-".$ikeid.".key";
575
						$keypath = $g['varetc_path']."/".$keyfile;
576

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

    
583
						chmod($keypath, 0600);
584

    
585
						$ca = lookup_ca($ph1ent['caref']);
586
						if ($ca) {
587
							$cafile = "ca-".$ikeid.".crt";
588
							$capath = $g['varetc_path']."/".$cafile;
589

    
590
							if (!file_put_contents($capath, base64_decode($ca['crt'])))
591
							{
592
								log_error(sprintf(gettext("Error: Cannot write phase1 CA certificate file for %s"), $ph1ent['name']));
593
								continue;
594
							}
595

    
596
							chmod($capath, 0600);
597
							$caline = "ca_type x509 \"".basename($capath)."\";";
598
						}
599

    
600
						$certline = "certificate_type x509 \"".basename($certpath)."\" \"".basename($keypath)."\";";
601

    
602
					}
603

    
604
					$ealgos = '';
605
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
606
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
607
					if ($ealg_kl)
608
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
609
					else
610
						$ealgos = $ealgos.$ealg_id;
611

    
612
					$lifeline = '';
613
					if ($ph1ent['lifetime'])
614
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
615

    
616
					/* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */
617
					if (!(($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))) {
618
						$peerid_spec = "peers_identifier {$peerid_type} {$peerid_data};";
619
					}
620

    
621
					/* add remote section to configuration */
622

    
623
					$racoonconf .=<<<EOD
624

    
625
remote {$rgip}
626
{
627
	ph1id {$ikeid};
628
	exchange_mode {$ph1ent['mode']};
629
	my_identifier {$myid_type} {$myid_data};
630
	{$peerid_spec}
631
	ike_frag on;
632
	generate_policy = {$genp};
633
	initial_contact = {$init};
634
	nat_traversal = {$natt};
635
	{$certline}
636
	{$caline}
637
	{$dpdline1}
638
	{$dpdline2}
639
	support_proxy on;
640
	proposal_check {$pcheck};
641
	{$passive}
642

    
643
	proposal
644
	{
645
		authentication_method {$authmethod};
646
		encryption_algorithm ${ealgos};
647
		hash_algorithm {$ph1ent['hash-algorithm']};
648
		dh_group {$ph1ent['dhgroup']};
649
		${lifeline}
650
	}
651
}
652

    
653
EOD;
654
				}
655
				/* end remote */
656
			}
657
			/* end remote sections */
658
		
659
			/* begin sainfo sections */
660
			if (is_array($a_phase2) && count($a_phase2)) {
661

    
662
				/* begin sainfo */
663
				foreach ($a_phase2 as $ph2ent) {
664

    
665
					$ikeid = $ph2ent['ikeid'];
666

    
667
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
668
						continue;
669

    
670
					if (isset($ph1ent['disabled']))
671
						continue;
672

    
673
					if (isset($ph2ent['disabled']))
674
						continue;
675

    
676
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
677
						continue;
678

    
679
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
680

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

    
703
						if (!isset($ph2ent['mobile'])) {
704
							$remoteid_type = $ph2ent['remoteid']['type'];
705
							if ($remoteid_type != "address")
706
								$remoteid_type = "subnet";
707

    
708
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
709
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
710
						} else
711
							$remoteid_spec = "anonymous";
712

    
713
					} else {
714
						$rgip = $rgmap[$ph1ent['remote-gateway']];
715

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

    
733
					if($ph2ent['protocol'] == 'esp') {
734

    
735
						$ealgos = '';
736

    
737
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
738

    
739
							$ealg_id = $ealg['name'];
740
							$ealg_kl = $ealg['keylen'];
741

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

    
777
						$ealgosline = "encryption_algorithm {$ealgos};";
778

    
779
					} else {
780

    
781
						$ealgosline = "encryption_algorithm null_enc;";
782
					}
783

    
784
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
785
					$halgosline = "authentication_algorithm {$halgos};";
786

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

    
796
					$lifeline = '';
797
					if ($ph2ent['lifetime'])
798
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
799

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

    
814
EOD;
815
				}
816
				/* end sainfo */
817
			}
818
			/* end sainfo sections */
819

    
820
			fwrite($fd, $racoonconf);
821
			fclose($fd);
822
		}
823
		/* end racoon.conf */
824

    
825
		/* generate IPsec policies */
826
		/* generate spd.conf */
827
		$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
828
		if (!$fd) {
829
			printf(gettext("Error: cannot open spd.conf in vpn_ipsec_configure().") . "\n");
830
			return 1;
831
		}
832

    
833
		$spdconf = "";
834
		if (is_array($a_phase2) && count($a_phase2)) {
835
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
836
			if ($config['interfaces']['lan']) {
837
				$lanip = get_interface_ip("lan");
838
				if (!empty($lanip) && is_ipaddrv4($lanip)) {
839
					$lansn = get_interface_subnet("lan");
840
					$lansa = gen_subnet($lanip, $lansn);
841
					$spdconf .= "spdadd -4 {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
842
					$spdconf .= "spdadd -4 {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
843
				}
844
				$lanipv6 = get_interface_ipv6("lan");
845
				if (!empty($lanipv6) && is_ipaddrv6($lanipv6)) {
846
					$lansnv6 = get_interface_subnetv6("lan");
847
					$lansav6 = gen_subnetv6($lanipv6, $lansnv6);
848
					$spdconf .= "spdadd -6 {$lanipv6}/128 {$lansav6}/{$lansnv6} any -P out none;\n";
849
					$spdconf .= "spdadd -6 {$lansav6}/{$lansnv6} {$lanipv6}/128 any -P in none;\n";
850
				}
851
			}
852

    
853
			foreach ($a_phase2 as $ph2ent) {
854

    
855
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
856
					continue;
857

    
858
				if (isset($ph1ent['mobile']))
859
					continue;
860

    
861
				if (isset($ph1ent['disabled']))
862
					continue;
863

    
864
				if (isset($ph2ent['disabled']))
865
					continue;
866

    
867
				$ep = ipsec_get_phase1_src($ph1ent);
868
				if (!$ep)
869
					continue;
870

    
871
				$rgip = $rgmap[$ph1ent['remote-gateway']];
872
				if(!is_ipaddr($rgip))
873
					continue;
874

    
875
				$ph2ent['localid']['mode'] = $ph2ent['mode'];
876
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
877
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
878

    
879
				// Error will be logged above, no need to log this twice. #2201
880
				if (!is_subnet($localid))
881
					continue;
882

    
883
				if(($ph2ent['mode'] == "tunnel") or ($ph2ent['mode'] == 'tunnel6')) {
884
					if($ph2ent['mode'] == "tunnel6")
885
						$family = "-6";
886
					else
887
						$family = "-4";
888

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

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

    
895
				} else {
896

    
897
					$localid_data = ipsec_get_phase1_src($ph1ent);
898
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
899

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

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

    
906
				}
907

    
908
				/* static route needed? */
909
				if (preg_match("/^carp|^vip/i", $ph1ent['interface']))
910
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
911
				else
912
					$parentinterface = $ph1ent['interface'];
913

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

    
934
		}
935
		fwrite($fd, $spdconf);
936
		fclose($fd);
937

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

    
961
		}
962
		/* start filterdns, if necessary */
963
		if (count($filterdns_list) > 0) {
964
			$interval = 60;
965
			if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval']))
966
				$interval = $ipseccfg['dns-interval'];
967

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

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

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

    
985
	return 0;
986
}
987

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

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

    
999
	/* kill racoon */
1000
	if(is_process_running("racoon"))
1001
		mwexec("/usr/bin/killall racoon", true);
1002

    
1003
	/* wait for process to die */
1004
	sleep(4);
1005

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

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

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

    
1018
}
1019

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

    
1024
	if ($g['platform'] == 'jail')
1025
		return;
1026

    
1027
	/* start pptpd */
1028
	vpn_pptpd_configure();
1029

    
1030
	/* start pppoe server */
1031
	vpn_pppoes_configure();
1032

    
1033
	/* setup l2tp */
1034
	vpn_l2tp_configure();
1035
}
1036

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

    
1048
function vpn_pptpd_configure() {
1049
	global $config, $g;
1050

    
1051
	$syscfg = $config['system'];
1052
	$pptpdcfg = $config['pptpd'];
1053

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

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

    
1063
		/* wait for process to die */
1064
		sleep(3);
1065

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

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

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

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

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

    
1095
			$mpdconf = <<<EOD
1096
pptps:
1097

    
1098
EOD;
1099

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

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

    
1106
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1107

    
1108
				$mpdconf .= <<<EOD
1109

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

    
1115
EOD;
1116
			}
1117

    
1118
			$mpdconf .=<<<EOD
1119

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

    
1140
EOD;
1141

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

    
1147
EOD;
1148
			}
1149

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

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

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

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

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

    
1187
EOD;
1188

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

    
1194
EOD;
1195
				}
1196
			}
1197

    
1198
			fwrite($fd, $mpdconf);
1199
			fclose($fd);
1200

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

    
1208
			$mpdlinks = "";
1209

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

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

    
1219
EOD;
1220
			}
1221

    
1222
			fwrite($fd, $mpdlinks);
1223
			fclose($fd);
1224

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

    
1232
			$mpdsecret = "";
1233

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

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

    
1246
			vpn_netgraph_support();
1247

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

    
1251
			break;
1252

    
1253
		case 'redir' :
1254
			break;
1255
	}
1256

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

    
1260
	return 0;
1261
}
1262

    
1263
function vpn_pppoes_configure() {
1264
	global $config;
1265

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

    
1272
function vpn_pppoe_configure(&$pppoecfg) {
1273
	global $config, $g;
1274

    
1275
	$syscfg = $config['system'];
1276

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

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

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

    
1290
		/* wait for process to die */
1291
		sleep(2);
1292

    
1293
	}
1294

    
1295
	switch ($pppoecfg['mode']) {
1296

    
1297
		case 'server' :
1298

    
1299
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1300

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

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

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

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

    
1321
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1322

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

    
1329
				$mpdconf .=<<<EOD
1330

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

    
1336
EOD;
1337
			}
1338

    
1339
			$mpdconf .=<<<EOD
1340

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

    
1367
EOD;
1368

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

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

    
1396
EOD;
1397

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

    
1402
EOD;
1403
				}
1404
			}
1405

    
1406
			fwrite($fd, $mpdconf);
1407
			fclose($fd);
1408

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

    
1416
			$mpdlinks = "";
1417

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

    
1428
EOD;
1429
			}
1430

    
1431
			fwrite($fd, $mpdlinks);
1432
			fclose($fd);
1433

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

    
1442
				$mpdsecret = "\n\n";
1443

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

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

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

    
1462
			break;
1463
	}
1464

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

    
1468
	return 0;
1469
}
1470

    
1471
function vpn_l2tp_configure() {
1472
	global $config, $g;
1473

    
1474
	$syscfg = $config['system'];
1475
	$l2tpcfg = $config['l2tp'];
1476

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

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

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

    
1490
		/* wait for process to die */
1491
		sleep(8);
1492

    
1493
	}
1494

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

    
1499
	switch ($l2tpcfg['mode']) {
1500

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

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

    
1517
EOD;
1518

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

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

    
1525
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1526

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

    
1533
				$mpdconf .=<<<EOD
1534

    
1535
l2tp{$i}:
1536
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1537
	{$isssue_ip_type}
1538
	load l2tp_standard
1539

    
1540
EOD;
1541
			}
1542

    
1543
			$mpdconf .=<<<EOD
1544

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

    
1561
EOD;
1562

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

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

    
1587
EOD;
1588

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

    
1593
EOD;
1594
				}
1595
			}
1596

    
1597
			fwrite($fd, $mpdconf);
1598
			fclose($fd);
1599

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

    
1607
			$mpdlinks = "";
1608

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

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

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

    
1622
			fwrite($fd, $mpdlinks);
1623
			fclose($fd);
1624

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

    
1632
			$mpdsecret = "\n\n";
1633

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

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

    
1643
			vpn_netgraph_support();
1644

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

    
1648
			break;
1649

    
1650
		case 'redir' :
1651
			break;
1652
	}
1653

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

    
1657
	return 0;
1658
}
1659

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

    
1667
	$ipseccfg = $config['ipsec'];
1668
	$a_phase1 = $config['ipsec']['phase1'];
1669
	$a_phase2 = $config['ipsec']['phase2'];
1670

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

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

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

    
1707
	/* process all generated spd.conf files from tmp which are left behind
1708
	 * behind by either changes of dynamic tunnels or manual edits
1709
	 * scandir() is only available in PHP5 */
1710
	$tmpfiles = array();
1711
	$dh  = opendir($g['tmp_path']);
1712
	while (false !== ($filename = readdir($dh))) {
1713
		if(preg_match("/^spd.conf.reload./", $filename)) {
1714
			$tmpfiles[] = $filename;
1715
		}
1716
	}
1717
	sort($tmpfiles);
1718
	foreach($tmpfiles as $tmpfile) {
1719
		$ret = mwexec("/usr/local/sbin/setkey -f {$g['tmp_path']}/{$tmpfile} 2>&1", false);
1720
		if($ret == 0) {
1721
			unlink_if_exists("{$g['tmp_path']}/{$tmpfile}");
1722
		} else {
1723
			rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1724
		}
1725
	}
1726
}
1727

    
1728
/* reloads the tunnel configuration for a tunnel item
1729
 * Will remove and add SPD polices */
1730
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1731
	global $config;
1732
	global $g;
1733

    
1734
	/* if we are not passed a old tunnel array we create one */
1735
	if(empty($old_phase1)) {
1736
		$old_phase1 = $phase1;
1737
	}
1738
	if(empty($old_phase2)) {
1739
		$old_phase2 = $phase2;
1740
	}
1741

    
1742
	$sad_arr = ipsec_dump_sad();
1743

    
1744
	$ep = ipsec_get_phase1_src($phase1);
1745
	$phase2['localid']['mode'] = $phase2['mode'];
1746
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1747
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1748

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

    
1752
	$old_ep = ipsec_get_phase1_src($old_phase1);
1753
	$old_phase2['localid']['mode'] = $old_phase2['mode'];
1754
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1755
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1756

    
1757
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1758
	 * try to resolve it now and add it to the list for filterdns */
1759
	$rgip = "";
1760
	if (!is_ipaddr($phase1['remote-gateway'])) {
1761
		if(! $g['booting']) {
1762
			$rgip = resolve_retry($phase1['remote-gateway']);
1763
			add_hostname_to_watch($phase1['remote-gateway']);
1764
		} else {
1765
			add_hostname_to_watch($phase1['remote-gateway']);
1766
		}
1767
		if (!is_ipaddr($rgip)) {
1768
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1769
			return false;
1770
		}
1771
	} else {
1772
		$rgip = $phase1['remote-gateway'];
1773
	}
1774
	if (!$ep) {
1775
		log_error(sprintf(gettext("Could not determine VPN endpoint for '%s'"), $phase1['descr']));
1776
		return false;
1777
	}
1778

    
1779
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1780
		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));
1781
	}
1782
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1783
		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));
1784
	}
1785

    
1786
	$spdconf = "";
1787
	/* Delete old SPD policies if there are changes between the old and new */
1788
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1789
		if($old_phase2['mode'] == "tunnel6")
1790
			$family = "-6";
1791
		else
1792
			$family = "-4";
1793

    
1794
		$spdconf .= "spddelete {$family} {$old_local_subnet} " .
1795
			"{$old_remote_subnet} any -P out ipsec " .
1796
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1797
			"{$old_gw}/unique;\n";
1798
		$spdconf .= "spddelete {$family} {$old_remote_subnet} " .
1799
			"{$old_local_subnet} any -P in ipsec " .
1800
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1801
			"{$old_ep}/unique;\n";
1802

    
1803
		/* zap any existing SA entries */
1804
		foreach($sad_arr as $sad) {
1805
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1806
				$spdconf .= "delete {$family} {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1807
			}
1808
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1809
				$spdconf .= "delete {$family} {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1810
			}
1811
		}
1812
	}
1813

    
1814
	if($phase2['mode'] == "tunnel6")
1815
		$family = "-6";
1816
	else
1817
		$family = "-4";
1818

    
1819
	/* Create new SPD entries for the new configuration */
1820
	/* zap any existing SA entries beforehand */
1821
	foreach($sad_arr as $sad) {
1822
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1823
			$spdconf .= "delete {$family} {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1824
		}
1825
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1826
			$spdconf .= "delete {$family} {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1827
		}
1828
	}
1829
	/* add new SPD policies to replace them */
1830
	$spdconf .= "spdadd {$family} {$local_subnet} " .
1831
		"{$remote_subnet} any -P out ipsec " .
1832
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1833
		"{$rgip}/unique;\n";
1834
	$spdconf .= "spdadd {$family} {$remote_subnet} " .
1835
		"{$local_subnet} any -P in ipsec " .
1836
		"{$phase2['protocol']}/tunnel/{$rgip}-" .
1837
		"{$ep}/unique;\n";
1838

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

    
1841
	$now = time();
1842
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1843
	/* generate temporary spd.conf */
1844
	file_put_contents($spdfile, $spdconf);
1845
	return true;
1846
}
1847

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

    
1856
?>
(56-56/65)