Project

General

Profile

Download (44.5 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 = get_interface_ip("lan");
119
	$lansn = get_interface_subnet("lan");
120
	$lansa = gen_subnet($lanip, $lansn);
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
	} else {
141
		if ($g['booting'])
142
			echo "Configuring IPsec VPN... ";
143

    
144
		/* fastforwarding is not compatible with ipsec tunnels */
145
		mwexec("/sbin/sysctl net.inet.ip.fastforwarding=0");
146

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

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

    
158
		/* resolve all local, peer addresses and setup pings */
159
		$ipmap = array();
160
		$rgmap = array();
161
		$dnswatch_list = array();
162
		if (is_array($a_phase1) && count($a_phase1)) {
163

    
164
			/* step through each phase1 entry */
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
				/* step through each phase2 entry */
195
				foreach ($a_phase2 as $ph2ent) {
196

    
197
					$ikeid = $ph2ent['ikeid'];
198

    
199
					if (isset($ph2ent['disabled']))
200
						continue;
201

    
202
					if ($ikeid != $ph1ent['ikeid'])
203
						continue;
204

    
205
					/* add an ipsec pinghosts entry */
206
					if ($ph2ent['pinghost']) {
207
						$pfd = fopen("/var/db/ipsecpinghosts", "a");
208
						$iflist = get_configured_interface_list();
209
						foreach ($iflist as $ifent => $ifname) {
210
							$interface_ip = get_interface_ip($ifent);
211
							$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
212
							if (ip_in_subnet($interface_ip, $local_subnet))
213
								$srcip = $interface_ip;
214
						}
215
						$dstip = $ph2ent['pinghost'];
216
						fwrite($pfd, "$srcip|$dstip|3\n");
217
						fclose($pfd);
218
					}
219
				}
220
			}
221
		}
222

    
223
		/* generate CA certificates files */
224
		if (is_array($config['system']['ca']) && count($config['system']['ca'])) {
225
			foreach ($config['system']['ca'] as $ca) {
226
				if (!isset($ca['crt'])) {
227
					log_error("Error: Invalid certificate info for {$ca['name']}");
228
					continue;
229
				}
230
				$cert = base64_decode($ca['crt']);
231
				$x509cert = openssl_x509_parse(openssl_x509_read($cert));
232
				if (!is_array($x509cert) || !isset($x509cert['hash'])) {
233
					log_error("Error: Invalid certificate hash info for {$ca['name']}");
234
					continue;
235
				}
236
				$fname = $g['varetc_path']."/".$x509cert['hash'];
237
				if (!file_put_contents($fname, $cert)) {
238
					log_error("Error: Cannot write IPsec CA file for {$ca['name']}");
239
					continue;
240
				}
241
			}
242
		}
243
		
244
		/* generate psk.txt */
245
		$fd = fopen("{$g['varetc_path']}/psk.txt", "w");
246
		if (!$fd) {
247
			printf("Error: cannot open psk.txt in vpn_ipsec_configure().\n");
248
			return 1;
249
		}
250

    
251
		$pskconf = "";
252

    
253
		if (is_array($a_phase1) && count($a_phase1)) {
254
			foreach ($a_phase1 as $ph1ent) {
255

    
256
				if (isset($ph1ent['disabled']))
257
					continue;
258

    
259
				if (strstr($ph1ent['authentication_method'],'rsa'))
260
					continue;
261

    
262
				$peerid_type = $ph1ent['peerid_type'];
263

    
264
				switch ($peerid_type) {
265
					case "peeraddress":
266
						$peerid_type = "address";
267
						$peerid_data = $rgmap[$ph1ent['remote-gateway']];
268
						break;
269

    
270
					case "address";
271
						$peerid_data = $ph1ent['peerid_data'];
272
						break;
273

    
274
					case "fqdn";
275
					case "keyid tag";
276
					case "user_fqdn";
277
						$peerid_data = $ph1ent['peerid_data'];
278
						break;
279
				}
280

    
281
				$pskconf .= "{$peerid_data}\t{$ph1ent['pre-shared-key']}\n";
282
			}
283
		}
284

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

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

    
299
			$racoonconf = "# This file is automatically generated. Do not edit\n";			
300
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
301
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
302

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

    
315
			/* begin mode_cfg section */
316
			if (is_array($a_client) && isset($a_client['enable'])) {
317

    
318
				$racoonconf .= "\nmode_cfg\n";
319
				$racoonconf .= "{\n";
320

    
321
				if ($a_client['user_source'])
322
					$racoonconf .= "\tauth_source {$a_client['user_source']};\n";
323
				if ($a_client['group_source'])
324
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
325

    
326
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
327
					$pool_address = $a_client['pool_address'];
328
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
329

    
330
					$pool_address = long2ip(ip2long($pool_address)+1);
331
					$pool_size = ~ip2long($pool_netmask) - 2;
332

    
333
					$racoonconf .= "\tpool_size {$pool_size};\n";
334
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
335
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
336
				}
337

    
338
				if (isset($a_client['net_list'])) {
339

    
340
					$net_list = '';
341

    
342
					foreach ($a_phase2 as $ph2ent) {
343

    
344
						if (isset($ph2ent['disabled']))
345
							continue;
346

    
347
						if (!isset($ph2ent['mobile']))
348
							continue;
349

    
350
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
351

    
352
						if ($net_list)
353
							$net_list .= ", ";
354
						$net_list .= $localid;
355
					}
356

    
357
					if ($net_list)
358
						$racoonconf .= "\tsplit_network include {$net_list};\n";
359
				}
360

    
361
				if ($a_client['dns_server1'])
362
					$racoonconf .= "\tdns4 {$a_client['dns_server1']};\n";
363
				if ($a_client['dns_server2'])
364
					$racoonconf .= "\tdns4 {$a_client['dns_server2']};\n";
365
				if ($a_client['dns_server3'])
366
					$racoonconf .= "\tdns4 {$a_client['dns_server3']};\n";
367
				if ($a_client['dns_server4'])
368
					$racoonconf .= "\tdns4 {$a_client['dns_server4']};\n";
369

    
370
				if ($a_client['wins_server1'])
371
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
372
				if ($a_client['wins_server2'])
373
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
374

    
375
				if ($a_client['dns_domain'])
376
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
377

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

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

    
389
					fwrite($fd1, $a_client['login_banner']);
390
					fclose($fd1);
391

    
392
					$racoonconf .= "\tbanner \"{$fn}\";\n";
393
				}
394

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

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

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

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

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

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

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

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

    
424
					switch ($myid_type) {
425

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

    
431
						case "dyn_dns":
432
							$myid_data = gethostbyname($ph1ent['myid_data']);
433
							break;
434

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

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

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

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

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

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

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

    
475
					$init = "on";
476
					$genp = "off";
477
					if (isset($ph1ent['mobile'])) {
478
						$rgip = "anonymous";
479
						$init = "off";
480
						$genp = "unique";
481
					}
482

    
483
					$dpdline1 = '';
484
					$dpdline2 = '';
485
					if ($ph1ent['dpd_delay'] && $ph1ent['dpd_maxfail']) {
486
						$dpdline1 = "dpd_delay = {$ph1ent['dpd_delay']};";
487
						$dpdline2 = "dpd_maxfail = {$ph1ent['dpd_maxfail']};";
488
					}
489

    
490
					if (isset ($ph1ent['authentication_method']))
491
						$authmethod = $ph1ent['authentication_method'];
492
					else
493
						$authmethod = 'pre_shared_key';
494

    
495
					$certline = '';
496

    
497
					if (strstr($authmethod,'rsa')) {
498

    
499
						$cert = lookup_cert($ph1ent['certref']);
500

    
501
						if (!$cert)
502
						{
503
							log_error("Error: Invalid phase1 certificate reference for {$ph1ent['name']}");
504
							continue;
505
						}
506

    
507
						$certfile = "cert-".$ikeid.".crt";
508
						$certpath = $g['varetc_path']."/".$certfile;
509

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

    
516
						chmod($certpath, 0600);
517

    
518
						$keyfile = "cert-".$ikeid.".key";
519
						$keypath = $g['varetc_path']."/".$keyfile;
520

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

    
527
						chmod($keypath, 0600);
528

    
529
						$certline = "certificate_type x509 \"{$certpath}\" \"{$keypath}.key\";";
530
					}
531

    
532
					$ealgos = '';
533
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
534
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
535
					if ($ealg_kl)
536
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
537
					else
538
						$ealgos = $ealgos.$ealg_id;
539

    
540
					$lifeline = '';
541
					if ($ph1ent['lifetime'])
542
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
543

    
544
					/* add remote section to configuration */
545

    
546
					$racoonconf .=<<<EOD
547

    
548
remote {$rgip}
549
{
550
	ph1id {$ikeid};
551
	exchange_mode {$ph1ent['mode']};
552
	my_identifier {$myid_type} {$myid_data};
553
	peers_identifier {$peerid_type} {$peerid_data};
554
	ike_frag on;
555
	generate_policy = {$genp};
556
	initial_contact = {$init};
557
	nat_traversal = {$natt};
558
	{$certline}
559
	{$dpdline1}
560
	{$dpdline2}
561
	support_proxy on;
562
	proposal_check claim;
563

    
564
	proposal
565
	{
566
		authentication_method {$authmethod};
567
		encryption_algorithm ${ealgos};
568
		hash_algorithm {$ph1ent['hash-algorithm']};
569
		dh_group {$ph1ent['dhgroup']};
570
		${lifeline}
571
	}
572
}
573

    
574
EOD;
575
				}
576
				/* end remote */
577
			}
578
			/* end remote sections */
579
		
580
			/* begin sainfo sections */
581
			if (is_array($a_phase2) && count($a_phase2)) {
582

    
583
				/* begin sainfo */
584
				foreach ($a_phase2 as $ph2ent) {
585

    
586
					$ikeid = $ph2ent['ikeid'];
587

    
588
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
589
						continue;
590

    
591
					if (isset($ph1ent['disabled']))
592
						continue;
593

    
594
					if (isset($ph2ent['disabled']))
595
						continue;
596

    
597
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
598
						continue;
599

    
600
					if ($ph2ent['mode'] == 'tunnel') {
601

    
602
						$localid_type = $ph2ent['localid']['type'];
603
						if ($localid_type != "address")
604
							$localid_type = "subnet";
605

    
606
						$localid_data = ipsec_idinfo_to_cidr($ph2ent['localid']);
607
						$localid_spec = $localid_type." ".$localid_data." any";
608

    
609
						if (!isset($ph2ent['mobile'])) {
610
							$remoteid_type = $ph2ent['remoteid']['type'];
611
							if ($remoteid_type != "address")
612
								$remoteid_type = "subnet";
613

    
614
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
615
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
616
						} else
617
							$remoteid_spec = "anonymous";
618

    
619
					} else {
620

    
621
						$rgip = $rgmap[$ph1ent['remote-gateway']];
622

    
623
						$localid_data = ipsec_get_phase1_src($ph1ent);
624
						$localid_spec = "address {$localid_data}";
625

    
626
						$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
627
						$remoteid_spec = "address {$remoteid_data}";
628
					}
629

    
630
					if($ph2ent['protocol'] == 'esp') {
631

    
632
						$ealgos = '';
633

    
634
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
635

    
636
							$ealg_id = $ealg['name'];
637
							$ealg_kl = $ealg['keylen'];
638

    
639
							if ($ealg_kl) {
640
								if( $ealg_kl == "auto" ) {
641
									/*   This seems to be required on my system and was not reproducable
642
									 *   on other systems.   For some reason $p2_ealgos is not defined
643
									 *   and needs to be read back in!?  -sullrich Aug 26, 2009 
644
									 */
645
									if(!$p2_ealgos)
646
										require("ipsec.inc");
647
									$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
648
									$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
649
									$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
650
									/* in some cases where include ordering is suspect these variables
651
									   are somehow 0 and we enter this loop forever and timeout after 900
652
									   seconds wrecking bootup */
653
									if($key_hi != 0 and $key_lo !=0 and $key_step !=0) {
654
										for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
655
//											Uncomment the next line if you want to test the comment 5 lines up.											
656
//											echo "$keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step \n";
657
											if ($ealgos)
658
												$ealgos = $ealgos.", ";
659
											$ealgos = $ealgos.$ealg_id." ".$keylen;
660
										}
661
									}
662
								} else {
663
									if ($ealgos)
664
										$ealgos = $ealgos.", ";
665
									$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
666
								}
667
							} else {
668
								if ($ealgos)
669
									$ealgos = $ealgos.", ";
670
								$ealgos = $ealgos.$ealg_id;
671
							}
672
						}
673

    
674
						$ealgosline = "encryption_algorithm {$ealgos};";
675

    
676
					} else {
677

    
678
						$ealgosline = "encryption_algorithm null_enc;";
679
					}
680

    
681
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
682
					$halgosline = "authentication_algorithm {$halgos};";
683

    
684
					$pfsline = '';
685
					if ($ph2ent['pfsgroup'])
686
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
687
					if (isset($a_client['pfs_group'])) {
688
						$pfsline = '';
689
						if ($a_client['pfs_group'])
690
							$pfsline = "pfs_group {$a_client['pfs_group']};";
691
					}
692

    
693
					$lifeline = '';
694
					if ($ph2ent['lifetime'])
695
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
696

    
697
					/* add sainfo section to configuration */
698
					
699
					$racoonconf .=<<<EOD
700
					
701
sainfo {$localid_spec} {$remoteid_spec}
702
{
703
	remoteid {$ikeid};
704
	{$ealgosline}
705
	{$halgosline}
706
	{$pfsline}
707
	{$lifeline}
708
	compression_algorithm deflate;
709
}
710

    
711
EOD;
712
				}
713
				/* end sainfo */
714
			}
715
			/* end sainfo sections */
716

    
717
			fwrite($fd, $racoonconf);
718
			fclose($fd);
719
		}
720
		/* end racoon.conf */
721

    
722
		/* generate IPsec policies */
723
		if (is_array($a_phase2) && count($a_phase2)) {
724
			/* generate spd.conf */
725
			$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
726
			if (!$fd) {
727
				printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
728
				return 1;
729
			}
730

    
731
			$spdconf = "";
732

    
733
			/* What are these SPD entries for?
734
			 * -mgrooms 07/10/2008
735
			 */
736
			$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
737
			$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
738

    
739
			foreach ($a_phase2 as $ph2ent) {
740

    
741
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
742
					continue;
743

    
744
				if (isset($ph1ent['mobile']))
745
					continue;
746

    
747
				if (isset($ph1ent['disabled']))
748
					continue;
749

    
750
				if (isset($ph2ent['disabled']))
751
					continue;
752

    
753
				$ep = ipsec_get_phase1_src($ph1ent);
754
				if (!$ep)
755
					continue;
756

    
757
				$rgip = $rgmap[$ph1ent['remote-gateway']];
758

    
759
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
760
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
761

    
762
				if (isset ($ph2ent['creategif'])) {
763
					$number_of_gifs = find_last_gif_device();
764
					$number_of_gifs++;
765
					$curwanip = get_interface_ip();
766
					if ($config['installedpackages']['sasyncd']['config'] <> "") {
767
						foreach ($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
768
							if ($sasyncd['ip'] <> "")
769
								$curwanip = $sasyncd['ip'];
770
						}
771
					}
772
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " tunnel" . $curwanip . " " . $rgip);
773
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " {$lansa}/{$lansn} {$lanip}/32");
774
				}
775

    
776
				if($ph2ent['mode'] == "tunnel") {
777

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

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

    
784
				} else {
785

    
786
					$spdconf .= "spdadd {$localid} {$remoteid} any -P out ipsec " .
787
						"{$ph2ent['protocol']}/transport//unique;\n";
788

    
789
					$spdconf .= "spdadd {$remoteid} {$localid} any -P in ipsec " .
790
						"{$ph2ent['protocol']}/transport//unique;\n";
791

    
792
				}
793

    
794
				/* static route needed? */
795
				if (preg_match("/^carp/i", $ph1ent['interface']))
796
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
797
				else
798
					$parentinterface = $ph1ent['interface'];
799

    
800
				if ($parentinterface <> "wan") {
801
					/* add endpoint routes to correct gateway on interface */
802
					if (interface_has_gateway($parentinterface)) {
803
						$gatewayip = get_interface_gateway("$parentinterface");
804
						$interfaceip = get_interface_ip($parentinterface);
805
						$subnet_bits = get_interface_subnet($parentinterface);
806
						$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
807
						/* if the remote gateway is in the local subnet, then don't add a route */
808
						if (! ip_in_subnet($rgip, "{$subnet_ip}/{$subnet_bits}")) {
809
							if(is_ipaddr($gatewayip)) {
810
								/* FIXME: does adding route-to and reply-to on the in/outbound
811
								 * rules fix this? smos@ 13-01-2009 */
812
								log_error("IPSEC interface is not WAN but {$parentinterface}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
813
								mwexec("/sbin/route delete -host {$rgip}");
814
								mwexec("/sbin/route add -host {$rgip} {$gatewayip}");
815
							}
816
						}
817
					}
818
				} else {
819
					if(stristr($route_str, "{$rgip}")) {
820
						mwexec("/sbin/route delete -host {$rgip}", true);
821
					}
822
				}
823
			}
824

    
825
			fwrite($fd, $spdconf);
826
			fclose($fd);
827
		}
828

    
829
		/* needed for racoonctl admin socket */
830
		if (!is_dir("/var/db/racoon"))
831
			mkdir("/var/db/racoon/");
832
		
833
		exec("/bin/mkdir -p /var/db/racoon");
834
		
835
		/* mange racoon process */
836
		if (is_process_running("racoon")) {
837
			sleep("0.1");
838
			mwexec("/usr/local/sbin/racoonctl -s /var/run/racoon.sock reload-config", false);
839
			/* load SPD without flushing to be safe on config additions or changes. */
840
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
841
		} else {
842
			/* flush SA + SPD entries */
843
			mwexec("/usr/local/sbin/setkey -FP", false);
844
 			sleep("0.1");
845
			mwexec("/usr/local/sbin/setkey -F", false);
846
 			sleep("0.1");
847
 			/* start racoon */
848
			mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf", false);
849
 			sleep("0.1");
850
 			/* load SPD */
851
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
852

    
853
			/* start dnswatch, if necessary */
854
			if (count($dnswatch_list) > 0) {
855
				$interval = 60;
856
				if ($ipseccfg['dns-interval'])
857
					$interval = $ipseccfg['dns-interval'];
858

    
859
				$hostnames = "";
860
				array_unique($dnswatch_list);
861
				$hostnames = implode("\n", $dnswatch_list);
862
				file_put_contents("{$g['varetc_path']}/dnswatch-ipsec.hosts", $hostnames);
863

    
864
				killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
865
				mwexec("/usr/local/sbin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval /etc/rc.newipsecdns {$g['varetc_path']}/dnswatch-ipsec.hosts");
866
			}
867
		}
868
	
869
		vpn_ipsec_failover_configure();
870

    
871
		if ($g['booting'])
872
			echo "done\n";
873
	}
874

    
875
	return 0;
876
}
877

    
878
/* Forcefully restart IPsec
879
 * This is required for when dynamic interfaces reload
880
 * For all other occasions the normal vpn_ipsec_configure()
881
 * will gracefully reload the settings without restarting
882
 */
883
function vpn_ipsec_force_reload() {
884
	global $config;
885
	global $g;
886

    
887
	$ipseccfg = $config['ipsec'];
888

    
889
	/* kill racoon */
890
	mwexec("/usr/bin/killall racoon", true);
891

    
892
	/* wait for process to die */
893
	sleep(4);
894

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

    
898
	/* wait for flushing to finish */
899
	sleep(1);
900

    
901
	/* if ipsec is enabled, start up again */
902
	if (isset($ipseccfg['enable'])) {
903
		log_error("Forcefully reloading IPsec racoon daemon");
904
		vpn_ipsec_configure();
905
	}
906

    
907
}
908

    
909
/* master setup for vpn (mpd) */
910
function vpn_setup() {
911
	/* start pptpd */
912
	vpn_pptpd_configure();
913

    
914
	/* start pppoe server */
915
	vpn_pppoe_configure();
916

    
917
	/* setup l2tp */
918
	vpn_l2tp_configure();
919
}
920

    
921
function vpn_pptpd_configure() {
922
	global $config, $g;
923

    
924
	$syscfg = $config['system'];
925
	$pptpdcfg = $config['pptpd'];
926

    
927
	if ($g['booting']) {
928
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
929
			return 0;
930

    
931
		echo "Configuring PPTP VPN service... ";
932
	} else {
933
		/* kill mpd */
934
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
935

    
936
		/* wait for process to die */
937
		sleep(3);
938

    
939
		if (is_process_running("mpd -b")) {
940
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
941
			log_error("Could not kill mpd within 3 seconds.   Trying again.");
942
		}
943

    
944
		/* remove mpd.conf, if it exists */
945
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
946
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
947
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
948
	}
949

    
950
	/* make sure pptp-vpn directory exists */
951
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
952
		mkdir("{$g['varetc_path']}/pptp-vpn");
953

    
954
	switch ($pptpdcfg['mode']) {
955
		case 'server' :
956
			/* write mpd.conf */
957
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
958
			if (!$fd) {
959
				printf("Error: cannot open mpd.conf in vpn_pptpd_configure().\n");
960
				return 1;
961
			}
962

    
963
			$mpdconf =<<<EOD
964
pptpd:
965

    
966
EOD;
967

    
968
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
969
				$mpdconf .= "	load pt{$i}\n";
970
			}
971

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

    
974
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
975

    
976
				if(isset($pptpdcfg['radius']['radiusissueips']) && isset($pptpdcfg['radius']['server']['enable'])) {
977
					$isssue_ip_type = "set ipcp ranges {$pptpdcfg['localip']}/32 0.0.0.0/0";
978
				} else {
979
					$isssue_ip_type = "set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32";
980
				}
981

    
982
				$mpdconf .=<<<EOD
983

    
984
pt{$i}:
985
	new pt{$i} pt{$i}
986
	{$isssue_ip_type}
987
	load pts
988

    
989
EOD;
990
			}
991

    
992
			$mpdconf .=<<<EOD
993

    
994
pts:
995
	set iface disable on-demand
996
	set iface enable proxy-arp
997
	set iface enable tcpmssfix
998
	set iface idle 1800
999
	set iface up-script /usr/local/sbin/pptp-linkup
1000
	set iface down-script /usr/local/sbin/vpn-linkdown
1001
	set bundle enable multilink
1002
	set bundle enable crypt-reqd
1003
	set link yes acfcomp protocomp
1004
	set link no pap chap
1005
	set link enable chap-msv2
1006
	set link mtu 1460
1007
	set link keep-alive 10 60
1008
	set ipcp yes vjcomp
1009
	set bundle enable compression
1010
	set ccp yes mppc
1011
	set ccp yes mpp-e128
1012
	set ccp yes mpp-stateless
1013

    
1014
EOD;
1015

    
1016
			if (!isset ($pptpdcfg['req128'])) {
1017
				$mpdconf .=<<<EOD
1018
	set ccp yes mpp-e40
1019
	set ccp yes mpp-e56
1020

    
1021
EOD;
1022
			}
1023

    
1024
			if  (isset($pptpdcfg["wins"]) && $pptpdcfg['wins'] != "")
1025
				$mpdconf  .=  "	set ipcp nbns {$pptpdcfg['wins']}\n";
1026
			if (is_array($pptpdcfg['dnsserver']) && ($pptpdcfg['dnsserver'][0])) {
1027
				$mpdconf .= "	set ipcp dns " . join(" ", $pptpdcfg['dnsserver']) . "\n";
1028
			} else
1029
				if (isset ($config['dnsmasq']['enable'])) {
1030
					$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1031
					if ($syscfg['dnsserver'][0])
1032
						$mpdconf .= " " . $syscfg['dnsserver'][0];
1033
					$mpdconf .= "\n";
1034
				} else
1035
					if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1036
						$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1037
					}
1038

    
1039
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1040
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1041
				$acctport = $authport + 1;
1042
				$mpdconf .=<<<EOD
1043
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1044
EOD;
1045
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1046
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1047
				$acctport = $authport + 1;
1048
				$mpdconf .=<<<EOD
1049
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret']}" {$authport} {$acctport}
1050
EOD;
1051
			}
1052
			$mpdconf .=<<<EOD
1053
	set radius retries 3
1054
	set radius timeout 10
1055
	set auth enable radius-auth
1056

    
1057
EOD;
1058

    
1059
				if (isset ($pptpdcfg['radius']['accounting'])) {
1060
					$mpdconf .=<<<EOD
1061
	set auth enable radius-acct
1062
	set radius acct-update 300
1063

    
1064
EOD;
1065
				}
1066
			}
1067

    
1068
			fwrite($fd, $mpdconf);
1069
			fclose($fd);
1070

    
1071
			/* write mpd.links */
1072
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.links", "w");
1073
			if (!$fd) {
1074
				printf("Error: cannot open mpd.links in vpn_pptpd_configure().\n");
1075
				return 1;
1076
			}
1077

    
1078
			$mpdlinks = "";
1079

    
1080
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1081
				$mpdlinks .=<<<EOD
1082

    
1083
pt{$i}:
1084
	set link type pptp
1085
	set pptp enable incoming
1086
	set pptp disable originate
1087
	set pptp disable windowing
1088

    
1089
EOD;
1090
			}
1091

    
1092
			fwrite($fd, $mpdlinks);
1093
			fclose($fd);
1094

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

    
1102
			$mpdsecret = "";
1103

    
1104
			if (is_array($pptpdcfg['user'])) {
1105
				foreach ($pptpdcfg['user'] as $user)
1106
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1107
			}
1108

    
1109
			fwrite($fd, $mpdsecret);
1110
			fclose($fd);
1111
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1112

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

    
1116
			break;
1117

    
1118
		case 'redir' :
1119
			break;
1120
	}
1121

    
1122
	if ($g['booting'])
1123
		echo "done\n";
1124

    
1125
	return 0;
1126
}
1127

    
1128
function vpn_pppoe_configure() {
1129
	global $config, $g;
1130

    
1131
	$syscfg = $config['system'];
1132
	$pppoecfg = $config['pppoe'];
1133

    
1134
	/* create directory if it does not exist */
1135
	if (!is_dir("{$g['varetc_path']}/pppoe-vpn"))
1136
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1137

    
1138
	if ($g['booting']) {
1139
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1140
			return 0;
1141

    
1142
		echo "Configuring PPPoE VPN service... ";
1143
	} else {
1144
		/* kill mpd */
1145
		killbypid("{$g['varrun_path']}/pppoe-vpn.pid");
1146

    
1147
		/* wait for process to die */
1148
		sleep(2);
1149

    
1150
	}
1151

    
1152
	/* make sure pppoe-vpn directory exists */
1153
	if (!file_exists("{$g['varetc_path']}/pppoe-vpn"))
1154
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1155

    
1156
	switch ($pppoecfg['mode']) {
1157

    
1158
		case 'server' :
1159

    
1160
			$pppoe_interface = interface_translate_type_to_real($pppoecfg['interface']);
1161

    
1162
			if ($pppoecfg['paporchap'] == "chap")
1163
				$paporchap = "set link enable chap";
1164
			else
1165
				$paporchap = "set link enable pap";
1166

    
1167
			/* write mpd.conf */
1168
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.conf", "w");
1169
			if (!$fd) {
1170
				printf("Error: cannot open mpd.conf in vpn_pppoe_configure().\n");
1171
				return 1;
1172
			}
1173
			$mpdconf = "\n\n";
1174
			$mpdconf .=<<<EOD
1175
pppoe:
1176

    
1177
EOD;
1178

    
1179
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1180
				$mpdconf .= "	load pppoe{$i}\n";
1181
			}
1182

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

    
1185
				$clientip = long2ip(ip2long($pppoecfg['remoteip']) + $i);
1186

    
1187
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['enable'])) {
1188
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1189
				} else {
1190
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1191
				}
1192

    
1193
				$mpdconf .=<<<EOD
1194

    
1195
pppoe{$i}:
1196
	new pppoe{$i} pppoe{$i}
1197
	{$isssue_ip_type}
1198
	load pppoe_standart
1199

    
1200
EOD;
1201
			}
1202

    
1203
			$mpdconf .=<<<EOD
1204

    
1205
pppoe_standart:
1206
	set bundle no multilink
1207
	set bundle enable compression
1208
	set auth max-logins 1
1209
	set iface up-script /usr/local/sbin/pppoe-linkup
1210
        set iface down-script /usr/local/sbin/vpn-linkdown
1211
	set iface idle 0
1212
	set iface disable on-demand
1213
	set iface disable proxy-arp
1214
	set iface enable tcpmssfix
1215
	set iface mtu 1500
1216
	set link no pap chap
1217
	{$paporchap}
1218
	set link keep-alive 60 180
1219
	set ipcp yes vjcomp
1220
	set ipcp no vjcomp
1221
	set link max-redial -1
1222
	set link mtu 1492
1223
	set link mru 1492
1224
	set ccp yes mpp-e40
1225
	set ccp yes mpp-e128
1226
	set ccp yes mpp-stateless
1227
	set link latency 1
1228
	#set ipcp dns 10.10.1.3
1229
	#set bundle accept encryption
1230

    
1231
EOD;
1232

    
1233
			if (isset ($config['dnsmasq']['enable'])) {
1234
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1235
				if ($syscfg['dnsserver'][0])
1236
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1237
				$mpdconf .= "\n";
1238
			} else
1239
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1240
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1241
				}
1242

    
1243
			if (isset ($pppoecfg['radius']['enable'])) {
1244
				$mpdconf .=<<<EOD
1245
	set radius server {$pppoecfg['radius']['server']} "{$pppoecfg['radius']['secret']}"
1246
	set radius retries 3
1247
	set radius timeout 10
1248
	set auth enable radius-auth
1249

    
1250
EOD;
1251

    
1252
				if (isset ($pppoecfg['radius']['accounting'])) {
1253
					$mpdconf .=<<<EOD
1254
	set auth enable radius-acct
1255

    
1256
EOD;
1257
				}
1258
			}
1259

    
1260
			fwrite($fd, $mpdconf);
1261
			fclose($fd);
1262

    
1263
			/* write mpd.links */
1264
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.links", "w");
1265
			if (!$fd) {
1266
				printf("Error: cannot open mpd.links in vpn_pppoe_configure().\n");
1267
				return 1;
1268
			}
1269

    
1270
			$mpdlinks = "";
1271

    
1272
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1273
				$mpdlinks .=<<<EOD
1274
			
1275
pppoe{$i}:
1276
	set phys type pppoe
1277
        set pppoe iface {$pppoe_interface}
1278
        set pppoe service "*"
1279
        set pppoe disable originate
1280
        set pppoe enable incoming
1281

    
1282
EOD;
1283
			}
1284

    
1285
			fwrite($fd, $mpdlinks);
1286
			fclose($fd);
1287

    
1288
			/* write mpd.secret */
1289
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.secret", "w");
1290
			if (!$fd) {
1291
				printf("Error: cannot open mpd.secret in vpn_pppoe_configure().\n");
1292
				return 1;
1293
			}
1294

    
1295
			$mpdsecret = "\n\n";
1296

    
1297
			if (is_array($pppoecfg['user'])) {
1298
				foreach ($pppoecfg['user'] as $user)
1299
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1300
			}
1301

    
1302
			fwrite($fd, $mpdsecret);
1303
			fclose($fd);
1304
			chmod("{$g['varetc_path']}/pppoe-vpn/mpd.secret", 0600);
1305

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

    
1309
			break;
1310

    
1311
		case 'redir' :
1312
			break;
1313
	}
1314

    
1315
	if ($g['booting'])
1316
		echo "done\n";
1317

    
1318
	return 0;
1319
}
1320

    
1321
function vpn_l2tp_configure() {
1322
	global $config, $g;
1323

    
1324
	$syscfg = $config['system'];
1325
	$l2tpcfg = $config['l2tp'];
1326

    
1327
	/* create directory if it does not exist */
1328
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1329
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1330

    
1331
	if ($g['booting']) {
1332
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1333
			return 0;
1334

    
1335
		echo "Configuring l2tp VPN service... ";
1336
	} else {
1337
		/* kill mpd */
1338
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1339

    
1340
		/* wait for process to die */
1341
		sleep(8);
1342

    
1343
	}
1344

    
1345
	/* make sure l2tp-vpn directory exists */
1346
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1347
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1348

    
1349
	switch ($l2tpcfg['mode']) {
1350

    
1351
		case 'server' :
1352
			if ($l2tpcfg['paporchap'] == "chap")
1353
				$paporchap = "set link enable chap";
1354
			else
1355
				$paporchap = "set link enable pap";
1356

    
1357
			/* write mpd.conf */
1358
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1359
			if (!$fd) {
1360
				printf("Error: cannot open mpd.conf in vpn_l2tp_configure().\n");
1361
				return 1;
1362
			}
1363
			$mpdconf = "\n\n";
1364
			$mpdconf .=<<<EOD
1365
l2tp:
1366

    
1367
EOD;
1368

    
1369
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1370
				$mpdconf .= "	load l2tp{$i}\n";
1371
			}
1372

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

    
1375
				$clientip = long2ip(ip2long($l2tpcfg['remoteip']) + $i);
1376

    
1377
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1378
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1379
				} else {
1380
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1381
				}
1382

    
1383
				$mpdconf .=<<<EOD
1384

    
1385
l2tp{$i}:
1386
	new l2tp{$i} l2tp{$i}
1387
	{$isssue_ip_type}
1388
	load l2tp_standard
1389

    
1390
EOD;
1391
			}
1392

    
1393
			$mpdconf .=<<<EOD
1394

    
1395
l2tp_standard:
1396
        set bundle disable multilink
1397
        set bundle enable compression
1398
        set bundle yes crypt-reqd
1399
        set ipcp yes vjcomp
1400
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1401
        set ccp yes mppc
1402
        set iface disable on-demand
1403
        set iface enable proxy-arp
1404
	set iface up-script /usr/local/sbin/l2tp-linkup
1405
        set iface down-script /usr/local/sbin/vpn-linkdown
1406
        set link yes acfcomp protocomp
1407
        set link no pap chap
1408
        set link enable chap
1409
        set link keep-alive 10 180
1410

    
1411
EOD;
1412

    
1413
			if (isset ($config['dnsmasq']['enable'])) {
1414
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1415
				if ($syscfg['dnsserver'][0])
1416
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1417
				$mpdconf .= "\n";
1418
			} else
1419
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1420
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1421
				}
1422

    
1423
			if (isset ($l2tpcfg['radius']['enable'])) {
1424
				$mpdconf .=<<<EOD
1425
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1426
	set radius retries 3
1427
	set radius timeout 10
1428
	set auth enable radius-auth
1429

    
1430
EOD;
1431

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

    
1436
EOD;
1437
				}
1438
			}
1439

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

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

    
1450
			$mpdlinks = "";
1451

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

    
1455
l2tp{$i}:
1456
	set link type l2tp
1457
        set l2tp enable incoming
1458
        set l2tp disable originate
1459

    
1460
EOD;
1461
			if (!empty($l2tpcfg['secret']))
1462
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1463
			}
1464

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

    
1468
			/* write mpd.secret */
1469
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.secret", "w");
1470
			if (!$fd) {
1471
				printf("Error: cannot open mpd.secret in vpn_l2tp_configure().\n");
1472
				return 1;
1473
			}
1474

    
1475
			$mpdsecret = "\n\n";
1476

    
1477
			if (is_array($l2tpcfg['user'])) {
1478
				foreach ($l2tpcfg['user'] as $user)
1479
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1480
			}
1481

    
1482
			fwrite($fd, $mpdsecret);
1483
			fclose($fd);
1484
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1485

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

    
1489
			break;
1490

    
1491
		case 'redir' :
1492
			break;
1493
	}
1494

    
1495
	if ($g['booting'])
1496
		echo "done\n";
1497

    
1498
	return 0;
1499
}
1500

    
1501
/* Walk the tunnels for hostname endpoints. If the hostnames 
1502
 * resolve to a different IP now compared to the DNS cache
1503
 * we reload the policies if the endpoint has changed */
1504
function vpn_ipsec_refresh_policies() {
1505
	global $config;
1506
	global $g;
1507

    
1508
	$ipseccfg = $config['ipsec'];
1509
	$a_phase1 = $config['ipsec']['phase1'];
1510
	$a_phase2 = $config['ipsec']['phase2'];
1511

    
1512
	if (isset($ipseccfg['disable'])) {
1513
		return true;
1514
	}
1515

    
1516
	/* Walk the Ipsec tunnel array */
1517
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1518
		return;
1519
	}
1520

    
1521
	foreach ($a_phase1 as $phase1) {
1522
		if (isset($phase1['disabled'])) {
1523
			continue;
1524
		}
1525
		if (is_ipaddr($phase1['remote-gateway'])) {
1526
			continue;
1527
		}
1528
		if (!is_ipaddr($phase1['remote-gateway'])) {
1529
			$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1530
			$dnscache = trim($dnscache);
1531
			/* we should have the old IP addresses in the dnscache now */
1532
			if($dnscache <> "") {
1533
				$oldphase1 = $phase1;
1534
				$oldphase1['remote-gateway'] = trim($dnscache);
1535
				/* now we need to find all tunnels for this host */
1536
				if (!is_array($a_phase2) || (!count($a_phase2))) {
1537
					continue;
1538
				}
1539
				foreach ($a_phase2 as $phase2) {
1540
					if($phase2['ikeid'] == $phase1['ikeid']) {
1541
						reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1542
					}
1543
				}
1544
			}
1545
		}
1546
	}
1547

    
1548
	/* process all generated spd.conf files from tmp which are left behind
1549
	 * behind by either changes of dynamic tunnels or manual edits
1550
	 * scandir() is only available in PHP5 */
1551
	$tmpfiles = array();
1552
	$dh  = opendir($g['tmp_path']);
1553
	while (false !== ($filename = readdir($dh))) {
1554
		if(preg_match("/^spd.conf.reload./", $tmpfile)) {
1555
			$tmpfiles[] = $filename;
1556
		}
1557
	}
1558
	sort($tmpfiles);
1559
	foreach($tmpfiles as $tmpfile) {
1560
		$ret = mwexec("/usr/local/sbin/setkey -f {$g['tmp_path']}/{$tmpfile} 2>&1", false);
1561
		if($ret == 0) {
1562
			unlink_if_exists("{$g['tmp_path']}/{$tmpfile}");
1563
		} else {
1564
			rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1565
		}
1566
	}
1567
}
1568

    
1569
/* reloads the tunnel configuration for a tunnel item
1570
 * Will remove and add SPD polices */
1571
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1572
	global $config;
1573
	global $g;
1574

    
1575
	/* if we are not passed a old tunnel array we create one */
1576
	if(empty($old_phase1)) {
1577
		$old_phase1 = $phase1;
1578
	}
1579
	if(empty($old_phase2)) {
1580
		$old_phase2 = $phase2;
1581
	}
1582

    
1583
	$sad_arr = ipsec_dump_sad();
1584

    
1585
	$ep = ipsec_get_phase1_src($phase1);
1586
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1587
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1588

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

    
1592
	$old_ep = ipsec_get_phase1_src($old_phase1);
1593
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1594
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1595

    
1596
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1597
	 * try to resolve it now and add it to the list for dnswatch */
1598
	if (!is_ipaddr($phase1['remote-gateway'])) {
1599
		$rgip = resolve_retry($phase1['remote-gateway']);
1600
		add_hostname_to_watch($phase1['remote-gateway']);
1601
		if (!$rgip) {
1602
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1603
			return false;
1604
		}
1605
	} else {
1606
		$rgip = $phase1['remote-gateway'];
1607
	}
1608
	if (!$ep) {
1609
		log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1610
		return false;
1611
	}
1612

    
1613
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1614
		log_error("IPSEC: ERROR: One of the endpoints is not a IP address. Old EP '{$old_ep}' new EP '{$ep}'");
1615
	}
1616
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1617
		log_error("IPSEC: ERROR: One of the remote endpoints is not a IP address. Old RG '{$old_gw}' new RG '{$rgip}'");
1618
	}
1619

    
1620
	$spdconf = "";
1621
	/* Delete old SPD policies if there are changes between the old and new */
1622
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1623
		$spdconf .= "spddelete {$old_local_subnet} " .
1624
			"{$old_remote_subnet} any -P out ipsec " .
1625
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1626
			"{$old_gw}/unique;\n";
1627
		$spdconf .= "spddelete {$old_remote_subnet} " .
1628
			"{$old_local_subnet} any -P in ipsec " .
1629
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1630
			"{$old_ep}/unique;\n";
1631

    
1632
		/* zap any existing SA entries */
1633
		foreach($sad_arr as $sad) {
1634
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1635
				$spdconf .= "delete {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1636
			}
1637
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1638
				$spdconf .= "delete {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1639
			}
1640
		}
1641
	}
1642

    
1643
	/* Create new SPD entries for the new configuration */
1644
	/* zap any existing SA entries beforehand */
1645
	foreach($sad_arr as $sad) {
1646
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1647
			$spdconf .= "delete {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1648
		}
1649
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1650
			$spdconf .= "delete {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1651
		}
1652
	}
1653
	/* add new SPD policies to replace them */
1654
	$spdconf .= "spdadd {$local_subnet} " .
1655
		"{$remote_subnet} any -P out ipsec " .
1656
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1657
		"{$rgip}/unique;\n";
1658
	$spdconf .= "spdadd {$remote_subnet} " .
1659
		"{$local_subnet} any -P in ipsec " .
1660
		"{$phase2['protocol']}/tunnel/{$rgip}-" .
1661
		"{$ep}/unique;\n";
1662

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

    
1665
	$now = time();
1666
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1667
	/* generate temporary spd.conf */
1668
	file_put_contents($spdfile, $spdconf);
1669
	return true;
1670
}
1671

    
1672
?>
(39-39/44)