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
				if (is_ipaddr($ph1ent['interface'])) {
909
					$vip = find_virtual_ip_alias($ph1ent['interface']);
910
					if (preg_match("/^carp|^[a-z0-9]+_vip/i", $vip['interface']))
911
						$parentinterface = link_carp_interface_to_parent($vip['interface']);
912
					else
913
						$parentinterface = $vip['interface'];
914
				} else if (preg_match("/^carp|^[a-z0-9]+_vip/i", $ph1ent['interface']))
915
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
916
				else
917
					$parentinterface = $ph1ent['interface'];
918

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

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

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

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

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

    
987
		vpn_ipsec_failover_configure();
988

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

    
992
		return count($filterdns_list);
993
	}
994
}
995

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1119
EOD;
1120

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

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

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

    
1129
				$mpdconf .= <<<EOD
1130

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

    
1136
EOD;
1137
			}
1138

    
1139
			$mpdconf .=<<<EOD
1140

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

    
1161
EOD;
1162

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

    
1168
EOD;
1169
			}
1170

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

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

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

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

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

    
1208
EOD;
1209

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

    
1215
EOD;
1216
				}
1217
			}
1218

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

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

    
1230
			$mpdlinks = "";
1231

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

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

    
1241
EOD;
1242
			}
1243

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

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

    
1255
			$mpdsecret = "";
1256

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

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

    
1270
			vpn_netgraph_support();
1271

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

    
1275
			break;
1276

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

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

    
1284
	return 0;
1285
}
1286

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

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

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

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

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

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

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

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

    
1317
	}
1318

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

    
1321
		case 'server' :
1322

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

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

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

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

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

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

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

    
1353
				$mpdconf .=<<<EOD
1354

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

    
1360
EOD;
1361
			}
1362

    
1363
			$mpdconf .=<<<EOD
1364

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

    
1391
EOD;
1392

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

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

    
1420
EOD;
1421

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

    
1426
EOD;
1427
				}
1428
			}
1429

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

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

    
1441
			$mpdlinks = "";
1442

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

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

    
1453
EOD;
1454
			}
1455

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

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

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

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

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

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

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

    
1493
			break;
1494
	}
1495

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

    
1499
	return 0;
1500
}
1501

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

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

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

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

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

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

    
1524
	}
1525

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

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

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

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

    
1548
EOD;
1549

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

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

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

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

    
1564
				$mpdconf .=<<<EOD
1565

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

    
1571
EOD;
1572
			}
1573

    
1574
			$mpdconf .=<<<EOD
1575

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

    
1592
EOD;
1593

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

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

    
1618
EOD;
1619

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

    
1624
EOD;
1625
				}
1626
			}
1627

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

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

    
1639
			$mpdlinks = "";
1640

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

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

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

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

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

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

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

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

    
1677
			vpn_netgraph_support();
1678

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

    
1682
			break;
1683

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

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

    
1691
	return 0;
1692
}
1693

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1800
	return true;
1801
}
1802

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

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

    
1817
	$sad_arr = ipsec_dump_sad();
1818

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

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

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

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

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

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

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

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

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

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

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

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

    
1921
	$now = time();
1922
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1923
	/* generate temporary spd.conf */
1924
	@file_put_contents($spdfile, $spdconf);
1925
	unset($spdconf);
1926
	return true;
1927
}
1928

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

    
1937
?>
(57-57/66)