Projet

Général

Profil

Télécharger (57,3 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / vpn.inc @ a3331d72

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
							$viplist = get_configured_vips_list();
198
							$srcip = null;
199
							$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']);
200
							if(is_ipaddrv6($ph2ent['pinghost'])) {
201
								foreach ($iflist as $ifent => $ifname) {
202
									$interface_ip = get_interface_ipv6($ifent);
203
									if(!is_ipaddrv6($interface_ip))
204
										continue;
205
									$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']);
206
									if (ip_in_subnet($interface_ip, $local_subnet)) {
207
										$srcip = $interface_ip;
208
										break;
209
									}
210
								}
211
							} else {
212
								foreach ($iflist as $ifent => $ifname) {
213
									$interface_ip = get_interface_ip($ifent);
214
									if(!is_ipaddrv4($interface_ip))
215
										continue;
216
									if ($local_subnet == "0.0.0.0/0" || ip_in_subnet($interface_ip, $local_subnet)) {
217
										$srcip = $interface_ip;
218
										break;
219
									}
220
								}
221
							}
222
							/* if no valid src IP was found in configured interfaces, try the vips */
223
							if (is_null($srcip)) {
224
								foreach ($viplist as $vip) {
225
									if (ip_in_subnet($vip['ipaddr'], $local_subnet)) {
226
										$srcip = $vip['ipaddr'];
227
										break;
228
									}
229
								}
230
							}
231
							$dstip = $ph2ent['pinghost'];
232
							if(is_ipaddrv6($dstip)) {
233
								$family = "inet6";
234
							} else {
235
								$family = "inet";
236
							}
237
							if (is_ipaddr($srcip))
238
								$ipsecpinghosts[] = "{$srcip}|{$dstip}|3|||||{$family}|\n";
239
						}
240
					}
241
				}
242
			}
243
			@file_put_contents("{$g['vardb_path']}/ipsecpinghosts", $ipsecpinghosts);
244
			unset($ipsecpinghosts);
245
		}
246

    
247
		/* generate CA certificates files */
248
		if (is_array($config['ca']) && count($config['ca'])) {
249
			foreach ($config['ca'] as $ca) {
250
				if (!isset($ca['crt'])) {
251
					log_error(sprintf(gettext("Error: Invalid certificate info for %s"), $ca['descr']));
252
					continue;
253
				}
254
				$cert = base64_decode($ca['crt']);
255
				$x509cert = openssl_x509_parse(openssl_x509_read($cert));
256
				if (!is_array($x509cert) || !isset($x509cert['hash'])) {
257
					log_error(sprintf(gettext("Error: Invalid certificate hash info for %s"), $ca['descr']));
258
					continue;
259
				}
260
				$fname = "{$g['varetc_path']}/ipsec/{$x509cert['hash']}.0";
261
				if (!@file_put_contents($fname, $cert)) {
262
					log_error(sprintf(gettext("Error: Cannot write IPsec CA file for %s"), $ca['descr']));
263
					continue;
264
				}
265
				unset($cert);
266
			}
267
		}
268

    
269
		$pskconf = "";
270

    
271
		if (is_array($a_phase1) && count($a_phase1)) {
272
			foreach ($a_phase1 as $ph1ent) {
273

    
274
				if (isset($ph1ent['disabled']))
275
					continue;
276

    
277
				if (strstr($ph1ent['authentication_method'],'rsa'))
278
					continue;
279

    
280
				$peerid_type = $ph1ent['peerid_type'];
281

    
282
				switch ($peerid_type) {
283
					case "peeraddress":
284
						$peerid_type = "address";
285
						$peerid_data = $rgmap[$ph1ent['remote-gateway']];
286
						break;
287

    
288
					case "address";
289
						$peerid_data = $ph1ent['peerid_data'];
290
						break;
291

    
292
					case "fqdn";
293
					case "keyid tag";
294
					case "user_fqdn";
295
						$peerid_data = $ph1ent['peerid_data'];
296
						break;
297
				}
298

    
299
				if (!empty($peerid_data) && !empty($ph1ent['pre-shared-key']))
300
					$pskconf .= trim($peerid_data) . "\t" . trim($ph1ent['pre-shared-key']) . "\n";
301
			}
302
		}
303

    
304
		/* Add user PSKs */
305
		foreach ($config['system']['user'] as $user) {
306
			if (!empty($user['ipsecpsk'])) {
307
				$pskconf .= "{$user['name']}\t{$user['ipsecpsk']}\n";
308
			}
309
		}
310

    
311
		/* add PSKs for mobile clients */
312
		if (is_array($ipseccfg['mobilekey'])) {
313
			foreach ($ipseccfg['mobilekey'] as $key) {
314
				$pskconf .= "{$key['ident']}\t{$key['pre-shared-key']}\n";
315
			}
316
		}
317

    
318
		@file_put_contents("{$g['varetc_path']}/ipsec/psk.txt", $pskconf);
319
		chmod("{$g['varetc_path']}/ipsec/psk.txt", 0600);
320
		unset($pskconf);
321

    
322
		/* begin racoon.conf */
323
		$racoonconf = "";
324
		$peerid_verify = "";
325
		if ((is_array($a_phase1) && count($a_phase1)) || (is_array($a_phase2) && count($a_phase2))) {
326

    
327
			$racoonconf .= "# This file is automatically generated. Do not edit\n";
328
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/ipsec/psk.txt\";\n\n";
329
			$racoonconf .= "path certificate  \"{$g['varetc_path']}/ipsec\";\n\n";
330

    
331
			/* begin listen section */
332
			if (count($ipmap)) {
333
				$racoonconf .= "\nlisten\n";
334
				$racoonconf .= "{\n";
335
				$racoonconf .= "	adminsock \"/var/db/racoon/racoon.sock\" \"root\" \"wheel\" 0660;\n";
336
				foreach ($ipmap as $addr) {
337
					$racoonconf .= "\tisakmp {$addr} [500];\n";
338
					$racoonconf .= "\tisakmp_natt {$addr} [4500];\n";
339
				}
340
				$racoonconf .= "}\n\n";
341
			}
342

    
343
			/* begin mode_cfg section */
344
			if (is_array($a_client) && isset($a_client['enable'])) {
345

    
346
				$racoonconf .= "\nmode_cfg\n";
347
				$racoonconf .= "{\n";
348

    
349
				if (!empty($a_client['user_source']))
350
					$racoonconf .= "\tauth_source external;\n";
351
				if (!empty($a_client['group_source']) && $a_client['group_source'] != "none")
352
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
353

    
354
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
355
					$pool_address = $a_client['pool_address'];
356
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
357

    
358
					$pool_address = long2ip32(ip2long($pool_address)+1);
359
					$pool_size = (~ip2long($pool_netmask) & 0xFFFFFFFF) - 2;
360

    
361
					if ($pool_size < 0) {
362
						log_error(sprintf(gettext("Invalid mobile IPsec pool size: %s, using 0"), $pool_size));
363
						$pool_size = 0;
364
					}
365

    
366
					$racoonconf .= "\tpool_size {$pool_size};\n";
367
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
368
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
369
				}
370

    
371
				if (isset($a_client['net_list'])) {
372

    
373
					$net_list = '';
374

    
375
					foreach ($a_phase2 as $ph2ent) {
376

    
377
						if (isset($ph2ent['disabled']))
378
							continue;
379

    
380
						if (!isset($ph2ent['mobile']))
381
							continue;
382

    
383
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']);
384

    
385
						if ($net_list)
386
							$net_list .= ", ";
387
						$net_list .= $localid;
388
					}
389

    
390
					if ($net_list)
391
						$racoonconf .= "\tsplit_network include {$net_list};\n";
392
				}
393

    
394
				if ($a_client['dns_server1'])
395
					$racoonconf .= "\tdns4 {$a_client['dns_server1']};\n";
396
				if ($a_client['dns_server2'])
397
					$racoonconf .= "\tdns4 {$a_client['dns_server2']};\n";
398
				if ($a_client['dns_server3'])
399
					$racoonconf .= "\tdns4 {$a_client['dns_server3']};\n";
400
				if ($a_client['dns_server4'])
401
					$racoonconf .= "\tdns4 {$a_client['dns_server4']};\n";
402

    
403
				if ($a_client['wins_server1'])
404
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
405
				if ($a_client['wins_server2'])
406
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
407

    
408
				if ($a_client['dns_domain']) {
409
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
410
					if (empty($a_client['dns_split']))
411
						$racoonconf .= "\tsplit_dns \"{$a_client['dns_domain']}\";\n";
412
				}
413

    
414
				if ($a_client['dns_split']) {
415
					$domain_array = preg_split("/[ ,]+/",$a_client['dns_split']);
416
					$domain_string = implode('", "', $domain_array);
417
					$racoonconf .= "\tsplit_dns \"{$domain_string}\";\n";
418
				}
419

    
420
				if ($a_client['pfs_group'])
421
					$racoonconf .= "\tpfs_group {$a_client['pfs_group']};\n";
422

    
423
				if ($a_client['login_banner']) {
424
					@file_put_contents("{$g['varetc_path']}/ipsec/racoon.motd", $a_client['login_banner']);
425
					$racoonconf .= "\tbanner \"{$g['varetc_path']}/ipsec/racoon.motd\";\n";
426
				}
427

    
428
				if (isset($a_client['save_passwd']))
429
					$racoonconf .= "\tsave_passwd on;\n";
430

    
431
				$racoonconf .= "}\n\n";
432
			}
433
			/* end mode_cfg section */
434

    
435
			if ($a_client['user_source'] != "none") {
436
				$authcfgs = explode(",", $a_client['user_source']);
437
				$sed = "\$authmodes=array(";
438
				$firstsed = 0;
439
				foreach ($authcfgs as $authcfg) {
440
					if ($authcfg == "system")
441
						$authcfg = "Local Database";
442
					if ($firstsed > 0)
443
						$sed .= ",";
444
					$firstsed = 1;
445
					$sed .= "\"{$authcfg}\"";
446
				}
447
				$sed .= ");\\\n";
448
				if ($a_client['strictusercn'])
449
					$sed .= "\$strictusercn = true;";
450
				mwexec("/bin/cat /etc/inc/ipsec.auth-user.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' >  {$g['varetc_path']}/ipsec/ipsec.php");
451
				mwexec("/bin/chmod a+x {$g['varetc_path']}/ipsec/ipsec.php");
452
				$racoonconf .= "extcfg { script \"{$g['varetc_path']}/ipsec/ipsec.php\" }\n";
453
			}
454

    
455
			/* begin remote sections */
456
			if (is_array($a_phase1) && count($a_phase1)) {
457
				/* begin remote */
458
				foreach ($a_phase1 as $ph1ent) {
459

    
460
					if (isset($ph1ent['disabled']))
461
						continue;
462

    
463
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
464
						continue;
465

    
466
					$ikeid = $ph1ent['ikeid'];
467

    
468
					$ep = ipsec_get_phase1_src($ph1ent);
469
					if (!$ep)
470
						continue;
471

    
472
					if (!isset($ph1ent['mobile'])) {
473
						$rgip = $rgmap[$ph1ent['remote-gateway']];
474
						if (!$rgip)
475
							continue;
476
					}
477

    
478
					$myid_type = $ph1ent['myid_type'];
479

    
480
					switch ($myid_type) {
481

    
482
						case "myaddress":
483
							$myid_type = "address";
484
							$myid_data = $ep;
485
							break;
486

    
487
						case "dyn_dns":
488
							$myid_type = "address";
489
							$myid_data = resolve_retry($ph1ent['myid_data']);
490
							break;
491

    
492
						case "address";
493
							$myid_data = $ph1ent['myid_data'];
494
							break;
495

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

    
506
					$peerid_type = $ph1ent['peerid_type'];
507

    
508
					switch ($peerid_type) {
509
						case "peeraddress":
510
							$peerid_type = "address";
511
							$peerid_data = $rgip;
512
							break;
513

    
514
						case "address";
515
							$peerid_data = $ph1ent['peerid_data'];
516
							break;
517

    
518
						case "fqdn";
519
						case "keyid tag";
520
						case "user_fqdn";
521
						case "asn1dn";
522
							$peerid_data = $ph1ent['peerid_data'];
523
							if( $peerid_data )
524
								$peerid_data = "\"".$peerid_data."\"";
525
							break;
526
					}
527

    
528
					$natt = "off";
529
					if (isset($ph1ent['nat_traversal']))
530
						$natt = $ph1ent['nat_traversal'];
531

    
532
					$init = "on";
533
					$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "off";
534
					$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "claim";
535
					$passive = "";
536
					if (isset($ph1ent['mobile'])) {
537
						$rgip = "anonymous";
538
						$passive = "passive on;";
539
						$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "obey";
540
						/* Mimic 1.2.3's behavior for pure-psk mobile tunnels */
541
						if ($ph1ent['authentication_method'] == "pre_shared_key") {
542
							$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "on";
543
						} else {
544
							$init = "off";
545
							$genp = !empty($ph1ent['generate_policy']) ? $ph1ent['generate_policy'] : "unique";
546
						}
547
					}
548

    
549
					$dpdline1 = '';
550
					$dpdline2 = '';
551
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
552
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
553
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
554
					}
555

    
556
					if (isset ($ph1ent['authentication_method']))
557
						$authmethod = $ph1ent['authentication_method'];
558
					else
559
						$authmethod = 'pre_shared_key';
560

    
561
					$certline = '';
562

    
563
					if (strstr($authmethod,'rsa')) {
564

    
565
						$cert = lookup_cert($ph1ent['certref']);
566

    
567
						if (!$cert)
568
						{
569
							log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
570
							continue;
571
						}
572

    
573
						$certfile = "cert-{$ikeid}.crt";
574
						$certpath = "{$g['varetc_path']}/ipsec/{$certfile}";
575

    
576
						if (!file_put_contents($certpath, base64_decode($cert['crt'])))
577
						{
578
							log_error(sprintf(gettext("Error: Cannot write phase1 certificate file for %s"), $ph1ent['name']));
579
							continue;
580
						}
581

    
582
						chmod($certpath, 0600);
583

    
584
						$keyfile = "cert-{$ikeid}.key";
585
						$keypath = "{$g['varetc_path']}/ipsec/{$keyfile}";
586

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

    
593
						chmod($keypath, 0600);
594

    
595
						$ca = lookup_ca($ph1ent['caref']);
596
						if ($ca) {
597
							$cafile = "ca-{$ikeid}.crt";
598
							$capath = "{$g['varetc_path']}/ipsec/{$cafile}";
599

    
600
							if (!file_put_contents($capath, base64_decode($ca['crt'])))
601
							{
602
								log_error(sprintf(gettext("Error: Cannot write phase1 CA certificate file for %s"), $ph1ent['name']));
603
								continue;
604
							}
605

    
606
							chmod($capath, 0600);
607
							$caline = "ca_type x509 \"{$cafile}\";";
608
						}
609

    
610
						$certline = "certificate_type x509 \"{$certfile}\" \"{$keyfile}\";";
611

    
612
					}
613

    
614
					$ealgos = '';
615
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
616
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
617
					if ($ealg_kl)
618
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
619
					else
620
						$ealgos = $ealgos.$ealg_id;
621

    
622
					$lifeline = '';
623
					if ($ph1ent['lifetime'])
624
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
625

    
626
					/* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */
627
					if (!(($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))) {
628
						$peerid_spec = "peers_identifier {$peerid_type} {$peerid_data};";
629
						if (isset($ph1ent['verify_identifier']))
630
							$peerid_verify = "verify_identifier on;";
631
					}
632

    
633
					/* add remote section to configuration */
634

    
635
					$racoonconf .=<<<EOD
636

    
637
remote {$rgip}
638
{
639
	ph1id {$ikeid};
640
	exchange_mode {$ph1ent['mode']};
641
	my_identifier {$myid_type} {$myid_data};
642
	{$peerid_spec}
643
	{$peerid_verify}
644
	ike_frag on;
645
	generate_policy = {$genp};
646
	initial_contact = {$init};
647
	nat_traversal = {$natt};
648
	{$certline}
649
	{$caline}
650
	{$dpdline1}
651
	{$dpdline2}
652
	support_proxy on;
653
	proposal_check {$pcheck};
654
	{$passive}
655

    
656
	proposal
657
	{
658
		authentication_method {$authmethod};
659
		encryption_algorithm ${ealgos};
660
		hash_algorithm {$ph1ent['hash-algorithm']};
661
		dh_group {$ph1ent['dhgroup']};
662
		${lifeline}
663
	}
664
}
665

    
666
EOD;
667
				}
668
				/* end remote */
669
			}
670
			/* end remote sections */
671

    
672
			/* begin sainfo sections */
673
			if (is_array($a_phase2) && count($a_phase2)) {
674

    
675
				/* begin sainfo */
676
				foreach ($a_phase2 as $ph2ent) {
677

    
678
					$ikeid = $ph2ent['ikeid'];
679

    
680
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
681
						continue;
682

    
683
					if (isset($ph1ent['disabled']))
684
						continue;
685

    
686
					if (isset($ph2ent['disabled']))
687
						continue;
688

    
689
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
690
						continue;
691

    
692
					if (($ph2ent['mode'] == 'tunnel') or ($ph2ent['mode'] == 'tunnel6')) {
693

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

    
725
						if (!isset($ph2ent['mobile'])) {
726
							$remoteid_type = $ph2ent['remoteid']['type'];
727
							if ($remoteid_type != "address")
728
								$remoteid_type = "subnet";
729

    
730
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid'], false, $ph2ent['mode']);
731
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
732
						} else
733
							$remoteid_spec = "anonymous";
734

    
735
					} else {
736
						$rgip = $rgmap[$ph1ent['remote-gateway']];
737

    
738
						if ((($ph1ent['authentication_method'] == "xauth_psk_server") ||
739
							($ph1ent['authentication_method'] == "pre_shared_key"))
740
							&& isset($ph1ent['mobile']))
741
							$localid_spec = " ";
742
						else {
743
							$localid_data = ipsec_get_phase1_src($ph1ent);
744
							if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
745
							$localid_spec = "address {$localid_data}";
746
						}
747
						if (!isset($ph2ent['mobile'])) {
748
							$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
749
							if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
750
							$remoteid_spec = "address {$remoteid_data}";
751
						} else
752
							$remoteid_spec = "anonymous";
753
					}
754

    
755
					if($ph2ent['protocol'] == 'esp') {
756

    
757
						$ealgos = '';
758

    
759
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
760

    
761
							$ealg_id = $ealg['name'];
762
							$ealg_kl = $ealg['keylen'];
763

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

    
799
						$ealgosline = "encryption_algorithm {$ealgos};";
800

    
801
					} else {
802

    
803
						$ealgosline = "encryption_algorithm null_enc;";
804
					}
805

    
806
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
807
					$halgosline = "authentication_algorithm {$halgos};";
808

    
809
					$pfsline = '';
810
					if ($ph2ent['pfsgroup'])
811
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
812
					if (isset($a_client['pfs_group'])) {
813
						$pfsline = '';
814
						if ($a_client['pfs_group'])
815
							$pfsline = "pfs_group {$a_client['pfs_group']};";
816
					}
817

    
818
					$lifeline = '';
819
					if ($ph2ent['lifetime'])
820
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
821

    
822
					/* add sainfo section to configuration */
823

    
824
					$racoonconf .=<<<EOD
825

    
826
sainfo {$localid_spec} {$remoteid_spec}
827
{
828
	remoteid {$ikeid};
829
	{$ealgosline}
830
	{$halgosline}
831
	{$pfsline}
832
	{$lifeline}
833
	compression_algorithm deflate;
834
}
835

    
836
EOD;
837
				}
838
				/* end sainfo */
839
			}
840
			/* end sainfo sections */
841
		}
842
		@file_put_contents("{$g['varetc_path']}/ipsec/racoon.conf", $racoonconf);
843
		unset($racoonconf);
844
		/* end racoon.conf */
845

    
846
		/* generate IPsec policies */
847
		/* generate spd.conf */
848
		$spdconf = "";
849
		$natfilterrules = false;
850
		if (is_array($a_phase2) && count($a_phase2)) {
851
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
852
			if ($config['interfaces']['lan']) {
853
				$lanip = get_interface_ip("lan");
854
				if (!empty($lanip) && is_ipaddrv4($lanip)) {
855
					$lansn = get_interface_subnet("lan");
856
					$lansa = gen_subnet($lanip, $lansn);
857
					$spdconf .= "spdadd -4 {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
858
					$spdconf .= "spdadd -4 {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
859
				}
860
				$lanipv6 = get_interface_ipv6("lan");
861
				if (!empty($lanipv6) && is_ipaddrv6($lanipv6)) {
862
					$lansnv6 = get_interface_subnetv6("lan");
863
					$lansav6 = gen_subnetv6($lanipv6, $lansnv6);
864
					$spdconf .= "spdadd -6 {$lanipv6}/128 {$lansav6}/{$lansnv6} any -P out none;\n";
865
					$spdconf .= "spdadd -6 {$lansav6}/{$lansnv6} {$lanipv6}/128 any -P in none;\n";
866
				}
867
			}
868

    
869
			foreach ($a_phase2 as $ph2ent) {
870

    
871
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
872
					continue;
873

    
874
				if (isset($ph1ent['mobile']))
875
					continue;
876

    
877
				if (isset($ph1ent['disabled']))
878
					continue;
879

    
880
				if (isset($ph2ent['disabled']))
881
					continue;
882

    
883
				$ep = ipsec_get_phase1_src($ph1ent);
884
				if (!$ep)
885
					continue;
886

    
887
				$rgip = $rgmap[$ph1ent['remote-gateway']];
888
				if(!is_ipaddr($rgip))
889
					continue;
890

    
891
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'], true, $ph2ent['mode']);
892
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'], true, $ph2ent['mode']);
893

    
894
				if(($ph2ent['mode'] == "tunnel") or ($ph2ent['mode'] == 'tunnel6')) {
895
					// Error will be logged above, no need to log this twice. #2201
896
					if (!is_subnet($localid) && ($localid != "0.0.0.0/0"))
897
						continue;
898

    
899
					if($ph2ent['mode'] == "tunnel6")
900
						$family = "-6";
901
					else
902
						$family = "-4";
903

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

    
907
					if (!empty($ph2ent['natlocalid'])) {
908
						$natlocalid = ipsec_idinfo_to_cidr($ph2ent['natlocalid'], true, $ph2ent['mode']);
909
						$spdconf .= "spdadd {$family} {$remoteid} {$natlocalid} any -P in ipsec " .
910
							"{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
911
						$natfilterrules = true;
912
					} else
913
						$spdconf .= "spdadd {$family} {$remoteid} {$localid} any -P in ipsec " .
914
							"{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
915

    
916
				} else {
917

    
918
					$localid_data = ipsec_get_phase1_src($ph1ent);
919
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
920

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

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

    
927
				}
928

    
929
				/* static route needed? */
930
				if (is_ipaddr($ph1ent['interface'])) {
931
					$vip = find_virtual_ip_alias($ph1ent['interface']);
932
					if (preg_match("/^carp|^[a-z0-9]+_vip/i", $vip['interface']))
933
						$parentinterface = link_carp_interface_to_parent($vip['interface']);
934
					else
935
						$parentinterface = $vip['interface'];
936
				} else if (preg_match("/^carp|^[a-z0-9]+_vip/i", $ph1ent['interface']))
937
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
938
				else
939
					$parentinterface = $ph1ent['interface'];
940

    
941
				if (is_ipaddr($rgip)) {
942
					/* add endpoint routes to correct gateway on interface */
943
					if (interface_has_gateway($parentinterface)) {
944
						$gatewayip = get_interface_gateway("$parentinterface");
945
						$interfaceip = get_interface_ip($parentinterface);
946
						$subnet_bits = get_interface_subnet($parentinterface);
947
						$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
948
						/* if the remote gateway is in the local subnet, then don't add a route */
949
						if (! ip_in_subnet($rgip, "{$subnet_ip}/{$subnet_bits}")) {
950
							if(is_ipaddr($gatewayip)) {
951
								/* FIXME: does adding route-to and reply-to on the in/outbound
952
								 * rules fix this? smos@ 13-01-2009 */
953
								// log_error("IPSEC interface is not WAN but {$parentinterface}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
954
								mwexec("/sbin/route change -host {$rgip} {$gatewayip}", true);
955
							}
956
						}
957
					}
958
				}
959
			}
960
		}
961
		@file_put_contents("{$g['varetc_path']}/ipsec/spd.conf", $spdconf);
962
		unset($spdconf);
963

    
964
		/* mange racoon process */
965
		if (is_process_running("racoon")) {
966
			sleep("0.1");
967
			mwexec("/usr/local/sbin/racoonctl -s /var/db/racoon/racoon.sock reload-config", false);
968
			/* load SPD without flushing to be safe on config additions or changes. */
969
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/ipsec/spd.conf", false);
970
		} else {
971
			/* flush SA + SPD entries */
972
			mwexec("/usr/local/sbin/setkey -FP", false);
973
			sleep("0.1");
974
			mwexec("/usr/local/sbin/setkey -F", false);
975
			sleep("0.1");
976
			/* start racoon */
977
			$ipsecdebug = isset($config['ipsec']['racoondebug']) ? "-d -v" : "";
978
			mwexec("/usr/local/sbin/racoon {$ipsecdebug} -f {$g['varetc_path']}/ipsec/racoon.conf", false);
979
			sleep("0.1");
980
			/* load SPD */
981
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/ipsec/spd.conf", false);
982

    
983
		}
984
		if ($natfilterrules == true)
985
			filter_configure();
986
		/* start filterdns, if necessary */
987
		if (count($filterdns_list) > 0) {
988
			$interval = 60;
989
			if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval']))
990
				$interval = $ipseccfg['dns-interval'];
991

    
992
			$hostnames = "";
993
			array_unique($filterdns_list);
994
			foreach ($filterdns_list as $hostname)
995
				$hostnames .= "cmd {$hostname} '/usr/local/sbin/pfSctl -c \"service reload ipsecdns\"'\n";
996
			file_put_contents("{$g['varetc_path']}/ipsec/filterdns-ipsec.hosts", $hostnames);
997
			unset($hostnames);
998

    
999
			if (isvalidpid("{$g['varrun_path']}/filterdns-ipsec.pid"))
1000
				sigkillbypid("{$g['varrun_path']}/filterdns-ipsec.pid", "HUP");
1001
			else {
1002
				mwexec("/usr/local/sbin/filterdns -p {$g['varrun_path']}/filterdns-ipsec.pid -i {$interval} -c {$g['varetc_path']}/ipsec/filterdns-ipsec.hosts -d 1");
1003
			}
1004
		} else {
1005
			killbypid("{$g['varrun_path']}/filterdns-ipsec.pid");
1006
			@unlink("{$g['varrun_path']}/filterdns-ipsec.pid");
1007
		}
1008

    
1009
		vpn_ipsec_failover_configure();
1010

    
1011
		if ($g['booting'])
1012
			echo "done\n";
1013

    
1014
		return count($filterdns_list);
1015
	}
1016
}
1017

    
1018
/*
1019
 * Forcefully restart IPsec
1020
 * This is required for when dynamic interfaces reload
1021
 * For all other occasions the normal vpn_ipsec_configure()
1022
 * will gracefully reload the settings without restarting
1023
 */
1024
function vpn_ipsec_force_reload($interface = "") {
1025
	global $g, $config;
1026

    
1027
	$ipseccfg = $config['ipsec'];
1028

    
1029
	if (!empty($interface) && is_array($ipseccfg['phase1'])) {
1030
		$found = false;
1031
		foreach ($ipseccfg['phase1'] as $ipsec) {
1032
			if (!isset($ipsec['disabled']) && ($ipsec['interface'] == $interface)) {
1033
				$found = true;
1034
				break;
1035
			}
1036
		}
1037
		if (!$found) {
1038
			log_error(sprintf(gettext("Ignoring IPsec racoon daemon reload since there are no tunnels on interface %s"), $interface));
1039
			return;
1040
		}
1041
	}
1042

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

    
1046
	/* wait for process to die */
1047
	sleep(4);
1048

    
1049
	/* kill racoon forcefully */
1050
	if (is_process_running("racoon"))
1051
		mwexec("/usr/bin/killall -9 racoon", true);
1052

    
1053
	/* wait for flushing to finish */
1054
	sleep(1);
1055

    
1056
	/* if ipsec is enabled, start up again */
1057
	if (isset($ipseccfg['enable'])) {
1058
		log_error(gettext("Forcefully reloading IPsec racoon daemon"));
1059
		vpn_ipsec_configure();
1060
	}
1061
}
1062

    
1063
/* master setup for vpn (mpd) */
1064
function vpn_setup() {
1065
	global $g;
1066

    
1067
	if ($g['platform'] == 'jail')
1068
		return;
1069

    
1070
	/* start pptpd */
1071
	vpn_pptpd_configure();
1072

    
1073
	/* start pppoe server */
1074
	vpn_pppoes_configure();
1075

    
1076
	/* setup l2tp */
1077
	vpn_l2tp_configure();
1078
}
1079

    
1080
function vpn_netgraph_support() {
1081
	$iflist = get_configured_interface_list();
1082
	foreach ($iflist as $iface) {
1083
		$realif = get_real_interface($iface);
1084
		/* Get support for netgraph(4) from the nic */
1085
		$ifinfo = pfSense_get_interface_addresses($realif);
1086
		if (!empty($ifinfo) && in_array($ifinfo['iftype'], array("ether", "vlan", "bridge")))
1087
			pfSense_ngctl_attach(".", $realif);
1088
	}
1089
}
1090

    
1091
function vpn_pptpd_configure() {
1092
	global $config, $g;
1093

    
1094
	$syscfg = $config['system'];
1095
	$pptpdcfg = $config['pptpd'];
1096

    
1097
	if ($g['booting']) {
1098
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
1099
			return 0;
1100

    
1101
		echo gettext("Configuring PPTP VPN service... ");
1102
	} else {
1103
		/* kill mpd */
1104
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1105

    
1106
		/* wait for process to die */
1107
		sleep(3);
1108

    
1109
		if (is_process_running("mpd -b")) {
1110
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
1111
			log_error(gettext("Could not kill mpd within 3 seconds.   Trying again."));
1112
		}
1113

    
1114
		/* remove mpd.conf, if it exists */
1115
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
1116
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
1117
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
1118
	}
1119

    
1120
	if (empty($pptpdcfg['n_pptp_units'])) {
1121
		log_error("Something wrong in the PPTPd configuration. Preventing starting the daemon because issues would arise.");
1122
		return;
1123
	}
1124

    
1125
	/* make sure pptp-vpn directory exists */
1126
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
1127
		mkdir("{$g['varetc_path']}/pptp-vpn");
1128

    
1129
	switch ($pptpdcfg['mode']) {
1130
		case 'server' :
1131
			/* write mpd.conf */
1132
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
1133
			if (!$fd) {
1134
				printf(gettext("Error: cannot open mpd.conf in vpn_pptpd_configure().") . "\n");
1135
				return 1;
1136
			}
1137

    
1138
			$mpdconf = <<<EOD
1139
pptps:
1140

    
1141
EOD;
1142

    
1143
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1144
				$mpdconf .= "	load pt{$i}\n";
1145
			}
1146

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

    
1149
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1150

    
1151
				$mpdconf .= <<<EOD
1152

    
1153
pt{$i}:
1154
	new -i pptpd{$i} pt{$i} pt{$i}
1155
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1156
	load pts
1157

    
1158
EOD;
1159
			}
1160

    
1161
			$mpdconf .=<<<EOD
1162

    
1163
pts:
1164
	set iface disable on-demand
1165
	set iface enable proxy-arp
1166
	set iface enable tcpmssfix
1167
	set iface idle 1800
1168
	set iface up-script /usr/local/sbin/vpn-linkup
1169
	set iface down-script /usr/local/sbin/vpn-linkdown
1170
	set bundle enable multilink
1171
	set bundle enable crypt-reqd
1172
	set link yes acfcomp protocomp
1173
	set link no pap chap
1174
	set link enable chap-msv2
1175
	set link mtu 1460
1176
	set link keep-alive 10 60
1177
	set ipcp yes vjcomp
1178
	set bundle enable compression
1179
	set ccp yes mppc
1180
	set ccp yes mpp-e128
1181
	set ccp yes mpp-stateless
1182

    
1183
EOD;
1184

    
1185
			if (!isset ($pptpdcfg['req128'])) {
1186
				$mpdconf .=<<<EOD
1187
	set ccp yes mpp-e40
1188
	set ccp yes mpp-e56
1189

    
1190
EOD;
1191
			}
1192

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

    
1196
			if (!empty($pptpdcfg['dns1'])) {
1197
				$mpdconf .= "	set ipcp dns " . $pptpdcfg['dns1'];
1198
				if (!empty($pptpdcfg['dns2']))
1199
					$mpdconf .= " " . $pptpdcfg['dns2'];
1200
				$mpdconf .= "\n";
1201
			} elseif (isset ($config['dnsmasq']['enable'])) {
1202
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1203
				if ($syscfg['dnsserver'][0])
1204
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1205
				$mpdconf .= "\n";
1206
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1207
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1208
			}
1209

    
1210
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1211
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1212
				$acctport = $authport + 1;
1213
				$mpdconf .=<<<EOD
1214
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1215

    
1216
EOD;
1217
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1218
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1219
				$acctport = $authport + 1;
1220
				$mpdconf .=<<<EOD
1221
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret2']}" {$authport} {$acctport}
1222

    
1223
EOD;
1224
			}
1225
			$mpdconf .=<<<EOD
1226
	set radius retries 3
1227
	set radius timeout 10
1228
	set auth enable radius-auth
1229

    
1230
EOD;
1231

    
1232
				if (isset ($pptpdcfg['radius']['accounting'])) {
1233
					$mpdconf .=<<<EOD
1234
	set auth enable radius-acct
1235
	set radius acct-update 300
1236

    
1237
EOD;
1238
				}
1239
			}
1240

    
1241
			fwrite($fd, $mpdconf);
1242
			fclose($fd);
1243
			unset($mpdconf);
1244

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

    
1252
			$mpdlinks = "";
1253

    
1254
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1255
				$mpdlinks .=<<<EOD
1256

    
1257
pt{$i}:
1258
	set link type pptp
1259
	set pptp enable incoming
1260
	set pptp disable originate
1261
	set pptp disable windowing
1262

    
1263
EOD;
1264
			}
1265

    
1266
			fwrite($fd, $mpdlinks);
1267
			fclose($fd);
1268
			unset($mpdlinks);
1269

    
1270
			/* write mpd.secret */
1271
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1272
			if (!$fd) {
1273
				printf(gettext("Error: cannot open mpd.secret in vpn_pptpd_configure().") . "\n");
1274
				return 1;
1275
			}
1276

    
1277
			$mpdsecret = "";
1278

    
1279
			if (is_array($pptpdcfg['user'])) {
1280
				foreach ($pptpdcfg['user'] as $user) {
1281
					$pass = str_replace('\\', '\\\\', $user['password']);
1282
					$pass = str_replace('"', '\"', $pass);
1283
					$mpdsecret .= "{$user['name']} \"{$pass}\" {$user['ip']}\n";
1284
				}
1285
			}
1286

    
1287
			fwrite($fd, $mpdsecret);
1288
			fclose($fd);
1289
			unset($mpdsecret);
1290
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1291

    
1292
			vpn_netgraph_support();
1293

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

    
1297
			break;
1298

    
1299
		case 'redir' :
1300
			break;
1301
	}
1302

    
1303
	if ($g['booting'])
1304
		echo "done\n";
1305

    
1306
	return 0;
1307
}
1308

    
1309
function vpn_pppoes_configure() {
1310
	global $config;
1311

    
1312
	if (is_array($config['pppoes']['pppoe'])) {
1313
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1314
			vpn_pppoe_configure($pppoe);
1315
	}
1316
}
1317

    
1318
function vpn_pppoe_configure(&$pppoecfg) {
1319
	global $config, $g;
1320

    
1321
	$syscfg = $config['system'];
1322

    
1323
	/* create directory if it does not exist */
1324
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1325
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1326

    
1327
	if ($g['booting']) {
1328
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1329
			return 0;
1330

    
1331
		echo gettext("Configuring PPPoE VPN service... ");
1332
	} else {
1333
		/* kill mpd */
1334
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1335

    
1336
		/* wait for process to die */
1337
		sleep(2);
1338

    
1339
	}
1340

    
1341
	switch ($pppoecfg['mode']) {
1342

    
1343
		case 'server' :
1344

    
1345
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1346

    
1347
			if ($pppoecfg['paporchap'] == "chap")
1348
				$paporchap = "set link enable chap";
1349
			else
1350
				$paporchap = "set link enable pap";
1351

    
1352
			/* write mpd.conf */
1353
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1354
			if (!$fd) {
1355
				printf(gettext("Error: cannot open mpd.conf in vpn_pppoe_configure().") . "\n");
1356
				return 1;
1357
			}
1358
			$mpdconf = "\n\n";
1359
			$mpdconf .= "poes:\n";
1360

    
1361
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1362
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1363
			}
1364

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

    
1367
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1368

    
1369
				if (isset($pppoecfg['radius']['radiusissueips']) && isset($pppoecfg['radius']['server']['enable'])) {
1370
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1371
				} else {
1372
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1373
				}
1374

    
1375
				$mpdconf .=<<<EOD
1376

    
1377
poes{$pppoecfg['pppoeid']}{$i}:
1378
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1379
	{$isssue_ip_type}
1380
	load pppoe_standard
1381

    
1382
EOD;
1383
			}
1384

    
1385
			$mpdconf .=<<<EOD
1386

    
1387
pppoe_standard:
1388
	set bundle no multilink
1389
	set bundle enable compression
1390
	set auth max-logins 1
1391
	set iface up-script /usr/local/sbin/vpn-linkup
1392
	set iface down-script /usr/local/sbin/vpn-linkdown
1393
	set iface idle 0
1394
	set iface disable on-demand
1395
	set iface disable proxy-arp
1396
	set iface enable tcpmssfix
1397
	set iface mtu 1500
1398
	set link no pap chap
1399
	{$paporchap}
1400
	set link keep-alive 60 180
1401
	set ipcp yes vjcomp
1402
	set ipcp no vjcomp
1403
	set link max-redial -1
1404
	set link mtu 1492
1405
	set link mru 1492
1406
	set ccp yes mpp-e40
1407
	set ccp yes mpp-e128
1408
	set ccp yes mpp-stateless
1409
	set link latency 1
1410
	#set ipcp dns 10.10.1.3
1411
	#set bundle accept encryption
1412

    
1413
EOD;
1414

    
1415
			if (!empty($pppoecfg['dns1'])) {
1416
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1417
				if (!empty($pppoecfg['dns2']))
1418
					$mpdconf .= " " . $pppoecfg['dns2'];
1419
				$mpdconf .= "\n";
1420
			} elseif (isset ($config['dnsmasq']['enable'])) {
1421
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1422
				if ($syscfg['dnsserver'][0])
1423
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1424
				$mpdconf .= "\n";
1425
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1426
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1427
			}
1428

    
1429
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1430
				$radiusport = "";
1431
				$radiusacctport = "";
1432
				if (isset($pppoecfg['radius']['server']['port']))
1433
					$radiusport = $pppoecfg['radius']['server']['port'];
1434
				if (isset($pppoecfg['radius']['server']['acctport']))
1435
					$radiusacctport = $pppoecfg['radius']['server']['acctport'];
1436
				$mpdconf .=<<<EOD
1437
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}" {$radiusport} {$radiusacctport}
1438
	set radius retries 3
1439
	set radius timeout 10
1440
	set auth enable radius-auth
1441

    
1442
EOD;
1443

    
1444
				if (isset ($pppoecfg['radius']['accounting'])) {
1445
					$mpdconf .=<<<EOD
1446
	set auth enable radius-acct
1447

    
1448
EOD;
1449
				}
1450
			}
1451

    
1452
			fwrite($fd, $mpdconf);
1453
			fclose($fd);
1454
			unset($mpdconf);
1455

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

    
1463
			$mpdlinks = "";
1464

    
1465
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1466
				$mpdlinks .=<<<EOD
1467

    
1468
poes{$pppoecfg['pppoeid']}{$i}:
1469
	set phys type pppoe
1470
	set pppoe iface {$pppoe_interface}
1471
	set pppoe service "*"
1472
	set pppoe disable originate
1473
	set pppoe enable incoming
1474

    
1475
EOD;
1476
			}
1477

    
1478
			fwrite($fd, $mpdlinks);
1479
			fclose($fd);
1480
			unset($mpdlinks);
1481

    
1482
			if ($pppoecfg['username']) {
1483
				/* write mpd.secret */
1484
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1485
				if (!$fd) {
1486
					printf(gettext("Error: cannot open mpd.secret in vpn_pppoe_configure().") . "\n");
1487
					return 1;
1488
				}
1489

    
1490
				$mpdsecret = "\n\n";
1491

    
1492
				if (!empty($pppoecfg['username'])) {
1493
					$item = explode(" ", $pppoecfg['username']);
1494
					foreach($item as $userdata) {
1495
						$data = explode(":", $userdata);
1496
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1497
					}
1498
				}
1499

    
1500
				fwrite($fd, $mpdsecret);
1501
				fclose($fd);
1502
				unset($mpdsecret);
1503
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1504
			}
1505

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

    
1510
			/* Get support for netgraph(4) from the nic */
1511
			pfSense_ngctl_attach(".", $pppoe_interface);
1512
			/* fire up mpd */
1513
			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");
1514

    
1515
			break;
1516
	}
1517

    
1518
	if ($g['booting'])
1519
		echo gettext("done") . "\n";
1520

    
1521
	return 0;
1522
}
1523

    
1524
function vpn_l2tp_configure() {
1525
	global $config, $g;
1526

    
1527
	$syscfg = $config['system'];
1528
	$l2tpcfg = $config['l2tp'];
1529

    
1530
	/* create directory if it does not exist */
1531
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1532
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1533

    
1534
	if ($g['booting']) {
1535
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1536
			return 0;
1537

    
1538
		echo gettext("Configuring l2tp VPN service... ");
1539
	} else {
1540
		/* kill mpd */
1541
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1542

    
1543
		/* wait for process to die */
1544
		sleep(8);
1545

    
1546
	}
1547

    
1548
	/* make sure l2tp-vpn directory exists */
1549
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1550
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1551

    
1552
	switch ($l2tpcfg['mode']) {
1553

    
1554
		case 'server' :
1555
			if ($l2tpcfg['paporchap'] == "chap")
1556
				$paporchap = "set link enable chap";
1557
			else
1558
				$paporchap = "set link enable pap";
1559

    
1560
			/* write mpd.conf */
1561
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1562
			if (!$fd) {
1563
				printf(gettext("Error: cannot open mpd.conf in vpn_l2tp_configure().") . "\n");
1564
				return 1;
1565
			}
1566
			$mpdconf = "\n\n";
1567
			$mpdconf .=<<<EOD
1568
l2tps:
1569

    
1570
EOD;
1571

    
1572
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1573
				$mpdconf .= "	load l2tp{$i}\n";
1574
			}
1575

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

    
1578
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1579

    
1580
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1581
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1582
				} else {
1583
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1584
				}
1585

    
1586
				$mpdconf .=<<<EOD
1587

    
1588
l2tp{$i}:
1589
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1590
	{$isssue_ip_type}
1591
	load l2tp_standard
1592

    
1593
EOD;
1594
			}
1595

    
1596
			$mpdconf .=<<<EOD
1597

    
1598
l2tp_standard:
1599
	set bundle disable multilink
1600
	set bundle enable compression
1601
	set bundle yes crypt-reqd
1602
	set ipcp yes vjcomp
1603
	# set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1604
	set ccp yes mppc
1605
	set iface disable on-demand
1606
	set iface enable proxy-arp
1607
	set iface up-script /usr/local/sbin/vpn-linkup
1608
	set iface down-script /usr/local/sbin/vpn-linkdown
1609
	set link yes acfcomp protocomp
1610
	set link no pap chap
1611
	set link enable chap
1612
	set link keep-alive 10 180
1613

    
1614
EOD;
1615

    
1616
			if (is_ipaddr($l2tpcfg['wins'])) {
1617
				$mpdconf .= "	set ipcp nbns {$l2tpcfg['wins']}\n";
1618
			}
1619
			if (is_ipaddr($l2tpcfg['dns1'])) {
1620
				$mpdconf .= "	set ipcp dns " . $l2tpcfg['dns1'];
1621
				if (is_ipaddr($l2tpcfg['dns2']))
1622
					$mpdconf .= " " . $l2tpcfg['dns2'];
1623
				$mpdconf .= "\n";
1624
			} elseif (isset ($config['dnsmasq']['enable'])) {
1625
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1626
				if ($syscfg['dnsserver'][0])
1627
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1628
				$mpdconf .= "\n";
1629
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1630
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1631
			}
1632

    
1633
			if (isset ($l2tpcfg['radius']['enable'])) {
1634
				$mpdconf .=<<<EOD
1635
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1636
	set radius retries 3
1637
	set radius timeout 10
1638
	set auth enable radius-auth
1639

    
1640
EOD;
1641

    
1642
				if (isset ($l2tpcfg['radius']['accounting'])) {
1643
					$mpdconf .=<<<EOD
1644
	set auth enable radius-acct
1645

    
1646
EOD;
1647
				}
1648
			}
1649

    
1650
			fwrite($fd, $mpdconf);
1651
			fclose($fd);
1652
			unset($mpdconf);
1653

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

    
1661
			$mpdlinks = "";
1662

    
1663
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1664
				$mpdlinks .=<<<EOD
1665

    
1666
l2tp{$i}:
1667
	set link type l2tp
1668
	set l2tp enable incoming
1669
	set l2tp disable originate
1670

    
1671
EOD;
1672
			if (!empty($l2tpcfg['secret']))
1673
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1674
			}
1675

    
1676
			fwrite($fd, $mpdlinks);
1677
			fclose($fd);
1678
			unset($mpdlinks);
1679

    
1680
			/* write mpd.secret */
1681
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1682
			if (!$fd) {
1683
				printf(gettext("Error: cannot open mpd.secret in vpn_l2tp_configure().") . "\n");
1684
				return 1;
1685
			}
1686

    
1687
			$mpdsecret = "\n\n";
1688

    
1689
			if (is_array($l2tpcfg['user'])) {
1690
				foreach ($l2tpcfg['user'] as $user)
1691
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1692
			}
1693

    
1694
			fwrite($fd, $mpdsecret);
1695
			fclose($fd);
1696
			unset($mpdsecret);
1697
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1698

    
1699
			vpn_netgraph_support();
1700

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

    
1704
			break;
1705

    
1706
		case 'redir' :
1707
			break;
1708
	}
1709

    
1710
	if ($g['booting'])
1711
		echo "done\n";
1712

    
1713
	return 0;
1714
}
1715

    
1716
/* Walk the tunnels for hostname endpoints. If the hostnames
1717
 * resolve to a different IP now compared to the DNS cache
1718
 * we reload the policies if the endpoint has changed */
1719
function vpn_ipsec_refresh_policies() {
1720
	global $config;
1721
	global $g;
1722

    
1723
	$ipseccfg = $config['ipsec'];
1724
	$a_phase1 = $config['ipsec']['phase1'];
1725
	$a_phase2 = $config['ipsec']['phase2'];
1726

    
1727
	if (isset($ipseccfg['disable'])) {
1728
		return true;
1729
	}
1730

    
1731
	/* Walk the Ipsec tunnel array */
1732
	if (!is_array($a_phase1) || (!count($a_phase1)))
1733
		return;
1734

    
1735
	foreach ($a_phase1 as $phase1) {
1736
		if (isset($phase1['disabled']))
1737
			continue;
1738
		if (is_ipaddr($phase1['remote-gateway']))
1739
			continue;
1740
		$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1741
		$dnscache = trim($dnscache);
1742
		/* we should have the old IP addresses in the dnscache now */
1743
		if(!empty($dnscache)) {
1744
			$oldphase1 = $phase1;
1745
			$oldphase1['remote-gateway'] = $dnscache;
1746
			/* now we need to find all tunnels for this host */
1747
			if (!is_array($a_phase2) || (!count($a_phase2)))
1748
				continue;
1749
			foreach ($a_phase2 as $phase2) {
1750
				if ($phase2['ikeid'] == $phase1['ikeid'])
1751
					reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1752
			}
1753
		}
1754
	}
1755

    
1756
	/* process all generated temporary spd.conf files */
1757
	$tmpfiles = glob("{$g['tmp_path']}/spd.conf.reload.*");
1758
	foreach($tmpfiles as $tmpfile) {
1759
		$ret = mwexec("/usr/local/sbin/setkey -f {$tmpfile} 2>&1", false);
1760
		if ($ret == 0)
1761
			unlink_if_exists($tmpfile);
1762
		else {
1763
			$tmpfile = basename($tmpfile);
1764
			@rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1765
		}
1766
	}
1767
}
1768

    
1769
/* remove SPD polices */
1770
function remove_tunnel_spd_policy($phase1,$phase2) {
1771
	global $config;
1772
	global $g;
1773

    
1774
	if (!$phase1 || !$phase2)
1775
		return false;
1776

    
1777
	if (isset($phase1['mobile']))
1778
		return false;
1779

    
1780
	$spdconf = "";
1781
	$ep = ipsec_get_phase1_src($phase1);
1782
	$gw = trim($phase1['remote-gateway']);
1783
	$sad_arr = ipsec_dump_sad();
1784
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid'], false, $phase2['mode']);
1785

    
1786
	if (!empty($phase2['natlocalid']))
1787
		$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid'], false, $phase2['mode']);
1788
	else
1789
		$local_subnet = ipsec_idinfo_to_cidr($phase2['localid'], false, $phase2['mode']);
1790

    
1791
	if ($phase2['mode'] == "tunnel6")
1792
		$family = "-6";
1793
	else
1794
		$family = "-4";
1795

    
1796
	$spdconf .= "spddelete {$family} {$local_subnet} " .
1797
		"{$remote_subnet} any -P out ipsec " .
1798
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1799
		"{$gw}/unique;\n";
1800

    
1801
	$spdconf .= "spddelete {$family} {$remote_subnet} " .
1802
		"{$local_subnet} any -P in ipsec " .
1803
		"{$phase2['protocol']}/tunnel/{$gw}-" .
1804
		"{$ep}/unique;\n";
1805

    
1806
	/* zap any existing SA entries */
1807
	foreach($sad_arr as $sad) {
1808
		if(($sad['dst'] == $ep) && ($sad['src'] == $gw))
1809
			$spdconf .= "delete {$family} {$ep} {$gw} {$phase2['protocol']} 0x{$sad['spi']};\n";
1810
		if(($sad['src'] == $ep) && ($sad['dst'] == $_gw))
1811
			$spdconf .= "delete {$family} {$gw} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1812
	}
1813

    
1814
	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));
1815

    
1816
	$now = time();
1817
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1818
	/* generate temporary spd.conf */
1819
	@file_put_contents($spdfile, $spdconf);
1820
	unset($spdconf);
1821

    
1822
	return true;
1823
}
1824

    
1825
/* reloads the tunnel configuration for a tunnel item
1826
 * Will remove and add SPD polices */
1827
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1828
	global $config;
1829
	global $g;
1830

    
1831
	/* if we are not passed a old tunnel array we create one */
1832
	if(empty($old_phase1)) {
1833
		$old_phase1 = $phase1;
1834
	}
1835
	if(empty($old_phase2)) {
1836
		$old_phase2 = $phase2;
1837
	}
1838

    
1839
	$sad_arr = ipsec_dump_sad();
1840

    
1841
	$ep = ipsec_get_phase1_src($phase1);
1842
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid'], false, $phase2['mode']);
1843
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid'], false, $phase2['mode']);
1844

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

    
1848
	$old_ep = ipsec_get_phase1_src($old_phase1);
1849
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid'], false, $old_phase2['mode']);
1850
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid'], false, $old_phase2['mode']);
1851

    
1852
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1853
	 * try to resolve it now and add it to the list for filterdns */
1854
	$rgip = "";
1855
	if (!is_ipaddr($phase1['remote-gateway'])) {
1856
		if(! $g['booting']) {
1857
			$rgip = resolve_retry($phase1['remote-gateway']);
1858
			add_hostname_to_watch($phase1['remote-gateway']);
1859
		} else {
1860
			add_hostname_to_watch($phase1['remote-gateway']);
1861
		}
1862
		if (isset($phase1['mobile'])) {
1863
			/* Don't log anything here, it's normal and we should skip it. */
1864
			return false;
1865
		} elseif (!is_ipaddr($rgip)) {
1866
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1867
			return false;
1868
		}
1869
	} else {
1870
		$rgip = $phase1['remote-gateway'];
1871
	}
1872
	if (!$ep) {
1873
		log_error(sprintf(gettext("Could not determine VPN endpoint for '%s'"), $phase1['descr']));
1874
		return false;
1875
	}
1876

    
1877
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1878
		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));
1879
	}
1880
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1881
		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));
1882
	}
1883

    
1884
	$spdconf = "";
1885
	/* Delete old SPD policies if there are changes between the old and new */
1886
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1887
		if($old_phase2['mode'] == "tunnel6")
1888
			$family = "-6";
1889
		else
1890
			$family = "-4";
1891

    
1892
		$spdconf .= "spddelete {$family} {$old_local_subnet} " .
1893
			"{$old_remote_subnet} any -P out ipsec " .
1894
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1895
			"{$old_gw}/unique;\n";
1896
		if (!empty($old_phase2['natlocalid']))
1897
			$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['natlocalid'], false, $old_phase2['mode']);
1898
		$spdconf .= "spddelete {$family} {$old_remote_subnet} " .
1899
			"{$old_local_subnet} any -P in ipsec " .
1900
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1901
			"{$old_ep}/unique;\n";
1902

    
1903
		/* zap any existing SA entries */
1904
		foreach($sad_arr as $sad) {
1905
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1906
				$spdconf .= "delete {$family} {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1907
			}
1908
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1909
				$spdconf .= "delete {$family} {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1910
			}
1911
		}
1912
	}
1913

    
1914
	if($phase2['mode'] == "tunnel6")
1915
		$family = "-6";
1916
	else
1917
		$family = "-4";
1918

    
1919
	/* Create new SPD entries for the new configuration */
1920
	/* zap any existing SA entries beforehand */
1921
	foreach($sad_arr as $sad) {
1922
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1923
			$spdconf .= "delete {$family} {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1924
		}
1925
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1926
			$spdconf .= "delete {$family} {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1927
		}
1928
	}
1929
	/* add new SPD policies to replace them */
1930
	if (!isset($phase1['disabled']) && !isset($phase2['disabled'])) {
1931
		$spdconf .= "spdadd {$family} {$local_subnet} " .
1932
			"{$remote_subnet} any -P out ipsec " .
1933
			"{$phase2['protocol']}/tunnel/{$ep}-" .
1934
			"{$rgip}/unique;\n";
1935

    
1936
		if (!empty($phase2['natlocalid']))
1937
			$local_subnet = ipsec_idinfo_to_cidr($phase2['natlocalid'], false, $phase2['mode']);
1938
		$spdconf .= "spdadd {$family} {$remote_subnet} " .
1939
			"{$local_subnet} any -P in ipsec " .
1940
			"{$phase2['protocol']}/tunnel/{$rgip}-" .
1941
			"{$ep}/unique;\n";
1942
	}
1943

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

    
1946
	$now = time();
1947
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1948
	/* generate temporary spd.conf */
1949
	@file_put_contents($spdfile, $spdconf);
1950
	unset($spdconf);
1951
	/* remove static route to old gw */
1952
	if (is_ipaddr($old_gw))
1953
		mwexec("/sbin/route delete {$old_gw}", true);
1954
	return true;
1955
}
1956

    
1957
function vpn_ipsec_configure_preferoldsa() {
1958
	global $config;
1959
	if(isset($config['ipsec']['preferoldsa']))
1960
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1961
	else
1962
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1963
}
1964

    
1965
?>
(57-57/66)