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

    
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
	$lancfg = $config['interfaces']['lan'];
123
	$lanip = get_interface_ip("lan");
124
	$lansn = get_interface_subnet("lan");
125
	$lansa = gen_subnet($lanip, $lansn);
126

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
261
		$pskconf = "";
262

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
350
					$net_list = '';
351

    
352
					foreach ($a_phase2 as $ph2ent) {
353

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
434
					switch ($myid_type) {
435

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

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

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

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

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

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

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

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

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

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

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

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

    
506
					$certline = '';
507

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

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

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

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

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

    
527
						chmod($certpath, 0600);
528

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

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

    
538
						chmod($keypath, 0600);
539

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

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

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

    
555
					/* add remote section to configuration */
556

    
557
					$racoonconf .=<<<EOD
558

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
630
					} else {
631

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

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

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

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

    
645
						$ealgos = '';
646

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

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

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

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

    
689
					} else {
690

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

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

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

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

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

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

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

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

    
744
			$spdconf = "";
745

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

    
752
			foreach ($a_phase2 as $ph2ent) {
753

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

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

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

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

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

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

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

    
775
				if (isset ($ph2ent['creategif'])) {
776
					$number_of_gifs = find_last_gif_device();
777
					$number_of_gifs++;
778
					$curwanip = get_interface_ip();
779
					if ($config['installedpackages']['sasyncd']['config'] <> "") {
780
						foreach ($config['installedpackages']['sasyncd']['config'] as $sasyncd) {
781
							if ($sasyncd['ip'] <> "")
782
								$curwanip = $sasyncd['ip'];
783
						}
784
					}
785
					mwexec("/sbin/ifconfig gif" . $number_of_gifs . " tunnel" . $curwanip . " " . $rgip);
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
		exec("/bin/mkdir -p /var/db/racoon");
850

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

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

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

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

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

    
892
	return 0;
893
}
894

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

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

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

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

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

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

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

    
925
}
926

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

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

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

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

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

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

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

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

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

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

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

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

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

    
984
EOD;
985

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

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

    
992
				$clientip = long2ip(ip2long($pptpdcfg['remoteip']) + $i);
993

    
994
				$mpdconf .= <<<EOD
995

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

    
1001
EOD;
1002
			}
1003

    
1004
			$mpdconf .=<<<EOD
1005

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

    
1026
EOD;
1027

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

    
1033
EOD;
1034
			}
1035

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

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

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

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

    
1071
EOD;
1072

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

    
1078
EOD;
1079
				}
1080
			}
1081

    
1082
			fwrite($fd, $mpdconf);
1083
			fclose($fd);
1084

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

    
1092
			$mpdlinks = "";
1093

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

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

    
1103
EOD;
1104
			}
1105

    
1106
			fwrite($fd, $mpdlinks);
1107
			fclose($fd);
1108

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

    
1116
			$mpdsecret = "";
1117

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

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

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

    
1130
			break;
1131

    
1132
		case 'redir' :
1133
			break;
1134
	}
1135

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

    
1139
	return 0;
1140
}
1141

    
1142
function vpn_pppoe_configure() {
1143
	global $config, $g;
1144

    
1145
	$syscfg = $config['system'];
1146
	$pppoecfg = $config['pppoe'];
1147

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

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

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

    
1161
		/* wait for process to die */
1162
		sleep(2);
1163

    
1164
	}
1165

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

    
1170
	switch ($pppoecfg['mode']) {
1171

    
1172
		case 'server' :
1173

    
1174
			$pppoe_interface = interface_translate_type_to_real($pppoecfg['interface']);
1175

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

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

    
1191
EOD;
1192

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

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

    
1199
				$clientip = long2ip(ip2long($pppoecfg['remoteip']) + $i);
1200

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

    
1207
				$mpdconf .=<<<EOD
1208

    
1209
pppoe{$i}:
1210
	new -i ppoed{$i} pppoe{$i} pppoe{$i}
1211
	{$isssue_ip_type}
1212
	load pppoe_standart
1213

    
1214
EOD;
1215
			}
1216

    
1217
			$mpdconf .=<<<EOD
1218

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

    
1245
EOD;
1246

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

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

    
1264
EOD;
1265

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

    
1270
EOD;
1271
				}
1272
			}
1273

    
1274
			fwrite($fd, $mpdconf);
1275
			fclose($fd);
1276

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

    
1284
			$mpdlinks = "";
1285

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

    
1296
EOD;
1297
			}
1298

    
1299
			fwrite($fd, $mpdlinks);
1300
			fclose($fd);
1301

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

    
1309
			$mpdsecret = "\n\n";
1310

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

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

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

    
1323
			break;
1324

    
1325
		case 'redir' :
1326
			break;
1327
	}
1328

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

    
1332
	return 0;
1333
}
1334

    
1335
function vpn_l2tp_configure() {
1336
	global $config, $g;
1337

    
1338
	$syscfg = $config['system'];
1339
	$l2tpcfg = $config['l2tp'];
1340

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

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

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

    
1354
		/* wait for process to die */
1355
		sleep(8);
1356

    
1357
	}
1358

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

    
1363
	switch ($l2tpcfg['mode']) {
1364

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

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

    
1381
EOD;
1382

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

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

    
1389
				$clientip = long2ip(ip2long($l2tpcfg['remoteip']) + $i);
1390

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

    
1397
				$mpdconf .=<<<EOD
1398

    
1399
l2tp{$i}:
1400
	new l2tp{$i} l2tp{$i}
1401
	{$isssue_ip_type}
1402
	load l2tp_standard
1403

    
1404
EOD;
1405
			}
1406

    
1407
			$mpdconf .=<<<EOD
1408

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

    
1425
EOD;
1426

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

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

    
1444
EOD;
1445

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

    
1450
EOD;
1451
				}
1452
			}
1453

    
1454
			fwrite($fd, $mpdconf);
1455
			fclose($fd);
1456

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

    
1464
			$mpdlinks = "";
1465

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

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

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

    
1479
			fwrite($fd, $mpdlinks);
1480
			fclose($fd);
1481

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

    
1489
			$mpdsecret = "\n\n";
1490

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

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

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

    
1503
			break;
1504

    
1505
		case 'redir' :
1506
			break;
1507
	}
1508

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

    
1512
	return 0;
1513
}
1514

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

    
1522
	$ipseccfg = $config['ipsec'];
1523
	$a_phase1 = $config['ipsec']['phase1'];
1524
	$a_phase2 = $config['ipsec']['phase2'];
1525

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

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

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

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

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

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

    
1597
	$sad_arr = ipsec_dump_sad();
1598

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

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

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

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

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

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

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

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

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

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

    
1686
?>
(44-44/50)