Project

General

Profile

Download (45.3 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

    
50
	if (is_array($config['installedpackages']['sasyncd'])) {
51
		$sasyncd_text = "";
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
		file_put_contents("{$g['varetc_path']}/sasyncd.conf", $sasyncd_text);
71
		chmod("{$g['varetc_path']}/sasyncd.conf", 0600);
72

    
73
		if(is_process_running("sasyncd"))
74
			mwexec("killall sasyncd", true);
75

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

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

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

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

    
104
	/* get the automatic ping_hosts.sh ready */
105
	unlink_if_exists("{$g['vardb_path']}/ipsecpinghosts");
106
	touch("{$g['vardb_path']}/ipsecpinghosts");
107

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

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

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

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

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

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

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

    
147
		return true;
148
	} else {
149
		if ($g['booting'])
150
			echo "Configuring IPsec VPN... ";
151

    
152
		/* fastforwarding is not compatible with ipsec tunnels */
153
		mwexec("/sbin/sysctl net.inet.ip.fastforwarding=0");
154

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

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

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

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

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

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

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

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

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

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

    
195
				/* step through each phase2 entry */
196
				$ipsecpinghosts = "";
197
				foreach ($a_phase2 as $ph2ent) {
198

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

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

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

    
207
					/* add an ipsec pinghosts entry */
208
					if ($ph2ent['pinghost']) {
209
						$iflist = get_configured_interface_list();
210
						foreach ($iflist as $ifent => $ifname) {
211
							$interface_ip = get_interface_ip($ifent);
212
							$local_subnet = ipsec_idinfo_to_cidr($ph2ent['localid'], true);
213
							if (ip_in_subnet($interface_ip, $local_subnet)) {
214
								$srcip = $interface_ip;
215
								break;
216
							}
217
						}
218
						$dstip = $ph2ent['pinghost'];
219
						if (is_ipaddr($srcip))
220
							$ipsecpinghosts .= "{$srcip}|{$dstip}|3\n";
221
					}
222
				}
223
				$pfd = fopen("{$g['vardb_path']}/ipsecpinghosts", "w");
224
				if ($pfd) {
225
					fwrite($pfd, $ipsecpinghosts);
226
					fclose($pfd);
227
				}
228
				
229
			}
230
		}
231

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

    
260
		$pskconf = "";
261

    
262
		if (is_array($a_phase1) && count($a_phase1)) {
263
			foreach ($a_phase1 as $ph1ent) {
264

    
265
				if (isset($ph1ent['disabled']))
266
					continue;
267

    
268
				if (strstr($ph1ent['authentication_method'],'rsa'))
269
					continue;
270

    
271
				$peerid_type = $ph1ent['peerid_type'];
272

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

    
279
					case "address";
280
						$peerid_data = $ph1ent['peerid_data'];
281
						break;
282

    
283
					case "fqdn";
284
					case "keyid tag";
285
					case "user_fqdn";
286
						$peerid_data = $ph1ent['peerid_data'];
287
						break;
288
				}
289

    
290
				$pskconf .= "{$peerid_data}\t{$ph1ent['pre-shared-key']}\n";
291
			}
292
		}
293

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

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

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

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

    
324
			/* begin mode_cfg section */
325
			if (is_array($a_client) && isset($a_client['enable'])) {
326

    
327
				$racoonconf .= "\nmode_cfg\n";
328
				$racoonconf .= "{\n";
329

    
330
				if ($a_client['user_source'])
331
					$racoonconf .= "\tauth_source {$a_client['user_source']};\n";
332
				if ($a_client['group_source'])
333
					$racoonconf .= "\tgroup_source {$a_client['group_source']};\n";
334

    
335
				if ($a_client['pool_address'] && $a_client['pool_netbits']) {
336
					$pool_address = $a_client['pool_address'];
337
					$pool_netmask = gen_subnet_mask($a_client['pool_netbits']);
338

    
339
					$pool_address = long2ip(ip2long($pool_address)+1);
340
					$pool_size = ~ip2long($pool_netmask) - 2;
341

    
342
					$racoonconf .= "\tpool_size {$pool_size};\n";
343
					$racoonconf .= "\tnetwork4 {$pool_address};\n";
344
					$racoonconf .= "\tnetmask4 {$pool_netmask};\n";
345
				}
346

    
347
				if (isset($a_client['net_list'])) {
348

    
349
					$net_list = '';
350

    
351
					foreach ($a_phase2 as $ph2ent) {
352

    
353
						if (isset($ph2ent['disabled']))
354
							continue;
355

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

    
359
						$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
360

    
361
						if ($net_list)
362
							$net_list .= ", ";
363
						$net_list .= $localid;
364
					}
365

    
366
					if ($net_list)
367
						$racoonconf .= "\tsplit_network include {$net_list};\n";
368
				}
369

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

    
379
				if ($a_client['wins_server1'])
380
					$racoonconf .= "\twins4 {$a_client['wins_server1']};\n";
381
				if ($a_client['wins_server2'])
382
					$racoonconf .= "\twins4 {$a_client['wins_server2']};\n";
383

    
384
				if ($a_client['dns_domain'])
385
					$racoonconf .= "\tdefault_domain \"{$a_client['dns_domain']}\";\n";
386

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

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

    
398
					fwrite($fd1, $a_client['login_banner']);
399
					fclose($fd1);
400

    
401
					$racoonconf .= "\tbanner \"{$fn}\";\n";
402
				}
403

    
404
				$racoonconf .= "}\n\n";
405
			}
406
			/* end mode_cfg section */
407

    
408
			/* begin remote sections */
409
			if (is_array($a_phase1) && count($a_phase1)) {
410
				/* begin remote */
411
				foreach ($a_phase1 as $ph1ent) {
412

    
413
					if (isset($ph1ent['disabled']))
414
						continue;
415

    
416
					if (isset($ph1ent['mobile']) && !isset($a_client['enable']))
417
						continue;
418

    
419
					$ikeid = $ph1ent['ikeid'];
420

    
421
					$ep = ipsec_get_phase1_src($ph1ent);
422
					if (!$ep)
423
						continue;
424

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

    
431
					$myid_type = $ph1ent['myid_type'];
432

    
433
					switch ($myid_type) {
434

    
435
						case "myaddress":
436
							$myid_type = "address";
437
							$myid_data = $ep;
438
							break;
439

    
440
						case "dyn_dns":
441
							$myid_type = "address";
442
							$myid_data = gethostbyname($ph1ent['myid_data']);
443
							break;
444

    
445
						case "address";
446
							$myid_data = $ph1ent['myid_data'];
447
							break;
448

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

    
459
					$peerid_type = $ph1ent['peerid_type'];
460

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

    
467
						case "address";
468
							$peerid_data = $ph1ent['peerid_data'];
469
							break;
470

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

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

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

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

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

    
505
					$certline = '';
506

    
507
					if (strstr($authmethod,'rsa')) {
508

    
509
						$cert = lookup_cert($ph1ent['certref']);
510

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

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

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

    
526
						chmod($certpath, 0600);
527

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

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

    
537
						chmod($keypath, 0600);
538

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

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

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

    
554
					/* add remote section to configuration */
555

    
556
					$racoonconf .=<<<EOD
557

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

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

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

    
593
				/* begin sainfo */
594
				foreach ($a_phase2 as $ph2ent) {
595

    
596
					$ikeid = $ph2ent['ikeid'];
597

    
598
					if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
599
						continue;
600

    
601
					if (isset($ph1ent['disabled']))
602
						continue;
603

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

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

    
610
					if ($ph2ent['mode'] == 'tunnel') {
611

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

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

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

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

    
629
					} else {
630

    
631
						$rgip = $rgmap[$ph1ent['remote-gateway']];
632

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

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

    
642
					if($ph2ent['protocol'] == 'esp') {
643

    
644
						$ealgos = '';
645

    
646
						foreach ($ph2ent['encryption-algorithm-option'] as $ealg) {
647

    
648
							$ealg_id = $ealg['name'];
649
							$ealg_kl = $ealg['keylen'];
650

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

    
686
						$ealgosline = "encryption_algorithm {$ealgos};";
687

    
688
					} else {
689

    
690
						$ealgosline = "encryption_algorithm null_enc;";
691
					}
692

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

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

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

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

    
723
EOD;
724
				}
725
				/* end sainfo */
726
			}
727
			/* end sainfo sections */
728

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

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

    
743
			$spdconf = "";
744

    
745
			/* Try to prevent people from locking themselves out of webgui. Just in case. */
746
			if ($config['interfaces']['lan']) {
747
				$spdconf .= "spdadd {$lanip}/32 {$lansa}/{$lansn} any -P out none;\n";
748
				$spdconf .= "spdadd {$lansa}/{$lansn} {$lanip}/32 any -P in none;\n";
749
			}
750

    
751
			foreach ($a_phase2 as $ph2ent) {
752

    
753
				if( !ipsec_lookup_phase1($ph2ent,$ph1ent))
754
					continue;
755

    
756
				if (isset($ph1ent['mobile']))
757
					continue;
758

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

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

    
765
				$ep = ipsec_get_phase1_src($ph1ent);
766
				if (!$ep)
767
					continue;
768

    
769
				$rgip = $rgmap[$ph1ent['remote-gateway']];
770

    
771
				$localid = ipsec_idinfo_to_cidr($ph2ent['localid'],true);
772
				$remoteid = ipsec_idinfo_to_cidr($ph2ent['remoteid'],true);
773

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

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

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

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

    
797
				} else {
798

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

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

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

    
808
				}
809

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

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

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

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

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

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

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

    
886
		if ($g['booting'])
887
			echo "done\n";
888
	}
889

    
890
	return 0;
891
}
892

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

    
902
	$ipseccfg = $config['ipsec'];
903

    
904
	/* kill racoon */
905
	if(is_process_running("racoon"))
906
		mwexec("/usr/bin/killall racoon", true);
907

    
908
	/* wait for process to die */
909
	sleep(4);
910

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

    
914
	/* wait for flushing to finish */
915
	sleep(1);
916

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

    
923
}
924

    
925
/* master setup for vpn (mpd) */
926
function vpn_setup() {
927
	/* start pptpd */
928
	vpn_pptpd_configure();
929

    
930
	/* start pppoe server */
931
	vpn_pppoe_configure();
932

    
933
	/* setup l2tp */
934
	vpn_l2tp_configure();
935
}
936

    
937
function vpn_pptpd_configure() {
938
	global $config, $g;
939

    
940
	$syscfg = $config['system'];
941
	$pptpdcfg = $config['pptpd'];
942

    
943
	if ($g['booting']) {
944
		if (!$pptpdcfg['mode'] || ($pptpdcfg['mode'] == "off"))
945
			return 0;
946

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

    
952
		/* wait for process to die */
953
		sleep(3);
954

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

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

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

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

    
979
			$mpdconf = <<<EOD
980
pptpd:
981

    
982
EOD;
983

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

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

    
990
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
991

    
992
				$mpdconf .= <<<EOD
993

    
994
pt{$i}:
995
	new -i pptpd{$i} pt{$i} pt{$i}
996
	set ipcp ranges {$pptpdcfg['localip']}/32 {$clientip}/32
997
	load pts
998

    
999
EOD;
1000
			}
1001

    
1002
			$mpdconf .=<<<EOD
1003

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

    
1024
EOD;
1025

    
1026
			if (!isset ($pptpdcfg['req128'])) {
1027
				$mpdconf .=<<<EOD
1028
	set ccp yes mpp-e40
1029
	set ccp yes mpp-e56
1030

    
1031
EOD;
1032
			}
1033

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

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

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

    
1062
EOD;
1063
			}
1064
			$mpdconf .=<<<EOD
1065
	set radius retries 3
1066
	set radius timeout 10
1067
	set auth enable radius-auth
1068

    
1069
EOD;
1070

    
1071
				if (isset ($pptpdcfg['radius']['accounting'])) {
1072
					$mpdconf .=<<<EOD
1073
	set auth enable radius-acct
1074
	set radius acct-update 300
1075

    
1076
EOD;
1077
				}
1078
			}
1079

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

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

    
1090
			$mpdlinks = "";
1091

    
1092
			for ($i = 0; $i < $pptpdcfg['n_pptp_units']; $i++) {
1093
				$mpdlinks .=<<<EOD
1094

    
1095
pt{$i}:
1096
	set link type pptp
1097
	set pptp enable incoming
1098
	set pptp disable originate
1099
	set pptp disable windowing
1100

    
1101
EOD;
1102
			}
1103

    
1104
			fwrite($fd, $mpdlinks);
1105
			fclose($fd);
1106

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

    
1114
			$mpdsecret = "";
1115

    
1116
			if (is_array($pptpdcfg['user'])) {
1117
				foreach ($pptpdcfg['user'] as $user)
1118
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1119
			}
1120

    
1121
			fwrite($fd, $mpdsecret);
1122
			fclose($fd);
1123
			chmod("{$g['varetc_path']}/pptp-vpn/mpd.secret", 0600);
1124

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

    
1128
			break;
1129

    
1130
		case 'redir' :
1131
			break;
1132
	}
1133

    
1134
	if ($g['booting'])
1135
		echo "done\n";
1136

    
1137
	return 0;
1138
}
1139

    
1140
function vpn_pppoe_configure() {
1141
	global $config, $g;
1142

    
1143
	$syscfg = $config['system'];
1144
	$pppoecfg = $config['pppoe'];
1145

    
1146
	/* create directory if it does not exist */
1147
	if (!is_dir("{$g['varetc_path']}/pppoe-vpn"))
1148
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1149

    
1150
	if ($g['booting']) {
1151
		if (!$pppoecfg['mode'] || ($pppoecfg['mode'] == "off"))
1152
			return 0;
1153

    
1154
		echo "Configuring PPPoE VPN service... ";
1155
	} else {
1156
		/* kill mpd */
1157
		killbypid("{$g['varrun_path']}/pppoe-vpn.pid");
1158

    
1159
		/* wait for process to die */
1160
		sleep(2);
1161

    
1162
	}
1163

    
1164
	/* make sure pppoe-vpn directory exists */
1165
	if (!file_exists("{$g['varetc_path']}/pppoe-vpn"))
1166
		mkdir("{$g['varetc_path']}/pppoe-vpn");
1167

    
1168
	switch ($pppoecfg['mode']) {
1169

    
1170
		case 'server' :
1171

    
1172
			$pppoe_interface = interface_translate_type_to_real($pppoecfg['interface']);
1173

    
1174
			if ($pppoecfg['paporchap'] == "chap")
1175
				$paporchap = "set link enable chap";
1176
			else
1177
				$paporchap = "set link enable pap";
1178

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

    
1189
EOD;
1190

    
1191
			for ($i = 0; $i < $pppoecfg['n_pppoe_units']; $i++) {
1192
				$mpdconf .= "	load pppoe{$i}\n";
1193
			}
1194

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

    
1197
				$clientip = long2ip(ip2long($pppoecfg['remoteip']) + $i);
1198

    
1199
				if (isset ($pppoecfg['radius']['radiusissueips']) && isset ($pppoecfg['radius']['enable'])) {
1200
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 0.0.0.0/0";
1201
				} else {
1202
					$isssue_ip_type = "set ipcp ranges {$pppoecfg['localip']}/32 {$clientip}/32";
1203
				}
1204

    
1205
				$mpdconf .=<<<EOD
1206

    
1207
pppoe{$i}:
1208
	new -i ppoed{$i} pppoe{$i} pppoe{$i}
1209
	{$isssue_ip_type}
1210
	load pppoe_standart
1211

    
1212
EOD;
1213
			}
1214

    
1215
			$mpdconf .=<<<EOD
1216

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

    
1243
EOD;
1244

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

    
1255
			if (isset ($pppoecfg['radius']['enable'])) {
1256
				$mpdconf .=<<<EOD
1257
	set radius server {$pppoecfg['radius']['server']} "{$pppoecfg['radius']['secret']}"
1258
	set radius retries 3
1259
	set radius timeout 10
1260
	set auth enable radius-auth
1261

    
1262
EOD;
1263

    
1264
				if (isset ($pppoecfg['radius']['accounting'])) {
1265
					$mpdconf .=<<<EOD
1266
	set auth enable radius-acct
1267

    
1268
EOD;
1269
				}
1270
			}
1271

    
1272
			fwrite($fd, $mpdconf);
1273
			fclose($fd);
1274

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

    
1282
			$mpdlinks = "";
1283

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

    
1294
EOD;
1295
			}
1296

    
1297
			fwrite($fd, $mpdlinks);
1298
			fclose($fd);
1299

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

    
1307
			$mpdsecret = "\n\n";
1308

    
1309
			if (is_array($pppoecfg['user'])) {
1310
				foreach ($pppoecfg['user'] as $user)
1311
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1312
			}
1313

    
1314
			fwrite($fd, $mpdsecret);
1315
			fclose($fd);
1316
			chmod("{$g['varetc_path']}/pppoe-vpn/mpd.secret", 0600);
1317

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

    
1321
			break;
1322

    
1323
		case 'redir' :
1324
			break;
1325
	}
1326

    
1327
	if ($g['booting'])
1328
		echo "done\n";
1329

    
1330
	return 0;
1331
}
1332

    
1333
function vpn_l2tp_configure() {
1334
	global $config, $g;
1335

    
1336
	$syscfg = $config['system'];
1337
	$l2tpcfg = $config['l2tp'];
1338

    
1339
	/* create directory if it does not exist */
1340
	if (!is_dir("{$g['varetc_path']}/l2tp-vpn"))
1341
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1342

    
1343
	if ($g['booting']) {
1344
		if (!$l2tpcfg['mode'] || ($l2tpcfg['mode'] == "off"))
1345
			return 0;
1346

    
1347
		echo "Configuring l2tp VPN service... ";
1348
	} else {
1349
		/* kill mpd */
1350
		killbypid("{$g['varrun_path']}/l2tp-vpn.pid");
1351

    
1352
		/* wait for process to die */
1353
		sleep(8);
1354

    
1355
	}
1356

    
1357
	/* make sure l2tp-vpn directory exists */
1358
	if (!file_exists("{$g['varetc_path']}/l2tp-vpn"))
1359
		mkdir("{$g['varetc_path']}/l2tp-vpn");
1360

    
1361
	switch ($l2tpcfg['mode']) {
1362

    
1363
		case 'server' :
1364
			if ($l2tpcfg['paporchap'] == "chap")
1365
				$paporchap = "set link enable chap";
1366
			else
1367
				$paporchap = "set link enable pap";
1368

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

    
1379
EOD;
1380

    
1381
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1382
				$mpdconf .= "	load l2tp{$i}\n";
1383
			}
1384

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

    
1387
				$clientip = long2ip(ip2long($l2tpcfg['remoteip']) + $i);
1388

    
1389
				if (isset ($l2tpcfg['radius']['radiusissueips']) && isset ($l2tpcfg['radius']['enable'])) {
1390
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 0.0.0.0/0";
1391
				} else {
1392
					$isssue_ip_type = "set ipcp ranges {$l2tpcfg['localip']}/32 {$clientip}/32";
1393
				}
1394

    
1395
				$mpdconf .=<<<EOD
1396

    
1397
l2tp{$i}:
1398
	new l2tp{$i} l2tp{$i}
1399
	{$isssue_ip_type}
1400
	load l2tp_standard
1401

    
1402
EOD;
1403
			}
1404

    
1405
			$mpdconf .=<<<EOD
1406

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

    
1423
EOD;
1424

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

    
1435
			if (isset ($l2tpcfg['radius']['enable'])) {
1436
				$mpdconf .=<<<EOD
1437
	set radius server {$l2tpcfg['radius']['server']} "{$l2tpcfg['radius']['secret']}"
1438
	set radius retries 3
1439
	set radius timeout 10
1440
	set auth enable radius-auth
1441

    
1442
EOD;
1443

    
1444
				if (isset ($l2tpcfg['radius']['accounting'])) {
1445
					$mpdconf .=<<<EOD
1446
	set auth enable radius-acct
1447

    
1448
EOD;
1449
				}
1450
			}
1451

    
1452
			fwrite($fd, $mpdconf);
1453
			fclose($fd);
1454

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

    
1462
			$mpdlinks = "";
1463

    
1464
			for ($i = 0; $i < $l2tpcfg['n_l2tp_units']; $i++) {
1465
				$mpdlinks .=<<<EOD
1466

    
1467
l2tp{$i}:
1468
	set link type l2tp
1469
        set l2tp enable incoming
1470
        set l2tp disable originate
1471

    
1472
EOD;
1473
			if (!empty($l2tpcfg['secret']))
1474
					$mpdlinks .= "set l2tp secret {$l2tpcfg['secret']}\n";
1475
			}
1476

    
1477
			fwrite($fd, $mpdlinks);
1478
			fclose($fd);
1479

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

    
1487
			$mpdsecret = "\n\n";
1488

    
1489
			if (is_array($l2tpcfg['user'])) {
1490
				foreach ($l2tpcfg['user'] as $user)
1491
					$mpdsecret .= "{$user['name']} \"{$user['password']}\" {$user['ip']}\n";
1492
			}
1493

    
1494
			fwrite($fd, $mpdsecret);
1495
			fclose($fd);
1496
			chmod("{$g['varetc_path']}/l2tp-vpn/mpd.secret", 0600);
1497

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

    
1501
			break;
1502

    
1503
		case 'redir' :
1504
			break;
1505
	}
1506

    
1507
	if ($g['booting'])
1508
		echo "done\n";
1509

    
1510
	return 0;
1511
}
1512

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

    
1520
	$ipseccfg = $config['ipsec'];
1521
	$a_phase1 = $config['ipsec']['phase1'];
1522
	$a_phase2 = $config['ipsec']['phase2'];
1523

    
1524
	if (isset($ipseccfg['disable'])) {
1525
		return true;
1526
	}
1527

    
1528
	/* Walk the Ipsec tunnel array */
1529
	if (!is_array($a_phase1) || (!count($a_phase1))) {
1530
		return;
1531
	}
1532

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

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

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

    
1587
	/* if we are not passed a old tunnel array we create one */
1588
	if(empty($old_phase1)) {
1589
		$old_phase1 = $phase1;
1590
	}
1591
	if(empty($old_phase2)) {
1592
		$old_phase2 = $phase2;
1593
	}
1594

    
1595
	$sad_arr = ipsec_dump_sad();
1596

    
1597
	$ep = ipsec_get_phase1_src($phase1);
1598
	$local_subnet = ipsec_idinfo_to_cidr($phase2['localid']);
1599
	$remote_subnet = ipsec_idinfo_to_cidr($phase2['remoteid']);
1600

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

    
1604
	$old_ep = ipsec_get_phase1_src($old_phase1);
1605
	$old_local_subnet = ipsec_idinfo_to_cidr($old_phase2['localid']);
1606
	$old_remote_subnet = ipsec_idinfo_to_cidr($old_phase2['remoteid']);
1607

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

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

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

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

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

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

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

    
1684
?>
(46-46/52)