Project

General

Profile

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

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

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

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

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

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

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

    
36
/*
37
	pfSense_BUILDER_BINARIES:	/usr/bin/killall	/usr/local/sbin/sasyncd	/sbin/ifconfig	/sbin/sysctl
38
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/setkey	/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['descr']}");
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['descr']}");
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['descr']}");
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
				if (isset($a_client['save_passwd']))
394
					$racoonconf .= "\tsave_passwd on;\n";
395

    
396
				$racoonconf .= "}\n\n";
397
			}
398
			/* end mode_cfg section */
399

    
400
			/* begin remote sections */
401
			if (is_array($a_phase1) && count($a_phase1)) {
402
				/* begin remote */
403
				foreach ($a_phase1 as $ph1ent) {
404

    
405
					if (isset($ph1ent['disabled']))
406
						continue;
407

    
408
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
409
						continue;
410

    
411
					$ikeid = $ph1ent['ikeid'];
412

    
413
					$ep = ipsec_get_phase1_src($ph1ent);
414
					if (!$ep)
415
						continue;
416

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

    
423
					$myid_type = $ph1ent['myid_type'];
424

    
425
					switch ($myid_type) {
426

    
427
						case "myaddress":
428
							$myid_type = "address";
429
							$myid_data = $ep;
430
							break;
431

    
432
						case "dyn_dns":
433
							$myid_type = "address";
434
							$myid_data = gethostbyname($ph1ent['myid_data']);
435
							break;
436

    
437
						case "address";
438
							$myid_data = $ph1ent['myid_data'];
439
							break;
440

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

    
451
					$peerid_type = $ph1ent['peerid_type'];
452

    
453
					switch ($peerid_type) {
454
						case "peeraddress":
455
							$peerid_type = "address";
456
							$peerid_data = $rgip;
457
							break;
458

    
459
						case "address";
460
							$peerid_data = $ph1ent['peerid_data'];
461
							break;
462

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

    
473
					$natt = "off";
474
					if (isset($ph1ent['nat_traversal']))
475
						$natt = $ph1ent['nat_traversal'];
476

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

    
494
					$dpdline1 = '';
495
					$dpdline2 = '';
496
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
497
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
498
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
499
					}
500

    
501
					if (isset ($ph1ent['authentication_method']))
502
						$authmethod = $ph1ent['authentication_method'];
503
					else
504
						$authmethod = 'pre_shared_key';
505

    
506
					$certline = '';
507

    
508
					if (strstr($authmethod,'rsa')) {
509

    
510
						$cert = lookup_cert($ph1ent['certref']);
511

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

    
518
						$certfile = "cert-".$ikeid.".crt";
519
						$certpath = $g['varetc_path']."/".$certfile;
520

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

    
527
						chmod($certpath, 0600);
528

    
529
						$keyfile = "cert-".$ikeid.".key";
530
						$keypath = $g['varetc_path']."/".$keyfile;
531

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

    
538
						chmod($keypath, 0600);
539

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

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

    
551
							chmod($capath, 0600);
552
							$caline = "ca_type x509 \"".basename($capath)."\";";
553
						}
554

    
555
						$certline = "certificate_type x509 \"".basename($certpath)."\" \"".basename($keypath)."\";";
556

    
557
					}
558

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

    
567
					$lifeline = '';
568
					if ($ph1ent['lifetime'])
569
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
570

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

    
576
					/* add remote section to configuration */
577

    
578
					$racoonconf .=<<<EOD
579

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

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

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

    
617
				/* begin sainfo */
618
				foreach ($a_phase2 as $ph2ent) {
619

    
620
					$ikeid = $ph2ent['ikeid'];
621

    
622
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
623
						continue;
624

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

    
628
					if (isset($ph2ent['disabled']))
629
						continue;
630

    
631
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
632
						continue;
633

    
634
					if ($ph2ent['mode'] == 'tunnel') {
635

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

    
648
						if (!isset($ph2ent['mobile'])) {
649
							$remoteid_type = $ph2ent['remoteid']['type'];
650
							if ($remoteid_type != "address")
651
								$remoteid_type = "subnet";
652

    
653
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
654
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
655
						} else
656
							$remoteid_spec = "anonymous";
657

    
658
					} else {
659

    
660
						$rgip = $rgmap[$ph1ent['remote-gateway']];
661

    
662
						$localid_data = ipsec_get_phase1_src($ph1ent);
663
						if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
664
						$localid_spec = "address {$localid_data}";
665

    
666
						$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
667
						if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
668
						$remoteid_spec = "address {$remoteid_data}";
669
					}
670

    
671
					if($ph2ent['protocol'] == 'esp') {
672

    
673
						$ealgos = '';
674

    
675
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
676

    
677
							$ealg_id = $ealg['name'];
678
							$ealg_kl = $ealg['keylen'];
679

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

    
715
						$ealgosline = "encryption_algorithm {$ealgos};";
716

    
717
					} else {
718

    
719
						$ealgosline = "encryption_algorithm null_enc;";
720
					}
721

    
722
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
723
					$halgosline = "authentication_algorithm {$halgos};";
724

    
725
					$pfsline = '';
726
					if ($ph2ent['pfsgroup'])
727
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
728
					if (isset($a_client['pfs_group'])) {
729
						$pfsline = '';
730
						if ($a_client['pfs_group'])
731
							$pfsline = "pfs_group {$a_client['pfs_group']};";
732
					}
733

    
734
					$lifeline = '';
735
					if ($ph2ent['lifetime'])
736
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
737

    
738
					/* add sainfo section to configuration */
739
					
740
					$racoonconf .=<<<EOD
741
					
742
sainfo {$localid_spec} {$remoteid_spec}
743
{
744
	remoteid {$ikeid};
745
	{$ealgosline}
746
	{$halgosline}
747
	{$pfsline}
748
	{$lifeline}
749
	compression_algorithm deflate;
750
}
751

    
752
EOD;
753
				}
754
				/* end sainfo */
755
			}
756
			/* end sainfo sections */
757

    
758
			fwrite($fd, $racoonconf);
759
			fclose($fd);
760
		}
761
		/* end racoon.conf */
762

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

    
772
			$spdconf = "";
773

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

    
785
			foreach ($a_phase2 as $ph2ent) {
786

    
787
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
788
					continue;
789

    
790
				if (isset($ph1ent['mobile']))
791
					continue;
792

    
793
				if (isset($ph1ent['disabled']))
794
					continue;
795

    
796
				if (isset($ph2ent['disabled']))
797
					continue;
798

    
799
				$ep = ipsec_get_phase1_src($ph1ent);
800
				if (!$ep)
801
					continue;
802

    
803
				$rgip = $rgmap[$ph1ent['remote-gateway']];
804

    
805
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
806
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
807

    
808
				if($ph2ent['mode'] == "tunnel") {
809

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

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

    
816
				} else {
817

    
818
					$localid_data = ipsec_get_phase1_src($ph1ent);
819
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
820

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

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

    
827
				}
828

    
829
				/* static route needed? */
830
				if (preg_match("/^carp|^vip/i", $ph1ent['interface']))
831
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
832
				else
833
					$parentinterface = $ph1ent['interface'];
834

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

    
860
			fwrite($fd, $spdconf);
861
			fclose($fd);
862
		}
863

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

    
887
			/* start dnswatch, if necessary */
888
			if (count($dnswatch_list) > 0) {
889
				$interval = 60;
890
				if (!empty($ipseccfg['dns-interval']) && is_numeric($ipseccfg['dns-interval']))
891
					$interval = $ipseccfg['dns-interval'];
892

    
893
				$hostnames = "";
894
				array_unique($dnswatch_list);
895
				$hostnames = implode("\n", $dnswatch_list);
896
				file_put_contents("{$g['varetc_path']}/dnswatch-ipsec.hosts", $hostnames);
897

    
898
				killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
899
				mwexec("/usr/local/sbin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval /etc/rc.newipsecdns {$g['varetc_path']}/dnswatch-ipsec.hosts");
900
			}
901
		}
902
	
903
		vpn_ipsec_failover_configure();
904

    
905
		if ($g['booting'])
906
			echo "done\n";
907
	}
908

    
909
	return 0;
910
}
911

    
912
/* Forcefully restart IPsec
913
 * This is required for when dynamic interfaces reload
914
 * For all other occasions the normal vpn_ipsec_configure()
915
 * will gracefully reload the settings without restarting
916
 */
917
function vpn_ipsec_force_reload() {
918
	global $config;
919
	global $g;
920

    
921
	$ipseccfg = $config['ipsec'];
922

    
923
	/* kill racoon */
924
	if(is_process_running("racoon"))
925
		mwexec("/usr/bin/killall racoon", true);
926

    
927
	/* wait for process to die */
928
	sleep(4);
929

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

    
933
	/* wait for flushing to finish */
934
	sleep(1);
935

    
936
	/* if ipsec is enabled, start up again */
937
	if (isset($ipseccfg['enable'])) {
938
		log_error("Forcefully reloading IPsec racoon daemon");
939
		vpn_ipsec_configure();
940
	}
941

    
942
}
943

    
944
/* master setup for vpn (mpd) */
945
function vpn_setup() {
946
	/* start pptpd */
947
	vpn_pptpd_configure();
948

    
949
	/* start pppoe server */
950
	vpn_pppoes_configure();
951

    
952
	/* setup l2tp */
953
	vpn_l2tp_configure();
954
}
955

    
956
function vpn_pptpd_configure() {
957
	global $config, $g;
958

    
959
	$syscfg = $config['system'];
960
	$pptpdcfg = $config['pptpd'];
961

    
962
	if ($g['booting']) {
963
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
964
			return 0;
965

    
966
		echo "Configuring PPTP VPN service... ";
967
	} else {
968
		/* kill mpd */
969
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
970

    
971
		/* wait for process to die */
972
		sleep(3);
973

    
974
		if (is_process_running("mpd -b")) {
975
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
976
			log_error("Could not kill mpd within 3 seconds.   Trying again.");
977
		}
978

    
979
		/* remove mpd.conf, if it exists */
980
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
981
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
982
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
983
	}
984

    
985
	/* make sure pptp-vpn directory exists */
986
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
987
		mkdir("{$g['varetc_path']}/pptp-vpn");
988

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

    
998
			$mpdconf = <<<EOD
999
pptps:
1000

    
1001
EOD;
1002

    
1003
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1004
				$mpdconf .= "	load pt{$i}\n";
1005
			}
1006

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

    
1009
				$clientip = long2ip32(ip2long($pptpdcfg['remoteip']) + $i);
1010

    
1011
				$mpdconf .= <<<EOD
1012

    
1013
pt{$i}:
1014
	new -i pptpd{$i} pt{$i} pt{$i}
1015
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1016
	load pts
1017

    
1018
EOD;
1019
			}
1020

    
1021
			$mpdconf .=<<<EOD
1022

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

    
1043
EOD;
1044

    
1045
			if (!isset ($pptpdcfg['req128'])) {
1046
				$mpdconf .=<<<EOD
1047
	set ccp yes mpp-e40
1048
	set ccp yes mpp-e56
1049

    
1050
EOD;
1051
			}
1052

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

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

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

    
1076
EOD;
1077
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1078
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1079
				$acctport = $authport + 1;
1080
				$mpdconf .=<<<EOD
1081
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret']}" {$authport} {$acctport}
1082

    
1083
EOD;
1084
			}
1085
			$mpdconf .=<<<EOD
1086
	set radius retries 3
1087
	set radius timeout 10
1088
	set auth enable radius-auth
1089

    
1090
EOD;
1091

    
1092
				if (isset ($pptpdcfg['radius']['accounting'])) {
1093
					$mpdconf .=<<<EOD
1094
	set auth enable radius-acct
1095
	set radius acct-update 300
1096

    
1097
EOD;
1098
				}
1099
			}
1100

    
1101
			fwrite($fd, $mpdconf);
1102
			fclose($fd);
1103

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

    
1111
			$mpdlinks = "";
1112

    
1113
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1114
				$mpdlinks .=<<<EOD
1115

    
1116
pt{$i}:
1117
	set link type pptp
1118
	set pptp enable incoming
1119
	set pptp disable originate
1120
	set pptp disable windowing
1121

    
1122
EOD;
1123
			}
1124

    
1125
			fwrite($fd, $mpdlinks);
1126
			fclose($fd);
1127

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

    
1135
			$mpdsecret = "";
1136

    
1137
			if (is_array($pptpdcfg['user'])) {
1138
				foreach ($pptpdcfg['user'] as $user)
1139
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1140
			}
1141

    
1142
			fwrite($fd, $mpdsecret);
1143
			fclose($fd);
1144
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1145

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

    
1149
			break;
1150

    
1151
		case 'redir' :
1152
			break;
1153
	}
1154

    
1155
	if ($g['booting'])
1156
		echo "done\n";
1157

    
1158
	return 0;
1159
}
1160

    
1161
function vpn_pppoes_configure() {
1162
	global $config;
1163

    
1164
	if (is_array($config['pppoes']['pppoe'])) {
1165
		foreach ($config['pppoes']['pppoe'] as $pppoe)
1166
			vpn_pppoe_configure($pppoe);
1167
	}
1168
}
1169

    
1170
function vpn_pppoe_configure(&$pppoecfg) {
1171
	global $config, $g;
1172

    
1173
	$syscfg = $config['system'];
1174

    
1175
	/* create directory if it does not exist */
1176
	if (!is_dir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn"))
1177
		mkdir("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn");
1178

    
1179
	if ($g['booting']) {
1180
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1181
			return 0;
1182

    
1183
		echo "Configuring PPPoE VPN service... ";
1184
	} else {
1185
		/* kill mpd */
1186
		killbypid("{$g['varrun_path']}/pppoe{$pppoecfg['pppoeid']}-vpn.pid");
1187

    
1188
		/* wait for process to die */
1189
		sleep(2);
1190

    
1191
	}
1192

    
1193
	switch ($pppoecfg['mode']) {
1194

    
1195
		case 'server' :
1196

    
1197
			$pppoe_interface = get_real_interface($pppoecfg['interface']);
1198

    
1199
			if ($pppoecfg['paporchap'] == "chap")
1200
				$paporchap = "set link enable chap";
1201
			else
1202
				$paporchap = "set link enable pap";
1203

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

    
1213
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1214
				$mpdconf .= "	load poes{$pppoecfg['pppoeid']}{$i}\n";
1215
			}
1216

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

    
1219
				$clientip = long2ip32(ip2long($pppoecfg['remoteip']) + $i);
1220

    
1221
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['server']['enable'])) {
1222
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1223
				} else {
1224
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1225
				}
1226

    
1227
				$mpdconf .=<<<EOD
1228

    
1229
poes{$pppoecfg['pppoeid']}{$i}:
1230
	new -i poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i} poes{$pppoecfg['pppoeid']}{$i}
1231
	{$isssue_ip_type}
1232
	load pppoe_standard
1233

    
1234
EOD;
1235
			}
1236

    
1237
			$mpdconf .=<<<EOD
1238

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

    
1265
EOD;
1266

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

    
1281
			if (isset ($pppoecfg['radius']['server']['enable'])) {
1282
				$mpdconf .=<<<EOD
1283
	set radius server {$pppoecfg['radius']['server']['ip']} "{$pppoecfg['radius']['server']['secret']}"
1284
	set radius retries 3
1285
	set radius timeout 10
1286
	set auth enable radius-auth
1287

    
1288
EOD;
1289

    
1290
				if (isset ($pppoecfg['radius']['accounting'])) {
1291
					$mpdconf .=<<<EOD
1292
	set auth enable radius-acct
1293

    
1294
EOD;
1295
				}
1296
			}
1297

    
1298
			fwrite($fd, $mpdconf);
1299
			fclose($fd);
1300

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

    
1308
			$mpdlinks = "";
1309

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

    
1320
EOD;
1321
			}
1322

    
1323
			fwrite($fd, $mpdlinks);
1324
			fclose($fd);
1325

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

    
1334
				$mpdsecret = "\n\n";
1335

    
1336
				if (!empty($pppoecfg['username'])) {
1337
					$item = explode(" ", $pppoecfg['username']);
1338
					foreach($item as $userdata) {
1339
						$data = explode(":", $userdata);
1340
						$mpdsecret .= "{$data[0]} \"" . base64_decode($data[1]) . "\" {$data[2]}\n";
1341
					}
1342
				}
1343

    
1344
				fwrite($fd, $mpdsecret);
1345
				fclose($fd);
1346
				chmod("{$g['varetc_path']}/pppoe{$pppoecfg['pppoeid']}-vpn/mpd.secret", 0600);
1347
			}
1348

    
1349
			/* fire up mpd */
1350
			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");
1351

    
1352
			break;
1353
	}
1354

    
1355
	if ($g['booting'])
1356
		echo "done\n";
1357

    
1358
	return 0;
1359
}
1360

    
1361
function vpn_l2tp_configure() {
1362
	global $config, $g;
1363

    
1364
	$syscfg = $config['system'];
1365
	$l2tpcfg = $config['l2tp'];
1366

    
1367
	/* create directory if it does not exist */
1368
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1369
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1370

    
1371
	if ($g['booting']) {
1372
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1373
			return 0;
1374

    
1375
		echo "Configuring l2tp VPN service... ";
1376
	} else {
1377
		/* kill mpd */
1378
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1379

    
1380
		/* wait for process to die */
1381
		sleep(8);
1382

    
1383
	}
1384

    
1385
	/* make sure l2tp-vpn directory exists */
1386
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1387
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1388

    
1389
	switch ($l2tpcfg['mode']) {
1390

    
1391
		case 'server' :
1392
			if ($l2tpcfg['paporchap'] == "chap")
1393
				$paporchap = "set link enable chap";
1394
			else
1395
				$paporchap = "set link enable pap";
1396

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

    
1407
EOD;
1408

    
1409
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1410
				$mpdconf .= "	load l2tp{$i}\n";
1411
			}
1412

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

    
1415
				$clientip = long2ip32(ip2long($l2tpcfg['remoteip']) + $i);
1416

    
1417
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1418
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1419
				} else {
1420
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1421
				}
1422

    
1423
				$mpdconf .=<<<EOD
1424

    
1425
l2tp{$i}:
1426
	new -i l2tp{$i} l2tp{$i} l2tp{$i}
1427
	{$isssue_ip_type}
1428
	load l2tp_standard
1429

    
1430
EOD;
1431
			}
1432

    
1433
			$mpdconf .=<<<EOD
1434

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

    
1451
EOD;
1452

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

    
1467
			if (isset ($l2tpcfg['radius']['enable'])) {
1468
				$mpdconf .=<<<EOD
1469
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1470
	set radius retries 3
1471
	set radius timeout 10
1472
	set auth enable radius-auth
1473

    
1474
EOD;
1475

    
1476
				if (isset ($l2tpcfg['radius']['accounting'])) {
1477
					$mpdconf .=<<<EOD
1478
	set auth enable radius-acct
1479

    
1480
EOD;
1481
				}
1482
			}
1483

    
1484
			fwrite($fd, $mpdconf);
1485
			fclose($fd);
1486

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

    
1494
			$mpdlinks = "";
1495

    
1496
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1497
				$mpdlinks .=<<<EOD
1498

    
1499
l2tp{$i}:
1500
	set link type l2tp
1501
        set l2tp enable incoming
1502
        set l2tp disable originate
1503

    
1504
EOD;
1505
			if (!empty($l2tpcfg['secret']))
1506
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1507
			}
1508

    
1509
			fwrite($fd, $mpdlinks);
1510
			fclose($fd);
1511

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

    
1519
			$mpdsecret = "\n\n";
1520

    
1521
			if (is_array($l2tpcfg['user'])) {
1522
				foreach ($l2tpcfg['user'] as $user)
1523
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1524
			}
1525

    
1526
			fwrite($fd, $mpdsecret);
1527
			fclose($fd);
1528
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1529

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

    
1533
			break;
1534

    
1535
		case 'redir' :
1536
			break;
1537
	}
1538

    
1539
	if ($g['booting'])
1540
		echo "done\n";
1541

    
1542
	return 0;
1543
}
1544

    
1545
/* Walk the tunnels for hostname endpoints. If the hostnames 
1546
 * resolve to a different IP now compared to the DNS cache
1547
 * we reload the policies if the endpoint has changed */
1548
function vpn_ipsec_refresh_policies() {
1549
	global $config;
1550
	global $g;
1551

    
1552
	$ipseccfg = $config['ipsec'];
1553
	$a_phase1 = $config['ipsec']['phase1'];
1554
	$a_phase2 = $config['ipsec']['phase2'];
1555

    
1556
	if (isset($ipseccfg['disable'])) {
1557
		return true;
1558
	}
1559

    
1560
	/* Walk the Ipsec tunnel array */
1561
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1562
		return;
1563
	}
1564

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

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

    
1613
/* reloads the tunnel configuration for a tunnel item
1614
 * Will remove and add SPD polices */
1615
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1616
	global $config;
1617
	global $g;
1618

    
1619
	/* if we are not passed a old tunnel array we create one */
1620
	if(empty($old_phase1)) {
1621
		$old_phase1 = $phase1;
1622
	}
1623
	if(empty($old_phase2)) {
1624
		$old_phase2 = $phase2;
1625
	}
1626

    
1627
	$sad_arr = ipsec_dump_sad();
1628

    
1629
	$ep = ipsec_get_phase1_src($phase1);
1630
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1631
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1632

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

    
1636
	$old_ep = ipsec_get_phase1_src($old_phase1);
1637
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1638
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1639

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

    
1657
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1658
		log_error("IPSEC: ERROR: One of the endpoints is not a IP address. Old EP '{$old_ep}' new EP '{$ep}'");
1659
	}
1660
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1661
		log_error("IPSEC: ERROR: One of the remote endpoints is not a IP address. Old RG '{$old_gw}' new RG '{$rgip}'");
1662
	}
1663

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

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

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

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

    
1709
	$now = time();
1710
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1711
	/* generate temporary spd.conf */
1712
	file_put_contents($spdfile, $spdconf);
1713
	return true;
1714
}
1715

    
1716
function vpn_ipsec_configure_preferoldsa() {
1717
	global $config;
1718
	if(isset($config['ipsec']['preferoldsa']))
1719
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
1720
	else
1721
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
1722
}
1723

    
1724
?>
(45-45/54)