Project

General

Profile

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

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

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

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

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

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

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

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

    
44
/* include all configuration functions */
45

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

    
49

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

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

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

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

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

    
85
	if ($g['platform'] == 'jail')
86
		return;
87

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

    
92
	vpn_ipsec_configure_preferoldsa();
93

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
233
		/* generate CA certificates files */
234
		if (is_array($config['ca']) && count($config['ca'])) {
235
			foreach ($config['ca'] as $ca) {
236
				if (!isset($ca['crt'])) {
237
					log_error(sprintf(gettext("Error: Invalid certificate info for %s"), $ca['descr']));
238
					continue;
239
				}
240
				$cert = base64_decode($ca['crt']);
241
				$x509cert = openssl_x509_parse(openssl_x509_read($cert));
242
				if (!is_array($x509cert) || !isset($x509cert['hash'])) {
243
					log_error(sprintf(gettext("Error: Invalid certificate hash info for %s"), $ca['descr']));
244
					continue;
245
				}
246
				$fname = "{$g['varetc_path']}/ipsec/{$x509cert['hash']}.0";
247
				if (!@file_put_contents($fname, $cert)) {
248
					log_error(sprintf(gettext("Error: Cannot write IPsec CA file for %s"), $ca['descr']));
249
					continue;
250
				}
251
				unset($cert);
252
			}
253
		}
254
		
255
		$pskconf = "";
256

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
353
					$net_list = '';
354

    
355
					foreach ($a_phase2 as $ph2ent) {
356

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

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

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

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

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

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

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

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

    
394
				if ($a_client['dns_split']) {
395
					$domain_array = preg_split("/[ ,]+/",$a_client['dns_split']);
396
					$domain_string = implode('", "', $domain_array);
397
					$racoonconf .= "\tsplit_dns \"{$domain_string}\";\n";
398
				}
399

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

    
403
				if ($a_client['login_banner']) {
404
					@file_put_contents("{$g['varetc_path']}/ipsec/racoon.motd", $a_client['login_banner']);
405
					$racoonconf .= "\tbanner \"{$g['varetc_path']}/ipsec/racoon.motd\";\n";
406
				}
407

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

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

    
435
			/* begin remote sections */
436
			if (is_array($a_phase1) && count($a_phase1)) {
437
				/* begin remote */
438
				foreach ($a_phase1 as $ph1ent) {
439

    
440
					if (isset($ph1ent['disabled']))
441
						continue;
442

    
443
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
444
						continue;
445

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

    
448
					$ep = ipsec_get_phase1_src($ph1ent);
449
					if (!$ep)
450
						continue;
451

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

    
458
					$myid_type = $ph1ent['myid_type'];
459

    
460
					switch ($myid_type) {
461

    
462
						case "myaddress":
463
							$myid_type = "address";
464
							$myid_data = $ep;
465
							break;
466

    
467
						case "dyn_dns":
468
							$myid_type = "address";
469
							$myid_data = resolve_retry($ph1ent['myid_data']);
470
							break;
471

    
472
						case "address";
473
							$myid_data = $ph1ent['myid_data'];
474
							break;
475

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

    
486
					$peerid_type = $ph1ent['peerid_type'];
487

    
488
					switch ($peerid_type) {
489
						case "peeraddress":
490
							$peerid_type = "address";
491
							$peerid_data = $rgip;
492
							break;
493

    
494
						case "address";
495
							$peerid_data = $ph1ent['peerid_data'];
496
							break;
497

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

    
508
					$natt = "off";
509
					if (isset($ph1ent['nat_traversal']))
510
						$natt = $ph1ent['nat_traversal'];
511

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

    
529
					$dpdline1 = '';
530
					$dpdline2 = '';
531
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
532
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
533
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
534
					}
535

    
536
					if (isset ($ph1ent['authentication_method']))
537
						$authmethod = $ph1ent['authentication_method'];
538
					else
539
						$authmethod = 'pre_shared_key';
540

    
541
					$certline = '';
542

    
543
					if (strstr($authmethod,'rsa')) {
544

    
545
						$cert = lookup_cert($ph1ent['certref']);
546

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

    
553
						$certfile = "cert-{$ikeid}.crt";
554
						$certpath = "{$g['varetc_path']}/ipsec/{$certfile}";
555

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

    
562
						chmod($certpath, 0600);
563

    
564
						$keyfile = "cert-{$ikeid}.key";
565
						$keypath = "{$g['varetc_path']}/ipsec/{$keyfile}";
566

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

    
573
						chmod($keypath, 0600);
574

    
575
						$ca = lookup_ca($ph1ent['caref']);
576
						if ($ca) {
577
							$cafile = "ca-{$ikeid}.crt";
578
							$capath = "{$g['varetc_path']}/ipsec/{$cafile}";
579

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

    
586
							chmod($capath, 0600);
587
							$caline = "ca_type x509 \"{$cafile}\";";
588
						}
589

    
590
						$certline = "certificate_type x509 \"{$certfile}\" \"{$keyfile}\";";
591

    
592
					}
593

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

    
602
					$lifeline = '';
603
					if ($ph1ent['lifetime'])
604
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
605

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

    
611
					/* add remote section to configuration */
612

    
613
					$racoonconf .=<<<EOD
614

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

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

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

    
652
				/* begin sainfo */
653
				foreach ($a_phase2 as $ph2ent) {
654

    
655
					$ikeid = $ph2ent['ikeid'];
656

    
657
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
658
						continue;
659

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

    
663
					if (isset($ph2ent['disabled']))
664
						continue;
665

    
666
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
667
						continue;
668

    
669
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
670

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

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

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

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

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

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

    
734
						$ealgos = '';
735

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

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

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

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

    
778
					} else {
779

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

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

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

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

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

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

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

    
846
			foreach ($a_phase2 as $ph2ent) {
847

    
848
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
849
					continue;
850

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

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

    
857
				if (isset($ph2ent['disabled']))
858
					continue;
859

    
860
				$ep = ipsec_get_phase1_src($ph1ent);
861
				if (!$ep)
862
					continue;
863

    
864
				$rgip = $rgmap[$ph1ent['remote-gateway']];
865
				if(!is_ipaddr($rgip))
866
					continue;
867

    
868
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']);
869
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'], true, $ph2ent['mode']);
870

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

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

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

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

    
893
				} else {
894

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

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

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

    
904
				}
905

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

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

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

    
960
		}
961
		if ($natfilterrules == true)
962
			filter_configure();
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']}/ipsec/filterdns-ipsec.hosts", $hostnames);
974
			unset($hostnames);
975

    
976
			if (isvalidpid("{$g['varrun_path']}/filterdns-ipsec.pid"))
977
				sigkillbypid("{$g['varrun_path']}/filterdns-ipsec.pid", "HUP");
978
			else {
979
				mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/ipsec/filterdns-ipsec.hosts -d 1");
980
			}
981
		} else {
982
			killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
983
			@unlink("{$g['varrun_path']}/filterdns-ipsec.pid");
984
		}
985
	
986
		vpn_ipsec_failover_configure();
987

    
988
		if ($g['booting'])
989
			echo "done\n";
990
	}
991

    
992
	return 0;
993
}
994

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

    
1005
	$ipseccfg = $config['ipsec'];
1006

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

    
1010
	/* wait for process to die */
1011
	sleep(4);
1012

    
1013
	/* kill racoon forcefully */
1014
	if (is_process_running("racoon"))
1015
		mwexec("/usr/bin/killall -9 racoon", true);
1016

    
1017
	/* wait for flushing to finish */
1018
	sleep(1);
1019

    
1020
	/* if ipsec is enabled, start up again */
1021
	if (isset($ipseccfg['enable'])) {
1022
		log_error(gettext("Forcefully reloading IPsec racoon daemon"));
1023
		vpn_ipsec_configure();
1024
	}
1025
}
1026

    
1027
/* master setup for vpn (mpd) */
1028
function vpn_setup() {
1029
	global $g;
1030

    
1031
	if ($g['platform'] == 'jail')
1032
		return;
1033

    
1034
	/* start pptpd */
1035
	vpn_pptpd_configure();
1036

    
1037
	/* start pppoe server */
1038
	vpn_pppoes_configure();
1039

    
1040
	/* setup l2tp */
1041
	vpn_l2tp_configure();
1042
}
1043

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

    
1055
function vpn_pptpd_configure() {
1056
	global $config, $g;
1057

    
1058
	$syscfg = $config['system'];
1059
	$pptpdcfg = $config['pptpd'];
1060

    
1061
	if ($g['booting']) {
1062
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
1063
			return 0;
1064

    
1065
		echo gettext("Configuring PPTP VPN service... ");
1066
	} else {
1067
		/* kill mpd */
1068
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1069

    
1070
		/* wait for process to die */
1071
		sleep(3);
1072

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

    
1078
		/* remove mpd.conf, if it exists */
1079
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
1080
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
1081
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
1082
	}
1083

    
1084
	if (empty($pptpdcfg['n_pptp_units'])) {
1085
		log_error("Something wrong in the PPTPd configuration. Preventing starting the daemon because issues would arise.");
1086
		return; 
1087
	}
1088

    
1089
	/* make sure pptp-vpn directory exists */
1090
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
1091
		mkdir("{$g['varetc_path']}/pptp-vpn");
1092

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

    
1102
			$mpdconf = <<<EOD
1103
pptps:
1104

    
1105
EOD;
1106

    
1107
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1108
				$mpdconf .= "	load pt{$i}\n";
1109
			}
1110

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

    
1113
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1114

    
1115
				$mpdconf .= <<<EOD
1116

    
1117
pt{$i}:
1118
	new -i pptpd{$i} pt{$i} pt{$i}
1119
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1120
	load pts
1121

    
1122
EOD;
1123
			}
1124

    
1125
			$mpdconf .=<<<EOD
1126

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

    
1147
EOD;
1148

    
1149
			if (!isset ($pptpdcfg['req128'])) {
1150
				$mpdconf .=<<<EOD
1151
	set ccp yes mpp-e40
1152
	set ccp yes mpp-e56
1153

    
1154
EOD;
1155
			}
1156

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

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

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

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

    
1187
EOD;
1188
			}
1189
			$mpdconf .=<<<EOD
1190
	set radius retries 3
1191
	set radius timeout 10
1192
	set auth enable radius-auth
1193

    
1194
EOD;
1195

    
1196
				if (isset ($pptpdcfg['radius']['accounting'])) {
1197
					$mpdconf .=<<<EOD
1198
	set auth enable radius-acct
1199
	set radius acct-update 300
1200

    
1201
EOD;
1202
				}
1203
			}
1204

    
1205
			fwrite($fd, $mpdconf);
1206
			fclose($fd);
1207
			unset($mpdconf);
1208

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

    
1216
			$mpdlinks = "";
1217

    
1218
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1219
				$mpdlinks .=<<<EOD
1220

    
1221
pt{$i}:
1222
	set link type pptp
1223
	set pptp enable incoming
1224
	set pptp disable originate
1225
	set pptp disable windowing
1226

    
1227
EOD;
1228
			}
1229

    
1230
			fwrite($fd, $mpdlinks);
1231
			fclose($fd);
1232
			unset($mpdlinks);
1233

    
1234
			/* write mpd.secret */
1235
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1236
			if (!$fd) {
1237
				printf(gettext("Error: cannot open mpd.secret in vpn_pptpd_configure().") . "\n");
1238
				return 1;
1239
			}
1240

    
1241
			$mpdsecret = "";
1242

    
1243
			if (is_array($pptpdcfg['user'])) {
1244
				foreach ($pptpdcfg['user'] as $user) {
1245
					$pass = str_replace('\\', '\\\\', $user['password']);
1246
					$pass = str_replace('"', '\"', $pass);
1247
					$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
1248
				}
1249
			}
1250

    
1251
			fwrite($fd, $mpdsecret);
1252
			fclose($fd);
1253
			unset($mpdsecret);
1254
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1255

    
1256
			vpn_netgraph_support();
1257

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

    
1261
			break;
1262

    
1263
		case 'redir' :
1264
			break;
1265
	}
1266

    
1267
	if ($g['booting'])
1268
		echo "done\n";
1269

    
1270
	return 0;
1271
}
1272

    
1273
function vpn_pppoes_configure() {
1274
	global $config;
1275

    
1276
	if (is_array($config['pppoes']['pppoe'])) {
1277
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1278
			vpn_pppoe_configure($pppoe);
1279
	}
1280
}
1281

    
1282
function vpn_pppoe_configure(&$pppoecfg) {
1283
	global $config, $g;
1284

    
1285
	$syscfg = $config['system'];
1286

    
1287
	/* create directory if it does not exist */
1288
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1289
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1290

    
1291
	if ($g['booting']) {
1292
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1293
			return 0;
1294

    
1295
		echo gettext("Configuring PPPoE VPN service... ");
1296
	} else {
1297
		/* kill mpd */
1298
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1299

    
1300
		/* wait for process to die */
1301
		sleep(2);
1302

    
1303
	}
1304

    
1305
	switch ($pppoecfg['mode']) {
1306

    
1307
		case 'server' :
1308

    
1309
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1310

    
1311
			if ($pppoecfg['paporchap'] == "chap")
1312
				$paporchap = "set link enable chap";
1313
			else
1314
				$paporchap = "set link enable pap";
1315

    
1316
			/* write mpd.conf */
1317
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1318
			if (!$fd) {
1319
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
1320
				return 1;
1321
			}
1322
			$mpdconf = "\n\n";
1323
			$mpdconf .= "poes:\n";
1324

    
1325
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1326
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1327
			}
1328

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

    
1331
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1332

    
1333
				if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
1334
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1335
				} else {
1336
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1337
				}
1338

    
1339
				$mpdconf .=<<<EOD
1340

    
1341
poes{$pppoecfg['pppoeid']}{$i}:
1342
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1343
	{$isssue_ip_type}
1344
	load pppoe_standard
1345

    
1346
EOD;
1347
			}
1348

    
1349
			$mpdconf .=<<<EOD
1350

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

    
1377
EOD;
1378

    
1379
			if (!empty($pppoecfg['dns1'])) {
1380
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1381
				if (!empty($pppoecfg['dns2']))
1382
					$mpdconf .= " " . $pppoecfg['dns2'];
1383
				$mpdconf .= "\n";
1384
			} elseif (isset ($config['dnsmasq']['enable'])) {
1385
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1386
				if ($syscfg['dnsserver'][0])
1387
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1388
				$mpdconf .= "\n";
1389
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1390
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1391
			}
1392

    
1393
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1394
				$radiusport = "";
1395
				$radiusacctport = "";
1396
				if (isset($pppoecfg['radius']['server']['port']))
1397
					$radiusport = $pppoecfg['radius']['server']['port'];
1398
				if (isset($pppoecfg['radius']['server']['acctport']))
1399
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1400
				$mpdconf .=<<<EOD
1401
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
1402
	set radius retries 3
1403
	set radius timeout 10
1404
	set auth enable radius-auth
1405

    
1406
EOD;
1407

    
1408
				if (isset ($pppoecfg['radius']['accounting'])) {
1409
					$mpdconf .=<<<EOD
1410
	set auth enable radius-acct
1411

    
1412
EOD;
1413
				}
1414
			}
1415

    
1416
			fwrite($fd, $mpdconf);
1417
			fclose($fd);
1418
			unset($mpdconf);
1419

    
1420
			/* write mpd.links */
1421
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.links", "w");
1422
			if (!$fd) {
1423
				printf(gettext("Error: cannot open mpd.links in vpn_pppoe_configure().") . "\n");
1424
				return 1;
1425
			}
1426

    
1427
			$mpdlinks = "";
1428

    
1429
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1430
				$mpdlinks .=<<<EOD
1431
			
1432
poes{$pppoecfg['pppoeid']}{$i}:
1433
	set phys type pppoe
1434
        set pppoe iface {$pppoe_interface}
1435
        set pppoe service "*"
1436
        set pppoe disable originate
1437
        set pppoe enable incoming
1438

    
1439
EOD;
1440
			}
1441

    
1442
			fwrite($fd, $mpdlinks);
1443
			fclose($fd);
1444
			unset($mpdlinks);
1445

    
1446
			if ($pppoecfg['username']) {
1447
				/* write mpd.secret */
1448
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1449
				if (!$fd) {
1450
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1451
					return 1;
1452
				}
1453

    
1454
				$mpdsecret = "\n\n";
1455

    
1456
				if (!empty($pppoecfg['username'])) {
1457
					$item = explode(" ", $pppoecfg['username']);
1458
					foreach($item as $userdata) {
1459
						$data = explode(":", $userdata);
1460
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1461
					}
1462
				}
1463

    
1464
				fwrite($fd, $mpdsecret);
1465
				fclose($fd);
1466
				unset($mpdsecret);
1467
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1468
			}
1469

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

    
1474
			/* Get support for netgraph(4) from the nic */
1475
			pfSense_ngctl_attach(".", $pppoe_interface);
1476
			/* fire up mpd */
1477
			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");
1478

    
1479
			break;
1480
	}
1481

    
1482
	if ($g['booting'])
1483
		echo gettext("done") . "\n";
1484

    
1485
	return 0;
1486
}
1487

    
1488
function vpn_l2tp_configure() {
1489
	global $config, $g;
1490

    
1491
	$syscfg = $config['system'];
1492
	$l2tpcfg = $config['l2tp'];
1493

    
1494
	/* create directory if it does not exist */
1495
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1496
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1497

    
1498
	if ($g['booting']) {
1499
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1500
			return 0;
1501

    
1502
		echo gettext("Configuring l2tp VPN service... ");
1503
	} else {
1504
		/* kill mpd */
1505
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1506

    
1507
		/* wait for process to die */
1508
		sleep(8);
1509

    
1510
	}
1511

    
1512
	/* make sure l2tp-vpn directory exists */
1513
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1514
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1515

    
1516
	switch ($l2tpcfg['mode']) {
1517

    
1518
		case 'server' :
1519
			if ($l2tpcfg['paporchap'] == "chap")
1520
				$paporchap = "set link enable chap";
1521
			else
1522
				$paporchap = "set link enable pap";
1523

    
1524
			/* write mpd.conf */
1525
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1526
			if (!$fd) {
1527
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
1528
				return 1;
1529
			}
1530
			$mpdconf = "\n\n";
1531
			$mpdconf .=<<<EOD
1532
l2tps:
1533

    
1534
EOD;
1535

    
1536
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1537
				$mpdconf .= "	load l2tp{$i}\n";
1538
			}
1539

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

    
1542
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1543

    
1544
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1545
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1546
				} else {
1547
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1548
				}
1549

    
1550
				$mpdconf .=<<<EOD
1551

    
1552
l2tp{$i}:
1553
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1554
	{$isssue_ip_type}
1555
	load l2tp_standard
1556

    
1557
EOD;
1558
			}
1559

    
1560
			$mpdconf .=<<<EOD
1561

    
1562
l2tp_standard:
1563
        set bundle disable multilink
1564
        set bundle enable compression
1565
        set bundle yes crypt-reqd
1566
        set ipcp yes vjcomp
1567
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1568
        set ccp yes mppc
1569
        set iface disable on-demand
1570
        set iface enable proxy-arp
1571
	set iface up-script /usr/local/sbin/vpn-linkup
1572
	set iface down-script /usr/local/sbin/vpn-linkdown
1573
        set link yes acfcomp protocomp
1574
        set link no pap chap
1575
        set link enable chap
1576
        set link keep-alive 10 180
1577

    
1578
EOD;
1579

    
1580
			if (is_ipaddr($l2tpcfg['wins'])) {
1581
				$mpdconf .= "	set ipcp nbns {$l2tpcfg['wins']}\n";
1582
			}
1583
			if (is_ipaddr($l2tpcfg['dns1'])) {
1584
				$mpdconf .= "	set ipcp dns " . $l2tpcfg['dns1'];
1585
				if (is_ipaddr($l2tpcfg['dns2']))
1586
					$mpdconf .= " " . $l2tpcfg['dns2'];
1587
				$mpdconf .= "\n";
1588
			} elseif (isset ($config['dnsmasq']['enable'])) {
1589
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1590
				if ($syscfg['dnsserver'][0])
1591
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1592
				$mpdconf .= "\n";
1593
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1594
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1595
			}
1596

    
1597
			if (isset ($l2tpcfg['radius']['enable'])) {
1598
				$mpdconf .=<<<EOD
1599
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1600
	set radius retries 3
1601
	set radius timeout 10
1602
	set auth enable radius-auth
1603

    
1604
EOD;
1605

    
1606
				if (isset ($l2tpcfg['radius']['accounting'])) {
1607
					$mpdconf .=<<<EOD
1608
	set auth enable radius-acct
1609

    
1610
EOD;
1611
				}
1612
			}
1613

    
1614
			fwrite($fd, $mpdconf);
1615
			fclose($fd);
1616
			unset($mpdconf);
1617

    
1618
			/* write mpd.links */
1619
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.links", "w");
1620
			if (!$fd) {
1621
				printf(gettext("Error: cannot open mpd.links in vpn_l2tp_configure().") . "\n");
1622
				return 1;
1623
			}
1624

    
1625
			$mpdlinks = "";
1626

    
1627
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1628
				$mpdlinks .=<<<EOD
1629

    
1630
l2tp{$i}:
1631
	set link type l2tp
1632
        set l2tp enable incoming
1633
        set l2tp disable originate
1634

    
1635
EOD;
1636
			if (!empty($l2tpcfg['secret']))
1637
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1638
			}
1639

    
1640
			fwrite($fd, $mpdlinks);
1641
			fclose($fd);
1642
			unset($mpdlinks);
1643

    
1644
			/* write mpd.secret */
1645
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1646
			if (!$fd) {
1647
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
1648
				return 1;
1649
			}
1650

    
1651
			$mpdsecret = "\n\n";
1652

    
1653
			if (is_array($l2tpcfg['user'])) {
1654
				foreach ($l2tpcfg['user'] as $user)
1655
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1656
			}
1657

    
1658
			fwrite($fd, $mpdsecret);
1659
			fclose($fd);
1660
			unset($mpdsecret);
1661
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1662

    
1663
			vpn_netgraph_support();
1664

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

    
1668
			break;
1669

    
1670
		case 'redir' :
1671
			break;
1672
	}
1673

    
1674
	if ($g['booting'])
1675
		echo "done\n";
1676

    
1677
	return 0;
1678
}
1679

    
1680
/* Walk the tunnels for hostname endpoints. If the hostnames 
1681
 * resolve to a different IP now compared to the DNS cache
1682
 * we reload the policies if the endpoint has changed */
1683
function vpn_ipsec_refresh_policies() {
1684
	global $config;
1685
	global $g;
1686

    
1687
	$ipseccfg = $config['ipsec'];
1688
	$a_phase1 = $config['ipsec']['phase1'];
1689
	$a_phase2 = $config['ipsec']['phase2'];
1690

    
1691
	if (isset($ipseccfg['disable'])) {
1692
		return true;
1693
	}
1694

    
1695
	/* Walk the Ipsec tunnel array */
1696
	if (!is_array($a_phase1) || (!count($a_phase1)))
1697
		return;
1698

    
1699
	foreach ($a_phase1 as $phase1) {
1700
		if (isset($phase1['disabled']))
1701
			continue;
1702
		if (is_ipaddr($phase1['remote-gateway']))
1703
			continue;
1704
		if (!is_ipaddr($phase1['remote-gateway'])) {
1705
			$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1706
			$dnscache = trim($dnscache);
1707
			/* we should have the old IP addresses in the dnscache now */
1708
			if(!empty($dnscache)) {
1709
				$oldphase1 = $phase1;
1710
				$oldphase1['remote-gateway'] = $dnscache;
1711
				/* now we need to find all tunnels for this host */
1712
				if (!is_array($a_phase2) || (!count($a_phase2)))
1713
					continue;
1714
				foreach ($a_phase2 as $phase2) {
1715
					if ($phase2['ikeid'] == $phase1['ikeid'])
1716
						reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1717
				}
1718
			}
1719
		}
1720
	}
1721

    
1722
	/* process all generated temporary spd.conf files */
1723
	$tmpfiles = glob("{$g['tmp_path']}/spd.conf.reload.*");
1724
	foreach($tmpfiles as $tmpfile) {
1725
		$ret = mwexec("/usr/local/sbin/setkey -f {$tmpfile} 2>&1", false);
1726
		if ($ret == 0)
1727
			unlink_if_exists($tmpfile);
1728
		else {
1729
			$tmpfile = basename($tmpfile);
1730
			@rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1731
		}
1732
	}
1733
}
1734

    
1735
/* remove SPD polices */
1736
function remove_tunnel_spd_policy($phase1,$phase2) {
1737
	global $config;
1738
	global $g;
1739

    
1740
	if (!$phase1 || !$phase2)
1741
		return false;
1742

    
1743
	if (isset($phase1['mobile']))
1744
		return false;
1745

    
1746
	$spdconf = "";
1747
	$ep = ipsec_get_phase1_src($phase1);
1748
	$gw = trim($phase1['remote-gateway']);
1749
	$sad_arr = ipsec_dump_sad();
1750
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid'], false, $phase2['mode']);
1751

    
1752
	if (!empty($phase2['natlocalid']))
1753
		$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid'], false, $phase2['mode']);
1754
	else
1755
		$local_subnet = ipsec_idinfo_to_cidr($phase2['localid'], false, $phase2['mode']);
1756

    
1757
	if ($phase2['mode'] == "tunnel6")
1758
		$family = "-6";
1759
	else
1760
		$family = "-4";
1761

    
1762
	$spdconf .= "spddelete {$family} {$local_subnet} " .
1763
		"{$remote_subnet} any -P out ipsec " .
1764
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1765
		"{$gw}/unique;\n";
1766

    
1767
	$spdconf .= "spddelete {$family} {$remote_subnet} " .
1768
		"{$local_subnet} any -P in ipsec " .
1769
		"{$phase2['protocol']}/tunnel/{$gw}-" .
1770
		"{$ep}/unique;\n";
1771

    
1772
	/* zap any existing SA entries */
1773
	foreach($sad_arr as $sad) {
1774
		if(($sad['dst'] == $ep) && ($sad['src'] == $gw))
1775
			$spdconf .= "delete {$family} {$ep} {$gw} {$phase2['protocol']} 0x{$sad['spi']};\n";
1776
		if(($sad['src'] == $ep) && ($sad['dst'] == $_gw))
1777
			$spdconf .= "delete {$family} {$gw} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1778
	}
1779

    
1780
	log_error(sprintf(gettext("Removing SPDs from tunnel gw '%1\$s'. Local Subnet '%2\$s' and Remote Subnet '%3\$s'. Reloading policy"),$phase1['remote-gateway'],$local_subnet,$remote_subnet));
1781

    
1782
	$now = time();
1783
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1784
	/* generate temporary spd.conf */
1785
	@file_put_contents($spdfile, $spdconf);
1786
	unset($spdconf);
1787

    
1788
	return true;
1789
}
1790

    
1791
/* reloads the tunnel configuration for a tunnel item
1792
 * Will remove and add SPD polices */
1793
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1794
	global $config;
1795
	global $g;
1796

    
1797
	/* if we are not passed a old tunnel array we create one */
1798
	if(empty($old_phase1)) {
1799
		$old_phase1 = $phase1;
1800
	}
1801
	if(empty($old_phase2)) {
1802
		$old_phase2 = $phase2;
1803
	}
1804

    
1805
	$sad_arr = ipsec_dump_sad();
1806

    
1807
	$ep = ipsec_get_phase1_src($phase1);
1808
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid'], false, $phase2['mode']);
1809
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid'], false, $phase2['mode']);
1810

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

    
1814
	$old_ep = ipsec_get_phase1_src($old_phase1);
1815
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid'], false, $old_phase2['mode']);
1816
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid'], false, $old_phase2['mode']);
1817

    
1818
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1819
	 * try to resolve it now and add it to the list for filterdns */
1820
	$rgip = "";
1821
	if (!is_ipaddr($phase1['remote-gateway'])) {
1822
		if(! $g['booting']) {
1823
			$rgip = resolve_retry($phase1['remote-gateway']);
1824
			add_hostname_to_watch($phase1['remote-gateway']);
1825
		} else {
1826
			add_hostname_to_watch($phase1['remote-gateway']);
1827
		}
1828
		if (!is_ipaddr($rgip)) {
1829
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1830
			return false;
1831
		}
1832
	} else {
1833
		$rgip = $phase1['remote-gateway'];
1834
	}
1835
	if (!$ep) {
1836
		log_error(sprintf(gettext("Could not determine VPN endpoint for '%s'"), $phase1['descr']));
1837
		return false;
1838
	}
1839

    
1840
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1841
		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));
1842
	}
1843
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1844
		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));
1845
	}
1846

    
1847
	$spdconf = "";
1848
	/* Delete old SPD policies if there are changes between the old and new */
1849
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1850
		if($old_phase2['mode'] == "tunnel6")
1851
			$family = "-6";
1852
		else
1853
			$family = "-4";
1854

    
1855
		$spdconf .= "spddelete {$family} {$old_local_subnet} " .
1856
			"{$old_remote_subnet} any -P out ipsec " .
1857
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1858
			"{$old_gw}/unique;\n";
1859
		if (!empty($old_phase2['natlocalid']))
1860
			$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['natlocalid'], false, $old_phase2['mode']);
1861
		$spdconf .= "spddelete {$family} {$old_remote_subnet} " .
1862
			"{$old_local_subnet} any -P in ipsec " .
1863
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1864
			"{$old_ep}/unique;\n";
1865

    
1866
		/* zap any existing SA entries */
1867
		foreach($sad_arr as $sad) {
1868
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1869
				$spdconf .= "delete {$family} {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1870
			}
1871
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1872
				$spdconf .= "delete {$family} {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1873
			}
1874
		}
1875
	}
1876

    
1877
	if($phase2['mode'] == "tunnel6")
1878
		$family = "-6";
1879
	else
1880
		$family = "-4";
1881

    
1882
	/* Create new SPD entries for the new configuration */
1883
	/* zap any existing SA entries beforehand */
1884
	foreach($sad_arr as $sad) {
1885
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1886
			$spdconf .= "delete {$family} {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1887
		}
1888
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1889
			$spdconf .= "delete {$family} {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1890
		}
1891
	}
1892
	/* add new SPD policies to replace them */
1893
	if (!isset($phase1['disabled'])) {
1894
		$spdconf .= "spdadd {$family} {$local_subnet} " .
1895
			"{$remote_subnet} any -P out ipsec " .
1896
			"{$phase2['protocol']}/tunnel/{$ep}-" .
1897
			"{$rgip}/unique;\n";
1898

    
1899
		if (!empty($phase2['natlocalid']))
1900
			$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid'], false, $phase2['mode']);
1901
		$spdconf .= "spdadd {$family} {$remote_subnet} " .
1902
			"{$local_subnet} any -P in ipsec " .
1903
			"{$phase2['protocol']}/tunnel/{$rgip}-" .
1904
			"{$ep}/unique;\n";
1905
	}
1906

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

    
1909
	$now = time();
1910
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1911
	/* generate temporary spd.conf */
1912
	@file_put_contents($spdfile, $spdconf);
1913
	unset($spdconf);
1914
	return true;
1915
}
1916

    
1917
function vpn_ipsec_configure_preferoldsa() {
1918
	global $config;
1919
	if(isset($config['ipsec']['preferoldsa']))
1920
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1921
	else
1922
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1923
}
1924

    
1925
?>
(57-57/66)