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_type = "address";
445
							$myid_data = gethostbyname($ph1ent['myid_data']);
446
							break;
447

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

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

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

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

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

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

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

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

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

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

    
508
					$certline = '';
509

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

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

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

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

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

    
529
						chmod($certpath, 0600);
530

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

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

    
540
						chmod($keypath, 0600);
541

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

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

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

    
557
					/* add remote section to configuration */
558

    
559
					$racoonconf .=<<<EOD
560

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
632
					} else {
633

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

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

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

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

    
647
						$ealgos = '';
648

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

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

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

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

    
691
					} else {
692

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

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

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

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

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

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

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

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

    
746
			$spdconf = "";
747

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

    
754
			foreach ($a_phase2 as $ph2ent) {
755

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

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

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

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

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

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

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

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

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

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

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

    
799
				} else {
800

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

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

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

    
810
				}
811

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

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

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

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

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

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

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

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

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

    
894
	return 0;
895
}
896

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

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

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

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

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

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

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

    
927
}
928

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

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

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

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

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

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

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

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

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

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

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

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

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

    
986
EOD;
987

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

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

    
994
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
995

    
996
				$mpdconf .= <<<EOD
997

    
998
pt{$i}:
999
	new -i pptpd{$i} 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 -i ppoed{$i} 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
?>
(45-45/51)