Project

General

Profile

Download (43.8 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($ifnet);
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
									$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
642
									$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
643
									$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
644

    
645
									for ($keylen = $key_hi; $keylen >= $key_lo; $keylen -= $key_step) {
646
										if ($ealgos)
647
											$ealgos = $ealgos.", ";
648
										$ealgos = $ealgos.$ealg_id." ".$keylen;
649
									}
650
								} else {
651
									if ($ealgos)
652
										$ealgos = $ealgos.", ";
653
									$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
654
								}
655
							} else {
656
								if ($ealgos)
657
									$ealgos = $ealgos.", ";
658
								$ealgos = $ealgos.$ealg_id;
659
							}
660
						}
661

    
662
						$ealgosline = "encryption_algorithm {$ealgos};";
663

    
664
					} else {
665

    
666
						$ealgosline = "encryption_algorithm null_enc;";
667
					}
668

    
669
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
670
					$halgosline = "authentication_algorithm {$halgos};";
671

    
672
					$pfsline = '';
673
					if ($ph2ent['pfsgroup'])
674
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
675
					if (isset($a_client['pfs_group'])) {
676
						$pfsline = '';
677
						if ($a_client['pfs_group'])
678
							$pfsline = "pfs_group {$a_client['pfs_group']};";
679
					}
680

    
681
					$lifeline = '';
682
					if ($ph2ent['lifetime'])
683
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
684

    
685
					/* add sainfo section to configuration */
686
					
687
					$racoonconf .=<<<EOD
688
					
689
sainfo {$localid_spec} {$remoteid_spec}
690
{
691
	remoteid {$ikeid};
692
	{$ealgosline}
693
	{$halgosline}
694
	{$pfsline}
695
	{$lifeline}
696
	compression_algorithm deflate;
697
}
698

    
699
EOD;
700
				}
701
				/* end sainfo */
702
			}
703
			/* end sainfo sections */
704

    
705
			fwrite($fd, $racoonconf);
706
			fclose($fd);
707
		}
708
		/* end racoon.conf */
709

    
710
		/* generate IPsec policies */
711
		if (is_array($a_phase2) && count($a_phase2)) {
712
			/* generate spd.conf */
713
			$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
714
			if (!$fd) {
715
				printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
716
				return 1;
717
			}
718

    
719
			$spdconf = "";
720

    
721
			/* What are these SPD entries for?
722
			 * -mgrooms 07/10/2008
723
			 */
724
			$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
725
			$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
726

    
727
			foreach ($a_phase2 as $ph2ent) {
728

    
729
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
730
					continue;
731

    
732
				if (isset($ph1ent['mobile']))
733
					continue;
734

    
735
				if (isset($ph1ent['disabled']))
736
					continue;
737

    
738
				if (isset($ph2ent['disabled']))
739
					continue;
740

    
741
				$ep = ipsec_get_phase1_src($ph1ent);
742
				if (!$ep)
743
					continue;
744

    
745
				$rgip = $rgmap[$ph1ent['remote-gateway']];
746

    
747
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
748
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
749

    
750
				if (isset ($ph2ent['creategif'])) {
751
					$number_of_gifs = find_last_gif_device();
752
					$number_of_gifs++;
753
					$curwanip = get_interface_ip();
754
					if ($config['installedpackages']['sasyncd']['config'] <> "") {
755
						foreach ($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
756
							if ($sasyncd['ip'] <> "")
757
								$curwanip = $sasyncd['ip'];
758
						}
759
					}
760
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " tunnel" . $curwanip . " " . $rgip);
761
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " {$lansa}/{$lansn} {$lanip}/32");
762
				}
763

    
764
				if($ph2ent['mode'] == "tunnel") {
765

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

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

    
772
				} else {
773

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

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

    
780
				}
781

    
782
				/* static route needed? */
783
				if (preg_match("/^carp/i", $ph1ent['interface']))
784
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
785
				else
786
					$parentinterface = $ph1ent['interface'];
787

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

    
813
			fwrite($fd, $spdconf);
814
			fclose($fd);
815
		}
816

    
817
		/* needed for racoonctl admin socket */
818
		if (!is_dir("/var/db/racoon"))
819
			mkdir("/var/db/racoon/");
820
		
821
		exec("/bin/mkdir -p /var/db/racoon");
822
		
823
		/* mange racoon process */
824
		if (is_process_running("racoon")) {
825
			sleep("0.1");
826
			mwexec("/usr/local/sbin/racoonctl -s /var/run/racoon.sock reload-config", false);
827
			/* load SPD without flushing to be safe on config additions or changes. */
828
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
829
		} else {
830
			/* flush SA + SPD entries */
831
			mwexec("/usr/local/sbin/setkey -FP", false);
832
 			sleep("0.1");
833
			mwexec("/usr/local/sbin/setkey -F", false);
834
 			sleep("0.1");
835
 			/* start racoon */
836
			mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf", false);
837
 			sleep("0.1");
838
 			/* load SPD */
839
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
840

    
841
			/* start dnswatch, if necessary */
842
			if (count($dnswatch_list) > 0) {
843
				$interval = 60;
844
				if ($ipseccfg['dns-interval'])
845
					$interval = $ipseccfg['dns-interval'];
846

    
847
				$hostnames = "";
848
				array_unique($dnswatch_list);
849
				$hostnames = implode("\n", $dnswatch_list);
850
				file_put_contents("{$g['varetc_path']}/dnswatch-ipsec.hosts", $hostnames);
851

    
852
				killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
853
				mwexec("/usr/local/sbin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval /etc/rc.newipsecdns {$g['varetc_path']}/dnswatch-ipsec.hosts");
854
			}
855
		}
856
	
857
		vpn_ipsec_failover_configure();
858

    
859
		if ($g['booting'])
860
			echo "done\n";
861
	}
862

    
863
	return 0;
864
}
865

    
866
/* Forcefully restart IPsec
867
 * This is required for when dynamic interfaces reload
868
 * For all other occasions the normal vpn_ipsec_configure()
869
 * will gracefully reload the settings without restarting
870
 */
871
function vpn_ipsec_force_reload() {
872
	global $config;
873
	global $g;
874

    
875
	$ipseccfg = $config['ipsec'];
876

    
877
	/* kill racoon */
878
	mwexec("/usr/bin/killall racoon", true);
879

    
880
	/* wait for process to die */
881
	sleep(4);
882

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

    
886
	/* wait for flushing to finish */
887
	sleep(1);
888

    
889
	/* if ipsec is enabled, start up again */
890
	if (isset($ipseccfg['enable'])) {
891
		log_error("Forcefully reloading IPsec racoon daemon");
892
		vpn_ipsec_configure();
893
	}
894

    
895
}
896

    
897
/* master setup for vpn (mpd) */
898
function vpn_setup() {
899
	/* start pptpd */
900
	vpn_pptpd_configure();
901

    
902
	/* start pppoe server */
903
	vpn_pppoe_configure();
904

    
905
	/* setup l2tp */
906
	vpn_l2tp_configure();
907
}
908

    
909
function vpn_pptpd_configure() {
910
	global $config, $g;
911

    
912
	$syscfg = $config['system'];
913
	$pptpdcfg = $config['pptpd'];
914

    
915
	if ($g['booting']) {
916
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
917
			return 0;
918

    
919
		echo "Configuring PPTP VPN service... ";
920
	} else {
921
		/* kill mpd */
922
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
923

    
924
		/* wait for process to die */
925
		sleep(3);
926

    
927
		if (is_process_running("mpd -b")) {
928
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
929
			log_error("Could not kill mpd within 3 seconds.   Trying again.");
930
		}
931

    
932
		/* remove mpd.conf, if it exists */
933
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
934
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
935
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
936
	}
937

    
938
	/* make sure pptp-vpn directory exists */
939
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
940
		mkdir("{$g['varetc_path']}/pptp-vpn");
941

    
942
	switch ($pptpdcfg['mode']) {
943
		case 'server' :
944
			/* write mpd.conf */
945
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
946
			if (!$fd) {
947
				printf("Error: cannot open mpd.conf in vpn_pptpd_configure().\n");
948
				return 1;
949
			}
950

    
951
			$mpdconf =<<<EOD
952
pptpd:
953

    
954
EOD;
955

    
956
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
957
				$mpdconf .= "	load pt{$i}\n";
958
			}
959

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

    
962
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
963

    
964
				if(isset($pptpdcfg['radius']['radiusissueips']) && isset($pptpdcfg['radius']['server']['enable'])) {
965
					$isssue_ip_type = "set ipcp ranges {$pptpdcfg['localip']}/32 0.0.0.0/0";
966
				} else {
967
					$isssue_ip_type = "set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32";
968
				}
969

    
970
				$mpdconf .=<<<EOD
971

    
972
pt{$i}:
973
	new pt{$i} pt{$i}
974
	{$isssue_ip_type}
975
	load pts
976

    
977
EOD;
978
			}
979

    
980
			$mpdconf .=<<<EOD
981

    
982
pts:
983
	set iface disable on-demand
984
	set iface enable proxy-arp
985
	set iface enable tcpmssfix
986
	set iface idle 1800
987
	set iface up-script /usr/local/sbin/pptp-linkup
988
	set iface down-script /usr/local/sbin/vpn-linkdown
989
	set bundle enable multilink
990
	set bundle enable crypt-reqd
991
	set link yes acfcomp protocomp
992
	set link no pap chap
993
	set link enable chap-msv2
994
	set link mtu 1460
995
	set link keep-alive 10 60
996
	set ipcp yes vjcomp
997
	set bundle enable compression
998
	set ccp yes mppc
999
	set ccp yes mpp-e128
1000
	set ccp yes mpp-stateless
1001

    
1002
EOD;
1003

    
1004
			if (!isset ($pptpdcfg['req128'])) {
1005
				$mpdconf .=<<<EOD
1006
	set ccp yes mpp-e40
1007
	set ccp yes mpp-e56
1008

    
1009
EOD;
1010
			}
1011

    
1012
			if  (isset($pptpdcfg["wins"]) && $pptpdcfg['wins'] != "")
1013
				$mpdconf  .=  "	set ipcp nbns {$pptpdcfg['wins']}\n";
1014
			if (is_array($pptpdcfg['dnsserver']) && ($pptpdcfg['dnsserver'][0])) {
1015
				$mpdconf .= "	set ipcp dns " . join(" ", $pptpdcfg['dnsserver']) . "\n";
1016
			} else
1017
				if (isset ($config['dnsmasq']['enable'])) {
1018
					$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1019
					if ($syscfg['dnsserver'][0])
1020
						$mpdconf .= " " . $syscfg['dnsserver'][0];
1021
					$mpdconf .= "\n";
1022
				} else
1023
					if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1024
						$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1025
					}
1026

    
1027
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1028
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1029
				$acctport = $authport + 1;
1030
				$mpdconf .=<<<EOD
1031
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1032
EOD;
1033
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1034
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1035
				$acctport = $authport + 1;
1036
				$mpdconf .=<<<EOD
1037
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret']}" {$authport} {$acctport}
1038
EOD;
1039
			}
1040
			$mpdconf .=<<<EOD
1041
	set radius retries 3
1042
	set radius timeout 10
1043
	set auth enable radius-auth
1044

    
1045
EOD;
1046

    
1047
				if (isset ($pptpdcfg['radius']['accounting'])) {
1048
					$mpdconf .=<<<EOD
1049
	set auth enable radius-acct
1050
	set radius acct-update 300
1051

    
1052
EOD;
1053
				}
1054
			}
1055

    
1056
			fwrite($fd, $mpdconf);
1057
			fclose($fd);
1058

    
1059
			/* write mpd.links */
1060
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.links", "w");
1061
			if (!$fd) {
1062
				printf("Error: cannot open mpd.links in vpn_pptpd_configure().\n");
1063
				return 1;
1064
			}
1065

    
1066
			$mpdlinks = "";
1067

    
1068
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1069
				$mpdlinks .=<<<EOD
1070

    
1071
pt{$i}:
1072
	set link type pptp
1073
	set pptp enable incoming
1074
	set pptp disable originate
1075
	set pptp disable windowing
1076

    
1077
EOD;
1078
			}
1079

    
1080
			fwrite($fd, $mpdlinks);
1081
			fclose($fd);
1082

    
1083
			/* write mpd.secret */
1084
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1085
			if (!$fd) {
1086
				printf("Error: cannot open mpd.secret in vpn_pptpd_configure().\n");
1087
				return 1;
1088
			}
1089

    
1090
			$mpdsecret = "";
1091

    
1092
			if (is_array($pptpdcfg['user'])) {
1093
				foreach ($pptpdcfg['user'] as $user)
1094
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1095
			}
1096

    
1097
			fwrite($fd, $mpdsecret);
1098
			fclose($fd);
1099
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1100

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

    
1104
			break;
1105

    
1106
		case 'redir' :
1107
			break;
1108
	}
1109

    
1110
	if ($g['booting'])
1111
		echo "done\n";
1112

    
1113
	return 0;
1114
}
1115

    
1116
function vpn_pppoe_configure() {
1117
	global $config, $g;
1118

    
1119
	$syscfg = $config['system'];
1120
	$pppoecfg = $config['pppoe'];
1121

    
1122
	/* create directory if it does not exist */
1123
	if (!is_dir("{$g['varetc_path']}/pppoe-vpn"))
1124
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1125

    
1126
	if ($g['booting']) {
1127
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1128
			return 0;
1129

    
1130
		echo "Configuring PPPoE VPN service... ";
1131
	} else {
1132
		/* kill mpd */
1133
		killbypid("{$g['varrun_path']}/pppoe-vpn.pid");
1134

    
1135
		/* wait for process to die */
1136
		sleep(2);
1137

    
1138
	}
1139

    
1140
	/* make sure pppoe-vpn directory exists */
1141
	if (!file_exists("{$g['varetc_path']}/pppoe-vpn"))
1142
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1143

    
1144
	switch ($pppoecfg['mode']) {
1145

    
1146
		case 'server' :
1147

    
1148
			$pppoe_interface = interface_translate_type_to_real($pppoecfg['interface']);
1149

    
1150
			if ($pppoecfg['paporchap'] == "chap")
1151
				$paporchap = "set link enable chap";
1152
			else
1153
				$paporchap = "set link enable pap";
1154

    
1155
			/* write mpd.conf */
1156
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.conf", "w");
1157
			if (!$fd) {
1158
				printf("Error: cannot open mpd.conf in vpn_pppoe_configure().\n");
1159
				return 1;
1160
			}
1161
			$mpdconf = "\n\n";
1162
			$mpdconf .=<<<EOD
1163
pppoe:
1164

    
1165
EOD;
1166

    
1167
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1168
				$mpdconf .= "	load pppoe{$i}\n";
1169
			}
1170

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

    
1173
				$clientip = long2ip(ip2long($pppoecfg['remoteip']) + $i);
1174

    
1175
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['enable'])) {
1176
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1177
				} else {
1178
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1179
				}
1180

    
1181
				$mpdconf .=<<<EOD
1182

    
1183
pppoe{$i}:
1184
	new pppoe{$i} pppoe{$i}
1185
	{$isssue_ip_type}
1186
	load pppoe_standart
1187

    
1188
EOD;
1189
			}
1190

    
1191
			$mpdconf .=<<<EOD
1192

    
1193
pppoe_standart:
1194
	set bundle no multilink
1195
	set bundle enable compression
1196
	set auth max-logins 1
1197
	set iface up-script /usr/local/sbin/pppoe-linkup
1198
        set iface down-script /usr/local/sbin/vpn-linkdown
1199
	set iface idle 0
1200
	set iface disable on-demand
1201
	set iface disable proxy-arp
1202
	set iface enable tcpmssfix
1203
	set iface mtu 1500
1204
	set link no pap chap
1205
	{$paporchap}
1206
	set link keep-alive 60 180
1207
	set ipcp yes vjcomp
1208
	set ipcp no vjcomp
1209
	set link max-redial -1
1210
	set link mtu 1492
1211
	set link mru 1492
1212
	set ccp yes mpp-e40
1213
	set ccp yes mpp-e128
1214
	set ccp yes mpp-stateless
1215
	set link latency 1
1216
	#set ipcp dns 10.10.1.3
1217
	#set bundle accept encryption
1218

    
1219
EOD;
1220

    
1221
			if (isset ($config['dnsmasq']['enable'])) {
1222
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1223
				if ($syscfg['dnsserver'][0])
1224
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1225
				$mpdconf .= "\n";
1226
			} else
1227
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1228
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1229
				}
1230

    
1231
			if (isset ($pppoecfg['radius']['enable'])) {
1232
				$mpdconf .=<<<EOD
1233
	set radius server {$pppoecfg['radius']['server']} "{$pppoecfg['radius']['secret']}"
1234
	set radius retries 3
1235
	set radius timeout 10
1236
	set auth enable radius-auth
1237

    
1238
EOD;
1239

    
1240
				if (isset ($pppoecfg['radius']['accounting'])) {
1241
					$mpdconf .=<<<EOD
1242
	set auth enable radius-acct
1243

    
1244
EOD;
1245
				}
1246
			}
1247

    
1248
			fwrite($fd, $mpdconf);
1249
			fclose($fd);
1250

    
1251
			/* write mpd.links */
1252
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.links", "w");
1253
			if (!$fd) {
1254
				printf("Error: cannot open mpd.links in vpn_pppoe_configure().\n");
1255
				return 1;
1256
			}
1257

    
1258
			$mpdlinks = "";
1259

    
1260
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1261
				$mpdlinks .=<<<EOD
1262
			
1263
pppoe{$i}:
1264
	set phys type pppoe
1265
        set pppoe iface {$pppoe_interface}
1266
        set pppoe service "*"
1267
        set pppoe disable originate
1268
        set pppoe enable incoming
1269

    
1270
EOD;
1271
			}
1272

    
1273
			fwrite($fd, $mpdlinks);
1274
			fclose($fd);
1275

    
1276
			/* write mpd.secret */
1277
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.secret", "w");
1278
			if (!$fd) {
1279
				printf("Error: cannot open mpd.secret in vpn_pppoe_configure().\n");
1280
				return 1;
1281
			}
1282

    
1283
			$mpdsecret = "\n\n";
1284

    
1285
			if (is_array($pppoecfg['user'])) {
1286
				foreach ($pppoecfg['user'] as $user)
1287
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1288
			}
1289

    
1290
			fwrite($fd, $mpdsecret);
1291
			fclose($fd);
1292
			chmod("{$g['varetc_path']}/pppoe-vpn/mpd.secret", 0600);
1293

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

    
1297
			break;
1298

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

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

    
1306
	return 0;
1307
}
1308

    
1309
function vpn_l2tp_configure() {
1310
	global $config, $g;
1311

    
1312
	$syscfg = $config['system'];
1313
	$l2tpcfg = $config['l2tp'];
1314

    
1315
	/* create directory if it does not exist */
1316
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1317
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1318

    
1319
	if ($g['booting']) {
1320
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1321
			return 0;
1322

    
1323
		echo "Configuring l2tp VPN service... ";
1324
	} else {
1325
		/* kill mpd */
1326
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1327

    
1328
		/* wait for process to die */
1329
		sleep(8);
1330

    
1331
	}
1332

    
1333
	/* make sure l2tp-vpn directory exists */
1334
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1335
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1336

    
1337
	switch ($l2tpcfg['mode']) {
1338

    
1339
		case 'server' :
1340
			if ($l2tpcfg['paporchap'] == "chap")
1341
				$paporchap = "set link enable chap";
1342
			else
1343
				$paporchap = "set link enable pap";
1344

    
1345
			/* write mpd.conf */
1346
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1347
			if (!$fd) {
1348
				printf("Error: cannot open mpd.conf in vpn_l2tp_configure().\n");
1349
				return 1;
1350
			}
1351
			$mpdconf = "\n\n";
1352
			$mpdconf .=<<<EOD
1353
l2tp:
1354

    
1355
EOD;
1356

    
1357
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1358
				$mpdconf .= "	load l2tp{$i}\n";
1359
			}
1360

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

    
1363
				$clientip = long2ip(ip2long($l2tpcfg['remoteip']) + $i);
1364

    
1365
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1366
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1367
				} else {
1368
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1369
				}
1370

    
1371
				$mpdconf .=<<<EOD
1372

    
1373
l2tp{$i}:
1374
	new l2tp{$i} l2tp{$i}
1375
	{$isssue_ip_type}
1376
	load l2tp_standard
1377

    
1378
EOD;
1379
			}
1380

    
1381
			$mpdconf .=<<<EOD
1382

    
1383
l2tp_standard:
1384
        set bundle disable multilink
1385
        set bundle enable compression
1386
        set bundle yes crypt-reqd
1387
        set ipcp yes vjcomp
1388
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1389
        set ccp yes mppc
1390
        set iface disable on-demand
1391
        set iface enable proxy-arp
1392
	set iface up-script /usr/local/sbin/l2tp-linkup
1393
        set iface down-script /usr/local/sbin/vpn-linkdown
1394
        set link yes acfcomp protocomp
1395
        set link no pap chap
1396
        set link enable chap
1397
        set link keep-alive 10 180
1398

    
1399
EOD;
1400

    
1401
			if (isset ($config['dnsmasq']['enable'])) {
1402
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1403
				if ($syscfg['dnsserver'][0])
1404
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1405
				$mpdconf .= "\n";
1406
			} else
1407
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1408
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1409
				}
1410

    
1411
			if (isset ($l2tpcfg['radius']['enable'])) {
1412
				$mpdconf .=<<<EOD
1413
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1414
	set radius retries 3
1415
	set radius timeout 10
1416
	set auth enable radius-auth
1417

    
1418
EOD;
1419

    
1420
				if (isset ($l2tpcfg['radius']['accounting'])) {
1421
					$mpdconf .=<<<EOD
1422
	set auth enable radius-acct
1423

    
1424
EOD;
1425
				}
1426
			}
1427

    
1428
			fwrite($fd, $mpdconf);
1429
			fclose($fd);
1430

    
1431
			/* write mpd.links */
1432
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.links", "w");
1433
			if (!$fd) {
1434
				printf("Error: cannot open mpd.links in vpn_l2tp_configure().\n");
1435
				return 1;
1436
			}
1437

    
1438
			$mpdlinks = "";
1439

    
1440
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1441
				$mpdlinks .=<<<EOD
1442

    
1443
l2tp{$i}:
1444
	set link type l2tp
1445
        set l2tp enable incoming
1446
        set l2tp disable originate
1447

    
1448
EOD;
1449
			if (!empty($l2tpcfg['secret']))
1450
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1451
			}
1452

    
1453
			fwrite($fd, $mpdlinks);
1454
			fclose($fd);
1455

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

    
1463
			$mpdsecret = "\n\n";
1464

    
1465
			if (is_array($l2tpcfg['user'])) {
1466
				foreach ($l2tpcfg['user'] as $user)
1467
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1468
			}
1469

    
1470
			fwrite($fd, $mpdsecret);
1471
			fclose($fd);
1472
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1473

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

    
1477
			break;
1478

    
1479
		case 'redir' :
1480
			break;
1481
	}
1482

    
1483
	if ($g['booting'])
1484
		echo "done\n";
1485

    
1486
	return 0;
1487
}
1488

    
1489
/* Walk the tunnels for hostname endpoints. If the hostnames 
1490
 * resolve to a different IP now compared to the DNS cache
1491
 * we reload the policies if the endpoint has changed */
1492
function vpn_ipsec_refresh_policies() {
1493
	global $config;
1494
	global $g;
1495

    
1496
	$ipseccfg = $config['ipsec'];
1497
	$a_phase1 = $config['ipsec']['phase1'];
1498
	$a_phase2 = $config['ipsec']['phase2'];
1499

    
1500
	if (isset($ipseccfg['disable'])) {
1501
		return true;
1502
	}
1503

    
1504
	/* Walk the Ipsec tunnel array */
1505
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1506
		return;
1507
	}
1508

    
1509
	foreach ($a_phase1 as $phase1) {
1510
		if (isset($phase1['disabled'])) {
1511
			continue;
1512
		}
1513
		if (is_ipaddr($phase1['remote-gateway'])) {
1514
			continue;
1515
		}
1516
		if (!is_ipaddr($phase1['remote-gateway'])) {
1517
			$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1518
			$dnscache = trim($dnscache);
1519
			/* we should have the old IP addresses in the dnscache now */
1520
			if($dnscache <> "") {
1521
				$oldphase1 = $phase1;
1522
				$oldphase1['remote-gateway'] = trim($dnscache);
1523
				/* now we need to find all tunnels for this host */
1524
				if (!is_array($a_phase2) || (!count($a_phase2))) {
1525
					continue;
1526
				}
1527
				foreach ($a_phase2 as $phase2) {
1528
					if($phase2['ikeid'] == $phase1['ikeid']) {
1529
						reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1530
					}
1531
				}
1532
			}
1533
		}
1534
	}
1535

    
1536
	/* process all generated spd.conf files from tmp which are left behind
1537
	 * behind by either changes of dynamic tunnels or manual edits
1538
	 * scandir() is only available in PHP5 */
1539
	$tmpfiles = array();
1540
	$dh  = opendir($g['tmp_path']);
1541
	while (false !== ($filename = readdir($dh))) {
1542
		if(preg_match("/^spd.conf.reload./", $tmpfile)) {
1543
			$tmpfiles[] = $filename;
1544
		}
1545
	}
1546
	sort($tmpfiles);
1547
	foreach($tmpfiles as $tmpfile) {
1548
		$ret = mwexec("/usr/local/sbin/setkey -f {$g['tmp_path']}/{$tmpfile} 2>&1", false);
1549
		if($ret == 0) {
1550
			unlink_if_exists("{$g['tmp_path']}/{$tmpfile}");
1551
		} else {
1552
			rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1553
		}
1554
	}
1555
}
1556

    
1557
/* reloads the tunnel configuration for a tunnel item
1558
 * Will remove and add SPD polices */
1559
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1560
	global $config;
1561
	global $g;
1562

    
1563
	/* if we are not passed a old tunnel array we create one */
1564
	if(empty($old_phase1)) {
1565
		$old_phase1 = $phase1;
1566
	}
1567
	if(empty($old_phase2)) {
1568
		$old_phase2 = $phase2;
1569
	}
1570

    
1571
	$sad_arr = ipsec_dump_sad();
1572

    
1573
	$ep = ipsec_get_phase1_src($phase1);
1574
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1575
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1576

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

    
1580
	$old_ep = ipsec_get_phase1_src($old_phase1);
1581
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1582
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1583

    
1584
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1585
	 * try to resolve it now and add it to the list for dnswatch */
1586
	if (!is_ipaddr($phase1['remote-gateway'])) {
1587
		$rgip = resolve_retry($phase1['remote-gateway']);
1588
		add_hostname_to_watch($phase1['remote-gateway']);
1589
		if (!$rgip) {
1590
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1591
			return false;
1592
		}
1593
	} else {
1594
		$rgip = $phase1['remote-gateway'];
1595
	}
1596
	if (!$ep) {
1597
		log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1598
		return false;
1599
	}
1600

    
1601
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1602
		log_error("IPSEC: ERROR: One of the endpoints is not a IP address. Old EP '{$old_ep}' new EP '{$ep}'");
1603
	}
1604
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1605
		log_error("IPSEC: ERROR: One of the remote endpoints is not a IP address. Old RG '{$old_gw}' new RG '{$rgip}'");
1606
	}
1607

    
1608
	$spdconf = "";
1609
	/* Delete old SPD policies if there are changes between the old and new */
1610
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1611
		$spdconf .= "spddelete {$old_local_subnet} " .
1612
			"{$old_remote_subnet} any -P out ipsec " .
1613
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1614
			"{$old_gw}/unique;\n";
1615
		$spdconf .= "spddelete {$old_remote_subnet} " .
1616
			"{$old_local_subnet} any -P in ipsec " .
1617
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1618
			"{$old_ep}/unique;\n";
1619

    
1620
		/* zap any existing SA entries */
1621
		foreach($sad_arr as $sad) {
1622
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1623
				$spdconf .= "delete {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1624
			}
1625
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1626
				$spdconf .= "delete {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1627
			}
1628
		}
1629
	}
1630

    
1631
	/* Create new SPD entries for the new configuration */
1632
	/* zap any existing SA entries beforehand */
1633
	foreach($sad_arr as $sad) {
1634
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1635
			$spdconf .= "delete {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1636
		}
1637
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1638
			$spdconf .= "delete {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1639
		}
1640
	}
1641
	/* add new SPD policies to replace them */
1642
	$spdconf .= "spdadd {$local_subnet} " .
1643
		"{$remote_subnet} any -P out ipsec " .
1644
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1645
		"{$rgip}/unique;\n";
1646
	$spdconf .= "spdadd {$remote_subnet} " .
1647
		"{$local_subnet} any -P in ipsec " .
1648
		"{$phase2['protocol']}/tunnel/{$rgip}-" .
1649
		"{$ep}/unique;\n";
1650

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

    
1653
	$now = time();
1654
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1655
	/* generate temporary spd.conf */
1656
	file_put_contents($spdfile, $spdconf);
1657
	return true;
1658
}
1659

    
1660
?>
(39-39/44)