Project

General

Profile

Download (43.9 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
	require_once ("ipsec.inc");
42

    
43
	$sasyncd_text = "";
44

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

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

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

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

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

    
92
function vpn_ipsec_configure($ipchg = false)
93
{
94
	global $config, $g, $sa, $sn, $p1_ealgos, $p2_ealgos;
95
	require_once ("ipsec.inc");
96

    
97
	mwexec("/sbin/ifconfig enc0 up");
98

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

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

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

    
112
	$curwanip = get_interface_ip();
113

    
114
	$syscfg = $config['system'];
115
	$ipseccfg = $config['ipsec'];
116
	$a_phase1 = $config['ipsec']['phase1'];
117
	$a_phase2 = $config['ipsec']['phase2'];
118
	$a_client = $config['ipsec']['client'];
119
	$lancfg = $config['interfaces']['lan'];
120
	$lanip = get_interface_ip("lan");
121
	$lansn = get_interface_subnet("lan");
122
	$lansa = gen_subnet($lanip, $lansn);
123

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

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

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

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

    
141
		return true;
142
	} else {
143
		if ($g['booting'])
144
			echo "Configuring IPsec VPN... ";
145

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

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

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

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

    
166
			/* step through each phase1 entry */
167
			foreach ($a_phase1 as $ph1ent) {
168
				if (isset($ph1ent['disabled']))
169
					continue;
170

    
171
				$ep = ipsec_get_phase1_src($ph1ent);
172
				if (!$ep)
173
					continue;
174

    
175
				if(!in_array($ep,$ipmap))
176
					$ipmap[] = $ep;
177

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

    
181
				if (isset ($ph1ent['mobile']))
182
					continue;
183

    
184
				$rg = $ph1ent['remote-gateway'];
185

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

    
194
				$rgmap[$ph1ent['remote-gateway']] = $rg;
195

    
196
				/* step through each phase2 entry */
197
				foreach ($a_phase2 as $ph2ent) {
198

    
199
					$ikeid = $ph2ent['ikeid'];
200

    
201
					if (isset($ph2ent['disabled']))
202
						continue;
203

    
204
					if ($ikeid != $ph1ent['ikeid'])
205
						continue;
206

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

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

    
253
		$pskconf = "";
254

    
255
		if (is_array($a_phase1) && count($a_phase1)) {
256
			foreach ($a_phase1 as $ph1ent) {
257

    
258
				if (isset($ph1ent['disabled']))
259
					continue;
260

    
261
				if (strstr($ph1ent['authentication_method'],'rsa'))
262
					continue;
263

    
264
				$peerid_type = $ph1ent['peerid_type'];
265

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

    
272
					case "address";
273
						$peerid_data = $ph1ent['peerid_data'];
274
						break;
275

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

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

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

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

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

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

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

    
320
				$racoonconf .= "\nmode_cfg\n";
321
				$racoonconf .= "{\n";
322

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

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

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

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

    
340
				if (isset($a_client['net_list'])) {
341

    
342
					$net_list = '';
343

    
344
					foreach ($a_phase2 as $ph2ent) {
345

    
346
						if (isset($ph2ent['disabled']))
347
							continue;
348

    
349
						if (!isset($ph2ent['mobile']))
350
							continue;
351

    
352
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
353

    
354
						if ($net_list)
355
							$net_list .= ", ";
356
						$net_list .= $localid;
357
					}
358

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

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

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

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

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

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

    
391
					fwrite($fd1, $a_client['login_banner']);
392
					fclose($fd1);
393

    
394
					$racoonconf .= "\tbanner \"{$fn}\";\n";
395
				}
396

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

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

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

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

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

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

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

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

    
426
					switch ($myid_type) {
427

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

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

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

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

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

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

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

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

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

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

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

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

    
497
					$certline = '';
498

    
499
					if (strstr($authmethod,'rsa')) {
500

    
501
						$cert = lookup_cert($ph1ent['certref']);
502

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

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

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

    
518
						chmod($certpath, 0600);
519

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

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

    
529
						chmod($keypath, 0600);
530

    
531
						$certline = "certificate_type x509 \"{$certpath}\" \"{$keypath}.key\";";
532
					}
533

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

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

    
546
					/* add remote section to configuration */
547

    
548
					$racoonconf .=<<<EOD
549

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

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

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

    
585
				/* begin sainfo */
586
				foreach ($a_phase2 as $ph2ent) {
587

    
588
					$ikeid = $ph2ent['ikeid'];
589

    
590
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
591
						continue;
592

    
593
					if (isset($ph1ent['disabled']))
594
						continue;
595

    
596
					if (isset($ph2ent['disabled']))
597
						continue;
598

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

    
602
					if ($ph2ent['mode'] == 'tunnel') {
603

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

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

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

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

    
621
					} else {
622

    
623
						$rgip = $rgmap[$ph1ent['remote-gateway']];
624

    
625
						$localid_data = ipsec_get_phase1_src($ph1ent);
626
						$localid_spec = "address {$localid_data}";
627

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

    
632
					if($ph2ent['protocol'] == 'esp') {
633

    
634
						$ealgos = '';
635

    
636
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
637

    
638
							$ealg_id = $ealg['name'];
639
							$ealg_kl = $ealg['keylen'];
640

    
641
							if ($ealg_kl) {
642
								if( $ealg_kl == "auto" ) {
643
									$key_hi = $p2_ealgos[$ealg_id]['keysel']['hi'];
644
									$key_lo = $p2_ealgos[$ealg_id]['keysel']['lo'];
645
									$key_step = $p2_ealgos[$ealg_id]['keysel']['step'];
646

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

    
664
						$ealgosline = "encryption_algorithm {$ealgos};";
665

    
666
					} else {
667

    
668
						$ealgosline = "encryption_algorithm null_enc;";
669
					}
670

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

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

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

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

    
701
EOD;
702
				}
703
				/* end sainfo */
704
			}
705
			/* end sainfo sections */
706

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

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

    
721
			$spdconf = "";
722

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

    
729
			foreach ($a_phase2 as $ph2ent) {
730

    
731
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
732
					continue;
733

    
734
				if (isset($ph1ent['mobile']))
735
					continue;
736

    
737
				if (isset($ph1ent['disabled']))
738
					continue;
739

    
740
				if (isset($ph2ent['disabled']))
741
					continue;
742

    
743
				$ep = ipsec_get_phase1_src($ph1ent);
744
				if (!$ep)
745
					continue;
746

    
747
				$rgip = $rgmap[$ph1ent['remote-gateway']];
748

    
749
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
750
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
751

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

    
766
				if($ph2ent['mode'] == "tunnel") {
767

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

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

    
774
				} else {
775

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

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

    
782
				}
783

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

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

    
815
			fwrite($fd, $spdconf);
816
			fclose($fd);
817
		}
818

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

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

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

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

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

    
865
	return 0;
866
}
867

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

    
878
	$ipseccfg = $config['ipsec'];
879

    
880
	/* kill racoon */
881
	mwexec("/usr/bin/killall racoon", true);
882

    
883
	/* wait for process to die */
884
	sleep(4);
885

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

    
889
	/* wait for flushing to finish */
890
	sleep(1);
891

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

    
898
}
899

    
900
/* master setup for vpn (mpd) */
901
function vpn_setup() {
902
	/* start pptpd */
903
	vpn_pptpd_configure();
904

    
905
	/* start pppoe server */
906
	vpn_pppoe_configure();
907

    
908
	/* setup l2tp */
909
	vpn_l2tp_configure();
910
}
911

    
912
function vpn_pptpd_configure() {
913
	global $config, $g;
914

    
915
	$syscfg = $config['system'];
916
	$pptpdcfg = $config['pptpd'];
917

    
918
	if ($g['booting']) {
919
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
920
			return 0;
921

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

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

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

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

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

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

    
954
			$mpdconf =<<<EOD
955
pptpd:
956

    
957
EOD;
958

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

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

    
965
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
966

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

    
973
				$mpdconf .=<<<EOD
974

    
975
pt{$i}:
976
	new pt{$i} pt{$i}
977
	{$isssue_ip_type}
978
	load pts
979

    
980
EOD;
981
			}
982

    
983
			$mpdconf .=<<<EOD
984

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

    
1005
EOD;
1006

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

    
1012
EOD;
1013
			}
1014

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

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

    
1048
EOD;
1049

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

    
1055
EOD;
1056
				}
1057
			}
1058

    
1059
			fwrite($fd, $mpdconf);
1060
			fclose($fd);
1061

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

    
1069
			$mpdlinks = "";
1070

    
1071
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1072
				$mpdlinks .=<<<EOD
1073

    
1074
pt{$i}:
1075
	set link type pptp
1076
	set pptp enable incoming
1077
	set pptp disable originate
1078
	set pptp disable windowing
1079

    
1080
EOD;
1081
			}
1082

    
1083
			fwrite($fd, $mpdlinks);
1084
			fclose($fd);
1085

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

    
1093
			$mpdsecret = "";
1094

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

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

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

    
1107
			break;
1108

    
1109
		case 'redir' :
1110
			break;
1111
	}
1112

    
1113
	if ($g['booting'])
1114
		echo "done\n";
1115

    
1116
	return 0;
1117
}
1118

    
1119
function vpn_pppoe_configure() {
1120
	global $config, $g;
1121

    
1122
	$syscfg = $config['system'];
1123
	$pppoecfg = $config['pppoe'];
1124

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

    
1129
	if ($g['booting']) {
1130
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1131
			return 0;
1132

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

    
1138
		/* wait for process to die */
1139
		sleep(2);
1140

    
1141
	}
1142

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

    
1147
	switch ($pppoecfg['mode']) {
1148

    
1149
		case 'server' :
1150

    
1151
			$pppoe_interface = interface_translate_type_to_real($pppoecfg['interface']);
1152

    
1153
			if ($pppoecfg['paporchap'] == "chap")
1154
				$paporchap = "set link enable chap";
1155
			else
1156
				$paporchap = "set link enable pap";
1157

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

    
1168
EOD;
1169

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

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

    
1176
				$clientip = long2ip(ip2long($pppoecfg['remoteip']) + $i);
1177

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

    
1184
				$mpdconf .=<<<EOD
1185

    
1186
pppoe{$i}:
1187
	new pppoe{$i} pppoe{$i}
1188
	{$isssue_ip_type}
1189
	load pppoe_standart
1190

    
1191
EOD;
1192
			}
1193

    
1194
			$mpdconf .=<<<EOD
1195

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

    
1222
EOD;
1223

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

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

    
1241
EOD;
1242

    
1243
				if (isset ($pppoecfg['radius']['accounting'])) {
1244
					$mpdconf .=<<<EOD
1245
	set auth enable radius-acct
1246

    
1247
EOD;
1248
				}
1249
			}
1250

    
1251
			fwrite($fd, $mpdconf);
1252
			fclose($fd);
1253

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

    
1261
			$mpdlinks = "";
1262

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

    
1273
EOD;
1274
			}
1275

    
1276
			fwrite($fd, $mpdlinks);
1277
			fclose($fd);
1278

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

    
1286
			$mpdsecret = "\n\n";
1287

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

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

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

    
1300
			break;
1301

    
1302
		case 'redir' :
1303
			break;
1304
	}
1305

    
1306
	if ($g['booting'])
1307
		echo "done\n";
1308

    
1309
	return 0;
1310
}
1311

    
1312
function vpn_l2tp_configure() {
1313
	global $config, $g;
1314

    
1315
	$syscfg = $config['system'];
1316
	$l2tpcfg = $config['l2tp'];
1317

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

    
1322
	if ($g['booting']) {
1323
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1324
			return 0;
1325

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

    
1331
		/* wait for process to die */
1332
		sleep(8);
1333

    
1334
	}
1335

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

    
1340
	switch ($l2tpcfg['mode']) {
1341

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

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

    
1358
EOD;
1359

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

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

    
1366
				$clientip = long2ip(ip2long($l2tpcfg['remoteip']) + $i);
1367

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

    
1374
				$mpdconf .=<<<EOD
1375

    
1376
l2tp{$i}:
1377
	new l2tp{$i} l2tp{$i}
1378
	{$isssue_ip_type}
1379
	load l2tp_standard
1380

    
1381
EOD;
1382
			}
1383

    
1384
			$mpdconf .=<<<EOD
1385

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

    
1402
EOD;
1403

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

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

    
1421
EOD;
1422

    
1423
				if (isset ($l2tpcfg['radius']['accounting'])) {
1424
					$mpdconf .=<<<EOD
1425
	set auth enable radius-acct
1426

    
1427
EOD;
1428
				}
1429
			}
1430

    
1431
			fwrite($fd, $mpdconf);
1432
			fclose($fd);
1433

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

    
1441
			$mpdlinks = "";
1442

    
1443
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1444
				$mpdlinks .=<<<EOD
1445

    
1446
l2tp{$i}:
1447
	set link type l2tp
1448
        set l2tp enable incoming
1449
        set l2tp disable originate
1450

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

    
1456
			fwrite($fd, $mpdlinks);
1457
			fclose($fd);
1458

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

    
1466
			$mpdsecret = "\n\n";
1467

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

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

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

    
1480
			break;
1481

    
1482
		case 'redir' :
1483
			break;
1484
	}
1485

    
1486
	if ($g['booting'])
1487
		echo "done\n";
1488

    
1489
	return 0;
1490
}
1491

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

    
1499
	$ipseccfg = $config['ipsec'];
1500
	$a_phase1 = $config['ipsec']['phase1'];
1501
	$a_phase2 = $config['ipsec']['phase2'];
1502

    
1503
	if (isset($ipseccfg['disable'])) {
1504
		return true;
1505
	}
1506

    
1507
	/* Walk the Ipsec tunnel array */
1508
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1509
		return;
1510
	}
1511

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

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

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

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

    
1574
	$sad_arr = ipsec_dump_sad();
1575

    
1576
	$ep = ipsec_get_phase1_src($phase1);
1577
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1578
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1579

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

    
1583
	$old_ep = ipsec_get_phase1_src($old_phase1);
1584
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1585
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1586

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

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

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

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

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

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

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

    
1663
?>
(38-38/43)