Projet

Général

Profil

Télécharger (56,9 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / vpn.inc @ ffb8e02f

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
		$peerid_verify = "";
312
		if ((is_array($a_phase1) && count($a_phase1)) || (is_array($a_phase2) && count($a_phase2))) {
313

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

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

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

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

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

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

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

    
348
					if ($pool_size < 0) {
349
						log_error(sprintf(gettext("Invalid mobile IPsec pool size: %s, using 0"), $pool_size));
350
						$pool_size = 0;
351
					}
352

    
353
					$racoonconf .= "\tpool_size {$pool_size};\n";
354
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
355
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
356
				}
357

    
358
				if (isset($a_client['net_list'])) {
359

    
360
					$net_list = '';
361

    
362
					foreach ($a_phase2 as $ph2ent) {
363

    
364
						if (isset($ph2ent['disabled']))
365
							continue;
366

    
367
						if (!isset($ph2ent['mobile']))
368
							continue;
369

    
370
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']);
371

    
372
						if ($net_list)
373
							$net_list .= ", ";
374
						$net_list .= $localid;
375
					}
376

    
377
					if ($net_list)
378
						$racoonconf .= "\tsplit_network include {$net_list};\n";
379
				}
380

    
381
				if ($a_client['dns_server1'])
382
					$racoonconf .= "\tdns4 {$a_client['dns_server1']};\n";
383
				if ($a_client['dns_server2'])
384
					$racoonconf .= "\tdns4 {$a_client['dns_server2']};\n";
385
				if ($a_client['dns_server3'])
386
					$racoonconf .= "\tdns4 {$a_client['dns_server3']};\n";
387
				if ($a_client['dns_server4'])
388
					$racoonconf .= "\tdns4 {$a_client['dns_server4']};\n";
389

    
390
				if ($a_client['wins_server1'])
391
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
392
				if ($a_client['wins_server2'])
393
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
394

    
395
				if ($a_client['dns_domain']) {
396
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
397
					if (empty($a_client['dns_split']))
398
						$racoonconf .= "\tsplit_dns \"{$a_client['dns_domain']}\";\n";
399
				}
400

    
401
				if ($a_client['dns_split']) {
402
					$domain_array = preg_split("/[ ,]+/",$a_client['dns_split']);
403
					$domain_string = implode('", "', $domain_array);
404
					$racoonconf .= "\tsplit_dns \"{$domain_string}\";\n";
405
				}
406

    
407
				if ($a_client['pfs_group'])
408
					$racoonconf .= "\tpfs_group {$a_client['pfs_group']};\n";
409

    
410
				if ($a_client['login_banner']) {
411
					@file_put_contents("{$g['varetc_path']}/ipsec/racoon.motd", $a_client['login_banner']);
412
					$racoonconf .= "\tbanner \"{$g['varetc_path']}/ipsec/racoon.motd\";\n";
413
				}
414

    
415
				if (isset($a_client['save_passwd']))
416
					$racoonconf .= "\tsave_passwd on;\n";
417

    
418
				$racoonconf .= "}\n\n";
419
			}
420
			/* end mode_cfg section */
421

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

    
442
			/* begin remote sections */
443
			if (is_array($a_phase1) && count($a_phase1)) {
444
				/* begin remote */
445
				foreach ($a_phase1 as $ph1ent) {
446

    
447
					if (isset($ph1ent['disabled']))
448
						continue;
449

    
450
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
451
						continue;
452

    
453
					$ikeid = $ph1ent['ikeid'];
454

    
455
					$ep = ipsec_get_phase1_src($ph1ent);
456
					if (!$ep)
457
						continue;
458

    
459
					if (!isset($ph1ent['mobile'])) {
460
						$rgip = $rgmap[$ph1ent['remote-gateway']];
461
						if (!$rgip)
462
							continue;
463
					}
464

    
465
					$myid_type = $ph1ent['myid_type'];
466

    
467
					switch ($myid_type) {
468

    
469
						case "myaddress":
470
							$myid_type = "address";
471
							$myid_data = $ep;
472
							break;
473

    
474
						case "dyn_dns":
475
							$myid_type = "address";
476
							$myid_data = resolve_retry($ph1ent['myid_data']);
477
							break;
478

    
479
						case "address";
480
							$myid_data = $ph1ent['myid_data'];
481
							break;
482

    
483
						case "fqdn";
484
						case "keyid tag";
485
						case "user_fqdn";
486
						case "asn1dn";
487
							$myid_data = $ph1ent['myid_data'];
488
							if( $myid_data )
489
								$myid_data = "\"".$myid_data."\"";
490
							break;
491
					}
492

    
493
					$peerid_type = $ph1ent['peerid_type'];
494

    
495
					switch ($peerid_type) {
496
						case "peeraddress":
497
							$peerid_type = "address";
498
							$peerid_data = $rgip;
499
							break;
500

    
501
						case "address";
502
							$peerid_data = $ph1ent['peerid_data'];
503
							break;
504

    
505
						case "fqdn";
506
						case "keyid tag";
507
						case "user_fqdn";
508
						case "asn1dn";
509
							$peerid_data = $ph1ent['peerid_data'];
510
							if( $peerid_data )
511
								$peerid_data = "\"".$peerid_data."\"";
512
							break;
513
					}
514

    
515
					$natt = "off";
516
					if (isset($ph1ent['nat_traversal']))
517
						$natt = $ph1ent['nat_traversal'];
518

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

    
536
					$dpdline1 = '';
537
					$dpdline2 = '';
538
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
539
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
540
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
541
					}
542

    
543
					if (isset ($ph1ent['authentication_method']))
544
						$authmethod = $ph1ent['authentication_method'];
545
					else
546
						$authmethod = 'pre_shared_key';
547

    
548
					$certline = '';
549

    
550
					if (strstr($authmethod,'rsa')) {
551

    
552
						$cert = lookup_cert($ph1ent['certref']);
553

    
554
						if (!$cert)
555
						{
556
							log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
557
							continue;
558
						}
559

    
560
						$certfile = "cert-{$ikeid}.crt";
561
						$certpath = "{$g['varetc_path']}/ipsec/{$certfile}";
562

    
563
						if (!file_put_contents($certpath, base64_decode($cert['crt'])))
564
						{
565
							log_error(sprintf(gettext("Error: Cannot write phase1 certificate file for %s"), $ph1ent['name']));
566
							continue;
567
						}
568

    
569
						chmod($certpath, 0600);
570

    
571
						$keyfile = "cert-{$ikeid}.key";
572
						$keypath = "{$g['varetc_path']}/ipsec/{$keyfile}";
573

    
574
						if (!file_put_contents($keypath, base64_decode($cert['prv'])))
575
						{
576
							log_error(sprintf(gettext("Error: Cannot write phase1 key file for %s"), $ph1ent['name']));
577
							continue;
578
						}
579

    
580
						chmod($keypath, 0600);
581

    
582
						$ca = lookup_ca($ph1ent['caref']);
583
						if ($ca) {
584
							$cafile = "ca-{$ikeid}.crt";
585
							$capath = "{$g['varetc_path']}/ipsec/{$cafile}";
586

    
587
							if (!file_put_contents($capath, base64_decode($ca['crt'])))
588
							{
589
								log_error(sprintf(gettext("Error: Cannot write phase1 CA certificate file for %s"), $ph1ent['name']));
590
								continue;
591
							}
592

    
593
							chmod($capath, 0600);
594
							$caline = "ca_type x509 \"{$cafile}\";";
595
						}
596

    
597
						$certline = "certificate_type x509 \"{$certfile}\" \"{$keyfile}\";";
598

    
599
					}
600

    
601
					$ealgos = '';
602
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
603
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
604
					if ($ealg_kl)
605
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
606
					else
607
						$ealgos = $ealgos.$ealg_id;
608

    
609
					$lifeline = '';
610
					if ($ph1ent['lifetime'])
611
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
612

    
613
					/* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */
614
					if (!(($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))) {
615
						$peerid_spec = "peers_identifier {$peerid_type} {$peerid_data};";
616
						if (isset($ph1ent['verify_identifier']))
617
							$peerid_verify = "verify_identifier on;";
618
					}
619

    
620
					/* add remote section to configuration */
621

    
622
					$racoonconf .=<<<EOD
623

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

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

    
653
EOD;
654
				}
655
				/* end remote */
656
			}
657
			/* end remote sections */
658

    
659
			/* begin sainfo sections */
660
			if (is_array($a_phase2) && count($a_phase2)) {
661

    
662
				/* begin sainfo */
663
				foreach ($a_phase2 as $ph2ent) {
664

    
665
					$ikeid = $ph2ent['ikeid'];
666

    
667
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
668
						continue;
669

    
670
					if (isset($ph1ent['disabled']))
671
						continue;
672

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

    
676
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
677
						continue;
678

    
679
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
680

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

    
712
						if (!isset($ph2ent['mobile'])) {
713
							$remoteid_type = $ph2ent['remoteid']['type'];
714
							if ($remoteid_type != "address")
715
								$remoteid_type = "subnet";
716

    
717
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']);
718
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
719
						} else
720
							$remoteid_spec = "anonymous";
721

    
722
					} else {
723
						$rgip = $rgmap[$ph1ent['remote-gateway']];
724

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

    
742
					if($ph2ent['protocol'] == 'esp') {
743

    
744
						$ealgos = '';
745

    
746
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
747

    
748
							$ealg_id = $ealg['name'];
749
							$ealg_kl = $ealg['keylen'];
750

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

    
786
						$ealgosline = "encryption_algorithm {$ealgos};";
787

    
788
					} else {
789

    
790
						$ealgosline = "encryption_algorithm null_enc;";
791
					}
792

    
793
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
794
					$halgosline = "authentication_algorithm {$halgos};";
795

    
796
					$pfsline = '';
797
					if ($ph2ent['pfsgroup'])
798
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
799
					if (isset($a_client['pfs_group'])) {
800
						$pfsline = '';
801
						if ($a_client['pfs_group'])
802
							$pfsline = "pfs_group {$a_client['pfs_group']};";
803
					}
804

    
805
					$lifeline = '';
806
					if ($ph2ent['lifetime'])
807
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
808

    
809
					/* add sainfo section to configuration */
810

    
811
					$racoonconf .=<<<EOD
812

    
813
sainfo {$localid_spec} {$remoteid_spec}
814
{
815
	remoteid {$ikeid};
816
	{$ealgosline}
817
	{$halgosline}
818
	{$pfsline}
819
	{$lifeline}
820
	compression_algorithm deflate;
821
}
822

    
823
EOD;
824
				}
825
				/* end sainfo */
826
			}
827
			/* end sainfo sections */
828
		}
829
		@file_put_contents("{$g['varetc_path']}/ipsec/racoon.conf", $racoonconf);
830
		unset($racoonconf);
831
		/* end racoon.conf */
832

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

    
856
			foreach ($a_phase2 as $ph2ent) {
857

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

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

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

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

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

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

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

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

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

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

    
894
					if (!empty($ph2ent['natlocalid'])) {
895
						$natlocalid = ipsec_idinfo_to_cidr($ph2ent['natlocalid'], true, $ph2ent['mode']);
896
						$spdconf .= "spdadd {$family} {$remoteid} {$natlocalid} any -P in ipsec " .
897
							"{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
898
						$natfilterrules = true;
899
					} else
900
						$spdconf .= "spdadd {$family} {$remoteid} {$localid} any -P in ipsec " .
901
							"{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
902

    
903
				} else {
904

    
905
					$localid_data = ipsec_get_phase1_src($ph1ent);
906
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
907

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

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

    
914
				}
915

    
916
				/* static route needed? */
917
				if (is_ipaddr($ph1ent['interface'])) {
918
					$vip = find_virtual_ip_alias($ph1ent['interface']);
919
					if (preg_match("/^carp|^[a-z0-9]+_vip/i", $vip['interface']))
920
						$parentinterface = link_carp_interface_to_parent($vip['interface']);
921
					else
922
						$parentinterface = $vip['interface'];
923
				} else if (preg_match("/^carp|^[a-z0-9]+_vip/i", $ph1ent['interface']))
924
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
925
				else
926
					$parentinterface = $ph1ent['interface'];
927

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

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

    
970
		}
971
		if ($natfilterrules == true)
972
			filter_configure();
973
		/* start filterdns, if necessary */
974
		if (count($filterdns_list) > 0) {
975
			$interval = 60;
976
			if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval']))
977
				$interval = $ipseccfg['dns-interval'];
978

    
979
			$hostnames = "";
980
			array_unique($filterdns_list);
981
			foreach ($filterdns_list as $hostname)
982
				$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n";
983
			file_put_contents("{$g['varetc_path']}/ipsec/filterdns-ipsec.hosts", $hostnames);
984
			unset($hostnames);
985

    
986
			if (isvalidpid("{$g['varrun_path']}/filterdns-ipsec.pid"))
987
				sigkillbypid("{$g['varrun_path']}/filterdns-ipsec.pid", "HUP");
988
			else {
989
				mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/ipsec/filterdns-ipsec.hosts -d 1");
990
			}
991
		} else {
992
			killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
993
			@unlink("{$g['varrun_path']}/filterdns-ipsec.pid");
994
		}
995

    
996
		vpn_ipsec_failover_configure();
997

    
998
		if ($g['booting'])
999
			echo "done\n";
1000

    
1001
		return count($filterdns_list);
1002
	}
1003
}
1004

    
1005
/*
1006
 * Forcefully restart IPsec
1007
 * This is required for when dynamic interfaces reload
1008
 * For all other occasions the normal vpn_ipsec_configure()
1009
 * will gracefully reload the settings without restarting
1010
 */
1011
function vpn_ipsec_force_reload($interface = "") {
1012
	global $g, $config;
1013

    
1014
	$ipseccfg = $config['ipsec'];
1015

    
1016
	if (!empty($interface) && is_array($ipseccfg['phase1'])) {
1017
		$found = false;
1018
		foreach ($ipseccfg['phase1'] as $ipsec) {
1019
			if (!isset($ipsec['disabled']) && ($ipsec['interface'] == $interface)) {
1020
				$found = true;
1021
				break;
1022
			}
1023
		}
1024
		if (!$found) {
1025
			log_error(sprintf(gettext("Ignoring IPsec racoon daemon reload since there are no tunnels on interface %s"), $interface));
1026
			return;
1027
		}
1028
	}
1029

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

    
1033
	/* wait for process to die */
1034
	sleep(4);
1035

    
1036
	/* kill racoon forcefully */
1037
	if (is_process_running("racoon"))
1038
		mwexec("/usr/bin/killall -9 racoon", true);
1039

    
1040
	/* wait for flushing to finish */
1041
	sleep(1);
1042

    
1043
	/* if ipsec is enabled, start up again */
1044
	if (isset($ipseccfg['enable'])) {
1045
		log_error(gettext("Forcefully reloading IPsec racoon daemon"));
1046
		vpn_ipsec_configure();
1047
	}
1048
}
1049

    
1050
/* master setup for vpn (mpd) */
1051
function vpn_setup() {
1052
	global $g;
1053

    
1054
	if ($g['platform'] == 'jail')
1055
		return;
1056

    
1057
	/* start pptpd */
1058
	vpn_pptpd_configure();
1059

    
1060
	/* start pppoe server */
1061
	vpn_pppoes_configure();
1062

    
1063
	/* setup l2tp */
1064
	vpn_l2tp_configure();
1065
}
1066

    
1067
function vpn_netgraph_support() {
1068
	$iflist = get_configured_interface_list();
1069
	foreach ($iflist as $iface) {
1070
		$realif = get_real_interface($iface);
1071
		/* Get support for netgraph(4) from the nic */
1072
		$ifinfo = pfSense_get_interface_addresses($realif);
1073
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge")))
1074
			pfSense_ngctl_attach(".", $realif);
1075
	}
1076
}
1077

    
1078
function vpn_pptpd_configure() {
1079
	global $config, $g;
1080

    
1081
	$syscfg = $config['system'];
1082
	$pptpdcfg = $config['pptpd'];
1083

    
1084
	if ($g['booting']) {
1085
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
1086
			return 0;
1087

    
1088
		echo gettext("Configuring PPTP VPN service... ");
1089
	} else {
1090
		/* kill mpd */
1091
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1092

    
1093
		/* wait for process to die */
1094
		sleep(3);
1095

    
1096
		if (is_process_running("mpd -b")) {
1097
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1098
			log_error(gettext("Could not kill mpd within 3 seconds.   Trying again."));
1099
		}
1100

    
1101
		/* remove mpd.conf, if it exists */
1102
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
1103
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
1104
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
1105
	}
1106

    
1107
	if (empty($pptpdcfg['n_pptp_units'])) {
1108
		log_error("Something wrong in the PPTPd configuration. Preventing starting the daemon because issues would arise.");
1109
		return;
1110
	}
1111

    
1112
	/* make sure pptp-vpn directory exists */
1113
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
1114
		mkdir("{$g['varetc_path']}/pptp-vpn");
1115

    
1116
	switch ($pptpdcfg['mode']) {
1117
		case 'server' :
1118
			/* write mpd.conf */
1119
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
1120
			if (!$fd) {
1121
				printf(gettext("Error: cannot open mpd.conf in vpn_pptpd_configure().") . "\n");
1122
				return 1;
1123
			}
1124

    
1125
			$mpdconf = <<<EOD
1126
pptps:
1127

    
1128
EOD;
1129

    
1130
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1131
				$mpdconf .= "	load pt{$i}\n";
1132
			}
1133

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

    
1136
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1137

    
1138
				$mpdconf .= <<<EOD
1139

    
1140
pt{$i}:
1141
	new -i pptpd{$i} pt{$i} pt{$i}
1142
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1143
	load pts
1144

    
1145
EOD;
1146
			}
1147

    
1148
			$mpdconf .=<<<EOD
1149

    
1150
pts:
1151
	set iface disable on-demand
1152
	set iface enable proxy-arp
1153
	set iface enable tcpmssfix
1154
	set iface idle 1800
1155
	set iface up-script /usr/local/sbin/vpn-linkup
1156
	set iface down-script /usr/local/sbin/vpn-linkdown
1157
	set bundle enable multilink
1158
	set bundle enable crypt-reqd
1159
	set link yes acfcomp protocomp
1160
	set link no pap chap
1161
	set link enable chap-msv2
1162
	set link mtu 1460
1163
	set link keep-alive 10 60
1164
	set ipcp yes vjcomp
1165
	set bundle enable compression
1166
	set ccp yes mppc
1167
	set ccp yes mpp-e128
1168
	set ccp yes mpp-stateless
1169

    
1170
EOD;
1171

    
1172
			if (!isset ($pptpdcfg['req128'])) {
1173
				$mpdconf .=<<<EOD
1174
	set ccp yes mpp-e40
1175
	set ccp yes mpp-e56
1176

    
1177
EOD;
1178
			}
1179

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

    
1183
			if (!empty($pptpdcfg['dns1'])) {
1184
				$mpdconf .= "	set ipcp dns " . $pptpdcfg['dns1'];
1185
				if (!empty($pptpdcfg['dns2']))
1186
					$mpdconf .= " " . $pptpdcfg['dns2'];
1187
				$mpdconf .= "\n";
1188
			} elseif (isset ($config['dnsmasq']['enable'])) {
1189
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1190
				if ($syscfg['dnsserver'][0])
1191
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1192
				$mpdconf .= "\n";
1193
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1194
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1195
			}
1196

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

    
1203
EOD;
1204
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1205
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1206
				$acctport = $authport + 1;
1207
				$mpdconf .=<<<EOD
1208
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret2']}" {$authport} {$acctport}
1209

    
1210
EOD;
1211
			}
1212
			$mpdconf .=<<<EOD
1213
	set radius retries 3
1214
	set radius timeout 10
1215
	set auth enable radius-auth
1216

    
1217
EOD;
1218

    
1219
				if (isset ($pptpdcfg['radius']['accounting'])) {
1220
					$mpdconf .=<<<EOD
1221
	set auth enable radius-acct
1222
	set radius acct-update 300
1223

    
1224
EOD;
1225
				}
1226
			}
1227

    
1228
			fwrite($fd, $mpdconf);
1229
			fclose($fd);
1230
			unset($mpdconf);
1231

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

    
1239
			$mpdlinks = "";
1240

    
1241
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1242
				$mpdlinks .=<<<EOD
1243

    
1244
pt{$i}:
1245
	set link type pptp
1246
	set pptp enable incoming
1247
	set pptp disable originate
1248
	set pptp disable windowing
1249

    
1250
EOD;
1251
			}
1252

    
1253
			fwrite($fd, $mpdlinks);
1254
			fclose($fd);
1255
			unset($mpdlinks);
1256

    
1257
			/* write mpd.secret */
1258
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1259
			if (!$fd) {
1260
				printf(gettext("Error: cannot open mpd.secret in vpn_pptpd_configure().") . "\n");
1261
				return 1;
1262
			}
1263

    
1264
			$mpdsecret = "";
1265

    
1266
			if (is_array($pptpdcfg['user'])) {
1267
				foreach ($pptpdcfg['user'] as $user) {
1268
					$pass = str_replace('\\', '\\\\', $user['password']);
1269
					$pass = str_replace('"', '\"', $pass);
1270
					$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
1271
				}
1272
			}
1273

    
1274
			fwrite($fd, $mpdsecret);
1275
			fclose($fd);
1276
			unset($mpdsecret);
1277
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1278

    
1279
			vpn_netgraph_support();
1280

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

    
1284
			break;
1285

    
1286
		case 'redir' :
1287
			break;
1288
	}
1289

    
1290
	if ($g['booting'])
1291
		echo "done\n";
1292

    
1293
	return 0;
1294
}
1295

    
1296
function vpn_pppoes_configure() {
1297
	global $config;
1298

    
1299
	if (is_array($config['pppoes']['pppoe'])) {
1300
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1301
			vpn_pppoe_configure($pppoe);
1302
	}
1303
}
1304

    
1305
function vpn_pppoe_configure(&$pppoecfg) {
1306
	global $config, $g;
1307

    
1308
	$syscfg = $config['system'];
1309

    
1310
	/* create directory if it does not exist */
1311
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1312
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1313

    
1314
	if ($g['booting']) {
1315
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1316
			return 0;
1317

    
1318
		echo gettext("Configuring PPPoE VPN service... ");
1319
	} else {
1320
		/* kill mpd */
1321
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1322

    
1323
		/* wait for process to die */
1324
		sleep(2);
1325

    
1326
	}
1327

    
1328
	switch ($pppoecfg['mode']) {
1329

    
1330
		case 'server' :
1331

    
1332
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1333

    
1334
			if ($pppoecfg['paporchap'] == "chap")
1335
				$paporchap = "set link enable chap";
1336
			else
1337
				$paporchap = "set link enable pap";
1338

    
1339
			/* write mpd.conf */
1340
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1341
			if (!$fd) {
1342
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
1343
				return 1;
1344
			}
1345
			$mpdconf = "\n\n";
1346
			$mpdconf .= "poes:\n";
1347

    
1348
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1349
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1350
			}
1351

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

    
1354
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1355

    
1356
				if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
1357
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1358
				} else {
1359
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1360
				}
1361

    
1362
				$mpdconf .=<<<EOD
1363

    
1364
poes{$pppoecfg['pppoeid']}{$i}:
1365
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1366
	{$isssue_ip_type}
1367
	load pppoe_standard
1368

    
1369
EOD;
1370
			}
1371

    
1372
			$mpdconf .=<<<EOD
1373

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

    
1400
EOD;
1401

    
1402
			if (!empty($pppoecfg['dns1'])) {
1403
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1404
				if (!empty($pppoecfg['dns2']))
1405
					$mpdconf .= " " . $pppoecfg['dns2'];
1406
				$mpdconf .= "\n";
1407
			} elseif (isset ($config['dnsmasq']['enable'])) {
1408
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1409
				if ($syscfg['dnsserver'][0])
1410
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1411
				$mpdconf .= "\n";
1412
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1413
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1414
			}
1415

    
1416
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1417
				$radiusport = "";
1418
				$radiusacctport = "";
1419
				if (isset($pppoecfg['radius']['server']['port']))
1420
					$radiusport = $pppoecfg['radius']['server']['port'];
1421
				if (isset($pppoecfg['radius']['server']['acctport']))
1422
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1423
				$mpdconf .=<<<EOD
1424
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
1425
	set radius retries 3
1426
	set radius timeout 10
1427
	set auth enable radius-auth
1428

    
1429
EOD;
1430

    
1431
				if (isset ($pppoecfg['radius']['accounting'])) {
1432
					$mpdconf .=<<<EOD
1433
	set auth enable radius-acct
1434

    
1435
EOD;
1436
				}
1437
			}
1438

    
1439
			fwrite($fd, $mpdconf);
1440
			fclose($fd);
1441
			unset($mpdconf);
1442

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

    
1450
			$mpdlinks = "";
1451

    
1452
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1453
				$mpdlinks .=<<<EOD
1454

    
1455
poes{$pppoecfg['pppoeid']}{$i}:
1456
	set phys type pppoe
1457
	set pppoe iface {$pppoe_interface}
1458
	set pppoe service "*"
1459
	set pppoe disable originate
1460
	set pppoe enable incoming
1461

    
1462
EOD;
1463
			}
1464

    
1465
			fwrite($fd, $mpdlinks);
1466
			fclose($fd);
1467
			unset($mpdlinks);
1468

    
1469
			if ($pppoecfg['username']) {
1470
				/* write mpd.secret */
1471
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1472
				if (!$fd) {
1473
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1474
					return 1;
1475
				}
1476

    
1477
				$mpdsecret = "\n\n";
1478

    
1479
				if (!empty($pppoecfg['username'])) {
1480
					$item = explode(" ", $pppoecfg['username']);
1481
					foreach($item as $userdata) {
1482
						$data = explode(":", $userdata);
1483
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1484
					}
1485
				}
1486

    
1487
				fwrite($fd, $mpdsecret);
1488
				fclose($fd);
1489
				unset($mpdsecret);
1490
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1491
			}
1492

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

    
1497
			/* Get support for netgraph(4) from the nic */
1498
			pfSense_ngctl_attach(".", $pppoe_interface);
1499
			/* fire up mpd */
1500
			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");
1501

    
1502
			break;
1503
	}
1504

    
1505
	if ($g['booting'])
1506
		echo gettext("done") . "\n";
1507

    
1508
	return 0;
1509
}
1510

    
1511
function vpn_l2tp_configure() {
1512
	global $config, $g;
1513

    
1514
	$syscfg = $config['system'];
1515
	$l2tpcfg = $config['l2tp'];
1516

    
1517
	/* create directory if it does not exist */
1518
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1519
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1520

    
1521
	if ($g['booting']) {
1522
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1523
			return 0;
1524

    
1525
		echo gettext("Configuring l2tp VPN service... ");
1526
	} else {
1527
		/* kill mpd */
1528
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1529

    
1530
		/* wait for process to die */
1531
		sleep(8);
1532

    
1533
	}
1534

    
1535
	/* make sure l2tp-vpn directory exists */
1536
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1537
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1538

    
1539
	switch ($l2tpcfg['mode']) {
1540

    
1541
		case 'server' :
1542
			if ($l2tpcfg['paporchap'] == "chap")
1543
				$paporchap = "set link enable chap";
1544
			else
1545
				$paporchap = "set link enable pap";
1546

    
1547
			/* write mpd.conf */
1548
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1549
			if (!$fd) {
1550
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
1551
				return 1;
1552
			}
1553
			$mpdconf = "\n\n";
1554
			$mpdconf .=<<<EOD
1555
l2tps:
1556

    
1557
EOD;
1558

    
1559
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1560
				$mpdconf .= "	load l2tp{$i}\n";
1561
			}
1562

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

    
1565
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1566

    
1567
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1568
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1569
				} else {
1570
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1571
				}
1572

    
1573
				$mpdconf .=<<<EOD
1574

    
1575
l2tp{$i}:
1576
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1577
	{$isssue_ip_type}
1578
	load l2tp_standard
1579

    
1580
EOD;
1581
			}
1582

    
1583
			$mpdconf .=<<<EOD
1584

    
1585
l2tp_standard:
1586
	set bundle disable multilink
1587
	set bundle enable compression
1588
	set bundle yes crypt-reqd
1589
	set ipcp yes vjcomp
1590
	# set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1591
	set ccp yes mppc
1592
	set iface disable on-demand
1593
	set iface enable proxy-arp
1594
	set iface up-script /usr/local/sbin/vpn-linkup
1595
	set iface down-script /usr/local/sbin/vpn-linkdown
1596
	set link yes acfcomp protocomp
1597
	set link no pap chap
1598
	set link enable chap
1599
	set link keep-alive 10 180
1600

    
1601
EOD;
1602

    
1603
			if (is_ipaddr($l2tpcfg['wins'])) {
1604
				$mpdconf .= "	set ipcp nbns {$l2tpcfg['wins']}\n";
1605
			}
1606
			if (is_ipaddr($l2tpcfg['dns1'])) {
1607
				$mpdconf .= "	set ipcp dns " . $l2tpcfg['dns1'];
1608
				if (is_ipaddr($l2tpcfg['dns2']))
1609
					$mpdconf .= " " . $l2tpcfg['dns2'];
1610
				$mpdconf .= "\n";
1611
			} elseif (isset ($config['dnsmasq']['enable'])) {
1612
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1613
				if ($syscfg['dnsserver'][0])
1614
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1615
				$mpdconf .= "\n";
1616
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1617
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1618
			}
1619

    
1620
			if (isset ($l2tpcfg['radius']['enable'])) {
1621
				$mpdconf .=<<<EOD
1622
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1623
	set radius retries 3
1624
	set radius timeout 10
1625
	set auth enable radius-auth
1626

    
1627
EOD;
1628

    
1629
				if (isset ($l2tpcfg['radius']['accounting'])) {
1630
					$mpdconf .=<<<EOD
1631
	set auth enable radius-acct
1632

    
1633
EOD;
1634
				}
1635
			}
1636

    
1637
			fwrite($fd, $mpdconf);
1638
			fclose($fd);
1639
			unset($mpdconf);
1640

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

    
1648
			$mpdlinks = "";
1649

    
1650
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1651
				$mpdlinks .=<<<EOD
1652

    
1653
l2tp{$i}:
1654
	set link type l2tp
1655
	set l2tp enable incoming
1656
	set l2tp disable originate
1657

    
1658
EOD;
1659
			if (!empty($l2tpcfg['secret']))
1660
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1661
			}
1662

    
1663
			fwrite($fd, $mpdlinks);
1664
			fclose($fd);
1665
			unset($mpdlinks);
1666

    
1667
			/* write mpd.secret */
1668
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1669
			if (!$fd) {
1670
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
1671
				return 1;
1672
			}
1673

    
1674
			$mpdsecret = "\n\n";
1675

    
1676
			if (is_array($l2tpcfg['user'])) {
1677
				foreach ($l2tpcfg['user'] as $user)
1678
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1679
			}
1680

    
1681
			fwrite($fd, $mpdsecret);
1682
			fclose($fd);
1683
			unset($mpdsecret);
1684
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1685

    
1686
			vpn_netgraph_support();
1687

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

    
1691
			break;
1692

    
1693
		case 'redir' :
1694
			break;
1695
	}
1696

    
1697
	if ($g['booting'])
1698
		echo "done\n";
1699

    
1700
	return 0;
1701
}
1702

    
1703
/* Walk the tunnels for hostname endpoints. If the hostnames
1704
 * resolve to a different IP now compared to the DNS cache
1705
 * we reload the policies if the endpoint has changed */
1706
function vpn_ipsec_refresh_policies() {
1707
	global $config;
1708
	global $g;
1709

    
1710
	$ipseccfg = $config['ipsec'];
1711
	$a_phase1 = $config['ipsec']['phase1'];
1712
	$a_phase2 = $config['ipsec']['phase2'];
1713

    
1714
	if (isset($ipseccfg['disable'])) {
1715
		return true;
1716
	}
1717

    
1718
	/* Walk the Ipsec tunnel array */
1719
	if (!is_array($a_phase1) || (!count($a_phase1)))
1720
		return;
1721

    
1722
	foreach ($a_phase1 as $phase1) {
1723
		if (isset($phase1['disabled']))
1724
			continue;
1725
		if (is_ipaddr($phase1['remote-gateway']))
1726
			continue;
1727
		$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1728
		$dnscache = trim($dnscache);
1729
		/* we should have the old IP addresses in the dnscache now */
1730
		if(!empty($dnscache)) {
1731
			$oldphase1 = $phase1;
1732
			$oldphase1['remote-gateway'] = $dnscache;
1733
			/* now we need to find all tunnels for this host */
1734
			if (!is_array($a_phase2) || (!count($a_phase2)))
1735
				continue;
1736
			foreach ($a_phase2 as $phase2) {
1737
				if ($phase2['ikeid'] == $phase1['ikeid'])
1738
					reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1739
			}
1740
		}
1741
	}
1742

    
1743
	/* process all generated temporary spd.conf files */
1744
	$tmpfiles = glob("{$g['tmp_path']}/spd.conf.reload.*");
1745
	foreach($tmpfiles as $tmpfile) {
1746
		$ret = mwexec("/usr/local/sbin/setkey -f {$tmpfile} 2>&1", false);
1747
		if ($ret == 0)
1748
			unlink_if_exists($tmpfile);
1749
		else {
1750
			$tmpfile = basename($tmpfile);
1751
			@rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1752
		}
1753
	}
1754
}
1755

    
1756
/* remove SPD polices */
1757
function remove_tunnel_spd_policy($phase1,$phase2) {
1758
	global $config;
1759
	global $g;
1760

    
1761
	if (!$phase1 || !$phase2)
1762
		return false;
1763

    
1764
	if (isset($phase1['mobile']))
1765
		return false;
1766

    
1767
	$spdconf = "";
1768
	$ep = ipsec_get_phase1_src($phase1);
1769
	$gw = trim($phase1['remote-gateway']);
1770
	$sad_arr = ipsec_dump_sad();
1771
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid'], false, $phase2['mode']);
1772

    
1773
	if (!empty($phase2['natlocalid']))
1774
		$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid'], false, $phase2['mode']);
1775
	else
1776
		$local_subnet = ipsec_idinfo_to_cidr($phase2['localid'], false, $phase2['mode']);
1777

    
1778
	if ($phase2['mode'] == "tunnel6")
1779
		$family = "-6";
1780
	else
1781
		$family = "-4";
1782

    
1783
	$spdconf .= "spddelete {$family} {$local_subnet} " .
1784
		"{$remote_subnet} any -P out ipsec " .
1785
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1786
		"{$gw}/unique;\n";
1787

    
1788
	$spdconf .= "spddelete {$family} {$remote_subnet} " .
1789
		"{$local_subnet} any -P in ipsec " .
1790
		"{$phase2['protocol']}/tunnel/{$gw}-" .
1791
		"{$ep}/unique;\n";
1792

    
1793
	/* zap any existing SA entries */
1794
	foreach($sad_arr as $sad) {
1795
		if(($sad['dst'] == $ep) && ($sad['src'] == $gw))
1796
			$spdconf .= "delete {$family} {$ep} {$gw} {$phase2['protocol']} 0x{$sad['spi']};\n";
1797
		if(($sad['src'] == $ep) && ($sad['dst'] == $_gw))
1798
			$spdconf .= "delete {$family} {$gw} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1799
	}
1800

    
1801
	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));
1802

    
1803
	$now = time();
1804
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1805
	/* generate temporary spd.conf */
1806
	@file_put_contents($spdfile, $spdconf);
1807
	unset($spdconf);
1808

    
1809
	return true;
1810
}
1811

    
1812
/* reloads the tunnel configuration for a tunnel item
1813
 * Will remove and add SPD polices */
1814
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1815
	global $config;
1816
	global $g;
1817

    
1818
	/* if we are not passed a old tunnel array we create one */
1819
	if(empty($old_phase1)) {
1820
		$old_phase1 = $phase1;
1821
	}
1822
	if(empty($old_phase2)) {
1823
		$old_phase2 = $phase2;
1824
	}
1825

    
1826
	$sad_arr = ipsec_dump_sad();
1827

    
1828
	$ep = ipsec_get_phase1_src($phase1);
1829
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid'], false, $phase2['mode']);
1830
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid'], false, $phase2['mode']);
1831

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

    
1835
	$old_ep = ipsec_get_phase1_src($old_phase1);
1836
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid'], false, $old_phase2['mode']);
1837
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid'], false, $old_phase2['mode']);
1838

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

    
1864
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1865
		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));
1866
	}
1867
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1868
		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));
1869
	}
1870

    
1871
	$spdconf = "";
1872
	/* Delete old SPD policies if there are changes between the old and new */
1873
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1874
		if($old_phase2['mode'] == "tunnel6")
1875
			$family = "-6";
1876
		else
1877
			$family = "-4";
1878

    
1879
		$spdconf .= "spddelete {$family} {$old_local_subnet} " .
1880
			"{$old_remote_subnet} any -P out ipsec " .
1881
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1882
			"{$old_gw}/unique;\n";
1883
		if (!empty($old_phase2['natlocalid']))
1884
			$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['natlocalid'], false, $old_phase2['mode']);
1885
		$spdconf .= "spddelete {$family} {$old_remote_subnet} " .
1886
			"{$old_local_subnet} any -P in ipsec " .
1887
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1888
			"{$old_ep}/unique;\n";
1889

    
1890
		/* zap any existing SA entries */
1891
		foreach($sad_arr as $sad) {
1892
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1893
				$spdconf .= "delete {$family} {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1894
			}
1895
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1896
				$spdconf .= "delete {$family} {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1897
			}
1898
		}
1899
	}
1900

    
1901
	if($phase2['mode'] == "tunnel6")
1902
		$family = "-6";
1903
	else
1904
		$family = "-4";
1905

    
1906
	/* Create new SPD entries for the new configuration */
1907
	/* zap any existing SA entries beforehand */
1908
	foreach($sad_arr as $sad) {
1909
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1910
			$spdconf .= "delete {$family} {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1911
		}
1912
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1913
			$spdconf .= "delete {$family} {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1914
		}
1915
	}
1916
	/* add new SPD policies to replace them */
1917
	if (!isset($phase1['disabled']) && !isset($phase2['disabled'])) {
1918
		$spdconf .= "spdadd {$family} {$local_subnet} " .
1919
			"{$remote_subnet} any -P out ipsec " .
1920
			"{$phase2['protocol']}/tunnel/{$ep}-" .
1921
			"{$rgip}/unique;\n";
1922

    
1923
		if (!empty($phase2['natlocalid']))
1924
			$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid'], false, $phase2['mode']);
1925
		$spdconf .= "spdadd {$family} {$remote_subnet} " .
1926
			"{$local_subnet} any -P in ipsec " .
1927
			"{$phase2['protocol']}/tunnel/{$rgip}-" .
1928
			"{$ep}/unique;\n";
1929
	}
1930

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

    
1933
	$now = time();
1934
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1935
	/* generate temporary spd.conf */
1936
	@file_put_contents($spdfile, $spdconf);
1937
	unset($spdconf);
1938
	/* remove static route to old gw */
1939
	if (is_ipaddr($old_gw))
1940
		mwexec("/sbin/route delete {$old_gw}", true);
1941
	return true;
1942
}
1943

    
1944
function vpn_ipsec_configure_preferoldsa() {
1945
	global $config;
1946
	if(isset($config['ipsec']['preferoldsa']))
1947
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1948
	else
1949
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1950
}
1951

    
1952
?>
(57-57/66)