Project

General

Profile

Download (56.4 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
require_once("ipsec.inc");
45

    
46
/* include all configuration functions */
47

    
48
function vpn_ipsec_failover_configure() {
49
	global $config, $g;
50

    
51

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

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

    
75
		if(is_process_running("sasyncd"))
76
			mwexec("killall sasyncd", true);
77

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

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

    
87
	if ($g['platform'] == 'jail')
88
		return;
89

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

    
94
	vpn_ipsec_configure_preferoldsa();
95

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

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

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

    
112
		/* wait for racoon process to die */
113
		sleep(2);
114

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
256
		$pskconf = "";
257

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

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

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

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

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

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

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

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

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

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

    
305
		@file_put_contents("{$g['varetc_path']}/ipsec/psk.txt", $pskconf);
306
		chmod("{$g['varetc_path']}/ipsec/psk.txt", 0600);
307
		unset($pskconf);
308

    
309
		/* begin racoon.conf */
310
		$racoonconf = "";
311
		if ((is_array($a_phase1) && count($a_phase1)) || (is_array($a_phase2) && count($a_phase2))) {
312

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

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

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

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

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

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

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

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

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

    
354
					$net_list = '';
355

    
356
					foreach ($a_phase2 as $ph2ent) {
357

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

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

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

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

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

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

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

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

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

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

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

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

    
412
				$racoonconf .= "}\n\n";
413
			}
414
			/* end mode_cfg section */
415

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

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

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

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

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

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

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

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

    
461
					switch ($myid_type) {
462

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

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

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

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

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

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

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

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

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

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

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

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

    
542
					$certline = '';
543

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

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

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

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

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

    
563
						chmod($certpath, 0600);
564

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

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

    
574
						chmod($keypath, 0600);
575

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

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

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

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

    
593
					}
594

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

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

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

    
612
					/* add remote section to configuration */
613

    
614
					$racoonconf .=<<<EOD
615

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

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

    
644
EOD;
645
				}
646
				/* end remote */
647
			}
648
			/* end remote sections */
649

    
650
			/* begin sainfo sections */
651
			if (is_array($a_phase2) && count($a_phase2)) {
652

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

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

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

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

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

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

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

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

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

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

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

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

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

    
735
						$ealgos = '';
736

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

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

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

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

    
779
					} else {
780

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

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

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

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

    
800
					/* add sainfo section to configuration */
801

    
802
					$racoonconf .=<<<EOD
803

    
804
sainfo {$localid_spec} {$remoteid_spec}
805
{
806
	remoteid {$ikeid};
807
	{$ealgosline}
808
	{$halgosline}
809
	{$pfsline}
810
	{$lifeline}
811
	compression_algorithm deflate;
812
}
813

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

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

    
847
			foreach ($a_phase2 as $ph2ent) {
848

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

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

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

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

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

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

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

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

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

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

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

    
894
				} else {
895

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

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

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

    
905
				}
906

    
907
				/* static route needed? */
908
				$vip = "";
909
				if (is_ipaddr($ph1ent['interface'])) {
910
					$vip = find_virtual_ip_alias($ph1ent['interface']);
911
					$parentinterface = $vip['interface'];
912
				} else
913
					$parentinterface = $ph1ent['interface'];
914

    
915
				if (is_ipaddr($rgip)) {
916
					/* add endpoint routes to correct gateway on interface */
917
					if (interface_has_gateway($parentinterface)) {
918
						$gatewayip = get_interface_gateway("$parentinterface");
919
						if (empty($vip))
920
							$interfaceip = get_interface_ip($parentinterface);
921
						else
922
							$interfaceip = $vip['subnet'];
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
		return count($filterdns_list);
992
	}
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($interface = "") {
1002
	global $g, $config;
1003

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

    
1006
	if (!empty($interface) && is_array($ipseccfg['phase1'])) {
1007
		$found = false;
1008
		foreach ($ipseccfg['phase1'] as $ipsec) {
1009
			if (!isset($ipsec['disabled']) && ($ipsec['interface'] == $interface)) {
1010
				$found = true;
1011
				break;
1012
			}
1013
		}
1014
		if (!$found) {
1015
			log_error(sprintf(gettext("Ignoring IPsec racoon daemon reload since there are no tunnels on interface %s"), $interface));
1016
			return;
1017
		}
1018
	}
1019

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

    
1023
	/* wait for process to die */
1024
	sleep(4);
1025

    
1026
	/* kill racoon forcefully */
1027
	if (is_process_running("racoon"))
1028
		mwexec("/usr/bin/killall -9 racoon", true);
1029

    
1030
	/* wait for flushing to finish */
1031
	sleep(1);
1032

    
1033
	/* if ipsec is enabled, start up again */
1034
	if (isset($ipseccfg['enable'])) {
1035
		log_error(gettext("Forcefully reloading IPsec racoon daemon"));
1036
		vpn_ipsec_configure();
1037
	}
1038
}
1039

    
1040
/* master setup for vpn (mpd) */
1041
function vpn_setup() {
1042
	global $g;
1043

    
1044
	if ($g['platform'] == 'jail')
1045
		return;
1046

    
1047
	/* start pptpd */
1048
	vpn_pptpd_configure();
1049

    
1050
	/* start pppoe server */
1051
	vpn_pppoes_configure();
1052

    
1053
	/* setup l2tp */
1054
	vpn_l2tp_configure();
1055
}
1056

    
1057
function vpn_netgraph_support() {
1058
	$iflist = get_configured_interface_list();
1059
	foreach ($iflist as $iface) {
1060
		$realif = get_real_interface($iface);
1061
		/* Get support for netgraph(4) from the nic */
1062
		$ifinfo = pfSense_get_interface_addresses($realif);
1063
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge")))
1064
			pfSense_ngctl_attach(".", $realif);
1065
	}
1066
}
1067

    
1068
function vpn_pptpd_configure() {
1069
	global $config, $g;
1070

    
1071
	$syscfg = $config['system'];
1072
	$pptpdcfg = $config['pptpd'];
1073

    
1074
	if ($g['booting']) {
1075
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
1076
			return 0;
1077

    
1078
		echo gettext("Configuring PPTP VPN service... ");
1079
	} else {
1080
		/* kill mpd */
1081
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1082

    
1083
		/* wait for process to die */
1084
		sleep(3);
1085

    
1086
		if (is_process_running("mpd -b")) {
1087
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1088
			log_error(gettext("Could not kill mpd within 3 seconds.   Trying again."));
1089
		}
1090

    
1091
		/* remove mpd.conf, if it exists */
1092
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
1093
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
1094
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
1095
	}
1096

    
1097
	if (empty($pptpdcfg['n_pptp_units'])) {
1098
		log_error("Something wrong in the PPTPd configuration. Preventing starting the daemon because issues would arise.");
1099
		return;
1100
	}
1101

    
1102
	/* make sure pptp-vpn directory exists */
1103
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
1104
		mkdir("{$g['varetc_path']}/pptp-vpn");
1105

    
1106
	switch ($pptpdcfg['mode']) {
1107
		case 'server' :
1108
			/* write mpd.conf */
1109
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
1110
			if (!$fd) {
1111
				printf(gettext("Error: cannot open mpd.conf in vpn_pptpd_configure().") . "\n");
1112
				return 1;
1113
			}
1114

    
1115
			$mpdconf = <<<EOD
1116
pptps:
1117

    
1118
EOD;
1119

    
1120
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1121
				$mpdconf .= "	load pt{$i}\n";
1122
			}
1123

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

    
1126
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1127

    
1128
				$mpdconf .= <<<EOD
1129

    
1130
pt{$i}:
1131
	new -i pptpd{$i} pt{$i} pt{$i}
1132
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1133
	load pts
1134

    
1135
EOD;
1136
			}
1137

    
1138
			$mpdconf .=<<<EOD
1139

    
1140
pts:
1141
	set iface disable on-demand
1142
	set iface enable proxy-arp
1143
	set iface enable tcpmssfix
1144
	set iface idle 1800
1145
	set iface up-script /usr/local/sbin/vpn-linkup
1146
	set iface down-script /usr/local/sbin/vpn-linkdown
1147
	set bundle enable multilink
1148
	set bundle enable crypt-reqd
1149
	set link yes acfcomp protocomp
1150
	set link no pap chap
1151
	set link enable chap-msv2
1152
	set link mtu 1460
1153
	set link keep-alive 10 60
1154
	set ipcp yes vjcomp
1155
	set bundle enable compression
1156
	set ccp yes mppc
1157
	set ccp yes mpp-e128
1158
	set ccp yes mpp-stateless
1159

    
1160
EOD;
1161

    
1162
			if (!isset ($pptpdcfg['req128'])) {
1163
				$mpdconf .=<<<EOD
1164
	set ccp yes mpp-e40
1165
	set ccp yes mpp-e56
1166

    
1167
EOD;
1168
			}
1169

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

    
1173
			if (!empty($pptpdcfg['dns1'])) {
1174
				$mpdconf .= "	set ipcp dns " . $pptpdcfg['dns1'];
1175
				if (!empty($pptpdcfg['dns2']))
1176
					$mpdconf .= " " . $pptpdcfg['dns2'];
1177
				$mpdconf .= "\n";
1178
			} elseif (isset ($config['dnsmasq']['enable'])) {
1179
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1180
				if ($syscfg['dnsserver'][0])
1181
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1182
				$mpdconf .= "\n";
1183
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1184
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1185
			}
1186

    
1187
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1188
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1189
				$acctport = $authport + 1;
1190
				$mpdconf .=<<<EOD
1191
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1192

    
1193
EOD;
1194
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1195
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1196
				$acctport = $authport + 1;
1197
				$mpdconf .=<<<EOD
1198
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret2']}" {$authport} {$acctport}
1199

    
1200
EOD;
1201
			}
1202
			$mpdconf .=<<<EOD
1203
	set radius retries 3
1204
	set radius timeout 10
1205
	set auth enable radius-auth
1206

    
1207
EOD;
1208

    
1209
				if (isset ($pptpdcfg['radius']['accounting'])) {
1210
					$mpdconf .=<<<EOD
1211
	set auth enable radius-acct
1212
	set radius acct-update 300
1213

    
1214
EOD;
1215
				}
1216
			}
1217

    
1218
			fwrite($fd, $mpdconf);
1219
			fclose($fd);
1220
			unset($mpdconf);
1221

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

    
1229
			$mpdlinks = "";
1230

    
1231
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1232
				$mpdlinks .=<<<EOD
1233

    
1234
pt{$i}:
1235
	set link type pptp
1236
	set pptp enable incoming
1237
	set pptp disable originate
1238
	set pptp disable windowing
1239

    
1240
EOD;
1241
			}
1242

    
1243
			fwrite($fd, $mpdlinks);
1244
			fclose($fd);
1245
			unset($mpdlinks);
1246

    
1247
			/* write mpd.secret */
1248
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1249
			if (!$fd) {
1250
				printf(gettext("Error: cannot open mpd.secret in vpn_pptpd_configure().") . "\n");
1251
				return 1;
1252
			}
1253

    
1254
			$mpdsecret = "";
1255

    
1256
			if (is_array($pptpdcfg['user'])) {
1257
				foreach ($pptpdcfg['user'] as $user) {
1258
					$pass = str_replace('\\', '\\\\', $user['password']);
1259
					$pass = str_replace('"', '\"', $pass);
1260
					$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
1261
				}
1262
			}
1263

    
1264
			fwrite($fd, $mpdsecret);
1265
			fclose($fd);
1266
			unset($mpdsecret);
1267
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1268

    
1269
			vpn_netgraph_support();
1270

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

    
1274
			break;
1275

    
1276
		case 'redir' :
1277
			break;
1278
	}
1279

    
1280
	if ($g['booting'])
1281
		echo "done\n";
1282

    
1283
	return 0;
1284
}
1285

    
1286
function vpn_pppoes_configure() {
1287
	global $config;
1288

    
1289
	if (is_array($config['pppoes']['pppoe'])) {
1290
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1291
			vpn_pppoe_configure($pppoe);
1292
	}
1293
}
1294

    
1295
function vpn_pppoe_configure(&$pppoecfg) {
1296
	global $config, $g;
1297

    
1298
	$syscfg = $config['system'];
1299

    
1300
	/* create directory if it does not exist */
1301
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1302
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1303

    
1304
	if ($g['booting']) {
1305
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1306
			return 0;
1307

    
1308
		echo gettext("Configuring PPPoE VPN service... ");
1309
	} else {
1310
		/* kill mpd */
1311
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1312

    
1313
		/* wait for process to die */
1314
		sleep(2);
1315

    
1316
	}
1317

    
1318
	switch ($pppoecfg['mode']) {
1319

    
1320
		case 'server' :
1321

    
1322
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1323

    
1324
			if ($pppoecfg['paporchap'] == "chap")
1325
				$paporchap = "set link enable chap";
1326
			else
1327
				$paporchap = "set link enable pap";
1328

    
1329
			/* write mpd.conf */
1330
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1331
			if (!$fd) {
1332
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
1333
				return 1;
1334
			}
1335
			$mpdconf = "\n\n";
1336
			$mpdconf .= "poes:\n";
1337

    
1338
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1339
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1340
			}
1341

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

    
1344
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1345

    
1346
				if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
1347
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1348
				} else {
1349
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1350
				}
1351

    
1352
				$mpdconf .=<<<EOD
1353

    
1354
poes{$pppoecfg['pppoeid']}{$i}:
1355
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1356
	{$isssue_ip_type}
1357
	load pppoe_standard
1358

    
1359
EOD;
1360
			}
1361

    
1362
			$mpdconf .=<<<EOD
1363

    
1364
pppoe_standard:
1365
	set bundle no multilink
1366
	set bundle enable compression
1367
	set auth max-logins 1
1368
	set iface up-script /usr/local/sbin/vpn-linkup
1369
	set iface down-script /usr/local/sbin/vpn-linkdown
1370
	set iface idle 0
1371
	set iface disable on-demand
1372
	set iface disable proxy-arp
1373
	set iface enable tcpmssfix
1374
	set iface mtu 1500
1375
	set link no pap chap
1376
	{$paporchap}
1377
	set link keep-alive 60 180
1378
	set ipcp yes vjcomp
1379
	set ipcp no vjcomp
1380
	set link max-redial -1
1381
	set link mtu 1492
1382
	set link mru 1492
1383
	set ccp yes mpp-e40
1384
	set ccp yes mpp-e128
1385
	set ccp yes mpp-stateless
1386
	set link latency 1
1387
	#set ipcp dns 10.10.1.3
1388
	#set bundle accept encryption
1389

    
1390
EOD;
1391

    
1392
			if (!empty($pppoecfg['dns1'])) {
1393
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1394
				if (!empty($pppoecfg['dns2']))
1395
					$mpdconf .= " " . $pppoecfg['dns2'];
1396
				$mpdconf .= "\n";
1397
			} elseif (isset ($config['dnsmasq']['enable'])) {
1398
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1399
				if ($syscfg['dnsserver'][0])
1400
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1401
				$mpdconf .= "\n";
1402
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1403
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1404
			}
1405

    
1406
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1407
				$radiusport = "";
1408
				$radiusacctport = "";
1409
				if (isset($pppoecfg['radius']['server']['port']))
1410
					$radiusport = $pppoecfg['radius']['server']['port'];
1411
				if (isset($pppoecfg['radius']['server']['acctport']))
1412
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1413
				$mpdconf .=<<<EOD
1414
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
1415
	set radius retries 3
1416
	set radius timeout 10
1417
	set auth enable radius-auth
1418

    
1419
EOD;
1420

    
1421
				if (isset ($pppoecfg['radius']['accounting'])) {
1422
					$mpdconf .=<<<EOD
1423
	set auth enable radius-acct
1424

    
1425
EOD;
1426
				}
1427
			}
1428

    
1429
			fwrite($fd, $mpdconf);
1430
			fclose($fd);
1431
			unset($mpdconf);
1432

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

    
1440
			$mpdlinks = "";
1441

    
1442
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1443
				$mpdlinks .=<<<EOD
1444

    
1445
poes{$pppoecfg['pppoeid']}{$i}:
1446
	set phys type pppoe
1447
	set pppoe iface {$pppoe_interface}
1448
	set pppoe service "*"
1449
	set pppoe disable originate
1450
	set pppoe enable incoming
1451

    
1452
EOD;
1453
			}
1454

    
1455
			fwrite($fd, $mpdlinks);
1456
			fclose($fd);
1457
			unset($mpdlinks);
1458

    
1459
			if ($pppoecfg['username']) {
1460
				/* write mpd.secret */
1461
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1462
				if (!$fd) {
1463
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1464
					return 1;
1465
				}
1466

    
1467
				$mpdsecret = "\n\n";
1468

    
1469
				if (!empty($pppoecfg['username'])) {
1470
					$item = explode(" ", $pppoecfg['username']);
1471
					foreach($item as $userdata) {
1472
						$data = explode(":", $userdata);
1473
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1474
					}
1475
				}
1476

    
1477
				fwrite($fd, $mpdsecret);
1478
				fclose($fd);
1479
				unset($mpdsecret);
1480
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1481
			}
1482

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

    
1487
			/* Get support for netgraph(4) from the nic */
1488
			pfSense_ngctl_attach(".", $pppoe_interface);
1489
			/* fire up mpd */
1490
			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");
1491

    
1492
			break;
1493
	}
1494

    
1495
	if ($g['booting'])
1496
		echo gettext("done") . "\n";
1497

    
1498
	return 0;
1499
}
1500

    
1501
function vpn_l2tp_configure() {
1502
	global $config, $g;
1503

    
1504
	$syscfg = $config['system'];
1505
	$l2tpcfg = $config['l2tp'];
1506

    
1507
	/* create directory if it does not exist */
1508
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1509
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1510

    
1511
	if ($g['booting']) {
1512
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1513
			return 0;
1514

    
1515
		echo gettext("Configuring l2tp VPN service... ");
1516
	} else {
1517
		/* kill mpd */
1518
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1519

    
1520
		/* wait for process to die */
1521
		sleep(8);
1522

    
1523
	}
1524

    
1525
	/* make sure l2tp-vpn directory exists */
1526
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1527
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1528

    
1529
	switch ($l2tpcfg['mode']) {
1530

    
1531
		case 'server' :
1532
			if ($l2tpcfg['paporchap'] == "chap")
1533
				$paporchap = "set link enable chap";
1534
			else
1535
				$paporchap = "set link enable pap";
1536

    
1537
			/* write mpd.conf */
1538
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1539
			if (!$fd) {
1540
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
1541
				return 1;
1542
			}
1543
			$mpdconf = "\n\n";
1544
			$mpdconf .=<<<EOD
1545
l2tps:
1546

    
1547
EOD;
1548

    
1549
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1550
				$mpdconf .= "	load l2tp{$i}\n";
1551
			}
1552

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

    
1555
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1556

    
1557
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1558
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1559
				} else {
1560
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1561
				}
1562

    
1563
				$mpdconf .=<<<EOD
1564

    
1565
l2tp{$i}:
1566
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1567
	{$isssue_ip_type}
1568
	load l2tp_standard
1569

    
1570
EOD;
1571
			}
1572

    
1573
			$mpdconf .=<<<EOD
1574

    
1575
l2tp_standard:
1576
	set bundle disable multilink
1577
	set bundle enable compression
1578
	set bundle yes crypt-reqd
1579
	set ipcp yes vjcomp
1580
	# set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1581
	set ccp yes mppc
1582
	set iface disable on-demand
1583
	set iface enable proxy-arp
1584
	set iface up-script /usr/local/sbin/vpn-linkup
1585
	set iface down-script /usr/local/sbin/vpn-linkdown
1586
	set link yes acfcomp protocomp
1587
	set link no pap chap
1588
	set link enable chap
1589
	set link keep-alive 10 180
1590

    
1591
EOD;
1592

    
1593
			if (is_ipaddr($l2tpcfg['wins'])) {
1594
				$mpdconf .= "	set ipcp nbns {$l2tpcfg['wins']}\n";
1595
			}
1596
			if (is_ipaddr($l2tpcfg['dns1'])) {
1597
				$mpdconf .= "	set ipcp dns " . $l2tpcfg['dns1'];
1598
				if (is_ipaddr($l2tpcfg['dns2']))
1599
					$mpdconf .= " " . $l2tpcfg['dns2'];
1600
				$mpdconf .= "\n";
1601
			} elseif (isset ($config['dnsmasq']['enable'])) {
1602
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1603
				if ($syscfg['dnsserver'][0])
1604
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1605
				$mpdconf .= "\n";
1606
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1607
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1608
			}
1609

    
1610
			if (isset ($l2tpcfg['radius']['enable'])) {
1611
				$mpdconf .=<<<EOD
1612
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1613
	set radius retries 3
1614
	set radius timeout 10
1615
	set auth enable radius-auth
1616

    
1617
EOD;
1618

    
1619
				if (isset ($l2tpcfg['radius']['accounting'])) {
1620
					$mpdconf .=<<<EOD
1621
	set auth enable radius-acct
1622

    
1623
EOD;
1624
				}
1625
			}
1626

    
1627
			fwrite($fd, $mpdconf);
1628
			fclose($fd);
1629
			unset($mpdconf);
1630

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

    
1638
			$mpdlinks = "";
1639

    
1640
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1641
				$mpdlinks .=<<<EOD
1642

    
1643
l2tp{$i}:
1644
	set link type l2tp
1645
	set l2tp enable incoming
1646
	set l2tp disable originate
1647

    
1648
EOD;
1649
			if (!empty($l2tpcfg['secret']))
1650
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1651
			}
1652

    
1653
			fwrite($fd, $mpdlinks);
1654
			fclose($fd);
1655
			unset($mpdlinks);
1656

    
1657
			/* write mpd.secret */
1658
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1659
			if (!$fd) {
1660
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
1661
				return 1;
1662
			}
1663

    
1664
			$mpdsecret = "\n\n";
1665

    
1666
			if (is_array($l2tpcfg['user'])) {
1667
				foreach ($l2tpcfg['user'] as $user)
1668
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1669
			}
1670

    
1671
			fwrite($fd, $mpdsecret);
1672
			fclose($fd);
1673
			unset($mpdsecret);
1674
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1675

    
1676
			vpn_netgraph_support();
1677

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

    
1681
			break;
1682

    
1683
		case 'redir' :
1684
			break;
1685
	}
1686

    
1687
	if ($g['booting'])
1688
		echo "done\n";
1689

    
1690
	return 0;
1691
}
1692

    
1693
/* Walk the tunnels for hostname endpoints. If the hostnames
1694
 * resolve to a different IP now compared to the DNS cache
1695
 * we reload the policies if the endpoint has changed */
1696
function vpn_ipsec_refresh_policies() {
1697
	global $config;
1698
	global $g;
1699

    
1700
	$ipseccfg = $config['ipsec'];
1701
	$a_phase1 = $config['ipsec']['phase1'];
1702
	$a_phase2 = $config['ipsec']['phase2'];
1703

    
1704
	if (isset($ipseccfg['disable'])) {
1705
		return true;
1706
	}
1707

    
1708
	/* Walk the Ipsec tunnel array */
1709
	if (!is_array($a_phase1) || (!count($a_phase1)))
1710
		return;
1711

    
1712
	foreach ($a_phase1 as $phase1) {
1713
		if (isset($phase1['disabled']))
1714
			continue;
1715
		if (is_ipaddr($phase1['remote-gateway']))
1716
			continue;
1717
		$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1718
		$dnscache = trim($dnscache);
1719
		/* we should have the old IP addresses in the dnscache now */
1720
		if(!empty($dnscache)) {
1721
			$oldphase1 = $phase1;
1722
			$oldphase1['remote-gateway'] = $dnscache;
1723
			/* now we need to find all tunnels for this host */
1724
			if (!is_array($a_phase2) || (!count($a_phase2)))
1725
				continue;
1726
			foreach ($a_phase2 as $phase2) {
1727
				if ($phase2['ikeid'] == $phase1['ikeid'])
1728
					reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1729
			}
1730
		}
1731
	}
1732

    
1733
	/* process all generated temporary spd.conf files */
1734
	$tmpfiles = glob("{$g['tmp_path']}/spd.conf.reload.*");
1735
	foreach($tmpfiles as $tmpfile) {
1736
		$ret = mwexec("/usr/local/sbin/setkey -f {$tmpfile} 2>&1", false);
1737
		if ($ret == 0)
1738
			unlink_if_exists($tmpfile);
1739
		else {
1740
			$tmpfile = basename($tmpfile);
1741
			@rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1742
		}
1743
	}
1744
}
1745

    
1746
/* remove SPD polices */
1747
function remove_tunnel_spd_policy($phase1,$phase2) {
1748
	global $config;
1749
	global $g;
1750

    
1751
	if (!$phase1 || !$phase2)
1752
		return false;
1753

    
1754
	if (isset($phase1['mobile']))
1755
		return false;
1756

    
1757
	$spdconf = "";
1758
	$ep = ipsec_get_phase1_src($phase1);
1759
	$gw = trim($phase1['remote-gateway']);
1760
	$sad_arr = ipsec_dump_sad();
1761
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid'], false, $phase2['mode']);
1762

    
1763
	if (!empty($phase2['natlocalid']))
1764
		$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid'], false, $phase2['mode']);
1765
	else
1766
		$local_subnet = ipsec_idinfo_to_cidr($phase2['localid'], false, $phase2['mode']);
1767

    
1768
	if ($phase2['mode'] == "tunnel6")
1769
		$family = "-6";
1770
	else
1771
		$family = "-4";
1772

    
1773
	$spdconf .= "spddelete {$family} {$local_subnet} " .
1774
		"{$remote_subnet} any -P out ipsec " .
1775
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1776
		"{$gw}/unique;\n";
1777

    
1778
	$spdconf .= "spddelete {$family} {$remote_subnet} " .
1779
		"{$local_subnet} any -P in ipsec " .
1780
		"{$phase2['protocol']}/tunnel/{$gw}-" .
1781
		"{$ep}/unique;\n";
1782

    
1783
	/* zap any existing SA entries */
1784
	foreach($sad_arr as $sad) {
1785
		if(($sad['dst'] == $ep) && ($sad['src'] == $gw))
1786
			$spdconf .= "delete {$family} {$ep} {$gw} {$phase2['protocol']} 0x{$sad['spi']};\n";
1787
		if(($sad['src'] == $ep) && ($sad['dst'] == $_gw))
1788
			$spdconf .= "delete {$family} {$gw} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1789
	}
1790

    
1791
	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));
1792

    
1793
	$now = time();
1794
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1795
	/* generate temporary spd.conf */
1796
	@file_put_contents($spdfile, $spdconf);
1797
	unset($spdconf);
1798

    
1799
	return true;
1800
}
1801

    
1802
/* reloads the tunnel configuration for a tunnel item
1803
 * Will remove and add SPD polices */
1804
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1805
	global $config;
1806
	global $g;
1807

    
1808
	/* if we are not passed a old tunnel array we create one */
1809
	if(empty($old_phase1)) {
1810
		$old_phase1 = $phase1;
1811
	}
1812
	if(empty($old_phase2)) {
1813
		$old_phase2 = $phase2;
1814
	}
1815

    
1816
	$sad_arr = ipsec_dump_sad();
1817

    
1818
	$ep = ipsec_get_phase1_src($phase1);
1819
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid'], false, $phase2['mode']);
1820
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid'], false, $phase2['mode']);
1821

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

    
1825
	$old_ep = ipsec_get_phase1_src($old_phase1);
1826
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid'], false, $old_phase2['mode']);
1827
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid'], false, $old_phase2['mode']);
1828

    
1829
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1830
	 * try to resolve it now and add it to the list for filterdns */
1831
	$rgip = "";
1832
	if (!is_ipaddr($phase1['remote-gateway'])) {
1833
		if(! $g['booting']) {
1834
			$rgip = resolve_retry($phase1['remote-gateway']);
1835
			add_hostname_to_watch($phase1['remote-gateway']);
1836
		} else {
1837
			add_hostname_to_watch($phase1['remote-gateway']);
1838
		}
1839
		if (isset($phase1['mobile'])) {
1840
			/* Don't log anything here, it's normal and we should skip it. */
1841
			return false;
1842
		} elseif (!is_ipaddr($rgip)) {
1843
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1844
			return false;
1845
		}
1846
	} else {
1847
		$rgip = $phase1['remote-gateway'];
1848
	}
1849
	if (!$ep) {
1850
		log_error(sprintf(gettext("Could not determine VPN endpoint for '%s'"), $phase1['descr']));
1851
		return false;
1852
	}
1853

    
1854
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1855
		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));
1856
	}
1857
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1858
		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));
1859
	}
1860

    
1861
	$spdconf = "";
1862
	/* Delete old SPD policies if there are changes between the old and new */
1863
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1864
		if($old_phase2['mode'] == "tunnel6")
1865
			$family = "-6";
1866
		else
1867
			$family = "-4";
1868

    
1869
		$spdconf .= "spddelete {$family} {$old_local_subnet} " .
1870
			"{$old_remote_subnet} any -P out ipsec " .
1871
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1872
			"{$old_gw}/unique;\n";
1873
		if (!empty($old_phase2['natlocalid']))
1874
			$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['natlocalid'], false, $old_phase2['mode']);
1875
		$spdconf .= "spddelete {$family} {$old_remote_subnet} " .
1876
			"{$old_local_subnet} any -P in ipsec " .
1877
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1878
			"{$old_ep}/unique;\n";
1879

    
1880
		/* zap any existing SA entries */
1881
		foreach($sad_arr as $sad) {
1882
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1883
				$spdconf .= "delete {$family} {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1884
			}
1885
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1886
				$spdconf .= "delete {$family} {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1887
			}
1888
		}
1889
	}
1890

    
1891
	if($phase2['mode'] == "tunnel6")
1892
		$family = "-6";
1893
	else
1894
		$family = "-4";
1895

    
1896
	/* Create new SPD entries for the new configuration */
1897
	/* zap any existing SA entries beforehand */
1898
	foreach($sad_arr as $sad) {
1899
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1900
			$spdconf .= "delete {$family} {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1901
		}
1902
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1903
			$spdconf .= "delete {$family} {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1904
		}
1905
	}
1906
	/* add new SPD policies to replace them */
1907
	if (!isset($phase1['disabled']) && !isset($phase2['disabled'])) {
1908
		$spdconf .= "spdadd {$family} {$local_subnet} " .
1909
			"{$remote_subnet} any -P out ipsec " .
1910
			"{$phase2['protocol']}/tunnel/{$ep}-" .
1911
			"{$rgip}/unique;\n";
1912

    
1913
		if (!empty($phase2['natlocalid']))
1914
			$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid'], false, $phase2['mode']);
1915
		$spdconf .= "spdadd {$family} {$remote_subnet} " .
1916
			"{$local_subnet} any -P in ipsec " .
1917
			"{$phase2['protocol']}/tunnel/{$rgip}-" .
1918
			"{$ep}/unique;\n";
1919
	}
1920

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

    
1923
	$now = time();
1924
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1925
	/* generate temporary spd.conf */
1926
	@file_put_contents($spdfile, $spdconf);
1927
	unset($spdconf);
1928
	/* remove static route to old gw */
1929
	if (is_ipaddr($old_gw))
1930
		mwexec("/sbin/route delete {$old_gw}", true);
1931
	return true;
1932
}
1933

    
1934
function vpn_ipsec_configure_preferoldsa() {
1935
	global $config;
1936
	if(isset($config['ipsec']['preferoldsa']))
1937
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1938
	else
1939
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1940
}
1941

    
1942
?>
(57-57/66)