Project

General

Profile

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

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

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

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

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

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

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

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

    
44
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
				if (is_ipaddr($ph1ent['interface'])) {
909
					$vip = find_virtual_ip_alias($ph1ent['interface']);
910
					$parentinterface = $vip['interface'];
911
				} else
912
					$parentinterface = $ph1ent['interface'];
913

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

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

    
956
		}
957
		if ($natfilterrules == true)
958
			filter_configure();
959
		/* start filterdns, if necessary */
960
		if (count($filterdns_list) > 0) {
961
			$interval = 60;
962
			if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval']))
963
				$interval = $ipseccfg['dns-interval'];
964

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

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

    
982
		vpn_ipsec_failover_configure();
983

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

    
987
		return count($filterdns_list);
988
	}
989
}
990

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

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

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

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

    
1019
	/* wait for process to die */
1020
	sleep(4);
1021

    
1022
	/* kill racoon forcefully */
1023
	if (is_process_running("racoon"))
1024
		mwexec("/usr/bin/killall -9 racoon", true);
1025

    
1026
	/* wait for flushing to finish */
1027
	sleep(1);
1028

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

    
1036
/* master setup for vpn (mpd) */
1037
function vpn_setup() {
1038
	global $g;
1039

    
1040
	if ($g['platform'] == 'jail')
1041
		return;
1042

    
1043
	/* start pptpd */
1044
	vpn_pptpd_configure();
1045

    
1046
	/* start pppoe server */
1047
	vpn_pppoes_configure();
1048

    
1049
	/* setup l2tp */
1050
	vpn_l2tp_configure();
1051
}
1052

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

    
1064
function vpn_pptpd_configure() {
1065
	global $config, $g;
1066

    
1067
	$syscfg = $config['system'];
1068
	$pptpdcfg = $config['pptpd'];
1069

    
1070
	if ($g['booting']) {
1071
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
1072
			return 0;
1073

    
1074
		echo gettext("Configuring PPTP VPN service... ");
1075
	} else {
1076
		/* kill mpd */
1077
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1078

    
1079
		/* wait for process to die */
1080
		sleep(3);
1081

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

    
1087
		/* remove mpd.conf, if it exists */
1088
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
1089
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
1090
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
1091
	}
1092

    
1093
	if (empty($pptpdcfg['n_pptp_units'])) {
1094
		log_error("Something wrong in the PPTPd configuration. Preventing starting the daemon because issues would arise.");
1095
		return;
1096
	}
1097

    
1098
	/* make sure pptp-vpn directory exists */
1099
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
1100
		mkdir("{$g['varetc_path']}/pptp-vpn");
1101

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

    
1111
			$mpdconf = <<<EOD
1112
pptps:
1113

    
1114
EOD;
1115

    
1116
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1117
				$mpdconf .= "	load pt{$i}\n";
1118
			}
1119

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

    
1122
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1123

    
1124
				$mpdconf .= <<<EOD
1125

    
1126
pt{$i}:
1127
	new -i pptpd{$i} pt{$i} pt{$i}
1128
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1129
	load pts
1130

    
1131
EOD;
1132
			}
1133

    
1134
			$mpdconf .=<<<EOD
1135

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

    
1156
EOD;
1157

    
1158
			if (!isset ($pptpdcfg['req128'])) {
1159
				$mpdconf .=<<<EOD
1160
	set ccp yes mpp-e40
1161
	set ccp yes mpp-e56
1162

    
1163
EOD;
1164
			}
1165

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

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

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

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

    
1196
EOD;
1197
			}
1198
			$mpdconf .=<<<EOD
1199
	set radius retries 3
1200
	set radius timeout 10
1201
	set auth enable radius-auth
1202

    
1203
EOD;
1204

    
1205
				if (isset ($pptpdcfg['radius']['accounting'])) {
1206
					$mpdconf .=<<<EOD
1207
	set auth enable radius-acct
1208
	set radius acct-update 300
1209

    
1210
EOD;
1211
				}
1212
			}
1213

    
1214
			fwrite($fd, $mpdconf);
1215
			fclose($fd);
1216
			unset($mpdconf);
1217

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

    
1225
			$mpdlinks = "";
1226

    
1227
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1228
				$mpdlinks .=<<<EOD
1229

    
1230
pt{$i}:
1231
	set link type pptp
1232
	set pptp enable incoming
1233
	set pptp disable originate
1234
	set pptp disable windowing
1235

    
1236
EOD;
1237
			}
1238

    
1239
			fwrite($fd, $mpdlinks);
1240
			fclose($fd);
1241
			unset($mpdlinks);
1242

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

    
1250
			$mpdsecret = "";
1251

    
1252
			if (is_array($pptpdcfg['user'])) {
1253
				foreach ($pptpdcfg['user'] as $user) {
1254
					$pass = str_replace('\\', '\\\\', $user['password']);
1255
					$pass = str_replace('"', '\"', $pass);
1256
					$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
1257
				}
1258
			}
1259

    
1260
			fwrite($fd, $mpdsecret);
1261
			fclose($fd);
1262
			unset($mpdsecret);
1263
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1264

    
1265
			vpn_netgraph_support();
1266

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

    
1270
			break;
1271

    
1272
		case 'redir' :
1273
			break;
1274
	}
1275

    
1276
	if ($g['booting'])
1277
		echo "done\n";
1278

    
1279
	return 0;
1280
}
1281

    
1282
function vpn_pppoes_configure() {
1283
	global $config;
1284

    
1285
	if (is_array($config['pppoes']['pppoe'])) {
1286
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1287
			vpn_pppoe_configure($pppoe);
1288
	}
1289
}
1290

    
1291
function vpn_pppoe_configure(&$pppoecfg) {
1292
	global $config, $g;
1293

    
1294
	$syscfg = $config['system'];
1295

    
1296
	/* create directory if it does not exist */
1297
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1298
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1299

    
1300
	if ($g['booting']) {
1301
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1302
			return 0;
1303

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

    
1309
		/* wait for process to die */
1310
		sleep(2);
1311

    
1312
	}
1313

    
1314
	switch ($pppoecfg['mode']) {
1315

    
1316
		case 'server' :
1317

    
1318
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1319

    
1320
			if ($pppoecfg['paporchap'] == "chap")
1321
				$paporchap = "set link enable chap";
1322
			else
1323
				$paporchap = "set link enable pap";
1324

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

    
1334
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1335
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1336
			}
1337

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

    
1340
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1341

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

    
1348
				$mpdconf .=<<<EOD
1349

    
1350
poes{$pppoecfg['pppoeid']}{$i}:
1351
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1352
	{$isssue_ip_type}
1353
	load pppoe_standard
1354

    
1355
EOD;
1356
			}
1357

    
1358
			$mpdconf .=<<<EOD
1359

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

    
1386
EOD;
1387

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

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

    
1415
EOD;
1416

    
1417
				if (isset ($pppoecfg['radius']['accounting'])) {
1418
					$mpdconf .=<<<EOD
1419
	set auth enable radius-acct
1420

    
1421
EOD;
1422
				}
1423
			}
1424

    
1425
			fwrite($fd, $mpdconf);
1426
			fclose($fd);
1427
			unset($mpdconf);
1428

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

    
1436
			$mpdlinks = "";
1437

    
1438
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1439
				$mpdlinks .=<<<EOD
1440

    
1441
poes{$pppoecfg['pppoeid']}{$i}:
1442
	set phys type pppoe
1443
	set pppoe iface {$pppoe_interface}
1444
	set pppoe service "*"
1445
	set pppoe disable originate
1446
	set pppoe enable incoming
1447

    
1448
EOD;
1449
			}
1450

    
1451
			fwrite($fd, $mpdlinks);
1452
			fclose($fd);
1453
			unset($mpdlinks);
1454

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

    
1463
				$mpdsecret = "\n\n";
1464

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

    
1473
				fwrite($fd, $mpdsecret);
1474
				fclose($fd);
1475
				unset($mpdsecret);
1476
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1477
			}
1478

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

    
1483
			/* Get support for netgraph(4) from the nic */
1484
			pfSense_ngctl_attach(".", $pppoe_interface);
1485
			/* fire up mpd */
1486
			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");
1487

    
1488
			break;
1489
	}
1490

    
1491
	if ($g['booting'])
1492
		echo gettext("done") . "\n";
1493

    
1494
	return 0;
1495
}
1496

    
1497
function vpn_l2tp_configure() {
1498
	global $config, $g;
1499

    
1500
	$syscfg = $config['system'];
1501
	$l2tpcfg = $config['l2tp'];
1502

    
1503
	/* create directory if it does not exist */
1504
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1505
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1506

    
1507
	if ($g['booting']) {
1508
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1509
			return 0;
1510

    
1511
		echo gettext("Configuring l2tp VPN service... ");
1512
	} else {
1513
		/* kill mpd */
1514
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1515

    
1516
		/* wait for process to die */
1517
		sleep(8);
1518

    
1519
	}
1520

    
1521
	/* make sure l2tp-vpn directory exists */
1522
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1523
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1524

    
1525
	switch ($l2tpcfg['mode']) {
1526

    
1527
		case 'server' :
1528
			if ($l2tpcfg['paporchap'] == "chap")
1529
				$paporchap = "set link enable chap";
1530
			else
1531
				$paporchap = "set link enable pap";
1532

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

    
1543
EOD;
1544

    
1545
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1546
				$mpdconf .= "	load l2tp{$i}\n";
1547
			}
1548

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

    
1551
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1552

    
1553
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1554
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1555
				} else {
1556
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1557
				}
1558

    
1559
				$mpdconf .=<<<EOD
1560

    
1561
l2tp{$i}:
1562
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1563
	{$isssue_ip_type}
1564
	load l2tp_standard
1565

    
1566
EOD;
1567
			}
1568

    
1569
			$mpdconf .=<<<EOD
1570

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

    
1587
EOD;
1588

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

    
1606
			if (isset ($l2tpcfg['radius']['enable'])) {
1607
				$mpdconf .=<<<EOD
1608
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1609
	set radius retries 3
1610
	set radius timeout 10
1611
	set auth enable radius-auth
1612

    
1613
EOD;
1614

    
1615
				if (isset ($l2tpcfg['radius']['accounting'])) {
1616
					$mpdconf .=<<<EOD
1617
	set auth enable radius-acct
1618

    
1619
EOD;
1620
				}
1621
			}
1622

    
1623
			fwrite($fd, $mpdconf);
1624
			fclose($fd);
1625
			unset($mpdconf);
1626

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

    
1634
			$mpdlinks = "";
1635

    
1636
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1637
				$mpdlinks .=<<<EOD
1638

    
1639
l2tp{$i}:
1640
	set link type l2tp
1641
	set l2tp enable incoming
1642
	set l2tp disable originate
1643

    
1644
EOD;
1645
			if (!empty($l2tpcfg['secret']))
1646
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1647
			}
1648

    
1649
			fwrite($fd, $mpdlinks);
1650
			fclose($fd);
1651
			unset($mpdlinks);
1652

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

    
1660
			$mpdsecret = "\n\n";
1661

    
1662
			if (is_array($l2tpcfg['user'])) {
1663
				foreach ($l2tpcfg['user'] as $user)
1664
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1665
			}
1666

    
1667
			fwrite($fd, $mpdsecret);
1668
			fclose($fd);
1669
			unset($mpdsecret);
1670
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1671

    
1672
			vpn_netgraph_support();
1673

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

    
1677
			break;
1678

    
1679
		case 'redir' :
1680
			break;
1681
	}
1682

    
1683
	if ($g['booting'])
1684
		echo "done\n";
1685

    
1686
	return 0;
1687
}
1688

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

    
1696
	$ipseccfg = $config['ipsec'];
1697
	$a_phase1 = $config['ipsec']['phase1'];
1698
	$a_phase2 = $config['ipsec']['phase2'];
1699

    
1700
	if (isset($ipseccfg['disable'])) {
1701
		return true;
1702
	}
1703

    
1704
	/* Walk the Ipsec tunnel array */
1705
	if (!is_array($a_phase1) || (!count($a_phase1)))
1706
		return;
1707

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

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

    
1742
/* remove SPD polices */
1743
function remove_tunnel_spd_policy($phase1,$phase2) {
1744
	global $config;
1745
	global $g;
1746

    
1747
	if (!$phase1 || !$phase2)
1748
		return false;
1749

    
1750
	if (isset($phase1['mobile']))
1751
		return false;
1752

    
1753
	$spdconf = "";
1754
	$ep = ipsec_get_phase1_src($phase1);
1755
	$gw = trim($phase1['remote-gateway']);
1756
	$sad_arr = ipsec_dump_sad();
1757
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid'], false, $phase2['mode']);
1758

    
1759
	if (!empty($phase2['natlocalid']))
1760
		$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid'], false, $phase2['mode']);
1761
	else
1762
		$local_subnet = ipsec_idinfo_to_cidr($phase2['localid'], false, $phase2['mode']);
1763

    
1764
	if ($phase2['mode'] == "tunnel6")
1765
		$family = "-6";
1766
	else
1767
		$family = "-4";
1768

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

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

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

    
1787
	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));
1788

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

    
1795
	return true;
1796
}
1797

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

    
1804
	/* if we are not passed a old tunnel array we create one */
1805
	if(empty($old_phase1)) {
1806
		$old_phase1 = $phase1;
1807
	}
1808
	if(empty($old_phase2)) {
1809
		$old_phase2 = $phase2;
1810
	}
1811

    
1812
	$sad_arr = ipsec_dump_sad();
1813

    
1814
	$ep = ipsec_get_phase1_src($phase1);
1815
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid'], false, $phase2['mode']);
1816
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid'], false, $phase2['mode']);
1817

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

    
1821
	$old_ep = ipsec_get_phase1_src($old_phase1);
1822
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid'], false, $old_phase2['mode']);
1823
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid'], false, $old_phase2['mode']);
1824

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

    
1850
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1851
		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));
1852
	}
1853
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1854
		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));
1855
	}
1856

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

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

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

    
1887
	if($phase2['mode'] == "tunnel6")
1888
		$family = "-6";
1889
	else
1890
		$family = "-4";
1891

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

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

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

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

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

    
1938
?>
(57-57/66)