Project

General

Profile

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

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

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

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

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

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

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

    
36
/*
37
	pfSense_BUILDER_BINARIES:	/usr/bin/killall	/usr/local/sbin/sasyncd	/sbin/ifconfig	/sbin/sysctl
38
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/setkey	/usr/bin/netstat	/sbin/route	/bin/mkdir
39
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/racoonctl	/usr/local/sbin/racoon
40
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/dnswatch	/usr/local/sbin/mpd4	
41
	pfSense_MODULE:	vpn
42
*/
43

    
44
/* include all configuration functions */
45

    
46
function vpn_ipsec_failover_configure() {
47
	global $config, $g;
48

    
49
	$sasyncd_text = "";
50

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

    
70
	$fd = fopen("{$g['varetc_path']}/sasyncd.conf", "w");
71
	fwrite($fd, $sasyncd_text);
72
	fclose($fd);
73
	chmod("{$g['varetc_path']}/sasyncd.conf", 0600);
74

    
75
	if(is_process_running("sasyncd"))
76
		mwexec("killall sasyncd", true);
77

    
78
	/* launch sasyncd, oh wise one */
79
	mwexec_bg("/usr/local/sbin/sasyncd -d -v -v -v");
80
}
81

    
82
function find_last_gif_device() {
83
	$last_gif_found = -1;
84
	$regs = "";
85
	if (!($fp = popen("/sbin/ifconfig -l", "r")))
86
		return -1;
87
	$ifconfig_data = fread($fp, 4096);
88
	pclose($fp);
89
	$ifconfig_array = split(" ", $ifconfig_data);
90
	foreach ($ifconfig_array as $ifconfig) {
91
		ereg("gif(.)", $ifconfig, $regs);
92
		if ($regs[0] && $regs[0] > $last_gif_found) {
93
			$last_gif_found = $regs[1];
94
		}
95
	}
96
	return $last_gif_found;
97
}
98

    
99
function vpn_ipsec_configure($ipchg = false)
100
{
101
	global $config, $g, $sa, $sn, $p1_ealgos, $p2_ealgos;
102

    
103
	mwexec("/sbin/ifconfig enc0 up");
104

    
105
	/* get the automatic /etc/ping_hosts.sh ready */
106
	unlink_if_exists("/var/db/ipsecpinghosts");
107
	touch("/var/db/ipsecpinghosts");
108

    
109
	if(isset($config['ipsec']['preferredoldsa']))
110
		mwexec("/sbin/sysctl -w net.key.preferred_oldsa=-30");
111
	else
112
		mwexec("/sbin/sysctl net.key.preferred_oldsa=0");
113

    
114
	$number_of_gifs = find_last_gif_device();
115
	for ($x = 0; $x < $number_of_gifs; $x++)
116
		mwexec("/sbin/ifconfig gif" . $x . " delete");
117

    
118
	$curwanip = get_interface_ip();
119

    
120
	$syscfg = $config['system'];
121
	$ipseccfg = $config['ipsec'];
122
	$a_phase1 = $config['ipsec']['phase1'];
123
	$a_phase2 = $config['ipsec']['phase2'];
124
	$a_client = $config['ipsec']['client'];
125
	$lancfg = $config['interfaces']['lan'];
126
	$lanip = get_interface_ip("lan");
127
	$lansn = get_interface_subnet("lan");
128
	$lansa = gen_subnet($lanip, $lansn);
129

    
130
	if (!isset($ipseccfg['enable'])) {
131
		mwexec("/sbin/ifconfig enc0 down");
132

    
133
		/* kill racoon */
134
		if(is_process_running("racoon"))
135
			mwexec("/usr/bin/killall racoon", true);
136
		killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
137
		
138
		/* wait for racoon process to die */
139
		sleep(2);
140

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

    
144
		/* flush SPD and SAD */
145
		mwexec("/usr/local/sbin/setkey -FP");
146
		mwexec("/usr/local/sbin/setkey -F");
147
		
148
		/* disallow IPSEC, it is off */
149
//		exec("/sbin/sysctl net.inet.ip.ipsec_in_use=0");
150

    
151
		return true;
152
	} else {
153
		if ($g['booting'])
154
			echo "Configuring IPsec VPN... ";
155

    
156
		/* fastforwarding is not compatible with ipsec tunnels */
157
		mwexec("/sbin/sysctl net.inet.ip.fastforwarding=0");
158

    
159
		if (!$curwanip) {
160
			/* IP address not configured yet, exit */
161
			if ($g['booting'])
162
				echo "done\n";
163
			return 0;
164
		}
165

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

    
170
		/* resolve all local, peer addresses and setup pings */
171
		$ipmap = array();
172
		$rgmap = array();
173
		$dnswatch_list = array();
174
		if (is_array($a_phase1) && count($a_phase1)) {
175

    
176
			/* step through each phase1 entry */
177
			foreach ($a_phase1 as $ph1ent) {
178
				if (isset($ph1ent['disabled']))
179
					continue;
180

    
181
				$ep = ipsec_get_phase1_src($ph1ent);
182
				if (!$ep)
183
					continue;
184

    
185
				if(!in_array($ep,$ipmap))
186
					$ipmap[] = $ep;
187

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

    
191
				if (isset ($ph1ent['mobile']))
192
					continue;
193

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

    
196
				if (!is_ipaddr($rg)) {
197
					$dnswatch_list[] = $rg;
198
					add_hostname_to_watch($rg);
199
					$rg = resolve_retry($rg);
200
					if (!$rg)
201
						continue;
202
				}
203

    
204
				$rgmap[$ph1ent['remote-gateway']] = $rg;
205

    
206
				/* step through each phase2 entry */
207
				foreach ($a_phase2 as $ph2ent) {
208

    
209
					$ikeid = $ph2ent['ikeid'];
210

    
211
					if (isset($ph2ent['disabled']))
212
						continue;
213

    
214
					if ($ikeid != $ph1ent['ikeid'])
215
						continue;
216

    
217
					/* add an ipsec pinghosts entry */
218
					if ($ph2ent['pinghost']) {
219
						$pfd = fopen("/var/db/ipsecpinghosts", "a");
220
						$iflist = get_configured_interface_list();
221
						foreach ($iflist as $ifent => $ifname) {
222
							$interface_ip = get_interface_ip($ifent);
223
							$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
224
							if (ip_in_subnet($interface_ip, $local_subnet))
225
								$srcip = $interface_ip;
226
						}
227
						$dstip = $ph2ent['pinghost'];
228
						fwrite($pfd, "$srcip|$dstip|3\n");
229
						fclose($pfd);
230
					}
231
				}
232
			}
233
		}
234

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

    
263
		$pskconf = "";
264

    
265
		if (is_array($a_phase1) && count($a_phase1)) {
266
			foreach ($a_phase1 as $ph1ent) {
267

    
268
				if (isset($ph1ent['disabled']))
269
					continue;
270

    
271
				if (strstr($ph1ent['authentication_method'],'rsa'))
272
					continue;
273

    
274
				$peerid_type = $ph1ent['peerid_type'];
275

    
276
				switch ($peerid_type) {
277
					case "peeraddress":
278
						$peerid_type = "address";
279
						$peerid_data = $rgmap[$ph1ent['remote-gateway']];
280
						break;
281

    
282
					case "address";
283
						$peerid_data = $ph1ent['peerid_data'];
284
						break;
285

    
286
					case "fqdn";
287
					case "keyid tag";
288
					case "user_fqdn";
289
						$peerid_data = $ph1ent['peerid_data'];
290
						break;
291
				}
292

    
293
				$pskconf .= "{$peerid_data}\t{$ph1ent['pre-shared-key']}\n";
294
			}
295
		}
296

    
297
		fwrite($fd, $pskconf);
298
		fclose($fd);
299
		chmod("{$g['varetc_path']}/psk.txt", 0600);
300
			
301
		/* begin racoon.conf */
302
		if ((is_array($a_phase1) && count($a_phase1)) ||
303
			(is_array($a_phase2) && count($a_phase2))) {
304

    
305
			$fd = fopen("{$g['varetc_path']}/racoon.conf", "w");
306
			if (!$fd) {
307
				printf("Error: cannot open racoon.conf in vpn_ipsec_configure().\n");
308
				return 1;
309
			}
310

    
311
			$racoonconf = "# This file is automatically generated. Do not edit\n";			
312
			$racoonconf .= "path pre_shared_key \"{$g['varetc_path']}/psk.txt\";\n\n";
313
			$racoonconf .= "path certificate  \"{$g['varetc_path']}\";\n\n";
314

    
315
			/* begin listen section */
316
			if (count($ipmap)) {
317
				$racoonconf .= "\nlisten\n";
318
				$racoonconf .= "{\n";
319
				$racoonconf .= "	adminsock \"/var/run/racoon.sock\" \"root\" \"wheel\" 0660;\n";
320
				foreach ($ipmap as $addr) {
321
					$racoonconf .= "\tisakmp {$addr} [500];\n";
322
					$racoonconf .= "\tisakmp_natt {$addr} [4500];\n";
323
				}
324
				$racoonconf .= "}\n\n";
325
			}
326

    
327
			/* begin mode_cfg section */
328
			if (is_array($a_client) && isset($a_client['enable'])) {
329

    
330
				$racoonconf .= "\nmode_cfg\n";
331
				$racoonconf .= "{\n";
332

    
333
				if ($a_client['user_source'])
334
					$racoonconf .= "\tauth_source {$a_client['user_source']};\n";
335
				if ($a_client['group_source'])
336
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
337

    
338
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
339
					$pool_address = $a_client['pool_address'];
340
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
341

    
342
					$pool_address = long2ip(ip2long($pool_address)+1);
343
					$pool_size = ~ip2long($pool_netmask) - 2;
344

    
345
					$racoonconf .= "\tpool_size {$pool_size};\n";
346
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
347
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
348
				}
349

    
350
				if (isset($a_client['net_list'])) {
351

    
352
					$net_list = '';
353

    
354
					foreach ($a_phase2 as $ph2ent) {
355

    
356
						if (isset($ph2ent['disabled']))
357
							continue;
358

    
359
						if (!isset($ph2ent['mobile']))
360
							continue;
361

    
362
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
363

    
364
						if ($net_list)
365
							$net_list .= ", ";
366
						$net_list .= $localid;
367
					}
368

    
369
					if ($net_list)
370
						$racoonconf .= "\tsplit_network include {$net_list};\n";
371
				}
372

    
373
				if ($a_client['dns_server1'])
374
					$racoonconf .= "\tdns4 {$a_client['dns_server1']};\n";
375
				if ($a_client['dns_server2'])
376
					$racoonconf .= "\tdns4 {$a_client['dns_server2']};\n";
377
				if ($a_client['dns_server3'])
378
					$racoonconf .= "\tdns4 {$a_client['dns_server3']};\n";
379
				if ($a_client['dns_server4'])
380
					$racoonconf .= "\tdns4 {$a_client['dns_server4']};\n";
381

    
382
				if ($a_client['wins_server1'])
383
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
384
				if ($a_client['wins_server2'])
385
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
386

    
387
				if ($a_client['dns_domain'])
388
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
389

    
390
				if ($a_client['pfs_group'])
391
					$racoonconf .= "\tpfs_group {$a_client['pfs_group']};\n";
392

    
393
				if ($a_client['login_banner']) {
394
					$fn = "{$g['varetc_path']}/racoon.motd";
395
					$fd1 = fopen($fn, "w");
396
					if (!$fd1) {
397
						printf("Error: cannot open server{$fn} in vpn.\n");
398
						return 1;
399
					}
400

    
401
					fwrite($fd1, $a_client['login_banner']);
402
					fclose($fd1);
403

    
404
					$racoonconf .= "\tbanner \"{$fn}\";\n";
405
				}
406

    
407
				$racoonconf .= "}\n\n";
408
			}
409
			/* end mode_cfg section */
410

    
411
			/* begin remote sections */
412
			if (is_array($a_phase1) && count($a_phase1)) {
413
				/* begin remote */
414
				foreach ($a_phase1 as $ph1ent) {
415

    
416
					if (isset($ph1ent['disabled']))
417
						continue;
418

    
419
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
420
						continue;
421

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

    
424
					$ep = ipsec_get_phase1_src($ph1ent);
425
					if (!$ep)
426
						continue;
427

    
428
					if (!isset($ph1ent['mobile'])) {
429
						$rgip = $rgmap[$ph1ent['remote-gateway']];
430
						if (!$rgip)
431
							continue;
432
					}
433

    
434
					$myid_type = $ph1ent['myid_type'];
435

    
436
					switch ($myid_type) {
437

    
438
						case "myaddress":
439
							$myid_type = "address";
440
							$myid_data = $ep;
441
							break;
442

    
443
						case "dyn_dns":
444
							$myid_data = gethostbyname($ph1ent['myid_data']);
445
							break;
446

    
447
						case "address";
448
							$myid_data = $ph1ent['myid_data'];
449
							break;
450

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

    
461
					$peerid_type = $ph1ent['peerid_type'];
462

    
463
					switch ($peerid_type) {
464
						case "peeraddress":
465
							$peerid_type = "address";
466
							$peerid_data = $rgip;
467
							break;
468

    
469
						case "address";
470
							$peerid_data = $ph1ent['peerid_data'];
471
							break;
472

    
473
						case "fqdn";
474
						case "keyid tag";
475
						case "user_fqdn";
476
						case "asn1dn";
477
							$peerid_data = $ph1ent['peerid_data'];
478
							if( $peerid_data )
479
								$peerid_data = "\"".$peerid_data."\"";
480
							break;
481
					}
482

    
483
					$natt = "off";
484
					if (isset($ph1ent['nat_traversal']))
485
						$natt = $ph1ent['nat_traversal'];
486

    
487
					$init = "on";
488
					$genp = "off";
489
					if (isset($ph1ent['mobile'])) {
490
						$rgip = "anonymous";
491
						$init = "off";
492
						$genp = "unique";
493
					}
494

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

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

    
507
					$certline = '';
508

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

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

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

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

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

    
528
						chmod($certpath, 0600);
529

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

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

    
539
						chmod($keypath, 0600);
540

    
541
						$certline = "certificate_type x509 \"".basename($certpath)."\" \"".basename($keypath)."\";";
542
					}
543

    
544
					$ealgos = '';
545
					$ealg_id = $ph1ent['encryption-algorithm']['name'];
546
					$ealg_kl = $ph1ent['encryption-algorithm']['keylen'];
547
					if ($ealg_kl)
548
						$ealgos = $ealgos.$ealg_id." ".$ealg_kl;
549
					else
550
						$ealgos = $ealgos.$ealg_id;
551

    
552
					$lifeline = '';
553
					if ($ph1ent['lifetime'])
554
						$lifeline = "lifetime time {$ph1ent['lifetime']} secs;";
555

    
556
					/* add remote section to configuration */
557

    
558
					$racoonconf .=<<<EOD
559

    
560
remote {$rgip}
561
{
562
	ph1id {$ikeid};
563
	exchange_mode {$ph1ent['mode']};
564
	my_identifier {$myid_type} {$myid_data};
565
	peers_identifier {$peerid_type} {$peerid_data};
566
	ike_frag on;
567
	generate_policy = {$genp};
568
	initial_contact = {$init};
569
	nat_traversal = {$natt};
570
	{$certline}
571
	{$dpdline1}
572
	{$dpdline2}
573
	support_proxy on;
574
	proposal_check claim;
575

    
576
	proposal
577
	{
578
		authentication_method {$authmethod};
579
		encryption_algorithm ${ealgos};
580
		hash_algorithm {$ph1ent['hash-algorithm']};
581
		dh_group {$ph1ent['dhgroup']};
582
		${lifeline}
583
	}
584
}
585

    
586
EOD;
587
				}
588
				/* end remote */
589
			}
590
			/* end remote sections */
591
		
592
			/* begin sainfo sections */
593
			if (is_array($a_phase2) && count($a_phase2)) {
594

    
595
				/* begin sainfo */
596
				foreach ($a_phase2 as $ph2ent) {
597

    
598
					$ikeid = $ph2ent['ikeid'];
599

    
600
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
601
						continue;
602

    
603
					if (isset($ph1ent['disabled']))
604
						continue;
605

    
606
					if (isset($ph2ent['disabled']))
607
						continue;
608

    
609
					if (isset($ph2ent['mobile']) && !isset($a_client['enable']))
610
						continue;
611

    
612
					if ($ph2ent['mode'] == 'tunnel') {
613

    
614
						$localid_type = $ph2ent['localid']['type'];
615
						if ($localid_type != "address")
616
							$localid_type = "subnet";
617

    
618
						$localid_data = ipsec_idinfo_to_cidr($ph2ent['localid']);
619
						$localid_spec = $localid_type." ".$localid_data." any";
620

    
621
						if (!isset($ph2ent['mobile'])) {
622
							$remoteid_type = $ph2ent['remoteid']['type'];
623
							if ($remoteid_type != "address")
624
								$remoteid_type = "subnet";
625

    
626
							$remoteid_data = ipsec_idinfo_to_cidr($ph2ent['remoteid']);
627
							$remoteid_spec = $remoteid_type." ".$remoteid_data." any";
628
						} else
629
							$remoteid_spec = "anonymous";
630

    
631
					} else {
632

    
633
						$rgip = $rgmap[$ph1ent['remote-gateway']];
634

    
635
						$localid_data = ipsec_get_phase1_src($ph1ent);
636
						if($ph2ent['mode'] == 'transport') { $localid_data="$localid_data any"; }
637
						$localid_spec = "address {$localid_data}";
638

    
639
						$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
640
						if($ph2ent['mode'] == 'transport') { $remoteid_data="$remoteid_data any"; }
641
						$remoteid_spec = "address {$remoteid_data}";
642
					}
643

    
644
					if($ph2ent['protocol'] == 'esp') {
645

    
646
						$ealgos = '';
647

    
648
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
649

    
650
							$ealg_id = $ealg['name'];
651
							$ealg_kl = $ealg['keylen'];
652

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

    
688
						$ealgosline = "encryption_algorithm {$ealgos};";
689

    
690
					} else {
691

    
692
						$ealgosline = "encryption_algorithm null_enc;";
693
					}
694

    
695
					$halgos = join(",", $ph2ent['hash-algorithm-option']);
696
					$halgosline = "authentication_algorithm {$halgos};";
697

    
698
					$pfsline = '';
699
					if ($ph2ent['pfsgroup'])
700
						$pfsline = "pfs_group {$ph2ent['pfsgroup']};";
701
					if (isset($a_client['pfs_group'])) {
702
						$pfsline = '';
703
						if ($a_client['pfs_group'])
704
							$pfsline = "pfs_group {$a_client['pfs_group']};";
705
					}
706

    
707
					$lifeline = '';
708
					if ($ph2ent['lifetime'])
709
						$lifeline = "lifetime time {$ph2ent['lifetime']} secs;";
710

    
711
					/* add sainfo section to configuration */
712
					
713
					$racoonconf .=<<<EOD
714
					
715
sainfo {$localid_spec} {$remoteid_spec}
716
{
717
	remoteid {$ikeid};
718
	{$ealgosline}
719
	{$halgosline}
720
	{$pfsline}
721
	{$lifeline}
722
	compression_algorithm deflate;
723
}
724

    
725
EOD;
726
				}
727
				/* end sainfo */
728
			}
729
			/* end sainfo sections */
730

    
731
			fwrite($fd, $racoonconf);
732
			fclose($fd);
733
		}
734
		/* end racoon.conf */
735

    
736
		/* generate IPsec policies */
737
		if (is_array($a_phase2) && count($a_phase2)) {
738
			/* generate spd.conf */
739
			$fd = fopen("{$g['varetc_path']}/spd.conf", "w");
740
			if (!$fd) {
741
				printf("Error: cannot open spd.conf in vpn_ipsec_configure().\n");
742
				return 1;
743
			}
744

    
745
			$spdconf = "";
746

    
747
			/* What are these SPD entries for?
748
			 * -mgrooms 07/10/2008
749
			 */
750
			$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
751
			$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
752

    
753
			foreach ($a_phase2 as $ph2ent) {
754

    
755
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
756
					continue;
757

    
758
				if (isset($ph1ent['mobile']))
759
					continue;
760

    
761
				if (isset($ph1ent['disabled']))
762
					continue;
763

    
764
				if (isset($ph2ent['disabled']))
765
					continue;
766

    
767
				$ep = ipsec_get_phase1_src($ph1ent);
768
				if (!$ep)
769
					continue;
770

    
771
				$rgip = $rgmap[$ph1ent['remote-gateway']];
772

    
773
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
774
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
775

    
776
				if (isset ($ph2ent['creategif'])) {
777
					$number_of_gifs = find_last_gif_device();
778
					$number_of_gifs++;
779
					$curwanip = get_interface_ip();
780
					if ($config['installedpackages']['sasyncd']['config'] <> "") {
781
						foreach ($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
782
							if ($sasyncd['ip'] <> "")
783
								$curwanip = $sasyncd['ip'];
784
						}
785
					}
786
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " tunnel" . $curwanip . " " . $rgip);
787
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " {$lansa}/{$lansn} {$lanip}/32");
788
				}
789

    
790
				if($ph2ent['mode'] == "tunnel") {
791

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

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

    
798
				} else {
799

    
800
					$localid_data = ipsec_get_phase1_src($ph1ent);
801
					$remoteid_data = $rgmap[$ph1ent['remote-gateway']];
802

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

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

    
809
				}
810

    
811
				/* static route needed? */
812
				if (preg_match("/^carp/i", $ph1ent['interface']))
813
					$parentinterface = link_carp_interface_to_parent($ph1ent['interface']);
814
				else
815
					$parentinterface = $ph1ent['interface'];
816

    
817
				if ($parentinterface <> "wan") {
818
					/* add endpoint routes to correct gateway on interface */
819
					if (interface_has_gateway($parentinterface)) {
820
						$gatewayip = get_interface_gateway("$parentinterface");
821
						$interfaceip = get_interface_ip($parentinterface);
822
						$subnet_bits = get_interface_subnet($parentinterface);
823
						$subnet_ip = gen_subnet("{$interfaceip}", "{$subnet_bits}");
824
						/* if the remote gateway is in the local subnet, then don't add a route */
825
						if (! ip_in_subnet($rgip, "{$subnet_ip}/{$subnet_bits}")) {
826
							if(is_ipaddr($gatewayip)) {
827
								/* FIXME: does adding route-to and reply-to on the in/outbound
828
								 * rules fix this? smos@ 13-01-2009 */
829
								log_error("IPSEC interface is not WAN but {$parentinterface}, adding static route for VPN endpoint {$rgip} via {$gatewayip}");
830
								mwexec("/sbin/route delete -host {$rgip}");
831
								mwexec("/sbin/route add -host {$rgip} {$gatewayip}");
832
							}
833
						}
834
					}
835
				} else {
836
					if(stristr($route_str, "{$rgip}")) {
837
						mwexec("/sbin/route delete -host {$rgip}", true);
838
					}
839
				}
840
			}
841

    
842
			fwrite($fd, $spdconf);
843
			fclose($fd);
844
		}
845

    
846
		/* needed for racoonctl admin socket */
847
		if (!is_dir("/var/db/racoon"))
848
			mkdir("/var/db/racoon/");
849
		
850
		exec("/bin/mkdir -p /var/db/racoon");
851

    
852
		/* mange racoon process */
853
		if (is_process_running("racoon")) {
854
			sleep("0.1");
855
			mwexec("/usr/local/sbin/racoonctl -s /var/run/racoon.sock reload-config", false);
856
			/* load SPD without flushing to be safe on config additions or changes. */
857
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
858
		} else {
859
			/* flush SA + SPD entries */
860
			mwexec("/usr/local/sbin/setkey -FP", false);
861
 			sleep("0.1");
862
			mwexec("/usr/local/sbin/setkey -F", false);
863
 			sleep("0.1");
864
//			exec("/sbin/sysctl net.inet.ip.ipsec_in_use=1");
865
 			/* start racoon */
866
			mwexec("/usr/local/sbin/racoon -f {$g['varetc_path']}/racoon.conf", false);
867
 			sleep("0.1");
868
 			/* load SPD */
869
			mwexec("/usr/local/sbin/setkey -f {$g['varetc_path']}/spd.conf", false);
870

    
871
			/* start dnswatch, if necessary */
872
			if (count($dnswatch_list) > 0) {
873
				$interval = 60;
874
				if ($ipseccfg['dns-interval'])
875
					$interval = $ipseccfg['dns-interval'];
876

    
877
				$hostnames = "";
878
				array_unique($dnswatch_list);
879
				$hostnames = implode("\n", $dnswatch_list);
880
				file_put_contents("{$g['varetc_path']}/dnswatch-ipsec.hosts", $hostnames);
881

    
882
				killbypid("{$g['varrun_path']}/dnswatch-ipsec.pid");
883
				mwexec("/usr/local/sbin/dnswatch {$g['varrun_path']}/dnswatch-ipsec.pid $interval /etc/rc.newipsecdns {$g['varetc_path']}/dnswatch-ipsec.hosts");
884
			}
885
		}
886
	
887
		vpn_ipsec_failover_configure();
888

    
889
		if ($g['booting'])
890
			echo "done\n";
891
	}
892

    
893
	return 0;
894
}
895

    
896
/* Forcefully restart IPsec
897
 * This is required for when dynamic interfaces reload
898
 * For all other occasions the normal vpn_ipsec_configure()
899
 * will gracefully reload the settings without restarting
900
 */
901
function vpn_ipsec_force_reload() {
902
	global $config;
903
	global $g;
904

    
905
	$ipseccfg = $config['ipsec'];
906

    
907
	/* kill racoon */
908
	if(is_process_running("racoon"))
909
		mwexec("/usr/bin/killall racoon", true);
910

    
911
	/* wait for process to die */
912
	sleep(4);
913

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

    
917
	/* wait for flushing to finish */
918
	sleep(1);
919

    
920
	/* if ipsec is enabled, start up again */
921
	if (isset($ipseccfg['enable'])) {
922
		log_error("Forcefully reloading IPsec racoon daemon");
923
		vpn_ipsec_configure();
924
	}
925

    
926
}
927

    
928
/* master setup for vpn (mpd) */
929
function vpn_setup() {
930
	/* start pptpd */
931
	vpn_pptpd_configure();
932

    
933
	/* start pppoe server */
934
	vpn_pppoe_configure();
935

    
936
	/* setup l2tp */
937
	vpn_l2tp_configure();
938
}
939

    
940
function vpn_pptpd_configure() {
941
	global $config, $g;
942

    
943
	$syscfg = $config['system'];
944
	$pptpdcfg = $config['pptpd'];
945

    
946
	if ($g['booting']) {
947
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
948
			return 0;
949

    
950
		echo "Configuring PPTP VPN service... ";
951
	} else {
952
		/* kill mpd */
953
		killbypid("{$g['varrun_path']}/pptp-vpn.pid");
954

    
955
		/* wait for process to die */
956
		sleep(3);
957

    
958
		if (is_process_running("mpd -b")) {
959
			killbypid("{$g['varrun_path']}/pptp-vpn.pid");
960
			log_error("Could not kill mpd within 3 seconds.   Trying again.");
961
		}
962

    
963
		/* remove mpd.conf, if it exists */
964
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.conf");
965
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.links");
966
		unlink_if_exists("{$g['varetc_path']}/pptp-vpn/mpd.secret");
967
	}
968

    
969
	/* make sure pptp-vpn directory exists */
970
	if (!file_exists("{$g['varetc_path']}/pptp-vpn"))
971
		mkdir("{$g['varetc_path']}/pptp-vpn");
972

    
973
	switch ($pptpdcfg['mode']) {
974
		case 'server' :
975
			/* write mpd.conf */
976
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.conf", "w");
977
			if (!$fd) {
978
				printf("Error: cannot open mpd.conf in vpn_pptpd_configure().\n");
979
				return 1;
980
			}
981

    
982
			$mpdconf = <<<EOD
983
pptpd:
984

    
985
EOD;
986

    
987
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
988
				$mpdconf .= "	load pt{$i}\n";
989
			}
990

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

    
993
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
994
				$ngif = "ng" . ($i+1);
995

    
996
				$mpdconf .= <<<EOD
997

    
998
pt{$i}:
999
	new -i {$ngif} pt{$i} pt{$i}
1000
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
1001
	load pts
1002

    
1003
EOD;
1004
			}
1005

    
1006
			$mpdconf .=<<<EOD
1007

    
1008
pts:
1009
	set iface disable on-demand
1010
	set iface enable proxy-arp
1011
	set iface enable tcpmssfix
1012
	set iface idle 1800
1013
	set iface up-script /usr/local/sbin/pptp-linkup
1014
	set iface down-script /usr/local/sbin/vpn-linkdown
1015
	set bundle enable multilink
1016
	set bundle enable crypt-reqd
1017
	set link yes acfcomp protocomp
1018
	set link no pap chap
1019
	set link enable chap-msv2
1020
	set link mtu 1460
1021
	set link keep-alive 10 60
1022
	set ipcp yes vjcomp
1023
	set bundle enable compression
1024
	set ccp yes mppc
1025
	set ccp yes mpp-e128
1026
	set ccp yes mpp-stateless
1027

    
1028
EOD;
1029

    
1030
			if (!isset ($pptpdcfg['req128'])) {
1031
				$mpdconf .=<<<EOD
1032
	set ccp yes mpp-e40
1033
	set ccp yes mpp-e56
1034

    
1035
EOD;
1036
			}
1037

    
1038
			if  (isset($pptpdcfg["wins"]) && $pptpdcfg['wins'] != "")
1039
				$mpdconf  .=  "	set ipcp nbns {$pptpdcfg['wins']}\n";
1040
			if (is_array($pptpdcfg['dnsserver']) && ($pptpdcfg['dnsserver'][0])) {
1041
				$mpdconf .= "	set ipcp dns " . join(" ", $pptpdcfg['dnsserver']) . "\n";
1042
			} else
1043
				if (isset ($config['dnsmasq']['enable'])) {
1044
					$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1045
					if ($syscfg['dnsserver'][0])
1046
						$mpdconf .= " " . $syscfg['dnsserver'][0];
1047
					$mpdconf .= "\n";
1048
				} else
1049
					if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1050
						$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1051
					}
1052

    
1053
			if (isset ($pptpdcfg['radius']['server']['enable'])) {
1054
				$authport = (isset($pptpdcfg['radius']['server']['port']) && strlen($pptpdcfg['radius']['server']['port']) > 1) ? $pptpdcfg['radius']['server']['port'] : 1812;
1055
				$acctport = $authport + 1;
1056
				$mpdconf .=<<<EOD
1057
	set radius server {$pptpdcfg['radius']['server']['ip']} "{$pptpdcfg['radius']['server']['secret']}" {$authport} {$acctport}
1058

    
1059
EOD;
1060
			if (isset ($pptpdcfg['radius']['server2']['enable'])) {
1061
				$authport = (isset($pptpdcfg['radius']['server2']['port']) && strlen($pptpdcfg['radius']['server2']['port']) > 1) ? $pptpdcfg['radius']['server2']['port'] : 1812;
1062
				$acctport = $authport + 1;
1063
				$mpdconf .=<<<EOD
1064
	set radius server {$pptpdcfg['radius']['server2']['ip']} "{$pptpdcfg['radius']['server2']['secret']}" {$authport} {$acctport}
1065

    
1066
EOD;
1067
			}
1068
			$mpdconf .=<<<EOD
1069
	set radius retries 3
1070
	set radius timeout 10
1071
	set auth enable radius-auth
1072

    
1073
EOD;
1074

    
1075
				if (isset ($pptpdcfg['radius']['accounting'])) {
1076
					$mpdconf .=<<<EOD
1077
	set auth enable radius-acct
1078
	set radius acct-update 300
1079

    
1080
EOD;
1081
				}
1082
			}
1083

    
1084
			fwrite($fd, $mpdconf);
1085
			fclose($fd);
1086

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

    
1094
			$mpdlinks = "";
1095

    
1096
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1097
				$mpdlinks .=<<<EOD
1098

    
1099
pt{$i}:
1100
	set link type pptp
1101
	set pptp enable incoming
1102
	set pptp disable originate
1103
	set pptp disable windowing
1104

    
1105
EOD;
1106
			}
1107

    
1108
			fwrite($fd, $mpdlinks);
1109
			fclose($fd);
1110

    
1111
			/* write mpd.secret */
1112
			$fd = fopen("{$g['varetc_path']}/pptp-vpn/mpd.secret", "w");
1113
			if (!$fd) {
1114
				printf("Error: cannot open mpd.secret in vpn_pptpd_configure().\n");
1115
				return 1;
1116
			}
1117

    
1118
			$mpdsecret = "";
1119

    
1120
			if (is_array($pptpdcfg['user'])) {
1121
				foreach ($pptpdcfg['user'] as $user)
1122
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1123
			}
1124

    
1125
			fwrite($fd, $mpdsecret);
1126
			fclose($fd);
1127
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1128

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

    
1132
			break;
1133

    
1134
		case 'redir' :
1135
			break;
1136
	}
1137

    
1138
	if ($g['booting'])
1139
		echo "done\n";
1140

    
1141
	return 0;
1142
}
1143

    
1144
function vpn_pppoe_configure() {
1145
	global $config, $g;
1146

    
1147
	$syscfg = $config['system'];
1148
	$pppoecfg = $config['pppoe'];
1149

    
1150
	/* create directory if it does not exist */
1151
	if (!is_dir("{$g['varetc_path']}/pppoe-vpn"))
1152
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1153

    
1154
	if ($g['booting']) {
1155
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1156
			return 0;
1157

    
1158
		echo "Configuring PPPoE VPN service... ";
1159
	} else {
1160
		/* kill mpd */
1161
		killbypid("{$g['varrun_path']}/pppoe-vpn.pid");
1162

    
1163
		/* wait for process to die */
1164
		sleep(2);
1165

    
1166
	}
1167

    
1168
	/* make sure pppoe-vpn directory exists */
1169
	if (!file_exists("{$g['varetc_path']}/pppoe-vpn"))
1170
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1171

    
1172
	switch ($pppoecfg['mode']) {
1173

    
1174
		case 'server' :
1175

    
1176
			$pppoe_interface = interface_translate_type_to_real($pppoecfg['interface']);
1177

    
1178
			if ($pppoecfg['paporchap'] == "chap")
1179
				$paporchap = "set link enable chap";
1180
			else
1181
				$paporchap = "set link enable pap";
1182

    
1183
			/* write mpd.conf */
1184
			$fd = fopen("{$g['varetc_path']}/pppoe-vpn/mpd.conf", "w");
1185
			if (!$fd) {
1186
				printf("Error: cannot open mpd.conf in vpn_pppoe_configure().\n");
1187
				return 1;
1188
			}
1189
			$mpdconf = "\n\n";
1190
			$mpdconf .=<<<EOD
1191
pppoe:
1192

    
1193
EOD;
1194

    
1195
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1196
				$mpdconf .= "	load pppoe{$i}\n";
1197
			}
1198

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

    
1201
				$clientip = long2ip(ip2long($pppoecfg['remoteip']) + $i);
1202

    
1203
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['enable'])) {
1204
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1205
				} else {
1206
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1207
				}
1208

    
1209
				$mpdconf .=<<<EOD
1210

    
1211
pppoe{$i}:
1212
	new pppoe{$i} pppoe{$i}
1213
	{$isssue_ip_type}
1214
	load pppoe_standart
1215

    
1216
EOD;
1217
			}
1218

    
1219
			$mpdconf .=<<<EOD
1220

    
1221
pppoe_standart:
1222
	set bundle no multilink
1223
	set bundle enable compression
1224
	set auth max-logins 1
1225
	set iface up-script /usr/local/sbin/pppoe-linkup
1226
        set iface down-script /usr/local/sbin/vpn-linkdown
1227
	set iface idle 0
1228
	set iface disable on-demand
1229
	set iface disable proxy-arp
1230
	set iface enable tcpmssfix
1231
	set iface mtu 1500
1232
	set link no pap chap
1233
	{$paporchap}
1234
	set link keep-alive 60 180
1235
	set ipcp yes vjcomp
1236
	set ipcp no vjcomp
1237
	set link max-redial -1
1238
	set link mtu 1492
1239
	set link mru 1492
1240
	set ccp yes mpp-e40
1241
	set ccp yes mpp-e128
1242
	set ccp yes mpp-stateless
1243
	set link latency 1
1244
	#set ipcp dns 10.10.1.3
1245
	#set bundle accept encryption
1246

    
1247
EOD;
1248

    
1249
			if (isset ($config['dnsmasq']['enable'])) {
1250
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1251
				if ($syscfg['dnsserver'][0])
1252
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1253
				$mpdconf .= "\n";
1254
			} else
1255
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1256
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1257
				}
1258

    
1259
			if (isset ($pppoecfg['radius']['enable'])) {
1260
				$mpdconf .=<<<EOD
1261
	set radius server {$pppoecfg['radius']['server']} "{$pppoecfg['radius']['secret']}"
1262
	set radius retries 3
1263
	set radius timeout 10
1264
	set auth enable radius-auth
1265

    
1266
EOD;
1267

    
1268
				if (isset ($pppoecfg['radius']['accounting'])) {
1269
					$mpdconf .=<<<EOD
1270
	set auth enable radius-acct
1271

    
1272
EOD;
1273
				}
1274
			}
1275

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

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

    
1286
			$mpdlinks = "";
1287

    
1288
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1289
				$mpdlinks .=<<<EOD
1290
			
1291
pppoe{$i}:
1292
	set phys type pppoe
1293
        set pppoe iface {$pppoe_interface}
1294
        set pppoe service "*"
1295
        set pppoe disable originate
1296
        set pppoe enable incoming
1297

    
1298
EOD;
1299
			}
1300

    
1301
			fwrite($fd, $mpdlinks);
1302
			fclose($fd);
1303

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

    
1311
			$mpdsecret = "\n\n";
1312

    
1313
			if (is_array($pppoecfg['user'])) {
1314
				foreach ($pppoecfg['user'] as $user)
1315
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1316
			}
1317

    
1318
			fwrite($fd, $mpdsecret);
1319
			fclose($fd);
1320
			chmod("{$g['varetc_path']}/pppoe-vpn/mpd.secret", 0600);
1321

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

    
1325
			break;
1326

    
1327
		case 'redir' :
1328
			break;
1329
	}
1330

    
1331
	if ($g['booting'])
1332
		echo "done\n";
1333

    
1334
	return 0;
1335
}
1336

    
1337
function vpn_l2tp_configure() {
1338
	global $config, $g;
1339

    
1340
	$syscfg = $config['system'];
1341
	$l2tpcfg = $config['l2tp'];
1342

    
1343
	/* create directory if it does not exist */
1344
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1345
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1346

    
1347
	if ($g['booting']) {
1348
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1349
			return 0;
1350

    
1351
		echo "Configuring l2tp VPN service... ";
1352
	} else {
1353
		/* kill mpd */
1354
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1355

    
1356
		/* wait for process to die */
1357
		sleep(8);
1358

    
1359
	}
1360

    
1361
	/* make sure l2tp-vpn directory exists */
1362
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1363
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1364

    
1365
	switch ($l2tpcfg['mode']) {
1366

    
1367
		case 'server' :
1368
			if ($l2tpcfg['paporchap'] == "chap")
1369
				$paporchap = "set link enable chap";
1370
			else
1371
				$paporchap = "set link enable pap";
1372

    
1373
			/* write mpd.conf */
1374
			$fd = fopen("{$g['varetc_path']}/l2tp-vpn/mpd.conf", "w");
1375
			if (!$fd) {
1376
				printf("Error: cannot open mpd.conf in vpn_l2tp_configure().\n");
1377
				return 1;
1378
			}
1379
			$mpdconf = "\n\n";
1380
			$mpdconf .=<<<EOD
1381
l2tp:
1382

    
1383
EOD;
1384

    
1385
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1386
				$mpdconf .= "	load l2tp{$i}\n";
1387
			}
1388

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

    
1391
				$clientip = long2ip(ip2long($l2tpcfg['remoteip']) + $i);
1392

    
1393
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1394
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1395
				} else {
1396
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1397
				}
1398

    
1399
				$mpdconf .=<<<EOD
1400

    
1401
l2tp{$i}:
1402
	new l2tp{$i} l2tp{$i}
1403
	{$isssue_ip_type}
1404
	load l2tp_standard
1405

    
1406
EOD;
1407
			}
1408

    
1409
			$mpdconf .=<<<EOD
1410

    
1411
l2tp_standard:
1412
        set bundle disable multilink
1413
        set bundle enable compression
1414
        set bundle yes crypt-reqd
1415
        set ipcp yes vjcomp
1416
        # set ipcp ranges 131.188.69.161/32 131.188.69.170/28
1417
        set ccp yes mppc
1418
        set iface disable on-demand
1419
        set iface enable proxy-arp
1420
	set iface up-script /usr/local/sbin/l2tp-linkup
1421
        set iface down-script /usr/local/sbin/vpn-linkdown
1422
        set link yes acfcomp protocomp
1423
        set link no pap chap
1424
        set link enable chap
1425
        set link keep-alive 10 180
1426

    
1427
EOD;
1428

    
1429
			if (isset ($config['dnsmasq']['enable'])) {
1430
				$mpdconf .= "	set ipcp dns " . get_interface_ip("lan");
1431
				if ($syscfg['dnsserver'][0])
1432
					$mpdconf .= " " . $syscfg['dnsserver'][0];
1433
				$mpdconf .= "\n";
1434
			} else
1435
				if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
1436
					$mpdconf .= "	set ipcp dns " . join(" ", $syscfg['dnsserver']) . "\n";
1437
				}
1438

    
1439
			if (isset ($l2tpcfg['radius']['enable'])) {
1440
				$mpdconf .=<<<EOD
1441
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1442
	set radius retries 3
1443
	set radius timeout 10
1444
	set auth enable radius-auth
1445

    
1446
EOD;
1447

    
1448
				if (isset ($l2tpcfg['radius']['accounting'])) {
1449
					$mpdconf .=<<<EOD
1450
	set auth enable radius-acct
1451

    
1452
EOD;
1453
				}
1454
			}
1455

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

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

    
1466
			$mpdlinks = "";
1467

    
1468
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1469
				$mpdlinks .=<<<EOD
1470

    
1471
l2tp{$i}:
1472
	set link type l2tp
1473
        set l2tp enable incoming
1474
        set l2tp disable originate
1475

    
1476
EOD;
1477
			if (!empty($l2tpcfg['secret']))
1478
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1479
			}
1480

    
1481
			fwrite($fd, $mpdlinks);
1482
			fclose($fd);
1483

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

    
1491
			$mpdsecret = "\n\n";
1492

    
1493
			if (is_array($l2tpcfg['user'])) {
1494
				foreach ($l2tpcfg['user'] as $user)
1495
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1496
			}
1497

    
1498
			fwrite($fd, $mpdsecret);
1499
			fclose($fd);
1500
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1501

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

    
1505
			break;
1506

    
1507
		case 'redir' :
1508
			break;
1509
	}
1510

    
1511
	if ($g['booting'])
1512
		echo "done\n";
1513

    
1514
	return 0;
1515
}
1516

    
1517
/* Walk the tunnels for hostname endpoints. If the hostnames 
1518
 * resolve to a different IP now compared to the DNS cache
1519
 * we reload the policies if the endpoint has changed */
1520
function vpn_ipsec_refresh_policies() {
1521
	global $config;
1522
	global $g;
1523

    
1524
	$ipseccfg = $config['ipsec'];
1525
	$a_phase1 = $config['ipsec']['phase1'];
1526
	$a_phase2 = $config['ipsec']['phase2'];
1527

    
1528
	if (isset($ipseccfg['disable'])) {
1529
		return true;
1530
	}
1531

    
1532
	/* Walk the Ipsec tunnel array */
1533
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1534
		return;
1535
	}
1536

    
1537
	foreach ($a_phase1 as $phase1) {
1538
		if (isset($phase1['disabled'])) {
1539
			continue;
1540
		}
1541
		if (is_ipaddr($phase1['remote-gateway'])) {
1542
			continue;
1543
		}
1544
		if (!is_ipaddr($phase1['remote-gateway'])) {
1545
			$dnscache = compare_hostname_to_dnscache($phase1['remote-gateway']);
1546
			$dnscache = trim($dnscache);
1547
			/* we should have the old IP addresses in the dnscache now */
1548
			if($dnscache <> "") {
1549
				$oldphase1 = $phase1;
1550
				$oldphase1['remote-gateway'] = trim($dnscache);
1551
				/* now we need to find all tunnels for this host */
1552
				if (!is_array($a_phase2) || (!count($a_phase2))) {
1553
					continue;
1554
				}
1555
				foreach ($a_phase2 as $phase2) {
1556
					//if($phase2['ikeid'] == $phase1['ikeid']) {
1557
					reload_tunnel_spd_policy ($phase1, $phase2, $oldphase1, $oldphase2);
1558
					//}
1559
				}
1560
			}
1561
		}
1562
	}
1563

    
1564
	/* process all generated spd.conf files from tmp which are left behind
1565
	 * behind by either changes of dynamic tunnels or manual edits
1566
	 * scandir() is only available in PHP5 */
1567
	$tmpfiles = array();
1568
	$dh  = opendir($g['tmp_path']);
1569
	while (false !== ($filename = readdir($dh))) {
1570
		if(preg_match("/^spd.conf.reload./", $tmpfile)) {
1571
			$tmpfiles[] = $filename;
1572
		}
1573
	}
1574
	sort($tmpfiles);
1575
	foreach($tmpfiles as $tmpfile) {
1576
		$ret = mwexec("/usr/local/sbin/setkey -f {$g['tmp_path']}/{$tmpfile} 2>&1", false);
1577
		if($ret == 0) {
1578
			unlink_if_exists("{$g['tmp_path']}/{$tmpfile}");
1579
		} else {
1580
			rename("{$g['tmp_path']}/{$tmpfile}", ("{$g['tmp_path']}/failed.{$tmpfile}"));
1581
		}
1582
	}
1583
}
1584

    
1585
/* reloads the tunnel configuration for a tunnel item
1586
 * Will remove and add SPD polices */
1587
function reload_tunnel_spd_policy($phase1, $phase2, $old_phase1, $old_phase2) {
1588
	global $config;
1589
	global $g;
1590

    
1591
	/* if we are not passed a old tunnel array we create one */
1592
	if(empty($old_phase1)) {
1593
		$old_phase1 = $phase1;
1594
	}
1595
	if(empty($old_phase2)) {
1596
		$old_phase2 = $phase2;
1597
	}
1598

    
1599
	$sad_arr = ipsec_dump_sad();
1600

    
1601
	$ep = ipsec_get_phase1_src($phase1);
1602
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1603
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1604

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

    
1608
	$old_ep = ipsec_get_phase1_src($old_phase1);
1609
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1610
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1611

    
1612
	/* see if this tunnel has a hostname for the remote-gateway, and if so,
1613
	 * try to resolve it now and add it to the list for dnswatch */
1614
	if (!is_ipaddr($phase1['remote-gateway'])) {
1615
		$rgip = resolve_retry($phase1['remote-gateway']);
1616
		add_hostname_to_watch($phase1['remote-gateway']);
1617
		if (!$rgip) {
1618
			log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1619
			return false;
1620
		}
1621
	} else {
1622
		$rgip = $phase1['remote-gateway'];
1623
	}
1624
	if (!$ep) {
1625
		log_error("Could not determine VPN endpoint for '{$phase1['descr']}'");
1626
		return false;
1627
	}
1628

    
1629
	if((!is_ipaddr($old_ep)) || (! is_ipaddr($ep))) {
1630
		log_error("IPSEC: ERROR: One of the endpoints is not a IP address. Old EP '{$old_ep}' new EP '{$ep}'");
1631
	}
1632
	if((! is_ipaddr($rgip)) || (! is_ipaddr($old_gw))) {
1633
		log_error("IPSEC: ERROR: One of the remote endpoints is not a IP address. Old RG '{$old_gw}' new RG '{$rgip}'");
1634
	}
1635

    
1636
	$spdconf = "";
1637
	/* Delete old SPD policies if there are changes between the old and new */
1638
	if(($phase1 != $old_phase1) || ($phase2 != $old_phase2)) {
1639
		$spdconf .= "spddelete {$old_local_subnet} " .
1640
			"{$old_remote_subnet} any -P out ipsec " .
1641
			"{$old_phase2['protocol']}/tunnel/{$old_ep}-" .
1642
			"{$old_gw}/unique;\n";
1643
		$spdconf .= "spddelete {$old_remote_subnet} " .
1644
			"{$old_local_subnet} any -P in ipsec " .
1645
			"{$old_phase2['protocol']}/tunnel/{$old_gw}-" .
1646
			"{$old_ep}/unique;\n";
1647

    
1648
		/* zap any existing SA entries */
1649
		foreach($sad_arr as $sad) {
1650
			if(($sad['dst'] == $old_ep) && ($sad['src'] == $old_gw)) {
1651
				$spdconf .= "delete {$old_ep} {$old_gw} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1652
			}
1653
			if(($sad['src'] == $oldep) && ($sad['dst'] == $old_gw)) {
1654
				$spdconf .= "delete {$old_gw} {$old_ep} {$old_phase2['protocol']} 0x{$sad['spi']};\n";
1655
			}
1656
		}
1657
	}
1658

    
1659
	/* Create new SPD entries for the new configuration */
1660
	/* zap any existing SA entries beforehand */
1661
	foreach($sad_arr as $sad) {
1662
		if(($sad['dst'] == $ep) && ($sad['src'] == $rgip)) {
1663
			$spdconf .= "delete {$rgip} {$ep} {$phase2['protocol']} 0x{$sad['spi']};\n";
1664
		}
1665
		if(($sad['src'] == $ep) && ($sad['dst'] == $rgip)) {
1666
			$spdconf .= "delete {$ep} {$rgip} {$phase2['protocol']} 0x{$sad['spi']};\n";
1667
		}
1668
	}
1669
	/* add new SPD policies to replace them */
1670
	$spdconf .= "spdadd {$local_subnet} " .
1671
		"{$remote_subnet} any -P out ipsec " .
1672
		"{$phase2['protocol']}/tunnel/{$ep}-" .
1673
		"{$rgip}/unique;\n";
1674
	$spdconf .= "spdadd {$remote_subnet} " .
1675
		"{$local_subnet} any -P in ipsec " .
1676
		"{$phase2['protocol']}/tunnel/{$rgip}-" .
1677
		"{$ep}/unique;\n";
1678

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

    
1681
	$now = time();
1682
	$spdfile = tempnam("{$g['tmp_path']}", "spd.conf.reload.{$now}.");
1683
	/* generate temporary spd.conf */
1684
	file_put_contents($spdfile, $spdconf);
1685
	return true;
1686
}
1687

    
1688
?>
(44-44/50)