Project

General

Profile

Download (52.9 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 (($parentinterface <> "wan") && (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
				} else if(is_ipaddr($rgip))
932
					mwexec("/sbin/route delete -host {$rgip}", true);
933
			}
934

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

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

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

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

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

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

    
986
	return 0;
987
}
988

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

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

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

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

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

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

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

    
1019
}
1020

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1099
EOD;
1100

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

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

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

    
1109
				$mpdconf .= <<<EOD
1110

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

    
1116
EOD;
1117
			}
1118

    
1119
			$mpdconf .=<<<EOD
1120

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

    
1141
EOD;
1142

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

    
1148
EOD;
1149
			}
1150

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

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

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

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

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

    
1188
EOD;
1189

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

    
1195
EOD;
1196
				}
1197
			}
1198

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

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

    
1209
			$mpdlinks = "";
1210

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

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

    
1220
EOD;
1221
			}
1222

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

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

    
1233
			$mpdsecret = "";
1234

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

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

    
1247
			vpn_netgraph_support();
1248

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

    
1252
			break;
1253

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

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

    
1261
	return 0;
1262
}
1263

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

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

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

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

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

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

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

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

    
1294
	}
1295

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

    
1298
		case 'server' :
1299

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

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

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

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

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

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

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

    
1330
				$mpdconf .=<<<EOD
1331

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

    
1337
EOD;
1338
			}
1339

    
1340
			$mpdconf .=<<<EOD
1341

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

    
1368
EOD;
1369

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

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

    
1397
EOD;
1398

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

    
1403
EOD;
1404
				}
1405
			}
1406

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

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

    
1417
			$mpdlinks = "";
1418

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

    
1429
EOD;
1430
			}
1431

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

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

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

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

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

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

    
1463
			break;
1464
	}
1465

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

    
1469
	return 0;
1470
}
1471

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

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

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

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

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

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

    
1494
	}
1495

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

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

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

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

    
1518
EOD;
1519

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

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

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

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

    
1534
				$mpdconf .=<<<EOD
1535

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

    
1541
EOD;
1542
			}
1543

    
1544
			$mpdconf .=<<<EOD
1545

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

    
1562
EOD;
1563

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

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

    
1588
EOD;
1589

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

    
1594
EOD;
1595
				}
1596
			}
1597

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

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

    
1608
			$mpdlinks = "";
1609

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

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

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

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

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

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

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

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

    
1644
			vpn_netgraph_support();
1645

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

    
1649
			break;
1650

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

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

    
1658
	return 0;
1659
}
1660

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

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

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

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

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

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

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

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

    
1743
	$sad_arr = ipsec_dump_sad();
1744

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1857
?>
(56-56/65)