Project

General

Profile

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

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

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

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

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

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

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

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

    
44
/* include all configuration functions */
45

    
46
function vpn_ipsec_failover_configure() {
47
	global $config, $g;
48

    
49

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

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

    
73
		if(is_process_running("sasyncd"))
74
			mwexec("killall sasyncd", true);
75

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

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

    
85
	/* get the automatic ping_hosts.sh ready */
86
	unlink_if_exists("{$g['vardb_path']}/ipsecpinghosts");
87
	touch("{$g['vardb_path']}/ipsecpinghosts");
88

    
89
	vpn_ipsec_configure_preferoldsa();
90

    
91
	$syscfg = $config['system'];
92
	$ipseccfg = $config['ipsec'];
93
	$a_phase1 = $config['ipsec']['phase1'];
94
	$a_phase2 = $config['ipsec']['phase2'];
95
	$a_client = $config['ipsec']['client'];
96

    
97
	if (!isset($ipseccfg['enable'])) {
98
		mwexec("/sbin/ifconfig enc0 down");
99

    
100
		/* send a SIGKILL to be sure */
101
		sigkillbypid("{$g['varrun_path']}/racoon.pid", "KILL");
102

    
103
		/* kill racoon */
104
		if(is_process_running("racoon"))
105
			mwexec("/usr/bin/killall racoon", true);
106
		killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
107

    
108
		/* wait for racoon process to die */
109
		sleep(2);
110

    
111
		/* flush SPD and SAD */
112
		mwexec("/usr/local/sbin/setkey -F");
113
		mwexec("/usr/local/sbin/setkey -FP");
114

    
115
		/* disallow IPSEC, it is off */
116
//		exec("/sbin/sysctl net.inet.ip.ipsec_in_use=0");
117

    
118
		return true;
119
	} else {
120
		mwexec("/sbin/ifconfig enc0 up");
121

    
122
		if ($g['booting'])
123
			echo "Configuring IPsec VPN... ";
124

    
125
		/* fastforwarding is not compatible with ipsec tunnels */
126
		mwexec("/sbin/sysctl net.inet.ip.fastforwarding=0");
127

    
128
		/* this loads a route table which is used to determine if a route needs to be removed. */
129
		exec("/usr/bin/netstat -rnf inet", $route_arr, $retval);
130
		$route_str = implode("\n", $route_arr);
131

    
132
		/* resolve all local, peer addresses and setup pings */
133
		$ipmap = array();
134
		$rgmap = array();
135
		$dnswatch_list = array();
136
		if (is_array($a_phase1) && count($a_phase1)) {
137

    
138
			/* step through each phase1 entry */
139
			foreach ($a_phase1 as $ph1ent) {
140
				if (isset($ph1ent['disabled']))
141
					continue;
142

    
143
				$ep = ipsec_get_phase1_src($ph1ent);
144
				if (!$ep)
145
					continue;
146

    
147
				if(!in_array($ep,$ipmap))
148
					$ipmap[] = $ep;
149

    
150
				/* see if this tunnel has a hostname for the remote-gateway. If so,
151
				   try to resolve it now and add it to the list for dnswatch */
152

    
153
				if (isset ($ph1ent['mobile']))
154
					continue;
155

    
156
				$rg = $ph1ent['remote-gateway'];
157

    
158
				if (!is_ipaddr($rg)) {
159
					$dnswatch_list[] = "{$rg} = value";
160
					add_hostname_to_watch($rg);
161
					$rg = resolve_retry($rg);
162
					if (!$rg)
163
						continue;
164
				}
165

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

    
168
				/* step through each phase2 entry */
169
				$ipsecpinghosts = "";
170
				foreach ($a_phase2 as $ph2ent) {
171

    
172
					$ikeid = $ph2ent['ikeid'];
173

    
174
					if (isset($ph2ent['disabled']))
175
						continue;
176

    
177
					if ($ikeid != $ph1ent['ikeid'])
178
						continue;
179

    
180
					/* add an ipsec pinghosts entry */
181
					if ($ph2ent['pinghost']) {
182
						$iflist = get_configured_interface_list();
183
						foreach ($iflist as $ifent => $ifname) {
184
							$interface_ip = get_interface_ip($ifent);
185
							$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
186
							if (ip_in_subnet($interface_ip, $local_subnet)) {
187
								$srcip = $interface_ip;
188
								break;
189
							}
190
						}
191
						$dstip = $ph2ent['pinghost'];
192
						if (is_ipaddr($srcip))
193
							$ipsecpinghosts .= "{$srcip}|{$dstip}|3\n";
194
					}
195
				}
196
				$pfd = fopen("{$g['vardb_path']}/ipsecpinghosts", "w");
197
				if ($pfd) {
198
					fwrite($pfd, $ipsecpinghosts);
199
					fclose($pfd);
200
				}
201
				
202
			}
203
		}
204

    
205
		/* generate CA certificates files */
206
		if (is_array($config['ca']) && count($config['ca'])) {
207
			foreach ($config['ca'] as $ca) {
208
				if (!isset($ca['crt'])) {
209
					log_error("Error: Invalid certificate info for {$ca['name']}");
210
					continue;
211
				}
212
				$cert = base64_decode($ca['crt']);
213
				$x509cert = openssl_x509_parse(openssl_x509_read($cert));
214
				if (!is_array($x509cert) || !isset($x509cert['hash'])) {
215
					log_error("Error: Invalid certificate hash info for {$ca['name']}");
216
					continue;
217
				}
218
				$fname = $g['varetc_path']."/".$x509cert['hash'].".0";
219
				if (!file_put_contents($fname, $cert)) {
220
					log_error("Error: Cannot write IPsec CA file for {$ca['name']}");
221
					continue;
222
				}
223
			}
224
		}
225
		
226
		/* generate psk.txt */
227
		$fd = fopen("{$g['varetc_path']}/psk.txt", "w");
228
		if (!$fd) {
229
			printf("Error: cannot open psk.txt in vpn_ipsec_configure().\n");
230
			return 1;
231
		}
232

    
233
		$pskconf = "";
234

    
235
		if (is_array($a_phase1) && count($a_phase1)) {
236
			foreach ($a_phase1 as $ph1ent) {
237

    
238
				if (isset($ph1ent['disabled']))
239
					continue;
240

    
241
				if (strstr($ph1ent['authentication_method'],'rsa'))
242
					continue;
243

    
244
				$peerid_type = $ph1ent['peerid_type'];
245

    
246
				switch ($peerid_type) {
247
					case "peeraddress":
248
						$peerid_type = "address";
249
						$peerid_data = $rgmap[$ph1ent['remote-gateway']];
250
						break;
251

    
252
					case "address";
253
						$peerid_data = $ph1ent['peerid_data'];
254
						break;
255

    
256
					case "fqdn";
257
					case "keyid tag";
258
					case "user_fqdn";
259
						$peerid_data = $ph1ent['peerid_data'];
260
						break;
261
				}
262

    
263
				$pskconf .= "{$peerid_data}\t{$ph1ent['pre-shared-key']}\n";
264
			}
265
		}
266

    
267
		/* Add user PSKs */
268
		foreach ($config['system']['user'] as $user) {
269
			if (!empty($user['ipsecpsk'])) {
270
				$pskconf .= "{$user['name']}\t{$user['ipsecpsk']}\n";
271
			}
272
		}
273

    
274
		/* add PSKs for mobile clients */
275
		if (is_array($ipseccfg['mobilekey'])) {
276
			foreach ($ipseccfg['mobilekey'] as $key) {
277
				$pskconf .= "{$key['ident']}\t{$key['pre-shared-key']}\n";
278
			}
279
		}
280

    
281
		fwrite($fd, $pskconf);
282
		fclose($fd);
283
		chmod("{$g['varetc_path']}/psk.txt", 0600);
284
			
285
		/* begin racoon.conf */
286
		if ((is_array($a_phase1) && count($a_phase1)) ||
287
			(is_array($a_phase2) && count($a_phase2))) {
288

    
289
			$fd = fopen("{$g['varetc_path']}/racoon.conf", "w");
290
			if (!$fd) {
291
				printf("Error: cannot open racoon.conf in vpn_ipsec_configure().\n");
292
				return 1;
293
			}
294

    
295
			$racoonconf = "# This file is automatically generated. Do not edit\n";			
296
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
297
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
298

    
299
			/* begin listen section */
300
			if (count($ipmap)) {
301
				$racoonconf .= "\nlisten\n";
302
				$racoonconf .= "{\n";
303
				$racoonconf .= "	adminsock \"/var/db/racoon/racoon.sock\" \"root\" \"wheel\" 0660;\n";
304
				foreach ($ipmap as $addr) {
305
					$racoonconf .= "\tisakmp {$addr} [500];\n";
306
					$racoonconf .= "\tisakmp_natt {$addr} [4500];\n";
307
				}
308
				$racoonconf .= "}\n\n";
309
			}
310

    
311
			/* begin mode_cfg section */
312
			if (is_array($a_client) && isset($a_client['enable'])) {
313

    
314
				$racoonconf .= "\nmode_cfg\n";
315
				$racoonconf .= "{\n";
316

    
317
				if ($a_client['user_source'])
318
					$racoonconf .= "\tauth_source {$a_client['user_source']};\n";
319
				if ($a_client['group_source'])
320
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
321

    
322
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
323
					$pool_address = $a_client['pool_address'];
324
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
325

    
326
					$pool_address = long2ip32(ip2long($pool_address)+1);
327
					$pool_size = (~ip2long($pool_netmask) & 0xFFFFFFFF) - 2;
328

    
329
					$racoonconf .= "\tpool_size {$pool_size};\n";
330
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
331
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
332
				}
333

    
334
				if (isset($a_client['net_list'])) {
335

    
336
					$net_list = '';
337

    
338
					foreach ($a_phase2 as $ph2ent) {
339

    
340
						if (isset($ph2ent['disabled']))
341
							continue;
342

    
343
						if (!isset($ph2ent['mobile']))
344
							continue;
345

    
346
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
347

    
348
						if ($net_list)
349
							$net_list .= ", ";
350
						$net_list .= $localid;
351
					}
352

    
353
					if ($net_list)
354
						$racoonconf .= "\tsplit_network include {$net_list};\n";
355
				}
356

    
357
				if ($a_client['dns_server1'])
358
					$racoonconf .= "\tdns4 {$a_client['dns_server1']};\n";
359
				if ($a_client['dns_server2'])
360
					$racoonconf .= "\tdns4 {$a_client['dns_server2']};\n";
361
				if ($a_client['dns_server3'])
362
					$racoonconf .= "\tdns4 {$a_client['dns_server3']};\n";
363
				if ($a_client['dns_server4'])
364
					$racoonconf .= "\tdns4 {$a_client['dns_server4']};\n";
365

    
366
				if ($a_client['wins_server1'])
367
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
368
				if ($a_client['wins_server2'])
369
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
370

    
371
				if ($a_client['dns_domain']) {
372
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
373
					$racoonconf .= "\tsplit_dns \"{$a_client['dns_domain']}\";\n";
374
				}
375

    
376
				if ($a_client['pfs_group'])
377
					$racoonconf .= "\tpfs_group {$a_client['pfs_group']};\n";
378

    
379
				if ($a_client['login_banner']) {
380
					$fn = "{$g['varetc_path']}/racoon.motd";
381
					$fd1 = fopen($fn, "w");
382
					if (!$fd1) {
383
						printf("Error: cannot open server{$fn} in vpn.\n");
384
						return 1;
385
					}
386

    
387
					fwrite($fd1, $a_client['login_banner']);
388
					fclose($fd1);
389

    
390
					$racoonconf .= "\tbanner \"{$fn}\";\n";
391
				}
392

    
393
				$racoonconf .= "}\n\n";
394
			}
395
			/* end mode_cfg section */
396

    
397
			/* begin remote sections */
398
			if (is_array($a_phase1) && count($a_phase1)) {
399
				/* begin remote */
400
				foreach ($a_phase1 as $ph1ent) {
401

    
402
					if (isset($ph1ent['disabled']))
403
						continue;
404

    
405
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
406
						continue;
407

    
408
					$ikeid = $ph1ent['ikeid'];
409

    
410
					$ep = ipsec_get_phase1_src($ph1ent);
411
					if (!$ep)
412
						continue;
413

    
414
					if (!isset($ph1ent['mobile'])) {
415
						$rgip = $rgmap[$ph1ent['remote-gateway']];
416
						if (!$rgip)
417
							continue;
418
					}
419

    
420
					$myid_type = $ph1ent['myid_type'];
421

    
422
					switch ($myid_type) {
423

    
424
						case "myaddress":
425
							$myid_type = "address";
426
							$myid_data = $ep;
427
							break;
428

    
429
						case "dyn_dns":
430
							$myid_type = "address";
431
							$myid_data = gethostbyname($ph1ent['myid_data']);
432
							break;
433

    
434
						case "address";
435
							$myid_data = $ph1ent['myid_data'];
436
							break;
437

    
438
						case "fqdn";
439
						case "keyid tag";
440
						case "user_fqdn";
441
						case "asn1dn";
442
							$myid_data = $ph1ent['myid_data'];
443
							if( $myid_data )
444
								$myid_data = "\"".$myid_data."\"";
445
							break;
446
					}
447

    
448
					$peerid_type = $ph1ent['peerid_type'];
449

    
450
					switch ($peerid_type) {
451
						case "peeraddress":
452
							$peerid_type = "address";
453
							$peerid_data = $rgip;
454
							break;
455

    
456
						case "address";
457
							$peerid_data = $ph1ent['peerid_data'];
458
							break;
459

    
460
						case "fqdn";
461
						case "keyid tag";
462
						case "user_fqdn";
463
						case "asn1dn";
464
							$peerid_data = $ph1ent['peerid_data'];
465
							if( $peerid_data )
466
								$peerid_data = "\"".$peerid_data."\"";
467
							break;
468
					}
469

    
470
					$natt = "off";
471
					if (isset($ph1ent['nat_traversal']))
472
						$natt = $ph1ent['nat_traversal'];
473

    
474
					$init = "on";
475
					$genp = "off";
476
					$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "claim";
477
					$passive = "";
478
					if (isset($ph1ent['mobile'])) {
479
						$rgip = "anonymous";
480
						/* Mimic 1.2.3's behavior for pure-psk mobile tunnels */
481
						if ($ph1ent['authentication_method'] == "pre_shared_key") {
482
							$passive = "passive on;";
483
							$pcheck = !empty($ph1ent['proposal_check']) ? $ph1ent['proposal_check'] : $pcheck = "obey";
484
							$genp = "on";
485
						} else {
486
							$init = "off";
487
							$genp = "unique";
488
						}
489
					}
490

    
491
					$dpdline1 = '';
492
					$dpdline2 = '';
493
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
494
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
495
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
496
					}
497

    
498
					if (isset ($ph1ent['authentication_method']))
499
						$authmethod = $ph1ent['authentication_method'];
500
					else
501
						$authmethod = 'pre_shared_key';
502

    
503
					$certline = '';
504

    
505
					if (strstr($authmethod,'rsa')) {
506

    
507
						$cert = lookup_cert($ph1ent['certref']);
508

    
509
						if (!$cert)
510
						{
511
							log_error("Error: Invalid phase1 certificate reference for {$ph1ent['name']}");
512
							continue;
513
						}
514

    
515
						$certfile = "cert-".$ikeid.".crt";
516
						$certpath = $g['varetc_path']."/".$certfile;
517

    
518
						if (!file_put_contents($certpath, base64_decode($cert['crt'])))
519
						{
520
							log_error("Error: Cannot write phase1 certificate file for {$ph1ent['name']}");
521
							continue;
522
						}
523

    
524
						chmod($certpath, 0600);
525

    
526
						$keyfile = "cert-".$ikeid.".key";
527
						$keypath = $g['varetc_path']."/".$keyfile;
528

    
529
						if (!file_put_contents($keypath, base64_decode($cert['prv'])))
530
						{
531
							log_error("Error: Cannot write phase1 key file for {$ph1ent['name']}");
532
							continue;
533
						}
534

    
535
						chmod($keypath, 0600);
536

    
537
						$ca = lookup_ca($ph1ent['caref']);
538
						if ($ca) {
539
							$cafile = "ca-".$ikeid.".crt";
540
							$capath = $g['varetc_path']."/".$cafile;
541

    
542
							if (!file_put_contents($capath, base64_decode($ca['crt'])))
543
							{
544
								log_error("Error: Cannot write phase1 CA certificate file for {$ph1ent['name']}");
545
								continue;
546
							}
547

    
548
							chmod($capath, 0600);
549
							$caline = "ca_type x509 \"".basename($capath)."\";";
550
						}
551

    
552
						$certline = "certificate_type x509 \"".basename($certpath)."\" \"".basename($keypath)."\";";
553

    
554
					}
555

    
556
					$ealgos = '';
557
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
558
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
559
					if ($ealg_kl)
560
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
561
					else
562
						$ealgos = $ealgos.$ealg_id;
563

    
564
					$lifeline = '';
565
					if ($ph1ent['lifetime'])
566
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
567

    
568
					/* Only specify peer ID if we are not dealing with a mobile PSK-only tunnel */
569
					if (!(($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))) {
570
						$peerid_spec = "peers_identifier {$peerid_type} {$peerid_data};";
571
					}
572

    
573
					/* add remote section to configuration */
574

    
575
					$racoonconf .=<<<EOD
576

    
577
remote {$rgip}
578
{
579
	ph1id {$ikeid};
580
	exchange_mode {$ph1ent['mode']};
581
	my_identifier {$myid_type} {$myid_data};
582
	{$peerid_spec}
583
	ike_frag on;
584
	generate_policy = {$genp};
585
	initial_contact = {$init};
586
	nat_traversal = {$natt};
587
	{$certline}
588
	{$caline}
589
	{$dpdline1}
590
	{$dpdline2}
591
	support_proxy on;
592
	proposal_check {$pcheck};
593
	{$passive}
594

    
595
	proposal
596
	{
597
		authentication_method {$authmethod};
598
		encryption_algorithm ${ealgos};
599
		hash_algorithm {$ph1ent['hash-algorithm']};
600
		dh_group {$ph1ent['dhgroup']};
601
		${lifeline}
602
	}
603
}
604

    
605
EOD;
606
				}
607
				/* end remote */
608
			}
609
			/* end remote sections */
610
		
611
			/* begin sainfo sections */
612
			if (is_array($a_phase2) && count($a_phase2)) {
613

    
614
				/* begin sainfo */
615
				foreach ($a_phase2 as $ph2ent) {
616

    
617
					$ikeid = $ph2ent['ikeid'];
618

    
619
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
620
						continue;
621

    
622
					if (isset($ph1ent['disabled']))
623
						continue;
624

    
625
					if (isset($ph2ent['disabled']))
626
						continue;
627

    
628
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
629
						continue;
630

    
631
					if ($ph2ent['mode'] == 'tunnel') {
632

    
633
						$localid_type = $ph2ent['localid']['type'];
634
						$localid_data = ipsec_idinfo_to_cidr($ph2ent['localid']);
635
						/* Do not print localid in some cases, such as a pure-psk mobile tunnel */
636
						if (($localid_type == "none") || ($ph1ent['authentication_method'] == "pre_shared_key") && isset($ph1ent['mobile']))
637
							$localid_spec = " ";
638
						else if ($localid_type != "address") {
639
							$localid_type = "subnet";
640
							$localid_spec = $localid_type." ".$localid_data." any";
641
						}
642

    
643
						if (!isset($ph2ent['mobile'])) {
644
							$remoteid_type = $ph2ent['remoteid']['type'];
645
							if ($remoteid_type != "address")
646
								$remoteid_type = "subnet";
647

    
648
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
649
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
650
						} else
651
							$remoteid_spec = "anonymous";
652

    
653
					} else {
654

    
655
						$rgip = $rgmap[$ph1ent['remote-gateway']];
656

    
657
						$localid_data = ipsec_get_phase1_src($ph1ent);
658
						if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
659
						$localid_spec = "address {$localid_data}";
660

    
661
						$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
662
						if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
663
						$remoteid_spec = "address {$remoteid_data}";
664
					}
665

    
666
					if($ph2ent['protocol'] == 'esp') {
667

    
668
						$ealgos = '';
669

    
670
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
671

    
672
							$ealg_id = $ealg['name'];
673
							$ealg_kl = $ealg['keylen'];
674

    
675
							if ($ealg_kl) {
676
								if( $ealg_kl == "auto" ) {
677
									/*   This seems to be required on my system and was not reproducable
678
									 *   on other systems.   For some reason $p2_ealgos is not defined
679
									 *   and needs to be read back in!?  -sullrich Aug 26, 2009 
680
									 */
681
									if(!$p2_ealgos)
682
										require("ipsec.inc");
683
									$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
684
									$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
685
									$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
686
									/* in some cases where include ordering is suspect these variables
687
									   are somehow 0 and we enter this loop forever and timeout after 900
688
									   seconds wrecking bootup */
689
									if($key_hi != 0 and $key_lo !=0 and $key_step !=0) {
690
										for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
691
//											Uncomment the next line if you want to test the comment 5 lines up.											
692
//											echo "$keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step \n";
693
											if ($ealgos)
694
												$ealgos = $ealgos.", ";
695
											$ealgos = $ealgos.$ealg_id." ".$keylen;
696
										}
697
									}
698
								} else {
699
									if ($ealgos)
700
										$ealgos = $ealgos.", ";
701
									$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
702
								}
703
							} else {
704
								if ($ealgos)
705
									$ealgos = $ealgos.", ";
706
								$ealgos = $ealgos.$ealg_id;
707
							}
708
						}
709

    
710
						$ealgosline = "encryption_algorithm {$ealgos};";
711

    
712
					} else {
713

    
714
						$ealgosline = "encryption_algorithm null_enc;";
715
					}
716

    
717
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
718
					$halgosline = "authentication_algorithm {$halgos};";
719

    
720
					$pfsline = '';
721
					if ($ph2ent['pfsgroup'])
722
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
723
					if (isset($a_client['pfs_group'])) {
724
						$pfsline = '';
725
						if ($a_client['pfs_group'])
726
							$pfsline = "pfs_group {$a_client['pfs_group']};";
727
					}
728

    
729
					$lifeline = '';
730
					if ($ph2ent['lifetime'])
731
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
732

    
733
					/* add sainfo section to configuration */
734
					
735
					$racoonconf .=<<<EOD
736
					
737
sainfo {$localid_spec} {$remoteid_spec}
738
{
739
	remoteid {$ikeid};
740
	{$ealgosline}
741
	{$halgosline}
742
	{$pfsline}
743
	{$lifeline}
744
	compression_algorithm deflate;
745
}
746

    
747
EOD;
748
				}
749
				/* end sainfo */
750
			}
751
			/* end sainfo sections */
752

    
753
			fwrite($fd, $racoonconf);
754
			fclose($fd);
755
		}
756
		/* end racoon.conf */
757

    
758
		/* generate IPsec policies */
759
		if (is_array($a_phase2) && count($a_phase2)) {
760
			/* generate spd.conf */
761
			$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
762
			if (!$fd) {
763
				printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
764
				return 1;
765
			}
766

    
767
			$spdconf = "";
768

    
769
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
770
			if ($config['interfaces']['lan']) {
771
				$lanip = get_interface_ip("lan");
772
				if (!empty($lanip) && is_ipaddr($lanip)) {
773
					$lansn = get_interface_subnet("lan");
774
					$lansa = gen_subnet($lanip, $lansn);
775
					$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
776
					$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
777
				}
778
			}
779

    
780
			foreach ($a_phase2 as $ph2ent) {
781

    
782
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
783
					continue;
784

    
785
				if (isset($ph1ent['mobile']))
786
					continue;
787

    
788
				if (isset($ph1ent['disabled']))
789
					continue;
790

    
791
				if (isset($ph2ent['disabled']))
792
					continue;
793

    
794
				$ep = ipsec_get_phase1_src($ph1ent);
795
				if (!$ep)
796
					continue;
797

    
798
				$rgip = $rgmap[$ph1ent['remote-gateway']];
799

    
800
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
801
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
802

    
803
				if($ph2ent['mode'] == "tunnel") {
804

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

    
808
					$spdconf .= "spdadd {$remoteid} {$localid} any -P in ipsec " .
809
						"{$ph2ent['protocol']}/tunnel/{$rgip}-{$ep}/unique;\n";
810

    
811
				} else {
812

    
813
					$localid_data = ipsec_get_phase1_src($ph1ent);
814
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
815

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

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

    
822
				}
823

    
824
				/* static route needed? */
825
				if (preg_match("/^carp|^vip/i", $ph1ent['interface']))
826
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
827
				else
828
					$parentinterface = $ph1ent['interface'];
829

    
830
				if ($parentinterface <> "wan") {
831
					/* add endpoint routes to correct gateway on interface */
832
					if (interface_has_gateway($parentinterface)) {
833
						$gatewayip = get_interface_gateway("$parentinterface");
834
						$interfaceip = get_interface_ip($parentinterface);
835
						$subnet_bits = get_interface_subnet($parentinterface);
836
						$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
837
						/* if the remote gateway is in the local subnet, then don't add a route */
838
						if (! ip_in_subnet($rgip, "{$subnet_ip}/{$subnet_bits}")) {
839
							if(is_ipaddr($gatewayip)) {
840
								/* FIXME: does adding route-to and reply-to on the in/outbound
841
								 * rules fix this? smos@ 13-01-2009 */
842
								log_error("IPSEC interface is not WAN but {$parentinterface}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
843
								mwexec("/sbin/route delete -host {$rgip}");
844
								mwexec("/sbin/route add -host {$rgip} {$gatewayip}");
845
							}
846
						}
847
					}
848
				} else {
849
					if(stristr($route_str, "{$rgip}")) {
850
						mwexec("/sbin/route delete -host {$rgip}", true);
851
					}
852
				}
853
			}
854

    
855
			fwrite($fd, $spdconf);
856
			fclose($fd);
857
		}
858

    
859
		/* needed for racoonctl admin socket */
860
		if (!is_dir("/var/db/racoon"))
861
			mkdir("/var/db/racoon/");
862
		
863
		/* mange racoon process */
864
		if (is_process_running("racoon")) {
865
			sleep("0.1");
866
			mwexec("/usr/local/sbin/racoonctl -s /var/db/racoon/racoon.sock reload-config", false);
867
			/* load SPD without flushing to be safe on config additions or changes. */
868
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
869
		} else {
870
			/* flush SA + SPD entries */
871
			mwexec("/usr/local/sbin/setkey -FP", false);
872
 			sleep("0.1");
873
			mwexec("/usr/local/sbin/setkey -F", false);
874
 			sleep("0.1");
875
//			exec("/sbin/sysctl net.inet.ip.ipsec_in_use=1");
876
 			/* start racoon */
877
			mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf", false);
878
 			sleep("0.1");
879
 			/* load SPD */
880
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
881

    
882
			/* start dnswatch, if necessary */
883
			if (count($dnswatch_list) > 0) {
884
				$interval = 60;
885
				if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval']))
886
					$interval = $ipseccfg['dns-interval'];
887

    
888
				$hostnames = "";
889
				array_unique($dnswatch_list);
890
				$hostnames = implode("\n", $dnswatch_list);
891
				file_put_contents("{$g['varetc_path']}/dnswatch-ipsec.hosts", $hostnames);
892

    
893
				killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
894
				mwexec("/usr/local/sbin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval /etc/rc.newipsecdns {$g['varetc_path']}/dnswatch-ipsec.hosts");
895
			}
896
		}
897
	
898
		vpn_ipsec_failover_configure();
899

    
900
		if ($g['booting'])
901
			echo "done\n";
902
	}
903

    
904
	return 0;
905
}
906

    
907
/* Forcefully restart IPsec
908
 * This is required for when dynamic interfaces reload
909
 * For all other occasions the normal vpn_ipsec_configure()
910
 * will gracefully reload the settings without restarting
911
 */
912
function vpn_ipsec_force_reload() {
913
	global $config;
914
	global $g;
915

    
916
	$ipseccfg = $config['ipsec'];
917

    
918
	/* kill racoon */
919
	if(is_process_running("racoon"))
920
		mwexec("/usr/bin/killall racoon", true);
921

    
922
	/* wait for process to die */
923
	sleep(4);
924

    
925
	/* send a SIGKILL to be sure */
926
	sigkillbypid("{$g['varrun_path']}/racoon.pid", "KILL");
927

    
928
	/* wait for flushing to finish */
929
	sleep(1);
930

    
931
	/* if ipsec is enabled, start up again */
932
	if (isset($ipseccfg['enable'])) {
933
		log_error("Forcefully reloading IPsec racoon daemon");
934
		vpn_ipsec_configure();
935
	}
936

    
937
}
938

    
939
/* master setup for vpn (mpd) */
940
function vpn_setup() {
941
	/* start pptpd */
942
	vpn_pptpd_configure();
943

    
944
	/* start pppoe server */
945
	vpn_pppoes_configure();
946

    
947
	/* setup l2tp */
948
	vpn_l2tp_configure();
949
}
950

    
951
function vpn_pptpd_configure() {
952
	global $config, $g;
953

    
954
	$syscfg = $config['system'];
955
	$pptpdcfg = $config['pptpd'];
956

    
957
	if ($g['booting']) {
958
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
959
			return 0;
960

    
961
		echo "Configuring PPTP VPN service... ";
962
	} else {
963
		/* kill mpd */
964
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
965

    
966
		/* wait for process to die */
967
		sleep(3);
968

    
969
		if (is_process_running("mpd -b")) {
970
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
971
			log_error("Could not kill mpd within 3 seconds.   Trying again.");
972
		}
973

    
974
		/* remove mpd.conf, if it exists */
975
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
976
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
977
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
978
	}
979

    
980
	/* make sure pptp-vpn directory exists */
981
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
982
		mkdir("{$g['varetc_path']}/pptp-vpn");
983

    
984
	switch ($pptpdcfg['mode']) {
985
		case 'server' :
986
			/* write mpd.conf */
987
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
988
			if (!$fd) {
989
				printf("Error: cannot open mpd.conf in vpn_pptpd_configure().\n");
990
				return 1;
991
			}
992

    
993
			$mpdconf = <<<EOD
994
pptpd:
995

    
996
EOD;
997

    
998
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
999
				$mpdconf .= "	load pt{$i}\n";
1000
			}
1001

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

    
1004
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1005

    
1006
				$mpdconf .= <<<EOD
1007

    
1008
pt{$i}:
1009
	new -i pptpd{$i} pt{$i} pt{$i}
1010
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1011
	load pts
1012

    
1013
EOD;
1014
			}
1015

    
1016
			$mpdconf .=<<<EOD
1017

    
1018
pts:
1019
	set iface disable on-demand
1020
	set iface enable proxy-arp
1021
	set iface enable tcpmssfix
1022
	set iface idle 1800
1023
	set iface up-script /usr/local/sbin/pptp-linkup
1024
	set iface down-script /usr/local/sbin/vpn-linkdown
1025
	set bundle enable multilink
1026
	set bundle enable crypt-reqd
1027
	set link yes acfcomp protocomp
1028
	set link no pap chap
1029
	set link enable chap-msv2
1030
	set link mtu 1460
1031
	set link keep-alive 10 60
1032
	set ipcp yes vjcomp
1033
	set bundle enable compression
1034
	set ccp yes mppc
1035
	set ccp yes mpp-e128
1036
	set ccp yes mpp-stateless
1037

    
1038
EOD;
1039

    
1040
			if (!isset ($pptpdcfg['req128'])) {
1041
				$mpdconf .=<<<EOD
1042
	set ccp yes mpp-e40
1043
	set ccp yes mpp-e56
1044

    
1045
EOD;
1046
			}
1047

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

    
1051
			if (!empty($pptpdcfg['dns1'])) {
1052
				$mpdconf .= "	set ipcp dns " . $pptpdcfg['dns1'];
1053
				if (!empty($pptpdcfg['dns2']))
1054
					$mpdconf .= " " . $pptpdcfg['dns2'];
1055
				$mpdconf .= "\n";
1056
			} elseif (isset ($config['dnsmasq']['enable'])) {
1057
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1058
				if ($syscfg['dnsserver'][0])
1059
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1060
				$mpdconf .= "\n";
1061
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1062
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1063
			}
1064

    
1065
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1066
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1067
				$acctport = $authport + 1;
1068
				$mpdconf .=<<<EOD
1069
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1070

    
1071
EOD;
1072
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1073
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1074
				$acctport = $authport + 1;
1075
				$mpdconf .=<<<EOD
1076
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret']}" {$authport} {$acctport}
1077

    
1078
EOD;
1079
			}
1080
			$mpdconf .=<<<EOD
1081
	set radius retries 3
1082
	set radius timeout 10
1083
	set auth enable radius-auth
1084

    
1085
EOD;
1086

    
1087
				if (isset ($pptpdcfg['radius']['accounting'])) {
1088
					$mpdconf .=<<<EOD
1089
	set auth enable radius-acct
1090
	set radius acct-update 300
1091

    
1092
EOD;
1093
				}
1094
			}
1095

    
1096
			fwrite($fd, $mpdconf);
1097
			fclose($fd);
1098

    
1099
			/* write mpd.links */
1100
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.links", "w");
1101
			if (!$fd) {
1102
				printf("Error: cannot open mpd.links in vpn_pptpd_configure().\n");
1103
				return 1;
1104
			}
1105

    
1106
			$mpdlinks = "";
1107

    
1108
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1109
				$mpdlinks .=<<<EOD
1110

    
1111
pt{$i}:
1112
	set link type pptp
1113
	set pptp enable incoming
1114
	set pptp disable originate
1115
	set pptp disable windowing
1116

    
1117
EOD;
1118
			}
1119

    
1120
			fwrite($fd, $mpdlinks);
1121
			fclose($fd);
1122

    
1123
			/* write mpd.secret */
1124
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1125
			if (!$fd) {
1126
				printf("Error: cannot open mpd.secret in vpn_pptpd_configure().\n");
1127
				return 1;
1128
			}
1129

    
1130
			$mpdsecret = "";
1131

    
1132
			if (is_array($pptpdcfg['user'])) {
1133
				foreach ($pptpdcfg['user'] as $user)
1134
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1135
			}
1136

    
1137
			fwrite($fd, $mpdsecret);
1138
			fclose($fd);
1139
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1140

    
1141
			/* fire up mpd */
1142
			mwexec("/usr/local/sbin/mpd4 -b -d {$g['varetc_path']}/pptp-vpn -p {$g['varrun_path']}/pptp-vpn.pid -s pptp -f mpd.conf pptpd");
1143

    
1144
			break;
1145

    
1146
		case 'redir' :
1147
			break;
1148
	}
1149

    
1150
	if ($g['booting'])
1151
		echo "done\n";
1152

    
1153
	return 0;
1154
}
1155

    
1156
function vpn_pppoes_configure() {
1157
	global $config;
1158

    
1159
	if (is_array($config['pppoes']['pppoe'])) {
1160
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1161
			vpn_pppoe_configure($pppoe);
1162
	}
1163
}
1164

    
1165
function vpn_pppoe_configure(&$pppoecfg) {
1166
	global $config, $g;
1167

    
1168
	$syscfg = $config['system'];
1169

    
1170
	/* create directory if it does not exist */
1171
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1172
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1173

    
1174
	if ($g['booting']) {
1175
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1176
			return 0;
1177

    
1178
		echo "Configuring PPPoE VPN service... ";
1179
	} else {
1180
		/* kill mpd */
1181
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1182

    
1183
		/* wait for process to die */
1184
		sleep(2);
1185

    
1186
	}
1187

    
1188
	switch ($pppoecfg['mode']) {
1189

    
1190
		case 'server' :
1191

    
1192
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1193

    
1194
			if ($pppoecfg['paporchap'] == "chap")
1195
				$paporchap = "set link enable chap";
1196
			else
1197
				$paporchap = "set link enable pap";
1198

    
1199
			/* write mpd.conf */
1200
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.conf", "w");
1201
			if (!$fd) {
1202
				printf("Error: cannot open mpd.conf in vpn_pppoe_configure().\n");
1203
				return 1;
1204
			}
1205
			$mpdconf = "\n\n";
1206
			$mpdconf .= "pppoe:\n";
1207

    
1208
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1209
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1210
			}
1211

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

    
1214
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1215

    
1216
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['server']['enable'])) {
1217
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1218
				} else {
1219
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1220
				}
1221

    
1222
				$mpdconf .=<<<EOD
1223

    
1224
poes{$pppoecfg['pppoeid']}{$i}:
1225
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1226
	{$isssue_ip_type}
1227
	load pppoe_standart
1228

    
1229
EOD;
1230
			}
1231

    
1232
			$mpdconf .=<<<EOD
1233

    
1234
pppoe_standart:
1235
	set bundle no multilink
1236
	set bundle enable compression
1237
	set auth max-logins 1
1238
	set iface up-script /usr/local/sbin/pppoe-linkup
1239
        set iface down-script /usr/local/sbin/vpn-linkdown
1240
	set iface idle 0
1241
	set iface disable on-demand
1242
	set iface disable proxy-arp
1243
	set iface enable tcpmssfix
1244
	set iface mtu 1500
1245
	set link no pap chap
1246
	{$paporchap}
1247
	set link keep-alive 60 180
1248
	set ipcp yes vjcomp
1249
	set ipcp no vjcomp
1250
	set link max-redial -1
1251
	set link mtu 1492
1252
	set link mru 1492
1253
	set ccp yes mpp-e40
1254
	set ccp yes mpp-e128
1255
	set ccp yes mpp-stateless
1256
	set link latency 1
1257
	#set ipcp dns 10.10.1.3
1258
	#set bundle accept encryption
1259

    
1260
EOD;
1261

    
1262
			if (!empty($pppoecfg['dns1'])) {
1263
				$mpdconf .= "	set ipcp dns " . $pppoecfg['dns1'];
1264
				if (!empty($pppoecfg['dns2']))
1265
					$mpdconf .= " " . $pppoecfg['dns2'];
1266
				$mpdconf .= "\n";
1267
			} elseif (isset ($config['dnsmasq']['enable'])) {
1268
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1269
				if ($syscfg['dnsserver'][0])
1270
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1271
				$mpdconf .= "\n";
1272
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1273
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1274
			}
1275

    
1276
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1277
				$mpdconf .=<<<EOD
1278
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}"
1279
	set radius retries 3
1280
	set radius timeout 10
1281
	set auth enable radius-auth
1282

    
1283
EOD;
1284

    
1285
				if (isset ($pppoecfg['radius']['accounting'])) {
1286
					$mpdconf .=<<<EOD
1287
	set auth enable radius-acct
1288

    
1289
EOD;
1290
				}
1291
			}
1292

    
1293
			fwrite($fd, $mpdconf);
1294
			fclose($fd);
1295

    
1296
			/* write mpd.links */
1297
			$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.links", "w");
1298
			if (!$fd) {
1299
				printf("Error: cannot open mpd.links in vpn_pppoe_configure().\n");
1300
				return 1;
1301
			}
1302

    
1303
			$mpdlinks = "";
1304

    
1305
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1306
				$mpdlinks .=<<<EOD
1307
			
1308
poes{$pppoecfg['pppoeid']}{$i}:
1309
	set phys type pppoe
1310
        set pppoe iface {$pppoe_interface}
1311
        set pppoe service "*"
1312
        set pppoe disable originate
1313
        set pppoe enable incoming
1314

    
1315
EOD;
1316
			}
1317

    
1318
			fwrite($fd, $mpdlinks);
1319
			fclose($fd);
1320

    
1321
			if ($pppoecfg['username']) {
1322
				/* write mpd.secret */
1323
				$fd = fopen("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", "w");
1324
				if (!$fd) {
1325
					printf("Error: cannot open mpd.secret in vpn_pppoe_configure().\n");
1326
					return 1;
1327
				}
1328

    
1329
				$mpdsecret = "\n\n";
1330

    
1331
				if (!empty($pppoecfg['username'])) {
1332
					$item = explode(" ", $pppoecfg['username']);
1333
					foreach($item as $userdata) {
1334
						$data = explode(":", $userdata);
1335
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1336
					}
1337
				}
1338

    
1339
				fwrite($fd, $mpdsecret);
1340
				fclose($fd);
1341
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1342
			}
1343

    
1344
			/* fire up mpd */
1345
			mwexec("/usr/local/sbin/mpd4 -b -d {$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn -p {$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid -s pppoe pppoe");
1346

    
1347
			break;
1348
	}
1349

    
1350
	if ($g['booting'])
1351
		echo "done\n";
1352

    
1353
	return 0;
1354
}
1355

    
1356
function vpn_l2tp_configure() {
1357
	global $config, $g;
1358

    
1359
	$syscfg = $config['system'];
1360
	$l2tpcfg = $config['l2tp'];
1361

    
1362
	/* create directory if it does not exist */
1363
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1364
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1365

    
1366
	if ($g['booting']) {
1367
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1368
			return 0;
1369

    
1370
		echo "Configuring l2tp VPN service... ";
1371
	} else {
1372
		/* kill mpd */
1373
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1374

    
1375
		/* wait for process to die */
1376
		sleep(8);
1377

    
1378
	}
1379

    
1380
	/* make sure l2tp-vpn directory exists */
1381
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1382
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1383

    
1384
	switch ($l2tpcfg['mode']) {
1385

    
1386
		case 'server' :
1387
			if ($l2tpcfg['paporchap'] == "chap")
1388
				$paporchap = "set link enable chap";
1389
			else
1390
				$paporchap = "set link enable pap";
1391

    
1392
			/* write mpd.conf */
1393
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1394
			if (!$fd) {
1395
				printf("Error: cannot open mpd.conf in vpn_l2tp_configure().\n");
1396
				return 1;
1397
			}
1398
			$mpdconf = "\n\n";
1399
			$mpdconf .=<<<EOD
1400
l2tp:
1401

    
1402
EOD;
1403

    
1404
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1405
				$mpdconf .= "	load l2tp{$i}\n";
1406
			}
1407

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

    
1410
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1411

    
1412
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1413
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1414
				} else {
1415
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1416
				}
1417

    
1418
				$mpdconf .=<<<EOD
1419

    
1420
l2tp{$i}:
1421
	new l2tp{$i} l2tp{$i}
1422
	{$isssue_ip_type}
1423
	load l2tp_standard
1424

    
1425
EOD;
1426
			}
1427

    
1428
			$mpdconf .=<<<EOD
1429

    
1430
l2tp_standard:
1431
        set bundle disable multilink
1432
        set bundle enable compression
1433
        set bundle yes crypt-reqd
1434
        set ipcp yes vjcomp
1435
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1436
        set ccp yes mppc
1437
        set iface disable on-demand
1438
        set iface enable proxy-arp
1439
	set iface up-script /usr/local/sbin/l2tp-linkup
1440
        set iface down-script /usr/local/sbin/vpn-linkdown
1441
        set link yes acfcomp protocomp
1442
        set link no pap chap
1443
        set link enable chap
1444
        set link keep-alive 10 180
1445

    
1446
EOD;
1447

    
1448
			if (!empty($l2tpcfg['dns1'])) {
1449
				$mpdconf .= "	set ipcp dns " . $l2tpcfg['dns1'];
1450
				if (!empty($l2tpcfg['dns2']))
1451
					$mpdconf .= " " . $l2tpcfg['dns2'];
1452
				$mpdconf .= "\n";
1453
			} elseif (isset ($config['dnsmasq']['enable'])) {
1454
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1455
				if ($syscfg['dnsserver'][0])
1456
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1457
				$mpdconf .= "\n";
1458
			} elseif (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1459
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1460
			}
1461

    
1462
			if (isset ($l2tpcfg['radius']['enable'])) {
1463
				$mpdconf .=<<<EOD
1464
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1465
	set radius retries 3
1466
	set radius timeout 10
1467
	set auth enable radius-auth
1468

    
1469
EOD;
1470

    
1471
				if (isset ($l2tpcfg['radius']['accounting'])) {
1472
					$mpdconf .=<<<EOD
1473
	set auth enable radius-acct
1474

    
1475
EOD;
1476
				}
1477
			}
1478

    
1479
			fwrite($fd, $mpdconf);
1480
			fclose($fd);
1481

    
1482
			/* write mpd.links */
1483
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.links", "w");
1484
			if (!$fd) {
1485
				printf("Error: cannot open mpd.links in vpn_l2tp_configure().\n");
1486
				return 1;
1487
			}
1488

    
1489
			$mpdlinks = "";
1490

    
1491
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1492
				$mpdlinks .=<<<EOD
1493

    
1494
l2tp{$i}:
1495
	set link type l2tp
1496
        set l2tp enable incoming
1497
        set l2tp disable originate
1498

    
1499
EOD;
1500
			if (!empty($l2tpcfg['secret']))
1501
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1502
			}
1503

    
1504
			fwrite($fd, $mpdlinks);
1505
			fclose($fd);
1506

    
1507
			/* write mpd.secret */
1508
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1509
			if (!$fd) {
1510
				printf("Error: cannot open mpd.secret in vpn_l2tp_configure().\n");
1511
				return 1;
1512
			}
1513

    
1514
			$mpdsecret = "\n\n";
1515

    
1516
			if (is_array($l2tpcfg['user'])) {
1517
				foreach ($l2tpcfg['user'] as $user)
1518
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1519
			}
1520

    
1521
			fwrite($fd, $mpdsecret);
1522
			fclose($fd);
1523
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1524

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

    
1528
			break;
1529

    
1530
		case 'redir' :
1531
			break;
1532
	}
1533

    
1534
	if ($g['booting'])
1535
		echo "done\n";
1536

    
1537
	return 0;
1538
}
1539

    
1540
/* Walk the tunnels for hostname endpoints. If the hostnames 
1541
 * resolve to a different IP now compared to the DNS cache
1542
 * we reload the policies if the endpoint has changed */
1543
function vpn_ipsec_refresh_policies() {
1544
	global $config;
1545
	global $g;
1546

    
1547
	$ipseccfg = $config['ipsec'];
1548
	$a_phase1 = $config['ipsec']['phase1'];
1549
	$a_phase2 = $config['ipsec']['phase2'];
1550

    
1551
	if (isset($ipseccfg['disable'])) {
1552
		return true;
1553
	}
1554

    
1555
	/* Walk the Ipsec tunnel array */
1556
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1557
		return;
1558
	}
1559

    
1560
	foreach ($a_phase1 as $phase1) {
1561
		if (isset($phase1['disabled'])) {
1562
			continue;
1563
		}
1564
		if (is_ipaddr($phase1['remote-gateway'])) {
1565
			continue;
1566
		}
1567
		if (!is_ipaddr($phase1['remote-gateway'])) {
1568
			$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1569
			$dnscache = trim($dnscache);
1570
			/* we should have the old IP addresses in the dnscache now */
1571
			if($dnscache <> "") {
1572
				$oldphase1 = $phase1;
1573
				$oldphase1['remote-gateway'] = trim($dnscache);
1574
				/* now we need to find all tunnels for this host */
1575
				if (!is_array($a_phase2) || (!count($a_phase2))) {
1576
					continue;
1577
				}
1578
				foreach ($a_phase2 as $phase2) {
1579
					if($phase2['ikeid'] == $phase1['ikeid']) {
1580
						reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1581
					}
1582
				}
1583
			}
1584
		}
1585
	}
1586

    
1587
	/* process all generated spd.conf files from tmp which are left behind
1588
	 * behind by either changes of dynamic tunnels or manual edits
1589
	 * scandir() is only available in PHP5 */
1590
	$tmpfiles = array();
1591
	$dh  = opendir($g['tmp_path']);
1592
	while (false !== ($filename = readdir($dh))) {
1593
		if(preg_match("/^spd.conf.reload./", $filename)) {
1594
			$tmpfiles[] = $filename;
1595
		}
1596
	}
1597
	sort($tmpfiles);
1598
	foreach($tmpfiles as $tmpfile) {
1599
		$ret = mwexec("/usr/local/sbin/setkey -f {$g['tmp_path']}/{$tmpfile} 2>&1", false);
1600
		if($ret == 0) {
1601
			unlink_if_exists("{$g['tmp_path']}/{$tmpfile}");
1602
		} else {
1603
			rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1604
		}
1605
	}
1606
}
1607

    
1608
/* reloads the tunnel configuration for a tunnel item
1609
 * Will remove and add SPD polices */
1610
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1611
	global $config;
1612
	global $g;
1613

    
1614
	/* if we are not passed a old tunnel array we create one */
1615
	if(empty($old_phase1)) {
1616
		$old_phase1 = $phase1;
1617
	}
1618
	if(empty($old_phase2)) {
1619
		$old_phase2 = $phase2;
1620
	}
1621

    
1622
	$sad_arr = ipsec_dump_sad();
1623

    
1624
	$ep = ipsec_get_phase1_src($phase1);
1625
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1626
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1627

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

    
1631
	$old_ep = ipsec_get_phase1_src($old_phase1);
1632
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1633
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1634

    
1635
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1636
	 * try to resolve it now and add it to the list for dnswatch */
1637
	if (!is_ipaddr($phase1['remote-gateway'])) {
1638
		$rgip = resolve_retry($phase1['remote-gateway']);
1639
		add_hostname_to_watch($phase1['remote-gateway']);
1640
		if (!$rgip) {
1641
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1642
			return false;
1643
		}
1644
	} else {
1645
		$rgip = $phase1['remote-gateway'];
1646
	}
1647
	if (!$ep) {
1648
		log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1649
		return false;
1650
	}
1651

    
1652
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1653
		log_error("IPSEC: ERROR: One of the endpoints is not a IP address. Old EP '{$old_ep}' new EP '{$ep}'");
1654
	}
1655
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1656
		log_error("IPSEC: ERROR: One of the remote endpoints is not a IP address. Old RG '{$old_gw}' new RG '{$rgip}'");
1657
	}
1658

    
1659
	$spdconf = "";
1660
	/* Delete old SPD policies if there are changes between the old and new */
1661
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1662
		$spdconf .= "spddelete {$old_local_subnet} " .
1663
			"{$old_remote_subnet} any -P out ipsec " .
1664
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1665
			"{$old_gw}/unique;\n";
1666
		$spdconf .= "spddelete {$old_remote_subnet} " .
1667
			"{$old_local_subnet} any -P in ipsec " .
1668
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1669
			"{$old_ep}/unique;\n";
1670

    
1671
		/* zap any existing SA entries */
1672
		foreach($sad_arr as $sad) {
1673
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1674
				$spdconf .= "delete {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1675
			}
1676
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1677
				$spdconf .= "delete {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1678
			}
1679
		}
1680
	}
1681

    
1682
	/* Create new SPD entries for the new configuration */
1683
	/* zap any existing SA entries beforehand */
1684
	foreach($sad_arr as $sad) {
1685
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1686
			$spdconf .= "delete {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1687
		}
1688
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1689
			$spdconf .= "delete {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1690
		}
1691
	}
1692
	/* add new SPD policies to replace them */
1693
	$spdconf .= "spdadd {$local_subnet} " .
1694
		"{$remote_subnet} any -P out ipsec " .
1695
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1696
		"{$rgip}/unique;\n";
1697
	$spdconf .= "spdadd {$remote_subnet} " .
1698
		"{$local_subnet} any -P in ipsec " .
1699
		"{$phase2['protocol']}/tunnel/{$rgip}-" .
1700
		"{$ep}/unique;\n";
1701

    
1702
	log_error("Reloading IPsec tunnel '{$phase1['descr']}'. Previous IP '{$old_gw}', current IP '{$rgip}'. Reloading policy");
1703

    
1704
	$now = time();
1705
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1706
	/* generate temporary spd.conf */
1707
	file_put_contents($spdfile, $spdconf);
1708
	return true;
1709
}
1710

    
1711
function vpn_ipsec_configure_preferoldsa() {
1712
	global $config;
1713
	if(isset($config['ipsec']['preferoldsa']))
1714
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1715
	else
1716
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1717
}
1718
?>
(45-45/54)