Project

General

Profile

Download (42.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
/* include all configuration functions */
37
require_once ("functions.inc");
38

    
39
function vpn_ipsec_failover_configure() {
40
	global $config, $g;
41

    
42
	$sasyncd_text = "";
43

    
44
	if ($config['installedpackages']['sasyncd'] <> "")
45
		foreach ($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
46
			$enabled = isset ($sasyncd['enable']);
47
			if (!$enabled)
48
				return;
49
			if ($sasyncd['peerip'] <> "")
50
				$sasyncd_text .= "peer {$sasyncd['peerip']}\n";
51
			if ($sasyncd['interface'])
52
				$sasyncd_text .= "carp interface {$sasyncd['interface']}\n";
53
			if ($sasyncd['sharedkey'] <> "")
54
				$sasyncd_text .= "sharedkey {$sasyncd['sharedkey']}\n";
55
			if ($sasyncd['mode'] <> "")
56
				$sasyncd_text .= "mode {$sasyncd['mode']}\n";
57
			if ($sasyncd['listenon'] <> "")
58
				$sasyncd_text .= "listen on {$sasyncd['listenon']}\n";
59
			if ($sasyncd['flushmodesync'] <> "")
60
				$sasyncd_text .= "flushmode sync {$sasyncd['flushmodesync']}\n";
61
		}
62

    
63
	$fd = fopen("{$g['varetc_path']}/sasyncd.conf", "w");
64
	fwrite($fd, $sasyncd_text);
65
	fclose($fd);
66
	chmod("{$g['varetc_path']}/sasyncd.conf", 0600);
67

    
68
	mwexec("killall sasyncd", true);
69

    
70
	/* launch sasyncd, oh wise one */
71
	mwexec_bg("/usr/local/sbin/sasyncd -d -v -v -v");
72
}
73

    
74
function find_last_gif_device() {
75
	$last_gif_found = -1;
76
	$regs = "";
77
	if (!($fp = popen("/sbin/ifconfig -l", "r")))
78
		return -1;
79
	$ifconfig_data = fread($fp, 4096);
80
	pclose($fp);
81
	$ifconfig_array = split(" ", $ifconfig_data);
82
	foreach ($ifconfig_array as $ifconfig) {
83
		ereg("gif(.)", $ifconfig, $regs);
84
		if ($regs[0] && $regs[0] > $last_gif_found) {
85
			$last_gif_found = $regs[1];
86
		}
87
	}
88
	return $last_gif_found;
89
}
90

    
91
function vpn_ipsec_configure($ipchg = false)
92
{
93
	global $config, $g, $sa, $sn, $p1_ealgos, $p2_ealgos;
94

    
95
	mwexec("/sbin/ifconfig enc0 up");
96

    
97
	/* get the automatic /etc/ping_hosts.sh ready */
98
	unlink_if_exists("/var/db/ipsecpinghosts");
99
	touch("/var/db/ipsecpinghosts");
100

    
101
	if(isset($config['ipsec']['preferredoldsa']))
102
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
103
	else
104
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
105

    
106
	$number_of_gifs = find_last_gif_device();
107
	for ($x = 0; $x < $number_of_gifs; $x++)
108
		mwexec("/sbin/ifconfig gif" . $x . " delete");
109

    
110
	$curwanip = get_interface_ip();
111

    
112
	$syscfg = $config['system'];
113
	$ipseccfg = $config['ipsec'];
114
	$a_phase1 = $config['ipsec']['phase1'];
115
	$a_phase2 = $config['ipsec']['phase2'];
116
	$a_client = $config['ipsec']['client'];
117
	$lancfg = $config['interfaces']['lan'];
118
	$lanip = $lancfg['ipaddr'];
119
	$lansa = gen_subnet($lancfg['ipaddr'], $lancfg['subnet']);
120
	$lansn = $lancfg['subnet'];
121

    
122
	if (!isset($ipseccfg['enable'])) {
123
		mwexec("/sbin/ifconfig enc0 down");
124

    
125
		/* kill racoon */
126
		mwexec("/usr/bin/killall racoon", true);
127
		killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
128
		
129
		/* wait for racoon process to die */
130
		sleep(2);
131

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

    
135
		/* flush SPD and SAD */
136
		mwexec("/usr/local/sbin/setkey -FP");
137
		mwexec("/usr/local/sbin/setkey -F");
138

    
139
		return true;
140
	}
141

    
142
	if ($g['booting'])
143
		echo "Configuring IPsec VPN... ";
144

    
145
	if (isset ($ipseccfg['enable'])) {
146
		/* fastforwarding is not compatible with ipsec tunnels */
147
		mwexec("/sbin/sysctl net.inet.ip.fastforwarding=0");
148

    
149
		if (!$curwanip) {
150
			/* IP address not configured yet, exit */
151
			if ($g['booting'])
152
				echo "done\n";
153
			return 0;
154
		}
155

    
156
		/* this loads a route table which is used to determine if a route needs to be removed. */
157
		exec("/usr/bin/netstat -rn", $route_arr, $retval);
158
		$route_str = implode("\n", $route_arr);
159

    
160
		/* resolve all local, peer addresses and setup pings */
161
		$ipmap = array();
162
		$rgmap = array();
163
		$dnswatch_list = array();
164
		if (is_array($a_phase1) && count($a_phase1)) {
165
			foreach ($a_phase1 as $ph1ent) {
166
				if (isset($ph1ent['disabled']))
167
					continue;
168

    
169
				$ep = ipsec_get_phase1_src($ph1ent);
170
				if (!$ep)
171
					continue;
172

    
173
				if(!in_array($ep,$ipmap))
174
					$ipmap[] = $ep;
175

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

    
179
				if (isset ($ph1ent['mobile']))
180
					continue;
181

    
182
				$rg = $ph1ent['remote-gateway'];
183

    
184
				if (!is_ipaddr($rg)) {
185
					$dnswatch_list[] = $rg;
186
					add_hostname_to_watch($rg);
187
					$rg = resolve_retry($rg);
188
					if (!$rg)
189
						continue;
190
				}
191

    
192
				$rgmap[$ph1ent['remote-gateway']] = $rg;
193

    
194
				/* add an ipsec pinghosts entry */
195

    
196
				if ($ph1ent['pinghost']) {
197
					$pfd = fopen("/var/db/ipsecpinghosts", "a");
198
					$iflist = get_configured_interface_list();
199
					foreach ($iflist as $ifent => $ifname) {
200
						$interface_ip = find_interface_ip($config['interfaces'][$ifname]['if']);
201
						if (ip_in_subnet($interface_ip, $sa . "/" . $sn))
202
						$srcip = find_interface_ip($config['interfaces'][$ifname]['if']);
203
					}
204
					$dstip = $ph1ent['pinghost'];
205
					fwrite($pfd, "$srcip|$dstip|3\n");
206
					fclose($pfd);
207
				}
208
			}
209
		}
210

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

    
239
		$pskconf = "";
240

    
241
		if (is_array($a_phase1) && count($a_phase1)) {
242
			foreach ($a_phase1 as $ph1ent) {
243

    
244
				if (isset($ph1ent['disabled']))
245
					continue;
246

    
247
				if (strstr($ph1ent['authentication_method'],'rsa'))
248
					continue;
249

    
250
				$peerid_type = $ph1ent['peerid_type'];
251

    
252
				switch ($peerid_type) {
253
					case "peeraddress":
254
						$peerid_type = "address";
255
						$peerid_data = $rgmap[$ph1ent['remote-gateway']];
256
						break;
257

    
258
					case "address";
259
						$peerid_data = $ph1ent['peerid_data'];
260
						break;
261

    
262
					case "fqdn";
263
					case "keyid tag";
264
					case "user_fqdn";
265
						$peerid_data = $ph1ent['peerid_data'];
266
						break;
267
				}
268

    
269
				$pskconf .= "{$peerid_data}\t{$ph1ent['pre-shared-key']}\n";
270
			}
271
		}
272

    
273
		fwrite($fd, $pskconf);
274
		fclose($fd);
275
		chmod("{$g['varetc_path']}/psk.txt", 0600);
276
			
277
		/* begin racoon.conf */
278
		if ((is_array($a_phase1) && count($a_phase1)) ||
279
			(is_array($a_phase2) && count($a_phase2))) {
280

    
281
			$fd = fopen("{$g['varetc_path']}/racoon.conf", "w");
282
			if (!$fd) {
283
				printf("Error: cannot open racoon.conf in vpn_ipsec_configure().\n");
284
				return 1;
285
			}
286

    
287
			$racoonconf = "# This file is automatically generated. Do not edit\n";
288
			$racoonconf .= "listen {\n";
289
			$racoonconf .= "	adminsock \"/var/run/racoon.sock\" \"root\" \"wheel\" 0660;\n";
290
			$racoonconf .= "}\n";
291
			
292
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
293
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
294

    
295
			/* begin listen section */
296
			if (count($ipmap)) {
297
				$racoonconf .= "\nlisten\n";
298
				$racoonconf .= "{\n";
299
				foreach ($ipmap as $addr) {
300
					$racoonconf .= "\tisakmp {$addr} [500];\n";
301
					$racoonconf .= "\tisakmp_natt {$addr} [4500];\n";
302
				}
303
				$racoonconf .= "}\n\n";
304
			}
305

    
306
			/* begin mode_cfg section */
307
			if (is_array($a_client) && isset($a_client['enable'])) {
308

    
309
				$racoonconf .= "\nmode_cfg\n";
310
				$racoonconf .= "{\n";
311

    
312
				if ($a_client['user_source'])
313
					$racoonconf .= "\tauth_source {$a_client['user_source']};\n";
314
				if ($a_client['group_source'])
315
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
316

    
317
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
318
					$pool_address = $a_client['pool_address'];
319
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
320

    
321
					$pool_address = long2ip(ip2long($pool_address)+1);
322
					$pool_size = ~ip2long($pool_netmask) - 2;
323

    
324
					$racoonconf .= "\tpool_size {$pool_size};\n";
325
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
326
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
327
				}
328

    
329
				if (isset($a_client['net_list'])) {
330

    
331
					$net_list = '';
332

    
333
					foreach ($a_phase2 as $ph2ent) {
334

    
335
						if (isset($ph2ent['disabled']))
336
							continue;
337

    
338
						if (!isset($ph2ent['mobile']))
339
							continue;
340

    
341
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
342

    
343
						if ($net_list)
344
							$net_list .= ", ";
345
						$net_list .= $localid;
346
					}
347

    
348
					if ($net_list)
349
						$racoonconf .= "\tsplit_network include {$net_list};\n";
350
				}
351

    
352
				if ($a_client['dns_server1'])
353
					$racoonconf .= "\tdns4 {$a_client['dns_server1']};\n";
354
				if ($a_client['dns_server2'])
355
					$racoonconf .= "\tdns4 {$a_client['dns_server2']};\n";
356
				if ($a_client['dns_server3'])
357
					$racoonconf .= "\tdns4 {$a_client['dns_server3']};\n";
358
				if ($a_client['dns_server4'])
359
					$racoonconf .= "\tdns4 {$a_client['dns_server4']};\n";
360

    
361
				if ($a_client['wins_server1'])
362
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
363
				if ($a_client['wins_server2'])
364
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
365

    
366
				if ($a_client['dns_domain'])
367
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
368

    
369
				if ($a_client['pfs_group'])
370
					$racoonconf .= "\tpfs_group {$a_client['pfs_group']};\n";
371

    
372
				if ($a_client['login_banner']) {
373
					$fn = "{$g['varetc_path']}/racoon.motd";
374
					$fd1 = fopen($fn, "w");
375
					if (!$fd1) {
376
						printf("Error: cannot open server{$fn} in vpn.\n");
377
						return 1;
378
					}
379

    
380
					fwrite($fd1, $a_client['login_banner']);
381
					fclose($fd1);
382

    
383
					$racoonconf .= "\tbanner \"{$fn}\";\n";
384
				}
385

    
386
				$racoonconf .= "}\n\n";
387
			}
388
			/* end mode_cfg section */
389

    
390
			/* begin remote sections */
391
			if (is_array($a_phase1) && count($a_phase1)) {
392
				/* begin remote */
393
				foreach ($a_phase1 as $ph1ent) {
394

    
395
					if (isset($ph1ent['disabled']))
396
						continue;
397

    
398
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
399
						continue;
400

    
401
					$ikeid = $ph1ent['ikeid'];
402

    
403
					$ep = ipsec_get_phase1_src($ph1ent);
404
					if (!$ep)
405
						continue;
406

    
407
					if (!isset($ph1ent['mobile'])) {
408
						$rgip = $rgmap[$ph1ent['remote-gateway']];
409
						if (!$rgip)
410
							continue;
411
					}
412

    
413
					$myid_type = $ph1ent['myid_type'];
414

    
415
					switch ($myid_type) {
416

    
417
						case "myaddress":
418
							$myid_type = "address";
419
							$myid_data = $ep;
420
							break;
421

    
422
						case "dyn_dns":
423
							$myid_data = gethostbyname($ph1ent['myid_data']);
424
							break;
425

    
426
						case "address";
427
							$myid_data = $ph1ent['myid_data'];
428
							break;
429

    
430
						case "fqdn";
431
						case "keyid tag";
432
						case "user_fqdn";
433
						case "asn1dn";
434
							$myid_data = $ph1ent['myid_data'];
435
							if( $myid_data )
436
								$myid_data = "\"".$myid_data."\"";
437
							break;
438
					}
439

    
440
					$peerid_type = $ph1ent['peerid_type'];
441

    
442
					switch ($peerid_type) {
443
						case "peeraddress":
444
							$peerid_type = "address";
445
							$peerid_data = $rgip;
446
							break;
447

    
448
						case "address";
449
							$peerid_data = $ph1ent['peerid_data'];
450
							break;
451

    
452
						case "fqdn";
453
						case "keyid tag";
454
						case "user_fqdn";
455
						case "asn1dn";
456
							$peerid_data = $ph1ent['peerid_data'];
457
							if( $peerid_data )
458
								$peerid_data = "\"".$peerid_data."\"";
459
							break;
460
					}
461

    
462
					$natt = "off";
463
					if (isset($ph1ent['nat_traversal']))
464
						$natt = $ph1ent['nat_traversal'];
465

    
466
					$init = "on";
467
					$genp = "off";
468
					if (isset($ph1ent['mobile'])) {
469
						$rgip = "anonymous";
470
						$init = "off";
471
						$genp = "unique";
472
					}
473

    
474
					$dpdline1 = '';
475
					$dpdline2 = '';
476
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
477
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
478
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
479
					}
480

    
481
					if (isset ($ph1ent['authentication_method']))
482
						$authmethod = $ph1ent['authentication_method'];
483
					else
484
						$authmethod = 'pre_shared_key';
485

    
486
					$certline = '';
487

    
488
					if (strstr($authmethod,'rsa')) {
489

    
490
						$cert = lookup_cert($ph1ent['certref']);
491

    
492
						if (!$cert)
493
						{
494
							log_error("Error: Invalid phase1 certificate reference for {$ph1ent['name']}");
495
							continue;
496
						}
497

    
498
						$certfile = "cert-".$ikeid.".crt";
499
						$certpath = $g['varetc_path']."/".$certfile;
500

    
501
						if (!file_put_contents($certpath, base64_decode($cert['crt'])))
502
						{
503
							log_error("Error: Cannot write phase1 certificate file for {$ph1ent['name']}");
504
							continue;
505
						}
506

    
507
						chmod($certpath, 0600);
508

    
509
						$keyfile = "cert-".$ikeid.".key";
510
						$keypath = $g['varetc_path']."/".$keyfile;
511

    
512
						if (!file_put_contents($keypath, base64_decode($cert['crt'])))
513
						{
514
							log_error("Error: Cannot write phase1 key file for {$ph1ent['name']}");
515
							continue;
516
						}
517

    
518
						chmod($keypath, 0600);
519

    
520
						$certline = "certificate_type x509 \"{$certpath}\" \"{$keypath}.key\";";
521
					}
522

    
523
					$ealgos = '';
524
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
525
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
526
					if ($ealg_kl)
527
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
528
					else
529
						$ealgos = $ealgos.$ealg_id;
530

    
531
					$lifeline = '';
532
					if ($ph1ent['lifetime'])
533
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
534

    
535
					/* add remote section to configuration */
536

    
537
					$racoonconf .=<<<EOD
538

    
539
remote {$rgip}
540
{
541
	ph1id {$ikeid};
542
	exchange_mode {$ph1ent['mode']};
543
	my_identifier {$myid_type} {$myid_data};
544
	peers_identifier {$peerid_type} {$peerid_data};
545
	ike_frag on;
546
	generate_policy = {$genp};
547
	initial_contact = {$init};
548
	nat_traversal = {$natt};
549
	{$certline}
550
	{$dpdline1}
551
	{$dpdline2}
552
	support_proxy on;
553
	proposal_check claim;
554

    
555
	proposal
556
	{
557
		authentication_method {$authmethod};
558
		encryption_algorithm ${ealgos};
559
		hash_algorithm {$ph1ent['hash-algorithm']};
560
		dh_group {$ph1ent['dhgroup']};
561
		${lifeline}
562
	}
563
}
564

    
565
EOD;
566
				}
567
				/* end remote */
568
			}
569
			/* end remote sections */
570
		
571
			/* begin sainfo sections */
572
			if (is_array($a_phase2) && count($a_phase2)) {
573

    
574
				/* begin sainfo */
575
				foreach ($a_phase2 as $ph2ent) {
576

    
577
					$ikeid = $ph2ent['ikeid'];
578

    
579
					if (isset($ph2ent['disabled']))
580
						continue;
581

    
582
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
583
						continue;
584

    
585
					$localid_type = $ph2ent['localid']['type'];
586
					if ($localid_type != "address")
587
						$localid_type = "subnet";
588

    
589
					$localid_data = ipsec_idinfo_to_cidr($ph2ent['localid']);
590
					$localid_spec = $localid_type." ".$localid_data." any";
591

    
592
					if (!isset($ph2ent['mobile'])) {
593

    
594
						$remoteid_type = $ph2ent['remoteid']['type'];
595
						if ($remoteid_type != "address")
596
							$remoteid_type = "subnet";
597

    
598
						$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
599
						$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
600

    
601
					} else
602
						$remoteid_spec = "anonymous";
603

    
604
					$ealgos = '';
605
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
606

    
607
					$pfsline = '';
608
					if ($ph2ent['pfsgroup'])
609
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
610
					if (isset($a_client['pfs_group'])) {
611
						$pfsline = '';
612
						if ($a_client['pfs_group'])
613
							$pfsline = "pfs_group {$a_client['pfs_group']};";
614
					}
615

    
616
					$lifeline = '';
617
					if ($ph2ent['lifetime'])
618
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
619

    
620
					foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
621

    
622
						$ealg_id = $ealg['name'];
623
						$ealg_kl = $ealg['keylen'];
624

    
625
						if ($ealg_kl) {
626
							if( $ealg_kl == "auto" ) {
627
								$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
628
								$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
629
								$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
630

    
631
								for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
632
									if( $ealgos )
633
										$ealgos = $ealgos.", ";
634
									$ealgos = $ealgos.$ealg_id." ".$keylen;
635
								}
636
							} else {
637
								if ($ealgos)
638
									$ealgos = $ealgos.", ";
639
								$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
640
							}
641
						} else {
642
							if ($ealgos)
643
								$ealgos = $ealgos.", ";
644
							$ealgos = $ealgos.$ealg_id;
645
						}
646
					}
647

    
648
					/* add sainfo section to configuration */
649
					
650
					$racoonconf .=<<<EOD
651
					
652
sainfo {$localid_spec} {$remoteid_spec}
653
{
654
	remoteid {$ikeid};
655
	encryption_algorithm {$ealgos};
656
	authentication_algorithm {$halgos};
657
	compression_algorithm deflate;
658
	{$pfsline}
659
	{$lifeline}
660
}
661

    
662
EOD;
663
				}
664
				/* end sainfo */
665
			}
666
			/* end sainfo sections */
667

    
668
			fwrite($fd, $racoonconf);
669
			fclose($fd);
670
		}
671
		/* end racoon.conf */
672

    
673
		/* generate IPsec policies */
674
		if (is_array($a_phase2) && count($a_phase2)) {
675
			/* generate spd.conf */
676
			$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
677
			if (!$fd) {
678
				printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
679
				return 1;
680
			}
681

    
682
			$spdconf = "";
683

    
684
			/* What are these SPD entries for?
685
			 * -mgrooms 07/10/2008
686
			 */
687
			$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
688
			$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
689

    
690
			foreach ($a_phase2 as $ph2ent) {
691

    
692
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
693
					continue;
694

    
695
				if (isset($ph1ent['mobile']))
696
					continue;
697

    
698
				if (isset($ph1ent['disabled']))
699
					continue;
700

    
701
				if (isset($ph2ent['disabled']))
702
					continue;
703

    
704
				$ep = ipsec_get_phase1_src($ph1ent);
705
				if (!$ep)
706
					continue;
707

    
708
				$rgip = $rgmap[$ph1ent['remote-gateway']];
709

    
710
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
711
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
712

    
713
				if (isset ($ph2ent['creategif'])) {
714
					$number_of_gifs = find_last_gif_device();
715
					$number_of_gifs++;
716
					$curwanip = get_interface_ip();
717
					if ($config['installedpackages']['sasyncd']['config'] <> "") {
718
						foreach ($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
719
							if ($sasyncd['ip'] <> "")
720
								$curwanip = $sasyncd['ip'];
721
						}
722
					}
723
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " tunnel" . $curwanip . " " . $rgip);
724
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " {$lansa}/{$lansn} {$lanip}/32");
725
				}
726

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

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

    
733
				/* static route needed? */
734
				if (preg_match("/^carp/i", $ph1ent['interface']))
735
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
736
				else
737
					$parentinterface = $ph1ent['interface'];
738

    
739
				if ($parentinterface <> "wan") {
740
					/* add endpoint routes to correct gateway on interface */
741
					if (interface_has_gateway($parentinterface)) {
742
						$gatewayip = get_interface_gateway("$parentinterface");
743
						$interfaceip = $config['interfaces'][$parentinterface]['ipaddr'];
744
						$subnet_bits = $config['interfaces'][$parentinterface]['subnet'];
745
						$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
746
						/* if the remote gateway is in the local subnet, then don't add a route */
747
						if (! ip_in_subnet($rgip, "{$subnet_ip}/{$subnet_bits}")) {
748
							if(is_ipaddr($gatewayip)) {
749
								/* FIXME: does adding route-to and reply-to on the in/outbound
750
								 * rules fix this? smos@ 13-01-2009 */
751
								log_error("IPSEC interface is not WAN but {$parentinterface}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
752
								mwexec("/sbin/route delete -host {$rgip}");
753
								mwexec("/sbin/route add -host {$rgip} {$gatewayip}");
754
							}
755
						}
756
					}
757
				}
758
				else
759
				{
760
					if(stristr($route_str, "/{$rgip}/")) {
761
						mwexec("/sbin/route delete -host {$rgip}");
762
					}
763
				}
764
			}
765

    
766
			fwrite($fd, $spdconf);
767
			fclose($fd);
768
		}
769

    
770
		/* needed for racoonctl admin socket */
771
		if (!file_exists("/var/db/racoon"))
772
			mkdir("/var/db/racoon/");
773
		
774
		/* mange racoon process */
775
		if (is_process_running("racoon")) {
776
			sleep("0.1");
777
			log_error("IPSEC: Sent a reload signal to the IPsec process");
778
			mwexec("/usr/local/sbin/racoonctl -s /var/run/racoon.sock reload-config", false);
779
		} else {
780
			/* flush SA + SPD entries */
781
			mwexec("/usr/local/sbin/setkey -FP", false);
782
 			sleep("0.1");
783
			mwexec("/usr/local/sbin/setkey -F", false);
784
 			sleep("0.1");
785
 			/* start racoon */
786
			mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf", false);
787
 			sleep("0.1");
788
 			/* load SPD */
789
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
790
 			/* We are already online, reload */
791
 			sleep("0.1");
792
			mwexec("/usr/bin/killall -HUP racoon", false);
793

    
794
			/* start dnswatch, if necessary */
795
			if (count($dnswatch_list) > 0) {
796
				$interval = 60;
797
				if ($ipseccfg['dns-interval'])
798
					$interval = $ipseccfg['dns-interval'];
799

    
800
				$hostnames = "";
801
				foreach ($dnswatch_list as $dns)
802
					$hostnames .= " " . escapeshellarg($dns);
803

    
804
				killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
805
				mwexec("/usr/local/sbin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval " .
806
				escapeshellarg("/etc/rc.newipsecdns") . $hostnames);
807
			}
808
		}
809
	}
810
	
811
	vpn_ipsec_failover_configure();
812

    
813
	if (!$g['booting']) {
814
		/* reload the filter */
815
		filter_configure();
816
	}
817

    
818
	if ($g['booting'])
819
		echo "done\n";
820

    
821
	return 0;
822
}
823

    
824
/* Forcefully restart IPsec
825
 * This is required for when dynamic interfaces reload
826
 * For all other occasions the normal vpn_ipsec_configure()
827
 * will gracefully reload the settings without restarting
828
 */
829
function vpn_ipsec_force_reload() {
830
	global $config;
831
	global $g;
832

    
833
	$ipseccfg = $config['ipsec'];
834

    
835
	/* kill racoon */
836
	mwexec("/usr/bin/killall racoon", true);
837

    
838
	/* wait for process to die */
839
	sleep(4);
840

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

    
844
	/* wait for flushing to finish */
845
	sleep(1);
846

    
847
	/* if ipsec is enabled, start up again */
848
	if (isset($ipseccfg['enable'])) {
849
		log_error("Forcefully reloading IPsec racoon daemon");
850
		vpn_ipsec_configure();
851
	}
852

    
853
}
854

    
855
/* master setup for vpn (mpd) */
856
function vpn_setup() {
857
	/* start pptpd */
858
	vpn_pptpd_configure();
859

    
860
	/* start pppoe server */
861
	vpn_pppoe_configure();
862

    
863
	/* setup l2tp */
864
	vpn_l2tp_configure();
865
}
866

    
867
function vpn_pptpd_configure() {
868
	global $config, $g;
869

    
870
	$syscfg = $config['system'];
871
	$pptpdcfg = $config['pptpd'];
872

    
873
	if ($g['booting']) {
874
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
875
			return 0;
876

    
877
		echo "Configuring PPTP VPN service... ";
878
	} else {
879
		/* kill mpd */
880
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
881

    
882
		/* wait for process to die */
883
		sleep(3);
884

    
885
		if (is_process_running("mpd -b")) {
886
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
887
			log_error("Could not kill mpd within 3 seconds.   Trying again.");
888
		}
889

    
890
		/* remove mpd.conf, if it exists */
891
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
892
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
893
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
894
	}
895

    
896
	/* make sure pptp-vpn directory exists */
897
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
898
		mkdir("{$g['varetc_path']}/pptp-vpn");
899

    
900
	switch ($pptpdcfg['mode']) {
901
		case 'server' :
902
			/* write mpd.conf */
903
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
904
			if (!$fd) {
905
				printf("Error: cannot open mpd.conf in vpn_pptpd_configure().\n");
906
				return 1;
907
			}
908

    
909
			$mpdconf =<<<EOD
910
pptpd:
911

    
912
EOD;
913

    
914
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
915
				$mpdconf .= "	load pt{$i}\n";
916
			}
917

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

    
920
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
921

    
922
				if(isset($pptpdcfg['radius']['radiusissueips']) && isset($pptpdcfg['radius']['enable'])) {
923
					$isssue_ip_type = "set ipcp ranges {$pptpdcfg['localip']}/32 0.0.0.0/0";
924
				} else {
925
					$isssue_ip_type = "set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32";
926
				}
927

    
928
				$mpdconf .=<<<EOD
929

    
930
pt{$i}:
931
	new pt{$i} pt{$i}
932
	{$isssue_ip_type}
933
	load pts
934

    
935
EOD;
936
			}
937

    
938
			$mpdconf .=<<<EOD
939

    
940
pts:
941
	set iface disable on-demand
942
	set iface enable proxy-arp
943
	set iface enable tcpmssfix
944
	set iface idle 1800
945
	set iface up-script /usr/local/sbin/pptp-linkup
946
	set iface down-script /usr/local/sbin/vpn-linkdown
947
	set bundle enable multilink
948
	set bundle enable crypt-reqd
949
	set link yes acfcomp protocomp
950
	set link no pap chap
951
	set link enable chap-msv2
952
	set link mtu 1460
953
	set link keep-alive 10 60
954
	set ipcp yes vjcomp
955
	set bundle enable compression
956
	set ccp yes mppc
957
	set ccp yes mpp-e128
958
	set ccp yes mpp-stateless
959

    
960
EOD;
961

    
962
			if (!isset ($pptpdcfg['req128'])) {
963
				$mpdconf .=<<<EOD
964
	set ccp yes mpp-e40
965
	set ccp yes mpp-e56
966

    
967
EOD;
968
			}
969

    
970
			if  (isset($pptpdcfg["wins"]) && $pptpdcfg['wins'] != "")
971
				$mpdconf  .=  "	set ipcp nbns {$pptpdcfg['wins']}\n";
972
			if (is_array($pptpdcfg['dnsserver']) && ($pptpdcfg['dnsserver'][0])) {
973
				$mpdconf .= "	set ipcp dns " . join(" ", $pptpdcfg['dnsserver']) . "\n";
974
			} else
975
				if (isset ($config['dnsmasq']['enable'])) {
976
					$mpdconf .= "	set ipcp dns " . $config['interfaces']['lan']['ipaddr'];
977
					if ($syscfg['dnsserver'][0])
978
						$mpdconf .= " " . $syscfg['dnsserver'][0];
979
					$mpdconf .= "\n";
980
				} else
981
					if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
982
						$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
983
					}
984

    
985
			if (isset ($pptpdcfg['radius']['enable'])) {
986
				$authport = isset($pptpdcfg['radius']['port']) ? $pptpdcfg['radius']['port'] : 1812;
987
				$acctport = $authport + 1;
988
				$mpdconf .=<<<EOD
989
	set radius server {$pptpdcfg['radius']['server']} "{$pptpdcfg['radius']['secret']}" {$authport} {$acctport}
990
	set radius retries 3
991
	set radius timeout 10
992
	set auth enable radius-auth
993

    
994
EOD;
995

    
996
				if (isset ($pptpdcfg['radius']['accounting'])) {
997
					$mpdconf .=<<<EOD
998
	set auth enable radius-acct
999
	set radius acct-update 300
1000

    
1001
EOD;
1002
				}
1003
			}
1004

    
1005
			fwrite($fd, $mpdconf);
1006
			fclose($fd);
1007

    
1008
			/* write mpd.links */
1009
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.links", "w");
1010
			if (!$fd) {
1011
				printf("Error: cannot open mpd.links in vpn_pptpd_configure().\n");
1012
				return 1;
1013
			}
1014

    
1015
			$mpdlinks = "";
1016

    
1017
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1018
				$mpdlinks .=<<<EOD
1019

    
1020
pt{$i}:
1021
	set link type pptp
1022
	set pptp enable incoming
1023
	set pptp disable originate
1024
	set pptp disable windowing
1025

    
1026
EOD;
1027
			}
1028

    
1029
			fwrite($fd, $mpdlinks);
1030
			fclose($fd);
1031

    
1032
			/* write mpd.secret */
1033
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1034
			if (!$fd) {
1035
				printf("Error: cannot open mpd.secret in vpn_pptpd_configure().\n");
1036
				return 1;
1037
			}
1038

    
1039
			$mpdsecret = "";
1040

    
1041
			if (is_array($pptpdcfg['user'])) {
1042
				foreach ($pptpdcfg['user'] as $user)
1043
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1044
			}
1045

    
1046
			fwrite($fd, $mpdsecret);
1047
			fclose($fd);
1048
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1049

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

    
1053
			break;
1054

    
1055
		case 'redir' :
1056
			break;
1057
	}
1058

    
1059
	if (!$g['booting']) {
1060
		/* reload the filter */
1061
		filter_configure();
1062
	}
1063

    
1064
	if ($g['booting'])
1065
		echo "done\n";
1066

    
1067
	return 0;
1068
}
1069

    
1070
function vpn_pppoe_configure() {
1071
	global $config, $g;
1072

    
1073
	$syscfg = $config['system'];
1074
	$pppoecfg = $config['pppoe'];
1075

    
1076
	/* create directory if it does not exist */
1077
	if (!is_dir("{$g['varetc_path']}/pppoe-vpn"))
1078
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1079

    
1080
	if ($g['booting']) {
1081
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1082
			return 0;
1083

    
1084
		echo "Configuring PPPoE VPN service... ";
1085
	} else {
1086
		/* kill mpd */
1087
		killbypid("{$g['varrun_path']}/pppoe-vpn.pid");
1088

    
1089
		/* wait for process to die */
1090
		sleep(2);
1091

    
1092
	}
1093

    
1094
	/* make sure pppoe-vpn directory exists */
1095
	if (!file_exists("{$g['varetc_path']}/pppoe-vpn"))
1096
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1097

    
1098
	switch ($pppoecfg['mode']) {
1099

    
1100
		case 'server' :
1101

    
1102
			$pppoe_interface = filter_translate_type_to_real_interface($pppoecfg['interface']);
1103

    
1104
			if ($pppoecfg['paporchap'] == "chap")
1105
				$paporchap = "set link enable chap";
1106
			else
1107
				$paporchap = "set link enable pap";
1108

    
1109
			/* write mpd.conf */
1110
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.conf", "w");
1111
			if (!$fd) {
1112
				printf("Error: cannot open mpd.conf in vpn_pppoe_configure().\n");
1113
				return 1;
1114
			}
1115
			$mpdconf = "\n\n";
1116
			$mpdconf .=<<<EOD
1117
pppoe:
1118

    
1119
EOD;
1120

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

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

    
1127
				$clientip = long2ip(ip2long($pppoecfg['remoteip']) + $i);
1128

    
1129
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['enable'])) {
1130
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1131
				} else {
1132
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1133
				}
1134

    
1135
				$mpdconf .=<<<EOD
1136

    
1137
pppoe{$i}:
1138
	new pppoe{$i} pppoe{$i}
1139
	{$isssue_ip_type}
1140
	load pppoe_standart
1141

    
1142
EOD;
1143
			}
1144

    
1145
			$mpdconf .=<<<EOD
1146

    
1147
pppoe_standart:
1148
	set bundle no multilink
1149
	set bundle enable compression
1150
	set auth max-logins 1
1151
	set iface up-script /usr/local/sbin/pppoe-linkup
1152
        set iface down-script /usr/local/sbin/vpn-linkdown
1153
	set iface idle 0
1154
	set iface disable on-demand
1155
	set iface disable proxy-arp
1156
	set iface enable tcpmssfix
1157
	set iface mtu 1500
1158
	set link no pap chap
1159
	{$paporchap}
1160
	set link keep-alive 60 180
1161
	set ipcp yes vjcomp
1162
	set ipcp no vjcomp
1163
	set link max-redial -1
1164
	set link mtu 1492
1165
	set link mru 1492
1166
	set ccp yes mpp-e40
1167
	set ccp yes mpp-e128
1168
	set ccp yes mpp-stateless
1169
	set link latency 1
1170
	#set ipcp dns 10.10.1.3
1171
	#set bundle accept encryption
1172

    
1173
EOD;
1174

    
1175
			if (isset ($config['dnsmasq']['enable'])) {
1176
				$mpdconf .= "	set ipcp dns " . $config['interfaces']['lan']['ipaddr'];
1177
				if ($syscfg['dnsserver'][0])
1178
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1179
				$mpdconf .= "\n";
1180
			} else
1181
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1182
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1183
				}
1184

    
1185
			if (isset ($pppoecfg['radius']['enable'])) {
1186
				$mpdconf .=<<<EOD
1187
	set radius server {$pppoecfg['radius']['server']} "{$pppoecfg['radius']['secret']}"
1188
	set radius retries 3
1189
	set radius timeout 10
1190
	set auth enable radius-auth
1191

    
1192
EOD;
1193

    
1194
				if (isset ($pppoecfg['radius']['accounting'])) {
1195
					$mpdconf .=<<<EOD
1196
	set auth enable radius-acct
1197

    
1198
EOD;
1199
				}
1200
			}
1201

    
1202
			fwrite($fd, $mpdconf);
1203
			fclose($fd);
1204

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

    
1212
			$mpdlinks = "";
1213

    
1214
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1215
				$mpdlinks .=<<<EOD
1216
			
1217
pppoe{$i}:
1218
	set phys type pppoe
1219
        set pppoe iface {$pppoe_interface}
1220
        set pppoe service "*"
1221
        set pppoe disable originate
1222
        set pppoe enable incoming
1223

    
1224
EOD;
1225
			}
1226

    
1227
			fwrite($fd, $mpdlinks);
1228
			fclose($fd);
1229

    
1230
			/* write mpd.secret */
1231
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.secret", "w");
1232
			if (!$fd) {
1233
				printf("Error: cannot open mpd.secret in vpn_pppoe_configure().\n");
1234
				return 1;
1235
			}
1236

    
1237
			$mpdsecret = "\n\n";
1238

    
1239
			if (is_array($pppoecfg['user'])) {
1240
				foreach ($pppoecfg['user'] as $user)
1241
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1242
			}
1243

    
1244
			fwrite($fd, $mpdsecret);
1245
			fclose($fd);
1246
			chmod("{$g['varetc_path']}/pppoe-vpn/mpd.secret", 0600);
1247

    
1248
			/* fire up mpd */
1249
			mwexec("/usr/local/sbin/mpd4 -b -d {$g['varetc_path']}/pppoe-vpn -p {$g['varrun_path']}/pppoe-vpn.pid pppoe");
1250

    
1251
			break;
1252

    
1253
		case 'redir' :
1254
			break;
1255
	}
1256

    
1257
	filter_configure();
1258

    
1259
	if ($g['booting'])
1260
		echo "done\n";
1261

    
1262
	return 0;
1263
}
1264

    
1265
function vpn_l2tp_configure() {
1266
	global $config, $g;
1267

    
1268
	$syscfg = $config['system'];
1269
	$l2tpcfg = $config['l2tp'];
1270

    
1271
	if (!is_module_loaded("ng_l2tp.ko"))
1272
		mwexec("/sbin/kldload /boot/kernel/ng_l2tp.ko");
1273

    
1274
	/* create directory if it does not exist */
1275
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1276
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1277

    
1278
	if ($g['booting']) {
1279
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1280
			return 0;
1281

    
1282
		echo "Configuring l2tp VPN service... ";
1283
	} else {
1284
		/* kill mpd */
1285
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1286

    
1287
		/* wait for process to die */
1288
		sleep(8);
1289

    
1290
	}
1291

    
1292
	/* make sure l2tp-vpn directory exists */
1293
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1294
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1295

    
1296
	switch ($l2tpcfg['mode']) {
1297

    
1298
		case 'server' :
1299
			if ($l2tpcfg['paporchap'] == "chap")
1300
				$paporchap = "set link enable chap";
1301
			else
1302
				$paporchap = "set link enable pap";
1303

    
1304
			/* write mpd.conf */
1305
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1306
			if (!$fd) {
1307
				printf("Error: cannot open mpd.conf in vpn_l2tp_configure().\n");
1308
				return 1;
1309
			}
1310
			$mpdconf = "\n\n";
1311
			$mpdconf .=<<<EOD
1312
l2tp:
1313

    
1314
EOD;
1315

    
1316
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1317
				$mpdconf .= "	load l2tp{$i}\n";
1318
			}
1319

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

    
1322
				$clientip = long2ip(ip2long($l2tpcfg['remoteip']) + $i);
1323

    
1324
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1325
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1326
				} else {
1327
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1328
				}
1329

    
1330
				$mpdconf .=<<<EOD
1331

    
1332
l2tp{$i}:
1333
	new l2tp{$i} l2tp{$i}
1334
	{$isssue_ip_type}
1335
	load l2tp_standard
1336

    
1337
EOD;
1338
			}
1339

    
1340
			$mpdconf .=<<<EOD
1341

    
1342
l2tp_standard:
1343
        set bundle disable multilink
1344
        set bundle enable compression
1345
        set bundle yes crypt-reqd
1346
        set ipcp yes vjcomp
1347
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1348
        set ccp yes mppc
1349
        set iface disable on-demand
1350
        set iface enable proxy-arp
1351
	set iface up-script /usr/local/sbin/l2tp-linkup
1352
        set iface down-script /usr/local/sbin/vpn-linkdown
1353
        set link yes acfcomp protocomp
1354
        set link no pap chap
1355
        set link enable chap
1356
        set link keep-alive 10 180
1357

    
1358
EOD;
1359

    
1360
			if (isset ($config['dnsmasq']['enable'])) {
1361
				$mpdconf .= "	set ipcp dns " . $config['interfaces']['lan']['ipaddr'];
1362
				if ($syscfg['dnsserver'][0])
1363
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1364
				$mpdconf .= "\n";
1365
			} else
1366
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1367
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1368
				}
1369

    
1370
			if (isset ($l2tpcfg['radius']['enable'])) {
1371
				$mpdconf .=<<<EOD
1372
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1373
	set radius retries 3
1374
	set radius timeout 10
1375
	set auth enable radius-auth
1376

    
1377
EOD;
1378

    
1379
				if (isset ($l2tpcfg['radius']['accounting'])) {
1380
					$mpdconf .=<<<EOD
1381
	set auth enable radius-acct
1382

    
1383
EOD;
1384
				}
1385
			}
1386

    
1387
			fwrite($fd, $mpdconf);
1388
			fclose($fd);
1389

    
1390
			/* write mpd.links */
1391
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.links", "w");
1392
			if (!$fd) {
1393
				printf("Error: cannot open mpd.links in vpn_l2tp_configure().\n");
1394
				return 1;
1395
			}
1396

    
1397
			$mpdlinks = "";
1398

    
1399
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1400
				$mpdlinks .=<<<EOD
1401

    
1402
l2tp{$i}:
1403
	set link type l2tp
1404
        set l2tp enable incoming
1405
        set l2tp disable originate
1406

    
1407
EOD;
1408
			}
1409

    
1410
			fwrite($fd, $mpdlinks);
1411
			fclose($fd);
1412

    
1413
			/* write mpd.secret */
1414
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1415
			if (!$fd) {
1416
				printf("Error: cannot open mpd.secret in vpn_l2tp_configure().\n");
1417
				return 1;
1418
			}
1419

    
1420
			$mpdsecret = "\n\n";
1421

    
1422
			if (is_array($l2tpcfg['user'])) {
1423
				foreach ($l2tpcfg['user'] as $user)
1424
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1425
			}
1426

    
1427
			fwrite($fd, $mpdsecret);
1428
			fclose($fd);
1429
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1430

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

    
1434
			break;
1435

    
1436
		case 'redir' :
1437
			break;
1438
	}
1439

    
1440
	filter_configure();
1441

    
1442
	if ($g['booting'])
1443
		echo "done\n";
1444

    
1445
	return 0;
1446
}
1447

    
1448
/* Walk the tunnels for hostname endpoints. If the hostnames 
1449
 * resolve to a different IP now compared to the DNS cache
1450
 * we reload the policies if the endpoint has changed */
1451
function vpn_ipsec_refresh_policies() {
1452
	global $config;
1453
	global $g;
1454

    
1455
	$ipseccfg = $config['ipsec'];
1456
	$a_phase1 = $config['ipsec']['phase1'];
1457
	$a_phase2 = $config['ipsec']['phase2'];
1458

    
1459
	if (isset($ipseccfg['disable'])) {
1460
		return true;
1461
	}
1462

    
1463
	/* Walk the Ipsec tunnel array */
1464
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1465
		return;
1466
	}
1467

    
1468
	foreach ($a_phase1 as $phase1) {
1469
		if (isset($phase1['disabled'])) {
1470
			continue;
1471
		}
1472
		if (is_ipaddr($phase1['remote-gateway'])) {
1473
			continue;
1474
		}
1475
		if (!is_ipaddr($phase1['remote-gateway'])) {
1476
			$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1477
			$dnscache = trim($dnscache);
1478
			/* we should have the old IP addresses in the dnscache now */
1479
			if($dnscache <> "") {
1480
				$oldphase1 = $phase1;
1481
				$oldphase1['remote-gateway'] = trim($dnscache);
1482
				/* now we need to find all tunnels for this host */
1483
				if (!is_array($a_phase2) || (!count($a_phase2))) {
1484
					continue;
1485
				}
1486
				foreach ($a_phase2 as $phase2) {
1487
					if($phase2['ikeid'] == $phase1['ikeid']) {
1488
						reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1489
					}
1490
				}
1491
			}
1492
		}
1493
	}
1494

    
1495
	/* process all generated spd.conf files from tmp which are left behind
1496
	 * behind by either changes of dynamic tunnels or manual edits
1497
	 * scandir() is only available in PHP5 */
1498
	$tmpfiles = array();
1499
	$dh  = opendir($g['tmp_path']);
1500
	while (false !== ($filename = readdir($dh))) {
1501
		$tmpfiles[] = $filename;
1502
	}
1503
	sort($tmpfiles);
1504
	foreach($tmpfiles as $tmpfile) {
1505
		if(preg_match("/^spd.conf.reload./", $tmpfile)) {
1506
			$ret = mwexec("/usr/local/sbin/setkey -f {$g['tmp_path']}/{$tmpfile} 2>&1", false);
1507
			if($ret == 0) {
1508
				// unlink_if_exists("{$g['tmp_path']}/{$tmpfile}");
1509
			} else {
1510
				rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1511
			}
1512
		}
1513
	}
1514
}
1515

    
1516
/* reloads the tunnel configuration for a tunnel item
1517
 * Will remove and add SPD polices */
1518
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1519
	global $config;
1520
	global $g;
1521

    
1522
	/* if we are not passed a old tunnel array we create one */
1523
	if(empty($old_phase1)) {
1524
		$old_phase1 = $phase1;
1525
	}
1526
	if(empty($old_phase2)) {
1527
		$old_phase2 = $phase2;
1528
	}
1529

    
1530
	$sad_arr = ipsec_dump_sad();
1531

    
1532
	$ep = ipsec_get_phase1_src($phase1);
1533
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1534
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1535

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

    
1539
	$old_ep = ipsec_get_phase1_src($old_phase1);
1540
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1541
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1542

    
1543
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1544
	 * try to resolve it now and add it to the list for dnswatch */
1545
	if (!is_ipaddr($phase1['remote-gateway'])) {
1546
		$rgip = resolve_retry($phase1['remote-gateway']);
1547
		add_hostname_to_watch($phase1['remote-gateway']);
1548
		if (!$rgip) {
1549
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1550
			return false;
1551
		}
1552
	} else {
1553
		$rgip = $phase1['remote-gateway'];
1554
	}
1555
	if (!$ep) {
1556
		log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1557
		return false;
1558
	}
1559

    
1560
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1561
		log_error("IPSEC: ERROR: One of the endpoints is not a IP address. Old EP '{$old_ep}' new EP '{$ep}'");
1562
	}
1563
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1564
		log_error("IPSEC: ERROR: One of the remote endpoints is not a IP address. Old RG '{$old_gw}' new RG '{$rgip}'");
1565
	}
1566

    
1567
	$spdconf = "";
1568
	/* Delete old SPD policies if there are changes between the old and new */
1569
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1570
		$spdconf .= "spddelete {$old_local_subnet} " .
1571
			"{$old_remote_subnet} any -P out ipsec " .
1572
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1573
			"{$old_gw}/unique;\n";
1574
		$spdconf .= "spddelete {$old_remote_subnet} " .
1575
			"{$old_local_subnet} any -P in ipsec " .
1576
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1577
			"{$old_ep}/unique;\n";
1578

    
1579
		/* zap any existing SA entries */
1580
		foreach($sad_arr as $sad) {
1581
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1582
				$spdconf .= "delete {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1583
			}
1584
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1585
				$spdconf .= "delete {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1586
			}
1587
		}
1588
	}
1589

    
1590
	/* Create new SPD entries for the new configuration */
1591
	/* zap any existing SA entries beforehand */
1592
	foreach($sad_arr as $sad) {
1593
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1594
			$spdconf .= "delete {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1595
		}
1596
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1597
			$spdconf .= "delete {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1598
		}
1599
	}
1600
	/* add new SPD policies to replace them */
1601
	$spdconf .= "spdadd {$local_subnet} " .
1602
		"{$remote_subnet} any -P out ipsec " .
1603
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1604
		"{$rgip}/unique;\n";
1605
	$spdconf .= "spdadd {$remote_subnet} " .
1606
		"{$local_subnet} any -P in ipsec " .
1607
		"{$phase2['protocol']}/tunnel/{$rgip}-" .
1608
		"{$ep}/unique;\n";
1609

    
1610
	log_error("IPSEC: Tunnel '{$phase1['descr']}' has changed IP from '{$old_gw}' to '{$rgip}', reloading policy");
1611

    
1612
	$now = time();
1613
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1614
	/* generate temporary spd.conf */
1615
	file_put_contents($spdfile, $spdconf);
1616
	return true;
1617
}
1618

    
1619
?>
(34-34/39)