Project

General

Profile

Download (53.3 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
// Disable this for now, when LDAP support returns it will be via external script auth, 
421
//    since we no longer build racoon with LDAP integrated. This is only preventing racoon from running.
422
//
423
//			if ($a_client['user_source'] != "system") {
424
//				if (is_array($config['system']['authserver'])) {
425
//					foreach ($config['system']['authserver'] as $authcfg) {
426
//						if ($authcfg['type'] == 'ldap' and $authcfg['name'] == $a_client['user_source']) 
427
//							$thisauthcfg = $authcfg;
428
//					}
429
//
430
//					/* begin ldapcfg */
431
//					$racoonconf .= "ldapcfg {\n";
432
//					$racoonconf .= "\tversion 3;\n";
433
//					$racoonconf .= "\thost \"".$thisauthcfg['host']."\";\n";
434
//					$lport = "389";
435
//					if ($authcfg['port'] != "")
436
//						$lport = $authcfg['port'];
437
//					$racoonconf .= "\tport ".$lport.";\n";
438
//					$racoonconf .= "\tbase \"".$thisauthcfg['ldap_basedn']."\";\n";
439
//					$racoonconf .= "\tsubtree on;\n";
440
//					$racoonconf .= "\tbind_dn \"".$thisauthcfg['ldap_binddn']."\";\n";
441
//					$racoonconf .= "\tbind_pw \"".$thisauthcfg['ldap_bindpw']."\";\n";
442
//					$racoonconf .= "\tattr_user \"".$thisauthcfg['ldap_attr_user']."\";\n";
443
//					$racoonconf .= "}\n\n";
444
//					/* end ldapcfg */
445
//				}
446
//			}
447

    
448
			/* begin remote sections */
449
			if (is_array($a_phase1) && count($a_phase1)) {
450
				/* begin remote */
451
				foreach ($a_phase1 as $ph1ent) {
452

    
453
					if (isset($ph1ent['disabled']))
454
						continue;
455

    
456
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
457
						continue;
458

    
459
					$ikeid = $ph1ent['ikeid'];
460

    
461
					$ep = ipsec_get_phase1_src($ph1ent);
462
					if (!$ep)
463
						continue;
464

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

    
471
					$myid_type = $ph1ent['myid_type'];
472

    
473
					switch ($myid_type) {
474

    
475
						case "myaddress":
476
							$myid_type = "address";
477
							$myid_data = $ep;
478
							break;
479

    
480
						case "dyn_dns":
481
							$myid_type = "address";
482
							$myid_data = resolve_retry($ph1ent['myid_data']);
483
							break;
484

    
485
						case "address";
486
							$myid_data = $ph1ent['myid_data'];
487
							break;
488

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

    
499
					$peerid_type = $ph1ent['peerid_type'];
500

    
501
					switch ($peerid_type) {
502
						case "peeraddress":
503
							$peerid_type = "address";
504
							$peerid_data = $rgip;
505
							break;
506

    
507
						case "address";
508
							$peerid_data = $ph1ent['peerid_data'];
509
							break;
510

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

    
521
					$natt = "off";
522
					if (isset($ph1ent['nat_traversal']))
523
						$natt = $ph1ent['nat_traversal'];
524

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

    
542
					$dpdline1 = '';
543
					$dpdline2 = '';
544
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
545
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
546
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
547
					}
548

    
549
					if (isset ($ph1ent['authentication_method']))
550
						$authmethod = $ph1ent['authentication_method'];
551
					else
552
						$authmethod = 'pre_shared_key';
553

    
554
					$certline = '';
555

    
556
					if (strstr($authmethod,'rsa')) {
557

    
558
						$cert = lookup_cert($ph1ent['certref']);
559

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

    
566
						$certfile = "cert-".$ikeid.".crt";
567
						$certpath = $g['varetc_path']."/".$certfile;
568

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

    
575
						chmod($certpath, 0600);
576

    
577
						$keyfile = "cert-".$ikeid.".key";
578
						$keypath = $g['varetc_path']."/".$keyfile;
579

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

    
586
						chmod($keypath, 0600);
587

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

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

    
599
							chmod($capath, 0600);
600
							$caline = "ca_type x509 \"".basename($capath)."\";";
601
						}
602

    
603
						$certline = "certificate_type x509 \"".basename($certpath)."\" \"".basename($keypath)."\";";
604

    
605
					}
606

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

    
615
					$lifeline = '';
616
					if ($ph1ent['lifetime'])
617
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
618

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

    
624
					/* add remote section to configuration */
625

    
626
					$racoonconf .=<<<EOD
627

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

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

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

    
665
				/* begin sainfo */
666
				foreach ($a_phase2 as $ph2ent) {
667

    
668
					$ikeid = $ph2ent['ikeid'];
669

    
670
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
671
						continue;
672

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

    
676
					if (isset($ph2ent['disabled']))
677
						continue;
678

    
679
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
680
						continue;
681

    
682
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
683

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

    
706
						if (!isset($ph2ent['mobile'])) {
707
							$remoteid_type = $ph2ent['remoteid']['type'];
708
							if ($remoteid_type != "address")
709
								$remoteid_type = "subnet";
710

    
711
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
712
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
713
						} else
714
							$remoteid_spec = "anonymous";
715

    
716
					} else {
717
						$rgip = $rgmap[$ph1ent['remote-gateway']];
718

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

    
736
					if($ph2ent['protocol'] == 'esp') {
737

    
738
						$ealgos = '';
739

    
740
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
741

    
742
							$ealg_id = $ealg['name'];
743
							$ealg_kl = $ealg['keylen'];
744

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

    
780
						$ealgosline = "encryption_algorithm {$ealgos};";
781

    
782
					} else {
783

    
784
						$ealgosline = "encryption_algorithm null_enc;";
785
					}
786

    
787
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
788
					$halgosline = "authentication_algorithm {$halgos};";
789

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

    
799
					$lifeline = '';
800
					if ($ph2ent['lifetime'])
801
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
802

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

    
817
EOD;
818
				}
819
				/* end sainfo */
820
			}
821
			/* end sainfo sections */
822

    
823
			fwrite($fd, $racoonconf);
824
			fclose($fd);
825
		}
826
		/* end racoon.conf */
827

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

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

    
856
			foreach ($a_phase2 as $ph2ent) {
857

    
858
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
859
					continue;
860

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

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

    
867
				if (isset($ph2ent['disabled']))
868
					continue;
869

    
870
				$ep = ipsec_get_phase1_src($ph1ent);
871
				if (!$ep)
872
					continue;
873

    
874
				$rgip = $rgmap[$ph1ent['remote-gateway']];
875
				if(!is_ipaddr($rgip))
876
					continue;
877

    
878
				$ph2ent['localid']['mode'] = $ph2ent['mode'];
879
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
880
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
881

    
882
				if(($ph2ent['mode'] == "tunnel") or ($ph2ent['mode'] == 'tunnel6')) {
883
					// Error will be logged above, no need to log this twice. #2201
884
					if (!is_subnet($localid))
885
						continue;
886

    
887
					if($ph2ent['mode'] == "tunnel6")
888
						$family = "-6";
889
					else
890
						$family = "-4";
891

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

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

    
898
				} else {
899

    
900
					$localid_data = ipsec_get_phase1_src($ph1ent);
901
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
902

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

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

    
909
				}
910

    
911
				/* static route needed? */
912
				if (preg_match("/^carp|^[a-z0-9]+_vip/i", $ph1ent['interface']))
913
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
914
				else
915
					$parentinterface = $ph1ent['interface'];
916

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

    
937
		}
938
		fwrite($fd, $spdconf);
939
		fclose($fd);
940

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

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

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

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

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

    
988
	return 0;
989
}
990

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

    
1000
	$ipseccfg = $config['ipsec'];
1001

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

    
1006
	/* wait for process to die */
1007
	sleep(4);
1008

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

    
1012
	/* wait for flushing to finish */
1013
	sleep(1);
1014

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

    
1021
}
1022

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

    
1027
	if ($g['platform'] == 'jail')
1028
		return;
1029

    
1030
	/* start pptpd */
1031
	vpn_pptpd_configure();
1032

    
1033
	/* start pppoe server */
1034
	vpn_pppoes_configure();
1035

    
1036
	/* setup l2tp */
1037
	vpn_l2tp_configure();
1038
}
1039

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

    
1051
function vpn_pptpd_configure() {
1052
	global $config, $g;
1053

    
1054
	$syscfg = $config['system'];
1055
	$pptpdcfg = $config['pptpd'];
1056

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

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

    
1066
		/* wait for process to die */
1067
		sleep(3);
1068

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

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

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

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

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

    
1098
			$mpdconf = <<<EOD
1099
pptps:
1100

    
1101
EOD;
1102

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

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

    
1109
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1110

    
1111
				$mpdconf .= <<<EOD
1112

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

    
1118
EOD;
1119
			}
1120

    
1121
			$mpdconf .=<<<EOD
1122

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

    
1143
EOD;
1144

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

    
1150
EOD;
1151
			}
1152

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

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

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

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

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

    
1190
EOD;
1191

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

    
1197
EOD;
1198
				}
1199
			}
1200

    
1201
			fwrite($fd, $mpdconf);
1202
			fclose($fd);
1203

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

    
1211
			$mpdlinks = "";
1212

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

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

    
1222
EOD;
1223
			}
1224

    
1225
			fwrite($fd, $mpdlinks);
1226
			fclose($fd);
1227

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

    
1235
			$mpdsecret = "";
1236

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

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

    
1249
			vpn_netgraph_support();
1250

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

    
1254
			break;
1255

    
1256
		case 'redir' :
1257
			break;
1258
	}
1259

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

    
1263
	return 0;
1264
}
1265

    
1266
function vpn_pppoes_configure() {
1267
	global $config;
1268

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

    
1275
function vpn_pppoe_configure(&$pppoecfg) {
1276
	global $config, $g;
1277

    
1278
	$syscfg = $config['system'];
1279

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

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

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

    
1293
		/* wait for process to die */
1294
		sleep(2);
1295

    
1296
	}
1297

    
1298
	switch ($pppoecfg['mode']) {
1299

    
1300
		case 'server' :
1301

    
1302
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1303

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

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

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

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

    
1324
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1325

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

    
1332
				$mpdconf .=<<<EOD
1333

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

    
1339
EOD;
1340
			}
1341

    
1342
			$mpdconf .=<<<EOD
1343

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

    
1370
EOD;
1371

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

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

    
1399
EOD;
1400

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

    
1405
EOD;
1406
				}
1407
			}
1408

    
1409
			fwrite($fd, $mpdconf);
1410
			fclose($fd);
1411

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

    
1419
			$mpdlinks = "";
1420

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

    
1431
EOD;
1432
			}
1433

    
1434
			fwrite($fd, $mpdlinks);
1435
			fclose($fd);
1436

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

    
1445
				$mpdsecret = "\n\n";
1446

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

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

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

    
1464
			/* Get support for netgraph(4) from the nic */
1465
			pfSense_ngctl_attach(".", $pppoe_interface);
1466
			/* fire up mpd */
1467
			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");
1468

    
1469
			break;
1470
	}
1471

    
1472
	if ($g['booting'])
1473
		echo gettext("done") . "\n";
1474

    
1475
	return 0;
1476
}
1477

    
1478
function vpn_l2tp_configure() {
1479
	global $config, $g;
1480

    
1481
	$syscfg = $config['system'];
1482
	$l2tpcfg = $config['l2tp'];
1483

    
1484
	/* create directory if it does not exist */
1485
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1486
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1487

    
1488
	if ($g['booting']) {
1489
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1490
			return 0;
1491

    
1492
		echo gettext("Configuring l2tp VPN service... ");
1493
	} else {
1494
		/* kill mpd */
1495
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1496

    
1497
		/* wait for process to die */
1498
		sleep(8);
1499

    
1500
	}
1501

    
1502
	/* make sure l2tp-vpn directory exists */
1503
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1504
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1505

    
1506
	switch ($l2tpcfg['mode']) {
1507

    
1508
		case 'server' :
1509
			if ($l2tpcfg['paporchap'] == "chap")
1510
				$paporchap = "set link enable chap";
1511
			else
1512
				$paporchap = "set link enable pap";
1513

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

    
1524
EOD;
1525

    
1526
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1527
				$mpdconf .= "	load l2tp{$i}\n";
1528
			}
1529

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

    
1532
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1533

    
1534
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1535
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1536
				} else {
1537
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1538
				}
1539

    
1540
				$mpdconf .=<<<EOD
1541

    
1542
l2tp{$i}:
1543
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1544
	{$isssue_ip_type}
1545
	load l2tp_standard
1546

    
1547
EOD;
1548
			}
1549

    
1550
			$mpdconf .=<<<EOD
1551

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

    
1568
EOD;
1569

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

    
1587
			if (isset ($l2tpcfg['radius']['enable'])) {
1588
				$mpdconf .=<<<EOD
1589
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1590
	set radius retries 3
1591
	set radius timeout 10
1592
	set auth enable radius-auth
1593

    
1594
EOD;
1595

    
1596
				if (isset ($l2tpcfg['radius']['accounting'])) {
1597
					$mpdconf .=<<<EOD
1598
	set auth enable radius-acct
1599

    
1600
EOD;
1601
				}
1602
			}
1603

    
1604
			fwrite($fd, $mpdconf);
1605
			fclose($fd);
1606

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

    
1614
			$mpdlinks = "";
1615

    
1616
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1617
				$mpdlinks .=<<<EOD
1618

    
1619
l2tp{$i}:
1620
	set link type l2tp
1621
        set l2tp enable incoming
1622
        set l2tp disable originate
1623

    
1624
EOD;
1625
			if (!empty($l2tpcfg['secret']))
1626
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1627
			}
1628

    
1629
			fwrite($fd, $mpdlinks);
1630
			fclose($fd);
1631

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

    
1639
			$mpdsecret = "\n\n";
1640

    
1641
			if (is_array($l2tpcfg['user'])) {
1642
				foreach ($l2tpcfg['user'] as $user)
1643
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1644
			}
1645

    
1646
			fwrite($fd, $mpdsecret);
1647
			fclose($fd);
1648
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1649

    
1650
			vpn_netgraph_support();
1651

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

    
1655
			break;
1656

    
1657
		case 'redir' :
1658
			break;
1659
	}
1660

    
1661
	if ($g['booting'])
1662
		echo "done\n";
1663

    
1664
	return 0;
1665
}
1666

    
1667
/* Walk the tunnels for hostname endpoints. If the hostnames 
1668
 * resolve to a different IP now compared to the DNS cache
1669
 * we reload the policies if the endpoint has changed */
1670
function vpn_ipsec_refresh_policies() {
1671
	global $config;
1672
	global $g;
1673

    
1674
	$ipseccfg = $config['ipsec'];
1675
	$a_phase1 = $config['ipsec']['phase1'];
1676
	$a_phase2 = $config['ipsec']['phase2'];
1677

    
1678
	if (isset($ipseccfg['disable'])) {
1679
		return true;
1680
	}
1681

    
1682
	/* Walk the Ipsec tunnel array */
1683
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1684
		return;
1685
	}
1686

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

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

    
1735
/* reloads the tunnel configuration for a tunnel item
1736
 * Will remove and add SPD polices */
1737
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1738
	global $config;
1739
	global $g;
1740

    
1741
	/* if we are not passed a old tunnel array we create one */
1742
	if(empty($old_phase1)) {
1743
		$old_phase1 = $phase1;
1744
	}
1745
	if(empty($old_phase2)) {
1746
		$old_phase2 = $phase2;
1747
	}
1748

    
1749
	$sad_arr = ipsec_dump_sad();
1750

    
1751
	$ep = ipsec_get_phase1_src($phase1);
1752
	$phase2['localid']['mode'] = $phase2['mode'];
1753
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1754
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1755

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

    
1759
	$old_ep = ipsec_get_phase1_src($old_phase1);
1760
	$old_phase2['localid']['mode'] = $old_phase2['mode'];
1761
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1762
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1763

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

    
1786
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1787
		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));
1788
	}
1789
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1790
		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));
1791
	}
1792

    
1793
	$spdconf = "";
1794
	/* Delete old SPD policies if there are changes between the old and new */
1795
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1796
		if($old_phase2['mode'] == "tunnel6")
1797
			$family = "-6";
1798
		else
1799
			$family = "-4";
1800

    
1801
		$spdconf .= "spddelete {$family} {$old_local_subnet} " .
1802
			"{$old_remote_subnet} any -P out ipsec " .
1803
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1804
			"{$old_gw}/unique;\n";
1805
		$spdconf .= "spddelete {$family} {$old_remote_subnet} " .
1806
			"{$old_local_subnet} any -P in ipsec " .
1807
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1808
			"{$old_ep}/unique;\n";
1809

    
1810
		/* zap any existing SA entries */
1811
		foreach($sad_arr as $sad) {
1812
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1813
				$spdconf .= "delete {$family} {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1814
			}
1815
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1816
				$spdconf .= "delete {$family} {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1817
			}
1818
		}
1819
	}
1820

    
1821
	if($phase2['mode'] == "tunnel6")
1822
		$family = "-6";
1823
	else
1824
		$family = "-4";
1825

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

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

    
1848
	$now = time();
1849
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1850
	/* generate temporary spd.conf */
1851
	file_put_contents($spdfile, $spdconf);
1852
	return true;
1853
}
1854

    
1855
function vpn_ipsec_configure_preferoldsa() {
1856
	global $config;
1857
	if(isset($config['ipsec']['preferoldsa']))
1858
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1859
	else
1860
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1861
}
1862

    
1863
?>
(57-57/66)